Browse Source

add uiml based gui system

Kolja Strohm 2 years ago
parent
commit
07fcb7293f

+ 1 - 1
FactoryCraft/Area.h

@@ -20,7 +20,7 @@ enum Direction
     WEST = 8,
     TOP = 16,
     BOTTOM = 32,
-    INSIDE
+    INSIDE = 64
 };
 typedef int Directions;
 

+ 64 - 64
FactoryCraft/CraftingStorage.cpp

@@ -1,80 +1,80 @@
 #include "CraftingStorage.h"
 
-BasicShapedCrafter::BasicShapedCrafter( int width, int height, Inventory* zInventory )
-    : zInventory( zInventory ),
-    width( width ),
-    height( height )
+BasicShapedCrafter::BasicShapedCrafter(int width, int height, Inventory* zInventory)
+	: zInventory(zInventory),
+	width(width),
+	height(height)
 {
-    for( int i = 0; i < width * height; i++ )
-    {
-        ItemSlot* slot = new ItemSlot( 1, std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), INSIDE, INSIDE, 0 );
-        zInventory->addSlot( slot );
-        craftingInput.add( slot );
-    }
+	for (int i = 0; i < width * height; i++)
+	{
+		ItemSlot* slot = new ItemSlot("CraftingGrid", 1, std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), INSIDE, INSIDE, 0);
+		zInventory->addSlot(slot);
+		craftingInput.add(slot);
+	}
 }
 
-bool BasicShapedCrafter::isAllAvailable( Framework::RCArray<ItemFilter>& filters, int width, int height )
+bool BasicShapedCrafter::isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height)
 {
-    for( int x = 0; x <= this->width - width; x++ )
-    {
-        for( int y = 0; y <= this->height - height; y++ )
-        {
-            for( int w = 0; w < width; w++ )
-            {
-                for( int h = 0; h < height; h++ )
-                {
-                    ItemFilter* f = filters.z( w * width + h );
-                    ItemSlot* s = craftingInput.get( w * 2 + h );
-                    const Item* item = 0;
-                    if( s && s->zStack() )
-                        item = s->zStack()->zItem();
-                    if( (item && !f) || (!item && f) ) return 0;
-                    if( item && f && !f->matchItem( item ) )
-                        return 0;
-                }
-            }
-        }
-    }
-    return 1;
+	for (int x = 0; x <= this->width - width; x++)
+	{
+		for (int y = 0; y <= this->height - height; y++)
+		{
+			for (int w = 0; w < width; w++)
+			{
+				for (int h = 0; h < height; h++)
+				{
+					ItemFilter* f = filters.z(w * width + h);
+					ItemSlot* s = craftingInput.get(w * 2 + h);
+					const Item* item = 0;
+					if (s && s->zStack())
+						item = s->zStack()->zItem();
+					if ((item && !f) || (!item && f)) return 0;
+					if (item && f && !f->matchItem(item))
+						return 0;
+				}
+			}
+		}
+	}
+	return 1;
 }
 
-bool BasicShapedCrafter::hasFreeSpace( const Item* zItem, int amount )
+bool BasicShapedCrafter::hasFreeSpace(const Item* zItem, int amount)
 {
-    ItemStack* stack = new ItemStack( (Item*)zItem, amount );
-    int addable = zInventory->numberOfAddableItems( stack, NO_DIRECTION );
-    stack->release();
-    return addable >= amount;
+	ItemStack* stack = new ItemStack((Item*)zItem, amount);
+	int addable = zInventory->numberOfAddableItems(stack, NO_DIRECTION);
+	stack->release();
+	return addable >= amount;
 }
 
-bool BasicShapedCrafter::consume( Framework::RCArray<ItemFilter>& filters, int width, int height )
+bool BasicShapedCrafter::consume(Framework::RCArray<ItemFilter>& filters, int width, int height)
 {
-    for( ItemSlot* slot : craftingInput )
-    {
-        if( slot && slot->zStack() )
-        {
-            ItemStack* stack = zInventory->takeItemsOut( slot, 1, INSIDE );
-            if( stack )
-                stack->release();
-        }
-    }
-    for( int x = 0; x < width; x++ )
-    {
-        for( int y = 0; y < height; y++ )
-        {
-            ItemFilter* f = filters.z( x * width + y );
-            if( f )
-            {
-                ItemSlot* target = craftingInput.get( x * this->width + y );
-                Framework::Array< ItemSlot*> tmp;
-                tmp.add( target );
-                zInventory->localTransaction( 0, &tmp, f, 1, NO_DIRECTION, INSIDE );
-            }
-        }
-    }
-    return 1;
+	for (ItemSlot* slot : craftingInput)
+	{
+		if (slot && slot->zStack())
+		{
+			ItemStack* stack = zInventory->takeItemsOut(slot, 1, INSIDE);
+			if (stack)
+				stack->release();
+		}
+	}
+	for (int x = 0; x < width; x++)
+	{
+		for (int y = 0; y < height; y++)
+		{
+			ItemFilter* f = filters.z(x * width + y);
+			if (f)
+			{
+				ItemSlot* target = craftingInput.get(x * this->width + y);
+				Framework::Array< ItemSlot*> tmp;
+				tmp.add(target);
+				zInventory->localTransaction(0, &tmp, f, 1, NO_DIRECTION, INSIDE);
+			}
+		}
+	}
+	return 1;
 }
 
-void BasicShapedCrafter::addCraftingResult( ItemStack* stack )
+void BasicShapedCrafter::addCraftingResult(ItemStack* stack)
 {
-    zInventory->addItems( stack, NO_DIRECTION );
+	zInventory->addItems(stack, NO_DIRECTION);
 }

+ 17 - 17
FactoryCraft/CraftingStorage.h

@@ -10,33 +10,33 @@
 class CraftingStorage
 {
 public:
-    virtual bool isAllAvailable( Framework::RCArray<ItemFilter>& filters, Framework::Array<int>& inputAmount ) = 0;
-    virtual bool hasFreeSpace( const Item* zItem, int amount ) = 0;
-    virtual bool consume( Framework::RCArray<ItemFilter>& filters, Framework::Array<int>& inputAmount ) = 0;
-    virtual void addCraftingResult( ItemStack* stack ) = 0;
+	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, Framework::Array<int>& inputAmount) = 0;
+	virtual bool hasFreeSpace(const Item* zItem, int amount) = 0;
+	virtual bool consume(Framework::RCArray<ItemFilter>& filters, Framework::Array<int>& inputAmount) = 0;
+	virtual void addCraftingResult(ItemStack* stack) = 0;
 };
 
 class ShapedCraftingStorage
 {
 public:
-    virtual bool isAllAvailable( Framework::RCArray<ItemFilter>& filters, int width, int height ) = 0;
-    virtual bool hasFreeSpace( const Item* zItem, int amount ) = 0;
-    virtual bool consume( Framework::RCArray<ItemFilter>& filters, int width, int height ) = 0;
-    virtual void addCraftingResult( ItemStack* stack ) = 0;
+	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height) = 0;
+	virtual bool hasFreeSpace(const Item* zItem, int amount) = 0;
+	virtual bool consume(Framework::RCArray<ItemFilter>& filters, int width, int height) = 0;
+	virtual void addCraftingResult(ItemStack* stack) = 0;
 };
 
 class BasicShapedCrafter : public ShapedCraftingStorage
 {
 private:
-    Framework::Array<ItemSlot*> craftingInput;
-    Inventory* zInventory;
-    int width;
-    int height;
+	Framework::Array<ItemSlot*> craftingInput;
+	Inventory* zInventory;
+	int width;
+	int height;
 
 public:
-    BasicShapedCrafter( int width, int height, Inventory* zInventory );
-    virtual bool isAllAvailable( Framework::RCArray<ItemFilter>& filters, int width, int height );
-    virtual bool hasFreeSpace( const Item* zItem, int amount );
-    virtual bool consume( Framework::RCArray<ItemFilter>& filters, int width, int height );
-    virtual void addCraftingResult( ItemStack* stack );
+	BasicShapedCrafter(int width, int height, Inventory* zInventory);
+	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height);
+	virtual bool hasFreeSpace(const Item* zItem, int amount);
+	virtual bool consume(Framework::RCArray<ItemFilter>& filters, int width, int height);
+	virtual void addCraftingResult(ItemStack* stack);
 };

+ 233 - 233
FactoryCraft/Dimension.cpp

@@ -6,299 +6,299 @@
 using namespace Framework;
 
 
-Dimension::Dimension( int id )
-    : dimensionId( id ),
-    gravity( 9.8f ),
-    chunks( new Trie<Chunk>() ),
-    entities( new RCArray<Entity>() )
+Dimension::Dimension(int id)
+	: dimensionId(id),
+	gravity(9.8f),
+	chunks(new Trie<Chunk>()),
+	entities(new RCArray<Entity>())
 {}
 
 Dimension::~Dimension()
 {
-    entities->release();
-    chunks->release();
+	entities->release();
+	chunks->release();
 }
 
-void Dimension::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
+void Dimension::api(Framework::StreamReader* zRequest, NetworkResponse* zResponse)
 {
-    // TODO: switch type chunck, block, entity
+	// TODO: switch type chunck, block
 }
 
 void Dimension::tickEntities()
 {
-    for( auto entity : *entities )
-    {
-        if( !entity->isRemoved() && zChunk( Punkt( (int)entity->getPosition().x, (int)entity->getPosition().y ) ) )
-            entity->prepareTick( this );
-    }
-    int index = 0;
-    for( auto entity : *entities )
-    {
-        if( !entity->isRemoved() && zChunk( Punkt( (int)entity->getPosition().x, (int)entity->getPosition().y ) ) )
-            entity->tick( this );
-        index++;
-    }
+	for (auto entity : *entities)
+	{
+		if (!entity->isRemoved() && zChunk(Punkt((int)entity->getPosition().x, (int)entity->getPosition().y)))
+			entity->prepareTick(this);
+	}
+	int index = 0;
+	for (auto entity : *entities)
+	{
+		if (!entity->isRemoved() && zChunk(Punkt((int)entity->getPosition().x, (int)entity->getPosition().y)))
+			entity->tick(this);
+		index++;
+	}
 }
 
-void Dimension::getAddrOf( Punkt cPos, char* addr ) const
+void Dimension::getAddrOf(Punkt cPos, char* addr) const
 {
-    *(int*)addr = cPos.x;
-    *((int*)addr + 1) = cPos.y;
+	*(int*)addr = cPos.x;
+	*((int*)addr + 1) = cPos.y;
 }
 
-void Dimension::getAddrOfWorld( Punkt wPos, char* addr ) const
+void Dimension::getAddrOfWorld(Punkt wPos, char* addr) const
 {
-    if( wPos.x < 0 )
-        wPos.x -= CHUNK_SIZE;
-    if( wPos.y < 0 ) // needed because otherwise would (-8, -8) have the same adress as (8, 8)
-        wPos.y -= CHUNK_SIZE;
-    wPos /= CHUNK_SIZE;
-    getAddrOf( wPos, addr );
+	if (wPos.x < 0)
+		wPos.x -= CHUNK_SIZE;
+	if (wPos.y < 0) // needed because otherwise would (-8, -8) have the same adress as (8, 8)
+		wPos.y -= CHUNK_SIZE;
+	wPos /= CHUNK_SIZE;
+	getAddrOf(wPos, addr);
 }
 
-Chunk* Dimension::zChunk( Punkt wPos ) const
+Chunk* Dimension::zChunk(Punkt wPos) const
 {
-    char addr[ 8 ];
-    getAddrOfWorld( wPos, addr );
-    return chunks->z( addr, 8 );
+	char addr[8];
+	getAddrOfWorld(wPos, addr);
+	return chunks->z(addr, 8);
 }
 
-Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location )
+Framework::Either<Block*, int> Dimension::zBlock(Vec3<int> location)
 {
-    Chunk* c = zChunk( Game::INSTANCE->getChunkCenter( location.x, location.y ) );
-    if( c )
-    {
-        int x = location.x % CHUNK_SIZE;
-        int y = location.y % CHUNK_SIZE;
-        if( x < 0 )
-            x += CHUNK_SIZE;
-        if( y < 0 )
-            y += CHUNK_SIZE;
-        return c->zBlockAt( Vec3<int>( x, y, location.z ) );
-    }
-    return 0;
+	Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
+	if (c)
+	{
+		int x = location.x % CHUNK_SIZE;
+		int y = location.y % CHUNK_SIZE;
+		if (x < 0)
+			x += CHUNK_SIZE;
+		if (y < 0)
+			y += CHUNK_SIZE;
+		return c->zBlockAt(Vec3<int>(x, y, location.z));
+	}
+	return 0;
 }
 
-Block* Dimension::zRealBlockInstance( Framework::Vec3<int> location )
+Block* Dimension::zRealBlockInstance(Framework::Vec3<int> location)
 {
-    Chunk* c = zChunk( Game::INSTANCE->getChunkCenter( location.x, location.y ) );
-    if( c )
-    {
-        int x = location.x % CHUNK_SIZE;
-        int y = location.y % CHUNK_SIZE;
-        if( x < 0 )
-            x += CHUNK_SIZE;
-        if( y < 0 )
-            y += CHUNK_SIZE;
-        c->instantiateBlock( Vec3<int>( x, y, location.z ) );
-        return c->zBlockAt( Vec3<int>( x, y, location.z ) );
-    }
-    return 0;
+	Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
+	if (c)
+	{
+		int x = location.x % CHUNK_SIZE;
+		int y = location.y % CHUNK_SIZE;
+		if (x < 0)
+			x += CHUNK_SIZE;
+		if (y < 0)
+			y += CHUNK_SIZE;
+		c->instantiateBlock(Vec3<int>(x, y, location.z));
+		return c->zBlockAt(Vec3<int>(x, y, location.z));
+	}
+	return 0;
 }
 
-void Dimension::placeBlock( Framework::Vec3<int> location, Framework::Either<Block*, int> block )
+void Dimension::placeBlock(Framework::Vec3<int> location, Framework::Either<Block*, int> block)
 {
-    Chunk* c = zChunk( Game::getChunkCenter( location.x, location.y ) );
-    if( c )
-    {
-        int x = location.x % CHUNK_SIZE;
-        int y = location.y % CHUNK_SIZE;
-        if( x < 0 )
-            x += CHUNK_SIZE;
-        if( y < 0 )
-            y += CHUNK_SIZE;
-        if( block.isA() )
-            c->putBlockAt( Vec3<int>( x, y, location.z ), block );
-        else
-        {
-            c->putBlockAt( Vec3<int>( x, y, location.z ), 0 );
-            c->putBlockTypeAt( Vec3<int>( x, y, location.z ), block );
-        }
-    }
-    else if( block.isA() )
-        block.getA()->release();
+	Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
+	if (c)
+	{
+		int x = location.x % CHUNK_SIZE;
+		int y = location.y % CHUNK_SIZE;
+		if (x < 0)
+			x += CHUNK_SIZE;
+		if (y < 0)
+			y += CHUNK_SIZE;
+		if (block.isA())
+			c->putBlockAt(Vec3<int>(x, y, location.z), block);
+		else
+		{
+			c->putBlockAt(Vec3<int>(x, y, location.z), 0);
+			c->putBlockTypeAt(Vec3<int>(x, y, location.z), block);
+		}
+	}
+	else if (block.isA())
+		block.getA()->release();
 }
 
-void Dimension::addEntity( Entity* entity )
+void Dimension::addEntity(Entity* entity)
 {
-    entities->add( entity );
+	entities->add(entity);
 }
 
-void Dimension::setChunk( Chunk* chunk, Punkt center )
+void Dimension::setChunk(Chunk* chunk, Punkt center)
 {
-    char addr[ 8 ];
-    getAddrOfWorld( center, addr );
-    Chunk* old = chunks->z( addr, 8 );
-    if( old )
-    {
-        for( int i = 0; i < chunkList.getEintragAnzahl(); i++ )
-        {
-            if( chunkList.get( i ) == old )
-            {
-                chunkList.remove( i );
-                break;
-            }
-        }
-    }
-    chunks->set( addr, 8, chunk );
-    if( chunk )
-    {
-        chunkList.add( chunk );
-        chunk->setAdded();
-    }
-    getAddrOfWorld( center + Punkt( CHUNK_SIZE, 0 ), addr );
-    Chunk* zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( WEST, chunk );
-        if( chunk )
-            chunk->setNeighbor( EAST, zChunk );
-    }
-    getAddrOfWorld( center + Punkt( -CHUNK_SIZE, 0 ), addr );
-    zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( EAST, chunk );
-        if( chunk )
-            chunk->setNeighbor( WEST, zChunk );
-    }
-    getAddrOfWorld( center + Punkt( 0, CHUNK_SIZE ), addr );
-    zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( NORTH, chunk );
-        if( chunk )
-            chunk->setNeighbor( SOUTH, zChunk );
-    }
-    getAddrOfWorld( center + Punkt( 0, -CHUNK_SIZE ), addr );
-    zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( SOUTH, chunk );
-        if( chunk )
-            chunk->setNeighbor( NORTH, zChunk );
-    }
+	char addr[8];
+	getAddrOfWorld(center, addr);
+	Chunk* old = chunks->z(addr, 8);
+	if (old)
+	{
+		for (int i = 0; i < chunkList.getEintragAnzahl(); i++)
+		{
+			if (chunkList.get(i) == old)
+			{
+				chunkList.remove(i);
+				break;
+			}
+		}
+	}
+	chunks->set(addr, 8, chunk);
+	if (chunk)
+	{
+		chunkList.add(chunk);
+		chunk->setAdded();
+	}
+	getAddrOfWorld(center + Punkt(CHUNK_SIZE, 0), addr);
+	Chunk* zChunk = chunks->z(addr, 8);
+	if (zChunk)
+	{
+		zChunk->setNeighbor(WEST, chunk);
+		if (chunk)
+			chunk->setNeighbor(EAST, zChunk);
+	}
+	getAddrOfWorld(center + Punkt(-CHUNK_SIZE, 0), addr);
+	zChunk = chunks->z(addr, 8);
+	if (zChunk)
+	{
+		zChunk->setNeighbor(EAST, chunk);
+		if (chunk)
+			chunk->setNeighbor(WEST, zChunk);
+	}
+	getAddrOfWorld(center + Punkt(0, CHUNK_SIZE), addr);
+	zChunk = chunks->z(addr, 8);
+	if (zChunk)
+	{
+		zChunk->setNeighbor(NORTH, chunk);
+		if (chunk)
+			chunk->setNeighbor(SOUTH, zChunk);
+	}
+	getAddrOfWorld(center + Punkt(0, -CHUNK_SIZE), addr);
+	zChunk = chunks->z(addr, 8);
+	if (zChunk)
+	{
+		zChunk->setNeighbor(SOUTH, chunk);
+		if (chunk)
+			chunk->setNeighbor(NORTH, zChunk);
+	}
 }
 
-void Dimension::save( Text worldDir ) const
+void Dimension::save(Text worldDir) const
 {
-    for( auto chunk = chunks->getIterator(); chunk; chunk++ )
-    {
-        if( !chunk._ )
-            continue;
-        Datei* file = new Datei();
-        Text filePath = worldDir + "/dim/" + dimensionId + "/";
-        filePath.appendHex( chunk->getCenter().x );
-        filePath += "_";
-        filePath.appendHex( chunk->getCenter().y );
-        filePath += ".chunk";
-        file->setDatei( filePath );
-        if( file->open( Datei::Style::schreiben ) )
-            chunk->save( file, StreamTarget::FULL );
-        file->close();
-        file->release();
-    }
-    Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
-    Datei* file = new Datei();
-    file->setDatei( filePath );
-    if( file->open( Datei::Style::schreiben ) )
-    {
-        for( Entity* entity : *entities )
-        {
-            if( entity->zType()->getId() != PlayerEntityType::ID )
-            {
-                if( !entity->isRemoved() )
-                {
-                    int type = entity->zType()->getId();
-                    file->schreibe( (char*)&type, 4 );
-                    StaticRegistry<EntityType>::INSTANCE.zElement( type )->saveEntity( entity, file );
-                }
-            }
-            else
-            {
-                Datei pFile;
-                pFile.setDatei( worldDir + "/player/" + ((Player*)entity)->getName() );
-                if( pFile.open( Datei::Style::schreiben ) )
-                    PlayerEntityType::INSTANCE->saveEntity( entity, &pFile );
-            }
-        }
-        file->close();
-    }
+	for (auto chunk = chunks->getIterator(); chunk; chunk++)
+	{
+		if (!chunk._)
+			continue;
+		Datei* file = new Datei();
+		Text filePath = worldDir + "/dim/" + dimensionId + "/";
+		filePath.appendHex(chunk->getCenter().x);
+		filePath += "_";
+		filePath.appendHex(chunk->getCenter().y);
+		filePath += ".chunk";
+		file->setDatei(filePath);
+		if (file->open(Datei::Style::schreiben))
+			chunk->save(file, StreamTarget::FULL);
+		file->close();
+		file->release();
+	}
+	Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
+	Datei* file = new Datei();
+	file->setDatei(filePath);
+	if (file->open(Datei::Style::schreiben))
+	{
+		for (Entity* entity : *entities)
+		{
+			if (entity->zType()->getId() != PlayerEntityType::ID)
+			{
+				if (!entity->isRemoved())
+				{
+					int type = entity->zType()->getId();
+					file->schreibe((char*)&type, 4);
+					StaticRegistry<EntityType>::INSTANCE.zElement(type)->saveEntity(entity, file);
+				}
+			}
+			else
+			{
+				Datei pFile;
+				pFile.setDatei(worldDir + "/player/" + ((Player*)entity)->getName());
+				if (pFile.open(Datei::Style::schreiben))
+					PlayerEntityType::INSTANCE->saveEntity(entity, &pFile);
+			}
+		}
+		file->close();
+	}
 }
 
 int Dimension::getDimensionId() const
 {
-    return dimensionId;
+	return dimensionId;
 }
 
-bool Dimension::hasChunck( int x, int y ) const
+bool Dimension::hasChunck(int x, int y) const
 {
-    return zChunk( Punkt( x, y ) );
+	return zChunk(Punkt(x, y));
 }
 
 float Dimension::getGravity() const
 {
-    return gravity;
+	return gravity;
 }
 
 void Dimension::removeOldChunks()
 {
-    Array<int> removed;
-    int index = 0;
-    for( Chunk* chunk : chunkList )
-    {
-        if( !chunk->hasViews() )
-            removed.add( index, 0 );
-        index++;
-    }
-    for( int i : removed )
-    {
-        Chunk* chunk = chunkList.get( i );
-        // TODO: save chunk
-        chunk->prepareRemove();
-        setChunk( 0, chunk->getCenter() );
-    }
+	Array<int> removed;
+	int index = 0;
+	for (Chunk* chunk : chunkList)
+	{
+		if (!chunk->hasViews())
+			removed.add(index, 0);
+		index++;
+	}
+	for (int i : removed)
+	{
+		Chunk* chunk = chunkList.get(i);
+		// TODO: save chunk
+		chunk->prepareRemove();
+		setChunk(0, chunk->getCenter());
+	}
 }
 
