Block.cpp 7.6 KB

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