Kolja Strohm пре 2 година
родитељ
комит
225a611a68

+ 1 - 56
FactoryCraft/BasicBlock.cpp

@@ -2,6 +2,7 @@
 #include "ItemEntity.h"
 #include "Game.h"
 #include "AddEntityUpdate.h"
+#include "TreeSeblingBlock.h"
 
 
 BasicBlock::BasicBlock(const BlockType* zType, ItemType* zTool, Framework::Vec3<int> pos)
@@ -194,20 +195,6 @@ Item* OakLeavesBlockItemType::createItem() const
 }
 
 // Oak Sebling
-OakSeblingBlockType::OakSeblingBlockType()
-	: BasicBlockType(ID, OakSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
-{
-	hardness = 0.1f;
-	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
-}
-
-Block* OakSeblingBlockType::createBlock(Framework::Vec3<int> position) const
-{
-	// TODO: add sebling block
-	return BasicBlockType::createBlock(position);
-}
-
-
 OakSeblingBlockItemType::OakSeblingBlockItemType()
 	: BasicBlockItemType(ID, "Oak Sebling", 0, 0, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
 {}
@@ -327,20 +314,6 @@ Item* BirchLeavesBlockItemType::createItem() const
 }
 
 // Birch Sebling
-BirchSeblingBlockType::BirchSeblingBlockType()
-	: BasicBlockType(ID, BirchSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
-{
-	hardness = 0.1f;
-	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
-}
-
-Block* BirchSeblingBlockType::createBlock(Framework::Vec3<int> position) const
-{
-	// TODO: add sebling block
-	return BasicBlockType::createBlock(position);
-}
-
-
 BirchSeblingBlockItemType::BirchSeblingBlockItemType()
 	: BasicBlockItemType(ID, "Birch Sebling", 0, 0, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
 {}
@@ -400,20 +373,6 @@ Item* BeechLeavesBlockItemType::createItem() const
 }
 
 // Beech Sebling
-BeechSeblingBlockType::BeechSeblingBlockType()
-	: BasicBlockType(ID, BeechSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
-{
-	hardness = 0.1f;
-	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
-}
-
-Block* BeechSeblingBlockType::createBlock(Framework::Vec3<int> position) const
-{
-	// TODO: add sebling block
-	return BasicBlockType::createBlock(position);
-}
-
-
 BeechSeblingBlockItemType::BeechSeblingBlockItemType()
 	: BasicBlockItemType(ID, "Beech Sebling", 0, 0, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
 {}
@@ -493,20 +452,6 @@ Block* PineLeavesBlockType::createBlock(Framework::Vec3<int> position) const
 }
 
 // Pine Sebling
-PineSeblingBlockType::PineSeblingBlockType()
-	: BasicBlockType(ID, PineSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
-{
-	hardness = 0.1f;
-	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
-}
-
-Block* PineSeblingBlockType::createBlock(Framework::Vec3<int> position) const
-{
-	// TODO: add sebling block
-	return BasicBlockType::createBlock(position);
-}
-
-
 PineSeblingBlockItemType::PineSeblingBlockItemType()
 	: BasicBlockItemType(ID, "Pine Sebling", 0, 0, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
 {}

+ 1 - 49
FactoryCraft/BasicBlocks.h

@@ -184,18 +184,6 @@ public:
 };
 REGISTER(OakSeblingBlockItemType, ItemType)
 
-class OakSeblingBlockType : public BasicBlockType
-{
-	REGISTRABLE(OakSeblingBlockType)
-
-protected:
-	OakSeblingBlockType();
-
-public:
-	virtual Block* createBlock(Framework::Vec3<int> position) const override;
-};
-REGISTER(OakSeblingBlockType, BlockType)
-
 // Gravel
 class GravelBlockItemType : public BasicBlockItemType
 {
@@ -322,18 +310,6 @@ public:
 };
 REGISTER(BirchSeblingBlockItemType, ItemType)
 
-class BirchSeblingBlockType : public BasicBlockType
-{
-	REGISTRABLE(BirchSeblingBlockType)
-
-protected:
-	BirchSeblingBlockType();
-
-public:
-	virtual Block* createBlock(Framework::Vec3<int> position) const override;
-};
-REGISTER(BirchSeblingBlockType, BlockType)
-
 // Beech Wood
 class BeechBlockItemType : public BasicBlockItemType
 {
@@ -394,18 +370,6 @@ public:
 };
 REGISTER(BeechSeblingBlockItemType, ItemType)
 
-class BeechSeblingBlockType : public BasicBlockType
-{
-	REGISTRABLE(BeechSeblingBlockType)
-
-protected:
-	BeechSeblingBlockType();
-
-public:
-	virtual Block* createBlock(Framework::Vec3<int> position) const override;
-};
-REGISTER(BeechSeblingBlockType, BlockType)
-
 // Basalt
 class BasaltBlockItemType : public BasicBlockItemType
 {
@@ -486,16 +450,4 @@ protected:
 public:
 	virtual Item* createItem() const override;
 };
-REGISTER(PineSeblingBlockItemType, ItemType)
-
-class PineSeblingBlockType : public BasicBlockType
-{
-	REGISTRABLE(PineSeblingBlockType)
-
-protected:
-	PineSeblingBlockType();
-
-public:
-	virtual Block* createBlock(Framework::Vec3<int> position) const override;
-};
-REGISTER(PineSeblingBlockType, BlockType)
+REGISTER(PineSeblingBlockItemType, ItemType)

+ 2 - 2
FactoryCraft/Block.cpp

@@ -7,7 +7,7 @@
 #include "MultiblockStructure.h"
 
 
-Block::Block(const BlockType* zType, ItemType* zTool, Framework::Vec3<int> pos, bool hasInventory)
+Block::Block(const BlockType* zType, const ItemType* zTool, Framework::Vec3<int> pos, bool hasInventory)
 	: Inventory(pos, hasInventory)
 {
 	transparent = false;
@@ -195,7 +195,7 @@ float Block::getHardness() const
 	return hardness;
 }
 
-ItemType* Block::zEffectiveTool() const
+const ItemType* Block::zEffectiveTool() const
 {
 	return zTool;
 }

+ 3 - 3
FactoryCraft/Block.h

@@ -36,7 +36,7 @@ protected:
 	float maxHP;
 	float hardness;
 	const BlockType* zType;
-	ItemType* zTool;
+	const ItemType* zTool;
 	float speedModifier;
 	Block* zNeighbours[6];
 	int neighbourTypes[6];
@@ -67,7 +67,7 @@ protected:
 	virtual void onDestroy();
 
 public:
-	Block(const BlockType* zType, ItemType* zTool, Framework::Vec3<int> pos, bool hasInventory);
+	Block(const BlockType* zType, const ItemType* zTool, Framework::Vec3<int> pos, bool hasInventory);
 	virtual ~Block();
 
 	void tick(TickQueue* zQueue);
@@ -90,7 +90,7 @@ public:
 	float getHP() const;
 	float getMaxHP() const;
 	float getHardness() const;
-	ItemType* zEffectiveTool() const;
+	const ItemType* zEffectiveTool() const;
 	float getSpeedModifier() const;
 	const Framework::Vec3<int> getPos() const;
 	int getDimensionId() const;

+ 42 - 0
FactoryCraft/DimensionGenerator.cpp

@@ -2,6 +2,8 @@
 #include "Constants.h"
 #include "Noise.h"
 #include "NoBlock.h"
+#include "RandNoise.h"
+#include "Game.h"
 
 #include <iostream>
 
@@ -173,6 +175,46 @@ Framework::Either<Block*, int> DimensionGenerator::generateBlock(Framework::Vec3
 	return AirBlockBlockType::ID;
 }
 
+bool DimensionGenerator::spawnStructure(Framework::Vec3<int> location, std::function<bool(GenerationTemplate* tmpl)> filter)
+{
+	BiomGenerator* biom = zBiomGenerator(location.x, location.y);
+	for (auto t : biom->getTemplates())
+	{
+		if (filter(t))
+		{
+			RandNoise noise((int)time(0));
+			GeneratedStructure *genStr = t->generateAt(location, &noise, dimensionId);
+			if (genStr)
+			{
+				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 y = minSearchY; y <= maxSearchY; y++)
+					{
+						for (int z = minSearchZ; z <= maxSearchZ; z++)
+						{
+							if (genStr->isBlockAffected(Framework::Vec3<int>(x, y, z)))
+							{
+								auto gen = genStr->generateBlockAt(Framework::Vec3<int>(x, y, z));
+								Game::INSTANCE->zDimension(dimensionId)->placeBlock(Framework::Vec3<int>(x, y, z), gen);
+							}
+						}
+					}
+				}
+				genStr->release();
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
 int DimensionGenerator::getDimensionId() const
 {
 	return dimensionId;

+ 1 - 0
FactoryCraft/DimensionGenerator.h

@@ -31,6 +31,7 @@ public:
 	void initialize(int seed);
 	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;

+ 2 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -147,6 +147,7 @@
     <ClInclude Include="TickOrganizer.h" />
     <ClInclude Include="TickQueue.h" />
     <ClInclude Include="TickWorker.h" />
+    <ClInclude Include="TreeSeblingBlock.h" />
     <ClInclude Include="TreeTemplate.h" />
     <ClInclude Include="WorldGenerator.h" />
     <ClInclude Include="WorldLoader.h" />
@@ -205,6 +206,7 @@
     <ClCompile Include="TickOrganizer.cpp" />
     <ClCompile Include="TickQueue.cpp" />
     <ClCompile Include="TickWorker.cpp" />
+    <ClCompile Include="TreeSeblingBlock.cpp" />
     <ClCompile Include="TreeTemplate.cpp" />
     <ClCompile Include="WorldGenerator.cpp" />
     <ClCompile Include="WorldLoader.cpp" />

+ 6 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -249,6 +249,9 @@
     <ClInclude Include="MultiblockTree.h">
       <Filter>world\structures</Filter>
     </ClInclude>
+    <ClInclude Include="TreeSeblingBlock.h">
+      <Filter>world\blocks</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
@@ -419,5 +422,8 @@
     <ClCompile Include="MultiblockTree.cpp">
       <Filter>world\structures</Filter>
     </ClCompile>
+    <ClCompile Include="TreeSeblingBlock.cpp">
+      <Filter>world\blocks</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 14 - 0
FactoryCraft/Game.cpp

@@ -329,6 +329,13 @@ void Game::thread()
 	{
 		m.messungStart();
 		ticker->nextTick();
+		actionsCs.lock();
+		while (actions.getEintragAnzahl() > 0)
+		{
+			actions.get(0)();
+			actions.remove(0);
+		}
+		actionsCs.unlock();
 		Array<int> removed;
 		double waitTotal = 0;
 		waitForLock.messungStart();
@@ -814,4 +821,11 @@ Entity* Game::zNearestEntity(int dimensionId, Framework::Vec3<float> pos, std::f
 const RecipieLoader& Game::getRecipies() const
 {
 	return recipies;
+}
+
+void Game::doLater(std::function<void()> action)
+{
+	actionsCs.lock();
+	actions.add(action);
+	actionsCs.unlock();
 }

+ 3 - 0
FactoryCraft/Game.h

@@ -77,6 +77,8 @@ private:
 	Framework::RCArray<Dimension>* dimensions;
 	Framework::RCArray<WorldUpdate>* updates;
 	Framework::RCArray<GameClient>* clients;
+	Framework::Array<std::function<void()>> actions;
+	Critical actionsCs;
 	TickOrganizer* ticker;
 	Framework::Text path;
 	bool stop;
@@ -124,6 +126,7 @@ public:
 	Entity* zEntity(int id) const;
 	Entity* zNearestEntity(int dimensionId, Framework::Vec3<float> pos, std::function<bool(Entity*)> filter);
 	const RecipieLoader& getRecipies() const;
+	void doLater(std::function<void()> action);
 
 	static Game* INSTANCE;
 	static void initialize(Framework::Text name, Framework::Text worldsDir);

+ 0 - 1
FactoryCraft/Server.cpp

@@ -374,5 +374,4 @@ bool FCKlient::matchAuthKey(char* key, int len) const
 			return 0;
 	}
 	return 1;
-	an account to play
 }

+ 1 - 0
FactoryCraft/TickOrganizer.cpp

@@ -35,6 +35,7 @@ void TickOrganizer::nextTick()
 		for (int i = 0; i < workerCount; i++)
 			notWaiting |= !workers[i]->isWaiting();
 	} while (notWaiting);
+	queue->postTick();
 }
 
 void TickOrganizer::addTickSource(Block* zBlock)

+ 7 - 0
FactoryCraft/TickQueue.cpp

@@ -1,4 +1,5 @@
 #include "TickQueue.h"
+#include "Block.h"
 
 
 TickQueue::TickQueue()
@@ -87,4 +88,10 @@ void TickQueue::waitForEmpty()
 	std::unique_lock<std::mutex> lk(mutex);
 	if (readPosition != writePosition)
 		hasNoBlocks.wait(lk, [this] { return readPosition == writePosition || exit; });
+}
+
+void TickQueue::postTick()
+{
+	for(int i = 0; i < writePosition; i++)
+		queue[i]->postTick();
 }

+ 1 - 0
FactoryCraft/TickQueue.h

@@ -27,4 +27,5 @@ public:
 	Block* zNextBlock(bool& waiting);
 	void requestExit();
 	void waitForEmpty();
+	void postTick();
 };

+ 155 - 0
FactoryCraft/TreeSeblingBlock.cpp

@@ -0,0 +1,155 @@
+#include "TreeSeblingBlock.h"
+#include "BasicBlocks.h"
+#include "TreeTemplate.h"
+#include "RandNoise.h"
+#include "Game.h"
+#include "NoBlock.h"
+
+
+TreeSeblingBlock::TreeSeblingBlock(const BlockType* zType, const ItemType* zTool, Framework::Vec3<int> pos, const BlockType* wood, const BlockType* leaves)
+	: Block(zType, zTool, pos, 0),
+	wood(wood),
+	leaves(leaves)
+{
+	tickSource = 1;
+}
+
+bool TreeSeblingBlock::onTick(TickQueue* zQueue, int numTicks, bool& blocked)
+{
+	seblingTicks += 1;
+	return 0;
+}
+
+void TreeSeblingBlock::onPostTick()
+{
+	if (seblingTicks >= seblingTicksMax)
+	{
+		Game::INSTANCE->doLater([wood = wood, leaves = leaves, pos = getPos(), dim = getDimensionId()]()
+			{
+				// the tree sebling object will be deleted during this operation
+				RandNoise noise((int)time(0));
+				if (!Game::INSTANCE->zGenerator()->spawnStructure(pos, dim, [wood = wood, leaves = leaves](GenerationTemplate* tmpl)
+					{
+						TreeTemplate* tree = dynamic_cast<TreeTemplate*>(tmpl);
+						return tree && tree->getWoodType() == wood && tree->getLeavesType() == leaves;
+					}))
+				{
+					Game::INSTANCE->zDimension(dim)->placeBlock(pos, AirBlockBlockType::ID);
+				}
+			});
+	}
+}
+
+
+TreeSeblingBlockType::TreeSeblingBlockType(int typeId, int itemTypeId, ModelInfo model)
+	: BlockType(typeId, 0, model, 1, 10, 0),
+	itemType(itemTypeId),
+	transparent(true),
+	passable(true),
+	hardness(0.1f),
+	zTool(0),
+	speedModifier(0.5f),
+	interactable(1)
+{}
+
+void TreeSeblingBlockType::createSuperBlock(Block* zBlock, Item* zItem) const
+{
+	TreeSeblingBlock* block = dynamic_cast<TreeSeblingBlock*>(zBlock);
+	if (!block)
+		throw "TreeSeblingBlockType::createSuperBlock was called with a block witch is not an instance of TreeSeblingBlock";
+	block->transparent = transparent;
+	block->passable = passable;
+	block->hp = (float)getInitialMaxHP();
+	block->maxHP = (float)getInitialMaxHP();
+	block->hardness = hardness;
+	block->zTool = zTool;
+	block->speedModifier = speedModifier;
+	block->interactable = interactable;
+	BlockType::createSuperBlock(zBlock, zItem);
+}
+
+void TreeSeblingBlockType::loadSuperBlock(Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const
+{
+	TreeSeblingBlock* block = dynamic_cast<TreeSeblingBlock*>(zBlock);
+	if (!block)
+		throw "TreeSeblingBlockType::loadSuperBlock was called with a block witch is not an instance of TreeSeblingBlock";
+	zReader->lese((char*)&block->seblingTicks, 4);
+	zReader->lese((char*)&block->seblingTicksMax, 4);
+	int id;
+	zReader->lese((char*)&id, 4);
+	block->wood = StaticRegistry<BlockType>::INSTANCE.zElement(id);
+	zReader->lese((char*)&id, 4);
+	block->leaves = StaticRegistry<BlockType>::INSTANCE.zElement(id);
+	BlockType::loadSuperBlock(zBlock, zReader, dimensionId);
+}
+
+void TreeSeblingBlockType::saveSuperBlock(Block* zBlock, Framework::StreamWriter* zWriter) const
+{
+	TreeSeblingBlock* block = dynamic_cast<TreeSeblingBlock*>(zBlock);
+	if (!block)
+		throw "TreeSeblingBlockType::saveSuperBlock was called with a block witch is not an instance of TreeSeblingBlock";
+	zWriter->schreibe((char*)&block->seblingTicks, 4);
+	zWriter->schreibe((char*)&block->seblingTicksMax, 4);
+	int id = block->wood->getId();
+	zWriter->schreibe((char*)&id, 4);
+	int id = block->leaves->getId();
+	zWriter->schreibe((char*)&id, 4);
+	BlockType::saveSuperBlock(zBlock, zWriter);
+}
+
+Item* TreeSeblingBlockType::createItem() const
+{
+	return StaticRegistry<ItemType>::INSTANCE.zElement(itemType)->createItem();
+}
+
+
+OakSeblingBlockType::OakSeblingBlockType()
+	: TreeSeblingBlockType(ID, OakSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
+{
+	hardness = 0.1f;
+	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
+}
+
+Block* OakSeblingBlockType::createBlock(Framework::Vec3<int> position) const
+{
+	return new TreeSeblingBlock(this, zTool, position, OakBlockType::INSTANCE, OakLeavesBlockType::INSTANCE);
+}
+
+
+BirchSeblingBlockType::BirchSeblingBlockType()
+	: TreeSeblingBlockType(ID, BirchSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
+{
+	hardness = 0.1f;
+	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
+}
+
+Block* BirchSeblingBlockType::createBlock(Framework::Vec3<int> position) const
+{
+	return new TreeSeblingBlock(this, zTool, position, BirchBlockType::INSTANCE, BirchLeavesBlockType::INSTANCE);
+}
+
+
+BeechSeblingBlockType::BeechSeblingBlockType()
+	: TreeSeblingBlockType(ID, BeechSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
+{
+	hardness = 0.1f;
+	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
+}
+
+Block* BeechSeblingBlockType::createBlock(Framework::Vec3<int> position) const
+{
+	return new TreeSeblingBlock(this, zTool, position, BeechBlockType::INSTANCE, BeechLeavesBlockType::INSTANCE);
+}
+
+
+PineSeblingBlockType::PineSeblingBlockType()
+	: TreeSeblingBlockType(ID, PineSeblingBlockItemType::ID, ModelInfo("blocks.m3/sebling", "blocks.ltdb/sebling.png", 1))
+{
+	hardness = 0.1f;
+	defaultBlock = createBlockAt({ 0, 0, 0 }, 0);
+}
+
+Block* PineSeblingBlockType::createBlock(Framework::Vec3<int> position) const
+{
+	return new TreeSeblingBlock(this, zTool, position, PineBlockType::INSTANCE, PineLeavesBlockType::INSTANCE);
+}

+ 95 - 0
FactoryCraft/TreeSeblingBlock.h

@@ -0,0 +1,95 @@
+#pragma once
+
+#include "Block.h"
+
+class TreeSeblingBlockType;
+
+class TreeSeblingBlock : public Block
+{
+private:
+	float seblingTicks;
+	int seblingTicksMax;
+	const BlockType* wood;
+	const BlockType* leaves;
+
+public:
+	TreeSeblingBlock(const BlockType* zType, const ItemType* zTool, Framework::Vec3<int> pos, const BlockType* wood, const BlockType* leaves);
+	virtual bool onTick(TickQueue* zQueue, int numTicks, bool& blocked) override;
+	virtual void onPostTick() override;
+
+	friend TreeSeblingBlockType;
+};
+
+
+class TreeSeblingBlockType : public BlockType
+{
+private:
+	int itemType;
+
+protected:
+	bool transparent;
+	bool passable;
+	float hardness;
+	const ItemType* zTool;
+	float speedModifier;
+	bool interactable;
+
+	TreeSeblingBlockType(int typeId, int itemTypeId, ModelInfo model);
+	virtual void createSuperBlock(Block* zBlock, Item* zItem) const override;
+	virtual void loadSuperBlock(Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const override;
+	virtual void saveSuperBlock(Block* zBlock, Framework::StreamWriter* zWriter) const override;
+	virtual Item* createItem() const override;
+};
+
+
+class OakSeblingBlockType : public TreeSeblingBlockType
+{
+	REGISTRABLE(OakSeblingBlockType)
+
+protected:
+	OakSeblingBlockType();
+
+public:
+	virtual Block* createBlock(Framework::Vec3<int> position) const override;
+};
+REGISTER(OakSeblingBlockType, BlockType)
+
+
+class BirchSeblingBlockType : public TreeSeblingBlockType
+{
+	REGISTRABLE(BirchSeblingBlockType)
+
+protected:
+	BirchSeblingBlockType();
+
+public:
+	virtual Block* createBlock(Framework::Vec3<int> position) const override;
+};
+REGISTER(BirchSeblingBlockType, BlockType)
+
+
+class BeechSeblingBlockType : public TreeSeblingBlockType
+{
+	REGISTRABLE(BeechSeblingBlockType)
+
+protected:
+	BeechSeblingBlockType();
+
+public:
+	virtual Block* createBlock(Framework::Vec3<int> position) const override;
+};
+REGISTER(BeechSeblingBlockType, BlockType)
+
+
+class PineSeblingBlockType : public TreeSeblingBlockType
+{
+	REGISTRABLE(PineSeblingBlockType)
+
+protected:
+	PineSeblingBlockType();
+
+public:
+	virtual Block* createBlock(Framework::Vec3<int> position) const override;
+	
+};
+REGISTER(PineSeblingBlockType, BlockType)

+ 10 - 0
FactoryCraft/TreeTemplate.cpp

@@ -48,4 +48,14 @@ GeneratedStructure* TreeTemplate::generateAt(Framework::Vec3<int> location, Nois
 		generated->setBlockAt(zWoodType->getId(), Framework::Vec3<int>(2, 2, i));
 	generated->addAllBlocksToStructure(dynamic_cast<MultiblockStructure*>(treeStructure->getThis()));
 	return generated;
+}
+
+const BlockType* TreeTemplate::getWoodType() const
+{
+	return zWoodType;
+}
+
+const BlockType* TreeTemplate::getLeavesType() const
+{
+	return zLeaveType;
 }

+ 2 - 0
FactoryCraft/TreeTemplate.h

@@ -13,4 +13,6 @@ private:
 public:
 	TreeTemplate(float propability, const BlockType* zWoodType, const BlockType* zLeaveType, int minHeight, int maxHeight);
 	virtual GeneratedStructure* generateAt(Framework::Vec3<int> location, Noise* zNoise, int dimensionId) override;
+	const BlockType* getWoodType() const;
+	const BlockType* getLeavesType() const;
 };

+ 7 - 0
FactoryCraft/WorldGenerator.cpp

@@ -3,6 +3,8 @@
 #include "Game.h"
 #include "NoiseInterpolator.h"
 
+#include <functional>
+
 using namespace Framework;
 
 WorldGenerator::WorldGenerator(int seed)
@@ -81,4 +83,9 @@ void WorldGenerator::exitAndWait()
 Framework::Either<Block*, int> WorldGenerator::generateSingleBlock(Framework::Vec3<int> location, int dimensionId)
 {
 	return StaticRegistry<DimensionGenerator>::INSTANCE.zElement(dimensionId)->generateBlock(location);
+}
+
+bool WorldGenerator::spawnStructure(Framework::Vec3<int> location, int dimensionId, std::function<bool(GenerationTemplate* tmpl)> filter)
+{
+	return StaticRegistry<DimensionGenerator>::INSTANCE.zElement(dimensionId)->spawnStructure(location, filter);
 }

+ 1 - 0
FactoryCraft/WorldGenerator.h

@@ -22,4 +22,5 @@ public:
 	void requestGeneration(Area request);
 	void exitAndWait();
 	Framework::Either<Block*, int> generateSingleBlock(Framework::Vec3<int> location, int dimensionId);
+	bool spawnStructure(Framework::Vec3<int> location, int dimensionId, std::function<bool(GenerationTemplate* tmpl)> filter);
 };