-Entity* Dimension::zEntity( int id )
+Entity* Dimension::zEntity(int id)
 {
-    for( auto entity : *entities )
-    {
-        if( !entity->isRemoved() && entity->getId() == id )
-            return entity;
-    }
-    return 0;
+	for (auto entity : *entities)
+	{
+		if (!entity->isRemoved() && entity->getId() == id)
+			return entity;
+	}
+	return 0;
 }
 
-Entity* Dimension::zNearestEntity( Framework::Vec3<float> pos, std::function<bool( Entity* )> filter )
+Entity* Dimension::zNearestEntity(Framework::Vec3<float> pos, std::function<bool(Entity*)> filter)
 {
-    Entity* result = 0;
-    float sqDist = 0;
-    for( auto entity : *entities )
-    {
-        if( !entity->isRemoved() && filter( entity ) )
-        {
-            float d = pos.abstandSq( entity->getPosition() );
-            if( !result || d < sqDist )
-            {
-                result = entity;
-                sqDist = d;
-            }
-        }
-    }
-    return result;
+	Entity* result = 0;
+	float sqDist = 0;
+	for (auto entity : *entities)
+	{
+		if (!entity->isRemoved() && filter(entity))
+		{
+			float d = pos.abstandSq(entity->getPosition());
+			if (!result || d < sqDist)
+			{
+				result = entity;
+				sqDist = d;
+			}
+		}
+	}
+	return result;
 }
 
-void Dimension::removeEntity( int id )
+void Dimension::removeEntity(int id)
 {
-    int index = 0;
-    for( auto entity : *entities )
-    {
-        if( entity->getId() == id )
-        {
-            entities->remove( index );
-            return;
-        }
-        index++;
-    }
+	int index = 0;
+	for (auto entity : *entities)
+	{
+		if (entity->getId() == id)
+		{
+			entities->remove(index);
+			return;
+		}
+		index++;
+	}
 }

+ 418 - 366
FactoryCraft/Entity.cpp

@@ -8,483 +8,535 @@
 #include "EntityChangedUpdate.h"
 
 
-ActionTarget::ActionTarget( Vec3<int> blockPos, Direction blockSide )
-    : blockPos( blockPos ),
-    targetBlockSide( blockSide ),
-    entityId( -1 )
+ActionTarget::ActionTarget(Vec3<int> blockPos, Direction blockSide)
+	: blockPos(blockPos),
+	targetBlockSide(blockSide),
+	entityId(-1)
 {}
 
-ActionTarget::ActionTarget( int entityId )
-    : entityId( entityId )
+ActionTarget::ActionTarget(int entityId)
+	: entityId(entityId)
 {}
 
-bool ActionTarget::isBlock( Framework::Vec3<int> blockPos, Direction blockSide ) const
+bool ActionTarget::isBlock(Framework::Vec3<int> blockPos, Direction blockSide) const
 {
-    return this->entityId == -1 && this->blockPos == blockPos && this->targetBlockSide == targetBlockSide;
+	return this->entityId == -1 && this->blockPos == blockPos && this->targetBlockSide == targetBlockSide;
 }
 
-bool ActionTarget::isEntity( int entityId ) const
+bool ActionTarget::isEntity(int entityId) const
 {
-    return this->entityId == entityId;
+	return this->entityId == entityId;
 }
 
-void ActionTarget::applyItemSkillOnTarget( Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem )
+void ActionTarget::applyItemSkillOnTarget(Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
 {
-    if( entityId >= 0 )
-    {
-        // TODO: get entity from game and apply skill
-    }
-    else
-    {
-        Block* block = Game::INSTANCE->zRealBlockInstance( blockPos, zActor->getCurrentDimensionId() );
-        if( block )
-            zItemSkill->use( zActor, zUsedItem, block );
-    }
+	if (entityId >= 0)
+	{
+		// TODO: get entity from game and apply skill
+	}
+	else
+	{
+		Block* block = Game::INSTANCE->zRealBlockInstance(blockPos, zActor->getCurrentDimensionId());
+		if (block)
+			zItemSkill->use(zActor, zUsedItem, block);
+	}
 }
 
-void ActionTarget::placeBlock( Entity* zActor, Item* zItem )
+void ActionTarget::placeBlock(Entity* zActor, Item* zItem)
 {
-    // TODO: check stamina of actor
-    Block* block = zItem->zPlacedBlockType()->createBlockAt( blockPos + getDirection( targetBlockSide ), zItem );
-    if( block )
-    {
-        if( Game::INSTANCE->requestWorldUpdate( new PlaceBlockUpdate( block, block->getPos(), zActor->getCurrentDimensionId() ) ) )
-        {
-            zItem->onPlaced();
-            // TODO: decrese stamina of actor
-        }
-    }
+	// TODO: check stamina of actor
+	Block* block = zItem->zPlacedBlockType()->createBlockAt(blockPos + getDirection(targetBlockSide), zItem);
+	if (block)
+	{
+		if (Game::INSTANCE->requestWorldUpdate(new PlaceBlockUpdate(block, block->getPos(), zActor->getCurrentDimensionId())))
+		{
+			zItem->onPlaced();
+			// TODO: decrese stamina of actor
+		}
+	}
 }
 
-void ActionTarget::save( ActionTarget* zTarget, Framework::StreamWriter* zWriter )
+void ActionTarget::save(ActionTarget* zTarget, Framework::StreamWriter* zWriter)
 {
-    if( zTarget )
-    {
-        if( zTarget->entityId >= 0 )
-        {
-            char b = 1;
-            zWriter->schreibe( &b, 1 );
-            zWriter->schreibe( (char*)&zTarget->entityId, 4 );
-        }
-        else
-        {
-            char b = 2;
-            zWriter->schreibe( &b, 1 );
-            zWriter->schreibe( (char*)&zTarget->blockPos.x, 4 );
-            zWriter->schreibe( (char*)&zTarget->blockPos.y, 4 );
-            zWriter->schreibe( (char*)&zTarget->blockPos.z, 4 );
-            zWriter->schreibe( (char*)&zTarget->targetBlockSide, 4 );
-        }
-    }
-    else
-    {
-        char b = 0;
-        zWriter->schreibe( &b, 1 );
-    }
+	if (zTarget)
+	{
+		if (zTarget->entityId >= 0)
+		{
+			char b = 1;
+			zWriter->schreibe(&b, 1);
+			zWriter->schreibe((char*)&zTarget->entityId, 4);
+		}
+		else
+		{
+			char b = 2;
+			zWriter->schreibe(&b, 1);
+			zWriter->schreibe((char*)&zTarget->blockPos.x, 4);
+			zWriter->schreibe((char*)&zTarget->blockPos.y, 4);
+			zWriter->schreibe((char*)&zTarget->blockPos.z, 4);
+			zWriter->schreibe((char*)&zTarget->targetBlockSide, 4);
+		}
+	}
+	else
+	{
+		char b = 0;
+		zWriter->schreibe(&b, 1);
+	}
 }
 
-ActionTarget* ActionTarget::load( Framework::StreamReader* zReader )
+ActionTarget* ActionTarget::load(Framework::StreamReader* zReader)
 {
-    char b;
-    zReader->lese( &b, 1 );
-    if( b == 1 )
-    {
-        int id;
-        zReader->lese( (char*)&id, 4 );
-        return new ActionTarget( id );
-    }
-    else if( b == 2 )
-    {
-        Framework::Vec3<int> pos;
-        Direction side;
-        zReader->lese( (char*)&pos.x, 4 );
-        zReader->lese( (char*)&pos.y, 4 );
-        zReader->lese( (char*)&pos.z, 4 );
-        zReader->lese( (char*)&side, 4 );
-        return new ActionTarget( pos, side );
-    }
-    return 0;
+	char b;
+	zReader->lese(&b, 1);
+	if (b == 1)
+	{
+		int id;
+		zReader->lese((char*)&id, 4);
+		return new ActionTarget(id);
+	}
+	else if (b == 2)
+	{
+		Framework::Vec3<int> pos;
+		Direction side;
+		zReader->lese((char*)&pos.x, 4);
+		zReader->lese((char*)&pos.y, 4);
+		zReader->lese((char*)&pos.z, 4);
+		zReader->lese((char*)&side, 4);
+		return new ActionTarget(pos, side);
+	}
+	return 0;
 }
 
 
-Entity::Entity( const EntityType* zType, Framework::Vec3<float> location, int dimensionId, int entityId )
-    : Inventory( location, true ),
-    speed( 0, 0, 0 ),
-    faceDir( 1, 0, 0 ),
-    target( 0 ),
-    zEntityType( zType ),
-    currentDimensionId( dimensionId ),
-    removed( 0 ),
-    gravityMultiplier( 1.f ),
-    needUpdate( 0 ),
-    id( entityId )
+Entity::Entity(const EntityType* zType, Framework::Vec3<float> location, int dimensionId, int entityId)
+	: Inventory(location, true),
+	speed(0, 0, 0),
+	faceDir(1, 0, 0),
+	target(0),
+	zEntityType(zType),
+	currentDimensionId(dimensionId),
+	removed(0),
+	gravityMultiplier(1.f),
+	needUpdate(0),
+	id(entityId)
 {}
 
 void Entity::onDeath()
 {
-    removed = 1;
-    Game::INSTANCE->requestWorldUpdate( new EntityRemovedUpdate( id, currentDimensionId, location ) );
+	removed = 1;
+	Game::INSTANCE->requestWorldUpdate(new EntityRemovedUpdate(id, currentDimensionId, location));
 }
 
-void Entity::useItem( const ItemType* zType, Item* zItem )
+void Entity::useItem(const ItemType* zType, Item* zItem)
 {
-    if( zItem && zItem->isEatable() )
-    { // TODO: eat item
-        zItem->applyFoodEffects( this );
-    }
-    else if( zItem && zItem->isPlaceable() )
-    { // TODO: place item
-        if( target )
-            target->placeBlock( this, zItem );
-    }
-    else if( !zItem || zItem->isUsable() )
-    { // use item skill
-        if( target )
-        {
-            ItemSkill* selected = 0;
-            for( ItemSkill* skill : skills )
-            {
-                if( skill->zSkillType() == zType )
-                {
-                    selected = skill;
-                    break;
-                }
-            }
-            if( !selected )
-            {
-                selected = zType->createDefaultItemSkill();
-                skills.add( selected );
-            }
-            target->applyItemSkillOnTarget( this, selected, zItem );
-        }
-    }
+	if (zItem && zItem->isEatable())
+	{ // TODO: eat item
+		zItem->applyFoodEffects(this);
+	}
+	else if (zItem && zItem->isPlaceable())
+	{ // TODO: place item
+		if (target)
+			target->placeBlock(this, zItem);
+	}
+	else if (!zItem || zItem->isUsable())
+	{ // use item skill
+		if (target)
+		{
+			ItemSkill* selected = 0;
+			for (ItemSkill* skill : skills)
+			{
+				if (skill->zSkillType() == zType)
+				{
+					selected = skill;
+					break;
+				}
+			}
+			if (!selected)
+			{
+				selected = zType->createDefaultItemSkill();
+				skills.add(selected);
+			}
+			target->applyItemSkillOnTarget(this, selected, zItem);
+		}
+	}
 }
 
-void Entity::prepareTick( const Dimension* zDimension )
+void Entity::prepareTick(const Dimension* zDimension)
 {
-    Vec3<float> headPosition = location + faceOffset;
-    int px = (int)floor( headPosition.x );
-    int py = (int)floor( headPosition.y );
-    int pz = (int)floor( headPosition.z );
-    faceDir.normalize();
-    Direction dir = BOTTOM;
-    while( true )
-    {
-        if( getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py, pz }, zDimension->getDimensionId() ) )->isInteractable() )
-        {
-            if( !target || !target->isBlock( { px, py, pz }, dir ) )
-            {
-                delete target;
-                target = new ActionTarget( { px, py, pz }, dir );
-                needUpdate = 1;
-            }
-            break;
-        }
-        // collision to neighbor of current block
-        if( faceDir.x > 0 )
-        {
-            float xt = ((float)px + 1.f - headPosition.x) / faceDir.x;
-            Vec3<float> tmp = headPosition + faceDir * xt;
-            if( xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                dir = WEST;
-                px++;
-                continue;
-            }
-        }
-        if( faceDir.x < 0 )
-        {
-            float xt = ((float)px - headPosition.x) / faceDir.x;
-            Vec3<float> tmp = headPosition + faceDir * xt;
-            if( xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                dir = EAST;
-                px--;
-                continue;
-            }
-        }
-        if( faceDir.y > 0 )
-        {
-            float yt = ((float)py + 1.f - headPosition.y) / faceDir.y;
-            Vec3<float> tmp = headPosition + faceDir * yt;
-            if( yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                dir = NORTH;
-                py++;
-                continue;
-            }
-        }
-        if( faceDir.y < 0 )
-        {
-            float yt = ((float)py - headPosition.y) / faceDir.y;
-            Vec3<float> tmp = headPosition + faceDir * yt;
-            if( yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                dir = SOUTH;
-                py--;
-                continue;
-            }
-        }
-        if( faceDir.z > 0 )
-        {
-            float zt = ((float)pz + 1.f - headPosition.z) / faceDir.z;
-            Vec3<float> tmp = headPosition + faceDir * zt;
-            if( zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f )
-            {
-                dir = BOTTOM;
-                pz++;
-                continue;
-            }
-        }
-        if( faceDir.z < 0 )
-        {
-            float zt = ((float)pz - headPosition.z) / faceDir.z;
-            Vec3<float> tmp = headPosition + faceDir * zt;
-            if( zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1 )
-            {
-                dir = TOP;
-                pz--;
-                continue;
-            }
-        }
-        if( target )
-        {
-            delete target;
-            target = 0;
-            needUpdate = 1;
-        }
-        break;
-    }
+	Vec3<float> headPosition = location + faceOffset;
+	int px = (int)floor(headPosition.x);
+	int py = (int)floor(headPosition.y);
+	int pz = (int)floor(headPosition.z);
+	faceDir.normalize();
+	Direction dir = BOTTOM;
+	while (true)
+	{
+		if (getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz }, zDimension->getDimensionId()))->isInteractable())
+		{
+			if (!target || !target->isBlock({ px, py, pz }, dir))
+			{
+				delete target;
+				target = new ActionTarget({ px, py, pz }, dir);
+				needUpdate = 1;
+			}
+			break;
+		}
+		// collision to neighbor of current block
+		if (faceDir.x > 0)
+		{
+			float xt = ((float)px + 1.f - headPosition.x) / faceDir.x;
+			Vec3<float> tmp = headPosition + faceDir * xt;
+			if (xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				dir = WEST;
+				px++;
+				continue;
+			}
+		}
+		if (faceDir.x < 0)
+		{
+			float xt = ((float)px - headPosition.x) / faceDir.x;
+			Vec3<float> tmp = headPosition + faceDir * xt;
+			if (xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				dir = EAST;
+				px--;
+				continue;
+			}
+		}
+		if (faceDir.y > 0)
+		{
+			float yt = ((float)py + 1.f - headPosition.y) / faceDir.y;
+			Vec3<float> tmp = headPosition + faceDir * yt;
+			if (yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				dir = NORTH;
+				py++;
+				continue;
+			}
+		}
+		if (faceDir.y < 0)
+		{
+			float yt = ((float)py - headPosition.y) / faceDir.y;
+			Vec3<float> tmp = headPosition + faceDir * yt;
+			if (yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				dir = SOUTH;
+				py--;
+				continue;
+			}
+		}
+		if (faceDir.z > 0)
+		{
+			float zt = ((float)pz + 1.f - headPosition.z) / faceDir.z;
+			Vec3<float> tmp = headPosition + faceDir * zt;
+			if (zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f)
+			{
+				dir = BOTTOM;
+				pz++;
+				continue;
+			}
+		}
+		if (faceDir.z < 0)
+		{
+			float zt = ((float)pz - headPosition.z) / faceDir.z;
+			Vec3<float> tmp = headPosition + faceDir * zt;
+			if (zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1)
+			{
+				dir = TOP;
+				pz--;
+				continue;
+			}
+		}
+		if (target)
+		{
+			delete target;
+			target = 0;
+			needUpdate = 1;
+		}
+		break;
+	}
 }
 
-void Entity::tick( const Dimension* zDimension )
+void Entity::tick(const Dimension* zDimension)
 {
-    Vec3<float> oldPos = location;
-    // current block cooredinates
-    int px = (int)floor( location.x );
-    int py = (int)floor( location.y );
-    int pz = (int)floor( location.z );
-    // falling down
-    speed.z -= (zDimension->getGravity() * gravityMultiplier) / 30.f;
-    // movement in current tick
-    Vec3<float> frameSpeed = speed / 30.f;
-    // loop through all collided blocks
-    bool needCollisionCheck = 1;
-    while( needCollisionCheck )
-    {
-        needCollisionCheck = 0;
-        // collision to neighbor of current block
-        if( speed.x > 0 )
-        {
-            float xt = ((float)px + 1.f - oldPos.x) / frameSpeed.x;
-            Vec3<float> tmp = oldPos + frameSpeed * xt;
-            if( xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px + 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
-                {
-                    frameSpeed.x = frameSpeed.x * (xt - 0.1f);
-                    speed.x = 0;
-                }
-                else
-                    px++;
-                needCollisionCheck = 1;
-                continue;
-            }
-        }
-        if( speed.x < 0 )
-        {
-            float xt = ((float)px - oldPos.x) / frameSpeed.x;
-            Vec3<float> tmp = oldPos + frameSpeed * xt;
-            if( xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px - 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
-                {
-                    frameSpeed.x = frameSpeed.x * (xt - 0.1f);
-                    speed.x = 0;
-                }
-                else
-                    px--;
-                needCollisionCheck = 1;
-                continue;
-            }
-        }
-        if( speed.y > 0 )
-        {
-            float yt = ((float)py + 1.f - oldPos.y) / frameSpeed.y;
-            Vec3<float> tmp = oldPos + frameSpeed * yt;
-            if( yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py + 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
-                {
-                    frameSpeed.y = frameSpeed.y * (yt - 0.1f);
-                    speed.y = 0;
-                }
-                else
-                    py++;
-                needCollisionCheck = 1;
-                continue;
-            }
-        }
-        if( speed.y < 0 )
-        {
-            float yt = ((float)py - oldPos.y) / frameSpeed.y;
-            Vec3<float> tmp = oldPos + frameSpeed * yt;
-            if( yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
-            {
-                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py - 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
-                {
-                    frameSpeed.y = frameSpeed.y * (yt - 0.1f);
-                    speed.y = 0;
-                }
-                else
-                    py--;
-                needCollisionCheck = 1;
-                continue;
-            }
-        }
-        if( speed.z > 0 )
-        {
-            float zt = ((float)pz + 1.f - oldPos.z) / frameSpeed.z;
-            Vec3<float> tmp = oldPos + frameSpeed * zt;
-            if( zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f )
-            {
-                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py, pz + 1 }, zDimension->getDimensionId() ) )->isPassable() )
-                {
-                    frameSpeed.z = frameSpeed.z * (zt - 0.1f);
-                    speed.z = 0;
-                }
-                else
-                    pz++;
-                needCollisionCheck = 1;
-                continue;
-            }
-        }
-        if( speed.z < 0 )
-        {
-            float zt = ((float)pz - oldPos.z) / frameSpeed.z;
-            Vec3<float> tmp = oldPos + frameSpeed * zt;
-            if( zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1 )
-            {
-                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py, pz - 1 }, zDimension->getDimensionId() ) )->isPassable() )
-                {
-                    frameSpeed.z = frameSpeed.z * (zt - 0.1f);
-                    onFall( speed.z );
-                    speed.z = 0;
-                }
-                else
-                    pz--;
-                needCollisionCheck = 1;
-                continue;
-            }
-        }
-    }
-    location += frameSpeed;
-    if( oldPos != location || needUpdate )
-    {
-        needUpdate = 0;
-        Game::INSTANCE->requestWorldUpdate( new EntityChangedUpdate( id, location, currentDimensionId ) );
-    }
+	Vec3<float> oldPos = location;
+	// current block cooredinates
+	int px = (int)floor(location.x);
+	int py = (int)floor(location.y);
+	int pz = (int)floor(location.z);
+	// falling down
+	speed.z -= (zDimension->getGravity() * gravityMultiplier) / 30.f;
+	// movement in current tick
+	Vec3<float> frameSpeed = speed / 30.f;
+	// loop through all collided blocks
+	bool needCollisionCheck = 1;
+	while (needCollisionCheck)
+	{
+		needCollisionCheck = 0;
+		// collision to neighbor of current block
+		if (speed.x > 0)
+		{
+			float xt = ((float)px + 1.f - oldPos.x) / frameSpeed.x;
+			Vec3<float> tmp = oldPos + frameSpeed * xt;
+			if (xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px + 1, py, pz }, zDimension->getDimensionId()))->isPassable())
+				{
+					frameSpeed.x = frameSpeed.x * (xt - 0.1f);
+					speed.x = 0;
+				}
+				else
+					px++;
+				needCollisionCheck = 1;
+				continue;
+			}
+		}
+		if (speed.x < 0)
+		{
+			float xt = ((float)px - oldPos.x) / frameSpeed.x;
+			Vec3<float> tmp = oldPos + frameSpeed * xt;
+			if (xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px - 1, py, pz }, zDimension->getDimensionId()))->isPassable())
+				{
+					frameSpeed.x = frameSpeed.x * (xt - 0.1f);
+					speed.x = 0;
+				}
+				else
+					px--;
+				needCollisionCheck = 1;
+				continue;
+			}
+		}
+		if (speed.y > 0)
+		{
+			float yt = ((float)py + 1.f - oldPos.y) / frameSpeed.y;
+			Vec3<float> tmp = oldPos + frameSpeed * yt;
+			if (yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py + 1, pz }, zDimension->getDimensionId()))->isPassable())
+				{
+					frameSpeed.y = frameSpeed.y * (yt - 0.1f);
+					speed.y = 0;
+				}
+				else
+					py++;
+				needCollisionCheck = 1;
+				continue;
+			}
+		}
+		if (speed.y < 0)
+		{
+			float yt = ((float)py - oldPos.y) / frameSpeed.y;
+			Vec3<float> tmp = oldPos + frameSpeed * yt;
+			if (yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
+			{
+				if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py - 1, pz }, zDimension->getDimensionId()))->isPassable())
+				{
+					frameSpeed.y = frameSpeed.y * (yt - 0.1f);
+					speed.y = 0;
+				}
+				else
+					py--;
+				needCollisionCheck = 1;
+				continue;
+			}
+		}
+		if (speed.z > 0)
+		{
+			float zt = ((float)pz + 1.f - oldPos.z) / frameSpeed.z;
+			Vec3<float> tmp = oldPos + frameSpeed * zt;
+			if (zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f)
+			{
+				if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz + 1 }, zDimension->getDimensionId()))->isPassable())
+				{
+					frameSpeed.z = frameSpeed.z * (zt - 0.1f);
+					speed.z = 0;
+				}
+				else
+					pz++;
+				needCollisionCheck = 1;
+				continue;
+			}
+		}
+		if (speed.z < 0)
+		{
+			float zt = ((float)pz - oldPos.z) / frameSpeed.z;
+			Vec3<float> tmp = oldPos + frameSpeed * zt;
+			if (zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1)
+			{
+				if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz - 1 }, zDimension->getDimensionId()))->isPassable())
+				{
+					frameSpeed.z = frameSpeed.z * (zt - 0.1f);
+					onFall(speed.z);
+					speed.z = 0;
+				}
+				else
+					pz--;
+				needCollisionCheck = 1;
+				continue;
+			}
+		}
+	}
+	location += frameSpeed;
+	if (oldPos != location || needUpdate)
+	{
+		needUpdate = 0;
+		Game::INSTANCE->requestWorldUpdate(new EntityChangedUpdate(id, location, currentDimensionId));
+	}
 }
 
