Browse Source

playerHands can now make damage on some blocks and block updates will be send

Kolja Strohm 3 years ago
parent
commit
fb9d1f19f0

+ 3 - 3
FactoryCraft/BasicBlock.cpp

@@ -17,7 +17,7 @@ void BasicBlock::onPostTick()
 DirtBlockType::DirtBlockType()
     : BlockType( ID, 0 )
 {
-    defaultBlock = createBlockAt( { 0, 0, 0 }, 0, 0 );
+    defaultBlock = createBlockAt( { 0, 0, 0 }, 0 );
 }
 
 void DirtBlockType::loadSuperBlock( Block* zBlock, Framework::StreamReader* zReader ) const
@@ -55,12 +55,12 @@ void DirtBlockType::createSuperItem( Block* zBlock, Item* zItem ) const
     BlockType::createSuperItem( zBlock, zItem );
 }
 
-Block* DirtBlockType::createBlock( Framework::Vec3<int> position, Game* zTarget ) const
+Block* DirtBlockType::createBlock( Framework::Vec3<int> position ) const
 {
     return new BasicBlock( this, 0, position ); // TODO: add efective tool
 }
 
-Item* DirtBlockType::createItem( Game* zTarget ) const
+Item* DirtBlockType::createItem() const
 {
     return StaticRegistry<ItemType>::INSTANCE.zElement( DirtBlockItemType::ID )->createItem();
 }

+ 2 - 2
FactoryCraft/BasicBlocks.h

@@ -28,8 +28,8 @@ protected:
     virtual void saveSuperBlock( Block* zBlock, Framework::StreamWriter* zWriter ) const override;
     virtual void createSuperBlock( Block* zBlock, Item* zItem ) const override;
     virtual void createSuperItem( Block* zBlock, Item* zItem ) const override;
-    virtual Block* createBlock( Framework::Vec3<int> position, Game* zTarget ) const override;
-    virtual Item* createItem( Game* zTarget ) const override;
+    virtual Block* createBlock( Framework::Vec3<int> position ) const override;
+    virtual Item* createItem() const override;
     DirtBlockType();
 };
 REGISTER( DirtBlockType, BlockType )

+ 1 - 2
FactoryCraft/BiomGenerator.h

@@ -5,12 +5,11 @@
 
 class Block;
 class Noise;
-class Game;
 
 class BiomGenerator : public virtual Framework::ReferenceCounter
 {
 public:
     BiomGenerator();
-    virtual Framework::Either<Block*, int> getBlock( int x, int y, int z, Game* zGame ) = 0;
+    virtual Framework::Either<Block*, int> getBlock( int x, int y, int z ) = 0;
     virtual Noise* zHeightMapNoise( int seed ) = 0;
 };

+ 22 - 0
FactoryCraft/Block.cpp

@@ -1,6 +1,8 @@
 #include "Block.h"
 #include "Inventory.h"
 #include "NoBlock.h"
+#include "Game.h"
+#include "BlockChangedUpdate.h"
 
 Block::Block( const BlockType* zType, ItemType* zTool, Framework::Vec3<int> pos, bool hasInventory )
     : Inventory( pos, hasInventory )
@@ -173,6 +175,26 @@ bool Block::isVisible() const
     return 0;
 }
 
+void Block::setHP( float hp )
+{
+    this->hp = MAX( 0, hp );
+    requestTransmission();
+}
+
+void Block::onAfterTransmission()
+{
+    transmissionRequested = 0;
+}
+
+void Block::requestTransmission()
+{
+    if( !transmissionRequested )
+    {
+        transmissionRequested = 1;
+        Game::INSTANCE->requestWorldUpdate( new BlockChangedUpdate( (Framework::Vec3<int>)location, getDimensionId() ) );
+    }
+}
+
 
 BasicBlockItem::BasicBlockItem( const ItemType* zType, const BlockType* zPlacedBlockType, const char* name )
     : Item( zType, name )

+ 4 - 0
FactoryCraft/Block.h

@@ -43,6 +43,7 @@ protected:
     int maxTickTimeout;
     bool tickSource;
     bool interactable;
+    bool transmissionRequested;
 
     /// <summary>
     /// executes block specific things
@@ -84,6 +85,9 @@ public:
     const Framework::Vec3<int> getPos() const;
     int getDimensionId() const;
     bool isVisible() const;
+    void setHP( float hp );
+    void onAfterTransmission();
+    void requestTransmission();
 
     friend BlockType;
 };

+ 47 - 0
FactoryCraft/BlockChangedUpdate.cpp

@@ -0,0 +1,47 @@
+#include "BlockChangedUpdate.h"
+#include "Game.h"
+
+
+BlockChangedUpdate::BlockChangedUpdate( Framework::Vec3<int> pos, int dimension )
+    : WorldUpdate( BlockChangedUpdateType::ID, dimension, pos, pos )
+{}
+
+BlockChangedUpdate::~BlockChangedUpdate()
+{
+    auto b = Game::INSTANCE->zBlockAt( getMinAffectedPoint(), getAffectedDimension() );
+    if( b.isA() && b.getA() )
+        b.getA()->onAfterTransmission();
+}
+
+void BlockChangedUpdate::onUpdate( Dimension* zDimension )
+{}
+
+void BlockChangedUpdate::write( Framework::StreamWriter* zWriter )
+{
+    zWriter->schreibe( (char*)&BlockChangedUpdateType::ID, 4 );
+    int dimensionID = getAffectedDimension();
+    zWriter->schreibe( (char*)&dimensionID, 4 );
+    auto pos = getMinAffectedPoint();
+    zWriter->schreibe( (char*)&pos.x, 4 );
+    zWriter->schreibe( (char*)&pos.y, 4 );
+    zWriter->schreibe( (char*)&pos.z, 4 );
+    auto b = Game::INSTANCE->zBlockAt( getMinAffectedPoint(), getAffectedDimension() );
+    unsigned short blockType = b.isA() ? (unsigned short)b.getA()->zBlockType()->getId() : (unsigned short)b.getB();
+    zWriter->schreibe( (char*)&blockType, 2 );
+    if( b.isA() )
+    {
+        bool d = 1;
+        zWriter->schreibe( (char*)&d, 1 );
+        StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->saveBlock( b.getA(), zWriter );
+    }
+    else
+    {
+        bool d = 0;
+        zWriter->schreibe( (char*)&d, 1 );
+    }
+}
+
+
+BlockChangedUpdateType::BlockChangedUpdateType()
+    : WorldUpdateType( ID )
+{}

+ 21 - 0
FactoryCraft/BlockChangedUpdate.h

@@ -0,0 +1,21 @@
+#pragma once
+#include "WorldUpdate.h"
+
+class BlockChangedUpdate : public WorldUpdate
+{
+public:
+    BlockChangedUpdate( Framework::Vec3<int> pos, int dimension );
+    ~BlockChangedUpdate();
+
+    void onUpdate( Dimension* zDimension ) override;
+    void write( Framework::StreamWriter* zWriter ) override;
+};
+
+class BlockChangedUpdateType : WorldUpdateType
+{
+    REGISTRABLE( BlockChangedUpdateType )
+
+protected:
+    BlockChangedUpdateType();
+};
+REGISTER( BlockChangedUpdateType, WorldUpdateType )

+ 6 - 6
FactoryCraft/BlockType.cpp

@@ -81,9 +81,9 @@ void BlockType::createSuperItem( Block* zBlock, Item* zItem ) const
     item->toolId = zBlock->zTool->getId();
 }
 
