123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- #include "FluidBlock.h"
- #include "FluidContainer.h"
- #include "Game.h"
- FluidBlock::FluidBlock(int typeId,
- Framework::Vec3<int> pos,
- int dimensionId,
- Vec3<float> lightWeights)
- : Block(typeId, 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<const FluidBlockType*>(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;
- int minNeighborDistance = maxFlowDistance;
- for (int i = 0; i < 6; i++)
- {
- Direction dir = getDirectionFromIndex(i);
- if (dir & Direction::TOP)
- {
- if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType())
- {
- FluidBlock* neighbour
- = dynamic_cast<FluidBlock*>(zNeighbours[i]);
- minNeighborDistance = 0;
- distanceToSource = neighbour->distanceToSource + 1;
- flowOptions = (char)getOppositeDirection(dir);
- changed = true;
- }
- 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<FluidBlock*>(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<FluidBlock*>(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 (neighbour->distanceToSource < minNeighborDistance)
- {
- minNeighborDistance = neighbour->distanceToSource;
- }
- }
- }
- }
- if (distanceToSource)
- {
- if (minNeighborDistance + 1 > distanceToSource)
- {
- distanceToSource = minNeighborDistance + 1;
- flowOptions = 0; // reavaluated next tick
- changed = true;
- }
- }
- if (distanceToSource > maxFlowDistance)
- {
- distanceToSource = maxFlowDistance;
- Game::INSTANCE->doLater([this]() { setHP(0.f); });
- }
- 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<FluidBlock*>(zNeighbours[i]);
- if (neighbour)
- {
- neighbour->neighborChanged = 1;
- }
- }
- }
- }
- }
- bool FluidBlock::isInteractable(const Item* zItem) const
- {
- return distanceToSource == 0
- && dynamic_cast<const FluidContainerItem*>(zItem);
- }
- 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(ModelInfo* model,
- Framework::Text name,
- int mapColor,
- Vec3<float> lightWeights,
- int ticktsToFlow,
- unsigned char flowDistance,
- float hpRecoveryPerL,
- float thirstRecoveryPerL,
- float heat,
- Framework::RCArray<Framework::Text> groupNames)
- : BlockType(0, model, 1, 10, 0, name, true, mapColor, groupNames, 0.f),
- lightWeights(lightWeights),
- ticktsToFlow(ticktsToFlow),
- flowDistance(flowDistance),
- hungerRecoveryPerL(hungerRecoveryPerL),
- thirstRecoveryPerL(thirstRecoveryPerL),
- heat(heat)
- {}
- void FluidBlockType::loadSuperBlock(
- Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const
- {
- FluidBlock* block = dynamic_cast<FluidBlock*>(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<FluidBlock*>(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<int> 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;
- }
- unsigned char FluidBlockType::getFlowDistance() const
- {
- return flowDistance;
- }
- Framework::Vec3<float> FluidBlockType::getLightWeights() const
- {
- return lightWeights;
- }
- float FluidBlockType::getHungerRecoveryPerL() const
- {
- return hungerRecoveryPerL;
- }
- float FluidBlockType::getThirstRecoveryPerL() const
- {
- return thirstRecoveryPerL;
- }
- ItemType* FluidBlockType::createItemType() const
- {
- return 0;
- }
- float FluidBlockType::getHeat() const
- {
- return heat;
- }
- FluidBlockTypeFactory::FluidBlockTypeFactory()
- : SubTypeFactory()
- {}
- FluidBlockType* FluidBlockTypeFactory::fromJson(
- Framework::JSON::JSONObject* zJson) const
- {
- Framework::RCArray<Framework::Text> groupNames;
- for (Framework::JSON::JSONValue* value :
- *zJson->zValue("groupNames")->asArray())
- {
- groupNames.add(new Framework::Text(value->asString()->getString()));
- }
- return new FluidBlockType(
- Game::INSTANCE->zTypeRegistry()->fromJson<ModelInfo>(
- zJson->zValue("model")),
- zJson->zValue("name")->asString()->getString(),
- (int)zJson->zValue("mapColor")->asString()->getString(),
- Framework::Vec3<float>((float)zJson->zValue("lightWeight")
- ->asObject()
- ->zValue("red")
- ->asNumber()
- ->getNumber(),
- (float)zJson->zValue("lightWeight")
- ->asObject()
- ->zValue("green")
- ->asNumber()
- ->getNumber(),
- (float)zJson->zValue("lightWeight")
- ->asObject()
- ->zValue("blue")
- ->asNumber()
- ->getNumber()),
- (int)zJson->zValue("ticksToFlow")->asNumber()->getNumber(),
- (char)zJson->zValue("flowDistance")->asNumber()->getNumber(),
- (float)zJson->zValue("hungerRecoveryPerL")->asNumber()->getNumber(),
- (float)zJson->zValue("thirstRecoveryPerL")->asNumber()->getNumber(),
- (float)zJson->zValue("heat")->asNumber()->getNumber(),
- groupNames);
- }
- Framework::JSON::JSONObject* FluidBlockTypeFactory::toJson(
- FluidBlockType* zObject) const
- {
- Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
- result->addValue(
- "model", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModel()));
- result->addValue(
- "name", new Framework::JSON::JSONString(zObject->getName()));
- result->addValue(
- "mapColor", new Framework::JSON::JSONString(zObject->getMapColor()));
- Framework::JSON::JSONObject* lightWeight
- = new Framework::JSON::JSONObject();
- lightWeight->addValue(
- "red", new Framework::JSON::JSONNumber(zObject->getLightWeights().x));
- lightWeight->addValue(
- "green", new Framework::JSON::JSONNumber(zObject->getLightWeights().y));
- lightWeight->addValue(
- "blue", new Framework::JSON::JSONNumber(zObject->getLightWeights().z));
- result->addValue("lightWeight", lightWeight);
- result->addValue("ticksToFlow",
- new Framework::JSON::JSONNumber((double)zObject->getTicktsToFlow()));
- result->addValue("flowDistance",
- new Framework::JSON::JSONNumber((double)zObject->getFlowDistance()));
- result->addValue("hungerRecoveryPerL",
- new Framework::JSON::JSONNumber(
- (double)zObject->getHungerRecoveryPerL()));
- result->addValue("thirstRecoveryPerL",
- new Framework::JSON::JSONNumber(
- (double)zObject->getThirstRecoveryPerL()));
- result->addValue("heat",
- new Framework::JSON::JSONNumber(
- (double)zObject->getHeat()));
- Framework::JSON::JSONArray* groupNames = new Framework::JSON::JSONArray();
- for (Framework::Text* groupName : zObject->getGroupNames())
- {
- groupNames->addValue(new Framework::JSON::JSONString(*groupName));
- }
- result->addValue("groupNames", groupNames);
- return result;
- }
- Framework::JSON::Validator::JSONValidator* FluidBlockTypeFactory::getValidator(
- Framework::JSON::Validator::ObjectValidationBuilder<
- Framework::JSON::Validator::JSONValidator>* builder) const
- {
- return builder
- ->withRequiredAttribute(
- "model", Game::INSTANCE->zTypeRegistry()->getValidator<ModelInfo>())
- ->withRequiredString("name")
- ->finishString()
- ->withRequiredString("mapColor")
- ->finishString()
- ->withRequiredObject("lightWeight")
- ->withRequiredNumber("red")
- ->whichIsGreaterOrEqual(0.0)
- ->whichIsLessOrEqual(1.0)
- ->finishNumber()
- ->withRequiredNumber("green")
- ->whichIsGreaterOrEqual(0.0)
- ->whichIsLessOrEqual(1.0)
- ->finishNumber()
- ->withRequiredNumber("blue")
- ->whichIsGreaterOrEqual(0.0)
- ->whichIsLessOrEqual(1.0)
- ->finishNumber()
- ->finishObject()
- ->withRequiredNumber("ticksToFlow")
- ->whichIsGreaterOrEqual(1.0)
- ->finishNumber()
- ->withRequiredNumber("flowDistance")
- ->whichIsGreaterOrEqual(0.0)
- ->finishNumber()
- ->withRequiredNumber("hungerRecoveryPerL")
- ->whichIsGreaterOrEqual(0.0)
- ->withDefault(0.0)
- ->finishNumber()
- ->withRequiredNumber("thirstRecoveryPerL")
- ->whichIsGreaterOrEqual(0.0)
- ->withDefault(0.0)
- ->finishNumber()
- ->withRequiredNumber("heat")
- ->withDefault(10.0)
- ->finishNumber()
- ->withRequiredArray("groupNames")
- ->withDefault(new Framework::JSON::JSONArray())
- ->addAcceptedStringInArray()
- ->finishString()
- ->finishArray()
- ->finishObject();
- }
- Framework::Text FluidBlockTypeFactory::getTypeToken() const
- {
- return "fluid";
- }
|