1
0

Added a queue for setting chunk data.

Fixes #1196.
This commit is contained in:
madmaxoft 2014-07-24 18:32:05 +02:00
parent 9678341a11
commit c0b62ef139
11 changed files with 353 additions and 122 deletions

View File

@ -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

View File

@ -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));
if (a_HeightMap != NULL)
{
memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
}
if (a_HeightMap == NULL)
{
CalculateHeightmap(a_BlockTypes);
}
m_ChunkData.SetBlockTypes(a_BlockTypes);
m_ChunkData.SetMetas(a_BlockMeta);
m_ChunkData.SetBlockLight(a_BlockLight);
m_ChunkData.SetSkyLight(a_BlockSkyLight);
ASSERT(a_SetChunkData.IsHeightMapValid());
ASSERT(a_SetChunkData.AreBiomesValid());
m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
m_ChunkData.SetBlockTypes(a_SetChunkData.GetBlockTypes());
m_ChunkData.SetMetas(a_SetChunkData.GetBlockMetas());
if (a_SetChunkData.IsLightValid())
{
m_ChunkData.SetBlockLight(a_SetChunkData.GetBlockLight());
m_ChunkData.SetSkyLight(a_SetChunkData.GetSkyLight());
m_IsLightValid = true;
}
else
{
m_IsLightValid = false;
}
// 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)

View File

@ -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,

View File

@ -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);
}

View File

@ -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,

115
src/SetChunkData.cpp Normal file
View File

@ -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;
}

120
src/SetChunkData.h Normal file
View File

@ -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;

View File

@ -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(a_ChunkX, a_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_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());
)));
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}