소스 검색

remove unneeded chunks from memory

Kolja Strohm 3 년 전
부모
커밋
9f078c1f34

+ 23 - 0
FactoryCraft/Area.cpp

@@ -35,4 +35,27 @@ int getDirectionIndex( Direction dir )
         return 5;
     assert( false );
     return -1;
+}
+
+Direction getOppositeDirection( Direction dir )
+{
+    if( dir == NORTH )
+        return SOUTH;
+    if( dir == EAST )
+        return WEST;
+    if( dir == SOUTH )
+        return NORTH;
+    if( dir == WEST )
+        return EAST;
+    if( dir == TOP )
+        return BOTTOM;
+    if( dir == BOTTOM )
+        return TOP;
+    assert( false );
+    return NO_DIRECTION;
+}
+
+Direction getDirectionFromIndex( int index )
+{
+    return (Direction)(1 << index);
 }

+ 3 - 1
FactoryCraft/Area.h

@@ -24,4 +24,6 @@ enum Direction
 typedef int Directions;
 
 Framework::Vec3<int> getDirection( Directions dir );
-int getDirectionIndex( Direction dir );
+int getDirectionIndex( Direction dir );
+Direction getOppositeDirection( Direction dir );
+Direction getDirectionFromIndex( int index );

+ 9 - 0
FactoryCraft/Block.cpp

@@ -61,6 +61,15 @@ void Block::setNeighbourType( Direction dir, int type )
     neighbourTypes[ getDirectionIndex( dir ) ] = type;
 }
 
+void Block::remove()
+{
+    if( visible )
+    {
+        visible = 0;
+        currentGame->setVisibility( this, visible );
+    }
+}
+
 bool Block::isVisible() const
 {
     return visible;

+ 1 - 0
FactoryCraft/Block.h

@@ -38,6 +38,7 @@ public:
     virtual void setNeighbourBlock( Direction dir, Block* zN );
     virtual void setNeighbourType( Direction dir, int type );
 
+    void remove();
     bool isVisible() const;
     const BlockType* zBlockType() const;
     friend Chunk;

+ 61 - 7
FactoryCraft/Chunk.cpp

@@ -9,7 +9,8 @@
 Chunk::Chunk( Framework::Punkt location, int dimensionId )
     : ReferenceCounter(),
     dimensionId( dimensionId ),
-    location( location )
+    location( location ),
+    added( 0 )
 {
     blocks = new Block * [ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT ];
     blockIds = new unsigned short[ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT ];
@@ -48,7 +49,7 @@ Framework::Either<Block*, int> Chunk::zBlockNeighbor( Framework::Vec3<int> locat
         else
             return (int)blockIds[ index ];
     }
-    if( location.z >= 0 && location.z < WORLD_HEIGHT )
+    if( added && location.z >= 0 && location.z < WORLD_HEIGHT )
         return currentGame->zBlockAt( { location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId );
     return 0;
 }
@@ -165,29 +166,59 @@ void Chunk::setNeighbor( Direction dir, Chunk* zChunk )
                 if( blocks[ index ] )
                 {
                     int j = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
-                    if( zChunk->blocks[ j ] )
+                    if( zChunk && zChunk->blocks[ j ] )
                         blocks[ index ]->setNeighbour( NORTH, zChunk->blocks[ j ] );
                     else
-                        blocks[ index ]->setNeighbourType( NORTH, zChunk->blockIds[ j ] );
+                    {
+                        blocks[ index ]->setNeighbour( NORTH, 0 );
+                        blocks[ index ]->setNeighbourType( NORTH, zChunk ? zChunk->blockIds[ j ] : 0 );
+                    }
                 }
             }
             else if( dir == EAST )
             {
                 int index = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
                 if( blocks[ index ] )
-                    blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ i * WORLD_HEIGHT + z ] );
+                {
+                    int j = i * WORLD_HEIGHT + z;
+                    if( zChunk && zChunk->blocks[ j ] )
+                        blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ j ] );
+                    else
+                    {
+                        blocks[ index ]->setNeighbour( EAST, 0 );
+                        blocks[ index ]->setNeighbourType( EAST, zChunk ? zChunk->blockIds[ j ] : 0 );
+                    }
+                }
             }
             else if( dir == SOUTH )
             {
                 int index = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
                 if( blocks[ index ] )
-                    blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ i * CHUNK_SIZE * WORLD_HEIGHT + z ] );
+                {
+                    int j = i * CHUNK_SIZE * WORLD_HEIGHT + z;
+                    if( zChunk && zChunk->blocks[ j ] )
+                        blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ j ] );
+                    else
+                    {
+                        blocks[ index ]->setNeighbour( SOUTH, 0 );
+                        blocks[ index ]->setNeighbourType( SOUTH, zChunk ? zChunk->blockIds[ j ] : 0 );
+                    }
+                }
             }
             else if( dir == WEST )
             {
                 int index = i * WORLD_HEIGHT + z;
                 if( blocks[ index ] )
-                    blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z ] );
+                {
+                    int j = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
+                    if( zChunk && zChunk->blocks[ j ] )
+                        blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ j ] );
+                    else
+                    {
+                        blocks[ index ]->setNeighbour( WEST, 0 );
+                        blocks[ index ]->setNeighbourType( WEST, zChunk ? zChunk->blockIds[ j ] : 0 );
+                    }
+                }
             }
         }
     }