-void Entity::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
+void Entity::api(Framework::StreamReader* zRequest, NetworkResponse* zResponse)
 {
-    // TODO: answer api requests
+	char type;
+	zRequest->lese(&type, 1);
+	switch (type)
+	{
+	case 100: // request inventory
+	{
+		char idLen;
+		zRequest->lese(&idLen, 1);
+		char* id = new char[idLen + 1];
+		zRequest->lese(id, idLen);
+		id[(int)idLen] = 0;
+		zResponse->adressGui(id);
+		delete[] id;
+		char filterLen;
+		zRequest->lese(&filterLen, 1);
+		char* filter = new char[filterLen + 1];
+		zRequest->lese(filter, filterLen);
+		filter[(int)filterLen] = 0;
+		InMemoryBuffer buffer;
+		int count = 0;
+		for (ItemSlot* slot : *this)
+		{
+			if (slot->getName().istGleich(filter))
+			{
+				count++;
+				int id = slot->getId();
+				buffer.schreibe((char*)&id, 4);
+				int itemCount = slot->getNumberOfItems();
+				buffer.schreibe((char*)&itemCount, 4);
+				if (itemCount > 0)
+				{
+					float f = slot->zStack()->zItem()->getDamage();
+					buffer.schreibe((char*)&f, 4);
+					f = slot->zStack()->zItem()->getMaxDamage();
+					buffer.schreibe((char*)&f, 4);
+					f = slot->zStack()->zItem()->getDurability();
+					buffer.schreibe((char*)&f, 4);
+					f = slot->zStack()->zItem()->getMaxDurability();
+					buffer.schreibe((char*)&f, 4);
+					int id = slot->zStack()->zItem()->zItemType()->getId();
+					buffer.schreibe((char*)&id, 4);
+				}
+			}
+		}
+		delete[] filter;
+		char* msg = new char[5 + buffer.getSize()];
+		msg[0] = 0;
+		*(int*)(msg + 1) = count;
+		buffer.lese(msg + 5, (int)buffer.getSize());
+		zResponse->setMessage(msg, 5 + (int)buffer.getSize(), 1);
+		break;
+	}
+	}
 }
 
-void Entity::onFall( float collisionSpeed )
+void Entity::onFall(float collisionSpeed)
 {
-    if( collisionSpeed > 5 )
-    {
-        // TODO: take damage
-    }
+	if (collisionSpeed > 5)
+	{
+		// TODO: take damage
+	}
 }
 
-void Entity::setPosition( Framework::Vec3<float> pos )
+void Entity::setPosition(Framework::Vec3<float> pos)
 {
-    location = pos;
+	location = pos;
 }
 
 float Entity::getMaxHP() const
 {
-    return maxHP;
+	return maxHP;
 }
 
 float Entity::getCurrentHP() const
 {
-    return currentHP;
+	return currentHP;
 }
 
 float Entity::getStamina() const
 {
-    return stamina;
+	return stamina;
 }
 
 float Entity::getMaxStamina() const
 {
-    return maxStamina;
+	return maxStamina;
 }
 
 float Entity::getHunger() const
 {
-    return hunger;
+	return hunger;
 }
 
 float Entity::getMaxHunger() const
 {
-    return maxHunger;
+	return maxHunger;
 }
 
 float Entity::getThirst() const
 {
-    return thirst;
+	return thirst;
 }
 
 float Entity::getMaxThirst() const
 {
-    return maxThirst;
+	return maxThirst;
 }
 
 Framework::Vec3<float> Entity::getSpeed() const
 {
-    return speed;
+	return speed;
 }
 
 Framework::Vec3<float> Entity::getFaceDir() const
 {
-    return faceDir;
+	return faceDir;
 }
 
 Framework::Vec3<float> Entity::getPosition() const
 {
-    return location;
+	return location;
 }
 
 float Entity::getGravityMultiplier() const
 {
-    return gravityMultiplier;
+	return gravityMultiplier;
 }
 
 int Entity::getCurrentDimensionId() const
 {
-    return currentDimensionId;
+	return currentDimensionId;
 }
 
 bool Entity::isRemoved() const
 {
-    return removed;
+	return removed;
 }
 
 const EntityType* Entity::zType() const
 {
-    return zEntityType;
+	return zEntityType;
 }
 
 const ActionTarget* Entity::zTarget() const
 {
-    return target;
+	return target;
 }
 
 int Entity::getId() const
 {
-    return id;
+	return id;
 }

+ 0 - 2
FactoryCraft/FactoryCraft.vcxproj

@@ -96,7 +96,6 @@
     <ClInclude Include="AddEntityUpdate.h" />
     <ClInclude Include="Area.h" />
     <ClInclude Include="BasicBlocks.h" />
-    <ClInclude Include="BasicInterpolator.h" />
     <ClInclude Include="BiomGenerator.h" />
     <ClInclude Include="Block.h" />
     <ClInclude Include="BlockChangedUpdate.h" />
@@ -155,7 +154,6 @@
     <ClCompile Include="AddEntityUpdate.cpp" />
     <ClCompile Include="Area.cpp" />
     <ClCompile Include="BasicBlock.cpp" />
-    <ClCompile Include="BasicInterpolator.cpp" />
     <ClCompile Include="BiomGenerator.cpp" />
     <ClCompile Include="Block.cpp" />
     <ClCompile Include="BlockChangedUpdate.cpp" />

+ 0 - 9
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -31,9 +31,6 @@
     <Filter Include="world\generator\dimensions">
       <UniqueIdentifier>{b04d9ff5-ad58-41e2-8e72-8de835e09c99}</UniqueIdentifier>
     </Filter>
-    <Filter Include="world\generator\interpolators">
-      <UniqueIdentifier>{0a55e1c5-132f-4a40-bbfe-9bc9f100e4fa}</UniqueIdentifier>
-    </Filter>
     <Filter Include="world\ticking">
       <UniqueIdentifier>{03a72d46-51b8-4f26-b04a-f5f4d4f5af6e}</UniqueIdentifier>
     </Filter>
@@ -135,9 +132,6 @@
     <ClInclude Include="OverworldDimension.h">
       <Filter>world\generator\dimensions</Filter>
     </ClInclude>
-    <ClInclude Include="BasicInterpolator.h">
-      <Filter>world\generator\interpolators</Filter>
-    </ClInclude>
     <ClInclude Include="Constants.h">
       <Filter>game</Filter>
     </ClInclude>
@@ -275,9 +269,6 @@
     <ClCompile Include="GrasslandBiom.cpp">
       <Filter>world\generator\bioms</Filter>
     </ClCompile>
-    <ClCompile Include="BasicInterpolator.cpp">
-      <Filter>world\generator\interpolators</Filter>
-    </ClCompile>
     <ClCompile Include="BiomGenerator.cpp">
       <Filter>world\generator</Filter>
     </ClCompile>

+ 464 - 447
FactoryCraft/Game.cpp

@@ -10,535 +10,552 @@
 
 using namespace Framework;
 
