Kaynağa Gözat

big speedup of chunk network transmission

Kolja Strohm 3 yıl önce
ebeveyn
işleme
26f32aec01

+ 1 - 1
FactoryCraft/AddChunkUpdate.cpp

@@ -27,7 +27,7 @@ void AddChunkUpdate::write( Framework::StreamWriter* zWriter )
     Framework::Punkt center = chunk->getCenter();
     zWriter->schreibe( (char*)&center.x, 4 );
     zWriter->schreibe( (char*)&center.y, 4 );
-    chunk->save( zWriter );
+    chunk->save( zWriter, StreamTarget::CLIENT );
 }
 
 Chunk* AddChunkUpdate::zChunk() const

+ 52 - 30
FactoryCraft/Chunk.cpp

@@ -242,30 +242,27 @@ void Chunk::setNeighbor( Direction dir, Chunk* zChunk )
 
 void Chunk::load( Framework::StreamReader* zReader )
 {
-    // TODO: adjust this to new way to save chunks
-    zReader->lese( (char*)blockIds, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof( unsigned short ) );
-    for( int x = 0; x < CHUNK_SIZE; x++ )
+    unsigned short id = 0;
+    zReader->lese( (char*)&id, 2 );
+    Framework::Vec3<int> pos;
+    bool d = 0;
+    while( id )
     {
-        for( int y = 0; y < CHUNK_SIZE; y++ )
-        {
-            for( int z = 0; z < WORLD_HEIGHT; z++ )
-            {
-                unsigned short blockType;
-                zReader->lese( (char*)&blockType, 2 );
-                Block* block = StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->loadBlock( Framework::Vec3<int>( x, y, z ), zGame, zReader );
-                if( block )
-                    putBlockAt( { x, y, z }, block );
-                else
-                    putBlockTypeAt( { x, y, z }, blockIds[ (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z ] );
-            }
-        }
+        zReader->lese( (char*)&pos.x, 4 );
+        zReader->lese( (char*)&pos.y, 4 );
+        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 ) );
+        else
+            putBlockTypeAt( pos, id );
+
+        zReader->lese( (char*)&id, 2 );
     }
 }
 
-void Chunk::save( Framework::StreamWriter* zWriter )
+void Chunk::save( Framework::StreamWriter* zWriter, StreamTarget target )
 {
-    // TODO: check if target is client or file
-    // if client then only transfer visible blocks
     for( int x = 0; x < CHUNK_SIZE; x++ )
     {
         for( int y = 0; y < CHUNK_SIZE; y++ )
@@ -276,20 +273,45 @@ void Chunk::save( Framework::StreamWriter* zWriter )
                 unsigned short blockType = blocks[ index ] ? (unsigned short)blocks[ index ]->zBlockType()->getId() : blockIds[ index ];
                 if( blockType )
                 {
-                    zWriter->schreibe( (char*)&blockType, 2 );
-                    zWriter->schreibe( (char*)&x, 4 );
-                    zWriter->schreibe( (char*)&y, 4 );
-                    zWriter->schreibe( (char*)&z, 4 );
-                    if( blocks[ index ] )
+                    bool visible = target == StreamTarget::FULL;
+                    if( !visible )
                     {
-                        bool d = 1;
-                        zWriter->schreibe( (char*)&d, 1 );
-                        StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->saveBlock( blocks[ index ], zWriter );
+                        if( !blocks[ index ] )
+                        {
+                            if( CONST_BLOCK( 0, blockIds[ index ] )->isTransparent() || CONST_BLOCK( 0, blockIds[ index ] )->isPassable() )
+                                visible = 1;
+                            else
+                            {
+                                for( int d = 0; d < 6 && !visible; d++ )
+                                {
+                                    auto n = zBlockNeighbor( getDirection( (Directions)getDirectionFromIndex( d ) ) + Framework::Vec3<int>( x, y, z ) );
+                                    if( n.isA() && (((Block*)n)->isPassable() || ((Block*)n)->isTransparent()) )
+                                        visible = 1;
+                                    if( n.isB() && (CONST_BLOCK( 0, n )->isTransparent() || CONST_BLOCK( 0, n )->isPassable()) )
+                                        visible = 1;
+                                }
+                            }
+                        }
+                        else
+                            visible = blocks[ index ]->isVisible();
                     }
-                    else
+                    if( target == StreamTarget::FULL || (visible && (blocks[ index ] || blockType != AirBlockBlockType::ID)) )
                     {
-                        bool d = 0;
-                        zWriter->schreibe( (char*)&d, 1 );
+                        zWriter->schreibe( (char*)&blockType, 2 );
+                        zWriter->schreibe( (char*)&x, 4 );
+                        zWriter->schreibe( (char*)&y, 4 );
+                        zWriter->schreibe( (char*)&z, 4 );
+                        if( blocks[ index ] )
+                        {
+                            bool d = 1;
+                            zWriter->schreibe( (char*)&d, 1 );
+                            StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->saveBlock( blocks[ index ], zWriter );
+                        }
+                        else
+                        {
+                            bool d = 0;
+                            zWriter->schreibe( (char*)&d, 1 );
+                        }
                     }
                 }
             }

+ 1 - 1
FactoryCraft/Chunk.h

@@ -39,7 +39,7 @@ public:
     void putBlockTypeAt( Framework::Vec3<int> location, int type );
     void setNeighbor( Direction dir, Chunk* zChunk );
     void load( Framework::StreamReader* zReader );
-    void save( Framework::StreamWriter* zWriter );
+    void save( Framework::StreamWriter* zWriter, StreamTarget target );
     void removeUnusedBlocks();
     int getDimensionId() const;
     Framework::Punkt getCenter() const;

+ 1 - 1
FactoryCraft/Dimension.cpp

@@ -193,7 +193,7 @@ void Dimension::save( Text worldDir ) const
         filePath += ".chunk";
         file->setDatei( filePath );
         if( file->open( Datei::Style::schreiben ) )
-            chunk->save( file );
+            chunk->save( file, StreamTarget::FULL );
         file->close();
         file->release();
     }

+ 8 - 1
FactoryCraft/StaticRegistry.h

@@ -71,4 +71,11 @@ public:
 };
 
 template <typename T>
-StaticRegistry<T> StaticRegistry<T>::INSTANCE;
+StaticRegistry<T> StaticRegistry<T>::INSTANCE;
+
+
+enum class StreamTarget
+{
+    FULL,
+    CLIENT
+};