parent
9678341a11
commit
c0b62ef139
@ -56,6 +56,7 @@ SET (SRCS
|
|||||||
Root.cpp
|
Root.cpp
|
||||||
Scoreboard.cpp
|
Scoreboard.cpp
|
||||||
Server.cpp
|
Server.cpp
|
||||||
|
SetChunkData.cpp
|
||||||
Statistics.cpp
|
Statistics.cpp
|
||||||
StringCompression.cpp
|
StringCompression.cpp
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
@ -124,6 +125,7 @@ SET (HDRS
|
|||||||
Root.h
|
Root.h
|
||||||
Scoreboard.h
|
Scoreboard.h
|
||||||
Server.h
|
Server.h
|
||||||
|
SetChunkData.h
|
||||||
StackWalker.h
|
StackWalker.h
|
||||||
Statistics.h
|
Statistics.h
|
||||||
StringCompression.h
|
StringCompression.h
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "MobCensus.h"
|
#include "MobCensus.h"
|
||||||
#include "MobSpawner.h"
|
#include "MobSpawner.h"
|
||||||
#include "BlockInServerPluginInterface.h"
|
#include "BlockInServerPluginInterface.h"
|
||||||
|
#include "SetChunkData.h"
|
||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
@ -265,41 +266,34 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::SetAllData(
|
void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
memcpy(m_BiomeMap, a_BiomeMap, sizeof(m_BiomeMap));
|
ASSERT(a_SetChunkData.IsHeightMapValid());
|
||||||
|
ASSERT(a_SetChunkData.AreBiomesValid());
|
||||||
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);
|
|
||||||
|
|
||||||
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:
|
// 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)
|
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||||
{
|
{
|
||||||
delete *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:
|
// Set all block entities' World variable:
|
||||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||||
|
14
src/Chunk.h
14
src/Chunk.h
@ -95,16 +95,10 @@ public:
|
|||||||
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
||||||
void GetAllData(cChunkDataCallback & a_Callback);
|
void GetAllData(cChunkDataCallback & a_Callback);
|
||||||
|
|
||||||
/** Sets all chunk data */
|
/** Sets all chunk data as either loaded from the storage or generated.
|
||||||
void SetAllData(
|
BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
|
||||||
const BLOCKTYPE * a_BlockTypes,
|
Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk. */
|
||||||
const NIBBLETYPE * a_BlockMeta,
|
void SetAllData(cSetChunkData & a_SetChunkData);
|
||||||
const NIBBLETYPE * a_BlockLight,
|
|
||||||
const NIBBLETYPE * a_BlockSkyLight,
|
|
||||||
const cChunkDef::HeightMap * a_HeightMap,
|
|
||||||
const cChunkDef::BiomeMap & a_BiomeMap,
|
|
||||||
cBlockEntityList & a_BlockEntities
|
|
||||||
);
|
|
||||||
|
|
||||||
void SetLight(
|
void SetLight(
|
||||||
const cChunkDef::BlockNibbles & a_BlockLight,
|
const cChunkDef::BlockNibbles & a_BlockLight,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "MobCensus.h"
|
#include "MobCensus.h"
|
||||||
#include "MobSpawner.h"
|
#include "MobSpawner.h"
|
||||||
#include "BoundingBox.h"
|
#include "BoundingBox.h"
|
||||||
|
#include "SetChunkData.h"
|
||||||
|
|
||||||
#include "Entities/Pickup.h"
|
#include "Entities/Pickup.h"
|
||||||
|
|
||||||
@ -912,28 +913,20 @@ void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::SetChunkData(
|
void cChunkMap::SetChunkData(cSetChunkData & a_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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
int ChunkX = a_SetChunkData.GetChunkX();
|
||||||
|
int ChunkZ = a_SetChunkData.GetChunkZ();
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
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)
|
if (Chunk == NULL)
|
||||||
{
|
{
|
||||||
return;
|
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();
|
Chunk->MarkDirty();
|
||||||
}
|
}
|
||||||
@ -942,7 +935,7 @@ void cChunkMap::SetChunkData(
|
|||||||
cChunkStays ToBeDisabled;
|
cChunkStays ToBeDisabled;
|
||||||
for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
|
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:
|
// The chunkstay wants to be disabled, add it to a list of to-be-disabled chunkstays for later processing:
|
||||||
ToBeDisabled.push_back(*itr);
|
ToBeDisabled.push_back(*itr);
|
||||||
@ -957,7 +950,7 @@ void cChunkMap::SetChunkData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify plugins of the chunk becoming available
|
// Notify plugins of the chunk becoming available
|
||||||
cPluginManager::Get()->CallHookChunkAvailable(m_World, a_ChunkX, a_ChunkZ);
|
cPluginManager::Get()->CallHookChunkAvailable(m_World, ChunkX, ChunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ class cChunkDataSerializer;
|
|||||||
class cBlockArea;
|
class cBlockArea;
|
||||||
class cMobCensus;
|
class cMobCensus;
|
||||||
class cMobSpawner;
|
class cMobSpawner;
|
||||||
|
class cSetChunkData;
|
||||||
|
|
||||||
typedef std::list<cClientHandle *> cClientHandleList;
|
typedef std::list<cClientHandle *> cClientHandleList;
|
||||||
typedef cChunk * cChunkPtr;
|
typedef cChunk * cChunkPtr;
|
||||||
@ -112,22 +113,11 @@ public:
|
|||||||
void MarkChunkSaved (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.
|
/** 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.
|
BlockLight and 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
|
If MarkDirty is set, the chunk is set as dirty (used after generating)
|
||||||
a_HeightMap is optional, if not present, will be calculated.
|
Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk.
|
||||||
If a_MarkDirty is set, the chunk is set as dirty (used after generating)
|
|
||||||
*/
|
*/
|
||||||
void SetChunkData(
|
void SetChunkData(cSetChunkData & a_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 ChunkLighted(
|
void ChunkLighted(
|
||||||
int a_ChunkX, int a_ChunkZ,
|
int a_ChunkX, int a_ChunkZ,
|
||||||
|
115
src/SetChunkData.cpp
Normal file
115
src/SetChunkData.cpp
Normal 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
120
src/SetChunkData.h
Normal 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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
|||||||
#include "ChunkMap.h"
|
#include "ChunkMap.h"
|
||||||
#include "Generating/ChunkDesc.h"
|
#include "Generating/ChunkDesc.h"
|
||||||
#include "OSSupport/Timer.h"
|
#include "OSSupport/Timer.h"
|
||||||
|
#include "SetChunkData.h"
|
||||||
|
|
||||||
// Serializers
|
// Serializers
|
||||||
#include "WorldStorage/ScoreboardSerializer.h"
|
#include "WorldStorage/ScoreboardSerializer.h"
|
||||||
@ -719,6 +720,17 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
|
|||||||
// Call the plugins
|
// Call the plugins
|
||||||
cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec);
|
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
|
// 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_WorldAgeSecs += (double)a_Dt / 1000.0;
|
||||||
m_TimeOfDaySecs += (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(
|
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Validate biomes, if needed:
|
// Validate biomes, if needed:
|
||||||
cChunkDef::BiomeMap BiomeMap;
|
if (!a_SetChunkData->AreBiomesValid())
|
||||||
const cChunkDef::BiomeMap * Biomes = a_BiomeMap;
|
|
||||||
if (a_BiomeMap == NULL)
|
|
||||||
{
|
{
|
||||||
// The biomes are not assigned, get them from the generator:
|
// The biomes are not assigned, get them from the generator:
|
||||||
Biomes = &BiomeMap;
|
m_Generator.GenerateBiomes(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ(), a_SetChunkData->GetBiomes());
|
||||||
m_Generator.GenerateBiomes(a_ChunkX, a_ChunkZ, BiomeMap);
|
a_SetChunkData->MarkBiomesValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ChunkMap->SetChunkData(
|
// Validate heightmap, if needed:
|
||||||
a_ChunkX, a_ChunkZ,
|
if (!a_SetChunkData->IsHeightMapValid())
|
||||||
a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight,
|
{
|
||||||
a_HeightMap, *Biomes,
|
a_SetChunkData->CalculateHeightMap();
|
||||||
a_BlockEntities,
|
}
|
||||||
a_MarkDirty
|
|
||||||
);
|
// 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):
|
// 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);
|
(*itr)->Initialize(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a client is requesting this chunk, send it to them:
|
// 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;
|
cChunkDef::BlockNibbles BlockMetas;
|
||||||
a_ChunkDesc.CompressBlockMetas(BlockMetas);
|
a_ChunkDesc.CompressBlockMetas(BlockMetas);
|
||||||
|
|
||||||
m_World->SetChunkData(
|
m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
|
||||||
a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(),
|
a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(),
|
||||||
a_ChunkDesc.GetBlockTypes(), BlockMetas,
|
a_ChunkDesc.GetBlockTypes(), BlockMetas,
|
||||||
NULL, NULL, // We don't have lighting, chunk will be lighted when needed
|
NULL, NULL, // We don't have lighting, chunk will be lighted when needed
|
||||||
&a_ChunkDesc.GetHeightMap(), &a_ChunkDesc.GetBiomeMap(),
|
&a_ChunkDesc.GetHeightMap(), &a_ChunkDesc.GetBiomeMap(),
|
||||||
a_ChunkDesc.GetEntities(), a_ChunkDesc.GetBlockEntities(),
|
a_ChunkDesc.GetEntities(), a_ChunkDesc.GetBlockEntities(),
|
||||||
true
|
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
36
src/World.h
36
src/World.h
@ -49,9 +49,14 @@ class cNoteEntity;
|
|||||||
class cMobHeadEntity;
|
class cMobHeadEntity;
|
||||||
class cCompositeChat;
|
class cCompositeChat;
|
||||||
class cCuboid;
|
class cCuboid;
|
||||||
|
class cSetChunkData;
|
||||||
|
|
||||||
|
|
||||||
typedef std::list< cPlayer * > cPlayerList;
|
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<cPlayer> cPlayerListCallback;
|
||||||
typedef cItemCallback<cEntity> cEntityCallback;
|
typedef cItemCallback<cEntity> cEntityCallback;
|
||||||
typedef cItemCallback<cChestEntity> cChestCallback;
|
typedef cItemCallback<cChestEntity> cChestCallback;
|
||||||
@ -246,24 +251,9 @@ public:
|
|||||||
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ);
|
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ);
|
||||||
void MarkChunkSaved (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.
|
/** Puts the chunk data into a queue to be set into the chunkmap in the tick thread.
|
||||||
a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
|
If the chunk data doesn't contain valid biomes, the biomes are calculated before adding the data into the queue. */
|
||||||
a_BiomeMap is optional, if not present, biomes will be calculated by the generator
|
void QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData);
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
void ChunkLighted(
|
void ChunkLighted(
|
||||||
int a_ChunkX, int a_ChunkZ,
|
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. */
|
/** List of players that are scheduled for adding, waiting for the Tick thread to add them. */
|
||||||
cPlayerList m_PlayersToAdd;
|
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);
|
cWorld(const AString & a_WorldName);
|
||||||
@ -1011,6 +1007,10 @@ private:
|
|||||||
/** Adds the players queued in the m_PlayersToAdd queue into the m_Players list.
|
/** Adds the players queued in the m_PlayersToAdd queue into the m_Players list.
|
||||||
Assumes it is called from the Tick thread. */
|
Assumes it is called from the Tick thread. */
|
||||||
void AddQueuedPlayers(void);
|
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
|
}; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "../Item.h"
|
#include "../Item.h"
|
||||||
#include "../ItemGrid.h"
|
#include "../ItemGrid.h"
|
||||||
#include "../StringCompression.h"
|
#include "../StringCompression.h"
|
||||||
|
#include "../SetChunkData.h"
|
||||||
|
|
||||||
#include "../BlockEntities/ChestEntity.h"
|
#include "../BlockEntities/ChestEntity.h"
|
||||||
#include "../BlockEntities/CommandBlockEntity.h"
|
#include "../BlockEntities/CommandBlockEntity.h"
|
||||||
@ -391,7 +392,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
|
|||||||
} // for y
|
} // for y
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
m_World->SetChunkData(
|
m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
|
||||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
|
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
|
||||||
BlockTypes, MetaData,
|
BlockTypes, MetaData,
|
||||||
IsLightValid ? BlockLight : NULL,
|
IsLightValid ? BlockLight : NULL,
|
||||||
@ -399,7 +400,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
|
|||||||
NULL, Biomes,
|
NULL, Biomes,
|
||||||
Entities, BlockEntities,
|
Entities, BlockEntities,
|
||||||
false
|
false
|
||||||
);
|
)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "../BlockEntities/MobHeadEntity.h"
|
#include "../BlockEntities/MobHeadEntity.h"
|
||||||
#include "../BlockEntities/NoteEntity.h"
|
#include "../BlockEntities/NoteEntity.h"
|
||||||
#include "../BlockEntities/SignEntity.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 * BlockLight = (NIBBLETYPE *)(BlockData + LightOffset);
|
||||||
NIBBLETYPE * SkyLight = (NIBBLETYPE *)(BlockData + SkyLightOffset);
|
NIBBLETYPE * SkyLight = (NIBBLETYPE *)(BlockData + SkyLightOffset);
|
||||||
|
|
||||||
a_World->SetChunkData(
|
a_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
|
||||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
|
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
|
||||||
BlockData, MetaData,
|
BlockData, MetaData,
|
||||||
IsLightValid ? BlockLight : NULL,
|
IsLightValid ? BlockLight : NULL,
|
||||||
@ -919,7 +920,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
Entities, BlockEntities,
|
Entities, BlockEntities,
|
||||||
false
|
false
|
||||||
);
|
)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user