-GameClient::GameClient( Player* zPlayer, FCKlient* client )
-    : ReferenceCounter(),
-    zPlayer( zPlayer ),
-    client( client ),
-    viewDistance( DEFAULT_VIEW_DISTANCE ),
-    first( 1 ),
-    online( 1 ),
-    finished( 0 )
-{
-    new AsynchronCall( "Game Client", [this]() {
-        while( online )
-        {
-            other.lock();
-            if( updateQueue.hat( 0 ) )
-            {
-                WorldUpdate* update = updateQueue.get( 0 );
-                updateQueue.remove( 0 );
-                other.unlock();
-                background.lock();
-                this->client->zBackgroundWriter()->schreibe( (char*)&Message::WORLD_UPDATE, 1 );
-                update->writeAndCheck( this->client->zBackgroundWriter() );
-                background.unlock();
-                update->release();
-            }
-            else
-            {
-                other.unlock();
-                updateSync.wait();
-            }
-        }
-        finished = 1;
-    } );
+GameClient::GameClient(Player* zPlayer, FCKlient* client)
+	: ReferenceCounter(),
+	zPlayer(zPlayer),
+	client(client),
+	viewDistance(DEFAULT_VIEW_DISTANCE),
+	first(1),
+	online(1),
+	finished(0)
+{
+	new AsynchronCall("Game Client", [this]()
+		{
+			while (online)
+			{
+				other.lock();
+				if (updateQueue.hat(0))
+				{
+					WorldUpdate* update = updateQueue.get(0);
+					updateQueue.remove(0);
+					other.unlock();
+					background.lock();
+					this->client->zBackgroundWriter()->schreibe((char*)&Message::WORLD_UPDATE, 1);
+					update->writeAndCheck(this->client->zBackgroundWriter());
+					background.unlock();
+					update->release();
+				}
+				else
+				{
+					other.unlock();
+					updateSync.wait();
+				}
+			}
+			finished = 1;
+		});
 }
 
 GameClient::~GameClient()
 {
-    online = 0;
-    updateSync.notify();
-    while( !finished )
-        Sleep( 100 );
-    client->release();
-}
-
-void GameClient::sendWorldUpdate( WorldUpdate* update )
-{
-    bool add = 0;
-    if( zPlayer->getCurrentDimensionId() == update->getAffectedDimension() )
-    {
-        auto pos = (Vec3<int>)zPlayer->getPosition();
-        int dist = update->distanceTo( pos.x, pos.y );
-        if( dist < viewDistance * CHUNK_SIZE )
-        {
-            other.lock();
-            int index = 0;
-            for( auto update2 : updateQueue )
-            {
-                int dist2 = update2->distanceTo( pos.x, pos.y );
-                if( dist2 > dist )
-                    break;
-                index++;
-            }
-            if( update->getType() == AddChunkUpdateType::ID )
-                ((AddChunkUpdate*)update)->zChunk()->addView( zPlayer );
-            updateQueue.add( update, index );
-            other.unlock();
-            updateSync.notify();
-            add = 1;
-        }
-    }
-    if( !add )
-        update->release();
+	online = 0;
+	updateSync.notify();
+	while (!finished)
+		Sleep(100);
+	client->release();
+}
+
+void GameClient::sendWorldUpdate(WorldUpdate* update)
+{
+	bool add = 0;
+	if (zPlayer->getCurrentDimensionId() == update->getAffectedDimension())
+	{
+		auto pos = (Vec3<int>)zPlayer->getPosition();
+		int dist = update->distanceTo(pos.x, pos.y);
+		if (dist < viewDistance * CHUNK_SIZE)
+		{
+			other.lock();
+			int index = 0;
+			for (auto update2 : updateQueue)
+			{
+				int dist2 = update2->distanceTo(pos.x, pos.y);
+				if (dist2 > dist)
+					break;
+				index++;
+			}
+			if (update->getType() == AddChunkUpdateType::ID)
+				((AddChunkUpdate*)update)->zChunk()->addView(zPlayer);
+			updateQueue.add(update, index);
+			other.unlock();
+			updateSync.notify();
+			add = 1;
+		}
+	}
+	if (!add)
+		update->release();
 }
 
 void GameClient::reply()
 {
-    other.lock();
-    for( auto req : requests )
-        Game::INSTANCE->api( req, this );
-    requests.leeren();
-    other.unlock();
-    int x = (int)floor( zPlayer->getPosition().x );
-    int y = (int)floor( zPlayer->getPosition().y );
-    int d = zPlayer->getCurrentDimensionId();
-    // send world to client
-    if( first )
-    {
-        foreground.lock();
-        int id = zPlayer->getId();
-        client->zForegroundWriter()->schreibe( (char*)&Message::POSITION_UPDATE, 1 );
-        client->zForegroundWriter()->schreibe( (char*)&id, 4 );
-        foreground.unlock();
-        first = 0;
-        Dimension* dim = Game::INSTANCE->zDimension( d );
-        if( dim )
-        {
-            for( int xP = x - CHUNK_SIZE * viewDistance; xP <= x + CHUNK_SIZE * viewDistance; xP += CHUNK_SIZE )
-            {
-                for( int yP = y - CHUNK_SIZE * viewDistance; yP <= y + CHUNK_SIZE * viewDistance; yP += CHUNK_SIZE )
-                {
-                    Chunk* chunk = dim->zChunk( Game::INSTANCE->getChunkCenter( xP, yP ) );
-                    if( chunk )
-                        sendWorldUpdate( new AddChunkUpdate( dynamic_cast<Chunk*>(chunk->getThis()) ) );
-                }
-            }
-        }
-        Game::INSTANCE->requestArea( { x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance, x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance, d } );
-    }
-    else
-    {
-        Punkt lastMin = Game::INSTANCE->getChunkCenter( (int)floor( lastPos.x ) - CHUNK_SIZE * viewDistance, (int)floor( lastPos.y ) - CHUNK_SIZE * viewDistance );
-        Punkt curMin = Game::INSTANCE->getChunkCenter( x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance );
-        Punkt lastMax = Game::INSTANCE->getChunkCenter( (int)floor( lastPos.x ) + CHUNK_SIZE * viewDistance, (int)floor( lastPos.y ) + CHUNK_SIZE * viewDistance );
-        Punkt curMax = Game::INSTANCE->getChunkCenter( x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance );
-        Dimension* dim = Game::INSTANCE->zDimension( d );
-        if( dim )
-        {
-            for( int xP = curMin.x; xP <= curMax.x; xP += CHUNK_SIZE )
-            {
-                for( int yP = curMin.y; yP <= curMax.y; yP += CHUNK_SIZE )
-                {
-                    if( xP < lastMin.x || xP > lastMax.x || yP < lastMin.y || yP > lastMax.y )
-                    {
-                        Chunk* chunk = dim->zChunk( Game::INSTANCE->getChunkCenter( xP, yP ) );
-                        if( chunk )
-                            sendWorldUpdate( new AddChunkUpdate( dynamic_cast<Chunk*>(chunk->getThis()) ) );
-                        else
-                            Game::INSTANCE->requestArea( Game::INSTANCE->getChunckArea( Game::INSTANCE->getChunkCenter( xP, yP ) ) );
-                    }
-                }
-            }
-            for( int xP = lastMin.x; xP <= lastMax.x; xP += CHUNK_SIZE )
-            {
-                for( int yP = lastMin.y; yP <= lastMax.y; yP += CHUNK_SIZE )
-                {
-                    if( xP < curMin.x || xP > curMax.x || yP < curMin.y || yP > curMax.y )
-                    {
-                        Chunk* chunk = dim->zChunk( Game::INSTANCE->getChunkCenter( xP, yP ) );
-                        if( chunk )
-                            chunk->removeView( zPlayer );
-                    }
-                }
-            }
-        }
-    }
-    lastPos = zPlayer->getPosition();
+	other.lock();
+	for (auto req : requests)
+		Game::INSTANCE->api(req, this);
+	requests.leeren();
+	other.unlock();
+	int x = (int)floor(zPlayer->getPosition().x);
+	int y = (int)floor(zPlayer->getPosition().y);
+	int d = zPlayer->getCurrentDimensionId();
+	// send world to client
+	if (first)
+	{
+		foreground.lock();
+		int id = zPlayer->getId();
+		client->zForegroundWriter()->schreibe((char*)&Message::POSITION_UPDATE, 1);
+		client->zForegroundWriter()->schreibe((char*)&id, 4);
+		foreground.unlock();
+		first = 0;
+		Dimension* dim = Game::INSTANCE->zDimension(d);
+		if (dim)
+		{
+			for (int xP = x - CHUNK_SIZE * viewDistance; xP <= x + CHUNK_SIZE * viewDistance; xP += CHUNK_SIZE)
+			{
+				for (int yP = y - CHUNK_SIZE * viewDistance; yP <= y + CHUNK_SIZE * viewDistance; yP += CHUNK_SIZE)
+				{
+					Chunk* chunk = dim->zChunk(Game::INSTANCE->getChunkCenter(xP, yP));
+					if (chunk)
+						sendWorldUpdate(new AddChunkUpdate(dynamic_cast<Chunk*>(chunk->getThis())));
+				}
+			}
+		}
+		Game::INSTANCE->requestArea({ x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance, x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance, d });
+	}
+	else
+	{
+		Punkt lastMin = Game::INSTANCE->getChunkCenter((int)floor(lastPos.x) - CHUNK_SIZE * viewDistance, (int)floor(lastPos.y) - CHUNK_SIZE * viewDistance);
+		Punkt curMin = Game::INSTANCE->getChunkCenter(x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance);
+		Punkt lastMax = Game::INSTANCE->getChunkCenter((int)floor(lastPos.x) + CHUNK_SIZE * viewDistance, (int)floor(lastPos.y) + CHUNK_SIZE * viewDistance);
+		Punkt curMax = Game::INSTANCE->getChunkCenter(x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance);
+		Dimension* dim = Game::INSTANCE->zDimension(d);
+		if (dim)
+		{
+			for (int xP = curMin.x; xP <= curMax.x; xP += CHUNK_SIZE)
+			{
+				for (int yP = curMin.y; yP <= curMax.y; yP += CHUNK_SIZE)
+				{
+					if (xP < lastMin.x || xP > lastMax.x || yP < lastMin.y || yP > lastMax.y)
+					{
+						Chunk* chunk = dim->zChunk(Game::INSTANCE->getChunkCenter(xP, yP));
+						if (chunk)
+							sendWorldUpdate(new AddChunkUpdate(dynamic_cast<Chunk*>(chunk->getThis())));
+						else
+							Game::INSTANCE->requestArea(Game::INSTANCE->getChunckArea(Game::INSTANCE->getChunkCenter(xP, yP)));
+					}
+				}
+			}
+			for (int xP = lastMin.x; xP <= lastMax.x; xP += CHUNK_SIZE)
+			{
+				for (int yP = lastMin.y; yP <= lastMax.y; yP += CHUNK_SIZE)
+				{
+					if (xP < curMin.x || xP > curMax.x || yP < curMin.y || yP > curMax.y)
+					{
+						Chunk* chunk = dim->zChunk(Game::INSTANCE->getChunkCenter(xP, yP));
+						if (chunk)
+							chunk->removeView(zPlayer);
+					}
+				}
+			}
+		}
+	}
+	lastPos = zPlayer->getPosition();
 }
 
 void GameClient::logout()
 {
-    online = 0;
+	online = 0;
 }
 
-void GameClient::addMessage( StreamReader* reader )
+void GameClient::addMessage(StreamReader* reader)
 {
-    short len = 0;
-    reader->lese( (char*)&len, 2 );
-    InMemoryBuffer* buffer = new InMemoryBuffer();
-    char* tmp = new char[ len ];
-    reader->lese( tmp, len );
-    buffer->schreibe( tmp, len );
-    delete[]tmp;
-    other.lock();
-    requests.add( buffer );
-    other.unlock();
+	short len = 0;
+	reader->lese((char*)&len, 2);
+	InMemoryBuffer* buffer = new InMemoryBuffer();
+	char* tmp = new char[len];
+	reader->lese(tmp, len);
+	buffer->schreibe(tmp, len);
+	delete[]tmp;
+	other.lock();
+	requests.add(buffer);
+	other.unlock();
 }
 
 bool GameClient::isOnline() const
 {
-    return online;
+	return online;
 }
 
-void GameClient::sendResponse( NetworkResponse* zResponse )
+void GameClient::sendResponse(NetworkResponse* zResponse)
 {
-    if( zResponse->isAreaAffected( { lastPos.x - (float)CHUNK_SIZE * (float)viewDistance, lastPos.y - (float)CHUNK_SIZE * (float)viewDistance, 0.f }, { lastPos.x + (float)CHUNK_SIZE * (float)viewDistance, lastPos.y + (float)CHUNK_SIZE * (float)viewDistance, (float)WORLD_HEIGHT } ) )
-    {
-        if( zResponse->isUseBackground() )
-        {
-            background.unlock();
-            client->zBackgroundWriter()->schreibe( (char*)&Message::API_MESSAGE, 1 );
-            zResponse->writeTo( client->zBackgroundWriter() );
-            background.unlock();
-        }
-        else
-        {
-            foreground.unlock();
-            client->zForegroundWriter()->schreibe( (char*)&Message::API_MESSAGE, 1 );
-            zResponse->writeTo( client->zForegroundWriter() );
-            foreground.unlock();
-        }
-    }
+	if (zResponse->isAreaAffected({ lastPos.x - (float)CHUNK_SIZE * (float)viewDistance, lastPos.y - (float)CHUNK_SIZE * (float)viewDistance, 0.f }, { lastPos.x + (float)CHUNK_SIZE * (float)viewDistance, lastPos.y + (float)CHUNK_SIZE * (float)viewDistance, (float)WORLD_HEIGHT }))
+	{
+		if (zResponse->isUseBackground())
+		{
+			background.unlock();
+			client->zBackgroundWriter()->schreibe((char*)&Message::API_MESSAGE, 1);
+			zResponse->writeTo(client->zBackgroundWriter());
+			background.unlock();
+		}
+		else
+		{
+			foreground.unlock();
+			client->zForegroundWriter()->schreibe((char*)&Message::API_MESSAGE, 1);
+			zResponse->writeTo(client->zForegroundWriter());
+			foreground.unlock();
+		}
+	}
 }
 
 Player* GameClient::zEntity() const
 {
-    return zPlayer;
-}
-
-
-Game::Game( Framework::Text name, Framework::Text worldsDir )
-    : Thread(),
-    name( name ),
-    dimensions( new RCArray<Dimension>() ),
-    updates( new RCArray<WorldUpdate>() ),
-    clients( new RCArray<GameClient>() ),
-    ticker( new TickOrganizer() ),
-    path( (const char*)(worldsDir + "/" + name) ),
-    stop( 0 ),
-    tickId( 0 ),
-    nextEntityId( 0 ),
-    generator( 0 ),
-    loader( 0 )
-{
-    if( !DateiExistiert( worldsDir + "/" + name ) )
-        DateiPfadErstellen( worldsDir + "/" + name + "/" );
-    Datei d;
-    d.setDatei( path + "/eid" );
-    if( d.existiert() )
-    {
-        d.open( Datei::Style::lesen );
-        d.lese( (char*)&nextEntityId, 4 );
-        d.close();
-    }
-    start();
+	return zPlayer;
+}
+
+
+Game::Game(Framework::Text name, Framework::Text worldsDir)
+	: Thread(),
+	name(name),
+	dimensions(new RCArray<Dimension>()),
+	updates(new RCArray<WorldUpdate>()),
+	clients(new RCArray<GameClient>()),
+	ticker(new TickOrganizer()),
+	path((const char*)(worldsDir + "/" + name)),
+	stop(0),
+	tickId(0),
+	nextEntityId(0),
+	generator(0),
+	loader(0)
+{
+	if (!DateiExistiert(worldsDir + "/" + name))
+		DateiPfadErstellen(worldsDir + "/" + name + "/");
+	Datei d;
+	d.setDatei(path + "/eid");
+	if (d.existiert())
+	{
+		d.open(Datei::Style::lesen);
+		d.lese((char*)&nextEntityId, 4);
+		d.close();
+	}
+	start();
 }
 
 Game::~Game()
 {
-    dimensions->release();
-    updates->release();
-    clients->release();
-    generator->release();
-    loader->release();
+	dimensions->release();
+	updates->release();
+	clients->release();
+	generator->release();
+	loader->release();
 }
 
 void Game::initialize()
 {
-    int seed = 0;
-    int index = 0;
-    for( char* n = name; *n; n++ )
-        seed += (int)pow( (float)*n * 31, (float)++index );
-    generator = new WorldGenerator( seed );
-    loader = new WorldLoader();
+	int seed = 0;
+	int index = 0;
+	for (char* n = name; *n; n++)
+		seed += (int)pow((float)*n * 31, (float)++index);
+	generator = new WorldGenerator(seed);
+	loader = new WorldLoader();
+	recipies.loadRecipies("data/recipies");
 }
 
 void Game::thread()
 {
-    ZeitMesser m;
-    while( !stop )
-    {
-        m.messungStart();
-        ticker->nextTick();
-        Array<int> removed;
-        cs.lock();
-        int index = 0;
-        for( auto player : *clients )
-        {
-            if( !player->isOnline() )
-            {
-                Datei pFile;
-                pFile.setDatei( path + "/player/" + player->zEntity()->getName() );
-                if( pFile.open( Datei::Style::schreiben ) )
-                    PlayerEntityType::INSTANCE->saveEntity( player->zEntity(), &pFile );
-                removed.add( index, 0 );
-            }
-            index++;
-        }
-        for( auto i : removed )
-            clients->remove( i );
-        cs.unlock();
-        for( auto dim : *dimensions )
-            dim->tickEntities();
-        cs.lock();
-        while( updates->hat( 0 ) )
-        {
-            WorldUpdate* update = updates->z( 0 );
-            for( auto client : *clients )
-                client->sendWorldUpdate( dynamic_cast<WorldUpdate*>(update->getThis()) );
-            if( !zDimension( update->getAffectedDimension() ) )
-                addDimension( new Dimension( update->getAffectedDimension() ) );
-            update->onUpdate( zDimension( update->getAffectedDimension() ) );
-            updates->remove( 0 );
-        }
-        cs.unlock();
-        for( auto client : *clients )
-            client->reply();
-        cs.lock();
-        for( auto dim : *dimensions )
-            dim->removeOldChunks();
-        cs.unlock();
-        m.messungEnde();
-        double sec = m.getSekunden();
-        if( sec < 0.05 )
-            Sleep( (int)((0.05 - sec) * 1000) );
-        else
-        {
-            std::cout << "WARNING: tick needed " << sec << " seconds. The game will run sower then normal.\n";
-        }
-    }
-    save();
-}
-
-void Game::api( Framework::StreamReader* zRequest, GameClient* zOrigin )
-{
-    char type;
-    zRequest->lese( &type, 1 );
-    NetworkResponse response;
-    switch( type )
-    {
-    case 1: // world
-    {
-        int dimensionId;
-        zRequest->lese( (char*)&dimensionId, 4 );
-        Dimension* dim = zDimension( dimensionId );
-        if( !dim )
-        {
-            dim = new Dimension( dimensionId );
-            addDimension( dim );
-        }
-        dim->api( zRequest, &response );
-        break;
-    }
-    case 2: // player
-        zOrigin->zEntity()->api( zRequest, &response );
-        break;
-    default:
-        std::cout << "received unknown api request in game with type " << (int)type << "\n";
-    }
-    if( !response.isEmpty() )
-    {
-        if( response.isBroadcast() )
-            distributeResponse( &response );
-        else
-            zOrigin->sendResponse( &response );
-    }
-}
-
-void Game::distributeResponse( NetworkResponse* zResponse )
-{
-    for( auto client : *clients )
-        client->sendResponse( zResponse );
-}
-
-bool Game::requestWorldUpdate( WorldUpdate* update )
-{
-    cs.lock();
-    for( WorldUpdate* u : *updates )
-    {
-        if( u->getMaxAffectedPoint().x >= update->getMinAffectedPoint().x && u->getMinAffectedPoint().x <= update->getMaxAffectedPoint().x &&
-            u->getMaxAffectedPoint().y >= update->getMinAffectedPoint().y && u->getMinAffectedPoint().y <= update->getMaxAffectedPoint().y &&
-            u->getMaxAffectedPoint().z >= update->getMinAffectedPoint().z && u->getMinAffectedPoint().z <= update->getMaxAffectedPoint().z && u->getType() == update->getType() )
-        {
-            cs.unlock();
-            update->release();
-            return 0;
-        }
-    }
-    updates->add( update );
-    cs.unlock();
-    return 1;
-}
-
-GameClient* Game::addPlayer( FCKlient* client, Framework::Text name )
-{
-    cs.lock();
-    Datei pFile;
-    pFile.setDatei( path + "/player/" + name );
-    Player* player;
-    bool isNew = 0;
-    if( !pFile.existiert() || !pFile.open( Datei::Style::lesen ) )
-    {
-        player = (Player*)PlayerEntityType::INSTANCE->createEntityAt( Vec3<float>( 0.5, 0.5, 0 ), OverworldDimension::ID );
-        player->setName( name );
-        isNew = 1;
-    }
-    else
-    {
-        player = (Player*)PlayerEntityType::INSTANCE->loadEntity( &pFile );
-        pFile.close();
-    }
-    GameClient* gameClient = new GameClient( player, client );
-    clients->add( gameClient );
-    requestArea( getChunckArea( getChunkCenter( (int)player->getPosition().x, (int)player->getPosition().y ) ) );
-    while( !zDimension( player->getCurrentDimensionId() ) || (isNew && !zDimension( player->getCurrentDimensionId() )->zChunk( getChunkCenter( (int)player->getPosition().x, (int)player->getPosition().y ) )) )
-    {
-        cs.unlock();
-        Sleep( 1000 );
-        cs.lock();
-    }
-    if( isNew )
-    {
-        Either<Block*, int> b = AirBlockBlockType::ID;
-        int h = WORLD_HEIGHT;
-        while( ((b.isA() && (!(Block*)b || ((Block*)b)->isPassable())) || (b.isB() && StaticRegistry<BlockType>::INSTANCE.zElement( b )->zDefault()->isPassable())) && h > 0 )
-            b = zBlockAt( { (int)player->getPosition().x, (int)player->getPosition().y, --h }, player->getCurrentDimensionId() );
-        player->setPosition( { player->getPosition().x, player->getPosition().y, (float)h + 1.f } );
-    }
-    requestWorldUpdate( new AddEntityUpdate( player, player->getCurrentDimensionId() ) );
-    cs.unlock();
-    return dynamic_cast<GameClient*>(gameClient->getThis());
-}
-
-bool Game::isChunkLoaded( int x, int y, int dimension ) const
-{
-    Dimension* dim = zDimension( dimension );
-    return (dim && dim->hasChunck( x, y ));
-}
-
-bool Game::doesChunkExist( int x, int y, int dimension )
-{
-    cs.lock();
-    bool result = isChunkLoaded( x, y, dimension ) || loader->existsChunk( x, y, dimension );
-    if( !result )
-    {
-        for( WorldUpdate* update : *updates )
-        {
-            if( update->getType() == AddChunkUpdateType::ID )
-                result |= ((AddChunkUpdate*)update)->zChunk()->getCenter() == Framework::Punkt( x, y );
-        }
-    }
-    cs.unlock();
-    return result;
-}
-
-Framework::Either<Block*, int> Game::zBlockAt( Framework::Vec3<int> location, int dimension ) const
-{
-    Dimension* dim = zDimension( dimension );
-    if( dim )
-        return dim->zBlock( location );
-    return 0;
+	ZeitMesser m;
+	while (!stop)
+	{
+		m.messungStart();
+		ticker->nextTick();
+		Array<int> removed;
+		cs.lock();
+		int index = 0;
+		for (auto player : *clients)
+		{
+			if (!player->isOnline())
+			{
+				Datei pFile;
+				pFile.setDatei(path + "/player/" + player->zEntity()->getName());
+				if (pFile.open(Datei::Style::schreiben))
+					PlayerEntityType::INSTANCE->saveEntity(player->zEntity(), &pFile);
+				removed.add(index, 0);
+			}
+			index++;
+		}
+		for (auto i : removed)
+			clients->remove(i);
+		cs.unlock();
+		for (auto dim : *dimensions)
+			dim->tickEntities();
+		cs.lock();
+		while (updates->hat(0))
+		{
+			WorldUpdate* update = updates->z(0);
+			for (auto client : *clients)
+				client->sendWorldUpdate(dynamic_cast<WorldUpdate*>(update->getThis()));
+			if (!zDimension(update->getAffectedDimension()))
+				addDimension(new Dimension(update->getAffectedDimension()));
+			update->onUpdate(zDimension(update->getAffectedDimension()));
+			updates->remove(0);
+		}
+		cs.unlock();
+		for (auto client : *clients)
+			client->reply();
+		cs.lock();
+		for (auto dim : *dimensions)
+			dim->removeOldChunks();
+		cs.unlock();
+		m.messungEnde();
+		double sec = m.getSekunden();
+		if (sec < 0.05)
+			Sleep((int)((0.05 - sec) * 1000));
+		else
+		{
+			std::cout << "WARNING: tick needed " << sec << " seconds. The game will run sower then normal.\n";
+		}
+	}
+	save();
+}
+
+void Game::api(Framework::StreamReader* zRequest, GameClient* zOrigin)
+{
+	char type;
+	zRequest->lese(&type, 1);
+	NetworkResponse response;
+	switch (type)
+	{
+	case 1: // world
+	{
+		int dimensionId;
+		zRequest->lese((char*)&dimensionId, 4);
+		Dimension* dim = zDimension(dimensionId);
+		if (!dim)
+		{
+			dim = new Dimension(dimensionId);
+			addDimension(dim);
+		}
+		dim->api(zRequest, &response);
+		break;
+	}
+	case 2: // player
+		zOrigin->zEntity()->playerApi(zRequest, &response);
+		break;
+	case 3: // entity
+	{
+		int id;
+		zRequest->lese((char*)&id, 4);
+		for (Dimension* dim : *dimensions)
+		{
+			Entity* entity = dim->zEntity(id);
+			if (entity)
+			{
+				entity->api(zRequest, &response);
+				break;
+			}
+		}
+		break;
+	}
+	default:
+		std::cout << "received unknown api request in game with type " << (int)type << "\n";
+	}
+	if (!response.isEmpty())
+	{
+		if (response.isBroadcast())
+			distributeResponse(&response);
+		else
+			zOrigin->sendResponse(&response);
+	}
+}
+
+void Game::distributeResponse(NetworkResponse* zResponse)
+{
+	for (auto client : *clients)
+		client->sendResponse(zResponse);
+}
+
+bool Game::requestWorldUpdate(WorldUpdate* update)
+{
+	cs.lock();
+	for (WorldUpdate* u : *updates)
+	{
+		if (u->getMaxAffectedPoint().x >= update->getMinAffectedPoint().x && u->getMinAffectedPoint().x <= update->getMaxAffectedPoint().x &&
+			u->getMaxAffectedPoint().y >= update->getMinAffectedPoint().y && u->getMinAffectedPoint().y <= update->getMaxAffectedPoint().y &&
+			u->getMaxAffectedPoint().z >= update->getMinAffectedPoint().z && u->getMinAffectedPoint().z <= update->getMaxAffectedPoint().z && u->getType() == update->getType())
+		{
+			cs.unlock();
+			update->release();
+			return 0;
+		}
+	}
+	updates->add(update);
+	cs.unlock();
+	return 1;
+}
+
+GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
+{
+	cs.lock();
+	Datei pFile;
+	pFile.setDatei(path + "/player/" + name);
+	Player* player;
+	bool isNew = 0;
+	if (!pFile.existiert() || !pFile.open(Datei::Style::lesen))
+	{
+		player = (Player*)PlayerEntityType::INSTANCE->createEntityAt(Vec3<float>(0.5, 0.5, 0), OverworldDimension::ID);
+		player->setName(name);
+		isNew = 1;
+	}
+	else
+	{
+		player = (Player*)PlayerEntityType::INSTANCE->loadEntity(&pFile);
+		pFile.close();
+	}
+	GameClient* gameClient = new GameClient(player, client);
+	clients->add(gameClient);
+	requestArea(getChunckArea(getChunkCenter((int)player->getPosition().x, (int)player->getPosition().y)));
+	while (!zDimension(player->getCurrentDimensionId()) || (isNew && !zDimension(player->getCurrentDimensionId())->zChunk(getChunkCenter((int)player->getPosition().x, (int)player->getPosition().y))))
+	{
+		cs.unlock();
+		Sleep(1000);
+		cs.lock();
+	}
+	if (isNew)
+	{
+		Either<Block*, int> b = AirBlockBlockType::ID;
+		int h = WORLD_HEIGHT;
+		while (((b.isA() && (!(Block*)b || ((Block*)b)->isPassable())) || (b.isB() && StaticRegistry<BlockType>::INSTANCE.zElement(b)->zDefault()->isPassable())) && h > 0)
+			b = zBlockAt({ (int)player->getPosition().x, (int)player->getPosition().y, --h }, player->getCurrentDimensionId());
+		player->setPosition({ player->getPosition().x, player->getPosition().y, (float)h + 1.f });
+	}
+	requestWorldUpdate(new AddEntityUpdate(player, player->getCurrentDimensionId()));
+	cs.unlock();
+	return dynamic_cast<GameClient*>(gameClient->getThis());
+}
+
+bool Game::isChunkLoaded(int x, int y, int dimension) const
+{
+	Dimension* dim = zDimension(dimension);
+	return (dim && dim->hasChunck(x, y));
+}
+
+bool Game::doesChunkExist(int x, int y, int dimension)
+{
+	cs.lock();
+	bool result = isChunkLoaded(x, y, dimension) || loader->existsChunk(x, y, dimension);
+	if (!result)
+	{
+		for (WorldUpdate* update : *updates)
+		{
+			if (update->getType() == AddChunkUpdateType::ID)
+				result |= ((AddChunkUpdate*)update)->zChunk()->getCenter() == Framework::Punkt(x, y);
+		}
+	}
+	cs.unlock();
+	return result;
+}
+
+Framework::Either<Block*, int> Game::zBlockAt(Framework::Vec3<int> location, int dimension) const
+{
+	Dimension* dim = zDimension(dimension);
+	if (dim)
+		return dim->zBlock(location);
+	return 0;
 }
 
-Block* Game::zRealBlockInstance( Framework::Vec3<int> location, int dimension )
+Block* Game::zRealBlockInstance(Framework::Vec3<int> location, int dimension)
 {
-    Dimension* dim = zDimension( dimension );
-    if( dim )
-        return dim->zRealBlockInstance( location );
-    return 0;
+	Dimension* dim = zDimension(dimension);
+	if (dim)
+		return dim->zRealBlockInstance(location);
+	return 0;
 }
-
-Dimension* Game::zDimension( int id ) const
+
+Dimension* Game::zDimension(int id) const
 {
-    for( auto dim : *dimensions )
-    {
-        if( dim->getDimensionId() == id )
-            return dim;
-    }
-    return 0;
-}
-
-Framework::Punkt Game::getChunkCenter( int x, int y )
-{
-    return Punkt( ((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2, ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2 );
+	for (auto dim : *dimensions)
+	{
+		if (dim->getDimensionId() == id)
+			return dim;
+	}
+	return 0;
+}
+
+Framework::Punkt Game::getChunkCenter(int x, int y)
+{
+	return Punkt(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2, ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2);
 }
 
-Area Game::getChunckArea( Punkt center ) const
+Area Game::getChunckArea(Punkt center) const
 {
-    return { center.x - CHUNK_SIZE / 2, center.y - CHUNK_SIZE / 2, center.x + CHUNK_SIZE / 2 - 1, center.y + CHUNK_SIZE / 2 - 1, 0 };
+	return { center.x - CHUNK_SIZE / 2, center.y - CHUNK_SIZE / 2, center.x + CHUNK_SIZE / 2 - 1, center.y + CHUNK_SIZE / 2 - 1, 0 };
 }
 
 Framework::Text Game::getWorldDirectory() const
 {
-    return path;
+	return path;
 }
 
-void Game::requestArea( Area area )
+void Game::requestArea(Area area)
 {
-    generator->requestGeneration( area );
-    loader->requestLoading( area );
+	generator->requestGeneration(area);
+	loader->requestLoading(area);
 }
 
 void Game::save() const
 {
-    Datei d;
-    d.setDatei( path + "/eid" );
-    d.open( Datei::Style::schreiben );
-    d.schreibe( (char*)&nextEntityId, 4 );
-    d.close();
-    for( auto dim : *dimensions )
-        dim->save( path );
+	Datei d;
+	d.setDatei(path + "/eid");
+	d.open(Datei::Style::schreiben);
+	d.schreibe((char*)&nextEntityId, 4);
+	d.close();
+	for (auto dim : *dimensions)
+		dim->save(path);
 }
 
 void Game::requestStop()
 {
-    stop = 1;
-    warteAufThread( 1000000 );
+	stop = 1;
+	warteAufThread(1000000);
 }
 
-void Game::addDimension( Dimension* d )
+void Game::addDimension(Dimension* d)
 {
-    dimensions->add( d );
+	dimensions->add(d);
 }
 
 int Game::getNextEntityId()
 {
-    cs.lock();
-    int result = nextEntityId++;
-    cs.unlock();
-    return result;
+	cs.lock();
+	int result = nextEntityId++;
+	cs.unlock();
+	return result;
 }
 
 WorldGenerator* Game::zGenerator() const
 {
-    return generator;
+	return generator;
 }
 
 Game* Game::INSTANCE = 0;
 
-void Game::initialize( Framework::Text name, Framework::Text worldsDir )
+void Game::initialize(Framework::Text name, Framework::Text worldsDir)
 {
-    if( !Game::INSTANCE )
-    {
-        Game::INSTANCE = new Game( name, worldsDir );
-        Game::INSTANCE->initialize();
-    }
+	if (!Game::INSTANCE)
+	{
+		Game::INSTANCE = new Game(name, worldsDir);
+		Game::INSTANCE->initialize();
+	}
 }
 
-Entity* Game::zEntity( int id, int dimensionId ) const
+Entity* Game::zEntity(int id, int dimensionId) const
 {
-    Dimension* d = zDimension( dimensionId );
-    if( d )
-        return d->zEntity( id );
-    return 0;
+	Dimension* d = zDimension(dimensionId);
+	if (d)
+		return d->zEntity(id);
+	return 0;
 }
 
-Entity* Game::zNearestEntity( int dimensionId, Framework::Vec3<float> pos, std::function<bool( Entity* )> filter )
+Entity* Game::zNearestEntity(int dimensionId, Framework::Vec3<float> pos, std::function<bool(Entity*)> filter)
 {
-    Dimension* d = zDimension( dimensionId );
-    if( !d )
-        return 0;
-    return d->zNearestEntity( pos, filter );
+	Dimension* d = zDimension(dimensionId);
+	if (!d)
+		return 0;
+	return d->zNearestEntity(pos, filter);
 }
 

+ 70 - 68
FactoryCraft/Game.h

@@ -15,92 +15,94 @@
 #include "TickOrganizer.h"
 #include "Server.h"
 #include "InMemoryBuffer.h"
+#include "RecipieLoader.h"
 
 class FCKlient;
 
 class GameClient : public virtual Framework::ReferenceCounter
 {
 private:
-    Player* zPlayer;
-    FCKlient* client;
-    Critical background;
-    Critical foreground;
-    Critical other;
-    Framework::Synchronizer updateSync;
-    RCArray<InMemoryBuffer> requests;
-    Vec3<float> lastPos;
-    RCArray<WorldUpdate> updateQueue;
-    int viewDistance;
-    bool first;
-    bool online;
-    bool finished;
+	Player* zPlayer;
+	FCKlient* client;
+	Critical background;
+	Critical foreground;
+	Critical other;
+	Framework::Synchronizer updateSync;
+	RCArray<InMemoryBuffer> requests;
+	Vec3<float> lastPos;
+	RCArray<WorldUpdate> updateQueue;
+	int viewDistance;
+	bool first;
+	bool online;
+	bool finished;
 
 public:
-    GameClient( Player* zPlayer, FCKlient* client );
-    ~GameClient();
+	GameClient(Player* zPlayer, FCKlient* client);
+	~GameClient();
 
-    void sendWorldUpdate( WorldUpdate* update );
-    void reply();
-    void logout();
-    void addMessage( StreamReader* reader );
-    bool isOnline() const;
-    void sendResponse( NetworkResponse* zResponse );
-    Player* zEntity() const;
+	void sendWorldUpdate(WorldUpdate* update);
+	void reply();
+	void logout();
+	void addMessage(StreamReader* reader);
+	bool isOnline() const;
+	void sendResponse(NetworkResponse* zResponse);
+	Player* zEntity() const;
 
 private:
-    class Message
-    {
-    public:
-        inline const static unsigned char TERMINATE = 1;
-        inline const static unsigned char WORLD_UPDATE = 2;
-        inline const static unsigned char API_MESSAGE = 3;
-        inline const static unsigned char POSITION_UPDATE = 4;
-    };
+	class Message
+	{
+	public:
+		inline const static unsigned char TERMINATE = 1;
+		inline const static unsigned char WORLD_UPDATE = 2;
+		inline const static unsigned char API_MESSAGE = 3;
+		inline const static unsigned char POSITION_UPDATE = 4;
+	};
 };
 
 class Game : public virtual Framework::Thread
 {
 private:
-    Framework::Text name;
-    Framework::RCArray<Dimension>* dimensions;
-    Framework::RCArray<WorldUpdate>* updates;
-    Framework::RCArray<GameClient>* clients;
-    TickOrganizer* ticker;
-    Framework::Text path;
-    bool stop;
-    __int64 tickId;
-    Critical cs;
-    int nextEntityId;
-    WorldGenerator* generator;
-    WorldLoader* loader;
+	Framework::Text name;
+	Framework::RCArray<Dimension>* dimensions;
+	Framework::RCArray<WorldUpdate>* updates;
+	Framework::RCArray<GameClient>* clients;
+	TickOrganizer* ticker;
+	Framework::Text path;
+	bool stop;
+	__int64 tickId;
+	Critical cs;
+	int nextEntityId;
+	WorldGenerator* generator;
+	WorldLoader* loader;
+	RecipieLoader recipies;
 
-    void thread() override;
+	void thread() override;
 
-    Game( Framework::Text name, Framework::Text worldsDir );
+	Game(Framework::Text name, Framework::Text worldsDir);
 public:
-    ~Game();
-    void initialize();
-    void api( Framework::StreamReader* zRequest, GameClient* zOrigin );
-    void distributeResponse( NetworkResponse* zResponse );
-    bool requestWorldUpdate( WorldUpdate* update );
-    GameClient* addPlayer( FCKlient* client, Framework::Text name );
-    bool doesChunkExist( int x, int y, int dimension );
-    bool isChunkLoaded( int x, int y, int dimension ) const;
-    Framework::Either<Block*, int> zBlockAt( Framework::Vec3<int> location, int dimension ) const;
-    Block* zRealBlockInstance( Framework::Vec3<int> location, int dimension );
-    Dimension* zDimension( int id ) const;
-    static Framework::Punkt getChunkCenter( int x, int y );
-    Area getChunckArea( Punkt center ) const;
-    Framework::Text getWorldDirectory() const;
-    void requestArea( Area area );
-    void save() const;
-    void requestStop();
-    void addDimension( Dimension* d );
-    int getNextEntityId();
-    WorldGenerator* zGenerator() const;
-    Entity* zEntity( int id, int dimensionId ) const;
-    Entity* zNearestEntity( int dimensionId, Framework::Vec3<float> pos, std::function<bool( Entity* )> filter );
+	~Game();
+	void initialize();
+	void api(Framework::StreamReader* zRequest, GameClient* zOrigin);
+	void distributeResponse(NetworkResponse* zResponse);
+	bool requestWorldUpdate(WorldUpdate* update);
+	GameClient* addPlayer(FCKlient* client, Framework::Text name);
+	bool doesChunkExist(int x, int y, int dimension);
+	bool isChunkLoaded(int x, int y, int dimension) const;
+	Framework::Either<Block*, int> zBlockAt(Framework::Vec3<int> location, int dimension) const;
+	Block* zRealBlockInstance(Framework::Vec3<int> location, int dimension);
+	Dimension* zDimension(int id) const;
+	static Framework::Punkt getChunkCenter(int x, int y);
+	Area getChunckArea(Punkt center) const;
+	Framework::Text getWorldDirectory() const;
+	void requestArea(Area area);
+	void save() const;
+	void requestStop();
+	void addDimension(Dimension* d);
+	int getNextEntityId();
+	WorldGenerator* zGenerator() const;
+	Entity* zEntity(int id, int dimensionId) const;
+	Entity* zNearestEntity(int dimensionId, Framework::Vec3<float> pos, std::function<bool(Entity*)> filter);
 
-    static Game* INSTANCE;
-    static void initialize( Framework::Text name, Framework::Text worldsDir );
+	static Game* INSTANCE;
+	static void initialize(Framework::Text name, Framework::Text worldsDir);
 };

+ 451 - 439
FactoryCraft/Inventory.cpp

@@ -5,523 +5,535 @@
 
 using namespace Framework;
 
-InventoryInteraction::InventoryInteraction( Inventory* current, Inventory* other, Direction dir )
-    : current( current ),
-    other( other ),
-    dir( dir )
+InventoryInteraction::InventoryInteraction(Inventory* current, Inventory* other, Direction dir)
+	: current(current),
+	other(other),
+	dir(dir)
 {
-    lock();
+	lock();
 }
 
-InventoryInteraction::InventoryInteraction( const InventoryInteraction& interaction )
-    : InventoryInteraction( interaction.current, interaction.other, interaction.dir )
+InventoryInteraction::InventoryInteraction(const InventoryInteraction& interaction)
+	: InventoryInteraction(interaction.current, interaction.other, interaction.dir)
 {}
 
 InventoryInteraction::~InventoryInteraction()
 {
-    unlock();
+	unlock();
 }
 
 void InventoryInteraction::lock()
 {
-    if( !current || !other ) return;
-    if( current->location.x < other->location.x )
-    {
-        current->cs.lock();
-        other->cs.lock();
-        return;
-    }
-    else if( current->location.x == other->location.x )
-    {
-        if( current->location.y < other->location.y )
-        {
-            current->cs.lock();
-            other->cs.lock();
-            return;
-        }
-        else if( current->location.y == other->location.y )
-        {
-            if( current->location.z < other->location.z )
-            {
-                current->cs.lock();
-                other->cs.lock();
-                return;
-            }
-        }
-    }
-    other->cs.lock();
-    current->cs.lock();
+	if (!current || !other) return;
+	if (current->location.x < other->location.x)
+	{
+		current->cs.lock();
+		other->cs.lock();
+		return;
+	}
+	else if (current->location.x == other->location.x)
+	{
+		if (current->location.y < other->location.y)
+		{
+			current->cs.lock();
+			other->cs.lock();
+			return;
+		}
+		else if (current->location.y == other->location.y)
+		{
+			if (current->location.z < other->location.z)
+			{
+				current->cs.lock();
+				other->cs.lock();
+				return;
+			}
+		}
+	}
+	other->cs.lock();
+	current->cs.lock();
 }
 
 void InventoryInteraction::unlock()
 {
-    if( !current || !other ) return;
-    if( current->location.x < other->location.x )
-    {
-        current->cs.unlock();
-        other->cs.unlock();
-        return;
-    }
-    else if( current->location.x == other->location.x )
-    {
-        if( current->location.y < other->location.y )
-        {
-            current->cs.unlock();
-            other->cs.unlock();
-            return;
-        }
-        else if( current->location.y == other->location.y )
-        {
-            if( current->location.z < other->location.z )
-            {
-                current->cs.unlock();
-                other->cs.unlock();
-                return;
-            }
-        }
-    }
-    other->cs.unlock();
-    current->cs.unlock();
+	if (!current || !other) return;
+	if (current->location.x < other->location.x)
+	{
+		current->cs.unlock();
+		other->cs.unlock();
+		return;
+	}
+	else if (current->location.x == other->location.x)
+	{
+		if (current->location.y < other->location.y)
+		{
+			current->cs.unlock();
+			other->cs.unlock();
+			return;
+		}
+		else if (current->location.y == other->location.y)
+		{
+			if (current->location.z < other->location.z)
+			{
+				current->cs.unlock();
+				other->cs.unlock();
+				return;
+			}
+		}
+	}
+	other->cs.unlock();
+	current->cs.unlock();
 }
 
-void InventoryInteraction::transaction( Inventory* zSource, Inventory* zTarget, ItemFilter* zFilter, Direction sourceView, Direction targetView, int count )
+void InventoryInteraction::transaction(Inventory* zSource, Inventory* zTarget, ItemFilter* zFilter, Direction sourceView, Direction targetView, int count)
 {
-    // TODO: rewrite this such that for each source slot all target slots are looped trough
-    auto sourceSlot = zSource->pullSlotsOrder->begin();
-    for( auto targetSlot = zTarget->pushSlotsOrder->begin(); targetSlot; )
-    {
-        int amount = count;
-        if( !targetSlot->isFull() )
-        {
-            if( targetSlot->zStack() )
-            {
-                Array<ItemSlot*>* zSurceListe = zSource->itemCache->safeGet( targetSlot->zStack()->zItem()->zItemType()->getId(), 0 );
-                if( zSurceListe )
-                {
-                    Array<int> toDelete;
-                    int index = 0;
-                    for( auto sourceSlot = zSurceListe->begin(); sourceSlot; sourceSlot++, index++ )
-                    {
-                        if( zFilter && !zFilter->matchItem( sourceSlot->zStack()->zItem() ) )
-                            continue;
-                        int number = MIN( targetSlot->numberOfAddableItems( sourceSlot->zStack(), sourceView ), count );
-                        int tmp = number;
-                        if( number > 0 && zSource->allowPullStack( sourceSlot, sourceView ) && zTarget->allowPushStack( targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp ) )
-                        {
-                            number = MIN( number, tmp );
-                            ItemStack* stack = sourceSlot->takeItemsOut( number, dir );
-                            if( stack )
-                            {
-                                if( !sourceSlot->zStack() )
-                                    toDelete.add( index, 0 );
-                                targetSlot->addItems( stack, dir );
-                                zSource->updateCache( sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId() );
-                                zSource->afterPullStack( sourceSlot, sourceView, targetSlot->zStack()->zItem(), number );
-                                zTarget->afterPushStack( targetSlot, targetView, targetSlot->zStack()->zItem(), number );
-                                if( stack->getSize() )
-                                    throw stack;
-                                stack->release();
-                                count -= number;
-                                if( count == 0 )
-                                    break;
-                            }
-                        }
-                    }
-                    for( auto indexToDelete = toDelete.begin(); indexToDelete; indexToDelete++ )
-                        zSurceListe->remove( indexToDelete );
-                    if( count == 0 )
-                        return;
-                }
-            }
-            else
-            {
-                while( sourceSlot && (!sourceSlot->zStack() || (zFilter && !zFilter->matchItem( sourceSlot->zStack()->zItem() ))) )
-                    sourceSlot++;
-                if( !sourceSlot )
-                    return;
-                int number = MIN( targetSlot->numberOfAddableItems( sourceSlot->zStack(), sourceView ), count );
-                int tmp = number;
-                if( number > 0 && zSource->allowPullStack( sourceSlot, sourceView ) && zTarget->allowPushStack( targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp ) )
-                {
-                    number = MIN( number, tmp );
-                    if( number > 0 )
-                    {
-                        ItemStack* stack = sourceSlot->takeItemsOut( number, dir );
-                        if( stack )
-                        {
-                            targetSlot->addItems( stack, dir );
-                            zSource->updateCache( sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId() );
-                            zTarget->updateCache( targetSlot, -1 );
-                            zSource->afterPullStack( sourceSlot, sourceView, targetSlot->zStack()->zItem(), number );
-                            zTarget->afterPushStack( targetSlot, targetView, targetSlot->zStack()->zItem(), number );
-                            if( stack->getSize() )
-                                throw stack;
-                            stack->release();
-                            count -= number;
-                            if( count == 0 )
-                                return;
-                        }
-                    }
-                }
-            }
-        }
-        if( amount == count || targetSlot->isFull() )
-            targetSlot++;
-    }
+	// TODO: rewrite this such that for each source slot all target slots are looped trough
+	auto sourceSlot = zSource->pullSlotsOrder->begin();
+	for (auto targetSlot = zTarget->pushSlotsOrder->begin(); targetSlot; )
+	{
+		int amount = count;
+		if (!targetSlot->isFull())
+		{
+			if (targetSlot->zStack())
+			{
+				Array<ItemSlot*>* zSurceListe = zSource->itemCache->safeGet(targetSlot->zStack()->zItem()->zItemType()->getId(), 0);
+				if (zSurceListe)
+				{
+					Array<int> toDelete;
+					int index = 0;
+					for (auto sourceSlot = zSurceListe->begin(); sourceSlot; sourceSlot++, index++)
+					{
+						if (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))
+							continue;
+						int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), sourceView), count);
+						int tmp = number;
+						if (number > 0 && zSource->allowPullStack(sourceSlot, sourceView) && zTarget->allowPushStack(targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp))
+						{
+							number = MIN(number, tmp);
+							ItemStack* stack = sourceSlot->takeItemsOut(number, dir);
+							if (stack)
+							{
+								if (!sourceSlot->zStack())
+									toDelete.add(index, 0);
+								targetSlot->addItems(stack, dir);
+								zSource->updateCache(sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId());
+								zSource->afterPullStack(sourceSlot, sourceView, targetSlot->zStack()->zItem(), number);
+								zTarget->afterPushStack(targetSlot, targetView, targetSlot->zStack()->zItem(), number);
+								if (stack->getSize())
+									throw stack;
+								stack->release();
+								count -= number;
+								if (count == 0)
+									break;
+							}
+						}
+					}
+					for (auto indexToDelete = toDelete.begin(); indexToDelete; indexToDelete++)
+						zSurceListe->remove(indexToDelete);
+					if (count == 0)
+						return;
+				}
+			}
+			else
+			{
+				while (sourceSlot && (!sourceSlot->zStack() || (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))))
+					sourceSlot++;
+				if (!sourceSlot)
+					return;
+				int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), sourceView), count);
+				int tmp = number;
+				if (number > 0 && zSource->allowPullStack(sourceSlot, sourceView) && zTarget->allowPushStack(targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp))
+				{
+					number = MIN(number, tmp);
+					if (number > 0)
+					{
+						ItemStack* stack = sourceSlot->takeItemsOut(number, dir);
+						if (stack)
+						{
+							targetSlot->addItems(stack, dir);
+							zSource->updateCache(sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId());
+							zTarget->updateCache(targetSlot, -1);
+							zSource->afterPullStack(sourceSlot, sourceView, targetSlot->zStack()->zItem(), number);
+							zTarget->afterPushStack(targetSlot, targetView, targetSlot->zStack()->zItem(), number);
+							if (stack->getSize())
+								throw stack;
+							stack->release();
+							count -= number;
+							if (count == 0)
+								return;
+						}
+					}
+				}
+			}
+		}
+		if (amount == count || targetSlot->isFull())
+			targetSlot++;
+	}
 }
 
 
