FluidBlock.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #include "FluidBlock.h"
  2. #include "Game.h"
  3. FluidBlock::FluidBlock(int typeId,
  4. Framework::Vec3<int> pos,
  5. int dimensionId,
  6. Vec3<float> lightWeights)
  7. : Block(typeId, 0, pos, dimensionId, 0),
  8. lightWeights(lightWeights),
  9. neighborChanged(1),
  10. nextFlow(0),
  11. maxFlowDistance(8)
  12. {
  13. transparent = 1;
  14. passable = 1;
  15. hp = 1;
  16. maxHP = 1;
  17. hardness = -1.f;
  18. speedModifier = 0.5f;
  19. tickSource = 1;
  20. interactable = 0;
  21. flowOptions = 0;
  22. distanceToSource = 0;
  23. }
  24. FluidBlock::~FluidBlock() {}
  25. bool FluidBlock::onTick(TickQueue* zQueue, int numTicks, bool& blocked)
  26. {
  27. if (neighborChanged)
  28. {
  29. nextFlow -= numTicks;
  30. if (nextFlow <= 0)
  31. {
  32. const FluidBlockType* zType
  33. = dynamic_cast<const FluidBlockType*>(zBlockType());
  34. if (zType)
  35. {
  36. nextFlow = zType->getTicktsToFlow();
  37. }
  38. else
  39. {
  40. nextFlow = 0;
  41. }
  42. neighborChanged = 0;
  43. doFlow();
  44. }
  45. return true;
  46. }
  47. return false;
  48. }
  49. void FluidBlock::onPostTick() {}
  50. void FluidBlock::setNeighbourType(Direction dir, int type)
  51. {
  52. Block::setNeighbourType(dir, type);
  53. neighborChanged = 1;
  54. }
  55. void FluidBlock::sendModelInfo(NetworkMessage* zMessage)
  56. {
  57. zMessage->addressBlock(this);
  58. char* msg = new char[3];
  59. msg[0] = 2; // fluid amount change
  60. *(msg + 1) = flowOptions;
  61. *(msg + 2) = distanceToSource;
  62. zMessage->setMessage(msg, 3);
  63. }
  64. void FluidBlock::broadcastFlow()
  65. {
  66. NetworkMessage* changeMsg = new NetworkMessage();
  67. sendModelInfo(changeMsg);
  68. Game::INSTANCE->broadcastMessage(changeMsg);
  69. }
  70. void FluidBlock::doFlow()
  71. {
  72. bool doesFlowSidewards = 1;
  73. if ((zNeighbours[getDirectionIndex(Direction::BOTTOM)]
  74. && zNeighbours[getDirectionIndex(Direction::BOTTOM)]
  75. ->zBlockType()
  76. == zBlockType()
  77. || neighbourTypes[getDirectionIndex(Direction::BOTTOM)]
  78. == BlockTypeEnum::AIR)
  79. && distanceToSource)
  80. {
  81. doesFlowSidewards = 0;
  82. }
  83. bool changed = false;
  84. for (int i = 0; i < 6; i++)
  85. {
  86. Direction dir = getDirectionFromIndex(i);
  87. if (dir & Direction::TOP) continue;
  88. if (neighbourTypes[i] == BlockTypeEnum::AIR)
  89. {
  90. if (dir & Direction::BOTTOM || doesFlowSidewards)
  91. {
  92. Game::INSTANCE->doLater([this, dir, i]() {
  93. if (neighbourTypes[i] == BlockTypeEnum::AIR)
  94. {
  95. Block* belowBlock = zBlockType()->createBlockAt(
  96. getPos() + getDirection(dir), getDimensionId(), 0);
  97. FluidBlock* fluidBlock
  98. = dynamic_cast<FluidBlock*>(belowBlock);
  99. if (fluidBlock)
  100. {
  101. fluidBlock->distanceToSource
  102. = dir & Direction::BOTTOM
  103. ? 1
  104. : distanceToSource + 1;
  105. fluidBlock->flowOptions = (char)dir;
  106. Game::INSTANCE->zDimension(getDimensionId())
  107. ->placeBlock(
  108. getPos() + getDirection(dir), belowBlock);
  109. }
  110. else
  111. {
  112. std::cout
  113. << "ERROR: created flow fuild block is not an "
  114. "instance of FluidBlock\n";
  115. belowBlock->release();
  116. }
  117. }
  118. });
  119. }
  120. }
  121. else if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType())
  122. {
  123. if (dir & Direction::BOTTOM) continue;
  124. FluidBlock* neighbour = dynamic_cast<FluidBlock*>(zNeighbours[i]);
  125. if (neighbour)
  126. {
  127. if (distanceToSource > neighbour->distanceToSource + 1)
  128. {
  129. distanceToSource = neighbour->distanceToSource + 1;
  130. flowOptions = (char)getOppositeDirection(dir);
  131. changed = true;
  132. }
  133. else if (distanceToSource == neighbour->distanceToSource + 1)
  134. {
  135. char tmp = flowOptions;
  136. flowOptions |= (char)getOppositeDirection(dir);
  137. changed |= tmp != flowOptions;
  138. }
  139. }
  140. }
  141. }
  142. if (changed)
  143. {
  144. broadcastFlow();
  145. neighborChanged = 1;
  146. for (int i = 0; i < 6; i++)
  147. {
  148. Direction dir = getDirectionFromIndex(i);
  149. if (dir & (Direction::TOP | Direction::BOTTOM)) continue;
  150. if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType())
  151. {
  152. FluidBlock* neighbour
  153. = dynamic_cast<FluidBlock*>(zNeighbours[i]);
  154. if (neighbour)
  155. {
  156. neighbour->neighborChanged = 1;
  157. }
  158. }
  159. }
  160. }
  161. }
  162. void FluidBlock::filterPassingLight(unsigned char rgb[3]) const
  163. {
  164. rgb[0] = (unsigned char)(rgb[0] * lightWeights.x);
  165. rgb[1] = (unsigned char)(rgb[1] * lightWeights.y);
  166. rgb[2] = (unsigned char)(rgb[2] * lightWeights.z);
  167. }
  168. char FluidBlock::getDistanceToSource() const
  169. {
  170. return distanceToSource;
  171. }
  172. char FluidBlock::getFlowOptions() const
  173. {
  174. return flowOptions;
  175. }
  176. FluidBlockType::FluidBlockType(int id,
  177. ModelInfo model,
  178. const char* name,
  179. int mapColor,
  180. Vec3<float> lightWeights,
  181. int ticktsToFlow,
  182. char flowDistance)
  183. : BlockType(id, 0, model, 1, 10, 0, name, true, mapColor),
  184. lightWeights(lightWeights),
  185. ticktsToFlow(ticktsToFlow),
  186. flowDistance(flowDistance)
  187. {}
  188. void FluidBlockType::loadSuperBlock(
  189. Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const
  190. {
  191. FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
  192. zReader->lese(&block->flowOptions, 1);
  193. zReader->lese(&block->distanceToSource, 1);
  194. block->nextFlow = ticktsToFlow;
  195. block->maxFlowDistance = flowDistance;
  196. BlockType::loadSuperBlock(zBlock, zReader, dimensionId);
  197. }
  198. void FluidBlockType::saveSuperBlock(
  199. Block* zBlock, Framework::StreamWriter* zWriter) const
  200. {
  201. FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
  202. zWriter->schreibe(&block->flowOptions, 1);
  203. zWriter->schreibe(&block->distanceToSource, 1);
  204. BlockType::saveSuperBlock(zBlock, zWriter);
  205. }
  206. Item* FluidBlockType::createItem() const
  207. {
  208. return 0;
  209. }
  210. Block* FluidBlockType::createBlock(
  211. Framework::Vec3<int> position, int dimensionId) const
  212. {
  213. FluidBlock* result
  214. = new FluidBlock(getId(), position, dimensionId, lightWeights);
  215. result->nextFlow = ticktsToFlow;
  216. result->maxFlowDistance = flowDistance;
  217. return result;
  218. }
  219. bool FluidBlockType::isFluid() const
  220. {
  221. return true;
  222. }
  223. int FluidBlockType::getTicktsToFlow() const
  224. {
  225. return ticktsToFlow;
  226. }
  227. char FluidBlockType::getFlowDistance() const
  228. {
  229. return flowDistance;
  230. }