Browse Source

fix some issues with lazy block instantiation

Kolja Strohm 3 years ago
parent
commit
d07bd95435
6 changed files with 86 additions and 39 deletions
  1. 12 3
      FactoryCraft/Block.cpp
  2. 3 1
      FactoryCraft/Block.h
  3. 27 27
      FactoryCraft/Chunk.cpp
  4. 1 1
      FactoryCraft/Game.cpp
  5. 28 3
      FactoryCraft/NoBlock.cpp
  6. 15 4
      FactoryCraft/NoBlock.h

+ 12 - 3
FactoryCraft/Block.cpp

@@ -66,7 +66,18 @@ void Block::postTick()
     }
 }
 
-void Block::setNeighbour( Direction dir, Block* zN )
+void Block::setNeighbour( Direction dir, Framework::Either<Block*, int> neighbour )
+{
+    if( neighbour.isA() )
+        setNeighbourBlock( dir, neighbour );
+    else
+    {
+        setNeighbourBlock( dir, 0 );
+        setNeighbourType( dir, neighbour );
+    }
+}
+
+void Block::setNeighbourBlock( Direction dir, Block* zN )
 {
     if( zN )
         setNeighbourType( dir, zN->zBlockType()->getId() );
@@ -149,8 +160,6 @@ bool Block::isVisible() const
         return 1;
     for( int i = 0; i < 6; i++ )
     {
-        if( neighbourTypes[ i ] == NoBlockBlockType::ID )
-            continue;
         const Block* neighbour = CONST_BLOCK( zNeighbours[ i ], neighbourTypes[ i ] );
         if( neighbour->isPassable() || neighbour->isTransparent() )
             return 1;

+ 3 - 1
FactoryCraft/Block.h

@@ -8,6 +8,7 @@
 
 #include <Trie.h>
 #include <Vec3.h>
+#include <Either.h>
 
 #define CONST_BLOCK(maybeBlock, type) (maybeBlock ? maybeBlock : StaticRegistry<BlockType>::INSTANCE.zElement((int)type)->zDefault())
 
@@ -63,7 +64,8 @@ public:
     void tick( TickQueue* zQueue );
     void postTick();
     void setDimensionId( int id );
-    virtual void setNeighbour( Direction dir, Block* zN );
+    virtual void setNeighbour( Direction dir, Framework::Either<Block*, int> neighbor );
+    virtual void setNeighbourBlock( Direction dir, Block* zN );
     virtual void setNeighbourType( Direction dir, int type );
 
     void api( Framework::StreamReader* zRequest, NetworkResponse* zResponse );

+ 27 - 27
FactoryCraft/Chunk.cpp

@@ -109,34 +109,34 @@ void Chunk::putBlockAt( Framework::Vec3<int> location, Block* block )
     if( block )
         blockIds[ index ] = (unsigned short)block->zBlockType()->getId();
     blocks[ index ] = block;
-    Block* neighbor = zBlockNeighbor( location + getDirection( NORTH ) );
-    if( neighbor )
-        neighbor->setNeighbour( SOUTH, block );
+    Either<Block*, int> neighbor = zBlockNeighbor( location + getDirection( NORTH ) );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbour( SOUTH, block );
     if( block )
         block->setNeighbour( NORTH, neighbor );
     neighbor = zBlockNeighbor( location + getDirection( EAST ) );
-    if( neighbor )
-        neighbor->setNeighbour( WEST, block );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbour( WEST, block );
     if( block )
         block->setNeighbour( EAST, neighbor );
     neighbor = zBlockNeighbor( location + getDirection( SOUTH ) );
-    if( neighbor )
-        neighbor->setNeighbour( NORTH, block );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbour( NORTH, block );
     if( block )
         block->setNeighbour( SOUTH, neighbor );
     neighbor = zBlockNeighbor( location + getDirection( WEST ) );
-    if( neighbor )
-        neighbor->setNeighbour( EAST, block );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbour( EAST, block );
     if( block )
         block->setNeighbour( WEST, neighbor );
     neighbor = zBlockNeighbor( location + getDirection( TOP ) );
-    if( neighbor )
-        neighbor->setNeighbour( BOTTOM, block );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbour( BOTTOM, block );
     if( block )
         block->setNeighbour( TOP, neighbor );
     neighbor = zBlockNeighbor( location + getDirection( BOTTOM ) );
-    if( neighbor )
-        neighbor->setNeighbour( TOP, block );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbour( TOP, block );
     if( block )
         block->setNeighbour( BOTTOM, neighbor );
     if( old )
@@ -148,24 +148,24 @@ void Chunk::putBlockTypeAt( Framework::Vec3<int> location, int type )
     int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
     assert( index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT );
     blockIds[ index ] = (unsigned short)type;
-    Block* neighbor = zBlockNeighbor( location + getDirection( NORTH ) );
-    if( neighbor )
-        neighbor->setNeighbourType( SOUTH, type );
+    Either<Block*, int> neighbor = zBlockNeighbor( location + getDirection( NORTH ) );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbourType( SOUTH, type );
     neighbor = zBlockNeighbor( location + getDirection( EAST ) );
-    if( neighbor )
-        neighbor->setNeighbourType( WEST, type );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbourType( WEST, type );
     neighbor = zBlockNeighbor( location + getDirection( SOUTH ) );
-    if( neighbor )
-        neighbor->setNeighbourType( NORTH, type );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbourType( NORTH, type );
     neighbor = zBlockNeighbor( location + getDirection( WEST ) );
-    if( neighbor )
-        neighbor->setNeighbourType( EAST, type );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbourType( EAST, type );
     neighbor = zBlockNeighbor( location + getDirection( TOP ) );
-    if( neighbor )
-        neighbor->setNeighbourType( BOTTOM, type );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbourType( BOTTOM, type );
     neighbor = zBlockNeighbor( location + getDirection( BOTTOM ) );
-    if( neighbor )
-        neighbor->setNeighbourType( TOP, type );
+    if( neighbor.isA() )
+        ((Block*)neighbor)->setNeighbourType( TOP, type );
 }
 
 void Chunk::setNeighbor( Direction dir, Chunk* zChunk )
@@ -278,7 +278,7 @@ void Chunk::removeUnusedBlocks()
                     auto n = zBlockNeighbor( getDirection( (Directions)getFromIndex( d ) ) + Framework::Vec3<int>( x, y, z ) );
                     if( n.isA() && (((Block*)n)->isPassable() || ((Block*)n)->isTransparent()) )
                         visible = 1;
-                    if( n.isB() && n != NoBlockBlockType::ID && CONST_BLOCK( 0, n )->isTransparent() )
+                    if( n.isB() && (CONST_BLOCK( 0, n )->isTransparent() || CONST_BLOCK( 0, n )->isPassable()) )
                         visible = 1;
                 }
             }