-InventoryInteraction& InventoryInteraction::operator=( const InventoryInteraction& data )
+InventoryInteraction& InventoryInteraction::operator=(const InventoryInteraction& data)
 {
-    if( &data == this ) return *this;
-    unlock();
-    current = data.current;
-    other = data.other;
-    dir = data.dir;
-    lock();
-    return *this;
+	if (&data == this) return *this;
+	unlock();
+	current = data.current;
+	other = data.other;
+	dir = data.dir;
+	lock();
+	return *this;
 }
 
 void InventoryInteraction::endInteraction()
 {
-    unlock();
-    current = 0;
-    other = 0;
+	unlock();
+	current = 0;
+	other = 0;
 }
 
-void InventoryInteraction::pullItems( int count, ItemFilter* zFilter )
+void InventoryInteraction::pullItems(int count, ItemFilter* zFilter)
 {
-    if( !current || !other ) return;
-    transaction( other, current, zFilter, getOppositeDirection( dir ), dir, count );
+	if (!current || !other) return;
+	transaction(other, current, zFilter, getOppositeDirection(dir), dir, count);
 }
 
-void InventoryInteraction::pushItems( int count, ItemFilter* zFilter )
+void InventoryInteraction::pushItems(int count, ItemFilter* zFilter)
 {
-    if( !current || !other ) return;
-    transaction( current, other, zFilter, dir, getOppositeDirection( dir ), count );
+	if (!current || !other) return;
+	transaction(current, other, zFilter, dir, getOppositeDirection(dir), count);
 }
 
 
-Inventory::Inventory( const Framework::Vec3<float> location, bool hasInventory )
-    : ReferenceCounter(),
-    location( location )
+Inventory::Inventory(const Framework::Vec3<float> location, bool hasInventory)
+	: ReferenceCounter(),
+	nextSlotId(1),
+	location(location)
 {
-    if( hasInventory )
-    {
-        pullSlotsOrder = new Framework::RCArray<ItemSlot>();
-        pushSlotsOrder = new Framework::RCArray<ItemSlot>();
-        itemCache = new Framework::HashMap<int, Framework::Array<ItemSlot*>*>( ITEM_CACHE_SIZE, std::_Identity<int>() );
-    }
-    else
-    {
-        pullSlotsOrder = 0;
-        pushSlotsOrder = 0;
-        itemCache = 0;
-    }
+	if (hasInventory)
+	{
+		pullSlotsOrder = new Framework::RCArray<ItemSlot>();
+		pushSlotsOrder = new Framework::RCArray<ItemSlot>();
+		itemCache = new Framework::HashMap<int, Framework::Array<ItemSlot*>*>(ITEM_CACHE_SIZE, std::_Identity<int>());
+	}
+	else
+	{
+		pullSlotsOrder = 0;
+		pushSlotsOrder = 0;
+		itemCache = 0;
+	}
 }
 
 Inventory::~Inventory()
 {
-    if( pullSlotsOrder )
-        pullSlotsOrder->release();
-    if( pushSlotsOrder )
-        pushSlotsOrder->release();
-    if( itemCache )
-        itemCache->release();
+	if (pullSlotsOrder)
+		pullSlotsOrder->release();
+	if (pushSlotsOrder)
+		pushSlotsOrder->release();
+	if (itemCache)
+		itemCache->release();
 }
 
-void Inventory::updateCache( ItemSlot* zSlot, int beforeKey )
+void Inventory::updateCache(ItemSlot* zSlot, int beforeKey)
 {
-    if( !itemCache )
-        return;
-    int key = zSlot->zStack() ? zSlot->zStack()->zItem()->zItemType()->getId() : -1;
-    if( key == beforeKey )
-        return;
-    if( beforeKey >= 0 )
-    {
-        auto tmp = itemCache->safeGet( key, 0 );
-        if( tmp )
-            tmp->removeValue( zSlot );
-    }
-    if( zSlot->zStack() )
-    {
-        auto tmp = itemCache->safeGet( key, 0 );
-        if( !tmp )
-        {
-            tmp = new Array<ItemSlot*>();
-            itemCache->put( key, tmp );
-        }
-        tmp->add( zSlot, 0 );
-    }
+	if (!itemCache)
+		return;
+	int key = zSlot->zStack() ? zSlot->zStack()->zItem()->zItemType()->getId() : -1;
+	if (key == beforeKey)
+		return;
+	if (beforeKey >= 0)
+	{
+		auto tmp = itemCache->safeGet(key, 0);
+		if (tmp)
+			tmp->removeValue(zSlot);
+	}
+	if (zSlot->zStack())
+	{
+		auto tmp = itemCache->safeGet(key, 0);
+		if (!tmp)
+		{
+			tmp = new Array<ItemSlot*>();
+			itemCache->put(key, tmp);
+		}
+		tmp->add(zSlot, 0);
+	}
 }
 
-void Inventory::addSlot( ItemSlot* slot )
+void Inventory::addSlot(ItemSlot* slot)
 {
-    cs.lock();
-    int pullPrio = slot->getPullPriority();
-    int pushPrio = slot->getPushPriority();
-    int index = 0;
-    for( auto stack : *pullSlotsOrder )
-    {
-        if( stack->getPullPriority() > pullPrio )
-            break;
-        index++;
-    }
-    pullSlotsOrder->add( dynamic_cast<ItemSlot*>(slot->getThis()), index );
-    index = 0;
-    for( auto stack : *pushSlotsOrder )
-    {
-        if( stack->getPushPriority() > pushPrio )
-            break;
-        index++;
-    }
-    pushSlotsOrder->add( slot, index );
-    updateCache( slot, -1 );
-    cs.unlock();
+	cs.lock();
+	((ItemSlotIDSetter*)slot)->setId(nextSlotId++);
+	int pullPrio = slot->getPullPriority();
+	int pushPrio = slot->getPushPriority();
+	int index = 0;
+	for (auto stack : *pullSlotsOrder)
+	{
+		if (stack->getPullPriority() > pullPrio)
+			break;
+		index++;
+	}
+	pullSlotsOrder->add(dynamic_cast<ItemSlot*>(slot->getThis()), index);
+	index = 0;
+	for (auto stack : *pushSlotsOrder)
+	{
+		if (stack->getPushPriority() > pushPrio)
+			break;
+		index++;
+	}
+	pushSlotsOrder->add(slot, index);
+	updateCache(slot, -1);
+	cs.unlock();
 }
 
-bool Inventory::allowPullStack( ItemSlot* zSlot, Direction dir ) const
+bool Inventory::allowPullStack(ItemSlot* zSlot, Direction dir) const
 {
-    return pullSlotsOrder;
+	return pullSlotsOrder;
 }
 
-bool Inventory::allowPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int& count ) const
+bool Inventory::allowPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int& count) const
 {
-    return pushSlotsOrder;
+	return pushSlotsOrder;
 }
 
-void Inventory::afterPullStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count )
+void Inventory::afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
 {}
 
-void Inventory::afterPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count )
+void Inventory::afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
 {}
 
-void Inventory::loadInventory( Framework::StreamReader* zReader )
+void Inventory::loadInventory(Framework::StreamReader* zReader)
 {
-    if( itemCache )
-    {
-        for( auto stack : *pushSlotsOrder )
-        {
-            int size = 0;
-            zReader->lese( (char*)&size, 4 );
-            if( size != 0 )
-            {
-                int id = 0;
-                zReader->lese( (char*)&id, 4 );
-                Item* item = StaticRegistry<ItemType>::INSTANCE.zElement( id )->loadItem( zReader );
-                stack->addItems( new ItemStack( item, size ), NO_DIRECTION );
-            }
-        }
-    }
+	if (itemCache)
+	{
+		for (auto stack : *pushSlotsOrder)
+		{
+			int size = 0;
+			zReader->lese((char*)&size, 4);
+			if (size != 0)
+			{
+				int id = 0;
+				zReader->lese((char*)&id, 4);
+				Item* item = StaticRegistry<ItemType>::INSTANCE.zElement(id)->loadItem(zReader);
+				stack->addItems(new ItemStack(item, size), NO_DIRECTION);
+			}
+		}
+	}
 }
 
-void Inventory::saveInventory( Framework::StreamWriter* zWriter )
+void Inventory::saveInventory(Framework::StreamWriter* zWriter)
 {
-    if( itemCache )
-    {
-        for( auto slot : *pushSlotsOrder )
-        {
-            const ItemStack* stack = slot->zStack();
-            int value = 0;
-            if( !stack || !stack->zItem() )
-            {
-                zWriter->schreibe( (char*)&value, 4 );
-            }
-            else
-            {
-                value = stack->getSize();
-                zWriter->schreibe( (char*)&value, 4 );
-                value = stack->zItem()->zItemType()->getId();
-                zWriter->schreibe( (char*)&value, 4 );
-                stack->zItem()->zItemType()->saveItem( stack->zItem(), zWriter );
-            }
-        }
-    }
+	if (itemCache)
+	{
+		for (auto slot : *pushSlotsOrder)
+		{
+			const ItemStack* stack = slot->zStack();
+			int value = 0;
+			if (!stack || !stack->zItem())
+			{
+				zWriter->schreibe((char*)&value, 4);
+			}
+			else
+			{
+				value = stack->getSize();
+				zWriter->schreibe((char*)&value, 4);
+				value = stack->zItem()->zItemType()->getId();
+				zWriter->schreibe((char*)&value, 4);
+				stack->zItem()->zItemType()->saveItem(stack->zItem(), zWriter);
+			}
+		}
+	}
 }
 
