From 054a89dd9e5d6819adede9d7ba781b69f98ff2f4 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 6 Jan 2021 00:35:42 +0000 Subject: Clarify cClientHandle, cPlayer ownership semantics + A cPlayer, once created, has a strong pointer to the cClientHandle. The player ticks the clienthandle. If he finds the handle destroyed, he destroys himself in turn. Nothing else can kill the player. * The client handle has a pointer to the player. Once a player is created, the client handle never outlasts the player, nor does it manage the player's lifetime. The pointer is always safe to use after FinishAuthenticate, which is also the point where cProtocol is put into the Game state that allows player manipulation. + Entities are once again never lost by constructing a chunk when they try to move into one that doesn't exist. * Fixed a forgotten Super invocation in cPlayer::OnRemoveFromWorld. * Fix SaveToDisk usage in destructor by only saving things cPlayer owns, instead of accessing cWorld. --- src/World.h | 56 ++++++++------------------------------------------------ 1 file changed, 8 insertions(+), 48 deletions(-) (limited to 'src/World.h') diff --git a/src/World.h b/src/World.h index ba4e5ee58..2fc5040b8 100644 --- a/src/World.h +++ b/src/World.h @@ -54,7 +54,6 @@ class cDeadlockDetect; class cUUID; typedef std::list< cPlayer * > cPlayerList; -typedef std::list< std::pair< std::unique_ptr, cWorld * > > cAwaitingPlayerList; typedef std::unique_ptr cSetChunkDataPtr; typedef std::vector cSetChunkDataPtrs; @@ -269,22 +268,6 @@ public: void CollectPickupsByPlayer(cPlayer & a_Player); - /** Adds the player to the world. - Uses a queue to store the player object until the Tick thread processes the addition event. - Also adds the player as an entity in the chunkmap, and the player's ClientHandle, if any, for ticking. - If a_OldWorld is provided, a corresponding ENTITY_CHANGED_WORLD event is triggerred after the addition. */ - void AddPlayer(std::unique_ptr a_Player, cWorld * a_OldWorld = nullptr); - - /** 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. - @return An owning reference to the given player. */ - std::unique_ptr RemovePlayer(cPlayer & a_Player); - -#ifdef _DEBUG - bool IsPlayerReferencedInWorldOrChunk(cPlayer & a_Player); -#endif - /** 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 << @@ -304,8 +287,9 @@ public: void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player /** 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(OwnedEntity a_Entity); + The entity is added lazily - this function only puts it in a queue that is then processed by the Tick thread. + If a_OldWorld is provided, a corresponding ENTITY_CHANGED_WORLD event is triggerred after the addition. */ + void AddEntity(OwnedEntity a_Entity, cWorld * a_OldWorld = nullptr); /** Removes the entity from the world. Returns an owning reference to the found entity. */ @@ -346,9 +330,6 @@ public: 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::Priority a_Priority, cClientHandle * a_Client); - /** Removes client from ChunkSender's queue of chunks to be sent */ - void RemoveClientFromChunkSender(cClientHandle * a_Client); - /** Queues the chunk for preparing - making sure that it's generated and lit. The specified chunk is queued to be loaded or generated, and lit if needed. The specified callback is called after the chunk has been prepared. If there's no preparation to do, only the callback is called. @@ -1271,29 +1252,11 @@ private: /** 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>> 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. */ - cAwaitingPlayerList m_PlayersToAdd; + std::vector> m_EntitiesToAdd; /** CS protecting m_SetChunkDataQueue. */ cCriticalSection m_CSSetChunkDataQueue; @@ -1309,12 +1272,13 @@ private: /** Handles the mob spawning / moving / destroying each tick */ void TickMobs(std::chrono::milliseconds a_Dt); + /** Adds the entities queued in the m_EntitiesToAdd queue into their chunk. + If the entity was a player, he is also added to the m_Players list. */ + void TickQueuedEntityAdditions(void); + /** 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); @@ -1339,10 +1303,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 mob spawning values if nonexistant to their dimension specific defaults */ void InitializeAndLoadMobSpawningValues(cIniFile & a_IniFile); -- cgit v1.2.3