-Block* BlockType::loadBlock( Framework::Vec3<int> position, Game* zTarget, Framework::StreamReader* zReader ) const
+Block* BlockType::loadBlock( Framework::Vec3<int> position, Framework::StreamReader* zReader ) const
 {
-    Block* result = createBlock( position, zTarget );
+    Block* result = createBlock( position );
     loadSuperBlock( result, zReader );
     return result;
 }
@@ -93,16 +93,16 @@ void BlockType::saveBlock( Block* zBlock, Framework::StreamWriter* zWriter ) con
     saveSuperBlock( zBlock, zWriter );
 }
 
-Item* BlockType::getItemFromBlock( Block* zBlock, Game* zTarget ) const
+Item* BlockType::getItemFromBlock( Block* zBlock ) const
 {
-    Item* result = createItem( zTarget );
+    Item* result = createItem();
     createSuperItem( zBlock, result );
     return result;
 }
 
-Block* BlockType::createBlockAt( Framework::Vec3<int> position, Game* zTarget, Item* zUsedItem ) const
+Block* BlockType::createBlockAt( Framework::Vec3<int> position, Item* zUsedItem ) const
 {
-    Block* result = createBlock( position, zTarget );
+    Block* result = createBlock( position );
     createSuperBlock( result, zUsedItem );
     return result;
 }

+ 5 - 6
FactoryCraft/BlockType.h

@@ -7,7 +7,6 @@
 
 #include "StaticRegistry.h"
 
-class Game;
 class Item;
 class Block;
 
@@ -25,14 +24,14 @@ protected:
     virtual void saveSuperBlock( Block* zBlock, Framework::StreamWriter* zWriter ) const;
     virtual void createSuperBlock( Block* zBlock, Item* zItem ) const;
     virtual void createSuperItem( Block* zBlock, Item* zItem ) const;
-    virtual Block* createBlock( Framework::Vec3<int> position, Game* zTarget ) const = 0;
-    virtual Item* createItem( Game* zTarget ) const = 0;
+    virtual Block* createBlock( Framework::Vec3<int> position ) const = 0;
+    virtual Item* createItem() const = 0;
 
 public:
-    virtual Block* loadBlock( Framework::Vec3<int> position, Game* zTarget, Framework::StreamReader* zReader ) const;
+    virtual Block* loadBlock( Framework::Vec3<int> position, Framework::StreamReader* zReader ) const;
     virtual void saveBlock( Block* zBlock, Framework::StreamWriter* zWriter ) const;
-    virtual Item* getItemFromBlock( Block* zBlock, Game* zTarget ) const;
-    virtual Block* createBlockAt( Framework::Vec3<int> position, Game* zTarget, Item* zUsedItem ) const;
+    virtual Item* getItemFromBlock( Block* zBlock ) const;
+    virtual Block* createBlockAt( Framework::Vec3<int> position, Item* zUsedItem ) const;
     virtual const Block* zDefault() const;
     int getId() const;
 };

+ 16 - 22
FactoryCraft/Chunk.cpp

@@ -4,9 +4,8 @@
 #include "NoBlock.h"
 
 
-Chunk::Chunk( Framework::Punkt location, Game* zGame, int dimensionId )
+Chunk::Chunk( Framework::Punkt location, int dimensionId )
     : ReferenceCounter(),
-    zGame( zGame ),
     dimensionId( dimensionId ),
     location( location ),
     added( 0 )
@@ -21,8 +20,8 @@ Chunk::Chunk( Framework::Punkt location, Game* zGame, int dimensionId )
     zNeighbours[ 3 ] = 0;
 }
 
-Chunk::Chunk( Framework::Punkt location, Game* zGame, int dimensionId, Framework::StreamReader* zReader )
-    : Chunk( location, zGame, dimensionId )
+Chunk::Chunk( Framework::Punkt location, int dimensionId, Framework::StreamReader* zReader )
+    : Chunk( location, dimensionId )
 {
     load( zReader );
 }
@@ -49,7 +48,7 @@ Framework::Either<Block*, int> Chunk::zBlockNeighbor( Framework::Vec3<int> locat
             return (int)blockIds[ index ];
     }
     if( added && location.z >= 0 && location.z < WORLD_HEIGHT )
-        return zGame->zBlockAt( { location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId );
+        return Game::INSTANCE->zBlockAt( { location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId );
     return 0;
 }
 
@@ -70,24 +69,24 @@ Framework::Either<Block*, int> Chunk::zBlockAt( Framework::Vec3<int> location )
 
 const Block* Chunk::zBlockConst( Framework::Vec3<int> location ) const
 {
-    Block* b = zBlockAt( location );
-    if( b )
+    auto b = zBlockAt( location );
+    if( b.isA() )
         return b;
-    int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
-    if( blockIds[ index ] )
-        return StaticRegistry<BlockType>::INSTANCE.zElement( blockIds[ index ] )->zDefault();
+    if( b.getB() )
+        return StaticRegistry<BlockType>::INSTANCE.zElement( b.getB() )->zDefault();
     return 0;
 }
 
 void Chunk::instantiateBlock( Framework::Vec3<int> location )
 {
-    if( zBlockAt( location ) )
+    auto b = zBlockAt( location );
+    if( b.isA() )
         return;
-    int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
-    if( !blockIds[ index ] )
+    if( !b.getB() )
         generateBlock( location );
-    if( !zBlockAt( location ) )
-        putBlockAt( location, StaticRegistry<BlockType>::INSTANCE.zElement( blockIds[ index ] )->createBlockAt( location, zGame, 0 ) );
+    b = zBlockAt( location );
+    if( b.isB() )
+        putBlockAt( location, StaticRegistry<BlockType>::INSTANCE.zElement( b.getB() )->createBlockAt( location, 0 ) );
 }
 
 void Chunk::generateBlock( Framework::Vec3<int> location )
@@ -95,7 +94,7 @@ void Chunk::generateBlock( Framework::Vec3<int> location )
     int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
     if( blockIds[ index ] )
         return;
-    auto generated = zGame->zGenerator()->generateSingleBlock( location, dimensionId );
+    auto generated = Game::INSTANCE->zGenerator()->generateSingleBlock( location, dimensionId );
     if( generated.isA() )
         putBlockAt( location, generated );
     else
@@ -253,7 +252,7 @@ void Chunk::load( Framework::StreamReader* zReader )
         zReader->lese( (char*)&pos.z, 4 );
         zReader->lese( (char*)&d, 1 );
         if( d )
-            putBlockAt( pos, StaticRegistry<BlockType>::INSTANCE.zElement( id )->loadBlock( Framework::Vec3<int>( pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z ), zGame, zReader ) );
+            putBlockAt( pos, StaticRegistry<BlockType>::INSTANCE.zElement( id )->loadBlock( Framework::Vec3<int>( pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z ), zReader ) );
         else
             putBlockTypeAt( pos, id );
 
@@ -391,11 +390,6 @@ Framework::Vec3<int> Chunk::getMax() const
     return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
 }
 
