summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft <github@xoft.cz>2014-07-24 18:32:05 +0200
committermadmaxoft <github@xoft.cz>2014-07-24 18:32:05 +0200
commitc0b62ef139a65ca648135fb6999e6623438fdd71 (patch)
tree7b7c2bf9ec889308163f8a53dee9e9d4e23025be
parentMade the cWorld::SpawnMobFinalize function more readable. (diff)
downloadcuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.tar
cuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.tar.gz
cuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.tar.bz2
cuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.tar.lz
cuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.tar.xz
cuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.tar.zst
cuberite-c0b62ef139a65ca648135fb6999e6623438fdd71.zip
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Chunk.cpp40
-rw-r--r--src/Chunk.h14
-rw-r--r--src/ChunkMap.cpp25
-rw-r--r--src/ChunkMap.h20
-rw-r--r--src/SetChunkData.cpp115
-rw-r--r--src/SetChunkData.h120
-rw-r--r--src/World.cpp85
-rw-r--r--src/World.h36
-rw-r--r--src/WorldStorage/WSSAnvil.cpp5
-rw-r--r--src/WorldStorage/WSSCompact.cpp5
11 files changed, 349 insertions, 118 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b8780e8a6..29337cb2e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -56,6 +56,7 @@ SET (SRCS
Root.cpp
Scoreboard.cpp
Server.cpp
+ SetChunkData.cpp
Statistics.cpp
StringCompression.cpp
StringUtils.cpp
@@ -124,6 +125,7 @@ SET (HDRS
Root.h
Scoreboard.h
Server.h
+ SetChunkData.h
StackWalker.h
Statistics.h
StringCompression.h
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 60987b070..10bc2ff23 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -34,6 +34,7 @@
#include "MobCensus.h"
#include "MobSpawner.h"
#include "BlockInServerPluginInterface.h"
+#include "SetChunkData.h"
#include "json/json.h"
@@ -265,41 +266,34 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
-void cChunk::SetAllData(
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const HeightMap * a_HeightMap,
- const BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities
-)
+void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
{
- memcpy(m_BiomeMap, a_BiomeMap, sizeof(m_BiomeMap));
+ ASSERT(a_SetChunkData.IsHeightMapValid());
+ ASSERT(a_SetChunkData.AreBiomesValid());
+
+ memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
+ memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
- if (a_HeightMap != NULL)
+ m_ChunkData.SetBlockTypes(a_SetChunkData.GetBlockTypes());
+ m_ChunkData.SetMetas(a_SetChunkData.GetBlockMetas());
+ if (a_SetChunkData.IsLightValid())
{
- memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
+ m_ChunkData.SetBlockLight(a_SetChunkData.GetBlockLight());
+ m_ChunkData.SetSkyLight(a_SetChunkData.GetSkyLight());
+ m_IsLightValid = true;
}
-
- if (a_HeightMap == NULL)
+ else
{
- CalculateHeightmap(a_BlockTypes);
+ m_IsLightValid = false;
}
- m_ChunkData.SetBlockTypes(a_BlockTypes);
- m_ChunkData.SetMetas(a_BlockMeta);
- m_ChunkData.SetBlockLight(a_BlockLight);
- m_ChunkData.SetSkyLight(a_BlockSkyLight);
-
- m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
-
// Clear the block entities present - either the loader / saver has better, or we'll create empty ones:
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
delete *itr;
}
- std::swap(a_BlockEntities, m_BlockEntities);
+ m_BlockEntities.clear();
+ std::swap(a_SetChunkData.GetBlockEntities(), m_BlockEntities);
// Set all block entities' World variable:
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
diff --git a/src/Chunk.h b/src/Chunk.h
index 9ab39a0a2..5d50f9717 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -95,16 +95,10 @@ public:
/** Gets all chunk data, calls the a_Callback's methods for each data type */
void GetAllData(cChunkDataCallback & a_Callback);
- /** Sets all chunk data */
- void SetAllData(
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities
- );
+ /** Sets all chunk data as either loaded from the storage or generated.
+ BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
+ Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk. */
+ void SetAllData(cSetChunkData & a_SetChunkData);
void SetLight(
const cChunkDef::BlockNibbles & a_BlockLight,
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 3ef981e94..05d219918 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -16,6 +16,7 @@
#include "MobCensus.h"
#include "MobSpawner.h"
#include "BoundingBox.h"
+#include "SetChunkData.h"
#include "Entities/Pickup.h"
@@ -912,28 +913,20 @@ void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
-void cChunkMap::SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
-)
+void cChunkMap::SetChunkData(cSetChunkData & a_SetChunkData)
{
+ int ChunkX = a_SetChunkData.GetChunkX();
+ int ChunkZ = a_SetChunkData.GetChunkZ();
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if (Chunk == NULL)
{
return;
}
- Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
+ Chunk->SetAllData(a_SetChunkData);
- if (a_MarkDirty)
+ if (a_SetChunkData.ShouldMarkDirty())
{
Chunk->MarkDirty();
}
@@ -942,7 +935,7 @@ void cChunkMap::SetChunkData(
cChunkStays ToBeDisabled;
for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
{
- if ((*itr)->ChunkAvailable(a_ChunkX, a_ChunkZ))
+ if ((*itr)->ChunkAvailable(ChunkX, ChunkZ))
{
// The chunkstay wants to be disabled, add it to a list of to-be-disabled chunkstays for later processing:
ToBeDisabled.push_back(*itr);
@@ -957,7 +950,7 @@ void cChunkMap::SetChunkData(
}
// Notify plugins of the chunk becoming available
- cPluginManager::Get()->CallHookChunkAvailable(m_World, a_ChunkX, a_ChunkZ);
+ cPluginManager::Get()->CallHookChunkAvailable(m_World, ChunkX, ChunkZ);
}
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 4be1a4752..e33d9f894 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -34,6 +34,7 @@ class cChunkDataSerializer;
class cBlockArea;
class cMobCensus;
class cMobSpawner;
+class cSetChunkData;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cChunk * cChunkPtr;
@@ -112,22 +113,11 @@ public:
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
/** Sets the chunk data as either loaded from the storage or generated.
- a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
- a_BiomeMap is optional, if not present, biomes will be calculated by the generator
- a_HeightMap is optional, if not present, will be calculated.
- If a_MarkDirty is set, the chunk is set as dirty (used after generating)
+ BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
+ If MarkDirty is set, the chunk is set as dirty (used after generating)
+ Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk.
*/
- void SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
- );
+ void SetChunkData(cSetChunkData & a_SetChunkData);
void ChunkLighted(
int a_ChunkX, int a_ChunkZ,
diff --git a/src/SetChunkData.cpp b/src/SetChunkData.cpp
new file mode 100644
index 000000000..6e0c2733e
--- /dev/null
+++ b/src/SetChunkData.cpp
@@ -0,0 +1,115 @@
+
+// SetChunkData.cpp
+
+// Implements the cSetChunkData class used for sending loaded / generated chunk
+
+#include "Globals.h"
+#include "SetChunkData.h"
+
+
+
+
+
+cSetChunkData::cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty) :
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_ShouldMarkDirty(a_ShouldMarkDirty)
+{
+}
+
+
+
+
+
+cSetChunkData::cSetChunkData(
+ int a_ChunkX, int a_ChunkZ,
+ const BLOCKTYPE * a_BlockTypes,
+ const NIBBLETYPE * a_BlockMetas,
+ const NIBBLETYPE * a_BlockLight,
+ const NIBBLETYPE * a_SkyLight,
+ const cChunkDef::HeightMap * a_HeightMap,
+ const cChunkDef::BiomeMap * a_Biomes,
+ cEntityList & a_Entities,
+ cBlockEntityList & a_BlockEntities,
+ bool a_ShouldMarkDirty
+) :
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_ShouldMarkDirty(a_ShouldMarkDirty)
+{
+ // Check the params' validity:
+ ASSERT(a_BlockTypes != NULL);
+ ASSERT(a_BlockMetas != NULL);
+ ASSERT(a_Biomes != NULL);
+
+ // Copy block types and metas:
+ memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
+ memcpy(m_BlockMetas, a_BlockMetas, sizeof(cChunkDef::BlockNibbles));
+
+ // Copy lights, if both given:
+ if ((a_BlockLight != NULL) && (a_SkyLight != NULL))
+ {
+ memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight));
+ memcpy(m_SkyLight, a_SkyLight, sizeof(m_SkyLight));
+ m_IsLightValid = true;
+ }
+ else
+ {
+ m_IsLightValid = false;
+ }
+
+ // Copy the heightmap, if available:
+ if (a_HeightMap != NULL)
+ {
+ memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
+ m_IsHeightMapValid = true;
+ }
+ else
+ {
+ m_IsHeightMapValid = false;
+ }
+
+ // Copy biomes, if available:
+ if (a_Biomes != NULL)
+ {
+ memcpy(m_Biomes, a_Biomes, sizeof(m_Biomes));
+ m_AreBiomesValid = true;
+ }
+ else
+ {
+ m_AreBiomesValid = false;
+ }
+
+ // Move entities and blockentities:
+ std::swap(m_Entities, a_Entities);
+ std::swap(m_BlockEntities, a_BlockEntities);
+}
+
+
+
+
+
+void cSetChunkData::CalculateHeightMap(void)
+{
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ for (int y = cChunkDef::Height - 1; y > -1; y--)
+ {
+ int index = cChunkDef::MakeIndexNoCheck(x, y, z);
+ if (m_BlockTypes[index] != E_BLOCK_AIR)
+ {
+ m_HeightMap[x + z * cChunkDef::Width] = (HEIGHTTYPE)y;
+ break;
+ }
+ } // for y
+ } // for z
+ } // for x
+ m_IsHeightMapValid = true;
+}
+
+
+
+
+
diff --git a/src/SetChunkData.h b/src/SetChunkData.h
new file mode 100644
index 000000000..a2f776f6b
--- /dev/null
+++ b/src/SetChunkData.h
@@ -0,0 +1,120 @@
+
+// SetChunkData.h
+
+// Declares the cSetChunkData class used for sending loaded / generated chunk data into cWorld
+
+
+
+
+
+#pragma once
+
+
+
+
+
+class cSetChunkData
+{
+public:
+ /** Constructs a new instance with empty data.
+ Allocates new buffers for the block data.
+ Prefer to use this constructor, then fill the object with data and then send it to cWorld, as this will
+ reduce the copying required to queue the set operation. */
+ cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty);
+
+ /** Constructs a new instance based on data existing elsewhere, will copy all the memory. Prefer to use the
+ other constructor as much as possible.
+ Will move the entity and blockentity lists into the internal storage, and empty the a_Entities and
+ a_BlockEntities lists.
+ a_BlockTypes and a_BlockMetas must always be valid.
+ If either of the light arrays are NULL, the chunk data will be marked as not having any light at all and
+ will be scheduled for re-lighting once it is set into the chunkmap.
+ If a_Biomes is not valid, the internal flag is set and the world will calculate the biomes using the chunk
+ generator when setting the chunk data.
+ If a_HeightMap is not assigned, the world will calculate the heightmap based on the blocktypes when setting
+ the chunk data. */
+ cSetChunkData(
+ int a_ChunkX, int a_ChunkZ,
+ const BLOCKTYPE * a_BlockTypes,
+ const NIBBLETYPE * a_BlockMetas,
+ const NIBBLETYPE * a_BlockLight,
+ const NIBBLETYPE * a_SkyLight,
+ const cChunkDef::HeightMap * a_HeightMap,
+ const cChunkDef::BiomeMap * a_Biomes,
+ cEntityList & a_Entities,
+ cBlockEntityList & a_BlockEntities,
+ bool a_ShouldMarkDirty
+ );
+
+ int GetChunkX(void) const { return m_ChunkX; }
+ int GetChunkZ(void) const { return m_ChunkZ; }
+
+ /** Returns the internal storage of the block types, read-only. */
+ const cChunkDef::BlockTypes & GetBlockTypes(void) const { return m_BlockTypes; }
+
+ /** Returns the internal storage of the block types, read-only. */
+ const cChunkDef::BlockNibbles & GetBlockMetas(void) const { return m_BlockMetas; }
+
+ /** Returns the internal storage of the block light, read-only. */
+ const cChunkDef::BlockNibbles & GetBlockLight(void) const { return m_BlockLight; }
+
+ /** Returns the internal storage of the block types, read-only. */
+ const cChunkDef::BlockNibbles & GetSkyLight(void) const { return m_SkyLight; }
+
+ /** Returns the internal storage for heightmap, read-only. */
+ const cChunkDef::HeightMap & GetHeightMap(void) const { return m_HeightMap; }
+
+ /** Returns the internal storage for biomes, read-write. */
+ cChunkDef::BiomeMap & GetBiomes(void) { return m_Biomes; }
+
+ /** Returns the internal storage for entities, read-write. */
+ cEntityList & GetEntities(void) { return m_Entities; }
+
+ /** Returns the internal storage for block entities, read-write. */
+ cBlockEntityList & GetBlockEntities(void) { return m_BlockEntities; }
+
+ /** Returns whether both light arrays stored in this object are valid. */
+ bool IsLightValid(void) const { return m_IsLightValid; }
+
+ /** Returns whether the heightmap stored in this object is valid. */
+ bool IsHeightMapValid(void) const { return m_IsHeightMapValid; }
+
+ /** Returns whether the biomes stored in this object are valid. */
+ bool AreBiomesValid(void) const { return m_AreBiomesValid; }
+
+ /** Returns whether the chunk should be marked as dirty after its data is set.
+ Used by the generator to save chunks after generating. */
+ bool ShouldMarkDirty(void) const { return m_ShouldMarkDirty; }
+
+ /** Marks the biomes stored in this object as valid. */
+ void MarkBiomesValid(void) { m_AreBiomesValid = true; }
+
+ /** Calculates the heightmap based on the contained blocktypes and marks it valid. */
+ void CalculateHeightMap(void);
+
+protected:
+ int m_ChunkX;
+ int m_ChunkZ;
+
+ cChunkDef::BlockTypes m_BlockTypes;
+ cChunkDef::BlockNibbles m_BlockMetas;
+ cChunkDef::BlockNibbles m_BlockLight;
+ cChunkDef::BlockNibbles m_SkyLight;
+ cChunkDef::HeightMap m_HeightMap;
+ cChunkDef::BiomeMap m_Biomes;
+ cEntityList m_Entities;
+ cBlockEntityList m_BlockEntities;
+
+ bool m_IsLightValid;
+ bool m_IsHeightMapValid;
+ bool m_AreBiomesValid;
+ bool m_ShouldMarkDirty;
+};
+
+typedef SharedPtr<cSetChunkData> cSetChunkDataPtr; // TODO: Change to unique_ptr once we go C++11
+typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
+
+
+
+
+
diff --git a/src/World.cpp b/src/World.cpp
index 104805209..7ad350e24 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -11,6 +11,7 @@
#include "ChunkMap.h"
#include "Generating/ChunkDesc.h"
#include "OSSupport/Timer.h"
+#include "SetChunkData.h"
// Serializers
#include "WorldStorage/ScoreboardSerializer.h"
@@ -719,6 +720,17 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
// Call the plugins
cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec);
+ // Set any chunk data that has been queued for setting:
+ cSetChunkDataPtrs SetChunkDataQueue;
+ {
+ cCSLock Lock(m_CSSetChunkDataQueue);
+ std::swap(SetChunkDataQueue, m_SetChunkDataQueue);
+ }
+ for (cSetChunkDataPtrs::iterator itr = SetChunkDataQueue.begin(), end = SetChunkDataQueue.end(); itr != end; ++itr)
+ {
+ SetChunkData(**itr);
+ } // for itr - SetChunkDataQueue[]
+
// We need sub-tick precision here, that's why we store the time in seconds and calculate ticks off of it
m_WorldAgeSecs += (double)a_Dt / 1000.0;
m_TimeOfDaySecs += (double)a_Dt / 1000.0;
@@ -2217,47 +2229,59 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
-void cWorld::SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap * a_BiomeMap,
- cEntityList & a_Entities,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
-)
+void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
{
// Validate biomes, if needed:
- cChunkDef::BiomeMap BiomeMap;
- const cChunkDef::BiomeMap * Biomes = a_BiomeMap;
- if (a_BiomeMap == NULL)
+ if (!a_SetChunkData->AreBiomesValid())
{
// The biomes are not assigned, get them from the generator:
- Biomes = &BiomeMap;
- m_Generator.GenerateBiomes(a_ChunkX, a_ChunkZ, BiomeMap);
+ m_Generator.GenerateBiomes(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ(), a_SetChunkData->GetBiomes());
+ a_SetChunkData->MarkBiomesValid();
}
- m_ChunkMap->SetChunkData(
- a_ChunkX, a_ChunkZ,
- a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight,
- a_HeightMap, *Biomes,
- a_BlockEntities,
- a_MarkDirty
- );
+ // Validate heightmap, if needed:
+ if (!a_SetChunkData->IsHeightMapValid())
+ {
+ a_SetChunkData->CalculateHeightMap();
+ }
+
+ // Store a copy of the data in the queue:
+ // TODO: If the queue is too large, wait for it to get processed. Not likely, though.
+ cCSLock Lock(m_CSSetChunkDataQueue);
+ m_SetChunkDataQueue.push_back(a_SetChunkData);
+}
+
+
+
+
+
+void cWorld::SetChunkData(cSetChunkData & a_SetChunkData)
+{
+ ASSERT(a_SetChunkData.AreBiomesValid());
+ ASSERT(a_SetChunkData.IsHeightMapValid());
+
+ m_ChunkMap->SetChunkData(a_SetChunkData);
// Initialize the entities (outside the m_ChunkMap's CS, to fix FS #347):
- for (cEntityList::iterator itr = a_Entities.begin(), end = a_Entities.end(); itr != end; ++itr)
+ cEntityList Entities;
+ std::swap(a_SetChunkData.GetEntities(), Entities);
+ for (cEntityList::iterator itr = Entities.begin(), end = Entities.end(); itr != end; ++itr)
{
(*itr)->Initialize(*this);
}
// If a client is requesting this chunk, send it to them:
- if (m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkZ))
+ int ChunkX = a_SetChunkData.GetChunkX();
+ int ChunkZ = a_SetChunkData.GetChunkZ();
+ if (m_ChunkMap->HasChunkAnyClients(ChunkX, ChunkZ))
+ {
+ m_ChunkSender.ChunkReady(ChunkX, ChunkZ);
+ }
+
+ // Save the chunk right after generating, so that we don't have to generate it again on next run
+ if (a_SetChunkData.ShouldMarkDirty())
{
- m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkZ);
+ m_Storage.QueueSaveChunk(ChunkX, 0, ChunkZ);
}
}
@@ -3295,17 +3319,14 @@ void cWorld::cChunkGeneratorCallbacks::OnChunkGenerated(cChunkDesc & a_ChunkDesc
cChunkDef::BlockNibbles BlockMetas;
a_ChunkDesc.CompressBlockMetas(BlockMetas);
- m_World->SetChunkData(
+ m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(),
a_ChunkDesc.GetBlockTypes(), BlockMetas,
NULL, NULL, // We don't have lighting, chunk will be lighted when needed
&a_ChunkDesc.GetHeightMap(), &a_ChunkDesc.GetBiomeMap(),
a_ChunkDesc.GetEntities(), a_ChunkDesc.GetBlockEntities(),
true
- );
-
- // Save the chunk right after generating, so that we don't have to generate it again on next run
- m_World->GetStorage().QueueSaveChunk(a_ChunkDesc.GetChunkX(), 0, a_ChunkDesc.GetChunkZ());
+ )));
}
diff --git a/src/World.h b/src/World.h
index 2346ac523..6613b495a 100644
--- a/src/World.h
+++ b/src/World.h
@@ -49,9 +49,14 @@ class cNoteEntity;
class cMobHeadEntity;
class cCompositeChat;
class cCuboid;
+class cSetChunkData;
+
typedef std::list< cPlayer * > cPlayerList;
+typedef SharedPtr<cSetChunkData> cSetChunkDataPtr; // TODO: Change to unique_ptr once we go C++11
+typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
+
typedef cItemCallback<cPlayer> cPlayerListCallback;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
@@ -246,24 +251,9 @@ public:
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ);
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
- /** Sets the chunk data as either loaded from the storage or generated.
- a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
- a_BiomeMap is optional, if not present, biomes will be calculated by the generator
- a_HeightMap is optional, if not present, will be calculated.
- If a_MarkDirty is set, the chunk is set as dirty (used after generating)
- */
- void SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap * a_BiomeMap,
- cEntityList & a_Entities,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
- );
+ /** Puts the chunk data into a queue to be set into the chunkmap in the tick thread.
+ If the chunk data doesn't contain valid biomes, the biomes are calculated before adding the data into the queue. */
+ void QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData);
void ChunkLighted(
int a_ChunkX, int a_ChunkZ,
@@ -969,6 +959,12 @@ private:
/** List of players that are scheduled for adding, waiting for the Tick thread to add them. */
cPlayerList m_PlayersToAdd;
+
+ /** CS protecting m_SetChunkDataQueue. */
+ cCriticalSection m_CSSetChunkDataQueue;
+
+ /** Queue for the chunk data to be set into m_ChunkMap by the tick thread. Protected by m_CSSetChunkDataQueue */
+ cSetChunkDataPtrs m_SetChunkDataQueue;
cWorld(const AString & a_WorldName);
@@ -1011,6 +1007,10 @@ private:
/** Adds the players queued in the m_PlayersToAdd queue into the m_Players list.
Assumes it is called from the Tick thread. */
void AddQueuedPlayers(void);
+
+ /** Sets the specified chunk data into the chunkmap. Called in the tick thread.
+ Modifies the a_SetChunkData - moves the entities contained in it into the chunk. */
+ void SetChunkData(cSetChunkData & a_SetChunkData);
}; // tolua_export
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 663d489bc..2851647fe 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -14,6 +14,7 @@
#include "../Item.h"
#include "../ItemGrid.h"
#include "../StringCompression.h"
+#include "../SetChunkData.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
@@ -391,7 +392,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
} // for y
//*/
- m_World->SetChunkData(
+ m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
BlockTypes, MetaData,
IsLightValid ? BlockLight : NULL,
@@ -399,7 +400,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
NULL, Biomes,
Entities, BlockEntities,
false
- );
+ )));
return true;
}
diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp
index 5382a3e01..ee47047a0 100644
--- a/src/WorldStorage/WSSCompact.cpp
+++ b/src/WorldStorage/WSSCompact.cpp
@@ -18,6 +18,7 @@
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/NoteEntity.h"
#include "../BlockEntities/SignEntity.h"
+#include "../SetChunkData.h"
@@ -911,7 +912,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
NIBBLETYPE * BlockLight = (NIBBLETYPE *)(BlockData + LightOffset);
NIBBLETYPE * SkyLight = (NIBBLETYPE *)(BlockData + SkyLightOffset);
- a_World->SetChunkData(
+ a_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
BlockData, MetaData,
IsLightValid ? BlockLight : NULL,
@@ -919,7 +920,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
NULL, NULL,
Entities, BlockEntities,
false
- );
+ )));
return true;
}