summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt19
-rw-r--r--COMPILING.md73
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua4
m---------MCServer/Plugins/Core0
-rw-r--r--Tools/ProtoProxy/.gitignore3
-rw-r--r--Tools/ProtoProxy/CMakeLists.txt153
-rw-r--r--Tools/ProtoProxy/Connection.cpp12
-rw-r--r--Tools/ProtoProxy/ProtoProxy.sln29
-rw-r--r--Tools/ProtoProxy/ProtoProxy.vcproj279
-rw-r--r--VC2013/CryptoPP.vcxproj.filters6
-rw-r--r--VC2013/MCServer.vcxproj5
-rw-r--r--VC2013/MCServer.vcxproj.filters55
-rw-r--r--lib/lua/CMakeLists.txt15
-rw-r--r--lib/zlib/CMakeLists.txt8
-rw-r--r--src/Bindings/ManualBindings.cpp62
-rw-r--r--src/Bindings/PluginManager.cpp6
-rw-r--r--src/BlockID.cpp1
-rw-r--r--src/CMakeLists.txt16
-rw-r--r--src/Entities/Entity.cpp57
-rw-r--r--src/Entities/Entity.h2
-rw-r--r--src/Entities/Minecart.cpp550
-rw-r--r--src/Entities/Minecart.h35
-rw-r--r--src/Entities/Player.cpp30
-rw-r--r--src/Entities/Player.h2
-rw-r--r--src/Log.cpp8
-rw-r--r--src/Log.h8
-rw-r--r--src/Protocol/Protocol17x.cpp64
-rw-r--r--src/Protocol/Protocol17x.h6
-rw-r--r--src/Simulator/RedstoneSimulator.cpp7
-rw-r--r--src/StringUtils.cpp33
-rw-r--r--src/StringUtils.h2
-rw-r--r--src/World.cpp39
-rw-r--r--src/World.h24
33 files changed, 1016 insertions, 597 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c39fe679c..f2ad8b364 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,6 +36,13 @@ 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 (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
@@ -60,6 +67,15 @@ if(LINUX AND NOT CROSSCOMPILE)
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)
@@ -163,7 +179,6 @@ MARK_AS_ADVANCED(
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
project (MCServer)
-
# Include all the libraries:
add_subdirectory(lib/inifile/)
add_subdirectory(lib/jsoncpp/)
@@ -187,5 +202,5 @@ if (NOT MSVC)
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
endif()
-add_subdirectory (src)
+add_subdirectory (src)
diff --git a/COMPILING.md b/COMPILING.md
index 0989440a6..31222a5d8 100644
--- a/COMPILING.md
+++ b/COMPILING.md
@@ -1,24 +1,79 @@
-COMPILING
-=========
+# COMPILING #
-To compile MCServer on *nix, you need CMake and make, as well as a C compiler, C++ compiler and linker.
+To compile MCServer from source, you need CMake and make, as well as a C compiler, C++ compiler and linker. To contribute code, you also need a Git client.
-Release Mode
-------------
+## Windows ##
+
+We use Microsoft Visual Studio for Windows compilation. It is possible to use other toolchains, but it isn't tested nor supported. Visual Studio versions 2008 Express and 2013 Express are being actively used for development, so either should work.
+You can find download links for VS2008 Express here: http://stackoverflow.com/questions/15318560/visual-c-2008-express-download-link-dead
+And VS2013 Express here: http://www.microsoft.com/en-us/download/details.aspx?id=40787
+
+Next, you need to download and install CMake. Download from here: http://cmake.org/cmake/resources/software.html . You should download a full installation package, so that the installer will set everything up for you (especially the paths).
+
+To contribute your changes to the sources back to the repository, you need a Git client. Options are:
+- MsysGit: http://msysgit.github.io/
+- GitHub windows client: http://windows.github.com/
+- TortoiseGit: http://code.google.com/p/tortoisegit/
+
+Alternatively, if you want only to compile the source, without contributing, you can download the sources in a ZIP file directly from GitHub: https://github.com/mc-server/MCServer/archive/master.zip
+If you're using Git to get the sources, use the following set of commands to set up the local workspace correctly:
+```
+mkdir MCServer
+cd MCServer
+git clone https://github.com/mc-server/MCServer.git .
+git submodule init
+git submodule update
+```
+
+Now that you have the sources, it's time to prepare the project files for your favorite compiler. Open a command window in the folder with the sources and type in `cmake .` . This will run CMake, it will auto-detect your Visual Studio version and produce the appropriate project and solution files.
+
+Finally, open the newly created file, `MCServer.sln`, in your Visual Studio.
+
+If you want to run MCServer from within the IDE, you need to first make sure that it will be run with the correct home folder. Normally this happens automatically, but for some Visual Studio versions the process doesn't stick. Right-click on the MCServer project in the Solution Explorer tool window, and select Properties. In the dialog, navigate to Configuration properties -> Debugging in the tree on the left, then make sure the value `Working Directory` is set to `../MCServer`. If you don't do this, the server won't be able to find crafting recipes, item names or plugins.
+
+### Release configuration ###
+
+To make Visual Studio produce the version with the best performance, you will need to select a Release configuration. Go to menu Build -> Configuration Manager, and in the opened dialog, change the top left combo box (Active solution configuration) to Release. Close the dialog and build the solution. The resulting executable is called `MCServer.exe` in the `MCServer` folder.
+
+### Debug configuration ###
+
+In order to tinker with the code, you'll more than likely need to use the debugging features of the IDE. To make them the easiest to use, you should switch to the Debug configuration - this provides the highest level of information while debugging, for the price of the executable being 2 - 10 times slower. Go to menu Build -> Configuration Manager, and in the opened dialog, change the top left combo box (Active solution configuration) to Debug. Close the dialog and build the solution. The resulting executable is called `MCServer_debug.exe` in the `MCServer` folder.
+
+### Profiling ###
+
+It is possible to use an external profiler to learn more about how the code performs. You can find more information about the techniques in the article here: http://www.codeproject.com/Articles/144643/Profiling-of-C-Applications-in-Visual-Studio-for-F
+
+There's a script file, `MCServer/profile_run.cmd` that encapsulates most of the profiling work, have a look at the comments at the top of that script for details on how to get it to work. You'll need to change to a profiled configuration (both debug and release can be profiled).
+
+## Linux, MacOS, FreeBSD etc. ##
+
+Install git, cmake and gcc or clang, using your platform's package manager:
+```
+sudo apt-get install git cmake gcc
+```
+
+### Getting the sources ###
+```
+mkdir MCServer
+cd MCServer
+git clone https://github.com/mc-server/MCServer.git .
+git submodule init
+git submodule update
+```
+
+### Release Mode ###
Release mode is preferred for almost all cases, it has much better speed and less console spam. However, if you are developing MCServer actively, debug mode might be better.
cmake . -DCMAKE_BUILD_TYPE=RELEASE && make
-Debug Mode
-----------
+### Debug Mode ###
Debug mode is useful if you want more debugging information about MCServer as it's running or if you want to use a debugger like GDB to debug issues and crashes.
cmake . -DCMAKE_BUILD_TYPE=DEBUG && make
-32 Bit Mode
------------
+### 32 Bit Mode ###
This is useful if you want to compile MCServer to use on another 32-bit machine. It can be used with debug or release mode. To use 32 bit mode, simply add:
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index 4f01c375e..a5b6d8210 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -1571,7 +1571,7 @@ a_Player:OpenWindow(Window);
{
AddFoodExhaustion = { Params = "Exhaustion", Return = "", Notes = "Adds the specified number to the food exhaustion. Only positive numbers expected." },
AddToGroup = { Params = "GroupName", Return = "", Notes = "Temporarily adds the player to the specified group. The assignment is lost when the player disconnects." },
- CalcLevelFromXp = { Params = "XPAmount", Return = "number", Notes = "Returns the level which is reached with the specified amount of XP. Inverse of XpForLevel()." },
+ CalcLevelFromXp = { Params = "XPAmount", Return = "number", Notes = "(STATIC) Returns the level which is reached with the specified amount of XP. Inverse of XpForLevel()." },
CanFly = { Return = "bool", Notes = "Returns if the player is able to fly." },
CanUseCommand = { Params = "Command", Return = "bool", Notes = "Returns true if the player is allowed to use the specified command." },
CloseWindow = { Params = "[CanRefuse]", Return = "", Notes = "Closes the currently open UI window. If CanRefuse is true (default), the window may refuse the closing." },
@@ -1648,7 +1648,7 @@ a_Player:OpenWindow(Window);
SetSprintingMaxSpeed = { Params = "SprintingMaxSpeed", Return = "", Notes = "Sets the sprinting maximum speed (as reported by the 1.6.1+ protocols)" },
SetVisible = { Params = "IsVisible", Return = "", Notes = "Sets the player visibility to other players" },
TossItem = { Params = "DraggedItem, [Amount], [CreateType], [CreateDamage]", Return = "", Notes = "FIXME: This function will be rewritten, avoid it. It tosses an item, either from the inventory, dragged in hand (while in UI window) or a newly created one." },
- XpForLevel = { Params = "XPLevel", Return = "number", Notes = "Returns the total amount of XP needed for the specified XP level. Inverse of CalcLevelFromXp()." },
+ XpForLevel = { Params = "XPLevel", Return = "number", Notes = "(STATIC) Returns the total amount of XP needed for the specified XP level. Inverse of CalcLevelFromXp()." },
},
Constants =
{
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
-Subproject c65b56767a5e59ca387a05be72ef18791baa9ae
+Subproject decc72f3a9134d80df5e14c3f2570e1479d521c
diff --git a/Tools/ProtoProxy/.gitignore b/Tools/ProtoProxy/.gitignore
index 2a38341e5..8def77d0b 100644
--- a/Tools/ProtoProxy/.gitignore
+++ b/Tools/ProtoProxy/.gitignore
@@ -3,3 +3,6 @@ Release
Logs/
*.log
*.nbt
+*.sln
+*.vcproj
+*.vcxproj
diff --git a/Tools/ProtoProxy/CMakeLists.txt b/Tools/ProtoProxy/CMakeLists.txt
new file mode 100644
index 000000000..2178705a8
--- /dev/null
+++ b/Tools/ProtoProxy/CMakeLists.txt
@@ -0,0 +1,153 @@
+
+cmake_minimum_required (VERSION 2.6)
+
+project (ProtoProxy)
+
+
+
+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")
+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 (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ add_flags_cxx("-pthread")
+ endif()
+else()
+ # Let gcc / clang know that we're compiling a multi-threaded app:
+ add_flags_cxx("-pthread")
+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 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:
+file(GLOB CRYPTOPP_SRC "../../lib/CryptoPP/*.cpp")
+file(GLOB CRYPTOPP_HDR "../../lib/CryptoPP/*.h")
+flatten_files(CRYPTOPP_SRC)
+flatten_files(CRYPTOPP_HDR)
+source_group("CryptoPP" FILES ${CRYPTOPP_SRC} ${CRYPTOPP_HDR})
+
+file(GLOB ZLIB_SRC "../../lib/zlib/*.c")
+file(GLOB ZLIB_HDR "../../lib/zlib/*.h")
+flatten_files(ZLIB_SRC)
+flatten_files(ZLIB_HDR)
+source_group("ZLib" FILES ${ZLIB_SRC} ${ZLIB_HDR})
+
+
+# Include the shared files:
+set(SHARED_SRC
+ ../../src/ByteBuffer.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
+)
+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_SRC)
+flatten_files(SHARED_HDR)
+flatten_files(SHARED_OSS_SRC)
+flatten_files(SHARED_OSS_HDR)
+source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR})
+source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR})
+
+
+
+# Include the main source files:
+set(SOURCES
+ Connection.cpp
+ Globals.cpp
+ ProtoProxy.cpp
+ Server.cpp
+)
+set(HEADERS
+ Connection.h
+ Globals.h
+ Server.h
+)
+source_group("" FILES ${SOURCES} ${HEADERS})
+
+add_executable(ProtoProxy
+ ${SOURCES}
+ ${HEADERS}
+ ${SHARED_SRC}
+ ${SHARED_HDR}
+ ${SHARED_OSS_SRC}
+ ${SHARED_OSS_HDR}
+ ${CRYPTOPP_SRC}
+ ${CRYPTOPP_HDR}
+ ${ZLIB_SRC}
+ ${ZLIB_HDR}
+)
+
diff --git a/Tools/ProtoProxy/Connection.cpp b/Tools/ProtoProxy/Connection.cpp
index de67c6e43..e91b9935e 100644
--- a/Tools/ProtoProxy/Connection.cpp
+++ b/Tools/ProtoProxy/Connection.cpp
@@ -249,10 +249,12 @@ void cConnection::Run(void)
void cConnection::Log(const char * a_Format, ...)
{
- va_list args;
+ va_list args, argsCopy;
va_start(args, a_Format);
+ va_start(argsCopy, a_Format);
AString msg;
- AppendVPrintf(msg, a_Format, args);
+ AppendVPrintf(msg, a_Format, args, argsCopy);
+ va_end(argsCopy);
va_end(args);
AString FullMsg;
Printf(FullMsg, "[%5.3f] %s\n", GetRelativeTime(), msg.c_str());
@@ -274,10 +276,12 @@ void cConnection::Log(const char * a_Format, ...)
void cConnection::DataLog(const void * a_Data, int a_Size, const char * a_Format, ...)
{
- va_list args;
+ va_list args, argsCopy;
va_start(args, a_Format);
+ va_start(argsCopy, a_Format);
AString msg;
- AppendVPrintf(msg, a_Format, args);
+ AppendVPrintf(msg, a_Format, args, argsCopy);
+ va_end(argsCopy);
va_end(args);
AString FullMsg;
AString Hex;
diff --git a/Tools/ProtoProxy/ProtoProxy.sln b/Tools/ProtoProxy/ProtoProxy.sln
deleted file mode 100644
index 1c8c1a2a7..000000000
--- a/Tools/ProtoProxy/ProtoProxy.sln
+++ /dev/null
@@ -1,29 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProtoProxy", "ProtoProxy.vcproj", "{EFEC8F76-1397-49A4-885B-314CB4244231}"
- ProjectSection(ProjectDependencies) = postProject
- {3423EC9A-52E4-4A4D-9753-EDEBC38785EF} = {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CryptoPP", "..\..\VC2008\CryptoPP.vcproj", "{3423EC9A-52E4-4A4D-9753-EDEBC38785EF}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {EFEC8F76-1397-49A4-885B-314CB4244231}.Debug|Win32.ActiveCfg = Debug|Win32
- {EFEC8F76-1397-49A4-885B-314CB4244231}.Debug|Win32.Build.0 = Debug|Win32
- {EFEC8F76-1397-49A4-885B-314CB4244231}.Release|Win32.ActiveCfg = Release|Win32
- {EFEC8F76-1397-49A4-885B-314CB4244231}.Release|Win32.Build.0 = Release|Win32
- {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|Win32.ActiveCfg = Debug|Win32
- {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|Win32.Build.0 = Debug|Win32
- {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|Win32.ActiveCfg = Release|Win32
- {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/Tools/ProtoProxy/ProtoProxy.vcproj b/Tools/ProtoProxy/ProtoProxy.vcproj
deleted file mode 100644
index 0b3c77bc5..000000000
--- a/Tools/ProtoProxy/ProtoProxy.vcproj
+++ /dev/null
@@ -1,279 +0,0 @@
-<?xml version="1.0" encoding="windows-1250"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9,00"
- Name="ProtoProxy"
- ProjectGUID="{EFEC8F76-1397-49A4-885B-314CB4244231}"
- RootNamespace="ProtoProxy"
- Keyword="Win32Proj"
- TargetFrameworkVersion="196613"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="../../lib;../../src"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="2"
- PrecompiledHeaderThrough="Globals.h"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="../../lib;../../src"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- UsePrecompiledHeader="2"
- PrecompiledHeaderThrough="Globals.h"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib"
- LinkIncremental="1"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;h;hpp"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath=".\Connection.cpp"
- >
- </File>
- <File
- RelativePath=".\Connection.h"
- >
- </File>
- <File
- RelativePath=".\Globals.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\Globals.h"
- >
- </File>
- <File
- RelativePath=".\ProtoProxy.cpp"
- >
- </File>
- <File
- RelativePath=".\Server.cpp"
- >
- </File>
- <File
- RelativePath=".\Server.h"
- >
- </File>
- </Filter>
- <Filter
- Name="shared"
- >
- <File
- RelativePath="..\..\src\ByteBuffer.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\ByteBuffer.h"
- >
- </File>
- <File
- RelativePath="..\..\src\StringUtils.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\StringUtils.h"
- >
- </File>
- <Filter
- Name="OSSupport"
- >
- <File
- RelativePath="..\..\src\OSSupport\CriticalSection.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\CriticalSection.h"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\IsThread.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\IsThread.h"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\Timer.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\OSSupport\Timer.h"
- >
- </File>
- </Filter>
- </Filter>
- <File
- RelativePath=".\ProtoProxy.txt"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/VC2013/CryptoPP.vcxproj.filters b/VC2013/CryptoPP.vcxproj.filters
index becd042b8..d47a1c34c 100644
--- a/VC2013/CryptoPP.vcxproj.filters
+++ b/VC2013/CryptoPP.vcxproj.filters
@@ -2,15 +2,15 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
- <UniqueIdentifier>{3c30caed-20a3-4bd8-b12e-fdd1e13455e5}</UniqueIdentifier>
+ <UniqueIdentifier>{59bfc075-705c-42cd-adf7-40cef1aed8e1}</UniqueIdentifier>
<Extensions>.cpp</Extensions>
</Filter>
<Filter Include="Header Files">
- <UniqueIdentifier>{770573d2-b90d-43f4-ac1c-464ab10c46ec}</UniqueIdentifier>
+ <UniqueIdentifier>{407d7f02-df9e-485b-a95f-2f1dad08cbed}</UniqueIdentifier>
<Extensions>.;.h</Extensions>
</Filter>
<Filter Include="Miscellaneous">
- <UniqueIdentifier>{1ac058bb-f217-4ac3-a14b-9c6ba021e030}</UniqueIdentifier>
+ <UniqueIdentifier>{293a01a6-81d1-4272-a7ff-310526bbc77f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
diff --git a/VC2013/MCServer.vcxproj b/VC2013/MCServer.vcxproj
index 95b73ae57..36c29bf11 100644
--- a/VC2013/MCServer.vcxproj
+++ b/VC2013/MCServer.vcxproj
@@ -226,6 +226,7 @@
<ItemGroup>
<ClInclude Include="..\src\Resources\resource_MCServer.h" />
<ClInclude Include="..\src\Authenticator.h" />
+ <ClInclude Include="..\src\BiomeDef.h" />
<ClInclude Include="..\src\BlockArea.h" />
<ClInclude Include="..\src\BlockID.h" />
<ClInclude Include="..\src\BlockTracer.h" />
@@ -234,8 +235,6 @@
<ClInclude Include="..\src\ChatColor.h" />
<ClInclude Include="..\src\Chunk.h" />
<ClInclude Include="..\src\ChunkDef.h" />
- <ClInclude Include="..\src\BiomeDef.h" />
- <ClInclude Include="..\src\BiomeDef.cpp" />
<ClInclude Include="..\src\ChunkMap.h" />
<ClInclude Include="..\src\ChunkSender.h" />
<ClInclude Include="..\src\ClientHandle.h" />
@@ -374,7 +373,6 @@
<ClInclude Include="..\src\Bindings\Plugin.h" />
<ClInclude Include="..\src\Bindings\PluginLua.h" />
<ClInclude Include="..\src\Bindings\PluginManager.h" />
- <ClInclude Include="..\src\Bindings\tolua_base.h" />
<ClInclude Include="..\src\Bindings\WebPlugin.h" />
<ClInclude Include="..\lib\inifile\iniFile.h" />
<ClInclude Include="..\lib\md5\md5.h" />
@@ -618,6 +616,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Authenticator.cpp" />
+ <ClCompile Include="..\src\BiomeDef.cpp" />
<ClCompile Include="..\src\BlockArea.cpp" />
<ClCompile Include="..\src\BlockID.cpp" />
<ClCompile Include="..\src\BoundingBox.cpp" />
diff --git a/VC2013/MCServer.vcxproj.filters b/VC2013/MCServer.vcxproj.filters
index 30e90a9b0..176afad2e 100644
--- a/VC2013/MCServer.vcxproj.filters
+++ b/VC2013/MCServer.vcxproj.filters
@@ -10,73 +10,73 @@
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Source Files\Mobs">
- <UniqueIdentifier>{813698c3-b2c1-4f3d-a89c-7ac6239fff97}</UniqueIdentifier>
+ <UniqueIdentifier>{46ffa881-c36b-41b0-85df-90e0f78c6285}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Entities">
- <UniqueIdentifier>{b120a538-d8b9-4576-8675-36cf01fd69fc}</UniqueIdentifier>
+ <UniqueIdentifier>{5eb3c155-b618-4232-92a5-52b3ae70ec96}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\UI">
- <UniqueIdentifier>{85037cf1-81a5-47c7-8c2e-899ea706b8e7}</UniqueIdentifier>
+ <UniqueIdentifier>{5f745788-b9aa-4dde-9763-cdfaddb3dfdf}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Simulator">
- <UniqueIdentifier>{46c9cb22-7c7f-4589-b9b2-1fc79d2bdbdf}</UniqueIdentifier>
+ <UniqueIdentifier>{acb44271-df18-41b2-8a50-656a49c39d3c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\OSSupport">
- <UniqueIdentifier>{f12178cb-2ecb-4e48-9a8d-ba3e2e73cfbc}</UniqueIdentifier>
+ <UniqueIdentifier>{1091cb9f-3d9d-4ed5-9359-fc762be21759}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\OSSupport\Android Specific">
- <UniqueIdentifier>{488bc224-735f-405c-83de-870373cb52cb}</UniqueIdentifier>
+ <UniqueIdentifier>{c40bec86-f173-440a-b07e-bab15c8ce965}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Bindings">
- <UniqueIdentifier>{41c0d7c9-43b5-4d17-b50e-3c8ac3aa2905}</UniqueIdentifier>
+ <UniqueIdentifier>{4180990c-1257-4d07-9009-08535fedfbf8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\External">
- <UniqueIdentifier>{2c71a15a-8c65-4be7-bdfb-e083f4841c4a}</UniqueIdentifier>
+ <UniqueIdentifier>{ffc2297f-c790-4190-a56f-ac6a1f97a30c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\WorldStorage">
- <UniqueIdentifier>{2227f719-f0ac-444e-af14-230853017c45}</UniqueIdentifier>
+ <UniqueIdentifier>{011ff757-845a-4342-862e-44207ec46a94}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Generating">
- <UniqueIdentifier>{eb070b55-ba10-4bce-ba06-5d785a055e54}</UniqueIdentifier>
+ <UniqueIdentifier>{7f7a0b8c-4ee6-4a3a-92d6-5ba242a565f3}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Blocks">
- <UniqueIdentifier>{779dac55-c718-4fe1-8b67-547d431b9ebc}</UniqueIdentifier>
+ <UniqueIdentifier>{07157169-9da7-4998-9f00-4580641cf811}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Items">
- <UniqueIdentifier>{89847a5d-608a-4137-a766-1557276b4fcf}</UniqueIdentifier>
+ <UniqueIdentifier>{5b92b198-0a58-4399-9c8e-662bd5062b6c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Protocol">
- <UniqueIdentifier>{e159d08d-daec-46de-9b60-9f8e660da91d}</UniqueIdentifier>
+ <UniqueIdentifier>{16a88457-3862-4ff0-a591-a7160ea956f5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\SQLite">
- <UniqueIdentifier>{0278092b-abe5-4276-81cf-59e4079e5bc7}</UniqueIdentifier>
+ <UniqueIdentifier>{a3561ecf-a501-4c76-b176-1f214b7a5523}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\LuaExpat">
- <UniqueIdentifier>{e4879cf2-e769-4e1d-8905-0f6c40ee5bc1}</UniqueIdentifier>
+ <UniqueIdentifier>{a35eb320-d10b-4592-92ed-2d2f242dbed7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\BlockEntities">
- <UniqueIdentifier>{d641a9d4-f5dc-4808-bee6-194306505244}</UniqueIdentifier>
+ <UniqueIdentifier>{1c271d11-30ce-4aef-b8a9-7c8ee560d5d6}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\HTTPServer">
- <UniqueIdentifier>{a1e39415-2aca-4779-a558-2567a9de304f}</UniqueIdentifier>
+ <UniqueIdentifier>{223bdf26-d107-498f-8c42-00c19ef80348}</UniqueIdentifier>
</Filter>
<Filter Include="Config files">
- <UniqueIdentifier>{eb5f3060-03ed-4548-8bde-340454d3d23a}</UniqueIdentifier>
+ <UniqueIdentifier>{99140e5f-0287-4601-ad28-bad2533d8876}</UniqueIdentifier>
</Filter>
<Filter Include="Plugins">
- <UniqueIdentifier>{7c681450-041a-4846-acf6-951c1f4e32a4}</UniqueIdentifier>
+ <UniqueIdentifier>{beb25b3b-31f3-468e-a721-6d0dc297e4b5}</UniqueIdentifier>
</Filter>
<Filter Include="Plugins\Core">
- <UniqueIdentifier>{e961964c-9fb7-4513-89fa-05e0b760e0f1}</UniqueIdentifier>
+ <UniqueIdentifier>{f848f39d-680d-4f9c-8dcb-da9a0bb871f5}</UniqueIdentifier>
</Filter>
<Filter Include="Plugins\ChatLog">
- <UniqueIdentifier>{70696c83-2307-43c6-8851-81aa3baa8523}</UniqueIdentifier>
+ <UniqueIdentifier>{7c735e41-f3b2-4500-856b-54845f834eb2}</UniqueIdentifier>
</Filter>
<Filter Include="Plugins\Debuggers">
- <UniqueIdentifier>{d3b692db-0684-4b89-9d38-2e5af12e9a6e}</UniqueIdentifier>
+ <UniqueIdentifier>{83d5aac9-2975-4334-9acc-b48e96a16b23}</UniqueIdentifier>
</Filter>
<Filter Include="Plugins\APIDump">
- <UniqueIdentifier>{6eee304c-f055-4758-a248-a125e1af7e73}</UniqueIdentifier>
+ <UniqueIdentifier>{e5167107-9cc8-4e03-b519-c3a13b9b7955}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@@ -96,6 +96,9 @@
<ClInclude Include="..\src\Authenticator.h">
<Filter>Source Files</Filter>
</ClInclude>
+ <ClInclude Include="..\src\BiomeDef.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
<ClInclude Include="..\src\BlockArea.h">
<Filter>Source Files</Filter>
</ClInclude>
@@ -513,9 +516,6 @@
<ClInclude Include="..\src\Bindings\PluginManager.h">
<Filter>Source Files\Bindings</Filter>
</ClInclude>
- <ClInclude Include="..\src\Bindings\tolua_base.h">
- <Filter>Source Files\Bindings</Filter>
- </ClInclude>
<ClInclude Include="..\src\Bindings\WebPlugin.h">
<Filter>Source Files\Bindings</Filter>
</ClInclude>
@@ -1114,6 +1114,9 @@
<ClCompile Include="..\src\Authenticator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\src\BiomeDef.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\src\BlockArea.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/lib/lua/CMakeLists.txt b/lib/lua/CMakeLists.txt
index 4a77578dd..02c20388d 100644
--- a/lib/lua/CMakeLists.txt
+++ b/lib/lua/CMakeLists.txt
@@ -22,11 +22,18 @@ endif()
if (WIN32)
add_library(lua SHARED ${SOURCE})
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
- if (MSVC)
- # MSVC generator adds a "Debug" or "Release" postfixes to the LIBRARY_OUTPUT_PATH, we need to cancel them:
- SET_TARGET_PROPERTIES(lua PROPERTIES PREFIX "../")
- SET_TARGET_PROPERTIES(lua PROPERTIES IMPORT_PREFIX "../")
+ # Output the executable into the $/MCServer folder, so that MCServer can find it:
+ set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
+ SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
+ RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+ RUNTIME_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+ )
+
+ if (MSVC)
+ # Remove SCL warnings, we expect this library to have been tested safe
SET_TARGET_PROPERTIES(
lua PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS"
)
diff --git a/lib/zlib/CMakeLists.txt b/lib/zlib/CMakeLists.txt
index fe6dba6ae..b1b74031d 100644
--- a/lib/zlib/CMakeLists.txt
+++ b/lib/zlib/CMakeLists.txt
@@ -9,3 +9,11 @@ file(GLOB SOURCE
)
add_library(zlib ${SOURCE})
+
+if (MSVC)
+ # Remove SCL warnings, we expect this library to have been tested safe
+ SET_TARGET_PROPERTIES(
+ zlib PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS"
+ )
+endif()
+
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index a9368f613..b12fa5f03 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -941,10 +941,6 @@ protected:
}
} ;
-
-
-
-
static int tolua_cWorld_QueueTask(lua_State * tolua_S)
{
// Binding for cWorld::QueueTask
@@ -980,7 +976,65 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
return 0;
}
+class cLuaScheduledWorldTask :
+ public cWorld::cScheduledTask
+{
+public:
+ cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef, int a_Ticks) :
+ cScheduledTask(a_Ticks),
+ m_Plugin(a_Plugin),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+protected:
+ cPluginLua & m_Plugin;
+ int m_FnRef;
+
+ // cWorld::cTask overrides:
+ virtual void Run(cWorld & a_World) override
+ {
+ m_Plugin.Call(m_FnRef, &a_World);
+ }
+};
+
+
+static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
+{
+ // Binding for cWorld::ScheduleTask
+ // Params: function, Ticks
+
+ // Retrieve the cPlugin from the LuaState:
+ cPluginLua * Plugin = GetLuaPlugin(tolua_S);
+ if (Plugin == NULL)
+ {
+ // An error message has been already printed in GetLuaPlugin()
+ return 0;
+ }
+
+ // Retrieve the args:
+ cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, 0);
+ if (self == NULL)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
+ }
+ if (!lua_isfunction(tolua_S, 2))
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
+ }
+
+ // Create a reference to the function:
+ int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
+ if (FnRef == LUA_REFNIL)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
+ }
+
+ int Ticks = (int) tolua_tonumber (tolua_S, 3, 0);
+ self->ScheduleTask(new cLuaScheduledWorldTask(*Plugin, FnRef,Ticks));
+ return 0;
+}
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 68e6aea33..24bb914d1 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -169,9 +169,9 @@ void cPluginManager::InsertDefaultPlugins(cIniFile & a_SettingsIni)
a_SettingsIni.AddKeyComment("Plugins", " Plugin=HookNotify");
a_SettingsIni.AddKeyComment("Plugins", " Plugin=ChunkWorx");
a_SettingsIni.AddKeyComment("Plugins", " Plugin=APIDump");
- a_SettingsIni.SetValue("Plugins", "Plugin", "Core");
- a_SettingsIni.SetValue("Plugins", "Plugin", "TransAPI");
- a_SettingsIni.SetValue("Plugins", "Plugin", "ChatLog");
+ a_SettingsIni.AddValue("Plugins", "Plugin", "Core");
+ a_SettingsIni.AddValue("Plugins", "Plugin", "TransAPI");
+ a_SettingsIni.AddValue("Plugins", "Plugin", "ChatLog");
}
diff --git a/src/BlockID.cpp b/src/BlockID.cpp
index 69a3a817c..095865d07 100644
--- a/src/BlockID.cpp
+++ b/src/BlockID.cpp
@@ -767,6 +767,7 @@ public:
g_BlockIsSolid[E_BLOCK_MELON_STEM] = false;
g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false;
g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false;
+ g_BlockIsSolid[E_BLOCK_POWERED_RAIL] = false;
g_BlockIsSolid[E_BLOCK_RAIL] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_OFF] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_ON] = false;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1c031173b..b3af6aedd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.2)
project (MCServer)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
@@ -88,13 +88,15 @@ set(EXECUTABLE MCServer)
add_executable(${EXECUTABLE} ${SOURCE})
-set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
-if (MSVC)
- # MSVC generator adds a "Debug" or "Release" postfixes to the EXECUTABLE_OUTPUT_PATH, we need to cancel them:
- SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES PREFIX "../")
- SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES IMPORT_PREFIX "../")
-endif()
+# Output the executable into the $/MCServer folder, so that it has access to external resources:
+set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
+SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
+ RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+ RUNTIME_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+)
# Make the debug executable have a "_debug" suffix
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 8a74c9da4..cd97c6766 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -321,7 +321,10 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
m_Health = 0;
}
- AddSpeed(a_TDI.Knockback * 2);
+ if (IsMob() || IsPlayer()) // Knockback for only players and mobs
+ {
+ AddSpeed(a_TDI.Knockback * 2);
+ }
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_HURT);
@@ -626,11 +629,6 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
}
- else if (IsBlockRail(BlockBelow) && IsMinecart()) // Rails aren't solid, except for Minecarts
- {
- fallspeed = 0;
- m_bOnGround = true;
- }
else if (BlockIn == E_BLOCK_COBWEB)
{
NextSpeed.y *= 0.05; // Reduce overall falling speed
@@ -645,41 +643,18 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
else
{
- if (IsMinecart())
+ // Friction
+ if (NextSpeed.SqrLength() > 0.0004f)
{
- if (!IsBlockRail(BlockBelow))
+ NextSpeed.x *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.x) < 0.05)
{
- // Friction if minecart is off track, otherwise, Minecart.cpp handles this
- if (NextSpeed.SqrLength() > 0.0004f)
- {
- NextSpeed.x *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.x) < 0.05)
- {
- NextSpeed.x = 0;
- }
- NextSpeed.z *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.z) < 0.05)
- {
- NextSpeed.z = 0;
- }
- }
+ NextSpeed.x = 0;
}
- }
- else
- {
- // Friction for non-minecarts
- if (NextSpeed.SqrLength() > 0.0004f)
+ NextSpeed.z *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.z) < 0.05)
{
- NextSpeed.x *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.x) < 0.05)
- {
- NextSpeed.x = 0;
- }
- NextSpeed.z *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.z) < 0.05)
- {
- NextSpeed.z = 0;
- }
+ NextSpeed.z = 0;
}
}
}
@@ -1104,9 +1079,11 @@ void cEntity::AttachTo(cEntity * a_AttachTo)
// Already attached to that entity, nothing to do here
return;
}
-
- // Detach from any previous entity:
- Detach();
+ if (m_AttachedTo != NULL)
+ {
+ // Detach from any previous entity:
+ Detach();
+ }
// Attach to the new entity:
m_AttachedTo = a_AttachTo;
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 2ba1b303d..878e69668 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -327,7 +327,7 @@ public:
void AttachTo(cEntity * a_AttachTo);
/// Detaches from the currently attached entity, if any
- void Detach(void);
+ virtual void Detach(void);
/// Makes sure head yaw is not over the specified range.
void WrapHeadYaw();
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index f75e23d8b..7f3fea5ec 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -2,6 +2,7 @@
// Minecart.cpp
// Implements the cMinecart class representing a minecart in the world
+// Handles physics when a minecart is on any type of rail (overrides simulator in Entity.cpp)
// Indiana Jones!
#include "Globals.h"
@@ -10,6 +11,10 @@
#include "../ClientHandle.h"
#include "../Chunk.h"
#include "Player.h"
+#include "../BoundingBox.h"
+
+#define MAX_SPEED 8
+#define MAX_SPEED_NEGATIVE -MAX_SPEED
@@ -18,11 +23,15 @@
cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7),
m_Payload(a_Payload),
- m_LastDamage(0)
+ m_LastDamage(0),
+ m_DetectorRailPosition(0, 0, 0),
+ m_bIsOnDetectorRail(false)
{
SetMass(20.f);
SetMaxHealth(6);
SetHealth(6);
+ SetWidth(1.2);
+ SetHeight(0.9);
}
@@ -53,6 +62,11 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
+ if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
+ {
+ return;
+ }
+
int PosY = (int)floor(GetPosY());
if ((PosY <= 0) || (PosY >= cChunkDef::Height))
{
@@ -70,286 +84,513 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
// Inside an unloaded chunk, bail out all processing
return;
}
- BLOCKTYPE BelowType = Chunk->GetBlock(RelPosX, PosY - 1, RelPosZ);
- BLOCKTYPE InsideType = Chunk->GetBlock(RelPosX, PosY, RelPosZ);
- if (IsBlockRail(BelowType))
+ BLOCKTYPE InsideType;
+ NIBBLETYPE InsideMeta;
+ Chunk->GetBlockTypeMeta(RelPosX, PosY, RelPosZ, InsideType, InsideMeta);
+
+ if (!IsBlockRail(InsideType))
{
- HandleRailPhysics(a_Dt, *Chunk);
+ Chunk->GetBlockTypeMeta(RelPosX, PosY + 1, RelPosZ, InsideType, InsideMeta); // When an descending minecart hits a flat rail, it goes through the ground; check for this
+ if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards
}
- else
+
+ if (IsBlockRail(InsideType))
{
- if (IsBlockRail(InsideType))
+ bool WasDetectorRail = false;
+ SnapToRail(InsideMeta);
+
+ switch (InsideType)
{
- SetPosY(PosY + 1);
- HandleRailPhysics(a_Dt, *Chunk);
+ case E_BLOCK_RAIL: HandleRailPhysics(InsideMeta, a_Dt); break;
+ case E_BLOCK_ACTIVATOR_RAIL: break;
+ case E_BLOCK_POWERED_RAIL: HandlePoweredRailPhysics(InsideMeta); break;
+ case E_BLOCK_DETECTOR_RAIL:
+ {
+ HandleDetectorRailPhysics(InsideMeta, a_Dt);
+ WasDetectorRail = true;
+ break;
+ }
+ default: VERIFY(!"Unhandled rail type despite checking if block was rail!"); break;
}
- else
+
+ AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
+
+ if (m_bIsOnDetectorRail && !WasDetectorRail)
{
- super::HandlePhysics(a_Dt, *Chunk);
- BroadcastMovementUpdate();
+ m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
+ m_bIsOnDetectorRail = false;
}
}
+ else
+ {
+ // Not on rail, default physics
+ SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail
+ super::HandlePhysics(a_Dt, *Chunk);
+ }
+
+ // Broadcast positioning changes to client
+ BroadcastMovementUpdate();
}
-static const double MAX_SPEED = 8;
-static const double MAX_SPEED_NEGATIVE = (0 - MAX_SPEED);
-
-void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk)
+void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
{
-
- super::HandlePhysics(a_Dt, a_Chunk); // Main physics handling
-
/*
NOTE: Please bear in mind that taking away from negatives make them even more negative,
adding to negatives make them positive, etc.
*/
- // Get block meta below the cart
- int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width;
- int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width;
- NIBBLETYPE BelowMeta = a_Chunk.GetMeta(RelPosX, (int)floor(GetPosY() - 1), RelPosZ);
- double SpeedX = GetSpeedX(), SpeedY = GetSpeedY(), SpeedZ = GetSpeedZ(); // Get current speed
-
- switch (BelowMeta)
+ switch (a_RailMeta)
{
case E_META_RAIL_ZM_ZP: // NORTHSOUTH
{
SetRotation(270);
- SpeedY = 0; // Don't move vertically as on ground
- SpeedX = 0; // Correct diagonal movement from curved rails
+ SetPosY(floor(GetPosY()) + 0.55);
+ SetSpeedY(0); // Don't move vertically as on ground
+ SetSpeedX(0); // Correct diagonal movement from curved rails
+
+ if (TestBlockCollision(a_RailMeta)) return;
- if (SpeedZ != 0) // Don't do anything if cart is stationary
+ if (GetSpeedZ() != 0) // Don't do anything if cart is stationary
{
- if (SpeedZ > 0)
+ if (GetSpeedZ() > 0)
{
// Going SOUTH, slow down
- SpeedZ = SpeedZ - 0.1;
+ AddSpeedZ(-0.1);
}
else
{
// Going NORTH, slow down
- SpeedZ = SpeedZ + 0.1;
+ AddSpeedZ(0.1);
}
}
break;
}
-
case E_META_RAIL_XM_XP: // EASTWEST
{
SetRotation(180);
- SpeedY = 0;
- SpeedZ = 0;
+ SetPosY(floor(GetPosY()) + 0.55);
+ SetSpeedY(0);
+ SetSpeedZ(0);
+
+ if (TestBlockCollision(a_RailMeta)) return;
- if (SpeedX != 0)
+ if (GetSpeedX() != 0)
{
- if (SpeedX > 0)
+ if (GetSpeedX() > 0)
{
- SpeedX = SpeedX - 0.1;
+ AddSpeedX(-0.1);
}
else
{
- SpeedX = SpeedX + 0.1;
+ AddSpeedX(0.1);
}
}
break;
}
-
case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
{
SetRotation(270);
- SetPosY(floor(GetPosY()) + 0.2); // It seems it doesn't work without levitation :/
- SpeedX = 0;
+ SetSpeedX(0);
- if (SpeedZ >= 0)
+ if (GetSpeedZ() >= 0)
{
// SpeedZ POSITIVE, going SOUTH
- if (SpeedZ <= MAX_SPEED) // Speed limit
+ if (GetSpeedZ() <= MAX_SPEED) // Speed limit
{
- SpeedZ = SpeedZ + 0.5; // Speed up
- SpeedY = (0 - SpeedZ); // Downward movement is negative (0 minus positive numbers is negative)
- }
- else
- {
- SpeedZ = MAX_SPEED; // Enforce speed limit
- SpeedY = (0 - SpeedZ);
+ AddSpeedZ(0.5); // Speed up
+ SetSpeedY(-GetSpeedZ()); // Downward movement is negative (0 minus positive numbers is negative)
}
}
else
{
// SpeedZ NEGATIVE, going NORTH
- SpeedZ = SpeedZ + 0.4; // Slow down
- SpeedY = (0 - SpeedZ); // Upward movement is positive (0 minus negative number is positive number)
+ AddSpeedZ(1); // Slow down
+ SetSpeedY(-GetSpeedZ()); // Upward movement is positive (0 minus negative number is positive number)
}
break;
}
-
case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
{
SetRotation(270);
- SetPosY(floor(GetPosY()) + 0.2);
- SpeedX = 0;
+ SetSpeedX(0);
- if (SpeedZ > 0)
+ if (GetSpeedZ() > 0)
{
// SpeedZ POSITIVE, going SOUTH
- SpeedZ = SpeedZ - 0.4; // Slow down
- SpeedY = SpeedZ; // Upward movement positive
+ AddSpeedZ(-1); // Slow down
+ SetSpeedY(GetSpeedZ()); // Upward movement positive
}
else
{
- if (SpeedZ >= MAX_SPEED_NEGATIVE) // Speed limit
+ if (GetSpeedZ() >= MAX_SPEED_NEGATIVE) // Speed limit
{
// SpeedZ NEGATIVE, going NORTH
- SpeedZ = SpeedZ - 0.5; // Speed up
- SpeedY = SpeedZ; // Downward movement negative
- }
- else
- {
- SpeedZ = MAX_SPEED_NEGATIVE; // Enforce speed limit
- SpeedY = SpeedZ;
+ AddSpeedZ(-0.5); // Speed up
+ SetSpeedY(GetSpeedZ()); // Downward movement negative
}
}
break;
}
-
case E_META_RAIL_ASCEND_XM: // ASCEND EAST
{
SetRotation(180);
- SetPosY(floor(GetPosY()) + 0.2);
- SpeedZ = 0;
+ SetSpeedZ(0);
- if (SpeedX >= 0)
+ if (GetSpeedX() >= 0)
{
- if (SpeedX <= MAX_SPEED)
- {
- SpeedX = SpeedX + 0.5;
- SpeedY = (0 - SpeedX);
- }
- else
+ if (GetSpeedX() <= MAX_SPEED)
{
- SpeedX = MAX_SPEED;
- SpeedY = (0 - SpeedX);
+ AddSpeedX(0.5);
+ SetSpeedY(-GetSpeedX());
}
}
else
{
- SpeedX = SpeedX + 0.4;
- SpeedY = (0 - SpeedX);
+ AddSpeedX(1);
+ SetSpeedY(-GetSpeedX());
}
break;
}
-
case E_META_RAIL_ASCEND_XP: // ASCEND WEST
{
SetRotation(180);
- SetPosY(floor(GetPosY()) + 0.2);
- SpeedZ = 0;
+ SetSpeedZ(0);
- if (SpeedX > 0)
+ if (GetSpeedX() > 0)
{
- SpeedX = SpeedX - 0.4;
- SpeedY = SpeedX;
+ AddSpeedX(-1);
+ SetSpeedY(GetSpeedX());
}
else
{
- if (SpeedX >= MAX_SPEED_NEGATIVE)
+ if (GetSpeedX() >= MAX_SPEED_NEGATIVE)
{
- SpeedX = SpeedX - 0.5;
- SpeedY = SpeedX;
- }
- else
- {
- SpeedX = MAX_SPEED_NEGATIVE;
- SpeedY = SpeedX;
+ AddSpeedX(-0.5);
+ SetSpeedY(GetSpeedX());
}
}
break;
}
-
case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST
{
SetRotation(315); // Set correct rotation server side
- SetPosY(floor(GetPosY()) + 0.2); // Levitate dat cart
+ SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart
+
+ if (TestBlockCollision(a_RailMeta)) return;
- if (SpeedZ > 0) // Cart moving south
+ if (GetSpeedZ() > 0) // Cart moving south
{
- SpeedX = (0 - SpeedZ); // Diagonally move southwest (which will make cart hit a southwest rail)
+ int OldX = (int)floor(GetPosX());
+ AddSpeedX(-GetSpeedZ() + 0.5); // See below
+ AddPosX(-GetSpeedZ() * (a_Dt / 1000)); // Diagonally move southwest (which will make cart hit a southwest rail)
+ // If we are already at southwest rail, set Z speed to zero as we can be moving so fast, MCS doesn't tick fast enough to active the handle for the rail...
+ // ...and so we derail unexpectedly.
+ if (GetPosX() <= OldX - 1) SetSpeedZ(0);
}
- else if (SpeedX > 0) // Cart moving east
+ else if (GetSpeedX() > 0) // Cart moving east
{
- SpeedZ = (0 - SpeedX); // Diagonally move northeast
+ int OldZ = (int)floor(GetPosZ());
+ AddSpeedZ(-GetSpeedX() + 0.5);
+ AddPosZ(-GetSpeedX() * (a_Dt / 1000)); // Diagonally move northeast
+ if (GetPosZ() <= OldZ - 1) SetSpeedX(0);
}
break;
}
-
case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST
{
SetRotation(225);
- SetPosY(floor(GetPosY()) + 0.2);
+ SetPosY(floor(GetPosY()) + 0.55);
+
+ if (TestBlockCollision(a_RailMeta)) return;
- if (SpeedZ > 0)
+ if (GetSpeedZ() > 0)
{
- SpeedX = SpeedZ;
+ int OldX = (int)floor(GetPosX());
+ AddSpeedX(GetSpeedZ() - 0.5);
+ AddPosX(GetSpeedZ() * (a_Dt / 1000));
+ if (GetPosX() >= OldX + 1) SetSpeedZ(0);
}
- else if (SpeedX < 0)
+ else if (GetSpeedX() < 0)
{
- SpeedZ = SpeedX;
+ int OldZ = (int)floor(GetPosZ());
+ AddSpeedZ(GetSpeedX() + 0.5);
+ AddPosZ(GetSpeedX() * (a_Dt / 1000));
+ if (GetPosZ() <= OldZ - 1) SetSpeedX(0);
}
break;
}
-
case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST
{
SetRotation(135);
- SetPosY(floor(GetPosY()) + 0.2);
+ SetPosY(floor(GetPosY()) + 0.55);
- if (SpeedZ < 0)
+ if (TestBlockCollision(a_RailMeta)) return;
+
+ if (GetSpeedZ() < 0)
{
- SpeedX = SpeedZ;
+ int OldX = (int)floor(GetPosX());
+ AddSpeedX(GetSpeedZ() + 0.5);
+ AddPosX(GetSpeedZ() * (a_Dt / 1000));
+ if (GetPosX() <= OldX - 1) SetSpeedZ(0);
}
- else if (SpeedX > 0)
+ else if (GetSpeedX() > 0)
{
- SpeedZ = SpeedX;
+ int OldZ = (int)floor(GetPosZ());
+ AddSpeedZ(GetSpeedX() - 0.5);
+ AddPosZ(GetSpeedX() * (a_Dt / 1000));
+ if (GetPosZ() >= OldZ + 1) SetSpeedX(0);
}
break;
}
-
case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST
{
SetRotation(45);
- SetPosY(floor(GetPosY()) + 0.2);
+ SetPosY(floor(GetPosY()) + 0.55);
+
+ if (TestBlockCollision(a_RailMeta)) return;
- if (SpeedZ < 0)
+ if (GetSpeedZ() < 0)
{
- SpeedX = (0 - SpeedZ);
+ int OldX = (int)floor(GetPosX());
+ AddSpeedX(-GetSpeedZ() - 0.5);
+ AddPosX(-GetSpeedZ() * (a_Dt / 1000));
+ if (GetPosX() >= OldX + 1) SetSpeedZ(0);
}
- else if (SpeedX < 0)
+ else if (GetSpeedX() < 0)
{
- SpeedZ = (0 - SpeedX);
+ int OldZ = (int)floor(GetPosZ());
+ AddSpeedZ(-GetSpeedX() - 0.5);
+ AddPosZ(-GetSpeedX() * (a_Dt / 1000));
+ if (GetPosZ() >= OldZ + 1) SetSpeedX(0);
}
break;
}
-
default:
{
ASSERT(!"Unhandled rail meta!"); // Dun dun DUN!
break;
}
}
+}
- // Set speed to speed variables
- SetSpeedX(SpeedX);
- SetSpeedY(SpeedY);
- SetSpeedZ(SpeedZ);
- // Broadcast position to client
- BroadcastMovementUpdate();
+
+void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
+{
+ // Initialise to 'slow down' values
+ int AccelDecelSpeed = -1;
+ int AccelDecelNegSpeed = 1;
+
+ if ((a_RailMeta & 0x8) == 0x8)
+ {
+ // Rail powered - set variables to 'speed up' values
+ AccelDecelSpeed = 1;
+ AccelDecelNegSpeed = -1;
+ }
+
+ switch (a_RailMeta & 0x07)
+ {
+ case E_META_RAIL_ZM_ZP: // NORTHSOUTH
+ {
+ SetRotation(270);
+ SetPosY(floor(GetPosY()) + 0.55);
+ SetSpeedY(0);
+ SetSpeedX(0);
+
+ if (TestBlockCollision(a_RailMeta)) return;
+
+ if (GetSpeedZ() != 0)
+ {
+ if (GetSpeedZ() > 0)
+ {
+ AddSpeedZ(AccelDecelNegSpeed);
+ }
+ else
+ {
+ AddSpeedZ(AccelDecelSpeed);
+ }
+ }
+ break;
+ }
+ case E_META_RAIL_XM_XP: // EASTWEST
+ {
+ SetRotation(180);
+ SetPosY(floor(GetPosY()) + 0.55);
+ SetSpeedY(0);
+ SetSpeedZ(0);
+
+ if (TestBlockCollision(a_RailMeta)) return;
+
+ if (GetSpeedX() != 0)
+ {
+ if (GetSpeedX() > 0)
+ {
+ AddSpeedX(AccelDecelSpeed);
+ }
+ else
+ {
+ AddSpeedX(AccelDecelNegSpeed);
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+
+
+
+void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
+{
+ m_bIsOnDetectorRail = true;
+ m_DetectorRailPosition = Vector3i((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()));
+
+ m_World->SetBlockMeta(m_DetectorRailPosition, a_RailMeta | 0x08);
+
+ HandleRailPhysics(a_RailMeta & 0x07, a_Dt);
+}
+
+
+
+
+
+void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta)
+{
+ switch (a_RailMeta)
+ {
+ case E_META_RAIL_ASCEND_XM:
+ case E_META_RAIL_ASCEND_XP:
+ case E_META_RAIL_XM_XP:
+ {
+ SetSpeedZ(0);
+ SetPosZ(floor(GetPosZ()) + 0.5);
+ break;
+ }
+ case E_META_RAIL_ASCEND_ZM:
+ case E_META_RAIL_ASCEND_ZP:
+ case E_META_RAIL_ZM_ZP:
+ {
+ SetSpeedX(0);
+ SetPosX(floor(GetPosX()) + 0.5);
+ break;
+ }
+ default: break;
+ }
+}
+
+
+
+
+
+bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
+{
+ switch (a_RailMeta)
+ {
+ case E_META_RAIL_ZM_ZP:
+ {
+ if (GetSpeedZ() > 0)
+ {
+ BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)ceil(GetPosZ()));
+ if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
+ {
+ // We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P
+ cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()), (int)floor(GetPosY()), (int)ceil(GetPosZ())), 0.5, 1);
+ cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
+
+ if (bbBlock.DoesIntersect(bbMinecart))
+ {
+ SetSpeed(0, 0, 0);
+ SetPosZ(floor(GetPosZ()) + 0.4);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1);
+ if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
+ {
+ cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1), 0.5, 1);
+ cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ() - 1), GetWidth() / 2, GetHeight());
+
+ if (bbBlock.DoesIntersect(bbMinecart))
+ {
+ SetSpeed(0, 0, 0);
+ SetPosZ(floor(GetPosZ()) + 0.65);
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ case E_META_RAIL_XM_XP:
+ {
+ if (GetSpeedX() > 0)
+ {
+ BLOCKTYPE Block = m_World->GetBlock((int)ceil(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()));
+ if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
+ {
+ cBoundingBox bbBlock(Vector3d((int)ceil(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())), 0.5, 1);
+ cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
+
+ if (bbBlock.DoesIntersect(bbMinecart))
+ {
+ SetSpeed(0, 0, 0);
+ SetPosX(floor(GetPosX()) + 0.4);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ()));
+ if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
+ {
+ cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ())), 0.5, 1);
+ cBoundingBox bbMinecart(Vector3d(GetPosX() - 1, floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
+
+ if (bbBlock.DoesIntersect(bbMinecart))
+ {
+ SetSpeed(0, 0, 0);
+ SetPosX(floor(GetPosX()) + 0.65);
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ case E_META_RAIL_CURVED_ZM_XM:
+ case E_META_RAIL_CURVED_ZM_XP:
+ case E_META_RAIL_CURVED_ZP_XM:
+ case E_META_RAIL_CURVED_ZP_XP:
+ {
+ BLOCKTYPE BlockXM = m_World->GetBlock((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ()));
+ BLOCKTYPE BlockXP = m_World->GetBlock((int)floor(GetPosX()) + 1, (int)floor(GetPosY()), (int)floor(GetPosZ()));
+ BLOCKTYPE BlockZM = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) + 1);
+ BLOCKTYPE BlockZP = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) + 1);
+ if (
+ (!IsBlockRail(BlockXM) && g_BlockIsSolid[BlockXM]) ||
+ (!IsBlockRail(BlockXP) && g_BlockIsSolid[BlockXP]) ||
+ (!IsBlockRail(BlockZM) && g_BlockIsSolid[BlockZM]) ||
+ (!IsBlockRail(BlockZP) && g_BlockIsSolid[BlockZP])
+ )
+ {
+ SetSpeed(0, 0, 0);
+ SetPosition((int)floor(GetPosX()) + 0.5, GetPosY(), (int)floor(GetPosZ()) + 0.5);
+ return true;
+ }
+ break;
+ }
+ default: break;
+ }
+ return false;
}
@@ -358,6 +599,14 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk)
void cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
{
+ if (TDI.Attacker->IsPlayer() && ((cPlayer *)TDI.Attacker)->IsGameModeCreative())
+ {
+ Destroy();
+ TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative
+ super::DoTakeDamage(TDI);
+ return; // No drops for creative
+ }
+
m_LastDamage = TDI.FinalDamage;
super::DoTakeDamage(TDI);
@@ -365,7 +614,7 @@ void cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
if (GetHealth() <= 0)
{
- Destroy(true);
+ Destroy();
cItems Drops;
switch (m_Payload)
@@ -410,6 +659,18 @@ void cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
+void cMinecart::Destroyed()
+{
+ if (m_bIsOnDetectorRail)
+ {
+ m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
+ }
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cEmptyMinecart:
@@ -489,7 +750,8 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
super(mpFurnace, a_X, a_Y, a_Z),
- m_IsFueled(false)
+ m_IsFueled(false),
+ m_FueledTimeLeft(-1)
{
}
@@ -505,8 +767,12 @@ void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
-
+ if (!m_IsFueled) // We don't want to change the direction by right clicking it.
+ {
+ AddSpeed(a_Player.GetLookVector().x, 0, a_Player.GetLookVector().z);
+ }
m_IsFueled = true;
+ m_FueledTimeLeft = m_FueledTimeLeft + 600; // The minecart will be active 600 more ticks.
m_World->BroadcastEntityMetadata(*this);
}
}
@@ -515,6 +781,32 @@ void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
+void cMinecartWithFurnace::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ if (m_IsFueled)
+ {
+ m_FueledTimeLeft--;
+ if (m_FueledTimeLeft < 0)
+ {
+ m_IsFueled = false;
+ m_World->BroadcastEntityMetadata(*this);
+ return;
+ }
+
+ if (GetSpeed().Length() > 6)
+ {
+ return;
+ }
+ AddSpeed(GetSpeed() / 4);
+ }
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cMinecartWithTNT:
diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h
index b1b48be4e..1ebddfdda 100644
--- a/src/Entities/Minecart.h
+++ b/src/Entities/Minecart.h
@@ -51,17 +51,38 @@ public:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
+ virtual void Destroyed() override;
int LastDamage(void) const { return m_LastDamage; }
- void HandleRailPhysics(float a_Dt, cChunk & a_Chunk);
ePayload GetPayload(void) const { return m_Payload; }
protected:
ePayload m_Payload;
+ int m_LastDamage;
+ Vector3i m_DetectorRailPosition;
+ bool m_bIsOnDetectorRail;
cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z);
- int m_LastDamage;
+ /** Handles physics on normal rails
+ For each tick, slow down on flat rails, speed up or slow down on ascending/descending rails (depending on direction), and turn on curved rails
+ */
+ void HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt);
+
+ /** Handles powered rail physics
+ Each tick, speed up or slow down cart, depending on metadata of rail (powered or not)
+ */
+ void HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta);
+
+ /** Handles detector rail activation
+ Activates detector rails when a minecart is on them. Calls HandleRailPhysics() for physics simulations
+ */
+ void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt);
+
+ /** Snaps a minecart to a rail's axis, resetting its speed */
+ void SnapToRail(NIBBLETYPE a_RailMeta);
+ /** Tests is a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no obstruction*/
+ bool TestBlockCollision(NIBBLETYPE a_RailMeta);
} ;
@@ -130,10 +151,18 @@ public:
// cEntity overrides:
virtual void OnRightClicked(cPlayer & a_Player) override;
- bool IsFueled (void) const { return m_IsFueled; }
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+
+ // Set functions.
+ void SetIsFueled(bool a_IsFueled, int a_FueledTimeLeft = -1) {m_IsFueled = a_IsFueled; m_FueledTimeLeft = a_FueledTimeLeft;}
+
+ // Get functions.
+ int GetFueledTimeLeft(void) const {return m_FueledTimeLeft; }
+ bool IsFueled (void) const {return m_IsFueled;}
private:
+ int m_FueledTimeLeft;
bool m_IsFueled;
} ;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index bc92790aa..fa6422389 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1884,3 +1884,33 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
+
+void cPlayer::Detach()
+{
+ super::Detach();
+ int PosX = (int)floor(GetPosX());
+ int PosY = (int)floor(GetPosY());
+ int PosZ = (int)floor(GetPosZ());
+
+ // Search for a position within an area to teleport player after detachment
+ // Position must be solid land, and occupied by a nonsolid block
+ // If nothing found, player remains where they are
+ for (int x = PosX - 2; x <= (PosX + 2); ++x)
+ {
+ for (int y = PosY; y <= (PosY + 3); ++y)
+ {
+ for (int z = PosZ - 2; z <= (PosZ + 2); ++z)
+ {
+ if (!g_BlockIsSolid[m_World->GetBlock(x, y, z)] && g_BlockIsSolid[m_World->GetBlock(x, y - 1, z)])
+ {
+ TeleportToCoords(x, y, z);
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index f9ce950ba..bf3ca08e8 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -350,6 +350,8 @@ public:
virtual bool IsCrouched (void) const { return m_IsCrouched; }
virtual bool IsSprinting(void) const { return m_IsSprinting; }
virtual bool IsRclking (void) const { return IsEating(); }
+
+ virtual void Detach(void);
protected:
typedef std::map< std::string, bool > PermissionMap;
diff --git a/src/Log.cpp b/src/Log.cpp
index a0de4531b..2d6be0f59 100644
--- a/src/Log.cpp
+++ b/src/Log.cpp
@@ -147,11 +147,11 @@ void cLog::Log(const char * a_Format, va_list argList)
-void cLog::Log(const char* a_Format, ...)
+void cLog::Log(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
- Log( a_Format, argList );
+ Log(a_Format, argList);
va_end(argList);
}
@@ -159,9 +159,9 @@ void cLog::Log(const char* a_Format, ...)
-void cLog::SimpleLog(const char* a_String)
+void cLog::SimpleLog(const char * a_String)
{
- Log("%s", a_String );
+ Log("%s", a_String);
}
diff --git a/src/Log.h b/src/Log.h
index d00022c6f..cba248dae 100644
--- a/src/Log.h
+++ b/src/Log.h
@@ -14,11 +14,11 @@ private:
public:
cLog(const AString & a_FileName);
~cLog();
- void Log(const char* a_Format, va_list argList );
- void Log(const char* a_Format, ...);
+ void Log(const char * a_Format, va_list argList);
+ void Log(const char * a_Format, ...);
// tolua_begin
- void SimpleLog(const char* a_String);
- void OpenLog( const char* a_FileName );
+ void SimpleLog(const char * a_String);
+ void OpenLog(const char * a_FileName);
void CloseLog();
void ClearLog();
static cLog* GetInstance();
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 68992155e..162194bc6 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1037,11 +1037,18 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
return;
}
- HandlePacket(bb, PacketType);
+ if (!HandlePacket(bb, PacketType))
+ {
+ // Unknown packet, already been reported, just bail out
+ return;
+ }
if (bb.GetReadableSpace() != 1)
{
// Read more or less than packet length, report as error
+ LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x. Read %u bytes, packet contained %u bytes",
+ PacketType, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen
+ );
ASSERT(!"Read wrong number of bytes!");
m_Client->PacketError(PacketType);
}
@@ -1051,7 +1058,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
-void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
+bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
{
switch (m_State)
{
@@ -1060,8 +1067,8 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
// Status
switch (a_PacketType)
{
- case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return;
- case 0x01: HandlePacketStatusPing (a_ByteBuffer); return;
+ case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true;
+ case 0x01: HandlePacketStatusPing (a_ByteBuffer); return true;
}
break;
}
@@ -1071,8 +1078,8 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
// Login
switch (a_PacketType)
{
- case 0x00: HandlePacketLoginStart (a_ByteBuffer); return;
- case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return;
+ case 0x00: HandlePacketLoginStart (a_ByteBuffer); return true;
+ case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true;
}
break;
}
@@ -1082,29 +1089,29 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
// Game
switch (a_PacketType)
{
- case 0x00: HandlePacketKeepAlive (a_ByteBuffer); return;
- case 0x01: HandlePacketChatMessage (a_ByteBuffer); return;
- case 0x02: HandlePacketUseEntity (a_ByteBuffer); return;
- case 0x03: HandlePacketPlayer (a_ByteBuffer); return;
- case 0x04: HandlePacketPlayerPos (a_ByteBuffer); return;
- case 0x05: HandlePacketPlayerLook (a_ByteBuffer); return;
- case 0x06: HandlePacketPlayerPosLook (a_ByteBuffer); return;
- case 0x07: HandlePacketBlockDig (a_ByteBuffer); return;
- case 0x08: HandlePacketBlockPlace (a_ByteBuffer); return;
- case 0x09: HandlePacketSlotSelect (a_ByteBuffer); return;
- case 0x0a: HandlePacketAnimation (a_ByteBuffer); return;
- case 0x0b: HandlePacketEntityAction (a_ByteBuffer); return;
- case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return;
- case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return;
- case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return;
+ case 0x00: HandlePacketKeepAlive (a_ByteBuffer); return true;
+ case 0x01: HandlePacketChatMessage (a_ByteBuffer); return true;
+ case 0x02: HandlePacketUseEntity (a_ByteBuffer); return true;
+ case 0x03: HandlePacketPlayer (a_ByteBuffer); return true;
+ case 0x04: HandlePacketPlayerPos (a_ByteBuffer); return true;
+ case 0x05: HandlePacketPlayerLook (a_ByteBuffer); return true;
+ case 0x06: HandlePacketPlayerPosLook (a_ByteBuffer); return true;
+ case 0x07: HandlePacketBlockDig (a_ByteBuffer); return true;
+ case 0x08: HandlePacketBlockPlace (a_ByteBuffer); return true;
+ case 0x09: HandlePacketSlotSelect (a_ByteBuffer); return true;
+ case 0x0a: HandlePacketAnimation (a_ByteBuffer); return true;
+ case 0x0b: HandlePacketEntityAction (a_ByteBuffer); return true;
+ case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true;
+ case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true;
+ case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
case 0x0f: // Confirm transaction - not used in MCS
- case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return;
- case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return;
- case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return;
- case 0x14: HandlePacketTabComplete (a_ByteBuffer); return;
- case 0x15: HandlePacketClientSettings (a_ByteBuffer); return;
- case 0x16: HandlePacketClientStatus (a_ByteBuffer); return;
- case 0x17: HandlePacketPluginMessage (a_ByteBuffer); return;
+ case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
+ case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
+ case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return true;
+ case 0x14: HandlePacketTabComplete (a_ByteBuffer); return true;
+ case 0x15: HandlePacketClientSettings (a_ByteBuffer); return true;
+ case 0x16: HandlePacketClientStatus (a_ByteBuffer); return true;
+ case 0x17: HandlePacketPluginMessage (a_ByteBuffer); return true;
}
break;
}
@@ -1112,6 +1119,7 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
// Unknown packet type, report to the client:
m_Client->PacketUnknown(a_PacketType);
+ return false;
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index fd6b1fc0f..07dba834b 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -222,8 +222,10 @@ protected:
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
void AddReceivedData(const char * a_Data, int a_Size);
- /// Reads and handles the packet. The packet length and type have already been read.
- void HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType);
+ /** Reads and handles the packet. The packet length and type have already been read.
+ Returns true if the packet was understood, false if it was an unknown packet
+ */
+ bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType);
// Packet handlers while in the Status state (m_State == 1):
void HandlePacketStatusPing (cByteBuffer & a_ByteBuffer);
diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp
index 6ab915d03..469680098 100644
--- a/src/Simulator/RedstoneSimulator.cpp
+++ b/src/Simulator/RedstoneSimulator.cpp
@@ -69,7 +69,7 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu
// Changeable sources
((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
- ((Block == E_BLOCK_DETECTOR_RAIL) && (Meta & 0x08) == 0x08) ||
+ ((Block == E_BLOCK_DETECTOR_RAIL) && (Meta & 0x08) == 0) ||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
(((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0))
)
@@ -505,8 +505,7 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
// transferring power to other wires around.
// However, self not directly powered anymore, so source must have been removed,
// therefore, self must be set to meta zero
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0);
- m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, 0); // SetMeta & WakeUpSims doesn't seem to work here, so SetBlock
return; // No need to process block power sets because self not powered
}
else
@@ -903,6 +902,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B
else
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
+ m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
@@ -965,6 +965,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B
else
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
+ m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
index 0b38297ef..0dbd41c12 100644
--- a/src/StringUtils.cpp
+++ b/src/StringUtils.cpp
@@ -18,27 +18,40 @@
-AString & AppendVPrintf(AString & str, const char *format, va_list args)
+AString & AppendVPrintf(AString & str, const char * format, va_list args)
{
ASSERT(format != NULL);
char buffer[2048];
size_t len;
+ #ifdef va_copy
+ va_list argsCopy;
+ va_copy(argsCopy, args);
+ #else
+ #define argsCopy args
+ #endif
#ifdef _MSC_VER
// MS CRT provides secure printf that doesn't behave like in the C99 standard
- if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, args)) != -1)
+ if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, argsCopy)) != -1)
#else // _MSC_VER
- if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, args)) < ARRAYCOUNT(buffer))
+ if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, argsCopy)) < ARRAYCOUNT(buffer))
#endif // else _MSC_VER
{
// The result did fit into the static buffer
+ #ifdef va_copy
+ va_end(argsCopy);
+ #endif
str.append(buffer, len);
return str;
}
+ #ifdef va_copy
+ va_end(argsCopy);
+ #endif
- // The result did not fit into the static buffer
+ // The result did not fit into the static buffer, use a dynamic buffer:
#ifdef _MSC_VER
// for MS CRT, we need to calculate the result length
+ // MS doesn't have va_copy() and does nod need it at all
len = _vscprintf(format, args);
if (len == -1)
{
@@ -47,13 +60,19 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args)
#endif // _MSC_VER
// Allocate a buffer and printf into it:
+ #ifdef va_copy
+ va_copy(argsCopy, args);
+ #endif
std::vector<char> Buffer(len + 1);
#ifdef _MSC_VER
- vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, args);
+ vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
#else // _MSC_VER
- vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, args);
+ vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
#endif // else _MSC_VER
str.append(&(Buffer.front()), Buffer.size() - 1);
+ #ifdef va_copy
+ va_end(argsCopy);
+ #endif
return str;
}
@@ -89,7 +108,7 @@ AString Printf(const char * format, ...)
-AString & AppendPrintf(AString &str, const char *format, ...)
+AString & AppendPrintf(AString &str, const char * format, ...)
{
va_list args;
va_start(args, format);
diff --git a/src/StringUtils.h b/src/StringUtils.h
index 2373f3843..dfbfc2a75 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -21,7 +21,7 @@ typedef std::list<AString> AStringList;
-/// Add the formated string to the existing data in the string
+/** Add the formated string to the existing data in the string */
extern AString & AppendVPrintf(AString & str, const char * format, va_list args);
/// Output the formatted text into the string
diff --git a/src/World.cpp b/src/World.cpp
index 1cf82d641..2b85e4b58 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -690,6 +690,7 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
TickClients(a_Dt);
TickQueuedBlocks();
TickQueuedTasks();
+ TickScheduledTasks();
GetSimulatorManager()->Simulate(a_Dt);
@@ -861,6 +862,31 @@ void cWorld::TickQueuedTasks(void)
} // for itr - m_Tasks[]
}
+void cWorld::TickScheduledTasks()
+{
+ ScheduledTaskList Tasks;
+ // Make a copy of the tasks to avoid deadlocks on accessing m_Tasks
+ {
+ cCSLock Lock(m_CSScheduledTasks);
+ ScheduledTaskList::iterator itr = m_ScheduledTasks.begin();
+ while (itr != m_ScheduledTasks.end() && (*itr)->Ticks > 0)
+ {
+ Tasks.push_back(m_ScheduledTasks.front());
+ m_ScheduledTasks.pop_front();
+ }
+ for(;itr != m_ScheduledTasks.end(); itr++)
+ {
+ (*itr)->Ticks--;
+ }
+ }
+
+ // Execute and delete each task:
+ for (ScheduledTaskList::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
+ {
+ (*itr)->Run(*this);
+ delete *itr;
+ } // for itr - m_Tasks[]
+}
@@ -2571,6 +2597,19 @@ void cWorld::QueueTask(cTask * a_Task)
m_Tasks.push_back(a_Task);
}
+void cWorld::ScheduleTask(cScheduledTask * a_Task)
+{
+ cCSLock Lock(m_CSScheduledTasks);
+ for(ScheduledTaskList::iterator itr = m_ScheduledTasks.begin(); itr != m_ScheduledTasks.end(); itr++)
+ {
+ if((*itr)->Ticks >= a_Task->Ticks)
+ {
+ m_ScheduledTasks.insert(itr, a_Task);
+ return;
+ }
+ }
+ m_ScheduledTasks.push_back(a_Task);
+}
diff --git a/src/World.h b/src/World.h
index b61708d03..6ddb3ec86 100644
--- a/src/World.h
+++ b/src/World.h
@@ -82,7 +82,18 @@ public:
virtual void Run(cWorld & a_World) = 0;
} ;
+ /// A common ancestor for all scheduled tasks queued onto the tick thread
+ class cScheduledTask
+ {
+ public:
+ cScheduledTask(const int a_Ticks) : Ticks(a_Ticks) {};
+ virtual ~cScheduledTask() {};
+ virtual void Run(cWorld & a_World) = 0;
+ int Ticks;
+ };
+
typedef std::vector<cTask *> cTasks;
+ typedef std::list<cScheduledTask *> ScheduledTaskList;
class cTaskSaveAllChunks :
public cTask
@@ -533,6 +544,9 @@ public:
/// Queues a task onto the tick thread. The task object will be deleted once the task is finished
void QueueTask(cTask * a_Task); // Exported in ManualBindings.cpp
+
+ // Queues a task onto the tick thread. The task object will be deleted once the task is finished
+ void ScheduleTask(cScheduledTask * a_Task);
/// Returns the number of chunks loaded
int GetNumChunks() const; // tolua_export
@@ -745,9 +759,16 @@ private:
/// Guards the m_Tasks
cCriticalSection m_CSTasks;
+ /// Guards the m_ScheduledTasks
+ cCriticalSection m_CSScheduledTasks;
+
/// Tasks that have been queued onto the tick thread; guarded by m_CSTasks
cTasks m_Tasks;
+ /// Tasks that have been queued to be executed on the tick thread at some number of ticks in
+ /// the future; guarded by m_CSScheduledTasks
+ ScheduledTaskList m_ScheduledTasks;
+
/// Guards m_Clients
cCriticalSection m_CSClients;
@@ -775,6 +796,9 @@ private:
/// Executes all tasks queued onto the tick thread
void TickQueuedTasks(void);
+ /// Executes all tasks queued onto the tick thread
+ void TickScheduledTasks(void);
+
/// Ticks all clients that are in this world
void TickClients(float a_Dt);