cWorldGenerator speedup - doesn't call GetChunk() anymore, not queueing the chunk it's generating to be loaded recursively.
cChunk fix - setting a block to the same value doesn't mark chunk dirty (resulted in un-unloadable chunks) git-svn-id: http://mc-server.googlecode.com/svn/trunk@279 0a769ca7-a7f5-676a-18bf-c427514a06d6master
parent
008addf5d7
commit
2928cb6853
|
@ -805,8 +805,6 @@ void cChunk::SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_Block
|
||||||
|
|
||||||
assert(IsValid()); // Is this chunk loaded / generated?
|
assert(IsValid()); // Is this chunk loaded / generated?
|
||||||
|
|
||||||
MarkDirty();
|
|
||||||
|
|
||||||
int index = a_Y + (a_Z * 128) + (a_X * 128 * 16);
|
int index = a_Y + (a_Z * 128) + (a_X * 128 * 16);
|
||||||
char OldBlockMeta = GetLight( m_BlockMeta, index );
|
char OldBlockMeta = GetLight( m_BlockMeta, index );
|
||||||
char OldBlockType = m_BlockType[index];
|
char OldBlockType = m_BlockType[index];
|
||||||
|
@ -819,6 +817,8 @@ void cChunk::SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_Block
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
|
|
||||||
cCSLock Lock(m_CSBlockLists);
|
cCSLock Lock(m_CSBlockLists);
|
||||||
m_PendingSendBlocks.push_back( index );
|
m_PendingSendBlocks.push_back( index );
|
||||||
|
|
||||||
|
@ -871,14 +871,15 @@ void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_B
|
||||||
|
|
||||||
assert(IsValid());
|
assert(IsValid());
|
||||||
|
|
||||||
MarkDirty();
|
|
||||||
|
|
||||||
const int index = a_Y + (a_Z * 128) + (a_X * 128 * 16);
|
const int index = a_Y + (a_Z * 128) + (a_X * 128 * 16);
|
||||||
const char OldBlock = m_BlockType[index];
|
const char OldBlock = m_BlockType[index];
|
||||||
if (OldBlock == a_BlockType)
|
if (OldBlock == a_BlockType)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
|
|
||||||
m_BlockType[index] = a_BlockType;
|
m_BlockType[index] = a_BlockType;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1107,7 +1108,7 @@ bool cChunk::HasClient( cClientHandle* a_Client )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cChunk::HasAnyClient(void)
|
bool cChunk::HasAnyClients(void)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSClients);
|
cCSLock Lock(m_CSClients);
|
||||||
return !m_LoadedByClient.empty();
|
return !m_LoadedByClient.empty();
|
||||||
|
|
|
@ -114,10 +114,10 @@ public:
|
||||||
|
|
||||||
void SendBlockTo( int a_X, int a_Y, int a_Z, cClientHandle* a_Client );
|
void SendBlockTo( int a_X, int a_Y, int a_Z, cClientHandle* a_Client );
|
||||||
|
|
||||||
void AddClient ( cClientHandle* a_Client );
|
void AddClient (cClientHandle* a_Client );
|
||||||
void RemoveClient( cClientHandle* a_Client );
|
void RemoveClient (cClientHandle* a_Client );
|
||||||
bool HasClient ( cClientHandle* a_Client );
|
bool HasClient (cClientHandle* a_Client );
|
||||||
bool HasAnyClient(void); // Returns true if theres any client in the chunk; false otherwise
|
bool HasAnyClients(void); // Returns true if theres any client in the chunk; false otherwise
|
||||||
|
|
||||||
void AddEntity( cEntity * a_Entity );
|
void AddEntity( cEntity * a_Entity );
|
||||||
void RemoveEntity( cEntity * a_Entity);
|
void RemoveEntity( cEntity * a_Entity);
|
||||||
|
|
|
@ -53,11 +53,11 @@ bool cChunkGenerator::Start(cWorld * a_World, const AString & a_WorldGeneratorNa
|
||||||
|
|
||||||
if (a_WorldGeneratorName.compare("Test") == 0 )
|
if (a_WorldGeneratorName.compare("Test") == 0 )
|
||||||
{
|
{
|
||||||
m_pWorldGenerator = new cWorldGenerator_Test();
|
m_pWorldGenerator = new cWorldGenerator_Test(a_World);
|
||||||
}
|
}
|
||||||
else // Default
|
else // Default
|
||||||
{
|
{
|
||||||
m_pWorldGenerator = new cWorldGenerator();
|
m_pWorldGenerator = new cWorldGenerator(a_World);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super::Start();
|
return super::Start();
|
||||||
|
@ -129,17 +129,22 @@ void cChunkGenerator::Execute(void)
|
||||||
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
|
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
|
||||||
Lock.Unlock(); // Unlock ASAP
|
Lock.Unlock(); // Unlock ASAP
|
||||||
|
|
||||||
cChunkPtr Chunk = m_World->GetChunk(coords.m_ChunkX, 0, coords.m_ChunkZ);
|
if (
|
||||||
if ((Chunk != NULL) && (Chunk->IsValid() || (SkipEnabled && !Chunk->HasAnyClient())))
|
m_World->IsChunkValid(coords.m_ChunkX, 0, coords.m_ChunkZ) ||
|
||||||
|
(SkipEnabled && m_World->HasChunkAnyClients(coords.m_ChunkX, 0, coords.m_ChunkZ))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Already generated / overload-skip, ignore request
|
// Already generated / overload-skip, ignore request
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("Generating chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
|
LOG("Generating chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
|
||||||
m_pWorldGenerator->GenerateChunk(Chunk);
|
m_pWorldGenerator->GenerateChunk(coords.m_ChunkX, 0, coords.m_ChunkZ);
|
||||||
|
|
||||||
Chunk->SetValid();
|
// Chunk->SetValid();
|
||||||
|
|
||||||
|
// Save the chunk right after generating, so that we don't have to generate it again on next run
|
||||||
|
m_World->GetStorage().QueueSaveChunk(coords.m_ChunkX, coords.m_ChunkZ);
|
||||||
} // while (!bStop)
|
} // while (!bStop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,6 +276,17 @@ bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||||
|
return (Chunk != NULL) && Chunk->HasAnyClients();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
|
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
|
@ -389,7 +400,6 @@ void cChunkMap::cChunkLayer::Save(void)
|
||||||
|
|
||||||
void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
|
void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
|
||||||
{
|
{
|
||||||
cWorld * World = m_Parent->GetWorld();
|
|
||||||
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||||
{
|
{
|
||||||
if ((m_Chunks[i] != NULL) && (m_Chunks[i]->CanUnload()))
|
if ((m_Chunks[i] != NULL) && (m_Chunks[i]->CanUnload()))
|
||||||
|
|
|
@ -37,12 +37,13 @@ public:
|
||||||
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // a_Player rclked block entity at the coords specified, handle it
|
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // a_Player rclked block entity at the coords specified, handle it
|
||||||
|
|
||||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
void MarkChunkSaving(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
void ChunkDataLoaded(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
||||||
void SetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
void SetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
||||||
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
|
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
|
||||||
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
|
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
|
|
||||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ void cMonsterConfig::AssignAttributes(cMonster *m, const char* n)
|
||||||
m->SetAttackRange (itr->m_AttackRange);
|
m->SetAttackRange (itr->m_AttackRange);
|
||||||
m->SetSightDistance(itr->m_SightDistance);
|
m->SetSightDistance(itr->m_SightDistance);
|
||||||
m->SetAttackRate ((int)itr->m_AttackRate);
|
m->SetAttackRate ((int)itr->m_AttackRate);
|
||||||
m->SetMaxHealth ((int)itr->m_MaxHealth);
|
m->SetMaxHealth ((short)itr->m_MaxHealth);
|
||||||
}
|
}
|
||||||
} // for itr - m_pState->AttributesList[]
|
} // for itr - m_pState->AttributesList[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1009,6 +1009,15 @@ bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
|
||||||
|
{
|
||||||
|
return m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::SetMaxPlayers(int iMax)
|
void cWorld::SetMaxPlayers(int iMax)
|
||||||
{
|
{
|
||||||
m_MaxPlayers = MAX_PLAYERS;
|
m_MaxPlayers = MAX_PLAYERS;
|
||||||
|
|
|
@ -71,12 +71,13 @@ public:
|
||||||
void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL);
|
void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL);
|
||||||
|
|
||||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
void MarkChunkSaving(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
void ChunkDataLoaded(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
||||||
void SetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
void SetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
|
||||||
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
|
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
|
||||||
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
||||||
|
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
||||||
|
|
||||||
// MOTD
|
// MOTD
|
||||||
const AString & GetDescription(void) const {return m_Description; }
|
const AString & GetDescription(void) const {return m_Description; }
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cWorldGenerator::cWorldGenerator()
|
cWorldGenerator::cWorldGenerator(cWorld * a_World) :
|
||||||
|
m_World(a_World)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,15 +31,19 @@ cWorldGenerator::~cWorldGenerator()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorldGenerator::GenerateChunk( cChunkPtr a_Chunk )
|
void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
assert(!a_Chunk->IsValid());
|
// TODO: use a raw char array instead of the entire chunk, then set it as chunk's blockdata
|
||||||
|
|
||||||
memset(a_Chunk->pGetBlockData(), 0, cChunk::c_BlockDataSize);
|
cChunkPtr Chunk = m_World->GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||||
GenerateTerrain( a_Chunk );
|
assert(!Chunk->IsValid());
|
||||||
GenerateFoliage( a_Chunk );
|
|
||||||
a_Chunk->CalculateHeightmap();
|
memset(Chunk->pGetBlockData(), 0, cChunk::c_BlockDataSize);
|
||||||
a_Chunk->CalculateLighting();
|
GenerateTerrain(Chunk);
|
||||||
|
GenerateFoliage(Chunk);
|
||||||
|
Chunk->CalculateHeightmap();
|
||||||
|
Chunk->CalculateLighting();
|
||||||
|
Chunk->SetValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,16 @@
|
||||||
class cWorldGenerator
|
class cWorldGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cWorldGenerator();
|
cWorldGenerator(cWorld * a_World);
|
||||||
~cWorldGenerator();
|
~cWorldGenerator();
|
||||||
|
|
||||||
virtual void GenerateChunk( cChunkPtr a_Chunk );
|
virtual void GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
cWorld * m_World;
|
||||||
|
|
||||||
|
// Thread-unsafe:
|
||||||
MTRand r1;
|
MTRand r1;
|
||||||
|
|
||||||
virtual void GenerateTerrain( cChunkPtr a_Chunk );
|
virtual void GenerateTerrain( cChunkPtr a_Chunk );
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
class cWorldGenerator_Test :
|
class cWorldGenerator_Test :
|
||||||
public cWorldGenerator
|
public cWorldGenerator
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
cWorldGenerator_Test(cWorld * a_World) : cWorldGenerator(a_World) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void GenerateTerrain( cChunkPtr a_Chunk ) override;
|
virtual void GenerateTerrain( cChunkPtr a_Chunk ) override;
|
||||||
virtual void GenerateFoliage( cChunkPtr a_Chunk ) override;
|
virtual void GenerateFoliage( cChunkPtr a_Chunk ) override;
|
||||||
|
|
Loading…
Reference in New Issue