summaryrefslogtreecommitdiffstats
path: root/src/World.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/World.h')
-rw-r--r--src/World.h142
1 files changed, 44 insertions, 98 deletions
diff --git a/src/World.h b/src/World.h
index c1794b159..6d5df5c4a 100644
--- a/src/World.h
+++ b/src/World.h
@@ -28,7 +28,7 @@
#include "FastRandom.h"
#include "ClientHandle.h"
#include "EffectID.h"
-#include <functional>
+#include <future>
@@ -39,9 +39,6 @@ class cRedstoneSimulator;
class cItem;
class cPlayer;
class cClientHandle;
-typedef SharedPtr<cClientHandle> cClientHandlePtr;
-typedef std::list<cClientHandlePtr> cClientHandlePtrs;
-typedef std::list<cClientHandle *> cClientHandles;
class cEntity;
class cBlockEntity;
class cWorldGenerator; // The generator that actually generates the chunks for a single world
@@ -59,12 +56,6 @@ class cCuboid;
class cSetChunkData;
class cBroadcaster;
-
-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<cBeaconEntity> cBeaconCallback;
@@ -92,14 +83,9 @@ public:
// tolua_end
- /** A simple RAII locker for the chunkmap - locks the chunkmap in its constructor, unlocks it in the destructor */
- class cLock :
- public cCSLock
- {
- typedef cCSLock super;
- public:
- cLock(cWorld & a_World);
- };
+ cWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = "");
+ virtual ~cWorld();
+ cWorld(const cWorld & a_World) = delete;
static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates
{
@@ -234,7 +220,7 @@ public:
/** 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 QueueSetChunkData(cSetChunkData & a_SetChunkData);
void ChunkLighted(
int a_ChunkX, int a_ChunkZ,
@@ -267,9 +253,8 @@ public:
/** Removes the player from the world.
Removes the player from the addition queue, too, if appropriate.
- If the player has a ClientHandle, the ClientHandle is removed from all chunks in the world and will not be ticked by this world anymore.
- @param a_RemoveFromChunk determines if the entity should be removed from its chunk as well. Should be false when ticking from cChunk. */
- void RemovePlayer(cPlayer * a_Player, bool a_RemoveFromChunk);
+ If the player has a ClientHandle, the ClientHandle is removed from all chunks in the world and will not be ticked by this world anymore. */
+ void RemovePlayer(cPlayer * a_Player);
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
virtual bool ForEachPlayer(cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS <<
@@ -291,7 +276,7 @@ public:
/** Adds the entity into its appropriate chunk; takes ownership of the entity ptr.
The entity is added lazily - this function only puts it in a queue that is then processed by the Tick thread. */
- void AddEntity(cEntity * a_Entity);
+ void AddEntity(std::unique_ptr<cEntity> a_Entity);
/** Returns true if an entity with the specified UniqueID exists in the world.
Note: Only loaded chunks are considered. */
@@ -316,24 +301,12 @@ public:
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
/** Adds client to a chunk, if not already present; returns true if added, false if present */
- bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
+ bool AddChunkClient(int a_ChunkX, int a_ChunkZ, const std::shared_ptr<cClientHandle> & a_Client);
/** Removes client from the chunk specified */
- void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
-
- /** Removes the client from all chunks it is present in */
- void RemoveClientFromChunks(cClientHandle * a_Client);
-
- /** Sends the chunk to the client specified, if the client doesn't have the chunk yet.
- If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */
- void SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client);
+ void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, const std::shared_ptr<cClientHandle> & a_Client);
- /** Sends the chunk to the client specified, even if the client already has the chunk.
- If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */
- void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client);
-
- /** Removes client from ChunkSender's queue of chunks to be sent */
- void RemoveClientFromChunkSender(cClientHandle * a_Client);
+ cChunkSender & GetChunkSender(void) { return m_ChunkSender; }
/** Touches the chunk, causing it to be loaded or generated */
void TouchChunk(int a_ChunkX, int a_ChunkZ);
@@ -675,7 +648,13 @@ public:
void QueueSaveAllChunks(void); // tolua_export
/** Queues a task onto the tick thread. The task object will be deleted once the task is finished */
- void QueueTask(std::function<void(cWorld &)> a_Task); // Exported in ManualBindings.cpp
+ template <typename FunctionType>
+ auto QueueTask(FunctionType && a_Task) // Exported in ManualBindings.cpp
+ {
+ cCSLock Lock(m_CSTasks);
+ m_Tasks.emplace_back(-1, std::forward<FunctionType>(a_Task));
+ return m_Tasks.back().second.get_future();
+ }
/** Queues a lambda task onto the tick thread, with the specified delay. */
void ScheduleTask(int a_DelayTicks, std::function<void(cWorld &)> a_Task);
@@ -694,10 +673,16 @@ public:
cLightingThread & GetLightingThread(void) { return m_Lighting; }
- void InitializeSpawn(void);
+ /** Starts the tick thread that belongs to this world. */
+ void Start(void) { m_TickThread.Start(); }
- /** Starts threads that belong to this world */
- void Start(void);
+ /** Performs one-off initial configuration of the world.
+ MUST be called within the context of the world tick thread. */
+ void Initialise(void);
+
+ /** Performs one-off initial configuration of the world spawn.
+ MUST be called within the context of the world tick thread. */
+ void InitialiseSpawn(void);
/** Stops threads that belong to this world (part of deinit) */
void Stop(void);
@@ -785,7 +770,7 @@ public:
/** Spawns a mob of the specified type. Returns the mob's UniqueID if recognized and spawned, cEntity::INVALID_ID otherwise */
virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby = false) override; // tolua_export
- UInt32 SpawnMobFinalize(cMonster * a_Monster);
+ UInt32 SpawnMobFinalize(std::unique_ptr<cMonster> a_Monster);
/** Creates a projectile of the specified type. Returns the projectile's UniqueID if successful, cEntity::INVALID_ID otherwise
Item parameter is currently used for Fireworks to correctly set entity metadata based on item metadata. */
@@ -809,6 +794,14 @@ public:
cBroadcaster GetBroadcaster();
+#ifdef _DEBUG
+
+ /** Debug-only function to ensure the current execution is within the context of this world's tick thread
+ Enforces single-thread access requirements of cWorld, cChunkMap, cChunk, cEntity and descendants, etc. */
+ bool IsInTickThread(void) { return m_TickThread.IsCurrentThread(); }
+
+#endif
+
private:
friend class cRoot;
@@ -846,8 +839,11 @@ private:
public:
cChunkGeneratorCallbacks(cWorld & a_World);
- } ;
+ };
+ /** Flag to indicate whether cWorld::Tick should be called in cTickThread::Execute.
+ MUST NOT be mutated by a caller other than cWorld::Stop. */
+ bool m_ShouldTick;
AString m_WorldName;
@@ -909,8 +905,9 @@ private:
std::unique_ptr<cFireSimulator> m_FireSimulator;
cRedstoneSimulator * m_RedstoneSimulator;
- cCriticalSection m_CSPlayers;
- cPlayerList m_Players;
+ /** Stores pointers to all players in the world for easy access.
+ Players MUST be removed from this list through a call to RemovePlayer before they are destroyed. */
+ std::vector<cPlayer *> m_Players;
cWorldStorage m_Storage;
@@ -982,41 +979,7 @@ private:
cCriticalSection m_CSTasks;
/** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */
- std::vector<std::pair<Int64, std::function<void(cWorld &)>>> m_Tasks;
-
- /** Guards m_Clients */
- cCriticalSection m_CSClients;
-
- /** List of clients in this world, these will be ticked by this world */
- cClientHandlePtrs m_Clients;
-
- /** Clients that are scheduled for removal (ticked in another world), waiting for TickClients() to remove them */
- cClientHandles m_ClientsToRemove;
-
- /** Clients that are scheduled for adding, waiting for TickClients to add them */
- cClientHandlePtrs m_ClientsToAdd;
-
- /** Guards m_EntitiesToAdd */
- cCriticalSection m_CSEntitiesToAdd;
-
- /** List of entities that are scheduled for adding, waiting for the Tick thread to add them. */
- cEntityList m_EntitiesToAdd;
-
- /** Guards m_PlayersToAdd */
- cCriticalSection m_CSPlayersToAdd;
-
- /** 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, eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = "");
- virtual ~cWorld();
+ std::vector<std::pair<Int64, std::packaged_task<void(cWorld &)>>> m_Tasks;
void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
@@ -1029,24 +992,11 @@ private:
/** Executes all tasks queued onto the tick thread */
void TickQueuedTasks(void);
- /** Ticks all clients that are in this world */
- void TickClients(float a_Dt);
-
/** Unloads all chunks immediately. */
void UnloadUnusedChunks(void);
void UpdateSkyDarkness(void);
- /** Generates a random spawnpoint on solid land by walking chunks and finding their biomes */
- void GenerateRandomSpawn(int a_MaxSpawnRadius);
-
- /** Can the specified coordinates be used as a spawn point?
- Returns true if spawn position is valid and sets a_Y to the valid spawn height */
- bool CanSpawnAt(double a_X, double & a_Y, double a_Z);
-
- /** Check if player starting point is acceptable */
- bool CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ);
-
/** Chooses a reasonable transition from the current weather to a new weather */
eWeather ChooseNewWeather(void);
@@ -1056,10 +1006,6 @@ private:
/** Creates a new redstone simulator. */
cRedstoneSimulator * InitializeRedstoneSimulator(cIniFile & a_IniFile);
- /** 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 generator values to dimension specific defaults, if those values do not exist */
void InitialiseGeneratorDefaults(cIniFile & a_IniFile);