Kolja Strohm 9 місяців тому
батько
коміт
8f9b619f15

+ 1 - 1
.gitignore

@@ -365,4 +365,4 @@ FodyWeavers.xsd
 /Windows Version/cert.crt
 /Windows Version/cert.key
 *.dll
-/enc_temp_folder/b9c178f2419744cd34d8a85c0ed08c
+/enc_temp_folder

+ 10 - 0
FactoryCraft/BlockType.cpp

@@ -233,6 +233,11 @@ void BlockType::writeTypeInfo(StreamWriter* zWriter) const
     zWriter->schreibe((char*)&sub, 1);
     bool fluid = isFluid();
     zWriter->schreibe((char*)&fluid, 1);
+    if (fluid)
+    {
+        char flowDist = getFlowDistance();
+        zWriter->schreibe(&flowDist, 1);
+    }
     int maxHp = getInitialMaxHP();
     zWriter->schreibe((char*)&maxHp, 4);
     getModel().writeTo(zWriter);
@@ -266,3 +271,8 @@ Framework::Text BlockType::getTypeName(int id)
     }
     return 0;
 }
+
+char BlockType::getFlowDistance() const
+{
+    return 0;
+}

+ 1 - 0
FactoryCraft/BlockType.h

@@ -106,6 +106,7 @@ public:
 
     static int getTypeId(const char* name);
     static Framework::Text getTypeName(int id);
+    virtual char getFlowDistance() const;
 };
 
 const Block* getDefaultBlock(Framework::Either<Block*, int> b);

+ 6 - 7
FactoryCraft/Chunk.cpp

@@ -876,13 +876,12 @@ void Chunk::sendToClient(Framework::StreamWriter* zWriter)
                             .zElement(blockIds[index])
                             ->isFluid())
                     {
-                        short amount = 1000;
-                        if (blocks[index])
-                        {
-                            amount = dynamic_cast<FluidBlock*>(blocks[index])
-                                         ->getFluidAmount();
-                        }
-                        zWriter->schreibe((char*)&amount, 2);
+                        FluidBlock* fluidBlock
+                            = dynamic_cast<FluidBlock*>(blocks[index]);
+                        char data = fluidBlock->getFlowOptions();
+                        zWriter->schreibe(&data, 1);
+                        data = fluidBlock->getDistanceToSource();
+                        zWriter->schreibe(&data, 1);
                     }
                 }
             }

+ 126 - 196
FactoryCraft/FluidBlock.cpp

@@ -7,7 +7,10 @@ FluidBlock::FluidBlock(int typeId,
     int dimensionId,
     Vec3<float> lightWeights)
     : Block(typeId, 0, pos, dimensionId, 0),
-      lightWeights(lightWeights)
+      lightWeights(lightWeights),
+      neighborChanged(1),
+      nextFlow(0),
+      maxFlowDistance(8)
 {
     transparent = 1;
     passable = 1;
@@ -17,111 +20,43 @@ FluidBlock::FluidBlock(int typeId,
     speedModifier = 0.5f;
     tickSource = 1;
     interactable = 0;
-    fluidAmount = 0;
-    lastBroadcastedAmount = fluidAmount;
+    flowOptions = 0;
+    distanceToSource = 0;
 }
 
 FluidBlock::~FluidBlock() {}
 
 bool FluidBlock::onTick(TickQueue* zQueue, int numTicks, bool& blocked)
 {
-    nextFlow = 0;
-    int bottom = neighbourTypes[getDirectionIndex(Direction::BOTTOM)];
-    if (bottom == BlockTypeEnum::AIR)
+    if (neighborChanged)
     {
-        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)
+        nextFlow -= numTicks;
+        if (nextFlow <= 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++)
+            const FluidBlockType* zType
+                = dynamic_cast<const FluidBlockType*>(zBlockType());
+            if (zType)
             {
-                otherFluids[i] = dynamic_cast<FluidBlock*>(others[i]);
+                nextFlow = zType->getTicktsToFlow();
             }
-            // 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)
+            else
             {
-                int neighbor = neighbourTypes[i];
-                if (neighbor == BlockTypeEnum::AIR
-                    && fluidAmount > neighborCount + 1)
-                {
-                    nextFlow |= 1 << i;
-                    neighborCount++;
-                }
+                nextFlow = 0;
             }
+            neighborChanged = 0;
+            doFlow();
         }
+        return true;
     }
-    return 1;
+    return false;
+}
+
+void FluidBlock::onPostTick() {}
+
+void FluidBlock::setNeighbourType(Direction dir, int type)
+{
+    Block::setNeighbourType(dir, type);
+    neighborChanged = 1;
 }
 
 void FluidBlock::sendModelInfo(NetworkMessage* zMessage)
@@ -129,122 +64,93 @@ void FluidBlock::sendModelInfo(NetworkMessage* zMessage)
     zMessage->addressBlock(this);
     char* msg = new char[3];
     msg[0] = 2; // fluid amount change
-    *(short*)(msg + 1) = fluidAmount;
+    *(msg + 1) = flowOptions;
+    *(msg + 2) = distanceToSource;
     zMessage->setMessage(msg, 3);
 }
 