+ 1 - 1
FactoryCraft/Game.cpp

@@ -319,7 +319,7 @@ GameClient* Game::addPlayer( FCKlient* client, Framework::Text name )
     }
     if( isNew )
     {
-        Either<Block*, int> b = NoBlockBlockType::ID;
+        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() );

+ 28 - 3
FactoryCraft/NoBlock.cpp

@@ -3,8 +3,8 @@
 NoBlock::NoBlock()
     : Block( NoBlockBlockType::INSTANCE, 0, { 0,0,0 }, false )
 {
-    transparent = 1;
-    passable = 1;
+    transparent = 0;
+    passable = 0;
     hp = 0;
     maxHP = 0;
     hardness = 0;
@@ -61,7 +61,32 @@ const Block* NoBlockBlockType::zDefault()
     return &NoBlock::INSTANCE;
 }
 
+AirBlock::AirBlock()
+    : Block( AirBlockBlockType::INSTANCE, 0, { 0,0,0 }, false )
+{
+    transparent = 1;
+    passable = 1;
+    hp = 0;
+    maxHP = 0;
+    hardness = 0;
+}
+
+bool AirBlock::onTick( TickQueue* zQueue, int numTicks, bool& blocked )
+{
+    return 0;
+}
+
+void AirBlock::onPostTick()
+{}
+
+const AirBlock AirBlock::INSTANCE;
+
 
 AirBlockBlockType::AirBlockBlockType()
     : NoBlockBlockType( ID )
-{}
+{}
+
+const Block* AirBlockBlockType::zDefault()
+{
+    return &AirBlock::INSTANCE;
+}

+ 15 - 4
FactoryCraft/NoBlock.h

@@ -15,8 +15,6 @@ protected:
 
     virtual bool onTick( TickQueue* zQueue, int numTicks, bool& blocked ) override;
     virtual void onPostTick() override;
-
-    friend NoBlockBlockType;
 };
 
 class NoBlockBlockType : public BlockType
@@ -24,6 +22,8 @@ class NoBlockBlockType : public BlockType
     REGISTRABLE( NoBlockBlockType )
 
 protected:
+    NoBlockBlockType();
+    NoBlockBlockType( int id );
     virtual Block* createBlock( Framework::Vec3<int> position, Game* zTarget ) override;
     virtual Item* createItem( Game* zTarget ) override;
     virtual Block* loadBlock( Framework::Vec3<int> position, Game* zTarget, Framework::StreamReader* zReader ) override;
@@ -31,16 +31,27 @@ protected:
     virtual Item* getItemFromBlock( Block* zBlock, Game* zTarget ) override;
     virtual Block* createBlockAt( Framework::Vec3<int> position, Game* zTarget, Item* zUsedItem ) override;
     virtual const Block* zDefault() override;
-    NoBlockBlockType();
-    NoBlockBlockType( int id );
 };
 REGISTER( NoBlockBlockType, BlockType )
 
+class AirBlock : public Block
+{
+public:
+    static const AirBlock INSTANCE;
+
+protected:
+    AirBlock();
+
+    virtual bool onTick( TickQueue* zQueue, int numTicks, bool& blocked ) override;
+    virtual void onPostTick() override;
+};
+
 class AirBlockBlockType : public NoBlockBlockType
 {
     REGISTRABLE( AirBlockBlockType )
 
 protected:
     AirBlockBlockType();
+    virtual const Block* zDefault() override;
 };
 REGISTER( AirBlockBlockType, BlockType )