summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/LuaState.cpp18
-rw-r--r--src/Bindings/LuaState.h1
-rw-r--r--src/Bindings/ManualBindings.cpp418
-rw-r--r--src/Bindings/ManualBindings.h2
-rw-r--r--src/Bindings/ManualBindings_World.cpp109
-rw-r--r--src/Bindings/PluginLua.h4
-rw-r--r--src/Bindings/PluginManager.cpp2
-rw-r--r--src/BiomeDef.h2
-rw-r--r--src/Blocks/BlockLilypad.h16
-rw-r--r--src/Blocks/BlockPiston.cpp25
-rw-r--r--src/Chunk.cpp2
-rw-r--r--src/ChunkDef.h4
-rw-r--r--src/ChunkMap.cpp32
-rw-r--r--src/ChunkMap.h3
-rw-r--r--src/ClientHandle.cpp10
-rw-r--r--src/Entities/Player.cpp4
-rw-r--r--src/Globals.h2
-rw-r--r--src/HTTPServer/HTTPServer.cpp2
-rw-r--r--src/LoggerListeners.cpp2
-rw-r--r--src/Mobs/Monster.cpp2
-rw-r--r--src/Mobs/Path.h2
-rw-r--r--src/OSSupport/File.cpp206
-rw-r--r--src/OSSupport/File.h75
-rw-r--r--src/PolarSSL++/SslContext.cpp2
-rw-r--r--src/Protocol/Authenticator.cpp4
-rw-r--r--src/Protocol/Authenticator.h4
-rw-r--r--src/Protocol/MojangAPI.cpp4
-rw-r--r--src/Protocol/Protocol17x.cpp6
-rw-r--r--src/Protocol/Protocol18x.cpp4
-rw-r--r--src/Root.cpp2
-rw-r--r--src/Server.cpp2
-rw-r--r--src/WebAdmin.cpp10
-rw-r--r--src/World.cpp175
-rw-r--r--src/World.h112
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp2
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp2
-rw-r--r--src/main.cpp16
37 files changed, 832 insertions, 456 deletions
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 7b519a798..c9e7815ca 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -128,7 +128,7 @@ void cLuaState::Close(void)
{
LOGWARNING(
"%s: Detected mis-use, calling Close() on an attached state (0x%p). Detaching instead.",
- __FUNCTION__, m_LuaState
+ __FUNCTION__, static_cast<void *>(m_LuaState)
);
Detach();
return;
@@ -146,7 +146,7 @@ void cLuaState::Attach(lua_State * a_State)
{
if (m_LuaState != nullptr)
{
- LOGINFO("%s: Already contains a LuaState (0x%p), will be closed / detached.", __FUNCTION__, m_LuaState);
+ LOGINFO("%s: Already contains a LuaState (0x%p), will be closed / detached.", __FUNCTION__, static_cast<void *>(m_LuaState));
if (m_IsOwned)
{
Close();
@@ -174,7 +174,7 @@ void cLuaState::Detach(void)
{
LOGWARNING(
"%s: Detected a mis-use, calling Detach() when the state is owned. Closing the owned state (0x%p).",
- __FUNCTION__, m_LuaState
+ __FUNCTION__, static_cast<void *>(m_LuaState)
);
Close();
return;
@@ -676,6 +676,18 @@ void cLuaState::Push(int a_Value)
+void cLuaState::Push(long a_Value)
+{
+ ASSERT(IsValid());
+
+ tolua_pushnumber(m_LuaState, static_cast<lua_Number>(a_Value));
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
void cLuaState::Push(UInt32 a_Value)
{
ASSERT(IsValid());
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 759fdc54f..269a10369 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -248,6 +248,7 @@ public:
void Push(cLuaUDPEndpoint * a_UDPEndpoint);
void Push(double a_Value);
void Push(int a_Value);
+ void Push(long a_Value);
void Push(const UInt32 a_Value);
void Push(void * a_Ptr);
void Push(std::chrono::milliseconds a_time);
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 876d4e280..7e6839fdf 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -482,8 +482,258 @@ cPluginLua * cManualBindings::GetLuaPlugin(lua_State * L)
+static int tolua_cFile_ChangeFileExt(lua_State * tolua_S)
+{
+ // API signature:
+ // ChangeFileExt(string, string) -> string
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2, 3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString FileName, NewExt;
+ ASSERT(L.GetStackValues(2, FileName, NewExt));
+ L.Push(cFile::ChangeFileExt(FileName, NewExt));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_Copy(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:Copy(string, string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2, 3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString SrcFile, DstFile;
+ ASSERT(L.GetStackValues(2, SrcFile, DstFile));
+ L.Push(cFile::Copy(SrcFile, DstFile));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_CreateFolder(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:CreateFolder(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString FolderPath;
+ ASSERT(L.GetStackValues(2, FolderPath));
+ L.Push(cFile::CreateFolder(FolderPath));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_CreateFolderRecursive(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:CreateFolderRecursive(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString FolderPath;
+ ASSERT(L.GetStackValues(2, FolderPath));
+ L.Push(cFile::CreateFolderRecursive(FolderPath));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_Delete(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:Delete(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::Delete(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_DeleteFile(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:DeleteFile(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::DeleteFile(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_DeleteFolder(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:DeleteFolder(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::DeleteFolder(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_DeleteFolderContents(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:DeleteFolderContents(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::DeleteFolderContents(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_Exists(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:Exists(string) -> bool
+
+ // Obsolete, use IsFile() or IsFolder() instead
+ cLuaState L(tolua_S);
+ LOGWARNING("cFile:Exists() is obsolete, use cFile:IsFolder() or cFile:IsFile() instead!");
+ L.LogStackTrace();
+
+ // Check params:
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::Exists(Path));
+ return 1;
+}
+
+
+
+
+
static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
{
+ // API signature:
+ // cFile:GetFolderContents(string) -> {string, string, ...}
+
// Check params:
cLuaState LuaState(tolua_S);
if (
@@ -497,7 +747,7 @@ static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
// Get params:
AString Folder;
- LuaState.GetStackValues(2, Folder);
+ ASSERT(LuaState.GetStackValues(2, Folder));
// Execute and push result:
LuaState.Push(cFile::GetFolderContents(Folder));
@@ -508,8 +758,119 @@ static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
+static int tolua_cFile_GetLastModificationTime(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:GetLastModificationTime(string) -> number
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::GetLastModificationTime(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_GetSize(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:GetSize(string) -> number
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::GetSize(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_IsFile(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:IsFile(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::IsFile(Path));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cFile_IsFolder(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:IsFolder(string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString Path;
+ ASSERT(L.GetStackValues(2, Path));
+ L.Push(cFile::IsFolder(Path));
+ return 1;
+}
+
+
+
+
+
static int tolua_cFile_ReadWholeFile(lua_State * tolua_S)
{
+ // API signature:
+ // cFile:ReadWholeFile(string) -> string
+
// Check params:
cLuaState LuaState(tolua_S);
if (
@@ -523,7 +884,7 @@ static int tolua_cFile_ReadWholeFile(lua_State * tolua_S)
// Get params:
AString FileName;
- LuaState.GetStackValues(2, FileName);
+ ASSERT(LuaState.GetStackValues(2, FileName));
// Execute and push result:
LuaState.Push(cFile::ReadWholeFile(FileName));
@@ -534,6 +895,33 @@ static int tolua_cFile_ReadWholeFile(lua_State * tolua_S)
+static int tolua_cFile_Rename(lua_State * tolua_S)
+{
+ // API signature:
+ // cFile:Rename(string, string) -> bool
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserTable(1, "cFile") ||
+ !L.CheckParamString(2, 3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Execute:
+ AString SrcPath, DstPath;
+ ASSERT(L.GetStackValues(2, SrcPath, DstPath));
+ L.Push(cFile::Rename(SrcPath, DstPath));
+ return 1;
+}
+
+
+
+
+
static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
{
// API function no longer available:
@@ -1151,7 +1539,7 @@ static int tolua_cPlayer_GetPermissions(lua_State * tolua_S)
cPlayer * self = reinterpret_cast<cPlayer *>(tolua_tousertype(tolua_S, 1, nullptr));
if (self == nullptr)
{
- LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
+ LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast<void *>(self));
return 0;
}
@@ -1182,7 +1570,7 @@ static int tolua_cPlayer_GetRestrictions(lua_State * tolua_S)
cPlayer * self = reinterpret_cast<cPlayer *>(tolua_tousertype(tolua_S, 1, nullptr));
if (self == nullptr)
{
- LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
+ LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast<void *>(self));
return 0;
}
@@ -1211,7 +1599,7 @@ static int tolua_cPlayer_OpenWindow(lua_State * tolua_S)
cWindow * wnd = reinterpret_cast<cWindow *>(tolua_tousertype(tolua_S, 2, nullptr));
if ((self == nullptr) || (wnd == nullptr))
{
- LOGWARNING("%s: invalid self (%p) or wnd (%p)", __FUNCTION__, self, wnd);
+ LOGWARNING("%s: invalid self (%p) or wnd (%p)", __FUNCTION__, static_cast<void *>(self), static_cast<void *>(wnd));
return 0;
}
@@ -1292,7 +1680,7 @@ static int tolua_SetObjectCallback(lua_State * tolua_S)
OBJTYPE * self = reinterpret_cast<OBJTYPE *>(tolua_tousertype(tolua_S, 1, nullptr));
if (self == nullptr)
{
- LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
+ LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast<void *>(self));
return 0;
}
int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); // Store function reference for later retrieval
@@ -2846,8 +3234,22 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cFile");
- tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents);
- tolua_function(tolua_S, "ReadWholeFile", tolua_cFile_ReadWholeFile);
+ tolua_function(tolua_S, "ChangeFileExt", tolua_cFile_ChangeFileExt);
+ tolua_function(tolua_S, "Copy", tolua_cFile_Copy);
+ tolua_function(tolua_S, "CreateFolder", tolua_cFile_CreateFolder);
+ tolua_function(tolua_S, "CreateFolderRecursive", tolua_cFile_CreateFolderRecursive);
+ tolua_function(tolua_S, "Delete", tolua_cFile_Delete);
+ tolua_function(tolua_S, "DeleteFile", tolua_cFile_DeleteFile);
+ tolua_function(tolua_S, "DeleteFolder", tolua_cFile_DeleteFolder);
+ tolua_function(tolua_S, "DeleteFolderContents", tolua_cFile_DeleteFolderContents);
+ tolua_function(tolua_S, "Exists", tolua_cFile_Exists);
+ tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents);
+ tolua_function(tolua_S, "GetLastModificationTime", tolua_cFile_GetLastModificationTime);
+ tolua_function(tolua_S, "GetSize", tolua_cFile_GetSize);
+ tolua_function(tolua_S, "IsFile", tolua_cFile_IsFile);
+ tolua_function(tolua_S, "IsFolder", tolua_cFile_IsFolder);
+ tolua_function(tolua_S, "ReadWholeFile", tolua_cFile_ReadWholeFile);
+ tolua_function(tolua_S, "Rename", tolua_cFile_Rename);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cHopperEntity");
diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h
index 38f7ac5f1..e2556bafd 100644
--- a/src/Bindings/ManualBindings.h
+++ b/src/Bindings/ManualBindings.h
@@ -400,7 +400,7 @@ public:
L.GetStackValues(1, Self, Box, FnRef);
if ((Self == nullptr) || (Box == nullptr))
{
- LOGWARNING("Invalid world (%p) or boundingbox (%p)", Self, Box);
+ LOGWARNING("Invalid world (%p) or boundingbox (%p)", static_cast<void *>(Self), static_cast<void *>(Box));
L.LogStackTrace();
return 0;
}
diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp
index e2902b81a..ba80d7130 100644
--- a/src/Bindings/ManualBindings_World.cpp
+++ b/src/Bindings/ManualBindings_World.cpp
@@ -110,6 +110,59 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
+static int tolua_cWorld_ForEachLoadedChunk(lua_State * tolua_S)
+{
+ // Exported manually, because tolua doesn't support converting functions to functor types.
+ // Function signature: ForEachLoadedChunk(callback) -> bool
+
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamFunction(2)
+ )
+ {
+ return 0;
+ }
+
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
+ if (Plugin == nullptr)
+ {
+ return 0;
+ }
+
+ // Read the params:
+ cWorld * World = reinterpret_cast<cWorld *>(tolua_tousertype(tolua_S, 1, nullptr));
+ if (World == nullptr)
+ {
+ LOGWARNING("World:ForEachLoadedChunk(): invalid world parameter");
+ L.LogStackTrace();
+ return 0;
+ }
+ cLuaState::cRef FnRef;
+ L.GetStackValues(2, FnRef);
+ if (!FnRef.IsValid())
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2");
+ }
+
+ // Call the enumeration:
+ bool ret = World->ForEachLoadedChunk(
+ [&L, &FnRef](int a_ChunkX, int a_ChunkZ) -> bool
+ {
+ bool res = false; // By default continue the enumeration
+ L.Call(FnRef, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ return res;
+ }
+ );
+
+ // Push the return value:
+ L.Push(ret);
+ return 1;
+}
+
+
+
+
static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S)
{
@@ -321,7 +374,6 @@ static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
class cLuaWorldTask :
- public cWorld::cTask,
public cPluginLua::cResettable
{
public:
@@ -331,11 +383,7 @@ public:
{
}
-protected:
- int m_FnRef;
-
- // cWorld::cTask overrides:
- virtual void Run(cWorld & a_World) override
+ void Run(cWorld & a_World)
{
cCSLock Lock(m_CSPlugin);
if (m_Plugin != nullptr)
@@ -343,7 +391,10 @@ protected:
m_Plugin->Call(m_FnRef, &a_World);
}
}
-} ;
+
+protected:
+ int m_FnRef;
+};
@@ -380,9 +431,9 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
- auto task = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
- Plugin->AddResettable(task);
- self->QueueTask(task);
+ auto ResettableTask = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(ResettableTask);
+ self->QueueTask(std::bind(&cLuaWorldTask::Run, ResettableTask, std::placeholders::_1));
return 0;
}
@@ -430,35 +481,6 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
-class cLuaScheduledWorldTask :
- public cWorld::cTask,
- public cPluginLua::cResettable
-{
-public:
- cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
- cPluginLua::cResettable(a_Plugin),
- m_FnRef(a_FnRef)
- {
- }
-
-protected:
- int m_FnRef;
-
- // cWorld::cTask overrides:
- virtual void Run(cWorld & a_World) override
- {
- cCSLock Lock(m_CSPlugin);
- if (m_Plugin != nullptr)
- {
- m_Plugin->Call(m_FnRef, &a_World);
- }
- }
-};
-
-
-
-
-
static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
{
// Binding for cWorld::ScheduleTask
@@ -495,11 +517,9 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
- int DelayTicks = static_cast<int>(tolua_tonumber(tolua_S, 2, 0));
-
- auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef);
- Plugin->AddResettable(task);
- World->ScheduleTask(DelayTicks, static_cast<cWorld::cTaskPtr>(task));
+ auto ResettableTask = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(ResettableTask);
+ World->ScheduleTask(static_cast<int>(tolua_tonumber(tolua_S, 2, 0)), std::bind(&cLuaWorldTask::Run, ResettableTask, std::placeholders::_1));
return 0;
}
@@ -580,6 +600,7 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
tolua_function(tolua_S, "ForEachEntityInChunk", ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
tolua_function(tolua_S, "ForEachPlayer", ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
+ tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk);
tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 4344b36ac..1312103b8 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -14,8 +14,8 @@
#include "LuaState.h"
// Names for the global variables through which the plugin is identified in its LuaState
-#define LUA_PLUGIN_NAME_VAR_NAME "_MCServerInternal_PluginName"
-#define LUA_PLUGIN_INSTANCE_VAR_NAME "_MCServerInternal_PluginInstance"
+#define LUA_PLUGIN_NAME_VAR_NAME "_CuberiteInternal_PluginName"
+#define LUA_PLUGIN_INSTANCE_VAR_NAME "_CuberiteInternal_PluginInstance"
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 026865f5b..72e031b33 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -1761,7 +1761,7 @@ bool cPluginManager::BindConsoleCommand(const AString & a_Command, cPlugin * a_P
{
if (cmd->second.m_Plugin == nullptr)
{
- LOGWARNING("Console command \"%s\" is already bound internally by MCServer, cannot bind in plugin \"%s\".", a_Command.c_str(), a_Plugin->GetName().c_str());
+ LOGWARNING("Console command \"%s\" is already bound internally by Cuberite, cannot bind in plugin \"%s\".", a_Command.c_str(), a_Plugin->GetName().c_str());
}
else
{
diff --git a/src/BiomeDef.h b/src/BiomeDef.h
index 48726123c..0fad23100 100644
--- a/src/BiomeDef.h
+++ b/src/BiomeDef.h
@@ -16,7 +16,7 @@
// tolua_begin
/** Biome IDs
The first batch corresponds to the clientside biomes, used by MineCraft.
-BiomeIDs over 255 are used by MCServer internally and are translated to MC biomes before sending them to client
+BiomeIDs over 255 are used by Cuberite internally and are translated to MC biomes before sending them to client
*/
enum EMCSBiome
{
diff --git a/src/Blocks/BlockLilypad.h b/src/Blocks/BlockLilypad.h
index b2fb69309..18a576017 100644
--- a/src/Blocks/BlockLilypad.h
+++ b/src/Blocks/BlockLilypad.h
@@ -23,6 +23,22 @@ public:
UNUSED(a_Meta);
return 7;
}
+
+
+ virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
+ {
+ if ((a_RelY < 1) || (a_RelY >= cChunkDef::Height))
+ {
+ return false;
+ }
+ BLOCKTYPE UnderType;
+ NIBBLETYPE UnderMeta;
+ a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, UnderType, UnderMeta);
+ return (
+ ((UnderType == E_BLOCK_STATIONARY_WATER) || (UnderType == E_BLOCK_WATER)) && // Water is below...
+ (UnderMeta == 0) // ... and it's a source
+ );
+ }
};
diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp
index 4e4814242..94782a7ed 100644
--- a/src/Blocks/BlockPiston.cpp
+++ b/src/Blocks/BlockPiston.cpp
@@ -27,7 +27,6 @@
} \
}
-#define PISTON_TICK_DELAY 1
#define PISTON_MAX_PUSH_DISTANCE 12
@@ -156,15 +155,12 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
// Push blocks, from the furthest to the nearest:
int oldx = a_BlockX, oldy = a_BlockY, oldz = a_BlockZ;
NIBBLETYPE currBlockMeta;
- std::vector<Vector3i> ScheduledBlocks;
- ScheduledBlocks.reserve(PISTON_MAX_PUSH_DISTANCE);
for (int i = dist + 1; i > 1; i--)
{
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, currBlock, currBlockMeta);
- a_World->SetBlock(oldx, oldy, oldz, currBlock, currBlockMeta, false);
- ScheduledBlocks.push_back(Vector3i(oldx, oldy, oldz));
+ a_World->SetBlock(oldx, oldy, oldz, currBlock, currBlockMeta);
oldx = a_BlockX;
oldy = a_BlockY;
oldz = a_BlockZ;
@@ -173,13 +169,11 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
int extx = a_BlockX;
int exty = a_BlockY;
int extz = a_BlockZ;
- ScheduledBlocks.push_back(Vector3i(extx, exty, extz));
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
// "a_Block" now at piston body, "ext" at future extension
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8);
- a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), false);
- a_World->ScheduleTask(PISTON_TICK_DELAY, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
+ a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0));
}
@@ -223,23 +217,14 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
if (CanPull(tempBlock, tempMeta))
{
// Pull the block
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, tempBlock, tempMeta, false);
- a_World->SetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0, false);
-
- std::vector<Vector3i> ScheduledBlocks;
- ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- ScheduledBlocks.push_back(Vector3i(tempx, tempy, tempz));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, tempBlock, tempMeta);
+ a_World->SetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0);
return;
}
}
// Retract without pulling
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0, false);
-
- std::vector<Vector3i> ScheduledBlocks;
- ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 7a6938b77..39a5a6053 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -490,7 +490,7 @@ void cChunk::CollectMobCensus(cMobCensus & toFill)
{
auto & Monster = reinterpret_cast<cMonster &>(*entity);
currentPosition = Monster.GetPosition();
- for (const auto PlayerPos : PlayerPositions)
+ for (const auto & PlayerPos : PlayerPositions)
{
toFill.CollectMob(Monster, *this, (currentPosition - PlayerPos).SqrLength());
}
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index 7af0ef630..f6c0381db 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -68,8 +68,8 @@ public:
/** The type used for any heightmap operations and storage; idx = x + Width * z; Height points to the highest non-air block in the column */
typedef HEIGHTTYPE HeightMap[Width * Width];
- /** The type used for any biomemap operations and storage inside MCServer,
- using MCServer biomes (need not correspond to client representation!)
+ /** The type used for any biomemap operations and storage inside Cuberite,
+ using Cuberite biomes (need not correspond to client representation!)
idx = x + Width * z */
typedef EMCSBiome BiomeMap[Width * Width];
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index aeae8f350..a4771ce52 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -1723,7 +1723,7 @@ void cChunkMap::AddEntity(cEntity * a_Entity)
)
{
LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
- a_Entity, a_Entity->GetClass(), a_Entity->GetUniqueID()
+ static_cast<void *>(a_Entity), a_Entity->GetClass(), a_Entity->GetUniqueID()
);
return;
}
@@ -1744,7 +1744,7 @@ void cChunkMap::AddEntityIfNotPresent(cEntity * a_Entity)
)
{
LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
- a_Entity, a_Entity->GetClass(), a_Entity->GetUniqueID()
+ static_cast<void *>(a_Entity), a_Entity->GetClass(), a_Entity->GetUniqueID()
);
return;
}
@@ -2576,6 +2576,34 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh
+bool cChunkMap::ForEachLoadedChunk(std::function<bool(int, int)> a_Callback)
+{
+ cCSLock Lock(m_CSLayers);
+ for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr) // iterate over ALL loaded layers
+ {
+ cChunkLayer * layer = *itr;
+ for (int x = 0; x < LAYER_SIZE; x++)
+ {
+ for (int z = 0; z < LAYER_SIZE; z++)
+ {
+ cChunkPtr p = layer->FindChunk(layer->GetX() * LAYER_SIZE + x, layer->GetZ() * LAYER_SIZE + z);
+ if ((p != nullptr) && p->IsValid()) // if chunk is loaded
+ {
+ if (a_Callback(p->GetPosX(), p->GetPosZ()))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+
+
+
+
bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
{
// Convert block coords to chunks coords:
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 4974671da..e9309dbd8 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -344,6 +344,9 @@ public:
/** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */
bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback);
+
+ /** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */
+ bool ForEachLoadedChunk(std::function<bool(int, int)> a_Callback);
/** Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead. */
bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 6c9e6a781..98005e934 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -95,7 +95,7 @@ cClientHandle::cClientHandle(const AString & a_IPString, int a_ViewDistance) :
m_UniqueID = s_ClientCount;
m_PingStartTime = std::chrono::steady_clock::now();
- LOGD("New ClientHandle created at %p", this);
+ LOGD("New ClientHandle created at %p", static_cast<void *>(this));
}
@@ -106,7 +106,7 @@ cClientHandle::~cClientHandle()
{
ASSERT(m_State == csDestroyed); // Has Destroy() been called?
- LOGD("Deleting client \"%s\" at %p", GetUsername().c_str(), this);
+ LOGD("Deleting client \"%s\" at %p", GetUsername().c_str(), static_cast<void *>(this));
{
cCSLock Lock(m_CSChunkLists);
@@ -140,7 +140,7 @@ cClientHandle::~cClientHandle()
delete m_Protocol;
m_Protocol = nullptr;
- LOGD("ClientHandle at %p deleted", this);
+ LOGD("ClientHandle at %p deleted", static_cast<void *>(this));
}
@@ -164,7 +164,7 @@ void cClientHandle::Destroy(void)
}
// DEBUG:
- LOGD("%s: client %p, \"%s\"", __FUNCTION__, this, m_Username.c_str());
+ LOGD("%s: client %p, \"%s\"", __FUNCTION__, static_cast<void *>(this), m_Username.c_str());
if ((m_Player != nullptr) && (m_Player->GetWorld() != nullptr))
{
@@ -2935,7 +2935,7 @@ void cClientHandle::AddWantedChunk(int a_ChunkX, int a_ChunkZ)
return;
}
- LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, this);
+ LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, static_cast<void *>(this));
cCSLock Lock(m_CSChunkLists);
if (m_ChunksToSend.find(cChunkCoords(a_ChunkX, a_ChunkZ)) == m_ChunksToSend.end())
{
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 910ad4c0e..d35b92296 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -150,7 +150,7 @@ cPlayer::~cPlayer(void)
LOGINFO("Player %s has left the game", GetName().c_str());
}
- LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), this, GetUniqueID());
+ LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), static_cast<void *>(this), GetUniqueID());
// Notify the server that the player is being destroyed
cRoot::Get()->GetServer()->PlayerDestroying(this);
@@ -162,7 +162,7 @@ cPlayer::~cPlayer(void)
delete m_InventoryWindow;
m_InventoryWindow = nullptr;
- LOGD("Player %p deleted", this);
+ LOGD("Player %p deleted", static_cast<void *>(this));
}
diff --git a/src/Globals.h b/src/Globals.h
index a69a64452..2ee8574ba 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -225,7 +225,7 @@ template class SizeChecker<UInt8, 1>;
#endif
#if defined(ANDROID_NDK)
- #define FILE_IO_PREFIX "/sdcard/mcserver/"
+ #define FILE_IO_PREFIX "/sdcard/Cuberite/"
#else
#define FILE_IO_PREFIX ""
#endif
diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTPServer/HTTPServer.cpp
index 7a6303b1f..bbff5d57a 100644
--- a/src/HTTPServer/HTTPServer.cpp
+++ b/src/HTTPServer/HTTPServer.cpp
@@ -83,7 +83,7 @@ class cDebugCallbacks :
{
if (!a_Request.HasAuth() || (a_Request.GetAuthUsername() != "a") || (a_Request.GetAuthPassword() != "b"))
{
- a_Connection.SendNeedAuth("MCServer WebAdmin");
+ a_Connection.SendNeedAuth("Cuberite WebAdmin");
return;
}
}
diff --git a/src/LoggerListeners.cpp b/src/LoggerListeners.cpp
index 3b6ed2147..ed10e648c 100644
--- a/src/LoggerListeners.cpp
+++ b/src/LoggerListeners.cpp
@@ -190,7 +190,7 @@
break;
}
}
- __android_log_print(AndroidLogLevel, "MCServer", "%s", a_Message.c_str());
+ __android_log_print(AndroidLogLevel, "Cuberite", "%s", a_Message.c_str());
}
};
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index fa86f28ae..b28e94ec1 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -912,7 +912,7 @@ eMonsterType cMonster::StringToMobType(const AString & a_Name)
{
AString lcName = StrToLower(a_Name);
- // Search MCServer name:
+ // Search Cuberite name:
for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
{
if (strcmp(g_MobTypeNames[i].m_lcName, lcName.c_str()) == 0)
diff --git a/src/Mobs/Path.h b/src/Mobs/Path.h
index d42bb77bc..69a05f651 100644
--- a/src/Mobs/Path.h
+++ b/src/Mobs/Path.h
@@ -10,7 +10,7 @@ class cPath;
#include "../FastRandom.h"
#ifdef COMPILING_PATHFIND_DEBUGGER
/* Note: the COMPILING_PATHFIND_DEBUGGER flag is used by Native / WiseOldMan95 to debug
- this class outside of MCServer. This preprocessor flag is never set when compiling MCServer. */
+ this class outside of Cuberite. This preprocessor flag is never set when compiling Cuberite. */
#include "PathFinderIrrlicht_Head.h"
#endif
diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp
index 09f6147b2..dec873ccd 100644
--- a/src/OSSupport/File.cpp
+++ b/src/OSSupport/File.cpp
@@ -16,11 +16,7 @@
cFile::cFile(void) :
- #ifdef USE_STDIO_FILE
m_File(nullptr)
- #else
- m_File(INVALID_HANDLE_VALUE)
- #endif // USE_STDIO_FILE
{
// Nothing needed yet
}
@@ -30,11 +26,7 @@ cFile::cFile(void) :
cFile::cFile(const AString & iFileName, eMode iMode) :
- #ifdef USE_STDIO_FILE
m_File(nullptr)
- #else
- m_File(INVALID_HANDLE_VALUE)
- #endif // USE_STDIO_FILE
{
Open(iFileName, iMode);
}
@@ -78,11 +70,11 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
return false;
}
-#ifdef _WIN32
- m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), Mode, _SH_DENYWR);
-#else
- m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), Mode);
-#endif // _WIN32
+ #ifdef _WIN32
+ m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), Mode, _SH_DENYWR);
+ #else
+ m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), Mode);
+ #endif // _WIN32
if ((m_File == nullptr) && (iMode == fmReadWrite))
{
@@ -91,11 +83,11 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
// So now we know either the file doesn't exist or we don't have rights, no need to worry about file contents.
// Simply re-open for read-writing, erasing existing contents:
-#ifdef _WIN32
- m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+", _SH_DENYWR);
-#else
- m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+");
-#endif // _WIN32
+ #ifdef _WIN32
+ m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+", _SH_DENYWR);
+ #else
+ m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+");
+ #endif // _WIN32
}
return (m_File != nullptr);
@@ -310,7 +302,77 @@ bool cFile::Exists(const AString & a_FileName)
-bool cFile::Delete(const AString & a_FileName)
+bool cFile::Delete(const AString & a_Path)
+{
+ if (IsFolder(a_Path))
+ {
+ return DeleteFolder(a_Path);
+ }
+ else
+ {
+ return DeleteFile(a_Path);
+ }
+}
+
+
+
+
+
+bool cFile::DeleteFolder(const AString & a_FolderName)
+{
+ #ifdef _WIN32
+ return (RemoveDirectoryA(a_FolderName.c_str()) != 0);
+ #else // _WIN32
+ return (rmdir(a_FolderName.c_str()) == 0);
+ #endif // else _WIN32
+}
+
+
+
+
+
+bool cFile::DeleteFolderContents(const AString & a_FolderName)
+{
+ auto Contents = cFile::GetFolderContents(a_FolderName);
+ for (const auto item: Contents)
+ {
+ // Skip "." and ".." altogether:
+ if ((item == ".") || (item == ".."))
+ {
+ continue;
+ }
+
+ // Remove the item:
+ auto WholePath = a_FolderName + GetPathSeparator() + item;
+ if (IsFolder(WholePath))
+ {
+ if (!DeleteFolderContents(WholePath))
+ {
+ return false;
+ }
+ if (!DeleteFolder(WholePath))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!DeleteFile(WholePath))
+ {
+ return false;
+ }
+ }
+ } // for item - Contents[]
+
+ // All deletes succeeded
+ return true;
+}
+
+
+
+
+
+bool cFile::DeleteFile(const AString & a_FileName)
{
return (remove(a_FileName.c_str()) == 0);
}
@@ -331,7 +393,7 @@ bool cFile::Rename(const AString & a_OrigFileName, const AString & a_NewFileName
bool cFile::Copy(const AString & a_SrcFileName, const AString & a_DstFileName)
{
#ifdef _WIN32
- return (CopyFileA(a_SrcFileName.c_str(), a_DstFileName.c_str(), true) != 0);
+ return (CopyFileA(a_SrcFileName.c_str(), a_DstFileName.c_str(), FALSE) != 0);
#else
// Other OSs don't have a direct CopyFile equivalent, do it the harder way:
std::ifstream src(a_SrcFileName.c_str(), std::ios::binary);
@@ -409,57 +471,85 @@ bool cFile::CreateFolder(const AString & a_FolderPath)
+bool cFile::CreateFolderRecursive(const AString & a_FolderPath)
+{
+ // Special case: Fail if the path is empty
+ if (a_FolderPath.empty())
+ {
+ return false;
+ }
+
+ // Go through each path element and create the folder:
+ auto len = a_FolderPath.length();
+ auto PathSep = GetPathSeparator()[0];
+ for (decltype(len) i = 0; i < len; i++)
+ {
+ if (a_FolderPath[i] == PathSep)
+ {
+ CreateFolder(a_FolderPath.substr(0, i));
+ }
+ }
+ CreateFolder(a_FolderPath);
+
+ // Check the result by querying whether the final path exists:
+ return IsFolder(a_FolderPath);
+}
+
+
+
+
+
AStringVector cFile::GetFolderContents(const AString & a_Folder)
{
AStringVector AllFiles;
#ifdef _WIN32
- // If the folder name doesn't contain the terminating slash / backslash, add it:
- AString FileFilter = a_Folder;
- if (
- !FileFilter.empty() &&
- (FileFilter[FileFilter.length() - 1] != '\\') &&
- (FileFilter[FileFilter.length() - 1] != '/')
- )
- {
- FileFilter.push_back('\\');
- }
+ // If the folder name doesn't contain the terminating slash / backslash, add it:
+ AString FileFilter = a_Folder;
+ if (
+ !FileFilter.empty() &&
+ (FileFilter[FileFilter.length() - 1] != '\\') &&
+ (FileFilter[FileFilter.length() - 1] != '/')
+ )
+ {
+ FileFilter.push_back('\\');
+ }
- // Find all files / folders:
- FileFilter.append("*.*");
- HANDLE hFind;
- WIN32_FIND_DATAA FindFileData;
- if ((hFind = FindFirstFileA(FileFilter.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE)
- {
- do
+ // Find all files / folders:
+ FileFilter.append("*.*");
+ HANDLE hFind;
+ WIN32_FIND_DATAA FindFileData;
+ if ((hFind = FindFirstFileA(FileFilter.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE)
{
- AllFiles.push_back(FindFileData.cFileName);
- } while (FindNextFileA(hFind, &FindFileData));
- FindClose(hFind);
- }
+ do
+ {
+ AllFiles.push_back(FindFileData.cFileName);
+ } while (FindNextFileA(hFind, &FindFileData));
+ FindClose(hFind);
+ }
#else // _WIN32
- DIR * dp;
- struct dirent *dirp;
- AString Folder = a_Folder;
- if (Folder.empty())
- {
- Folder = ".";
- }
- if ((dp = opendir(Folder.c_str())) == nullptr)
- {
- LOGERROR("Error (%i) opening directory \"%s\"\n", errno, Folder.c_str());
- }
- else
- {
- while ((dirp = readdir(dp)) != nullptr)
+ DIR * dp;
+ struct dirent *dirp;
+ AString Folder = a_Folder;
+ if (Folder.empty())
{
- AllFiles.push_back(dirp->d_name);
+ Folder = ".";
+ }
+ if ((dp = opendir(Folder.c_str())) == nullptr)
+ {
+ LOGERROR("Error (%i) opening directory \"%s\"\n", errno, Folder.c_str());
+ }
+ else
+ {
+ while ((dirp = readdir(dp)) != nullptr)
+ {
+ AllFiles.push_back(dirp->d_name);
+ }
+ closedir(dp);
}
- closedir(dp);
- }
#endif // else _WIN32
diff --git a/src/OSSupport/File.h b/src/OSSupport/File.h
index b8381ac0e..aab86811d 100644
--- a/src/OSSupport/File.h
+++ b/src/OSSupport/File.h
@@ -32,17 +32,6 @@ For reading entire files into memory, just use the static cFile::ReadWholeFile()
-#ifndef _WIN32
- #define USE_STDIO_FILE
-#endif // _WIN32
-
-// DEBUG:
-#define USE_STDIO_FILE
-
-
-
-
-
// tolua_begin
class cFile
@@ -101,48 +90,64 @@ public:
/** Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error */
int ReadRestOfFile(AString & a_Contents);
- // tolua_begin
-
/** Returns true if the file specified exists */
- static bool Exists(const AString & a_FileName);
+ static bool Exists(const AString & a_FileName); // Exported in ManualBindings.cpp
+
+ /** Deletes a file or a folder, returns true if successful.
+ Prefer to use DeleteFile or DeleteFolder, since those don't have the penalty of checking whether a_Path is a folder. */
+ static bool Delete(const AString & a_Path); // Exported in ManualBindings.cpp
+
+ /** Deletes a file, returns true if successful.
+ Returns false if a_FileName points to a folder. */
+ static bool DeleteFile(const AString & a_FileName); // Exported in ManualBindings.cpp
- /** Deletes a file, returns true if successful */
- static bool Delete(const AString & a_FileName);
+ /** Deletes a folder, returns true if successful.
+ Returns false if a_FolderName points to a file. */
+ static bool DeleteFolder(const AString & a_FolderName); // Exported in ManualBindings.cpp
+
+ /** Deletes all content from the specified folder.
+ The specified folder itself stays intact.
+ Returns true on success, false on failure. */
+ static bool DeleteFolderContents(const AString & a_FolderName); // Exported in ManualBindings.cpp
/** Renames a file or folder, returns true if successful. May fail if dest already exists (libc-dependant)! */
- static bool Rename(const AString & a_OrigPath, const AString & a_NewPath);
+ static bool Rename(const AString & a_OrigPath, const AString & a_NewPath); // Exported in ManualBindings.cpp
- /** Copies a file, returns true if successful. */
- static bool Copy(const AString & a_SrcFileName, const AString & a_DstFileName);
+ /** Copies a file, returns true if successful.
+ Overwrites the dest file if it already exists. */
+ static bool Copy(const AString & a_SrcFileName, const AString & a_DstFileName); // Exported in ManualBindings.cpp
/** Returns true if the specified path is a folder */
- static bool IsFolder(const AString & a_Path);
+ static bool IsFolder(const AString & a_Path); // Exported in ManualBindings.cpp
/** Returns true if the specified path is a regular file */
- static bool IsFile(const AString & a_Path);
+ static bool IsFile(const AString & a_Path); // Exported in ManualBindings.cpp
/** Returns the size of the file, or a negative number on error */
- static long GetSize(const AString & a_FileName);
+ static long GetSize(const AString & a_FileName); // Exported in ManualBindings.cpp
/** Creates a new folder with the specified name. Returns true if successful. Path may be relative or absolute */
- static bool CreateFolder(const AString & a_FolderPath);
-
- // tolua_end
+ static bool CreateFolder(const AString & a_FolderPath); // Exported in ManualBindings.cpp
- /** Returns the entire contents of the specified file as a string. Returns empty string on error.
- Exported manually in ManualBindings.cpp due to #1914 - ToLua code doesn't work well with binary files. */
- static AString ReadWholeFile(const AString & a_FileName);
-
- // tolua_begin
+ /** Creates a new folder with the specified name, creating its parents if needed. Path may be relative or absolute.
+ Returns true if the folder exists at the end of the operation (either created, or already existed).
+ Supports only paths that use the path separator used by the current platform (MSVC CRT supports slashes for file paths, too, but this function doesn't) */
+ static bool CreateFolderRecursive(const AString & a_FolderPath); // Exported in ManualBindings.cpp
+
+ /** Returns the entire contents of the specified file as a string. Returns empty string on error. */
+ static AString ReadWholeFile(const AString & a_FileName); // Exported in ManualBindings.cpp
/** Returns a_FileName with its extension changed to a_NewExt.
a_FileName may contain path specification. */
- static AString ChangeFileExt(const AString & a_FileName, const AString & a_NewExt);
+ static AString ChangeFileExt(const AString & a_FileName, const AString & a_NewExt); // Exported in ManualBindings.cpp
/** Returns the last modification time (in current timezone) of the specified file.
The value returned is in the same units as the value returned by time() function.
- If the file is not found / accessible, zero is returned. */
- static unsigned GetLastModificationTime(const AString & a_FileName);
+ If the file is not found / accessible, zero is returned.
+ Works for folders, too, when specified without the trailing path separator. */
+ static unsigned GetLastModificationTime(const AString & a_FileName); // Exported in ManualBindings.cpp
+
+ // tolua_begin
/** Returns the path separator used by the current platform.
Note that the platform / CRT may support additional path separators (such as slashes on Windows), these don't get reported. */
@@ -162,11 +167,7 @@ public:
void Flush(void);
private:
- #ifdef USE_STDIO_FILE
FILE * m_File;
- #else
- HANDLE m_File;
- #endif
} ; // tolua_export
diff --git a/src/PolarSSL++/SslContext.cpp b/src/PolarSSL++/SslContext.cpp
index 1409405bc..90e0ae0e2 100644
--- a/src/PolarSSL++/SslContext.cpp
+++ b/src/PolarSSL++/SslContext.cpp
@@ -50,7 +50,7 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
if (m_CtrDrbg.get() == nullptr)
{
m_CtrDrbg.reset(new cCtrDrbgContext);
- m_CtrDrbg->Initialize("MCServer", 8);
+ m_CtrDrbg->Initialize("Cuberite", 8);
}
// Initialize PolarSSL's structures:
diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp
index bfbe5028d..304486935 100644
--- a/src/Protocol/Authenticator.cpp
+++ b/src/Protocol/Authenticator.cpp
@@ -149,7 +149,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
AString Request;
Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
Request += "Host: " + m_Server + "\r\n";
- Request += "User-Agent: MCServer\r\n";
+ Request += "User-Agent: Cuberite\r\n";
Request += "Connection: close\r\n";
Request += "\r\n";
@@ -223,7 +223,7 @@ bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a
AString Request;
Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
Request += "Host: " + m_Server + "\r\n";
- Request += "User-Agent: MCServer\r\n";
+ Request += "User-Agent: Cuberite\r\n";
Request += "Connection: close\r\n";
Request += "\r\n";
diff --git a/src/Protocol/Authenticator.h b/src/Protocol/Authenticator.h
index 02b349256..845277569 100644
--- a/src/Protocol/Authenticator.h
+++ b/src/Protocol/Authenticator.h
@@ -1,10 +1,10 @@
// cAuthenticator.h
-// Interfaces to the cAuthenticator class representing the thread that authenticates users against the official MC server
+// Interfaces to the cAuthenticator class representing the thread that authenticates users against the official Mojang servers
// Authentication prevents "hackers" from joining with an arbitrary username (possibly impersonating the server admins)
// For more info, see http://wiki.vg/Session#Server_operation
-// In MCS, authentication is implemented as a single thread that receives queued auth requests and dispatches them one by one.
+// In Cuberite, authentication is implemented as a single thread that receives queued auth requests and dispatches them one by one.
diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp
index f3f9baf25..73b3bd8c0 100644
--- a/src/Protocol/MojangAPI.cpp
+++ b/src/Protocol/MojangAPI.cpp
@@ -688,7 +688,7 @@ void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
AString Request;
Request += "POST " + m_NameToUUIDAddress + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding
Request += "Host: " + m_NameToUUIDServer + "\r\n";
- Request += "User-Agent: MCServer\r\n";
+ Request += "User-Agent: Cuberite\r\n";
Request += "Connection: close\r\n";
Request += "Content-Type: application/json\r\n";
Request += Printf("Content-Length: %u\r\n", static_cast<unsigned>(RequestBody.length()));
@@ -802,7 +802,7 @@ void cMojangAPI::QueryUUIDToProfile(const AString & a_UUID)
AString Request;
Request += "GET " + Address + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding
Request += "Host: " + m_UUIDToProfileServer + "\r\n";
- Request += "User-Agent: MCServer\r\n";
+ Request += "User-Agent: Cuberite\r\n";
Request += "Connection: close\r\n";
Request += "Content-Length: 0\r\n";
Request += "\r\n";
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index ad76480b3..d17537ff7 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1800,7 +1800,7 @@ void cProtocol172::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
// Version:
Json::Value Version;
- Version["name"] = "MCServer 1.7.2";
+ Version["name"] = "Cuberite 1.7.2";
Version["protocol"] = 4;
// Players:
@@ -2394,7 +2394,7 @@ void cProtocol172::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const
}
// Send back our brand:
- SendPluginMessage("MC|Brand", "MCServer");
+ SendPluginMessage("MC|Brand", "Cuberite");
return;
}
else if (a_Channel == "MC|Beacon")
@@ -3256,7 +3256,7 @@ void cProtocol176::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
// Version:
Json::Value Version;
- Version["name"] = "MCServer 1.7.6";
+ Version["name"] = "Cuberite 1.7.6";
Version["protocol"] = 5;
// Players:
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index d69c631d2..ea71103f7 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -2080,7 +2080,7 @@ void cProtocol180::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
// Version:
Json::Value Version;
- Version["name"] = "MCServer 1.8";
+ Version["name"] = "Cuberite 1.8";
Version["protocol"] = 47;
// Players:
@@ -2685,7 +2685,7 @@ void cProtocol180::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand);
m_Client->SetClientBrand(Brand);
// Send back our brand, including the length:
- SendPluginMessage("MC|Brand", "\x08MCServer");
+ SendPluginMessage("MC|Brand", "\x08Cuberite");
return;
}
else if (a_Channel == "MC|Beacon")
diff --git a/src/Root.cpp b/src/Root.cpp
index 13166d883..57056cc1b 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -121,7 +121,7 @@ void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> a_OverridesRepo)
LOG("--- Started Log ---");
#ifdef BUILD_ID
- LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID);
+ LOG("Cuberite " BUILD_SERIES_NAME " build id: " BUILD_ID);
LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME);
#endif
diff --git a/src/Server.cpp b/src/Server.cpp
index 313db90e6..a21248695 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -187,7 +187,7 @@ void cServer::PlayerDestroying(const cPlayer * a_Player)
bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth)
{
- m_Description = a_Settings.GetValueSet("Server", "Description", "MCServer - in C++!");
+ m_Description = a_Settings.GetValueSet("Server", "Description", "Cuberite - in C++!");
m_MaxPlayers = a_Settings.GetValueSetI("Server", "MaxPlayers", 100);
m_bIsHardcore = a_Settings.GetValueSetB("Server", "HardcoreEnabled", false);
m_bAllowMultiLogin = a_Settings.GetValueSetB("Server", "AllowMultiLogin", false);
diff --git a/src/WebAdmin.cpp b/src/WebAdmin.cpp
index 91fad96c6..27294f19b 100644
--- a/src/WebAdmin.cpp
+++ b/src/WebAdmin.cpp
@@ -96,7 +96,7 @@ bool cWebAdmin::Init(void)
if (!m_IniFile.ReadFile("webadmin.ini"))
{
LOGWARN("Regenerating webadmin.ini, all settings will be reset");
- m_IniFile.AddHeaderComment(" This file controls the webadmin feature of MCServer");
+ m_IniFile.AddHeaderComment(" This file controls the webadmin feature of Cuberite");
m_IniFile.AddHeaderComment(" Username format: [User:*username*]");
m_IniFile.AddHeaderComment(" Password format: Password=*password*; for example:");
m_IniFile.AddHeaderComment(" [User:admin]");
@@ -131,7 +131,7 @@ bool cWebAdmin::Init(void)
// Sets the fallback template:
m_LoginTemplate = \
- "<h1>MCServer WebAdmin</h1>" \
+ "<h1>Cuberite WebAdmin</h1>" \
"<center>" \
"<form method='get' action='webadmin/'>" \
"<input type='submit' value='Log in'>" \
@@ -216,7 +216,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
{
if (!a_Request.HasAuth())
{
- a_Connection.SendNeedAuth("MCServer WebAdmin");
+ a_Connection.SendNeedAuth("Cuberite WebAdmin");
return;
}
@@ -224,7 +224,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
AString UserPassword = m_IniFile.GetValue("User:" + a_Request.GetAuthUsername(), "Password", "");
if ((UserPassword == "") || (a_Request.GetAuthPassword() != UserPassword))
{
- a_Connection.SendNeedAuth("MCServer WebAdmin - bad username or password");
+ a_Connection.SendNeedAuth("Cuberite WebAdmin - bad username or password");
return;
}
@@ -333,7 +333,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
ReplaceString(Template, "{MENU}", Menu);
ReplaceString(Template, "{PLUGIN_NAME}", FoundPlugin);
ReplaceString(Template, "{CONTENT}", Content);
- ReplaceString(Template, "{TITLE}", "MCServer");
+ ReplaceString(Template, "{TITLE}", "Cuberite");
AString NumChunks;
Printf(NumChunks, "%d", cRoot::Get()->GetTotalChunkCount());
diff --git a/src/World.cpp b/src/World.cpp
index eb96eb57a..18d042382 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -839,7 +839,6 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La
TickClients(static_cast<float>(a_Dt.count()));
TickQueuedBlocks();
TickQueuedTasks();
- TickScheduledTasks();
GetSimulatorManager()->Simulate(static_cast<float>(a_Dt.count()));
@@ -962,55 +961,39 @@ void cWorld::TickMobs(std::chrono::milliseconds a_Dt)
void cWorld::TickQueuedTasks(void)
{
- // Make a copy of the tasks to avoid deadlocks on accessing m_Tasks
- cTasks Tasks;
- {
- cCSLock Lock(m_CSTasks);
- std::swap(Tasks, m_Tasks);
- }
-
- // Execute and delete each task:
- for (cTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
- {
- (*itr)->Run(*this);
- } // for itr - m_Tasks[]
-}
-
-
-
-
-
-void cWorld::TickScheduledTasks(void)
-{
// Move the tasks to be executed to a seperate vector to avoid deadlocks on accessing m_Tasks
- cScheduledTasks Tasks;
+ decltype(m_Tasks) Tasks;
{
- cCSLock Lock(m_CSScheduledTasks);
- auto WorldAge = m_WorldAge;
-
- // Move all the due tasks from m_ScheduledTasks into Tasks:
- for (auto itr = m_ScheduledTasks.begin(); itr != m_ScheduledTasks.end();) // Cannot use range-based for, we're modifying the container
+ cCSLock Lock(m_CSTasks);
+ if (m_Tasks.empty())
{
- if ((*itr)->m_TargetTick < std::chrono::duration_cast<cTickTimeLong>(WorldAge).count())
- {
- auto next = itr;
- ++next;
- Tasks.push_back(std::move(*itr));
- m_ScheduledTasks.erase(itr);
- itr = next;
- }
- else
+ return;
+ }
+
+ // Partition everything to be executed by returning false to move to end of list if time reached
+ auto MoveBeginIterator = std::partition(m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task)
{
- // All the eligible tasks have been moved, bail out now
- break;
+ if (a_Task.first < std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count())
+ {
+ return false;
+ }
+ return true;
}
- }
+ );
+
+ // Cut all the due tasks from m_Tasks into Tasks:
+ Tasks.insert(
+ Tasks.end(),
+ std::make_move_iterator(MoveBeginIterator),
+ std::make_move_iterator(m_Tasks.end())
+ );
+ m_Tasks.erase(MoveBeginIterator, m_Tasks.end());
}
- // Execute and delete each task:
- for (cScheduledTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
+ // Execute each task:
+ for (const auto & Task : Tasks)
{
- (*itr)->m_Task->Run(*this);
+ Task.second(*this);
} // for itr - m_Tasks[]
}
@@ -2662,7 +2645,7 @@ void cWorld::UnloadUnusedChunks(void)
void cWorld::QueueUnloadUnusedChunks(void)
{
- QueueTask(cpp14::make_unique<cWorld::cTaskUnloadUnusedChunks>());
+ QueueTask([](cWorld & a_World) { a_World.UnloadUnusedChunks(); });
}
@@ -3140,6 +3123,15 @@ bool cWorld::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunk
+bool cWorld::ForEachLoadedChunk(std::function<bool(int, int)> a_Callback)
+{
+ return m_ChunkMap->ForEachLoadedChunk(a_Callback);
+}
+
+
+
+
+
void cWorld::SaveAllChunks(void)
{
m_LastSave = std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
@@ -3152,42 +3144,32 @@ void cWorld::SaveAllChunks(void)
void cWorld::QueueSaveAllChunks(void)
{
- QueueTask(std::make_shared<cWorld::cTaskSaveAllChunks>());
+ QueueTask([](cWorld & a_World) { a_World.SaveAllChunks(); });
}
-void cWorld::QueueTask(cTaskPtr a_Task)
+void cWorld::QueueTask(std::function<void(cWorld &)> a_Task)
{
cCSLock Lock(m_CSTasks);
- m_Tasks.push_back(std::move(a_Task));
+ m_Tasks.emplace_back(0, a_Task);
}
-void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld&)> a_Func)
-{
- cTaskLambda task(a_Func);
- ScheduleTask(a_DelayTicks, static_cast<cTaskPtr>(std::make_shared<cTaskLambda>(task)));
-}
-void cWorld::ScheduleTask(int a_DelayTicks, cTaskPtr a_Task)
+
+void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld &)> a_Task)
{
Int64 TargetTick = a_DelayTicks + std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
-
- // Insert the task into the list of scheduled tasks, ordered by its target tick
- cCSLock Lock(m_CSScheduledTasks);
- for (cScheduledTasks::iterator itr = m_ScheduledTasks.begin(), end = m_ScheduledTasks.end(); itr != end; ++itr)
+
+ // Insert the task into the list of scheduled tasks
{
- if ((*itr)->m_TargetTick >= TargetTick)
- {
- m_ScheduledTasks.insert(itr, cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
- return;
- }
+ cCSLock Lock(m_CSTasks);
+ m_Tasks.emplace_back(TargetTick, a_Task);
}
- m_ScheduledTasks.push_back(cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
}
@@ -3616,75 +3598,6 @@ void cWorld::AddQueuedPlayers(void)
////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskSaveAllChunks:
-
-void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World)
-{
- a_World.SaveAllChunks();
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskUnloadUnusedChunks
-
-void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
-{
- a_World.UnloadUnusedChunks();
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskSendBlockToAllPlayers
-
-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_CallbackWorld) :
- m_SendQueue(a_SendQueue),
- m_World(a_CallbackWorld)
- {
- }
-
- 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);
-}
-
-void cWorld::cTaskLambda::Run(cWorld & a_World)
-{
- m_func(a_World);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
// cWorld::cChunkGeneratorCallbacks:
cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks(cWorld & a_World) :
diff --git a/src/World.h b/src/World.h
index 1ee473970..44f18df4a 100644
--- a/src/World.h
+++ b/src/World.h
@@ -27,7 +27,7 @@
#include "Blocks/BroadcastInterface.h"
#include "FastRandom.h"
#include "ClientHandle.h"
-
+#include <functional>
@@ -96,72 +96,8 @@ public:
typedef cCSLock super;
public:
cLock(cWorld & a_World);
- } ;
-
-
- /** A common ancestor for all tasks queued onto the tick thread */
- class cTask
- {
- public:
- cTask(const cTask & other) = default;
- virtual ~cTask() {}
- virtual void Run(cWorld & a_World) = 0;
-
- protected:
- cTask() {}
- } ;
-
- typedef SharedPtr<cTask> cTaskPtr;
- typedef std::vector<cTaskPtr> cTasks;
-
-
- class cTaskSaveAllChunks :
- public cTask
- {
- protected:
- // cTask overrides:
- virtual void Run(cWorld & a_World) override;
- } ;
-
-
- class cTaskUnloadUnusedChunks :
- public cTask
- {
- protected:
- // cTask overrides:
- virtual void Run(cWorld & a_World) override;
- };
-
-
- class cTaskSendBlockToAllPlayers :
- public cTask
- {
- public:
- cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue);
-
- protected:
- // cTask overrides:
- virtual void Run(cWorld & a_World) override;
-
- std::vector<Vector3i> m_SendQueue;
};
- class cTaskLambda :
- public cTask
- {
-
- public:
- cTaskLambda(std::function<void(cWorld&)> a_Func) :
- m_func(a_Func)
- { }
-
- protected:
- virtual void Run(cWorld & a_World) override;
-
- std::function<void(cWorld&)> m_func;
- };
-
-
static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates
{
return "cWorld";
@@ -434,6 +370,9 @@ public:
/** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override;
+ /** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */
+ bool ForEachLoadedChunk(std::function<bool(int, int)> a_Callback);
+
// tolua_begin
/** Sets the block at the specified coords to the specified value.
@@ -736,13 +675,10 @@ public:
void QueueSaveAllChunks(void); // tolua_export
/** Queues a task onto the tick thread. The task object will be deleted once the task is finished */
- void QueueTask(cTaskPtr a_Task); // Exported in ManualBindings.cpp
+ void QueueTask(std::function<void(cWorld &)> a_Task); // Exported in ManualBindings.cpp
/** Queues a lambda task onto the tick thread, with the specified delay. */
- void ScheduleTask(int a_DelayTicks, std::function<void(cWorld&)> a_Func);
-
- /** Queues a task onto the tick thread, with the specified delay. */
- void ScheduleTask(int a_DelayTicks, cTaskPtr a_Task);
+ void ScheduleTask(int a_DelayTicks, std::function<void(cWorld &)> a_Task);
/** Returns the number of chunks loaded */
int GetNumChunks() const; // tolua_export
@@ -909,27 +845,6 @@ private:
public:
cChunkGeneratorCallbacks(cWorld & a_World);
} ;
-
-
- /** A container for tasks that have been scheduled for a specific game tick */
- class cScheduledTask
- {
- public:
- Int64 m_TargetTick;
- cTaskPtr m_Task;
-
- /** Creates a new scheduled task; takes ownership of the task object passed to it. */
- cScheduledTask(Int64 a_TargetTick, cTaskPtr a_Task) :
- m_TargetTick(a_TargetTick),
- m_Task(a_Task)
- {
- }
-
- virtual ~cScheduledTask() {}
- };
-
- typedef std::unique_ptr<cScheduledTask> cScheduledTaskPtr;
- typedef std::list<cScheduledTaskPtr> cScheduledTasks;
AString m_WorldName;
@@ -1059,16 +974,8 @@ private:
/** Guards the m_Tasks */
cCriticalSection m_CSTasks;
- /** Tasks that have been queued onto the tick thread; guarded by m_CSTasks */
- cTasks m_Tasks;
-
- /** Guards the m_ScheduledTasks */
- cCriticalSection m_CSScheduledTasks;
-
- /** Tasks that have been queued to be executed on the tick thread at target tick in the future.
- Ordered by increasing m_TargetTick.
- Guarded by m_CSScheduledTasks */
- cScheduledTasks m_ScheduledTasks;
+ /** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */
+ std::vector<std::pair<Int64, std::function<void(cWorld &)>>> m_Tasks;
/** Guards m_Clients */
cCriticalSection m_CSClients;
@@ -1115,9 +1022,6 @@ private:
/** Executes all tasks queued onto the tick thread */
void TickQueuedTasks(void);
- /** Executes all tasks queued onto the tick thread */
- void TickScheduledTasks(void);
-
/** Ticks all clients that are in this world */
void TickClients(float a_Dt);
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index f204ec52b..e2ba416c6 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -415,7 +415,7 @@ void cNBTChunkSerializer::AddFallingBlockEntity(cFallingBlock * a_FallingBlock)
AddBasicEntity(a_FallingBlock, "FallingSand");
m_Writer.AddInt("TileID", a_FallingBlock->GetBlockType());
m_Writer.AddByte("Data", a_FallingBlock->GetBlockMeta());
- m_Writer.AddByte("Time", 1); // Unused in MCServer, Vanilla said to need nonzero
+ m_Writer.AddByte("Time", 1); // Unused in Cuberite, Vanilla said to need nonzero
m_Writer.AddByte("DropItem", 1);
m_Writer.AddByte("HurtEntities", a_FallingBlock->GetBlockType() == E_BLOCK_ANVIL);
m_Writer.EndCompound();
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index dc1b7faff..f0c990037 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1139,7 +1139,7 @@ cBlockEntity * cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int a_
std::unique_ptr<cMobSpawnerEntity> MobSpawner = cpp14::make_unique<cMobSpawnerEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
- // Load entity (MCServer worlds):
+ // Load entity (Cuberite worlds):
int Type = a_NBT.FindChildByName(a_TagIdx, "Entity");
if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_Short))
{
diff --git a/src/main.cpp b/src/main.cpp
index b9c3ae0bc..c26e7900f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -39,7 +39,7 @@ bool cRoot::m_RunAsService = false;
#if defined(_WIN32)
SERVICE_STATUS_HANDLE g_StatusHandle = nullptr;
HANDLE g_ServiceThread = INVALID_HANDLE_VALUE;
- #define SERVICE_NAME "MCServerService"
+ #define SERVICE_NAME "CuberiteService"
#endif
@@ -77,10 +77,10 @@ void NonCtrlHandler(int a_Signal)
case SIGSEGV:
{
std::signal(SIGSEGV, SIG_DFL);
- LOGERROR(" D: | MCServer has encountered an error and needs to close");
+ LOGERROR(" D: | Cuberite has encountered an error and needs to close");
LOGERROR("Details | SIGSEGV: Segmentation fault");
#ifdef BUILD_ID
- LOGERROR("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID);
+ LOGERROR("Cuberite " BUILD_SERIES_NAME " build id: " BUILD_ID);
LOGERROR("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME);
#endif
PrintStackTrace();
@@ -92,10 +92,10 @@ void NonCtrlHandler(int a_Signal)
#endif
{
std::signal(a_Signal, SIG_DFL);
- LOGERROR(" D: | MCServer has encountered an error and needs to close");
+ LOGERROR(" D: | Cuberite has encountered an error and needs to close");
LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault");
#ifdef BUILD_ID
- LOGERROR("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID);
+ LOGERROR("Cuberite " BUILD_SERIES_NAME " build id: " BUILD_ID);
LOGERROR("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME);
#endif
PrintStackTrace();
@@ -358,7 +358,7 @@ std::unique_ptr<cMemorySettingsRepository> ParseArguments(int argc, char **argv)
try
{
// Parse the comand line args:
- TCLAP::CmdLine cmd("MCServer");
+ TCLAP::CmdLine cmd("Cuberite");
TCLAP::ValueArg<int> slotsArg ("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
TCLAP::MultiArg<int> portsArg ("p", "port", "The port number the server should listen to", false, "port", cmd);
TCLAP::SwitchArg commLogArg ("", "log-comm", "Log server client communications to file", cmd);
@@ -522,7 +522,7 @@ int main(int argc, char **argv)
while (!cRoot::m_TerminateEventRaised)
{
- UniversalMain(std::move(ParseArguments(argc, argv)));
+ UniversalMain(ParseArguments(argc, argv));
}
#endif
}
@@ -531,7 +531,7 @@ int main(int argc, char **argv)
while (!cRoot::m_TerminateEventRaised)
{
// Not running as a service, do normal startup
- UniversalMain(std::move(ParseArguments(argc, argv)));
+ UniversalMain(ParseArguments(argc, argv));
}
}