-void Inventory::localTransaction( Array< ItemSlot* >* zSourceSlots, Array< ItemSlot* >* zTargetSlots, ItemFilter* zFilter, int count, Direction outDir, Direction inDir )
+void Inventory::localTransaction(Array< ItemSlot* >* zSourceSlots, Array< ItemSlot* >* zTargetSlots, ItemFilter* zFilter, int count, Direction outDir, Direction inDir)
 {
-    if( itemCache )
-    {
-        cs.lock();
-        auto sourceSlot = zSourceSlots ? zSourceSlots->begin() : pullSlotsOrder->begin();
-        for( auto targetSlot = zTargetSlots->begin(); targetSlot; )
-        {
-            int amount = count;
-            if( !targetSlot->isFull() )
-            {
-                if( targetSlot->zStack() )
-                {
-                    Array<ItemSlot*>* zSurceListe = itemCache->safeGet( targetSlot->zStack()->zItem()->zItemType()->getId(), 0 );
-                    if( zSurceListe )
-                    {
-                        Array<int> toDelete;
-                        int index = 0;
-                        for( auto sourceSlot = zSurceListe->begin(); sourceSlot; sourceSlot++, index++ )
-                        {
-                            if( zSourceSlots && zSourceSlots->getWertIndex( sourceSlot ) < 0 )
-                                continue;
-                            if( zFilter && !zFilter->matchItem( sourceSlot->zStack()->zItem() ) )
-                                continue;
-                            int number = MIN( targetSlot->numberOfAddableItems( sourceSlot->zStack(), inDir ), count );
-                            if( number > 0 )
-                            {
-                                ItemStack* stack = sourceSlot->takeItemsOut( number, outDir );
-                                if( stack )
-                                {
-                                    if( !sourceSlot->zStack() )
-                                        toDelete.add( index, 0 );
-                                    targetSlot->addItems( stack, inDir );
-                                    updateCache( sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId() );
-                                    if( stack->getSize() )
-                                    {
-                                        cs.unlock();
-                                        throw stack;
-                                    }
-                                    stack->release();
-                                    count -= number;
-                                    if( count == 0 )
-                                        break;
-                                }
-                            }
-                        }
-                        for( auto indexToDelete = toDelete.begin(); indexToDelete; indexToDelete++ )
-                            zSurceListe->remove( indexToDelete );
-                        if( count == 0 )
-                        {
-                            cs.unlock();
-                            return;
-                        }
-                    }
-                }
-                else
-                {
-                    while( sourceSlot && (!sourceSlot->zStack() || (zFilter && !zFilter->matchItem( sourceSlot->zStack()->zItem() ))) )
-                        sourceSlot++;
-                    if( !sourceSlot )
-                    {
-                        cs.unlock();
-                        return;
-                    }
-                    int number = MIN( targetSlot->numberOfAddableItems( sourceSlot->zStack(), inDir ), count );
-                    if( number > 0 )
-                    {
-                        ItemStack* stack = sourceSlot->takeItemsOut( number, outDir );
-                        if( stack )
-                        {
-                            targetSlot->addItems( stack, inDir );
-                            updateCache( sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId() );
-                            updateCache( targetSlot, -1 );
-                            if( stack->getSize() )
-                            {
-                                cs.unlock();
-                                throw stack;
-                            }
-                            stack->release();
-                            count -= number;
-                            if( count == 0 )
-                            {
-                                cs.unlock();
-                                return;
-                            }
-                        }
-                    }
-                }
-            }
-            if( amount == count || targetSlot->isFull() )
-                targetSlot++;
-        }
-        cs.unlock();
-    }
+	if (itemCache)
+	{
+		cs.lock();
+		auto sourceSlot = zSourceSlots ? zSourceSlots->begin() : pullSlotsOrder->begin();
+		for (auto targetSlot = zTargetSlots->begin(); targetSlot; )
+		{
+			int amount = count;
+			if (!targetSlot->isFull())
+			{
+				if (targetSlot->zStack())
+				{
+					Array<ItemSlot*>* zSurceListe = itemCache->safeGet(targetSlot->zStack()->zItem()->zItemType()->getId(), 0);
+					if (zSurceListe)
+					{
+						Array<int> toDelete;
+						int index = 0;
+						for (auto sourceSlot = zSurceListe->begin(); sourceSlot; sourceSlot++, index++)
+						{
+							if (zSourceSlots && zSourceSlots->getWertIndex(sourceSlot) < 0)
+								continue;
+							if (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))
+								continue;
+							int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), inDir), count);
+							if (number > 0)
+							{
+								ItemStack* stack = sourceSlot->takeItemsOut(number, outDir);
+								if (stack)
+								{
+									if (!sourceSlot->zStack())
+										toDelete.add(index, 0);
+									targetSlot->addItems(stack, inDir);
+									updateCache(sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId());
+									if (stack->getSize())
+									{
+										cs.unlock();
+										throw stack;
+									}
+									stack->release();
+									count -= number;
+									if (count == 0)
+										break;
+								}
+							}
+						}
+						for (auto indexToDelete = toDelete.begin(); indexToDelete; indexToDelete++)
+							zSurceListe->remove(indexToDelete);
+						if (count == 0)
+						{
+							cs.unlock();
+							return;
+						}
+					}
+				}
+				else
+				{
+					while (sourceSlot && (!sourceSlot->zStack() || (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))))
+						sourceSlot++;
+					if (!sourceSlot)
+					{
+						cs.unlock();
+						return;
+					}
+					int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), inDir), count);
+					if (number > 0)
+					{
+						ItemStack* stack = sourceSlot->takeItemsOut(number, outDir);
+						if (stack)
+						{
+							targetSlot->addItems(stack, inDir);
+							updateCache(sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId());
+							updateCache(targetSlot, -1);
+							if (stack->getSize())
+							{
+								cs.unlock();
+								throw stack;
+							}
+							stack->release();
+							count -= number;
+							if (count == 0)
+							{
+								cs.unlock();
+								return;
+							}
+						}
+					}
+				}
+			}
+			if (amount == count || targetSlot->isFull())
+				targetSlot++;
+		}
+		cs.unlock();
+	}
 }
 
-void Inventory::addItems( ItemStack* items, Direction dir )
+void Inventory::addItems(ItemStack* items, Direction dir)
 {
-    if( itemCache && items && items->getSize() > 0 )
-    {
-        cs.lock();
-        for( auto targetSlot = pushSlotsOrder->begin(); targetSlot; targetSlot++ )
-        {
-            if( !targetSlot->isFull() )
-            {
-                if( targetSlot->zStack() )
-                {
-                    int number = MIN( targetSlot->numberOfAddableItems( items, dir ), items->getSize() );
-                    int tmp = number;
-                    if( number > 0 && allowPushStack( targetSlot, dir, items->zItem(), tmp ) )
-                    {
-                        number = MIN( number, tmp );
-                        ItemStack* stack = items->split( number );
-                        if( stack )
-                        {
-                            targetSlot->addItems( stack, dir );
-                            afterPushStack( targetSlot, dir, targetSlot->zStack()->zItem(), number );
-                            if( stack->getSize() )
-                                throw stack;
-                            stack->release();
-                            if( !items->getSize() )
-                                break;
-                        }
-                    }
-                }
-                else
-                {
-                    int number = MIN( targetSlot->numberOfAddableItems( items, dir ), items->getSize() );
-                    int tmp = number;
-                    if( number > 0 && allowPushStack( targetSlot, dir, items->zItem(), tmp ) )
-                    {
-                        number = MIN( number, tmp );
-                        ItemStack* stack = items->split( number );
-                        if( stack )
-                        {
-                            targetSlot->addItems( stack, dir );
-                            updateCache( targetSlot, -1 );
-                            afterPushStack( targetSlot, dir, targetSlot->zStack()->zItem(), number );
-                            if( stack->getSize() )
-                                throw stack;
-                            stack->release();
-                            if( !items->getSize() )
-                                break;
-                        }
-                    }
-                }
-            }
-        }
-        cs.unlock();
-    }
+	if (itemCache && items && items->getSize() > 0)
+	{
+		cs.lock();
+		for (auto targetSlot = pushSlotsOrder->begin(); targetSlot; targetSlot++)
+		{
+			if (!targetSlot->isFull())
+			{
+				if (targetSlot->zStack())
+				{
+					int number = MIN(targetSlot->numberOfAddableItems(items, dir), items->getSize());
+					int tmp = number;
+					if (number > 0 && allowPushStack(targetSlot, dir, items->zItem(), tmp))
+					{
+						number = MIN(number, tmp);
+						ItemStack* stack = items->split(number);
+						if (stack)
+						{
+							targetSlot->addItems(stack, dir);
+							afterPushStack(targetSlot, dir, targetSlot->zStack()->zItem(), number);
+							if (stack->getSize())
+								throw stack;
+							stack->release();
+							if (!items->getSize())
+								break;
+						}
+					}
+				}
+				else
+				{
+					int number = MIN(targetSlot->numberOfAddableItems(items, dir), items->getSize());
+					int tmp = number;
+					if (number > 0 && allowPushStack(targetSlot, dir, items->zItem(), tmp))
+					{
+						number = MIN(number, tmp);
+						ItemStack* stack = items->split(number);
+						if (stack)
+						{
+							targetSlot->addItems(stack, dir);
+							updateCache(targetSlot, -1);
+							afterPushStack(targetSlot, dir, targetSlot->zStack()->zItem(), number);
+							if (stack->getSize())
+								throw stack;
+							stack->release();
+							if (!items->getSize())
+								break;
+						}
+					}
+				}
+			}
+		}
+		cs.unlock();
+	}
 }
 
-ItemStack* Inventory::takeItemsOut( ItemSlot* zSlot, int count, Direction dir )
+ItemStack* Inventory::takeItemsOut(ItemSlot* zSlot, int count, Direction dir)
 {
-    if( allowPullStack( zSlot, dir ) )
-    {
-        ItemStack* stack = zSlot->takeItemsOut( count, dir );
-        if( stack )
-            updateCache( zSlot, stack->zItem()->zItemType()->getId() );
-        return stack;
-    }
-    return 0;
+	if (allowPullStack(zSlot, dir))
+	{
+		ItemStack* stack = zSlot->takeItemsOut(count, dir);
+		if (stack)
+			updateCache(zSlot, stack->zItem()->zItemType()->getId());
+		return stack;
+	}
+	return 0;
 }
 
-InventoryInteraction Inventory::interactWith( Inventory* zInventory, Direction dir )
+InventoryInteraction Inventory::interactWith(Inventory* zInventory, Direction dir)
 {
-    return InventoryInteraction( this, zInventory, dir );
+	return InventoryInteraction(this, zInventory, dir);
 }
 
-void Inventory::unsaveAddItem( ItemStack* zStack, Direction dir )
+void Inventory::unsaveAddItem(ItemStack* zStack, Direction dir)
 {
-    addItems( zStack, dir );
+	addItems(zStack, dir);
 }
 
-int Inventory::numberOfAddableItems( const ItemStack* zStack, Direction dir ) const
+int Inventory::numberOfAddableItems(const ItemStack* zStack, Direction dir) const
 {
-    int count = 0;
-    for( auto targetSlot = pushSlotsOrder->begin(); targetSlot; targetSlot++ )
-    {
-        int maxCount = targetSlot->numberOfAddableItems( zStack, dir );
-        int allowed = maxCount;
-        if( allowPushStack( targetSlot, dir, zStack->zItem(), allowed ) )
-            count += MIN( maxCount, allowed );
-    }
-    return count;
+	int count = 0;
+	for (auto targetSlot = pushSlotsOrder->begin(); targetSlot; targetSlot++)
+	{
+		int maxCount = targetSlot->numberOfAddableItems(zStack, dir);
+		int allowed = maxCount;
+		if (allowPushStack(targetSlot, dir, zStack->zItem(), allowed))
+			count += MIN(maxCount, allowed);
+	}
+	return count;
+}
+
+Framework::Iterator<ItemSlot*> Inventory::begin()
+{
+	return pullSlotsOrder->begin();
+}
+
+Framework::Iterator<ItemSlot*> Inventory::end()
+{
+	return pullSlotsOrder->end();
 }

+ 40 - 35
FactoryCraft/Inventory.h

@@ -14,51 +14,56 @@ class Inventory;
 class InventoryInteraction
 {
 private:
-    Inventory* current;
-    Inventory* other;
-    Direction dir;
-    void lock();
-    void unlock();
-    void transaction( Inventory* zSource, Inventory* zTarget, ItemFilter* zFilter, Direction sourceView, Direction targetView, int count );
+	Inventory* current;
+	Inventory* other;
+	Direction dir;
+	void lock();
+	void unlock();
+	void transaction(Inventory* zSource, Inventory* zTarget, ItemFilter* zFilter, Direction sourceView, Direction targetView, int count);
 
 public:
-    InventoryInteraction( Inventory* zCurrent, Inventory* zOther, Direction dir );
-    InventoryInteraction( const InventoryInteraction& interaction );
-    ~InventoryInteraction();
-    InventoryInteraction& operator=( const InventoryInteraction& data );
-    void endInteraction();
-    void pullItems( int count, ItemFilter* zFilter );
-    void pushItems( int count, ItemFilter* zFilter );
+	InventoryInteraction(Inventory* zCurrent, Inventory* zOther, Direction dir);
+	InventoryInteraction(const InventoryInteraction& interaction);
+	~InventoryInteraction();
+	InventoryInteraction& operator=(const InventoryInteraction& data);
+	void endInteraction();
+	void pullItems(int count, ItemFilter* zFilter);
+	void pushItems(int count, ItemFilter* zFilter);
 };
 
 class Inventory : public virtual Framework::ReferenceCounter
 {
 private:
-    Framework::RCArray<ItemSlot>* pullSlotsOrder;
-    Framework::RCArray<ItemSlot>* pushSlotsOrder;
-    Framework::HashMap<int, Framework::Array<ItemSlot*>*>* itemCache;
-    Framework::Critical cs;
-    void updateCache( ItemSlot* zSlot, int beforeKey );
+	Framework::RCArray<ItemSlot>* pullSlotsOrder;
+	Framework::RCArray<ItemSlot>* pushSlotsOrder;
+	Framework::HashMap<int, Framework::Array<ItemSlot*>*>* itemCache;
+	Framework::Critical cs;
+	int nextSlotId;
+
+	void updateCache(ItemSlot* zSlot, int beforeKey);
 
 protected:
-    Framework::Vec3<float> location;
-    virtual bool allowPullStack( ItemSlot* zSlot, Direction dir ) const;
-    virtual bool allowPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int& count ) const;
-    virtual void afterPullStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count );
-    virtual void afterPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count );
-    virtual void loadInventory( Framework::StreamReader* zReader );
-    virtual void saveInventory( Framework::StreamWriter* zWriter );
+	Framework::Vec3<float> location;
+
+	virtual bool allowPullStack(ItemSlot* zSlot, Direction dir) const;
+	virtual bool allowPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int& count) const;
+	virtual void afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count);
+	virtual void afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count);
+	virtual void loadInventory(Framework::StreamReader* zReader);
+	virtual void saveInventory(Framework::StreamWriter* zWriter);
 
 public:
-    Inventory( const Framework::Vec3<float> location, bool hasInventory );
-    virtual ~Inventory();
-    void addSlot( ItemSlot* slot );
-    void localTransaction( Framework::Array< ItemSlot* >* zSourceSlots, Framework::Array< ItemSlot* >* zTargetSlots, ItemFilter* zFilter, int count, Direction outDir, Direction inDir );
-    ItemStack* takeItemsOut( ItemSlot* zSlot, int count, Direction dir );
-    virtual void addItems( ItemStack* items, Direction dir );
-    InventoryInteraction interactWith( Inventory* zInventory, Direction dir );
-    void unsaveAddItem( ItemStack* zStack, Direction dir );
-    int numberOfAddableItems( const ItemStack* zStack, Direction dir ) const;
+	Inventory(const Framework::Vec3<float> location, bool hasInventory);
+	virtual ~Inventory();
+	void addSlot(ItemSlot* slot);
+	void localTransaction(Framework::Array< ItemSlot* >* zSourceSlots, Framework::Array< ItemSlot* >* zTargetSlots, ItemFilter* zFilter, int count, Direction outDir, Direction inDir);
+	ItemStack* takeItemsOut(ItemSlot* zSlot, int count, Direction dir);
+	virtual void addItems(ItemStack* items, Direction dir);
+	InventoryInteraction interactWith(Inventory* zInventory, Direction dir);
+	void unsaveAddItem(ItemStack* zStack, Direction dir);
+	int numberOfAddableItems(const ItemStack* zStack, Direction dir) const;
+	Framework::Iterator<ItemSlot*> begin();
+	Framework::Iterator<ItemSlot*> end();
 
-    friend InventoryInteraction;
+	friend InventoryInteraction;
 };

+ 57 - 56
FactoryCraft/ItemEntity.cpp

@@ -3,78 +3,79 @@
 #include "EntityChangedUpdate.h"
 
 
-ItemEntity::ItemEntity( Framework::Vec3<float> location, int dimensionId, int entityId )
-    : Entity( ItemEntityType::INSTANCE, location, dimensionId, entityId )
+ItemEntity::ItemEntity(Framework::Vec3<float> location, int dimensionId, int entityId)
+	: Entity(ItemEntityType::INSTANCE, location, dimensionId, entityId)
 {
-    slot = new ItemSlot( __INT32_MAX__, 0, 0, 0, ANY_DIRECTION, 0 );
-    addSlot( slot );
-    faceOffset = { 0.f, 0.f, 0.f };
-    maxHP = 10;
-    currentHP = 10;
-    stamina = 10;
-    maxStamina = 10;
-    hunger = 10;
-    maxHunger = 10;
-    thirst = 10;
-    maxThirst = 10;
-    targetDistanceLimit = 4;
+	slot = new ItemSlot("Inventory", __INT32_MAX__, 0, 0, 0, ANY_DIRECTION, 0);
+	addSlot(slot);
+	faceOffset = { 0.f, 0.f, 0.f };
+	maxHP = 10;
+	currentHP = 10;
+	stamina = 10;
+	maxStamina = 10;
+	hunger = 10;
+	maxHunger = 10;
+	thirst = 10;
+	maxThirst = 10;
+	targetDistanceLimit = 4;
 }
 
-void ItemEntity::tick( const Dimension* zDimension )
+void ItemEntity::tick(const Dimension* zDimension)
 {
-    if( slot->zStack() == 0 && !removed )
-        throw "Illegal State exception";
-    // add speed to next entity with free inventory
-    Entity* zOther = Game::INSTANCE->zNearestEntity( currentDimensionId, location, [this]( Entity* zOther ) {
-        return zOther != this && zOther->numberOfAddableItems( slot->zStack(), NO_DIRECTION );
-    } );
-    bool found = 1;
-    if( zOther )
-    {
-        float d = location.abstand( zOther->getPosition() );
-        if( d < 0.5f )
-        {
-            // add items of this entity to the other entity
-            zOther->interactWith( this, NO_DIRECTION ).pullItems( slot->getNumberOfItems(), 0 );
-            if( slot->getNumberOfItems() == 0 )
-                onDeath();
-        }
-        else if( d < 3.f )
-        {
-            // accelerate towards of the other entity
-            speed += (zOther->getPosition() - location).normalize() * (20 / (d + 0.5f)) / 30.f;
-        }
-        else
-            found = 0;
-    }
-    else
-        found = 0;
-    if( !found )
-    {
-        speed -= speed / 30.f;
-        if( speed.getLength() < 0.2f )
-            speed = { 0.f, 0.f, 0.f };
-    }
-    Entity::tick( zDimension );
+	if (slot->zStack() == 0 && !removed)
+		throw "Illegal State exception";
+	// add speed to next entity with free inventory
+	Entity* zOther = Game::INSTANCE->zNearestEntity(currentDimensionId, location, [this](Entity* zOther)
+		{
+			return zOther != this && zOther->numberOfAddableItems(slot->zStack(), NO_DIRECTION);
+		});
+	bool found = 1;
+	if (zOther)
+	{
+		float d = location.abstand(zOther->getPosition());
+		if (d < 0.5f)
+		{
+			// add items of this entity to the other entity
+			zOther->interactWith(this, NO_DIRECTION).pullItems(slot->getNumberOfItems(), 0);
+			if (slot->getNumberOfItems() == 0)
+				onDeath();
+		}
+		else if (d < 3.f)
+		{
+			// accelerate towards of the other entity
+			speed += (zOther->getPosition() - location).normalize() * (20 / (d + 0.5f)) / 30.f;
+		}
+		else
+			found = 0;
+	}
+	else
+		found = 0;
+	if (!found)
+	{
+		speed -= speed / 30.f;
+		if (speed.getLength() < 0.2f)
+			speed = { 0.f, 0.f, 0.f };
+	}
+	Entity::tick(zDimension);
 }
 
-void ItemEntity::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
+void ItemEntity::api(Framework::StreamReader* zRequest, NetworkResponse* zResponse)
 {
 
 }
 
-void ItemEntity::onFall( float collisionSpeed )
+void ItemEntity::onFall(float collisionSpeed)
 {
-    if( collisionSpeed >= 50.f )
-        this->currentHP = 0;
+	if (collisionSpeed >= 50.f)
+		this->currentHP = 0;
 }
 
 
 ItemEntityType::ItemEntityType()
-    : EntityType( ID )
+	: EntityType(ID)
 {}
 
-Entity* ItemEntityType::createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const
+Entity* ItemEntityType::createEntity(Framework::Vec3<float> position, int dimensionId, int entityId) const
 {
-    return new ItemEntity( position, dimensionId, entityId );
+	return new ItemEntity(position, dimensionId, entityId);
 }

+ 10 - 10
FactoryCraft/ItemEntity.h

@@ -8,26 +8,26 @@ class ItemEntityType;
 class ItemEntity : public Entity
 {
 private:
-    ItemSlot* slot;
+	ItemSlot* slot;
 
-    ItemEntity( Framework::Vec3<float> location, int dimensionId, int entityId );
+	ItemEntity(Framework::Vec3<float> location, int dimensionId, int entityId);
 
 public:
-    void tick( const Dimension* zDimension ) override;
+	void tick(const Dimension* zDimension) override;
 
-    void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse ) override;
-    void onFall( float collisionSpeed ) override;
+	void api(Framework::StreamReader* zRequest, NetworkResponse* zResponse) override;
+	void onFall(float collisionSpeed) override;
 
-    friend ItemEntityType;
+	friend ItemEntityType;
 };
 
 class ItemEntityType : public EntityType
 {
-    REGISTRABLE( ItemEntityType )
+	REGISTRABLE(ItemEntityType)
 
 public:
-    ItemEntityType();
+	ItemEntityType();
 
-    virtual Entity* createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const override;
+	virtual Entity* createEntity(Framework::Vec3<float> position, int dimensionId, int entityId) const override;
 };
-REGISTER( ItemEntityType, EntityType )
+REGISTER(ItemEntityType, EntityType)

+ 82 - 65
FactoryCraft/ItemSlot.cpp

@@ -1,110 +1,127 @@
 #include "ItemSlot.h"
 
 
-ItemSlot::ItemSlot( int maxSize, int pullPriority, int pushPriority, int allowedPullSide, int allowedPushSides, bool allowHigherStackSize )
-    : ReferenceCounter(),
-    items( 0 ),
-    maxSize( maxSize ),
-    allowedPullSide( allowedPullSide ),
-    allowedPushSides( allowedPushSides ),
-    pullPriority( pullPriority ),
-    pushPriority( pushPriority ),
-    allowHigherStackSize( allowHigherStackSize )
+ItemSlot::ItemSlot(Framework::Text name, int maxSize, int pullPriority, int pushPriority, int allowedPullSide, int allowedPushSides, bool allowHigherStackSize)
+	: ReferenceCounter(),
+	items(0),
+	maxSize(maxSize),
+	allowedPullSide(allowedPullSide),
+	allowedPushSides(allowedPushSides),
+	pullPriority(pullPriority),
+	pushPriority(pushPriority),
+	allowHigherStackSize(allowHigherStackSize),
+	name(name),
+	id(0)
 {}
 
 ItemSlot::~ItemSlot()
 {
-    if( items )
-        items->release();
+	if (items)
+		items->release();
 }
 
