parent
36eab1b323
commit
9d277f1d10
|
@ -121,10 +121,10 @@ void cChunkGeneratorThread::WaitForQueueEmpty(void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cChunkGeneratorThread::GetQueueLength(void) const
|
size_t cChunkGeneratorThread::GetQueueLength(void) const
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CS);
|
cCSLock Lock(m_CS);
|
||||||
return static_cast<int>(m_Queue.size());
|
return m_Queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ public:
|
||||||
|
|
||||||
void WaitForQueueEmpty();
|
void WaitForQueueEmpty();
|
||||||
|
|
||||||
int GetQueueLength() const;
|
size_t GetQueueLength() const;
|
||||||
|
|
||||||
int GetSeed() const;
|
int GetSeed() const;
|
||||||
|
|
||||||
|
|
141
src/Root.cpp
141
src/Root.cpp
|
@ -308,9 +308,6 @@ void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> a_OverridesRepo)
|
||||||
delete m_FurnaceRecipe; m_FurnaceRecipe = nullptr;
|
delete m_FurnaceRecipe; m_FurnaceRecipe = nullptr;
|
||||||
delete m_CraftingRecipes; m_CraftingRecipes = nullptr;
|
delete m_CraftingRecipes; m_CraftingRecipes = nullptr;
|
||||||
|
|
||||||
LOG("Unloading worlds...");
|
|
||||||
UnloadWorlds();
|
|
||||||
|
|
||||||
LOGD("Stopping plugin manager...");
|
LOGD("Stopping plugin manager...");
|
||||||
delete m_PluginManager; m_PluginManager = nullptr;
|
delete m_PluginManager; m_PluginManager = nullptr;
|
||||||
|
|
||||||
|
@ -456,11 +453,10 @@ void cRoot::LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_
|
||||||
a_Settings.AddValue("WorldPaths", "world_nether", "world_nether");
|
a_Settings.AddValue("WorldPaths", "world_nether", "world_nether");
|
||||||
a_Settings.AddValue("WorldPaths", "world_the_end", "world_the_end");
|
a_Settings.AddValue("WorldPaths", "world_the_end", "world_the_end");
|
||||||
|
|
||||||
AStringVector WorldNames{ "world", "world_nether", "world_the_end" };
|
const AStringVector WorldNames{ "world", "world_nether", "world_the_end" };
|
||||||
m_pDefaultWorld = new cWorld("world", "world", a_dd, WorldNames);
|
m_pDefaultWorld = &m_WorldsByName.try_emplace("world", "world", "world", a_dd, WorldNames).first->second;
|
||||||
m_WorldsByName["world"] = m_pDefaultWorld;
|
m_WorldsByName.try_emplace("world_nether", "world_nether", "world_nether", a_dd, WorldNames, dimNether, "world");
|
||||||
m_WorldsByName["world_nether"] = new cWorld("world_nether", "world_nether", a_dd, WorldNames, dimNether, "world");
|
m_WorldsByName.try_emplace("world_the_end", "world_the_end", "world_the_end", a_dd, WorldNames, dimEnd, "world");
|
||||||
m_WorldsByName["world_the_end"] = new cWorld("world_the_end", "world_the_end", a_dd, WorldNames, dimEnd, "world");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,8 +471,7 @@ void cRoot::LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_
|
||||||
// Get the default world
|
// Get the default world
|
||||||
AString DefaultWorldName = a_Settings.GetValueSet("Worlds", "DefaultWorld", "world");
|
AString DefaultWorldName = a_Settings.GetValueSet("Worlds", "DefaultWorld", "world");
|
||||||
AString DefaultWorldPath = a_Settings.GetValueSet("WorldPaths", DefaultWorldName, DefaultWorldName);
|
AString DefaultWorldPath = a_Settings.GetValueSet("WorldPaths", DefaultWorldName, DefaultWorldName);
|
||||||
m_pDefaultWorld = new cWorld(DefaultWorldName, DefaultWorldPath, a_dd, WorldNames);
|
m_pDefaultWorld = &m_WorldsByName.try_emplace(DefaultWorldName, DefaultWorldName, DefaultWorldPath, a_dd, WorldNames).first->second;
|
||||||
m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
|
|
||||||
|
|
||||||
// Then load the other worlds
|
// Then load the other worlds
|
||||||
if (Worlds.size() <= 0)
|
if (Worlds.size() <= 0)
|
||||||
|
@ -520,7 +515,6 @@ void cRoot::LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FoundAdditionalWorlds = true;
|
FoundAdditionalWorlds = true;
|
||||||
cWorld * NewWorld;
|
|
||||||
AString LowercaseName = StrToLower(WorldName);
|
AString LowercaseName = StrToLower(WorldName);
|
||||||
AString WorldPath = a_Settings.GetValueSet("WorldPaths", WorldName, WorldName);
|
AString WorldPath = a_Settings.GetValueSet("WorldPaths", WorldName, WorldName);
|
||||||
AString NetherAppend = "_nether";
|
AString NetherAppend = "_nether";
|
||||||
|
@ -573,8 +567,7 @@ void cRoot::LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_
|
||||||
}
|
}
|
||||||
Dimension = dimEnd;
|
Dimension = dimEnd;
|
||||||
}
|
}
|
||||||
NewWorld = new cWorld(WorldName, WorldPath, a_dd, WorldNames, Dimension, LinkTo);
|
m_WorldsByName.try_emplace(WorldName, WorldName, WorldPath, a_dd, WorldNames, Dimension, LinkTo);
|
||||||
m_WorldsByName[WorldName] = NewWorld;
|
|
||||||
} // for i - Worlds
|
} // for i - Worlds
|
||||||
|
|
||||||
if (!FoundAdditionalWorlds)
|
if (!FoundAdditionalWorlds)
|
||||||
|
@ -593,11 +586,12 @@ void cRoot::LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_
|
||||||
|
|
||||||
void cRoot::StartWorlds(cDeadlockDetect & a_DeadlockDetect)
|
void cRoot::StartWorlds(cDeadlockDetect & a_DeadlockDetect)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr->second->Start();
|
auto & World = Entry.second;
|
||||||
itr->second->InitializeSpawn();
|
World.Start();
|
||||||
m_PluginManager->CallHookWorldStarted(*itr->second);
|
World.InitializeSpawn();
|
||||||
|
m_PluginManager->CallHookWorldStarted(World);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,9 +601,9 @@ void cRoot::StartWorlds(cDeadlockDetect & a_DeadlockDetect)
|
||||||
|
|
||||||
void cRoot::StopWorlds(cDeadlockDetect & a_DeadlockDetect)
|
void cRoot::StopWorlds(cDeadlockDetect & a_DeadlockDetect)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr->second->Stop(a_DeadlockDetect);
|
Entry.second.Stop(a_DeadlockDetect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,22 +611,9 @@ void cRoot::StopWorlds(cDeadlockDetect & a_DeadlockDetect)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cRoot::UnloadWorlds(void)
|
|
||||||
{
|
|
||||||
m_pDefaultWorld = nullptr;
|
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
|
||||||
{
|
|
||||||
delete itr->second;
|
|
||||||
}
|
|
||||||
m_WorldsByName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cWorld * cRoot::GetDefaultWorld()
|
cWorld * cRoot::GetDefaultWorld()
|
||||||
{
|
{
|
||||||
|
ASSERT(m_pDefaultWorld != nullptr);
|
||||||
return m_pDefaultWorld;
|
return m_pDefaultWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,10 +623,10 @@ cWorld * cRoot::GetDefaultWorld()
|
||||||
|
|
||||||
cWorld * cRoot::GetWorld(const AString & a_WorldName)
|
cWorld * cRoot::GetWorld(const AString & a_WorldName)
|
||||||
{
|
{
|
||||||
WorldMap::iterator itr = m_WorldsByName.find(a_WorldName);
|
const auto FindResult = m_WorldsByName.find(a_WorldName);
|
||||||
if (itr != m_WorldsByName.end())
|
if (FindResult != m_WorldsByName.cend())
|
||||||
{
|
{
|
||||||
return itr->second;
|
return &FindResult->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -659,12 +640,9 @@ bool cRoot::ForEachWorld(cWorldListCallback a_Callback)
|
||||||
{
|
{
|
||||||
for (auto & World : m_WorldsByName)
|
for (auto & World : m_WorldsByName)
|
||||||
{
|
{
|
||||||
if (World.second != nullptr)
|
if (a_Callback(World.second))
|
||||||
{
|
{
|
||||||
if (a_Callback(*World.second))
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -755,14 +733,14 @@ void cRoot::AuthenticateUser(int a_ClientID, const AString & a_Name, const cUUID
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cRoot::GetTotalChunkCount(void)
|
size_t cRoot::GetTotalChunkCount(void)
|
||||||
{
|
{
|
||||||
int res = 0;
|
size_t Count = 0;
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
for (const auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
res += static_cast<int>(itr->second->GetNumChunks());
|
Count += Entry.second.GetNumChunks();
|
||||||
}
|
}
|
||||||
return res;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -771,9 +749,9 @@ int cRoot::GetTotalChunkCount(void)
|
||||||
|
|
||||||
void cRoot::SaveAllChunks(void)
|
void cRoot::SaveAllChunks(void)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr->second->QueueSaveAllChunks();
|
Entry.second.QueueSaveAllChunks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,9 +761,9 @@ void cRoot::SaveAllChunks(void)
|
||||||
|
|
||||||
void cRoot::SetSavingEnabled(bool a_SavingEnabled)
|
void cRoot::SetSavingEnabled(bool a_SavingEnabled)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr->second->SetSavingEnabled(a_SavingEnabled);
|
Entry.second.SetSavingEnabled(a_SavingEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,10 +773,10 @@ void cRoot::SetSavingEnabled(bool a_SavingEnabled)
|
||||||
|
|
||||||
void cRoot::SendPlayerLists(cPlayer * a_DestPlayer)
|
void cRoot::SendPlayerLists(cPlayer * a_DestPlayer)
|
||||||
{
|
{
|
||||||
for (const auto & itr : m_WorldsByName)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr.second->SendPlayerList(a_DestPlayer);
|
Entry.second.SendPlayerList(a_DestPlayer);
|
||||||
} // for itr - m_WorldsByName[]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -807,10 +785,10 @@ void cRoot::SendPlayerLists(cPlayer * a_DestPlayer)
|
||||||
|
|
||||||
void cRoot::BroadcastPlayerListsAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude)
|
void cRoot::BroadcastPlayerListsAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude)
|
||||||
{
|
{
|
||||||
for (const auto & itr : m_WorldsByName)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr.second->BroadcastPlayerListAddPlayer(a_Player);
|
Entry.second.BroadcastPlayerListAddPlayer(a_Player);
|
||||||
} // for itr - m_WorldsByName[]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -819,10 +797,10 @@ void cRoot::BroadcastPlayerListsAddPlayer(const cPlayer & a_Player, const cClien
|
||||||
|
|
||||||
void cRoot::BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude)
|
void cRoot::BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude)
|
||||||
{
|
{
|
||||||
for (const auto & itr : m_WorldsByName)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr.second->BroadcastPlayerListRemovePlayer(a_Player);
|
Entry.second.BroadcastPlayerListRemovePlayer(a_Player);
|
||||||
} // for itr - m_WorldsByName[]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -831,10 +809,10 @@ void cRoot::BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cCl
|
||||||
|
|
||||||
void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix)
|
void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr->second->BroadcastChat(a_Message, nullptr, a_ChatPrefix);
|
Entry.second.BroadcastChat(a_Message, nullptr, a_ChatPrefix);
|
||||||
} // for itr - m_WorldsByName[]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -843,10 +821,10 @@ void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix)
|
||||||
|
|
||||||
void cRoot::BroadcastChat(const cCompositeChat & a_Message)
|
void cRoot::BroadcastChat(const cCompositeChat & a_Message)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
itr->second->BroadcastChat(a_Message);
|
Entry.second.BroadcastChat(a_Message);
|
||||||
} // for itr - m_WorldsByName[]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -855,10 +833,9 @@ void cRoot::BroadcastChat(const cCompositeChat & a_Message)
|
||||||
|
|
||||||
bool cRoot::ForEachPlayer(cPlayerListCallback a_Callback)
|
bool cRoot::ForEachPlayer(cPlayerListCallback a_Callback)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
++itr2;
|
if (!Entry.second.ForEachPlayer(a_Callback))
|
||||||
if (!itr->second->ForEachPlayer(a_Callback))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -922,9 +899,9 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallbac
|
||||||
|
|
||||||
bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback)
|
bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback)
|
||||||
{
|
{
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
if (itr->second->DoWithPlayerByUUID(a_PlayerUUID, a_Callback))
|
if (Entry.second.DoWithPlayerByUUID(a_PlayerUUID, a_Callback))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -938,9 +915,9 @@ bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a
|
||||||
|
|
||||||
bool cRoot::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback)
|
bool cRoot::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback)
|
||||||
{
|
{
|
||||||
for (auto World : m_WorldsByName)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
if (World.second->DoWithPlayer(a_PlayerName, a_Callback))
|
if (Entry.second.DoWithPlayer(a_PlayerName, a_Callback))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1072,23 +1049,23 @@ void cRoot::LogChunkStats(cCommandOutputCallback & a_Output)
|
||||||
int SumNumInLighting = 0;
|
int SumNumInLighting = 0;
|
||||||
int SumNumInGenerator = 0;
|
int SumNumInGenerator = 0;
|
||||||
int SumMem = 0;
|
int SumMem = 0;
|
||||||
for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr)
|
for (auto & Entry : m_WorldsByName)
|
||||||
{
|
{
|
||||||
cWorld * World = itr->second;
|
auto & World = Entry.second;
|
||||||
int NumInGenerator = World->GetGeneratorQueueLength();
|
const auto NumInGenerator = World.GetGeneratorQueueLength();
|
||||||
int NumInSaveQueue = static_cast<int>(World->GetStorageSaveQueueLength());
|
const auto NumInSaveQueue = World.GetStorageSaveQueueLength();
|
||||||
int NumInLoadQueue = static_cast<int>(World->GetStorageLoadQueueLength());
|
const auto NumInLoadQueue = World.GetStorageLoadQueueLength();
|
||||||
int NumValid = 0;
|
int NumValid = 0;
|
||||||
int NumDirty = 0;
|
int NumDirty = 0;
|
||||||
int NumInLighting = 0;
|
int NumInLighting = 0;
|
||||||
World->GetChunkStats(NumValid, NumDirty, NumInLighting);
|
World.GetChunkStats(NumValid, NumDirty, NumInLighting);
|
||||||
a_Output.Out("World %s:", World->GetName().c_str());
|
a_Output.Out("World %s:", World.GetName().c_str());
|
||||||
a_Output.Out(" Num loaded chunks: %d", NumValid);
|
a_Output.Out(" Num loaded chunks: %d", NumValid);
|
||||||
a_Output.Out(" Num dirty chunks: %d", NumDirty);
|
a_Output.Out(" Num dirty chunks: %d", NumDirty);
|
||||||
a_Output.Out(" Num chunks in lighting queue: %d", NumInLighting);
|
a_Output.Out(" Num chunks in lighting queue: %d", NumInLighting);
|
||||||
a_Output.Out(" Num chunks in generator queue: %d", NumInGenerator);
|
a_Output.Out(" Num chunks in generator queue: %zu", NumInGenerator);
|
||||||
a_Output.Out(" Num chunks in storage load queue: %d", NumInLoadQueue);
|
a_Output.Out(" Num chunks in storage load queue: %zu", NumInLoadQueue);
|
||||||
a_Output.Out(" Num chunks in storage save queue: %d", NumInSaveQueue);
|
a_Output.Out(" Num chunks in storage save queue: %zu", NumInSaveQueue);
|
||||||
int Mem = NumValid * static_cast<int>(sizeof(cChunk));
|
int Mem = NumValid * static_cast<int>(sizeof(cChunk));
|
||||||
a_Output.Out(" Memory used by chunks: %d KiB (%d MiB)", (Mem + 1023) / 1024, (Mem + 1024 * 1024 - 1) / (1024 * 1024));
|
a_Output.Out(" Memory used by chunks: %d KiB (%d MiB)", (Mem + 1023) / 1024, (Mem + 1024 * 1024 - 1) / (1024 * 1024));
|
||||||
a_Output.Out(" Per-chunk memory size breakdown:");
|
a_Output.Out(" Per-chunk memory size breakdown:");
|
||||||
|
|
18
src/Root.h
18
src/Root.h
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Protocol/Authenticator.h"
|
#include "BlockTypeRegistry.h"
|
||||||
#include "Protocol/MojangAPI.h"
|
|
||||||
#include "HTTP/HTTPServer.h"
|
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
#include "FunctionRef.h"
|
#include "FunctionRef.h"
|
||||||
|
#include "HTTP/HTTPServer.h"
|
||||||
|
#include "Protocol/Authenticator.h"
|
||||||
|
#include "Protocol/MojangAPI.h"
|
||||||
#include "RankManager.h"
|
#include "RankManager.h"
|
||||||
#include "BlockTypeRegistry.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ public:
|
||||||
void TickCommands(void);
|
void TickCommands(void);
|
||||||
|
|
||||||
/** Returns the number of chunks loaded */
|
/** Returns the number of chunks loaded */
|
||||||
int GetTotalChunkCount(void); // tolua_export
|
size_t GetTotalChunkCount(void); // tolua_export
|
||||||
|
|
||||||
/** Saves all chunks in all worlds */
|
/** Saves all chunks in all worlds */
|
||||||
void SaveAllChunks(void); // tolua_export
|
void SaveAllChunks(void); // tolua_export
|
||||||
|
@ -214,7 +214,7 @@ private:
|
||||||
cCommandOutputCallback * m_Output;
|
cCommandOutputCallback * m_Output;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
typedef std::map<AString, cWorld *> WorldMap;
|
typedef std::map<AString, cWorld> WorldMap;
|
||||||
typedef std::vector<cCommand> cCommandQueue;
|
typedef std::vector<cCommand> cCommandQueue;
|
||||||
|
|
||||||
cWorld * m_pDefaultWorld;
|
cWorld * m_pDefaultWorld;
|
||||||
|
@ -268,12 +268,6 @@ private:
|
||||||
/** Stops each world's threads, so that it's safe to unload them */
|
/** Stops each world's threads, so that it's safe to unload them */
|
||||||
void StopWorlds(cDeadlockDetect & a_DeadlockDetect);
|
void StopWorlds(cDeadlockDetect & a_DeadlockDetect);
|
||||||
|
|
||||||
/** Unloads all worlds from memory */
|
|
||||||
void UnloadWorlds(void);
|
|
||||||
|
|
||||||
/** Does the actual work of executing a command */
|
|
||||||
void DoExecuteConsoleCommand(const AString & a_Cmd);
|
|
||||||
|
|
||||||
static cRoot * s_Root;
|
static cRoot * s_Root;
|
||||||
|
|
||||||
static void InputThread(cRoot & a_Params);
|
static void InputThread(cRoot & a_Params);
|
||||||
|
|
|
@ -457,21 +457,6 @@ cWorld::~cWorld()
|
||||||
delete m_WaterSimulator; m_WaterSimulator = nullptr;
|
delete m_WaterSimulator; m_WaterSimulator = nullptr;
|
||||||
delete m_LavaSimulator; m_LavaSimulator = nullptr;
|
delete m_LavaSimulator; m_LavaSimulator = nullptr;
|
||||||
delete m_RedstoneSimulator; m_RedstoneSimulator = nullptr;
|
delete m_RedstoneSimulator; m_RedstoneSimulator = nullptr;
|
||||||
|
|
||||||
m_Storage.WaitForFinish();
|
|
||||||
|
|
||||||
if (IsSavingEnabled())
|
|
||||||
{
|
|
||||||
// Unload the scoreboard
|
|
||||||
cScoreboardSerializer Serializer(m_DataPath, &m_Scoreboard);
|
|
||||||
Serializer.Save();
|
|
||||||
|
|
||||||
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.
|
|
||||||
m_ChunkMap.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -964,11 +949,25 @@ void cWorld::Stop(cDeadlockDetect & a_DeadlockDetect)
|
||||||
m_Lighting.Stop();
|
m_Lighting.Stop();
|
||||||
m_Generator.Stop();
|
m_Generator.Stop();
|
||||||
m_ChunkSender.Stop();
|
m_ChunkSender.Stop();
|
||||||
m_Storage.Stop();
|
m_Storage.Stop(); // Waits for thread to finish
|
||||||
|
|
||||||
a_DeadlockDetect.UntrackCriticalSection(m_CSClients);
|
a_DeadlockDetect.UntrackCriticalSection(m_CSClients);
|
||||||
a_DeadlockDetect.UntrackCriticalSection(m_CSTasks);
|
a_DeadlockDetect.UntrackCriticalSection(m_CSTasks);
|
||||||
m_ChunkMap->UntrackInDeadlockDetect(a_DeadlockDetect);
|
m_ChunkMap->UntrackInDeadlockDetect(a_DeadlockDetect);
|
||||||
|
|
||||||
|
if (IsSavingEnabled())
|
||||||
|
{
|
||||||
|
// Unload the scoreboard
|
||||||
|
cScoreboardSerializer Serializer(m_DataPath, &m_Scoreboard);
|
||||||
|
Serializer.Save();
|
||||||
|
|
||||||
|
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.
|
||||||
|
// TODO: destructors should only be used for releasing resources, not doing extra work
|
||||||
|
m_ChunkMap.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
29
src/World.h
29
src/World.h
|
@ -91,6 +91,18 @@ public:
|
||||||
return "cWorld";
|
return "cWorld";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Construct the world and read settings from its ini file.
|
||||||
|
@param a_DeadlockDetect is used for tracking this world's age, detecting a possible deadlock.
|
||||||
|
@param a_WorldNames is a list of all world names, used to validate linked worlds
|
||||||
|
*/
|
||||||
|
cWorld(
|
||||||
|
const AString & a_WorldName, const AString & a_DataPath,
|
||||||
|
cDeadlockDetect & a_DeadlockDetect, const AStringVector & a_WorldNames,
|
||||||
|
eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = {}
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual ~cWorld() override;
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
/** Get whether saving chunks is enabled */
|
/** Get whether saving chunks is enabled */
|
||||||
|
@ -966,7 +978,7 @@ public:
|
||||||
void GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue);
|
void GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue);
|
||||||
|
|
||||||
// Various queues length queries (cannot be const, they lock their CS):
|
// Various queues length queries (cannot be const, they lock their CS):
|
||||||
inline int GetGeneratorQueueLength (void) { return m_Generator.GetQueueLength(); } // tolua_export
|
inline size_t GetGeneratorQueueLength (void) { return m_Generator.GetQueueLength(); } // tolua_export
|
||||||
inline size_t GetLightingQueueLength (void) { return m_Lighting.GetQueueLength(); } // tolua_export
|
inline size_t GetLightingQueueLength (void) { return m_Lighting.GetQueueLength(); } // tolua_export
|
||||||
inline size_t GetStorageLoadQueueLength(void) { return m_Storage.GetLoadQueueLength(); } // tolua_export
|
inline size_t GetStorageLoadQueueLength(void) { return m_Storage.GetLoadQueueLength(); } // tolua_export
|
||||||
inline size_t GetStorageSaveQueueLength(void) { return m_Storage.GetSaveQueueLength(); } // tolua_export
|
inline size_t GetStorageSaveQueueLength(void) { return m_Storage.GetSaveQueueLength(); } // tolua_export
|
||||||
|
@ -1104,10 +1116,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class cRoot;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cTickThread:
|
class cTickThread:
|
||||||
public cIsThread
|
public cIsThread
|
||||||
{
|
{
|
||||||
|
@ -1327,17 +1335,6 @@ private:
|
||||||
/** Queue for the chunk data to be set into m_ChunkMap by the tick thread. Protected by m_CSSetChunkDataQueue */
|
/** Queue for the chunk data to be set into m_ChunkMap by the tick thread. Protected by m_CSSetChunkDataQueue */
|
||||||
cSetChunkDataPtrs m_SetChunkDataQueue;
|
cSetChunkDataPtrs m_SetChunkDataQueue;
|
||||||
|
|
||||||
/** Construct the world and read settings from its ini file.
|
|
||||||
@param a_DeadlockDetect is used for tracking this world's age, detecting a possible deadlock.
|
|
||||||
@param a_WorldNames is a list of all world names, used to validate linked worlds
|
|
||||||
*/
|
|
||||||
cWorld(
|
|
||||||
const AString & a_WorldName, const AString & a_DataPath,
|
|
||||||
cDeadlockDetect & a_DeadlockDetect, const AStringVector & a_WorldNames,
|
|
||||||
eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = {}
|
|
||||||
);
|
|
||||||
virtual ~cWorld() override;
|
|
||||||
|
|
||||||
void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
|
void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
|
||||||
|
|
||||||
/** Handles the weather in each tick */
|
/** Handles the weather in each tick */
|
||||||
|
|
Loading…
Reference in New Issue