Thread safe cMap manager
This commit is contained in:
parent
83d3a2eedf
commit
f201f4f176
@ -51,15 +51,6 @@ const int NEST_SIZE_GRAVEL = 32;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T> T Clamp(T a_Value, T a_Min, T a_Max)
|
|
||||||
{
|
|
||||||
return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cStructGenTrees:
|
// cStructGenTrees:
|
||||||
|
|
||||||
|
@ -235,11 +235,11 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Clamp a_X to the specified range. */
|
/** Clamp X to the specified range. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Clamp(T a_X, T a_Min, T a_Max)
|
T Clamp(T a_Value, T a_Min, T a_Max)
|
||||||
{
|
{
|
||||||
return std::min(std::max(a_X, a_Min), a_Max);
|
return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
15
src/Map.h
15
src/Map.h
@ -28,7 +28,14 @@ class cMap;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Encapsulates a map decorator. */
|
/** Encapsulates a map decorator.
|
||||||
|
*
|
||||||
|
* A map decorator represents an object drawn on the map that can move freely.
|
||||||
|
* (e.g. player trackers and item frame pointers)
|
||||||
|
*
|
||||||
|
* Excluding manually placed decorators,
|
||||||
|
* decorators are automatically managed (allocated and freed) by their parent cMap instance.
|
||||||
|
*/
|
||||||
class cMapDecorator
|
class cMapDecorator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -98,7 +105,11 @@ public:
|
|||||||
|
|
||||||
typedef std::vector<ColorID> cColorList;
|
typedef std::vector<ColorID> cColorList;
|
||||||
|
|
||||||
/** Encapsulates the state of a map client. */
|
/** Encapsulates the state of a map client.
|
||||||
|
*
|
||||||
|
* In order to enhance performace, maps are streamed column-by-column to each client.
|
||||||
|
* This structure stores the state of the stream.
|
||||||
|
*/
|
||||||
struct cMapClient
|
struct cMapClient
|
||||||
{
|
{
|
||||||
cClientHandle * m_Handle;
|
cClientHandle * m_Handle;
|
||||||
|
178
src/MapManager.cpp
Normal file
178
src/MapManager.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
|
||||||
|
// MapManager.cpp
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include "MapManager.h"
|
||||||
|
|
||||||
|
#include "World.h"
|
||||||
|
#include "WorldStorage/MapSerializer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cMapManager::cMapManager(cWorld * a_World)
|
||||||
|
: m_World(a_World)
|
||||||
|
{
|
||||||
|
ASSERT(m_World != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cMapManager::DoWithMap(unsigned int a_ID, cMapCallback & a_Callback)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CS);
|
||||||
|
cMap * Map = GetMapData(a_ID);
|
||||||
|
|
||||||
|
if (Map == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a_Callback.Item(Map);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cMapManager::ForEachMap(cMapCallback & a_Callback)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CS);
|
||||||
|
for (cMapList::iterator itr = m_MapData.begin(); itr != m_MapData.end(); ++itr)
|
||||||
|
{
|
||||||
|
cMap * Map = &(*itr);
|
||||||
|
if (a_Callback.Item(Map))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // for itr - m_MapData[]
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cMap * cMapManager::GetMapData(unsigned int a_ID)
|
||||||
|
{
|
||||||
|
if (a_ID < m_MapData.size())
|
||||||
|
{
|
||||||
|
return &m_MapData[a_ID];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cMap * cMapManager::CreateMap(int a_CenterX, int a_CenterY, int a_Scale)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CS);
|
||||||
|
|
||||||
|
if (m_MapData.size() >= 65536)
|
||||||
|
{
|
||||||
|
LOGWARN("Could not craft map - Too many maps in use");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cMap Map(m_MapData.size(), a_CenterX, a_CenterY, m_World, a_Scale);
|
||||||
|
|
||||||
|
m_MapData.push_back(Map);
|
||||||
|
|
||||||
|
return &m_MapData[Map.GetID()];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int cMapManager::GetNumMaps(void) const
|
||||||
|
{
|
||||||
|
return m_MapData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cMapManager::LoadMapData(void)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CS);
|
||||||
|
|
||||||
|
cIDCountSerializer IDSerializer(m_World->GetName());
|
||||||
|
|
||||||
|
if (!IDSerializer.Load())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int MapCount = IDSerializer.GetMapCount();
|
||||||
|
|
||||||
|
m_MapData.clear();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < MapCount; ++i)
|
||||||
|
{
|
||||||
|
cMap Map(i, m_World);
|
||||||
|
|
||||||
|
cMapSerializer Serializer(m_World->GetName(), &Map);
|
||||||
|
|
||||||
|
if (!Serializer.Load())
|
||||||
|
{
|
||||||
|
LOGWARN("Could not load map #%i", Map.GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_MapData.push_back(Map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cMapManager::SaveMapData(void)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CS);
|
||||||
|
|
||||||
|
if (m_MapData.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cIDCountSerializer IDSerializer(m_World->GetName());
|
||||||
|
|
||||||
|
IDSerializer.SetMapCount(m_MapData.size());
|
||||||
|
|
||||||
|
if (!IDSerializer.Save())
|
||||||
|
{
|
||||||
|
LOGERROR("Could not save idcounts.dat");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cMapList::iterator it = m_MapData.begin(); it != m_MapData.end(); ++it)
|
||||||
|
{
|
||||||
|
cMap & Map = *it;
|
||||||
|
|
||||||
|
cMapSerializer Serializer(m_World->GetName(), &Map);
|
||||||
|
|
||||||
|
if (!Serializer.Save())
|
||||||
|
{
|
||||||
|
LOGWARN("Could not save map #%i", Map.GetID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
76
src/MapManager.h
Normal file
76
src/MapManager.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
// MapManager.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "Map.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef cItemCallback<cMap> cMapCallback;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Manages the in-game maps of a single world - Thread safe. */
|
||||||
|
class cMapManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
cMapManager(cWorld * a_World);
|
||||||
|
|
||||||
|
/** Returns the map with the specified ID, NULL if out of range.
|
||||||
|
*
|
||||||
|
* WARNING: The returned map object is not thread safe.
|
||||||
|
*/
|
||||||
|
cMap * GetMapData(unsigned int a_ID);
|
||||||
|
|
||||||
|
/** Creates a new map. Returns NULL on error */
|
||||||
|
cMap * CreateMap(int a_CenterX, int a_CenterY, int a_Scale = 3);
|
||||||
|
|
||||||
|
/** Calls the callback for the map with the specified ID.
|
||||||
|
*
|
||||||
|
* Returns true if the map was found and the callback called, false if map not found.
|
||||||
|
* Callback return ignored.
|
||||||
|
*/
|
||||||
|
bool DoWithMap(unsigned int a_ID, cMapCallback & a_Callback);
|
||||||
|
|
||||||
|
/** Calls the callback for each map.
|
||||||
|
*
|
||||||
|
* Returns true if all maps processed, false if the callback aborted by returning true.
|
||||||
|
*/
|
||||||
|
bool ForEachMap(cMapCallback & a_Callback);
|
||||||
|
|
||||||
|
unsigned int GetNumMaps(void) const;
|
||||||
|
|
||||||
|
/** Loads the map data from the disk */
|
||||||
|
void LoadMapData(void);
|
||||||
|
|
||||||
|
/** Saves the map data to the disk */
|
||||||
|
void SaveMapData(void);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef std::vector<cMap> cMapList;
|
||||||
|
|
||||||
|
cCriticalSection m_CS;
|
||||||
|
|
||||||
|
cMapList m_MapData;
|
||||||
|
|
||||||
|
cWorld * m_World;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,8 +12,8 @@
|
|||||||
#include "Generating/ChunkDesc.h"
|
#include "Generating/ChunkDesc.h"
|
||||||
#include "OSSupport/Timer.h"
|
#include "OSSupport/Timer.h"
|
||||||
|
|
||||||
|
// Serializers
|
||||||
#include "WorldStorage/ScoreboardSerializer.h"
|
#include "WorldStorage/ScoreboardSerializer.h"
|
||||||
#include "WorldStorage/MapSerializer.h"
|
|
||||||
|
|
||||||
// Entities (except mobs):
|
// Entities (except mobs):
|
||||||
#include "Entities/ExpOrb.h"
|
#include "Entities/ExpOrb.h"
|
||||||
@ -233,6 +233,7 @@ void cWorld::cTickThread::Execute(void)
|
|||||||
// cWorld:
|
// cWorld:
|
||||||
|
|
||||||
cWorld::cWorld(const AString & a_WorldName) :
|
cWorld::cWorld(const AString & a_WorldName) :
|
||||||
|
cMapManager(this),
|
||||||
m_WorldName(a_WorldName),
|
m_WorldName(a_WorldName),
|
||||||
m_IniFileName(m_WorldName + "/world.ini"),
|
m_IniFileName(m_WorldName + "/world.ini"),
|
||||||
m_StorageSchema("Default"),
|
m_StorageSchema("Default"),
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "Entities/ProjectileEntity.h"
|
#include "Entities/ProjectileEntity.h"
|
||||||
#include "ForEachChunkProvider.h"
|
#include "ForEachChunkProvider.h"
|
||||||
#include "Scoreboard.h"
|
#include "Scoreboard.h"
|
||||||
#include "Map.h"
|
#include "MapManager.h"
|
||||||
#include "Blocks/WorldInterface.h"
|
#include "Blocks/WorldInterface.h"
|
||||||
#include "Blocks/BroadcastInterface.h"
|
#include "Blocks/BroadcastInterface.h"
|
||||||
|
|
||||||
@ -71,7 +71,8 @@ typedef cItemCallback<cMobHeadEntity> cMobHeadBlockCallback;
|
|||||||
class cWorld :
|
class cWorld :
|
||||||
public cForEachChunkProvider,
|
public cForEachChunkProvider,
|
||||||
public cWorldInterface,
|
public cWorldInterface,
|
||||||
public cBroadcastInterface
|
public cBroadcastInterface,
|
||||||
|
public cMapManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user