-ItemStack* ItemSlot::takeItemsOut( int count, Direction dir )
+void ItemSlot::setId(int id)
 {
-    if( !items )
-        return 0;
-    if( (dir | allowedPullSide) == allowedPullSide )
-    {
-        ItemStack* result = items->split( count );
-        if( items->getSize() == 0 )
-        {
-            items->release();
-            items = 0;
-        }
-        return result;
-    }
-    return 0;
+	this->id = id;
 }
 
-void ItemSlot::addItems( ItemStack* zStack, Direction dir )
+ItemStack* ItemSlot::takeItemsOut(int count, Direction dir)
 {
-    if( (dir | allowedPushSides) == allowedPushSides )
-    {
-        if( !items )
-        {
-            if( allowHigherStackSize )
-            {
-                items = zStack->split( maxSize );
-                items->setMaxSize( maxSize );
-            }
-            else
-            {
-                items = zStack->split( MIN( maxSize, zStack->zItem()->getMaxStackSize() ) );
-                items->setMaxSize( MIN( maxSize, items->zItem()->getMaxStackSize() ) );
-            }
-        }
-        else
-            items->addItemStack( zStack );
-    }
+	if (!items)
+		return 0;
+	if ((dir | allowedPullSide) == allowedPullSide)
+	{
+		ItemStack* result = items->split(count);
+		if (items->getSize() == 0)
+		{
+			items->release();
+			items = 0;
+		}
+		return result;
+	}
+	return 0;
 }
 
-int ItemSlot::numberOfAddableItems( const ItemStack* zStack, Direction dir ) const
+void ItemSlot::addItems(ItemStack* zStack, Direction dir)
 {
-    if( (dir | allowedPushSides) == allowedPushSides )
-    {
-        if( !items )
-        {
-            if( allowHigherStackSize )
-                return maxSize;
-            else
-                return MIN( maxSize, zStack->zItem()->getMaxStackSize() );
-        }
-        else
-            return items->getMaxSize() - items->getSize();
-    }
-    return 0;
+	if ((dir | allowedPushSides) == allowedPushSides)
+	{
+		if (!items)
+		{
+			if (allowHigherStackSize)
+			{
+				items = zStack->split(maxSize);
+				items->setMaxSize(maxSize);
+			}
+			else
+			{
+				items = zStack->split(MIN(maxSize, zStack->zItem()->getMaxStackSize()));
+				items->setMaxSize(MIN(maxSize, items->zItem()->getMaxStackSize()));
+			}
+		}
+		else
+			items->addItemStack(zStack);
+	}
+}
+
+int ItemSlot::numberOfAddableItems(const ItemStack* zStack, Direction dir) const
+{
+	if ((dir | allowedPushSides) == allowedPushSides)
+	{
+		if (!items)
+		{
+			if (allowHigherStackSize)
+				return maxSize;
+			else
+				return MIN(maxSize, zStack->zItem()->getMaxStackSize());
+		}
+		else
+			return items->getMaxSize() - items->getSize();
+	}
+	return 0;
 }
 
 const ItemStack* ItemSlot::zStack() const
 {
-    return items;
+	return items;
 }
 
 int ItemSlot::getPullPriority() const
 {
-    return pullPriority;
+	return pullPriority;
 }
 
 int ItemSlot::getPushPriority() const
 {
-    return pushPriority;
+	return pushPriority;
 }
 
 bool ItemSlot::isFull() const
 {
-    return items ? items->getSize() >= items->getMaxSize() : maxSize == 0;
+	return items ? items->getSize() >= items->getMaxSize() : maxSize == 0;
 }
 
 int ItemSlot::getFreeSpace() const
 {
-    return items ? items->getMaxSize() - items->getSize() : maxSize;
+	return items ? items->getMaxSize() - items->getSize() : maxSize;
 }
 
 bool ItemSlot::isEmpty() const
 {
-    return !items;
+	return !items;
 }
 
 int ItemSlot::getNumberOfItems() const
 {
-    return items ? items->getSize() : 0;
+	return items ? items->getSize() : 0;
+}
+
+const Framework::Text& ItemSlot::getName() const
+{
+	return name;
+}
+
+int ItemSlot::getId() const
+{
+	return id;
 }

+ 37 - 22
FactoryCraft/ItemSlot.h

@@ -3,30 +3,45 @@
 #include "ItemStack.h"
 #include "Area.h"
 
-class ItemSlot : public virtual Framework::ReferenceCounter
+class Inventory;
+class ItemSlotIDSetter
+{
+protected:
+	virtual void setId(int id) = 0;
+
+	friend Inventory;
+};
+
+class ItemSlot : public virtual Framework::ReferenceCounter, public ItemSlotIDSetter
 {
 private:
-    ItemStack* items;
-    int maxSize;
-    Directions allowedPullSide;
-    Directions allowedPushSides;
-    int pullPriority;
-    int pushPriority;
-    bool allowHigherStackSize;
+	ItemStack* items;
+	int maxSize;
+	Directions allowedPullSide;
+	Directions allowedPushSides;
+	int pullPriority;
+	int pushPriority;
+	bool allowHigherStackSize;
+	Framework::Text name;
+	int id;
+
+	void setId(int id) override;
 
 public:
-    ItemSlot( int maxSize, int pullPriority, int pushPriority, int allowedPullSide, int allowedPushSides, bool allowHigherStackSize );
-    ~ItemSlot();
-
-    ItemStack* takeItemsOut( int count, Direction dir );
-    void addItems( ItemStack* zStack, Direction dir );
-
-    int numberOfAddableItems( const ItemStack* zStack, Direction dir ) const;
-    const ItemStack* zStack() const;
-    int getPullPriority() const;
-    int getPushPriority() const;
-    bool isFull() const;
-    int getFreeSpace() const;
-    bool isEmpty() const;
-    int getNumberOfItems() const;
+	ItemSlot(Framework::Text name, int maxSize, int pullPriority, int pushPriority, int allowedPullSide, int allowedPushSides, bool allowHigherStackSize);
+	~ItemSlot();
+
+	ItemStack* takeItemsOut(int count, Direction dir);
+	void addItems(ItemStack* zStack, Direction dir);
+
+	int numberOfAddableItems(const ItemStack* zStack, Direction dir) const;
+	const ItemStack* zStack() const;
+	int getPullPriority() const;
+	int getPushPriority() const;
+	bool isFull() const;
+	int getFreeSpace() const;
+	bool isEmpty() const;
+	int getNumberOfItems() const;
+	const Framework::Text& getName() const;
+	int getId() const;
 };

+ 95 - 63
FactoryCraft/NetworkResponse.cpp

@@ -5,109 +5,141 @@
 
 NetworkResponse::NetworkResponse()
 {
-    adress = 0;
-    adressLength = 0;
-    broadcast = 0;
-    message = 0;
-    msgDelete = 0;
-    msgLength = 0;
-    useBackground = 0;
+	adress = 0;
+	adressLength = 0;
+	broadcast = 0;
+	message = 0;
+	msgDelete = 0;
+	msgLength = 0;
+	useBackground = 0;
 }
 
 NetworkResponse::~NetworkResponse()
 {
-    if( msgDelete )
-        delete[] message;
-    delete[] adress;
+	if (msgDelete)
+		delete[] message;
+	delete[] adress;
 }
 
-void NetworkResponse::adressChunck( Chunk* zChunk )
+void NetworkResponse::adressChunck(Chunk* zChunk)
 {
-    adressLength = 14;
-    adress = new char[ adressLength ];
-    adress[ 0 ] = 1; // world response
-    *(int*)(adress + 1) = zChunk->getDimensionId();
-    adress[ 5 ] = 1; // chunck
-    Framework::Punkt center = zChunk->getCenter();
-    *(int*)(adress + 6) = center.x;
-    *(int*)(adress + 10) = center.y;
-    minPosition = zChunk->getMin();
-    maxPosition = zChunk->getMax();
+	adressLength = 14;
+	adress = new char[adressLength];
+	adress[0] = 1; // dimension response
+	*(int*)(adress + 1) = zChunk->getDimensionId();
+	adress[5] = 1; // chunck
+	Framework::Punkt center = zChunk->getCenter();
+	*(int*)(adress + 6) = center.x;
+	*(int*)(adress + 10) = center.y;
+	minPosition = zChunk->getMin();
+	maxPosition = zChunk->getMax();
 }
 
-void NetworkResponse::adressEntity( Entity* zEntity )
+void NetworkResponse::adressEntity(Entity* zEntity)
 {
-    adressLength = 10;
-    adress = new char[ adressLength ];
-    adress[ 0 ] = 1; // world response
-    *(int*)(adress + 1) = zEntity->getCurrentDimensionId();
-    adress[ 5 ] = 2; // entity
-    *(int*)(adress + 6) = zEntity->getId();
-    minPosition = zEntity->getPosition();
-    maxPosition = zEntity->getPosition();
+	adressLength = 10;
+	adress = new char[adressLength];
+	adress[0] = 1; // dimension response
+	*(int*)(adress + 1) = zEntity->getCurrentDimensionId();
+	adress[5] = 2; // entity
+	*(int*)(adress + 6) = zEntity->getId();
+	minPosition = zEntity->getPosition();
+	maxPosition = zEntity->getPosition();
 }
 
-void NetworkResponse::adressBlock( Block* zBlock )
+void NetworkResponse::adressBlock(Block* zBlock)
 {
-    adressLength = 18;
-    adress = new char[ adressLength ];
-    adress[ 0 ] = 1; // world response
-    *(int*)(adress + 1) = zBlock->getDimensionId();
-    adress[ 5 ] = 3; // block
-    Framework::Vec3<int> pos = zBlock->getPos();
-    *(int*)(adress + 6) = pos.x;
-    *(int*)(adress + 10) = pos.y;
-    *(int*)(adress + 14) = pos.z;
-    minPosition = pos;
-    maxPosition = pos;
+	adressLength = 18;
+	adress = new char[adressLength];
+	adress[0] = 1; // dimension response
+	*(int*)(adress + 1) = zBlock->getDimensionId();
+	adress[5] = 3; // block
+	Framework::Vec3<int> pos = zBlock->getPos();
+	*(int*)(adress + 6) = pos.x;
+	*(int*)(adress + 10) = pos.y;
+	*(int*)(adress + 14) = pos.z;
+	minPosition = pos;
+	maxPosition = pos;
 }
 
-void NetworkResponse::setMessage( char* msg, int length, bool deleteMsg )
+void NetworkResponse::openDialog(Framework::Text dialogName)
 {
-    message = msg;
-    msgLength = length;
-    msgDelete = deleteMsg;
+	adressLength = (char)(4 + dialogName.getLength());
+	adress = new char[adressLength];
+	adress[0] = 2; // gui message
+	adress[1] = 0; // open dialog
+	*(short*)(adress + 2) = (short)dialogName.getLength(); // block
+	memcpy(adress + 4, dialogName.getText(), dialogName.getLength());
+	minPosition.x = std::numeric_limits<float>::min();
+	minPosition.y = std::numeric_limits<float>::min();
+	minPosition.z = std::numeric_limits<float>::min();
+	maxPosition.x = std::numeric_limits<float>::max();
+	maxPosition.y = std::numeric_limits<float>::max();
+	maxPosition.z = std::numeric_limits<float>::max();
+}
+
+void NetworkResponse::adressGui(Framework::Text elementId)
+{
+	adressLength = (char)(4 + elementId.getLength());
+	adress = new char[adressLength];
+	adress[0] = 2; // gui message
+	adress[1] = 1; // element message
+	*(short*)(adress + 2) = (short)elementId.getLength(); // block
+	memcpy(adress + 4, elementId.getText(), elementId.getLength());
+	minPosition.x = std::numeric_limits<float>::min();
+	minPosition.y = std::numeric_limits<float>::min();
+	minPosition.z = std::numeric_limits<float>::min();
+	maxPosition.x = std::numeric_limits<float>::max();
+	maxPosition.y = std::numeric_limits<float>::max();
+	maxPosition.z = std::numeric_limits<float>::max();
+}
+
+void NetworkResponse::setMessage(char* msg, int length, bool deleteMsg)
+{
+	message = msg;
+	msgLength = length;
+	msgDelete = deleteMsg;
 }
 
 void NetworkResponse::setUseBackground()
 {
-    useBackground = 1;
+	useBackground = 1;
 }
 
 void NetworkResponse::sendToAll()
 {
-    broadcast = true;
+	broadcast = true;
 }
 
-bool NetworkResponse::isAreaAffected( Framework::Vec3<float> min, Framework::Vec3<float> max ) const
+bool NetworkResponse::isAreaAffected(Framework::Vec3<float> min, Framework::Vec3<float> max) const
 {
-    return minPosition.x <= max.x && maxPosition.x >= min.x &&
-        minPosition.y <= max.y && maxPosition.y >= min.y &&
-        minPosition.z <= max.z && maxPosition.z >= min.z;
+	return minPosition.x <= max.x && maxPosition.x >= min.x &&
+		minPosition.y <= max.y && maxPosition.y >= min.y &&
+		minPosition.z <= max.z && maxPosition.z >= min.z;
 }
 
-void NetworkResponse::writeTo( Framework::StreamWriter* zWriter ) const
+void NetworkResponse::writeTo(Framework::StreamWriter* zWriter) const
 {
-    int total = msgLength + adressLength;
-    if( total )
-    {
-        zWriter->schreibe( (char*)&total, 4 );
-        zWriter->schreibe( adress, adressLength );
-        zWriter->schreibe( message, msgLength );
-    }
+	int total = msgLength + adressLength;
+	if (total)
+	{
+		zWriter->schreibe((char*)&total, 4);
+		zWriter->schreibe(adress, adressLength);
+		zWriter->schreibe(message, msgLength);
+	}
 }
 
 bool NetworkResponse::isBroadcast() const
 {
-    return broadcast;
+	return broadcast;
 }
 
 bool NetworkResponse::isEmpty() const
 {
-    return msgLength + adressLength <= 0;
+	return msgLength + adressLength <= 0;
 }
 
 bool NetworkResponse::isUseBackground() const
 {
-    return useBackground;
+	return useBackground;
 }

+ 24 - 22
FactoryCraft/NetworkResponse.h

@@ -10,30 +10,32 @@ class Entity;
 class NetworkResponse
 {
 private:
-    char* adress;
-    char adressLength;
-    Framework::Vec3<float> minPosition;
-    Framework::Vec3<float> maxPosition;
-    bool broadcast;
-    char* message;
-    bool msgDelete;
-    int msgLength;
-    bool useBackground;
+	char* adress;
+	char adressLength;
+	Framework::Vec3<float> minPosition;
+	Framework::Vec3<float> maxPosition;
+	bool broadcast;
+	char* message;
+	bool msgDelete;
+	int msgLength;
+	bool useBackground;
 
 public:
-    NetworkResponse();
-    ~NetworkResponse();
+	NetworkResponse();
+	~NetworkResponse();
 
-    void adressChunck( Chunk* zChunk );
-    void adressEntity( Entity* zEntity );
-    void adressBlock( Block* zBlock );
-    void setMessage( char* msg, int length, bool deleteMsg );
-    void setUseBackground();
-    void sendToAll();
+	void adressChunck(Chunk* zChunk);
+	void adressEntity(Entity* zEntity);
+	void adressBlock(Block* zBlock);
+	void openDialog(Framework::Text dialogName);
+	void adressGui(Framework::Text elementId);
+	void setMessage(char* msg, int length, bool deleteMsg);
+	void setUseBackground();
+	void sendToAll();
 
-    bool isAreaAffected( Framework::Vec3<float> min, Framework::Vec3<float> max ) const;
-    void writeTo( Framework::StreamWriter* zWriter ) const;
-    bool isBroadcast() const;
-    bool isEmpty() const;
-    bool isUseBackground() const;
+	bool isAreaAffected(Framework::Vec3<float> min, Framework::Vec3<float> max) const;
+	void writeTo(Framework::StreamWriter* zWriter) const;
+	bool isBroadcast() const;
+	bool isEmpty() const;
+	bool isUseBackground() const;
 };

+ 28 - 29
FactoryCraft/OverworldDimension.cpp

@@ -1,48 +1,47 @@
 #include "OverworldDimension.h"
-#include "BasicInterpolator.h"
 #include "GrasslandBiom.h"
 #include "FastNoiseWrapper.h"
 #include "RandNoise.h"
 
 
 OverworldDimension::OverworldDimension()
-    : DimensionGenerator( ID )
+	: DimensionGenerator(ID)
 {
-    registerBiom( new GrasslandBiom(), 1.0 );
-    biomNoise = 0;
-    structureNoise = 0;
+	registerBiom(new GrasslandBiom(), 1.0);
+	biomNoise = 0;
+	structureNoise = 0;
 }
 
 OverworldDimension::~OverworldDimension()
 {
-    if( biomNoise )
-        biomNoise->release();
-    if( structureNoise )
-        structureNoise->release();
+	if (biomNoise)
+		biomNoise->release();
+	if (structureNoise)
+		structureNoise->release();
 }
 
-Noise* OverworldDimension::zBiomNoise( int seed )
+Noise* OverworldDimension::zBiomNoise(int seed)
 {
-    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;
+	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;
 }
 
-Noise* OverworldDimension::zStructureNoise( int seed )
+Noise* OverworldDimension::zStructureNoise(int seed)
 {
-    if( structureNoise )
-        return structureNoise;
-    structureNoise = new RandNoise( seed );
-    return structureNoise;
+	if (structureNoise)
+		return structureNoise;
+	structureNoise = new RandNoise(seed);
+	return structureNoise;
 }

+ 308 - 264
FactoryCraft/Player.cpp

@@ -3,308 +3,352 @@
 #include "PlayerHand.h"
 #include "ItemFilter.h"
 
-Player::Player( Framework::Vec3<float> location, int dimensionId, int entityId )
-    : Entity( PlayerEntityType::INSTANCE, location, dimensionId, entityId ),
-    BasicShapedCrafter( 2, 2, this )
+Player::Player(Framework::Vec3<float> location, int dimensionId, int entityId)
+	: Entity(PlayerEntityType::INSTANCE, location, dimensionId, entityId),
+	BasicShapedCrafter(3, 3, this)
 {
-    for( int i = 0; i < 9; i++ )
-    {
-        ItemSlot* slot = new ItemSlot( 50, 0, i, 0, ANY_DIRECTION, 0 );
-        itemBar.add( slot );
-        addSlot( slot );
-    }
-    leftHandPosition = 0;
-    maxHP = 10;
-    currentHP = 10;
-    stamina = 10;
-    maxStamina = 10;
-    hunger = 10;
-    maxHunger = 10;
-    thirst = 10;
-    maxThirst = 10;
-    keyState = 0;
-    jumping = 0;
-    faceOffset = { 0.f, 0.f, 1.5f };
-    targetDistanceLimit = 4;
+	for (int i = 0; i < 10; i++)
+	{
+		ItemSlot* slot = new ItemSlot("ItemBar", 50, 0, i, 0, ANY_DIRECTION, 0);
+		itemBar.add(slot);
+		addSlot(slot);
+	}
+	for (int i = 0; i < 30; i++)
+	{
+		ItemSlot* slot = new ItemSlot("Inventory", 50, 0, i + 10, 0, ANY_DIRECTION, 0);
+		addSlot(slot);
+	}
+	leftHandPosition = 0;
+	maxHP = 10;
+	currentHP = 10;
+	stamina = 10;
+	maxStamina = 10;
+	hunger = 10;
+	maxHunger = 10;
+	thirst = 10;
+	maxThirst = 10;
+	keyState = 0;
+	jumping = 0;
+	faceOffset = { 0.f, 0.f, 1.5f };
+	targetDistanceLimit = 4;
 }
 
-void Player::afterPullStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count )
+void Player::afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
 {
-    for( auto slot : itemBar )
-    {
-        if( slot == zSlot )
-        {
-            needUpdate = 1;
-            return;
-        }
-    }
+	for (auto slot : itemBar)
+	{
+		if (slot == zSlot)
+		{
+			needUpdate = 1;
+			return;
+		}
+	}
 }
 
-void Player::afterPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count )
+void Player::afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
 {
-    for( auto slot : itemBar )
-    {
-        if( slot == zSlot )
-        {
-            needUpdate = 1;
-            return;
-        }
-    }
+	for (auto slot : itemBar)
+	{
+		if (slot == zSlot)
+		{
+			needUpdate = 1;
+			return;
+		}
+	}
 }
 
