FluidBlock.cpp 6.5 KB

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