@@ -237,4 +268,27 @@ Framework::Vec3<int> Chunk::getMin() const
 Framework::Vec3<int> Chunk::getMax() const
 {
     return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
+}
+
+void Chunk::prepareRemove()
+{
+    added = 0;
+    for( int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++ )
+    {
+        if( blocks[ i ] )
+            blocks[ i ]->remove();
+    }
+    for( int i = 0; i < 4; i++ )
+    {
+        if( zNeighbours[ i ] )
+        {
+            zNeighbours[ i ]->setNeighbor( getOppositeDirection( getDirectionFromIndex( i ) ), 0 );
+            zNeighbours[ i ] = 0;
+        }
+    }
+}
+
+void Chunk::setAdded()
+{
+    added = 1;
 }

+ 3 - 0
FactoryCraft/Chunk.h

@@ -18,6 +18,7 @@ private:
     unsigned short* blockIds;
     Chunk* zNeighbours[ 4 ];
     Framework::Either<Block*, int> zBlockNeighbor( Framework::Vec3<int> location );
+    bool added;
 
 public:
     Chunk( Framework::Punkt location, int dimensionId );
@@ -34,4 +35,6 @@ public:
     Framework::Punkt getCenter() const;
     Framework::Vec3<int> getMin() const;
     Framework::Vec3<int> getMax() const;
+    void prepareRemove();
+    void setAdded();
 };

+ 39 - 12
FactoryCraft/Dimension.cpp

@@ -6,6 +6,7 @@
 
 using namespace Framework;
 
+#define MAX_VIEW_DISTANCE CHUNK_SIZE * 8
 
 Dimension::Dimension( int id )
     : dimensionId( id ),
@@ -77,11 +78,11 @@ void Dimension::addEntity( Entity* entity )
     entities->add( entity );
 }
 
-void Dimension::addChunk( Chunk* chunk )
+void Dimension::setChunk( Chunk* chunk, Punkt center )
 {
     char addr[ 8 ];
-    getAddrOfWorld( chunk->getCenter(), addr );
-    Chunk *old = chunks->z( addr, 8 );
+    getAddrOfWorld( center, addr );
+    Chunk* old = chunks->z( addr, 8 );
     if( old )
     {
         for( int i = 0; i < chunkList.getEintragAnzahl(); i++ )
@@ -94,34 +95,42 @@ void Dimension::addChunk( Chunk* chunk )
         }
     }
     chunks->set( addr, 8, chunk );
