FluidBlock.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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::doFlow()
  65. {
  66. bool doesFlowSidewards = 1;
  67. if (((zNeighbours[getDirectionIndex(Direction::BOTTOM)]
  68. && zNeighbours[getDirectionIndex(Direction::BOTTOM)]
  69. ->zBlockType()
  70. == zBlockType()
  71. || neighbourTypes[getDirectionIndex(Direction::BOTTOM)]
  72. == BlockTypeEnum::AIR)
  73. && distanceToSource) || distanceToSource >= maxFlowDistance)
  74. {
  75. doesFlowSidewards = 0;
  76. }
  77. bool changed = false;
  78. for (int i = 0; i < 6; i++)
  79. {
  80. Direction dir = getDirectionFromIndex(i);
  81. if (dir & Direction::TOP) continue;
  82. if (neighbourTypes[i] == BlockTypeEnum::AIR)
  83. {
  84. if (dir & Direction::BOTTOM || doesFlowSidewards)
  85. {
  86. Game::INSTANCE->doLater([this, dir, i]() {
  87. if (neighbourTypes[i] == BlockTypeEnum::AIR)
  88. {
  89. Block* belowBlock = zBlockType()->createBlockAt(
  90. getPos() + getDirection(dir), getDimensionId(), 0);
  91. FluidBlock* fluidBlock
  92. = dynamic_cast<FluidBlock*>(belowBlock);
  93. if (fluidBlock)
  94. {
  95. fluidBlock->distanceToSource
  96. = dir & Direction::BOTTOM
  97. ? 1
  98. : distanceToSource + 1;
  99. fluidBlock->flowOptions = (char)dir;
  100. Game::INSTANCE->zDimension(getDimensionId())
  101. ->placeBlock(
  102. getPos() + getDirection(dir), belowBlock);
  103. }
  104. else
  105. {
  106. std::cout
  107. << "ERROR: created flow fuild block is not an "
  108. "instance of FluidBlock\n";
  109. belowBlock->release();
  110. }
  111. }
  112. });
  113. }
  114. }
  115. else if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType())
  116. {
  117. if (dir & Direction::BOTTOM) continue;
  118. FluidBlock* neighbour = dynamic_cast<FluidBlock*>(zNeighbours[i]);
  119. if (neighbour)
  120. {
  121. if (distanceToSource > neighbour->distanceToSource + 1)
  122. {
  123. distanceToSource = neighbour->distanceToSource + 1;
  124. flowOptions = (char)getOppositeDirection(dir);
  125. changed = true;
  126. }
  127. else if (distanceToSource == neighbour->distanceToSource + 1)
  128. {
  129. char tmp = flowOptions;
  130. flowOptions |= (char)getOppositeDirection(dir);
  131. changed |= tmp != flowOptions;
  132. }
  133. }
  134. }
  135. }
  136. if (changed)
  137. {
  138. broadcastModelInfoChange();
  139. neighborChanged = 1;
  140. for (int i = 0; i < 6; i++)
  141. {
  142. Direction dir = getDirectionFromIndex(i);
  143. if (dir & (Direction::TOP | Direction::BOTTOM)) continue;
  144. if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType())
  145. {
  146. FluidBlock* neighbour
  147. = dynamic_cast<FluidBlock*>(zNeighbours[i]);
  148. if (neighbour)
  149. {
  150. neighbour->neighborChanged = 1;
  151. }
  152. }
  153. }
  154. }
  155. }
  156. void FluidBlock::filterPassingLight(unsigned char rgb[3]) const
  157. {
  158. rgb[0] = (unsigned char)(rgb[0] * lightWeights.x);
  159. rgb[1] = (unsigned char)(rgb[1] * lightWeights.y);
  160. rgb[2] = (unsigned char)(rgb[2] * lightWeights.z);
  161. }
  162. char FluidBlock::getDistanceToSource() const
  163. {
  164. return distanceToSource;
  165. }
  166. char FluidBlock::getFlowOptions() const
  167. {
  168. return flowOptions;
  169. }
  170. FluidBlockType::FluidBlockType(int id,
  171. ModelInfo model,
  172. const char* name,
  173. int mapColor,
  174. Vec3<float> lightWeights,
  175. int ticktsToFlow,
  176. char flowDistance)
  177. : BlockType(id, 0, model, 1, 10, 0, name, true, mapColor),
  178. lightWeights(lightWeights),
  179. ticktsToFlow(ticktsToFlow),
  180. flowDistance(flowDistance)
  181. {}
  182. void FluidBlockType::loadSuperBlock(
  183. Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const
  184. {
  185. FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
  186. zReader->lese(&block->flowOptions, 1);
  187. zReader->lese(&block->distanceToSource, 1);
  188. block->nextFlow = ticktsToFlow;
  189. block->maxFlowDistance = flowDistance;
  190. BlockType::loadSuperBlock(zBlock, zReader, dimensionId);
  191. }
  192. void FluidBlockType::saveSuperBlock(
  193. Block* zBlock, Framework::StreamWriter* zWriter) const
  194. {
  195. FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
  196. zWriter->schreibe(&block->flowOptions, 1);
  197. zWriter->schreibe(&block->distanceToSource, 1);
  198. BlockType::saveSuperBlock(zBlock, zWriter);
  199. }
  200. Item* FluidBlockType::createItem() const
  201. {
  202. return 0;
  203. }
  204. Block* FluidBlockType::createBlock(
  205. Framework::Vec3<int> position, int dimensionId) const
  206. {
  207. FluidBlock* result
  208. = new FluidBlock(getId(), position, dimensionId, lightWeights);
  209. result->nextFlow = ticktsToFlow;
  210. result->maxFlowDistance = flowDistance;
  211. return result;
  212. }
  213. bool FluidBlockType::isFluid() const
  214. {
  215. return true;
  216. }
  217. int FluidBlockType::getTicktsToFlow() const
  218. {
  219. return ticktsToFlow;
  220. }
  221. char FluidBlockType::getFlowDistance() const
  222. {
  223. return flowDistance;
  224. }