Delay EntityChangedWorld players' callback until Entity fully linked to world (#3330)
Otherwise, some API calls just don't seem to happen .gitignore tweak for test executables
This commit is contained in:
parent
07c5f09ecf
commit
e9d1a942d1
1
.gitignore
vendored
1
.gitignore
vendored
@ -68,6 +68,7 @@ Makefile
|
||||
*.a
|
||||
*.d
|
||||
*.so
|
||||
tests/*/*-exe
|
||||
BuildInfo.h
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
|
@ -1827,8 +1827,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
|
||||
ParentChunk->GetPosX(), ParentChunk->GetPosZ()
|
||||
);
|
||||
ParentChunk->RemoveEntity(this);
|
||||
a_World->AddPlayer(this);
|
||||
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, a_OldWorld);
|
||||
a_World->AddPlayer(this, &a_OldWorld); // New world will appropriate and announce client at his next tick
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
@ -2990,10 +2990,10 @@ void cWorld::CollectPickupsByPlayer(cPlayer & a_Player)
|
||||
|
||||
|
||||
|
||||
void cWorld::AddPlayer(cPlayer * a_Player)
|
||||
void cWorld::AddPlayer(cPlayer * a_Player, cWorld * a_OldWorld)
|
||||
{
|
||||
cCSLock Lock(m_CSPlayersToAdd);
|
||||
m_PlayersToAdd.push_back(a_Player);
|
||||
m_PlayersToAdd.emplace_back(a_Player, a_OldWorld);
|
||||
}
|
||||
|
||||
|
||||
@ -3010,7 +3010,10 @@ void cWorld::RemovePlayer(cPlayer * a_Player, bool a_RemoveFromChunk)
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSPlayersToAdd);
|
||||
m_PlayersToAdd.remove(a_Player);
|
||||
m_PlayersToAdd.remove_if([&](const std::pair< cPlayer *, cWorld * > & value) -> bool
|
||||
{
|
||||
return (value.first == a_Player);
|
||||
});
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
@ -3895,7 +3898,7 @@ void cWorld::AddQueuedPlayers(void)
|
||||
ASSERT(m_TickThread.IsCurrentThread());
|
||||
|
||||
// Grab the list of players to add, it has to be locked to access it:
|
||||
cPlayerList PlayersToAdd;
|
||||
cAwaitingPlayerList PlayersToAdd;
|
||||
{
|
||||
cCSLock Lock(m_CSPlayersToAdd);
|
||||
std::swap(PlayersToAdd, m_PlayersToAdd);
|
||||
@ -3904,8 +3907,9 @@ void cWorld::AddQueuedPlayers(void)
|
||||
// Add all the players in the grabbed list:
|
||||
{
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
for (auto Player : PlayersToAdd)
|
||||
for (auto & AwaitingPlayer : PlayersToAdd)
|
||||
{
|
||||
auto & Player = AwaitingPlayer.first;
|
||||
ASSERT(std::find(m_Players.begin(), m_Players.end(), Player) == m_Players.end()); // Is it already in the list? HOW?
|
||||
LOGD("Adding player %s to world \"%s\".", Player->GetName().c_str(), m_WorldName.c_str());
|
||||
|
||||
@ -3922,9 +3926,10 @@ void cWorld::AddQueuedPlayers(void)
|
||||
// Add all the players' clienthandles:
|
||||
{
|
||||
cCSLock Lock(m_CSClients);
|
||||
for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr)
|
||||
for (auto & AwaitingPlayer : PlayersToAdd)
|
||||
{
|
||||
cClientHandlePtr Client = (*itr)->GetClientHandlePtr();
|
||||
auto & Player = AwaitingPlayer.first;
|
||||
cClientHandlePtr Client = Player->GetClientHandlePtr();
|
||||
if (Client != nullptr)
|
||||
{
|
||||
m_Clients.push_back(Client);
|
||||
@ -3933,16 +3938,26 @@ void cWorld::AddQueuedPlayers(void)
|
||||
} // Lock(m_CSClients)
|
||||
|
||||
// Stream chunks to all eligible clients:
|
||||
for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr)
|
||||
for (auto & AwaitingPlayer : PlayersToAdd)
|
||||
{
|
||||
cClientHandle * Client = (*itr)->GetClientHandle();
|
||||
auto & Player = AwaitingPlayer.first;
|
||||
cClientHandle * Client = Player->GetClientHandle();
|
||||
if (Client != nullptr)
|
||||
{
|
||||
Client->SendPlayerMoveLook();
|
||||
Client->SendHealth();
|
||||
Client->SendWholeInventory(*(*itr)->GetWindow());
|
||||
Client->SendWholeInventory(*Player->GetWindow());
|
||||
}
|
||||
} // for itr - PlayersToAdd[]
|
||||
|
||||
// Call EntityChangedWorld callback on all eligible clients
|
||||
for (auto & AwaitingPlayer : PlayersToAdd)
|
||||
{
|
||||
if (AwaitingPlayer.second != nullptr)
|
||||
{
|
||||
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*(static_cast <cEntity *>(AwaitingPlayer.first)), *AwaitingPlayer.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,6 +61,7 @@ class cBroadcaster;
|
||||
|
||||
|
||||
typedef std::list< cPlayer * > cPlayerList;
|
||||
typedef std::list< std::pair< cPlayer *, cWorld * > > cAwaitingPlayerList;
|
||||
|
||||
typedef SharedPtr<cSetChunkData> cSetChunkDataPtr; // TODO: Change to unique_ptr once we go C++11
|
||||
typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
|
||||
@ -262,8 +263,9 @@ public:
|
||||
|
||||
/** 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. */
|
||||
void AddPlayer(cPlayer * a_Player);
|
||||
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(cPlayer * a_Player, cWorld * a_OldWorld = nullptr);
|
||||
|
||||
/** Removes the player from the world.
|
||||
Removes the player from the addition queue, too, if appropriate.
|
||||
@ -1006,7 +1008,7 @@ private:
|
||||
cCriticalSection m_CSPlayersToAdd;
|
||||
|
||||
/** List of players that are scheduled for adding, waiting for the Tick thread to add them. */
|
||||
cPlayerList m_PlayersToAdd;
|
||||
cAwaitingPlayerList m_PlayersToAdd;
|
||||
|
||||
/** CS protecting m_SetChunkDataQueue. */
|
||||
cCriticalSection m_CSSetChunkDataQueue;
|
||||
|
Loading…
Reference in New Issue
Block a user