Block.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "Block.h"
  2. #include "Inventory.h"
  3. #include "NoBlock.h"
  4. #include "Game.h"
  5. #include "BlockChangedUpdate.h"
  6. #include "PlaceBlockUpdate.h"
  7. #include "BlockRemovedUpdate.h"
  8. #include "ItemEntity.h"
  9. #include "AddEntityUpdate.h"
  10. Block::Block( const BlockType* zType, ItemType* zTool, Framework::Vec3<int> pos, bool hasInventory )
  11. : Inventory( pos, hasInventory )
  12. {
  13. transparent = false;
  14. passable = false;
  15. hp = 1;
  16. maxHP = 1;
  17. hardness = 1;
  18. this->zType = zType;
  19. this->zTool = zTool;
  20. speedModifier = 1;
  21. ticksLeftCounter = 0;
  22. wasTicked = 0;
  23. onTickCalled = 0;
  24. minTickTimeout = -1;
  25. maxTickTimeout = -1;
  26. tickSource = 0;
  27. currentTickTimeout = 0;
  28. dimensionId = 0;
  29. interactable = 0;
  30. memset( zNeighbours, 0, sizeof( Block* ) * 6 );
  31. }
  32. Block::~Block()
  33. {}
  34. void Block::onDestroy()
  35. {
  36. Item* blockItem = zType->getItemFromBlock( this );
  37. if( blockItem )
  38. {
  39. ItemEntity* itemEntity = new ItemEntity( location + Framework::Vec3<float>( 0.5f, 0.5f, 0.5f ), dimensionId, Game::INSTANCE->getNextEntityId() );
  40. ItemStack* stack = new ItemStack( blockItem, 1, blockItem->getMaxStackSize() );
  41. itemEntity->unsaveAddItem( stack, NO_DIRECTION );
  42. stack->release();
  43. Game::INSTANCE->requestWorldUpdate( new AddEntityUpdate( itemEntity, dimensionId ) );
  44. }
  45. }
  46. void Block::tick( TickQueue* zQueue )
  47. {
  48. if( wasTicked )
  49. return;
  50. wasTicked = 1;
  51. ticksLeftCounter++;
  52. if( minTickTimeout >= 0 )
  53. {
  54. if( currentTickTimeout < ticksLeftCounter )
  55. {
  56. onTickCalled = 1;
  57. bool blocked = 0;
  58. bool result = onTick( zQueue, ticksLeftCounter, blocked );
  59. if( blocked )
  60. {
  61. wasTicked = 0;
  62. ticksLeftCounter--;
  63. onTickCalled = 0;
  64. return;
  65. }
  66. if( result )
  67. currentTickTimeout = MAX( MIN( currentTickTimeout - 1, maxTickTimeout ), MAX( minTickTimeout, 0 ) );
  68. else
  69. currentTickTimeout = MAX( MIN( currentTickTimeout + 1, maxTickTimeout ), MAX( minTickTimeout, 0 ) );
  70. ticksLeftCounter = 0;
  71. }
  72. }
  73. }
  74. void Block::postTick()
  75. {
  76. wasTicked = 0;
  77. if( onTickCalled )
  78. {
  79. onPostTick();
  80. onTickCalled = 0;
  81. }
  82. }
  83. void Block::setNeighbour( Direction dir, Framework::Either<Block*, int> neighbour )
  84. {
  85. if( neighbour.isA() )
  86. setNeighbourBlock( dir, neighbour );
  87. else
  88. {
  89. setNeighbourBlock( dir, 0 );
  90. setNeighbourType( dir, neighbour );
  91. }
  92. }
  93. void Block::setNeighbourBlock( Direction dir, Block* zN )
  94. {
  95. if( zN )
  96. setNeighbourType( dir, zN->zBlockType()->getId() );
  97. zNeighbours[ getDirectionIndex( dir ) ] = zN;
  98. }
  99. void Block::setNeighbourType( Direction dir, int type )
  100. {
  101. neighbourTypes[ getDirectionIndex( dir ) ] = type;
  102. }
  103. void Block::setDimensionId( int id )
  104. {
  105. dimensionId = id;
  106. }
  107. void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
  108. {
  109. // TODO: answer api requests
  110. }
  111. bool Block::isTickSource() const
  112. {
  113. return tickSource;
  114. }
  115. const BlockType* Block::zBlockType() const
  116. {
  117. return zType;
  118. }
  119. bool Block::isTransparent() const
  120. {
  121. return transparent;
  122. }
  123. bool Block::isPassable() const
  124. {
  125. return passable;
  126. }
  127. bool Block::isInteractable() const
  128. {
  129. return interactable;
  130. }
  131. float Block::getHP() const
  132. {
  133. return hp;
  134. }
  135. float Block::getMaxHP() const
  136. {
  137. return maxHP;
  138. }
  139. float Block::getHardness() const
  140. {
  141. return hardness;
  142. }
  143. ItemType* Block::zEffectiveTool() const
  144. {
  145. return zTool;
  146. }
  147. float Block::getSpeedModifier() const
  148. {
  149. return speedModifier;
  150. }
  151. const Framework::Vec3<int> Block::getPos() const
  152. {
  153. return (Framework::Vec3<int>)location;
  154. }
  155. int Block::getDimensionId() const
  156. {
  157. return dimensionId;
  158. }
  159. bool Block::isVisible() const
  160. {
  161. if( passable || transparent )
  162. return 1;
  163. for( int i = 0; i < 6; i++ )
  164. {
  165. const Block* neighbour = CONST_BLOCK( zNeighbours[ i ], neighbourTypes[ i ] );
  166. if( neighbour->isPassable() || neighbour->isTransparent() )
  167. return 1;
  168. }
  169. return 0;
  170. }
  171. void Block::setHP( float hp )
  172. {
  173. bool isDead = this->hp == 0.f;
  174. this->hp = MAX( 0.f, hp );
  175. if( !isDead && this->hp == 0.f )
  176. {
  177. for( int i = 0; i < 6; i++ )
  178. {
  179. if( neighbourTypes[ i ] == NoBlockBlockType::ID )
  180. {
  181. Framework::Vec3<int> pos = getPos() + getDirection( getDirectionFromIndex( i ) );
  182. Game::INSTANCE->requestWorldUpdate( new PlaceBlockUpdate( Game::INSTANCE->zGenerator()->generateSingleBlock( pos, dimensionId ), pos, dimensionId ) );
  183. }
  184. }
  185. Game::INSTANCE->requestWorldUpdate( new BlockRemovedUpdate( getPos(), dimensionId ) );
  186. onDestroy();
  187. }
  188. else
  189. requestTransmission();
  190. }
  191. void Block::onAfterTransmission()
  192. {
  193. transmissionRequested = 0;
  194. }
  195. void Block::requestTransmission()
  196. {
  197. if( !transmissionRequested )
  198. {
  199. transmissionRequested = 1;
  200. Game::INSTANCE->requestWorldUpdate( new BlockChangedUpdate( getPos(), getDimensionId() ) );
  201. }
  202. }
  203. BasicBlockItem::BasicBlockItem( const ItemType* zType, const BlockType* zPlacedBlockType, const char* name )
  204. : Item( zType, name )
  205. {
  206. placeable = 1;
  207. zBlockType = zPlacedBlockType;
  208. }
  209. bool BasicBlockItem::canBeStackedWith( Item* zItem ) const
  210. {
  211. BasicBlockItem* item = dynamic_cast<BasicBlockItem*>(zItem);
  212. if( item )
  213. {
  214. return Item::canBeStackedWith( zItem ) &&
  215. transparent == item->transparent &&
  216. passable == item->passable &&
  217. hp == item->hp &&
  218. maxHP == item->maxHP &&
  219. hardness == item->hardness &&
  220. toolId == item->toolId &&
  221. speedModifier == item->speedModifier;
  222. }
  223. return 0;
  224. }
  225. BasicBlockItemType::BasicBlockItemType( int id, ItemSkillLevelUpRule* levelUpRule, const ItemType* zBrokenType )
  226. : ItemType( id, levelUpRule, zBrokenType )
  227. {}
  228. void BasicBlockItemType::loadSuperItem( Item* zItem, Framework::StreamReader* zReader ) const
  229. {
  230. ItemType::loadSuperItem( zItem, zReader );
  231. BasicBlockItem* item = dynamic_cast<BasicBlockItem*>(zItem);
  232. if( !item )
  233. throw "BasicBlockItemType::loadSuperItem was called with an invalid item";
  234. zReader->lese( (char*)&item->transparent, 1 );
  235. zReader->lese( (char*)&item->passable, 1 );
  236. zReader->lese( (char*)&item->hp, 4 );
  237. zReader->lese( (char*)&item->maxHP, 4 );
  238. zReader->lese( (char*)&item->hardness, 4 );
  239. zReader->lese( (char*)&item->toolId, 4 );
  240. zReader->lese( (char*)&item->speedModifier, 4 );
  241. }
  242. void BasicBlockItemType::saveSuperItem( const Item* zItem, Framework::StreamWriter* zWriter ) const
  243. {
  244. ItemType::saveSuperItem( zItem, zWriter );
  245. const BasicBlockItem* item = dynamic_cast<const BasicBlockItem*>(zItem);
  246. if( !item )
  247. throw "BasicBlockItemType::saveSuperItem was called with an invalid item";
  248. zWriter->schreibe( (char*)&item->transparent, 1 );
  249. zWriter->schreibe( (char*)&item->passable, 1 );
  250. zWriter->schreibe( (char*)&item->hp, 4 );
  251. zWriter->schreibe( (char*)&item->maxHP, 4 );
  252. zWriter->schreibe( (char*)&item->hardness, 4 );
  253. zWriter->schreibe( (char*)&item->toolId, 4 );
  254. zWriter->schreibe( (char*)&item->speedModifier, 4 );
  255. }
  256. void BasicBlockItemType::initializeItem( BasicBlockItem* zItem, bool transparent, bool passable, float hp, float maxHP, float hardness, int toolId, float speedModifier ) const
  257. {
  258. zItem->transparent = transparent;
  259. zItem->passable = passable;
  260. zItem->hp = hp;
  261. zItem->maxHP = maxHP;
  262. zItem->hardness = hardness;
  263. zItem->toolId = toolId;
  264. zItem->speedModifier = speedModifier;
  265. }