-    chunkList.add( chunk );
-    getAddrOfWorld( chunk->getCenter() + Punkt( CHUNK_SIZE, 0 ), addr );
+    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 );
-        chunk->setNeighbor( EAST, chunk );
+        if( chunk )
+            chunk->setNeighbor( EAST, zChunk );
     }
-    getAddrOfWorld( chunk->getCenter() + Punkt( -CHUNK_SIZE, 0 ), addr );
+    getAddrOfWorld( center + Punkt( -CHUNK_SIZE, 0 ), addr );
     zChunk = chunks->z( addr, 8 );
     if( zChunk )
     {
         zChunk->setNeighbor( EAST, chunk );
-        chunk->setNeighbor( WEST, chunk );
+        if( chunk )
+            chunk->setNeighbor( WEST, zChunk );
     }
-    getAddrOfWorld( chunk->getCenter() + Punkt( 0, CHUNK_SIZE ), addr );
+    getAddrOfWorld( center + Punkt( 0, CHUNK_SIZE ), addr );
     zChunk = chunks->z( addr, 8 );
     if( zChunk )
     {
         zChunk->setNeighbor( NORTH, chunk );
-        chunk->setNeighbor( SOUTH, chunk );
+        if( chunk )
+            chunk->setNeighbor( SOUTH, zChunk );
     }
-    getAddrOfWorld( chunk->getCenter() + Punkt( 0, -CHUNK_SIZE ), addr );
+    getAddrOfWorld( center + Punkt( 0, -CHUNK_SIZE ), addr );
     zChunk = chunks->z( addr, 8 );
     if( zChunk )
     {
         zChunk->setNeighbor( SOUTH, chunk );
-        chunk->setNeighbor( NORTH, chunk );
+        if( chunk )
+            chunk->setNeighbor( NORTH, zChunk );
     }
 }
 
@@ -133,4 +142,22 @@ int Dimension::getDimensionId() const
 bool Dimension::hasChunck( int x, int y ) const
 {
     return zChunk( Punkt( x, y ) );
+}
+
+void Dimension::removeDistantChunks( Punkt wPos )
+{
+    Array<int> removed;
+    int index = 0;
+    for( Chunk* chunk : chunkList )
+    {
+        if( (chunk->getCenter() - wPos).getLength() > MAX_VIEW_DISTANCE )
+            removed.add( index, 0 );
+        index++;
+    }
+    for( int i : removed )
+    {
+        Chunk* chunk = chunkList.get( i );
+        chunk->prepareRemove();
+        setChunk( 0, chunk->getCenter() );
+    }
 }

+ 2 - 1
FactoryCraft/Dimension.h

@@ -23,8 +23,9 @@ public:
     void updateVisibility();
     Framework::Either<Block*, int> zBlock( Framework::Vec3<int> location );
     void addEntity( Entity* entity );
-    void addChunk( Chunk* chunk );
+    void setChunk( Chunk* chunk, Framework::Punkt center );
     int getDimensionId() const;
     bool hasChunck( int x, int y ) const;
     Chunk* zChunk( Framework::Punkt wPos ) const;
+    void removeDistantChunks( Framework::Punkt wPos );
 };

+ 23 - 3
FactoryCraft/FactoryClient.cpp

@@ -9,6 +9,8 @@ FactoryClient::FactoryClient()
     foreground = 0;
     backgroundReader = 0;
     foregroundReader = 0;
+    bgReaderUsage = 0;
+    fgReaderUsage = 0;
 }
 
 FactoryClient::~FactoryClient()
