Browse Source

add FloadDistributions to allow plants with a variety of heights

Kolja Strohm 2 weeks ago
parent
commit
9abb131634

+ 2 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -120,6 +120,7 @@
     <ClInclude Include="FactorizeNoise.h" />
     <ClInclude Include="FireBasedProcessingBlockComponent.h" />
     <ClInclude Include="FlattenNoise.h" />
+    <ClInclude Include="FloatDistribution.h" />
     <ClInclude Include="FluidContainer.h" />
     <ClInclude Include="GameClient.h" />
     <ClInclude Include="GeneratorRule.h" />
@@ -275,6 +276,7 @@
     <ClCompile Include="FastNoiseWrapper.cpp" />
     <ClCompile Include="FireBasedProcessingBlockComponent.cpp" />
     <ClCompile Include="FlattenNoise.cpp" />
+    <ClCompile Include="FloatDistribution.cpp" />
     <ClCompile Include="FluidBlock.cpp" />
     <ClCompile Include="FluidContainer.cpp" />
     <ClCompile Include="Game.cpp" />

+ 9 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -130,6 +130,9 @@
     <Filter Include="UI\Builder">
       <UniqueIdentifier>{e4ccd6d2-96b0-442e-81d3-ae23ce66d438}</UniqueIdentifier>
     </Filter>
+    <Filter Include="world\generator\distribution">
+      <UniqueIdentifier>{df18d1ea-0c12-41b8-8a3d-f8aef3d637e0}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Chunk.h">
@@ -520,6 +523,9 @@
     <ClInclude Include="SpecificItemDrop.h">
       <Filter>drops\implementations</Filter>
     </ClInclude>
+    <ClInclude Include="FloatDistribution.h">
+      <Filter>world\generator\distribution</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
@@ -895,5 +901,8 @@
       <Filter>world\generator\biom\plants</Filter>
     </ClCompile>
     <ClCompile Include="Orientation.cpp" />
+    <ClCompile Include="FloatDistribution.cpp">
+      <Filter>world\generator\distribution</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 120 - 0
FactoryCraft/FloatDistribution.cpp

@@ -0,0 +1,120 @@
+#include "FloatDistribution.h"
+
+#include "Noise.h"
+
+FloatDistribution::FloatDistribution()
+    : Framework::ReferenceCounter()
+{}
+
+ConstantFloatDistribution::ConstantFloatDistribution(float value)
+    : FloatDistribution(),
+      value(value)
+{}
+
+float ConstantFloatDistribution::getValue(
+    int x, int y, int z, int dimenstionId, Noise* zNoise) const
+{
+    return value;
+}
+
+float ConstantFloatDistribution::getValue() const
+{
+    return value;
+}
+
+ConstantFloatDistributionFactory::ConstantFloatDistributionFactory()
+    : SubTypeFactory()
+{}
+
+JSONObjectValidationBuilder* ConstantFloatDistributionFactory::addToValidator(
+    JSONObjectValidationBuilder* builder) const
+{
+    return builder->withRequiredNumber("value")->finishNumber();
+}
+
+ConstantFloatDistribution* ConstantFloatDistributionFactory::fromJson(
+    Framework::JSON::JSONObject* zJson) const
+{
+    return new ConstantFloatDistribution(
+        (float)zJson->zValue("value")->asNumber()->getNumber());
+}
+
+Framework::JSON::JSONObject* ConstantFloatDistributionFactory::toJsonObject(
+    ConstantFloatDistribution* zObject) const
+{
+    Framework::JSON::JSONObject* zJson = new Framework::JSON::JSONObject();
+    zJson->addValue(
+        "value", new Framework::JSON::JSONNumber(zObject->getValue()));
+    return zJson;
+}
+
+const char* ConstantFloatDistributionFactory::getTypeToken() const
+{
+    return "constant";
+}
+
+EqualyDistributedFloatDistribution::EqualyDistributedFloatDistribution(
+    float minValue, float maxValue)
+    : FloatDistribution(),
+      minValue(minValue),
+      maxValue(maxValue)
+{}
+
+float EqualyDistributedFloatDistribution::getValue(
+    int x, int y, int z, int dimenstionId, Noise* zNoise) const
+{
+    return zNoise->getNoise((float)z, (float)x, (float)y)
+             * (maxValue - minValue)
+         + minValue;
+}
+
+float EqualyDistributedFloatDistribution::getMinValue() const
+{
+    return minValue;
+}
+
+float EqualyDistributedFloatDistribution::getMaxValue() const
+{
+    return maxValue;
+}
+
+EqualyDistributedFloatDistributionFactory::
+    EqualyDistributedFloatDistributionFactory()
+    : SubTypeFactory()
+{}
+
+JSONObjectValidationBuilder*
+EqualyDistributedFloatDistributionFactory::addToValidator(
+    JSONObjectValidationBuilder* builder) const
+{
+    return builder->withRequiredNumber("minValue")
+        ->finishNumber()
+        ->withRequiredNumber("maxValue")
+        ->finishNumber();
+}
+
+EqualyDistributedFloatDistribution*
+EqualyDistributedFloatDistributionFactory::fromJson(
+    Framework::JSON::JSONObject* zJson) const
+{
+    return new EqualyDistributedFloatDistribution(
+        (float)zJson->zValue("minValue")->asNumber()->getNumber(),
+        (float)zJson->zValue("maxValue")->asNumber()->getNumber());
+}
+
+Framework::JSON::JSONObject*
+EqualyDistributedFloatDistributionFactory::toJsonObject(
+    EqualyDistributedFloatDistribution* zObject) const
+{
+    Framework::JSON::JSONObject* zJson = new Framework::JSON::JSONObject();
+    zJson->addValue(
+        "minValue", new Framework::JSON::JSONNumber(zObject->getMinValue()));
+    zJson->addValue(
+        "maxValue", new Framework::JSON::JSONNumber(zObject->getMaxValue()));
+    return zJson;
+}
+
+const char* EqualyDistributedFloatDistributionFactory::getTypeToken() const
+{
+    return "equalyDistributed";
+}

