summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua2
-rw-r--r--MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html6
-rw-r--r--MCServer/Plugins/APIDump/main_APIDump.lua2
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua19
-rw-r--r--MCServer/Plugins/InfoDump.deproj6
-rw-r--r--MCServer/Plugins/InfoDump.lua361
-rw-r--r--README.md4
-rw-r--r--VC2008/CryptoPP.vcproj3
-rw-r--r--VC2008/MCServer.vcproj4
-rw-r--r--src/Bindings/ManualBindings.cpp19
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp8
-rw-r--r--src/BlockEntities/HopperEntity.cpp1
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Globals.h18
-rw-r--r--src/HTTPServer/HTTPConnection.cpp2
-rw-r--r--src/HTTPServer/HTTPFormParser.cpp1
-rw-r--r--src/HTTPServer/NameValueParser.cpp1
-rw-r--r--src/Item.cpp2
-rw-r--r--src/Item.h4
-rw-r--r--src/OSSupport/CriticalSection.h5
-rw-r--r--src/OSSupport/Queue.h145
-rw-r--r--src/Protocol/Protocol132.cpp17
-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.cpp1
-rw-r--r--src/Protocol/Protocol17x.h14
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp2
-rw-r--r--src/Server.h17
-rw-r--r--src/StringUtils.cpp48
-rw-r--r--src/StringUtils.h3
-rw-r--r--src/World.h2
-rw-r--r--src/WorldStorage/WorldStorage.cpp11
33 files changed, 662 insertions, 97 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index d388d15dd..26537918e 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -1713,7 +1713,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "bool", Notes = "Same as ExecuteCommand, but doesn't check permissions" },
ForEachCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function(Command, Permission, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
ForEachConsoleCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function (Command, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
- Get = { Params = "", Return = "cPluginManager", Notes = "Returns the single instance of the plugin manager" },
+ Get = { Params = "", Return = "cPluginManager", Notes = "(STATIC) Returns the single instance of the plugin manager" },
GetAllPlugins = { Params = "", Return = "table", Notes = "Returns a table (dictionary) of all plugins, [name => {{cPlugin}}] pairing." },
GetCommandPermission = { Params = "Command", Return = "Permission", Notes = "Returns the permission needed for executing the specified command" },
GetCurrentPlugin = { Params = "", Return = "{{cPlugin}}", Notes = "Returns the {{cPlugin}} object for the calling plugin. This is the same object that the Initialize function receives as the argument." },
diff --git a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
index 50e39d533..0e07cebdf 100644
--- a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
+++ b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
@@ -84,7 +84,7 @@ end
To register a hook, insert the following code template into the "-- Hooks" area in the previous code example.
</p>
<pre class="prettyprint lang-lua">
-cPluginManager.AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
+cPluginManager:AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
</pre>
<p>
What does this code do?
@@ -102,7 +102,7 @@ function Initialize(Plugin)
Plugin:SetName("DerpyPlugin")
Plugin:SetVersion(1)
- cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
+ cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
local PluginManager = cPluginManager:Get()
-- Command bindings
@@ -200,7 +200,7 @@ function Initialize(Plugin)
local PluginManager = cPluginManager:Get()
PluginManager:BindCommand("/explode", "derpyplugin.explode", Explode, " ~ Explode a player");
- cPluginManager.AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup)
+ cPluginManager:AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup)
LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
return true
diff --git a/MCServer/Plugins/APIDump/main_APIDump.lua b/MCServer/Plugins/APIDump/main_APIDump.lua
index b3a95eb22..bd509dcb6 100644
--- a/MCServer/Plugins/APIDump/main_APIDump.lua
+++ b/MCServer/Plugins/APIDump/main_APIDump.lua
@@ -1177,7 +1177,7 @@ function WriteHtmlHook(a_Hook, a_HookNav)
f:write("</table>\n<p>" .. (a_Hook.Returns or "") .. "</p>\n\n");
f:write([[<hr /><h1>Code examples</h1><h2>Registering the callback</h2>]]);
f:write("<pre class=\"prettyprint lang-lua\">\n");
- f:write([[cPluginManager.AddHook(cPluginManager.]] .. a_Hook.Name .. ", My" .. a_Hook.DefaultFnName .. [[);]]);
+ f:write([[cPluginManager:AddHook(cPluginManager.]] .. a_Hook.Name .. ", My" .. a_Hook.DefaultFnName .. [[);]]);
f:write("</pre>\n\n");
local Examples = a_Hook.CodeExamples or {};
for i, example in ipairs(Examples) do
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 8f2fa3682..c769edc3e 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -963,3 +963,22 @@ end
+
+-- Test the hook adding formats in #121 and #401
+local function DoNothing()
+end
+
+LOG("Trying cPluginManager:AddHook()");
+cPluginManager:AddHook(cPluginManager.HOOK_CHAT, DoNothing);
+
+LOG("Trying cPluginManager.AddHook()");
+cPluginManager.AddHook(cPluginManager.HOOK_CHAT, DoNothing);
+
+LOG("Trying cPluginManager:Get():AddHook()");
+cPluginManager:Get():AddHook(cPluginManager.HOOK_CHAT, DoNothing);
+
+LOG("Trying cPluginManager:Get():AddHook(Plugin, Hook)");
+cPluginManager:Get():AddHook(cPluginManager:GetCurrentPlugin(), cPluginManager.HOOK_CHAT);
+
+LOG("Trying cPluginManager.AddHook(Plugin, Hook)");
+cPluginManager.AddHook(cPluginManager:GetCurrentPlugin(), cPluginManager.HOOK_CHAT);
diff --git a/MCServer/Plugins/InfoDump.deproj b/MCServer/Plugins/InfoDump.deproj
new file mode 100644
index 000000000..30003c36d
--- /dev/null
+++ b/MCServer/Plugins/InfoDump.deproj
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project>
+ <file>
+ <filename>InfoDump.lua</filename>
+ </file>
+</project>
diff --git a/MCServer/Plugins/InfoDump.lua b/MCServer/Plugins/InfoDump.lua
new file mode 100644
index 000000000..df47d566b
--- /dev/null
+++ b/MCServer/Plugins/InfoDump.lua
@@ -0,0 +1,361 @@
+#!/usr/bin/lua
+
+-- InfoDump.lua
+
+-- Goes through all subfolders, loads Info.lua and dumps its g_PluginInfo into various text formats
+-- This is used for generating plugin documentation for the forum and for GitHub's INFO.md files
+
+-- This script requires LuaRocks with LFS installed, instructions are printed when this is not present.
+
+
+
+
+
+-- Check Lua version. We use 5.1-specific construct when loading the plugin info, 5.2 is not compatible!
+if (_VERSION ~= "Lua 5.1") then
+ print("Unsupported Lua version. This script requires Lua version 5.1, this Lua is version " .. (_VERSION or "<nil>"));
+ return;
+end
+
+-- Try to load lfs, do not abort if not found
+local lfs, err = pcall(
+ function()
+ return require("lfs")
+ end
+);
+
+-- Rather, print a nice message with instructions:
+if not(lfs) then
+ print([[
+Cannot load LuaFileSystem
+Install it through luarocks by executing the following command:
+ sudo luarocks install luafilesystem
+
+If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
+ sudo apt-get install luarocks
+On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
+]]);
+
+ print("Original error text: ", err);
+ return;
+end
+
+-- We now know that LFS is present, get it normally:
+lfs = require("lfs");
+
+
+
+
+
+
+--- Replaces generic formatting with forum-specific formatting
+-- Also removes the single line-ends
+local function ForumizeString(a_Str)
+ assert(type(a_Str) == "string");
+
+ -- Remove the indentation, unless in the code tag:
+ -- Only one code or /code tag per line is supported!
+ local IsInCode = false;
+ local function RemoveIndentIfNotInCode(s)
+ if (IsInCode) then
+ -- we're in code section, check if this line terminates it
+ IsInCode = (s:find("{%%/code}") ~= nil);
+ return s .. "\n";
+ else
+ -- we're not in code section, check if this line starts it
+ IsInCode = (s:find("{%%code}") ~= nil);
+ return s:gsub("^%s*", "") .. "\n";
+ end
+ end
+ a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode);
+
+ -- Replace multiple line ends with {%p} and single line ends with a space,
+ -- so that manual word-wrap in the Info.lua file doesn't wrap in the forum.
+ a_Str = a_Str:gsub("\n\n", "{%%p}");
+ a_Str = a_Str:gsub("\n", " ");
+
+ -- Replace the generic formatting:
+ a_Str = a_Str:gsub("{%%p}", "\n\n");
+ a_Str = a_Str:gsub("{%%b}", "[b]"):gsub("{%%/b}", "[/b]");
+ a_Str = a_Str:gsub("{%%i}", "[i]"):gsub("{%%/i}", "[/i]");
+ a_Str = a_Str:gsub("{%%list}", "[list]"):gsub("{%%/list}", "[/list]");
+ a_Str = a_Str:gsub("{%%li}", "[*]"):gsub("{%%/li}", "");
+ -- TODO: Other formatting
+
+ return a_Str;
+end
+
+
+
+
+
+--- Builds an array of categories, each containing all the commands belonging to the category,
+-- and the category description, if available.
+-- Returns the array table, each item has the following format:
+-- { Name = "CategoryName", Description = "CategoryDescription", Commands = {{CommandString = "/cmd verb", Info = {...}}, ...}}
+local function BuildCategories(a_PluginInfo)
+ -- The returned result
+ -- This will contain both an array and a dict of the categories, to allow fast search
+ local res = {};
+
+ -- For each command add a reference to it into all of its categories:
+ local function AddCommands(a_CmdPrefix, a_Commands)
+ for cmd, info in pairs(a_Commands) do
+ local NewCmd =
+ {
+ CommandString = a_CmdPrefix .. cmd,
+ Info = info,
+ }
+
+ if ((info.HelpString ~= nil) and (info.HelpString ~= "")) then
+ -- Add to each specified category:
+ local Category = info.Category;
+ if (type(Category) == "string") then
+ Category = {Category};
+ end
+ for idx, cat in ipairs(Category or {""}) do
+ local CatEntry = res[cat];
+ if (CatEntry == nil) then
+ -- First time we came across this category, create it:
+ local NewCat = {Name = cat, Description = "", Commands = {NewCmd}};
+ table.insert(res, NewCat);
+ res[cat] = NewCat;
+ else
+ -- We already have this category, just add the command to its list of commands:
+ table.insert(CatEntry.Commands, NewCmd);
+ end
+ end -- for idx, cat - Category[]
+ end -- if (HelpString valid)
+
+ -- Recurse all subcommands:
+ if (info.Subcommands ~= nil) then
+ AddCommands(a_CmdPrefix .. cmd .. " ", info.Subcommands);
+ end
+ end -- for cmd, info - a_Commands[]
+ end -- AddCommands()
+
+ AddCommands("", a_PluginInfo.Commands);
+
+ -- Assign descriptions to categories:
+ for name, desc in pairs(a_PluginInfo.Categories or {}) do
+ local CatEntry = res[name];
+ if (CatEntry ~= nil) then
+ -- The result has this category, add the description:
+ CatEntry.Description = desc.Description;
+ end
+ end
+
+ -- Alpha-sort each category's command list:
+ for idx, cat in ipairs(res) do
+ table.sort(cat.Commands,
+ function (cmd1, cmd2)
+ return (string.lower(cmd1.CommandString) < string.lower(cmd2.CommandString));
+ end
+ );
+ end
+
+ return res;
+end
+
+
+
+
+
+--- Writes the specified command detailed help array to the output file, in the forum dump format
+local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCombinations, f)
+ assert(type(a_CmdString) == "string");
+ assert(type(a_ParameterCombinations) == "table");
+ assert(f ~= nil);
+
+ if (#a_ParameterCombinations == 0) then
+ -- No explicit parameter combinations to write
+ return;
+ end
+
+ f:write("The following parameter combinations are recognized:\n");
+ for idx, combination in ipairs(a_ParameterCombinations) do
+ f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params, "[/color]");
+ if (combination.Help ~= nil) then
+ f:write(" - ", ForumizeString(combination.Help));
+ end
+ if (combination.Permission ~= nil) then
+ f:write(" (Requires permission '[color=red]", combination.Permission, "[/color]')");
+ end
+ f:write("\n");
+ end
+end
+
+
+
+
+
+--- Writes all commands in the specified category to the output file, in the forum dump format
+local function WriteCommandsCategoryForum(a_Category, f)
+ -- Write category name:
+ local CategoryName = a_Category.Name;
+ if (CategoryName == "") then
+ CategoryName = "General";
+ end
+ f:write("\n[size=Large]", ForumizeString(a_Category.DisplayName or CategoryName), "[/size]\n");
+
+ -- Write description:
+ if (a_Category.Description ~= "") then
+ f:write(ForumizeString(a_Category.Description), "\n");
+ end
+
+ -- Write commands:
+ f:write("\n[list]");
+ for idx2, cmd in ipairs(a_Category.Commands) do
+ f:write("\n[b]", cmd.CommandString, "[/b] - ", ForumizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n");
+ if (cmd.Info.Permission ~= nil) then
+ f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n");
+ end
+ if (cmd.Info.DetailedDescription ~= nil) then
+ f:write(cmd.Info.DetailedDescription);
+ end
+ if (cmd.Info.ParameterCombinations ~= nil) then
+ WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f);
+ end
+ end
+ f:write("[/list]\n\n")
+end
+
+
+
+
+
+local function DumpCommandsForum(a_PluginInfo, f)
+ -- Copy all Categories from a dictionary into an array:
+ local Categories = BuildCategories(a_PluginInfo);
+
+ -- Sort the categories by name:
+ table.sort(Categories,
+ function(cat1, cat2)
+ return (string.lower(cat1.Name) < string.lower(cat2.Name));
+ end
+ );
+
+ if (#Categories == 0) then
+ return;
+ end
+
+ f:write("\n[size=X-Large]Commands[/size]\n");
+
+ -- Dump per-category commands:
+ for idx, cat in ipairs(Categories) do
+ WriteCommandsCategoryForum(cat, f);
+ end
+end
+
+
+
+
+
+local function DumpAdditionalInfoForum(a_PluginInfo, f)
+ local AInfo = a_PluginInfo.AdditionalInfo;
+ if ((AInfo == nil) or (type(AInfo) ~= "table")) then
+ -- There is no AdditionalInfo in a_PluginInfo
+ return;
+ end
+
+ for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do
+ if ((info.Title ~= nil) and (info.Contents ~= nil)) then
+ f:write("\n[size=X-Large]", ForumizeString(info.Title), "[/size]\n");
+ f:write(ForumizeString(info.Contents), "\n");
+ end
+ end
+end
+
+
+
+
+
+local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
+ -- Open the output file:
+ local f, msg = io.open(a_PluginInfo.Name .. "_forum.txt", "w");
+ if (f == nil) then
+ print("\tCannot dump forum info for plugin " .. a_PluginFolder .. ": " .. msg);
+ return;
+ end
+
+ -- Write the description:
+ f:write(ForumizeString(a_PluginInfo.Description), "\n");
+ DumpAdditionalInfoForum(a_PluginInfo, f);
+ DumpCommandsForum(a_PluginInfo, f);
+
+ f:close();
+end
+
+
+
+
+
+local function DumpPluginInfoGitHub()
+ -- TODO
+end
+
+
+
+
+
+--- Tries to load the g_PluginInfo from the plugin's Info.lua file
+-- Returns the g_PluginInfo table on success, or nil and error message on failure
+local function LoadPluginInfo(a_FolderName)
+ -- Check if the Info file is present at all:
+ local Attribs = lfs.attributes(a_FolderName .. "/Info.lua");
+ if ((Attribs == nil) or (Attribs.mode ~= "file")) then
+ return nil;
+ end
+
+ -- Load and compile the Info file:
+ local cfg, err = loadfile(a_FolderName .. "/Info.lua");
+ if (cfg == nil) then
+ return nil, "Cannot open 'Info.lua': " .. err;
+ end
+
+ -- Execute the loaded file in a sandbox:
+ -- This is Lua-5.1-specific and won't work in Lua 5.2!
+ local Sandbox = {};
+ setfenv(cfg, Sandbox);
+ cfg();
+ if (Sandbox.g_PluginInfo == nil) then
+ return nil, "Info.lua doesn't contain the g_PluginInfo declaration";
+ end
+ return Sandbox.g_PluginInfo;
+end
+
+
+
+
+
+local function ProcessPluginFolder(a_FolderName)
+ local PluginInfo, Msg = LoadPluginInfo(a_FolderName);
+ if (PluginInfo == nil) then
+ if (Msg ~= nil) then
+ print("\tCannot load Info.lua: " .. Msg);
+ end
+ return;
+ end
+ DumpPluginInfoForum(a_FolderName, PluginInfo);
+end
+
+
+
+
+
+print("Processing plugin subfolders:");
+for fnam in lfs.dir(".") do
+ if ((fnam ~= ".") and (fnam ~= "..")) then
+ local Attributes = lfs.attributes(fnam);
+ if (Attributes ~= nil) then
+ if (Attributes.mode == "directory") then
+ print(fnam);
+ ProcessPluginFolder(fnam);
+ end
+ end
+ end
+end
+
+
+
+
diff --git a/README.md b/README.md
index ff30d63b3..9004c531b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
MCServer
========
+**Current Protocol Supported:** Minecraft v1.2 -> v1.7
+
MCServer is a performant C++ Minecraft server designed for use in memory and cpu-limited places, or just to make regular server perform better.
MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis.
@@ -26,7 +28,7 @@ MCServer is licensed under the Apache license V2, and we welcome anybody to fork
Other Stuff
-----------
-For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [wiki](http://mc-server.org/wiki/).
+For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [wiki](http://wiki.mc-server.org/).
Earn bitcoins for commits or donate to reward the MCServer developers: [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
diff --git a/VC2008/CryptoPP.vcproj b/VC2008/CryptoPP.vcproj
index a818e9aa1..f44729d8a 100644
--- a/VC2008/CryptoPP.vcproj
+++ b/VC2008/CryptoPP.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1250"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="CryptoPP"
ProjectGUID="{3423EC9A-52E4-4A4D-9753-EDEBC38785EF}"
RootNamespace="cryptlib"
@@ -60,6 +60,7 @@
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
+ DisableSpecificWarnings="4702"
/>
<Tool
Name="VCManagedResourceCompilerTool"
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index 491e7740e..a017b5a25 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -1579,6 +1579,10 @@
>
</File>
<File
+ RelativePath="..\src\OSSupport\Queue.h"
+ >
+ </File>
+ <File
RelativePath="..\src\OSSupport\Semaphore.cpp"
>
</File>
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 2e19c2581..64f542880 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -1137,16 +1137,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 +1162,12 @@ static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
}
ParamIdx += 1;
}
+ else if (tolua_isusertable(S, 1, "cPluginManager", 0, &err))
+ {
+ LOGD("AddHook recommended style");
+ // Style 1, use the global PlgMgr, but increment ParamIdx
+ ParamIdx++;
+ }
if (lua_isnumber(S, ParamIdx) && lua_isfunction(S, ParamIdx + 1))
{
@@ -1177,7 +1184,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;
}
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/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/CMakeLists.txt b/src/CMakeLists.txt
index bd06798ff..853138769 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -66,7 +66,7 @@ set(EXECUTABLE MCServer)
add_executable(${EXECUTABLE} ${SOURCE})
-set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/MCServer)
+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:
diff --git a/src/Globals.h b/src/Globals.h
index 58badf4dd..1765c53d8 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -14,7 +14,21 @@
#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 : 4189) // Local variable is initialized but not referenced
+ #pragma warning(3 : 4702) // Unreachable code
+ #pragma warning(3 : 4245) // Conversion from 'type1' to 'type2', signed/unsigned mismatch
+ #pragma warning(3 : 4389) // Signed/unsigned mismatch
+ #pragma warning(3 : 4701) // Potentially unitialized local variable used
+ #pragma warning(3 : 4310) // Cast truncates constant value
+ #pragma warning(3 : 4505) // Unreferenced local function has been removed
+ #pragma warning(3 : 4127) // Conditional expression is constant
+ #pragma warning(3 : 4706) // Assignment within conditional expression
+
+ // 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 +206,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
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/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/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/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
index cde26e415..6c3d58295 100644
--- a/src/OSSupport/Queue.h
+++ b/src/OSSupport/Queue.h
@@ -19,123 +19,139 @@ 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
+/// This empty struct allows for the callback functions to be inlined
template<class T>
struct cQueueFuncs
{
- public:
- // Called when an Item is deleted form 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) {};
+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> >
+
+
+
+
+template <class ItemType, class Funcs = cQueueFuncs<ItemType> >
class cQueue
{
-// internal typedef for a List of Items
-typedef typename std::list<ItemType> ListType;
-// magic typedef to persuade clang that the iterator is a type
-typedef typename ListType::iterator iterator;
+ // 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)
+
+ /// 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_Contents.push_back(a_Item);
m_evtAdded.Set();
}
- // Enqueues an item to the queue if not already present as determined with
- // operator ==. Will block other threads from accessing the queue.
- void EnqueueItemIfNotPresent(ItemType a_item)
+
+ /// 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)
+ for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr)
{
- if((*itr) == a_item) {
- Funcs funcTable;
- funcTable.Combine(*itr,a_item);
+ if ((*itr) == a_Item)
+ {
+ Funcs::Combine(*itr, a_Item);
return;
}
}
- m_contents.push_back(a_item);
+ 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)
+
+ /// 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)
+ if (m_Contents.size() == 0)
{
return false;
}
- item = m_contents.front();
- m_contents.pop_front();
+ 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()
+
+ /// Dequeues an item from the queue, blocking until an item is available.
+ ItemType DequeueItem(void)
{
cCSLock Lock(m_CS);
- while (m_contents.size() == 0)
+ while (m_Contents.size() == 0)
{
- cCSUnlock Unlock(m_CS);
+ cCSUnlock Unlock(Lock);
m_evtAdded.Wait();
}
- ItemType item = m_contents.front();
- m_contents.pop_front();
+ ItemType item = m_Contents.front();
+ m_Contents.pop_front();
m_evtRemoved.Set();
return item;
}
- // Blocks Until the queue is Empty, Has a slight race condition which may
- // cause it to miss the queue being empty.
- void BlockTillEmpty() {
- // There is a very slight race condition here if the load completes between the check
- // and the wait.
- while(!(Size() == 0)){m_evtRemoved.Wait();}
+
+ /// 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.
- // can all be inlined when delete is a noop
- void Clear()
+
+ /// Removes all Items from the Queue, calling Delete on each of them.
+ void Clear(void)
{
cCSLock Lock(m_CS);
- Funcs funcTable;
- while (!m_contents.empty())
+ while (!m_Contents.empty())
{
- funcTable.Delete(m_contents.front());
- m_contents.pop_front();
+ Funcs::Delete(m_Contents.front());
+ m_Contents.pop_front();
}
}
- // Returns the Size at time of being called
- // Do not use to detirmine weather to call DequeueItem, use TryDequeue instead
- size_t Size()
+
+ /// 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();
+ return m_Contents.size();
}
- // Removes an Item from the queue
- bool Remove(ItemType a_item)
+
+ /// 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)
+ for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr)
{
- if((*itr) == a_item) {
- m_contents.erase(itr);
+ if ((*itr) == a_Item)
+ {
+ m_Contents.erase(itr);
m_evtRemoved.Set();
return true;
}
@@ -144,8 +160,19 @@ public:
}
private:
- ListType m_contents;
+ /// 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/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 46ac4ef89..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());
@@ -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..d36384a88 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: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
+
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..8536689c3 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -986,7 +986,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
while (true)
{
UInt32 PacketLen;
- int PacketStart = m_ReceivedData.GetDataStart();
if (!m_ReceivedData.ReadVarInt(PacketLen))
{
// Not enough data
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index cc0eda1e7..23ff2365d 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
+
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 1cae4a750..e2ea0e6e5 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);
}
}
diff --git a/src/Server.h b/src/Server.h
index 1f94bb3da..e62c4c7b7 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
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
index 5c6b99d88..8d2352331 100644
--- a/src/StringUtils.cpp
+++ b/src/StringUtils.cpp
@@ -765,6 +765,54 @@ AString Base64Decode(const AString & a_Base64String)
+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','+','/'
+ };
+
+ std::string 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];
diff --git a/src/StringUtils.h b/src/StringUtils.h
index 471e843e4..2373f3843 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -81,6 +81,9 @@ 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);
diff --git a/src/World.h b/src/World.h
index 67f1275c0..f90ddd90f 100644
--- a/src/World.h
+++ b/src/World.h
@@ -146,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
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index 5f4c112d5..6aec525a8 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -117,6 +117,10 @@ void cWorldStorage::WaitForLoadQueueEmpty(void)
m_LoadQueue.BlockTillEmpty();
}
+
+
+
+
void cWorldStorage::WaitForSaveQueueEmpty(void)
{
m_SaveQueue.BlockTillEmpty();
@@ -124,6 +128,8 @@ void cWorldStorage::WaitForSaveQueueEmpty(void)
+
+
size_t cWorldStorage::GetLoadQueueLength(void)
{
return m_LoadQueue.Size();
@@ -144,8 +150,8 @@ size_t cWorldStorage::GetSaveQueueLength(void)
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate)
{
- m_Event.Set();
m_LoadQueue.EnqueueItemIfNotPresent(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate));
+ m_Event.Set();
}
@@ -154,8 +160,8 @@ 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)
{
- m_Event.Set();
m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ m_Event.Set();
}
@@ -166,6 +172,7 @@ void cWorldStorage::QueueSavedMessage(void)
{
// Pushes a special coord pair into the queue, signalizing a message instead
m_SaveQueue.EnqueueItem(cChunkCoords(0, CHUNK_Y_MESSAGE, 0));
+ m_Event.Set();
}