From a28b0dc1201dca7c34d9a6c33232157e45a6d4f8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 22 Jul 2014 17:26:48 +0100 Subject: [PATCH] Speed improvements, crash fixes, & self-suggestions --- src/Chunk.cpp | 19 +++++-------- src/Entities/Entity.cpp | 59 ++++++++++++++++++++--------------------- src/Entities/Entity.h | 6 +++-- src/Entities/Player.cpp | 6 +++-- src/Entities/Player.h | 1 - src/Root.cpp | 6 +++-- src/World.cpp | 17 +++++------- src/World.h | 2 +- 8 files changed, 55 insertions(+), 61 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 9b9646b0c..0be61f753 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -583,19 +583,14 @@ void cChunk::Tick(float a_Dt) m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty; } - // Tick all entities in this chunk (except mobs): - for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) - { - // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) - // Don't tick things queued to be removed - if (!((*itr)->IsMob())) + for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) + { + if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) { + // Tick all entities in this chunk (except mobs): (*itr)->Tick(a_Dt, *this); } - } // for itr - m_Entitites[] - - for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) - { + if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal: { LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); @@ -604,7 +599,7 @@ void cChunk::Tick(float a_Dt) itr = m_Entities.erase(itr); delete ToDelete; } - else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world + else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world: { MarkDirty(); (*itr)->SetWorldTravellingFrom(NULL); @@ -1899,7 +1894,7 @@ void cChunk::AddEntity(cEntity * a_Entity) MarkDirty(); } - ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); + ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already m_Entities.push_back(a_Entity); } diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index a7340a29c..68bfabb30 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -614,11 +614,13 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) // Handle drowning HandleAir(); + } + + if (!DetectPortal()) // Our chunk is invalid if we have moved to another world + { + // None of the above functions changed position, we remain in the chunk of NextChunk + HandlePhysics(a_Dt, *NextChunk); } - DetectPortal(); - - // None of the above functions change position, we remain in the chunk of NextChunk - HandlePhysics(a_Dt, *NextChunk); } } @@ -1026,18 +1028,18 @@ void cEntity::DetectCacti(void) -void cEntity::DetectPortal() +bool cEntity::DetectPortal() { if (GetWorld()->GetDimension() == dimOverworld) { if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) { - return; + return false; } } else if (GetWorld()->GetLinkedOverworldName().empty()) { - return; + return false; } int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; @@ -1049,13 +1051,13 @@ void cEntity::DetectPortal() { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { - return; + return false; } if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80) { m_PortalCooldownData.m_TicksDelayed++; - return; + return false; } m_PortalCooldownData.m_TicksDelayed = 0; @@ -1065,7 +1067,7 @@ void cEntity::DetectPortal() { if (GetWorld()->GetLinkedOverworldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1074,15 +1076,14 @@ void cEntity::DetectPortal() { ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); - - return; + + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); } case dimOverworld: { if (GetWorld()->GetNetherWorldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1092,18 +1093,17 @@ void cEntity::DetectPortal() ((cPlayer *)this)->AwardAchievement(achEnterPortal); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); - - return; + + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); } - default: return; + default: return false; } } case E_BLOCK_END_PORTAL: { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { - return; + return false; } switch (GetWorld()->GetDimension()) @@ -1112,7 +1112,7 @@ void cEntity::DetectPortal() { if (GetWorld()->GetLinkedOverworldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1122,16 +1122,15 @@ void cEntity::DetectPortal() cPlayer * Player = (cPlayer *)this; Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); Player->GetClientHandle()->SendRespawn(dimOverworld); - } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + } - return; + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); } case dimOverworld: { if (GetWorld()->GetEndWorldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1140,12 +1139,11 @@ void cEntity::DetectPortal() { ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd); - } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); + } - return; + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); } - default: return; + default: return false; } } default: break; @@ -1155,6 +1153,7 @@ void cEntity::DetectPortal() // Allow portals to work again m_PortalCooldownData.m_ShouldPreventTeleportation = false; m_PortalCooldownData.m_ShouldPreventTeleportation = 0; + return false; } @@ -1164,7 +1163,7 @@ void cEntity::DetectPortal() bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { UNUSED(a_ShouldSendRespawn); - ASSERT(a_World == NULL); + ASSERT(a_World != NULL); if (GetWorld() == a_World) { @@ -1173,7 +1172,7 @@ bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) } // Remove all links to the old world - SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal GetWorld()->BroadcastDestroyEntity(*this); // Queue add to new world diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 1679b00d6..62a4097f3 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -337,8 +337,10 @@ public: /** Detects the time for application of cacti damage */ virtual void DetectCacti(void); - /** Detects whether we are in a portal block and begins teleportation procedures if so */ - virtual void DetectPortal(void); + /** Detects whether we are in a portal block and begins teleportation procedures if so + Returns true if MoveToWorld() was called, false if not + */ + virtual bool DetectPortal(void); /// Handles when the entity is in the void virtual void TickInVoid(cChunk & a_Chunk); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index e54e10a08..087ac448f 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -95,7 +95,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : SetPosX(World->GetSpawnX()); SetPosY(World->GetSpawnY()); SetPosZ(World->GetSpawnZ()); - SetBedPos(Vector3i(World->GetSpawnX(), World->GetSpawnY(), World->GetSpawnZ())); + SetBedPos(Vector3i((int)World->GetSpawnX(), (int)World->GetSpawnY(), (int)World->GetSpawnZ())); LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}", a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ() @@ -1611,6 +1611,8 @@ void cPlayer::TossItems(const cItems & a_Items) bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { + ASSERT(a_World != NULL); + if (GetWorld() == a_World) { // Don't move to same world @@ -1624,7 +1626,7 @@ bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) } // Remove player from the old world - SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal GetWorld()->RemovePlayer(this); // Queue adding player to the new world, including all the necessary adjustments to the object diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 400377381..d1b3a0339 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -424,7 +424,6 @@ public: /** Returns wheter the player can fly or not. */ virtual bool CanFly(void) const { return m_CanFly; } - // tolua_end // cEntity overrides: diff --git a/src/Root.cpp b/src/Root.cpp index b793cb154..b65e9b067 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -314,10 +314,12 @@ void cRoot::LoadWorlds(cIniFile & IniFile) cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) { - if (m_WorldsByName[a_WorldName] != NULL) + cWorld * World = m_WorldsByName[a_WorldName]; + if (World != NULL) { - return NULL; + return World; } + cWorld * NewWorld = new cWorld(a_WorldName.c_str(), a_Dimension, a_OverworldName); m_WorldsByName[a_WorldName] = NewWorld; NewWorld->Start(); diff --git a/src/World.cpp b/src/World.cpp index 2736e77d3..9cbaf48fb 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -255,8 +255,7 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin m_Scoreboard(this), m_MapManager(this), m_GeneratorCallbacks(*this), - m_TickThread(*this) - + m_TickThread(*this) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); @@ -526,7 +525,7 @@ void cWorld::Start(void) // TODO: More descriptions for each key IniFile.AddHeaderComment(" This is the per-world configuration file, managing settings such as generators, simulators, and spawn points"); - IniFile.AddKeyComment("LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation"); + IniFile.AddKeyComment(" LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation"); } // The presence of a configuration value overrides everything @@ -784,7 +783,7 @@ void cWorld::Stop(void) // Write settings to file; these are all plugin changeable values - keep updated! cIniFile IniFile; IniFile.ReadFile(m_IniFileName); - if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) + if (GetDimension() == dimOverworld) { IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_NetherWorldName); IniFile.SetValue("LinkedWorlds", "EndWorldName", m_EndWorldName); @@ -1040,11 +1039,7 @@ void cWorld::TickClients(float a_Dt) // Add clients scheduled for adding: for (cClientHandleList::iterator itr = m_ClientsToAdd.begin(), end = m_ClientsToAdd.end(); itr != end; ++itr) { - if (std::find(m_Clients.begin(), m_Clients.end(), *itr) != m_Clients.end()) - { - ASSERT(!"Adding a client that is already in the clientlist"); - continue; - } + ASSERT(std::find(m_Clients.begin(), m_Clients.end(), *itr) == m_Clients.end()); m_Clients.push_back(*itr); } // for itr - m_ClientsToRemove[] m_ClientsToAdd.clear(); @@ -3253,9 +3248,9 @@ void cWorld::AddQueuedPlayers(void) 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? - + ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW? LOGD("Adding player %s to world \"%s\".", (*itr)->GetName().c_str(), m_WorldName.c_str()); + m_Players.push_back(*itr); (*itr)->SetWorld(this); diff --git a/src/World.h b/src/World.h index 771cf51bf..f6c1437f1 100644 --- a/src/World.h +++ b/src/World.h @@ -669,7 +669,7 @@ public: void InitializeSpawn(void); /** Starts threads that belong to this world */ - void Start(); + void Start(void); /** Stops threads that belong to this world (part of deinit) */ void Stop(void);