+ 72 - 0
FactoryCraft/FloatDistribution.h

@@ -0,0 +1,72 @@
+#pragma once
+
+#include "TypeRegistry.h"
+
+class Noise;
+
+class FloatDistribution : public Framework::ReferenceCounter
+{
+public:
+    FloatDistribution();
+    virtual ~FloatDistribution() = default;
+    virtual float getValue(
+        int x, int y, int z, int dimenstionId, Noise* zNoise) const
+        = 0;
+};
+
+class ConstantFloatDistribution : public FloatDistribution
+{
+private:
+    float value;
+
+public:
+    ConstantFloatDistribution(float value);
+    float getValue(
+        int x, int y, int z, int dimenstionId, Noise* zNoise) const override;
+
+    float getValue() const;
+};
+
+class ConstantFloatDistributionFactory
+    : public SubTypeFactory<FloatDistribution, ConstantFloatDistribution>
+{
+public:
+    ConstantFloatDistributionFactory();
+    JSONObjectValidationBuilder* addToValidator(
+        JSONObjectValidationBuilder* builder) const override;
+    ConstantFloatDistribution* fromJson(
+        Framework::JSON::JSONObject* zJson) const override;
+    Framework::JSON::JSONObject* toJsonObject(
+        ConstantFloatDistribution* zObject) const override;
+    const char* getTypeToken() const override;
+};
+
+class EqualyDistributedFloatDistribution : public FloatDistribution
+
+{
+private:
+    float minValue;
+    float maxValue;
+
+public:
+    EqualyDistributedFloatDistribution(float minValue, float maxValue);
+    float getValue(
+        int x, int y, int z, int dimenstionId, Noise* zNoise) const override;
+    float getMinValue() const;
+    float getMaxValue() const;
+};
+
+class EqualyDistributedFloatDistributionFactory
+    : public SubTypeFactory<FloatDistribution,
+          EqualyDistributedFloatDistribution>
+{
+public:
+    EqualyDistributedFloatDistributionFactory();
+    JSONObjectValidationBuilder* addToValidator(
+        JSONObjectValidationBuilder* builder) const override;
+    EqualyDistributedFloatDistribution* fromJson(
+        Framework::JSON::JSONObject* zJson) const override;
+    Framework::JSON::JSONObject* toJsonObject(
+        EqualyDistributedFloatDistribution* zObject) const override;
+    const char* getTypeToken() const override;
+};

+ 18 - 12
FactoryCraft/PlantConfig.cpp

@@ -37,6 +37,10 @@ PlantConfig::~PlantConfig()
     {
         orientationConfig->release();
     }
+    if (plantHeight)
+    {
+        plantHeight->release();
+    }
 }
 
 void PlantConfig::initialize(JExpressionMemory* zMemory)
