summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Entities/Player.cpp4
-rw-r--r--src/MapManager.cpp8
-rw-r--r--src/Root.cpp48
-rw-r--r--src/Root.h3
-rw-r--r--src/World.cpp32
-rw-r--r--src/World.h18
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp6
7 files changed, 84 insertions, 35 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 614edef75..8d35d0bf5 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -2203,7 +2203,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
// Load the player stats.
// We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
- cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), GetUUID().ToLongString(), &m_Stats);
+ cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetDataPath(), GetName(), GetUUID().ToLongString(), &m_Stats);
StatSerializer.Load();
LOGD("Player %s was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
@@ -2301,7 +2301,7 @@ bool cPlayer::SaveToDisk()
// Save the player stats.
// We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
- cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), GetUUID().ToLongString(), &m_Stats);
+ cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetDataPath(), GetName(), GetUUID().ToLongString(), &m_Stats);
if (!StatSerializer.Save())
{
LOGWARNING("Could not save stats for player %s", GetName().c_str());
diff --git a/src/MapManager.cpp b/src/MapManager.cpp
index 2729e67dd..4408af76b 100644
--- a/src/MapManager.cpp
+++ b/src/MapManager.cpp
@@ -96,7 +96,7 @@ void cMapManager::LoadMapData(void)
{
cCSLock Lock(m_CS);
- cIDCountSerializer IDSerializer(m_World->GetName());
+ cIDCountSerializer IDSerializer(m_World->GetDataPath());
if (!IDSerializer.Load())
{
@@ -111,7 +111,7 @@ void cMapManager::LoadMapData(void)
{
cMap Map(i, m_World);
- cMapSerializer Serializer(m_World->GetName(), &Map);
+ cMapSerializer Serializer(m_World->GetDataPath(), &Map);
if (!Serializer.Load())
{
@@ -135,7 +135,7 @@ void cMapManager::SaveMapData(void)
return;
}
- cIDCountSerializer IDSerializer(m_World->GetName());
+ cIDCountSerializer IDSerializer(m_World->GetDataPath());
IDSerializer.SetMapCount(static_cast<unsigned>(m_MapData.size()));
@@ -149,7 +149,7 @@ void cMapManager::SaveMapData(void)
{
cMap & Map = *it;
- cMapSerializer Serializer(m_World->GetName(), &Map);
+ cMapSerializer Serializer(m_World->GetDataPath(), &Map);
if (!Serializer.Save())
{
diff --git a/src/Root.cpp b/src/Root.cpp
index 3e30d8a07..38c95f822 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -396,16 +396,20 @@ void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings, bool a_IsNewIn
a_Settings.AddValue("Worlds", "DefaultWorld", "world");
a_Settings.AddValue("Worlds", "World", "world_nether");
a_Settings.AddValue("Worlds", "World", "world_the_end");
- m_pDefaultWorld = new cWorld("world");
+ a_Settings.AddValue("WorldPaths", "world", "world");
+ a_Settings.AddValue("WorldPaths", "world_nether", "world_nether");
+ a_Settings.AddValue("WorldPaths", "world_the_end", "world_the_end");
+ m_pDefaultWorld = new cWorld("world", "world");
m_WorldsByName["world"] = m_pDefaultWorld;
- m_WorldsByName["world_nether"] = new cWorld("world_nether", dimNether, "world");
- m_WorldsByName["world_the_end"] = new cWorld("world_the_end", dimEnd, "world");
+ m_WorldsByName["world_nether"] = new cWorld("world_nether", "world_nether", dimNether, "world");
+ m_WorldsByName["world_the_end"] = new cWorld("world_the_end", "world_the_end", dimEnd, "world");
return;
}
// First get the default world
AString DefaultWorldName = a_Settings.GetValueSet("Worlds", "DefaultWorld", "world");
- m_pDefaultWorld = new cWorld(DefaultWorldName.c_str());
+ AString DefaultWorldPath = a_Settings.GetValueSet("WorldPaths", DefaultWorldName, DefaultWorldName);
+ m_pDefaultWorld = new cWorld(DefaultWorldName.c_str(), DefaultWorldPath.c_str());
m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
auto Worlds = a_Settings.GetValues("Worlds");
@@ -453,10 +457,15 @@ void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings, bool a_IsNewIn
FoundAdditionalWorlds = true;
cWorld * NewWorld;
AString LowercaseName = StrToLower(WorldName);
+ AString WorldPath = a_Settings.GetValueSet("WorldPaths", WorldName, WorldName);
AString NetherAppend = "_nether";
AString EndAppend1 = "_the_end";
AString EndAppend2 = "_end";
+ // The default world is an overworld with no links
+ eDimension Dimension = dimOverworld;
+ AString LinkTo = "";
+
// if the world is called x_nether
if ((LowercaseName.size() > NetherAppend.size()) && (LowercaseName.substr(LowercaseName.size() - NetherAppend.size()) == NetherAppend))
{
@@ -464,12 +473,12 @@ void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings, bool a_IsNewIn
// otherwise, choose the default world as the linked world.
// As before, any ini settings will completely override this if an ini is already present.
- AString LinkTo = WorldName.substr(0, WorldName.size() - NetherAppend.size());
+ LinkTo = WorldName.substr(0, WorldName.size() - NetherAppend.size());
if (GetWorld(LinkTo) == nullptr)
{
LinkTo = DefaultWorldName;
}
- NewWorld = new cWorld(WorldName.c_str(), dimNether, LinkTo);
+ Dimension = dimNether;
}
// if the world is called x_the_end
else if ((LowercaseName.size() > EndAppend1.size()) && (LowercaseName.substr(LowercaseName.size() - EndAppend1.size()) == EndAppend1))
@@ -478,12 +487,12 @@ void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings, bool a_IsNewIn
// otherwise, choose the default world as the linked world.
// As before, any ini settings will completely override this if an ini is already present.
- AString LinkTo = WorldName.substr(0, WorldName.size() - EndAppend1.size());
+ LinkTo = WorldName.substr(0, WorldName.size() - EndAppend1.size());
if (GetWorld(LinkTo) == nullptr)
{
LinkTo = DefaultWorldName;
}
- NewWorld = new cWorld(WorldName.c_str(), dimEnd, LinkTo);
+ Dimension = dimEnd;
}
// if the world is called x_end
else if ((LowercaseName.size() > EndAppend2.size()) && (LowercaseName.substr(LowercaseName.size() - EndAppend2.size()) == EndAppend2))
@@ -492,17 +501,14 @@ void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings, bool a_IsNewIn
// otherwise, choose the default world as the linked world.
// As before, any ini settings will completely override this if an ini is already present.
- AString LinkTo = WorldName.substr(0, WorldName.size() - EndAppend2.size());
+ LinkTo = WorldName.substr(0, WorldName.size() - EndAppend2.size());
if (GetWorld(LinkTo) == nullptr)
{
LinkTo = DefaultWorldName;
}
- NewWorld = new cWorld(WorldName.c_str(), dimEnd, LinkTo);
- }
- else
- {
- NewWorld = new cWorld(WorldName.c_str());
+ Dimension = dimEnd;
}
+ NewWorld = new cWorld(WorldName.c_str(), WorldPath.c_str(), Dimension, LinkTo);
m_WorldsByName[WorldName] = NewWorld;
} // for i - Worlds
@@ -709,6 +715,20 @@ void cRoot::SaveAllChunks(void)
+
+
+void cRoot::SetSavingEnabled(bool a_SavingEnabled)
+{
+ for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
+ {
+ itr->second->SetSavingEnabled(a_SavingEnabled);
+ }
+}
+
+
+
+
+
void cRoot::SendPlayerLists(cPlayer * a_DestPlayer)
{
for (const auto & itr : m_WorldsByName)
diff --git a/src/Root.h b/src/Root.h
index 44567018d..46b202c88 100644
--- a/src/Root.h
+++ b/src/Root.h
@@ -135,6 +135,9 @@ public:
/** Saves all chunks in all worlds */
void SaveAllChunks(void); // tolua_export
+ /** Sets whether saving chunks is enabled in all worlds (overrides however the worlds were already set) */
+ void SetSavingEnabled(bool a_SavingEnabled); // tolua_export
+
/** Calls the callback for each player in all worlds */
bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
diff --git a/src/World.cpp b/src/World.cpp
index f610d4d2e..e2ac24e71 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -120,16 +120,18 @@ void cWorld::cTickThread::Execute(void)
////////////////////////////////////////////////////////////////////////////////
// cWorld:
-cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_LinkedOverworldName) :
+cWorld::cWorld(const AString & a_WorldName, const AString & a_DataPath, eDimension a_Dimension, const AString & a_LinkedOverworldName) :
m_WorldName(a_WorldName),
+ m_DataPath(a_DataPath),
m_LinkedOverworldName(a_LinkedOverworldName),
- m_IniFileName(m_WorldName + "/world.ini"),
+ m_IniFileName(m_DataPath + "/world.ini"),
m_StorageSchema("Default"),
#ifdef __arm__
m_StorageCompressionFactor(0),
#else
m_StorageCompressionFactor(6),
#endif
+ m_IsSavingEnabled(true),
m_Dimension(a_Dimension),
m_IsSpawnExplicitlySet(false),
m_SpawnX(0),
@@ -194,10 +196,10 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin
{
LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str());
- cFile::CreateFolder(FILE_IO_PREFIX + m_WorldName);
+ cFile::CreateFolderRecursive(FILE_IO_PREFIX + m_DataPath);
// Load the scoreboard
- cScoreboardSerializer Serializer(m_WorldName, &m_Scoreboard);
+ cScoreboardSerializer Serializer(m_DataPath, &m_Scoreboard);
Serializer.Load();
}
@@ -213,11 +215,14 @@ cWorld::~cWorld()
m_Storage.WaitForFinish();
- // Unload the scoreboard
- cScoreboardSerializer Serializer(m_WorldName, &m_Scoreboard);
- Serializer.Save();
+ if (IsSavingEnabled())
+ {
+ // Unload the scoreboard
+ cScoreboardSerializer Serializer(m_DataPath, &m_Scoreboard);
+ Serializer.Save();
- m_MapManager.SaveMapData();
+ m_MapManager.SaveMapData();
+ }
// Explicitly destroy the chunkmap, so that it's guaranteed to be destroyed before the other internals
// This fixes crashes on stopping the server, because chunk destructor deletes entities and those access the world.
@@ -2965,7 +2970,9 @@ void cWorld::SetChunkData(cSetChunkData & a_SetChunkData)
);
// Save the chunk right after generating, so that we don't have to generate it again on next run
- if (a_SetChunkData.ShouldMarkDirty())
+ // If saving is disabled, then the chunk was marked dirty so it will get
+ // saved if saving is later enabled.
+ if (a_SetChunkData.ShouldMarkDirty() && IsSavingEnabled())
{
m_Storage.QueueSaveChunk(ChunkX, ChunkZ);
}
@@ -3629,8 +3636,11 @@ bool cWorld::ForEachLoadedChunk(std::function<bool(int, int)> a_Callback)
void cWorld::SaveAllChunks(void)
{
- m_LastSave = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
- m_ChunkMap->SaveAllChunks();
+ if (IsSavingEnabled())
+ {
+ m_LastSave = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
+ m_ChunkMap->SaveAllChunks();
+ }
}
diff --git a/src/World.h b/src/World.h
index 87110a5cf..22847b975 100644
--- a/src/World.h
+++ b/src/World.h
@@ -12,6 +12,7 @@
#include "ChunkSender.h"
#include "Defines.h"
#include "LightingThread.h"
+#include "IniFile.h"
#include "Item.h"
#include "Mobs/Monster.h"
#include "Entities/ProjectileEntity.h"
@@ -103,6 +104,12 @@ public:
// tolua_begin
+ /** Get whether saving chunks is enabled */
+ bool IsSavingEnabled(void) const { return m_IsSavingEnabled; }
+
+ /** Set whether saving chunks is enabled */
+ void SetSavingEnabled(bool a_IsSavingEnabled) { m_IsSavingEnabled = a_IsSavingEnabled; }
+
int GetTicksUntilWeatherChange(void) const { return m_WeatherInterval; }
/** Is the daylight cycle enabled? */
@@ -657,6 +664,9 @@ public:
/** Returns the name of the world */
const AString & GetName(void) const { return m_WorldName; }
+ /** Returns the data path to the world data */
+ const AString & GetDataPath(void) const { return m_DataPath; }
+
/** Returns the name of the world.ini file used by this world */
const AString & GetIniFileName(void) const {return m_IniFileName; }
@@ -900,6 +910,9 @@ private:
AString m_WorldName;
+ /** The path to the root directory for the world files. Does not including trailing path specifier. */
+ AString m_DataPath;
+
/** The name of the overworld that portals in this world should link to.
Only has effect if this world is a Nether or End world. */
AString m_LinkedOverworldName;
@@ -911,6 +924,9 @@ private:
int m_StorageCompressionFactor;
+ /** Whether or not writing chunks to disk is currently enabled */
+ std::atomic<bool> m_IsSavingEnabled;
+
/** The dimension of the world, used by the client to provide correct lighting scheme */
eDimension m_Dimension;
@@ -1065,7 +1081,7 @@ private:
cSetChunkDataPtrs m_SetChunkDataQueue;
- cWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = "");
+ cWorld(const AString & a_WorldName, const AString & a_DataPath, eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = "");
virtual ~cWorld() override;
void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 8f4d41598..158f7a819 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -85,7 +85,7 @@ cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) :
{
// Create a level.dat file for mapping tools, if it doesn't already exist:
AString fnam;
- Printf(fnam, "%s%clevel.dat", a_World->GetName().c_str(), cFile::PathSeparator);
+ Printf(fnam, "%s%clevel.dat", a_World->GetDataPath().c_str(), cFile::PathSeparator);
if (!cFile::Exists(fnam))
{
cFastNBTWriter Writer;
@@ -180,7 +180,7 @@ void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Re
{
// Construct the filename for offloading:
AString OffloadFileName;
- Printf(OffloadFileName, "%s%cregion%cbadchunks", m_World->GetName().c_str(), cFile::PathSeparator, cFile::PathSeparator);
+ Printf(OffloadFileName, "%s%cregion%cbadchunks", m_World->GetDataPath().c_str(), cFile::PathSeparator, cFile::PathSeparator);
cFile::CreateFolder(FILE_IO_PREFIX + OffloadFileName);
auto t = time(nullptr);
struct tm stm;
@@ -286,7 +286,7 @@ cWSSAnvil::cMCAFile * cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk)
// Load it anew:
AString FileName;
- Printf(FileName, "%s%cregion", m_World->GetName().c_str(), cFile::PathSeparator);
+ Printf(FileName, "%s%cregion", m_World->GetDataPath().c_str(), cFile::PathSeparator);
cFile::CreateFolder(FILE_IO_PREFIX + FileName);
AppendPrintf(FileName, "/r.%d.%d.mca", RegionX, RegionZ);
cMCAFile * f = new cMCAFile(*this, FileName, RegionX, RegionZ);