diff --git a/.gitignore b/.gitignore
index 007b21519..c8ad93a80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,9 @@ cloc.xsl
*.*~
*~
*.orig
+## Eclipse
+.cproject
+.project
# world inside source
ChunkWorx.ini
@@ -57,7 +60,7 @@ install_mainfest.txt
src/MCServer
lib/tolua++/tolua
src/Bindings/Bindings.*
-src/Bindings/BindingsDependecies.txt
+src/Bindings/BindingDependecies.txt
MCServer.dir/
#win32 cmake stuff
diff --git a/.travis.yml b/.travis.yml
index 38dd2f280..c6537cf47 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ compiler:
- gcc
- clang
# Build MCServer
-script: cmake . -DCMAKE_BUILD_TYPE=RELEASE -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | ./MCServer)
+script: cmake . -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_TOOLS=1 -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | ./MCServer)
# Notification Settings
notifications:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 57b200a2a..05b6d879b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,105 +3,20 @@ cmake_minimum_required (VERSION 2.6)
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
enable_language(CXX C)
-macro (add_flags_lnk FLAGS)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
- set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
- set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
- set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
- set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
- set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
- set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
- set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
-endmacro()
-
-macro(add_flags_cxx FLAGS)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
-endmacro()
-
-# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
-if (NOT MSVC)
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
+# This has to be done before any flags have been set up.
+if(${BUILD_TOOLS})
+ add_subdirectory(Tools/MCADefrag/)
+ add_subdirectory(Tools/ProtoProxy/)
endif()
-if(MSVC)
- # Make build use multiple threads under MSVC:
- add_flags_cxx("/MP")
-
- # Make release builds use link-time code generation:
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL")
- set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
- set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
- set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG")
-elseif(APPLE)
- #on os x clang adds pthread for us but we need to add it for gcc
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
- else()
- add_flags_cxx("-pthread")
- endif()
-
-else()
- # Let gcc / clang know that we're compiling a multi-threaded app:
- add_flags_cxx("-pthread")
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
- endif()
-
- # We use a signed char (fixes #640 on RasPi)
- add_flags_cxx("-fsigned-char")
-endif()
-
-
-# Allow for a forced 32-bit build under 64-bit OS:
-if (FORCE_32)
- add_flags_cxx("-m32")
- add_flags_lnk("-m32")
-endif()
-
-
-# Have the compiler generate code specifically targeted at the current machine on Linux
-if(LINUX AND NOT CROSSCOMPILE)
- add_flags_cxx("-march=native")
-endif()
-
-
-# Use static CRT in MSVC builds:
-if (MSVC)
- string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
- string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
- string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
- string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
-endif()
-
-
-# Set lower warnings-level for the libraries:
-if (MSVC)
- # Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2)
- string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
- string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
- string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
- string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
-else()
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
+if(${BUILD_UNSTABLE_TOOLS})
+ add_subdirectory(Tools/GeneratorPerformanceTest/)
endif()
+include(SetFlags.cmake)
+set_flags()
+set_lib_flags()
+enable_profile()
# Under Windows, we need Lua as DLL; on *nix we need it linked statically:
if (WIN32)
@@ -109,18 +24,6 @@ if (WIN32)
endif()
-# On Unix we use two dynamic loading libraries dl and ltdl.
-# Preference is for dl on unknown systems as it is specified in POSIX
-# the dynamic loader is used by lua and sqllite.
-if (UNIX)
- if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
- set(DYNAMIC_LOADER ltdl)
- else()
- set(DYNAMIC_LOADER dl)
- endif()
-endif()
-
-
# The Expat library is linked in statically, make the source files aware of that:
add_definitions(-DXML_STATIC)
@@ -129,64 +32,10 @@ if(${SELF_TEST})
add_definitions(-DSELF_TEST)
endif()
-# Declare the flags used for profiling builds:
-if (MSVC)
- set (CXX_PROFILING "")
- set (LNK_PROFILING "/PROFILE")
-else()
- set (CXX_PROFILING "-pg")
- set (LNK_PROFILING "-pg")
-endif()
-# Declare the profiling configurations:
-SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
- "${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}"
- CACHE STRING "Flags used by the C++ compiler during profile builds."
- FORCE )
-SET(CMAKE_C_FLAGS_DEBUGPROFILE
- "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}"
- CACHE STRING "Flags used by the C compiler during profile builds."
- FORCE )
-SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
- "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
- CACHE STRING "Flags used for linking binaries during profile builds."
- FORCE )
-SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE
- "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
- CACHE STRING "Flags used by the shared libraries linker during profile builds."
- FORCE )
-MARK_AS_ADVANCED(
- CMAKE_CXX_FLAGS_DEBUGPROFILE
- CMAKE_C_FLAGS_DEBUGPROFILE
- CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
- CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE )
-
-SET(CMAKE_CXX_FLAGS_RELEASEPROFILE
- "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}"
- CACHE STRING "Flags used by the C++ compiler during profile builds."
- FORCE )
-SET(CMAKE_C_FLAGS_RELEASEPROFILE
- "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}"
- CACHE STRING "Flags used by the C compiler during profile builds."
- FORCE )
-SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
- "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
- CACHE STRING "Flags used for linking binaries during profile builds."
- FORCE )
-SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE
- "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
- CACHE STRING "Flags used by the shared libraries linker during profile builds."
- FORCE )
-MARK_AS_ADVANCED(
- CMAKE_CXX_FLAGS_RELEASEPROFILE
- CMAKE_C_FLAGS_RELEASEPROFILE
- CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
- CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
-# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
-set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
project (MCServer)
# Include all the libraries:
@@ -203,24 +52,9 @@ add_subdirectory(lib/md5/)
# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
-add_subdirectory(lib/polarssl/ EXCLUDE_FROM_ALL)
+include(lib/polarssl.cmake)
-
-# Remove disabling the maximum warning level:
-# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
-# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
-# the important warnings are turned on using #pragma in Globals.h
-if (NOT MSVC)
- string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
- string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
- string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
- string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
- add_flags_cxx("-Wall")
-endif()
-
-if(${BUILD_TOOLS})
-add_subdirectory(Tools/GeneratorPerformanceTest/)
-endif()
+set_exe_flags()
add_subdirectory (src)
diff --git a/COMPILING.md b/COMPILING.md
index d3c896bdd..139f1a0ee 100644
--- a/COMPILING.md
+++ b/COMPILING.md
@@ -69,7 +69,7 @@ Assuming you are in the MCServer folder created in the initial setup step, you n
```
mkdir Release
cd Release
-cmake . -DCMAKE_BUILD_TYPE=RELEASE .. && make
+cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make
```
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`.
@@ -81,7 +81,7 @@ Assuming you are in the MCServer folder created in the Getting the sources step,
```
mkdir Debug
cd Debug
-cmake . -DCMAKE_BUILD_TYPE=DEBUG && make`
+cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make
```
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`.
diff --git a/MCServer/.gitignore b/MCServer/.gitignore
index e3aebbf92..0fd04ef59 100644
--- a/MCServer/.gitignore
+++ b/MCServer/.gitignore
@@ -4,6 +4,7 @@
*.lib
*.ini
MCServer
+MCServer_debug
CommLogs/
logs
players
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index 01554d99c..73bb5c7fb 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -118,7 +118,7 @@ g_APIDesc =
GetRelBlockMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the block meta at the specified relative coords" },
GetRelBlockSkyLight = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the skylight at the specified relative coords" },
GetRelBlockType = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "BLOCKTYPE", Notes = "Returns the block type at the specified relative coords" },
- GetRelBlockTypeMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the block type and meta at the specified relative coords" },
+ GetRelBlockTypeMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "BLOCKTYPE, NIBBLETYPE", Notes = "Returns the block type and meta at the specified relative coords" },
GetSizeX = { Params = "", Return = "number", Notes = "Returns the size of the held data in the x-axis" },
GetSizeY = { Params = "", Return = "number", Notes = "Returns the size of the held data in the y-axis" },
GetSizeZ = { Params = "", Return = "number", Notes = "Returns the size of the held data in the z-axis" },
@@ -713,6 +713,7 @@ end
IsMinecart = { Params = "", Return = "bool", Notes = "Returns true if the entity represents a {{cMinecart|minecart}}" },
IsMob = { Params = "", Return = "bool", Notes = "Returns true if the entity represents any {{cMonster|mob}}." },
IsOnFire = { Params = "", Return = "bool", Notes = "Returns true if the entity is on fire" },
+ IsPainting = { Params = "", Return = "bool", Notes = "Returns if this entity is a painting." },
IsPickup = { Params = "", Return = "bool", Notes = "Returns true if the entity represents a {{cPickup|pickup}}." },
IsPlayer = { Params = "", Return = "bool", Notes = "Returns true if the entity represents a {{cPlayer|player}}" },
IsProjectile = { Params = "", Return = "bool", Notes = "Returns true if the entity is a {{cProjectileEntity}} descendant." },
@@ -779,6 +780,7 @@ end
etPickup = { Notes = "The entity is a {{cPickup}}" },
etProjectile = { Notes = "The entity is a {{cProjectileEntity}} descendant" },
etTNT = { Notes = "The entity is a {{cTNTEntity}}" },
+ etPainting = { Notes = "The entity is a {{cPainting}}" },
},
ConstantGroups =
{
@@ -1109,6 +1111,9 @@ These ItemGrids are available in the API and can be manipulated by the plugins,
IsFullStack = { Params = "", Return = "bool", Notes = "Returns true if the item is stacked up to its maximum stacking" },
IsSameType = { Params = "cItem", Return = "bool", Notes = "Returns true if the item in the parameter is of the same ItemType as the one stored in the object. This is true even if the two items have different enchantments" },
IsStackableWith = { Params = "cItem", Return = "bool", Notes = "Returns true if the item in the parameter is stackable with the one stored in the object. Two items with different enchantments cannot be stacked" },
+ IsBothNameAndLoreEmpty = { Params = "", Return = "bool", Notes = "Returns if both the custom name and lore are not set." },
+ IsCustomNameEmpty = { Params = "", Return = "bool", Notes = "Returns if the custom name of the cItem is empty." },
+ IsLoreEmpty = { Params = "", Return = "", Notes = "Returns if the lore of the cItem is empty." },
},
Variables =
{
@@ -1116,6 +1121,8 @@ These ItemGrids are available in the API and can be manipulated by the plugins,
m_ItemCount = { Type = "number", Notes = "Number of items in this stack" },
m_ItemDamage = { Type = "number", Notes = "The damage of the item. Zero means no damage. Maximum damage can be queried with GetMaxDamage()" },
m_ItemType = { Type = "number", Notes = "The item type. One of E_ITEM_ or E_BLOCK_ constants" },
+ m_CustomName = { Type = "string", Notes = "The custom name for an item." },
+ m_Lore = { Type = "string", Notes = "The lore for an item. Line breaks are represented by the ` character." },
},
AdditionalInfo =
{
@@ -1160,6 +1167,17 @@ local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3");
},
}, -- cItem
+ cPainting =
+ {
+ Desc = "This class represents a painting in the world. These paintings are special and different from Vanilla in that they can be critical-hit.",
+ Functions =
+ {
+ GetDirection = { Params = "", Return = "number", Notes = "Returns the direction the painting faces. Directions: ZP - 0, ZM - 2, XM - 1, XP - 3. Note that these are not the BLOCK_FACE constants." },
+ GetName = { Params = "", Return = "string", Notes = "Returns the name of the painting" },
+ },
+
+ }, -- cPainting
+
cItemGrid =
{
Desc = [[This class represents a 2D array of items. It is used as the underlying storage and API for all cases that use a grid of items:
@@ -1749,6 +1767,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
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." },
GetNumPlugins = { Params = "", Return = "number", Notes = "Returns the number of plugins, including the disabled ones" },
GetPlugin = { Params = "PluginName", Return = "{{cPlugin}}", Notes = "(DEPRECATED, UNSAFE) Returns a plugin handle of the specified plugin, or nil if such plugin is not loaded. Note thatdue to multithreading the handle is not guaranteed to be safe for use when stored - a single-plugin reload may have been triggered in the mean time for the requested plugin." },
+ GetPluginsPath = { Params = "", Return = "string", Notes = "Returns the path where the individual plugin folders are located. Doesn't include the path separator at the end of the returned string." },
IsCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if in-game Command is already bound (by any plugin)" },
IsConsoleCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if console Command is already bound (by any plugin)" },
LoadPlugin = { Params = "PluginFolder", Return = "", Notes = "(DEPRECATED) Loads a plugin from the specified folder. NOTE: Loading plugins may be an unsafe operation and may result in a deadlock or a crash. This API is deprecated and might be removed." },
@@ -2026,11 +2045,13 @@ end
AreCommandBlocksEnabled = { Params = "", Return = "bool", Notes = "Returns whether command blocks are enabled on the (entire) server" },
BroadcastBlockAction = { Params = "BlockX, BlockY, BlockZ, ActionByte1, ActionByte2, BlockType, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Broadcasts the BlockAction packet to all clients who have the appropriate chunk loaded (except ExcludeClient). The contents of the packet are specified by the parameters for the call, the blocktype needn't match the actual block that is present in the world data at the specified location." },
BroadcastChat = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the Message to all players in this world, except the optional ExcludeClient. No formatting is done by the server." },
+ BroadcastChatDeath = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Gray [DEATH] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For when a player dies." },
BroadcastChatFailure = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a command that failed to run because of insufficient permissions, etc." },
BroadcastChatFatal = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a plugin that crashed, or similar." },
BroadcastChatInfo = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For informational messages, such as command usage." },
BroadcastChatSuccess = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For success messages." },
BroadcastChatWarning = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For concerning events, such as plugin reload etc." },
+ BroadcastParticleEffect = { Params = "ParticleName, X, Y, Z, OffSetX, OffSetY, OffSetZ, ParticleData, ParticleAmmount, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Spawns the specified particles to all players in the world exept the optional ExeptClient. A list of available particles by thinkofdeath can be found {{https://gist.github.com/thinkofdeath/5110835|Here}}" },
BroadcastSoundEffect = { Params = "SoundName, X, Y, Z, Volume, Pitch, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the specified sound effect to all players in this world, except the optional ExceptClient" },
BroadcastSoundParticleEffect = { Params = "EffectID, X, Y, Z, EffectData, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the specified effect to all players in this world, except the optional ExceptClient" },
CastThunderbolt = { Params = "X, Y, Z", Return = "", Notes = "Creates a thunderbolt at the specified coords" },
@@ -2041,6 +2062,7 @@ end
DoExplosionAt = { Params = "Force, X, Y, Z, CanCauseFire, Source, SourceData", Return = "", Notes = "Creates an explosion of the specified relative force in the specified position. If CanCauseFire is set, the explosion will set blocks on fire, too. The Source parameter specifies the source of the explosion, one of the esXXX constants. The SourceData parameter is specific to each source type, usually it provides more info about the source." },
DoWithBlockEntityAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a block entity at the specified coords, calls the CallbackFunction with the {{cBlockEntity}} parameter representing the block entity. The CallbackFunction has the following signature:
function Callback({{cBlockEntity|BlockEntity}}, [CallbackData])
The function returns false if there is no block entity, or if there is, it returns the bool value that the callback has returned. Use {{tolua}}.cast() to cast the Callback's BlockEntity parameter to the correct {{cBlockEntity}} descendant." },
DoWithChestAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a chest at the specified coords, calls the CallbackFunction with the {{cChestEntity}} parameter representing the chest. The CallbackFunction has the following signature: function Callback({{cChestEntity|ChestEntity}}, [CallbackData])
The function returns false if there is no chest, or if there is, it returns the bool value that the callback has returned." },
+ DoWithCommandBlockAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a command block at the specified coords, calls the CallbackFunction with the {{cCommandBlockEntity}} parameter representing the command block. The CallbackFunction has the following signature: function Callback({{cCommandBlockEntity|CommandBlockEntity}}, [CallbackData])
The function returns false if there is no command block, or if there is, it returns the bool value that the callback has returned." },
DoWithDispenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dispenser at the specified coords, calls the CallbackFunction with the {{cDispenserEntity}} parameter representing the dispenser. The CallbackFunction has the following signature: function Callback({{cDispenserEntity|DispenserEntity}}, [CallbackData])
The function returns false if there is no dispenser, or if there is, it returns the bool value that the callback has returned." },
DoWithDropSpenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper or a dispenser at the specified coords, calls the CallbackFunction with the {{cDropSpenserEntity}} parameter representing the dropper or dispenser. The CallbackFunction has the following signature: function Callback({{cDropSpenserEntity|DropSpenserEntity}}, [CallbackData])
Note that this can be used to access both dispensers and droppers in a similar way. The function returns false if there is neither dispenser nor dropper, or if there is, it returns the bool value that the callback has returned." },
DoWithDropperAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper at the specified coords, calls the CallbackFunction with the {{cDropperEntity}} parameter representing the dropper. The CallbackFunction has the following signature: function Callback({{cDropperEntity|DropperEntity}}, [CallbackData])
The function returns false if there is no dropper, or if there is, it returns the bool value that the callback has returned." },
@@ -2086,6 +2108,7 @@ end
GetMaxSugarcaneHeight = { Params = "", Return = "number", Notes = "Returns the configured maximum height to which sugarcane will grow naturally." },
GetName = { Params = "", Return = "string", Notes = "Returns the name of the world, as specified in the settings.ini file." },
GetNumChunks = { Params = "", Return = "number", Notes = "Returns the number of chunks currently loaded." },
+ GetScoreBoard = { Params = "", Return = "{{cScoreBoard}}", Notes = "Returns the {{cScoreBoard|ScoreBoard}} object used by this world. " },
GetSignLines = { Params = "BlockX, BlockY, BlockZ", Return = "IsValid, [Line1, Line2, Line3, Line4]", Notes = "Returns true and the lines of a sign at the specified coords, or false if there is no sign at the coords." },
GetSpawnX = { Params = "", Return = "number", Notes = "Returns the X coord of the default spawn" },
GetSpawnY = { Params = "", Return = "number", Notes = "Returns the Y coord of the default spawn" },
@@ -2117,9 +2140,15 @@ end
QueueSaveAllChunks = { Params = "", Return = "", Notes = "Queues all chunks to be saved in the world storage thread" },
QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." },
QueueTask = { Params = "TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is function()
All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." },
+ QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." },
RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." },
ScheduleTask = { Params = "DelayTicks, TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the world's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is function({{cWorld|World}})
All return values from the function are ignored. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." },
SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." },
+ SetAreaBiome = {
+ { Params = "MinX, MaxX, MinZ, MaxZ, EMCSBiome", Return = "bool", Notes = "Sets the biome in the rectangular area specified. Returns true if successful, false if any of the chunks were unloaded." },
+ { Params = "{{cCuboid|Cuboid}}, EMCSBiome", Return = "bool", Notes = "Sets the biome in the cuboid specified. Returns true if successful, false if any of the chunks were unloaded. The cuboid needn't be sorted." },
+ },
+ SetBiomeAt = { Params = "BlockX, BlockZ, EMCSBiome", Return = "bool", Notes = "Sets the biome at the specified block coords. Returns true if successful, false otherwise." },
SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." },
SetBlockMeta =
{
@@ -2146,7 +2175,6 @@ end
SpawnExperienceOrb = { Params = "X, Y, Z, Reward", Return = "EntityID", Notes = "Spawns an {{cExpOrb|experience orb}} at the specified coords, with the given reward" },
SpawnPrimedTNT = { Params = "X, Y, Z, FuseTimeSecs, InitialVelocityCoeff", Return = "", Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse time. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value." },
TryGetHeight = { Params = "BlockX, BlockZ", Return = "IsValid, Height", Notes = "Returns true and height of the highest non-air block if the chunk is loaded, or false otherwise." },
- UnloadUnusedChunks = { Params = "", Return = "", Notes = "Unloads chunks that are no longer needed, and are saved. NOTE: This API is deprecated and will be removed soon." },
UpdateSign = { Params = "X, Y, Z, Line1, Line2, Line3, Line4, [{{cPlayer|Player}}]", Return = "", Notes = "Sets the sign text at the specified coords. The sign-updating hooks are called for the change. The Player parameter is used to indicate the player from whom the change has come, it may be nil. Same as SetSignLiens()" },
UseBlockEntity = { Params = "{{cPlayer|Player}}, BlockX, BlockY, BlockZ", Return = "", Notes = "Makes the specified Player use the block entity at the specified coords (open chest UI, etc.) If the cords are in an unloaded chunk or there's no block entity, ignores the call." },
WakeUpSimulators = { Params = "BlockX, BlockY, BlockZ", Return = "", Notes = "Wakes up the simulators for the specified block." },
diff --git a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
index 1eec4842a..35c880b00 100644
--- a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
+++ b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
@@ -20,13 +20,7 @@
Let us begin. In order to begin development, we must firstly obtain a compiled copy
of MCServer, and make sure that the Core plugin is within the Plugins folder, and activated.
- Core handles much of the MCServer end-user experience and is a necessary component of
- plugin development, as necessary plugin components depend on sone of its functions.
-
-
- Next, we must obtain a copy of CoreMessaging.lua. This can be found
- here.
- This is used to provide messaging support that is compliant with MCServer standards.
+ Core handles much of the MCServer end-user experience and gameplay will be very bland without it.
Creating the basic template
@@ -41,7 +35,11 @@ function Initialize(Plugin)
Plugin:SetName("NewPlugin")
Plugin:SetVersion(1)
- PLUGIN = Plugin
+ -- Hooks
+
+ PLUGIN = Plugin -- NOTE: only needed if you want OnDisable() to use GetName() or something like that
+
+ -- Command Bindings
LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
return true
@@ -58,7 +56,8 @@ end
Plugin:SetName sets the name of the plugin.
Plugin:SetVersion sets the revision number of the plugin. This must be an integer.
LOG logs to console a message, in this case, it prints that the plugin was initialised.
- The PLUGIN variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize).
+ The PLUGIN variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize).
+ This global variable is only needed if you want to know the plugin details (name, etc.) when shutting down.
function OnDisable is called when the plugin is disabled, commonly when the server is shutting down. Perform cleanup and logging here.
Be sure to return true for this function, else MCS thinks you plugin had failed to initialise and prints a stacktrace with an error message.
@@ -159,21 +158,23 @@ cPluginManager.BindCommand("/commandname", "permissionnode", FunctionToCall, " ~
a message. Again, see the API documentation for fuller details. But, you ask, how do we send a message to the client?
- Remember that copy of CoreMessaging.lua that we downloaded earlier? Make sure that file is in your plugin folder, along with the main.lua file you are typing
- your code in. Since MCS brings all the files together on JIT compile, we don't need to worry about requiring any files or such. Simply follow the below examples:
+ There are dedicated functions used for sending a player formatted messages. By format, I refer to coloured prefixes/coloured text (depending on configuration)
+ that clearly categorise what type of message a player is being sent. For example, an informational message has a yellow coloured [INFO] prefix, and a warning message
+ has a rose coloured [WARNING] prefix. A few of the most used functions are listed here, but see the API docs for more details. Look in the cRoot, cWorld, and cPlayer sections
+ for functions that broadcast to the entire server, the whole world, and a single player, respectively.
-- Format: §yellow[INFO] §white%text% (yellow [INFO], white text following it)
-- Use: Informational message, such as instructions for usage of a command
-SendMessage(Player, "Usage: /explode [player]")
+Player:SendMessageInfo("Usage: /explode [player]")
-- Format: §green[INFO] §white%text% (green [INFO] etc.)
-- Use: Success message, like when a command executes successfully
-SendMessageSuccess(Player, "Notch was blown up!")
+Player:SendMessageSuccess("Notch was blown up!")
-- Format: §rose[INFO] §white%text% (rose coloured [INFO] etc.)
-- Use: Failure message, like when a command was entered correctly but failed to run, such as when the destination player wasn't found in a /tp command
-SendMessageFailure(Player, "Player Salted was not found")
+Player:SendMessageFailure("Player Salted was not found")
Those are the basics. If you want to output text to the player for a reason other than the three listed above, and you want to colour the text, simply concatenate
diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
index f74c4ea2d..88ecb3979 100644
--- a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
+++ b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
@@ -122,7 +122,7 @@ function OnTick( DeltaTime )
end
end
WW_instance:QueueSaveAllChunks()
- WW_instance:UnloadUnusedChunks()
+ WW_instance:QueueUnloadUnusedChunks()
end
end
end
\ No newline at end of file
diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
index 44993f81c..6c5eab676 100644
--- a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
+++ b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
@@ -44,7 +44,7 @@ function HandleRequest_Generation( Request )
if (Request.PostParams["AGHRRRR"] ~= nil) then
GENERATION_STATE = 0
WW_instance:SaveAllChunks()
- WW_instance:UnloadUnusedChunks()
+ WW_instance:QueueUnloadUnusedChunks()
LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin")
end
--Content = Content .. "
"
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
index d6ed20414..3b416b07a 160000
--- a/MCServer/Plugins/Core
+++ b/MCServer/Plugins/Core
@@ -1 +1 @@
-Subproject commit d6ed2041469ab959bbf3842db41c0e25fd249dc1
+Subproject commit 3b416b07a339b3abcbc127070d56eea05b05373d
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 8345e2169..66894d835 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -19,18 +19,18 @@ function Initialize(Plugin)
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick2);
--]]
- cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
- cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
- cPluginManager:AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage);
- cPluginManager:AddHook(cPluginManager.HOOK_TICK, OnTick);
- cPluginManager:AddHook(cPluginManager.HOOK_CHAT, OnChat);
- cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity);
- cPluginManager:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick);
- cPluginManager:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
- cPluginManager:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
- cPluginManager:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
+ local PM = cPluginManager;
+ PM:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
+ PM:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
+ PM:AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage);
+ PM:AddHook(cPluginManager.HOOK_TICK, OnTick);
+ PM:AddHook(cPluginManager.HOOK_CHAT, OnChat);
+ PM:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity);
+ PM:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick);
+ PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
+ PM:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
+ PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
- PM = cRoot:Get():GetPluginManager();
PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
PM:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool");
@@ -54,8 +54,11 @@ function Initialize(Plugin)
PM:BindCommand("/ff", "debuggers", HandleFurnaceFuel, "- Shows how long the currently held item would burn in a furnace");
PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()");
PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords");
+ PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings")
+ PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one");
- Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers);
+ Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
+ Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
@@ -1038,6 +1041,68 @@ end
+local g_Counter = 0
+local g_JavaScript =
+[[
+
+]]
+
+function HandleRequest_StressTest(a_Request)
+ if (a_Request.PostParams["counter"]) then
+ g_Counter = g_Counter + 1
+ return tostring(g_Counter)
+ end
+ return g_JavaScript .. "The counter below should be reloading as fast as possible
0
"
+end
+
+
+
+
+
function OnPluginMessage(a_Client, a_Channel, a_Message)
LOGINFO("Received a plugin message from client " .. a_Client:GetUsername() .. ": channel '" .. a_Channel .. "', message '" .. a_Message .. "'");
@@ -1132,3 +1197,64 @@ end
+
+function HandleCompo(a_Split, a_Player)
+ -- Send one composite message to self:
+ local msg = cCompositeChat()
+ msg:AddTextPart("Hello! ", "b@e") -- bold yellow
+ msg:AddUrlPart("MCServer", "http://mc-server.org")
+ msg:AddTextPart(" rules! ")
+ msg:AddRunCommandPart("Set morning", "/time set 0")
+ a_Player:SendMessage(msg)
+
+ -- Broadcast another one to the world:
+ local msg2 = cCompositeChat()
+ msg2:AddSuggestCommandPart(a_Player:GetName(), "/tell " .. a_Player:GetName() .. " ")
+ msg2:AddTextPart(" knows how to use cCompositeChat!");
+ a_Player:GetWorld():BroadcastChat(msg2)
+
+ return true
+end
+
+
+
+
+
+function HandleSetBiome(a_Split, a_Player)
+ local Biome = biJungle
+ local Size = 20
+ local SplitSize = #a_Split
+ if (SplitSize > 3) then
+ a_Player:SendMessage("Too many parameters. Usage: " .. a_Split[1] .. " ")
+ return true
+ end
+
+ if (SplitSize >= 2) then
+ Biome = StringToBiome(a_Split[2])
+ if (Biome == biInvalidBiome) then
+ a_Player:SendMessage("Unknown biome: '" .. a_Split[2] .. "'. Command ignored.")
+ return true
+ end
+ end
+ if (SplitSize >= 3) then
+ Size = tostring(a_Split[3])
+ if (Size == nil) then
+ a_Player:SendMessage("Unknown size: '" .. a_Split[3] .. "'. Command ignored.")
+ return true
+ end
+ end
+
+ local BlockX = math.floor(a_Player:GetPosX())
+ local BlockZ = math.floor(a_Player:GetPosZ())
+ a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome)
+ a_Player:SendMessage(
+ "Blocks {" .. (BlockX - Size) .. ", " .. (BlockZ - Size) ..
+ "} - {" .. (BlockX + Size) .. ", " .. (BlockZ + Size) ..
+ "} set to biome #" .. tostring(Biome) .. "."
+ )
+ return true
+end
+
+
+
+
diff --git a/MCServer/Plugins/InfoReg.lua b/MCServer/Plugins/InfoReg.lua
new file mode 100644
index 000000000..3afb57488
--- /dev/null
+++ b/MCServer/Plugins/InfoReg.lua
@@ -0,0 +1,157 @@
+
+-- InfoReg.lua
+
+-- Implements registration functions that process g_PluginInfo
+
+
+
+
+
+--- Lists all the subcommands that the player has permissions for
+local function ListSubcommands(a_Player, a_Subcommands, a_CmdString)
+ a_Player:SendMessage("The " .. a_CmdString .. " command requires another verb:");
+ local Verbs = {};
+ for cmd, info in pairs(a_Subcommands) do
+ if (a_Player:HasPermission(info.Permission or "")) then
+ table.insert(Verbs, a_CmdString .. " " .. cmd);
+ end
+ end
+ table.sort(Verbs);
+ for idx, verb in ipairs(Verbs) do
+ a_Player:SendMessage(verb);
+ end
+end
+
+
+
+
+
+--- This is a generic command callback used for handling multicommands' parent commands
+-- For example, if there are "/gal save" and "/gal load" commands, this callback handles the "/gal" command
+local function MultiCommandHandler(a_Split, a_Player, a_CmdString, a_CmdInfo, a_Level)
+ local Verb = a_Split[a_Level + 1];
+ if (Verb == nil) then
+ -- No verb was specified. If there is a handler for the upper level command, call it:
+ if (a_CmdInfo.Handler ~= nil) then
+ return a_CmdInfo.Handler(a_Split, a_Player);
+ end
+ -- Let the player know they need to give a subcommand:
+ ListSubcommands(a_Player, a_CmdInfo.Subcommands, a_CmdString);
+ return true;
+ end
+
+ -- A verb was specified, look it up in the subcommands table:
+ local Subcommand = a_CmdInfo.Subcommands[Verb];
+ if (Subcommand == nil) then
+ if (a_Level > 1) then
+ -- This is a true subcommand, display the message and make MCS think the command was handled
+ -- Otherwise we get weird behavior: for "/cmd verb" we get "unknown command /cmd" although "/cmd" is valid
+ a_Player:SendMessage("The " .. a_CmdString .. " command doesn't support verb " .. Verb);
+ return true;
+ end
+ -- This is a top-level command, let MCS handle the unknown message
+ return false;
+ end
+
+ -- Check the permission:
+ if not(a_Player:HasPermission(Subcommand.Permission or "")) then
+ a_Player:SendMessage("You don't have permission to execute this command");
+ return true;
+ end
+
+ -- Check if the handler is valid:
+ if (Subcommand.Handler == nil) then
+ if (Subcommand.Subcommands == nil) then
+ LOG("Cannot find handler for command " .. a_CmdString .. " " .. Verb);
+ return false;
+ end
+ ListSubcommands(a_Player, Subcommand.Subcommands, a_CmdString .. " " .. Verb);
+ return true;
+ end
+
+ -- Execute:
+ return Subcommand.Handler(a_Split, a_Player);
+end
+
+
+
+
+
+--- Registers all commands specified in the g_PluginInfo.Commands
+function RegisterPluginInfoCommands()
+ -- A sub-function that registers all subcommands of a single command, using the command's Subcommands table
+ -- The a_Prefix param already contains the space after the previous command
+ -- a_Level is the depth of the subcommands being registered, with 1 being the top level command
+ local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level)
+ assert(a_Subcommands ~= nil);
+
+ for cmd, info in pairs(a_Subcommands) do
+ local CmdName = a_Prefix .. cmd;
+ local Handler = info.Handler;
+ -- Provide a special handler for multicommands:
+ if (info.Subcommands ~= nil) then
+ Handler = function(a_Split, a_Player)
+ return MultiCommandHandler(a_Split, a_Player, CmdName, info, a_Level);
+ end
+ end
+
+ if (Handler == nil) then
+ LOGWARNING(g_PluginInfo.Name .. ": Invalid handler for command " .. CmdName .. ", command will not be registered.");
+ else
+ local HelpString;
+ if (info.HelpString ~= nil) then
+ HelpString = " - " .. info.HelpString;
+ else
+ HelpString = "";
+ end
+ cPluginManager.BindCommand(CmdName, info.Permission or "", Handler, HelpString);
+ -- Register all aliases for the command:
+ if (info.Alias ~= nil) then
+ if (type(info.Alias) == "string") then
+ info.Alias = {info.Alias};
+ end
+ for idx, alias in ipairs(info.Alias) do
+ cPluginManager.BindCommand(a_Prefix .. alias, info.Permission or "", Handler, HelpString);
+ end
+ end
+ end
+
+ -- Recursively register any subcommands:
+ if (info.Subcommands ~= nil) then
+ RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1);
+ end
+ end
+ end
+
+ -- Loop through all commands in the plugin info, register each:
+ RegisterSubcommands("", g_PluginInfo.Commands, 1);
+end
+
+
+
+
+
+--- Registers all console commands specified in the g_PluginInfo.ConsoleCommands
+function RegisterPluginInfoConsoleCommands()
+ -- A sub-function that registers all subcommands of a single command, using the command's Subcommands table
+ -- The a_Prefix param already contains the space after the previous command
+ local function RegisterSubcommands(a_Prefix, a_Subcommands)
+ assert(a_Subcommands ~= nil);
+
+ for cmd, info in pairs(a_Subcommands) do
+ local CmdName = a_Prefix .. cmd;
+ cPluginManager.BindConsoleCommand(cmd, info.Handler, info.HelpString or "");
+ -- Recursively register any subcommands:
+ if (info.Subcommands ~= nil) then
+ RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands);
+ end
+ end
+ end
+
+ -- Loop through all commands in the plugin info, register each:
+ RegisterSubcommands("", g_PluginInfo.ConsoleCommands);
+end
+
+
+
+
diff --git a/SetFlags.cmake b/SetFlags.cmake
new file mode 100644
index 000000000..ded57e6d7
--- /dev/null
+++ b/SetFlags.cmake
@@ -0,0 +1,189 @@
+
+
+macro (add_flags_lnk FLAGS)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
+ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
+ set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
+ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
+ set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
+ set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
+endmacro()
+
+macro(add_flags_cxx FLAGS)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
+endmacro()
+
+
+macro(set_flags)
+ # Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
+ if (NOT MSVC)
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
+ endif()
+
+ if(MSVC)
+ # Make build use multiple threads under MSVC:
+ add_flags_cxx("/MP")
+
+ # Make release builds use link-time code generation:
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL")
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
+ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
+ set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG")
+ elseif(APPLE)
+ #on os x clang adds pthread for us but we need to add it for gcc
+ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
+ else()
+ add_flags_cxx("-pthread")
+ endif()
+
+ else()
+ # Let gcc / clang know that we're compiling a multi-threaded app:
+ add_flags_cxx("-pthread")
+ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
+ endif()
+
+ # We use a signed char (fixes #640 on RasPi)
+ add_flags_cxx("-fsigned-char")
+ endif()
+
+
+ # Allow for a forced 32-bit build under 64-bit OS:
+ if (FORCE_32)
+ add_flags_cxx("-m32")
+ add_flags_lnk("-m32")
+ endif()
+
+
+ # Have the compiler generate code specifically targeted at the current machine on Linux
+ if(LINUX AND NOT CROSSCOMPILE)
+ add_flags_cxx("-march=native")
+ endif()
+
+
+ # Use static CRT in MSVC builds:
+ if (MSVC)
+ string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
+ string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+ string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+ string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
+ endif()
+endmacro()
+
+macro(set_lib_flags)
+ # Set lower warnings-level for the libraries:
+ if (MSVC)
+ # Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2)
+ string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
+ string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+ string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+ string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
+ else()
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
+ endif()
+
+ # On Unix we use two dynamic loading libraries dl and ltdl.
+ # Preference is for dl on unknown systems as it is specified in POSIX
+ # the dynamic loader is used by lua and sqllite.
+ if (UNIX)
+ if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
+ set(DYNAMIC_LOADER ltdl)
+ else()
+ set(DYNAMIC_LOADER dl)
+ endif()
+ endif()
+endmacro()
+
+macro(enable_profile)
+ # Declare the flags used for profiling builds:
+ if (MSVC)
+ set (CXX_PROFILING "")
+ set (LNK_PROFILING "/PROFILE")
+ else()
+ set (CXX_PROFILING "-pg")
+ set (LNK_PROFILING "-pg")
+ endif()
+
+
+ # Declare the profiling configurations:
+ SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
+ "${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}"
+ CACHE STRING "Flags used by the C++ compiler during profile builds."
+ FORCE )
+ SET(CMAKE_C_FLAGS_DEBUGPROFILE
+ "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}"
+ CACHE STRING "Flags used by the C compiler during profile builds."
+ FORCE )
+ SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
+ "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
+ CACHE STRING "Flags used for linking binaries during profile builds."
+ FORCE )
+ SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE
+ "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
+ CACHE STRING "Flags used by the shared libraries linker during profile builds."
+ FORCE )
+ MARK_AS_ADVANCED(
+ CMAKE_CXX_FLAGS_DEBUGPROFILE
+ CMAKE_C_FLAGS_DEBUGPROFILE
+ CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
+ CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE )
+
+ SET(CMAKE_CXX_FLAGS_RELEASEPROFILE
+ "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}"
+ CACHE STRING "Flags used by the C++ compiler during profile builds."
+ FORCE )
+ SET(CMAKE_C_FLAGS_RELEASEPROFILE
+ "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}"
+ CACHE STRING "Flags used by the C compiler during profile builds."
+ FORCE )
+ SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
+ "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
+ CACHE STRING "Flags used for linking binaries during profile builds."
+ FORCE )
+ SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE
+ "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
+ CACHE STRING "Flags used by the shared libraries linker during profile builds."
+ FORCE )
+ MARK_AS_ADVANCED(
+ CMAKE_CXX_FLAGS_RELEASEPROFILE
+ CMAKE_C_FLAGS_RELEASEPROFILE
+ CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
+ CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
+ # The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
+ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
+endmacro()
+
+macro(set_exe_flags)
+ # Remove disabling the maximum warning level:
+ # clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
+ # We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
+ # the important warnings are turned on using #pragma in Globals.h
+ if (NOT MSVC)
+ string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
+ string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+ string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+ string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
+ add_flags_cxx("-Wall -Wextra")
+ endif()
+
+endmacro()
diff --git a/Tools/MCADefrag/.gitignore b/Tools/MCADefrag/.gitignore
new file mode 100644
index 000000000..44a3e1f48
--- /dev/null
+++ b/Tools/MCADefrag/.gitignore
@@ -0,0 +1 @@
+*.mca
diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt
new file mode 100644
index 000000000..2a021049f
--- /dev/null
+++ b/Tools/MCADefrag/CMakeLists.txt
@@ -0,0 +1,97 @@
+
+cmake_minimum_required (VERSION 2.6)
+
+project (MCADefrag)
+
+# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
+enable_language(CXX C)
+
+include(../../SetFlags.cmake)
+set_flags()
+set_lib_flags()
+enable_profile()
+
+
+
+
+# Set include paths to the used libraries:
+include_directories("../../lib")
+include_directories("../../src")
+
+
+function(flatten_files arg1)
+ set(res "")
+ foreach(f ${${arg1}})
+ get_filename_component(f ${f} ABSOLUTE)
+ list(APPEND res ${f})
+ endforeach()
+ set(${arg1} "${res}" PARENT_SCOPE)
+endfunction()
+
+
+# Include the libraries:
+
+add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
+
+set_exe_flags()
+
+# Include the shared files:
+set(SHARED_SRC
+ ../../src/StringCompression.cpp
+ ../../src/StringUtils.cpp
+ ../../src/Log.cpp
+ ../../src/MCLogger.cpp
+)
+set(SHARED_HDR
+ ../../src/ByteBuffer.h
+ ../../src/StringUtils.h
+ ../../src/Log.h
+ ../../src/MCLogger.h
+)
+flatten_files(SHARED_SRC)
+flatten_files(SHARED_HDR)
+source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR})
+
+set(SHARED_OSS_SRC
+ ../../src/OSSupport/CriticalSection.cpp
+ ../../src/OSSupport/File.cpp
+ ../../src/OSSupport/IsThread.cpp
+ ../../src/OSSupport/Timer.cpp
+)
+set(SHARED_OSS_HDR
+ ../../src/OSSupport/CriticalSection.h
+ ../../src/OSSupport/File.h
+ ../../src/OSSupport/IsThread.h
+ ../../src/OSSupport/Timer.h
+)
+
+flatten_files(SHARED_OSS_SRC)
+flatten_files(SHARED_OSS_HDR)
+
+source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR})
+
+
+
+# Include the main source files:
+set(SOURCES
+ MCADefrag.cpp
+ Globals.cpp
+)
+set(HEADERS
+ MCADefrag.h
+ Globals.h
+)
+
+source_group("" FILES ${SOURCES} ${HEADERS})
+
+add_executable(MCADefrag
+ ${SOURCES}
+ ${HEADERS}
+ ${SHARED_SRC}
+ ${SHARED_HDR}
+ ${SHARED_OSS_SRC}
+ ${SHARED_OSS_HDR}
+)
+
+target_link_libraries(MCADefrag zlib)
+
diff --git a/Tools/MCADefrag/Globals.cpp b/Tools/MCADefrag/Globals.cpp
new file mode 100644
index 000000000..13c6ae709
--- /dev/null
+++ b/Tools/MCADefrag/Globals.cpp
@@ -0,0 +1,10 @@
+
+// Globals.cpp
+
+// This file is used for precompiled header generation in MSVC environments
+
+#include "Globals.h"
+
+
+
+
diff --git a/Tools/MCADefrag/Globals.h b/Tools/MCADefrag/Globals.h
new file mode 100644
index 000000000..6f4bbdc76
--- /dev/null
+++ b/Tools/MCADefrag/Globals.h
@@ -0,0 +1,229 @@
+
+// Globals.h
+
+// This file gets included from every module in the project, so that global symbols may be introduced easily
+// Also used for precompiled header generation in MSVC environments
+
+
+
+
+
+// Compiler-dependent stuff:
+#if defined(_MSC_VER)
+ // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
+ #pragma warning(disable:4481)
+
+ // Disable some warnings that we don't care about:
+ #pragma warning(disable:4100)
+
+ #define OBSOLETE __declspec(deprecated)
+
+ // No alignment needed in MSVC
+ #define ALIGN_8
+ #define ALIGN_16
+
+#elif defined(__GNUC__)
+
+ // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
+ #define abstract
+
+ // TODO: Can GCC mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class)
+ #define override
+
+ #define OBSOLETE __attribute__((deprecated))
+
+ #define ALIGN_8 __attribute__((aligned(8)))
+ #define ALIGN_16 __attribute__((aligned(16)))
+
+ // Some portability macros :)
+ #define stricmp strcasecmp
+
+#else
+
+ #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
+
+ /*
+ // Copy and uncomment this into another #elif section based on your compiler identification
+
+ // Explicitly mark classes as abstract (no instances can be created)
+ #define abstract
+
+ // Mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class)
+ #define override
+
+ // Mark functions as obsolete, so that their usage results in a compile-time warning
+ #define OBSOLETE
+
+ // Mark types / variables for alignment. Do the platforms need it?
+ #define ALIGN_8
+ #define ALIGN_16
+ */
+
+#endif
+
+
+
+
+
+// Integral types with predefined sizes:
+typedef long long Int64;
+typedef int Int32;
+typedef short Int16;
+
+typedef unsigned long long UInt64;
+typedef unsigned int UInt32;
+typedef unsigned short UInt16;
+
+typedef unsigned char Byte;
+
+
+
+
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for any class that shouldn't allow copying itself
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName &); \
+ void operator=(const TypeName &)
+
+// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
+#define UNUSED(X) (void)(X)
+
+
+
+
+// OS-dependent stuff:
+#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #include
+ #include
+ #include
+
+ // Windows SDK defines min and max macros, messing up with our std::min and std::max usage
+ #undef min
+ #undef max
+
+ // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
+ #ifdef GetFreeSpace
+ #undef GetFreeSpace
+ #endif // GetFreeSpace
+
+ #define SocketError WSAGetLastError()
+#else
+ #include
+ #include // for mkdir
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ typedef int SOCKET;
+ enum
+ {
+ INVALID_SOCKET = -1,
+ };
+ #define closesocket close
+ #define SocketError errno
+#if !defined(ANDROID_NDK)
+ #include
+#endif
+#endif
+
+#if !defined(ANDROID_NDK)
+ #define USE_SQUIRREL
+#endif
+
+#if defined(ANDROID_NDK)
+ #define FILE_IO_PREFIX "/sdcard/mcserver/"
+#else
+ #define FILE_IO_PREFIX ""
+#endif
+
+
+
+
+
+// CRT stuff:
+#include
+#include
+#include
+#include
+#include
+
+
+
+
+
+// STL stuff:
+#include
+#include
+#include
+#include
+#include