-Game* Chunk::zGameObj() const
-{
-    return zGame;
-}
-
 void Chunk::prepareRemove()
 {
     added = 0;

+ 2 - 5
FactoryCraft/Chunk.h

@@ -8,12 +8,10 @@
 #include <Punkt.h>
 #include <Either.h>
 
-class Game;
 
 class Chunk : public virtual Framework::ReferenceCounter
 {
 private:
-    Game* zGame;
     int dimensionId;
     Framework::Punkt location;
     Block** blocks;
@@ -25,8 +23,8 @@ private:
     Framework::Array<Entity*> views;
 
 public:
-    Chunk( Framework::Punkt location, Game* zGame, int dimensionId );
-    Chunk( Framework::Punkt location, Game* zGame, int dimensionId, Framework::StreamReader* zReader );
+    Chunk( Framework::Punkt location, int dimensionId );
+    Chunk( Framework::Punkt location, int dimensionId, Framework::StreamReader* zReader );
     ~Chunk();
 
     void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse );
@@ -45,7 +43,6 @@ public:
     Framework::Punkt getCenter() const;
     Framework::Vec3<int> getMin() const;
     Framework::Vec3<int> getMax() const;
-    Game* zGameObj() const;
     void prepareRemove();
     void setAdded();
     void addView( Entity* zEntity );

+ 7 - 7
FactoryCraft/Dimension.cpp

@@ -24,19 +24,19 @@ void Dimension::api( Framework::StreamReader* zRequest, NetworkResponse* zRespon
     // TODO: switch type chunck, block, entity
 }
 
-void Dimension::tickEntities( Game* zGame )
+void Dimension::tickEntities()
 {
     for( auto entity : *entities )
     {
         if( zChunk( Punkt( (int)entity->getPosition().x, (int)entity->getPosition().y ) ) )
-            entity->prepareTick( this, zGame );
+            entity->prepareTick( this );
     }
     int index = 0;
     Array<int> removed;
     for( auto entity : *entities )
     {
         if( zChunk( Punkt( (int)entity->getPosition().x, (int)entity->getPosition().y ) ) )
-            entity->tick( this, zGame );
+            entity->tick( this );
         if( entity->isRemoved() )
             removed.add( index, 0 );
         index++;
@@ -68,9 +68,9 @@ Chunk* Dimension::zChunk( Punkt wPos ) const
     return chunks->z( addr, 8 );
 }
 
-Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location, const Game* zGame )
+Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location )
 {
-    Chunk* c = zChunk( zGame->getChunkCenter( location.x, location.y ) );
+    Chunk* c = zChunk( Game::INSTANCE->getChunkCenter( location.x, location.y ) );
     if( c )
     {
         int x = location.x % CHUNK_SIZE;
@@ -84,9 +84,9 @@ Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location, const Game
     return 0;
 }
 
-Block* Dimension::zRealBlockInstance( Framework::Vec3<int> location, Game* zGame )
+Block* Dimension::zRealBlockInstance( Framework::Vec3<int> location )
 {
-    Chunk* c = zChunk( zGame->getChunkCenter( location.x, location.y ) );
+    Chunk* c = zChunk( Game::INSTANCE->getChunkCenter( location.x, location.y ) );
     if( c )
     {
         int x = location.x % CHUNK_SIZE;

+ 3 - 3
FactoryCraft/Dimension.h

@@ -22,10 +22,10 @@ public:
     ~Dimension();
 
     void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse );
-    void tickEntities( Game* zGame );
+    void tickEntities();
 
-    Framework::Either<Block*, int> zBlock( Framework::Vec3<int> location, const Game* zGame );
-    Block* zRealBlockInstance( Framework::Vec3<int> location, Game* zGame );
+    Framework::Either<Block*, int> zBlock( Framework::Vec3<int> location );
+    Block* zRealBlockInstance( Framework::Vec3<int> location );
     void placeBlock( Block* block );
     void addEntity( Entity* entity );
     void setChunk( Chunk* chunk, Framework::Punkt center );

+ 5 - 5
FactoryCraft/DimensionGenerator.cpp

@@ -37,10 +37,10 @@ void DimensionGenerator::registerBiom( BiomGenerator* generator, double possibil
     biomDistribution.add( possibility );
 }
 
-Chunk* DimensionGenerator::generateChunk( int seed, Game* zGame, int centerX, int centerY )
+Chunk* DimensionGenerator::generateChunk( int seed, int centerX, int centerY )
 {
     std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
-    Chunk* chunk = new Chunk( Framework::Punkt( centerX, centerY ), zGame, dimensionId );
+    Chunk* chunk = new Chunk( Framework::Punkt( centerX, centerY ), dimensionId );
     for( int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++ )
     {
         for( int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++ )
@@ -52,7 +52,7 @@ Chunk* DimensionGenerator::generateChunk( int seed, Game* zGame, int centerX, in
             {
                 Framework::Either<Block*, int> generated = AirBlockBlockType::ID;
                 if( z < height )
-                    generated = biom->getBlock( x + centerX, y + centerY, z, zGame );
+                    generated = biom->getBlock( x + centerX, y + centerY, z );
                 if( generated.isA() )
                     chunk->putBlockAt( Framework::Vec3<int>( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), generated );
                 else
@@ -63,13 +63,13 @@ Chunk* DimensionGenerator::generateChunk( int seed, Game* zGame, int centerX, in
     return chunk;
 }
 
-Framework::Either<Block*, int> DimensionGenerator::generateBlock( int seed, Game* zGame, Framework::Vec3<int> location )
+Framework::Either<Block*, int> DimensionGenerator::generateBlock( int seed, Framework::Vec3<int> location )
 {
     BiomGenerator* biom = zBiomGenerator( seed + dimensionId, location.x, location.y );
     // TODO: use Noise interpolator for height map between different bioms
     int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise( seed + dimensionId )->getNoise( (double)(location.x), (double)(location.y), 0.0 ) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
     if( location.z < height )
-        return biom->getBlock( location.x, location.y, location.z, zGame );
+        return biom->getBlock( location.x, location.y, location.z );
     return AirBlockBlockType::ID;
 }
 

+ 2 - 2
FactoryCraft/DimensionGenerator.h

@@ -22,8 +22,8 @@ protected:
     void registerBiom( BiomGenerator* generator, double possibility );
 
 public:
-    Chunk* generateChunk( int seed, Game* zGame, int centerX, int centerY );
-    Framework::Either<Block*, int> generateBlock( int seed, Game* zGame, Framework::Vec3<int> location );
+    Chunk* generateChunk( int seed, int centerX, int centerY );
+    Framework::Either<Block*, int> generateBlock( int seed, Framework::Vec3<int> location );
     int getDimensionId() const;
     virtual Noise* zBiomNoise( int seed ) = 0;
 };

+ 17 - 17
FactoryCraft/Entity.cpp

@@ -15,7 +15,7 @@ ActionTarget::ActionTarget( int entityId )
     : entityId( entityId )
 {}
 
-void ActionTarget::applyItemSkillOnTarget( Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem, Game* zGame )
+void ActionTarget::applyItemSkillOnTarget( Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem )
 {
     if( entityId >= 0 )
     {
@@ -23,19 +23,19 @@ void ActionTarget::applyItemSkillOnTarget( Entity* zActor, ItemSkill* zItemSkill
     }
     else
     {
-        Block* block = zGame->zRealBlockInstance( blockPos, zActor->getCurrentDimensionId() );
+        Block* block = Game::INSTANCE->zRealBlockInstance( blockPos, zActor->getCurrentDimensionId() );
         if( block )
             zItemSkill->use( zActor, zUsedItem, block );
     }
 }
 
-void ActionTarget::placeBlock( Entity* zActor, Item* zItem, Game* zGame )
+void ActionTarget::placeBlock( Entity* zActor, Item* zItem )
 {
     // TODO: check stamina of actor
-    Block* block = zItem->zPlacedBlockType()->createBlockAt( blockPos + getDirection( targetBlockSide ), zGame, zItem );
+    Block* block = zItem->zPlacedBlockType()->createBlockAt( blockPos + getDirection( targetBlockSide ), zItem );
     if( block )
     {
-        if( zGame->requestWorldUpdate( new PlaceBlockUpdate( block, zActor->getCurrentDimensionId() ) ) )
+        if( Game::INSTANCE->requestWorldUpdate( new PlaceBlockUpdate( block, zActor->getCurrentDimensionId() ) ) )
         {
             zItem->onPlaced();
             // TODO: decrese stamina of actor
@@ -78,7 +78,7 @@ Entity::Entity( const EntityType* zType, Framework::Vec3<float> location, int di
 void Entity::onDeath()
 {}
 
-void Entity::useItem( const ItemType* zType, Item* zItem, Game* zGame )
+void Entity::useItem( const ItemType* zType, Item* zItem )
 {
     if( zItem && zItem->isEatable() )
     { // TODO: eat item
@@ -87,7 +87,7 @@ void Entity::useItem( const ItemType* zType, Item* zItem, Game* zGame )
     else if( zItem && zItem->isPlaceable() )
     { // TODO: place item
         if( target )
-            target->placeBlock( this, zItem, zGame );
+            target->placeBlock( this, zItem );
     }
     else if( !zItem || zItem->isUsable() )
     { // use item skill
@@ -107,12 +107,12 @@ void Entity::useItem( const ItemType* zType, Item* zItem, Game* zGame )
                 selected = zType->createDefaultItemSkill();
                 skills.add( selected );
             }
-            target->applyItemSkillOnTarget( this, selected, zItem, zGame );
+            target->applyItemSkillOnTarget( this, selected, zItem );
         }
     }
 }
 
-void Entity::prepareTick( const Dimension* zDimension, Game* zGame )
+void Entity::prepareTick( const Dimension* zDimension )
 {
     Vec3<float> headPosition = location + faceOffset;
     int px = (int)floor( headPosition.x );
@@ -122,7 +122,7 @@ void Entity::prepareTick( const Dimension* zDimension, Game* zGame )
     Direction dir = BOTTOM;
     while( true )
     {
-        if( getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px, py, pz }, zDimension->getDimensionId() ) )->isInteractable() )
+        if( getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py, pz }, zDimension->getDimensionId() ) )->isInteractable() )
         {
             delete target;
             target = new ActionTarget( { px, py, pz }, dir );
@@ -201,7 +201,7 @@ void Entity::prepareTick( const Dimension* zDimension, Game* zGame )
     }
 }
 
-void Entity::tick( const Dimension* zDimension, Game* zGame )
+void Entity::tick( const Dimension* zDimension )
 {
     Vec3<float> oldPos = location;
     // current block cooredinates
@@ -224,7 +224,7 @@ void Entity::tick( const Dimension* zDimension, Game* zGame )
             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( zGame->zBlockAt( Vec3<int>{ px + 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
+                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px + 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
                 {
                     frameSpeed.x = frameSpeed.x * (xt - 0.1f);
                     speed.x = 0;
@@ -241,7 +241,7 @@ void Entity::tick( const Dimension* zDimension, Game* zGame )
             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( zGame->zBlockAt( Vec3<int>{ px - 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
+                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px - 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
                 {
                     frameSpeed.x = frameSpeed.x * (xt - 0.1f);
                     speed.x = 0;
@@ -258,7 +258,7 @@ void Entity::tick( const Dimension* zDimension, Game* zGame )
             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( zGame->zBlockAt( Vec3<int>{ px, py + 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
+                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py + 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
                 {
                     frameSpeed.y = frameSpeed.y * (yt - 0.1f);
                     speed.y = 0;
@@ -275,7 +275,7 @@ void Entity::tick( const Dimension* zDimension, Game* zGame )
             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( zGame->zBlockAt( Vec3<int>{ px, py - 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
+                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py - 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
                 {
                     frameSpeed.y = frameSpeed.y * (yt - 0.1f);
                     speed.y = 0;
@@ -292,7 +292,7 @@ void Entity::tick( const Dimension* zDimension, Game* zGame )
             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( zGame->zBlockAt( Vec3<int>{ px, py, pz + 1 }, zDimension->getDimensionId() ) )->isPassable() )
+                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py, pz + 1 }, zDimension->getDimensionId() ) )->isPassable() )
                 {
                     frameSpeed.z = frameSpeed.z * (zt - 0.1f);
                     speed.z = 0;
@@ -309,7 +309,7 @@ void Entity::tick( const Dimension* zDimension, Game* zGame )
             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( zGame->zBlockAt( Vec3<int>{ px, py, pz - 1 }, zDimension->getDimensionId() ) )->isPassable() )
+                if( !getDefaultBlock( Game::INSTANCE->zBlockAt( Vec3<int>{ px, py, pz - 1 }, zDimension->getDimensionId() ) )->isPassable() )
                 {
                     frameSpeed.z = frameSpeed.z * (zt - 0.1f);
                     onFall( speed.z );

+ 5 - 6
FactoryCraft/Entity.h

@@ -11,7 +11,6 @@
 
 class EntityType;
 class Dimension;
-class Game;
 class ItemSkill;
 
 class ActionTarget
@@ -25,8 +24,8 @@ public:
     ActionTarget( Framework::Vec3<int> blockPos, Direction blockSide );
     ActionTarget( int entityId );
 
-    void applyItemSkillOnTarget( Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem, Game* zGame );
-    void placeBlock( Entity* zActor, Item* zItem, Game* zGame );
+    void applyItemSkillOnTarget( Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem );
+    void placeBlock( Entity* zActor, Item* zItem );
     void save( Framework::StreamWriter* zWriter ) const;
 };
 
@@ -54,12 +53,12 @@ protected:
     int id;
 
     virtual void onDeath();
-    virtual void useItem( const ItemType* zType, Item* zItem, Game* zGame );
+    virtual void useItem( const ItemType* zType, Item* zItem );
     Entity( const EntityType* zType, Framework::Vec3<float> location, int dimensionId, int entityId );
 
 public:
-    void prepareTick( const Dimension* zDimension, Game* zGame );
-    virtual void tick( const Dimension* zDimension, Game* zGame );
+    void prepareTick( const Dimension* zDimension );
+    virtual void tick( const Dimension* zDimension );
 
     virtual void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse );
 

+ 4 - 4
FactoryCraft/EntityType.cpp

@@ -52,9 +52,9 @@ void EntityType::saveSuperEntity( Entity* zEntity, Framework::StreamWriter* zWri
 void EntityType::createSuperEntity( Entity* zEntity ) const
 {}
 
-Entity* EntityType::loadEntity( Game* zTarget, Framework::StreamReader* zReader ) const
+Entity* EntityType::loadEntity( Framework::StreamReader* zReader ) const
 {
-    Entity* entity = createEntity( Framework::Vec3<float>( 0, 0, 0 ), 0, zTarget, 0 );
+    Entity* entity = createEntity( Framework::Vec3<float>( 0, 0, 0 ), 0, 0 );
     loadSuperEntity( entity, zReader );
     return entity;
 }
@@ -64,9 +64,9 @@ void EntityType::saveEntity( Entity* zEntity, Framework::StreamWriter* zWriter )
     saveSuperEntity( zEntity, zWriter );
 }
 
-Entity* EntityType::createEntityAt( Framework::Vec3<float> position, int dimensionId, Game* zTarget ) const
+Entity* EntityType::createEntityAt( Framework::Vec3<float> position, int dimensionId ) const
 {
-    Entity* entity = createEntity( position, dimensionId, zTarget, zTarget->getNextEntityId() );
+    Entity* entity = createEntity( position, dimensionId, Game::INSTANCE->getNextEntityId() );
     createSuperEntity( entity );
     return entity;
 }

+ 3 - 4
FactoryCraft/EntityType.h

@@ -8,7 +8,6 @@
 #include "StaticRegistry.h"
 
 class Entity;
-class Game;
 
 class EntityType : public virtual Framework::ReferenceCounter
 {
@@ -21,12 +20,12 @@ protected:
     virtual void loadSuperEntity( Entity* zEntity, Framework::StreamReader* zReader ) const;
     virtual void saveSuperEntity( Entity* zEntity, Framework::StreamWriter* zWriter ) const;
     virtual void createSuperEntity( Entity* zEntity ) const;
-    virtual Entity* createEntity( Framework::Vec3<float> position, int dimensionId, Game* zTarget, int entityId ) const = 0;
+    virtual Entity* createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const = 0;
 
 public:
-    virtual Entity* loadEntity( Game* zTarget, Framework::StreamReader* zReader ) const;
+    virtual Entity* loadEntity( Framework::StreamReader* zReader ) const;
     virtual void saveEntity( Entity* zEntity, Framework::StreamWriter* zWriter ) const;
-    virtual Entity* createEntityAt( Framework::Vec3<float> position, int dimensionId, Game* zTarget ) const;
+    virtual Entity* createEntityAt( Framework::Vec3<float> position, int dimensionId ) const;
 
     int getId() const;
 };

+ 2 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -98,6 +98,7 @@
     <ClInclude Include="BasicInterpolator.h" />
     <ClInclude Include="BiomGenerator.h" />
     <ClInclude Include="Block.h" />
+    <ClInclude Include="BlockChangedUpdate.h" />
     <ClInclude Include="BlockType.h" />
     <ClInclude Include="Chunk.h" />
     <ClInclude Include="Constants.h" />
@@ -142,6 +143,7 @@
     <ClCompile Include="BasicInterpolator.cpp" />
     <ClCompile Include="BiomGenerator.cpp" />
     <ClCompile Include="Block.cpp" />
+    <ClCompile Include="BlockChangedUpdate.cpp" />
     <ClCompile Include="BlockType.cpp" />
     <ClCompile Include="Chunk.cpp" />
     <ClCompile Include="Dimension.cpp" />

+ 6 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -183,6 +183,9 @@
     <ClInclude Include="PlaceBlockUpdate.h">
       <Filter>world\update</Filter>
     </ClInclude>
+    <ClInclude Include="BlockChangedUpdate.h">
+      <Filter>world\update</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
@@ -302,5 +305,8 @@
     <ClCompile Include="PlayerHand.cpp">
       <Filter>inventory\items</Filter>
     </ClCompile>
+    <ClCompile Include="BlockChangedUpdate.cpp">
+      <Filter>world\update</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 40 - 25
FactoryCraft/Game.cpp

@@ -82,11 +82,11 @@ void GameClient::sendWorldUpdate( WorldUpdate* update )
         update->release();
 }
 
-void GameClient::reply( Game* zGame )
+void GameClient::reply()
 {
     other.lock();
     for( auto req : requests )
-        zGame->api( req, this );
+        Game::INSTANCE->api( req, this );
     requests.leeren();
     other.unlock();
     int x = (int)floor( zPlayer->getPosition().x );
@@ -121,28 +121,28 @@ void GameClient::reply( Game* zGame )
     if( first )
     {
         first = 0;
-        Dimension* dim = zGame->zDimension( d );
+        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( zGame->getChunkCenter( xP, yP ) );
+                    Chunk* chunk = dim->zChunk( Game::INSTANCE->getChunkCenter( xP, yP ) );
                     if( chunk )
                         sendWorldUpdate( new AddChunkUpdate( dynamic_cast<Chunk*>(chunk->getThis()) ) );
                 }
             }
         }
-        zGame->requestArea( { x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance, x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance, d } );
+        Game::INSTANCE->requestArea( { x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance, x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance, d } );
     }
     else
     {
-        Punkt lastMin = zGame->getChunkCenter( (int)floor( lastPos.x ) - CHUNK_SIZE * viewDistance, (int)floor( lastPos.y ) - CHUNK_SIZE * viewDistance );
-        Punkt curMin = zGame->getChunkCenter( x - CHUNK_SIZE * viewDistance, y - CHUNK_SIZE * viewDistance );
-        Punkt lastMax = zGame->getChunkCenter( (int)floor( lastPos.x ) + CHUNK_SIZE * viewDistance, (int)floor( lastPos.y ) + CHUNK_SIZE * viewDistance );
-        Punkt curMax = zGame->getChunkCenter( x + CHUNK_SIZE * viewDistance, y + CHUNK_SIZE * viewDistance );
-        Dimension* dim = zGame->zDimension( d );
+        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 )
@@ -151,11 +151,11 @@ void GameClient::reply( Game* zGame )
                 {
                     if( xP < lastMin.x || xP > lastMax.x || yP < lastMin.y || yP > lastMax.y )
                     {
-                        Chunk* chunk = dim->zChunk( zGame->getChunkCenter( xP, yP ) );
+                        Chunk* chunk = dim->zChunk( Game::INSTANCE->getChunkCenter( xP, yP ) );
                         if( chunk )
                             sendWorldUpdate( new AddChunkUpdate( dynamic_cast<Chunk*>(chunk->getThis()) ) );
                         else
-                            zGame->requestArea( zGame->getChunckArea( zGame->getChunkCenter( xP, yP ) ) );
+                            Game::INSTANCE->requestArea( Game::INSTANCE->getChunckArea( Game::INSTANCE->getChunkCenter( xP, yP ) ) );
                     }
                 }
             }
@@ -165,7 +165,7 @@ void GameClient::reply( Game* zGame )
                 {
                     if( xP < curMin.x || xP > curMax.x || yP < curMin.y || yP > curMax.y )
                     {
-                        Chunk* chunk = dim->zChunk( zGame->getChunkCenter( xP, yP ) );
+                        Chunk* chunk = dim->zChunk( Game::INSTANCE->getChunkCenter( xP, yP ) );
                         if( chunk )
                             chunk->removeView( zPlayer );
                     }
@@ -251,12 +251,6 @@ Game::Game( Framework::Text name, Framework::Text worldsDir )
         d.lese( (char*)&nextEntityId, 4 );
         d.close();
     }
-    int seed = 0;
-    int index = 0;
-    for( char* n = name; *n; n++ )
-        seed += (int)pow( (float)*n * 31, (float)++index );
-    generator = new WorldGenerator( seed, this );
-    loader = new WorldLoader( this );
     start();
 }
 
@@ -269,6 +263,16 @@ Game::~Game()
     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();
+}
+
 void Game::thread()
 {
     ZeitMesser m;
@@ -295,7 +299,7 @@ void Game::thread()
             clients->remove( i );
         cs.unlock();
         for( auto dim : *dimensions )
-            dim->tickEntities( this );
+            dim->tickEntities();
         cs.lock();
         while( updates->hat( 0 ) )
         {
@@ -309,7 +313,7 @@ void Game::thread()
         }
         cs.unlock();
         for( auto client : *clients )
-            client->reply( this );
+            client->reply();
         cs.lock();
         for( auto dim : *dimensions )
             dim->removeOldChunks();
@@ -395,13 +399,13 @@ GameClient* Game::addPlayer( FCKlient* client, Framework::Text name )
     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, this );
+        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( this, &pFile );
+        player = (Player*)PlayerEntityType::INSTANCE->loadEntity( &pFile );
         pFile.close();
     }
     GameClient* gameClient = new GameClient( player, client );
@@ -452,7 +456,7 @@ Framework::Either<Block*, int> Game::zBlockAt( Framework::Vec3<int> location, in
 {
     Dimension* dim = zDimension( dimension );
     if( dim )
-        return dim->zBlock( location, this );
+        return dim->zBlock( location );
     return 0;
 }
 
@@ -460,7 +464,7 @@ Block* Game::zRealBlockInstance( Framework::Vec3<int> location, int dimension )
 {
     Dimension* dim = zDimension( dimension );
     if( dim )
-        return dim->zRealBlockInstance( location, this );
+        return dim->zRealBlockInstance( location );
     return 0;
 }
 
@@ -528,4 +532,15 @@ int Game::getNextEntityId()
 WorldGenerator* Game::zGenerator() const
 {
     return generator;
+}
+
+Game* Game::INSTANCE = 0;
+
+void Game::initialize( Framework::Text name, Framework::Text worldsDir )
+{
+    if( !Game::INSTANCE )
+    {
+        Game::INSTANCE = new Game( name, worldsDir );
+        Game::INSTANCE->initialize();
+    }
 }

+ 7 - 2
FactoryCraft/Game.h

@@ -40,7 +40,7 @@ public:
     ~GameClient();
 
     void sendWorldUpdate( WorldUpdate* update );
-    void reply( Game* zGame );
+    void reply();
     void logout();
     void addMessage( StreamReader* reader );
     bool isOnline() const;
@@ -75,9 +75,11 @@ private:
     WorldLoader* loader;
 
     void thread() override;
-public:
+
     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 );
@@ -96,4 +98,7 @@ public:
     void addDimension( Dimension* d );
     int getNextEntityId();
     WorldGenerator* zGenerator() const;
+
+    static Game* INSTANCE;
+    static void initialize( Framework::Text name, Framework::Text worldsDir );
 };

+ 1 - 1
FactoryCraft/GrasslandBiom.cpp

@@ -16,7 +16,7 @@ GrasslandBiom::~GrasslandBiom()
         heightNoise->release();
 }
 
-Framework::Either<Block*, int> GrasslandBiom::getBlock( int x, int y, int z, Game* zGame )
+Framework::Either<Block*, int> GrasslandBiom::getBlock( int x, int y, int z )
 {
     return DirtBlockType::ID;
 }

+ 1 - 1
FactoryCraft/GrasslandBiom.h

@@ -10,6 +10,6 @@ class GrasslandBiom : public BiomGenerator
 public:
     GrasslandBiom();
     ~GrasslandBiom();
-    Framework::Either<Block*, int> getBlock( int x, int y, int z, Game* zGame ) override;
+    Framework::Either<Block*, int> getBlock( int x, int y, int z ) override;
     Noise* zHeightMapNoise( int seed ) override;
 };

+ 5 - 5
FactoryCraft/NoBlock.cpp

@@ -28,17 +28,17 @@ NoBlockBlockType::NoBlockBlockType( int id )
     : BlockType( id, 0 )
 {}
 
-Block* NoBlockBlockType::createBlock( Framework::Vec3<int> position, Game* zTarget ) const
+Block* NoBlockBlockType::createBlock( Framework::Vec3<int> position ) const
 {
     return 0;
 }
 
-Item* NoBlockBlockType::createItem( Game* zTarget ) const
+Item* NoBlockBlockType::createItem() const
 {
     return 0;
 }
 
-Block* NoBlockBlockType::loadBlock( Framework::Vec3<int> position, Game* zTarget, Framework::StreamReader* zReader ) const
+Block* NoBlockBlockType::loadBlock( Framework::Vec3<int> position, Framework::StreamReader* zReader ) const
 {
     return 0;
 }
@@ -46,12 +46,12 @@ Block* NoBlockBlockType::loadBlock( Framework::Vec3<int> position, Game* zTarget
 void NoBlockBlockType::saveBlock( Block* zBlock, Framework::StreamWriter* zWriter ) const
 {}
 
-Item* NoBlockBlockType::getItemFromBlock( Block* zBlock, Game* zTarget ) const
+Item* NoBlockBlockType::getItemFromBlock( Block* zBlock ) const
 {
     return 0;
 }
 
-Block* NoBlockBlockType::createBlockAt( Framework::Vec3<int> position, Game* zTarget, Item* zUsedItem ) const
+Block* NoBlockBlockType::createBlockAt( Framework::Vec3<int> position, Item* zUsedItem ) const
 {
     return 0;
 }

+ 5 - 5
FactoryCraft/NoBlock.h

@@ -24,12 +24,12 @@ class NoBlockBlockType : public BlockType
 protected:
     NoBlockBlockType();
     NoBlockBlockType( int id );
-    virtual Block* createBlock( Framework::Vec3<int> position, Game* zTarget ) const override;
-    virtual Item* createItem( Game* zTarget ) const override;
-    virtual Block* loadBlock( Framework::Vec3<int> position, Game* zTarget, Framework::StreamReader* zReader ) const override;
+    virtual Block* createBlock( Framework::Vec3<int> position ) const override;
+    virtual Item* createItem() const override;
+    virtual Block* loadBlock( Framework::Vec3<int> position, Framework::StreamReader* zReader ) const override;
     virtual void saveBlock( Block* zBlock, Framework::StreamWriter* zWriter ) const override;
-    virtual Item* getItemFromBlock( Block* zBlock, Game* zTarget ) const override;
-    virtual Block* createBlockAt( Framework::Vec3<int> position, Game* zTarget, Item* zUsedItem ) const override;
+    virtual Item* getItemFromBlock( Block* zBlock ) const override;
+    virtual Block* createBlockAt( Framework::Vec3<int> position, Item* zUsedItem ) const override;
     virtual const Block* zDefault() const override;
 };
 REGISTER( NoBlockBlockType, BlockType )

+ 8 - 2
FactoryCraft/PlaceBlockUpdate.cpp

@@ -21,8 +21,14 @@ void PlaceBlockUpdate::onUpdate( Dimension* zDimension )
 void PlaceBlockUpdate::write( Framework::StreamWriter* zWriter )
 {
     zWriter->schreibe( (char*)&PlaceBlockUpdateType::ID, 4 );
-    int id = block->zBlockType()->getId();
-    zWriter->schreibe( (char*)&id, 4 );
+    int dimensionID = getAffectedDimension();
+    zWriter->schreibe( (char*)&dimensionID, 4 );
+    auto pos = block->getPos();
+    zWriter->schreibe( (char*)&pos.x, 4 );
+    zWriter->schreibe( (char*)&pos.y, 4 );
+    zWriter->schreibe( (char*)&pos.z, 4 );
+    unsigned char id = (unsigned char)block->zBlockType()->getId();
+    zWriter->schreibe( (char*)&id, 2 );
     block->zBlockType()->saveBlock( block, zWriter );
 }
 

+ 8 - 8
FactoryCraft/Player.cpp

@@ -27,7 +27,7 @@ Player::Player( Framework::Vec3<float> location, int dimensionId, int entityId )
     targetDistanceLimit = 4;
 }
 
-void Player::useItemSlot( ItemSlot* zSlot, Game* zGame )
+void Player::useItemSlot( ItemSlot* zSlot )
 {
     if( zSlot->zStack() )
     {
@@ -35,7 +35,7 @@ void Player::useItemSlot( ItemSlot* zSlot, Game* zGame )
         if( stack )
         {
             Item* item = stack->extractFromStack();
-            Entity::useItem( item->zItemType(), item, zGame );
+            Entity::useItem( item->zItemType(), item );
             if( item->getDurability() > 0 && item->getDamage() < item->getMaxDamage() )
             { // put used item back
                 stack->addToStack( item );
@@ -86,7 +86,7 @@ void Player::useItemSlot( ItemSlot* zSlot, Game* zGame )
         }
     }
     else
-        Entity::useItem( PlayerHandItemType::INSTANCE, 0, zGame ); // hand usage
+        Entity::useItem( PlayerHandItemType::INSTANCE, 0 ); // hand usage
 }
 
 void Player::setName( Framework::Text name )
@@ -99,7 +99,7 @@ const char* Player::getName() const
     return name;
 }
 
-void Player::tick( const Dimension* zDimension, Game* zGame )
+void Player::tick( const Dimension* zDimension )
 {
     speed = { 0, 0, speed.z };
     if( (keyState | Key::MOVE_FRONT) == keyState )
@@ -128,10 +128,10 @@ void Player::tick( const Dimension* zDimension, Game* zGame )
     if( (keyState | Key::MOVE_DOWN) == keyState && gravityMultiplier == 0.f )
         speed.z = -4.f;
     if( (keyState | Key::LEFT_HAND_ACTION) == keyState )
-        useItemSlot( itemBar.z( leftHandPosition ), zGame );
+        useItemSlot( itemBar.z( leftHandPosition ) );
     if( (keyState | Key::RIGHT_HAND_ACTION) == keyState )
-        useItemSlot( itemBar.z( (leftHandPosition + 1) % itemBar.getEintragAnzahl() ), zGame );
-    return Entity::tick( zDimension, zGame );
+        useItemSlot( itemBar.z( (leftHandPosition + 1) % itemBar.getEintragAnzahl() ) );
+    return Entity::tick( zDimension );
 }
 
 void Player::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
@@ -263,7 +263,7 @@ void PlayerEntityType::loadSuperEntity( Entity* zEntity, Framework::StreamReader
 void PlayerEntityType::saveSuperEntity( Entity* zEntity, Framework::StreamWriter* zWriter ) const
 {}
 
-Entity* PlayerEntityType::createEntity( Framework::Vec3<float> position, int dimensionId, Game* zTarget, int entityId ) const
+Entity* PlayerEntityType::createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const
 {
     return new Player( position, dimensionId, entityId );
 }

+ 3 - 3
FactoryCraft/Player.h

@@ -31,13 +31,13 @@ private:
     bool jumping;
     __int64 keyState;
 
-    void useItemSlot( ItemSlot* zSlot, Game* zGame );
+    void useItemSlot( ItemSlot* zSlot );
 
 public:
     Player( Framework::Vec3<float> location, int dimensionId, int entityId );
     void setName( Framework::Text name );
     const char* getName() const;
-    void tick( const Dimension* zDimension, Game* zGame ) override;
+    void tick( const Dimension* zDimension ) override;
 
     void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse ) override;
     void onFall( float collisionSpeed ) override;
@@ -56,7 +56,7 @@ protected:
 public:
     PlayerEntityType();
 
-    virtual Entity* createEntity( Framework::Vec3<float> position, int dimensionId, Game* zTarget, int entityId ) const override;
+    virtual Entity* createEntity( Framework::Vec3<float> position, int dimensionId, int entityId ) const override;
 };
 
 REGISTER( PlayerEntityType, EntityType )

+ 5 - 0
FactoryCraft/PlayerHand.cpp

@@ -1,4 +1,5 @@
 #include "PlayerHand.h"
+#include "Block.h"
 
 
 PlayerHandItemType::PlayerHandItemType()
@@ -42,6 +43,10 @@ PlayerHandSkill::PlayerHandSkill()
 
 void PlayerHandSkill::use( Entity* zActor, Item* zUsedItem, Block* zTarget )
 {
+    if( zTarget && zTarget->getHardness() <= 1 )
+    {
+        zTarget->setHP( zTarget->getHP() - 1 / (zTarget->getHardness() + 1) );
+    }
     // TODO: make damage on the block
 }
 

+ 6 - 11
FactoryCraft/Server.cpp

@@ -35,7 +35,7 @@ FactoryCraftServer::FactoryCraftServer( InitDatei* zIni )
         std::cout << "Der SSL Server konnte nicht gestartet werden.\n";
         exit( 2 );
     }
-    game = new Game( zIni->zWert( "World" )->getText(), zIni->zWert( "SaveDir" )->getText() );
+    Game::initialize( zIni->zWert( "World" )->getText(), zIni->zWert( "SaveDir" )->getText() );
     new Framework::AsynchronCall( [this]() {
         runningThreads++;
         while( server->isConnected() )
@@ -86,8 +86,8 @@ FactoryCraftServer::~FactoryCraftServer()
     if( klients )
         klients->release();
     ini->release();
-    game->requestStop();
-    game->release();
+    Game::INSTANCE->requestStop();
+    Game::INSTANCE->release();
     DeleteCriticalSection( &cs );
 }
 
@@ -117,7 +117,7 @@ void FactoryCraftServer::close()
     for( int i = 0; i < klients->getEintragAnzahl(); i++ )
         klients->z( i )->absturz();
     klients = (RCArray< FCKlient > *)klients->release();
-    game->save();
+    Game::INSTANCE->save();
     LeaveCriticalSection( &cs );
 }
 
@@ -166,11 +166,6 @@ int FactoryCraftServer::getUnencryptedPort() const
     return server->getPort();
 }
 
-Game* FactoryCraftServer::zGame() const
-{
-    return game;
-}
-
 char* randomKey( int& len )
 {
     len = 1024 + (int)(((double)rand() / RAND_MAX - 0.5) * 512);
@@ -226,7 +221,7 @@ void FCKlient::setForegroundClient( SKlient* foreground )
     foregroundReader = new NetworkReader( foreground );
     foregroundWriter = new NetworkWriter( foreground );
     if( foreground && background )
-        zGameClient = ls->zGame()->addPlayer( dynamic_cast<FCKlient*>(getThis()), Framework::Text( (int)accountId ) );
+        zGameClient = Game::INSTANCE->addPlayer( dynamic_cast<FCKlient*>(getThis()), Framework::Text( (int)accountId ) );
     new AsynchronCall( [this]() {
         while( this->foreground->waitForNextMessage() )
         {
@@ -246,7 +241,7 @@ void FCKlient::setBackgroundClient( SKlient* background )
     backgroundReader = new NetworkReader( background );
     backgroundWriter = new NetworkWriter( background );
     if( foreground && background )
-        zGameClient = ls->zGame()->addPlayer( dynamic_cast<FCKlient*>(getThis()), Framework::Text( (int)accountId ) );
+        zGameClient = Game::INSTANCE->addPlayer( dynamic_cast<FCKlient*>(getThis()), Framework::Text( (int)accountId ) );
     new AsynchronCall( [this]() {
         while( this->background->waitForNextMessage() )
         {

+ 0 - 2
FactoryCraft/Server.h

@@ -22,7 +22,6 @@ private:
     InitDatei* ini;
     CRITICAL_SECTION cs;
     RCArray< FCKlient >* klients;
-    Game* game;
     int runningThreads;
     int id;
 
@@ -38,7 +37,6 @@ public:
     bool removeKlient( FCKlient* zKlient );
     bool hatClients() const;
     int getUnencryptedPort() const;
-    Game* zGame() const;
 };
 
 class FCKlient : public Thread

+ 4 - 1
FactoryCraft/StaticInitializerOrder.cpp

@@ -13,10 +13,13 @@ int count_EntityType = 0;
 const int c::ID = count_##typ++;       \
 const c *c::INSTANCE = new c(); 
 
+// order of includes determines the ids
+
 #include "NoBlock.h" // must be first
 #include "BasicBlocks.h"
 #include "OverworldDimension.h"
 #include "AddChunkUpdate.h"
 #include "Player.h"
 #include "PlaceBlockUpdate.h"
-#include "PlayerHand.h"
+#include "PlayerHand.h"
+#include "BlockChangedUpdate.h"

+ 7 - 8
FactoryCraft/WorldGenerator.cpp

@@ -6,9 +6,8 @@
 
 using namespace Framework;
 
-WorldGenerator::WorldGenerator( int seed, Game* zGame )
+WorldGenerator::WorldGenerator( int seed )
     : Thread(),
-    zGame( zGame ),
     exit( 0 ),
     seed( seed )
 {
@@ -37,19 +36,19 @@ void WorldGenerator::thread()
             sleep( 1 );
             continue;
         }
-        Punkt start = zGame->getChunkCenter( next.startX, next.startY );
-        Punkt end = zGame->getChunkCenter( next.endX, next.endY );
+        Punkt start = Game::INSTANCE->getChunkCenter( next.startX, next.startY );
+        Punkt end = Game::INSTANCE->getChunkCenter( next.endX, next.endY );
         int xDir = start.x > end.x ? -1 : 1;
         int yDir = start.y > end.y ? -1 : 1;
         for( int x = start.x; xDir < 0 ? x >= end.x : x <= end.x; x += CHUNK_SIZE * xDir )
         {
             for( int y = start.y; yDir < 0 ? y >= end.y : y <= end.y; y += CHUNK_SIZE * yDir )
             {
-                if( !zGame->doesChunkExist( x, y, next.dimensionId ) )
+                if( !Game::INSTANCE->doesChunkExist( x, y, next.dimensionId ) )
                 {
-                    Chunk* generatedChunk = StaticRegistry<DimensionGenerator>::INSTANCE.zElement( next.dimensionId )->generateChunk( seed, zGame, x, y );
+                    Chunk* generatedChunk = StaticRegistry<DimensionGenerator>::INSTANCE.zElement( next.dimensionId )->generateChunk( seed, x, y );
                     generatedChunk->removeUnusedBlocks();
-                    zGame->requestWorldUpdate( new AddChunkUpdate( generatedChunk ) );
+                    Game::INSTANCE->requestWorldUpdate( new AddChunkUpdate( generatedChunk ) );
                 }
             }
         }
@@ -72,5 +71,5 @@ void WorldGenerator::exitAndWait()
 
 Framework::Either<Block*, int> WorldGenerator::generateSingleBlock( Framework::Vec3<int> location, int dimensionId )
 {
-    return StaticRegistry<DimensionGenerator>::INSTANCE.zElement( dimensionId )->generateBlock( seed, zGame, location );
+    return StaticRegistry<DimensionGenerator>::INSTANCE.zElement( dimensionId )->generateBlock( seed, location );
 }

+ 1 - 3
FactoryCraft/WorldGenerator.h

@@ -6,19 +6,17 @@
 #include "DimensionGenerator.h"
 #include "Area.h"
 
-class Game;
 
 class WorldGenerator : public Framework::Thread
 {
 private:
     Framework::Critical cs;
     Framework::Array<Area> requestQueue;
-    Game* zGame;
     bool exit;
     int seed;
 
 public:
-    WorldGenerator( int seed, Game* zGame );
+    WorldGenerator( int seed );
     ~WorldGenerator();
     void thread() override;
     void requestGeneration( Area request );

+ 12 - 13
FactoryCraft/WorldLoader.cpp

@@ -7,20 +7,19 @@
 
 using namespace Framework;
 
-WorldLoader::WorldLoader( Game* zGame )
+WorldLoader::WorldLoader()
     : Thread(),
-    zGame( zGame ),
     exit( 0 )
 {
     Datei d;
-    d.setDatei( zGame->getWorldDirectory() + "/dim" );
+    d.setDatei( Game::INSTANCE->getWorldDirectory() + "/dim" );
     RCArray<Text>* names = d.getDateiListe();
     if( names )
     {
         for( Text* name : *names )
         {
             Datei entities;
-            entities.setDatei( zGame->getWorldDirectory() + "/dim/" + Text( name->getText() ) + "/entities" );
+            entities.setDatei( Game::INSTANCE->getWorldDirectory() + "/dim/" + Text( name->getText() ) + "/entities" );
             if( entities.open( Datei::Style::lesen ) )
             {
                 Dimension* dim = new Dimension( *name );
@@ -28,9 +27,9 @@ WorldLoader::WorldLoader( Game* zGame )
                 {
                     int type = 0;
                     entities.lese( (char*)&type, 4 );
-                    dim->addEntity( StaticRegistry<EntityType>::INSTANCE.zElement( type )->loadEntity( zGame, &entities ) );
+                    dim->addEntity( StaticRegistry<EntityType>::INSTANCE.zElement( type )->loadEntity( &entities ) );
                 }
-                zGame->addDimension( dim );
+                Game::INSTANCE->addDimension( dim );
             }
         }
         names->release();
@@ -60,18 +59,18 @@ void WorldLoader::thread()
             Sleep( 1000 );
             continue;
         }
-        Punkt start = zGame->getChunkCenter( next.startX, next.startY );
-        Punkt end = zGame->getChunkCenter( next.endX, next.endY );
+        Punkt start = Game::INSTANCE->getChunkCenter( next.startX, next.startY );
+        Punkt end = Game::INSTANCE->getChunkCenter( next.endX, next.endY );
         int xDir = start.x > end.x ? -1 : 1;
         int yDir = start.y > end.y ? -1 : 1;
         for( int x = start.x; xDir < 0 ? x >= end.x : x <= end.x; x += CHUNK_SIZE * xDir )
         {
             for( int y = start.y; yDir < 0 ? y >= end.y : y <= end.y; y += CHUNK_SIZE * yDir )
             {
-                if( !zGame->isChunkLoaded( x, y, next.dimensionId ) )
+                if( !Game::INSTANCE->isChunkLoaded( x, y, next.dimensionId ) )
                 {
                     Datei* file = new Datei();
-                    Text filePath = zGame->getWorldDirectory() + "/dim/" + next.dimensionId + "/";
+                    Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/" + next.dimensionId + "/";
                     filePath.appendHex( x );
                     filePath += "_";
                     filePath.appendHex( y );
@@ -79,8 +78,8 @@ void WorldLoader::thread()
                     file->setDatei( filePath );
                     if( file->open( Datei::Style::lesen ) )
                     {
-                        Chunk* chunk = new Chunk( Framework::Punkt( x, y ), zGame, next.dimensionId, file );
-                        zGame->requestWorldUpdate( new AddChunkUpdate( chunk ) );
+                        Chunk* chunk = new Chunk( Framework::Punkt( x, y ), next.dimensionId, file );
+                        Game::INSTANCE->requestWorldUpdate( new AddChunkUpdate( chunk ) );
                     }
                     file->close();
                     file->release();
@@ -106,7 +105,7 @@ void WorldLoader::exitAndWait()
 
 bool WorldLoader::existsChunk( int x, int y, int dimension ) const
 {
-    Text filePath = zGame->getWorldDirectory() + "/dim/" + dimension + "/";
+    Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/" + dimension + "/";
     filePath.appendHex( x );
     filePath += "_";
     filePath.appendHex( y );

+ 1 - 3
FactoryCraft/WorldLoader.h

@@ -6,18 +6,16 @@
 
 #include "Area.h"
 
-class Game;
 
 class WorldLoader : public Framework::Thread
 {
 private:
     Framework::Critical cs;
     Framework::Array<Area> requestQueue;
-    Game* zGame;
     bool exit;
 
 public:
-    WorldLoader( Game* zGame );
+    WorldLoader();
     ~WorldLoader();
     void thread() override;
     void requestLoading( Area request );