2012-02-08 04:36:54 -08:00
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
// cChunkMap.h
|
|
|
|
|
|
|
|
// Interfaces to the cChunkMap class representing the chunk storage for a single world
|
|
|
|
|
2011-10-03 11:41:19 -07:00
|
|
|
#pragma once
|
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
#include "cChunk.h"
|
|
|
|
|
2012-02-08 04:36:54 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-10-30 17:52:20 -07:00
|
|
|
class cWorld;
|
2011-10-03 11:41:19 -07:00
|
|
|
class cEntity;
|
2012-02-08 04:36:54 -08:00
|
|
|
class MTRand;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-10-03 11:41:19 -07:00
|
|
|
class cChunkMap
|
|
|
|
{
|
|
|
|
public:
|
2012-02-13 13:47:03 -08:00
|
|
|
|
|
|
|
static const int LAYER_SIZE = 32;
|
|
|
|
|
2012-01-29 13:40:21 -08:00
|
|
|
cChunkMap(cWorld* a_World );
|
2011-10-03 11:41:19 -07:00
|
|
|
~cChunkMap();
|
|
|
|
|
2012-02-16 05:42:35 -08:00
|
|
|
// TODO: Get rid of these (put into Private section) in favor of the direct action methods:
|
2012-02-14 13:09:14 -08:00
|
|
|
cChunkPtr GetChunk ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading / generating if not valid
|
|
|
|
cChunkPtr GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading if not valid; doesn't generate
|
2012-02-15 06:22:44 -08:00
|
|
|
|
|
|
|
// Direct action methods:
|
|
|
|
/// Broadcasts a_Packet to all clients in the chunk where block [x, y, z] is, except to client a_Exclude
|
|
|
|
void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL);
|
|
|
|
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
|
2011-10-03 11:41:19 -07:00
|
|
|
|
2012-02-16 09:45:26 -08:00
|
|
|
void MarkChunkDirty (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 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 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 HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
2012-02-16 05:42:35 -08:00
|
|
|
|
2012-02-08 04:36:54 -08:00
|
|
|
void Tick( float a_Dt, MTRand & a_TickRand );
|
2011-10-03 11:41:19 -07:00
|
|
|
|
|
|
|
void UnloadUnusedChunks();
|
|
|
|
void SaveAllChunks();
|
2011-12-24 15:34:30 -08:00
|
|
|
|
2012-02-15 06:22:44 -08:00
|
|
|
cWorld * GetWorld() { return m_World; }
|
2012-01-01 08:20:52 -08:00
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
int GetNumChunks(void);
|
2012-02-08 04:36:54 -08:00
|
|
|
|
2012-02-15 06:22:44 -08:00
|
|
|
/// Converts absolute block coords into relative (chunk + block) coords:
|
|
|
|
inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ )
|
|
|
|
{
|
|
|
|
BlockToChunk(a_X, a_Y, a_Z, a_ChunkX, a_ChunkZ);
|
|
|
|
|
|
|
|
a_X = a_X - a_ChunkX * 16;
|
2012-02-16 05:42:35 -08:00
|
|
|
a_Z = a_Z - a_ChunkZ * 16;
|
2012-02-15 06:22:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts absolute block coords to chunk coords:
|
|
|
|
inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkZ )
|
|
|
|
{
|
|
|
|
(void)a_Y;
|
|
|
|
a_ChunkX = a_X / 16;
|
|
|
|
if ((a_X < 0) && (a_X % 16 != 0))
|
|
|
|
{
|
|
|
|
a_ChunkX--;
|
|
|
|
}
|
|
|
|
a_ChunkZ = a_Z / 16;
|
|
|
|
if ((a_Z < 0) && (a_Z % 16 != 0))
|
|
|
|
{
|
|
|
|
a_ChunkZ--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-10-03 11:41:19 -07:00
|
|
|
private:
|
2012-02-08 04:36:54 -08:00
|
|
|
|
2011-10-03 11:41:19 -07:00
|
|
|
class cChunkLayer
|
|
|
|
{
|
|
|
|
public:
|
2012-02-13 13:47:03 -08:00
|
|
|
cChunkLayer(int a_LayerX, int a_LayerZ, cChunkMap * a_Parent);
|
|
|
|
|
|
|
|
/// Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check
|
|
|
|
cChunkPtr GetChunk( int a_ChunkX, int a_ChunkZ );
|
|
|
|
|
|
|
|
int GetX(void) const {return m_LayerX; }
|
|
|
|
int GetZ(void) const {return m_LayerZ; }
|
2012-02-16 05:23:54 -08:00
|
|
|
int GetNumChunksLoaded(void) const
|
|
|
|
{
|
|
|
|
int NumChunks = 0;
|
|
|
|
for( int i = 0; i < LAYER_SIZE*LAYER_SIZE; ++i )
|
|
|
|
if( m_Chunks[i].get() )
|
|
|
|
NumChunks++;
|
|
|
|
return NumChunks;
|
|
|
|
}
|
2012-01-30 05:54:39 -08:00
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
void Save(void);
|
|
|
|
void UnloadUnusedChunks(void);
|
|
|
|
|
|
|
|
void Tick( float a_Dt, MTRand & a_TickRand );
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
cChunkPtr m_Chunks[LAYER_SIZE * LAYER_SIZE];
|
|
|
|
int m_LayerX;
|
|
|
|
int m_LayerZ;
|
|
|
|
cChunkMap * m_Parent;
|
2011-10-03 11:41:19 -07:00
|
|
|
int m_NumChunksLoaded;
|
|
|
|
};
|
2012-02-13 13:47:03 -08:00
|
|
|
|
|
|
|
typedef std::list<cChunkLayer *> cChunkLayerList;
|
|
|
|
// TODO: Use smart pointers for cChunkLayerList as well, so that ticking and saving needn't lock the entire layerlist
|
|
|
|
// This however means that cChunkLayer needs to interlock its m_Chunks[]
|
2011-10-03 11:41:19 -07:00
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
cChunkLayer * GetLayerForChunk( int a_ChunkX, int a_ChunkZ ); // Creates the layer if it doesn't already exist
|
|
|
|
cChunkLayer * GetLayer( int a_LayerX, int a_LayerZ ); // Creates the layer if it doesn't already exist
|
|
|
|
void RemoveLayer( cChunkLayer* a_Layer );
|
2011-10-03 11:41:19 -07:00
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
cCriticalSection m_CSLayers;
|
|
|
|
cChunkLayerList m_Layers;
|
2011-10-03 11:41:19 -07:00
|
|
|
|
2012-02-13 13:47:03 -08:00
|
|
|
cWorld * m_World;
|
2011-10-29 14:19:06 -07:00
|
|
|
};
|
2012-02-08 04:36:54 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|