123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #include "FluidBlock.h"
- #include "Game.h"
- FluidBlock::FluidBlock(int typeId,
- Framework::Vec3<int> pos,
- int dimensionId,
- Vec3<float> lightWeights)
- : Block(typeId, 0, pos, dimensionId, 0),
- lightWeights(lightWeights)
- {
- transparent = 1;
- passable = 1;
- hp = 1;
- maxHP = 1;
- hardness = -1.f;
- speedModifier = 0.5f;
- tickSource = 1;
- interactable = 0;
- fluidAmount = 0;
- lastBroadcastedAmount = fluidAmount;
- }
- FluidBlock::~FluidBlock() {}
- bool FluidBlock::onTick(TickQueue* zQueue, int numTicks, bool& blocked)
- {
- nextFlow = 0;
- int bottom = neighbourTypes[getDirectionIndex(Direction::BOTTOM)];
- if (bottom == BlockTypeEnum::AIR)
- {
- nextFlow |= 1 << getDirectionIndex(Direction::BOTTOM);
- }
- else
- {
- if (zNeighbours[getDirectionIndex(Direction::BOTTOM)]
- && bottom == zBlockType()->getId())
- {
- Inventory* array[2]
- = {zNeighbours[getDirectionIndex(Direction::BOTTOM)], this};
- MultipleInventoryLock lock(array, 2);
- FluidBlock* below = dynamic_cast<FluidBlock*>(
- zNeighbours[getDirectionIndex(Direction::BOTTOM)]);
- if (below->fluidAmount < 1000)
- {
- short transferAmount = (short)MIN(
- this->fluidAmount, (short)1000 - below->fluidAmount);
- below->fluidAmount
- = (short)(below->fluidAmount + transferAmount);
- this->fluidAmount = (short)(this->fluidAmount - transferAmount);
- }
- }
- short neighborCount = 0;
- Inventory* others[4];
- for (int i = 0; i < 6; i++)
- {
- if (getDirectionFromIndex(i) != Direction::BOTTOM
- && getDirectionFromIndex(i) != Direction::TOP)
- {
- if (neighbourTypes[i] == typeId && zNeighbours[i])
- {
- others[neighborCount] = zNeighbours[i];
- neighborCount++;
- }
- }
- }
- if (neighborCount > 0)
- {
- Inventory* array[5]
- = {this, others[0], others[1], others[2], others[3]};
- MultipleInventoryLock lock(array, neighborCount + 1);
- // all neighbot fluid blocks are locked now
- FluidBlock* otherFluids[4];
- for (int i = 0; i < neighborCount; i++)
- {
- otherFluids[i] = dynamic_cast<FluidBlock*>(others[i]);
- }
- // order other fluids increasing by fluid amount
- sortByAmound(otherFluids, neighborCount);
- short distCount = 0;
- short targetAmount = 0;
- for (int i = 1; i <= neighborCount; i++)
- {
- int fluidAmount = this->fluidAmount;
- for (int j = 0; j < i; j++)
- {
- fluidAmount += otherFluids[j]->fluidAmount;
- }
- if (fluidAmount / (i + 1) < this->fluidAmount)
- {
- targetAmount = (short)(fluidAmount / (i + 1));
- distCount = (short)i;
- }
- else
- {
- break;
- }
- }
- for (int i = 0; i < distCount; i++)
- {
- short transferAmount
- = (short)(targetAmount - otherFluids[i]->fluidAmount);
- otherFluids[i]->fluidAmount
- = (short)(otherFluids[i]->fluidAmount + transferAmount);
- this->fluidAmount = (short)(this->fluidAmount - transferAmount);
- }
- } // unlock
- neighborCount = 0;
- for (int i = 0; i < 6; i++)
- {
- if (getDirectionFromIndex(i) != Direction::BOTTOM
- && getDirectionFromIndex(i) != Direction::TOP)
- {
- int neighbor = neighbourTypes[i];
- if (neighbor == BlockTypeEnum::AIR
- && fluidAmount > neighborCount + 1)
- {
- nextFlow |= 1 << i;
- neighborCount++;
- }
- }
- }
- }
- return 1;
- }
- void FluidBlock::sendModelInfo(NetworkMessage* zMessage)
- {
- zMessage->addressBlock(this);
- char* msg = new char[3];
- msg[0] = 2; // fluid amount change
- *(short*)(msg + 1) = fluidAmount;
- zMessage->setMessage(msg, 3);
- }
- void FluidBlock::broadcastAmount()
- {
- if (lastBroadcastedAmount != fluidAmount)
- {
- lastBroadcastedAmount = fluidAmount;
- NetworkMessage* changeMsg = new NetworkMessage();
- sendModelInfo(changeMsg);
- Game::INSTANCE->broadcastMessage(changeMsg);
- }
- }
- void FluidBlock::onPostTick()
- {
- if (nextFlow != 0)
- {
- Game::INSTANCE->doLater([this]() {
- for (int i = 0; i < 6; i++)
- {
- if ((nextFlow | (1 << i)) == nextFlow)
- {
- Vec3<int> pos
- = getPos() + getDirection(getDirectionFromIndex(i));
- if (neighbourTypes[i] == BlockTypeEnum::AIR)
- {
- FluidBlock* spawn = new FluidBlock(
- typeId, pos, dimensionId, lightWeights);
- spawn->fluidAmount = 1;
- Game::INSTANCE->zDimension(getDimensionId())
- ->placeBlock(pos, spawn);
- fluidAmount--;
- }
- }
- }
- if (fluidAmount == 0)
- {
- Game::INSTANCE->zDimension(getDimensionId())
- ->placeBlock(getPos(),
- StaticRegistry<BlockType>::INSTANCE
- .zElement(BlockTypeEnum::AIR)
- ->createBlockAt(getPos(), dimensionId, 0));
- }
- else
- {
- broadcastAmount();
- }
- });
- }
- }
- void FluidBlock::sortByAmound(FluidBlock** array, int count)
- {
- if (count == 2)
- {
- if (array[0]->fluidAmount > array[1]->fluidAmount)
- {
- FluidBlock* tmp = array[0];
- array[0] = array[1];
- array[1] = tmp;
- }
- }
- else if (count == 3)
- {
- if (array[0]->fluidAmount > array[1]->fluidAmount)
- {
- FluidBlock* tmp = array[0];
- array[0] = array[1];
- array[1] = tmp;
- }
- if (array[1]->fluidAmount > array[2]->fluidAmount)
- {
- FluidBlock* tmp = array[1];
- array[1] = array[2];
- array[2] = tmp;
- }
- if (array[0]->fluidAmount > array[1]->fluidAmount)
- {
- FluidBlock* tmp = array[0];
- array[0] = array[1];
- array[1] = tmp;
- }
- }
- else if (count == 4)
- {
- if (array[0]->fluidAmount > array[1]->fluidAmount)
- {
- FluidBlock* tmp = array[0];
- array[0] = array[1];
- array[1] = tmp;
- }
- if (array[2]->fluidAmount > array[3]->fluidAmount)
- {
- FluidBlock* tmp = array[2];
- array[2] = array[3];
- array[3] = tmp;
- }
- if (array[0]->fluidAmount > array[2]->fluidAmount)
- {
- FluidBlock* tmp = array[0];
- array[0] = array[2];
- array[2] = tmp;
- }
- if (array[1]->fluidAmount > array[3]->fluidAmount)
- {
- FluidBlock* tmp = array[1];
- array[1] = array[3];
- array[3] = tmp;
- }
- if (array[1]->fluidAmount > array[2]->fluidAmount)
- {
- FluidBlock* tmp = array[1];
- array[1] = array[2];
- array[2] = tmp;
- }
- }
- }
- 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);
- }
- short FluidBlock::getFluidAmount() const
- {
- return fluidAmount;
- }
- FluidBlockType::FluidBlockType(int id,
- ModelInfo model,
- const char* name,
- int mapColor,
- Vec3<float> lightWeights)
- : BlockType(id, 0, model, 1, 10, 0, name, true, mapColor),
- lightWeights(lightWeights)
- {}
- void FluidBlockType::loadSuperBlock(
- Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const
- {
- FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
- zReader->lese((char*)&block->fluidAmount, 2);
- BlockType::loadSuperBlock(zBlock, zReader, dimensionId);
- }
- void FluidBlockType::saveSuperBlock(
- Block* zBlock, Framework::StreamWriter* zWriter) const
- {
- FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
- zWriter->schreibe((char*)&block->fluidAmount, 2);
- 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->fluidAmount = 1000;
- return result;
- }
- bool FluidBlockType::isFluid() const
- {
- return true;
- }
|