summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authormadmaxoft <github@xoft.cz>2014-01-12 10:04:16 +0100
committermadmaxoft <github@xoft.cz>2014-01-12 10:04:16 +0100
commit180b9b90993870532a8daa2ee6498005b6c3bf49 (patch)
treedac846b760b6f5fd294fbd771975dd55b0856c0d /src
parentFixed Linux configuration. (diff)
parentDisabled a useless MSVC warning in Bindings.cpp. (diff)
downloadcuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.tar
cuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.tar.gz
cuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.tar.bz2
cuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.tar.lz
cuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.tar.xz
cuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.tar.zst
cuberite-180b9b90993870532a8daa2ee6498005b6c3bf49.zip
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/AllToLua.pkg3
-rw-r--r--src/Bindings/CMakeLists.txt23
-rw-r--r--src/Bindings/LuaState.cpp68
-rw-r--r--src/Bindings/LuaState.h141
-rw-r--r--src/Bindings/ManualBindings.cpp148
-rw-r--r--src/Bindings/Plugin.h4
-rw-r--r--src/Bindings/PluginLua.cpp104
-rw-r--r--src/Bindings/PluginLua.h4
-rw-r--r--src/Bindings/PluginManager.cpp89
-rw-r--r--src/Bindings/PluginManager.h10
-rw-r--r--src/Bindings/tolua++.h6
-rw-r--r--src/Bindings/tolua_base.h128
-rw-r--r--src/BiomeDef.cpp131
-rw-r--r--src/BiomeDef.h107
-rw-r--r--src/BlockArea.cpp8
-rw-r--r--src/BlockEntities/BlockEntity.h6
-rw-r--r--src/BlockEntities/BlockEntityWithItems.h1
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp8
-rw-r--r--src/BlockEntities/FurnaceEntity.h2
-rw-r--r--src/BlockEntities/HopperEntity.cpp1
-rw-r--r--src/BlockEntities/JukeboxEntity.h2
-rw-r--r--src/BlockEntities/NoteEntity.h2
-rw-r--r--src/BlockID.cpp100
-rw-r--r--src/BlockID.h3
-rw-r--r--src/BlockTracer.h25
-rw-r--r--src/Blocks/BlockGlowstone.h4
-rw-r--r--src/Blocks/BlockHandler.h6
-rw-r--r--src/ByteBuffer.cpp7
-rw-r--r--src/ByteBuffer.h2
-rw-r--r--src/CMakeLists.txt25
-rw-r--r--src/Chunk.cpp10
-rw-r--r--src/Chunk.h23
-rw-r--r--src/Chunk.inl.h34
-rw-r--r--src/ChunkDef.h93
-rw-r--r--src/ChunkMap.cpp2
-rw-r--r--src/ChunkSender.cpp2
-rw-r--r--src/ClientHandle.cpp19
-rw-r--r--src/ClientHandle.h2
-rw-r--r--src/CommandOutput.h1
-rw-r--r--src/Defines.h28
-rw-r--r--src/Entities/Entity.h14
-rw-r--r--src/Entities/Player.cpp4
-rw-r--r--src/Entities/Player.h4
-rw-r--r--src/Entities/ProjectileEntity.h6
-rw-r--r--src/Generating/Caves.cpp9
-rw-r--r--src/Generating/ChunkGenerator.cpp48
-rw-r--r--src/Generating/ChunkGenerator.h63
-rw-r--r--src/Generating/CompoGen.cpp17
-rw-r--r--src/Generating/ComposableGenerator.cpp204
-rw-r--r--src/Generating/ComposableGenerator.h17
-rw-r--r--src/Generating/DistortedHeightmap.cpp3
-rw-r--r--src/Generating/FinishGen.cpp6
-rw-r--r--src/Generating/FinishGen.h2
-rw-r--r--src/Generating/HeiGen.cpp74
-rw-r--r--src/Generating/Noise3DGenerator.cpp4
-rw-r--r--src/Generating/Noise3DGenerator.h2
-rw-r--r--src/Generating/Ravines.cpp2
-rw-r--r--src/Generating/Trees.cpp49
-rw-r--r--src/Generating/Trees.h3
-rw-r--r--src/Globals.h22
-rw-r--r--src/HTTPServer/HTTPConnection.cpp2
-rw-r--r--src/HTTPServer/HTTPFormParser.cpp1
-rw-r--r--src/HTTPServer/MultipartParser.cpp2
-rw-r--r--src/HTTPServer/NameValueParser.cpp1
-rw-r--r--src/Inventory.cpp4
-rw-r--r--src/Item.cpp2
-rw-r--r--src/Item.h4
-rw-r--r--src/Items/ItemFishingRod.h8
-rw-r--r--src/Items/ItemHandler.h8
-rw-r--r--src/Items/ItemSeeds.h1
-rw-r--r--src/LightingThread.cpp5
-rw-r--r--src/LineBlockTracer.cpp3
-rw-r--r--src/OSSupport/CriticalSection.h5
-rw-r--r--src/OSSupport/Queue.h178
-rw-r--r--src/OSSupport/SocketThreads.h3
-rw-r--r--src/Piston.cpp1
-rw-r--r--src/Protocol/Protocol.h1
-rw-r--r--src/Protocol/Protocol125.cpp14
-rw-r--r--src/Protocol/Protocol125.h1
-rw-r--r--src/Protocol/Protocol132.cpp23
-rw-r--r--src/Protocol/Protocol132.h14
-rw-r--r--src/Protocol/Protocol14x.cpp13
-rw-r--r--src/Protocol/Protocol15x.cpp2
-rw-r--r--src/Protocol/Protocol17x.cpp22
-rw-r--r--src/Protocol/Protocol17x.h15
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp12
-rw-r--r--src/Protocol/ProtocolRecognizer.h1
-rw-r--r--src/Root.cpp6
-rw-r--r--src/Server.cpp9
-rw-r--r--src/Server.h23
-rw-r--r--src/Simulator/FireSimulator.h2
-rw-r--r--src/Simulator/NoopFluidSimulator.h10
-rw-r--r--src/Simulator/RedstoneSimulator.h4
-rw-r--r--src/Simulator/SandSimulator.h2
-rw-r--r--src/Simulator/Simulator.h9
-rw-r--r--src/StringCompression.cpp4
-rw-r--r--src/StringUtils.cpp93
-rw-r--r--src/StringUtils.h12
-rw-r--r--src/UI/SlotArea.cpp4
-rw-r--r--src/WebAdmin.cpp3
-rw-r--r--src/WebAdmin.h15
-rw-r--r--src/World.cpp87
-rw-r--r--src/World.h27
-rw-r--r--src/WorldStorage/CMakeLists.txt2
-rw-r--r--src/WorldStorage/FastNBT.cpp23
-rw-r--r--src/WorldStorage/FastNBT.h6
-rw-r--r--src/WorldStorage/WorldStorage.cpp151
-rw-r--r--src/WorldStorage/WorldStorage.h40
-rw-r--r--src/main.cpp5
109 files changed, 1846 insertions, 972 deletions
diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg
index e9a5ea0c6..2d0300ebf 100644
--- a/src/Bindings/AllToLua.pkg
+++ b/src/Bindings/AllToLua.pkg
@@ -1,8 +1,6 @@
$#include "../Globals.h"
-$#include "tolua_base.h"
-
// Typedefs from Globals.h, so that we don't have to process that file:
typedef long long Int64;
typedef int Int32;
@@ -14,6 +12,7 @@ typedef unsigned short UInt16;
$cfile "../ChunkDef.h"
+$cfile "../BiomeDef.h"
$cfile "../../lib/inifile/iniFile.h"
diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt
index 41c641d9d..50b81e42a 100644
--- a/src/Bindings/CMakeLists.txt
+++ b/src/Bindings/CMakeLists.txt
@@ -2,17 +2,22 @@
cmake_minimum_required (VERSION 2.6)
project (MCServer)
+# NOTE: This CMake file is processed only for Unix builds; Windows(MSVC) builds handle all the subfolders in /src in a single file, /src/CMakeLists.txt
+
include_directories ("${PROJECT_SOURCE_DIR}/../")
- ADD_CUSTOM_COMMAND(
-#add any new generated bindings here
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Bindings.cpp ${CMAKE_CURRENT_BINARY_DIR}/Bindings.h
-#command execuded to regerate bindings
- COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
-#add any new generation dependencies here
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/virtual_method_hooks.lua ${CMAKE_CURRENT_SOURCE_DIR}/AllToLua.pkg tolua
- )
-
+ADD_CUSTOM_COMMAND(
+ # add any new generated bindings here
+ OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Bindings.h
+
+ # command execuded to regerate bindings
+ COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+
+ # add any new generation dependencies here
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/virtual_method_hooks.lua ${CMAKE_CURRENT_SOURCE_DIR}/AllToLua.pkg tolua
+)
+
#add cpp files here
add_library(Bindings PluginManager LuaState WebPlugin Bindings ManualBindings LuaWindow Plugin PluginLua WebPlugin)
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 64a818a60..149c304ed 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -228,6 +228,9 @@ bool cLuaState::PushFunction(const char * a_FunctionName)
return false;
}
+ // Push the error handler for lua_pcall()
+ lua_pushcfunction(m_LuaState, &ReportFnCallErrors);
+
lua_getglobal(m_LuaState, a_FunctionName);
if (!lua_isfunction(m_LuaState, -1))
{
@@ -249,6 +252,9 @@ bool cLuaState::PushFunction(int a_FnRef)
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
+ // Push the error handler for lua_pcall()
+ lua_pushcfunction(m_LuaState, &ReportFnCallErrors);
+
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // same as lua_getref()
if (!lua_isfunction(m_LuaState, -1))
{
@@ -264,27 +270,29 @@ bool cLuaState::PushFunction(int a_FnRef)
-bool cLuaState::PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName)
+bool cLuaState::PushFunction(const cTableRef & a_TableRef)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
-
- lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef); // Get the table ref
+
+ // Push the error handler for lua_pcall()
+ lua_pushcfunction(m_LuaState, &ReportFnCallErrors);
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef.GetTableRef()); // Get the table ref
if (!lua_istable(m_LuaState, -1))
{
// Not a table, bail out
lua_pop(m_LuaState, 1);
return false;
}
- lua_getfield(m_LuaState, -1, a_FnName);
+ lua_getfield(m_LuaState, -1, a_TableRef.GetFnName());
if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1))
{
// Not a valid function, bail out
lua_pop(m_LuaState, 2);
return false;
}
- lua_remove(m_LuaState, -2); // Remove the table ref from the stack
- m_CurrentFunctionName = "<table_callback>";
+ Printf(m_CurrentFunctionName, "<table-callback %s>", a_TableRef.GetFnName());
m_NumCurrentFunctionArgs = 0;
return true;
}
@@ -297,7 +305,7 @@ void cLuaState::Push(const AString & a_String)
{
ASSERT(IsValid());
- tolua_pushcppstring(m_LuaState, a_String);
+ lua_pushlstring(m_LuaState, a_String.data(), a_String.size());
m_NumCurrentFunctionArgs += 1;
}
@@ -468,6 +476,18 @@ void cLuaState::Push(cItems * a_Items)
+void cLuaState::Push(const cItems & a_Items)
+{
+ ASSERT(IsValid());
+
+ tolua_pushusertype(m_LuaState, (void *)&a_Items, "cItems");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
void cLuaState::Push(cClientHandle * a_Client)
{
ASSERT(IsValid());
@@ -720,11 +740,13 @@ void cLuaState::GetReturn(int a_StackPos, double & a_ReturnedVal)
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
- ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1));
+ ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1)); // The function to call
+ ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 2)); // The error handler
- int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, 0);
- if (ReportErrors(s))
+ int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, -m_NumCurrentFunctionArgs - 2);
+ if (s != 0)
{
+ // The error has already been printed together with the stacktrace
LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), m_CurrentFunctionName.c_str());
m_NumCurrentFunctionArgs = -1;
m_CurrentFunctionName.clear();
@@ -952,15 +974,24 @@ bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status)
void cLuaState::LogStackTrace(void)
{
+ LogStackTrace(m_LuaState);
+}
+
+
+
+
+
+void cLuaState::LogStackTrace(lua_State * a_LuaState)
+{
LOGWARNING("Stack trace:");
lua_Debug entry;
int depth = 0;
- while (lua_getstack(m_LuaState, depth, &entry))
+ while (lua_getstack(a_LuaState, depth, &entry))
{
- int status = lua_getinfo(m_LuaState, "Sln", &entry);
+ int status = lua_getinfo(a_LuaState, "Sln", &entry);
assert(status);
- LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "?");
+ LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "(no name)");
depth++;
}
LOGWARNING("Stack trace end");
@@ -993,6 +1024,17 @@ AString cLuaState::GetTypeText(int a_StackPos)
+int cLuaState::ReportFnCallErrors(lua_State * a_LuaState)
+{
+ LOGWARNING("LUA: %s", lua_tostring(a_LuaState, -1));
+ LogStackTrace(a_LuaState);
+ return 1; // We left the error message on the stack as the return value
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cLuaState::cRef:
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 15b0cdeff..a43d39732 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -85,6 +85,23 @@ public:
} ;
+ /** Used for calling functions stored in a reference-stored table */
+ class cTableRef
+ {
+ int m_TableRef;
+ const char * m_FnName;
+ public:
+ cTableRef(int a_TableRef, const char * a_FnName) :
+ m_TableRef(a_TableRef),
+ m_FnName(a_FnName)
+ {
+ }
+
+ int GetTableRef(void) const { return m_TableRef; }
+ const char * GetFnName(void) const { return m_FnName; }
+ } ;
+
+
/// A dummy class that's used only to delimit function args from return values for cLuaState::Call()
class cRet
{
@@ -133,24 +150,6 @@ public:
/// Returns true if a_FunctionName is a valid Lua function that can be called
bool HasFunction(const char * a_FunctionName);
- /** Pushes the function of the specified name onto the stack.
- Returns true if successful. Logs a warning on failure (incl. m_SubsystemName)
- */
- bool PushFunction(const char * a_FunctionName);
-
- /** Pushes a function that has been saved into the global registry, identified by a_FnRef.
- Returns true if successful. Logs a warning on failure
- */
- bool PushFunction(int a_FnRef);
-
- /** Pushes a function that is stored in a table ref.
- Returns true if successful, false on failure. Doesn't log failure.
- */
- bool PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName);
-
- /// Pushes a usertype of the specified class type onto the stack
- void PushUserType(void * a_Object, const char * a_Type);
-
// Push a value onto the stack
void Push(const AString & a_String);
void Push(const AStringVector & a_Vector);
@@ -165,6 +164,7 @@ public:
void Push(cMonster * a_Monster);
void Push(cItem * a_Item);
void Push(cItems * a_Items);
+ void Push(const cItems & a_Items);
void Push(cClientHandle * a_ClientHandle);
void Push(cPickup * a_Pickup);
void Push(cChunkDesc * a_ChunkDesc);
@@ -182,7 +182,7 @@ public:
void Push(void * a_Ptr);
void Push(cHopperEntity * a_Hopper);
void Push(cBlockEntity * a_BlockEntity);
-
+
/// Call any 0-param 0-return Lua function in a single line:
template <typename FnT>
bool Call(FnT a_FnName)
@@ -240,12 +240,33 @@ public:
return CallFunction(0);
}
+ /// Call any 0-param 1-return Lua function in a single line:
+ template<
+ typename FnT, typename RetT1
+ >
+ bool Call(FnT a_FnName, const cRet & a_Mark, RetT1 & a_Ret1)
+ {
+ UNUSED(a_Mark);
+ if (!PushFunction(a_FnName))
+ {
+ return false;
+ }
+ if (!CallFunction(1))
+ {
+ return false;
+ }
+ GetReturn(-1, a_Ret1);
+ lua_pop(m_LuaState, 1);
+ return true;
+ }
+
/// Call any 1-param 1-return Lua function in a single line:
template<
typename FnT, typename ArgT1, typename RetT1
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -266,6 +287,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -287,6 +309,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -309,6 +332,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -332,6 +356,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -357,6 +382,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -383,6 +409,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -410,6 +437,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -438,6 +466,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -467,6 +496,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, ArgT10 a_Arg10, const cRet & a_Mark, RetT1 & a_Ret1)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -496,6 +526,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -517,6 +548,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -540,6 +572,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -564,6 +597,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -589,6 +623,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -616,6 +651,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -644,6 +680,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -673,6 +710,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -703,6 +741,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -734,6 +773,7 @@ public:
>
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3, RetT4 & a_Ret4, RetT5 & a_Ret5)
{
+ UNUSED(a_Mark);
if (!PushFunction(a_FnName))
{
return false;
@@ -761,25 +801,6 @@ public:
}
- /// Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged
- void GetReturn(int a_StackPos, bool & a_ReturnedVal);
-
- /// Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged
- void GetReturn(int a_StackPos, AString & a_ReturnedVal);
-
- /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged
- void GetReturn(int a_StackPos, int & a_ReturnedVal);
-
- /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged
- void GetReturn(int a_StackPos, double & a_ReturnedVal);
-
- /**
- Calls the function that has been pushed onto the stack by PushFunction(),
- with arguments pushed by PushXXX().
- Returns true if successful, logs a warning on failure.
- */
- bool CallFunction(int a_NumReturnValues);
-
/// Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions
bool CheckParamUserTable(int a_StartParam, const char * a_UserTable, int a_EndParam = -1);
@@ -807,6 +828,9 @@ public:
/// Logs all items in the current stack trace to the server console
void LogStackTrace(void);
+ /// Logs all items in the current stack trace to the server console
+ static void LogStackTrace(lua_State * a_LuaState);
+
/// Returns the type of the item on the specified position in the stack
AString GetTypeText(int a_StackPos);
@@ -826,6 +850,47 @@ protected:
/// Number of arguments currently pushed (for the Push / Call chain)
int m_NumCurrentFunctionArgs;
+
+
+ /** Pushes the function of the specified name onto the stack.
+ Returns true if successful. Logs a warning on failure (incl. m_SubsystemName)
+ */
+ bool PushFunction(const char * a_FunctionName);
+
+ /** Pushes a function that has been saved into the global registry, identified by a_FnRef.
+ Returns true if successful. Logs a warning on failure
+ */
+ bool PushFunction(int a_FnRef);
+
+ /** Pushes a function that is stored in a referenced table by name
+ Returns true if successful. Logs a warning on failure
+ */
+ bool PushFunction(const cTableRef & a_TableRef);
+
+ /// Pushes a usertype of the specified class type onto the stack
+ void PushUserType(void * a_Object, const char * a_Type);
+
+ /// Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged
+ void GetReturn(int a_StackPos, bool & a_ReturnedVal);
+
+ /// Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged
+ void GetReturn(int a_StackPos, AString & a_ReturnedVal);
+
+ /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged
+ void GetReturn(int a_StackPos, int & a_ReturnedVal);
+
+ /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged
+ void GetReturn(int a_StackPos, double & a_ReturnedVal);
+
+ /**
+ Calls the function that has been pushed onto the stack by PushFunction(),
+ with arguments pushed by PushXXX().
+ Returns true if successful, logs a warning on failure.
+ */
+ bool CallFunction(int a_NumReturnValues);
+
+ /** Used as the error reporting function for function calls */
+ static int ReportFnCallErrors(lua_State * a_LuaState);
} ;
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 2e19c2581..a9368f613 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -991,7 +991,6 @@ static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
const cPluginManager::PluginMap & AllPlugins = self->GetAllPlugins();
lua_newtable(tolua_S);
- int newTable = lua_gettop(tolua_S);
int index = 1;
cPluginManager::PluginMap::const_iterator iter = AllPlugins.begin();
while (iter != AllPlugins.end())
@@ -1137,16 +1136,17 @@ static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
{
/*
Function signatures:
- cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) -- (1) recommended
- cPluginManager:Get():AddHook(HOOK_TYPE, CallbackFunction) -- (2) accepted silently
- cPluginManager:Get():AddHook(Plugin, HOOK_TYPE) -- (3) old style (#121), accepted but complained about
- cPluginManager.AddHook(Plugin, HOOK_TYPE) -- (4) old style (#121) mangled, accepted but complained about
+ cPluginManager:AddHook(HOOK_TYPE, CallbackFunction) -- (1) recommended
+ cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) -- (2) accepted silently (#401 deprecates this)
+ cPluginManager:Get():AddHook(HOOK_TYPE, CallbackFunction) -- (3) accepted silently
+ cPluginManager:Get():AddHook(Plugin, HOOK_TYPE) -- (4) old style (#121), accepted but complained about in the console
+ cPluginManager.AddHook(Plugin, HOOK_TYPE) -- (5) old style (#121) mangled, accepted but complained about in the console
*/
cLuaState S(tolua_S);
cPluginManager * PlgMgr = cPluginManager::Get();
- // If the first param is a cPluginManager, use it instead of the global one:
+ // If the first param is a cPluginManager instance, use it instead of the global one:
int ParamIdx = 1;
tolua_Error err;
if (tolua_isusertype(S, 1, "cPluginManager", 0, &err))
@@ -1161,6 +1161,11 @@ static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
}
ParamIdx += 1;
}
+ else if (tolua_isusertable(S, 1, "cPluginManager", 0, &err))
+ {
+ // Style 1, use the global PlgMgr, but increment ParamIdx
+ ParamIdx++;
+ }
if (lua_isnumber(S, ParamIdx) && lua_isfunction(S, ParamIdx + 1))
{
@@ -1177,7 +1182,7 @@ static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
AString ParamDesc;
Printf(ParamDesc, "%s, %s, %s", S.GetTypeText(1).c_str(), S.GetTypeText(2).c_str(), S.GetTypeText(3).c_str());
- LOGWARNING("cPluginManager.AddHook(): bad parameters. Expected HOOK_TYPE and CallbackFunction, got %s. Hook not added.", ParamDesc.c_str());
+ LOGWARNING("cPluginManager:AddHook(): bad parameters. Expected HOOK_TYPE and CallbackFunction, got %s. Hook not added.", ParamDesc.c_str());
S.LogStackTrace();
return 0;
}
@@ -1877,7 +1882,6 @@ static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
const cWebPlugin::TabNameList & TabNames = self->GetTabNames();
lua_newtable(tolua_S);
- int newTable = lua_gettop(tolua_S);
int index = 1;
cWebPlugin::TabNameList::const_iterator iter = TabNames.begin();
while(iter != TabNames.end())
@@ -1898,6 +1902,35 @@ static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
+static int tolua_cClientHandle_SendPluginMessage(lua_State * L)
+{
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserType(1, "cClientHandle") ||
+ !S.CheckParamString(2, 3) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+ cClientHandle * Client = (cClientHandle *)tolua_tousertype(L, 1, NULL);
+ if (Client == NULL)
+ {
+ LOGWARNING("ClientHandle is nil in cClientHandle:SendPluginMessage()");
+ S.LogStackTrace();
+ return 0;
+ }
+ AString Channel, Message;
+ Channel.assign(lua_tostring(L, 2), lua_strlen(L, 2));
+ Message.assign(lua_tostring(L, 3), lua_strlen(L, 3));
+ Client->SendPluginMessage(Channel, Message);
+ return 0;
+}
+
+
+
+
+
static int Lua_ItemGrid_GetSlotCoords(lua_State * L)
{
tolua_Error tolua_err;
@@ -1947,118 +1980,72 @@ public:
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
{
- if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
+ bool res = false;
+ if (!m_LuaState.Call(
+ cLuaState::cTableRef(m_TableRef, "OnNextBlock"),
+ a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_EntryFace,
+ cLuaState::Return, res
+ ))
{
// No such function in the table, skip the callback
return false;
}
- m_LuaState.Push(a_BlockX);
- m_LuaState.Push(a_BlockY);
- m_LuaState.Push(a_BlockZ);
- m_LuaState.Push(a_BlockType);
- m_LuaState.Push(a_BlockMeta);
- m_LuaState.Push(a_EntryFace);
- if (!m_LuaState.CallFunction(1))
- {
- return false;
- }
- bool res = false;
- if (lua_isboolean(m_LuaState, -1))
- {
- res = (lua_toboolean(m_LuaState, -1) != 0);
- }
- lua_pop(m_LuaState, 1);
return res;
}
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) override
{
- if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
+ bool res = false;
+ if (!m_LuaState.Call(
+ cLuaState::cTableRef(m_TableRef, "OnNextBlockNoData"),
+ a_BlockX, a_BlockY, a_BlockZ, a_EntryFace,
+ cLuaState::Return, res
+ ))
{
// No such function in the table, skip the callback
return false;
}
- m_LuaState.Push(a_BlockX);
- m_LuaState.Push(a_BlockY);
- m_LuaState.Push(a_BlockZ);
- m_LuaState.Push(a_EntryFace);
- if (!m_LuaState.CallFunction(1))
- {
- return false;
- }
- bool res = false;
- if (lua_isboolean(m_LuaState, -1))
- {
- res = (lua_toboolean(m_LuaState, -1) != 0);
- }
- lua_pop(m_LuaState, 1);
return res;
}
virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
{
- if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnOutOfWorld"))
+ bool res = false;
+ if (!m_LuaState.Call(
+ cLuaState::cTableRef(m_TableRef, "OnOutOfWorld"),
+ a_BlockX, a_BlockY, a_BlockZ,
+ cLuaState::Return, res
+ ))
{
// No such function in the table, skip the callback
return false;
}
- m_LuaState.Push(a_BlockX);
- m_LuaState.Push(a_BlockY);
- m_LuaState.Push(a_BlockZ);
- if (!m_LuaState.CallFunction(1))
- {
- return false;
- }
- bool res = false;
- if (lua_isboolean(m_LuaState, -1))
- {
- res = (lua_toboolean(m_LuaState, -1) != 0);
- }
- lua_pop(m_LuaState, 1);
return res;
}
virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
{
- if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnIntoWorld"))
+ bool res = false;
+ if (!m_LuaState.Call(
+ cLuaState::cTableRef(m_TableRef, "OnIntoWorld"),
+ a_BlockX, a_BlockY, a_BlockZ,
+ cLuaState::Return, res
+ ))
{
// No such function in the table, skip the callback
return false;
}
- m_LuaState.Push(a_BlockX);
- m_LuaState.Push(a_BlockY);
- m_LuaState.Push(a_BlockZ);
- if (!m_LuaState.CallFunction(1))
- {
- return false;
- }
- bool res = false;
- if (lua_isboolean(m_LuaState, -1))
- {
- res = (lua_toboolean(m_LuaState, -1) != 0);
- }
- lua_pop(m_LuaState, 1);
return res;
}
virtual void OnNoMoreHits(void) override
{
- if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoMoreHits"))
- {
- // No such function in the table, skip the callback
- return;
- }
- m_LuaState.CallFunction(0);
+ m_LuaState.Call(cLuaState::cTableRef(m_TableRef, "OnNoMoreHits"));
}
virtual void OnNoChunk(void) override
{
- if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoChunk"))
- {
- // No such function in the table, skip the callback
- return;
- }
- m_LuaState.CallFunction(0);
+ m_LuaState.Call(cLuaState::cTableRef(m_TableRef, "OnNoChunk"));
}
protected:
@@ -2286,6 +2273,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_beginmodule(tolua_S, "cClientHandle");
tolua_constant(tolua_S, "MAX_VIEW_DISTANCE", cClientHandle::MAX_VIEW_DISTANCE);
tolua_constant(tolua_S, "MIN_VIEW_DISTANCE", cClientHandle::MIN_VIEW_DISTANCE);
+ tolua_function(tolua_S, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cItemGrid");
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index 9a3c2383e..f4a117721 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -68,6 +68,8 @@ public:
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerEating (cPlayer & a_Player) = 0;
+ virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) = 0;
+ virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) = 0;
virtual bool OnPlayerJoined (cPlayer & a_Player) = 0;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) = 0;
virtual bool OnPlayerMoved (cPlayer & a_Player) = 0;
@@ -82,6 +84,8 @@ public:
virtual bool OnPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
virtual bool OnPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
+ virtual bool OnPluginMessage (cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message) = 0;
+ virtual bool OnPluginsLoaded (void) = 0;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) = 0;
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index 0e5a66cd6..eefcd2b09 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -90,6 +90,8 @@ bool cPluginLua::Initialize(void)
// Load all files for this plugin, and execute them
AStringVector Files = cFile::GetFolderContents(PluginPath.c_str());
+
+ int numFiles = 0;
for (AStringVector::const_iterator itr = Files.begin(); itr != Files.end(); ++itr)
{
if (itr->rfind(".lua") == AString::npos)
@@ -101,9 +103,20 @@ bool cPluginLua::Initialize(void)
{
Close();
return false;
+ }
+ else
+ {
+ numFiles++;
}
} // for itr - Files[]
+ if (numFiles == 0)
+ {
+ LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str());
+ Close();
+ return false;
+ }
+
// Call intialize function
bool res = false;
if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res))
@@ -630,6 +643,46 @@ bool cPluginLua::OnPlayerEating(cPlayer & a_Player)
+bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward)
+{
+ cCSLock Lock(m_CriticalSection);
+ bool res = false;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FISHED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_Reward, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+bool cPluginLua::OnPlayerFishing(cPlayer & a_Player, cItems & a_Reward)
+{
+ cCSLock Lock(m_CriticalSection);
+ bool res = false;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FISHING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_Reward, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginLua::OnPlayerJoined(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
@@ -910,6 +963,44 @@ bool cPluginLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_Block
+bool cPluginLua::OnPluginMessage(cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message)
+{
+ cCSLock Lock(m_CriticalSection);
+ bool res = false;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLUGIN_MESSAGE];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Client, a_Channel, a_Message);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+bool cPluginLua::OnPluginsLoaded(void)
+{
+ cCSLock Lock(m_CriticalSection);
+ bool res = false;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLUGINS_LOADED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ bool ret = false;
+ m_LuaState.Call((int)(**itr), cLuaState::Return, ret);
+ res = res || ret;
+ }
+ return res;
+}
+
+
+
+
+
bool cPluginLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
{
cCSLock Lock(m_CriticalSection);
@@ -1324,6 +1415,8 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
case cPluginManager::HOOK_PLAYER_USED_ITEM: return "OnPlayerUsedItem";
case cPluginManager::HOOK_PLAYER_USING_BLOCK: return "OnPlayerUsingBlock";
case cPluginManager::HOOK_PLAYER_USING_ITEM: return "OnPlayerUsingItem";
+ case cPluginManager::HOOK_PLUGIN_MESSAGE: return "OnPluginMessage";
+ case cPluginManager::HOOK_PLUGINS_LOADED: return "OnPluginsLoaded";
case cPluginManager::HOOK_POST_CRAFTING: return "OnPostCrafting";
case cPluginManager::HOOK_PRE_CRAFTING: return "OnPreCrafting";
case cPluginManager::HOOK_SPAWNED_ENTITY: return "OnSpawnedEntity";
@@ -1337,8 +1430,17 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
case cPluginManager::HOOK_WEATHER_CHANGED: return "OnWeatherChanged";
case cPluginManager::HOOK_WEATHER_CHANGING: return "OnWeatherChanging";
case cPluginManager::HOOK_WORLD_TICK: return "OnWorldTick";
- default: return NULL;
+
+ case cPluginManager::HOOK_NUM_HOOKS:
+ {
+ // Satisfy a warning that all enum values should be used in a switch
+ // but don't want a default branch, so that we catch new hooks missing from this list.
+ break;
+ }
} // switch (a_Hook)
+ LOGWARNING("Requested name of an unknown hook type function: %d (max is %d)", a_HookType, cPluginManager::HOOK_MAX);
+ ASSERT(!"Unknown hook requested!");
+ return NULL;
}
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index e1e274c72..c01f5ca89 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -65,6 +65,8 @@ public:
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerEating (cPlayer & a_Player) override;
+ virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) override;
+ virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) override;
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
virtual bool OnPlayerMoved (cPlayer & a_Player) override;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
@@ -79,6 +81,8 @@ public:
virtual bool OnPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool OnPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
+ virtual bool OnPluginMessage (cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message) override;
+ virtual bool OnPluginsLoaded (void) override;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) override;
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 832dc4249..68e6aea33 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -118,7 +118,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
int KeyNum = a_SettingsIni.FindKey("Plugins");
// If it does, how many plugins are there?
- unsigned int NumPlugins = ((KeyNum != -1) ? (a_SettingsIni.GetNumValues(KeyNum)) : 0);
+ int NumPlugins = ((KeyNum != -1) ? (a_SettingsIni.GetNumValues(KeyNum)) : 0);
if (KeyNum == -1)
{
@@ -126,7 +126,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
}
else if (NumPlugins > 0)
{
- for(unsigned int i = 0; i < NumPlugins; i++)
+ for (int i = 0; i < NumPlugins; i++)
{
AString ValueName = a_SettingsIni.GetValueName(KeyNum, i);
if (ValueName.compare("Plugin") == 0)
@@ -136,7 +136,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
{
if (m_Plugins.find(PluginFile) != m_Plugins.end())
{
- LoadPlugin( PluginFile );
+ LoadPlugin(PluginFile);
}
}
}
@@ -155,6 +155,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
{
LOG("-- Loaded 1 Plugin --");
}
+ CallHookPluginsLoaded();
}
@@ -693,6 +694,48 @@ bool cPluginManager::CallHookPlayerEating(cPlayer & a_Player)
+bool cPluginManager::CallHookPlayerFished(cPlayer & a_Player, const cItems a_Reward)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_FISHED);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnPlayerFished(a_Player, a_Reward))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+bool cPluginManager::CallHookPlayerFishing(cPlayer & a_Player, cItems a_Reward)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_FISHING);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnPlayerFishing(a_Player, a_Reward))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginManager::CallHookPlayerJoined(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_JOINED);
@@ -987,6 +1030,46 @@ bool cPluginManager::CallHookPlayerUsingItem(cPlayer & a_Player, int a_BlockX, i
+bool cPluginManager::CallHookPluginMessage(cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_PLUGIN_MESSAGE);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnPluginMessage(a_Client, a_Channel, a_Message))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+bool cPluginManager::CallHookPluginsLoaded(void)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_PLUGINS_LOADED);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ bool res = false;
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ res = !(*itr)->OnPluginsLoaded() || res;
+ }
+ return res;
+}
+
+
+
+
+
bool cPluginManager::CallHookPostCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_POST_CRAFTING);
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index 04d6470c7..9936f5a35 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -80,6 +80,8 @@ public: // tolua_export
HOOK_PLAYER_BREAKING_BLOCK,
HOOK_PLAYER_BROKEN_BLOCK,
HOOK_PLAYER_EATING,
+ HOOK_PLAYER_FISHED,
+ HOOK_PLAYER_FISHING,
HOOK_PLAYER_JOINED,
HOOK_PLAYER_LEFT_CLICK,
HOOK_PLAYER_MOVING,
@@ -94,6 +96,8 @@ public: // tolua_export
HOOK_PLAYER_USED_ITEM,
HOOK_PLAYER_USING_BLOCK,
HOOK_PLAYER_USING_ITEM,
+ HOOK_PLUGIN_MESSAGE,
+ HOOK_PLUGINS_LOADED,
HOOK_POST_CRAFTING,
HOOK_PRE_CRAFTING,
HOOK_SPAWNED_ENTITY,
@@ -167,6 +171,8 @@ public: // tolua_export
bool CallHookPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerEating (cPlayer & a_Player);
+ bool CallHookPlayerFished (cPlayer & a_Player, const cItems a_Reward);
+ bool CallHookPlayerFishing (cPlayer & a_Player, cItems a_Reward);
bool CallHookPlayerJoined (cPlayer & a_Player);
bool CallHookPlayerMoving (cPlayer & a_Player);
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
@@ -181,6 +187,8 @@ public: // tolua_export
bool CallHookPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
bool CallHookPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
+ bool CallHookPluginMessage (cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message);
+ bool CallHookPluginsLoaded (void);
bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookSpawnedEntity (cWorld & a_World, cEntity & a_Entity);
@@ -271,7 +279,7 @@ private:
bool m_bReloadPlugins;
cPluginManager();
- ~cPluginManager();
+ virtual ~cPluginManager();
/// Reloads all plugins, defaulting to settings.ini for settings location
void ReloadPluginsNow(void);
diff --git a/src/Bindings/tolua++.h b/src/Bindings/tolua++.h
index 4dfd06318..73e65b746 100644
--- a/src/Bindings/tolua++.h
+++ b/src/Bindings/tolua++.h
@@ -2,12 +2,18 @@
// tolua++.h
// Redirection file, needed because ToLua++ generates the Bindings.cpp file with >> #include "tolua++.h" <<
+// Only used from Bindings.cpp
#include "tolua++/include/tolua++.h"
+#ifdef _MSC_VER
+ // Disable specific warnings for the generated Bindings.cpp file:
+ #pragma warning(disable: 4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning)
+#endif // _MSC_VER
+
diff --git a/src/Bindings/tolua_base.h b/src/Bindings/tolua_base.h
deleted file mode 100644
index 6a76f97b1..000000000
--- a/src/Bindings/tolua_base.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef TOLUA_BASE_H
-#define TOLUA_BASE_H
-
-#pragma warning(disable:4800) // This file is ONLY included by Bindings.cpp and it throws lots of C4800 warnings
-
-#include "tolua++/include/tolua++.h"
-
-
-
-
-
-class ToluaBase {
-
- int lua_instance;
-
-protected:
-
- lua_State* lua_state;
-
- void lua_stacktrace(lua_State* L) const
- {
- lua_Debug entry;
- int depth = 0;
-
- while (lua_getstack(L, depth, &entry))
- {
- lua_getinfo(L, "Sln", &entry);
-
- LOGERROR("%s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "?");
- depth++;
- }
- }
-
-
- bool report_errors(int status) const
- {
- if ( status!=0 )
- {
- const char* s = lua_tostring(lua_state, -1);
- LOGERROR("-- %s", s );
- //lua_pop(lua_state, 1);
- LOGERROR("Stack:");
- lua_stacktrace( lua_state );
- return true;
- }
- return false;
- }
-
- bool push_method(const char* name, lua_CFunction f) const {
-
- if (!lua_state) return false;
-
- lua_getref(lua_state, lua_instance);
- lua_pushstring(lua_state, name);
- //LOGINFO("1. push_method() Stack size: %i", lua_gettop( lua_state ) );
- lua_gettable(lua_state, -2);
- //LOGINFO("2. push_method() Stack size: %i", lua_gettop( lua_state ) );
-
- if (lua_isnil(lua_state, -1)) {
-
- // pop the table
- lua_pop(lua_state, 2);
- return false;
-
- } else {
-
- if (f) {
- if (lua_iscfunction(lua_state, -1)) {
- lua_pop(lua_state, 2);
- return false;
- };
- /* // not for now
- lua_pushcfunction(lua_state, f);
- if (lua_rawequal(lua_state, -1, -2)) {
-
- // avoid recursion, pop both functions and the table
- lua_pop(lua_state, 3);
- return false;
- };
-
- // pop f
- lua_pop(lua_state, 1);
- */
- };
-
- // swap table with function
- lua_insert(lua_state, -2);
- };
-
- return true;
- };
-
- void dbcall(lua_State* L, int nargs, int nresults) const {
-
- // using lua_call for now
- int s = lua_pcall(L, nargs, nresults, 0);
- report_errors( s );
- };
-public:
-
- int GetInstance() { return lua_instance; }
- lua_State* GetLuaState() { return lua_state; }
-
- void tolua__set_instance(lua_State* L, lua_Object lo) {
-
- lua_state = L;
-
- lua_pushvalue(L, lo);
- lua_instance = lua_ref(lua_state, 1);
- };
-
- ToluaBase() {
-
- lua_state = NULL;
- };
-
- ~ToluaBase() {
-
- if (lua_state) {
-
- lua_unref(lua_state, lua_instance);
- };
- };
-};
-
-#endif
-
-
diff --git a/src/BiomeDef.cpp b/src/BiomeDef.cpp
new file mode 100644
index 000000000..89a1cdefb
--- /dev/null
+++ b/src/BiomeDef.cpp
@@ -0,0 +1,131 @@
+
+// BiomeDef.cpp
+
+// Implements biome helper functions
+
+#include "Globals.h"
+#include "BiomeDef.h"
+
+
+EMCSBiome StringToBiome(const AString & a_BiomeString)
+{
+ // If it is a number, return it:
+ int res = atoi(a_BiomeString.c_str());
+ if ((res != 0) || (a_BiomeString.compare("0") == 0))
+ {
+ // It was a valid number
+ return (EMCSBiome)res;
+ }
+
+ // Convert using the built-in map:
+ static struct {
+ EMCSBiome m_Biome;
+ const char * m_String;
+ } BiomeMap[] =
+ {
+ {biOcean, "Ocean"} ,
+ {biPlains, "Plains"},
+ {biDesert, "Desert"},
+ {biExtremeHills, "ExtremeHills"},
+ {biForest, "Forest"},
+ {biTaiga, "Taiga"},
+ {biSwampland, "Swampland"},
+ {biRiver, "River"},
+ {biNether, "Hell"},
+ {biNether, "Nether"},
+ {biEnd, "Sky"},
+ {biEnd, "End"},
+ {biFrozenOcean, "FrozenOcean"},
+ {biFrozenRiver, "FrozenRiver"},
+ {biIcePlains, "IcePlains"},
+ {biIcePlains, "Tundra"},
+ {biIceMountains, "IceMountains"},
+ {biMushroomIsland, "MushroomIsland"},
+ {biMushroomShore, "MushroomShore"},
+ {biBeach, "Beach"},
+ {biDesertHills, "DesertHills"},
+ {biForestHills, "ForestHills"},
+ {biTaigaHills, "TaigaHills"},
+ {biExtremeHillsEdge, "ExtremeHillsEdge"},
+ {biJungle, "Jungle"},
+ {biJungleHills, "JungleHills"},
+
+ // Release 1.7 biomes:
+ {biJungleEdge, "JungleEdge"},
+ {biDeepOcean, "DeepOcean"},
+ {biStoneBeach, "StoneBeach"},
+ {biColdBeach, "ColdBeach"},
+ {biBirchForest, "BirchForest"},
+ {biBirchForestHills, "BirchForestHills"},
+ {biRoofedForest, "RoofedForest"},
+ {biColdTaiga, "ColdTaiga"},
+ {biColdTaigaHills, "ColdTaigaHills"},
+ {biMegaTaiga, "MegaTaiga"},
+ {biMegaTaigaHills, "MegaTaigaHills"},
+ {biExtremeHillsPlus, "ExtremeHillsPlus"},
+ {biSavanna, "Savanna"},
+ {biSavannaPlateau, "SavannaPlateau"},
+ {biMesa, "Mesa"},
+ {biMesaPlateauF, "MesaPlateauF"},
+ {biMesaPlateau, "MesaPlateau"},
+
+ // Release 1.7 variants:
+ {biSunflowerPlains, "SunflowerPlains"},
+ {biDesertM, "DesertM"},
+ {biExtremeHillsM, "ExtremeHillsM"},
+ {biFlowerForest, "FlowerForest"},
+ {biTaigaM, "TaigaM"},
+ {biSwamplandM, "SwamplandM"},
+ {biIcePlainsSpikes, "IcePlainsSpikes"},
+ {biJungleM, "JungleM"},
+ {biJungleEdgeM, "JungleEdgeM"},
+ {biBirchForestM, "BirchForestM"},
+ {biBirchForestHillsM, "BirchForestHillsM"},
+ {biRoofedForestM, "RoofedForestM"},
+ {biColdTaigaM, "ColdTaigaM"},
+ {biMegaSpruceTaiga, "MegaSpruceTaiga"},
+ {biMegaSpruceTaigaHills, "MegaSpruceTaigaHills"},
+ {biExtremeHillsPlusM, "ExtremeHillsPlusM"},
+ {biSavannaM, "SavannaM"},
+ {biSavannaPlateauM, "SavannaPlateauM"},
+ {biMesaBryce, "MesaBryce"},
+ {biMesaPlateauFM, "MesaPlateauFM"},
+ {biMesaPlateauM, "MesaPlateauM"},
+ } ;
+
+ for (size_t i = 0; i < ARRAYCOUNT(BiomeMap); i++)
+ {
+ if (NoCaseCompare(BiomeMap[i].m_String, a_BiomeString) == 0)
+ {
+ return BiomeMap[i].m_Biome;
+ }
+ } // for i - BiomeMap[]
+ return (EMCSBiome)-1;
+}
+
+
+
+
+
+bool IsBiomeNoDownfall(EMCSBiome a_Biome)
+{
+ switch (a_Biome)
+ {
+ case biDesert:
+ case biDesertHills:
+ case biDesertM:
+ case biSavanna:
+ case biSavannaM:
+ case biSavannaPlateau:
+ case biSavannaPlateauM:
+ case biNether:
+ case biEnd:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/BiomeDef.h b/src/BiomeDef.h
new file mode 100644
index 000000000..df1e387f0
--- /dev/null
+++ b/src/BiomeDef.h
@@ -0,0 +1,107 @@
+
+// BiomeDef.h
+
+// Defines relevant information and methods related to biomes
+
+
+
+
+
+#pragma once
+
+
+
+
+
+// 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
+*/
+enum EMCSBiome
+{
+ biOcean = 0,
+ biPlains = 1,
+ biDesert = 2,
+ biExtremeHills = 3,
+ biForest = 4,
+ biTaiga = 5,
+ biSwampland = 6,
+ biRiver = 7,
+ biHell = 8, // same as Nether
+ biNether = 8,
+ biSky = 9, // same as biEnd
+ biEnd = 9,
+ biFrozenOcean = 10,
+ biFrozenRiver = 11,
+ biIcePlains = 12,
+ biTundra = 12, // same as Ice Plains
+ biIceMountains = 13,
+ biMushroomIsland = 14,
+ biMushroomShore = 15,
+ biBeach = 16,
+ biDesertHills = 17,
+ biForestHills = 18,
+ biTaigaHills = 19,
+ biExtremeHillsEdge = 20,
+ biJungle = 21,
+ biJungleHills = 22,
+
+ // Release 1.7 biomes:
+ biJungleEdge = 23,
+ biDeepOcean = 24,
+ biStoneBeach = 25,
+ biColdBeach = 26,
+ biBirchForest = 27,
+ biBirchForestHills = 28,
+ biRoofedForest = 29,
+ biColdTaiga = 30,
+ biColdTaigaHills = 31,
+ biMegaTaiga = 32,
+ biMegaTaigaHills = 33,
+ biExtremeHillsPlus = 34,
+ biSavanna = 35,
+ biSavannaPlateau = 36,
+ biMesa = 37,
+ biMesaPlateauF = 38,
+ biMesaPlateau = 39,
+
+ // Automatically capture the maximum consecutive biome value into biMaxBiome:
+ biNumBiomes, // True number of biomes, since they are zero-based
+ biMaxBiome = biNumBiomes - 1, // The maximum biome value
+
+ // Add this number to the biomes to get the variant
+ biVariant = 128,
+
+ // Release 1.7 biome variants:
+ biSunflowerPlains = 129,
+ biDesertM = 130,
+ biExtremeHillsM = 131,
+ biFlowerForest = 132,
+ biTaigaM = 133,
+ biSwamplandM = 134,
+ biIcePlainsSpikes = 140,
+ biJungleM = 149,
+ biJungleEdgeM = 151,
+ biBirchForestM = 155,
+ biBirchForestHillsM = 156,
+ biRoofedForestM = 157,
+ biColdTaigaM = 158,
+ biMegaSpruceTaiga = 160,
+ biMegaSpruceTaigaHills = 161,
+ biExtremeHillsPlusM = 162,
+ biSavannaM = 163,
+ biSavannaPlateauM = 164,
+ biMesaBryce = 165,
+ biMesaPlateauFM = 166,
+ biMesaPlateauM = 167,
+} ;
+
+/// Translates a biome string to biome enum. Takes either a number or a biome alias (built-in). Returns -1 on failure.
+extern EMCSBiome StringToBiome(const AString & a_BiomeString);
+
+/// Returns true if the biome has no downfall - deserts and savannas
+extern bool IsBiomeNoDownfall(EMCSBiome a_Biome);
+
+
+// tolua_end
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index 1148908c6..910661f60 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -28,6 +28,8 @@ template<typename Combinator> void InternalMergeBlocks(
Combinator a_Combinator
)
{
+ UNUSED(a_SrcSizeY);
+ UNUSED(a_DstSizeY);
for (int y = 0; y < a_SizeY; y++)
{
int SrcBaseY = (y + a_SrcOffY) * a_SrcSizeX * a_SrcSizeZ;
@@ -826,7 +828,7 @@ void cBlockArea::RelLine(int a_RelX1, int a_RelY1, int a_RelZ1, int a_RelX2, int
int yd = dy - dx / 2;
int zd = dz - dx / 2;
- while (true)
+ for (;;)
{
RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight);
@@ -858,7 +860,7 @@ void cBlockArea::RelLine(int a_RelX1, int a_RelY1, int a_RelZ1, int a_RelX2, int
int xd = dx - dy / 2;
int zd = dz - dy / 2;
- while (true)
+ for (;;)
{
RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight);
@@ -892,7 +894,7 @@ void cBlockArea::RelLine(int a_RelX1, int a_RelY1, int a_RelZ1, int a_RelX2, int
int xd = dx - dz / 2;
int yd = dy - dz / 2;
- while (true)
+ for (;;)
{
RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight);
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index 0d358b556..7c6688f8d 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -87,7 +87,11 @@ public:
virtual void SendTo(cClientHandle & a_Client) = 0;
/// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing.
- virtual bool Tick(float a_Dt, cChunk & a_Chunk) { return false; }
+ virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */)
+ {
+ UNUSED(a_Dt);
+ return false;
+ }
protected:
/// Position in absolute block coordinates
diff --git a/src/BlockEntities/BlockEntityWithItems.h b/src/BlockEntities/BlockEntityWithItems.h
index f35412e03..bf6289a2f 100644
--- a/src/BlockEntities/BlockEntityWithItems.h
+++ b/src/BlockEntities/BlockEntityWithItems.h
@@ -73,6 +73,7 @@ protected:
// cItemGrid::cListener overrides:
virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
{
+ UNUSED(a_SlotNum);
ASSERT(a_Grid == &m_Contents);
if (m_World != NULL)
{
diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp
index b1409f5cc..f15553968 100644
--- a/src/BlockEntities/FurnaceEntity.cpp
+++ b/src/BlockEntities/FurnaceEntity.cpp
@@ -70,8 +70,8 @@ void cFurnaceEntity::UsedBy(cPlayer * a_Player)
if (a_Player->GetWindow() != Window)
{
a_Player->OpenWindow(Window);
- BroadcastProgress(PROGRESSBAR_FUEL, m_LastProgressFuel);
- BroadcastProgress(PROGRESSBAR_SMELTING, m_LastProgressCook);
+ BroadcastProgress(PROGRESSBAR_FUEL, (short)m_LastProgressFuel);
+ BroadcastProgress(PROGRESSBAR_SMELTING, (short)m_LastProgressCook);
}
}
}
@@ -445,14 +445,14 @@ void cFurnaceEntity::UpdateProgressBars(void)
int CurFuel = (m_FuelBurnTime > 0) ? (200 - 200 * m_TimeBurned / m_FuelBurnTime) : 0;
if ((CurFuel / 8) != (m_LastProgressFuel / 8))
{
- BroadcastProgress(PROGRESSBAR_FUEL, CurFuel);
+ BroadcastProgress(PROGRESSBAR_FUEL, (short)CurFuel);
m_LastProgressFuel = CurFuel;
}
int CurCook = (m_NeedCookTime > 0) ? (200 * m_TimeCooked / m_NeedCookTime) : 0;
if ((CurCook / 8) != (m_LastProgressCook / 8))
{
- BroadcastProgress(PROGRESSBAR_SMELTING, CurCook);
+ BroadcastProgress(PROGRESSBAR_SMELTING, (short)CurCook);
m_LastProgressCook = CurCook;
}
}
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 8b695d61a..b08187300 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -95,7 +95,7 @@ public:
// tolua_end
- void SetBurnTimes(int a_FuelBurnTime, int a_TimeBurned) {m_FuelBurnTime = a_FuelBurnTime; m_TimeBurned = 0; }
+ void SetBurnTimes(int a_FuelBurnTime, int a_TimeBurned) {m_FuelBurnTime = a_FuelBurnTime; m_TimeBurned = a_TimeBurned; }
void SetCookTimes(int a_NeedCookTime, int a_TimeCooked) {m_NeedCookTime = a_NeedCookTime; m_TimeCooked = a_TimeCooked; }
protected:
diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp
index 0aca3209f..eac59e74d 100644
--- a/src/BlockEntities/HopperEntity.cpp
+++ b/src/BlockEntities/HopperEntity.cpp
@@ -488,7 +488,6 @@ bool cHopperEntity::MoveItemsToFurnace(cChunk & a_Chunk, int a_BlockX, int a_Blo
// Feed the fuel slot of the furnace
return MoveItemsToSlot(*Furnace, cFurnaceEntity::fsFuel);
}
- return false;
}
diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h
index fcafdc479..996de965b 100644
--- a/src/BlockEntities/JukeboxEntity.h
+++ b/src/BlockEntities/JukeboxEntity.h
@@ -45,7 +45,7 @@ public:
// tolua_end
virtual void UsedBy(cPlayer * a_Player) override;
- virtual void SendTo(cClientHandle & a_Client) override { };
+ virtual void SendTo(cClientHandle &) override { };
private:
int m_Record;
diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h
index e2d088f44..cf78aeac6 100644
--- a/src/BlockEntities/NoteEntity.h
+++ b/src/BlockEntities/NoteEntity.h
@@ -52,7 +52,7 @@ public:
// tolua_end
virtual void UsedBy(cPlayer * a_Player) override;
- virtual void SendTo(cClientHandle & a_Client) override { };
+ virtual void SendTo(cClientHandle &) override { };
private:
char m_Pitch;
diff --git a/src/BlockID.cpp b/src/BlockID.cpp
index 05d4c6595..b609af571 100644
--- a/src/BlockID.cpp
+++ b/src/BlockID.cpp
@@ -267,106 +267,6 @@ AString ItemToFullString(const cItem & a_Item)
-EMCSBiome StringToBiome(const AString & a_BiomeString)
-{
- // If it is a number, return it:
- int res = atoi(a_BiomeString.c_str());
- if ((res != 0) || (a_BiomeString.compare("0") == 0))
- {
- // It was a valid number
- return (EMCSBiome)res;
- }
-
- // Convert using the built-in map:
- static struct {
- EMCSBiome m_Biome;
- const char * m_String;
- } BiomeMap[] =
- {
- {biOcean, "Ocean"} ,
- {biPlains, "Plains"},
- {biDesert, "Desert"},
- {biExtremeHills, "ExtremeHills"},
- {biForest, "Forest"},
- {biTaiga, "Taiga"},
- {biSwampland, "Swampland"},
- {biRiver, "River"},
- {biNether, "Hell"},
- {biNether, "Nether"},
- {biEnd, "Sky"},
- {biEnd, "End"},
- {biFrozenOcean, "FrozenOcean"},
- {biFrozenRiver, "FrozenRiver"},
- {biIcePlains, "IcePlains"},
- {biIcePlains, "Tundra"},
- {biIceMountains, "IceMountains"},
- {biMushroomIsland, "MushroomIsland"},
- {biMushroomShore, "MushroomShore"},
- {biBeach, "Beach"},
- {biDesertHills, "DesertHills"},
- {biForestHills, "ForestHills"},
- {biTaigaHills, "TaigaHills"},
- {biExtremeHillsEdge, "ExtremeHillsEdge"},
- {biJungle, "Jungle"},
- {biJungleHills, "JungleHills"},
-
- // Release 1.7 biomes:
- {biJungleEdge, "JungleEdge"},
- {biDeepOcean, "DeepOcean"},
- {biStoneBeach, "StoneBeach"},
- {biColdBeach, "ColdBeach"},
- {biBirchForest, "BirchForest"},
- {biBirchForestHills, "BirchForestHills"},
- {biRoofedForest, "RoofedForest"},
- {biColdTaiga, "ColdTaiga"},
- {biColdTaigaHills, "ColdTaigaHills"},
- {biMegaTaiga, "MegaTaiga"},
- {biMegaTaigaHills, "MegaTaigaHills"},
- {biExtremeHillsPlus, "ExtremeHillsPlus"},
- {biSavanna, "Savanna"},
- {biSavannaPlateau, "SavannaPlateau"},
- {biMesa, "Mesa"},
- {biMesaPlateauF, "MesaPlateauF"},
- {biMesaPlateau, "MesaPlateau"},
-
- // Release 1.7 variants:
- {biSunflowerPlains, "SunflowerPlains"},
- {biDesertM, "DesertM"},
- {biExtremeHillsM, "ExtremeHillsM"},
- {biFlowerForest, "FlowerForest"},
- {biTaigaM, "TaigaM"},
- {biSwamplandM, "SwamplandM"},
- {biIcePlainsSpikes, "IcePlainsSpikes"},
- {biJungleM, "JungleM"},
- {biJungleEdgeM, "JungleEdgeM"},
- {biBirchForestM, "BirchForestM"},
- {biBirchForestHillsM, "BirchForestHillsM"},
- {biRoofedForestM, "RoofedForestM"},
- {biColdTaigaM, "ColdTaigaM"},
- {biMegaSpruceTaiga, "MegaSpruceTaiga"},
- {biMegaSpruceTaigaHills, "MegaSpruceTaigaHills"},
- {biExtremeHillsPlusM, "ExtremeHillsPlusM"},
- {biSavannaM, "SavannaM"},
- {biSavannaPlateauM, "SavannaPlateauM"},
- {biMesaBryce, "MesaBryce"},
- {biMesaPlateauFM, "MesaPlateauFM"},
- {biMesaPlateauM, "MesaPlateauM"},
- } ;
-
- for (size_t i = 0; i < ARRAYCOUNT(BiomeMap); i++)
- {
- if (NoCaseCompare(BiomeMap[i].m_String, a_BiomeString) == 0)
- {
- return BiomeMap[i].m_Biome;
- }
- } // for i - BiomeMap[]
- return (EMCSBiome)-1;
-}
-
-
-
-
-
int StringToMobType(const AString & a_MobString)
{
static struct {
diff --git a/src/BlockID.h b/src/BlockID.h
index 288719ccf..899336fa6 100644
--- a/src/BlockID.h
+++ b/src/BlockID.h
@@ -876,9 +876,6 @@ extern AString ItemTypeToString(short a_ItemType);
/// Translates a full item into a fully-specified string (including meta and count). If the ItemType is not recognized, the ItemType number is output into the string.
extern AString ItemToFullString(const cItem & a_Item);
-/// Translates a biome string to biome enum. Takes either a number or a biome alias (built-in). Returns -1 on failure.
-extern EMCSBiome StringToBiome(const AString & a_BiomeString);
-
/// Translates a mob string ("ocelot") to mobtype (E_ENTITY_TYPE_OCELOT)
extern int StringToMobType(const AString & a_MobString);
diff --git a/src/BlockTracer.h b/src/BlockTracer.h
index d0a34811d..40d80da1a 100644
--- a/src/BlockTracer.h
+++ b/src/BlockTracer.h
@@ -36,7 +36,14 @@ public:
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
When this callback returns true, the tracing is aborted.
*/
- virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) { return false; }
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace)
+ {
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ UNUSED(a_EntryFace);
+ return false;
+ }
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
The coords specify the exact point at which the path exited the world.
@@ -44,7 +51,13 @@ public:
Note that some paths can go out of the world and come back again (parabola),
in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls
*/
- virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; }
+ virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
+ {
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ return false;
+ }
/** Called when the path goes into the world, from either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
The coords specify the exact point at which the path entered the world.
@@ -52,7 +65,13 @@ public:
Note that some paths can go out of the world and come back again (parabola),
in such a case this callback is followed by further OnNextBlock() calls
*/
- virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; }
+ virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
+ {
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ return false;
+ }
/** Called when the path is sure not to hit any more blocks.
Note that for some shapes this might never happen (line with constant Y)
diff --git a/src/Blocks/BlockGlowstone.h b/src/Blocks/BlockGlowstone.h
index 5f0d95dee..6c198efc4 100644
--- a/src/Blocks/BlockGlowstone.h
+++ b/src/Blocks/BlockGlowstone.h
@@ -20,8 +20,8 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
- // TODO: More drops?
- a_Pickups.push_back(cItem(E_ITEM_GLOWSTONE_DUST, 1, 0));
+ MTRand r1;
+ a_Pickups.push_back(cItem(E_ITEM_GLOWSTONE_DUST, (char)(2 + r1.randInt(2)), 0));
}
} ;
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index 107d36476..a732aa797 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -99,7 +99,11 @@ public:
virtual bool DoesIgnoreBuildCollision(void);
/// <summary>Similar to DoesIgnoreBuildCollision(void), but is used for cases where block meta/player item-in-hand is needed to determine collision (thin snow)</summary>
- virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) { return DoesIgnoreBuildCollision(); }
+ virtual bool DoesIgnoreBuildCollision(cPlayer *, NIBBLETYPE a_Meta)
+ {
+ UNUSED(a_Meta);
+ return DoesIgnoreBuildCollision();
+ }
/// <summary>Returns if this block drops if it gets destroyed by an unsuitable situation. Default: true</summary>
virtual bool DoesDropOnUnsuitable(void);
diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp
index 64c03d0d3..e06f63a0e 100644
--- a/src/ByteBuffer.cpp
+++ b/src/ByteBuffer.cpp
@@ -773,7 +773,7 @@ void cByteBuffer::ReadAll(AString & a_Data)
-bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, int a_NumBytes)
+bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes)
{
if (!a_Dst.CanWriteBytes(a_NumBytes) || !CanReadBytes(a_NumBytes))
{
@@ -781,9 +781,10 @@ bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, int a_NumBytes)
return false;
}
char buf[1024];
- while (a_NumBytes > 0)
+ // > 0 without generating warnings about unsigned comparisons where size_t is unsigned
+ while (a_NumBytes != 0)
{
- int num = (a_NumBytes > sizeof(buf)) ? sizeof(buf) : a_NumBytes;
+ size_t num = (a_NumBytes > sizeof(buf)) ? sizeof(buf) : a_NumBytes;
VERIFY(ReadBuf(buf, num));
VERIFY(a_Dst.Write(buf, num));
a_NumBytes -= num;
diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h
index 06c846fa9..cbce119b1 100644
--- a/src/ByteBuffer.h
+++ b/src/ByteBuffer.h
@@ -110,7 +110,7 @@ public:
void ReadAll(AString & a_Data);
/// Reads the specified number of bytes and writes it into the destinatio bytebuffer. Returns true on success.
- bool ReadToByteBuffer(cByteBuffer & a_Dst, int a_NumBytes);
+ bool ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes);
/// Removes the bytes that have been read from the ringbuffer
void CommitRead(void);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 88e469b74..853138769 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,7 +14,7 @@ set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities)
-if (NOT WIN32)
+if (NOT MSVC)
foreach(folder ${FOLDERS})
add_subdirectory(${folder})
endforeach(folder)
@@ -62,18 +62,25 @@ else ()
endif()
-if (UNIX)
- set(EXECUTABLE ../MCServer/MCServer)
-else ()
- set(EXECUTABLE MCServer)
-endif ()
-
+set(EXECUTABLE MCServer)
add_executable(${EXECUTABLE} ${SOURCE})
+set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
+
+if (MSVC)
+ # MSVC generator adds a "Debug" or "Release" postfixes to the EXECUTABLE_OUTPUT_PATH, we need to cancel them:
+ SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES PREFIX "../")
+ SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES IMPORT_PREFIX "../")
+endif()
+
+
+# Make the debug executable have a "_debug" suffix
+SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES DEBUG_POSTFIX "_debug")
+
# Precompiled headers (2nd part)
-if (WIN32)
+if (MSVC)
SET_TARGET_PROPERTIES(
${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/Yu\"Globals.h\""
OBJECT_DEPENDS "$(IntDir)/$(TargetName.pch)"
@@ -81,7 +88,7 @@ if (WIN32)
endif ()
-if (NOT WIN32)
+if (NOT MSVC)
target_link_libraries(${EXECUTABLE} OSSupport HTTPServer Bindings Items Blocks)
target_link_libraries(${EXECUTABLE} Protocol Generating WorldStorage)
target_link_libraries(${EXECUTABLE} Mobs Entities Simulator UI BlockEntities)
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index c446db9a6..fb26e983d 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -527,9 +527,11 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner)
// MG TODO : check that "Level" really means Y
+ /*
NIBBLETYPE SkyLight = 0;
NIBBLETYPE BlockLight = 0;
+ */
if (IsLightValid())
{
@@ -2324,8 +2326,8 @@ BLOCKTYPE cChunk::GetBlock(int a_BlockIdx) const
void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
{
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
- a_BlockType = cChunkDef::GetBlock (m_BlockTypes, a_RelX, a_RelY, a_RelZ);
- a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ);
+ a_BlockType = cChunkDef::GetBlock (m_BlockTypes, Idx);
+ a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Idx);
}
@@ -2898,10 +2900,6 @@ NIBBLETYPE cChunk::GetTimeAlteredLight(NIBBLETYPE a_Skylight) const
-#if !C_CHUNK_USE_INLINE
-# include "cChunk.inl.h"
-#endif
-
diff --git a/src/Chunk.h b/src/Chunk.h
index 05a96d419..f0a50c3c4 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -12,19 +12,6 @@
-#define C_CHUNK_USE_INLINE 1
-
-// Do not touch
-#if C_CHUNK_USE_INLINE
- #define __C_CHUNK_INLINE__ inline
-#else
- #define __C_CHUNK_INLINE__
-#endif
-
-
-
-
-
namespace Json
{
class Value;
@@ -436,8 +423,6 @@ private:
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
void AddBlockEntity (cBlockEntity * a_BlockEntity);
- void SpreadLightOfBlock(NIBBLETYPE * a_LightBuffer, int a_X, int a_Y, int a_Z, char a_Falloff);
-
/// Creates a block entity for each block that needs a block entity and doesn't have one in the list
void CreateBlockEntities(void);
@@ -482,11 +467,3 @@ typedef std::list<cChunkPtr> cChunkPtrList;
-
-#if C_CHUNK_USE_INLINE
- #include "Chunk.inl.h"
-#endif
-
-
-
-
diff --git a/src/Chunk.inl.h b/src/Chunk.inl.h
deleted file mode 100644
index fb9c4dad1..000000000
--- a/src/Chunk.inl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#ifndef __C_CHUNK_INL_H__
-#define __C_CHUNK_INL_H__
-
-#ifndef MAX
-# define MAX(a,b) (((a)>(b))?(a):(b))
-#endif
-
-
-
-
-
-__C_CHUNK_INLINE__
-void cChunk::SpreadLightOfBlock(NIBBLETYPE * a_LightBuffer, int a_X, int a_Y, int a_Z, char a_Falloff)
-{
- unsigned char CurrentLight = cChunkDef::GetNibble( a_LightBuffer, a_X, a_Y, a_Z );
- cChunkDef::SetNibble( a_LightBuffer, a_X-1, a_Y, a_Z, MAX(cChunkDef::GetNibble( a_LightBuffer, a_X-1, a_Y, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- cChunkDef::SetNibble( a_LightBuffer, a_X+1, a_Y, a_Z, MAX(cChunkDef::GetNibble( a_LightBuffer, a_X+1, a_Y, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- cChunkDef::SetNibble( a_LightBuffer, a_X, a_Y-1, a_Z, MAX(cChunkDef::GetNibble( a_LightBuffer, a_X, a_Y-1, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- cChunkDef::SetNibble( a_LightBuffer, a_X, a_Y+1, a_Z, MAX(cChunkDef::GetNibble( a_LightBuffer, a_X, a_Y+1, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- cChunkDef::SetNibble( a_LightBuffer, a_X, a_Y, a_Z-1, MAX(cChunkDef::GetNibble( a_LightBuffer, a_X, a_Y, a_Z-1 ), MAX(0,CurrentLight-a_Falloff) ) );
- cChunkDef::SetNibble( a_LightBuffer, a_X, a_Y, a_Z+1, MAX(cChunkDef::GetNibble( a_LightBuffer, a_X, a_Y, a_Z+1 ), MAX(0,CurrentLight-a_Falloff) ) );
- MarkDirty();
-}
-
-
-
-
-
-#endif
-
-
-
-
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index 8c37e7907..edeb7c0a0 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -10,6 +10,7 @@
#pragma once
#include "Vector3i.h"
+#include "BiomeDef.h"
@@ -57,97 +58,6 @@ typedef unsigned char HEIGHTTYPE;
-
-
-// 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
-*/
-enum EMCSBiome
-{
- biOcean = 0,
- biPlains = 1,
- biDesert = 2,
- biExtremeHills = 3,
- biForest = 4,
- biTaiga = 5,
- biSwampland = 6,
- biRiver = 7,
- biHell = 8, // same as Nether
- biNether = 8,
- biSky = 9, // same as biEnd
- biEnd = 9,
- biFrozenOcean = 10,
- biFrozenRiver = 11,
- biIcePlains = 12,
- biTundra = 12, // same as Ice Plains
- biIceMountains = 13,
- biMushroomIsland = 14,
- biMushroomShore = 15,
- biBeach = 16,
- biDesertHills = 17,
- biForestHills = 18,
- biTaigaHills = 19,
- biExtremeHillsEdge = 20,
- biJungle = 21,
- biJungleHills = 22,
-
- // Release 1.7 biomes:
- biJungleEdge = 23,
- biDeepOcean = 24,
- biStoneBeach = 25,
- biColdBeach = 26,
- biBirchForest = 27,
- biBirchForestHills = 28,
- biRoofedForest = 29,
- biColdTaiga = 30,
- biColdTaigaHills = 31,
- biMegaTaiga = 32,
- biMegaTaigaHills = 33,
- biExtremeHillsPlus = 34,
- biSavanna = 35,
- biSavannaPlateau = 36,
- biMesa = 37,
- biMesaPlateauF = 38,
- biMesaPlateau = 39,
-
- // Automatically capture the maximum consecutive biome value into biMaxBiome:
- biNumBiomes, // True number of biomes, since they are zero-based
- biMaxBiome = biNumBiomes - 1, // The maximum biome value
-
- // Add this number to the biomes to get the variant
- biVariant = 128,
-
- // Release 1.7 biome variants:
- biSunflowerPlains = 129,
- biDesertM = 130,
- biExtremeHillsM = 131,
- biFlowerForest = 132,
- biTaigaM = 133,
- biSwamplandM = 134,
- biIcePlainsSpikes = 140,
- biJungleM = 149,
- biJungleEdgeM = 151,
- biBirchForestM = 155,
- biBirchForestHillsM = 156,
- biRoofedForestM = 157,
- biColdTaigaM = 158,
- biMegaSpruceTaiga = 160,
- biMegaSpruceTaigaHills = 161,
- biExtremeHillsPlusM = 162,
- biSavannaM = 163,
- biSavannaPlateauM = 164,
- biMesaBryce = 165,
- biMesaPlateauFM = 166,
- biMesaPlateauM = 167,
-} ;
-
-// tolua_end
-
-
-
-
/// Constants used throughout the code, useful typedefs and utility functions
class cChunkDef
{
@@ -182,6 +92,7 @@ public:
/// Converts absolute block coords into relative (chunk + block) coords:
inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ )
{
+ UNUSED(a_Y);
BlockToChunk(a_X, a_Z, a_ChunkX, a_ChunkZ);
a_X = a_X - a_ChunkX * Width;
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 86fbceff7..e14090b18 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -991,7 +991,7 @@ bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
int cChunkMap::GetHeight(int a_BlockX, int a_BlockZ)
{
- while (true)
+ for (;;)
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ, BlockY = 0;
diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp
index fe3ee9b42..2425adf18 100644
--- a/src/ChunkSender.cpp
+++ b/src/ChunkSender.cpp
@@ -264,7 +264,7 @@ void cChunkSender::BlockEntity(cBlockEntity * a_Entity)
-void cChunkSender::Entity(cEntity * a_Entity)
+void cChunkSender::Entity(cEntity *)
{
// Nothing needed yet, perhaps in the future when we save entities into chunks we'd like to send them upon load, too ;)
}
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 99df47bfb..9348a1825 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -543,6 +543,15 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
+void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString & a_Message)
+{
+ cPluginManager::Get()->CallHookPluginMessage(*this, a_Channel, a_Message);
+}
+
+
+
+
+
void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status)
{
LOGD("HandleLeftClick: {%i, %i, %i}; Face: %i; Stat: %i",
@@ -1409,6 +1418,7 @@ void cClientHandle::SendData(const char * a_Data, int a_Size)
void cClientHandle::MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket)
{
+ UNUSED(a_World);
ASSERT(m_Player != NULL);
if (a_SendRespawnPacket)
@@ -1968,6 +1978,15 @@ void cClientHandle::SendPlayerSpawn(const cPlayer & a_Player)
+void cClientHandle::SendPluginMessage(const AString & a_Channel, const AString & a_Message)
+{
+ m_Protocol->SendPluginMessage(a_Channel, a_Message);
+}
+
+
+
+
+
void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
{
m_Protocol->SendRemoveEntityEffect(a_Entity, a_EffectID);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 26d5e74b7..297d62d57 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -120,6 +120,7 @@ public:
void SendPlayerMoveLook (void);
void SendPlayerPosition (void);
void SendPlayerSpawn (const cPlayer & a_Player);
+ void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
void SendRespawn (void);
void SendExperience (void);
@@ -178,6 +179,7 @@ public:
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay)
void HandlePlayerPos (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround);
+ void HandlePluginMessage (const AString & a_Channel, const AString & a_Message);
void HandleRespawn (void);
void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem);
void HandleSlotSelected (short a_SlotNum);
diff --git a/src/CommandOutput.h b/src/CommandOutput.h
index bdf675238..3763d625f 100644
--- a/src/CommandOutput.h
+++ b/src/CommandOutput.h
@@ -38,6 +38,7 @@ class cNullCommandOutputCallback :
virtual void Out(const AString & a_Text) override
{
// Do nothing
+ UNUSED(a_Text);
}
} ;
diff --git a/src/Defines.h b/src/Defines.h
index 534802d55..c75effa44 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -563,34 +563,6 @@ namespace ItemCategory
}
}
-
-
-
-
-/// Returns true if the biome has no downfall - deserts and savannas
-inline bool IsBiomeNoDownfall(EMCSBiome a_Biome)
-{
- switch (a_Biome)
- {
- case biDesert:
- case biDesertHills:
- case biDesertM:
- case biSavanna:
- case biSavannaM:
- case biSavannaPlateau:
- case biSavannaPlateauM:
- case biNether:
- case biEnd:
- {
- return true;
- }
- default:
- {
- return false;
- }
- }
-}
-
// tolua_end
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 9cb36eb14..2ba1b303d 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -351,10 +351,14 @@ public:
// tolua_end
/// Called when the specified player right-clicks this entity
- virtual void OnRightClicked(cPlayer & a_Player) {};
+ virtual void OnRightClicked(cPlayer &) {};
/// Returns the list of drops for this pawn when it is killed. May check a_Killer for special handling (sword of looting etc.). Called from KilledBy().
- virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) {}
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL)
+ {
+ UNUSED(a_Drops);
+ UNUSED(a_Killer);
+ }
protected:
static cCriticalSection m_CSCount;
@@ -420,11 +424,13 @@ protected:
void Dereference( cEntity*& a_EntityPtr );
private:
- // Measured in degrees (MAX 360°)
+ // Measured in degrees, [-180, +180)
double m_HeadYaw;
+
// Measured in meter/second (m/s)
Vector3d m_Speed;
- // Measured in degrees (MAX 360°)
+
+ // Measured in degrees, [-180, +180)
Vector3d m_Rot;
/// Position of the entity's XZ center and Y bottom
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 67d5a47ef..bc92790aa 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -908,8 +908,8 @@ bool cPlayer::IsGameModeSurvival(void) const
bool cPlayer::IsGameModeAdventure(void) const
{
- return (m_GameMode == gmCreative) || // Either the player is explicitly in Adventure
- ((m_GameMode == gmNotSet) && m_World->IsGameModeCreative()); // or they inherit from the world and the world is Adventure
+ return (m_GameMode == gmAdventure) || // Either the player is explicitly in Adventure
+ ((m_GameMode == gmNotSet) && m_World->IsGameModeAdventure()); // or they inherit from the world and the world is Adventure
}
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 66f1c07a7..f9ce950ba 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -45,7 +45,7 @@ public:
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
- virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override { };
+ virtual void HandlePhysics(float a_Dt, cChunk &) override { UNUSED(a_Dt); };
/// Returns the curently equipped weapon; empty item if none
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
@@ -114,7 +114,7 @@ public:
double GetEyeHeight(void) const; // tolua_export
Vector3d GetEyePosition(void) const; // tolua_export
inline bool IsOnGround(void) const {return m_bTouchGround; } // tolua_export
- inline const double GetStance(void) const { return GetPosY() + 1.62; } // tolua_export // TODO: Proper stance when crouching etc.
+ inline double GetStance(void) const { return GetPosY() + 1.62; } // tolua_export // TODO: Proper stance when crouching etc.
inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
inline const cInventory & GetInventory(void) const { return m_Inventory; }
diff --git a/src/Entities/ProjectileEntity.h b/src/Entities/ProjectileEntity.h
index 959e81ae5..4721409ee 100644
--- a/src/Entities/ProjectileEntity.h
+++ b/src/Entities/ProjectileEntity.h
@@ -52,7 +52,11 @@ public:
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace);
/// Called by the physics blocktracer when the entity hits another entity
- virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) {}
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+ {
+ UNUSED(a_EntityHit);
+ UNUSED(a_HitPos);
+ }
/// Called by Chunk when the projectile is eligible for player collection
virtual void CollectedBy(cPlayer * a_Dest);
diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp
index df45bb4c2..2571e6b77 100644
--- a/src/Generating/Caves.cpp
+++ b/src/Generating/Caves.cpp
@@ -285,7 +285,7 @@ bool cCaveTunnel::RefineDefPoints(const cCaveDefPoints & a_Src, cCaveDefPoints &
void cCaveTunnel::Smooth(void)
{
cCaveDefPoints Pts;
- while (true)
+ for (;;)
{
if (!RefineDefPoints(m_Points, Pts))
{
@@ -331,7 +331,7 @@ void cCaveTunnel::FinishLinear(void)
int yd = dy - dx / 2;
int zd = dz - dx / 2;
- while (true)
+ for (;;)
{
m_Points.push_back(cCaveDefPoint(PrevX, PrevY, PrevZ, R));
@@ -363,7 +363,7 @@ void cCaveTunnel::FinishLinear(void)
int xd = dx - dy / 2;
int zd = dz - dy / 2;
- while (true)
+ for (;;)
{
m_Points.push_back(cCaveDefPoint(PrevX, PrevY, PrevZ, R));
@@ -397,7 +397,7 @@ void cCaveTunnel::FinishLinear(void)
int xd = dx - dz / 2;
int yd = dy - dz / 2;
- while (true)
+ for (;;)
{
m_Points.push_back(cCaveDefPoint(PrevX, PrevY, PrevZ, R));
@@ -509,6 +509,7 @@ void cCaveTunnel::ProcessChunk(
case E_BLOCK_GRAVEL:
case E_BLOCK_SAND:
case E_BLOCK_SANDSTONE:
+ case E_BLOCK_SOULSAND:
case E_BLOCK_NETHERRACK:
case E_BLOCK_COAL_ORE:
case E_BLOCK_IRON_ORE:
diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp
index 126a896af..baa5b76b8 100644
--- a/src/Generating/ChunkGenerator.cpp
+++ b/src/Generating/ChunkGenerator.cpp
@@ -2,13 +2,11 @@
#include "Globals.h"
#include "ChunkGenerator.h"
-#include "../World.h"
#include "inifile/iniFile.h"
-#include "../Root.h"
-#include "../Bindings/PluginManager.h"
#include "ChunkDesc.h"
#include "ComposableGenerator.h"
#include "Noise3DGenerator.h"
+#include "../MersenneTwister.h"
@@ -29,8 +27,9 @@ const unsigned int QUEUE_SKIP_LIMIT = 500;
cChunkGenerator::cChunkGenerator(void) :
super("cChunkGenerator"),
- m_World(NULL),
- m_Generator(NULL)
+ m_Generator(NULL),
+ m_PluginInterface(NULL),
+ m_ChunkSink(NULL)
{
}
@@ -47,10 +46,12 @@ cChunkGenerator::~cChunkGenerator()
-bool cChunkGenerator::Start(cWorld * a_World, cIniFile & a_IniFile)
+bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile)
{
+ m_PluginInterface = &a_PluginInterface;
+ m_ChunkSink = &a_ChunkSink;
+
MTRand rnd;
- m_World = a_World;
m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", rnd.randInt());
AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable");
@@ -73,7 +74,7 @@ bool cChunkGenerator::Start(cWorld * a_World, cIniFile & a_IniFile)
return false;
}
- m_Generator->Initialize(a_World, a_IniFile);
+ m_Generator->Initialize(a_IniFile);
return super::Start();
}
@@ -237,14 +238,14 @@ void cChunkGenerator::Execute(void)
}
// Hack for regenerating chunks: if Y != 0, the chunk is considered invalid, even if it has its data set
- if ((coords.m_ChunkY == 0) && m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
+ if ((coords.m_ChunkY == 0) && m_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
{
LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
// Already generated, ignore request
continue;
}
- if (SkipEnabled && !m_World->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkZ))
+ if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkZ))
{
LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
continue;
@@ -253,9 +254,6 @@ void cChunkGenerator::Execute(void)
LOGD("Generating chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
DoGenerate(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
- // Save the chunk right after generating, so that we don't have to generate it again on next run
- m_World->GetStorage().QueueSaveChunk(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
-
NumChunksGenerated++;
} // while (!bStop)
}
@@ -265,27 +263,20 @@ void cChunkGenerator::Execute(void)
void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
+ ASSERT(m_PluginInterface != NULL);
+ ASSERT(m_ChunkSink != NULL);
+
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
- cRoot::Get()->GetPluginManager()->CallHookChunkGenerating(m_World, a_ChunkX, a_ChunkZ, &ChunkDesc);
+ m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
- cRoot::Get()->GetPluginManager()->CallHookChunkGenerated(m_World, a_ChunkX, a_ChunkZ, &ChunkDesc);
+ m_PluginInterface->CallHookChunkGenerated(ChunkDesc);
#ifdef _DEBUG
// Verify that the generator has produced valid data:
ChunkDesc.VerifyHeightmap();
#endif
- cChunkDef::BlockNibbles BlockMetas;
- ChunkDesc.CompressBlockMetas(BlockMetas);
-
- m_World->SetChunkData(
- a_ChunkX, a_ChunkZ,
- ChunkDesc.GetBlockTypes(), BlockMetas,
- NULL, NULL, // We don't have lighting, chunk will be lighted when needed
- &ChunkDesc.GetHeightMap(), &ChunkDesc.GetBiomeMap(),
- ChunkDesc.GetEntities(), ChunkDesc.GetBlockEntities(),
- true
- );
+ m_ChunkSink->OnChunkGenerated(ChunkDesc);
}
@@ -304,9 +295,8 @@ cChunkGenerator::cGenerator::cGenerator(cChunkGenerator & a_ChunkGenerator) :
-void cChunkGenerator::cGenerator::Initialize(cWorld * a_World, cIniFile & a_IniFile)
+void cChunkGenerator::cGenerator::Initialize(cIniFile & a_IniFile)
{
- m_World = a_World;
UNUSED(a_IniFile);
}
@@ -319,7 +309,7 @@ EMCSBiome cChunkGenerator::cGenerator::GetBiomeAt(int a_BlockX, int a_BlockZ)
cChunkDef::BiomeMap Biomes;
int Y = 0;
int ChunkX, ChunkZ;
- cWorld::AbsoluteToRelative(a_BlockX, Y, a_BlockZ, ChunkX, Y, ChunkZ);
+ cChunkDef::AbsoluteToRelative(a_BlockX, Y, a_BlockZ, ChunkX, ChunkZ);
GenerateBiomes(ChunkX, ChunkZ, Biomes);
return cChunkDef::GetBiome(Biomes, a_BlockX, a_BlockZ);
}
diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h
index 2d3bb8082..9b2d9eb3c 100644
--- a/src/Generating/ChunkGenerator.h
+++ b/src/Generating/ChunkGenerator.h
@@ -26,7 +26,6 @@ If the generator queue is overloaded, the generator skips chunks with no clients
// fwd:
-class cWorld;
class cIniFile;
class cChunkDesc;
@@ -40,7 +39,7 @@ class cChunkGenerator :
typedef cIsThread super;
public:
- /// The interface that a class has to implement to become a generator
+ /** The interface that a class has to implement to become a generator */
class cGenerator
{
public:
@@ -48,7 +47,7 @@ public:
virtual ~cGenerator() {} ; // Force a virtual destructor
/// Called to initialize the generator on server startup.
- virtual void Initialize(cWorld * a_World, cIniFile & a_IniFile);
+ virtual void Initialize(cIniFile & a_IniFile);
/// Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading.
virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0;
@@ -61,14 +60,59 @@ public:
protected:
cChunkGenerator & m_ChunkGenerator;
- cWorld * m_World;
+ } ;
+
+
+ /** The interface through which the plugins are called for their OnChunkGenerating / OnChunkGenerated hooks. */
+ class cPluginInterface
+ {
+ public:
+ // Force a virtual destructor
+ virtual ~cPluginInterface() {}
+
+ /** Called when the chunk is about to be generated.
+ The generator may be partly or fully overriden by the implementation
+ */
+ virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) = 0;
+
+ /** Called after the chunk is generated, before it is handed to the chunk sink.
+ a_ChunkDesc contains the generated chunk data. Implementation may modify this data.
+ */
+ virtual void CallHookChunkGenerated(cChunkDesc & a_ChunkDesc) = 0;
+ } ;
+
+
+ /** The interface through which the generated chunks are handed to the cWorld or whoever created us. */
+ class cChunkSink
+ {
+ public:
+ // Force a virtual destructor
+ virtual ~cChunkSink() {}
+
+ /** Called after the chunk has been generated
+ The interface may store the chunk, send it over network, whatever.
+ The chunk is not expected to be modified, but the generator will survive if the implementation
+ changes the data within. All changes are ignored, though.
+ */
+ virtual void OnChunkGenerated(cChunkDesc & a_ChunkDesc) = 0;
+
+ /** Called just before the chunk generation is started,
+ to verify that it hasn't been generated in the meantime.
+ If this callback returns true, the chunk is not generated.
+ */
+ virtual bool IsChunkValid(int a_ChunkX, int a_ChunkZ) = 0;
+
+ /** Called when the generator is overloaded to skip chunks that are no longer needed.
+ If this callback returns false, the chunk is not generated.
+ */
+ virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
} ;
cChunkGenerator (void);
~cChunkGenerator();
- bool Start(cWorld * a_World, cIniFile & a_IniFile);
+ bool Start(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile);
void Stop(void);
/// Queues the chunk for generation; removes duplicate requests
@@ -91,8 +135,6 @@ public:
private:
- cWorld * m_World;
-
int m_Seed;
cCriticalSection m_CS;
@@ -101,6 +143,13 @@ private:
cEvent m_evtRemoved; ///< Set when an item is removed from the queue
cGenerator * m_Generator; ///< The actual generator engine used to generate chunks
+
+ /** The plugin interface that may modify the generated chunks */
+ cPluginInterface * m_PluginInterface;
+
+ /** The destination where the generated chunks are sent */
+ cChunkSink * m_ChunkSink;
+
// cIsThread override:
virtual void Execute(void) override;
diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp
index f929ddc2f..60356fe46 100644
--- a/src/Generating/CompoGen.cpp
+++ b/src/Generating/CompoGen.cpp
@@ -589,7 +589,22 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc)
for (int y = 0; y < SEGMENT_HEIGHT; y++)
{
int Val = Lo + (Hi - Lo) * y / SEGMENT_HEIGHT;
- a_ChunkDesc.SetBlockType(x, y + Segment, z, (Val < m_Threshold) ? E_BLOCK_NETHERRACK : E_BLOCK_AIR);
+ BLOCKTYPE Block = E_BLOCK_AIR;
+ if (Val < m_Threshold) // Don't calculate if the block should be Netherrack or Soulsand when it's already decided that it's air.
+ {
+ NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(BaseX + x)) / 8;
+ NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(BaseZ + z)) / 8;
+ NOISE_DATATYPE CompBlock = m_Noise1.CubicNoise3D(NoiseX, (float) (y + Segment) / 2, NoiseY);
+ if (CompBlock < -0.5)
+ {
+ Block = E_BLOCK_SOULSAND;
+ }
+ else
+ {
+ Block = E_BLOCK_NETHERRACK;
+ }
+ }
+ a_ChunkDesc.SetBlockType(x, y + Segment, z, Block);
}
}
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index c86568c95..87c4d2c52 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -28,11 +28,88 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cTerrainCompositionGen:
+cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed)
+{
+ AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", "");
+ if (CompoGenName.empty())
+ {
+ LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
+ CompoGenName = "Biomal";
+ a_IniFile.SetValue("Generator", "CompositionGen", CompoGenName);
+ }
+
+ cTerrainCompositionGen * res = NULL;
+ if (NoCaseCompare(CompoGenName, "sameblock") == 0)
+ {
+ res = new cCompoGenSameBlock;
+ }
+ else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0)
+ {
+ res = new cCompoGenDebugBiomes;
+ }
+ else if (NoCaseCompare(CompoGenName, "classic") == 0)
+ {
+ res = new cCompoGenClassic;
+ }
+ else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0)
+ {
+ res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
+ }
+ else if (NoCaseCompare(CompoGenName, "end") == 0)
+ {
+ res = new cEndGen(a_Seed);
+ }
+ else if (NoCaseCompare(CompoGenName, "nether") == 0)
+ {
+ res = new cCompoGenNether(a_Seed);
+ }
+ else if (NoCaseCompare(CompoGenName, "Noise3D") == 0)
+ {
+ res = new cNoise3DComposable(a_Seed);
+ }
+ else if (NoCaseCompare(CompoGenName, "biomal") == 0)
+ {
+ res = new cCompoGenBiomal(a_Seed);
+
+ /*
+ // Performance-testing:
+ LOGINFO("Measuring performance of cCompoGenBiomal...");
+ clock_t BeginTick = clock();
+ for (int x = 0; x < 500; x++)
+ {
+ cChunkDesc Desc(200 + x * 8, 200 + x * 8);
+ a_BiomeGen->GenBiomes(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetBiomeMap());
+ a_HeightGen->GenHeightMap(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetHeightMap());
+ res->ComposeTerrain(Desc);
+ }
+ clock_t Duration = clock() - BeginTick;
+ LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
+ //*/
+ }
+ else
+ {
+ LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str());
+ a_IniFile.DeleteValue("Generator", "CompositionGen");
+ a_IniFile.SetValue("Generator", "CompositionGen", "Biomal");
+ return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed);
+ }
+ ASSERT(res != NULL);
+
+ // Read the settings from the ini file:
+ res->InitializeCompoGen(a_IniFile);
+
+ return res;
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cComposableGenerator:
+
cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) :
super(a_ChunkGenerator),
m_BiomeGen(NULL),
@@ -80,9 +157,9 @@ cComposableGenerator::~cComposableGenerator()
-void cComposableGenerator::Initialize(cWorld * a_World, cIniFile & a_IniFile)
+void cComposableGenerator::Initialize(cIniFile & a_IniFile)
{
- super::Initialize(a_World, a_IniFile);
+ super::Initialize(a_IniFile);
InitBiomeGen(a_IniFile);
InitHeightGen(a_IniFile);
@@ -173,60 +250,8 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile)
{
- AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", "");
- if (HeightGenName.empty())
- {
- LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
- HeightGenName = "Biomal";
- }
-
- int Seed = m_ChunkGenerator.GetSeed();
bool CacheOffByDefault = false;
- if (NoCaseCompare(HeightGenName, "flat") == 0)
- {
- m_HeightGen = new cHeiGenFlat;
- CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
- }
- else if (NoCaseCompare(HeightGenName, "classic") == 0)
- {
- m_HeightGen = new cHeiGenClassic(Seed);
- }
- else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
- {
- m_HeightGen = new cDistortedHeightmap(Seed, *m_BiomeGen);
- }
- else if (NoCaseCompare(HeightGenName, "End") == 0)
- {
- m_HeightGen = new cEndGen(Seed);
- }
- else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
- {
- m_HeightGen = new cNoise3DComposable(Seed);
- }
- else // "biomal" or <not found>
- {
- if (NoCaseCompare(HeightGenName, "biomal") != 0)
- {
- LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str());
- }
- m_HeightGen = new cHeiGenBiomal(Seed, *m_BiomeGen);
-
- /*
- // Performance-testing:
- LOGINFO("Measuring performance of cHeiGenBiomal...");
- clock_t BeginTick = clock();
- for (int x = 0; x < 500; x++)
- {
- cChunkDef::HeightMap Heights;
- m_HeightGen->GenHeightMap(x * 5, x * 5, Heights);
- }
- clock_t Duration = clock() - BeginTick;
- LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
- //*/
- }
-
- // Read the settings:
- m_HeightGen->InitializeHeightGen(a_IniFile);
+ m_HeightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, *m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault);
// Add a cache, if requested:
int CacheSize = a_IniFile.GetValueSetI("Generator", "HeightGenCacheSize", CacheOffByDefault ? 0 : 64);
@@ -251,67 +276,7 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile)
void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
{
- int Seed = m_ChunkGenerator.GetSeed();
- AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", "");
- if (CompoGenName.empty())
- {
- LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
- CompoGenName = "Biomal";
- }
- if (NoCaseCompare(CompoGenName, "sameblock") == 0)
- {
- m_CompositionGen = new cCompoGenSameBlock;
- }
- else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0)
- {
- m_CompositionGen = new cCompoGenDebugBiomes;
- }
- else if (NoCaseCompare(CompoGenName, "classic") == 0)
- {
- m_CompositionGen = new cCompoGenClassic;
- }
- else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0)
- {
- m_CompositionGen = new cDistortedHeightmap(Seed, *m_BiomeGen);
- }
- else if (NoCaseCompare(CompoGenName, "end") == 0)
- {
- m_CompositionGen = new cEndGen(Seed);
- }
- else if (NoCaseCompare(CompoGenName, "nether") == 0)
- {
- m_CompositionGen = new cCompoGenNether(Seed);
- }
- else if (NoCaseCompare(CompoGenName, "Noise3D") == 0)
- {
- m_CompositionGen = new cNoise3DComposable(m_ChunkGenerator.GetSeed());
- }
- else
- {
- if (NoCaseCompare(CompoGenName, "biomal") != 0)
- {
- LOGWARN("Unknown CompositionGen \"%s\", using \"biomal\" instead.", CompoGenName.c_str());
- }
- m_CompositionGen = new cCompoGenBiomal(Seed);
-
- /*
- // Performance-testing:
- LOGINFO("Measuring performance of cCompoGenBiomal...");
- clock_t BeginTick = clock();
- for (int x = 0; x < 500; x++)
- {
- cChunkDesc Desc(200 + x * 8, 200 + x * 8);
- m_BiomeGen->GenBiomes(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetBiomeMap());
- m_HeightGen->GenHeightMap(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetHeightMap());
- m_CompositionGen->ComposeTerrain(Desc);
- }
- clock_t Duration = clock() - BeginTick;
- LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
- //*/
- }
-
- // Read the settings from the ini file:
- m_CompositionGen->InitializeCompoGen(a_IniFile);
+ m_CompositionGen = cTerrainCompositionGen::CreateCompositionGen(a_IniFile, *m_BiomeGen, *m_HeightGen, m_ChunkGenerator.GetSeed());
int CompoGenCacheSize = a_IniFile.GetValueSetI("Generator", "CompositionGenCacheSize", 64);
if (CompoGenCacheSize > 1)
@@ -404,13 +369,14 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
int Seed = m_ChunkGenerator.GetSeed();
AString Structures = a_IniFile.GetValueSet("Generator", "Finishers", "SprinkleFoliage,Ice,Snow,Lilypads,BottomLava,DeadBushes,PreSimulator");
+ eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld"));
AStringVector Str = StringSplitAndTrim(Structures, ",");
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
{
// Finishers, alpha-sorted:
if (NoCaseCompare(*itr, "BottomLava") == 0)
{
- int DefaultBottomLavaLevel = (m_World->GetDimension() == dimNether) ? 30 : 10;
+ int DefaultBottomLavaLevel = (Dimension == dimNether) ? 30 : 10;
int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel);
m_FinishGens.push_back(new cFinishGenBottomLava(BottomLavaLevel));
}
@@ -424,7 +390,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else if (NoCaseCompare(*itr, "LavaSprings") == 0)
{
- m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, *m_World));
+ m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, Dimension));
}
else if (NoCaseCompare(*itr, "Lilypads") == 0)
{
@@ -444,7 +410,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else if (NoCaseCompare(*itr, "WaterSprings") == 0)
{
- m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, *m_World));
+ m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, Dimension));
}
} // for itr - Str[]
}
diff --git a/src/Generating/ComposableGenerator.h b/src/Generating/ComposableGenerator.h
index 732f64303..29add0636 100644
--- a/src/Generating/ComposableGenerator.h
+++ b/src/Generating/ComposableGenerator.h
@@ -50,7 +50,7 @@ public:
virtual void InitializeBiomeGen(cIniFile & a_IniFile) {}
/// Creates the correct BiomeGen descendant based on the ini file settings and the seed provided.
- /// a_CacheOffByDefault gets set to whether the cache should be enabled by default
+ /// a_CacheOffByDefault gets set to whether the cache should be disabled by default
/// Used in BiomeVisualiser, too.
/// Implemented in BioGen.cpp!
static cBiomeGen * CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault);
@@ -77,6 +77,13 @@ public:
/// Reads parameters from the ini file, prepares generator for use.
virtual void InitializeHeightGen(cIniFile & a_IniFile) {}
+
+ /** Creates the correct TerrainHeightGen descendant based on the ini file settings and the seed provided.
+ a_BiomeGen is the underlying biome generator, some height generators may depend on it to generate more biomes
+ a_CacheOffByDefault gets set to whether the cache should be disabled by default
+ Implemented in HeiGen.cpp!
+ */
+ static cTerrainHeightGen * CreateHeightGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault);
} ;
@@ -97,6 +104,12 @@ public:
/// Reads parameters from the ini file, prepares generator for use.
virtual void InitializeCompoGen(cIniFile & a_IniFile) {}
+
+ /** Creates the correct TerrainCompositionGen descendant based on the ini file settings and the seed provided.
+ a_BiomeGen is the underlying biome generator, some composition generators may depend on it to generate more biomes
+ a_HeightGen is the underlying height generator, some composition generators may depend on it providing additional values
+ */
+ static cTerrainCompositionGen * CreateCompositionGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed);
} ;
@@ -149,7 +162,7 @@ public:
cComposableGenerator(cChunkGenerator & a_ChunkGenerator);
virtual ~cComposableGenerator();
- virtual void Initialize(cWorld * a_World, cIniFile & a_IniFile) override;
+ virtual void Initialize(cIniFile & a_IniFile) override;
virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override;
diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp
index 15e352e30..eb9fe92ba 100644
--- a/src/Generating/DistortedHeightmap.cpp
+++ b/src/Generating/DistortedHeightmap.cpp
@@ -774,10 +774,11 @@ void cDistortedHeightmap::ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, in
return;
}
default:
+ {
ASSERT(!"Unhandled biome");
return;
+ }
} // switch (Biome)
- ASSERT(!"Unexpected fallthrough");
}
diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp
index 866551e8a..4915e6818 100644
--- a/src/Generating/FinishGen.cpp
+++ b/src/Generating/FinishGen.cpp
@@ -520,7 +520,7 @@ void cFinishGenPreSimulator::StationarizeFluid(
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFinishGenFluidSprings:
-cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, const cWorld & a_World) :
+cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, eDimension a_Dimension) :
m_Noise(a_Seed + a_Fluid * 100), // Need to take fluid into account, otherwise water and lava springs generate next to each other
m_HeightDistribution(255),
m_Fluid(a_Fluid)
@@ -528,8 +528,8 @@ cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cI
bool IsWater = (a_Fluid == E_BLOCK_WATER);
AString SectionName = IsWater ? "WaterSprings" : "LavaSprings";
AString DefaultHeightDistribution;
- int DefaultChance;
- switch (a_World.GetDimension())
+ int DefaultChance = 0;
+ switch (a_Dimension)
{
case dimNether:
{
diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h
index ed7df5909..d89ffed15 100644
--- a/src/Generating/FinishGen.h
+++ b/src/Generating/FinishGen.h
@@ -164,7 +164,7 @@ class cFinishGenFluidSprings :
public cFinishGen
{
public:
- cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, const cWorld & a_World);
+ cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, eDimension a_Dimension);
protected:
diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp
index 2bf641089..10710b4a1 100644
--- a/src/Generating/HeiGen.cpp
+++ b/src/Generating/HeiGen.cpp
@@ -7,6 +7,9 @@
#include "HeiGen.h"
#include "../LinearUpscale.h"
#include "inifile/iniFile.h"
+#include "DistortedHeightmap.h"
+#include "EndGen.h"
+#include "Noise3DGenerator.h"
@@ -14,6 +17,77 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cTerrainHeightGen:
+
+cTerrainHeightGen * cTerrainHeightGen::CreateHeightGen(cIniFile &a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
+{
+ AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", "");
+ if (HeightGenName.empty())
+ {
+ LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
+ HeightGenName = "Biomal";
+ }
+
+ a_CacheOffByDefault = false;
+ cTerrainHeightGen * res = NULL;
+ if (NoCaseCompare(HeightGenName, "flat") == 0)
+ {
+ res = new cHeiGenFlat;
+ a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
+ }
+ else if (NoCaseCompare(HeightGenName, "classic") == 0)
+ {
+ res = new cHeiGenClassic(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
+ {
+ res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
+ }
+ else if (NoCaseCompare(HeightGenName, "End") == 0)
+ {
+ res = new cEndGen(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
+ {
+ res = new cNoise3DComposable(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "biomal") == 0)
+ {
+ res = new cHeiGenBiomal(a_Seed, a_BiomeGen);
+
+ /*
+ // Performance-testing:
+ LOGINFO("Measuring performance of cHeiGenBiomal...");
+ clock_t BeginTick = clock();
+ for (int x = 0; x < 500; x++)
+ {
+ cChunkDef::HeightMap Heights;
+ res->GenHeightMap(x * 5, x * 5, Heights);
+ }
+ clock_t Duration = clock() - BeginTick;
+ LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
+ //*/
+ }
+ else
+ {
+ // No match found, force-set the default and retry
+ LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str());
+ a_IniFile.DeleteValue("Generator", "HeightGen");
+ a_IniFile.SetValue("Generator", "HeightGen", "Biomal");
+ return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
+ }
+
+ // Read the settings:
+ res->InitializeHeightGen(a_IniFile);
+
+ return res;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cHeiGenFlat:
void cHeiGenFlat::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp
index 2511bb656..afa40c647 100644
--- a/src/Generating/Noise3DGenerator.cpp
+++ b/src/Generating/Noise3DGenerator.cpp
@@ -150,10 +150,8 @@ cNoise3DGenerator::~cNoise3DGenerator()
-void cNoise3DGenerator::Initialize(cWorld * a_World, cIniFile & a_IniFile)
+void cNoise3DGenerator::Initialize(cIniFile & a_IniFile)
{
- m_World = a_World;
-
// Params:
m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62);
m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0);
diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h
index 0d211cddc..42f61a854 100644
--- a/src/Generating/Noise3DGenerator.h
+++ b/src/Generating/Noise3DGenerator.h
@@ -24,7 +24,7 @@ public:
cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator);
virtual ~cNoise3DGenerator();
- virtual void Initialize(cWorld * a_World, cIniFile & a_IniFile) override;
+ virtual void Initialize(cIniFile & a_IniFile) override;
virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override;
diff --git a/src/Generating/Ravines.cpp b/src/Generating/Ravines.cpp
index 6413b963b..cfda47e32 100644
--- a/src/Generating/Ravines.cpp
+++ b/src/Generating/Ravines.cpp
@@ -381,7 +381,7 @@ void cStructGenRavines::cRavine::FinishLinear(void)
int R = itr->m_Radius;
int T = itr->m_Top;
int B = itr->m_Bottom;
- while (true)
+ for (;;)
{
m_Points.push_back(cRavDefPoint(PrevX, PrevZ, R, T, B));
if ((PrevX == x1) && (PrevZ == z1))
diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp
index fbed57cb6..7e8a3c75f 100644
--- a/src/Generating/Trees.cpp
+++ b/src/Generating/Trees.cpp
@@ -216,7 +216,14 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
break;
}
-
+
+ case biBirchForestM:
+ case biBirchForestHillsM:
+ {
+ GetTallBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
+ break;
+ }
+
case biRoofedForest:
case biColdTaiga:
case biColdTaigaHills:
@@ -237,8 +244,6 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
case biIcePlainsSpikes:
case biJungleM:
case biJungleEdgeM:
- case biBirchForestM:
- case biBirchForestHillsM:
case biRoofedForestM:
case biColdTaigaM:
case biMegaSpruceTaiga:
@@ -377,6 +382,44 @@ void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
+void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
+{
+ int Height = 9 + (a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ) % 3);
+
+ // Prealloc, so that we don't realloc too often later:
+ a_LogBlocks.reserve(Height);
+ a_OtherBlocks.reserve(80);
+
+ // The entire trunk, out of logs:
+ for (int i = Height - 1; i >= 0; --i)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_BIRCH));
+ }
+ int h = a_BlockY + Height;
+
+ // Top layer - just the Plus:
+ PushCoordBlocks(a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
+ a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH)); // There's no log at this layer
+ h--;
+
+ // Second layer - log, Plus and maybe Corners:
+ PushCoordBlocks (a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
+ PushCornerBlocks(a_BlockX, h, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
+ h--;
+
+ // Third and fourth layers - BigO2 and maybe 2*Corners:
+ for (int Row = 0; Row < 2; Row++)
+ {
+ PushCoordBlocks (a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
+ PushCornerBlocks(a_BlockX, h, a_BlockZ, a_Seq, a_Noise, 0x3fffffff + Row * 0x10000000, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
+ h--;
+ } // for Row - 2*
+}
+
+
+
+
+
void GetConiferTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
{
// Half chance for a spruce, half for a pine:
diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h
index f5148ad6f..514158eb7 100644
--- a/src/Generating/Trees.h
+++ b/src/Generating/Trees.h
@@ -63,6 +63,9 @@ void GetLargeAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a
/// Generates an image of a random birch tree
void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
+/// Generates an image of a random large birch tree
+void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks,sSetBlockVector & a_OtherBlocks);
+
/// Generates an image of a random conifer tree
void GetConiferTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
diff --git a/src/Globals.h b/src/Globals.h
index 58badf4dd..d2080b8eb 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -14,7 +14,24 @@
#pragma warning(disable:4481)
// Disable some warnings that we don't care about:
- #pragma warning(disable:4100)
+ #pragma warning(disable:4100) // Unreferenced formal parameter
+
+ // Useful warnings from warning level 4:
+ #pragma warning(3 : 4127) // Conditional expression is constant
+ #pragma warning(3 : 4189) // Local variable is initialized but not referenced
+ #pragma warning(3 : 4245) // Conversion from 'type1' to 'type2', signed/unsigned mismatch
+ #pragma warning(3 : 4310) // Cast truncates constant value
+ #pragma warning(3 : 4389) // Signed/unsigned mismatch
+ #pragma warning(3 : 4505) // Unreferenced local function has been removed
+ #pragma warning(3 : 4701) // Potentially unitialized local variable used
+ #pragma warning(3 : 4702) // Unreachable code
+ #pragma warning(3 : 4706) // Assignment within conditional expression
+
+ // Disabling this warning, because we know what we're doing when we're doing this:
+ #pragma warning(disable: 4355) // 'this' used in initializer list
+
+ // 2014_01_06 xoft: Disabled this warning because MSVC is stupid and reports it in obviously wrong places
+ // #pragma warning(3 : 4244) // Conversion from 'type1' to 'type2', possible loss of data
#define OBSOLETE __declspec(deprecated)
@@ -192,7 +209,7 @@ typedef unsigned short UInt16;
#ifdef _DEBUG
#define ASSERT( x ) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), assert(0), 0 ) )
#else
- #define ASSERT(x) ((void)0)
+ #define ASSERT(x) ((void)(x))
#endif
// Pretty much the same as ASSERT() but stays in Release builds
@@ -216,6 +233,7 @@ public:
// Common headers (part 2, with macros):
#include "ChunkDef.h"
+#include "BiomeDef.h"
#include "BlockID.h"
#include "Entities/Effects.h"
diff --git a/src/HTTPServer/HTTPConnection.cpp b/src/HTTPServer/HTTPConnection.cpp
index 68afdfc11..3d30ab177 100644
--- a/src/HTTPServer/HTTPConnection.cpp
+++ b/src/HTTPServer/HTTPConnection.cpp
@@ -57,7 +57,7 @@ void cHTTPConnection::SendNeedAuth(const AString & a_Realm)
void cHTTPConnection::Send(const cHTTPResponse & a_Response)
{
- ASSERT(m_State = wcsRecvIdle);
+ ASSERT(m_State == wcsRecvIdle);
a_Response.AppendToData(m_OutgoingData);
m_State = wcsSendingResp;
m_HTTPServer.NotifyConnectionWrite(*this);
diff --git a/src/HTTPServer/HTTPFormParser.cpp b/src/HTTPServer/HTTPFormParser.cpp
index 01c68881a..e661ea6f9 100644
--- a/src/HTTPServer/HTTPFormParser.cpp
+++ b/src/HTTPServer/HTTPFormParser.cpp
@@ -133,7 +133,6 @@ bool cHTTPFormParser::HasFormData(const cHTTPRequest & a_Request)
(a_Request.GetURL().find('?') != AString::npos)
)
);
- return false;
}
diff --git a/src/HTTPServer/MultipartParser.cpp b/src/HTTPServer/MultipartParser.cpp
index b49f6ec07..14c2c00fa 100644
--- a/src/HTTPServer/MultipartParser.cpp
+++ b/src/HTTPServer/MultipartParser.cpp
@@ -156,7 +156,7 @@ void cMultipartParser::Parse(const char * a_Data, int a_Size)
// Append to buffer, then parse it:
m_IncomingData.append(a_Data, a_Size);
- while (true)
+ for (;;)
{
if (m_EnvelopeParser.IsInHeaders())
{
diff --git a/src/HTTPServer/NameValueParser.cpp b/src/HTTPServer/NameValueParser.cpp
index fd56f6b24..9ea8594ae 100644
--- a/src/HTTPServer/NameValueParser.cpp
+++ b/src/HTTPServer/NameValueParser.cpp
@@ -253,7 +253,6 @@ void cNameValueParser::Parse(const char * a_Data, int a_Size)
m_State = psValueRaw;
break;
}
- i++;
} // while (i < a_Size)
break;
} // case psEqual
diff --git a/src/Inventory.cpp b/src/Inventory.cpp
index a9b4ab9c5..a7f77cf6d 100644
--- a/src/Inventory.cpp
+++ b/src/Inventory.cpp
@@ -57,6 +57,8 @@ int cInventory::HowManyCanFit(const cItem & a_ItemStack, bool a_ConsiderEmptySlo
int cInventory::HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int a_EndSlotNum, bool a_ConsiderEmptySlots)
{
+
+ UNUSED(a_ConsiderEmptySlots);
if ((a_BeginSlotNum < 0) || (a_BeginSlotNum >= invNumSlots))
{
LOGWARNING("%s: Bad BeginSlotNum, got %d, there are %d slots; correcting to 0.", __FUNCTION__, a_BeginSlotNum, invNumSlots - 1);
@@ -96,8 +98,6 @@ int cInventory::HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int
-
-
int cInventory::AddItem(const cItem & a_Item, bool a_AllowNewStacks, bool a_tryToFillEquippedFirst)
{
cItem ToAdd(a_Item);
diff --git a/src/Item.cpp b/src/Item.cpp
index 196a260ef..a44515019 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -246,7 +246,7 @@ void cItems::Delete(int a_Idx)
-void cItems::Set(int a_Idx, ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemDamage)
+void cItems::Set(int a_Idx, short a_ItemType, char a_ItemCount, short a_ItemDamage)
{
if ((a_Idx < 0) || (a_Idx >= (int)size()))
{
diff --git a/src/Item.h b/src/Item.h
index c60d0542c..64a30ade1 100644
--- a/src/Item.h
+++ b/src/Item.h
@@ -181,9 +181,9 @@ public:
void Delete(int a_Idx);
void Clear (void) {clear(); }
int Size (void) {return size(); }
- void Set (int a_Idx, ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemDamage);
+ void Set (int a_Idx, short a_ItemType, char a_ItemCount, short a_ItemDamage);
- void Add (ENUM_ITEM_ID a_ItemType, char a_ItemCount, short a_ItemDamage)
+ void Add (short a_ItemType, char a_ItemCount, short a_ItemDamage)
{
push_back(cItem(a_ItemType, a_ItemCount, a_ItemDamage));
}
diff --git a/src/Items/ItemFishingRod.h b/src/Items/ItemFishingRod.h
index 941ce3b71..b2eaee63a 100644
--- a/src/Items/ItemFishingRod.h
+++ b/src/Items/ItemFishingRod.h
@@ -9,9 +9,11 @@
#pragma once
+#include "../Bindings/PluginManager.h"
#include "../Entities/Floater.h"
#include "../Entities/Entity.h"
#include "../Item.h"
+#include "../Root.h"
@@ -210,10 +212,14 @@ public:
}
}
-
+ if (cRoot::Get()->GetPluginManager()->CallHookPlayerFishing(*a_Player, Drops))
+ {
+ return true;
+ }
Vector3d FloaterPos = FloaterInfo.GetPos();
Vector3d FlyDirection = a_Player->GetEyePosition() - FloaterPos;
a_World->SpawnItemPickups(Drops, FloaterPos.x, FloaterPos.y, FloaterPos.z, FlyDirection.x, FlyDirection.y + 1, FlyDirection.z);
+ cRoot::Get()->GetPluginManager()->CallHookPlayerFished(*a_Player, Drops);
}
}
else
diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h
index e39bb054b..db0ffc9db 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -25,7 +25,13 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
/// Called when the client sends the SHOOT status in the lclk packet
- virtual void OnItemShoot(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) {}
+ virtual void OnItemShoot(cPlayer *, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+ {
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ UNUSED(a_BlockFace);
+ }
/// Called while the player diggs a block using this item
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
diff --git a/src/Items/ItemSeeds.h b/src/Items/ItemSeeds.h
index 8ca86663f..67f0d38bd 100644
--- a/src/Items/ItemSeeds.h
+++ b/src/Items/ItemSeeds.h
@@ -56,7 +56,6 @@ public:
case E_ITEM_SEEDS: a_BlockType = E_BLOCK_CROPS; return true;
default: a_BlockType = E_BLOCK_AIR; return true;
}
- return false;
}
} ;
diff --git a/src/LightingThread.cpp b/src/LightingThread.cpp
index d7e60e458..a823c08cc 100644
--- a/src/LightingThread.cpp
+++ b/src/LightingThread.cpp
@@ -189,7 +189,7 @@ void cLightingThread::ChunkReady(int a_ChunkX, int a_ChunkZ)
{
if (
(itr->x - a_ChunkX >= -1) && (itr->x - a_ChunkX <= 1) &&
- (itr->x - a_ChunkX >= -1) && (itr->x - a_ChunkX <= 1)
+ (itr->z - a_ChunkZ >= -1) && (itr->z - a_ChunkZ <= 1)
)
{
// It is a neighbor
@@ -216,7 +216,7 @@ void cLightingThread::ChunkReady(int a_ChunkX, int a_ChunkZ)
void cLightingThread::Execute(void)
{
- while (true)
+ for (;;)
{
{
cCSLock Lock(m_CS);
@@ -495,6 +495,7 @@ void cLightingThread::CalcLightStep(
int & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
)
{
+ UNUSED(a_IsSeedIn);
int NumSeedsOut = 0;
for (int i = 0; i < a_NumSeedsIn; i++)
{
diff --git a/src/LineBlockTracer.cpp b/src/LineBlockTracer.cpp
index 9fcbca915..da1c7f2fd 100644
--- a/src/LineBlockTracer.cpp
+++ b/src/LineBlockTracer.cpp
@@ -196,8 +196,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
ASSERT((m_CurrentY >= 0) && (m_CurrentY < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld()
// This is the actual line tracing loop.
- bool Finished = false;
- while (true)
+ for (;;)
{
// Report the current block through the callbacks:
if (a_Chunk == NULL)
diff --git a/src/OSSupport/CriticalSection.h b/src/OSSupport/CriticalSection.h
index 1bfe81439..73a71f5e1 100644
--- a/src/OSSupport/CriticalSection.h
+++ b/src/OSSupport/CriticalSection.h
@@ -14,9 +14,14 @@ public:
void Lock(void);
void Unlock(void);
+ // IsLocked/IsLockedByCurrentThread are only used in ASSERT statements, but because of the changes with ASSERT they must always be defined
+ // The fake versions (in Release) will not effect the program in any way
#ifdef _DEBUG
bool IsLocked(void);
bool IsLockedByCurrentThread(void);
+ #else
+ bool IsLocked(void) { return false; }
+ bool IsLockedByCurrentThread(void) { return false; }
#endif // _DEBUG
private:
diff --git a/src/OSSupport/Queue.h b/src/OSSupport/Queue.h
new file mode 100644
index 000000000..6c3d58295
--- /dev/null
+++ b/src/OSSupport/Queue.h
@@ -0,0 +1,178 @@
+
+// Queue.h
+
+// Implements the cQueue class representing a thread safe queue
+
+#pragma once
+
+/*
+Items can be added multiple times to a queue, there are two functions for
+adding, EnqueueItem() and EnqueueItemIfNotPresent(). The first one always
+enqueues the specified item, the second one checks if the item is already
+present and only queues it if it isn't.
+
+Usage:
+To create a queue of type T, instantiate a cQueue<T> object. You can also
+modify the behavior of the queue when deleting items and when adding items
+that are already in the queue by providing a second parameter, a class that
+implements the functions Delete() and Combine(). An example is given in
+cQueueFuncs and is used as the default behavior.
+*/
+
+/// This empty struct allows for the callback functions to be inlined
+template<class T>
+struct cQueueFuncs
+{
+public:
+
+ /// Called when an Item is deleted from the queue without being returned
+ static void Delete(T) {};
+
+ /// Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already inserted
+ static void Combine(T & a_existing, const T & a_new) {};
+};
+
+
+
+
+
+template <class ItemType, class Funcs = cQueueFuncs<ItemType> >
+class cQueue
+{
+ // The actual storage type for the queue
+ typedef typename std::list<ItemType> QueueType;
+
+ // Make iterator an alias for the QueueType's iterator
+ typedef typename QueueType::iterator iterator;
+
+public:
+ cQueue() {}
+ ~cQueue() {}
+
+
+ /// Enqueues an item to the queue, may block if other threads are accessing the queue.
+ void EnqueueItem(ItemType a_Item)
+ {
+ cCSLock Lock(m_CS);
+ m_Contents.push_back(a_Item);
+ m_evtAdded.Set();
+ }
+
+
+ /// Enqueues an item in the queue if not already present (as determined by operator ==). Blocks other threads from accessing the queue.
+ void EnqueueItemIfNotPresent(ItemType a_Item)
+ {
+ cCSLock Lock(m_CS);
+
+ for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr)
+ {
+ if ((*itr) == a_Item)
+ {
+ Funcs::Combine(*itr, a_Item);
+ return;
+ }
+ }
+ m_Contents.push_back(a_Item);
+ m_evtAdded.Set();
+ }
+
+
+ /// Dequeues an item from the queue if any are present.
+ /// Returns true if successful. Value of item is undefined if dequeuing was unsuccessful.
+ bool TryDequeueItem(ItemType & item)
+ {
+ cCSLock Lock(m_CS);
+ if (m_Contents.size() == 0)
+ {
+ return false;
+ }
+ item = m_Contents.front();
+ m_Contents.pop_front();
+ m_evtRemoved.Set();
+ return true;
+ }
+
+
+ /// Dequeues an item from the queue, blocking until an item is available.
+ ItemType DequeueItem(void)
+ {
+ cCSLock Lock(m_CS);
+ while (m_Contents.size() == 0)
+ {
+ cCSUnlock Unlock(Lock);
+ m_evtAdded.Wait();
+ }
+ ItemType item = m_Contents.front();
+ m_Contents.pop_front();
+ m_evtRemoved.Set();
+ return item;
+ }
+
+
+ /// Blocks until the queue is empty.
+ void BlockTillEmpty(void)
+ {
+ cCSLock Lock(m_CS);
+ while (!m_Contents.empty())
+ {
+ cCSUnlock Unlock(Lock);
+ m_evtRemoved.Wait();
+ }
+ }
+
+
+ /// Removes all Items from the Queue, calling Delete on each of them.
+ void Clear(void)
+ {
+ cCSLock Lock(m_CS);
+ while (!m_Contents.empty())
+ {
+ Funcs::Delete(m_Contents.front());
+ m_Contents.pop_front();
+ }
+ }
+
+
+ /// Returns the size at time of being called.
+ /// Do not use to determine whether to call DequeueItem(), use TryDequeueItem() instead
+ size_t Size(void)
+ {
+ cCSLock Lock(m_CS);
+ return m_Contents.size();
+ }
+
+
+ /// Removes the item from the queue. If there are multiple such items, only the first one is removed.
+ /// Returns true if the item has been removed, false if no such item found.
+ bool Remove(ItemType a_Item)
+ {
+ cCSLock Lock(m_CS);
+ for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr)
+ {
+ if ((*itr) == a_Item)
+ {
+ m_Contents.erase(itr);
+ m_evtRemoved.Set();
+ return true;
+ }
+ }
+ return false;
+ }
+
+private:
+ /// The contents of the queue
+ QueueType m_Contents;
+
+ /// Mutex that protects access to the queue contents
+ cCriticalSection m_CS;
+
+ /// Event that is signalled when an item is added
+ cEvent m_evtAdded;
+
+ /// Event that is signalled when an item is removed (both dequeued or erased)
+ cEvent m_evtRemoved;
+};
+
+
+
+
diff --git a/src/OSSupport/SocketThreads.h b/src/OSSupport/SocketThreads.h
index ecbac3aeb..858729c49 100644
--- a/src/OSSupport/SocketThreads.h
+++ b/src/OSSupport/SocketThreads.h
@@ -61,6 +61,9 @@ public:
class cCallback
{
public:
+ // Force a virtual destructor in all subclasses:
+ virtual ~cCallback() {}
+
/// Called when data is received from the remote party
virtual void DataReceived(const char * a_Data, int a_Size) = 0;
diff --git a/src/Piston.cpp b/src/Piston.cpp
index b15e7d95e..75eeb5e98 100644
--- a/src/Piston.cpp
+++ b/src/Piston.cpp
@@ -238,6 +238,7 @@ bool cPiston::CanPush(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
bool cPiston::CanBreakPush(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
+ UNUSED(a_BlockMeta);
return g_BlockPistonBreakable[a_BlockType];
}
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index fdbffb3e9..3293da32c 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -87,6 +87,7 @@ public:
virtual void SendPlayerMoveLook (void) = 0;
virtual void SendPlayerPosition (void) = 0;
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
+ virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
virtual void SendRespawn (void) = 0;
virtual void SendExperience (void) = 0;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index e49dd43ff..48c085ae5 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -704,6 +704,20 @@ void cProtocol125::SendPlayerSpawn(const cPlayer & a_Player)
+void cProtocol125::SendPluginMessage(const AString & a_Channel, const AString & a_Message)
+{
+ cCSLock Lock(m_CSPacket);
+ WriteByte(PACKET_PLUGIN_MESSAGE);
+ WriteString(a_Channel);
+ WriteShort((short)a_Message.size());
+ SendData(a_Message.data(), a_Message.size());
+ Flush();
+}
+
+
+
+
+
void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
{
cCSLock Lock(m_CSPacket);
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 0b32137d8..d0e5c9428 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -63,6 +63,7 @@ public:
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 346607b79..302d1298c 100644
--- a/src/Protocol/Protocol132.cpp
+++ b/src/Protocol/Protocol132.cpp
@@ -5,7 +5,6 @@
#include "Globals.h"
#include "ChunkDataSerializer.h"
-#include "cryptopp/randpool.h"
#include "Protocol132.h"
#include "../Root.h"
#include "../Server.h"
@@ -19,8 +18,20 @@
#include "../WorldStorage/FastNBT.h"
#include "../StringCompression.h"
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127)
+ #pragma warning(disable:4244)
+ #pragma warning(disable:4231)
+ #pragma warning(disable:4189)
+ #pragma warning(disable:4702)
+#endif
+#include "cryptopp/randpool.h"
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
#define HANDLE_PACKET_READ(Proc, Type, Var) \
@@ -866,7 +877,7 @@ void cProtocol132::SendCompass(const cWorld & a_World)
void cProtocol132::SendEncryptionKeyRequest(void)
{
cCSLock Lock(m_CSPacket);
- WriteByte((char)0xfd);
+ WriteByte(0xfd);
WriteString(cRoot::Get()->GetServer()->GetServerID());
WriteShort((short)m_ServerPublicKey.size());
SendData(m_ServerPublicKey.data(), m_ServerPublicKey.size());
@@ -886,15 +897,15 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
time_t CurTime = time(NULL);
CryptoPP::RandomPool rng;
rng.Put((const byte *)&CurTime, sizeof(CurTime));
- byte DecryptedNonce[MAX_ENC_LEN];
- DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), DecryptedNonce);
+ Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
+ DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), (byte *)DecryptedNonce);
if (!res.isValidCoding || (res.messageLength != 4))
{
LOGD("Bad nonce length");
m_Client->Kick("Hacked client");
return;
}
- if (ntohl(*((int *)DecryptedNonce)) != (unsigned)(uintptr_t)this)
+ if (ntohl(DecryptedNonce[0]) != (unsigned)(uintptr_t)this)
{
LOGD("Bad nonce value");
m_Client->Kick("Hacked client");
@@ -914,7 +925,7 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
{
// Send encryption key response:
cCSLock Lock(m_CSPacket);
- WriteByte((char)0xfc);
+ WriteByte(0xfc);
WriteShort(0);
WriteShort(0);
Flush();
diff --git a/src/Protocol/Protocol132.h b/src/Protocol/Protocol132.h
index f76272b8d..80fc8740a 100644
--- a/src/Protocol/Protocol132.h
+++ b/src/Protocol/Protocol132.h
@@ -10,9 +10,23 @@
#pragma once
#include "Protocol125.h"
+
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127)
+ #pragma warning(disable:4189)
+ #pragma warning(disable:4231)
+ #pragma warning(disable:4244)
+ #pragma warning(disable:4702)
+#endif
+
#include "cryptopp/modes.h"
#include "cryptopp/aes.h"
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp
index 28122034c..926fe6ee8 100644
--- a/src/Protocol/Protocol14x.cpp
+++ b/src/Protocol/Protocol14x.cpp
@@ -16,7 +16,6 @@ Implements the 1.4.x protocol classes representing these protocols:
#include "../Root.h"
#include "../Server.h"
#include "../ClientHandle.h"
-#include "cryptopp/randpool.h"
#include "../Item.h"
#include "ChunkDataSerializer.h"
#include "../Entities/Player.h"
@@ -25,8 +24,20 @@ Implements the 1.4.x protocol classes representing these protocols:
#include "../Entities/Pickup.h"
#include "../Entities/FallingBlock.h"
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127)
+ #pragma warning(disable:4244)
+ #pragma warning(disable:4231)
+ #pragma warning(disable:4189)
+ #pragma warning(disable:4702)
+#endif
+#include "cryptopp/randpool.h"
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
#define HANDLE_PACKET_READ(Proc, Type, Var) \
diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp
index 7e2aa9490..0f1e59f10 100644
--- a/src/Protocol/Protocol15x.cpp
+++ b/src/Protocol/Protocol15x.cpp
@@ -112,7 +112,7 @@ int cProtocol150::ParseWindowClick(void)
}
// Convert Button, Mode, SlotNum and HeldItem into eClickAction:
- eClickAction Action;
+ eClickAction Action = caUnknown;
switch ((Mode << 8) | Button)
{
case 0x0000: Action = (SlotNum != -999) ? caLeftClick : caLeftClickOutside; break;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index bbbd5e973..9c46c6843 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -628,6 +628,18 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
+void cProtocol172::SendPluginMessage(const AString & a_Channel, const AString & a_Message)
+{
+ cPacketizer Pkt(*this, 0x3f);
+ Pkt.WriteString(a_Channel);
+ Pkt.WriteShort((short)a_Message.size());
+ Pkt.WriteBuf(a_Message.data(), a_Message.size());
+}
+
+
+
+
+
void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
{
cPacketizer Pkt(*this, 0x1E);
@@ -983,10 +995,9 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
}
// Handle all complete packets:
- while (true)
+ for (;;)
{
UInt32 PacketLen;
- int PacketStart = m_ReceivedData.GetDataStart();
if (!m_ReceivedData.ReadVarInt(PacketLen))
{
// Not enough data
@@ -1113,9 +1124,12 @@ void cProtocol172::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
cRoot::Get()->GetServer()->GetMaxPlayers(),
cRoot::Get()->GetServer()->GetNumPlayers()
);
- AppendPrintf(Response, "\"description\":{\"text\":\"%s\"}",
+ AppendPrintf(Response, "\"description\":{\"text\":\"%s\"},",
cRoot::Get()->GetServer()->GetDescription().c_str()
);
+ AppendPrintf(Response, "\"favicon\":\"data:image/png;base64,%s\"",
+ cRoot::Get()->GetServer()->GetFaviconData().c_str()
+ );
Response.append("}");
cPacketizer Pkt(*this, 0x00); // Response packet
@@ -1374,7 +1388,7 @@ void cProtocol172::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEShort, short, Length);
AString Data;
a_ByteBuffer.ReadString(Data, Length);
- // TODO: m_Client->HandlePluginMessage(Channel, Data);
+ m_Client->HandlePluginMessage(Channel, Data);
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index cc0eda1e7..fd6b1fc0f 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -16,9 +16,23 @@ Declares the 1.7.x protocol classes:
#include "Protocol.h"
#include "../ByteBuffer.h"
+
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127)
+ #pragma warning(disable:4244)
+ #pragma warning(disable:4231)
+ #pragma warning(disable:4189)
+ #pragma warning(disable:4702)
+#endif
+
#include "cryptopp/modes.h"
#include "cryptopp/aes.h"
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
@@ -72,6 +86,7 @@ public:
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 1cae4a750..a21f4f042 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -198,7 +198,7 @@ void cProtocolRecognizer::SendDisconnect(const AString & a_Reason)
else
{
// This is used when the client sends a server-ping, respond with the default packet:
- WriteByte ((char)0xff); // PACKET_DISCONNECT
+ WriteByte (0xff); // PACKET_DISCONNECT
WriteString(a_Reason);
}
}
@@ -476,6 +476,16 @@ void cProtocolRecognizer::SendPlayerSpawn(const cPlayer & a_Player)
+void cProtocolRecognizer::SendPluginMessage(const AString & a_Channel, const AString & a_Message)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendPluginMessage(a_Channel, a_Message);
+}
+
+
+
+
+
void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
{
ASSERT(m_Protocol != NULL);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index fbcf59f3b..e94f4cde8 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -98,6 +98,7 @@ public:
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
diff --git a/src/Root.cpp b/src/Root.cpp
index 798f965be..fa1fdb37a 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -596,10 +596,10 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallbac
public:
cCallback (const AString & a_PlayerName, cPlayerListCallback & a_Callback) :
- m_Callback(a_Callback),
m_BestRating(0),
m_NameLength(a_PlayerName.length()),
m_PlayerName(a_PlayerName),
+ m_Callback(a_Callback),
m_BestMatch(NULL),
m_NumMatches(0)
{}
@@ -701,9 +701,9 @@ int cRoot::GetPhysicalRAMUsage(void)
{
AString Line;
std::getline(StatFile, Line);
- if (strncmp(Line.c_str(), "VmRSS:", 7) == 0)
+ if (strncmp(Line.c_str(), "VmRSS:", 6) == 0)
{
- int res = atoi(Line.c_str() + 8);
+ int res = atoi(Line.c_str() + 7);
return (res == 0) ? -1 : res; // If parsing failed, return -1
}
}
diff --git a/src/Server.cpp b/src/Server.cpp
index a93be9a5b..49067c17f 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -173,6 +173,7 @@ void cServer::ClientMovedToWorld(const cClientHandle * a_Client)
void cServer::PlayerCreated(const cPlayer * a_Player)
{
+ UNUSED(a_Player);
// To avoid deadlocks, the player count is not handled directly, but rather posted onto the tick thread
cCSLock Lock(m_CSPlayerCountDiff);
m_PlayerCountDiff += 1;
@@ -184,6 +185,7 @@ void cServer::PlayerCreated(const cPlayer * a_Player)
void cServer::PlayerDestroying(const cPlayer * a_Player)
{
+ UNUSED(a_Player);
// To avoid deadlocks, the player count is not handled directly, but rather posted onto the tick thread
cCSLock Lock(m_CSPlayerCountDiff);
m_PlayerCountDiff -= 1;
@@ -201,6 +203,8 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
m_PlayerCount = 0;
m_PlayerCountDiff = 0;
+ m_FaviconData = Base64Encode(cFile::ReadWholeFile("favicon.png")); // Will return empty string if file nonexistant; client doesn't mind
+
if (m_bIsConnected)
{
LOGERROR("ERROR: Trying to initialize server while server is already running!");
@@ -491,7 +495,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
if (split[0].compare("killmem") == 0)
{
- while (true)
+ for (;;)
{
new char[100 * 1024 * 1024]; // Allocate and leak 100 MiB in a loop -> fill memory and kill MCS
}
@@ -514,6 +518,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
void cServer::PrintHelp(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
{
+ UNUSED(a_Split);
typedef std::pair<AString, AString> AStringPair;
typedef std::vector<AStringPair> AStringPairs;
@@ -525,6 +530,8 @@ void cServer::PrintHelp(const AStringVector & a_Split, cCommandOutputCallback &
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
{
+ UNUSED(a_Plugin);
+ UNUSED(a_Permission);
if (!a_HelpString.empty())
{
m_Commands.push_back(AStringPair(a_Command, a_HelpString));
diff --git a/src/Server.h b/src/Server.h
index 0d93469a5..d79417fb0 100644
--- a/src/Server.h
+++ b/src/Server.h
@@ -11,9 +11,24 @@
#include "OSSupport/SocketThreads.h"
#include "OSSupport/ListenThread.h"
+
+#include "RCONServer.h"
+
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127)
+ #pragma warning(disable:4244)
+ #pragma warning(disable:4231)
+ #pragma warning(disable:4189)
+ #pragma warning(disable:4702)
+#endif
+
#include "cryptopp/rsa.h"
#include "cryptopp/randpool.h"
-#include "RCONServer.h"
+
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
@@ -35,6 +50,8 @@ class cServer // tolua_export
: public cListenThread::cCallback
{ // tolua_export
public: // tolua_export
+
+ virtual ~cServer() {}
bool InitServer(cIniFile & a_SettingsIni);
// tolua_begin
@@ -89,6 +106,9 @@ public: // tolua_export
/// Notifies the server that a player is being destroyed; the server uses this to adjust the number of players
void PlayerDestroying(const cPlayer * a_Player);
+
+ /* Returns base64 encoded favicon data (obtained from favicon.png) */
+ const AString & GetFaviconData(void) const { return m_FaviconData; }
CryptoPP::RSA::PrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
CryptoPP::RSA::PublicKey & GetPublicKey (void) { return m_PublicKey; }
@@ -166,6 +186,7 @@ private:
cRCONServer m_RCONServer;
AString m_Description;
+ AString m_FaviconData;
int m_MaxPlayers;
bool m_bIsHardcore;
diff --git a/src/Simulator/FireSimulator.h b/src/Simulator/FireSimulator.h
index 66c31b440..9ccc3ef4f 100644
--- a/src/Simulator/FireSimulator.h
+++ b/src/Simulator/FireSimulator.h
@@ -22,7 +22,7 @@ public:
cFireSimulator(cWorld & a_World, cIniFile & a_IniFile);
~cFireSimulator();
- virtual void Simulate(float a_Dt) override {} // not used
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
diff --git a/src/Simulator/NoopFluidSimulator.h b/src/Simulator/NoopFluidSimulator.h
index 8f894433f..9113aec3c 100644
--- a/src/Simulator/NoopFluidSimulator.h
+++ b/src/Simulator/NoopFluidSimulator.h
@@ -27,8 +27,14 @@ public:
}
// cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {}
- virtual void Simulate(float a_Dt) override {}
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override
+ {
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ UNUSED(a_Chunk);
+ }
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);}
} ;
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 60c86a3c5..1080c3f81 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -19,7 +19,7 @@ public:
cRedstoneSimulator(cWorld & a_World);
~cRedstoneSimulator();
- virtual void Simulate(float a_Dt) override {}; // Not used in this simulator
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return IsRedstone(a_BlockType); }
@@ -271,4 +271,4 @@ private:
default: return false;
}
}
-}; \ No newline at end of file
+};
diff --git a/src/Simulator/SandSimulator.h b/src/Simulator/SandSimulator.h
index 6e9ea15ac..6e64aa425 100644
--- a/src/Simulator/SandSimulator.h
+++ b/src/Simulator/SandSimulator.h
@@ -15,7 +15,7 @@ public:
cSandSimulator(cWorld & a_World, cIniFile & a_IniFile);
// cSimulator overrides:
- virtual void Simulate(float a_Dt) override {} // Unused in this simulator
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h
index 5cd0e8657..a25b7f1b6 100644
--- a/src/Simulator/Simulator.h
+++ b/src/Simulator/Simulator.h
@@ -25,7 +25,14 @@ public:
virtual void Simulate(float a_Dt) = 0;
/// Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) {};
+ virtual void SimulateChunk(float a_Dt, int a_ChunkX,
+ int a_ChunkZ, cChunk * a_Chunk)
+ {
+ UNUSED(a_Dt);
+ UNUSED(a_ChunkX);
+ UNUSED(a_ChunkZ);
+ UNUSED(a_Chunk);
+ };
/// Called when a block changes
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);
diff --git a/src/StringCompression.cpp b/src/StringCompression.cpp
index 36946b282..e15058840 100644
--- a/src/StringCompression.cpp
+++ b/src/StringCompression.cpp
@@ -74,7 +74,7 @@ int CompressStringGZIP(const char * a_Data, int a_Length, AString & a_Compressed
return res;
}
- while (true)
+ for (;;)
{
res = deflate(&strm, Z_FINISH);
switch (res)
@@ -137,7 +137,7 @@ extern int UncompressStringGZIP(const char * a_Data, int a_Length, AString & a_U
return res;
}
- while (true)
+ for (;;)
{
res = inflate(&strm, Z_FINISH);
switch (res)
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
index f7aeeed26..0b38297ef 100644
--- a/src/StringUtils.cpp
+++ b/src/StringUtils.cpp
@@ -47,15 +47,13 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args)
#endif // _MSC_VER
// Allocate a buffer and printf into it:
- str.resize(len + 1);
- // HACK: we're accessing AString's internal buffer in a way that is NOT guaranteed to always work. But it works on all STL implementations tested.
- // I can't think of any other way that is safe, doesn't allocate twice as much space as needed and doesn't use C++11 features like the move constructor
+ std::vector<char> Buffer(len + 1);
#ifdef _MSC_VER
- vsprintf_s((char *)str.data(), len + 1, format, args);
+ vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, args);
#else // _MSC_VER
- vsnprintf((char *)str.data(), len + 1, format, args);
+ vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, args);
#endif // else _MSC_VER
- str.resize(len);
+ str.append(&(Buffer.front()), Buffer.size() - 1);
return str;
}
@@ -612,7 +610,7 @@ AString StripColorCodes(const AString & a_Message)
{
AString res(a_Message);
size_t idx = 0;
- while (true)
+ for (;;)
{
idx = res.find("\xc2\xa7", idx);
if (idx == AString::npos)
@@ -759,7 +757,86 @@ AString Base64Decode(const AString & a_Base64String)
}
}
res.resize(o >> 3);
- return res;}
+ return res;
+}
+
+
+
+
+
+AString Base64Encode(const AString & a_Input)
+{
+ static const char BASE64[64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+ };
+
+ AString output;
+ output.resize(((a_Input.size() + 2) / 3) * 4);
+
+ size_t output_index = 0;
+ size_t size_full24 = (a_Input.size() / 3) * 3;
+
+ for (size_t i = 0; i < size_full24; i += 3)
+ {
+ output[output_index++] = BASE64[(unsigned char)a_Input[i] >> 2];
+ output[output_index++] = BASE64[((unsigned char)a_Input[i] << 4 | (unsigned char)a_Input[i + 1] >> 4) & 63];
+ output[output_index++] = BASE64[((unsigned char)a_Input[i + 1] << 2 | (unsigned char)a_Input[i + 2] >> 6) & 63];
+ output[output_index++] = BASE64[(unsigned char)a_Input[i + 2] & 63];
+ }
+
+ if (size_full24 < a_Input.size())
+ {
+ output[output_index++] = BASE64[(unsigned char)a_Input[size_full24] >> 2];
+ if (size_full24 + 1 == a_Input.size())
+ {
+ output[output_index++] = BASE64[((unsigned char)a_Input[size_full24] << 4) & 63];
+ output[output_index++] = '=';
+ }
+ else
+ {
+ output[output_index++] = BASE64[((unsigned char)a_Input[size_full24] << 4 | (unsigned char)a_Input[size_full24 + 1] >> 4) & 63];
+ output[output_index++] = BASE64[((unsigned char)a_Input[size_full24 + 1] << 2) & 63];
+ }
+
+ output[output_index++] = '=';
+ }
+ ASSERT(output_index == output.size());
+
+ return output;
+}
+
+
+
+
+
+short GetBEShort(const char * a_Mem)
+{
+ return (((short)a_Mem[0]) << 8) | a_Mem[1];
+}
+
+
+
+
+
+int GetBEInt(const char * a_Mem)
+{
+ return (((int)a_Mem[0]) << 24) | (((int)a_Mem[1]) << 16) | (((int)a_Mem[2]) << 8) | a_Mem[3];
+}
+
+
+
+
+
+void SetBEInt(char * a_Mem, Int32 a_Value)
+{
+ a_Mem[0] = a_Value >> 24;
+ a_Mem[1] = (a_Value >> 16) & 0xff;
+ a_Mem[2] = (a_Value >> 8) & 0xff;
+ a_Mem[3] = a_Value & 0xff;
+}
diff --git a/src/StringUtils.h b/src/StringUtils.h
index 3917cc4ec..2373f3843 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -81,6 +81,18 @@ extern AString ReplaceAllCharOccurrences(const AString & a_String, char a_From,
/// Decodes a Base64-encoded string into the raw data
extern AString Base64Decode(const AString & a_Base64String);
+/// Encodes a string into Base64
+extern AString Base64Encode(const AString & a_Input);
+
+/// Reads two bytes from the specified memory location and interprets them as BigEndian short
+extern short GetBEShort(const char * a_Mem);
+
+/// Reads four bytes from the specified memory location and interprets them as BigEndian int
+extern int GetBEInt(const char * a_Mem);
+
+/// Writes four bytes to the specified memory location so that they interpret as BigEndian int
+extern void SetBEInt(char * a_Mem, Int32 a_Value);
+
// If you have any other string helper functions, declare them here
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 61e432665..a721e6b7e 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -491,7 +491,7 @@ void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player)
return;
}
cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1;
- do
+ for (;;)
{
// Try distributing the result. If it fails, bail out:
cItem ResultCopy(Result);
@@ -517,7 +517,7 @@ void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player)
// The recipe has changed, bail out
return;
}
- } while (true);
+ }
}
diff --git a/src/WebAdmin.cpp b/src/WebAdmin.cpp
index a1f0842aa..e6a5a01b3 100644
--- a/src/WebAdmin.cpp
+++ b/src/WebAdmin.cpp
@@ -305,6 +305,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
{
+ UNUSED(a_Request);
static const char LoginForm[] = \
"<h1>MCServer WebAdmin</h1>" \
"<center>" \
@@ -450,6 +451,7 @@ AString cWebAdmin::GetBaseURL(const AStringVector & a_URLSplit)
void cWebAdmin::OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
{
+ UNUSED(a_Connection);
const AString & URL = a_Request.GetURL();
if (
(strncmp(URL.c_str(), "/webadmin", 9) == 0) ||
@@ -473,6 +475,7 @@ void cWebAdmin::OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_
void cWebAdmin::OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, int a_Size)
{
+ UNUSED(a_Connection);
cRequestData * Data = (cRequestData *)(a_Request.GetUserData());
if (Data == NULL)
{
diff --git a/src/WebAdmin.h b/src/WebAdmin.h
index 0907e7bc3..3eb807640 100644
--- a/src/WebAdmin.h
+++ b/src/WebAdmin.h
@@ -105,7 +105,7 @@ public:
cWebAdmin(void);
- ~cWebAdmin();
+ virtual ~cWebAdmin();
/// Initializes the object. Returns true if successfully initialized and ready to start
bool Init(void);
@@ -169,9 +169,16 @@ protected:
virtual void OnBody(const char * a_Data, int a_Size) override;
// cHTTPFormParser::cCallbacks overrides. Files are ignored:
- virtual void OnFileStart(cHTTPFormParser & a_Parser, const AString & a_FileName) override {}
- virtual void OnFileData(cHTTPFormParser & a_Parser, const char * a_Data, int a_Size) override {}
- virtual void OnFileEnd(cHTTPFormParser & a_Parser) override {}
+ virtual void OnFileStart(cHTTPFormParser &, const AString & a_FileName) override
+ {
+ UNUSED(a_FileName);
+ }
+ virtual void OnFileData(cHTTPFormParser &, const char * a_Data, int a_Size) override
+ {
+ UNUSED(a_Data);
+ UNUSED(a_Size);
+ }
+ virtual void OnFileEnd(cHTTPFormParser &) override {}
} ;
diff --git a/src/World.cpp b/src/World.cpp
index 28c46c27e..1cf82d641 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -10,6 +10,7 @@
#include "Root.h"
#include "inifile/iniFile.h"
#include "ChunkMap.h"
+#include "Generating/ChunkDesc.h"
#include "OSSupport/Timer.h"
// Entities (except mobs):
@@ -238,6 +239,7 @@ cWorld::cWorld(const AString & a_WorldName) :
m_SkyDarkness(0),
m_Weather(eWeather_Sunny),
m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :)
+ m_GeneratorCallbacks(*this),
m_TickThread(*this)
{
LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str());
@@ -367,10 +369,13 @@ void cWorld::InitializeSpawn(void)
cWorldLoadProgress Progress(this);
// Wait for the loader to finish loading
- m_Storage.WaitForQueuesEmpty();
+ m_Storage.WaitForLoadQueueEmpty();
// Wait for the generator to finish generating
m_Generator.WaitForQueueEmpty();
+
+ // Wait for the loader to finish saving
+ m_Storage.WaitForSaveQueueEmpty();
Progress.Stop();
}
@@ -580,7 +585,7 @@ void cWorld::Start(void)
m_Lighting.Start(this);
m_Storage.Start(this, m_StorageSchema);
- m_Generator.Start(this, IniFile);
+ m_Generator.Start(m_GeneratorCallbacks, m_GeneratorCallbacks, IniFile);
m_ChunkSender.Start(this);
m_TickThread.Start();
@@ -723,6 +728,7 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
void cWorld::TickWeather(float a_Dt)
{
+ UNUSED(a_Dt);
// There are no weather changes anywhere but in the Overworld:
if (GetDimension() != dimOverworld)
{
@@ -794,7 +800,7 @@ void cWorld::TickMobs(float a_Dt)
cMonster::mfAmbient,
cMonster::mfWater,
} ;
- for (int i = 0; i < ARRAYCOUNT(AllFamilies); i++)
+ for (size_t i = 0; i < ARRAYCOUNT(AllFamilies); i++)
{
cMonster::eFamily Family = AllFamilies[i];
int SpawnDelay = cMonster::GetSpawnDelay(Family);
@@ -1643,6 +1649,7 @@ int cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward)
void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec, double a_InitialVelocityCoeff)
{
+ UNUSED(a_InitialVelocityCoeff);
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec);
TNT->Initialize(this);
// TODO: Add a bit of speed in horiz and vert axes, based on the a_InitialVelocityCoeff
@@ -2838,3 +2845,77 @@ void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World)
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cWorld::cChunkGeneratorCallbacks:
+
+cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks(cWorld & a_World) :
+ m_World(&a_World)
+{
+}
+
+
+
+
+
+void cWorld::cChunkGeneratorCallbacks::OnChunkGenerated(cChunkDesc & a_ChunkDesc)
+{
+ cChunkDef::BlockNibbles BlockMetas;
+ a_ChunkDesc.CompressBlockMetas(BlockMetas);
+
+ m_World->SetChunkData(
+ a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(),
+ a_ChunkDesc.GetBlockTypes(), BlockMetas,
+ NULL, NULL, // We don't have lighting, chunk will be lighted when needed
+ &a_ChunkDesc.GetHeightMap(), &a_ChunkDesc.GetBiomeMap(),
+ a_ChunkDesc.GetEntities(), a_ChunkDesc.GetBlockEntities(),
+ true
+ );
+
+ // Save the chunk right after generating, so that we don't have to generate it again on next run
+ m_World->GetStorage().QueueSaveChunk(a_ChunkDesc.GetChunkX(), 0, a_ChunkDesc.GetChunkZ());
+}
+
+
+
+
+
+bool cWorld::cChunkGeneratorCallbacks::IsChunkValid(int a_ChunkX, int a_ChunkZ)
+{
+ return m_World->IsChunkValid(a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
+bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
+{
+ return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
+void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerating(cChunkDesc & a_ChunkDesc)
+{
+ cPluginManager::Get()->CallHookChunkGenerating(
+ m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
+ );
+}
+
+
+
+
+
+void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_ChunkDesc)
+{
+ cPluginManager::Get()->CallHookChunkGenerated(
+ m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
+ );
+}
+
+
+
+
+
diff --git a/src/World.h b/src/World.h
index c067252d9..b61708d03 100644
--- a/src/World.h
+++ b/src/World.h
@@ -78,6 +78,7 @@ public:
class cTask
{
public:
+ virtual ~cTask(){};
virtual void Run(cWorld & a_World) = 0;
} ;
@@ -145,7 +146,7 @@ public:
// Broadcast respective packets to all clients of the chunk where the event is taking place
// (Please keep these alpha-sorted)
void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
- void BroadcastBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = NULL);
+ void BroadcastBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = NULL); // tolua_export
void BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = NULL);
void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude
void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = NULL); // tolua_export
@@ -635,6 +636,27 @@ private:
virtual void Execute(void) override;
} ;
+
+ /** Implementation of the callbacks that the ChunkGenerator uses to store new chunks and interface to plugins */
+ class cChunkGeneratorCallbacks :
+ public cChunkGenerator::cChunkSink,
+ public cChunkGenerator::cPluginInterface
+ {
+ cWorld * m_World;
+
+ // cChunkSink overrides:
+ virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
+ virtual bool IsChunkValid (int a_ChunkX, int a_ChunkZ) override;
+ virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) override;
+
+ // cPluginInterface overrides:
+ virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
+ virtual void CallHookChunkGenerated (cChunkDesc & a_ChunkDesc) override;
+
+ public:
+ cChunkGeneratorCallbacks(cWorld & a_World);
+ } ;
+
AString m_WorldName;
AString m_IniFileName;
@@ -713,6 +735,9 @@ private:
cChunkGenerator m_Generator;
+ /** The callbacks that the ChunkGenerator uses to store new chunks and interface to plugins */
+ cChunkGeneratorCallbacks m_GeneratorCallbacks;
+
cChunkSender m_ChunkSender;
cLightingThread m_Lighting;
cTickThread m_TickThread;
diff --git a/src/WorldStorage/CMakeLists.txt b/src/WorldStorage/CMakeLists.txt
index d431bdf6a..2c83c4662 100644
--- a/src/WorldStorage/CMakeLists.txt
+++ b/src/WorldStorage/CMakeLists.txt
@@ -9,3 +9,5 @@ file(GLOB SOURCE
)
add_library(WorldStorage ${SOURCE})
+
+target_link_libraries(WorldStorage OSSupport)
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index e55011069..8f80c3f75 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -16,9 +16,12 @@
#define NBT_RESERVE_SIZE 200
#endif // NBT_RESERVE_SIZE
-#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (0)
-
-
+#ifdef _MSC_VER
+ // Dodge a C4127 (conditional expression is constant) for this specific macro usage
+ #define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while ((false, false))
+#else
+ #define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (false)
+#endif
@@ -80,7 +83,7 @@ bool cParsedNBT::ReadString(int & a_StringStart, int & a_StringLen)
{
NEEDBYTES(2);
a_StringStart = m_Pos + 2;
- a_StringLen = ntohs(*((short *)(m_Data + m_Pos)));
+ a_StringLen = GetBEShort(m_Data + m_Pos);
if (a_StringLen < 0)
{
// Invalid string length
@@ -99,7 +102,7 @@ bool cParsedNBT::ReadCompound(void)
// Reads the latest tag as a compound
int ParentIdx = m_Tags.size() - 1;
int PrevSibling = -1;
- while (true)
+ for (;;)
{
NEEDBYTES(1);
eTagType TagType = (eTagType)(m_Data[m_Pos]);
@@ -135,7 +138,7 @@ bool cParsedNBT::ReadList(eTagType a_ChildrenType)
// Read the count:
NEEDBYTES(4);
- int Count = ntohl(*((int *)(m_Data + m_Pos)));
+ int Count = GetBEInt(m_Data + m_Pos);
m_Pos += 4;
if (Count < 0)
{
@@ -197,7 +200,7 @@ bool cParsedNBT::ReadTag(void)
case TAG_ByteArray:
{
NEEDBYTES(4);
- int len = ntohl(*((int *)(m_Data + m_Pos)));
+ int len = GetBEInt(m_Data + m_Pos);
m_Pos += 4;
if (len < 0)
{
@@ -229,7 +232,7 @@ bool cParsedNBT::ReadTag(void)
case TAG_IntArray:
{
NEEDBYTES(4);
- int len = ntohl(*((int *)(m_Data + m_Pos)));
+ int len = GetBEInt(m_Data + m_Pos);
m_Pos += 4;
if (len < 0)
{
@@ -276,7 +279,7 @@ int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLen
for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
{
if (
- (m_Tags[Child].m_NameLength == a_NameLength) &&
+ (m_Tags[Child].m_NameLength == (int)a_NameLength) &&
(memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
)
{
@@ -401,7 +404,7 @@ void cFastNBTWriter::EndList(void)
ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);
// Update the list count:
- *((int *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos)) = htonl(m_Stack[m_CurrentStack].m_Count);
+ SetBEInt((char *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos), m_Stack[m_CurrentStack].m_Count);
--m_CurrentStack;
}
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index 7323c29cb..b84eda1a1 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -154,13 +154,13 @@ public:
inline Int16 GetShort(int a_Tag) const
{
ASSERT(m_Tags[a_Tag].m_Type == TAG_Short);
- return ntohs(*((Int16 *)(m_Data + m_Tags[a_Tag].m_DataStart)));
+ return GetBEShort(m_Data + m_Tags[a_Tag].m_DataStart);
}
inline Int32 GetInt(int a_Tag) const
{
ASSERT(m_Tags[a_Tag].m_Type == TAG_Int);
- return ntohl(*((Int32 *)(m_Data + m_Tags[a_Tag].m_DataStart)));
+ return GetBEInt(m_Data + m_Tags[a_Tag].m_DataStart);
}
inline Int64 GetLong(int a_Tag) const
@@ -172,7 +172,7 @@ public:
inline float GetFloat(int a_Tag) const
{
ASSERT(m_Tags[a_Tag].m_Type == TAG_Float);
- Int32 tmp = ntohl(*((Int32 *)(m_Data + m_Tags[a_Tag].m_DataStart)));
+ Int32 tmp = GetBEInt(m_Data + m_Tags[a_Tag].m_DataStart);
return *((float *)&tmp);
}
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index f290ec128..6aec525a8 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -17,7 +17,6 @@
-
/// If a chunk with this Y coord is de-queued, it is a signal to emit the saved-all message (cWorldStorage::QueueSavedMessage())
#define CHUNK_Y_MESSAGE 2
@@ -63,8 +62,6 @@ cWorldStorage::~cWorldStorage()
{
delete *itr;
} // for itr - m_Schemas[]
- m_LoadQueue.clear();
- m_SaveQueue.clear();
}
@@ -98,18 +95,15 @@ void cWorldStorage::WaitForFinish(void)
LOG("Waiting for the world storage to finish saving");
{
- // Cancel all loading requests:
- cCSLock Lock(m_CSQueues);
- m_LoadQueue.clear();
+ m_LoadQueue.Clear();
}
// Wait for the saving to finish:
- WaitForQueuesEmpty();
+ WaitForSaveQueueEmpty();
// Wait for the thread to finish:
m_ShouldTerminate = true;
- m_Event.Set();
- m_evtRemoved.Set(); // Wake up anybody waiting in the WaitForQueuesEmpty() method
+ m_Event.Set(); // Wake up the thread if waiting
super::Wait();
LOG("World storage thread finished");
}
@@ -118,34 +112,36 @@ void cWorldStorage::WaitForFinish(void)
-void cWorldStorage::WaitForQueuesEmpty(void)
+void cWorldStorage::WaitForLoadQueueEmpty(void)
{
- cCSLock Lock(m_CSQueues);
- while (!m_ShouldTerminate && (!m_LoadQueue.empty() || !m_SaveQueue.empty()))
- {
- cCSUnlock Unlock(Lock);
- m_evtRemoved.Wait();
- }
+ m_LoadQueue.BlockTillEmpty();
+}
+
+
+
+
+
+void cWorldStorage::WaitForSaveQueueEmpty(void)
+{
+ m_SaveQueue.BlockTillEmpty();
}
-int cWorldStorage::GetLoadQueueLength(void)
+size_t cWorldStorage::GetLoadQueueLength(void)
{
- cCSLock Lock(m_CSQueues);
- return (int)m_LoadQueue.size();
+ return m_LoadQueue.Size();
}
-int cWorldStorage::GetSaveQueueLength(void)
+size_t cWorldStorage::GetSaveQueueLength(void)
{
- cCSLock Lock(m_CSQueues);
- return (int)m_SaveQueue.size();
+ return m_SaveQueue.Size();
}
@@ -154,21 +150,7 @@ int cWorldStorage::GetSaveQueueLength(void)
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate)
{
- // Queues the chunk for loading; if not loaded, the chunk will be generated
- {
- cCSLock Lock(m_CSQueues);
-
- // Check if already in the queue:
- for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr)
- {
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ) && (itr->m_Generate == a_Generate))
- {
- return;
- }
- }
- m_LoadQueue.push_back(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate));
- }
-
+ m_LoadQueue.EnqueueItemIfNotPresent(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate));
m_Event.Set();
}
@@ -178,11 +160,7 @@ void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, boo
void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- {
- cCSLock Lock(m_CSQueues);
- m_SaveQueue.remove (cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); // Don't add twice
- m_SaveQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
- }
+ m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
m_Event.Set();
}
@@ -192,11 +170,8 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cWorldStorage::QueueSavedMessage(void)
{
- // Pushes a special coord pair into the queue, signalizing a message instead:
- {
- cCSLock Lock(m_CSQueues);
- m_SaveQueue.push_back(cChunkCoords(0, CHUNK_Y_MESSAGE, 0));
- }
+ // Pushes a special coord pair into the queue, signalizing a message instead
+ m_SaveQueue.EnqueueItem(cChunkCoords(0, CHUNK_Y_MESSAGE, 0));
m_Event.Set();
}
@@ -206,18 +181,7 @@ void cWorldStorage::QueueSavedMessage(void)
void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- cCSLock Lock(m_CSQueues);
- for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr)
- {
- if ((itr->m_ChunkX != a_ChunkX) || (itr->m_ChunkY != a_ChunkY) || (itr->m_ChunkZ != a_ChunkZ))
- {
- continue;
- }
- m_LoadQueue.erase(itr);
- Lock.Unlock();
- m_evtRemoved.Set();
- return;
- } // for itr - m_LoadQueue[]
+ m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ,true));
}
@@ -226,11 +190,7 @@ void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cWorldStorage::UnqueueSave(const cChunkCoords & a_Chunk)
{
- {
- cCSLock Lock(m_CSQueues);
- m_SaveQueue.remove(a_Chunk);
- }
- m_evtRemoved.Set();
+ m_SaveQueue.Remove(a_Chunk);
}
@@ -279,21 +239,19 @@ void cWorldStorage::Execute(void)
while (!m_ShouldTerminate)
{
m_Event.Wait();
-
// Process both queues until they are empty again:
- bool HasMore;
+ bool Success;
do
{
- HasMore = false;
+ Success = false;
if (m_ShouldTerminate)
{
return;
}
- HasMore = LoadOneChunk();
- HasMore = HasMore | SaveOneChunk();
- m_evtRemoved.Set();
- } while (HasMore);
+ Success = LoadOneChunk();
+ Success |= SaveOneChunk();
+ } while (Success);
}
}
@@ -304,19 +262,7 @@ void cWorldStorage::Execute(void)
bool cWorldStorage::LoadOneChunk(void)
{
sChunkLoad ToLoad(0, 0, 0, false);
- bool HasMore;
- bool ShouldLoad = false;
- {
- cCSLock Lock(m_CSQueues);
- if (!m_LoadQueue.empty())
- {
- ToLoad = m_LoadQueue.front();
- m_LoadQueue.pop_front();
- ShouldLoad = true;
- }
- HasMore = !m_LoadQueue.empty();
- }
-
+ bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ))
{
if (ToLoad.m_Generate)
@@ -330,7 +276,7 @@ bool cWorldStorage::LoadOneChunk(void)
// m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ);
}
}
- return HasMore;
+ return ShouldLoad;
}
@@ -339,33 +285,24 @@ bool cWorldStorage::LoadOneChunk(void)
bool cWorldStorage::SaveOneChunk(void)
{
- cChunkCoords Save(0, 0, 0);
- bool HasMore;
- bool ShouldSave = false;
- {
- cCSLock Lock(m_CSQueues);
- if (!m_SaveQueue.empty())
+ cChunkCoords ToSave(0, 0, 0);
+ bool ShouldSave = m_SaveQueue.TryDequeueItem(ToSave);
+ if(ShouldSave) {
+ if (ToSave.m_ChunkY == CHUNK_Y_MESSAGE)
{
- Save = m_SaveQueue.front();
- m_SaveQueue.pop_front();
- ShouldSave = true;
+ LOGINFO("Saved all chunks in world %s", m_World->GetName().c_str());
+ return ShouldSave;
}
- HasMore = !m_SaveQueue.empty();
- }
- if (Save.m_ChunkY == CHUNK_Y_MESSAGE)
- {
- LOGINFO("Saved all chunks in world %s", m_World->GetName().c_str());
- return HasMore;
- }
- if (ShouldSave && m_World->IsChunkValid(Save.m_ChunkX, Save.m_ChunkZ))
- {
- m_World->MarkChunkSaving(Save.m_ChunkX, Save.m_ChunkZ);
- if (m_SaveSchema->SaveChunk(Save))
+ if (ShouldSave && m_World->IsChunkValid(ToSave.m_ChunkX, ToSave.m_ChunkZ))
{
- m_World->MarkChunkSaved(Save.m_ChunkX, Save.m_ChunkZ);
+ m_World->MarkChunkSaving(ToSave.m_ChunkX, ToSave.m_ChunkZ);
+ if (m_SaveSchema->SaveChunk(ToSave))
+ {
+ m_World->MarkChunkSaved(ToSave.m_ChunkX, ToSave.m_ChunkZ);
+ }
}
}
- return HasMore;
+ return ShouldSave;
}
diff --git a/src/WorldStorage/WorldStorage.h b/src/WorldStorage/WorldStorage.h
index 007d37571..06cae1717 100644
--- a/src/WorldStorage/WorldStorage.h
+++ b/src/WorldStorage/WorldStorage.h
@@ -16,6 +16,7 @@
#include "../ChunkDef.h"
#include "../OSSupport/IsThread.h"
+#include "../OSSupport/Queue.h"
@@ -24,6 +25,8 @@
// fwd:
class cWorld;
+typedef cQueue<cChunkCoords> cChunkCoordsQueue;
+
@@ -76,10 +79,11 @@ public:
bool Start(cWorld * a_World, const AString & a_StorageSchemaName); // Hide the cIsThread's Start() method, we need to provide args
void Stop(void); // Hide the cIsThread's Stop() method, we need to signal the event
void WaitForFinish(void);
- void WaitForQueuesEmpty(void);
+ void WaitForLoadQueueEmpty(void);
+ void WaitForSaveQueueEmpty(void);
- int GetLoadQueueLength(void);
- int GetSaveQueueLength(void);
+ size_t GetLoadQueueLength(void);
+ size_t GetSaveQueueLength(void);
protected:
@@ -91,20 +95,30 @@ protected:
bool m_Generate; // If true, the chunk will be generated if it cannot be loaded
sChunkLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkY(a_ChunkY), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {}
+
+ bool operator==(const sChunkLoad other) const
+ {
+ return this->m_ChunkX == other.m_ChunkX &&
+ this->m_ChunkY == other.m_ChunkY &&
+ this->m_ChunkZ == other.m_ChunkZ;
+ }
} ;
-
- typedef std::list<sChunkLoad> sChunkLoadQueue;
+
+ struct FuncTable {
+ static void Delete(sChunkLoad) {};
+ static void Combine(sChunkLoad& a_orig, const sChunkLoad a_new)
+ {
+ a_orig.m_Generate |= a_new.m_Generate;
+ };
+ };
+
+ typedef cQueue<sChunkLoad,FuncTable> sChunkLoadQueue;
cWorld * m_World;
AString m_StorageSchemaName;
-
- // Both queues are locked by the same CS
- cCriticalSection m_CSQueues;
+
sChunkLoadQueue m_LoadQueue;
- cChunkCoordsList m_SaveQueue;
-
- cEvent m_Event; // Set when there's any addition to the queues
- cEvent m_evtRemoved; // Set when an item has been removed from the queue, either by the worker thread or the Unqueue methods
+ cChunkCoordsQueue m_SaveQueue;
/// All the storage schemas (all used for loading)
cWSSchemaList m_Schemas;
@@ -116,6 +130,8 @@ protected:
virtual void Execute(void) override;
+ cEvent m_Event; // Set when there's any addition to the queues
+
/// Loads one chunk from the queue (if any queued); returns true if there are more chunks in the load queue
bool LoadOneChunk(void);
diff --git a/src/main.cpp b/src/main.cpp
index 81c6b41e4..0620e0f0e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -50,6 +50,11 @@ void NonCtrlHandler(int a_Signal)
LOGWARN("Segmentation fault; MCServer has crashed :(");
exit(EXIT_FAILURE);
}
+ case SIGTERM:
+ {
+ std::signal(SIGTERM, SIG_IGN); // Server is shutting down, wait for it...
+ break;
+ }
default: break;
}
}