Browse Source

made world generation configurable via json

Kolja Strohm 1 year ago
parent
commit
41e7a18a93
71 changed files with 4075 additions and 813 deletions
  1. 0 3
      .gitignore
  2. 18 0
      FactoryCraft.sln
  3. 0 15
      FactoryCraft/AbstractEventListener.h
  4. 0 25
      FactoryCraft/BasicInterpolator.cpp
  5. 0 9
      FactoryCraft/BasicInterpolator.h
  6. 118 7
      FactoryCraft/BiomGenerator.cpp
  7. 28 24
      FactoryCraft/BiomGenerator.h
  8. 0 15
      FactoryCraft/BlockDestroyedEvent.h
  9. 0 15
      FactoryCraft/BlockPlacedEvent.h
  10. 13 0
      FactoryCraft/BlockType.cpp
  11. 2 0
      FactoryCraft/BlockType.h
  12. 48 0
      FactoryCraft/BlockTypeGeneratorRule.cpp
  13. 24 0
      FactoryCraft/BlockTypeGeneratorRule.h
  14. 4 8
      FactoryCraft/CaveGenerator.cpp
  15. 1 2
      FactoryCraft/CaveGenerator.h
  16. 5 0
      FactoryCraft/Chunk.cpp
  17. 1 0
      FactoryCraft/Chunk.h
  18. 0 10
      FactoryCraft/DefaultEventListener.h
  19. 1 1
      FactoryCraft/Dimension.cpp
  20. 1 1
      FactoryCraft/Dimension.h
  21. 255 214
      FactoryCraft/DimensionGenerator.cpp
  22. 104 14
      FactoryCraft/DimensionGenerator.h
  23. 1 1
      FactoryCraft/DimensionMap.cpp
  24. 1 1
      FactoryCraft/DimensionMap.h
  25. 0 15
      FactoryCraft/Event.h
  26. 0 9
      FactoryCraft/EventListener.h
  27. 0 22
      FactoryCraft/EventThrower.h
  28. 18 4
      FactoryCraft/FactoryCraft.vcxproj
  29. 68 17
      FactoryCraft/FactoryCraft.vcxproj.filters
  30. 7 0
      FactoryCraft/Game.cpp
  31. 3 0
      FactoryCraft/Game.h
  32. 3 3
      FactoryCraft/GeneratedStructure.cpp
  33. 4 4
      FactoryCraft/GeneratedStructure.h
  34. 0 37
      FactoryCraft/GenerationTemplate.cpp
  35. 47 0
      FactoryCraft/GeneratorRule.cpp
  36. 56 0
      FactoryCraft/GeneratorRule.h
  37. 39 0
      FactoryCraft/GeneratorTemplate.cpp
  38. 12 8
      FactoryCraft/GeneratorTemplate.h
  39. 0 150
      FactoryCraft/GrasslandBiom.cpp
  40. 0 39
      FactoryCraft/GrasslandBiom.h
  41. 13 0
      FactoryCraft/ItemType.cpp
  42. 1 0
      FactoryCraft/ItemType.h
  43. 292 0
      FactoryCraft/JNoise.cpp
  44. 13 0
      FactoryCraft/JNoise.h
  45. 584 0
      FactoryCraft/JsonExpression.cpp
  46. 180 0
      FactoryCraft/JsonExpression.h
  47. 0 20
      FactoryCraft/LocationChangedEvent.h
  48. 463 34
      FactoryCraft/OverworldDimension.cpp
  49. 6 9
      FactoryCraft/OverworldDimension.h
  50. 11 14
      FactoryCraft/RecipieLoader.cpp
  51. 7 7
      FactoryCraft/Start.cpp
  52. 1 1
      FactoryCraft/StaticInitializerOrder.cpp
  53. 127 0
      FactoryCraft/StructureCollection.cpp
  54. 38 0
      FactoryCraft/StructureCollection.h
  55. 1 1
      FactoryCraft/TreeSeblingBlock.cpp
  56. 56 4
      FactoryCraft/TreeTemplate.cpp
  57. 11 2
      FactoryCraft/TreeTemplate.h
  58. 127 0
      FactoryCraft/TypeRegistry.cpp
  59. 33 0
      FactoryCraft/TypeRegistry.h
  60. 139 13
      FactoryCraft/WorldGenerator.cpp
  61. 9 1
      FactoryCraft/WorldGenerator.h
  62. 7 11
      FactoryCraft/WormCaveGenerator.cpp
  63. 2 2
      FactoryCraft/WormCaveGenerator.h
  64. 52 0
      NoiseTest/NoiseCombiner.h
  65. 245 0
      NoiseTest/NoiseTest.cpp
  66. 162 0
      NoiseTest/NoiseTest.vcxproj
  67. 60 0
      NoiseTest/NoiseTest.vcxproj.filters
  68. 14 4
      Windows Version/Windows Version.vcxproj
  69. 53 17
      Windows Version/Windows Version.vcxproj.filters
  70. 485 0
      Windows Version/data/generator/overworld.json
  71. 1 0
      Windows Version/data/syntax/generatorValidation.xml

+ 0 - 3
.gitignore

@@ -364,7 +364,4 @@ FodyWeavers.xsd
 /Windows Version/saves/Test
 /Windows Version/cert.crt
 /Windows Version/cert.key
-/Windows Version/Framework.dll
-/Windows Version/Network.dll
-/NoiseTest/Network.dll
 *.dll

+ 18 - 0
FactoryCraft.sln

@@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FactoryCraft", "FactoryCraf
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Windows Version", "Windows Version\Windows Version.vcxproj", "{47B54702-73F6-4004-89C3-0BF43CB2A2C4}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NoiseTest", "NoiseTest\NoiseTest.vcxproj", "{096A454C-3835-4A4E-89FE-34EDCCD80467}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|ARM = Debug|ARM
@@ -59,6 +61,22 @@ Global
 		{47B54702-73F6-4004-89C3-0BF43CB2A2C4}.Release|x64.Build.0 = Release|x64
 		{47B54702-73F6-4004-89C3-0BF43CB2A2C4}.Release|x86.ActiveCfg = Release|Win32
 		{47B54702-73F6-4004-89C3-0BF43CB2A2C4}.Release|x86.Build.0 = Release|Win32
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|ARM.ActiveCfg = Debug|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|ARM.Build.0 = Debug|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|ARM64.ActiveCfg = Debug|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|ARM64.Build.0 = Debug|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|x64.ActiveCfg = Debug|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|x64.Build.0 = Debug|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|x86.ActiveCfg = Debug|Win32
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Debug|x86.Build.0 = Debug|Win32
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|ARM.ActiveCfg = Release|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|ARM.Build.0 = Release|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|ARM64.ActiveCfg = Release|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|ARM64.Build.0 = Release|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|x64.ActiveCfg = Release|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|x64.Build.0 = Release|x64
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|x86.ActiveCfg = Release|Win32
+		{096A454C-3835-4A4E-89FE-34EDCCD80467}.Release|x86.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 0 - 15
FactoryCraft/AbstractEventListener.h

@@ -1,15 +0,0 @@
-#pragma once
-
-#include "EventListener.h"
-#include "BlockDestroyedEvent.h"
-#include "LocationChangedEvent.h"
-
-class AbstractEventListener : public EventListener
-{
-public:
-    void process( Event *event ) override;
-
-protected:
-    virtual void onBlockDestroyed( const BlockDestroyedEvent &event ) = 0;
-    virtual void onLocationChanged( const LocationChangedEvent &event ) = 0;
-};

+ 0 - 25
FactoryCraft/BasicInterpolator.cpp

@@ -1,25 +0,0 @@
-#include "BasicInterpolator.h"
-#include "Block.h"
-
-Framework::Either<Block*, int> BasicInterpolator::interpolateBlocks( Framework::Either<Block*, int> a, Framework::Either<Block*, int> b, double aWeight, double bWeight, Noise* zNoise )
-{
-    if( aWeight < bWeight )
-        return interpolateBlocks( b, a, bWeight, aWeight, zNoise );
-    double score = bWeight / aWeight;
-    if( score < 0.8 )
-    {
-        if( b.isA() )
-            ((Block*)b)->release();
-        return a;
-    }
-    score = (score - 0.8) * 5;
-    if( score < zNoise->getNoise( (score + 60) * 5, 100, 50 ) )
-    {
-        if( b.isA() )
-            ((Block*)b)->release();
-        return a;
-    }
-    if( a.isA() )
-        ((Block*)a)->release();
-    return b;
-}

+ 0 - 9
FactoryCraft/BasicInterpolator.h

@@ -1,9 +0,0 @@
-#pragma once
-
-#include "BiomInterpolator.h"
-
-class BasicInterpolator : public BiomInterpolator
-{
-public:
-    Framework::Either<Block*, int> interpolateBlocks( Framework::Either<Block*, int> a, Framework::Either<Block*, int> b, double aWeight, double bWeight, Noise* zNoise ) override;
-};

+ 118 - 7
FactoryCraft/BiomGenerator.cpp

@@ -1,20 +1,131 @@
 #include "BiomGenerator.h"
 
-BiomGenerator::BiomGenerator()
+#include "Game.h"
+#include "JNoise.h"
+
+BiomGenerator::BiomGenerator(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
     : ReferenceCounter()
-{}
+{
+    name = zConfig->asObject()->zValue("name")->asString()->getString();
+    condition = JExpressionParser::parseBoolExpression(
+        zConfig->asObject()->zValue("condition"));
+    bool first = 1;
+    for (Framework::JSON::JSONValue* value :
+        *zConfig->asObject()->zValue("structurCollections")->asArray())
+    {
+        StructureTemplateCollection* collection
+            = new StructureTemplateCollection(value, zMemory);
+        templates.add(collection);
+        if (first)
+        {
+            minStructureOffset = collection->getMinAffected();
+            maxStructureOffset = collection->getMaxAffected();
+            first = 0;
+        }
+        else
+        {
+            Framework::Vec3<int> min = collection->getMinAffected();
+            Framework::Vec3<int> max = collection->getMaxAffected();
+            if (minStructureOffset.x > min.x) minStructureOffset.x = min.x;
+            if (minStructureOffset.y > min.y) minStructureOffset.y = min.y;
+            if (minStructureOffset.z > min.z) minStructureOffset.z = min.z;
+            if (maxStructureOffset.x < max.x) maxStructureOffset.x = max.x;
+            if (maxStructureOffset.y < max.y) maxStructureOffset.y = max.y;
+            if (maxStructureOffset.z < max.z) maxStructureOffset.z = max.z;
+        }
+    }
+    for (Framework::JSON::JSONValue* value :
+        *zConfig->asObject()->zValue("blocks")->asArray())
+    {
+        rules.add(Game::INSTANCE->zTypeRegistry()->createGeneratorRule(
+            value, zMemory));
+    }
+}
+
+Framework::Either<Block*, int> BiomGenerator::generateBlock(int x,
+    int y,
+    int z,
+    int dimensionId,
+    JExpressionMemory* zMemory,
+    Chunk* partialGeneratedChunk)
+{
+    for (GeneratorRule* rule : rules)
+    {
+        if (rule->checkCondition(zMemory))
+        {
+            auto result = rule->generateBlock(x, y, z, dimensionId);
+            if ((result.isA() && result.getA())
+                || (result.isB() && result.getB()))
+            {
+                return result;
+            }
+        }
+    }
+    return BlockTypeEnum::AIR;
+}
 
-void BiomGenerator::addTemplateGenerator(GenerationTemplate* gTemplate)
+bool BiomGenerator::isApplicable(JExpressionMemory* zMemory)
 {
-    templates.add(gTemplate);
+    return condition->getValue(zMemory);
 }
 
-const Framework::RCArray<GenerationTemplate>& BiomGenerator::getTemplates()
+void BiomGenerator::generateStructures(int x,
+    int y,
+    int z,
+    int dimensionId,
+    JExpressionMemory* zMemory,
+    Framework::Vec3<int> minPos,
+    Framework::Vec3<int> maxPos,
+    Framework::RCArray<GeneratedStructure>* zResult)
+{
+    int minSearchX = minPos.x - maxStructureOffset.x;
+    int minSearchY = minPos.y - maxStructureOffset.y;
+    int minSearchZ = MAX(minPos.z - maxStructureOffset.z, 0);
+    int maxSearchX = maxPos.x - minStructureOffset.x;
+    int maxSearchY = maxPos.y - minStructureOffset.y;
+    int maxSearchZ = MIN(maxPos.z - minStructureOffset.z, WORLD_HEIGHT - 1);
+    if (x >= minSearchX && x <= maxSearchX && y >= minSearchY && y <= maxSearchY
+        && z >= minSearchZ && z <= maxSearchZ)
+    {
+        for (StructureTemplateCollection* collection : templates)
+        {
+            collection->generateStructures(
+                x, y, z, dimensionId, zMemory, minPos, maxPos, zResult);
+        }
+    }
+}
+
+const Framework::RCArray<StructureTemplateCollection>&
+BiomGenerator::getTemplates() const
 {
     return templates;
 }
 
-void BiomGenerator::setSeed(int seed)
+Framework::Vec3<int> BiomGenerator::getMinStructureOffset() const
+{
+    return minStructureOffset;
+}
+
+Framework::Vec3<int> BiomGenerator::getMaxStructureOffset() const
+{
+    return maxStructureOffset;
+}
+
+Framework::JSON::Validator::JSONValidator* BiomGenerator::getConfigValidator()
 {
-    this->seed = seed;
+    return Framework::JSON::Validator::JSONValidator::buildForObject()
+        ->withRequiredString("name")
+        ->finishString()
+        ->withRequiredAttribute(
+            "condition", JExpressionParser::getBoolValidator())
+        ->withRequiredArray("structurCollections")
+        ->addAcceptedTypeInArray(
+            StructureTemplateCollection::getConfigValidator())
+        ->finishArray()
+        ->withRequiredArray("blocks")
+        ->addAcceptedTypeInArray(
+            Game::INSTANCE->zTypeRegistry()->getGeneratorRuleValidator())
+        ->finishArray()
+        ->finishObject();
 }

+ 28 - 24
FactoryCraft/BiomGenerator.h

@@ -1,9 +1,13 @@
 #pragma once
 
 #include <Either.h>
+#include <JSON.h>
 #include <ReferenceCounter.h>
 
-#include "GenerationTemplate.h"
+#include "GeneratorRule.h"
+#include "JNoise.h"
+#include "JsonExpression.h"
+#include "StructureCollection.h"
 
 class Block;
 class Noise;
@@ -11,38 +15,38 @@ class Noise;
 class BiomGenerator : public virtual Framework::ReferenceCounter
 {
 private:
-    Framework::RCArray<GenerationTemplate> templates;
+    Framework::Text name;
+    Framework::RCArray<StructureTemplateCollection> templates;
+    Framework::RCArray<GeneratorRule> rules;
+    JBoolExpression* condition;
+    Framework::Vec3<int> minStructureOffset;
+    Framework::Vec3<int> maxStructureOffset;
 
 protected:
     int seed;
-    void addTemplateGenerator(GenerationTemplate* gTemplate);
 
 public:
-    BiomGenerator();
-    virtual Framework::Either<Block*, int> generateAboveSurfaceBlock(int x,
+    BiomGenerator(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    Framework::Either<Block*, int> generateBlock(int x,
         int y,
         int z,
         int dimensionId,
-        int surfaceHeight,
-        Chunk* partialGeneratedChunk)
-        = 0;
-    virtual Framework::Either<Block*, int> generateSurfaceBlock(
-        int x, int y, int z, int dimensionId)
-        = 0;
-    virtual Framework::Either<Block*, int> generateBelowSurfaceBlock(
-        int x, int y, int z, int dimensionId)
-        = 0;
-    virtual Framework::Either<Block*, int> generateCaveBlock(
-        int x, int y, int z, int dimensionId)
-        = 0;
-    virtual Framework::Either<Block*, int> generateUnderWaterBlock(int x,
+        JExpressionMemory* zMemory,
+        Chunk* partialGeneratedChunk);
+    bool isApplicable(JExpressionMemory* zMemory);
+    void generateStructures(int x,
         int y,
         int z,
         int dimensionId,
-        int surfaceHeight,
-        Chunk* partialGeneratedChunk)
-        = 0;
-    virtual void setSeed(int seed);
-    virtual Noise* zHeightMapNoise() = 0;
-    const Framework::RCArray<GenerationTemplate>& getTemplates();
+        JExpressionMemory* zMemory,
+        Framework::Vec3<int> minPos,
+        Framework::Vec3<int> maxPos,
+        Framework::RCArray<GeneratedStructure>* zResult);
+
+    const Framework::RCArray<StructureTemplateCollection>& getTemplates() const;
+    Framework::Vec3<int> getMinStructureOffset() const;
+    Framework::Vec3<int> getMaxStructureOffset() const;
+
+    static Framework::JSON::Validator::JSONValidator* getConfigValidator();
 };

+ 0 - 15
FactoryCraft/BlockDestroyedEvent.h

@@ -1,15 +0,0 @@
-#pragma once
-
-#include "Block.h"
-
-// TODO: add course of destruction
-class BlockDestroyedEvent : public Event
-{
-private:
-    const Block *block;
-
-public:
-    BlockDestroyedEvent( Block *block );
-
-    const Block *getBlock() const;
-};

+ 0 - 15
FactoryCraft/BlockPlacedEvent.h

@@ -1,15 +0,0 @@
-#pragma once
-
-#include "Event.h"
-#include "Block.h"
-
-class BlockPlacedEvent : public Event
-{
-private:
-    Block *block;
-
-public:
-    BlockPlacedEvent( Block *block );
-
-    const Block *getBlock() const;
-};

+ 13 - 0
FactoryCraft/BlockType.cpp

@@ -236,4 +236,17 @@ void BlockType::writeTypeInfo(StreamWriter* zWriter) const
     int maxHp = getInitialMaxHP();
     zWriter->schreibe((char*)&maxHp, 4);
     getModel().writeTo(zWriter);
+}
+
+int BlockType::getTypeId(const char* name)
+{
+    Text n = name;
+    for (int i = 0; i < StaticRegistry<BlockType>::INSTANCE.getCount(); i++)
+    {
+        if (StaticRegistry<BlockType>::INSTANCE.zElement(i)
+            && n.istGleich(
+                StaticRegistry<BlockType>::INSTANCE.zElement(i)->getName()))
+            return StaticRegistry<BlockType>::INSTANCE.zElement(i)->getId();
+    }
+    return 0;
 }

+ 2 - 0
FactoryCraft/BlockType.h

@@ -102,6 +102,8 @@ public:
     const char* getName() const;
     const bool doesNeedModelSubscription() const;
     void writeTypeInfo(Framework::StreamWriter* zWriter) const;
+
+    static int getTypeId(const char* name);
 };
 
 const Block* getDefaultBlock(Framework::Either<Block*, int> b);

+ 48 - 0
FactoryCraft/BlockTypeGeneratorRule.cpp

