summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt53
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--CONTRIBUTORS3
-rw-r--r--Install/MCServer_high_detail_debug.cmd2
-rw-r--r--Install/MCServer_medium_detail_debug.cmd2
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua17
-rw-r--r--MCServer/Plugins/APIDump/Hooks/OnKilling.lua1
-rw-r--r--MCServer/Plugins/APIDump/main.css2
-rw-r--r--MCServer/Plugins/APIDump/main_APIDump.lua32
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua111
-rw-r--r--MCServer/Plugins/Debuggers/Info.lua6
-rw-r--r--MCServer/install_windows_service.cmd2
-rw-r--r--SetFlags.cmake12
-rw-r--r--Tools/MCADefrag/MCADefrag.cpp2
-rw-r--r--Tools/ProtoProxy/ProtoProxy.cpp2
m---------lib/SQLiteCpp0
-rw-r--r--src/Bindings/ManualBindings.cpp58
-rw-r--r--src/BlockArea.cpp59
-rw-r--r--src/BlockArea.h9
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp42
-rw-r--r--src/BlockEntities/FurnaceEntity.h8
-rw-r--r--src/Blocks/BlockButton.h6
-rw-r--r--src/Blocks/BlockCocoaPod.h4
-rw-r--r--src/Blocks/BlockLadder.h4
-rw-r--r--src/Blocks/BlockLever.h4
-rw-r--r--src/Blocks/BlockQuartz.h5
-rw-r--r--src/Blocks/BlockSideways.h4
-rw-r--r--src/Blocks/BlockTrapdoor.h7
-rw-r--r--src/Blocks/BlockTripwireHook.h8
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/ClientHandle.cpp58
-rw-r--r--src/ClientHandle.h4
-rw-r--r--src/CraftingRecipes.cpp9
-rw-r--r--src/Defines.h36
-rw-r--r--src/Entities/HangingEntity.h15
-rw-r--r--src/Entities/Player.h21
-rw-r--r--src/Generating/MineShafts.cpp7
-rw-r--r--src/Globals.h2
-rw-r--r--src/LineBlockTracer.cpp19
-rw-r--r--src/LoggerListeners.cpp20
-rw-r--r--src/LoggerListeners.h2
-rw-r--r--src/MobCensus.cpp4
-rw-r--r--src/OSSupport/CMakeLists.txt2
-rw-r--r--src/OSSupport/Event.cpp4
-rw-r--r--src/OSSupport/Semaphore.cpp107
-rw-r--r--src/OSSupport/Semaphore.h17
-rw-r--r--src/Protocol/Protocol.h6
-rw-r--r--src/Protocol/Protocol17x.cpp72
-rw-r--r--src/Protocol/Protocol17x.h6
-rw-r--r--src/Protocol/Protocol18x.cpp60
-rw-r--r--src/Protocol/Protocol18x.h6
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp60
-rw-r--r--src/Protocol/ProtocolRecognizer.h6
-rw-r--r--src/Root.cpp2
-rw-r--r--src/WorldStorage/FastNBT.cpp3
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp5
-rw-r--r--src/main.cpp204
57 files changed, 922 insertions, 303 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ae83662c9..53e836262 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,11 @@ cmake_minimum_required (VERSION 2.8.7)
# 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)
+# Enable the support for solution folders in MSVC
+if (MSVC)
+ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+endif()
+
# These env variables are used for configuring Travis CI builds.
# See https://github.com/mc-server/MCServer/pull/767
if(DEFINED ENV{TRAVIS_MCSERVER_BUILD_TYPE})
@@ -19,6 +24,7 @@ if(DEFINED ENV{TRAVIS_BUILD_WITH_COVERAGE})
endif()
if(DEFINED ENV{MCSERVER_BUILD_ID})
+ # The build info is defined by the build system (Travis / Jenkins)
set(BUILD_ID $ENV{MCSERVER_BUILD_ID})
set(BUILD_SERIES_NAME $ENV{MCSERVER_BUILD_SERIES_NAME})
set(BUILD_DATETIME $ENV{MCSERVER_BUILD_DATETIME})
@@ -29,12 +35,41 @@ if(DEFINED ENV{MCSERVER_BUILD_ID})
execute_process(
COMMAND git rev-parse HEAD
RESULT_VARIABLE GIT_EXECUTED
- OUTPUT_VARIABLE BUILD_COMMIT_ID)
- string(STRIP ${BUILD_COMMIT_ID} BUILD_COMMIT_ID)
+ OUTPUT_VARIABLE BUILD_COMMIT_ID
+ )
+ string(STRIP ${BUILD_COMMIT_ID} BUILD_COMMIT_ID)
if (NOT (GIT_EXECUTED EQUAL 0))
message(FATAL_ERROR "Could not identifiy git commit id")
endif()
endif()
+else()
+ # This is a local build, stuff in some basic info:
+ set(BUILD_ID "Unknown")
+ set(BUILD_SERIES_NAME "local build")
+ execute_process(
+ COMMAND git rev-parse HEAD
+ RESULT_VARIABLE GIT_EXECUTED
+ OUTPUT_VARIABLE BUILD_COMMIT_ID
+ )
+ if (NOT(GIT_EXECUTED EQUAL 0))
+ set(BUILD_COMMIT_ID "Unknown")
+ endif()
+ string(STRIP ${BUILD_COMMIT_ID} BUILD_COMMIT_ID)
+ execute_process(
+ COMMAND git log -1 --date=iso --pretty=format:%ai
+ RESULT_VARIABLE GIT_EXECUTED
+ OUTPUT_VARIABLE BUILD_DATETIME
+ )
+ if (NOT(GIT_EXECUTED EQUAL 0))
+ set(BUILD_DATETIME "Unknown")
+ endif()
+ string(STRIP ${BUILD_DATETIME} BUILD_DATETIME)
+
+ # The BUILD_COMMIT_ID and BUILD_DATETIME aren't updated on each repo pull
+ # They are only updated when cmake re-configures the project
+ # Therefore mark them as "approx: "
+ set(BUILD_COMMIT_ID "approx: ${BUILD_COMMIT_ID}")
+ set(BUILD_DATETIME "approx: ${BUILD_DATETIME}")
endif()
# We need C++11 features, Visual Studio has those from VS2012, but it needs a new platform toolset for those; VS2013 supports them natively:
@@ -67,6 +102,7 @@ if(${BUILD_UNSTABLE_TOOLS})
add_subdirectory(Tools/GeneratorPerformanceTest/)
endif()
+include(CheckCXXCompilerFlag)
include(SetFlags.cmake)
set_flags()
set_lib_flags()
@@ -102,6 +138,7 @@ set(SQLITECPP_RUN_DOXYGEN OFF CACHE BOOL "Run Doxygen C++ documentation tool
set(SQLITECPP_BUILD_EXAMPLES OFF CACHE BOOL "Build examples." FORCE)
set(SQLITECPP_BUILD_TESTS OFF CACHE BOOL "Build and run tests." FORCE)
set(SQLITECPP_INTERNAL_SQLITE OFF CACHE BOOL "Add the internal SQLite3 source to the project." FORCE)
+set(SQLITE_ENABLE_COLUMN_METADATA OFF CACHE BOOL "" FORCE)
# Set options for LibEvent, disable all their tests and benchmarks:
set(EVENT__DISABLE_OPENSSL YES CACHE BOOL "Disable OpenSSL in LibEvent" FORCE)
@@ -130,7 +167,7 @@ add_subdirectory(lib/sqlite/)
add_subdirectory(lib/SQLiteCpp/)
add_subdirectory(lib/expat/)
add_subdirectory(lib/luaexpat/)
-add_subdirectory(lib/libevent/)
+add_subdirectory(lib/libevent/ EXCLUDE_FROM_ALL)
# Add proper include directories so that SQLiteCpp can find SQLite3:
get_property(SQLITECPP_INCLUDES DIRECTORY "lib/SQLiteCpp/" PROPERTY INCLUDE_DIRECTORIES)
@@ -160,3 +197,13 @@ if(${SELF_TEST})
add_subdirectory (tests)
endif()
+# Put project into solution folders in MSVC:
+if (MSVC)
+ set_target_properties(event_core event_extra expat jsoncpp lua luaexpat mbedtls sqlite SQLiteCpp tolualib zlib PROPERTIES FOLDER Lib)
+ set_target_properties(luaproxy tolua PROPERTIES FOLDER Support)
+ if (${SELF_TEST})
+ set_target_properties(Network PROPERTIES FOLDER Lib)
+ set_target_properties(arraystocoords-exe coordinates-exe copies-exe copyblocks-exe creatable-exe EchoServer Google-exe ChunkBuffer NameLookup PROPERTIES FOLDER Tests)
+ endif()
+endif()
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4e57e6efb..1b43ed214 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,7 +23,7 @@ Here are the conventions:
- This helps prevent mistakes such as `if (a & 1 == 0)`
*
* Use the provided wrappers for OS stuff:
- - Threading is done by inheriting from `cIsThread`, thread synchronization through `cCriticalSection`, `cSemaphore` and `cEvent`, file access and filesystem operations through the `cFile` class, high-precision timers through `cTimer`, high-precision sleep through `cSleep`
+ - Threading is done by inheriting from `cIsThread`, thread synchronization through `cCriticalSection` and `cEvent`, file access and filesystem operations through the `cFile` class, high-precision timers through `cTimer`, high-precision sleep through `cSleep`
* No magic numbers, use named constants:
- `E_ITEM_XXX`, `E_BLOCK_XXX` and `E_META_XXX` for items and blocks
- `cEntity::etXXX` for entity types, `cMonster::mtXXX` for mob types
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 3505d7155..82ae6a7a8 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -3,11 +3,14 @@ Many people have contributed to MCServer, and this list attempts to broadcast at
BasedDoge (Donated AlchemistVillage prefabs)
bearbin (Alexander Harkness)
beeduck
+birkett (Anthony Birkett)
derouinw
Diusrex
Duralex
FakeTruth (founder)
+HaoTNN
Howaner
+jan64
jasperarmstrong
keyboard
Lapayo
diff --git a/Install/MCServer_high_detail_debug.cmd b/Install/MCServer_high_detail_debug.cmd
index 384189c42..d94af8150 100644
--- a/Install/MCServer_high_detail_debug.cmd
+++ b/Install/MCServer_high_detail_debug.cmd
@@ -1 +1 @@
-MCServer /cdf \ No newline at end of file
+MCServer --crash-dump-full
diff --git a/Install/MCServer_medium_detail_debug.cmd b/Install/MCServer_medium_detail_debug.cmd
index b5bb0954c..0a33c27fd 100644
--- a/Install/MCServer_medium_detail_debug.cmd
+++ b/Install/MCServer_medium_detail_debug.cmd
@@ -1 +1 @@
-MCServer /cdg \ No newline at end of file
+MCServer --crash-dump-globals
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index 4af01c0a4..87edb226a 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -100,6 +100,11 @@ g_APIDesc =
CopyFrom = { Params = "BlockAreaSrc", Return = "", Notes = "Copies contents from BlockAreaSrc into self" },
CopyTo = { Params = "BlockAreaDst", Return = "", Notes = "Copies contents from self into BlockAreaDst." },
CountNonAirBlocks = { Params = "", Return = "number", Notes = "Returns the count of blocks that are not air. Returns 0 if blocktypes not available. Block metas are ignored (if present, air with any meta is still considered air)." },
+ CountSpecificBlocks =
+ {
+ { Params = "BlockType", Return = "number", Notes = "Counts the number of occurences of the specified blocktype contained in the area." },
+ { Params = "BlockType, BlockMeta", Return = "number", Notes = "Counts the number of occurrences of the specified blocktype + blockmeta combination contained in the area." },
+ },
Create = { Params = "SizeX, SizeY, SizeZ, [DataTypes]", Return = "", Notes = "Initializes this BlockArea to an empty area of the specified size and origin of {0, 0, 0}. Any previous contents are lost." },
Crop = { Params = "AddMinX, SubMaxX, AddMinY, SubMaxY, AddMinZ, SubMaxZ", Return = "", Notes = "Crops the specified number of blocks from each border. Modifies the size of this blockarea object." },
DumpToRawFile = { Params = "FileName", Return = "", Notes = "Dumps the raw data into a file. For debugging purposes only." },
@@ -1917,6 +1922,8 @@ a_Player:OpenWindow(Window);
SendMessagePrivateMsg = { Params = "Message, SenderName", Return = "", Notes = "Prepends Light Blue [MSG: *SenderName*] / prepends SenderName and colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For private messaging." },
SendMessageSuccess = { Params = "Message", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Success notification." },
SendMessageWarning = { Params = "Message, Sender", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Denotes that something concerning, such as plugin reload, is about to happen." },
+ SendAboveActionBarMessage = { Params = "Message", Return = "", Notes = "Sends the specified message to the player (shows above action bar, doesn't show for < 1.8 clients)." },
+ SendSystemMessage = { Params = "Message", Return = "", Notes = "Sends the specified message to the player (doesn't show for < 1.8 clients)." },
SendRotation = { Params = "YawDegrees, PitchDegrees", Return = "", Notes = "Sends the specified rotation to the player, forcing them to look that way" },
SetBedPos = { Params = "{{Vector3i|Position}}", Return = "", Notes = "Sets the internal representation of the last bed position the player has slept in. The player will respawn at this position if they die." },
SetCanFly = { Params = "CanFly", Notes = "Sets if the player can fly or not." },
@@ -2036,7 +2043,7 @@ a_Player:OpenWindow(Window);
BroadcastChat =
{
{ Params = "MessageText, MessageType", Return = "", Notes = "Broadcasts a message to all players, with its message type set to MessageType (default: mtCustom)." },
- { Params = "{{cCompositeChat|CompositeChat}}", Return = "", Notes = "Broadcasts a {{cCompositeChat|composite chat message} to all players." },
+ { Params = "{{cCompositeChat|CompositeChat}}", Return = "", Notes = "Broadcasts a {{cCompositeChat|composite chat message}} to all players." },
},
BroadcastChatDeath = { Params = "MessageText", Return = "", Notes = "Broadcasts the specified message to all players, with its message type set to mtDeath. Use for when a player has died." },
BroadcastChatFailure = { Params = "MessageText", Return = "", Notes = "Broadcasts the specified message to all players, with its message type set to mtFailure. Use for a command that failed to run because of insufficient permissions, etc." },
@@ -2046,12 +2053,16 @@ a_Player:OpenWindow(Window);
BroadcastChatLeave = { Params = "MessageText", Return = "", Notes = "Broadcasts the specified message to all players, with its message type set to mtLeave. Use for players leaving the server." },
BroadcastChatSuccess = { Params = "MessageText", Return = "", Notes = "Broadcasts the specified message to all players, with its message type set to mtSuccess. Use for success messages." },
BroadcastChatWarning = { Params = "MessageText", Return = "", Notes = "Broadcasts the specified message to all players, with its message type set to mtWarning. Use for concerning events, such as plugin reload etc." },
- CreateAndInitializeWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Creates a new world and initializes it. If there is a world whith the same name it returns nil.<br><br><b>NOTE</b>This function is currently unsafe, do not use!" },
+ CreateAndInitializeWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Creates a new world and initializes it. If there is a world whith the same name it returns nil.<br><br><b>NOTE:</b> This function is currently unsafe, do not use!" },
FindAndDoWithPlayer = { Params = "PlayerName, CallbackFunction", Return = "bool", Notes = "Calls the given callback function for the player with the name best matching the name string provided.<br>This function is case-insensitive and will match partial names.<br>Returns false if player not found or there is ambiguity, true otherwise. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}})</pre>" },
DoWithPlayerByUUID = { Params = "PlayerUUID, CallbackFunction", Return = "bool", Notes = "If there is the player with the uuid, calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}})</pre> The function returns false if the player was not found, or whatever bool value the callback returned if the player was found." },
ForEachPlayer = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each player. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|cPlayer}})</pre>" },
ForEachWorld = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each world. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cWorld|cWorld}})</pre>" },
- Get = { Params = "", Return = "Root object", Notes = "(STATIC)This function returns the cRoot object." },
+ Get = { Params = "", Return = "Root object", Notes = "(STATIC) This function returns the cRoot object." },
+ GetBuildCommitID = { Params = "", Return = "string", Notes = "(STATIC) For official builds (Travis CI / Jenkins) it returns the exact commit hash used for the build. For unofficial local builds, returns the approximate commit hash (since the true one cannot be determined), formatted as \"approx: &lt;CommitHash&gt;\"." },
+ GetBuildDateTime = { Params = "", Return = "string", Notes = "(STATIC) For official builds (Travic CI / Jenkins) it returns the date and time of the build. For unofficial local builds, returns the approximate datetime of the commit (since the true one cannot be determined), formatted as \"approx: &lt;DateTime-iso8601&gt;\"." },
+ GetBuildID = { Params = "", Return = "string", Notes = "(STATIC) For official builds (Travis CI / Jenkins) it returns the unique ID of the build, as recognized by the build system. For unofficial local builds, returns the string \"Unknown\"." },
+ GetBuildSeriesName = { Params = "", Return = "string", Notes = "(STATIC) For official builds (Travis CI / Jenkins) it returns the series name of the build (for example \"MCServer Windows x64 Master\"). For unofficial local builds, returns the string \"local build\"." },
GetCraftingRecipes = { Params = "", Return = "{{cCraftingRecipe|cCraftingRecipe}}", Notes = "Returns the CraftingRecipes object" },
GetDefaultWorld = { Params = "", Return = "{{cWorld|cWorld}}", Notes = "Returns the world object from the default world." },
GetFurnaceFuelBurnTime = { Params = "{{cItem|Fuel}}", Return = "number", Notes = "(STATIC) Returns the number of ticks for how long the item would fuel a furnace. Returns zero if not a fuel." },
diff --git a/MCServer/Plugins/APIDump/Hooks/OnKilling.lua b/MCServer/Plugins/APIDump/Hooks/OnKilling.lua
index 8ec1cfe2e..5e84009db 100644
--- a/MCServer/Plugins/APIDump/Hooks/OnKilling.lua
+++ b/MCServer/Plugins/APIDump/Hooks/OnKilling.lua
@@ -17,6 +17,7 @@ return
{
{ Name = "Victim", Type = "{{cPawn}}", Notes = "The player or mob that is about to be killed" },
{ Name = "Killer", Type = "{{cEntity}}", Notes = "The entity that has caused the victim to lose the last point of health. May be nil for environment damage" },
+ { Name = "TDI", Type = "{{TakeDamageInfo}}", Notes = "The damage type, cause and effects." },
},
Returns = [[
If the function returns false or no value, MCServer calls other plugins with this event. If the
diff --git a/MCServer/Plugins/APIDump/main.css b/MCServer/Plugins/APIDump/main.css
index 8041e0d01..e5685caab 100644
--- a/MCServer/Plugins/APIDump/main.css
+++ b/MCServer/Plugins/APIDump/main.css
@@ -61,7 +61,7 @@ footer
font-family: Segoe UI Light, Helvetica;
}
-#content
+#content, #timestamp
{
padding: 0px 25px 25px 25px;
}
diff --git a/MCServer/Plugins/APIDump/main_APIDump.lua b/MCServer/Plugins/APIDump/main_APIDump.lua
index e841922b6..543a299af 100644
--- a/MCServer/Plugins/APIDump/main_APIDump.lua
+++ b/MCServer/Plugins/APIDump/main_APIDump.lua
@@ -153,6 +153,19 @@ end
+--- Returns the timestamp in HTML format
+-- The timestamp will be inserted to all generated HTML files
+local function GetHtmlTimestamp()
+ return string.format("<div id='timestamp'>Generated on %s, Build ID %s, Commit %s</div>",
+ os.date("%Y-%m-%d %H:%M:%S"),
+ cRoot:GetBuildID(), cRoot:GetBuildCommitID()
+ )
+end
+
+
+
+
+
local function WriteArticles(f)
f:write([[
<a name="articles"><h2>Articles</h2></a>
@@ -296,7 +309,9 @@ local function WriteHtmlHook(a_Hook, a_HookNav)
f:write("<p>", (example.Desc or "<i>missing Desc</i>"), "</p>\n");
f:write("<pre class=\"prettyprint lang-lua\">", (example.Code or "<i>missing Code</i>"), "\n</pre>\n\n");
end
- f:write([[</td></tr></table></div><script>prettyPrint();</script></body></html>]]);
+ f:write([[</td></tr></table></div><script>prettyPrint();</script>]])
+ f:write(GetHtmlTimestamp())
+ f:write([[</body></html>]])
f:close();
end
@@ -941,8 +956,10 @@ local function WriteHtmlClass(a_ClassAPI, a_ClassMenu)
end
end
- cf:write([[</td></tr></table></div><script>prettyPrint();</script></body></html>]]);
- cf:close();
+ cf:write([[</td></tr></table></div><script>prettyPrint();</script>]])
+ cf:write(GetHtmlTimestamp())
+ cf:write([[</body></html>]])
+ cf:close()
end
@@ -1320,11 +1337,10 @@ local function DumpAPIHtml(a_API)
WriteStats(f);
- f:write([[ </ul>
- </div>
- </body>
-</html>]]);
- f:close();
+ f:write([[</ul></div>]])
+ f:write(GetHtmlTimestamp())
+ f:write([[</body></html>]])
+ f:close()
LOG("API subfolder written");
end
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index a49f8b5a6..bd0b94a06 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -1880,6 +1880,117 @@ end
+--- Returns the square of the distance from the specified point to the specified line
+local function SqDistPtFromLine(x, y, x1, y1, x2, y2)
+ local dx = x - x1
+ local dy = y - y1
+ local px = x2 - x1
+ local py = y2 - y1
+ local ss = px * dx + py * dy
+ local ds = px * px + py * py
+
+ if (ss < 0) then
+ -- Return sqdistance from point 1
+ return dx * dx + dy * dy
+ end
+ if (ss > ds) then
+ -- Return sqdistance from point 2
+ return ((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y))
+ end
+
+ -- Return sqdistance from the line
+ if ((px * px + py * py) == 0) then
+ return dx * dx + dy * dy
+ else
+ return (py * dx - px * dy) * (py * dx - px * dy) / (px * px + py * py)
+ end
+end
+
+
+
+
+
+function HandleConsoleTestTracer(a_Split, a_EntireCmd)
+ -- Check required params:
+ if not(a_Split[7]) then
+ return true, "Usage: " .. a_Split[1] .. " <x1> <y1> <z1> <x2> <y2> <z2> [<WorldName>]"
+ end
+ local Coords = {}
+ for i = 1, 6 do
+ local v = tonumber(a_Split[i + 1])
+ if not(v) then
+ return true, "Parameter " .. (i + 1) .. " (" .. tostring(a_Split[i + 1]) .. ") not a number "
+ end
+ Coords[i] = v
+ end
+
+ -- Get the world in which to test:
+ local World
+ if (a_Split[8]) then
+ World = cRoot:GetWorld(a_Split[2])
+ else
+ World = cRoot:Get():GetDefaultWorld()
+ end
+ if not(World) then
+ return true, "No such world"
+ end
+
+ -- Define the callbacks to use for tracing:
+ local Callbacks =
+ {
+ OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_EntryFace)
+ LOG(string.format("{%d, %d, %d}: %s", a_BlockX, a_BlockY, a_BlockZ, ItemToString(cItem(a_BlockType, 1, a_BlockMeta))))
+ end,
+ OnNextBlockNoData = function(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace)
+ LOG(string.format("{%d, %d, %d} (no data)", a_BlockX, a_BlockY, a_BlockZ))
+ end,
+ OnNoChunk = function()
+ LOG("Chunk not loaded")
+ end,
+ OnNoMoreHits = function()
+ LOG("Trace finished")
+ end,
+ OnOutOfWorld = function()
+ LOG("Out of world")
+ end,
+ OnIntoWorld = function()
+ LOG("Into world")
+ end,
+ }
+
+ -- Approximate the chunks needed for the trace by iterating over all chunks and measuring their center's distance from the traced line
+ local Chunks = {}
+ local sx = math.floor(Coords[1] / 16)
+ local sz = math.floor(Coords[3] / 16)
+ local ex = math.floor(Coords[4] / 16)
+ local ez = math.floor(Coords[6] / 16)
+ local sgnx = (sx < ex) and 1 or -1
+ local sgnz = (sz < ez) and 1 or -1
+ for z = sz, ez, sgnz do
+ local ChunkCenterZ = z * 16 + 8
+ for x = sx, ex, sgnx do
+ local ChunkCenterX = x * 16 + 8
+ local sqdist = SqDistPtFromLine(ChunkCenterX, ChunkCenterZ, Coords[1], Coords[3], Coords[4], Coords[6])
+ if (sqdist <= 128) then
+ table.insert(Chunks, {x, z})
+ end
+ end
+ end
+
+ -- Load the chunks and do the trace once loaded:
+ World:ChunkStay(Chunks,
+ nil,
+ function()
+ cLineBlockTracer:Trace(World, Callbacks, Coords[1], Coords[2], Coords[3], Coords[4], Coords[5], Coords[6])
+ end
+ )
+ return true
+end
+
+
+
+
+
function HandleConsoleBBox(a_Split)
local bbox = cBoundingBox(0, 10, 0, 10, 0, 10)
local v1 = Vector3d(1, 1, 1)
diff --git a/MCServer/Plugins/Debuggers/Info.lua b/MCServer/Plugins/Debuggers/Info.lua
index 2e170487b..a76690ea1 100644
--- a/MCServer/Plugins/Debuggers/Info.lua
+++ b/MCServer/Plugins/Debuggers/Info.lua
@@ -235,6 +235,12 @@ g_PluginInfo =
Handler = HandleConsoleSchedule,
HelpString = "Tests the world scheduling",
},
+
+ ["testtracer"] =
+ {
+ Handler = HandleConsoleTestTracer,
+ HelpString = "Tests the cLineBlockTracer",
+ }
}, -- ConsoleCommands
} -- g_PluginInfo
diff --git a/MCServer/install_windows_service.cmd b/MCServer/install_windows_service.cmd
index ba8a8c128..d6b6c15a3 100644
--- a/MCServer/install_windows_service.cmd
+++ b/MCServer/install_windows_service.cmd
@@ -3,5 +3,5 @@ rem Alter this if you need to install multiple instances.
set SERVICENAME="MCServer"
set CURRENTDIR=%CD%
-sc create %SERVICENAME% binPath= "%CURRENTDIR%\MCServer.exe /service" start= auto DisplayName= %SERVICENAME%
+sc create %SERVICENAME% binPath= "%CURRENTDIR%\MCServer.exe -d" start= auto DisplayName= %SERVICENAME%
sc description %SERVICENAME% "Minecraft server instance" \ No newline at end of file
diff --git a/SetFlags.cmake b/SetFlags.cmake
index b79551eef..57cab5a1c 100644
--- a/SetFlags.cmake
+++ b/SetFlags.cmake
@@ -63,7 +63,7 @@ macro(set_flags)
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)
-
+
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
@@ -262,8 +262,11 @@ macro(set_exe_flags)
add_flags_cxx("-Wno-documentation")
endif()
if ("${CLANG_VERSION}" VERSION_GREATER 3.5)
- # Use this flag to ignore error for a reserved macro problem in sqlite 3
- add_flags_cxx("-Wno-reserved-id-macro")
+ check_cxx_compiler_flag(-Wno-reserved-id-macro HAS_NO_RESERVED_ID_MACRO)
+ if (HAS_NO_RESERVED_ID_MACRO)
+ # Use this flag to ignore error for a reserved macro problem in sqlite 3
+ add_flags_cxx("-Wno-reserved-id-macro")
+ endif()
endif()
endif()
endif()
@@ -277,7 +280,7 @@ endmacro()
# set_source_files_properties(${FILENAME} PROPERTIES COMPILE_FLAGS "-Wno-error=missing-prototypes -Wno-error=deprecated")
# set_source_files_properties(${FILENAME} PROPERTIES COMPILE_FLAGS "-Wno-error=shadow -Wno-error=old-style-cast -Wno-error=switch-enum -Wno-error=switch")
# set_source_files_properties(${FILENAME} PROPERTIES COMPILE_FLAGS "-Wno-error=float-equal -Wno-error=global-constructors")
-
+
# if ("${CLANG_VERSION}" VERSION_GREATER 3.0)
# # flags that are not present in 3.0
# set_source_files_properties(${FILENAME} PROPERTIES COMPILE_FLAGS "-Wno-error=covered-switch-default ")
@@ -286,4 +289,3 @@ endmacro()
# endif()
# endforeach()
# endif()
-
diff --git a/Tools/MCADefrag/MCADefrag.cpp b/Tools/MCADefrag/MCADefrag.cpp
index 0d38a87f1..80c6f5be2 100644
--- a/Tools/MCADefrag/MCADefrag.cpp
+++ b/Tools/MCADefrag/MCADefrag.cpp
@@ -22,7 +22,7 @@ static const Byte g_Zeroes[4096] = {0};
int main(int argc, char ** argv)
{
- cLogger::cListener * consoleLogListener = MakeConsoleListener();
+ cLogger::cListener * consoleLogListener = MakeConsoleListener(false);
cLogger::cListener * fileLogListener = new cFileListener();
cLogger::GetInstance().AttachListener(consoleLogListener);
cLogger::GetInstance().AttachListener(fileLogListener);
diff --git a/Tools/ProtoProxy/ProtoProxy.cpp b/Tools/ProtoProxy/ProtoProxy.cpp
index 3f427f83f..2d27d7556 100644
--- a/Tools/ProtoProxy/ProtoProxy.cpp
+++ b/Tools/ProtoProxy/ProtoProxy.cpp
@@ -16,7 +16,7 @@ int main(int argc, char ** argv)
{
// Initialize logging subsystem:
cLogger::InitiateMultithreading();
- auto consoleLogListener = MakeConsoleListener();
+ auto consoleLogListener = MakeConsoleListener(false);
auto fileLogListener = new cFileListener();
cLogger::GetInstance().AttachListener(consoleLogListener);
cLogger::GetInstance().AttachListener(fileLogListener);
diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp
-Subproject b17195b8d03e8908807c51f4d6ce610b148fc1b
+Subproject 49679e7b54726e2d94d3aad76a65aeb9c1088af
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index bce1891e2..7655d8c83 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -34,6 +34,7 @@
#include "../CompositeChat.h"
#include "../StringCompression.h"
#include "../CommandOutput.h"
+#include "../BuildInfo.h"
@@ -2079,6 +2080,50 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
+static int tolua_cRoot_GetBuildCommitID(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_COMMIT_ID);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cRoot_GetBuildDateTime(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_DATETIME);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cRoot_GetBuildID(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_ID);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cRoot_GetBuildSeriesName(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_SERIES_NAME);
+ return 1;
+}
+
+
+
+
+
static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S)
{
cLuaState L(tolua_S);
@@ -2092,7 +2137,8 @@ static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S)
}
// Check the input param:
- cItem * Input = (cItem *)tolua_tousertype(L, 2, nullptr);
+ cItem * Input = nullptr;
+ L.GetStackValue(2, Input);
if (Input == nullptr)
{
LOGWARNING("cRoot:GetFurnaceRecipe: the Input parameter is nil or missing.");
@@ -2109,9 +2155,9 @@ static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S)
}
// Push the output, number of ticks and input as the three return values:
- tolua_pushusertype(L, Recipe->Out, "const cItem");
- tolua_pushnumber (L, (lua_Number)(Recipe->CookTime));
- tolua_pushusertype(L, Recipe->In, "const cItem");
+ L.Push(Recipe->Out);
+ L.Push(Recipe->CookTime);
+ L.Push(Recipe->In);
return 3;
}
@@ -2868,6 +2914,10 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "DoWithPlayerByUUID", DoWith <cRoot, cPlayer, &cRoot::DoWithPlayerByUUID>);
tolua_function(tolua_S, "ForEachPlayer", ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
tolua_function(tolua_S, "ForEachWorld", ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
+ tolua_function(tolua_S, "GetBuildCommitID", tolua_cRoot_GetBuildCommitID);
+ tolua_function(tolua_S, "GetBuildDateTime", tolua_cRoot_GetBuildDateTime);
+ tolua_function(tolua_S, "GetBuildID", tolua_cRoot_GetBuildID);
+ tolua_function(tolua_S, "GetBuildSeriesName", tolua_cRoot_GetBuildSeriesName);
tolua_function(tolua_S, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe);
tolua_endmodule(tolua_S);
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index 7982afc31..938351207 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -1665,6 +1665,65 @@ size_t cBlockArea::CountNonAirBlocks(void) const
+size_t cBlockArea::CountSpecificBlocks(BLOCKTYPE a_BlockType) const
+{
+ // If blocktypes are not valid, log a warning and return zero occurences:
+ if (m_BlockTypes == nullptr)
+ {
+ LOGWARNING("%s: BlockTypes not available!", __FUNCTION__);
+ return 0;
+ }
+
+ // Count the blocks:
+ size_t num = GetBlockCount();
+ size_t res = 0;
+ for (size_t i = 0; i < num; i++)
+ {
+ if (m_BlockTypes[i] == a_BlockType)
+ {
+ res++;
+ }
+ }
+ return res;
+}
+
+
+
+
+
+size_t cBlockArea::CountSpecificBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const
+{
+ // If blocktypes are not valid, log a warning and return zero occurences:
+ if (m_BlockTypes == nullptr)
+ {
+ LOGWARNING("%s: BlockTypes not available!", __FUNCTION__);
+ return 0;
+ }
+
+ // If blockmetas are not valid, log a warning and count only blocktypes:
+ if (m_BlockMetas == nullptr)
+ {
+ LOGWARNING("%s: BlockMetas not available, comparing blocktypes only!", __FUNCTION__);
+ return CountSpecificBlocks(a_BlockType);
+ }
+
+ // Count the blocks:
+ size_t num = GetBlockCount();
+ size_t res = 0;
+ for (size_t i = 0; i < num; i++)
+ {
+ if ((m_BlockTypes[i] == a_BlockType) && (m_BlockMetas[i] == a_BlockMeta))
+ {
+ res++;
+ }
+ }
+ return res;
+}
+
+
+
+
+
void cBlockArea::GetNonAirCropRelCoords(int & a_MinRelX, int & a_MinRelY, int & a_MinRelZ, int & a_MaxRelX, int & a_MaxRelY, int & a_MaxRelZ, BLOCKTYPE a_IgnoreBlockType)
{
// Check if blocktypes are valid:
diff --git a/src/BlockArea.h b/src/BlockArea.h
index 4b672029b..a9963b4ef 100644
--- a/src/BlockArea.h
+++ b/src/BlockArea.h
@@ -308,6 +308,15 @@ public:
Returns 0 if blocktypes not available. Block metas are ignored (if present, air with any meta is still considered air). */
size_t CountNonAirBlocks(void) const;
+ /** Returns how many times the specified block is contained in the area.
+ The blocks' meta values are ignored, only the blocktype is compared. */
+ size_t CountSpecificBlocks(BLOCKTYPE a_BlockType) const;
+
+ /** Returns how many times the specified block is contained in the area.
+ Both the block's type and meta must match in order to be counted in.
+ If the block metas aren't present in the area, logs a warning and ignores the meta specification. */
+ size_t CountSpecificBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const;
+
// tolua_end
/** Returns the minimum and maximum coords in each direction for the first non-ignored block in each direction.
diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp
index 2621b560b..d1588160d 100644
--- a/src/BlockEntities/FurnaceEntity.cpp
+++ b/src/BlockEntities/FurnaceEntity.cpp
@@ -32,7 +32,8 @@ cFurnaceEntity::cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTY
m_NeedCookTime(0),
m_TimeCooked(0),
m_FuelBurnTime(0),
- m_TimeBurned(0)
+ m_TimeBurned(0),
+ m_IsLoading(false)
{
m_Contents.AddListener(*this);
}
@@ -178,20 +179,15 @@ void cFurnaceEntity::BurnNewFuel(void)
{
cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe();
int NewTime = FR->GetBurnTime(m_Contents.GetSlot(fsFuel));
- if (NewTime == 0)
+ if ((NewTime == 0) || !CanCookInputToOutput())
{
// The item in the fuel slot is not suitable
+ // or the input and output isn't available for cooking
SetBurnTimes(0, 0);
SetIsCooking(false);
return;
}
- // Is the input and output ready for cooking?
- if (!CanCookInputToOutput())
- {
- return;
- }
-
// Burn one new fuel:
SetBurnTimes(NewTime, 0);
SetIsCooking(true);
@@ -218,6 +214,11 @@ void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
return;
}
+ if (m_IsLoading)
+ {
+ return;
+ }
+
ASSERT(a_ItemGrid == &m_Contents);
switch (a_SlotNum)
{
@@ -238,7 +239,10 @@ void cFurnaceEntity::UpdateInput(void)
if (!m_Contents.GetSlot(fsInput).IsEqual(m_LastInput))
{
// The input is different from what we had before, reset the cooking time
- m_TimeCooked = 0;
+ if (!m_IsLoading)
+ {
+ m_TimeCooked = 0;
+ }
}
m_LastInput = m_Contents.GetSlot(fsInput);
@@ -253,13 +257,17 @@ void cFurnaceEntity::UpdateInput(void)
else
{
m_NeedCookTime = m_CurrentRecipe->CookTime;
- SetIsCooking(true);
// Start burning new fuel if there's no flame now:
if (GetFuelBurnTimeLeft() <= 0)
{
BurnNewFuel();
}
+ // Already burning, set cooking to ensure that cooking is occuring
+ else
+ {
+ SetIsCooking(true);
+ }
}
}
@@ -293,11 +301,19 @@ void cFurnaceEntity::UpdateOutput(void)
return;
}
- // No need to burn new fuel, the Tick() function will take care of that
-
// Can cook, start cooking if not already underway:
m_NeedCookTime = m_CurrentRecipe->CookTime;
- SetIsCooking(m_FuelBurnTime > 0);
+
+ // Check if fuel needs to start a burn
+ if (GetFuelBurnTimeLeft() <= 0)
+ {
+ BurnNewFuel();
+ }
+ // Already burning, set cooking to ensure that cooking is occuring
+ else
+ {
+ SetIsCooking(true);
+ }
}
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 8b3ba3e36..8734d763c 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -101,6 +101,11 @@ public:
m_TimeCooked = a_TimeCooked;
}
+ void SetLoading(bool a_IsLoading)
+ {
+ m_IsLoading = a_IsLoading;
+ }
+
protected:
/** Block meta of the block currently represented by this entity */
@@ -129,6 +134,9 @@ protected:
/** Amount of ticks that the current fuel has been burning */
int m_TimeBurned;
+
+ /** Is the block currently being loaded into the world? */
+ bool m_IsLoading;
/** Sends the specified progressbar value to all clients of the window */
void BroadcastProgress(short a_ProgressbarID, short a_Value);
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index d65d9722d..154cd610e 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -73,8 +73,13 @@ public:
return 0x0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x7)
@@ -93,6 +98,7 @@ public:
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h
index 50552c788..4d16d2552 100644
--- a/src/Blocks/BlockCocoaPod.h
+++ b/src/Blocks/BlockCocoaPod.h
@@ -89,6 +89,10 @@ public:
return 0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index f49f1adc7..d727f8f8e 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -64,6 +64,10 @@ public:
return 0x2;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 5792d280b..8d676b56f 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -67,6 +67,10 @@ public:
case BLOCK_FACE_YM: return 0x0;
case BLOCK_FACE_NONE: return 0x6;
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h
index 6f5c23902..b936a7e4a 100644
--- a/src/Blocks/BlockQuartz.h
+++ b/src/Blocks/BlockQuartz.h
@@ -36,6 +36,7 @@ public:
return true;
}
+
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_QuartzMeta)
{
switch (a_BlockFace)
@@ -64,5 +65,9 @@ public:
return a_QuartzMeta; // No idea, give a special meta (all sides the same)
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h
index 74b05e33c..e52fbaa2f 100644
--- a/src/Blocks/BlockSideways.h
+++ b/src/Blocks/BlockSideways.h
@@ -64,6 +64,10 @@ public:
return a_Meta | 0xC; // No idea, give a special meta
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 2841e3e08..a1d2dff6f 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -66,6 +66,7 @@ public:
return true;
}
+
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
@@ -82,8 +83,13 @@ public:
return 0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x3)
@@ -100,6 +106,7 @@ public:
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index c7a96d393..39892af5a 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -16,6 +16,7 @@ public:
{
}
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
@@ -29,6 +30,7 @@ public:
return true;
}
+
inline static NIBBLETYPE DirectionToMetadata(eBlockFace a_Direction)
{
switch (a_Direction)
@@ -45,8 +47,13 @@ public:
return 0x0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x03)
@@ -59,6 +66,7 @@ public:
}
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to zero
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5556ddc4d..c68795bb3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -83,6 +83,7 @@ SET (HDRS
BlockTracer.h
Broadcaster.h
BoundingBox.h
+ BuildInfo.h
BuildInfo.h.cmake
ByteBuffer.h
ChatColor.h
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index e3f63b091..d89f7ab77 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -2113,6 +2113,64 @@ void cClientHandle::SendChat(const cCompositeChat & a_Message)
+void cClientHandle::SendChatAboveActionBar(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData)
+{
+ cWorld * World = GetPlayer()->GetWorld();
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName());
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetDefaultWorld();
+ }
+ }
+
+ AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData);
+ m_Protocol->SendChatAboveActionBar(Message.append(a_Message));
+}
+
+
+
+
+
+void cClientHandle::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ m_Protocol->SendChatAboveActionBar(a_Message);
+}
+
+
+
+
+
+void cClientHandle::SendChatSystem(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData)
+{
+ cWorld * World = GetPlayer()->GetWorld();
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName());
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetDefaultWorld();
+ }
+ }
+
+ AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData);
+ m_Protocol->SendChatSystem(Message.append(a_Message));
+}
+
+
+
+
+
+void cClientHandle::SendChatSystem(const cCompositeChat & a_Message)
+{
+ m_Protocol->SendChatSystem(a_Message);
+}
+
+
+
+
+
void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
{
ASSERT(m_Player != nullptr);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index bcfa55825..13b5f87e4 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -150,6 +150,10 @@ public: // tolua_export
void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes);
void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
void SendChat (const cCompositeChat & a_Message);
+ void SendChatAboveActionBar (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
+ void SendChatAboveActionBar (const cCompositeChat & a_Message);
+ void SendChatSystem (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
+ void SendChatSystem (const cCompositeChat & a_Message);
void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer);
void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player);
void SendDestroyEntity (const cEntity & a_Entity);
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index a95ac5f84..c6a407d4b 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -168,7 +168,14 @@ void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid)
m_Items[ThisIdx].m_ItemCount -= NumWantedItems;
if (m_Items[ThisIdx].m_ItemCount == 0)
{
- m_Items[ThisIdx].Clear();
+ if ((m_Items[ThisIdx].m_ItemType == E_ITEM_MILK) || (m_Items[ThisIdx].m_ItemType == E_ITEM_WATER_BUCKET) || (m_Items[ThisIdx].m_ItemType == E_ITEM_LAVA_BUCKET))
+ {
+ m_Items[ThisIdx] = cItem(E_ITEM_BUCKET, m_Items[ThisIdx].m_ItemCount);
+ }
+ else
+ {
+ m_Items[ThisIdx].Clear();
+ }
}
} // for x, for y
}
diff --git a/src/Defines.h b/src/Defines.h
index bbc69f79c..b167f69e3 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -133,6 +133,17 @@ enum eGameMode
+enum eChatType
+{
+ ctChatBox = 0,
+ ctSystem = 1,
+ ctAboveActionBar = 2,
+} ;
+
+
+
+
+
enum eWeather
{
eWeather_Sunny = 0,
@@ -245,6 +256,10 @@ inline eBlockFace MirrorBlockFaceY(eBlockFace a_BlockFace)
return a_BlockFace;
};
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
@@ -267,6 +282,10 @@ inline eBlockFace RotateBlockFaceCCW(eBlockFace a_BlockFace)
return a_BlockFace;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
@@ -288,8 +307,16 @@ inline eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace)
return a_BlockFace;
};
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
+
+
+
+
inline eBlockFace ReverseBlockFace(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
@@ -302,9 +329,16 @@ inline eBlockFace ReverseBlockFace(eBlockFace a_BlockFace)
case BLOCK_FACE_ZM: return BLOCK_FACE_ZP;
case BLOCK_FACE_NONE: return a_BlockFace;
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
+
+
+
/** Returns the textual representation of the BlockFace constant. */
inline AString BlockFaceToString(eBlockFace a_BlockFace)
{
@@ -320,7 +354,7 @@ inline AString BlockFaceToString(eBlockFace a_BlockFace)
}
// clang optimisises this line away then warns that it has done so.
#if !defined(__clang__)
- return Printf("Unknown BLOCK_FACE: %d", a_BlockFace);
+ return Printf("Unknown BLOCK_FACE: %d", a_BlockFace);
#endif
}
diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h
index 4d70cd1a0..5d0aa17b3 100644
--- a/src/Entities/HangingEntity.h
+++ b/src/Entities/HangingEntity.h
@@ -46,6 +46,9 @@ public:
protected:
+ Byte m_Facing;
+
+
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override
{
@@ -53,6 +56,7 @@ protected:
UNUSED(a_Chunk);
}
+
/** Converts protocol hanging item facing to eBlockFace values */
inline static eBlockFace ProtocolFaceToBlockFace(Byte a_ProtocolFace)
{
@@ -77,6 +81,7 @@ protected:
return Dir;
}
+
/** Converts eBlockFace values to protocol hanging item faces */
inline static Byte BlockFaceToProtocolFace(eBlockFace a_BlockFace)
{
@@ -99,13 +104,17 @@ protected:
Dir = cHangingEntity::BlockFaceToProtocolFace(BLOCK_FACE_XP);
}
+ #if !defined(__clang__)
+ default:
+ {
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ }
+ #endif
}
return Dir;
}
-
- Byte m_Facing;
-
}; // tolua_export
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index a84fdd0c7..799990bf2 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -235,14 +235,19 @@ public:
// tolua_begin
- void SendMessage (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); }
- void SendMessageInfo (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); }
- void SendMessageFailure (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
- void SendMessageSuccess (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); }
- void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); }
- void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
- void SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); }
- void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); }
+ void SendMessage (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); }
+ void SendMessageInfo (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); }
+ void SendMessageFailure (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
+ void SendMessageSuccess (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); }
+ void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); }
+ void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
+ void SendMessagePrivateMsg (const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); }
+ void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); }
+
+ void SendSystemMessage (const AString & a_Message) { m_ClientHandle->SendChatSystem(a_Message, mtCustom); }
+ void SendAboveActionBarMessage(const AString & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message, mtCustom); }
+ void SendSystemMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChatSystem(a_Message); }
+ void SendAboveActionBarMessage(const cCompositeChat & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message); }
const AString & GetName(void) const { return m_PlayerName; }
void SetName(const AString & a_Name) { m_PlayerName = a_Name; }
diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp
index 88dade240..4ba896ef6 100644
--- a/src/Generating/MineShafts.cpp
+++ b/src/Generating/MineShafts.cpp
@@ -787,6 +787,13 @@ void cMineShaftCorridor::PlaceChest(cChunkDesc & a_ChunkDesc)
Meta = E_META_CHEST_FACING_XP;
break;
}
+ #if !defined(__clang__)
+ default:
+ {
+ ASSERT(!"Unknown direction");
+ return;
+ }
+ #endif
} // switch (Dir)
if (
diff --git a/src/Globals.h b/src/Globals.h
index 8ff7b6894..b787a94da 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -220,6 +220,7 @@ template class SizeChecker<UInt8, 1>;
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
+ #include <unistd.h>
#endif
#if defined(ANDROID_NDK)
@@ -264,7 +265,6 @@ template class SizeChecker<UInt8, 1>;
// Common headers (part 1, without macros):
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
- #include "OSSupport/Semaphore.h"
#include "OSSupport/Event.h"
#include "OSSupport/File.h"
#include "Logger.h"
diff --git a/src/LineBlockTracer.cpp b/src/LineBlockTracer.cpp
index 315e8d082..587fa0e7c 100644
--- a/src/LineBlockTracer.cpp
+++ b/src/LineBlockTracer.cpp
@@ -154,38 +154,45 @@ bool cLineBlockTracer::MoveToNextBlock(void)
{
// Find out which of the current block's walls gets hit by the path:
static const double EPS = 0.00001;
- double Coeff = 1;
- enum eDirection
+ enum
{
dirNONE,
dirX,
dirY,
dirZ,
} Direction = dirNONE;
+
+ // Calculate the next YZ wall hit:
+ double Coeff = 1;
if (std::abs(m_DiffX) > EPS)
{
double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX;
- Coeff = (DestX - m_StartX) / m_DiffX;
- if (Coeff <= 1)
+ double CoeffX = (DestX - m_StartX) / m_DiffX;
+ if (CoeffX <= 1) // We need to include equality for the last block in the trace
{
+ Coeff = CoeffX;
Direction = dirX;
}
}
+
+ // If the next XZ wall hit is closer, use it instead:
if (std::abs(m_DiffY) > EPS)
{
double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY;
double CoeffY = (DestY - m_StartY) / m_DiffY;
- if (CoeffY < Coeff)
+ if (CoeffY <= Coeff) // We need to include equality for the last block in the trace
{
Coeff = CoeffY;
Direction = dirY;
}
}
+
+ // If the next XY wall hit is closer, use it instead:
if (std::abs(m_DiffZ) > EPS)
{
double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ;
double CoeffZ = (DestZ - m_StartZ) / m_DiffZ;
- if (CoeffZ < Coeff)
+ if (CoeffZ <= Coeff) // We need to include equality for the last block in the trace
{
Direction = dirZ;
}
diff --git a/src/LoggerListeners.cpp b/src/LoggerListeners.cpp
index 31b12af1e..132751e8e 100644
--- a/src/LoggerListeners.cpp
+++ b/src/LoggerListeners.cpp
@@ -238,8 +238,26 @@ public:
-cLogger::cListener * MakeConsoleListener(void)
+// Listener for when stdout is closed, i.e. When running as a daemon.
+class cNullConsoleListener
+ : public cLogger::cListener
+{
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
+ {
+ }
+};
+
+
+
+
+
+cLogger::cListener * MakeConsoleListener(bool a_IsService)
{
+ if (a_IsService)
+ {
+ return new cNullConsoleListener;
+ }
+
#ifdef _WIN32
// See whether we are writing to a console the default console attrib:
bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
diff --git a/src/LoggerListeners.h b/src/LoggerListeners.h
index c419aa75a..a7f9a35a5 100644
--- a/src/LoggerListeners.h
+++ b/src/LoggerListeners.h
@@ -25,7 +25,7 @@ private:
-cLogger::cListener * MakeConsoleListener();
+cLogger::cListener * MakeConsoleListener(bool a_IsService);
diff --git a/src/MobCensus.cpp b/src/MobCensus.cpp
index ca960a2bc..79b5176d2 100644
--- a/src/MobCensus.cpp
+++ b/src/MobCensus.cpp
@@ -48,6 +48,10 @@ int cMobCensus::GetCapMultiplier(cMonster::eFamily a_MobFamily)
return -1;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown mob family");
+ return -1;
+ #endif
}
diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt
index d1db0373d..df47394ae 100644
--- a/src/OSSupport/CMakeLists.txt
+++ b/src/OSSupport/CMakeLists.txt
@@ -15,7 +15,6 @@ SET (SRCS
IsThread.cpp
NetworkInterfaceEnum.cpp
NetworkSingleton.cpp
- Semaphore.cpp
ServerHandleImpl.cpp
StackTrace.cpp
TCPLinkImpl.cpp
@@ -34,7 +33,6 @@ SET (HDRS
Network.h
NetworkSingleton.h
Queue.h
- Semaphore.h
ServerHandleImpl.h
StackTrace.h
TCPLinkImpl.h
diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp
index 760e536a1..38144ead3 100644
--- a/src/OSSupport/Event.cpp
+++ b/src/OSSupport/Event.cpp
@@ -1,8 +1,8 @@
// Event.cpp
-// Implements the cEvent object representing an OS-specific synchronization primitive that can be waited-for
-// Implemented as an Event on Win and as a 1-semaphore on *nix
+// Interfaces to the cEvent object representing a synchronization primitive that can be waited-for
+// Implemented using C++11 condition variable and mutex
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
diff --git a/src/OSSupport/Semaphore.cpp b/src/OSSupport/Semaphore.cpp
deleted file mode 100644
index 6a2d57901..000000000
--- a/src/OSSupport/Semaphore.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-
-
-
-
-cSemaphore::cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount /* = 0 */)
-#ifndef _WIN32
- : m_bNamed( false)
-#endif
-{
-#ifndef _WIN32
- (void)a_MaxCount;
- m_Handle = new sem_t;
- if (sem_init( (sem_t*)m_Handle, 0, 0))
- {
- LOG("WARNING cSemaphore: Could not create unnamed semaphore, fallback to named.");
- delete (sem_t*)m_Handle; // named semaphores return their own address
- m_bNamed = true;
-
- AString Name;
- Printf(Name, "cSemaphore%p", this);
- m_Handle = sem_open(Name.c_str(), O_CREAT, 777, a_InitialCount);
- if (m_Handle == SEM_FAILED)
- {
- LOG("ERROR: Could not create Semaphore. (%i)", errno);
- }
- else
- {
- if (sem_unlink(Name.c_str()) != 0)
- {
- LOG("ERROR: Could not unlink cSemaphore. (%i)", errno);
- }
- }
- }
-#else
- m_Handle = CreateSemaphore(
- nullptr, // security attribute
- a_InitialCount, // initial count
- a_MaxCount, // maximum count
- 0 // name (optional)
- );
-#endif
-}
-
-
-
-
-
-cSemaphore::~cSemaphore()
-{
-#ifdef _WIN32
- CloseHandle( m_Handle);
-#else
- if (m_bNamed)
- {
- if (sem_close( (sem_t*)m_Handle) != 0)
- {
- LOG("ERROR: Could not close cSemaphore. (%i)", errno);
- }
- }
- else
- {
- sem_destroy( (sem_t*)m_Handle);
- delete (sem_t*)m_Handle;
- }
- m_Handle = 0;
-
-#endif
-}
-
-
-
-
-
-void cSemaphore::Wait()
-{
-#ifndef _WIN32
- if (sem_wait( (sem_t*)m_Handle) != 0)
- {
- LOG("ERROR: Could not wait for cSemaphore. (%i)", errno);
- }
-#else
- WaitForSingleObject( m_Handle, INFINITE);
-#endif
-}
-
-
-
-
-
-void cSemaphore::Signal()
-{
-#ifndef _WIN32
- if (sem_post( (sem_t*)m_Handle) != 0)
- {
- LOG("ERROR: Could not signal cSemaphore. (%i)", errno);
- }
-#else
- ReleaseSemaphore( m_Handle, 1, nullptr);
-#endif
-}
-
-
-
-
diff --git a/src/OSSupport/Semaphore.h b/src/OSSupport/Semaphore.h
deleted file mode 100644
index 57fa4bdb2..000000000
--- a/src/OSSupport/Semaphore.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-class cSemaphore
-{
-public:
- cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount = 0);
- ~cSemaphore();
-
- void Wait();
- void Signal();
-private:
- void * m_Handle; // HANDLE pointer
-
-#ifndef _WIN32
- bool m_bNamed;
-#endif
-};
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 7be72014a..1a19249bf 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -70,6 +70,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0;
virtual void SendChat (const AString & a_Message) = 0;
virtual void SendChat (const cCompositeChat & a_Message) = 0;
+ virtual void SendChatAboveActionBar (const AString & a_Message) = 0;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) = 0;
+ virtual void SendChatSystem (const AString & a_Message) = 0;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) = 0;
+ virtual void SendChatType (const AString & a_Message, eChatType type) = 0;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) = 0;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0;
virtual void SendDestroyEntity (const cEntity & a_Entity) = 0;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 6aa36e2a5..3d96071b5 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -247,8 +247,67 @@ void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV
void cProtocol172::SendChat(const AString & a_Message)
{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol172::SendChat(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol172::SendChatSystem(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol172::SendChatSystem(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol172::SendChatAboveActionBar(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol172::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol172::SendChatType(const AString & a_Message, eChatType type)
+{
ASSERT(m_State == 3); // In game mode?
-
+
+ if (type != ctChatBox) // 1.7.2 doesn't support anything else
+ {
+ return;
+ }
+
cPacketizer Pkt(*this, 0x02); // Chat Message packet
Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
}
@@ -257,10 +316,15 @@ void cProtocol172::SendChat(const AString & a_Message)
-void cProtocol172::SendChat(const cCompositeChat & a_Message)
+void cProtocol172::SendChatType(const cCompositeChat & a_Message, eChatType type)
{
ASSERT(m_State == 3); // In game mode?
+ if (type != ctChatBox) // 1.7.2 doesn't support anything else
+ {
+ return;
+ }
+
cWorld * World = m_Client->GetPlayer()->GetWorld();
bool ShouldUseChatPrefixes = (World == nullptr) ? false : World->ShouldUseChatPrefixes();
@@ -1041,8 +1105,8 @@ void cProtocol172::SendExperience (void)
cPacketizer Pkt(*this, 0x1f); // Experience Packet
cPlayer * Player = m_Client->GetPlayer();
Pkt.WriteBEFloat(Player->GetXpPercentage());
- Pkt.WriteBEInt16(static_cast<Int16>(std::max<int>(Player->GetXpLevel(), std::numeric_limits<Int16>::max())));
- Pkt.WriteBEInt16(static_cast<Int16>(std::max<int>(Player->GetCurrentXp(), std::numeric_limits<Int16>::max())));
+ Pkt.WriteBEInt16(static_cast<Int16>(std::min<int>(Player->GetXpLevel(), std::numeric_limits<Int16>::max())));
+ Pkt.WriteBEInt16(static_cast<Int16>(std::min<int>(Player->GetCurrentXp(), std::numeric_limits<Int16>::max())));
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index ead2935b0..b07fa9ed9 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -68,6 +68,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
+ virtual void SendChatAboveActionBar (const AString & a_Message) override;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override;
+ virtual void SendChatSystem (const AString & a_Message) override;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) override;
+ virtual void SendChatType (const AString & a_Message, eChatType type) override;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index d06022ce0..d9449283b 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -234,18 +234,72 @@ void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV
void cProtocol180::SendChat(const AString & a_Message)
{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol180::SendChat(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol180::SendChatSystem(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol180::SendChatSystem(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol180::SendChatAboveActionBar(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol180::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol180::SendChatType(const AString & a_Message, eChatType type)
+{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x02); // Chat Message packet
Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
- Pkt.WriteBEInt8(0);
+ Pkt.WriteBEInt8(type);
}
-void cProtocol180::SendChat(const cCompositeChat & a_Message)
+void cProtocol180::SendChatType(const cCompositeChat & a_Message, eChatType type)
{
ASSERT(m_State == 3); // In game mode?
@@ -255,7 +309,7 @@ void cProtocol180::SendChat(const cCompositeChat & a_Message)
// Send the message to the client:
cPacketizer Pkt(*this, 0x02);
Pkt.WriteString(a_Message.CreateJsonString(ShouldUseChatPrefixes));
- Pkt.WriteBEInt8(0);
+ Pkt.WriteBEInt8(type);
}
diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h
index 6143e8b4e..36ed251fe 100644
--- a/src/Protocol/Protocol18x.h
+++ b/src/Protocol/Protocol18x.h
@@ -67,6 +67,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
+ virtual void SendChatAboveActionBar (const AString & a_Message) override;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override;
+ virtual void SendChatSystem (const AString & a_Message) override;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) override;
+ virtual void SendChatType (const AString & a_Message, eChatType type) override;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 477f2d71e..c89c745a4 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -158,6 +158,66 @@ void cProtocolRecognizer::SendChat(const cCompositeChat & a_Message)
+void cProtocolRecognizer::SendChatAboveActionBar(const AString & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatAboveActionBar(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatAboveActionBar(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatSystem(const AString & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatSystem(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatSystem(const cCompositeChat & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatSystem(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatType(const AString & a_Message, eChatType type)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatType(a_Message, type);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatType(const cCompositeChat & a_Message, eChatType type)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatType(a_Message, type);
+}
+
+
+
+
+
void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
{
ASSERT(m_Protocol != nullptr);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 956b5dcc0..29eddcbc9 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -55,6 +55,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
+ virtual void SendChatAboveActionBar (const AString & a_Message) override;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override;
+ virtual void SendChatSystem (const AString & a_Message) override;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) override;
+ virtual void SendChatType (const AString & a_Message, eChatType type) override;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
diff --git a/src/Root.cpp b/src/Root.cpp
index 54e65b6da..8d344ee65 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -106,7 +106,7 @@ void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
#endif
- cLogger::cListener * consoleLogListener = MakeConsoleListener();
+ cLogger::cListener * consoleLogListener = MakeConsoleListener(m_RunAsService);
cLogger::cListener * fileLogListener = new cFileListener();
cLogger::GetInstance().AttachListener(consoleLogListener);
cLogger::GetInstance().AttachListener(fileLogListener);
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index f77197914..860eb3a4a 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -257,6 +257,9 @@ bool cParsedNBT::ReadTag(void)
return true;
}
+ #if !defined(__clang__)
+ default:
+ #endif
case TAG_Min:
{
ASSERT(!"Unhandled NBT tag type");
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 392b9bf83..8ca49c2c0 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1052,7 +1052,8 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
}
std::unique_ptr<cFurnaceEntity> Furnace(new cFurnaceEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, m_World));
-
+ Furnace->SetLoading(true);
+
// Load slots:
for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child))
{
@@ -1085,9 +1086,9 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
// Anvil doesn't store the time that an item takes to cook. We simply use the default - 10 seconds (200 ticks)
Furnace->SetCookTimes(200, ct);
}
-
// Restart cooking:
Furnace->ContinueCooking();
+ Furnace->SetLoading(false);
return Furnace.release();
}
diff --git a/src/main.cpp b/src/main.cpp
index 5cd057278..2103f3356 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -39,7 +39,7 @@ bool cRoot::m_RunAsService = false;
#if defined(_WIN32)
- SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
+ SERVICE_STATUS_HANDLE g_StatusHandle = nullptr;
HANDLE g_ServiceThread = INVALID_HANDLE_VALUE;
#define SERVICE_NAME "MCServerService"
#endif
@@ -145,7 +145,7 @@ Its purpose is to create the crashdump using the dbghlp DLLs
*/
LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo)
{
- char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack)];
+ char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack) - 1];
char * oldStack;
// Use the substitute stack:
@@ -249,7 +249,8 @@ void universalMain(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
-#if defined(_WIN32)
+
+#if defined(_WIN32) // Windows service support.
////////////////////////////////////////////////////////////////////////////////
// serviceWorkerThread: Keep the service alive
@@ -266,6 +267,7 @@ DWORD WINAPI serviceWorkerThread(LPVOID lpParam)
+
////////////////////////////////////////////////////////////////////////////////
// serviceSetState: Set the internal status of the service
@@ -319,14 +321,10 @@ void WINAPI serviceCtrlHandler(DWORD CtrlCode)
void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
{
- #if defined(_DEBUG) && defined(DEBUG_SERVICE_STARTUP)
- Sleep(10000);
- #endif
-
char applicationFilename[MAX_PATH];
char applicationDirectory[MAX_PATH];
- GetModuleFileName(NULL, applicationFilename, sizeof(applicationFilename)); // This binary's file path.
+ GetModuleFileName(nullptr, applicationFilename, sizeof(applicationFilename)); // This binary's file path.
// Strip off the filename, keep only the path:
strncpy_s(applicationDirectory, sizeof(applicationDirectory), applicationFilename, (strrchr(applicationFilename, '\\') - applicationFilename));
@@ -337,8 +335,7 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
SetCurrentDirectory(applicationDirectory);
g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler);
-
- if (g_StatusHandle == NULL)
+ if (g_StatusHandle == nullptr)
{
OutputDebugStringA("RegisterServiceCtrlHandler() failed\n");
serviceSetState(0, SERVICE_STOPPED, GetLastError());
@@ -347,8 +344,9 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
serviceSetState(SERVICE_ACCEPT_STOP, SERVICE_RUNNING, 0);
- g_ServiceThread = CreateThread(NULL, 0, serviceWorkerThread, NULL, 0, NULL);
- if (g_ServiceThread == NULL)
+ DWORD ThreadID;
+ g_ServiceThread = CreateThread(nullptr, 0, serviceWorkerThread, nullptr, 0, &ThreadID);
+ if (g_ServiceThread == nullptr)
{
OutputDebugStringA("CreateThread() failed\n");
serviceSetState(0, SERVICE_STOPPED, GetLastError());
@@ -360,7 +358,9 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
serviceSetState(0, SERVICE_STOPPED, 0);
}
-#endif
+#endif // Windows service support.
+
+
@@ -368,42 +368,33 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
{
try
{
+ // Parse the comand line args:
TCLAP::CmdLine cmd("MCServer");
-
- TCLAP::ValueArg<int> slotsArg("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
-
- TCLAP::MultiArg<int> portsArg("p", "port", "The port number the server should listen to", false, "port", cmd);
-
- TCLAP::SwitchArg commLogArg("", "log-comm", "Log server client communications to file", cmd);
-
- TCLAP::SwitchArg commLogInArg("", "log-comm-in", "Log inbound server client communications to file", cmd);
-
- TCLAP::SwitchArg commLogOutArg("", "log-comm-out", "Log outbound server client communications to file", cmd);
-
- TCLAP::SwitchArg noBufArg("", "no-output-buffering", "Disable output buffering", cmd);
-
+ TCLAP::ValueArg<int> slotsArg ("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
+ TCLAP::MultiArg<int> portsArg ("p", "port", "The port number the server should listen to", false, "port", cmd);
+ TCLAP::SwitchArg commLogArg ("", "log-comm", "Log server client communications to file", cmd);
+ TCLAP::SwitchArg commLogInArg ("", "log-comm-in", "Log inbound server client communications to file", cmd);
+ TCLAP::SwitchArg commLogOutArg ("", "log-comm-out", "Log outbound server client communications to file", cmd);
+ TCLAP::SwitchArg crashDumpFull ("", "crash-dump-full", "Crashdumps created by the server will contain full server memory", cmd);
+ TCLAP::SwitchArg crashDumpGlobals("", "crash-dump-globals", "Crashdumps created by the server will contain the global variables' values", cmd);
+ TCLAP::SwitchArg noBufArg ("", "no-output-buffering", "Disable output buffering", cmd);
+ TCLAP::SwitchArg runAsServiceArg ("d", "service", "Run as a service on Windows, or daemon on UNIX like systems", cmd);
cmd.parse(argc, argv);
+ // Copy the parsed args' values into a settings repository:
auto repo = cpp14::make_unique<cMemorySettingsRepository>();
-
if (slotsArg.isSet())
{
-
int slots = slotsArg.getValue();
-
repo->AddValue("Server", "MaxPlayers", static_cast<Int64>(slots));
-
}
-
if (portsArg.isSet())
{
- std::vector<int> ports = portsArg.getValue();
- for (auto port : ports)
+ for (auto port: portsArg.getValue())
{
repo->AddValue("Server", "Port", static_cast<Int64>(port));
}
}
-
if (commLogArg.getValue())
{
g_ShouldLogCommIn = true;
@@ -414,120 +405,133 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
g_ShouldLogCommIn = commLogInArg.getValue();
g_ShouldLogCommOut = commLogOutArg.getValue();
}
-
if (noBufArg.getValue())
{
setvbuf(stdout, nullptr, _IONBF, 0);
}
-
repo->SetReadOnly();
+ // Set the service flag directly to cRoot:
+ if (runAsServiceArg.getValue())
+ {
+ cRoot::m_RunAsService = true;
+ }
+
+ // Apply the CrashDump flags for platforms that support them:
+ #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC
+ if (crashDumpGlobals.getValue())
+ {
+ g_DumpFlags = static_cast<MINIDUMP_TYPE>(g_DumpFlags | MiniDumpWithDataSegs);
+ }
+ if (crashDumpFull.getValue())
+ {
+ g_DumpFlags = static_cast<MINIDUMP_TYPE>(g_DumpFlags | MiniDumpWithFullMemory);
+ }
+ #endif // 32-bit Windows app compiled in MSVC
+
return repo;
}
- catch (TCLAP::ArgException &e)
+ catch (const TCLAP::ArgException & exc)
{
- printf("error reading command line %s for arg %s", e.error().c_str(), e.argId().c_str());
+ printf("Error reading command line %s for arg %s", exc.error().c_str(), exc.argId().c_str());
return cpp14::make_unique<cMemorySettingsRepository>();
}
}
+
+
+
////////////////////////////////////////////////////////////////////////////////
// main:
int main(int argc, char **argv)
{
-
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
- InitLeakFinder();
+ InitLeakFinder();
#endif
// Magic code to produce dump-files on Windows if the server crashes:
- #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER)
- HINSTANCE hDbgHelp = LoadLibrary("DBGHELP.DLL");
- g_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
- if (g_WriteMiniDump != nullptr)
- {
- _snprintf_s(g_DumpFileName, ARRAYCOUNT(g_DumpFileName), _TRUNCATE, "crash_mcs_%x.dmp", GetCurrentProcessId());
- SetUnhandledExceptionFilter(LastChanceExceptionFilter);
-
- // Parse arguments for minidump flags:
- for (int i = 0; i < argc; i++)
+ #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC
+ HINSTANCE hDbgHelp = LoadLibrary("DBGHELP.DLL");
+ g_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
+ if (g_WriteMiniDump != nullptr)
{
- if (_stricmp(argv[i], "/cdg") == 0)
- {
- // Add globals to the dump
- g_DumpFlags = (MINIDUMP_TYPE)(g_DumpFlags | MiniDumpWithDataSegs);
- }
- else if (_stricmp(argv[i], "/cdf") == 0)
- {
- // Add full memory to the dump (HUUUGE file)
- g_DumpFlags = (MINIDUMP_TYPE)(g_DumpFlags | MiniDumpWithFullMemory);
- }
- } // for i - argv[]
- }
- #endif // _WIN32 && !_WIN64
+ _snprintf_s(g_DumpFileName, ARRAYCOUNT(g_DumpFileName), _TRUNCATE, "crash_mcs_%x.dmp", GetCurrentProcessId());
+ SetUnhandledExceptionFilter(LastChanceExceptionFilter);
+ }
+ #endif // 32-bit Windows app compiled in MSVC
// End of dump-file magic
+
#if defined(_DEBUG) && defined(_MSC_VER)
- _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
- // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
- // Only useful when the leak is in the same sequence all the time
- // _CrtSetBreakAlloc(85950);
+ // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
+ // Only useful when the leak is in the same sequence all the time
+ // _CrtSetBreakAlloc(85950);
#endif // _DEBUG && _MSC_VER
#ifndef _DEBUG
- std::signal(SIGSEGV, NonCtrlHandler);
- std::signal(SIGTERM, NonCtrlHandler);
- std::signal(SIGINT, NonCtrlHandler);
- std::signal(SIGABRT, NonCtrlHandler);
- #ifdef SIGABRT_COMPAT
- std::signal(SIGABRT_COMPAT, NonCtrlHandler);
- #endif // SIGABRT_COMPAT
+ std::signal(SIGSEGV, NonCtrlHandler);
+ std::signal(SIGTERM, NonCtrlHandler);
+ std::signal(SIGINT, NonCtrlHandler);
+ std::signal(SIGABRT, NonCtrlHandler);
+ #ifdef SIGABRT_COMPAT
+ std::signal(SIGABRT_COMPAT, NonCtrlHandler);
+ #endif // SIGABRT_COMPAT
#endif
- // DEBUG: test the dumpfile creation:
- // *((int *)0) = 0;
-
auto argsRepo = parseArguments(argc, argv);
-
- // Check if comm logging is to be enabled:
- for (int i = 0; i < argc; i++)
- {
- AString Arg(argv[i]);
- if (NoCaseCompare(Arg, "/service") == 0)
- {
- cRoot::m_RunAsService = true;
- }
- } // for i - argv[]
- #if defined(_WIN32)
// Attempt to run as a service
if (cRoot::m_RunAsService)
{
- SERVICE_TABLE_ENTRY ServiceTable[] =
- {
- { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain },
- { NULL, NULL }
- };
+ #if defined(_WIN32) // Windows service.
+ SERVICE_TABLE_ENTRY ServiceTable[] =
+ {
+ { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain },
+ { nullptr, nullptr }
+ };
- if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
- {
- LOGERROR("Attempted, but failed, service startup.");
- return GetLastError();
- }
+ if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
+ {
+ LOGERROR("Attempted, but failed, service startup.");
+ return GetLastError();
+ }
+ #else // UNIX daemon.
+ pid_t pid = fork();
+
+ // fork() returns a negative value on error.
+ if (pid < 0)
+ {
+ LOGERROR("Could not fork process.");
+ return EXIT_FAILURE;
+ }
+
+ // Check if we are the parent or child process. Parent stops here.
+ if (pid > 0)
+ {
+ return EXIT_SUCCESS;
+ }
+
+ // Child process now goes quiet, running in the background.
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ universalMain(std::move(argsRepo));
+ #endif
}
else
- #endif
{
// Not running as a service, do normal startup
universalMain(std::move(argsRepo));
}
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
- DeinitLeakFinder();
+ DeinitLeakFinder();
#endif
return EXIT_SUCCESS;