diff --git a/src/Root.cpp b/src/Root.cpp index 737d350ff..e022de588 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -327,6 +327,17 @@ void cRoot::Start(std::unique_ptr a_OverridesRepo) +void cRoot::StopServer() +{ + m_TerminateEventRaised = true; + m_StopEvent.Set(); + m_InputThreadRunFlag.clear(); +} + + + + + void cRoot::LoadGlobalSettings() { // Nothing needed yet @@ -597,9 +608,7 @@ void cRoot::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback // Some commands are built-in: if (a_Cmd == "stop") { - m_TerminateEventRaised = true; - m_StopEvent.Set(); - m_InputThreadRunFlag.clear(); + StopServer(); return; } else if (a_Cmd == "restart") diff --git a/src/Root.h b/src/Root.h index 261dac29f..2ce0e7c32 100644 --- a/src/Root.h +++ b/src/Root.h @@ -57,6 +57,9 @@ public: void Start(std::unique_ptr a_OverridesRepo); + /** Stops the server, as if "/stop" was typed in the console. */ + void StopServer(); + // tolua_begin cServer * GetServer(void) { return m_Server; } cWorld * GetDefaultWorld(void); @@ -66,6 +69,7 @@ public: */ cWorld * GetWorld(const AString & a_WorldName, bool a_SearchForFolder = false); + /** Returns a pointer to a world of specified name - will search loaded worlds first, then create anew if not found The dimension parameter is used to create a world with a specific dimension a_OverworldName should be set for non-overworld dimensions if one wishes that world to link back to an overworld via portals diff --git a/src/World.cpp b/src/World.cpp index 5b6a215d8..3d56cbe2e 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -520,6 +520,40 @@ void cWorld::Start(void) m_LinkedOverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName()); } + // If we are linked to one or more worlds that do not exist, ask the server to stop. + AString BadWorlds = ""; + cRoot * Root = cRoot::Get(); + if (GetDimension() == dimOverworld) + { + if ((!m_LinkedNetherWorldName.empty()) && (Root->GetWorld(m_LinkedNetherWorldName) == nullptr)) + { + BadWorlds = m_LinkedNetherWorldName; + } + if ((!m_LinkedEndWorldName.empty()) && (Root->GetWorld(m_LinkedEndWorldName) == nullptr)) + { + if (!(BadWorlds.empty())) + { + BadWorlds += ", "; + } + BadWorlds += m_LinkedEndWorldName; + } + } + else + { + if ((!m_LinkedOverworldName.empty()) && (Root->GetWorld(m_LinkedOverworldName) == nullptr)) + { + BadWorlds = m_LinkedOverworldName; + } + } + if (!BadWorlds.empty()) + { + const char * WorldName = m_WorldName.c_str(); + LOGERROR("\n######\nERROR: %s is linked to one or more invalid worlds: %s\nPlease edit %s/world.ini and fix this.\n######\n", + WorldName, BadWorlds.c_str(), WorldName); + cRoot::Get()->StopServer(); + } + + // Adjust the enum-backed variables into their respective bounds: m_GameMode = static_cast (Clamp(GameMode, gmSurvival, gmSpectator)); m_TNTShrapnelLevel = static_cast(Clamp(TNTShrapnelLevel, slNone, slAll));