@@ -0,0 +1,48 @@
+#include "BlockTypeGeneratorRule.h"
+
+BlockTypeGeneratorRule::BlockTypeGeneratorRule(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+    : GeneratorRule(zConfig, zMemory)
+{
+    blockType = BlockType::getTypeId(
+        zConfig->asObject()->zValue("blockType")->asString()->getString());
+}
+
+Framework::Either<Block*, int> BlockTypeGeneratorRule::createBlock(
+    int x, int y, int z, int dimensionId)
+{
+    return blockType;
+}
+
+BlockTypeGeneratorRuleFactory::BlockTypeGeneratorRuleFactory()
+    : ReferenceCounter()
+{}
+
+GeneratorRule* BlockTypeGeneratorRuleFactory::createRule(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+{
+    return new BlockTypeGeneratorRule(zConfig, zMemory);
+}
+
+Framework::JSON::Validator::JSONValidator*
+BlockTypeGeneratorRuleFactory::getValidator()
+{
+    Framework::RCArray<Framework::Text> blockTypeNames;
+    for (int i = 0; i < StaticRegistry<BlockType>::INSTANCE.getCount(); i++)
+    {
+        if (StaticRegistry<BlockType>::INSTANCE.zElement(i))
+        {
+            blockTypeNames.add(new Framework::Text(
+                StaticRegistry<BlockType>::INSTANCE.zElement(i)->getName()));
+        }
+    }
+    return GeneratorRule::addToValidator(
+        Framework::JSON::Validator::JSONValidator::buildForObject()
+            ->withRequiredString("type")
+            ->withExactMatch("blockType")
+            ->finishString()
+            ->withRequiredString("blockType")
+            ->whichIsOneOf(blockTypeNames)
+            ->finishString())
+        ->finishObject();
+}

+ 24 - 0
FactoryCraft/BlockTypeGeneratorRule.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include "GeneratorRule.h"
+
+class BlockTypeGeneratorRule : public GeneratorRule
+{
+private:
+    int blockType;
+
+public:
+    BlockTypeGeneratorRule(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    Framework::Either<Block*, int> createBlock(
+        int x, int y, int z, int dimensionId) override;
+};
+
+class BlockTypeGeneratorRuleFactory : public GeneratorRuleFactory
+{
+public:
+    BlockTypeGeneratorRuleFactory();
+    GeneratorRule* createRule(
+	    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory) override;
+    Framework::JSON::Validator::JSONValidator* getValidator() override;
+};

+ 4 - 8
FactoryCraft/CaveGenerator.cpp

@@ -6,11 +6,7 @@ CaveChunkGenerator::CaveChunkGenerator()
     : ReferenceCounter()
 {}
 
-CaveGenerator::CaveGenerator()
-    : ReferenceCounter()
-{}
-
-void CaveGenerator::initialize(int seed)
-{
-    this->seed = seed;
-}
+CaveGenerator::CaveGenerator(int seed)
+    : ReferenceCounter(),
+      seed(seed)
+{}

+ 1 - 2
FactoryCraft/CaveGenerator.h

@@ -15,7 +15,6 @@ protected:
     int seed;
 
 public:
-    CaveGenerator();
-    virtual void initialize(int seed);
+    CaveGenerator(int seed);
     virtual CaveChunkGenerator* getGeneratorForChunk(int x, int y) = 0;
 };

+ 5 - 0
FactoryCraft/Chunk.cpp

@@ -953,4 +953,9 @@ void Chunk::setLightData(
     {
         broadcastLightData(index, foreground);
     }
+}
+
+int Chunk::getBlockTypeAt(Framework::Vec3<int> location) const
+{
+    return blockIds[index(location)];
 }

+ 1 - 0
FactoryCraft/Chunk.h

@@ -83,6 +83,7 @@ public:
     unsigned char* getLightData(Framework::Vec3<int> location) const;
     void setLightData(
         Framework::Vec3<int> location, unsigned char* data, bool foreground);
+    int getBlockTypeAt(Framework::Vec3<int> location) const;
 
     inline static int index(Framework::Vec3<int> localLocation)
     {

+ 0 - 10
FactoryCraft/DefaultEventListener.h

@@ -1,10 +0,0 @@
-#pragma once
-
-#include "AbstractEventListener.h"
-
-class DefaultEventListener : public AbstractEventListener
-{
-protected:
-    virtual void onBlockDestroyed( const BlockDestroyedEvent &event ) override;
-    virtual void onLocationChanged( const LocationChangedEvent &event ) override;
-};

+ 1 - 1
FactoryCraft/Dimension.cpp

@@ -12,7 +12,7 @@ Dimension::Dimension(int id)
       nextStructureId(0),
       dimensionId(id),
       gravity(9.8f),
-      chunks(new Trie<Chunk>()),
+      chunks(new RCTrie<Chunk>()),
       entities(new RCArray<Entity>()),
       map(new DimensionMap(id)),
       stop(0)

+ 1 - 1
FactoryCraft/Dimension.h

@@ -22,7 +22,7 @@ private:
     __int64 nextStructureId;
     int dimensionId;
     float gravity;
-    Framework::Trie<Chunk>* chunks;
+    Framework::RCTrie<Chunk>* chunks;
     Framework::Array<Chunk*> chunkList;
     Framework::Critical chunkCs;
     Framework::RCArray<Entity>* entities;

+ 255 - 214
FactoryCraft/DimensionGenerator.cpp

@@ -7,130 +7,195 @@
 #include "NoBlock.h"
 #include "Noise.h"
 #include "RandNoise.h"
+#include "WormCaveGenerator.h"
+
+DimensionGeneratorFactory::DimensionGeneratorFactory(
+    Framework::Text name, int dimensionId)
+    : ReferenceCounter(),
+      name(name),
+      dimensionId(dimensionId)
+{}
+
+Framework::Text DimensionGeneratorFactory::getName() const
+{
+    return name;
+}
+
+int DimensionGeneratorFactory::getDimensionId() const
+{
+    return dimensionId;
+}
+
+WorldHeightLayer::WorldHeightLayer(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+    : ReferenceCounter()
+{
+    noise = JNoise::parseNoisse(zConfig->asObject()->zValue("noise"), zMemory);
+    name = zConfig->asObject()->zValue("name")->asString()->getString();
+    value = JExpressionParser::parseFloatExpression(
+        zConfig->asObject()->zValue("value"));
+    zMemory->setNoise(name, dynamic_cast<Noise*>(noise->getThis()));
+}
+
+WorldHeightLayer::~WorldHeightLayer()
+{
+    noise->release();
+    value->release();
+}
+
+void WorldHeightLayer::calculateValue(JExpressionMemory* zMemory)
+{
+    zMemory->setFloatVariable(name, value->getValue(zMemory));
+}
+
+Framework::JSON::Validator::JSONValidator* WorldHeightLayer::getValidator()
+{
+    return JSON::Validator::JSONValidator::buildForObject()
+        ->withRequiredString("name")
+        ->finishString()
+        ->withRequiredAttribute("noise", JNoise::getValidator(false))
+        ->withRequiredAttribute("value", JExpressionParser::getFloatValidator())
+        ->finishObject();
+}
 
 DimensionGenerator::DimensionGenerator(
-    int dimensionId, CaveGenerator* caveGenerator)
+    Framework::JSON::JSONValue* zConfig, int worldSeed)
     : ReferenceCounter(),
-      dimensionId(dimensionId),
-      minTemplateAffectedPosition(0, 0, 0),
-      maxTemplateAffectedPosition(0, 0, 0),
-      caveGenerator(caveGenerator)
+      jExpressionMemory(new JExpressionMemory()),
+      dimensionId(dimensionId)
 {
-    StaticRegistry<DimensionGenerator>::INSTANCE.registerT(this, dimensionId);
+    jExpressionMemory->setFloatVariable("worldSeed", (float)worldSeed);
+    JFloatExpression* expr = JExpressionParser::parseFloatExpression(
+        zConfig->asObject()->zValue("dimensionSeed"));
+    jExpressionMemory->setFloatVariable(
+        "dimensionSeed", expr->getValue(jExpressionMemory));
+    for (Framework::JSON::JSONValue* value :
+        *zConfig->asObject()->zValue("heightLayers")->asArray())
+    {
+        heightLayers.add(new WorldHeightLayer(value, jExpressionMemory));
+    }
 }
 
-DimensionGenerator::~DimensionGenerator() {}
+DimensionGenerator::~DimensionGenerator()
+{
+    jExpressionMemory->release();
+}
 
-void DimensionGenerator::initialize(int seed)
+JExpressionMemory* DimensionGenerator::zMemory() const
 {
-    this->seed = seed + dimensionId;
-    caveGenerator->initialize(this->seed);
-    for (auto biomGen : biomGenerators)
+    return jExpressionMemory;
+}
+
+void DimensionGenerator::calculateHeightLayers()
+{
+    for (WorldHeightLayer* layer : heightLayers)
     {
-        biomGen->setSeed(this->seed);
+        layer->calculateValue(jExpressionMemory);
     }
 }
 
-BiomGenerator* DimensionGenerator::zBiomGenerator(int x, int y)
+int DimensionGenerator::getDimensionId() const
 {
-    double noise = zBiomNoise()->getNoise((double)x, (double)y, 0.0);
-    double border = 0;
-    BiomGenerator* gen = 0;
-    auto genI = biomGenerators.begin();
-    auto distI = biomDistribution.begin();
-    do
+    return dimensionId;
+}
+
+BiomedCavedDimensionGenerator::BiomedCavedDimensionGenerator(
+    Framework::JSON::JSONValue* zConfig, int worldSeed)
+    : DimensionGenerator(zConfig, worldSeed),
+      caveGenerator(new WormCaveGenerator(75, 150, 1, 6, 0.1f, worldSeed - 1))
+{
+    biomNoise = JNoise::parseNoisse(
+        zConfig->asObject()->zValue("biomNoise"), zMemory());
+    bool first = 1;
+    for (Framework::JSON::JSONValue* value :
+        *zConfig->asObject()->zValue("bioms")->asArray())
     {
-        border += (double)distI++;
-        gen = genI++;
-    } while (border < noise && (bool)distI && (bool)genI);
-    return gen;
+        BiomGenerator* gen = new BiomGenerator(value, zMemory());
+        biomGenerators.add(gen);
+        if (first)
+        {
+            minStructureOffset = gen->getMinStructureOffset();
+            maxStructureOffset = gen->getMaxStructureOffset();
+            first = 0;
+        }
+        else
+        {
+            Framework::Vec3<int> min = gen->getMinStructureOffset();
+            Framework::Vec3<int> max = gen->getMaxStructureOffset();
+            if (minStructureOffset.x > min.x) minStructureOffset.x = min.x;
+            if (minStructureOffset.y > min.y) minStructureOffset.y = min.y;
+            if (minStructureOffset.z > min.z) minStructureOffset.z = min.z;
+            if (maxStructureOffset.x < max.x) maxStructureOffset.x = max.x;
+            if (maxStructureOffset.y < max.y) maxStructureOffset.y = max.y;
+            if (maxStructureOffset.z < max.z) maxStructureOffset.z = max.z;
+        }
+    }
 }
 
-void DimensionGenerator::registerBiom(
-    BiomGenerator* generator, double possibility)
+BiomedCavedDimensionGenerator::~BiomedCavedDimensionGenerator()
 {
-    biomGenerators.add(generator);
-    biomDistribution.add(possibility);
-    for (auto t : generator->getTemplates())
+    biomNoise->release();
+    caveGenerator->release();
+}
+
+BiomGenerator* BiomedCavedDimensionGenerator::zBiomGenerator()
+{
+    for (BiomGenerator* generator : biomGenerators)
     {
-        minTemplateAffectedPosition.x
-            = MIN(minTemplateAffectedPosition.x, t->getMinAffectedOffset().x);
-        minTemplateAffectedPosition.y
-            = MIN(minTemplateAffectedPosition.y, t->getMinAffectedOffset().y);
-        minTemplateAffectedPosition.z
-            = MIN(minTemplateAffectedPosition.z, t->getMinAffectedOffset().z);
-        maxTemplateAffectedPosition.x
-            = MAX(maxTemplateAffectedPosition.x, t->getMaxAffectedOffset().x);
-        maxTemplateAffectedPosition.y
-            = MAX(maxTemplateAffectedPosition.y, t->getMaxAffectedOffset().y);
-        maxTemplateAffectedPosition.z
-            = MAX(maxTemplateAffectedPosition.z, t->getMaxAffectedOffset().z);
+        if (generator->isApplicable(zMemory())) return generator;
     }
-    generator->setSeed(seed);
+    return 0;
 }
 
 Framework::RCArray<GeneratedStructure>*
-DimensionGenerator::getGeneratedStructoresForArea(
+BiomedCavedDimensionGenerator::getGeneratedStructoresForArea(
     Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos)
 {
+    int minSearchX = minPos.x - maxStructureOffset.x;
+    int minSearchY = minPos.y - maxStructureOffset.y;
+    int minSearchZ = MAX(minPos.z - maxStructureOffset.z, 0);
+    int maxSearchX = maxPos.x - minStructureOffset.x;
+    int maxSearchY = maxPos.y - minStructureOffset.y;
+    int maxSearchZ = MIN(maxPos.z - minStructureOffset.z, WORLD_HEIGHT - 1);
     Framework::RCArray<GeneratedStructure>* result
         = new Framework::RCArray<GeneratedStructure>();
-
-    int minSearchX = minPos.x - maxTemplateAffectedPosition.x;
-    int minSearchY = minPos.y - maxTemplateAffectedPosition.y;
-    int minSearchZ = MAX(minPos.z - maxTemplateAffectedPosition.z, 0);
-    int maxSearchX = maxPos.x - minTemplateAffectedPosition.x;
-    int maxSearchY = maxPos.y - minTemplateAffectedPosition.y;
-    int maxSearchZ
-        = MIN(maxPos.z - minTemplateAffectedPosition.z, WORLD_HEIGHT - 1);
-
-    Noise* structureNoise = zStructureNoise();
     for (int x = minSearchX; x <= maxSearchX; x++)
     {
         for (int y = minSearchY; y <= maxSearchY; y++)
         {
-            BiomGenerator* biom = zBiomGenerator(x, y);
-            int height = MIN_AIR_LEVEL
-                       + (int)(biom->zHeightMapNoise()->getNoise(
-                                   (double)(x), (double)(y), 0.0)
-                               * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
-            for (int z = minSearchZ; z <= maxSearchZ && z < height; z++)
+            zMemory()->setFloatVariable("x", (float)x);
+            zMemory()->setFloatVariable("y", (float)y);
+            calculateHeightLayers();
+            BiomGenerator* gen = zBiomGenerator();
+            for (int z = minSearchZ; z <= maxSearchZ; z++)
             {
-                double rValue
-                    = structureNoise->getNoise((double)x, (double)y, (double)z);
-                double probSum = 0;
-                for (auto t : biom->getTemplates())
-                {
-                    if (t->isGenerationPossable(
-                            Framework::Vec3<int>(x, y, z), height - z))
-                    {
-                        if (rValue - probSum <= t->getPropability())
-                        {
-                            result->add(
-                                t->generateAt(Framework::Vec3<int>(x, y, z),
-                                    structureNoise,
-                                    dimensionId));
-                            break;
-                        }
-                    }
-                    probSum += t->getPropability();
-                }
+                zMemory()->setFloatVariable("z", (float)z);
+                gen->generateStructures(x,
+                    y,
+                    z,
+                    getDimensionId(),
+                    zMemory(),
+                    minPos,
+                    maxPos,
+                    result);
             }
         }
     }
     return result;
 }
 
-Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
+Chunk* BiomedCavedDimensionGenerator::generateChunk(int centerX, int centerY)
 {
+    zMemory()->lock();
     std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
     double structureTime = 0;
     double structureTime2 = 0;
     double structureTime3 = 0;
     double caveTime = 0;
+    double caveTime2 = 0;
     double blockGenTime = 0;
     double biomTime = 0;
-    double heightTime = 0;
+    double layerTime = 0;
     ZeitMesser zm;
     ZeitMesser zmGlobal;
     zm.messungStart();
@@ -149,44 +214,35 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
         = caveGenerator->getGeneratorForChunk(centerX, centerY);
     zm.messungEnde();
     caveTime += zm.getSekunden();
-    Chunk* chunk = new Chunk(Framework::Punkt(centerX, centerY), dimensionId);
+    Chunk* chunk = new Chunk(Framework::Punkt(centerX, centerY), getDimensionId());
+    zMemory()->setCurrentChunk(dynamic_cast<Chunk*>(chunk->getThis()));
     for (int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++)
     {
         for (int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++)
         {
+            zMemory()->setFloatVariable("x", (float)x + (float)centerX);
+            zMemory()->setFloatVariable("y", (float)y + (float)centerY);
+            // calculate height layers
             zm.messungStart();
-            BiomGenerator* biom = zBiomGenerator(x + centerX, y + centerY);
+            calculateHeightLayers();
             zm.messungEnde();
-            biomTime += zm.getSekunden();
-            // TODO: use Noise interpolator for height map between different
-            // bioms
+            layerTime += zm.getSekunden();
+            // calculate biom
             zm.messungStart();
-            int height
-                = MIN_AIR_LEVEL
-                + (int)(biom->zHeightMapNoise()->getNoise(
-                            (double)(x + centerX), (double)(y + centerY), 0.0)
-                        * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
-            int maxSurfaceHeight
-                = (int)(MAX_SURFACE_HEIGHT
-                        * (1.f
-                            - (float)(height - MIN_AIR_LEVEL)
-                                  / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
-            int actualSurfaceHeight
-                = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
-                        + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
-                            * (float)biom->zHeightMapNoise()->getNoise(
-                                (double)(x + centerX),
-                                (double)(y + centerY),
-                                10.0)));
+            BiomGenerator* biom = zBiomGenerator();
             zm.messungEnde();
-            heightTime += zm.getSekunden();
+            biomTime += zm.getSekunden();
+            // generate blocks
             for (int z = 0; z < WORLD_HEIGHT; z++)
             {
+                zMemory()->setFloatVariable(
+                    "z", (float)z);
                 Framework::Either<Block*, int> generated = BlockTypeEnum::AIR;
                 bool structureAffected = 0;
+                // check if the block is inside of a structure
+                zm.messungStart();
                 for (auto structure : *structures)
                 {
-                    zm.messungStart();
                     if (structure->isBlockAffected(
                             Framework::Vec3<int>(x + centerX, y + centerY, z)))
                     {
@@ -195,52 +251,37 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
                         zm.messungStart();
                         generated = structure->generateBlockAt(
                             Framework::Vec3<int>(x + centerX, y + centerY, z),
-                            dimensionId);
+                            getDimensionId());
                         structureAffected = 1;
                         zm.messungEnde();
                         structureTime3 += zm.getSekunden();
+                        zm.messungStart();
                         break;
                     }
-                    zm.messungEnde();
-                    structureTime2 += zm.getSekunden();
                 }
+                zm.messungEnde();
+                structureTime2 += zm.getSekunden();
                 if (!structureAffected)
                 {
+                    // check if block is a cave block
                     zm.messungStart();
                     bool inCave
                         = caveGen->isInCave(x + centerX, y + centerY, z);
                     zm.messungEnde();
-                    caveTime += zm.getSekunden();
-                    zm.messungStart();
-                    if (inCave)
-                        generated = biom->generateCaveBlock(
-                            x + centerX, y + centerY, z, dimensionId);
-                    else if (z < height && z >= height - actualSurfaceHeight)
-                        generated = biom->generateSurfaceBlock(
-                            x + centerX, y + centerY, z, dimensionId);
-                    else if (z < height)
-                        generated = biom->generateBelowSurfaceBlock(
-                            x + centerX, y + centerY, z, dimensionId);
-                    else if (z >= height && z < WATER_LEVEL)
-                    {
-                        generated = biom->generateUnderWaterBlock(x + centerX,
-                            y + centerY,
-                            z,
-                            dimensionId,
-                            height,
-                            chunk);
-                    }
-                    else
+                    caveTime2 += zm.getSekunden();
+                    if (!inCave)
                     {
-                        generated = biom->generateAboveSurfaceBlock(x + centerX,
+                        // generate biom block
+                        zm.messungStart();
+                        generated = biom->generateBlock(x + centerX,
                             y + centerY,
                             z,
-                            dimensionId,
-                            height,
+                            getDimensionId(),
+                            zMemory(),
                             chunk);
+                        zm.messungEnde();
+                        blockGenTime += zm.getSekunden();
                     }
-                    zm.messungEnde();
-                    blockGenTime += zm.getSekunden();
                 }
                 if (generated.isA())
                     chunk->putBlockAt(
@@ -261,125 +302,125 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
     std::cout << "structureGenerationTime: " << structureTime << "\n";
     std::cout << "structure.isBlockAffected: " << structureTime2 << "\n";
     std::cout << "structure.generateBlockAt: " << structureTime3 << "\n";
-    std::cout << "caveTime: " << caveTime << "\n";
+    std::cout << "caveGenerationTime: " << caveTime << "\n";
+    std::cout << "caveEvaluationTime: " << caveTime2 << "\n";
     std::cout << "blockGenTime: " << blockGenTime << "\n";
     std::cout << "biomTime: " << biomTime << "\n";
-    std::cout << "heightTime: " << heightTime << "\n";
+    std::cout << "layerTime: " << layerTime << "\n";
     std::cout << "totalTime: " << zmGlobal.getSekunden() << "\n";
+    zMemory()->unlock();
     return chunk;
 }
 
-Framework::Either<Block*, int> DimensionGenerator::generateBlock(
+Framework::Either<Block*, int> BiomedCavedDimensionGenerator::generateBlock(
     Framework::Vec3<int> location)
 {
+    zMemory()->lock();
+
+    Chunk* zChunk
+        = Game::INSTANCE->zDimension(getDimensionId())
+              ->zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
+    zMemory()->setCurrentChunk(dynamic_cast<Chunk*>(zChunk->getThis()));
+
     Framework::RCArray<GeneratedStructure>* structures
         = getGeneratedStructoresForArea(location, location);
-    BiomGenerator* biom = zBiomGenerator(location.x, location.y);
-    // TODO: use Noise interpolator for height map between different bioms
-    int height = MIN_AIR_LEVEL
-               + (int)(biom->zHeightMapNoise()->getNoise(
-                           (double)(location.x), (double)(location.y), 0.0)
-                       * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
-    int maxSurfaceHeight
-        = (int)(MAX_SURFACE_HEIGHT
-                * (1.f
-                    - (float)(height - MIN_AIR_LEVEL)
-                          / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
-    int actualSurfaceHeight
-        = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
-                + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
-                    * (float)biom->zHeightMapNoise()->getNoise(
-                        (double)(location.x), (double)(location.y), 10.0)));
+
+    zMemory()->setFloatVariable("x", (float)location.x);
+    zMemory()->setFloatVariable("y", (float)location.y);
+
+    BiomGenerator* biom = zBiomGenerator();
+
+    zMemory()->setFloatVariable("z", (float)location.z);
+
     for (auto structure : *structures)
     {
         if (structure->isBlockAffected(location))
         {
-            auto generated = structure->generateBlockAt(location, dimensionId);
+            auto generated = structure->generateBlockAt(location, getDimensionId());
             structures->release();
+            zMemory()->unlock();
             return generated;
         }
     }
     structures->release();
-    if (location.z < height && location.z >= height - actualSurfaceHeight)
-        return biom->generateSurfaceBlock(
-            location.x, location.y, location.z, dimensionId);
-    else if (location.z < height)
-        return biom->generateBelowSurfaceBlock(
-            location.x, location.y, location.z, dimensionId);
-    else if (location.z >= height && location.z < WATER_LEVEL)
-    {
-        return biom->generateUnderWaterBlock(location.x,
-            location.y,
-            location.z,
-            dimensionId,
-            height,
-            Game::INSTANCE->zDimension(getDimensionId())
-                ->zChunk(
-                    Game::INSTANCE->getChunkCenter(location.x, location.y)));
-    }
-    if (location.z >= height)
+
+    Punkt chunkCenter = Game::getChunkCenter(location.x, location.y);
+    CaveChunkGenerator* caveGen
+        = caveGenerator->getGeneratorForChunk(chunkCenter.x, chunkCenter.y);
+    if (caveGen->isInCave(location.x, location.y, location.z))
     {
-        return biom->generateAboveSurfaceBlock(location.x,
-            location.x,
-            location.z,
-            dimensionId,
-            height,
-            Game::INSTANCE->zDimension(getDimensionId())
-                ->zChunk(
-                    Game::INSTANCE->getChunkCenter(location.x, location.y)));
+        caveGen->release();
+        zMemory()->unlock();
+        return BlockTypeEnum::AIR;
     }
-    return BlockTypeEnum::AIR;
+    caveGen->release();
+
+    auto generated = biom->generateBlock(location.x,
+        location.y,
+        location.z,
+        getDimensionId(),
+        zMemory(),
+        zChunk);
+    zMemory()->unlock();
+    return generated;
 }
 
-bool DimensionGenerator::spawnStructure(Framework::Vec3<int> location,
-    std::function<bool(GenerationTemplate* tmpl)> filter)
+bool BiomedCavedDimensionGenerator::spawnStructure(
+    Framework::Vec3<int> location,
+    std::function<bool(GeneratorTemplate* tmpl)> filter)
 {
-    BiomGenerator* biom = zBiomGenerator(location.x, location.y);
-    for (auto t : biom->getTemplates())
+    zMemory()->lock();
+    zMemory()->setFloatVariable("x", (float)location.x);
+    zMemory()->setFloatVariable("y", (float)location.y);
+
+    BiomGenerator* biom = zBiomGenerator();
+    zMemory()->unlock();
+    for (StructureTemplateCollection *tc : biom->getTemplates())
     {
-        if (filter(t))
+        for (GeneratorTemplate* t : tc->getStructures())
         {
-            RandNoise noise((int)time(0));
-            GeneratedStructure* genStr
-                = t->generateAt(location, &noise, dimensionId);
-            if (genStr)
+            if (filter(t))
             {
-                int minSearchX = location.x + t->getMinAffectedOffset().x;
-                int minSearchY = location.y + t->getMinAffectedOffset().y;
-                int minSearchZ
-                    = MAX(location.z + t->getMinAffectedOffset().z, 0);
-                int maxSearchX = location.x + t->getMaxAffectedOffset().x;
-                int maxSearchY = location.y + t->getMaxAffectedOffset().y;
-                int maxSearchZ = MIN(
-                    location.z + t->getMaxAffectedOffset().z, WORLD_HEIGHT - 1);
-
-                for (int x = minSearchX; x <= maxSearchX; x++)
+                RandNoise noise((int)time(0));
+                GeneratedStructure* genStr
+                    = t->generateAt(location, &noise, getDimensionId());
+                if (genStr)
                 {
-                    for (int y = minSearchY; y <= maxSearchY; y++)
+                    int minSearchX = location.x + t->getMinAffectedOffset().x;
+                    int minSearchY = location.y + t->getMinAffectedOffset().y;
+                    int minSearchZ
+                        = MAX(location.z + t->getMinAffectedOffset().z, 0);
+                    int maxSearchX = location.x + t->getMaxAffectedOffset().x;
+                    int maxSearchY = location.y + t->getMaxAffectedOffset().y;
+                    int maxSearchZ
+                        = MIN(location.z + t->getMaxAffectedOffset().z,
+                            WORLD_HEIGHT - 1);
+
+                    for (int x = minSearchX; x <= maxSearchX; x++)
                     {
-                        for (int z = minSearchZ; z <= maxSearchZ; z++)
+                        for (int y = minSearchY; y <= maxSearchY; y++)
                         {
-                            if (genStr->isBlockAffected(
-                                    Framework::Vec3<int>(x, y, z)))
+                            for (int z = minSearchZ; z <= maxSearchZ; z++)
                             {
-                                auto gen = genStr->generateBlockAt(
-                                    Framework::Vec3<int>(x, y, z), dimensionId);
-                                Game::INSTANCE->zDimension(dimensionId)
-                                    ->placeBlock(
-                                        Framework::Vec3<int>(x, y, z), gen);
+                                if (genStr->isBlockAffected(
+                                        Framework::Vec3<int>(x, y, z)))
+                                {
+                                    auto gen = genStr->generateBlockAt(
+                                        Framework::Vec3<int>(x, y, z),
+                                        getDimensionId());
+                                    Game::INSTANCE->zDimension(getDimensionId())
+                                        ->placeBlock(
+                                            Framework::Vec3<int>(x, y, z), gen);
+                                }
                             }
                         }
                     }
+                    genStr->release();
+                    zMemory()->unlock();
+                    return 1;
                 }
-                genStr->release();
-                return 1;
             }
         }
     }
     return 0;
-}
-
-int DimensionGenerator::getDimensionId() const
-{
-    return dimensionId;
 }

+ 104 - 14
FactoryCraft/DimensionGenerator.h

@@ -7,6 +7,8 @@
 #include "BiomGenerator.h"
 #include "CaveGenerator.h"
 #include "Chunk.h"
+#include "JNoise.h"
+#include "JsonExpression.h"
 
 class DimensionEnum
 {
@@ -14,33 +16,121 @@ public:
     static const int OVERWORLD = 0;
 };
 
+class DimensionGenerator;
+
+class DimensionGeneratorFactory : public virtual Framework::ReferenceCounter
+{
+private:
+    Framework::Text name;
+    int dimensionId;
+
+public:
+    DimensionGeneratorFactory(Framework::Text name, int dimensionId);
+
+    virtual DimensionGenerator* createDimensionGenerator(
+        int worldSeed, Framework::JSON::JSONValue* config)
+        = 0;
+    virtual Framework::JSON::Validator::JSONValidator* getConfigValidator() = 0;
+    virtual Framework::JSON::JSONValue* getDefaultConfig() = 0;
+
+    Framework::Text getName() const;
+    int getDimensionId() const;
+};
+
+class WorldHeightLayer : public virtual Framework::ReferenceCounter
+{
+private:
+    Noise* noise;
+    Framework::Text name;
+    JFloatExpression* value;
+
+public:
+    WorldHeightLayer(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    ~WorldHeightLayer();
+
+    void calculateValue(JExpressionMemory* zMemory);
+
+    static Framework::JSON::Validator::JSONValidator* getValidator();
+};
+
 class DimensionGenerator : public virtual Framework::ReferenceCounter
 {
 private:
-    Framework::RCArray<BiomGenerator> biomGenerators;
-    Framework::Array<double> biomDistribution;
+    JExpressionMemory* jExpressionMemory;
+    Framework::RCArray<WorldHeightLayer> heightLayers;
     const int dimensionId;
-    Framework::Vec3<int> minTemplateAffectedPosition;
-    Framework::Vec3<int> maxTemplateAffectedPosition;
+
+protected:
+    DimensionGenerator(Framework::JSON::JSONValue* zConfig, int worldSeed);
+    ~DimensionGenerator();
+
+    JExpressionMemory* zMemory() const;
+    void calculateHeightLayers();
+
+public:
+    virtual Chunk* generateChunk(int centerX, int centerY) = 0;
+    virtual Framework::Either<Block*, int> generateBlock(
+        Framework::Vec3<int> location)
+        = 0;
+    virtual bool spawnStructure(Framework::Vec3<int> location,
+        std::function<bool(GeneratorTemplate* tmpl)> filter)
+        = 0;
+    int getDimensionId() const;
+
+    template<typename T>
+    static Framework::JSON::Validator::ObjectValidationBuilder<T>*
+    addConfigAttributes(
+        Framework::JSON::Validator::ObjectValidationBuilder<T>* zBuilder)
+    {
+        return zBuilder
+            ->withRequiredAttribute(
+                "dimensionSeed", JExpressionParser::getFloatValidator())
+            ->withRequiredAttribute("heightLayers",
+                Framework::JSON::Validator::JSONValidator::buildForArray()
+                    ->withDefault(new Framework::JSON::JSONArray())
+                    ->removeInvalidEntries()
+                    ->addAcceptedTypeInArray(WorldHeightLayer::getValidator())
+                    ->finishArray());
+    }
+};
+
+class BiomGenerator;
+
+class BiomedCavedDimensionGenerator : public DimensionGenerator
+{
+private:
+    Framework::RCArray<BiomGenerator> biomGenerators;
     CaveGenerator* caveGenerator;
+    Noise* biomNoise;
+    Framework::Vec3<int> minStructureOffset;
+    Framework::Vec3<int> maxStructureOffset;
 
-    BiomGenerator* zBiomGenerator(int x, int y);
+    BiomGenerator* zBiomGenerator();
 
 protected:
-    int seed;
-    DimensionGenerator(int dimensionId, CaveGenerator* caveGenerator);
-    ~DimensionGenerator();
-    void registerBiom(BiomGenerator* generator, double possibility);
     Framework::RCArray<GeneratedStructure>* getGeneratedStructoresForArea(
         Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos);
 
 public:
-    void initialize(int seed);
+    BiomedCavedDimensionGenerator(
+        Framework::JSON::JSONValue* zConfig, int worldSeed);
+    ~BiomedCavedDimensionGenerator();
+
     Chunk* generateChunk(int centerX, int centerY);
     Framework::Either<Block*, int> generateBlock(Framework::Vec3<int> location);
     bool spawnStructure(Framework::Vec3<int> location,
-        std::function<bool(GenerationTemplate* tmpl)> filter);
-    int getDimensionId() const;
-    virtual Noise* zBiomNoise() = 0;
-    virtual Noise* zStructureNoise() = 0;
+        std::function<bool(GeneratorTemplate* tmpl)> filter);
+
+    template<typename T>
+    static Framework::JSON::Validator::ObjectValidationBuilder<T>*
+    addConfigAttributes(
+        Framework::JSON::Validator::ObjectValidationBuilder<T>* zBuilder)
+    {
+        return DimensionGenerator::addConfigAttributes(zBuilder
+            ->withRequiredArray("bioms")
+            ->addAcceptedTypeInArray(BiomGenerator::getConfigValidator())
+            ->finishArray()
+            ->withRequiredAttribute("biomNoise", JNoise::getValidator(false)));
+    }
 };

+ 1 - 1
FactoryCraft/DimensionMap.cpp

@@ -8,7 +8,7 @@ DimensionMap::DimensionMap(int dimensionId)
     : ReferenceCounter(),
       dimensionId(dimensionId)
 {
-    chunks = new Framework::Trie<ChunkMap>();
+    chunks = new Framework::RCTrie<ChunkMap>();
 }
 
 DimensionMap::~DimensionMap()

+ 1 - 1
FactoryCraft/DimensionMap.h

@@ -14,7 +14,7 @@ class Entity;
 class DimensionMap : public Framework::ReferenceCounter
 {
 private:
-    Framework::Trie<ChunkMap>* chunks;
+    Framework::RCTrie<ChunkMap>* chunks;
     Framework::Critical cs;
     Framework::Array<int> observers;
     int dimensionId;

+ 0 - 15
FactoryCraft/Event.h

@@ -1,15 +0,0 @@
-#pragma once
-
-#include <Text.h>
-
-
-class Event : public virtual Framework::ReferenceCounter
-{
-private:
-    const Framework::Text name;
-
-public:
-    Event( Framework::Text name );
-
-    const Framework::Text getName() const;
-};

+ 0 - 9
FactoryCraft/EventListener.h

@@ -1,9 +0,0 @@
-#pragma once
-
-#include "Event.h"
-
-class EventListener : public virtual Framework::ReferenceCounter
-{
-public:
-    virtual void process( Event *event ) = 0;
-};

+ 0 - 22
FactoryCraft/EventThrower.h

@@ -1,22 +0,0 @@
-#pragma once
-
-#include "EventListener.h"
-
-#include <Trie.h>
-
-class EventThrower : public virtual Framework::ReferenceCounter
-{
-private:
-    Framework::Trie<EventListener> *listeners;
-
-protected:
-    void throwEvent( Event *event );
-
-public:
-    EventThrower();
-    ~EventThrower();
-
-    void registerEventListener( Framework::Text eventName, EventListener *listener );
-    void removeEventListener( Framework::Text eventName, EventListener *listener );
-    void removeEventListener( EventListener *listener );
-};

+ 18 - 4
FactoryCraft/FactoryCraft.vcxproj

@@ -96,6 +96,9 @@
     <RemoteTargetPath>$(RemoteProjectDir)/$(TargetName)$(TargetExt)</RemoteTargetPath>
   </PropertyGroup>
   <ItemGroup>
+    <ClInclude Include="GeneratorRule.h" />
+    <ClInclude Include="BlockTypeGeneratorRule.h" />
+    <ClInclude Include="Chest.h" />
     <ClInclude Include="ChunkMap.h" />
     <ClInclude Include="AddEntityUpdate.h" />
     <ClInclude Include="Area.h" />
@@ -126,9 +129,8 @@
     <ClInclude Include="FluidBlock.h" />
     <ClInclude Include="Game.h" />
     <ClInclude Include="GeneratedStructure.h" />
-    <ClInclude Include="GenerationTemplate.h" />
+    <ClInclude Include="GeneratorTemplate.h" />
     <ClInclude Include="GrantCommand.h" />
-    <ClInclude Include="GrasslandBiom.h" />
     <ClInclude Include="Grass.h" />
     <ClInclude Include="Chat.h" />
     <ClInclude Include="Hoe.h" />
@@ -141,6 +143,8 @@
     <ClInclude Include="ItemSlot.h" />
     <ClInclude Include="ItemStack.h" />
     <ClInclude Include="ItemType.h" />
+    <ClInclude Include="JNoise.h" />
+    <ClInclude Include="JsonExpression.h" />
     <ClInclude Include="LightSources.h" />
     <ClInclude Include="DimensionMap.h" />
     <ClInclude Include="ModelInfo.h" />
@@ -162,7 +166,9 @@
     <ClInclude Include="Server.h" />
     <ClInclude Include="Dimension.h" />
     <ClInclude Include="ShapedNoise.h" />
+    <ClInclude Include="Shovel.h" />
     <ClInclude Include="StaticRegistry.h" />
+    <ClInclude Include="StructureCollection.h" />
     <ClInclude Include="Tickable.h" />
     <ClInclude Include="TickOrganizer.h" />
     <ClInclude Include="TickQueue.h" />
@@ -170,6 +176,7 @@
     <ClInclude Include="TreeSeblingBlock.h" />
     <ClInclude Include="TreeTemplate.h" />
     <ClInclude Include="GrowingPlant.h" />
+    <ClInclude Include="TypeRegistry.h" />
     <ClInclude Include="WorldGenerator.h" />
     <ClInclude Include="WorldLoader.h" />
     <ClInclude Include="WorldUpdate.h" />
@@ -185,12 +192,14 @@
     <ClCompile Include="BiomGenerator.cpp" />
     <ClCompile Include="Block.cpp" />
     <ClCompile Include="BlockType.cpp" />
+    <ClCompile Include="BlockTypeGeneratorRule.cpp" />
     <ClCompile Include="CaveGenerator.cpp" />
     <ClCompile Include="Chat.cpp" />
     <ClCompile Include="ChatCommand.cpp" />
     <ClCompile Include="ChatCommandExecutor.cpp" />
     <ClCompile Include="ChatMessage.cpp" />
     <ClCompile Include="ChatObserver.cpp" />
+    <ClCompile Include="Chest.cpp" />
     <ClCompile Include="Chunk.cpp" />
     <ClCompile Include="ChunkMap.cpp" />
     <ClCompile Include="CraftingStorage.cpp" />
@@ -205,9 +214,9 @@
     <ClCompile Include="FluidBlock.cpp" />
     <ClCompile Include="Game.cpp" />
     <ClCompile Include="GeneratedStructure.cpp" />
-    <ClCompile Include="GenerationTemplate.cpp" />
+    <ClCompile Include="GeneratorTemplate.cpp" />
+    <ClCompile Include="GeneratorRule.cpp" />
     <ClCompile Include="GrantCommand.cpp" />
-    <ClCompile Include="GrasslandBiom.cpp" />
     <ClCompile Include="Grass.cpp" />
     <ClCompile Include="Hoe.cpp" />
     <ClCompile Include="Inventory.cpp" />
@@ -219,6 +228,8 @@
     <ClCompile Include="ItemSlot.cpp" />
     <ClCompile Include="ItemStack.cpp" />
     <ClCompile Include="ItemType.cpp" />
+    <ClCompile Include="JNoise.cpp" />
+    <ClCompile Include="JsonExpression.cpp" />
     <ClCompile Include="LightSources.cpp" />
     <ClCompile Include="ModelInfo.cpp" />
     <ClCompile Include="MultiblockStructure.cpp" />
@@ -238,14 +249,17 @@
     <ClCompile Include="SaveCommand.cpp" />
     <ClCompile Include="Server.cpp" />
     <ClCompile Include="ShapedNoise.cpp" />
+    <ClCompile Include="Shovel.cpp" />
     <ClCompile Include="Start.cpp" />
     <ClCompile Include="StaticInitializerOrder.cpp" />
+    <ClCompile Include="StructureCollection.cpp" />
     <ClCompile Include="TickOrganizer.cpp" />
     <ClCompile Include="TickQueue.cpp" />
     <ClCompile Include="TickWorker.cpp" />
     <ClCompile Include="TreeSeblingBlock.cpp" />
     <ClCompile Include="TreeTemplate.cpp" />
     <ClCompile Include="GrowingPlant.cpp" />
+    <ClCompile Include="TypeRegistry.cpp" />
     <ClCompile Include="WorldGenerator.cpp" />
     <ClCompile Include="WorldLoader.cpp" />
     <ClCompile Include="WorldUpdate.cpp" />

+ 68 - 17
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -25,9 +25,6 @@
     <Filter Include="world\generator\noise">
       <UniqueIdentifier>{6a594ea1-a32c-4e11-9f2c-d694f42e9076}</UniqueIdentifier>
     </Filter>
-    <Filter Include="world\generator\bioms">
-      <UniqueIdentifier>{a69078f1-3e20-4b14-943e-9d02c4df470d}</UniqueIdentifier>
-    </Filter>
     <Filter Include="world\generator\dimensions">
       <UniqueIdentifier>{b04d9ff5-ad58-41e2-8e72-8de835e09c99}</UniqueIdentifier>
     </Filter>
@@ -85,6 +82,18 @@
     <Filter Include="world\map">
       <UniqueIdentifier>{cdafc254-a7ce-4911-8534-20ebcee5bec8}</UniqueIdentifier>
     </Filter>
+    <Filter Include="world\blocks\storage">
+      <UniqueIdentifier>{f0a18928-ee44-40d9-8872-e09b57585ac0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="server\config">
+      <UniqueIdentifier>{37cc61df-5924-4def-91db-443f07b51d5e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="world\generator\biom">
+      <UniqueIdentifier>{a69078f1-3e20-4b14-943e-9d02c4df470d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="world\generator\biom\rules">
+      <UniqueIdentifier>{3a03ed08-0a9d-4887-a1f0-d2a84028c425}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Chunk.h">
@@ -141,15 +150,9 @@
     <ClInclude Include="WorldGenerator.h">
       <Filter>world\generator</Filter>
     </ClInclude>
-    <ClInclude Include="BiomGenerator.h">
-      <Filter>world\generator</Filter>
-    </ClInclude>
     <ClInclude Include="DimensionGenerator.h">
       <Filter>world\generator</Filter>
     </ClInclude>
-    <ClInclude Include="GrasslandBiom.h">
-      <Filter>world\generator\bioms</Filter>
-    </ClInclude>
     <ClInclude Include="OverworldDimension.h">
       <Filter>world\generator\dimensions</Filter>
     </ClInclude>
@@ -201,7 +204,7 @@
     <ClInclude Include="EntityRemovedUpdate.h">
       <Filter>world\update</Filter>
     </ClInclude>
-    <ClInclude Include="GenerationTemplate.h">
+    <ClInclude Include="GeneratorTemplate.h">
       <Filter>world\generator\templates</Filter>
     </ClInclude>
     <ClInclude Include="GeneratedStructure.h">
@@ -321,6 +324,33 @@
     <ClInclude Include="ChunkMap.h">
       <Filter>world\map</Filter>
     </ClInclude>
+    <ClInclude Include="Chest.h">
+      <Filter>world\blocks\storage</Filter>
+    </ClInclude>
+    <ClInclude Include="Shovel.h">
+      <Filter>inventory\items\tools</Filter>
+    </ClInclude>
+    <ClInclude Include="JsonExpression.h">
+      <Filter>server\config</Filter>
+    </ClInclude>
+    <ClInclude Include="JNoise.h">
+      <Filter>world\generator\noise</Filter>
+    </ClInclude>
+    <ClInclude Include="StructureCollection.h">
+      <Filter>world\generator\templates</Filter>
+    </ClInclude>
+    <ClInclude Include="BiomGenerator.h">
+      <Filter>world\generator\biom</Filter>
+    </ClInclude>
+    <ClInclude Include="GeneratorRule.h">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClInclude>
+    <ClInclude Include="BlockTypeGeneratorRule.h">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClInclude>
+    <ClInclude Include="TypeRegistry.h">
+      <Filter>server\config</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
@@ -353,12 +383,6 @@
     <ClCompile Include="OverworldDimension.cpp">
       <Filter>world\generator\dimensions</Filter>
     </ClCompile>
-    <ClCompile Include="GrasslandBiom.cpp">
-      <Filter>world\generator\bioms</Filter>
-    </ClCompile>
-    <ClCompile Include="BiomGenerator.cpp">
-      <Filter>world\generator</Filter>
-    </ClCompile>
     <ClCompile Include="TickWorker.cpp">
       <Filter>world\ticking</Filter>
     </ClCompile>
@@ -434,7 +458,7 @@
     <ClCompile Include="GeneratedStructure.cpp">
       <Filter>world\generator\templates</Filter>
     </ClCompile>
-    <ClCompile Include="GenerationTemplate.cpp">
+    <ClCompile Include="GeneratorTemplate.cpp">
       <Filter>world\generator\templates</Filter>
     </ClCompile>
     <ClCompile Include="TreeTemplate.cpp">
@@ -545,5 +569,32 @@
     <ClCompile Include="DimensionMap.cpp">
       <Filter>world\map</Filter>
     </ClCompile>
+    <ClCompile Include="Chest.cpp">
+      <Filter>world\blocks\storage</Filter>
+    </ClCompile>
+    <ClCompile Include="Shovel.cpp">
+      <Filter>inventory\items\tools</Filter>
+    </ClCompile>
+    <ClCompile Include="JsonExpression.cpp">
+      <Filter>server\config</Filter>
+    </ClCompile>
+    <ClCompile Include="JNoise.cpp">
+      <Filter>world\generator\noise</Filter>
+    </ClCompile>
+    <ClCompile Include="BiomGenerator.cpp">
+      <Filter>world\generator\biom</Filter>
+    </ClCompile>
+    <ClCompile Include="GeneratorRule.cpp">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClCompile>
+    <ClCompile Include="BlockTypeGeneratorRule.cpp">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClCompile>
+    <ClCompile Include="TypeRegistry.cpp">
+      <Filter>server\config</Filter>
+    </ClCompile>
+    <ClCompile Include="StructureCollection.cpp">
+      <Filter>world\generator\templates</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 7 - 0
FactoryCraft/Game.cpp

@@ -280,6 +280,7 @@ void GameClient::sendTypes()
 Game::Game(Framework::Text name, Framework::Text worldsDir)
     : Thread(),
       name(name),
+      typeRegistry(new TypeRegistry()),
       dimensions(new RCArray<Dimension>()),
       updates(new RCArray<WorldUpdate>()),
       clients(new RCArray<GameClient>()),
@@ -320,6 +321,7 @@ Game::~Game()
     loader->release();
     chat->release();
     playerRegister->release();
+    typeRegistry->release();
 }
 
 void Game::initialize()
@@ -971,6 +973,11 @@ Player* Game::zPlayerByName(const char* name) const
     return 0;
 }
 
+TypeRegistry* Game::zTypeRegistry() const
+{
+    return typeRegistry;
+}
+
 int Game::getPlayerId(const char* name) const
 {
     return playerRegister->getPlayerId(name);

+ 3 - 0
FactoryCraft/Game.h

@@ -15,6 +15,7 @@
 #include "RecipieLoader.h"
 #include "Server.h"
 #include "TickOrganizer.h"
+#include "TypeRegistry.h"
 #include "WorldGenerator.h"
 #include "WorldLoader.h"
 #include "WorldUpdate.h"
@@ -74,6 +75,7 @@ class Game : public virtual Framework::Thread
 {
 private:
     Framework::Text name;
+    TypeRegistry* typeRegistry;
     Framework::RCArray<Dimension>* dimensions;
     Framework::RCArray<WorldUpdate>* updates;
     Framework::RCArray<GameClient>* clients;
@@ -144,6 +146,7 @@ public:
     TickOrganizer* zTickOrganizer() const;
     Chat* zChat() const;
     Player* zPlayerByName(const char* name) const;
+    TypeRegistry* zTypeRegistry() const;
     int getPlayerId(const char* name) const;
 
     double getAverageTickTime() const;

+ 3 - 3
FactoryCraft/GeneratedStructure.cpp

@@ -1,12 +1,12 @@
 #include "GeneratedStructure.h"
 
-#include "GenerationTemplate.h"
+#include "GeneratorTemplate.h"
 #include "MultiblockStructure.h"
 #include "NoBlock.h"
 
 using namespace Framework;
 
-GeneratedStructure::GeneratedStructure(GenerationTemplate* t,
+GeneratedStructure::GeneratedStructure(GeneratorTemplate* t,
     Framework::Vec3<int> originPos,
     Framework::Vec3<int> size,
     Framework::Vec3<int> minAffectedPos)
@@ -113,7 +113,7 @@ Framework::Vec3<int> GeneratedStructure::getOriginPos() const
     return originPos;
 }
 
-GenerationTemplate* GeneratedStructure::zTemplate() const
+GeneratorTemplate* GeneratedStructure::zTemplate() const
 {
     return t;
 }

+ 4 - 4
FactoryCraft/GeneratedStructure.h

@@ -6,7 +6,7 @@
 
 #include "Block.h"
 
-class GenerationTemplate;
+class GeneratorTemplate;
 class MultiblockStructure;
 
 class GeneratedStructure : public Framework::ReferenceCounter
@@ -17,11 +17,11 @@ private:
     Framework::Vec3<int> size;
     Framework::Vec3<int> minAffectedPos;
     Framework::Vec3<int> originPos;
-    GenerationTemplate* t;
+    GeneratorTemplate* t;
     MultiblockStructure* multiblock;
 
 public:
-    GeneratedStructure(GenerationTemplate* t,
+    GeneratedStructure(GeneratorTemplate* t,
         Framework::Vec3<int> originPos,
         Framework::Vec3<int> size,
         Framework::Vec3<int> minAffectedPos);
@@ -34,5 +34,5 @@ public:
     void addAllBlocksToStructure(MultiblockStructure* structure);
 
     Framework::Vec3<int> getOriginPos() const;
-    GenerationTemplate* zTemplate() const;
+    GeneratorTemplate* zTemplate() const;
 };

+ 0 - 37
FactoryCraft/GenerationTemplate.cpp

@@ -1,37 +0,0 @@
-#include "GenerationTemplate.h"
-
-
-GenerationTemplate::GenerationTemplate(float propability, int minSurfaceDist, int maxSurfaceDist, Framework::Vec3<int> minPosOffset, Framework::Vec3<int> maxSize)
-	: ReferenceCounter(),
-	propability(propability),
-	minSurfaceDist(minSurfaceDist),
-	maxSurfaceDist(maxSurfaceDist),
-	minPosOffset(minPosOffset),
-	maxSize(maxSize)
-{}
-
-bool GenerationTemplate::canEffect(Framework::Vec3<int> location, Framework::Vec3<int> affectedLocation) const
-{
-	Framework::Vec3<int> localPos = affectedLocation - (location + minPosOffset);
-	return localPos.x >= 0 && localPos.y >= 0 && localPos.z >= 0 && localPos.x < maxSize.x&& localPos.y < maxSize.y&& localPos.z < maxSize.z;
-}
-
-bool GenerationTemplate::isGenerationPossable(Framework::Vec3<int> location, int distToSurface) const
-{
-	return distToSurface >= minSurfaceDist && distToSurface <= maxSurfaceDist;
-}
-
-float GenerationTemplate::getPropability() const
-{
-	return propability;
-}
-
-Framework::Vec3<int> GenerationTemplate::getMinAffectedOffset() const
-{
-	return minPosOffset;
-}
-
-Framework::Vec3<int> GenerationTemplate::getMaxAffectedOffset() const
-{
-	return minPosOffset + maxSize;
-}

+ 47 - 0
FactoryCraft/GeneratorRule.cpp

@@ -0,0 +1,47 @@
+#include "GeneratorRule.h"
+
+#include "JNoise.h"
+
+GeneratorRule::GeneratorRule(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+    : ReferenceCounter(),
+      noise(0)
+{
+    if (zConfig->asObject()->hasValue("noise"))
+    {
+        noise = JNoise::parseNoisse(
+            zConfig->asObject()->zValue("noise"), zMemory);
+    }
+    condition = JExpressionParser::parseBoolExpression(
+        zConfig->asObject()->zValue("condition"));
+    if (zConfig->asObject()->hasValue("threshold"))
+    {
+        threshold = (float)zConfig->asObject()
+                        ->zValue("threshold")
+                        ->asNumber()
+                        ->getNumber();
+    }
+}
+
+GeneratorRule::~GeneratorRule()
+{
+    if (noise) noise->release();
+    if (condition) condition->release();
+}
+
+bool GeneratorRule::checkCondition(JExpressionMemory* zMemory)
+{
+    return condition->getValue(zMemory);
+}
+
+Framework::Either<Block*, int> GeneratorRule::generateBlock(
+    int x, int y, int z, int dimensionId)
+{
+    if (!noise || noise->getNoise((double)x, (double)y, (double)z) <= threshold)
+        return createBlock(x, y, z, dimensionId);
+    return BlockTypeEnum::NO_BLOCK;
+}
+
+GeneratorRuleFactory::GeneratorRuleFactory()
+    : ReferenceCounter()
+{}

+ 56 - 0
FactoryCraft/GeneratorRule.h

@@ -0,0 +1,56 @@
+#pragma once
+
+#include <Either.h>
+#include <JSON.h>
+
+#include "Block.h"
+#include "JNoise.h"
+#include "JsonExpression.h"
+
+class GeneratorRule : public virtual Framework::ReferenceCounter
+{
+private:
+    Noise* noise;
+    float threshold;
+    JBoolExpression* condition;
+
+protected:
+    virtual Framework::Either<Block*, int> createBlock(
+        int x, int y, int z, int dimensionId)
+        = 0;
+
+public:
+    GeneratorRule(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    ~GeneratorRule();
+
+    bool checkCondition(JExpressionMemory* zMemory);
+    Framework::Either<Block*, int> generateBlock(
+        int x, int y, int z, int dimensionId);
+
+    template<class T>
+    static Framework::JSON::Validator::ObjectValidationBuilder<T>*
+    addToValidator(
+        Framework::JSON::Validator::ObjectValidationBuilder<T>* builder)
+    {
+        return builder
+            ->withRequiredAttribute("noise", JNoise::getValidator(true))
+            ->withRequiredAttribute(
+                "condition", JExpressionParser::getBoolValidator())
+            ->withRequiredNumber("threshold")
+            ->whichIsOptional()
+            ->whichIsGreaterOrEqual(0.0)
+            ->whichIsLessOrEqual(1.0)
+            ->finishNumber();
+    }
+};
+
+class GeneratorRuleFactory : public virtual Framework::ReferenceCounter
+{
+public:
+    GeneratorRuleFactory();
+    virtual GeneratorRule* createRule(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+        = 0;
+    virtual Framework::JSON::Validator::JSONValidator* getValidator() = 0;
+};

+ 39 - 0
FactoryCraft/GeneratorTemplate.cpp

@@ -0,0 +1,39 @@
+#include "GeneratorTemplate.h"
+
+GeneratorTemplate::GeneratorTemplate(float propability,
+    Framework::Vec3<int> minPosOffset,
+    Framework::Vec3<int> maxSize)
+    : ReferenceCounter(),
+      propability(propability),
+      minPosOffset(minPosOffset),
+      maxSize(maxSize)
+{}
+
+bool GeneratorTemplate::canEffect(
+    Framework::Vec3<int> location, Framework::Vec3<int> affectedLocation) const
+{
+    Framework::Vec3<int> localPos
+        = affectedLocation - (location + minPosOffset);
+    return localPos.x >= 0 && localPos.y >= 0 && localPos.z >= 0
+        && localPos.x < maxSize.x && localPos.y < maxSize.y
+        && localPos.z < maxSize.z;
+}
+
+float GeneratorTemplate::getPropability() const
+{
+    return propability;
+}
+
+Framework::Vec3<int> GeneratorTemplate::getMinAffectedOffset() const
+{
+    return minPosOffset;
+}
+
+Framework::Vec3<int> GeneratorTemplate::getMaxAffectedOffset() const
+{
+    return minPosOffset + maxSize;
+}
+
+GeneratorTemplateFactory::GeneratorTemplateFactory()
+    : ReferenceCounter()
+{}

+ 12 - 8
FactoryCraft/GenerationTemplate.h → FactoryCraft/GeneratorTemplate.h

@@ -6,26 +6,20 @@
 #include "GeneratedStructure.h"
 #include "Noise.h"
 
-class GenerationTemplate : public Framework::ReferenceCounter
+class GeneratorTemplate : public Framework::ReferenceCounter
 {
 private:
     float propability;
-    int minSurfaceDist;
-    int maxSurfaceDist;
     Framework::Vec3<int> minPosOffset;
     Framework::Vec3<int> maxSize;
 
 public:
-    GenerationTemplate(float propability,
-        int minSurfaceDist,
-        int maxSurfaceDist,
+    GeneratorTemplate(float propability,
         Framework::Vec3<int> minPosOffset,
         Framework::Vec3<int> maxSize);
 
     virtual bool canEffect(Framework::Vec3<int> location,
         Framework::Vec3<int> affectedLocation) const;
-    virtual bool isGenerationPossable(
-        Framework::Vec3<int> location, int distToSurface) const;
     virtual GeneratedStructure* generateAt(
         Framework::Vec3<int> location, Noise* zNoise, int dimensionId)
         = 0;
@@ -33,4 +27,14 @@ public:
     float getPropability() const;
     Framework::Vec3<int> getMinAffectedOffset() const;
     Framework::Vec3<int> getMaxAffectedOffset() const;
+};
+
+class GeneratorTemplateFactory : public Framework::ReferenceCounter
+{
+public:
+    GeneratorTemplateFactory();
+    virtual GeneratorTemplate* createTemplate(
+        Framework::JSON::JSONValue* zConfig)
+        = 0;
+    virtual Framework::JSON::Validator::JSONValidator* getValidator() = 0;
 };

+ 0 - 150
FactoryCraft/GrasslandBiom.cpp

@@ -1,150 +0,0 @@
-#include "GrasslandBiom.h"
-
-#include "BasicBlocks.h"
-#include "BlockType.h"
-#include "Chunk.h"
-#include "Constants.h"
-#include "FastNoiseLite.h"
-#include "FastNoiseWrapper.h"
-#include "NoBlock.h"
-#include "TreeTemplate.h"
-#include "RandNoise.h"
-
-GrasslandBiom::GrasslandBiom()
-    : BiomGenerator()
-{
-    addTemplateGenerator(new TreeTemplate(0.002f,
-        BlockTypeEnum::WOOD_BIRCH,
-        BlockTypeEnum::LEAVES_WOOD_BIRCH,
-        8,
-        15));
-    addTemplateGenerator(new TreeTemplate(0.001f,
-        BlockTypeEnum::WOOD_BEECH,
-        BlockTypeEnum::LEAVES_WOOD_BEECH,
-        8,
-        13));
-    addTemplateGenerator(new TreeTemplate(0.0005f,
-        BlockTypeEnum::WOOD_OAK,
-        BlockTypeEnum::LEAVES_WOOD_OAK,
-        10,
-        15));
-    addTemplateGenerator(new TreeTemplate(0.00025f,
-        BlockTypeEnum::WOOD_PINE,
-        BlockTypeEnum::LEAVES_WOOD_PINE,
-        15,
-        24));
-    heightNoise = 0;
-    undergroundDirdNoise = 0;
-    surfaceSandNoise = 0;
-    undergroundGravelNoise = 0;
-    grassNoise = 0;
-}
-
-GrasslandBiom::~GrasslandBiom()
-{
-    if (heightNoise) heightNoise->release();
-    if (grassNoise) grassNoise->release();
-    if (undergroundGravelNoise) undergroundGravelNoise->release();
-    if (undergroundDirdNoise) undergroundDirdNoise->release();
-}
-
-Framework::Either<Block*, int> GrasslandBiom::generateAboveSurfaceBlock(int x,
-    int y,
-    int z,
-    int dimensionId,
-    int surfaceHeight,
-    Chunk* partialGeneratedChunk)
-{
-    int cx = x % CHUNK_SIZE;
-    int cy = y % CHUNK_SIZE;
-    if (cx < 0) cx += CHUNK_SIZE;
-    if (cy < 0) cy += CHUNK_SIZE;
-    auto below
-        = partialGeneratedChunk->zBlockAt(Framework::Vec3<int>(cx, cy, z - 1));
-    if ((below.isA()
-        && below.getA()->zBlockType()->getId() == BlockTypeEnum::DIRT)
-        || (below.isB() && below.getB() == BlockTypeEnum::DIRT))
-    {
-        if (grassNoise->getNoise((double)x, (double)y, (double)z) > 0.75)
-        {
-            return BlockTypeEnum::GRASS;
-        }
-    }
-    return BlockTypeEnum::AIR;
-}
-
-Framework::Either<Block*, int> GrasslandBiom::generateSurfaceBlock(
-    int x, int y, int z, int dimensionId)
-{
-    if (surfaceSandNoise->getNoise((double)x, (double)y, (double)z) < 0.35)
-    {
-        return BlockTypeEnum::SAND;
-    }
-    if (undergroundGravelNoise->getNoise((double)x, (double)y, (double)z)
-        < 0.35)
-    {
-        return BlockTypeEnum::GRAVEL;
-    }
-    return BlockTypeEnum::DIRT;
-}
-
-Framework::Either<Block*, int> GrasslandBiom::generateBelowSurfaceBlock(
-    int x, int y, int z, int dimensionId)
-{
-    if (undergroundDirdNoise->getNoise((double)x, (double)y, (double)z) < 0.35)
-    {
-        return BlockTypeEnum::DIRT;
-    }
-    if (undergroundGravelNoise->getNoise((double)x, (double)y, (double)z)
-        < 0.35)
-    {
-        return BlockTypeEnum::GRAVEL;
-    }
-    return BlockTypeEnum::STONE;
-}
-
-Framework::Either<Block*, int> GrasslandBiom::generateCaveBlock(
-    int x, int y, int z, int dimensionId)
-{
-    return BlockTypeEnum::AIR;
-}
-
-Framework::Either<Block*, int> GrasslandBiom::generateUnderWaterBlock(int x,
-    int y,
-    int z,
-    int dimensionId,
-    int surfaceHeight,
-    Chunk* partialGeneratedChunk)
-{
-    return StaticRegistry<BlockType>::INSTANCE.zElement(BlockTypeEnum::WATER)
-        ->createBlockAt(Framework::Vec3<int>(x, y, z), dimensionId, 0);
-}
-
-void GrasslandBiom::setSeed(int seed)
-{
-    BiomGenerator::setSeed(seed);
-    if (heightNoise) heightNoise->release();
-    FastNoiseLite* noise = new FastNoiseLite(seed);
-    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
-    FastNoiseWrapper* wrapper = new FastNoiseWrapper(noise, seed);
-    wrapper->setMultiplier(0.2f);
-    heightNoise = wrapper;
-    noise = new FastNoiseLite(seed);
-    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
-    noise->SetFrequency(0.15f);
-    undergroundDirdNoise = new FastNoiseWrapper(noise, seed);
-    noise = new FastNoiseLite(seed + 1);
-    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
-    noise->SetFrequency(0.125f);
-    undergroundGravelNoise = new FastNoiseWrapper(noise, seed + 1);
-    noise = new FastNoiseLite(seed + 2);
-    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
-    noise->SetFrequency(0.1f);
-    surfaceSandNoise = new FastNoiseWrapper(noise, seed + 2);
-    grassNoise = new RandNoise(seed + 3);
-}
-
-Noise* GrasslandBiom::zHeightMapNoise()
-{
-    return heightNoise;
-}

+ 0 - 39
FactoryCraft/GrasslandBiom.h

@@ -1,39 +0,0 @@
-#pragma once
-
-#include "BiomGenerator.h"
-#include "StaticRegistry.h"
-
-class GrasslandBiom : public BiomGenerator
-{
-    Noise* heightNoise;
-    Noise* undergroundDirdNoise;
-    Noise* surfaceSandNoise;
-    Noise* undergroundGravelNoise;
-    Noise* grassNoise;
-    // TODO: Noise* anySmallOreNoise;
-    // TODO: add water rivers
-
-public:
-    GrasslandBiom();
-    ~GrasslandBiom();
-    Framework::Either<Block*, int> generateAboveSurfaceBlock(int x,
-        int y,
-        int z,
-        int dimensionId,
-        int surfaceHeight,
-        Chunk* partialGeneratedChunk) override;
-    Framework::Either<Block*, int> generateSurfaceBlock(
-        int x, int y, int z, int dimensionId) override;
-    Framework::Either<Block*, int> generateBelowSurfaceBlock(
-        int x, int y, int z, int dimensionId) override;
-    Framework::Either<Block*, int> generateCaveBlock(
-        int x, int y, int z, int dimensionId) override;
-    Framework::Either<Block*, int> generateUnderWaterBlock(int x,
-        int y,
-        int z,
-        int dimensionId,
-        int surfaceHeight,
-        Chunk* partialGeneratedChunk) override;
-    Noise* zHeightMapNoise() override;
-    void setSeed(int seed) override;
-};

+ 13 - 0
FactoryCraft/ItemType.cpp

@@ -180,4 +180,17 @@ Item* ItemType::createBasicItem(int id,
     item->usable = usable;
     item->maxStackSize = maxStackSize;
     return item;
+}
+
+int ItemType::getTypeId(const char* name)
+{
+    for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
+    {
+        if (StaticRegistry<ItemType>::INSTANCE.zElement(i)
+            && StaticRegistry<ItemType>::INSTANCE.zElement(i)
+                   ->getName()
+                   .istGleich(name))
+            return StaticRegistry<ItemType>::INSTANCE.zElement(i)->getId();
+    }
+    return 0;
 }

+ 1 - 0
FactoryCraft/ItemType.h

@@ -88,4 +88,5 @@ public:
         bool solid,
         bool usable,
         int maxStackSize);
+    static int getTypeId(const char* name);
 };

+ 292 - 0
FactoryCraft/JNoise.cpp

@@ -0,0 +1,292 @@
+#include "JNoise.h"
+
+#include "FastNoiseWrapper.h"
+#include "RandNoise.h"
+
+using namespace Framework;
+
+Noise* JNoise::parseNoisse(JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+{
+    Text type = zConfig->asObject()->zValue("type")->asString()->getString();
+    if (type.istGleich("random"))
+    {
+        JFloatExpression* seedExpression
+            = JExpressionParser::parseFloatExpression(
+                zConfig->asObject()->zValue("seed"));
+        float seed = seedExpression->getValue(zMemory);
+        return new RandNoise((int)(seed + 0.5f));
+    }
+    else
+    {
+        JFloatExpression* seedExpression
+            = JExpressionParser::parseFloatExpression(
+                zConfig->asObject()->zValue("seed"));
+        float seed = seedExpression->getValue(zMemory);
+        FastNoiseLite* noise = new FastNoiseLite((int)(seed + 0.5f));
+        if (type.istGleich("Cellular"))
+            noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular);
+        else if (type.istGleich("ValueCubic"))
+            noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
+        else if (type.istGleich("Perlin"))
+            noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
+        else if (type.istGleich("OpenSimplex2S"))
+            noise->SetNoiseType(
+                FastNoiseLite::NoiseType::NoiseType_OpenSimplex2S);
+        else if (type.istGleich("OpenSimplex2"))
+            noise->SetNoiseType(
+                FastNoiseLite::NoiseType::NoiseType_OpenSimplex2);
+        else if (type.istGleich("Value"))
+            noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Value);
+        if (zConfig->asObject()->hasValue("rotationType3D"))
+        {
+            Text value = zConfig->asObject()
+                             ->zValue("rotationType3D")
+                             ->asString()
+                             ->getString();
+            if (value.istGleich("None"))
+            {
+                noise->SetRotationType3D(
+                    FastNoiseLite::RotationType3D::RotationType3D_None);
+            }
+            else if (value.istGleich("ImproveXYPlanes"))
+            {
+                noise->SetRotationType3D(FastNoiseLite::RotationType3D::
+                        RotationType3D_ImproveXYPlanes);
+            }
+            else if (value.istGleich("ImproveXZPlanes"))
+            {
+                noise->SetRotationType3D(FastNoiseLite::RotationType3D::
+                        RotationType3D_ImproveXZPlanes);
+            }
+        }
+        if (zConfig->asObject()->hasValue("frequency"))
+        {
+            noise->SetFrequency((float)zConfig->asObject()
+                                    ->zValue("frequency")
+                                    ->asNumber()
+                                    ->getNumber());
+        }
+        if (zConfig->asObject()->hasValue("fractalType"))
+        {
+            Text value = zConfig->asObject()
+                             ->zValue("fractalType")
+                             ->asString()
+                             ->getString();
+            if (value.istGleich("None"))
+            {
+                noise->SetFractalType(
+                    FastNoiseLite::FractalType::FractalType_None);
+            }
+            else if (value.istGleich("FBm"))
+            {
+                noise->SetFractalType(
+                    FastNoiseLite::FractalType::FractalType_FBm);
+            }
+            else if (value.istGleich("Ridged"))
+            {
+                noise->SetFractalType(
+                    FastNoiseLite::FractalType::FractalType_Ridged);
+            }
+            else if (value.istGleich("PingPong"))
+            {
+                noise->SetFractalType(
+                    FastNoiseLite::FractalType::FractalType_PingPong);
+            }
+            else if (value.istGleich("DomainWarpProgressive"))
+            {
+                noise->SetFractalType(FastNoiseLite::FractalType::
+                        FractalType_DomainWarpProgressive);
+            }
+            else if (value.istGleich("DomainWarpIndependent"))
+            {
+                noise->SetFractalType(FastNoiseLite::FractalType::
+                        FractalType_DomainWarpIndependent);
+            }
+        }
+        if (zConfig->asObject()->hasValue("cellularDistanceFunction"))
+        {
+            Text value = zConfig->asObject()
+                             ->zValue("cellularDistanceFunction")
+                             ->asString()
+                             ->getString();
+            if (value.istGleich("Hybrid"))
+            {
+                noise->SetCellularDistanceFunction(
+                    FastNoiseLite::CellularDistanceFunction::
+                        CellularDistanceFunction_Hybrid);
+            }
+            else if (value.istGleich("Manhattan"))
+            {
+                noise->SetCellularDistanceFunction(
+                    FastNoiseLite::CellularDistanceFunction::
+                        CellularDistanceFunction_Manhattan);
+            }
+            else if (value.istGleich("EuclideanSq"))
+            {
+                noise->SetCellularDistanceFunction(
+                    FastNoiseLite::CellularDistanceFunction::
+                        CellularDistanceFunction_EuclideanSq);
+            }
+            else if (value.istGleich("Euclidean"))
+            {
+                noise->SetCellularDistanceFunction(
+                    FastNoiseLite::CellularDistanceFunction::
+                        CellularDistanceFunction_Euclidean);
+            }
+        }
+        if (zConfig->asObject()->hasValue("cellularReturnType"))
+        {
+            Text value = zConfig->asObject()
+                             ->zValue("cellularReturnType")
+                             ->asString()
+                             ->getString();
+            if (value.istGleich("CellValue"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_CellValue);
+            }
+            else if (value.istGleich("Distance"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_Distance);
+            }
+            else if (value.istGleich("Distance2"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_Distance2);
+            }
+            else if (value.istGleich("Distance2Add"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_Distance2Add);
+            }
+            else if (value.istGleich("Distance2Sub"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_Distance2Sub);
+            }
+            else if (value.istGleich("Distance2Mul"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_Distance2Mul);
+            }
+            else if (value.istGleich("Distance2Div"))
+            {
+                noise->SetCellularReturnType(FastNoiseLite::CellularReturnType::
+                        CellularReturnType_Distance2Div);
+            }
+        }
+        if (zConfig->asObject()->hasValue("cellularJitter"))
+        {
+            noise->SetCellularJitter((float)zConfig->asObject()
+                                         ->zValue("cellularJitter")
+                                         ->asNumber()
+                                         ->getNumber());
+        }
+        if (zConfig->asObject()->hasValue("domainWarpType"))
+        {
+            Text value = zConfig->asObject()
+                             ->zValue("domainWarpType")
+                             ->asString()
+                             ->getString();
+            if (value.istGleich("OpenSimplex2Reduced"))
+            {
+                noise->SetDomainWarpType(FastNoiseLite::DomainWarpType::
+                        DomainWarpType_OpenSimplex2Reduced);
+            }
+            else if (value.istGleich("OpenSimplex2"))
+            {
+                noise->SetDomainWarpType(
+                    FastNoiseLite::DomainWarpType::DomainWarpType_OpenSimplex2);
+            }
+            else if (value.istGleich("BasicGrid"))
+            {
+                noise->SetDomainWarpType(
+                    FastNoiseLite::DomainWarpType::DomainWarpType_BasicGrid);
+            }
+        }
+        if (zConfig->asObject()->hasValue("domainWarpAmp"))
+        {
+            noise->SetDomainWarpAmp((float)zConfig->asObject()
+                                        ->zValue("domainWarpAmp")
+                                        ->asNumber()
+                                        ->getNumber());
+        }
+        return new FastNoiseWrapper(noise, (int)(seed + 0.5f));
+    }
+    return 0;
+}
+
+JSON::Validator::JSONValidator* JNoise::getValidator(bool optional)
+{
+    auto validator1 = JSON::Validator::JSONValidator::buildForObject();
+    auto validator2 = JSON::Validator::JSONValidator::buildForObject();
+    if (optional)
+    {
+        validator1 = validator1->whichIsOptional();
+        validator2 = validator2->whichIsOptional();
+    }
+    return JSON::Validator::JSONValidator::buildForOneOf()
+        ->typeSpecifiedByAttribute("type")
+        ->addAcceptedType(validator1->withRequiredString("type")
+                              ->withExactMatch("random")
+                              ->finishString()
+                              ->withRequiredAttribute("seed",
+                                  JExpressionParser::getFloatValidator())
+                              ->finishObject())
+        ->addAcceptedType(
+            validator2->withRequiredString("type")
+                ->whichIsOneOf({"Cellular",
+                    "ValueCubic",
+                    "Perlin",
+                    "OpenSimplex2S",
+                    "OpenSimplex2",
+                    "Value"})
+                ->finishString()
+                ->withRequiredAttribute(
+                    "seed", JExpressionParser::getFloatValidator())
+                ->withRequiredString("rotationType3D")
+                ->whichIsOptional()
+                ->whichIsOneOf({"None", "ImproveXYPlanes", "ImproveXZPlanes"})
+                ->finishString()
+                ->withRequiredNumber("frequency")
+                ->whichIsOptional()
+                ->finishNumber()
+                ->withRequiredString("fractalType")
+                ->whichIsOptional()
+                ->whichIsOneOf({"None",
+                    "FBm",
+                    "Ridged",
+                    "PingPong",
+                    "DomainWarpProgressive",
+                    "DomainWarpIndependent"})
+                ->finishString()
+                ->withRequiredString("cellularDistanceFunction")
+                ->whichIsOptional()
+                ->whichIsOneOf(
+                    {"Hybrid", "Manhattan", "EuclideanSq", "Euclidean"})
+                ->finishString()
+                ->withRequiredString("cellularReturnType")
+                ->whichIsOptional()
+                ->whichIsOneOf({"CellValue",
+                    "Distance",
+                    "Distance2",
+                    "Distance2Add",
+                    "Distance2Sub",
+                    "Distance2Mul",
+                    "Distance2Div"})
+                ->finishString()
+                ->withRequiredNumber("cellularJitter")
+                ->whichIsOptional()
+                ->finishNumber()
+                ->withRequiredString("domainWarpType")
+                ->whichIsOptional()
+                ->whichIsOneOf(
+                    {"BasicGrid", "OpenSimplex2", "OpenSimplex2Reduced"})
+                ->finishString()
+                ->withRequiredNumber("domainWarpAmp")
+                ->whichIsOptional()
+                ->finishNumber()
+                ->finishObject())
+        ->finishOneOf();
+}

+ 13 - 0
FactoryCraft/JNoise.h

@@ -0,0 +1,13 @@
+#pragma once
+
+#include <JSON.h>
+
+#include "Noise.h"
+#include "JsonExpression.h"
+
+namespace JNoise
+{
+    Noise* parseNoisse(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    Framework::JSON::Validator::JSONValidator* getValidator(bool optional);
+}

+ 584 - 0
FactoryCraft/JsonExpression.cpp

@@ -0,0 +1,584 @@
+#include "JsonExpression.h"
+
+#include "DimensionGenerator.h"
+#include "Game.h"
+
+JExpressionMemory::JExpressionMemory()
+    : ReferenceCounter(),
+      currentChunk(0)
+{}
+
+JExpressionMemory::~JExpressionMemory()
+{
+    if (currentChunk) currentChunk->release();
+}
+
+void JExpressionMemory::lock()
+{
+    cs.lock();
+}
+
+void JExpressionMemory::unlock()
+{
+    cs.unlock();
+}
+
+float JExpressionMemory::getNoise(
+    Framework::Text name, float x, float y, float z) const
+{
+    Noise* currentNoise = noises.z(name, name.getLength());
+    if (currentNoise)
+        return (float)currentNoise->getNoise((double)x, (double)y, (double)z);
+    return 0.f;
+}
+
+void JExpressionMemory::setNoise(Framework::Text name, Noise* noise)
+{
+    noises.set(name, name.getLength(), noise);
+}
+
+void JExpressionMemory::setCurrentChunk(Chunk* chunk)
+{
+    if (currentChunk) currentChunk->release();
+    currentChunk = chunk;
+}
+
+float JExpressionMemory::getFloatVariable(Framework::Text name) const
+{
+    return floatVariables.get(name, name.getLength());
+}
+
+void JExpressionMemory::setFloatVariable(Framework::Text name, float value)
+{
+    floatVariables.set(name, name.getLength(), value);
+}
+
+bool JExpressionMemory::getBoolVariable(Framework::Text name) const
+{
+    return boolVariables.get(name, name.getLength());
+}
+
+void JExpressionMemory::setBoolVariable(Framework::Text name, bool value)
+{
+    return boolVariables.set(name, name.getLength(), value);
+}
+
+Chunk* JExpressionMemory::zCurrentChunk()
+{
+    return currentChunk;
+}
+
+JFloatExpression::JFloatExpression()
+    : ReferenceCounter()
+{}
+
+JBoolExpression::JBoolExpression()
+    : ReferenceCounter()
+{}
+
+JVariableFloatExpression::JVariableFloatExpression(Framework::Text name)
+    : JFloatExpression(),
+      name(name)
+{}
+
+float JVariableFloatExpression::getValue(JExpressionMemory* zMemory)
+{
+    return zMemory->getFloatVariable(name);
+}
+
+JVariableBoolExpression::JVariableBoolExpression(Framework::Text name)
+    : JBoolExpression(),
+      name(name)
+{}
+
+bool JVariableBoolExpression::getValue(JExpressionMemory* zMemory)
+{
+    return zMemory->getBoolVariable(name);
+}
+
+JConstantFloatExpression::JConstantFloatExpression(float value)
+    : JFloatExpression(),
+      value(value)
+{}
+
+float JConstantFloatExpression::getValue(JExpressionMemory* zMemory)
+{
+    return value;
+}
+
+JConstantBoolExpression::JConstantBoolExpression(bool value)
+    : JBoolExpression(),
+      value(value)
+{}
+
+bool JConstantBoolExpression::getValue(JExpressionMemory* zMemory)
+{
+    return value;
+}
+
+JNoiseFloatExpression::JNoiseFloatExpression(Framework::Text name,
+    JFloatExpression* x,
+    JFloatExpression* y,
+    JFloatExpression* z)
+    : JFloatExpression(),
+      name(name),
+      x(x),
+      y(y),
+      z(z)
+{}
+
+JNoiseFloatExpression::~JNoiseFloatExpression()
+{
+    x->release();
+    y->release();
+    z->release();
+}
+
+float JNoiseFloatExpression::getValue(JExpressionMemory* zMemory)
+{
+    return zMemory->getNoise(
+        name, x->getValue(zMemory), y->getValue(zMemory), z->getValue(zMemory));
+}
+
+JOperatorFloatExpression::JOperatorFloatExpression(
+    std::function<float(float a, float b)> accumulator,
+    Framework::RCArray<JFloatExpression>* values)
+    : JFloatExpression(),
+      accumulator(accumulator),
+      values(values)
+{}
+
+JOperatorFloatExpression::~JOperatorFloatExpression()
+{
+    values->release();
+}
+
+float JOperatorFloatExpression::getValue(JExpressionMemory* zMemory)
+{
+    bool first = 1;
+    float val = 0.f;
+    for (JFloatExpression* expression : *values)
+    {
+        if (first)
+        {
+            first = 0;
+            val = expression->getValue(zMemory);
+        }
+        else
+        {
+            val = accumulator(val, expression->getValue(zMemory));
+        }
+    }
+    return val;
+}
+
+JBoolOperatorBoolExpression::JBoolOperatorBoolExpression(
+    std::function<bool(bool a, bool b)> accumulator,
+    Framework::RCArray<JBoolExpression>* values)
+    : JBoolExpression(),
+      accumulator(accumulator),
+      values(values)
+{}
+
+JBoolOperatorBoolExpression::~JBoolOperatorBoolExpression()
+{
+    values->release();
+}
+
+bool JBoolOperatorBoolExpression::getValue(JExpressionMemory* zMemory)
+{
+    bool first = 1;
+    bool val = 0;
+    for (JBoolExpression* expression : *values)
+    {
+        if (first)
+        {
+            first = 0;
+            val = expression->getValue(zMemory);
+        }
+        else
+        {
+            val = accumulator(val, expression->getValue(zMemory));
+        }
+    }
+    return val;
+}
+
+JFloatOperatorBoolExpression::JFloatOperatorBoolExpression(
+    std::function<bool(float a, float b)> accumulator,
+    Framework::RCArray<JFloatExpression>* values)
+    : JBoolExpression(),
+      accumulator(accumulator),
+      values(values)
+{}
+
+JFloatOperatorBoolExpression::~JFloatOperatorBoolExpression()
+{
+    values->release();
+}
+
+bool JFloatOperatorBoolExpression::getValue(JExpressionMemory* zMemory)
+{
+    bool first = 1;
+    bool val = 1;
+    float last = 0.f;
+    for (JFloatExpression* expression : *values)
+    {
+        float current = expression->getValue(zMemory);
+        if (!first) val &= accumulator(last, current);
+        first = 0;
+        last = current;
+    }
+    return val;
+}
+
+JBlockTypeBoolExpression::JBlockTypeBoolExpression(
+    int typeId, JFloatExpression* x, JFloatExpression* y, JFloatExpression* z)
+    : JBoolExpression(),
+      typeId(typeId),
+      x(x),
+      y(y),
+      z(z)
+{}
+
+JBlockTypeBoolExpression ::~JBlockTypeBoolExpression()
+{
+    x->release();
+    y->release();
+    z->release();
+}
+
+bool JBlockTypeBoolExpression::getValue(JExpressionMemory* zMemory)
+{
+    int x = (int)(this->x->getValue(zMemory) + 0.5f);
+    int y = (int)(this->y->getValue(zMemory) + 0.5f);
+    int z = (int)(this->z->getValue(zMemory) + 0.5f);
+    if (x < 0 || y < 0 || z < 0 || z >= WORLD_HEIGHT
+        || !zMemory->zCurrentChunk()
+        || Game::getChunkCenter(x, y) != zMemory->zCurrentChunk()->getCenter())
+    {
+        return 0;
+    }
+    return zMemory->zCurrentChunk()->getBlockTypeAt(
+               Dimension::chunkCoordinates({x, y, z}))
+        == typeId;
+}
+
+using namespace Framework::JSON;
+using namespace Framework::JSON::Validator;
+
+JFloatExpression* JExpressionParser::parseFloatExpression(
+    Framework::JSON::JSONValue* zValue)
+{
+    JSONObject* obj = zValue->asObject();
+    Framework::Text type = obj->zValue("type")->asString()->getString();
+    if (type.istGleich("variable"))
+    {
+        return new JVariableFloatExpression(
+            obj->zValue("name")->asString()->getString());
+    }
+    else if (type.istGleich("constant"))
+    {
+        return new JConstantFloatExpression(
+            (float)obj->zValue("value")->asNumber()->getNumber());
+    }
+    else if (type.istGleich("noise"))
+    {
+        return new JNoiseFloatExpression(
+            obj->zValue("name")->asString()->getString(),
+            parseFloatExpression(obj->zValue("x")),
+            parseFloatExpression(obj->zValue("y")),
+            parseFloatExpression(obj->zValue("z")));
+    }
+    else if (type.istGleich("operator"))
+    {
+        Framework::RCArray<JFloatExpression>* values
+            = new Framework::RCArray<JFloatExpression>();
+        JSONArray* valuesArray = obj->zValue("values")->asArray();
+        for (JSONValue* value : *valuesArray)
+        {
+            values->add(parseFloatExpression(value));
+        }
+        Framework::Text op = obj->zValue("operator")->asString()->getString();
+        if (op.istGleich("+"))
+        {
+            return new JOperatorFloatExpression(
+                [](float a, float b) { return a + b; }, values);
+        }
+        else if (op.istGleich("-"))
+        {
+            return new JOperatorFloatExpression(
+                [](float a, float b) { return a - b; }, values);
+        }
+        else if (op.istGleich("*"))
+        {
+            return new JOperatorFloatExpression(
+                [](float a, float b) { return a * b; }, values);
+        }
+        else if (op.istGleich("/"))
+        {
+            return new JOperatorFloatExpression(
+                [](float a, float b) { return a / b; }, values);
+        }
+        else
+        {
+            values->release();
+        }
+    }
+    return 0;
+}
+
+Framework::JSON::Validator::JSONValidator*
+JExpressionParser::getFloatValidator()
+{
+    JSONValidator* refs
+        = JSONValidator::buildForOneOf()
+              ->typeSpecifiedByAttribute("type")
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jef_variable"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jef_constant"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jef_noise"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jef_operator"))
+              ->finishOneOf();
+    JSONValidator* validator
+        = JSONValidator::buildForOneOf()
+              ->typeSpecifiedByAttribute("type")
+              ->addAcceptedType(JSONValidator::buildForObject()
+                                    ->setObjectReferenceId("jef_variable")
+                                    ->withRequiredString("type")
+                                    ->whichIs("variable")
+                                    ->finishString()
+                                    ->withRequiredString("name")
+                                    ->finishString()
+                                    ->finishObject())
+              ->addAcceptedType(JSONValidator::buildForObject()
+                                    ->setObjectReferenceId("jef_constant")
+                                    ->withRequiredString("type")
+                                    ->whichIs("constant")
+                                    ->finishString()
+                                    ->withRequiredNumber("value")
+                                    ->finishNumber()
+                                    ->finishObject())
+              ->addAcceptedType(
+                  JSONValidator::buildForObject()
+                      ->setObjectReferenceId("jef_noise")
+                      ->withRequiredString("type")
+                      ->whichIs("noise")
+                      ->finishString()
+                      ->withRequiredString("name")
+                      ->withDefault("noise")
+                      ->finishString()
+                      ->withRequiredAttribute(
+                          "x", dynamic_cast<JSONValidator*>(refs->getThis()))
+                      ->withRequiredAttribute(
+                          "y", dynamic_cast<JSONValidator*>(refs->getThis()))
+                      ->withRequiredAttribute(
+                          "z", dynamic_cast<JSONValidator*>(refs->getThis()))
+                      ->finishObject())
+              ->addAcceptedType(
+                  JSONValidator::buildForObject()
+                      ->setObjectReferenceId("jef_operator")
+                      ->withRequiredString("type")
+                      ->whichIs("operator")
+                      ->finishString()
+                      ->withRequiredString("operator")
+                      ->whichIsOneOf({"+", "-", "*", "/"})
+                      ->finishString()
+                      ->withRequiredArray("values")
+                      ->addAcceptedTypeInArray(
+                          dynamic_cast<JSONValidator*>(refs->getThis()))
+                      ->finishArray()
+                      ->finishObject())
+              ->finishOneOf();
+    return validator;
+}
+
+JBoolExpression* JExpressionParser::parseBoolExpression(
+    Framework::JSON::JSONValue* zValue)
+{
+    JSONObject* obj = zValue->asObject();
+    Framework::Text type = obj->zValue("type")->asString()->getString();
+    if (type.istGleich("variable"))
+    {
+        return new JVariableBoolExpression(
+            obj->zValue("name")->asString()->getString());
+    }
+    else if (type.istGleich("constant"))
+    {
+        return new JConstantBoolExpression(
+            (float)obj->zValue("value")->asBool()->getBool());
+    }
+    else if (type.istGleich("blockType"))
+    {
+        return new JBlockTypeBoolExpression(
+            BlockType::getTypeId(
+                obj->zValue("blockType")->asString()->getString()),
+            parseFloatExpression(obj->zValue("x")),
+            parseFloatExpression(obj->zValue("y")),
+            parseFloatExpression(obj->zValue("z")));
+    }
+    else if (type.istGleich("operator"))
+    {
+        Framework::Text op = obj->zValue("operator")->asString()->getString();
+        if (op.istGleich("&&") || op.istGleich("||"))
+        {
+            Framework::RCArray<JBoolExpression>* values
+                = new Framework::RCArray<JBoolExpression>();
+            JSONArray* valuesArray = obj->zValue("values")->asArray();
+            for (JSONValue* value : *valuesArray)
+            {
+                values->add(parseBoolExpression(value));
+            }
+            if (op.istGleich("&&"))
+            {
+                return new JBoolOperatorBoolExpression(
+                    [](bool a, bool b) { return a && b; }, values);
+            }
+            else if (op.istGleich("||"))
+            {
+                return new JBoolOperatorBoolExpression(
+                    [](bool a, bool b) { return a || b; }, values);
+            }
+            else
+            {
+                values->release();
+            }
+        }
+        else
+        {
+            Framework::RCArray<JFloatExpression>* values
+                = new Framework::RCArray<JFloatExpression>();
+            JSONArray* valuesArray = obj->zValue("values")->asArray();
+            for (JSONValue* value : *valuesArray)
+            {
+                values->add(parseFloatExpression(value));
+            }
+            if (op.istGleich(">"))
+            {
+                return new JFloatOperatorBoolExpression(
+                    [](float a, float b) { return a > b; }, values);
+            }
+            else if (op.istGleich("<"))
+            {
+                return new JFloatOperatorBoolExpression(
+                    [](float a, float b) { return a < b; }, values);
+            }
+            else if (op.istGleich(">="))
+            {
+                return new JFloatOperatorBoolExpression(
+                    [](float a, float b) { return a >= b; }, values);
+            }
+            else if (op.istGleich("<="))
+            {
+                return new JFloatOperatorBoolExpression(
+                    [](float a, float b) { return a <= b; }, values);
+            }
+            else if (op.istGleich("=="))
+            {
+                return new JFloatOperatorBoolExpression(
+                    [](float a, float b) { return a == b; }, values);
+            }
+            else if (op.istGleich("!="))
+            {
+                return new JFloatOperatorBoolExpression(
+                    [](float a, float b) { return a != b; }, values);
+            }
+            else
+            {
+                values->release();
+            }
+        }
+    }
+    return 0;
+}
+
+Framework::JSON::Validator::JSONValidator* JExpressionParser::getBoolValidator()
+{
+    Framework::RCArray<Framework::Text> blockTypeNames;
+    for (int i = 0; i < StaticRegistry<BlockType>::INSTANCE.getCount(); i++)
+    {
+        if (StaticRegistry<BlockType>::INSTANCE.zElement(i))
+        {
+            blockTypeNames.add(new Framework::Text(
+                StaticRegistry<BlockType>::INSTANCE.zElement(i)->getName()));
+        }
+    }
+    JSONValidator* refs
+        = JSONValidator::buildForOneOf()
+              ->typeSpecifiedByAttribute("type")
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jeb_variable"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jeb_constant"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jeb_blockType"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jeb_bool_operator"))
+              ->addAcceptedType(
+                  JSONValidator::buildForObjectReference("jeb_float_operator"))
+              ->finishOneOf();
+    JSONValidator* validator
+        = JSONValidator::buildForOneOf()
+              ->typeSpecifiedByAttribute("type")
+              ->addAcceptedType(JSONValidator::buildForObject()
+                                    ->setObjectReferenceId("jeb_variable")
+                                    ->withRequiredString("type")
+                                    ->whichIs("variable")
+                                    ->finishString()
+                                    ->withRequiredString("name")
+                                    ->finishString()
+                                    ->finishObject())
+              ->addAcceptedType(JSONValidator::buildForObject()
+                                    ->setObjectReferenceId("jeb_constant")
+                                    ->withRequiredString("type")
+                                    ->whichIs("constant")
+                                    ->finishString()
+                                    ->withRequiredBool("value")
+                                    ->finishBool()
+                                    ->finishObject())
+              ->addAcceptedType(
+                  JSONValidator::buildForObject()
+                      ->setObjectReferenceId("jeb_blockType")
+                      ->withRequiredString("type")
+                      ->whichIs("blockType")
+                      ->finishString()
+                      ->withRequiredString("blockType")
+                      ->whichIsOneOf(blockTypeNames)
+                      ->finishString()
+                      ->withRequiredAttribute("x", getFloatValidator())
+                      ->withRequiredAttribute("y", getFloatValidator())
+                      ->withRequiredAttribute("z", getFloatValidator())
+                      ->finishObject())
+              ->addAcceptedType(
+                  JSONValidator::buildForObject()
+                      ->setObjectReferenceId("jeb_bool_operator")
+                      ->withRequiredString("type")
+                      ->whichIs("operator")
+                      ->finishString()
+                      ->withRequiredString("operator")
+                      ->whichIsOneOf({"&&", "||"})
+                      ->finishString()
+                      ->withRequiredArray("values")
+                      ->addAcceptedTypeInArray(
+                          dynamic_cast<JSONValidator*>(refs->getThis()))
+                      ->finishArray()
+                      ->finishObject())
+              ->addAcceptedType(
+                  JSONValidator::buildForObject()
+                      ->setObjectReferenceId("jeb_float_operator")
+                      ->withRequiredString("type")
+                      ->whichIs("operator")
+                      ->finishString()
+                      ->withRequiredString("operator")
+                      ->whichIsOneOf({">", "<", ">=", "<=", "==", "!="})
+                      ->finishString()
+                      ->withRequiredArray("values")
+                      ->addAcceptedTypeInArray(getFloatValidator())
+                      ->finishArray()
+                      ->finishObject())
+              ->finishOneOf();
+    return validator;
+}

+ 180 - 0
FactoryCraft/JsonExpression.h

@@ -0,0 +1,180 @@
+#pragma once
+
+#include <Array.h>
+#include <functional>
+#include <JSON.h>
+#include <Text.h>
+#include <Trie.h>
+
+#include "Chunk.h"
+#include "Noise.h"
+
+class JExpressionMemory;
+
+class JExpressionMemory : public virtual Framework::ReferenceCounter
+{
+private:
+    Framework::RCTrie<Noise> noises;
+    Framework::Trie<float> floatVariables;
+    Framework::Trie<bool> boolVariables;
+    Chunk* currentChunk;
+    Framework::Critical cs;
+
+public:
+    JExpressionMemory();
+    ~JExpressionMemory();
+
+    void lock();
+    void unlock();
+
+    float getNoise(Framework::Text name, float x, float y, float z) const;
+    void setNoise(Framework::Text name, Noise* noise);
+    void setCurrentChunk(Chunk* chunk);
+
+    float getFloatVariable(Framework::Text name) const;
+    void setFloatVariable(Framework::Text name, float value);
+    bool getBoolVariable(Framework::Text name) const;
+    void setBoolVariable(Framework::Text name, bool value);
+    Chunk* zCurrentChunk();
+};
+
+class JFloatExpression : public virtual Framework::ReferenceCounter
+{
+private:
+
+public:
+    JFloatExpression();
+    virtual float getValue(JExpressionMemory* zMemory) = 0;
+};
+
+class JBoolExpression : public virtual Framework::ReferenceCounter
+{
+private:
+
+public:
+    JBoolExpression();
+    virtual bool getValue(JExpressionMemory* zMemory) = 0;
+};
+
+class JVariableFloatExpression : public JFloatExpression
+{
+private:
+    Framework::Text name;
+
+public:
+    JVariableFloatExpression(Framework::Text name);
+    float getValue(JExpressionMemory* zMemory) override;
+};
+
+class JVariableBoolExpression : public JBoolExpression
+{
+private:
+    Framework::Text name;
+
+public:
+    JVariableBoolExpression(Framework::Text name);
+    bool getValue(JExpressionMemory* zMemory) override;
+};
+
+class JConstantFloatExpression : public JFloatExpression
+{
+private:
+    float value;
+
+public:
+    JConstantFloatExpression(float value);
+    float getValue(JExpressionMemory* zMemory) override;
+};
+
+class JConstantBoolExpression : public JBoolExpression
+{
+private:
+    bool value;
+
+public:
+    JConstantBoolExpression(bool value);
+    bool getValue(JExpressionMemory* zMemory) override;
+};
+
+class JNoiseFloatExpression : public JFloatExpression
+{
+private:
+    Framework::Text name;
+    JFloatExpression* x;
+    JFloatExpression* y;
+    JFloatExpression* z;
+
+public:
+    JNoiseFloatExpression(Framework::Text name,
+        JFloatExpression* x,
+        JFloatExpression* y,
+        JFloatExpression* z);
+    ~JNoiseFloatExpression();
+    float getValue(JExpressionMemory* zMemory) override;
+};
+
+class JOperatorFloatExpression : public JFloatExpression
+{
+private:
+    std::function<float(float a, float b)> accumulator;
+    Framework::RCArray<JFloatExpression>* values;
+
+public:
+    JOperatorFloatExpression(std::function<float(float a, float b)> accumulator,
+        Framework::RCArray<JFloatExpression>* values);
+    ~JOperatorFloatExpression();
+    float getValue(JExpressionMemory* zMemory) override;
+};
+
+class JBoolOperatorBoolExpression : public JBoolExpression
+{
+private:
+    std::function<bool(bool a, bool b)> accumulator;
+    Framework::RCArray<JBoolExpression>* values;
+
+public:
+    JBoolOperatorBoolExpression(std::function<bool(bool a, bool b)> accumulator,
+        Framework::RCArray<JBoolExpression>* values);
+    ~JBoolOperatorBoolExpression();
+    bool getValue(JExpressionMemory* zMemory) override;
+};
+
+class JFloatOperatorBoolExpression : public JBoolExpression
+{
+private:
+    std::function<bool(float a, float b)> accumulator;
+    Framework::RCArray<JFloatExpression>* values;
+
+public:
+    JFloatOperatorBoolExpression(
+        std::function<bool(float a, float b)> accumulator,
+        Framework::RCArray<JFloatExpression>* values);
+    ~JFloatOperatorBoolExpression();
+    bool getValue(JExpressionMemory* zMemory) override;
+};
+
+class JBlockTypeBoolExpression : public JBoolExpression
+{
+private:
+    int typeId;
+    JFloatExpression* x;
+    JFloatExpression* y;
+    JFloatExpression* z;
+
+public:
+    JBlockTypeBoolExpression(int typeId,
+        JFloatExpression* x,
+        JFloatExpression* y,
+        JFloatExpression* z);
+    ~JBlockTypeBoolExpression();
+    bool getValue(JExpressionMemory* zMemory) override;
+};
+
+namespace JExpressionParser
+{
+    JFloatExpression* parseFloatExpression(Framework::JSON::JSONValue* zValue);
+    Framework::JSON::Validator::JSONValidator* getFloatValidator();
+
+    JBoolExpression* parseBoolExpression(Framework::JSON::JSONValue* zValue);
+    Framework::JSON::Validator::JSONValidator* getBoolValidator();
+}; // namespace JExpressionParser

+ 0 - 20
FactoryCraft/LocationChangedEvent.h

@@ -1,20 +0,0 @@
-#pragma once
-
-#include "Event.h"
-#include "Block.h"
-
-#include <Vec3.h>
-
-class LocationChangedEvent : public Event
-{
-private:
-    const Block *block;
-    const Framework::Vec3<int> oldPosition;
-    const Framework::Vec3<int> newPosition;
-
-public:
-    LocationChangedEvent( Block *block, Framework::Vec3<int> oldPosition, Framework::Vec3<int> newPosition );
-
-    Framework::Vec3<int> getOldPosition() const;
-    Framework::Vec3<int> getNewPosition() const;
-};

+ 463 - 34
FactoryCraft/OverworldDimension.cpp

@@ -1,49 +1,478 @@
 #include "OverworldDimension.h"
 
 #include "FastNoiseWrapper.h"
-#include "GrasslandBiom.h"
 #include "RandNoise.h"
 #include "WormCaveGenerator.h"
 
-OverworldDimension::OverworldDimension()
-    : DimensionGenerator(
-        DimensionEnum::OVERWORLD, new WormCaveGenerator(75, 150, 1, 6, 0.1f))
-{
-    registerBiom(new GrasslandBiom(), 1.0);
-    biomNoise = 0;
-    structureNoise = 0;
-}
+OverworldDimensionFactory::OverworldDimensionFactory()
+    : DimensionGeneratorFactory("Overworld", DimensionEnum::OVERWORLD)
+{}
 
-OverworldDimension::~OverworldDimension()
+DimensionGenerator* OverworldDimensionFactory::createDimensionGenerator(
+    int worldSeed, Framework::JSON::JSONValue* config)
 {
-    if (biomNoise) biomNoise->release();
-    if (structureNoise) structureNoise->release();
+    return new BiomedCavedDimensionGenerator(config, worldSeed);
 }
 
-Noise* OverworldDimension::zBiomNoise()
+Framework::JSON::Validator::JSONValidator*
+OverworldDimensionFactory::getConfigValidator()
 {
-    if (biomNoise) return biomNoise;
-    FastNoiseLite* noise = new FastNoiseLite(seed);
-    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular);
-    noise->SetRotationType3D(
-        FastNoiseLite::RotationType3D::RotationType3D_None);
-    noise->SetFrequency(0.015f);
-    noise->SetFractalType(FastNoiseLite::FractalType::FractalType_None);
-    noise->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::
-            CellularDistanceFunction_Hybrid);
-    noise->SetCellularReturnType(
-        FastNoiseLite::CellularReturnType::CellularReturnType_CellValue);
-    noise->SetCellularJitter(1.f);
-    noise->SetDomainWarpType(
-        FastNoiseLite::DomainWarpType::DomainWarpType_OpenSimplex2Reduced);
-    noise->SetDomainWarpAmp(30.f);
-    biomNoise = new FastNoiseWrapper(noise, seed);
-    return biomNoise;
+    auto validator = Framework::JSON::Validator::JSONValidator::buildForObject()
+                         ->withRequiredString("dimension")
+                         ->withExactMatch("Overworld")
+                         ->finishString();
+    return BiomedCavedDimensionGenerator::addConfigAttributes(validator)
+        ->finishObject();
 }
 
-Noise* OverworldDimension::zStructureNoise()
+Framework::JSON::JSONValue* OverworldDimensionFactory::getDefaultConfig()
 {
-    if (structureNoise) return structureNoise;
-    structureNoise = new RandNoise(seed);
-    return structureNoise;
+    return Framework::JSON::Parser::getValue(
+        "{"
+        "    \"bioms\": ["
+        "        {"
+        "            \"blocks\": ["
+        "                {"
+        "                    \"blockType\": \"Grass\","
+        "                    \"condition\": {"
+        "                        \"operator\": \"&&\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"operator\": \"==\","
+        "                                \"type\": \"operator\","
+        "                                \"values\": ["
+        "                                    {"
+        "                                        \"name\": \"z\","
+        "                                        \"type\": \"variable\""
+        "                                    },"
+        "                                    {"
+        "                                        \"name\": \"surfaceHeight\","
+        "                                        \"type\": \"variable\""
+        "                                    }"
+        "                                ]"
+        "                            },"
+        "                            {"
+        "                                \"blockType\": \"Dirt\","
+        "                                \"type\": \"blockType\","
+        "                                \"x\": {"
+        "                                    \"name\": \"x\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                \"y\": {"
+        "                                    \"name\": \"y\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                \"z\": {"
+        "                                    \"operator\": \"-\","
+        "                                    \"type\": \"operator\","
+        "                                    \"values\": ["
+        "                                        {"
+        "                                            \"name\": \"z\","
+        "                                            \"type\": \"variable\""
+        "                                        },"
+        "                                        {"
+        "                                            \"type\": \"constant\","
+        "                                            \"value\": 1"
+        "                                        }"
+        "                                    ]"
+        "                                }"
+        "                            }"
+        "                        ]"
+        "                    },"
+        "                    \"noise\": {"
+        "                        \"seed\": {"
+        "                            \"operator\": \"+\","
+        "                            \"type\": \"operator\","
+        "                            \"values\": ["
+        "                                {"
+        "                                    \"name\": \"dimensionSeed\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                {"
+        "                                    \"type\": \"constant\","
+        "                                    \"value\": 3"
+        "                                }"
+        "                            ]"
+        "                        },"
+        "                        \"type\": \"random\""
+        "                    },"
+        "                    \"threshold\": 0.25,"
+        "                    \"type\": \"blockType\""
+        "                },"
+        "                {"
+        "                    \"blockType\": \"Gravel\","
+        "                    \"condition\": {"
+        "                        \"operator\": \"<\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"name\": \"z\","
+        "                                \"type\": \"variable\""
+        "                            },"
+        "                            {"
+        "                                \"name\": \"surfaceHeight\","
+        "                                \"type\": \"variable\""
+        "                            }"
+        "                        ]"
+        "                    },"
+        "                    \"noise\": {"
+        "                        \"frequency\": 0.1,"
+        "                        \"seed\": {"
+        "                            \"operator\": \"+\","
+        "                            \"type\": \"operator\","
+        "                            \"values\": ["
+        "                                {"
+        "                                    \"name\": \"dimensionSeed\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                {"
+        "                                    \"type\": \"constant\","
+        "                                    \"value\": 2"
+        "                                }"
+        "                            ]"
+        "                        },"
+        "                        \"type\": \"ValueCubic\""
+        "                    },"
+        "                    \"threshold\": 0.35,"
+        "                    \"type\": \"blockType\""
+        "                },"
+        "                {"
+        "                    \"blockType\": \"Dirt\","
+        "                    \"condition\": {"
+        "                        \"operator\": \"<\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"name\": \"z\","
+        "                                \"type\": \"variable\""
+        "                            },"
+        "                            {"
+        "                                \"name\": \"surfaceHeight\","
+        "                                \"type\": \"variable\""
+        "                            }"
+        "                        ]"
+        "                    },"
+        "                    \"noise\": {"
+        "                        \"frequency\": 0.125,"
+        "                        \"seed\": {"
+        "                            \"operator\": \"+\","
+        "                            \"type\": \"operator\","
+        "                            \"values\": ["
+        "                                {"
+        "                                    \"name\": \"dimensionSeed\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                {"
+        "                                    \"type\": \"constant\","
+        "                                    \"value\": 1"
+        "                                }"
+        "                            ]"
+        "                        },"
+        "                        \"type\": \"ValueCubic\""
+        "                    },"
+        "                    \"threshold\": 0.35,"
+        "                    \"type\": \"blockType\""
+        "                },"
+        "                {"
+        "                    \"blockType\": \"Sand\","
+        "                    \"condition\": {"
+        "                        \"operator\": \"&&\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"operator\": \"<\","
+        "                                \"type\": \"operator\","
+        "                                \"values\": ["
+        "                                    {"
+        "                                        \"name\": \"z\","
+        "                                        \"type\": \"variable\""
+        "                                    },"
+        "                                    {"
+        "                                        \"name\": \"surfaceHeight\","
+        "                                        \"type\": \"variable\""
+        "                                    }"
+        "                                ]"
+        "                            },"
+        "                            {"
+        "                                \"operator\": \">\","
+        "                                \"type\": \"operator\","
+        "                                \"values\": ["
+        "                                    {"
+        "                                        \"name\": \"z\","
+        "                                        \"type\": \"variable\""
+        "                                    },"
+        "                                    {"
+        "                                        \"name\": \"underground1\","
+        "                                        \"type\": \"variable\""
+        "                                    }"
+        "                                ]"
+        "                            }"
+        "                        ]"
+        "                    },"
+        "                    \"noise\": {"
+        "                        \"frequency\": 0.125,"
+        "                        \"seed\": {"
+        "                            \"operator\": \"+\","
+        "                            \"type\": \"operator\","
+        "                            \"values\": ["
+        "                                {"
+        "                                    \"name\": \"dimensionSeed\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                {"
+        "                                    \"type\": \"constant\","
+        "                                    \"value\": 2"
+        "                                }"
+        "                            ]"
+        "                        },"
+        "                        \"type\": \"ValueCubic\""
+        "                    },"
+        "                    \"threshold\": 0.35,"
+        "                    \"type\": \"blockType\""
+        "                },"
+        "                {"
+        "                    \"blockType\": \"Dirt\","
+        "                    \"condition\": {"
+        "                        \"operator\": \"&&\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"operator\": \"<\","
+        "                                \"type\": \"operator\","
+        "                                \"values\": ["
+        "                                    {"
+        "                                        \"name\": \"z\","
+        "                                        \"type\": \"variable\""
+        "                                    },"
+        "                                    {"
+        "                                        \"name\": \"surfaceHeight\","
+        "                                        \"type\": \"variable\""
+        "                                    }"
+        "                                ]"
+        "                            },"
+        "                            {"
+        "                                \"operator\": \">\","
+        "                                \"type\": \"operator\","
+        "                                \"values\": ["
+        "                                    {"
+        "                                        \"name\": \"z\","
+        "                                        \"type\": \"variable\""
+        "                                    },"
+        "                                    {"
+        "                                        \"name\": \"underground1\","
+        "                                        \"type\": \"variable\""
+        "                                    }"
+        "                                ]"
+        "                            }"
+        "                        ]"
+        "                    },"
+        "                    \"type\": \"blockType\""
+        "                },"
+        "                {"
+        "                    \"blockType\": \"Stone\","
+        "                    \"condition\": {"
+        "                        \"operator\": \"<\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"name\": \"z\","
+        "                                \"type\": \"variable\""
+        "                            },"
+        "                            {"
+        "                                \"name\": \"underground1\","
+        "                                \"type\": \"variable\""
+        "                            }"
+        "                        ]"
+        "                    },"
+        "                    \"type\": \"blockType\""
+        "                }"
+        "            ],"
+        "            \"layerModifier\": ["
+        "                {"
+        "                    \"multiplier\": 0.2,"
+        "                    \"name\": \"surfaceHeight\""
+        "                }"
+        "            ],"
+        "            \"name\": \"Grassland\","
+        "            \"structurCollections\": ["
+        "                {"
+        "                    \"noise\": {"
+        "                        \"seed\": {"
+        "                            \"name\": \"dimensionSeed\","
+        "                            \"type\": \"variable\""
+        "                        },"
+        "                        \"type\": \"random\""
+        "                    },"
+        "                    \"structures\": ["
+        "                        {"
+        "                            \"leaves\": \"Birch Wood Leaves\","
+        "                            \"maxSize\": 15,"
+        "                            \"minSize\": 8,"
+        "                            \"propability\": 0.5,"
+        "                            \"type\": \"Tree\","
+        "                            \"wood\": \"Birch Wood\""
+        "                        },"
+        "                        {"
+        "                            \"leaves\": \"Beech Wood Leaves\","
+        "                            \"maxSize\": 13,"
+        "                            \"minSize\": 8,"
+        "                            \"propability\": 0.25,"
+        "                            \"type\": \"Tree\","
+        "                            \"wood\": \"Beech Wood\""
+        "                        },"
+        "                        {"
+        "                            \"leaves\": \"Oak Wood Leaves\","
+        "                            \"maxSize\": 15,"
+        "                            \"minSize\": 10,"
+        "                            \"propability\": 0.125,"
+        "                            \"type\": \"Tree\","
+        "                            \"wood\": \"Oak Wood\""
+        "                        },"
+        "                        {"
+        "                            \"leaves\": \"Pine Wood Leaves\","
+        "                            \"maxSize\": 24,"
+        "                            \"minSize\": 15,"
+        "                            \"propability\": 0.075,"
+        "                            \"type\": \"Tree\","
+        "                            \"wood\": \"Pine Wood\""
+        "                        }"
+        "                    ],"
+        "                    \"threshold\": 0.001"
+        "                }"
+        "            ]"
+        "        }"
+        "    ],"
+        "    \"dimension\": \"Overworld\","
+        "    \"dimensionSeed\": {"
+        "        \"operator\": \"+\","
+        "        \"type\": \"operator\","
+        "        \"values\": ["
+        "            {"
+        "                \"name\": \"worldSeed\","
+        "                \"type\": \"variable\""
+        "            },"
+        "            {"
+        "                \"name\": \"dimensionId\","
+        "                \"type\": \"variable\""
+        "            }"
+        "        ]"
+        "    },"
+        "    \"heightLayers\": ["
+        "        {"
+        "            \"name\": \"surfaceHeight\","
+        "            \"noise\": {"
+        "                \"seed\": {"
+        "                    \"name\": \"dimensionSeed\","
+        "                    \"type\": \"variable\""
+        "                },"
+        "                \"type\": \"ValueCubic\""
+        "            },"
+        "            \"value\": {"
+        "                \"operator\": \"+\","
+        "                \"type\": \"operator\","
+        "                \"values\": ["
+        "                    {"
+        "                        \"type\": \"constant\","
+        "                        \"value\": 50"
+        "                    },"
+        "                    {"
+        "                        \"operator\": \"*\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"type\": \"noise\","
+        "                                \"x\": {"
+        "                                    \"name\": \"x\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                \"y\": {"
+        "                                    \"name\": \"y\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                \"z\": {"
+        "                                    \"type\": \"constant\","
+        "                                    \"value\": 0"
+        "                                }"
+        "                            },"
+        "                            {"
+        "                                \"type\": \"constant\","
+        "                                \"value\": 400"
+        "                            }"
+        "                        ]"
+        "                    }"
+        "                ]"
+        "            }"
+        "        },"
+        "        {"
+        "            \"name\": \"underground1\","
+        "            \"noise\": {"
+        "                \"seed\": {"
+        "                    \"name\": \"dimensionSeed\","
+        "                    \"type\": \"variable\""
+        "                },"
+        "                \"type\": \"ValueCubic\""
+        "            },"
+        "            \"value\": {"
+        "                \"operator\": \"-\","
+        "                \"type\": \"operator\","
+        "                \"values\": ["
+        "                    {"
+        "                        \"name\": \"surfaceHeight\","
+        "                        \"type\": \"variable\""
+        "                    },"
+        "                    {"
+        "                        \"type\": \"constant\","
+        "                        \"value\": 5"
+        "                    },"
+        "                    {"
+        "                        \"operator\": \"*\","
+        "                        \"type\": \"operator\","
+        "                        \"values\": ["
+        "                            {"
+        "                                \"type\": \"noise\","
+        "                                \"x\": {"
+        "                                    \"name\": \"x\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                \"y\": {"
+        "                                    \"name\": \"y\","
+        "                                    \"type\": \"variable\""
+        "                                },"
+        "                                \"z\": {"
+        "                                    \"type\": \"constant\","
+        "                                    \"value\": 0"
+        "                                }"
+        "                            },"
+        "                            {"
+        "                                \"type\": \"constant\","
+        "                                \"value\": 45"
+        "                            }"
+        "                        ]"
+        "                    }"
+        "                ]"
+        "            }"
+        "        }"
+        "    ],"
+        "    \"noiseMaps\": ["
+        "        {"
+        "            \"name\": \"biomNoise\","
+        "            \"noise\": {"
+        "                \"cellularDistanceFunction\": \"Hybrid\","
+        "                \"cellularJitter\": 1,"
+        "                \"cellularReturnType\": \"CellValue\","
+        "                \"domainWarpAmp\": 30,"
+        "                \"domainWarpType\": \"OpenSimplex2Reduced\","
+        "                \"fractalType\": \"None\","
+        "                \"frequency\": 0.015,"
+        "                \"rotationType3D\": \"None\","
+        "                \"seed\": {"
+        "                    \"name\": \"dimensionSeed\","
+        "                    \"type\": \"variable\""
+        "                },"
+        "                \"type\": \"Cellular\""
+        "            }"
+        "        }"
+        "    ]"
+        "}");
 }

+ 6 - 9
FactoryCraft/OverworldDimension.h

@@ -4,15 +4,12 @@
 #include "Noise.h"
 #include "StaticRegistry.h"
 
-class OverworldDimension : public DimensionGenerator
+class OverworldDimensionFactory : public DimensionGeneratorFactory
 {
-private:
-    Noise* biomNoise;
-    Noise* structureNoise;
-
 public:
-    OverworldDimension();
-    ~OverworldDimension();
-    Noise* zBiomNoise() override;
-    Noise* zStructureNoise() override;
+    OverworldDimensionFactory();
+    DimensionGenerator* createDimensionGenerator(
+        int worldSeed, Framework::JSON::JSONValue* config) override;
+    Framework::JSON::Validator::JSONValidator* getConfigValidator() override;
+    Framework::JSON::JSONValue* getDefaultConfig() override;
 };

+ 11 - 14
FactoryCraft/RecipieLoader.cpp

@@ -35,9 +35,14 @@ void RecipieLoader::loadRecipies(const char* path)
     {
         JSONValue* json = loadJSONFromFile(path);
         JSONValidator* validator = zRecipieValidator();
-        JSONValue* valid = validator->getValidParts(json);
+        Framework::RCArray<JSONValidationResult> invalidParts;
+        JSONValue* valid = validator->getValidParts(json, &invalidParts);
+        for (JSONValidationResult* invalidPart : invalidParts)
+        {
+            invalidPart->printInvalidInfo();
+        }
         json->release();
-        int count = 0; 
+        int count = 0;
         if (valid)
         {
             for (JSONValue* recipie : *valid->asArray())
@@ -159,21 +164,13 @@ ItemFilter* RecipieLoader::loadFilter(JSONObject* zFilter)
     {
         Framework::Text type
             = zFilter->zValue("itemType")->asString()->getString();
-        for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
-        {
-            if (StaticRegistry<ItemType>::INSTANCE.zElement(i)
-                && StaticRegistry<ItemType>::INSTANCE.zElement(i)
-                       ->getName()
-                       .istGleich(type))
-                return new TypeItemFilter(
-                    StaticRegistry<ItemType>::INSTANCE.zElement(i));
-        }
+        return new TypeItemFilter(StaticRegistry<ItemType>::INSTANCE.zElement(
+            ItemType::getTypeId(type)));
     }
     else if (zFilter->hasValue("operator"))
     {
-        Framework::Text op = zFilter->zValue("operator")
-            ->asString()
-            ->getString();
+        Framework::Text op
+            = zFilter->zValue("operator")->asString()->getString();
         ItemFilter* left = loadFilter(zFilter->zValue("left")->asObject());
         ItemFilter* right = loadFilter(zFilter->zValue("right")->asObject());
         if (op.istGleich("&&"))

+ 7 - 7
FactoryCraft/Start.cpp

@@ -159,16 +159,16 @@ int main()
     DateiPfadErstellen(pfad->getText());
     std::ofstream file;
     std::streambuf* sbuf = std::cout.rdbuf();
-#ifndef _DEBUG
+// #ifndef _DEBUG
     file.open(pfad->getText());
     std::ostream newCout(sbuf);
     DuplicatingStreamBuf duplicator(newCout, file);
     std::cout.rdbuf(&duplicator);
-#else
+/* #else
     std::ostream newCout(sbuf);
     DuplicatingStreamBuf duplicator(newCout);
     std::cout.rdbuf(&duplicator);
-#endif
+#endif */
     pfad->release();
 
     std::cout << "Starting...\n";
@@ -180,9 +180,9 @@ int main()
         std::cout << "error: Datei konnte nicht gelesen werden. Das Programm "
                      "wird geschlossen.\n";
         dat->release();
-#ifndef _DEBUG
+//#ifndef _DEBUG
         file.close();
-#endif
+//#endif
         std::cout.rdbuf(sbuf);
         exit(1);
     }
@@ -249,9 +249,9 @@ int main()
     }
     dat->release();
     std::cout << "The server was shut down successfully.\n" << std::flush;
-#ifndef _DEBUG
+//#ifndef _DEBUG
     file.close();
-#endif
+//#endif
     std::cout.rdbuf(sbuf);
     Framework::releaseFramework();
     return 0;

+ 1 - 1
FactoryCraft/StaticInitializerOrder.cpp

@@ -657,7 +657,7 @@ void initializeEntityTypes()
 
 void initializeDimensions()
 {
-    new OverworldDimension();
+    //new OverworldDimension();
 }
 
 void initializeMultiblockTypes()

+ 127 - 0
FactoryCraft/StructureCollection.cpp

@@ -0,0 +1,127 @@
+#include "StructureCollection.h"
+
+#include "Game.h"
+#include "JNoise.h"
+
+StructureTemplateCollection::StructureTemplateCollection(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+    : ReferenceCounter()
+{
+    activeNoise = JNoise::parseNoisse(
+        zConfig->asObject()->zValue("activeNoise"), zMemory);
+    structureNoise = JNoise::parseNoisse(
+        zConfig->asObject()->zValue("structureNoise"), zMemory);
+    threshold
+        = zConfig->asObject()->zValue("threshold")->asNumber()->getNumber();
+    condition = JExpressionParser::parseBoolExpression(
+        zConfig->asObject()->zValue("condition"));
+    bool first = 1;
+    for (Framework::JSON::JSONValue* value :
+        *zConfig->asObject()->zValue("structures")->asArray())
+    {
+        GeneratorTemplate* templ
+            = Game::INSTANCE->zTypeRegistry()->createGeneratorTemplate(value);
+        if (first)
+        {
+            minAffected = templ->getMinAffectedOffset();
+            maxAffected = templ->getMaxAffectedOffset();
+            first = 0;
+        }
+        else
+        {
+            Framework::Vec3<int> min = templ->getMinAffectedOffset();
+            Framework::Vec3<int> max = templ->getMaxAffectedOffset();
+            if (minAffected.x > min.x) minAffected.x = min.x;
+            if (minAffected.y > min.y) minAffected.y = min.y;
+            if (minAffected.z > min.z) minAffected.z = min.z;
+            if (maxAffected.x < max.x) maxAffected.x = max.x;
+            if (maxAffected.y < max.y) maxAffected.y = max.y;
+            if (maxAffected.z < max.z) maxAffected.z = max.z;
+        }
+        structures.add(templ);
+    }
+}
+
+StructureTemplateCollection::~StructureTemplateCollection()
+{
+    activeNoise->release();
+    structureNoise->release();
+    condition->release();
+}
+
+void StructureTemplateCollection::generateStructures(int x,
+    int y,
+    int z,
+    int dimensionId,
+    JExpressionMemory* zMemory,
+    Framework::Vec3<int> minPos,
+    Framework::Vec3<int> maxPos,
+    Framework::RCArray<GeneratedStructure>* zResult)
+{
+    int minSearchX = minPos.x - maxAffected.x;
+    int minSearchY = minPos.y - maxAffected.y;
+    int minSearchZ = MAX(minPos.z - maxAffected.z, 0);
+    int maxSearchX = maxPos.x - minAffected.x;
+    int maxSearchY = maxPos.y - minAffected.y;
+    int maxSearchZ = MIN(maxPos.z - minAffected.z, WORLD_HEIGHT - 1);
+    if (x >= minSearchX && x <= maxSearchX && y >= minSearchY && y <= maxSearchY
+        && z >= minSearchZ && z <= maxSearchZ)
+    {
+        if (condition->getValue(zMemory))
+        {
+            if (activeNoise->getNoise((double)x, (double)y, (double)z)
+                < threshold)
+            {
+                double rValue
+                    = structureNoise->getNoise((double)x, (double)y, (double)z);
+                double probSum = 0;
+                for (auto t : structures)
+                {
+                    if (rValue - probSum <= t->getPropability())
+                    {
+                        zResult->add(
+                            t->generateAt(Framework::Vec3<int>(x, y, z),
+                                structureNoise,
+                                dimensionId));
+                        break;
+                    }
+                    probSum += t->getPropability();
+                }
+            }
+        }
+    }
+}
+
+const Framework::RCArray<GeneratorTemplate>&
+StructureTemplateCollection::getStructures() const
+{
+    return structures;
+}
+
+Framework::Vec3<int> StructureTemplateCollection::getMinAffected() const
+{
+    return minAffected;
+}
+
+Framework::Vec3<int> StructureTemplateCollection::getMaxAffected() const
+{
+    return maxAffected;
+}
+
+Framework::JSON::Validator::JSONValidator*
+StructureTemplateCollection::getConfigValidator()
+{
+    return Framework::JSON::Validator::JSONValidator::buildForObject()
+        ->withRequiredAttribute("activeNoise", JNoise::getValidator(false))
+        ->withRequiredAttribute("structureNoise", JNoise::getValidator(false))
+        ->withRequiredNumber("threshold")
+        ->whichIsGreaterThen(0)
+        ->finishNumber()
+        ->withRequiredAttribute(
+            "condition", JExpressionParser::getBoolValidator())
+        ->withRequiredArray("structures")
+        ->addAcceptedTypeInArray(
+            Game::INSTANCE->zTypeRegistry()->getGeneratorTemplateValidator())
+        ->finishArray()
+        ->finishObject();
+}

+ 38 - 0
FactoryCraft/StructureCollection.h

@@ -0,0 +1,38 @@
+#pragma once
+
+#include <functional>
+
+#include "GeneratorTemplate.h"
+#include "JsonExpression.h"
+#include "Noise.h"
+
+class StructureTemplateCollection : public virtual Framework::ReferenceCounter
+{
+private:
+    Noise* activeNoise;
+    Noise* structureNoise;
+    double threshold;
+    Framework::RCArray<GeneratorTemplate> structures;
+    Framework::Vec3<int> minAffected;
+    Framework::Vec3<int> maxAffected;
+    JBoolExpression* condition;
+
+public:
+    StructureTemplateCollection(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    ~StructureTemplateCollection();
+    void generateStructures(int x,
+        int y,
+        int z,
+        int dimensionId,
+        JExpressionMemory* zMemory,
+        Framework::Vec3<int> minPos,
+        Framework::Vec3<int> maxPos,
+        Framework::RCArray<GeneratedStructure>* zResult);
+
+    const Framework::RCArray<GeneratorTemplate>& getStructures() const;
+    Framework::Vec3<int> getMinAffected() const;
+    Framework::Vec3<int> getMaxAffected() const;
+
+    static Framework::JSON::Validator::JSONValidator* getConfigValidator();
+};

+ 1 - 1
FactoryCraft/TreeSeblingBlock.cpp

@@ -44,7 +44,7 @@ void TreeSeblingBlock::onPostTick()
             RandNoise noise((int)time(0));
             if (!Game::INSTANCE->zGenerator()->spawnStructure(pos,
                     dim,
-                    [wood = wood, leaves = leaves](GenerationTemplate* tmpl) {
+                    [wood = wood, leaves = leaves](GeneratorTemplate* tmpl) {
                         TreeTemplate* tree = dynamic_cast<TreeTemplate*>(tmpl);
                         return tree && tree->getWoodType() == wood
                             && tree->getLeavesType() == leaves;

+ 56 - 4
FactoryCraft/TreeTemplate.cpp

@@ -8,9 +8,7 @@ TreeTemplate::TreeTemplate(float propability,
     int leaveBlockType,
     int minHeight,
     int maxHeight)
-    : GenerationTemplate(propability,
-        0,
-        1,
+    : GeneratorTemplate(propability,
         Framework::Vec3<int>(-2, -2, 0),
         Framework::Vec3<int>(5, 5, maxHeight)),
       woodBlockTypeId(woodBlockTypeId),
@@ -37,7 +35,7 @@ GeneratedStructure* TreeTemplate::generateAt(
     Framework::Vec3<int> minAffected
         = Framework::Vec3<int>(-2, -2, 0) + location;
     GeneratedStructure* generated
-        = new GeneratedStructure(dynamic_cast<GenerationTemplate*>(getThis()),
+        = new GeneratedStructure(dynamic_cast<GeneratorTemplate*>(getThis()),
             location,
             Framework::Vec3<int>(5, 5, height),
             minAffected);
@@ -83,4 +81,58 @@ const BlockType* TreeTemplate::getWoodType() const
 const BlockType* TreeTemplate::getLeavesType() const
 {
     return StaticRegistry<BlockType>::INSTANCE.zElement(leaveBlockType);
+}
+
+TreeTemplateFactory::TreeTemplateFactory()
+    : GeneratorTemplateFactory()
+{}
+
+GeneratorTemplate* TreeTemplateFactory::createTemplate(
+    Framework::JSON::JSONValue* zConfig)
+{
+    return new TreeTemplate((float)zConfig->asObject()
+                                ->zValue("propability")
+                                ->asNumber()
+                                ->getNumber(),
+        BlockType::getTypeId(
+            zConfig->asObject()->zValue("wood")->asString()->getString()),
+        BlockType::getTypeId(
+            zConfig->asObject()->zValue("leaves")->asString()->getString()),
+        (int)(zConfig->asObject()->zValue("minSize")->asNumber()->getNumber()
+              + 0.5),
+        (int)(zConfig->asObject()->zValue("maxSize")->asNumber()->getNumber()
+              + 0.5));
+}
+
+Framework::JSON::Validator::JSONValidator* TreeTemplateFactory::getValidator()
+{
+    Framework::RCArray<Framework::Text> blockTypeNames;
+    for (int i = 0; i < StaticRegistry<BlockType>::INSTANCE.getCount(); i++)
+    {
+        if (StaticRegistry<BlockType>::INSTANCE.zElement(i))
+        {
+            blockTypeNames.add(new Framework::Text(
+                StaticRegistry<BlockType>::INSTANCE.zElement(i)->getName()));
+        }
+    }
+    return Framework::JSON::Validator::JSONValidator::buildForObject()
+        ->withRequiredString("type")
+        ->withExactMatch("Tree")
+        ->finishString()
+        ->withRequiredString("wood")
+        ->whichIsOneOf(blockTypeNames)
+        ->finishString()
+        ->withRequiredString("leaves")
+        ->whichIsOneOf(blockTypeNames)
+        ->finishString()
+        ->withRequiredNumber("minSize")
+        ->whichIsGreaterThen(0)
+        ->finishNumber()
+        ->withRequiredNumber("maxSize")
+        ->whichIsGreaterThen(0)
+        ->finishNumber()
+        ->withRequiredNumber("propability")
+        ->whichIsGreaterThen(0)
+        ->finishNumber()
+        ->finishObject();
 }

+ 11 - 2
FactoryCraft/TreeTemplate.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include "GenerationTemplate.h"
+#include "GeneratorTemplate.h"
 
-class TreeTemplate : public GenerationTemplate
+class TreeTemplate : public GeneratorTemplate
 {
 private:
     int woodBlockTypeId;
@@ -20,4 +20,13 @@ public:
         Framework::Vec3<int> location, Noise* zNoise, int dimensionId) override;
     const BlockType* getWoodType() const;
     const BlockType* getLeavesType() const;
+};
+
+class TreeTemplateFactory : public GeneratorTemplateFactory
+{
+public:
+	TreeTemplateFactory();
+    GeneratorTemplate* createTemplate(
+		Framework::JSON::JSONValue* zConfig) override;
+    Framework::JSON::Validator::JSONValidator* getValidator() override;
 };

+ 127 - 0
FactoryCraft/TypeRegistry.cpp

@@ -0,0 +1,127 @@
+#include "TypeRegistry.h"
+
+#include "BlockTypeGeneratorRule.h"
+#include "OverworldDimension.h"
+#include "TreeTemplate.h"
+
+TypeRegistry::TypeRegistry()
+    : ReferenceCounter()
+{
+    // register dimensions
+    registerDimensionGeneratorFactory(new OverworldDimensionFactory());
+    // register rules
+    registerGeneratorRuleFactory(new BlockTypeGeneratorRuleFactory());
+    // register templates
+    registerGeneratorTemplate(new TreeTemplateFactory());
+}
+
+void TypeRegistry::registerGeneratorRuleFactory(GeneratorRuleFactory* factory)
+{
+    generatorRules.add(factory);
+}
+
+GeneratorRule* TypeRegistry::createGeneratorRule(
+    Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
+{
+    for (GeneratorRuleFactory* f : generatorRules)
+    {
+        Framework::JSON::Validator::JSONValidator* validator
+            = f->getValidator();
+        if (validator->isValid(zConfig))
+        {
+            validator->release();
+            return f->createRule(zConfig, zMemory);
+        }
+        validator->release();
+    }
+    return 0;
+}
+
+Framework::JSON::Validator::JSONValidator*
+TypeRegistry::getGeneratorRuleValidator()
+{
+    auto validator = Framework::JSON::Validator::JSONValidator::buildForOneOf()
+                         ->typeSpecifiedByAttribute("type");
+    for (GeneratorRuleFactory* f : generatorRules)
+    {
+        validator->addAcceptedType(f->getValidator());
+    }
+    return validator->finishOneOf();
+}
+
+void TypeRegistry::registerDimensionGeneratorFactory(
+    DimensionGeneratorFactory* factory)
+{
+    dimensionGenerators.add(factory);
+}
+
+DimensionGenerator* TypeRegistry::createDimensionGenerator(
+    Framework::JSON::JSONValue* zConfig, int worldSeed)
+{
+    for (DimensionGeneratorFactory* f : dimensionGenerators)
+    {
+        Framework::JSON::Validator::JSONValidator* validator
+            = f->getConfigValidator();
+        if (validator->isValid(zConfig))
+        {
+            validator->release();
+            std::cout << "Loaded Config for dimension '" << f->getName()
+                      << "' with id " << f->getDimensionId() << "\n";
+            return f->createDimensionGenerator(worldSeed, zConfig);
+        }
+        validator->release();
+    }
+    return 0;
+}
+
+Framework::JSON::Validator::JSONValidator*
+TypeRegistry::getDimensionGeneratorValidator()
+{
+    auto validator = Framework::JSON::Validator::JSONValidator::buildForOneOf()
+                         ->typeSpecifiedByAttribute("dimension");
+    for (DimensionGeneratorFactory* f : dimensionGenerators)
+    {
+        validator->addAcceptedType(f->getConfigValidator());
+    }
+    return validator->finishOneOf();
+}
+
+const Framework::RCArray<DimensionGeneratorFactory>&
+TypeRegistry::getDimensionGeneratorFactories() const
+{
+    return dimensionGenerators;
+}
+
+void TypeRegistry::registerGeneratorTemplate(GeneratorTemplateFactory* factory)
+{
+    generatorTemplates.add(factory);
+}
+
+GeneratorTemplate* TypeRegistry::createGeneratorTemplate(
+    Framework::JSON::JSONValue* zConfig)
+{
+    for (GeneratorTemplateFactory* f : generatorTemplates)
+    {
+        Framework::JSON::Validator::JSONValidator* validator
+            = f->getValidator();
+        if (validator->isValid(zConfig))
+        {
+            validator->release();
+            return f->createTemplate(zConfig);
+        }
+        validator->release();
+    }
+    return 0;
+}
+
+Framework::JSON::Validator::JSONValidator*
+TypeRegistry::getGeneratorTemplateValidator()
+{
+    auto validator = Framework::JSON::Validator::JSONValidator::buildForOneOf()
+                         ->typeSpecifiedByAttribute("type");
+    for (GeneratorTemplateFactory* f : generatorTemplates)
+    {
+        validator->addAcceptedType(f->getValidator());
+    }
+    return validator->finishOneOf();
+}

+ 33 - 0
FactoryCraft/TypeRegistry.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include "DimensionGenerator.h"
+#include "GeneratorRule.h"
+#include "GeneratorTemplate.h"
+
+class TypeRegistry : public Framework::ReferenceCounter
+{
+private:
+    Framework::RCArray<GeneratorRuleFactory> generatorRules;
+    Framework::RCArray<DimensionGeneratorFactory> dimensionGenerators;
+    Framework::RCArray<GeneratorTemplateFactory> generatorTemplates;
+
+public:
+    TypeRegistry();
+
+    void registerGeneratorRuleFactory(GeneratorRuleFactory* factory);
+    GeneratorRule* createGeneratorRule(
+        Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory);
+    Framework::JSON::Validator::JSONValidator* getGeneratorRuleValidator();
+
+    void registerDimensionGeneratorFactory(DimensionGeneratorFactory* factory);
+    DimensionGenerator* createDimensionGenerator(
+        Framework::JSON::JSONValue* zConfig, int worldSeed);
+    Framework::JSON::Validator::JSONValidator* getDimensionGeneratorValidator();
+    const Framework::RCArray<DimensionGeneratorFactory>&
+    getDimensionGeneratorFactories() const;
+
+    void registerGeneratorTemplate(GeneratorTemplateFactory* factory);
+    GeneratorTemplate* createGeneratorTemplate(
+        Framework::JSON::JSONValue* zConfig);
+    Framework::JSON::Validator::JSONValidator* getGeneratorTemplateValidator();
+};

+ 139 - 13
FactoryCraft/WorldGenerator.cpp

@@ -5,9 +5,11 @@
 
 #include "Game.h"
 #include "NoiseInterpolator.h"
-#include "StaticRegistry.h"
+#include "OverworldDimension.h"
 
 using namespace Framework;
+using namespace Framework::JSON;
+using namespace Framework::JSON::Validator;
 
 WorldGenerator::WorldGenerator(int seed)
     : Thread(),
@@ -15,15 +17,143 @@ WorldGenerator::WorldGenerator(int seed)
       seed(seed)
 {
     setName("World Generator");
-    for (int i = 0; i < StaticRegistry<DimensionGenerator>::INSTANCE.getCount();
-         i++)
-        StaticRegistry<DimensionGenerator>::INSTANCE.zElement(i)->initialize(
-            seed);
+    std::cout << "loading world generator configs. Changes at the config giles "
+                 "may lead to a sudden change in landscape.\n";
+    JSONValidator* validator = buildConfigValidator();
+    loadConfig("data/generator", validator);
+    validator->release();
+    addMissingDimensions();
+
     start();
 }
 
 WorldGenerator::~WorldGenerator() {}
 
+Framework::JSON::Validator::JSONValidator*
+WorldGenerator::buildConfigValidator()
+{
+    JSONValidator* configValidator
+        = JSONValidator::buildForArray()
+              ->removeInvalidEntries()
+              ->addAcceptedTypeInArray(Game::INSTANCE->zTypeRegistry()
+                                           ->getDimensionGeneratorValidator())
+              ->finishArray();
+    Datei syntaxFile(new Text("data/syntax/generatorValidation.xml"));
+    syntaxFile.erstellen();
+    Text syntaxContent = configValidator->zConstraints()->toString();
+    syntaxFile.open(Datei::Style::schreiben);
+    syntaxFile.schreibe(syntaxContent, syntaxContent.getLength());
+    syntaxFile.close();
+    return configValidator;
+}
+
+void WorldGenerator::loadConfig(
+    const char* path, Framework::JSON::Validator::JSONValidator* zValidator)
+{
+    std::cout << "loading dimension configs from '" << path << "'" << std::endl;
+    Datei file(new Text(path));
+    if (file.istOrdner())
+    {
+        RCArray<Text>* fileNames = file.getDateiListe();
+        if (fileNames)
+        {
+            for (Text* name : *fileNames)
+            {
+                loadConfig(Text(path) + "/" + *name, zValidator);
+            }
+            fileNames->release();
+        }
+    }
+    else
+    {
+        JSONValue* json = loadJSONFromFile(path);
+        if (!json)
+        {
+            std::cout << "ERROR: the file does not contain valid json\n";
+        }
+        else
+        {
+            Framework::RCArray<JSONValidationResult> invalidParts;
+            JSONValue* valid = zValidator->getValidParts(json, &invalidParts);
+            for (JSONValidationResult* invalidPart : invalidParts)
+            {
+                invalidPart->printInvalidInfo();
+            }
+            json->release();
+            if (valid)
+            {
+                for (JSONValue* config : *valid->asArray())
+                    loadDimensionConfig(config);
+                valid->release();
+            }
+        }
+    }
+}
+
+void WorldGenerator::loadDimensionConfig(Framework::JSON::JSONValue* zConfig)
+{
+    DimensionGenerator* generator
+        = Game::INSTANCE->zTypeRegistry()->createDimensionGenerator(
+            zConfig, seed);
+    if (generator)
+    {
+        dimensionGenerators.add(generator);
+    }
+    else
+    {
+        std::cout << "ERROR: could not find dimension factory for config \n"
+                  << zConfig->toString() << "\n";
+    }
+}
+
+void WorldGenerator::addMissingDimensions()
+{
+    for (DimensionGeneratorFactory* factory : Game::INSTANCE->zTypeRegistry()->getDimensionGeneratorFactories())
+    {
+        bool found = 0;
+        for (DimensionGenerator* generator : dimensionGenerators)
+        {
+            if (generator->getDimensionId() == factory->getDimensionId())
+            {
+                found = 1;
+                break;
+            }
+        }
+        if (!found)
+        {
+            std::cout << "WARNING: missing config for dimension '"
+                      << factory->getName() << "' with id "
+                      << factory->getDimensionId()
+                      << ". Default config will be used.";
+            JSONValue* defaultConfig = factory->getDefaultConfig();
+            Datei file(new Text(
+                Text("data/generator/") + factory->getName() + ".json"));
+            if (!file.existiert())
+            {
+                file.erstellen();
+                file.open(Datei::Style::schreiben);
+                Text conficContent
+                    = Text("[") + defaultConfig->toString() + "]";
+                file.schreibe(conficContent, conficContent.getLength());
+                file.close();
+                std::cout << "Default config was written to '" << *file.zPfad()
+                          << "'\n";
+            }
+            loadDimensionConfig(defaultConfig);
+            defaultConfig->release();
+        }
+    }
+}
+
+DimensionGenerator* WorldGenerator::zGenerator(int dimensionId)
+{
+    for (DimensionGenerator* generator : dimensionGenerators)
+    {
+        if (generator->getDimensionId() == dimensionId) return generator;
+    }
+    return 0;
+}
+
 void WorldGenerator::thread()
 {
     while (!exit)
@@ -56,9 +186,7 @@ void WorldGenerator::thread()
                 if (!Game::INSTANCE->doesChunkExist(x, y, next.dimensionId))
                 {
                     Chunk* generatedChunk
-                        = StaticRegistry<DimensionGenerator>::INSTANCE
-                              .zElement(next.dimensionId)
-                              ->generateChunk(x, y);
+                        = zGenerator(next.dimensionId)->generateChunk(x, y);
                     ZeitMesser zm;
                     zm.messungStart();
                     generatedChunk->initializeLightning();
@@ -106,14 +234,12 @@ void WorldGenerator::exitAndWait()
 Framework::Either<Block*, int> WorldGenerator::generateSingleBlock(
     Framework::Vec3<int> location, int dimensionId)
 {
-    return StaticRegistry<DimensionGenerator>::INSTANCE.zElement(dimensionId)
-        ->generateBlock(location);
+    return zGenerator(dimensionId)->generateBlock(location);
 }
 
 bool WorldGenerator::spawnStructure(Framework::Vec3<int> location,
     int dimensionId,
-    std::function<bool(GenerationTemplate* tmpl)> filter)
+    std::function<bool(GeneratorTemplate* tmpl)> filter)
 {
-    return StaticRegistry<DimensionGenerator>::INSTANCE.zElement(dimensionId)
-        ->spawnStructure(location, filter);
+    return zGenerator(dimensionId)->spawnStructure(location, filter);
 }

+ 9 - 1
FactoryCraft/WorldGenerator.h

@@ -11,9 +11,17 @@ class WorldGenerator : public Framework::Thread
 private:
     Framework::Critical cs;
     Framework::Array<Area> requestQueue;
+    Framework::RCArray<DimensionGenerator> dimensionGenerators;
     bool exit;
     int seed;
 
+    Framework::JSON::Validator::JSONValidator *buildConfigValidator();
+    void loadConfig(
+        const char* path, Framework::JSON::Validator::JSONValidator *zValidator);
+    void loadDimensionConfig(Framework::JSON::JSONValue* zConfig);
+    void addMissingDimensions();
+    DimensionGenerator* zGenerator(int dimensionId);
+
 public:
     WorldGenerator(int seed);
     ~WorldGenerator();
@@ -24,5 +32,5 @@ public:
         Framework::Vec3<int> location, int dimensionId);
     bool spawnStructure(Framework::Vec3<int> location,
         int dimensionId,
-        std::function<bool(GenerationTemplate* tmpl)> filter);
+        std::function<bool(GeneratorTemplate* tmpl)> filter);
 };

+ 7 - 11
FactoryCraft/WormCaveGenerator.cpp

@@ -61,7 +61,7 @@ Framework::Punkt NoiseWorm3D::getStartChunkCenter()
     return startChunk;
 }
 
-NoiseWorm3D *NoiseWorm3D::getPartAffectedByChunk(int x, int y)
+NoiseWorm3D* NoiseWorm3D::getPartAffectedByChunk(int x, int y)
 {
     NoiseWorm3D* result = 0;
     if (x - CHUNK_SIZE / 2 <= maxAffected.x
@@ -74,7 +74,7 @@ NoiseWorm3D *NoiseWorm3D::getPartAffectedByChunk(int x, int y)
         while (pi && si)
         {
             if ((Vec2<float>((float)x, (float)y)
-                - Vec2<float>(pi.val().x, pi.val().y))
+                    - Vec2<float>(pi.val().x, pi.val().y))
                     .getLengthSq()
                 < (si.val() + CHUNK_SIZE / 2) * (si.val() + CHUNK_SIZE / 2))
             {
@@ -126,13 +126,15 @@ WormCaveGenerator::WormCaveGenerator(int minDistant,
     int maxDistant,
     int minRadius,
     int maxRadius,
-    float cavePosibillityPerChunk)
-    : CaveGenerator(),
+    float cavePosibillityPerChunk,
+    int seed)
+    : CaveGenerator(seed),
       maxDistant(maxDistant),
       minDistant(minDistant),
       maxRadius(maxRadius),
       minRadius(minRadius),
-      cavePosibillity(cavePosibillityPerChunk)
+      cavePosibillity(cavePosibillityPerChunk),
+      wormStartNoise(new RandNoise(seed))
 {}
 
 WormCaveGenerator::~WormCaveGenerator()
@@ -202,12 +204,6 @@ NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
     return 0;
 }
 
-void WormCaveGenerator::initialize(int seed)
-{
-    wormStartNoise = new RandNoise(seed);
-    CaveGenerator::initialize(seed);
-}
-
 CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
 {
     Framework::RCArray<NoiseWorm3D> affected;

+ 2 - 2
FactoryCraft/WormCaveGenerator.h

@@ -60,9 +60,9 @@ public:
         int maxDistant,
         int minRadius,
         int maxRadius,
-        float cavePosibillityPerChunk);
+        float cavePosibillityPerChunk,
+        int seed);
     ~WormCaveGenerator();
-    void initialize(int seed) override;
 
     CaveChunkGenerator* getGeneratorForChunk(int x, int y) override;
 };

+ 52 - 0
NoiseTest/NoiseCombiner.h

@@ -0,0 +1,52 @@
+#pragma once
+
+#include <Noise.h>
+
+class NoiseCombinerM : public Noise
+{
+private:
+    Noise* a;
+    Noise* b;
+
+public:
+    NoiseCombinerM(Noise* a, Noise* b)
+        : Noise(),
+          a(a),
+          b(b)
+    {}
+
+    virtual int getSeed() const
+    {
+        return 0;
+    }
+
+    virtual double getNoise(double x, double y, double z)
+    {
+        return a->getNoise(x, y, z) * b->getNoise(x, y, z)
+             + (1 - b->getNoise(x, y, z)) / 2;
+    }
+};
+
+class NoiseCombinerA : public Noise
+{
+private:
+    Noise* a;
+    Noise* b;
+
+public:
+    NoiseCombinerA(Noise* a, Noise* b)
+        : Noise(),
+          a(a),
+          b(b)
+    {}
+
+    virtual int getSeed() const
+    {
+        return 0;
+    }
+
+    virtual double getNoise(double x, double y, double z)
+    {
+        return a->getNoise(x, y, z)* 0.7 + b->getNoise(x, y, z) * 0.3;
+    }
+};

+ 245 - 0
NoiseTest/NoiseTest.cpp

@@ -0,0 +1,245 @@
+#include <AsynchronCall.h>
+#include <Bild.h>
+#include <Bildschirm.h>
+#include <Fenster.h>
+#include <Globals.h>
+#include <iostream>
+#include <RenderThread.h>
+#include <string.h>
+
+#include "FastNoiseLite.h"
+#include "FastNoiseWrapper.h"
+#include "RandNoise.h"
+#include "ShapedNoise.h"
+#include "NoiseCombiner.h"
+
+using namespace Framework;
+
+WFenster* window;
+Bild* img;
+Vec3<int> position(0, 0, 0);
+float zoom = 0.1;
+bool exitF = 0;
+Noise* wrapper;
+float border = 0.5;
+float border2 = -1;
+bool showValue = 1;
+
+void updateView()
+{
+    Vec3<int> minP
+        = position
+        - Vec3<float>(img->getBreite() / 2, img->getHeight() / 2, 0) / zoom;
+    Vec3<int> maxP
+        = position
+        + Vec3<float>(img->getBreite() / 2, img->getHeight() / 2, 0) / zoom;
+    int counter = 0;
+    double min = INFINITY;
+    double max = -INFINITY;
+    for (int i = 0; i < img->getBreite(); i++)
+    {
+        for (int j = 0; j < img->getHeight(); j++)
+        {
+            Vec3<float> pos(i, j, 0);
+            pos -= Vec3<int>(img->getBreite() / 2, img->getHeight() / 2, 0);
+            pos /= zoom;
+            pos += position;
+            double noise = wrapper->getNoise(pos.x, pos.y, pos.z);
+            if (noise > max)
+            {
+                max = noise;
+            }
+            if (noise < min)
+            {
+                min = noise;
+            }
+            if (showValue)
+            {
+                int value = (int)(noise * 255);
+                img->setPixelDP(
+                    i, j, 0xFF000000 | (value << 16) | (value << 8) | value);
+            }
+            else
+            {
+                if (noise < border && noise > border2)
+                {
+                    img->setPixelDP(i, j, 0xFFFFFFFF);
+                    counter++;
+                }
+                else
+                {
+                    img->setPixelDP(i, j, 0xFF000000);
+                }
+            }
+        }
+    }
+    float percentage
+        = ((float)counter / (img->getBreite() * img->getHeight())) * 100;
+    std::cout << "Showing " << minP.x << " " << minP.y << " to " << maxP.x
+              << " " << maxP.y << " at height " << position.z << " with border "
+              << border2 << " to " << border << " true for " << percentage
+              << "% of "
+              << (img->getBreite() / zoom) * (img->getHeight() / zoom)
+              << " blocks. Min: " << min << " Max: " << max << std::endl;
+}
+
+int main()
+{
+    Framework::initFramework();
+    FastNoiseLite* noise = new FastNoiseLite(1);
+    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
+    FastNoiseWrapper *wrapper1 = new FastNoiseWrapper(noise, 0);
+    //wrapper = wrapper2;
+    /* FastNoiseLite* noise = new FastNoiseLite(0);
+    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
+    noise->SetFrequency(3.f);
+    wrapper = new FastNoiseWrapper(noise, 0);*/
+     FastNoiseLite* n = new FastNoiseLite(2);
+    n->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular);
+    n->SetFrequency(0.005f);
+    n->SetRotationType3D(FastNoiseLite::RotationType3D::RotationType3D_None);
+    n->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::
+            CellularDistanceFunction_Hybrid);
+    n->SetCellularJitter(1.f);
+    n->SetCellularReturnType(
+        FastNoiseLite::CellularReturnType::CellularReturnType_Distance);
+    n->SetFractalType(
+        FastNoiseLite::FractalType::FractalType_DomainWarpIndependent);
+    n->SetDomainWarpType(
+        FastNoiseLite::DomainWarpType::DomainWarpType_OpenSimplex2);
+    n->SetDomainWarpAmp(100.f);
+    n->SetFractalOctaves(3.f);
+    n->SetFractalLacunarity(2.f);
+    n->SetFractalGain(0.5f);
+    FastNoiseWrapper* wrapper2 = new FastNoiseWrapper(n, 2);
+    wrapper2->setMultiplier(0.1f);
+    wrapper = new NoiseCombinerM(wrapper1, wrapper2);
+    n = new FastNoiseLite(3);
+    n->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular);
+    n->SetFrequency(0.005f);
+    n->SetRotationType3D(FastNoiseLite::RotationType3D::RotationType3D_None);
+    n->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::
+            CellularDistanceFunction_Hybrid);
+    n->SetCellularJitter(1.f);
+    n->SetCellularReturnType(
+        FastNoiseLite::CellularReturnType::CellularReturnType_Distance);
+    n->SetFractalType(
+        FastNoiseLite::FractalType::FractalType_DomainWarpIndependent);
+    n->SetDomainWarpType(
+        FastNoiseLite::DomainWarpType::DomainWarpType_OpenSimplex2);
+    n->SetDomainWarpAmp(100.f);
+    n->SetFractalOctaves(3.f);
+    n->SetFractalLacunarity(2.f);
+    n->SetFractalGain(0.5f);
+    wrapper2 = new FastNoiseWrapper(n, 0);
+    wrapper2->setMultiplier(0.4f);
+    wrapper = new NoiseCombinerM(wrapper, wrapper2);
+    noise = new FastNoiseLite(10);
+    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
+    wrapper2 = new FastNoiseWrapper(noise, 0);
+    wrapper2->setMultiplier(0.15f);
+    wrapper = new NoiseCombinerA(wrapper, wrapper2);
+    //wrapper = new ShapedNoise(wrapper);
+    //((ShapedNoise*)wrapper)->setNeighborOffset(4.f);
+    //wrapper = new RandNoise(34255);
+
+    img = new Bild();
+    img->neuBild(1600, 1600, 0xFF000000);
+
+    BildZ* view = new BildZ();
+    view->setBildZ(img);
+    view->setStyle(BildZ::Style::Sichtbar);
+    view->setSize(800, 800);
+
+    WNDCLASS wc = Framework::F_Normal(GetModuleHandle(NULL));
+    wc.lpszClassName = "Fenster";
+    window = new WFenster();
+    window->erstellen(WS_OVERLAPPEDWINDOW, wc);
+    window->setSize(800, 800);
+    window->setPosition(100, 100);
+    window->setAnzeigeModus(SW_SHOW);
+    window->setVSchließAktion([](void* p, void* o) {
+        StopNachrichtenSchleife(window->getFensterHandle());
+    });
+
+    Bildschirm* screen = new Bildschirm2D(window);
+    window->setBildschirm(dynamic_cast<Bildschirm*>(screen->getThis()));
+    screen->addMember(view);
+    screen->setTestRend(0);
+    screen->update();
+    screen->render();
+    RenderTh* rth = new RenderTh();
+    rth->setQuiet(1);
+    rth->setBildschirm(screen);
+    rth->beginn();
+
+    updateView();
+
+    new AsynchronCall([]() {
+        char line[256];
+        while (!exitF)
+        {
+            std::cin.getline(line, 256);
+            if (strcmp(line, "exit") == 0)
+            {
+                StopNachrichtenSchleife(window->getFensterHandle());
+                break;
+            }
+            Text txt(line);
+            if (txt.positionVon("show ") == 0)
+            {
+                Text* x = txt.getTeilText(5);
+                position.x = (int)*x;
+                Text* y = x->getTeilText(x->positionVon(" ") + 1);
+                position.y = (int)*y;
+                Text* z = y->getTeilText(y->positionVon(" ") + 1);
+                position.z = (int)*z;
+                updateView();
+                z->release();
+                y->release();
+                x->release();
+            }
+            if (txt.positionVon("border ") == 0)
+            {
+                Text* x = txt.getTeilText(7);
+                border = (float)*x;
+                updateView();
+                x->release();
+            }
+            if (txt.positionVon("border2 ") == 0)
+            {
+                Text* x = txt.getTeilText(7);
+                border2 = (float)*x;
+                updateView();
+                x->release();
+            }
+            if (txt.positionVon("zoom ") == 0)
+            {
+                Text* x = txt.getTeilText(5);
+                zoom = (int)*x;
+                updateView();
+                x->release();
+            }
+            if (txt.positionVon("show value") == 0)
+            {
+                showValue = 1;
+                updateView();
+            }
+            if (txt.positionVon("show border") == 0)
+            {
+                showValue = 0;
+                updateView();
+            }
+        }
+    });
+
+    StartNachrichtenSchleife();
+
+    exitF = 1;
+
+    rth->beenden();
+    window->setBildschirm(0);
+    rth->release();
+    Framework::releaseFramework();
+    return 0;
+}

+ 162 - 0
NoiseTest/NoiseTest.vcxproj

@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectGuid>{096a454c-3835-4a4e-89fe-34edccd80467}</ProjectGuid>
+    <RootNamespace>NoiseTest</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;..\FactoryCraft;..\..\..\..\..\Allgemein\Network\Network;..\..\..\..\..\Allgemein\Network;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\..\Allgemein\Framework\x64\debug;..\..\..\..\..\Allgemein\Network\x64\debug;$(LibraryPath)</LibraryPath>
+    <SourcePath>..\FactoryCraft;$(SourcePath)</SourcePath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <LanguageStandard>stdcpp17</LanguageStandard>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>Framework.lib;Network.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>copy ..\..\..\..\..\Allgemein\Network\x64\debug\Network.dll Network.dll
+copy ..\..\..\..\..\Allgemein\Framework\x64\debug\Framework.dll Framework.dll</Command>
+      <Outputs>kopieren ...;%(Outputs)</Outputs>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\FactoryCraft\FastNoiseWrapper.cpp" />
+    <ClCompile Include="..\FactoryCraft\Noise.cpp" />
+    <ClCompile Include="..\FactoryCraft\NoiseInterpolator.cpp" />
+    <ClCompile Include="..\FactoryCraft\RandNoise.cpp" />
+    <ClCompile Include="..\FactoryCraft\ShapedNoise.cpp" />
+    <ClCompile Include="NoiseTest.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\FactoryCraft\FastNoiseLite.h" />
+    <ClInclude Include="..\FactoryCraft\FastNoiseWrapper.h" />
+    <ClInclude Include="..\FactoryCraft\Noise.h" />
+    <ClInclude Include="..\FactoryCraft\NoiseInterpolator.h" />
+    <ClInclude Include="..\FactoryCraft\RandNoise.h" />
+    <ClInclude Include="..\FactoryCraft\ShapedNoise.h" />
+    <ClInclude Include="NoiseCombiner.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 60 - 0
NoiseTest/NoiseTest.vcxproj.filters

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Quelldateien">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Headerdateien">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Ressourcendateien">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="NoiseTest.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\FastNoiseWrapper.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\Noise.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\NoiseInterpolator.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\ShapedNoise.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\RandNoise.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\FactoryCraft\FastNoiseLite.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\FastNoiseWrapper.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\Noise.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\NoiseInterpolator.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+    <ClInclude Include="NoiseCombiner.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\ShapedNoise.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\RandNoise.h">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>

+ 14 - 4
Windows Version/Windows Version.vcxproj

@@ -166,6 +166,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClCompile Include="..\FactoryCraft\BiomGenerator.cpp" />
     <ClCompile Include="..\FactoryCraft\Block.cpp" />
     <ClCompile Include="..\FactoryCraft\BlockType.cpp" />
+    <ClCompile Include="..\FactoryCraft\BlockTypeGeneratorRule.cpp" />
     <ClCompile Include="..\FactoryCraft\CaveGenerator.cpp" />
     <ClCompile Include="..\FactoryCraft\Chat.cpp" />
     <ClCompile Include="..\FactoryCraft\ChatCommand.cpp" />
@@ -187,9 +188,9 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClCompile Include="..\FactoryCraft\FluidBlock.cpp" />
     <ClCompile Include="..\FactoryCraft\Game.cpp" />
     <ClCompile Include="..\FactoryCraft\GeneratedStructure.cpp" />
-    <ClCompile Include="..\FactoryCraft\GenerationTemplate.cpp" />
+    <ClCompile Include="..\FactoryCraft\GeneratorTemplate.cpp" />
+    <ClCompile Include="..\FactoryCraft\GeneratorRule.cpp" />
     <ClCompile Include="..\FactoryCraft\GrantCommand.cpp" />
-    <ClCompile Include="..\FactoryCraft\GrasslandBiom.cpp" />
     <ClCompile Include="..\FactoryCraft\Grass.cpp" />
     <ClCompile Include="..\FactoryCraft\Hoe.cpp" />
     <ClCompile Include="..\FactoryCraft\Inventory.cpp" />
@@ -201,6 +202,8 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClCompile Include="..\FactoryCraft\ItemSlot.cpp" />
     <ClCompile Include="..\FactoryCraft\ItemStack.cpp" />
     <ClCompile Include="..\FactoryCraft\ItemType.cpp" />
+    <ClCompile Include="..\FactoryCraft\JNoise.cpp" />
+    <ClCompile Include="..\FactoryCraft\JsonExpression.cpp" />
     <ClCompile Include="..\FactoryCraft\LightSources.cpp" />
     <ClCompile Include="..\FactoryCraft\ModelInfo.cpp" />
     <ClCompile Include="..\FactoryCraft\MultiblockStructure.cpp" />
@@ -223,18 +226,22 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClCompile Include="..\FactoryCraft\Shovel.cpp" />
     <ClCompile Include="..\FactoryCraft\Start.cpp" />
     <ClCompile Include="..\FactoryCraft\StaticInitializerOrder.cpp" />
+    <ClCompile Include="..\FactoryCraft\StructureCollection.cpp" />
     <ClCompile Include="..\FactoryCraft\TickOrganizer.cpp" />
     <ClCompile Include="..\FactoryCraft\TickQueue.cpp" />
     <ClCompile Include="..\FactoryCraft\TickWorker.cpp" />
     <ClCompile Include="..\FactoryCraft\TreeSeblingBlock.cpp" />
     <ClCompile Include="..\FactoryCraft\TreeTemplate.cpp" />
     <ClCompile Include="..\FactoryCraft\GrowingPlant.cpp" />
+    <ClCompile Include="..\FactoryCraft\TypeRegistry.cpp" />
     <ClCompile Include="..\FactoryCraft\WorldGenerator.cpp" />
     <ClCompile Include="..\FactoryCraft\WorldLoader.cpp" />
     <ClCompile Include="..\FactoryCraft\WorldUpdate.cpp" />
     <ClCompile Include="..\FactoryCraft\WormCaveGenerator.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\FactoryCraft\GeneratorRule.h" />
+    <ClInclude Include="..\FactoryCraft\BlockTypeGeneratorRule.h" />
     <ClInclude Include="..\FactoryCraft\Chest.h" />
     <ClInclude Include="..\FactoryCraft\ChunkMap.h" />
     <ClInclude Include="..\FactoryCraft\AddEntityUpdate.h" />
@@ -266,9 +273,8 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClInclude Include="..\FactoryCraft\FluidBlock.h" />
     <ClInclude Include="..\FactoryCraft\Game.h" />
     <ClInclude Include="..\FactoryCraft\GeneratedStructure.h" />
-    <ClInclude Include="..\FactoryCraft\GenerationTemplate.h" />
+    <ClInclude Include="..\FactoryCraft\GeneratorTemplate.h" />
     <ClInclude Include="..\FactoryCraft\GrantCommand.h" />
-    <ClInclude Include="..\FactoryCraft\GrasslandBiom.h" />
     <ClInclude Include="..\FactoryCraft\Grass.h" />
     <ClInclude Include="..\FactoryCraft\Chat.h" />
     <ClInclude Include="..\FactoryCraft\Hoe.h" />
@@ -281,6 +287,8 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClInclude Include="..\FactoryCraft\ItemSlot.h" />
     <ClInclude Include="..\FactoryCraft\ItemStack.h" />
     <ClInclude Include="..\FactoryCraft\ItemType.h" />
+    <ClInclude Include="..\FactoryCraft\JNoise.h" />
+    <ClInclude Include="..\FactoryCraft\JsonExpression.h" />
     <ClInclude Include="..\FactoryCraft\LightSources.h" />
     <ClInclude Include="..\FactoryCraft\DimensionMap.h" />
     <ClInclude Include="..\FactoryCraft\ModelInfo.h" />
@@ -304,6 +312,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClInclude Include="..\FactoryCraft\ShapedNoise.h" />
     <ClInclude Include="..\FactoryCraft\Shovel.h" />
     <ClInclude Include="..\FactoryCraft\StaticRegistry.h" />
+    <ClInclude Include="..\FactoryCraft\StructureCollection.h" />
     <ClInclude Include="..\FactoryCraft\Tickable.h" />
     <ClInclude Include="..\FactoryCraft\TickOrganizer.h" />
     <ClInclude Include="..\FactoryCraft\TickQueue.h" />
@@ -311,6 +320,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\release\Framework.dll Framework.dll<
     <ClInclude Include="..\FactoryCraft\TreeSeblingBlock.h" />
     <ClInclude Include="..\FactoryCraft\TreeTemplate.h" />
     <ClInclude Include="..\FactoryCraft\GrowingPlant.h" />
+    <ClInclude Include="..\FactoryCraft\TypeRegistry.h" />
     <ClInclude Include="..\FactoryCraft\WorldGenerator.h" />
     <ClInclude Include="..\FactoryCraft\WorldLoader.h" />
     <ClInclude Include="..\FactoryCraft\WorldUpdate.h" />

+ 53 - 17
Windows Version/Windows Version.vcxproj.filters

@@ -25,9 +25,6 @@
     <Filter Include="world\generator\noise">
       <UniqueIdentifier>{6a594ea1-a32c-4e11-9f2c-d694f42e9076}</UniqueIdentifier>
     </Filter>
-    <Filter Include="world\generator\bioms">
-      <UniqueIdentifier>{a69078f1-3e20-4b14-943e-9d02c4df470d}</UniqueIdentifier>
-    </Filter>
     <Filter Include="world\generator\dimensions">
       <UniqueIdentifier>{b04d9ff5-ad58-41e2-8e72-8de835e09c99}</UniqueIdentifier>
     </Filter>
@@ -88,6 +85,15 @@
     <Filter Include="world\blocks\storage">
       <UniqueIdentifier>{f0a18928-ee44-40d9-8872-e09b57585ac0}</UniqueIdentifier>
     </Filter>
+    <Filter Include="server\config">
+      <UniqueIdentifier>{37cc61df-5924-4def-91db-443f07b51d5e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="world\generator\biom">
+      <UniqueIdentifier>{a69078f1-3e20-4b14-943e-9d02c4df470d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="world\generator\biom\rules">
+      <UniqueIdentifier>{3a03ed08-0a9d-4887-a1f0-d2a84028c425}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\FactoryCraft\Server.cpp">
@@ -120,12 +126,6 @@
     <ClCompile Include="..\FactoryCraft\OverworldDimension.cpp">
       <Filter>world\generator\dimensions</Filter>
     </ClCompile>
-    <ClCompile Include="..\FactoryCraft\GrasslandBiom.cpp">
-      <Filter>world\generator\bioms</Filter>
-    </ClCompile>
-    <ClCompile Include="..\FactoryCraft\BiomGenerator.cpp">
-      <Filter>world\generator</Filter>
-    </ClCompile>
     <ClCompile Include="..\FactoryCraft\TickWorker.cpp">
       <Filter>world\ticking</Filter>
     </ClCompile>
@@ -201,7 +201,7 @@
     <ClCompile Include="..\FactoryCraft\GeneratedStructure.cpp">
       <Filter>world\generator\templates</Filter>
     </ClCompile>
-    <ClCompile Include="..\FactoryCraft\GenerationTemplate.cpp">
+    <ClCompile Include="..\FactoryCraft\GeneratorTemplate.cpp">
       <Filter>world\generator\templates</Filter>
     </ClCompile>
     <ClCompile Include="..\FactoryCraft\TreeTemplate.cpp">
@@ -318,6 +318,27 @@
     <ClCompile Include="..\FactoryCraft\Shovel.cpp">
       <Filter>inventory\items\tools</Filter>
     </ClCompile>
+    <ClCompile Include="..\FactoryCraft\JsonExpression.cpp">
+      <Filter>server\config</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\JNoise.cpp">
+      <Filter>world\generator\noise</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\BiomGenerator.cpp">
+      <Filter>world\generator\biom</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\GeneratorRule.cpp">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\BlockTypeGeneratorRule.cpp">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\TypeRegistry.cpp">
+      <Filter>server\config</Filter>
+    </ClCompile>
+    <ClCompile Include="..\FactoryCraft\StructureCollection.cpp">
+      <Filter>world\generator\templates</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\FactoryCraft\Chunk.h">
@@ -374,15 +395,9 @@
     <ClInclude Include="..\FactoryCraft\WorldGenerator.h">
       <Filter>world\generator</Filter>
     </ClInclude>
-    <ClInclude Include="..\FactoryCraft\BiomGenerator.h">
-      <Filter>world\generator</Filter>
-    </ClInclude>
     <ClInclude Include="..\FactoryCraft\DimensionGenerator.h">
       <Filter>world\generator</Filter>
     </ClInclude>
-    <ClInclude Include="..\FactoryCraft\GrasslandBiom.h">
-      <Filter>world\generator\bioms</Filter>
-    </ClInclude>
     <ClInclude Include="..\FactoryCraft\OverworldDimension.h">
       <Filter>world\generator\dimensions</Filter>
     </ClInclude>
@@ -434,7 +449,7 @@
     <ClInclude Include="..\FactoryCraft\EntityRemovedUpdate.h">
       <Filter>world\update</Filter>
     </ClInclude>
-    <ClInclude Include="..\FactoryCraft\GenerationTemplate.h">
+    <ClInclude Include="..\FactoryCraft\GeneratorTemplate.h">
       <Filter>world\generator\templates</Filter>
     </ClInclude>
     <ClInclude Include="..\FactoryCraft\GeneratedStructure.h">
@@ -560,5 +575,26 @@
     <ClInclude Include="..\FactoryCraft\Shovel.h">
       <Filter>inventory\items\tools</Filter>
     </ClInclude>
+    <ClInclude Include="..\FactoryCraft\JsonExpression.h">
+      <Filter>server\config</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\JNoise.h">
+      <Filter>world\generator\noise</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\StructureCollection.h">
+      <Filter>world\generator\templates</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\BiomGenerator.h">
+      <Filter>world\generator\biom</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\GeneratorRule.h">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\BlockTypeGeneratorRule.h">
+      <Filter>world\generator\biom\rules</Filter>
+    </ClInclude>
+    <ClInclude Include="..\FactoryCraft\TypeRegistry.h">
+      <Filter>server\config</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>

+ 485 - 0
Windows Version/data/generator/overworld.json

@@ -0,0 +1,485 @@
+[
+  {
+    "dimension": "Overworld",
+    "dimensionSeed": {
+      "type": "operator",
+      "operator": "+",
+      "values": [
+        {
+          "type": "variable",
+          "name": "worldSeed"
+        },
+        {
+          "type": "variable",
+          "name": "dimensionId"
+        }
+      ]
+    },
+    "biomNoise": {
+      "type": "Cellular",
+      "seed": {
+        "type": "variable",
+        "name": "dimensionSeed"
+      },
+      "rotationType3D": "None",
+      "frequency": 0.015,
+      "fractalType": "None",
+      "cellularDistanceFunction": "Hybrid",
+      "cellularReturnType": "CellValue",
+      "cellularJitter": 1,
+      "domainWarpType": "OpenSimplex2Reduced",
+      "domainWarpAmp": 30
+    },
+    "heightLayers": [
+      {
+        "name": "surfaceHeight",
+        "noise": {
+          "type": "ValueCubic",
+          "seed": {
+            "type": "variable",
+            "name": "dimensionSeed"
+          }
+        },
+        "value": {
+          "type": "operator",
+          "operator": "+",
+          "values": [
+            {
+              "type": "constant",
+              "value": 50
+            },
+            {
+              "type": "operator",
+              "operator": "*",
+              "values": [
+                {
+                  "type": "noise",
+                  "name": "surfaceHeight",
+                  "x": {
+                    "type": "variable",
+                    "name": "x"
+                  },
+                  "y": {
+                    "type": "variable",
+                    "name": "y"
+                  },
+                  "z": {
+                    "type": "constant",
+                    "value": 0
+                  }
+                },
+                {
+                  "type": "constant",
+                  "value": 400
+                }
+              ]
+            }
+          ]
+        }
+      },
+      {
+        "name": "underground1",
+        "noise": {
+          "type": "ValueCubic",
+          "seed": {
+            "type": "variable",
+            "name": "dimensionSeed"
+          }
+        },
+        "value": {
+          "type": "operator",
+          "operator": "-",
+          "values": [
+            {
+              "type": "variable",
+              "name": "surfaceHeight"
+            },
+            {
+              "type": "constant",
+              "value": 5
+            },
+            {
+              "type": "operator",
+              "operator": "*",
+              "values": [
+                {
+                  "type": "noise",
+                  "name": "underground1",
+                  "x": {
+                    "type": "variable",
+                    "name": "x"
+                  },
+                  "y": {
+                    "type": "variable",
+                    "name": "y"
+                  },
+                  "z": {
+                    "type": "constant",
+                    "value": 0
+                  }
+                },
+                {
+                  "type": "constant",
+                  "value": 45
+                }
+              ]
+            }
+          ]
+        }
+      }
+    ],
+    "bioms": [
+      {
+        "name": "Grassland",
+        "structurCollections": [
+          {
+            "activeNoise": {
+              "type": "random",
+              "seed": {
+                "type": "variable",
+                "name": "dimensionSeed"
+              }
+            },
+            "structureNoise": {
+              "type": "random",
+              "seed": {
+                "type": "operator",
+                "operator": "+",
+                "values": [
+                  {
+                    "type": "variable",
+                    "name": "dimensionSeed"
+                  },
+                  {
+                    "type": "constant",
+                    "value": 10
+                  }
+                ]
+              }
+            },
+            "threshold": 0.001,
+            "structures": [
+              {
+                "type": "Tree",
+                "wood": "Birch Wood",
+                "leaves": "Birch Wood Leaves",
+                "minSize": 8,
+                "maxSize": 15,
+                "propability": 0.5
+              },
+              {
+                "type": "Tree",
+                "wood": "Beech Wood",
+                "leaves": "Beech Wood Leaves",
+                "minSize": 8,
+                "maxSize": 13,
+                "propability": 0.25
+              },
+              {
+                "type": "Tree",
+                "wood": "Oak Wood",
+                "leaves": "Oak Wood Leaves",
+                "minSize": 10,
+                "maxSize": 15,
+                "propability": 0.125
+              },
+              {
+                "type": "Tree",
+                "wood": "Pine Wood",
+                "leaves": "Pine Wood Leaves",
+                "minSize": 15,
+                "maxSize": 24,
+                "propability": 0.075
+              }
+            ],
+            "condition": {
+              "type": "operator",
+              "operator": "==",
+              "values": [
+                {
+                  "type": "variable",
+                  "name": "z"
+                },
+                {
+                  "type": "operator",
+                  "operator": "-",
+                  "values": [
+                    {
+                      "type": "variable",
+                      "name": "surfaceHeight"
+                    },
+                    {
+                      "type": "constant",
+                      "value": 1
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "blocks": [
+          {
+            "type": "blockType",
+            "blockType": "Grass",
+            "noise": {
+              "type": "random",
+              "seed": {
+                "type": "operator",
+                "operator": "+",
+                "values": [
+                  {
+                    "type": "variable",
+                    "name": "dimensionSeed"
+                  },
+                  {
+                    "type": "constant",
+                    "value": 3
+                  }
+                ]
+              }
+            },
+            "threshold": 0.25,
+            "condition": {
+              "type": "operator",
+              "operator": "&&",
+              "values": [
+                {
+                  "type": "operator",
+                  "operator": "==",
+                  "values": [
+                    {
+                      "type": "variable",
+                      "name": "z"
+                    },
+                    {
+                      "type": "variable",
+                      "name": "surfaceHeight"
+                    }
+                  ]
+                },
+                {
+                  "type": "blockType",
+                  "x": {
+                    "type": "variable",
+                    "name": "x"
+                  },
+                  "y": {
+                    "type": "variable",
+                    "name": "y"
+                  },
+                  "z": {
+                    "type": "operator",
+                    "operator": "-",
+                    "values": [
+                      {
+                        "type": "variable",
+                        "name": "z"
+                      },
+                      {
+                        "type": "constant",
+                        "value": 1
+                      }
+                    ]
+                  },
+                  "blockType": "Dirt"
+                }
+              ]
+            }
+          },
+          {
+            "type": "blockType",
+            "blockType": "Gravel",
+            "noise": {
+              "type": "ValueCubic",
+              "frequency": 0.1,
+              "seed": {
+                "type": "operator",
+                "operator": "+",
+                "values": [
+                  {
+                    "type": "variable",
+                    "name": "dimensionSeed"
+                  },
+                  {
+                    "type": "constant",
+                    "value": 2
+                  }
+                ]
+              }
+            },
+            "threshold": 0.35,
+            "condition": {
+              "type": "operator",
+              "operator": "<",
+              "values": [
+                {
+                  "type": "variable",
+                  "name": "z"
+                },
+                {
+                  "type": "variable",
+                  "name": "surfaceHeight"
+                }
+              ]
+            }
+          },
+          {
+            "type": "blockType",
+            "blockType": "Dirt",
+            "noise": {
+              "type": "ValueCubic",
+              "frequency": 0.125,
+              "seed": {
+                "type": "operator",
+                "operator": "+",
+                "values": [
+                  {
+                    "type": "variable",
+                    "name": "dimensionSeed"
+                  },
+                  {
+                    "type": "constant",
+                    "value": 1
+                  }
+                ]
+              }
+            },
+            "threshold": 0.35,
+            "condition": {
+              "type": "operator",
+              "operator": "<",
+              "values": [
+                {
+                  "type": "variable",
+                  "name": "z"
+                },
+                {
+                  "type": "variable",
+                  "name": "surfaceHeight"
+                }
+              ]
+            }
+          },
+          {
+            "type": "blockType",
+            "blockType": "Sand",
+            "noise": {
+              "type": "ValueCubic",
+              "frequency": 0.125,
+              "seed": {
+                "type": "operator",
+                "operator": "+",
+                "values": [
+                  {
+                    "type": "variable",
+                    "name": "dimensionSeed"
+                  },
+                  {
+                    "type": "constant",
+                    "value": 2
+                  }
+                ]
+              }
+            },
+            "threshold": 0.35,
+            "condition": {
+              "type": "operator",
+              "operator": "&&",
+              "values": [
+                {
+                  "type": "operator",
+                  "operator": "<",
+                  "values": [
+                    {
+                      "type": "variable",
+                      "name": "z"
+                    },
+                    {
+                      "type": "variable",
+                      "name": "surfaceHeight"
+                    }
+                  ]
+                },
+                {
+                  "type": "operator",
+                  "operator": ">",
+                  "values": [
+                    {
+                      "type": "variable",
+                      "name": "z"
+                    },
+                    {
+                      "type": "variable",
+                      "name": "underground1"
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "type": "blockType",
+            "blockType": "Dirt",
+            "condition": {
+              "type": "operator",
+              "operator": "&&",
+              "values": [
+                {
+                  "type": "operator",
+                  "operator": "<",
+                  "values": [
+                    {
+                      "type": "variable",
+                      "name": "z"
+                    },
+                    {
+                      "type": "variable",
+                      "name": "surfaceHeight"
+                    }
+                  ]
+                },
+                {
+                  "type": "operator",
+                  "operator": ">",
+                  "values": [
+                    {
+                      "type": "variable",
+                      "name": "z"
+                    },
+                    {
+                      "type": "variable",
+                      "name": "underground1"
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "type": "blockType",
+            "blockType": "Stone",
+            "condition": {
+              "type": "operator",
+              "operator": "<",
+              "values": [
+                {
+                  "type": "variable",
+                  "name": "z"
+                },
+                {
+                  "type": "variable",
+                  "name": "underground1"
+                }
+              ]
+            }
+          }
+        ],
+        "condition": {
+          "type": "constant",
+          "value": true
+        }
+      }
+    ]
+  }
+]

+ 1 - 0
Windows Version/data/syntax/generatorValidation.xml

@@ -0,0 +1 @@
+<array removeInvalidEntries="true"><oneOf typeSpecifiedBy="dimension"><object><value name="dimension"><string equals="Overworld"/></value><value name="bioms"><array><object><value name="name"><string/></value><value name="condition"><oneOf typeSpecifiedBy="type"><object id="jeb_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jeb_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><bool/></value></object><object id="jeb_blockType"><value name="type"><string oneOf='["blockType"]'/></value><value name="blockType"><string oneOf='["","","Dirt","Sand","Gravel","Stone","Granite Stone","Cobble Stone","Basalt Stone","Oak Wood","Birch Wood","Beech Wood","Pine Wood","Oak Wood Leaves","Birch Wood Leaves","Beech Wood Leaves","Pine Wood Leaves","Oak Wood Sebling","Birch Wood Sebling","Beech Wood Sebling","Pine Wood Sebling","Torch","Grass","Farmland","WheatSeeds","Wheat","Water","Crafting Table","Chest"]'/></value><value name="x"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object id="jeb_bool_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["&&","||"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jeb_variable"/><objectRef ref="jeb_constant"/><objectRef ref="jeb_blockType"/><objectRef ref="jeb_bool_operator"/><objectRef ref="jeb_float_operator"/></oneOf></array></value></object><object id="jeb_float_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='[">","<",">=","<=","==","!="]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></array></value></object></oneOf></value><value name="structurCollections"><array><object><value name="activeNoise"><oneOf typeSpecifiedBy="type"><object><value name="type"><string equals="random"/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object><value name="type"><string oneOf='["Cellular","ValueCubic","Perlin","OpenSimplex2S","OpenSimplex2","Value"]'/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="rotationType3D"><string optional="true" oneOf='["None","ImproveXYPlanes","ImproveXZPlanes"]'/></value><value name="frequency"><number optional="true"/></value><value name="fractalType"><string optional="true" oneOf='["None","FBm","Ridged","PingPong","DomainWarpProgressive","DomainWarpIndependent"]'/></value><value name="cellularDistanceFunction"><string optional="true" oneOf='["Hybrid","Manhattan","EuclideanSq","Euclidean"]'/></value><value name="cellularReturnType"><string optional="true" oneOf='["CellValue","Distance","Distance2","Distance2Add","Distance2Sub","Distance2Mul","Distance2Div"]'/></value><value name="cellularJitter"><number optional="true"/></value><value name="domainWarpType"><string optional="true" oneOf='["BasicGrid","OpenSimplex2","OpenSimplex2Reduced"]'/></value><value name="domainWarpAmp"><number optional="true"/></value></object></oneOf></value><value name="structureNoise"><oneOf typeSpecifiedBy="type"><object><value name="type"><string equals="random"/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object><value name="type"><string oneOf='["Cellular","ValueCubic","Perlin","OpenSimplex2S","OpenSimplex2","Value"]'/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="rotationType3D"><string optional="true" oneOf='["None","ImproveXYPlanes","ImproveXZPlanes"]'/></value><value name="frequency"><number optional="true"/></value><value name="fractalType"><string optional="true" oneOf='["None","FBm","Ridged","PingPong","DomainWarpProgressive","DomainWarpIndependent"]'/></value><value name="cellularDistanceFunction"><string optional="true" oneOf='["Hybrid","Manhattan","EuclideanSq","Euclidean"]'/></value><value name="cellularReturnType"><string optional="true" oneOf='["CellValue","Distance","Distance2","Distance2Add","Distance2Sub","Distance2Mul","Distance2Div"]'/></value><value name="cellularJitter"><number optional="true"/></value><value name="domainWarpType"><string optional="true" oneOf='["BasicGrid","OpenSimplex2","OpenSimplex2Reduced"]'/></value><value name="domainWarpAmp"><number optional="true"/></value></object></oneOf></value><value name="threshold"><number greater="0.000000"/></value><value name="condition"><oneOf typeSpecifiedBy="type"><object id="jeb_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jeb_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><bool/></value></object><object id="jeb_blockType"><value name="type"><string oneOf='["blockType"]'/></value><value name="blockType"><string oneOf='["","","Dirt","Sand","Gravel","Stone","Granite Stone","Cobble Stone","Basalt Stone","Oak Wood","Birch Wood","Beech Wood","Pine Wood","Oak Wood Leaves","Birch Wood Leaves","Beech Wood Leaves","Pine Wood Leaves","Oak Wood Sebling","Birch Wood Sebling","Beech Wood Sebling","Pine Wood Sebling","Torch","Grass","Farmland","WheatSeeds","Wheat","Water","Crafting Table","Chest"]'/></value><value name="x"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object id="jeb_bool_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["&&","||"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jeb_variable"/><objectRef ref="jeb_constant"/><objectRef ref="jeb_blockType"/><objectRef ref="jeb_bool_operator"/><objectRef ref="jeb_float_operator"/></oneOf></array></value></object><object id="jeb_float_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='[">","<",">=","<=","==","!="]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></array></value></object></oneOf></value><value name="structures"><array><oneOf typeSpecifiedBy="type"><object><value name="type"><string equals="Tree"/></value><value name="wood"><string oneOf='["","","Dirt","Sand","Gravel","Stone","Granite Stone","Cobble Stone","Basalt Stone","Oak Wood","Birch Wood","Beech Wood","Pine Wood","Oak Wood Leaves","Birch Wood Leaves","Beech Wood Leaves","Pine Wood Leaves","Oak Wood Sebling","Birch Wood Sebling","Beech Wood Sebling","Pine Wood Sebling","Torch","Grass","Farmland","WheatSeeds","Wheat","Water","Crafting Table","Chest"]'/></value><value name="leaves"><string oneOf='["","","Dirt","Sand","Gravel","Stone","Granite Stone","Cobble Stone","Basalt Stone","Oak Wood","Birch Wood","Beech Wood","Pine Wood","Oak Wood Leaves","Birch Wood Leaves","Beech Wood Leaves","Pine Wood Leaves","Oak Wood Sebling","Birch Wood Sebling","Beech Wood Sebling","Pine Wood Sebling","Torch","Grass","Farmland","WheatSeeds","Wheat","Water","Crafting Table","Chest"]'/></value><value name="minSize"><number greater="0.000000"/></value><value name="maxSize"><number greater="0.000000"/></value><value name="propability"><number greater="0.000000"/></value></object></oneOf></array></value></object></array></value><value name="blocks"><array><oneOf typeSpecifiedBy="type"><object><value name="type"><string equals="blockType"/></value><value name="blockType"><string oneOf='["","","Dirt","Sand","Gravel","Stone","Granite Stone","Cobble Stone","Basalt Stone","Oak Wood","Birch Wood","Beech Wood","Pine Wood","Oak Wood Leaves","Birch Wood Leaves","Beech Wood Leaves","Pine Wood Leaves","Oak Wood Sebling","Birch Wood Sebling","Beech Wood Sebling","Pine Wood Sebling","Torch","Grass","Farmland","WheatSeeds","Wheat","Water","Crafting Table","Chest"]'/></value><value name="noise"><oneOf typeSpecifiedBy="type"><object optional="true"><value name="type"><string equals="random"/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object optional="true"><value name="type"><string oneOf='["Cellular","ValueCubic","Perlin","OpenSimplex2S","OpenSimplex2","Value"]'/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="rotationType3D"><string optional="true" oneOf='["None","ImproveXYPlanes","ImproveXZPlanes"]'/></value><value name="frequency"><number optional="true"/></value><value name="fractalType"><string optional="true" oneOf='["None","FBm","Ridged","PingPong","DomainWarpProgressive","DomainWarpIndependent"]'/></value><value name="cellularDistanceFunction"><string optional="true" oneOf='["Hybrid","Manhattan","EuclideanSq","Euclidean"]'/></value><value name="cellularReturnType"><string optional="true" oneOf='["CellValue","Distance","Distance2","Distance2Add","Distance2Sub","Distance2Mul","Distance2Div"]'/></value><value name="cellularJitter"><number optional="true"/></value><value name="domainWarpType"><string optional="true" oneOf='["BasicGrid","OpenSimplex2","OpenSimplex2Reduced"]'/></value><value name="domainWarpAmp"><number optional="true"/></value></object></oneOf></value><value name="condition"><oneOf typeSpecifiedBy="type"><object id="jeb_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jeb_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><bool/></value></object><object id="jeb_blockType"><value name="type"><string oneOf='["blockType"]'/></value><value name="blockType"><string oneOf='["","","Dirt","Sand","Gravel","Stone","Granite Stone","Cobble Stone","Basalt Stone","Oak Wood","Birch Wood","Beech Wood","Pine Wood","Oak Wood Leaves","Birch Wood Leaves","Beech Wood Leaves","Pine Wood Leaves","Oak Wood Sebling","Birch Wood Sebling","Beech Wood Sebling","Pine Wood Sebling","Torch","Grass","Farmland","WheatSeeds","Wheat","Water","Crafting Table","Chest"]'/></value><value name="x"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object id="jeb_bool_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["&&","||"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jeb_variable"/><objectRef ref="jeb_constant"/><objectRef ref="jeb_blockType"/><objectRef ref="jeb_bool_operator"/><objectRef ref="jeb_float_operator"/></oneOf></array></value></object><object id="jeb_float_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='[">","<",">=","<=","==","!="]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></array></value></object></oneOf></value><value name="threshold"><number optional="true" greaterOrEqual="0.000000" lessOrEqual="1.000000"/></value></object></oneOf></array></value></object></array></value><value name="biomNoise"><oneOf typeSpecifiedBy="type"><object><value name="type"><string equals="random"/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object><value name="type"><string oneOf='["Cellular","ValueCubic","Perlin","OpenSimplex2S","OpenSimplex2","Value"]'/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="rotationType3D"><string optional="true" oneOf='["None","ImproveXYPlanes","ImproveXZPlanes"]'/></value><value name="frequency"><number optional="true"/></value><value name="fractalType"><string optional="true" oneOf='["None","FBm","Ridged","PingPong","DomainWarpProgressive","DomainWarpIndependent"]'/></value><value name="cellularDistanceFunction"><string optional="true" oneOf='["Hybrid","Manhattan","EuclideanSq","Euclidean"]'/></value><value name="cellularReturnType"><string optional="true" oneOf='["CellValue","Distance","Distance2","Distance2Add","Distance2Sub","Distance2Mul","Distance2Div"]'/></value><value name="cellularJitter"><number optional="true"/></value><value name="domainWarpType"><string optional="true" oneOf='["BasicGrid","OpenSimplex2","OpenSimplex2Reduced"]'/></value><value name="domainWarpAmp"><number optional="true"/></value></object></oneOf></value><value name="dimensionSeed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="heightLayers"><array default="[]" removeInvalidEntries="true"><object><value name="name"><string/></value><value name="noise"><oneOf typeSpecifiedBy="type"><object><value name="type"><string equals="random"/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object><object><value name="type"><string oneOf='["Cellular","ValueCubic","Perlin","OpenSimplex2S","OpenSimplex2","Value"]'/></value><value name="seed"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value><value name="rotationType3D"><string optional="true" oneOf='["None","ImproveXYPlanes","ImproveXZPlanes"]'/></value><value name="frequency"><number optional="true"/></value><value name="fractalType"><string optional="true" oneOf='["None","FBm","Ridged","PingPong","DomainWarpProgressive","DomainWarpIndependent"]'/></value><value name="cellularDistanceFunction"><string optional="true" oneOf='["Hybrid","Manhattan","EuclideanSq","Euclidean"]'/></value><value name="cellularReturnType"><string optional="true" oneOf='["CellValue","Distance","Distance2","Distance2Add","Distance2Sub","Distance2Mul","Distance2Div"]'/></value><value name="cellularJitter"><number optional="true"/></value><value name="domainWarpType"><string optional="true" oneOf='["BasicGrid","OpenSimplex2","OpenSimplex2Reduced"]'/></value><value name="domainWarpAmp"><number optional="true"/></value></object></oneOf></value><value name="value"><oneOf typeSpecifiedBy="type"><object id="jef_variable"><value name="type"><string oneOf='["variable"]'/></value><value name="name"><string/></value></object><object id="jef_constant"><value name="type"><string oneOf='["constant"]'/></value><value name="value"><number/></value></object><object id="jef_noise"><value name="type"><string oneOf='["noise"]'/></value><value name="name"><string default='"noise"'/></value><value name="x"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="y"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value><value name="z"><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></value></object><object id="jef_operator"><value name="type"><string oneOf='["operator"]'/></value><value name="operator"><string oneOf='["+","-","*","/"]'/></value><value name="values"><array><oneOf typeSpecifiedBy="type"><objectRef ref="jef_variable"/><objectRef ref="jef_constant"/><objectRef ref="jef_noise"/><objectRef ref="jef_operator"/></oneOf></array></value></object></oneOf></value></object></array></value></object></oneOf></array>