-void FluidBlock::broadcastAmount()
+void FluidBlock::broadcastFlow()
 {
-    if (lastBroadcastedAmount != fluidAmount)
-    {
-        lastBroadcastedAmount = fluidAmount;
-        NetworkMessage* changeMsg = new NetworkMessage();
-        sendModelInfo(changeMsg);
-        Game::INSTANCE->broadcastMessage(changeMsg);
-    }
+    NetworkMessage* changeMsg = new NetworkMessage();
+    sendModelInfo(changeMsg);
+    Game::INSTANCE->broadcastMessage(changeMsg);
 }
 
-void FluidBlock::onPostTick()
+void FluidBlock::doFlow()
 {
-    if (nextFlow != 0)
+    bool changed = false;
+    for (int i = 0; i < 6; i++)
     {
-        Game::INSTANCE->doLater([this]() {
-            for (int i = 0; i < 6; i++)
-            {
-                if ((nextFlow | (1 << i)) == nextFlow)
+        Direction dir = getDirectionFromIndex(i);
+        if (dir & Direction::TOP) continue;
+        if (neighbourTypes[i] == BlockTypeEnum::AIR)
+        {
+            Game::INSTANCE->doLater([this, dir, i]() {
+                if (neighbourTypes[i] == BlockTypeEnum::AIR)
                 {
-                    Vec3<int> pos
-                        = getPos() + getDirection(getDirectionFromIndex(i));
-                    if (neighbourTypes[i] == BlockTypeEnum::AIR)
+                    Block* belowBlock = zBlockType()->createBlockAt(
+                        getPos() + getDirection(dir), getDimensionId(), 0);
+                    FluidBlock* fluidBlock
+                        = dynamic_cast<FluidBlock*>(belowBlock);
+                    if (fluidBlock)
                     {
-                        FluidBlock* spawn = new FluidBlock(
-                            typeId, pos, dimensionId, lightWeights);
-                        spawn->fluidAmount = 1;
+                        fluidBlock->distanceToSource
+                            = dir & Direction::BOTTOM
+                                ? 1
+                                : distanceToSource + 1;
+                        fluidBlock->flowOptions = (char)dir;
                         Game::INSTANCE->zDimension(getDimensionId())
-                            ->placeBlock(pos, spawn);
-                        fluidAmount--;
+                            ->placeBlock(
+                                getPos() + getDirection(dir), belowBlock);
+                    }
+                    else
+                    {
+                        std::cout
+                            << "ERROR: created flow fuild block is not an "
+                                "instance of FluidBlock\n";
+                        belowBlock->release();
                     }
                 }
-            }
-            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)
+        else if (zNeighbours[i] && zNeighbours[i]->zBlockType() == zBlockType())
         {
-            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;
+            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;
+                }
+            }
         }
     }
-    else if (count == 4)
+    if (changed)
     {
-        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)
+        broadcastFlow();
+        neighborChanged = 1;
+        for (int i = 0; i < 6; i++)
         {
-            FluidBlock* tmp = array[1];
-            array[1] = array[2];
-            array[2] = tmp;
+            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;
+                }
+            }
         }
     }
 }
@@ -256,25 +162,37 @@ void FluidBlock::filterPassingLight(unsigned char rgb[3]) const
     rgb[2] = (unsigned char)(rgb[2] * lightWeights.z);
 }
 
-short FluidBlock::getFluidAmount() const
+char FluidBlock::getDistanceToSource() const
 {
-    return fluidAmount;
+    return distanceToSource;
+}
+
+char FluidBlock::getFlowOptions() const
+{
+    return flowOptions;
 }
 
 FluidBlockType::FluidBlockType(int id,
     ModelInfo model,
     const char* name,
     int mapColor,
-    Vec3<float> lightWeights)
+    Vec3<float> lightWeights,
+    int ticktsToFlow,
+    char flowDistance)
     : BlockType(id, 0, model, 1, 10, 0, name, true, mapColor),