@@ -76,10 +78,18 @@ void FactoryClient::disconnect()
 {
     if( client )
     {
-        delete foregroundReader;
-        foregroundReader = 0;
-        delete backgroundReader;
+        NetworkReader* fgReader = foregroundReader;
+        NetworkReader* bgReader = backgroundReader;
         backgroundReader = 0;
+        foregroundReader = 0;
+        if( foreground )
+            foreground->trenne();
+        if( background )
+            background->trenne();
+        while( fgReaderUsage > 0 || bgReaderUsage > 0 )
+            Sleep( 100 );
+        delete fgReader;
+        delete bgReader;
         client->release();
         client = 0;
         if( foreground )
@@ -93,6 +103,7 @@ void FactoryClient::disconnect()
 
 NetworkReader* FactoryClient::getNextForegroundMessage()
 {
+    fgReaderUsage++;
     if( !foreground )
         return 0;
     if( !foreground->hatNachricht( 0 ) )
@@ -102,6 +113,7 @@ NetworkReader* FactoryClient::getNextForegroundMessage()
 
 NetworkReader* FactoryClient::getNextBackgroundMessage()
 {
+    bgReaderUsage++;
     if( !background )
         return 0;
     if( !background->hatNachricht( 0 ) )
@@ -109,6 +121,14 @@ NetworkReader* FactoryClient::getNextBackgroundMessage()
     return backgroundReader;
 }
 
+void FactoryClient::endMessageReading( bool bg )
+{
+    if( bg )
+        bgReaderUsage--;
+    else
+        fgReaderUsage--;
+}
+
 void FactoryClient::sendPlayerAction( void* data, unsigned short length )
 {
     if( !foreground )

+ 4 - 0
FactoryCraft/FactoryClient.h

@@ -15,6 +15,9 @@ private:
     Network::NetworkReader* foregroundReader;
     Network::NetworkReader* backgroundReader;
     Framework::Critical cs;
+    int bgReaderUsage;
+    int fgReaderUsage;
+
     void disconnect();
 
 public:
@@ -24,5 +27,6 @@ public:
     bool connect( Text ip, short port, int accountId, Text secret );
     Network::NetworkReader* getNextForegroundMessage();
     Network::NetworkReader* getNextBackgroundMessage();
+    void endMessageReading( bool bg );
     void sendPlayerAction( void* data, unsigned short length );
 };

+ 16 - 9
FactoryCraft/Game.cpp

@@ -2,22 +2,29 @@
 #include "Initialisierung.h"
 #include "Globals.h"
 
+#include <AsynchronCall.h>
+#include <Bildschirm.h>
+
 Game::Game( Bildschirm* zScreen )
     : Menu( zScreen )
 {
     logout = initKnopf( 10, 10, 200, 20, Knopf::Style::Normal, "Verlassen" );
-    logout->setMausEreignis( [this]( void* p, void* o, MausEreignis me ) {
+    logout->setMausEreignis( [this, zScreen]( void* p, void* o, MausEreignis me ) {
         if( me.id == ME_RLinks )
         {
             logout->removeStyle( Knopf::Style::Erlaubt );
-            if( network->leaveGame() )
-            {
-                currentGame->release();
-                currentGame = 0;
-                hide();
-                menuRegister->get( "directConnect" )->show();
-            }
-            logout->addStyle( Knopf::Style::Erlaubt );
+            new AsynchronCall( [this, zScreen]() {
+                if( network->leaveGame() )
+                {
+                    currentGame->release();
+                    currentGame = 0;
+                    zScreen->lock();
+                    hide();
+                    menuRegister->get( "directConnect" )->show();
+                    zScreen->unlock();
+                }
+                logout->addStyle( Knopf::Style::Erlaubt );
+            } );
         }
         return 1;
     } );

+ 1 - 0
FactoryCraft/Globals.h

@@ -5,6 +5,7 @@
 #include <UIInitialization.h>
 #include <Schrift.h>
 #include <DLLRegister.h>
+#include <Bildschirm.h>
 
 #include "Menu.h"
 #include "NetworkHandler.h"

+ 6 - 1
FactoryCraft/World.cpp

@@ -14,6 +14,7 @@
 using namespace Network;
 using namespace Framework;
 
+
 World::World( Bildschirm3D* zScreen )
     : Thread()
 {
@@ -64,8 +65,12 @@ void World::update( bool background )
             serverMessageReader->lese( (char*)&dir.y, 4 );
             ((Game*)(Menu*)menuRegister->get( "game" ))->updatePositionAndFace( pos, dir );
             kam->setDirection( { dir.x, dir.y } );
+            for( Dimension* dim : *dimensions )
+                dim->removeDistantChunks( { (int)dir.x, (int)dir.y } );
         }
+        network->zFactoryClient()->endMessageReading( background );
     }
+    network->zFactoryClient()->endMessageReading( background );
 }
 
 void World::setChunk( Chunk* chunk, int dimensionId )
@@ -77,7 +82,7 @@ void World::setChunk( Chunk* chunk, int dimensionId )
         zDim = new Dimension( dimensionId );
         dimensions->add( zDim );
     }
-    zDim->addChunk( chunk );
+    zDim->setChunk( chunk, chunk->getCenter() );
     zScreenPtr->unlock();
     zDim->updateVisibility();
 }

+ 0 - 124
enc_temp_folder/656d315483eef2966fbf926ffde34c1/Dimension.cpp

@@ -1,124 +0,0 @@
-#include "Dimension.h"
-#include "Constants.h"
-#include "Datei.h"
-#include "Game.h"
-#include "Globals.h"
-
-using namespace Framework;
-
-
-Dimension::Dimension( int id )
-    : dimensionId( id ),
-    chunks( new Trie<Chunk>() ),
-    entities( new RCArray<Entity>() )
-{}
-
-Dimension::~Dimension()
-{
-    entities->release();
-    chunks->release();
-}
-
-void Dimension::updateVisibility()
-{
-    bool changed = true;
-    while( changed )
-    {
-        changed = false;
-        for( auto chunk : chunkList )
-        {
-            if( chunk )
-                changed |= chunk->updateVisibility();
-        }
-    }
-}
-
-void Dimension::getAddrOf( Punkt cPos, char* addr ) const
-{
-    *(int*)addr = cPos.x;
-    *((int*)addr + 1) = cPos.y;
-}
-
-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 );
-}
-
-Chunk* Dimension::zChunk( Punkt wPos ) const
-{
-    char addr[ 8 ];
-    getAddrOfWorld( wPos, addr );
-    return chunks->z( addr, 8 );
-}
-
-Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location )
-{
-    Chunk* c = zChunk( currentGame->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;
-}
-
-void Dimension::addEntity( Entity* entity )
-{
-    entities->add( entity );
-}
-
-void Dimension::addChunk( Chunk* chunk )
-{
-    char addr[ 8 ];
-    getAddrOfWorld( chunk->getCenter(), addr );
-    chunks->set( addr, 8, chunk );
-    chunkList.add( chunk );
-    getAddrOfWorld( chunk->getCenter() + Punkt( CHUNK_SIZE, 0 ), addr );
-    Chunk* zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( WEST, chunk );
-        chunk->setNeighbor( EAST, chunk );
-    }
-    getAddrOfWorld( chunk->getCenter() + Punkt( -CHUNK_SIZE, 0 ), addr );
-    zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( EAST, chunk );
-        chunk->setNeighbor( WEST, chunk );
-    }
-    getAddrOfWorld( chunk->getCenter() + Punkt( 0, CHUNK_SIZE ), addr );
-    zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( NORTH, chunk );
-        chunk->setNeighbor( SOUTH, chunk );
-    }
-    getAddrOfWorld( chunk->getCenter() + Punkt( 0, -CHUNK_SIZE ), addr );
-    zChunk = chunks->z( addr, 8 );
-    if( zChunk )
-    {
-        zChunk->setNeighbor( SOUTH, chunk );
-        chunk->setNeighbor( NORTH, chunk );
-    }
-}
-
-int Dimension::getDimensionId() const
-{
-    return dimensionId;
-}
-
-bool Dimension::hasChunck( int x, int y ) const
-{
-    return zChunk( Punkt( x, y ) );
-}