diff options
Diffstat (limited to 'src/World.cpp')
-rw-r--r-- | src/World.cpp | 183 |
1 files changed, 151 insertions, 32 deletions
diff --git a/src/World.cpp b/src/World.cpp index 807065bfa..6bcd1391a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -743,6 +743,20 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec) m_LastTimeUpdate = m_WorldAge; } + // Add entities waiting in the queue to be added: + { + cCSLock Lock(m_CSEntitiesToAdd); + for (cEntityList::iterator itr = m_EntitiesToAdd.begin(), end = m_EntitiesToAdd.end(); itr != end; ++itr) + { + (*itr)->SetWorld(this); + m_ChunkMap->AddEntity(*itr); + } + m_EntitiesToAdd.clear(); + } + + // Add players waiting in the queue to be added: + AddQueuedPlayers(); + m_ChunkMap->Tick(a_Dt); TickClients(a_Dt); @@ -1551,9 +1565,9 @@ bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome) -void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients) { - m_ChunkMap->SetBlock(*this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); + m_ChunkMap->SetBlock(*this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_SendToClients); } @@ -1631,7 +1645,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockX, a_BlockY, a_BlockZ, *itr, IsPlayerCreated, SpeedX, SpeedY, SpeedZ ); - Pickup->Initialize(this); + Pickup->Initialize(*this); } } @@ -1652,7 +1666,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockX, a_BlockY, a_BlockZ, *itr, IsPlayerCreated, (float)a_SpeedX, (float)a_SpeedY, (float)a_SpeedZ ); - Pickup->Initialize(this); + Pickup->Initialize(*this); } } @@ -1663,7 +1677,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double int cWorld::SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta) { cFallingBlock * FallingBlock = new cFallingBlock(Vector3i(a_X, a_Y, a_Z), BlockType, BlockMeta); - FallingBlock->Initialize(this); + FallingBlock->Initialize(*this); return FallingBlock->GetUniqueID(); } @@ -1679,7 +1693,7 @@ int cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) } cExpOrb * ExpOrb = new cExpOrb(a_X, a_Y, a_Z, a_Reward); - ExpOrb->Initialize(this); + ExpOrb->Initialize(*this); return ExpOrb->GetUniqueID(); } @@ -1702,7 +1716,7 @@ int cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType return -1; } } // switch (a_MinecartType) - Minecart->Initialize(this); + Minecart->Initialize(*this); return Minecart->GetUniqueID(); } @@ -1713,7 +1727,7 @@ int cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks, double a_InitialVelocityCoeff) { cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTicks); - TNT->Initialize(this); + TNT->Initialize(*this); TNT->SetSpeed( a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1), /** -1, 0, 1 */ a_InitialVelocityCoeff * 2, @@ -2229,7 +2243,7 @@ void cWorld::SetChunkData( // Initialize the entities (outside the m_ChunkMap's CS, to fix FS #347): for (cEntityList::iterator itr = a_Entities.begin(), end = a_Entities.end(); itr != end; ++itr) { - (*itr)->Initialize(this); + (*itr)->Initialize(*this); } // If a client is requesting this chunk, send it to them: @@ -2322,23 +2336,8 @@ void cWorld::CollectPickupsByPlayer(cPlayer * a_Player) void cWorld::AddPlayer(cPlayer * a_Player) { - { - cCSLock Lock(m_CSPlayers); - - ASSERT(std::find(m_Players.begin(), m_Players.end(), a_Player) == m_Players.end()); // Is it already in the list? HOW? - - m_Players.remove(a_Player); // Make sure the player is registered only once - m_Players.push_back(a_Player); - } - - // Add the player's client to the list of clients to be ticked: - if (a_Player->GetClientHandle() != NULL) - { - cCSLock Lock(m_CSClients); - m_ClientsToAdd.push_back(a_Player->GetClientHandle()); - } - - // The player has already been added to the chunkmap as the entity, do NOT add again! + cCSLock Lock(m_CSPlayersToAdd); + m_PlayersToAdd.push_back(a_Player); } @@ -2347,17 +2346,26 @@ void cWorld::AddPlayer(cPlayer * a_Player) void cWorld::RemovePlayer(cPlayer * a_Player) { + m_ChunkMap->RemoveEntity(a_Player); { + cCSLock Lock(m_CSPlayersToAdd); + m_PlayersToAdd.remove(a_Player); + } + { cCSLock Lock(m_CSPlayers); + LOGD("Removing player \"%s\" from world \"%s\".", a_Player->GetName().c_str(), m_WorldName.c_str()); m_Players.remove(a_Player); } // Remove the player's client from the list of clients to be ticked: - if (a_Player->GetClientHandle() != NULL) + cClientHandle * Client = a_Player->GetClientHandle(); + if (Client != NULL) { + Client->RemoveFromWorld(); + m_ChunkMap->RemoveClientFromChunks(Client); cCSLock Lock(m_CSClients); - m_ClientsToRemove.push_back(a_Player->GetClientHandle()); + m_ClientsToRemove.push_back(Client); } } @@ -2808,9 +2816,11 @@ void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task) + void cWorld::AddEntity(cEntity * a_Entity) { - m_ChunkMap->AddEntity(a_Entity); + cCSLock Lock(m_CSEntitiesToAdd); + m_EntitiesToAdd.push_back(a_Entity); } @@ -2819,6 +2829,19 @@ void cWorld::AddEntity(cEntity * a_Entity) bool cWorld::HasEntity(int a_UniqueID) { + // Check if the entity is in the queue to be added to the world: + { + cCSLock Lock(m_CSEntitiesToAdd); + for (cEntityList::const_iterator itr = m_EntitiesToAdd.begin(), end = m_EntitiesToAdd.end(); itr != end; ++itr) + { + if ((*itr)->GetUniqueID() == a_UniqueID) + { + return true; + } + } // for itr - m_EntitiesToAdd[] + } + + // Check if the entity is in the chunkmap: return m_ChunkMap->HasEntity(a_UniqueID); } @@ -2951,7 +2974,7 @@ int cWorld::SpawnMobFinalize(cMonster * a_Monster) delete a_Monster; return -1; } - if (!a_Monster->Initialize(this)) + if (!a_Monster->Initialize(*this)) { delete a_Monster; return -1; @@ -2973,7 +2996,7 @@ int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProje { return -1; } - if (!Projectile->Initialize(this)) + if (!Projectile->Initialize(*this)) { delete Projectile; return -1; @@ -3103,6 +3126,60 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c +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; + { + cCSLock Lock(m_CSPlayersToAdd); + std::swap(PlayersToAdd, m_PlayersToAdd); + } + + // Add all the players in the grabbed list: + { + cCSLock Lock(m_CSPlayers); + for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr) + { + ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW? + + m_Players.push_back(*itr); + (*itr)->SetWorld(this); + + // Add to chunkmap, if not already there (Spawn vs MoveToWorld): + m_ChunkMap->AddEntityIfNotPresent(*itr); + } // for itr - PlayersToAdd[] + } // Lock(m_CSPlayers) + + // Add all the players' clienthandles: + { + cCSLock Lock(m_CSClients); + for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr) + { + cClientHandle * Client = (*itr)->GetClientHandle(); + if (Client != NULL) + { + m_Clients.push_back(Client); + } + } // for itr - PlayersToAdd[] + } // Lock(m_CSClients) + + // Stream chunks to all eligible clients: + for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr) + { + cClientHandle * Client = (*itr)->GetClientHandle(); + if (Client != NULL) + { + Client->StreamChunks(); + } + } // for itr - PlayersToAdd[] +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorld::cTaskSaveAllChunks: @@ -3128,6 +3205,49 @@ void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cWorld::cTaskSendBlockTo + +cWorld::cTaskSendBlockToAllPlayers::cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue) : + m_SendQueue(a_SendQueue) +{ +} + +void cWorld::cTaskSendBlockToAllPlayers::Run(cWorld & a_World) +{ + class cPlayerCallback : + public cPlayerListCallback + { + public: + cPlayerCallback(std::vector<Vector3i> & a_SendQueue, cWorld & a_World) : + m_SendQueue(a_SendQueue), + m_World(a_World) + { + } + + virtual bool Item(cPlayer * a_Player) + { + for (std::vector<Vector3i>::const_iterator itr = m_SendQueue.begin(); itr != m_SendQueue.end(); ++itr) + { + m_World.SendBlockTo(itr->x, itr->y, itr->z, a_Player); + } + return false; + } + + private: + + std::vector<Vector3i> m_SendQueue; + cWorld & m_World; + + } PlayerCallback(m_SendQueue, a_World); + + a_World.ForEachPlayer(PlayerCallback); +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorld::cChunkGeneratorCallbacks: cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks(cWorld & a_World) : @@ -3200,4 +3320,3 @@ void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_Ch - |