-      lightWeights(lightWeights)
+      lightWeights(lightWeights),
+      ticktsToFlow(ticktsToFlow),
+      flowDistance(flowDistance)
 {}
 
 void FluidBlockType::loadSuperBlock(
     Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const
 {
     FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
-    zReader->lese((char*)&block->fluidAmount, 2);
+    zReader->lese(&block->flowOptions, 1);
+    zReader->lese(&block->distanceToSource, 1);
+    block->nextFlow = ticktsToFlow;
+    block->maxFlowDistance = flowDistance;
     BlockType::loadSuperBlock(zBlock, zReader, dimensionId);
 }
 
@@ -282,7 +200,8 @@ void FluidBlockType::saveSuperBlock(
     Block* zBlock, Framework::StreamWriter* zWriter) const
 {
     FluidBlock* block = dynamic_cast<FluidBlock*>(zBlock);
-    zWriter->schreibe((char*)&block->fluidAmount, 2);
+    zWriter->schreibe(&block->flowOptions, 1);
+    zWriter->schreibe(&block->distanceToSource, 1);
     BlockType::saveSuperBlock(zBlock, zWriter);
 }
 
@@ -296,11 +215,22 @@ Block* FluidBlockType::createBlock(
 {
     FluidBlock* result
         = new FluidBlock(getId(), position, dimensionId, lightWeights);
-    result->fluidAmount = 1000;
+    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;
 }

+ 16 - 7
FactoryCraft/FluidBlock.h

@@ -8,17 +8,19 @@ class FluidBlockType;
 class FluidBlock : public Block
 {
 private:
-    Directions flowDir;
-    short fluidAmount;
-    short lastBroadcastedAmount;
+    char flowOptions;
+    char distanceToSource;
     int nextFlow;
     Framework::Vec3<float> lightWeights;
+    bool neighborChanged;
+    char maxFlowDistance;
 
 protected:
     virtual bool onTick(
         TickQueue* zQueue, int numTicks, bool& blocked) override;
     virtual void onPostTick() override;
-    void broadcastAmount();
+    void broadcastFlow();
+    void doFlow();
 
 public:
     FluidBlock(int typeId,
@@ -27,12 +29,13 @@ public:
         Framework::Vec3<float> lightWeights);
     virtual ~FluidBlock();
 
+    virtual void setNeighbourType(Direction dir, int type) override;
     virtual void sendModelInfo(NetworkMessage* zMessage) override;
-    static void sortByAmound(FluidBlock** array, int count);
 
     virtual void filterPassingLight(unsigned char rgb[3]) const override;
 
-    short getFluidAmount() const;
+    char getDistanceToSource() const;
+    char getFlowOptions() const;
 
     friend FluidBlockType;
 };
@@ -41,6 +44,8 @@ class FluidBlockType : public BlockType
 {
 private:
     Framework::Vec3<float> lightWeights;
+    int ticktsToFlow;
+    char flowDistance;
 
 protected:
     virtual void loadSuperBlock(Block* zBlock,
@@ -57,7 +62,11 @@ public:
         ModelInfo model,
         const char* name,
         int mapColor,
-        Framework::Vec3<float> lightWeights);
+        Framework::Vec3<float> lightWeights,
+        int ticktsToFlow,
+        char flowDistance);
 
     bool isFluid() const override;
+    int getTicktsToFlow() const;
+    char getFlowDistance() const override;
 };

+ 5 - 1
FactoryCraft/NetworkMessage.cpp

@@ -234,7 +234,7 @@ void NetworkMessage::syncTime(
 void NetworkMessage::writeTo(Framework::StreamWriter* zWriter) const
 {
     int total = msgLength + addressLength;
-    if (total)
+    if (total > 0)
     {
         zWriter->schreibe((char*)&GameClient::Message::API_MESSAGE, 1);
         zWriter->schreibe((char*)&total, 4);
@@ -242,6 +242,10 @@ void NetworkMessage::writeTo(Framework::StreamWriter* zWriter) const
         zWriter->schreibe(message, msgLength);
         if (onAfterSend) onAfterSend();
     }
+    else
+    {
+        std::cout << "ERROR: invalid message was queued\n";
+    }
 }
 
 bool NetworkMessage::isBroadcast() const

+ 1 - 1
FactoryCraft/StaticInitializerOrder.cpp

@@ -284,7 +284,7 @@ void initializeBlockTypes()
          ModelInfo("fluid", "fluids.ltdb/water.png", 6),
          "Water",
          0xFF2323BF,
-         Vec3<float>(0.8f, 0.8f, 0.95f)))
+         Vec3<float>(0.8f, 0.8f, 0.95f), 20, 8))
         ->initializeDefault();
     (new BasicBlockType(BlockTypeEnum::CRAFTING_TABLE,
          ItemTypeEnum::CRAFTING_TABLE,

+ 1 - 1
FactoryCraft/WorldUpdate.cpp

@@ -26,5 +26,5 @@ int WorldUpdate::getType() const
 
 int WorldUpdate::distanceTo(int x, int y) const
 {
-    return pos.abstand(Framework::Vec3<float>((float)x, (float)y, pos.z));
+    return (int)pos.abstand(Framework::Vec3<float>((float)x, (float)y, pos.z));
 }

+ 4 - 2
NoiseTest/NoiseTest.cpp

@@ -41,10 +41,12 @@ void updateView()
 {
     Vec3<int> minP
         = position
-        - Vec3<float>(img->getBreite() / 2, img->getHeight() / 2, 0) / zoom;
+        - (Vec3<int>)Vec3<float>((float)img->getBreite() / 2.f, (float)img->getHeight() / 2.f, 0.f) / zoom;
     Vec3<int> maxP
         = position
-        + Vec3<float>(img->getBreite() / 2, img->getHeight() / 2, 0) / zoom;
+        + (Vec3<int>)Vec3<float>(
+              (float)img->getBreite() / 2.f, (float)img->getHeight() / 2.f, 0.f)
+              / zoom;
     int counter = 0;
     double min = INFINITY;
     double max = -INFINITY;