-void Player::useItemSlot( ItemSlot* zSlot )
+Framework::Text Player::getInventoryUIML()
 {
-    if( zSlot->zStack() )
-    {
-        ItemStack* stack = takeItemsOut( zSlot, 1, NO_DIRECTION );
-        if( stack )
-        {
-            Item* item = stack->extractFromStack();
-            Entity::useItem( item->zItemType(), item );
-            if( item->getDurability() > 0 && item->getDamage() < item->getMaxDamage() )
-            { // put used item back
-                stack->addToStack( item );
-                // TODO: use inventory wrapper to update the cache of the inventory
-                if( !zSlot->numberOfAddableItems( stack, NO_DIRECTION ) )
-                { // move other items to other space
-                    ItemStack* oldItems = zSlot->takeItemsOut( zSlot->zStack()->getSize(), NO_DIRECTION );
-                    zSlot->addItems( stack, NO_DIRECTION );
-                    addItems( oldItems, NO_DIRECTION );
-                    if( oldItems->getSize() > 0 )
-                    {
-                        // TODO: drop remaining items
-                    }
-                }
-                else
-                    zSlot->addItems( stack, NO_DIRECTION );
-            }
-            else
-            { // item is broken
-                // move other items of the same type to the slot
-                Array< ItemSlot*> fromSlots;
-                for( ItemSlot* slot : itemBar )
-                {
-                    if( slot != zSlot )
-                        fromSlots.add( slot );
-                }
-                Array<ItemSlot*> targetSlots;
-                targetSlots.add( zSlot );
-                TypeItemFilter filter( item->zItemType() );
-                localTransaction( &fromSlots, &targetSlots, &filter, zSlot->getFreeSpace(), NO_DIRECTION, NO_DIRECTION );
-                // place broken item in inventory
-                const ItemType* brokenType = item->zItemType()->zBrokenItemType();
-                if( brokenType )
-                {
-                    Item* broken = item->zItemType()->breakItem( item );
-                    if( broken )
-                    {
-                        stack->addToStack( broken );
-                        addItems( stack, NO_DIRECTION );
-                        if( stack->getSize() > 0 )
-                        {
-                            // TODO: drop remaining items
-                        }
-                    }
-                }
-                item->release();
-            }
-            stack->release();
-        }
-    }
-    else
-        Entity::useItem( PlayerHandItemType::INSTANCE, 0 ); // hand usage
+	Framework::Text result = "<dialog id=\"player_inventory\" title=\"Inventory\" width=\"610\" height=\"450\">";
+
+	result += "<craftingGrid id=\"crafting\" margin-top=\"9\" align-top=\"start\" align-left=\"start\" margin-left=\"9\" width=\"272\" height=\"172\" rowSize=\"3\" colSize=\"3\" numOutputSlots=\"1\" target=\"";
+	result += getId();
+	result += "\"/>";
+
+	result += "<inventory id=\"inventory\" margin-bottom=\"18\" align-bottom=\"item_bar\" align-left=\"start\" margin-left=\"9\" width=\"592\" height=\"172\" rowSize=\"10\" numSlots=\"30\" slotNameFilter=\"Inventory\" target=\"";
+	result += getId();
+	result += "\"/>";
+
+	result += "<inventory id=\"item_bar\" margin-bottom=\"9\" align-bottom=\"end\" align-left=\"start\" margin-left=\"9\" width=\"592\" height=\"52\" rowSize=\"10\" numSlots=\"10\" slotNameFilter=\"ItemBar\" target=\"";
+	result += getId();
+	result += "\"/>";
+
+	result += "</dialog>";
+	return result;
+}
+
+void Player::useItemSlot(ItemSlot* zSlot)
+{
+	if (zSlot->zStack())
+	{
+		ItemStack* stack = takeItemsOut(zSlot, 1, NO_DIRECTION);
+		if (stack)
+		{
+			Item* item = stack->extractFromStack();
+			Entity::useItem(item->zItemType(), item);
+			if (item->getDurability() > 0 && item->getDamage() < item->getMaxDamage())
+			{ // put used item back
+				stack->addToStack(item);
+				// TODO: use inventory wrapper to update the cache of the inventory
+				if (!zSlot->numberOfAddableItems(stack, NO_DIRECTION))
+				{ // move other items to other space
+					ItemStack* oldItems = zSlot->takeItemsOut(zSlot->zStack()->getSize(), NO_DIRECTION);
+					zSlot->addItems(stack, NO_DIRECTION);
+					addItems(oldItems, NO_DIRECTION);
+					if (oldItems->getSize() > 0)
+					{
+						// TODO: drop remaining items
+					}
+				}
+				else
+					zSlot->addItems(stack, NO_DIRECTION);
+			}
+			else
+			{ // item is broken
+				// move other items of the same type to the slot
+				Array< ItemSlot*> fromSlots;
+				for (ItemSlot* slot : itemBar)
+				{
+					if (slot != zSlot)
+						fromSlots.add(slot);
+				}
+				Array<ItemSlot*> targetSlots;
+				targetSlots.add(zSlot);
+				TypeItemFilter filter(item->zItemType());
+				localTransaction(&fromSlots, &targetSlots, &filter, zSlot->getFreeSpace(), NO_DIRECTION, NO_DIRECTION);
+				// place broken item in inventory
+				const ItemType* brokenType = item->zItemType()->zBrokenItemType();
+				if (brokenType)
+				{
+					Item* broken = item->zItemType()->breakItem(item);
+					if (broken)
+					{
+						stack->addToStack(broken);
+						addItems(stack, NO_DIRECTION);
+						if (stack->getSize() > 0)
+						{
+							// TODO: drop remaining items
+						}
+					}
+				}
+				item->release();
+			}
+			stack->release();
+		}
+	}
+	else
+		Entity::useItem(PlayerHandItemType::INSTANCE, 0); // hand usage
 }
 
-void Player::setName( Framework::Text name )
+void Player::setName(Framework::Text name)
 {
-    this->name = name;
+	this->name = name;
 }
 
 const char* Player::getName() const
 {
-    return name;
+	return name;
 }
 
-void Player::tick( const Dimension* zDimension )
+void Player::tick(const Dimension* zDimension)
 {
-    speed = { 0, 0, speed.z };
-    if( (keyState | Key::MOVE_FRONT) == keyState )
-        speed += {faceDir.x, faceDir.y, 0};
-    if( (keyState | Key::MOVE_BACK) == keyState )
-        speed += {-faceDir.x, -faceDir.y, 0};
-    if( (keyState | Key::MOVE_RIGHT) == keyState )
-    {
-        Vec2<float> norm = { faceDir.x, faceDir.y };
-        norm.CW90().normalize();
-        speed += {norm.x, norm.y, 0};
-    }
-    if( (keyState | Key::MOVE_LEFT) == keyState )
-    {
-        Vec2<float> norm = { faceDir.x, faceDir.y };
-        norm.CCW90().normalize();
-        speed += {norm.x, norm.y, 0};
-    }
-    Vec2<float> norm = { speed.x, speed.y };
-    if( norm.getLengthSq() != 0 )
-    {
-        norm.normalize();
-        speed.x = norm.x * 4.f; // 4 blocks per second movement speed
-        speed.y = norm.y * 4.f;
-    }
-    if( (keyState | Key::MOVE_DOWN) == keyState && gravityMultiplier == 0.f )
-        speed.z = -4.f;
-    if( (keyState | Key::LEFT_HAND_ACTION) == keyState )
-        useItemSlot( itemBar.z( leftHandPosition ) );
-    if( (keyState | Key::RIGHT_HAND_ACTION) == keyState )
-        useItemSlot( itemBar.z( (leftHandPosition + 1) % itemBar.getEintragAnzahl() ) );
-    return Entity::tick( zDimension );
+	speed = { 0, 0, speed.z };
+	if ((keyState | Key::MOVE_FRONT) == keyState)
+		speed += {faceDir.x, faceDir.y, 0};
+	if ((keyState | Key::MOVE_BACK) == keyState)
+		speed += {-faceDir.x, -faceDir.y, 0};
+	if ((keyState | Key::MOVE_RIGHT) == keyState)
+	{
+		Vec2<float> norm = { faceDir.x, faceDir.y };
+		norm.CW90().normalize();
+		speed += {norm.x, norm.y, 0};
+	}
+	if ((keyState | Key::MOVE_LEFT) == keyState)
+	{
+		Vec2<float> norm = { faceDir.x, faceDir.y };
+		norm.CCW90().normalize();
+		speed += {norm.x, norm.y, 0};
+	}
+	Vec2<float> norm = { speed.x, speed.y };
+	if (norm.getLengthSq() != 0)
+	{
+		norm.normalize();
+		speed.x = norm.x * 4.f; // 4 blocks per second movement speed
+		speed.y = norm.y * 4.f;
+	}
+	if ((keyState | Key::MOVE_DOWN) == keyState && gravityMultiplier == 0.f)
+		speed.z = -4.f;
+	if ((keyState | Key::LEFT_HAND_ACTION) == keyState)
+		useItemSlot(itemBar.get(leftHandPosition));
+	if ((keyState | Key::RIGHT_HAND_ACTION) == keyState)
+		useItemSlot(itemBar.get((leftHandPosition + 1) % itemBar.getEintragAnzahl()));
+	return Entity::tick(zDimension);
 }
 
-void Player::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
+void Player::playerApi(Framework::StreamReader* zRequest, NetworkResponse* zResponse)
 {
-    char byte;
-    zRequest->lese( &byte, 1 );
-    switch( byte )
-    {
-    case 0:
-        zRequest->lese( &byte, 1 );
-        switch( byte )
-        {
-        case 0:
-            keyState = keyState & ~Key::MOVE_FRONT;
-            break;
-        case 1:
-            keyState = keyState & ~Key::MOVE_LEFT;
-            break;
-        case 2:
-            keyState = keyState & ~Key::MOVE_BACK;
-            break;
-        case 3:
-            keyState = keyState & ~Key::MOVE_RIGHT;
-            break;
-        case 4:
-            if( gravityMultiplier == 0.f )
-                speed.z = 0;
-            keyState = keyState & ~Key::MOVE_DOWN;
-            break;
-        case 5:
-            keyState = keyState & ~Key::ROTATE_LEFT;
-            break;
-        case 6:
-            keyState = keyState & ~Key::ROTATE_RIGHT;
-            break;
-        case 7:
-            if( gravityMultiplier == 0.f )
-                speed.z = 0;
-            keyState = keyState & ~Key::MOVE_UP;
-            break;
-        case 8:
-            keyState = keyState & ~Key::LEFT_HAND_ACTION;
-            break;
-        case 9:
-            keyState = keyState & ~Key::RIGHT_HAND_ACTION;
-            break;
-        }
-        break;
-    case 1:
-        zRequest->lese( &byte, 1 );
-        switch( byte )
-        {
-        case 0:
-            keyState = keyState | Key::MOVE_FRONT;
-            break;
-        case 1:
-            keyState = keyState | Key::MOVE_LEFT;
-            break;
-        case 2:
-            keyState = keyState | Key::MOVE_BACK;
-            break;
-        case 3:
-            keyState = keyState | Key::MOVE_RIGHT;
-            break;
-        case 4:
-            keyState = keyState | Key::MOVE_DOWN;
-            break;
-        case 5:
-            keyState = keyState | Key::ROTATE_LEFT;
-            break;
-        case 6:
-            keyState = keyState | Key::ROTATE_RIGHT;
-            break;
-        case 7:
-            if( (keyState | Key::MOVE_UP) != keyState )
-            {
-                if( gravityMultiplier > 0 )
-                {
-                    if( jumping )
-                    {
-                        // TODO: check if flight is enabled
-                        gravityMultiplier = 0;
-                        jumping = 0;
-                        speed.z = 1.5f;
-                    }
-                    else
-                    {
-                        jumping = 1;
-                        speed.z = 5.f;
-                    }
-                }
-                else
-                    speed.z = 1.5f;
-            }
-            keyState = keyState | Key::MOVE_UP;
-            break;
-        case 8:
-            keyState = keyState | Key::LEFT_HAND_ACTION;
-            break;
-        case 9:
-            keyState = keyState | Key::RIGHT_HAND_ACTION;
-            break;
-        }
-        break;
-    case 2:
-        zRequest->lese( (char*)&faceDir.x, 4 );
-        zRequest->lese( (char*)&faceDir.y, 4 );
-        zRequest->lese( (char*)&faceDir.z, 4 );
-    case 3:
-        zRequest->lese( (char*)&leftHandPosition, 4 );
-        leftHandPosition = leftHandPosition % itemBar.getEintragAnzahl();
-        needUpdate = 1;
-    }
+	char byte;
+	zRequest->lese(&byte, 1);
+	switch (byte)
+	{
+	case 0:
+		// begin action
+		zRequest->lese(&byte, 1);
+		switch (byte)
+		{
+		case 0:
+			keyState = keyState & ~Key::MOVE_FRONT;
+			break;
+		case 1:
+			keyState = keyState & ~Key::MOVE_LEFT;
+			break;
+		case 2:
+			keyState = keyState & ~Key::MOVE_BACK;
+			break;
+		case 3:
+			keyState = keyState & ~Key::MOVE_RIGHT;
+			break;
+		case 4:
+			if (gravityMultiplier == 0.f)
+				speed.z = 0;
+			keyState = keyState & ~Key::MOVE_DOWN;
+			break;
+		case 5:
+			keyState = keyState & ~Key::ROTATE_LEFT;
+			break;
+		case 6:
+			keyState = keyState & ~Key::ROTATE_RIGHT;
+			break;
+		case 7:
+			if (gravityMultiplier == 0.f)
+				speed.z = 0;
+			keyState = keyState & ~Key::MOVE_UP;
+			break;
+		case 8:
+			keyState = keyState & ~Key::LEFT_HAND_ACTION;
+			break;
+		case 9:
+			keyState = keyState & ~Key::RIGHT_HAND_ACTION;
+			break;
+		}
+		break;
+	case 1:
+		// stop action
+		zRequest->lese(&byte, 1);
+		switch (byte)
+		{
+		case 0:
+			keyState = keyState | Key::MOVE_FRONT;
+			break;
+		case 1:
+			keyState = keyState | Key::MOVE_LEFT;
+			break;
+		case 2:
+			keyState = keyState | Key::MOVE_BACK;
+			break;
+		case 3:
+			keyState = keyState | Key::MOVE_RIGHT;
+			break;
+		case 4:
+			keyState = keyState | Key::MOVE_DOWN;
+			break;
+		case 5:
+			keyState = keyState | Key::ROTATE_LEFT;
+			break;
+		case 6:
+			keyState = keyState | Key::ROTATE_RIGHT;
+			break;
+		case 7:
+			if ((keyState | Key::MOVE_UP) != keyState)
+			{
+				if (gravityMultiplier > 0)
+				{
+					if (jumping)
+					{
+						// TODO: check if flight is enabled
+						gravityMultiplier = 0;
+						jumping = 0;
+						speed.z = 1.5f;
+					}
+					else
+					{
+						jumping = 1;
+						speed.z = 5.f;
+					}
+				}
+				else
+					speed.z = 1.5f;
+			}
+			keyState = keyState | Key::MOVE_UP;
+			break;
+		case 8:
+			keyState = keyState | Key::LEFT_HAND_ACTION;
+			break;
+		case 9:
+			keyState = keyState | Key::RIGHT_HAND_ACTION;
+			break;
+		}
+		break;
+	case 2:
+		// switch target direction
+		zRequest->lese((char*)&faceDir.x, 4);
+		zRequest->lese((char*)&faceDir.y, 4);
+		zRequest->lese((char*)&faceDir.z, 4);
+		break;
+	case 3:
+		// switch item bar position
+		zRequest->lese((char*)&leftHandPosition, 4);
+		leftHandPosition = leftHandPosition % itemBar.getEintragAnzahl();
+		needUpdate = 1;
+		break;
+	case 4:
+	{
+		// open inventory
+		zResponse->openDialog("player_inventory");
+		Text uiml = getInventoryUIML();
+		int msgSize = 5 + uiml.getLength();
+		char* msg = new char[msgSize];
+		msg[0] = 0; // open dialog
+		*(int*)(msg + 1) = uiml.getLength();
+		memcpy(msg + 5, uiml.getText(), uiml.getLength());
+		zResponse->setMessage(msg, msgSize, 1);
+		break;
+	}
+	}
 }
 
-void Player::onFall( float collisionSpeed )
+void Player::onFall(float collisionSpeed)
 {
-    Entity::onFall( collisionSpeed );
-    gravityMultiplier = 1.f;
-    jumping = 0;
+	Entity::onFall(collisionSpeed);
+	gravityMultiplier = 1.f;
+	jumping = 0;
 }
 
 
 
 PlayerEntityType::PlayerEntityType()
-    : EntityType( ID )
+	: EntityType(ID)
 {}
 
-void PlayerEntityType::loadSuperEntity( Entity* zEntity, Framework::StreamReader* zReader ) const
+void PlayerEntityType::loadSuperEntity(Entity* zEntity, Framework::StreamReader* zReader) const
 {
-    Player* zPlayer = dynamic_cast<Player*>(zEntity);
-    if( !zPlayer )
-        throw "PlayerEntityType::loadSuperEntity was called with an entity witch is not an instance of Player";
-    zReader->lese( (char*)&zPlayer->leftHandPosition, 4 );
-    EntityType::loadSuperEntity( zPlayer, zReader );
+	Player* zPlayer = dynamic_cast<Player*>(zEntity);
+	if (!zPlayer)
+		throw "PlayerEntityType::loadSuperEntity was called with an entity witch is not an instance of Player";
+	zReader->lese((char*)&zPlayer->leftHandPosition, 4);
+	EntityType::loadSuperEntity(zPlayer, zReader);
 }
 
-void PlayerEntityType::saveSuperEntity( Entity* zEntity, Framework::StreamWriter* zWriter ) const
+void PlayerEntityType::saveSuperEntity(Entity* zEntity, Framework::StreamWriter* zWriter) const
 {
-    Player* zPlayer = dynamic_cast<Player*>(zEntity);
-    if( !zPlayer )
-        throw "PlayerEntityType::saveSuperEntity was called with an entity witch is not an instance of Player";
-    zWriter->schreibe( (char*)&zPlayer->leftHandPosition, 4 );
-    EntityType::saveSuperEntity( zEntity, zWriter );
+	Player* zPlayer = dynamic_cast<Player*>(zEntity);
+	if (!zPlayer)
+		throw "PlayerEntityType::saveSuperEntity was called with an entity witch is not an instance of Player";
+	zWriter->schreibe((char*)&zPlayer->leftHandPosition, 4);
+	EntityType::saveSuperEntity(zEntity, zWriter);
 }
 
-Entity* PlayerEntityType::createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const
+Entity* PlayerEntityType::createEntity(Framework::Vec3<float> position, int dimensionId, int entityId) const
 {
-    return new Player( position, dimensionId, entityId );
+	return new Player(position, dimensionId, entityId);
 }

+ 37 - 35
FactoryCraft/Player.h

@@ -10,57 +10,59 @@ class PlayerEntityType;
 class Player : public Entity, public BasicShapedCrafter
 {
 public:
-    class Key
-    {
-    public:
-        const static __int64 MOVE_FRONT = 0x1;
-        const static __int64 MOVE_BACK = 0x2;
-        const static __int64 MOVE_LEFT = 0x4;
-        const static __int64 MOVE_RIGHT = 0x8;
-        const static __int64 MOVE_UP = 0x10;
-        const static __int64 MOVE_DOWN = 0x20;
-        const static __int64 ROTATE_LEFT = 0x40;
-        const static __int64 ROTATE_RIGHT = 0x80;
-        const static __int64 LEFT_HAND_ACTION = 0x100;
-        const static __int64 RIGHT_HAND_ACTION = 0x200;
-    };
+	class Key
+	{
+	public:
+		const static __int64 MOVE_FRONT = 0x1;
+		const static __int64 MOVE_BACK = 0x2;
+		const static __int64 MOVE_LEFT = 0x4;
+		const static __int64 MOVE_RIGHT = 0x8;
+		const static __int64 MOVE_UP = 0x10;
+		const static __int64 MOVE_DOWN = 0x20;
+		const static __int64 ROTATE_LEFT = 0x40;
+		const static __int64 ROTATE_RIGHT = 0x80;
+		const static __int64 LEFT_HAND_ACTION = 0x100;
+		const static __int64 RIGHT_HAND_ACTION = 0x200;
+	};
 
 private:
-    Framework::Text name;
-    Framework::RCArray<ItemSlot> itemBar;
-    int leftHandPosition;
-    bool jumping;
-    __int64 keyState;
+	Framework::Text name;
+	Framework::Array<ItemSlot*> itemBar;
+	Framework::Array<ItemSlot*> crafting;
+	int leftHandPosition;
+	bool jumping;
+	__int64 keyState;
 
-    void useItemSlot( ItemSlot* zSlot );
-    Player( Framework::Vec3<float> location, int dimensionId, int entityId );
+	void useItemSlot(ItemSlot* zSlot);
+	Player(Framework::Vec3<float> location, int dimensionId, int entityId);
 
-    virtual void afterPullStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count ) override;
-    virtual void afterPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count ) override;
+	virtual void afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count) override;
+	virtual void afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count) override;
+	Framework::Text getInventoryUIML();
 
 public:
-    void setName( Framework::Text name );
-    const char* getName() const;
-    void tick( const Dimension* zDimension ) override;
+	void setName(Framework::Text name);
+	const char* getName() const;
+	void tick(const Dimension* zDimension) override;
 
-    void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse ) override;
-    void onFall( float collisionSpeed ) override;
+	void playerApi(Framework::StreamReader* zRequest, NetworkResponse* zResponse);
+	void onFall(float collisionSpeed) override;
 
-    friend PlayerEntityType;
+	friend PlayerEntityType;
 };
 
 class PlayerEntityType : public EntityType
 {
-    REGISTRABLE( PlayerEntityType )
+	REGISTRABLE(PlayerEntityType)
 
 protected:
-    virtual void loadSuperEntity( Entity* zEntity, Framework::StreamReader* zReader ) const override;
-    virtual void saveSuperEntity( Entity* zEntity, Framework::StreamWriter* zWriter ) const override;
+	virtual void loadSuperEntity(Entity* zEntity, Framework::StreamReader* zReader) const override;
+	virtual void saveSuperEntity(Entity* zEntity, Framework::StreamWriter* zWriter) const override;
 
 public:
-    PlayerEntityType();
+	PlayerEntityType();
 
-    virtual Entity* createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const override;
+	virtual Entity* createEntity(Framework::Vec3<float> position, int dimensionId, int entityId) const override;
 };
 
-REGISTER( PlayerEntityType, EntityType )
+REGISTER(PlayerEntityType, EntityType)

+ 11 - 11
FactoryCraft/RecipieLoader.cpp

@@ -64,11 +64,11 @@ void RecipieLoader::loadRecipie(JSONObject* zRecipie)
 		int outputCount = (int)zRecipie->asObject()->zValue("outputCount")->asNumber()->getNumber();
 		Framework::Text outputType = zRecipie->asObject()->zValue("output")->asObject()->zValue("itemType")->asString()->getString();
 		Item* item = 0;
-		for (ItemType& t : StaticRegistry<ItemType>::INSTANCE)
+		for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
 		{
-			if (t.getName().istGleich(outputType))
+			if (StaticRegistry<ItemType>::INSTANCE.zElement(i)->getName().istGleich(outputType))
 			{
-				item = t.createItem();
+				item = StaticRegistry<ItemType>::INSTANCE.zElement(i)->createItem();
 				break;
 			}
 		}
@@ -91,11 +91,11 @@ void RecipieLoader::loadRecipie(JSONObject* zRecipie)
 			int count = (int)output->asObject()->zValue("count")->asNumber()->getNumber();
 			Framework::Text outputType = output->asObject()->zValue("item")->asObject()->zValue("itemType")->asString()->getString();
 			Item* item = 0;
-			for (ItemType& t : StaticRegistry<ItemType>::INSTANCE)
+			for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
 			{
-				if (t.getName().istGleich(outputType))
+				if (StaticRegistry<ItemType>::INSTANCE.zElement(i)->getName().istGleich(outputType))
 				{
-					item = t.createItem();
+					item = StaticRegistry<ItemType>::INSTANCE.zElement(i)->createItem();
 					break;
 				}
 			}
@@ -110,10 +110,10 @@ void RecipieLoader::loadRecipie(JSONObject* zRecipie)
 ItemFilter* RecipieLoader::loadFilter(JSONObject* zFilter)
 {
 	Framework::Text type = zFilter->zValue("itemType")->asString()->getString();
-	for (const ItemType& t : StaticRegistry<ItemType>::INSTANCE)
+	for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
 	{
-		if (t.getName().istGleich(type))
-			return new TypeItemFilter(&t);
+		if (StaticRegistry<ItemType>::INSTANCE.zElement(i)->getName().istGleich(type))
+			return new TypeItemFilter(StaticRegistry<ItemType>::INSTANCE.zElement(i));
 	}
 	return 0;
 }
@@ -157,8 +157,8 @@ JSONValidator* RecipieLoader::zRecipieValidator()
 	if (validator)
 		return validator;
 	Framework::RCArray<Framework::Text> itemTypes;
-	for (ItemType& t : StaticRegistry<ItemType>::INSTANCE)
-		itemTypes.add(new Framework::Text(t.getName().getText()));
+	for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
+		itemTypes.add(new Framework::Text(StaticRegistry<ItemType>::INSTANCE.zElement(i)->getName().getText()));
 	JSONValidator* filterValidator = JSONValidator::buildForObject()
 		->withRequiredString("itemType")->whichIsOneOf(itemTypes)->finishString()
 		->finishObject();

+ 0 - 10
FactoryCraft/StaticRegistry.h

@@ -75,16 +75,6 @@ public:
 		return 1;
 	}
 
-	T* begin() const
-	{
-		return *registry;
-	}
-
-	T* end() const
-	{
-		return *(registry + count);
-	}
-
 	friend T;
 };