#include "FluidBlock.h" #include "Game.h" FluidBlock::FluidBlock(int typeId, Framework::Vec3 pos, int dimensionId, Vec3 lightWeights) : Block(typeId, 0, pos, dimensionId, 0), lightWeights(lightWeights), neighborChanged(1), nextFlow(0), maxFlowDistance(8) { transparent = 1; passable = 1; hp = 1; maxHP = 1; hardness = -1.f; speedModifier = 0.5f; tickSource = 1; interactable = 0; flowOptions = 0; distanceToSource = 0; } FluidBlock::~FluidBlock() {} bool FluidBlock::onTick(TickQueue* zQueue, int numTicks, bool& blocked) { if (neighborChanged) { nextFlow -= numTicks; if (nextFlow <= 0) { const FluidBlockType* zType = dynamic_cast(zBlockType()); if (zType) { nextFlow = zType->getTicktsToFlow(); } else { nextFlow = 0; } neighborChanged = 0; doFlow(); } return true; } return false; } void FluidBlock::onPostTick() {} void FluidBlock::setNeighbourType(Direction dir, int type) { Block::setNeighbourType(dir, type); neighborChanged = 1; } void FluidBlock::sendModelInfo(NetworkMessage* zMessage) { zMessage->addressBlock(this); char* msg = new char[3]; msg[0] = 2; // fluid amount change *(msg + 1) = flowOptions; *(msg + 2) = distanceToSource; zMessage->setMessage(msg, 3); } void FluidBlock::doFlow() { bool doesFlowSidewards = 1; if (((zNeighbours[getDirectionIndex(Direction::BOTTOM)] && zNeighbours[getDirectionIndex(Direction::BOTTOM)] ->zBlockType() == zBlockType() || neighbourTypes[getDirectionIndex(Direction::BOTTOM)] == BlockTypeEnum::AIR) && distanceToSource) || distanceToSource >= maxFlowDistance) { doesFlowSidewards = 0; } bool changed = false; for (int i = 0; i < 6; i++) { Direction dir = getDirectionFromIndex(i); if (dir & Direction::TOP) continue; if (neighbourTypes[i] == BlockTypeEnum::AIR) { if (dir & Direction::BOTTOM || doesFlowSidewards) { Game::INSTANCE->doLater([this, dir, i]() { if (neighbourTypes[i] == BlockTypeEnum::AIR) { Block* belowBlock = zBlockType()->createBlockAt( getPos() + getDirection(dir), getDimensionId(), 0); FluidBlock* fluidBlock = dynamic_cast(belowBlock); if (fluidBlock) { fluidBlock->distanceToSource = dir & Direction::BOTTOM ? 1 : distanceToSource + 1; fluidBlock->flowOptions = (char)dir; Game::INSTANCE->zDimension(getDimensionId()) ->placeBlock( getPos() + getDirection(dir), belowBlock); } else { std::cout << "ERROR: created flow fuild block is not an " "instance of FluidBlock\n"; belowBlock->release(); } } }); } } else if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType()) { if (dir & Direction::BOTTOM) continue; FluidBlock* neighbour = dynamic_cast(zNeighbours[i]); if (neighbour) { if (distanceToSource > neighbour->distanceToSource + 1) { distanceToSource = neighbour->distanceToSource + 1; flowOptions = (char)getOppositeDirection(dir); changed = true; } else if (distanceToSource == neighbour->distanceToSource + 1) { char tmp = flowOptions; flowOptions |= (char)getOppositeDirection(dir); changed |= tmp != flowOptions; } } } } if (changed) { broadcastModelInfoChange(); neighborChanged = 1; for (int i = 0; i < 6; i++) { Direction dir = getDirectionFromIndex(i); if (dir & (Direction::TOP | Direction::BOTTOM)) continue; if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType()) { FluidBlock* neighbour = dynamic_cast(zNeighbours[i]); if (neighbour) { neighbour->neighborChanged = 1; } } } } } void FluidBlock::filterPassingLight(unsigned char rgb[3]) const { rgb[0] = (unsigned char)(rgb[0] * lightWeights.x); rgb[1] = (unsigned char)(rgb[1] * lightWeights.y); rgb[2] = (unsigned char)(rgb[2] * lightWeights.z); } char FluidBlock::getDistanceToSource() const { return distanceToSource; } char FluidBlock::getFlowOptions() const { return flowOptions; } FluidBlockType::FluidBlockType(int id, ModelInfo model, const char* name, int mapColor, Vec3 lightWeights, int ticktsToFlow, char flowDistance) : BlockType(id, 0, model, 1, 10, 0, name, true, mapColor), lightWeights(lightWeights), ticktsToFlow(ticktsToFlow), flowDistance(flowDistance) {} void FluidBlockType::loadSuperBlock( Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const { FluidBlock* block = dynamic_cast(zBlock); zReader->lese(&block->flowOptions, 1); zReader->lese(&block->distanceToSource, 1); block->nextFlow = ticktsToFlow; block->maxFlowDistance = flowDistance; BlockType::loadSuperBlock(zBlock, zReader, dimensionId); } void FluidBlockType::saveSuperBlock( Block* zBlock, Framework::StreamWriter* zWriter) const { FluidBlock* block = dynamic_cast(zBlock); zWriter->schreibe(&block->flowOptions, 1); zWriter->schreibe(&block->distanceToSource, 1); BlockType::saveSuperBlock(zBlock, zWriter); } Item* FluidBlockType::createItem() const { return 0; } Block* FluidBlockType::createBlock( Framework::Vec3 position, int dimensionId) const { FluidBlock* result = new FluidBlock(getId(), position, dimensionId, lightWeights); result->nextFlow = ticktsToFlow; result->maxFlowDistance = flowDistance; return result; } bool FluidBlockType::isFluid() const { return true; } int FluidBlockType::getTicktsToFlow() const { return ticktsToFlow; } char FluidBlockType::getFlowDistance() const { return flowDistance; }