@@ -77,10 +81,6 @@ double PlantConfig::doesGeneratePlant(int x,
     {
         return 0.0;
     }
-    if (z + plantHeight > WORLD_HEIGHT)
-    {
-        return 0.0;
-    }
     if (!condition->getValue())
     {
         return 0.0;
@@ -99,7 +99,8 @@ void PlantConfig::generatePlantAt(
                                  ? orientationConfig->calculateOrientation(
                                        {x, y, z}, dimensionId, zChunk)
                                  : NO_DIRECTION;
-    for (int i = 0; i < plantHeight; i++)
+    int height = (int)round(plantHeight->getValue(x, y, z, dimensionId, noise));
+    for (int i = 0; i < height; i++)
     {
         Framework::Vec3<int> pos(x, y, z);
         if (direction == PlantDirection::UP)
@@ -110,6 +111,10 @@ void PlantConfig::generatePlantAt(
         {
             pos = {x, y, z - i};
         }
+        if (pos.z < 0 || pos.z >= WORLD_HEIGHT)
+        {
+            break;
+        }
         int currentType = zChunk->getBlockTypeAtWC(pos.x, pos.y, pos.z);
         if (currentType != BlockTypeEnum::AIR
             && currentType != BlockTypeEnum::NO_BLOCK)
@@ -192,12 +197,12 @@ Framework::Text PlantConfig::getPlantBlockTypeName() const
     return plantBlockTypeName;
 }
 
-void PlantConfig::setPlantHeight(int height)
+void PlantConfig::setPlantHeight(FloatDistribution* height)
 {
     this->plantHeight = height;
 }
 
-int PlantConfig::getPlantHeight() const
+FloatDistribution* PlantConfig::getPlantHeight() const
 {
     return plantHeight;
 }
@@ -269,7 +274,8 @@ PlantConfig* PlantConfigFactory::fromJson(
     config->setPlantBlockTypeName(
         zJson->zValue("plantBlock")->asString()->getString());
     config->setPlantHeight(
-        (int)zJson->zValue("plantHeight")->asNumber()->getNumber());
+        Game::INSTANCE->zTypeRegistry()->fromJson<FloatDistribution>(
+            zJson->zValue("plantHeight")));
     Framework::Text locationStr
         = zJson->zValue("direction")->asString()->getString();
     if (locationStr.isEqual("UP"))
@@ -326,7 +332,8 @@ Framework::JSON::JSONObject* PlantConfigFactory::toJsonObject(
     zJson->addValue("plantBlock",
         new Framework::JSON::JSONString(zObject->getPlantBlockTypeName()));
     zJson->addValue("plantHeight",
-        new Framework::JSON::JSONNumber(zObject->getPlantHeight()));
+        Game::INSTANCE->zTypeRegistry()->toJson<FloatDistribution>(
+            zObject->getPlantHeight()));
     if (zObject->getDirection() == PlantDirection::UP)
     {
         zJson->addValue("direction", new Framework::JSON::JSONString("UP"));
@@ -362,9 +369,8 @@ JSONObjectValidationBuilder* PlantConfigFactory::addToValidator(
         ->withRequiredAttribute("plantBlock",
             Game::INSTANCE->zTypeRegistry()->getValidator<Framework::Text>(
                 BlockTypeNameFactory::TYPE_ID))
-        ->withRequiredNumber("plantHeight")
-        ->whichIsGreaterOrEqual(1)
-        ->finishNumber()
+        ->withRequiredAttribute("plantHeight",
+            Game::INSTANCE->zTypeRegistry()->getValidator<FloatDistribution>())
         ->withRequiredString("direction")
         ->whichIsOneOf({"UP", "DOWN"})
         ->withDefault("UP")

+ 4 - 3
FactoryCraft/PlantConfig.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "FloatDistribution.h"
 #include "JsonExpression.h"
 #include "Orientation.h"
 #include "TypeRegistry.h"
@@ -30,7 +31,7 @@ private:
     int locations;
     Framework::Text plantBlockTypeName;
     int plantblockTypeId;
-    int plantHeight;
+    FloatDistribution* plantHeight;
     int direction;
     OrientationConfig* orientationConfig;
 
@@ -59,8 +60,8 @@ public:
     int getLocations() const;
     void setPlantBlockTypeName(Framework::Text name);
     Framework::Text getPlantBlockTypeName() const;
-    void setPlantHeight(int height);
-    int getPlantHeight() const;
+    void setPlantHeight(FloatDistribution* height);
+    FloatDistribution* getPlantHeight() const;
     void setDirection(int direction);
     int getDirection() const;
     void setOrientationConfig(OrientationConfig* orientationConfig);

+ 5 - 0
FactoryCraft/TypeRegistry.cpp

@@ -18,6 +18,7 @@
 #include "DropConditionOperator.h"
 #include "DropUsedItemCondition.h"
 #include "FireBasedProcessingBlockComponent.h"
+#include "FloatDistribution.h"
 #include "FluidBlock.h"
 #include "FluidContainer.h"
 #include "Grass.h"
@@ -186,6 +187,10 @@ TypeRegistry::TypeRegistry()
 
     // orientations
     registerSubType(new AttachToNeighborOrientationConfigFactory());
+
+    // float distributions
+    registerSubType(new ConstantFloatDistributionFactory());
+    registerSubType(new EqualyDistributedFloatDistributionFactory());
 }
 
 void TypeRegistry::writeSyntaxInfo(Framework::Text folderPath) const

+ 2 - 0
Windows Version/Windows Version.vcxproj

@@ -203,6 +203,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClCompile Include="..\FactoryCraft\FastNoiseWrapper.cpp" />
     <ClCompile Include="..\FactoryCraft\FireBasedProcessingBlockComponent.cpp" />
     <ClCompile Include="..\FactoryCraft\FlattenNoise.cpp" />
+    <ClCompile Include="..\FactoryCraft\FloatDistribution.cpp" />
     <ClCompile Include="..\FactoryCraft\FluidBlock.cpp" />
     <ClCompile Include="..\FactoryCraft\FluidContainer.cpp" />
     <ClCompile Include="..\FactoryCraft\Game.cpp" />
@@ -308,6 +309,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClInclude Include="..\FactoryCraft\FactorizeNoise.h" />
     <ClInclude Include="..\FactoryCraft\FireBasedProcessingBlockComponent.h" />
     <ClInclude Include="..\FactoryCraft\FlattenNoise.h" />
+    <ClInclude Include="..\FactoryCraft\FloatDistribution.h" />
     <ClInclude Include="..\FactoryCraft\FluidContainer.h" />
     <ClInclude Include="..\FactoryCraft\GameClient.h" />
     <ClInclude Include="..\FactoryCraft\GeneratorRule.h" />

+ 9 - 0
Windows Version/Windows Version.vcxproj.filters

@@ -133,6 +133,9 @@
     <Filter Include="world\orientation">
       <UniqueIdentifier>{69d25bc2-afc8-4ebf-a45e-6eda2b6ed048}</UniqueIdentifier>
     </Filter>
+    <Filter Include="world\generator\distribution">
+      <UniqueIdentifier>{898ac1a6-af41-458a-b53a-1f58567f0897}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\FactoryCraft\Server.cpp">
@@ -510,6 +513,9 @@
     <ClCompile Include="..\FactoryCraft\Orientation.cpp">
       <Filter>world\orientation</Filter>
     </ClCompile>
+    <ClCompile Include="..\FactoryCraft\FloatDistribution.cpp">
+      <Filter>world\generator\distribution</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\FactoryCraft\Chunk.h">
@@ -902,5 +908,8 @@
     <ClInclude Include="..\FactoryCraft\Orientation.h">
       <Filter>world\orientation</Filter>
     </ClInclude>
+    <ClInclude Include="..\FactoryCraft\FloatDistribution.h">
+      <Filter>world\generator\distribution</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>

+ 21 - 5
Windows Version/data/generator/overworld.json

@@ -521,7 +521,10 @@
                                 ]
                             }
                         },
-                        "plantHeight": 1,
+                        "plantHeight": {
+                            "type": "constant",
+                            "value": 1
+                        },
                         "threshold": 0.7,
                         "noise": {
                             "type": "random",
@@ -558,7 +561,10 @@
                         "locations": [
                             "SURFACE"
                         ],
-                        "plantHeight": 1,
+                        "plantHeight": {
+                            "type": "constant",
+                            "value": 1
+                        },
                         "threshold": 0.7,
                         "noise": {
                             "type": "random",
@@ -595,7 +601,10 @@
                         "locations": [
                             "SURFACE"
                         ],
-                        "plantHeight": 1,
+                        "plantHeight": {
+                            "type": "constant",
+                            "value": 1
+                        },
                         "threshold": 0.995,
                         "noise": {
                             "type": "random",
@@ -632,7 +641,10 @@
                         "locations": [
                             "SURFACE"
                         ],
-                        "plantHeight": 1,
+                        "plantHeight": {
+                            "type": "constant",
+                            "value": 1
+                        },
                         "threshold": 0.7,
                         "noise": {
                             "type": "random",
@@ -654,7 +666,11 @@
                     },
                     {
                         "plantBlock": "Vines",
-                        "plantHeight": 4,
+                        "plantHeight": {
+                            "type": "equalyDistributed",
+                            "maxValue": 10,
+                            "minValue": 1
+                        },
                         "condition": {
                             "type": "anyNeighborBlockMatches",
                             "condition": {