summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules12
-rw-r--r--Android/res/values-pl/strings.xml13
-rw-r--r--COMPILING.md5
-rw-r--r--CONTRIBUTORS1
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua1
m---------MCServer/Plugins/ChatLog0
-rw-r--r--MCServer/Plugins/ChatLog/plugin.lua31
m---------MCServer/Plugins/ChunkWorx0
-rw-r--r--MCServer/Plugins/ChunkWorx/ChunkWorx.deproj9
-rw-r--r--MCServer/Plugins/ChunkWorx/chunkworx_main.lua128
-rw-r--r--MCServer/Plugins/ChunkWorx/chunkworx_web.lua274
m---------MCServer/Plugins/Core0
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua19
m---------MCServer/Plugins/Handy0
-rw-r--r--MCServer/Plugins/Handy/handy.lua28
-rw-r--r--MCServer/Plugins/Handy/handy_functions.lua216
-rw-r--r--MCServer/Plugins/InfoDump.lua427
m---------MCServer/Plugins/MagicCarpet0
-rw-r--r--MCServer/Plugins/MagicCarpet/objects.lua97
-rw-r--r--MCServer/Plugins/MagicCarpet/plugin.lua81
-rw-r--r--MCServer/webadmin/(original).html8
-rw-r--r--MCServer/webadmin/files/style.css497
-rw-r--r--MCServer/webadmin/template.html261
-rw-r--r--MCServer/webadmin/template.lua63
-rw-r--r--MCServer/webadmin/template_orig.lua137
-rw-r--r--README.md22
-rw-r--r--SetFlags.cmake30
-rw-r--r--Tools/QtBiomeVisualiser/BiomeView.cpp97
-rw-r--r--Tools/QtBiomeVisualiser/BiomeView.h26
-rw-r--r--Tools/QtBiomeVisualiser/ChunkSource.cpp143
-rw-r--r--Tools/QtBiomeVisualiser/MainWindow.cpp132
-rw-r--r--Tools/QtBiomeVisualiser/MainWindow.h31
-rw-r--r--Tools/QtBiomeVisualiser/QtChunk.cpp159
-rw-r--r--Tools/QtBiomeVisualiser/QtChunk.h15
-rwxr-xr-xeasyinstall.sh17
-rw-r--r--src/Bindings/AllToLua.pkg1
-rw-r--r--src/Bindings/LuaChunkStay.cpp8
-rw-r--r--src/Bindings/LuaState.cpp14
-rw-r--r--src/Bindings/LuaState.h80
-rw-r--r--src/Bindings/ManualBindings.cpp10
-rw-r--r--src/Bindings/Plugin.h34
-rw-r--r--src/Bindings/PluginLua.cpp82
-rw-r--r--src/Bindings/PluginLua.h34
-rw-r--r--src/Bindings/PluginManager.cpp58
-rw-r--r--src/Bindings/PluginManager.h38
-rw-r--r--src/BlockID.cpp51
-rw-r--r--src/BlockID.h206
-rw-r--r--src/BlockInServerPluginInterface.h20
-rw-r--r--src/BlockInfo.cpp1
-rw-r--r--src/Blocks/BlockDirt.h2
-rw-r--r--src/Blocks/BlockHandler.cpp5
-rw-r--r--src/Blocks/BlockHayBale.h22
-rw-r--r--src/Blocks/BlockPluginInterface.h11
-rw-r--r--src/Blocks/BlockStone.h2
-rw-r--r--src/Blocks/BlockTorch.h124
-rw-r--r--src/Blocks/BlockVine.h12
-rw-r--r--src/Blocks/CMakeLists.txt1
-rw-r--r--src/CheckBasicStyle.lua1
-rw-r--r--src/Chunk.cpp10
-rw-r--r--src/Chunk.h2
-rw-r--r--src/ChunkMap.cpp14
-rw-r--r--src/ChunkMap.h2
-rw-r--r--src/ClientHandle.cpp58
-rw-r--r--src/ClientHandle.h10
-rw-r--r--src/CraftingRecipes.cpp8
-rw-r--r--src/CraftingRecipes.h2
-rw-r--r--src/Enchantments.cpp28
-rw-r--r--src/Enchantments.h3
-rw-r--r--src/Entities/ArrowEntity.cpp14
-rw-r--r--src/Entities/ArrowEntity.h2
-rw-r--r--src/Entities/Entity.h6
-rw-r--r--src/Entities/Minecart.h2
-rw-r--r--src/Entities/Pickup.cpp16
-rw-r--r--src/Entities/Pickup.h2
-rw-r--r--src/Entities/Player.cpp2
-rw-r--r--src/Entities/ProjectileEntity.cpp6
-rw-r--r--src/Entities/ProjectileEntity.h2
-rw-r--r--src/Generating/BioGen.cpp4
-rw-r--r--src/Generating/ComposableGenerator.cpp2
-rw-r--r--src/Generating/DistortedHeightmap.cpp9
-rw-r--r--src/Generating/DungeonRoomsFinisher.cpp30
-rw-r--r--src/Generating/Trees.cpp80
-rw-r--r--src/Globals.h36
-rw-r--r--src/ItemGrid.cpp29
-rw-r--r--src/Mobs/CMakeLists.txt1
-rw-r--r--src/Mobs/Monster.cpp10
-rw-r--r--src/Mobs/Monster.h3
-rw-r--r--src/Mobs/MonsterTypes.h13
-rw-r--r--src/OSSupport/CMakeLists.txt2
-rw-r--r--src/OSSupport/Event.cpp47
-rw-r--r--src/OSSupport/Event.h4
-rw-r--r--src/Protocol/MojangAPI.cpp135
-rw-r--r--src/Protocol/MojangAPI.h23
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp1
-rw-r--r--src/Protocol/ProtocolRecognizer.h2
-rw-r--r--src/Root.cpp5
-rw-r--r--src/Server.cpp6
-rw-r--r--src/Server.h2
-rw-r--r--src/Simulator/FireSimulator.cpp4
-rw-r--r--src/UI/SlotArea.cpp4
-rw-r--r--src/Vector3.h34
-rw-r--r--src/World.cpp73
-rw-r--r--src/World.h25
104 files changed, 2372 insertions, 2200 deletions
diff --git a/.gitignore b/.gitignore
index 6afc12116..b85b172cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,8 @@ AllFiles.lst
*.*~
*~
*.orig
+## CLion
+.idea
## Eclipse
.cproject
.project
diff --git a/.gitmodules b/.gitmodules
index 33649023e..d2ce2c855 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,6 +7,18 @@
[submodule "MCServer/Plugins/TransAPI"]
path = MCServer/Plugins/TransAPI
url = https://github.com/bearbin/transapi.git
+[submodule "MCServer/Plugins/ChunkWorx"]
+ path = MCServer/Plugins/ChunkWorx
+ url = https://github.com/mc-server/ChunkWorx.git
+[submodule "MCServer/Plugins/ChatLog"]
+ path = MCServer/Plugins/ChatLog
+ url = https://github.com/mc-server/ChatLog.git
+[submodule "MCServer/Plugins/Handy"]
+ path = MCServer/Plugins/Handy
+ url = https://github.com/mc-server/Handy.git
+[submodule "MCServer/Plugins/MagicCarpet"]
+ path = MCServer/Plugins/MagicCarpet
+ url = https://github.com/mc-server/MagicCarpet.git
[submodule "lib/polarssl"]
path = lib/polarssl
url = https://github.com/mc-server/polarssl.git
diff --git a/Android/res/values-pl/strings.xml b/Android/res/values-pl/strings.xml
new file mode 100644
index 000000000..74c8044d8
--- /dev/null
+++ b/Android/res/values-pl/strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello">Hello World, MCServerActivity!</string>
+ <string name="app_name">MCServer</string>
+ <string name="start">Start</string>
+ <string name="stop">Stop</string>
+ <string name="mcserver_is_running">MCServer jest włączony</string>
+ <string name="mcserver_is_not_running">MCServer jest wyłączony</string>
+ <string name="your_ip">Twoje IP …</string>
+ <string name="configure">Ustawienia</string>
+
+</resources>
diff --git a/COMPILING.md b/COMPILING.md
index ea6b580d5..731d64653 100644
--- a/COMPILING.md
+++ b/COMPILING.md
@@ -4,9 +4,8 @@ To compile MCServer from source, you need CMake and make, as well as a C compile
## 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
+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 2013 Express is being actively used for development.
+You can find download links for 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).
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 2d911a11d..e65239218 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -30,5 +30,6 @@ xoft
Yeeeeezus (Donated AlchemistVillage prefabs)
Howaner
Masy98
+WebFreak001
Please add yourself to this list if you contribute to MCServer.
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index bf5003035..6a151b5ef 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -529,6 +529,7 @@ end
GetLocale = { Params = "", Return = "Locale", Notes = "Returns the locale string that the client sends as part of the protocol handshake. Can be used to provide localized strings." },
GetPing = { Params = "", Return = "number", Notes = "Returns the ping time, in ms" },
GetPlayer = { Params = "", Return = "{{cPlayer|cPlayer}}", Notes = "Returns the player object connected to this client. Note that this may be nil, for example if the player object is not yet spawned." },
+ GetProtocolVersion = { Params = "", Return = "number", Notes = "Returns the protocol version number of the protocol that the client is talking. Returns zero if the protocol version is not (yet) known." },
GetUniqueID = { Params = "", Return = "number", Notes = "Returns the UniqueID of the client used to identify the client in the server" },
GetUUID = { Params = "", Return = "string", Notes = "Returns the authentication-based UUID of the client. This UUID should be used to identify the player when persisting any player-related data. Returns a 32-char UUID (no dashes)" },
GetUsername = { Params = "", Return = "string", Notes = "Returns the username that the client has provided" },
diff --git a/MCServer/Plugins/ChatLog b/MCServer/Plugins/ChatLog
new file mode 160000
+Subproject 983d23ca37baa89f7e4dc11d71502d9c059f637
diff --git a/MCServer/Plugins/ChatLog/plugin.lua b/MCServer/Plugins/ChatLog/plugin.lua
deleted file mode 100644
index adbf986e0..000000000
--- a/MCServer/Plugins/ChatLog/plugin.lua
+++ /dev/null
@@ -1,31 +0,0 @@
-
--- plugin.lua
-
--- Implements the main entrypoint for the plugin, as well as all the handling needed
-
--- ChatLog plugin logs all chat messages into the server log
-
-
-
-
-
-function Initialize(Plugin)
- Plugin:SetName("ChatLog")
- Plugin:SetVersion(3)
-
- cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChat)
-
- LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
- return true
-end
-
-
-
-
-
-function OnChat(Player, Message)
- -- Lets get loggin'
- LOGINFO("[" .. Player:GetName() .. "]: " .. StripColorCodes(Message));
-
- return false
-end \ No newline at end of file
diff --git a/MCServer/Plugins/ChunkWorx b/MCServer/Plugins/ChunkWorx
new file mode 160000
+Subproject 894c7e32049e9d2a1e736f7d721aaacd1ae29e5
diff --git a/MCServer/Plugins/ChunkWorx/ChunkWorx.deproj b/MCServer/Plugins/ChunkWorx/ChunkWorx.deproj
deleted file mode 100644
index 17420d1d7..000000000
--- a/MCServer/Plugins/ChunkWorx/ChunkWorx.deproj
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<project>
- <file>
- <filename>chunkworx_main.lua</filename>
- </file>
- <file>
- <filename>chunkworx_web.lua</filename>
- </file>
-</project>
diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
deleted file mode 100644
index 88ecb3979..000000000
--- a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua
+++ /dev/null
@@ -1,128 +0,0 @@
--- Global variables
-PLUGIN = {} -- Reference to own plugin object
-GENERATION_STATE = 0
-OPERATION_CODE = 0 -- 0 = generation
-CX = 0
-CZ = 0
-CURRENT = 0
-TOTAL = 0
-
--- AREA Variables
-AreaStartX = -10
-AreaStartZ = -10
-AreaEndX = 10
-AreaEndZ = 10
-
--- RADIAL Variables
-RadialX = 0
-RadialZ = 0
-Radius = 10
-
--- WORLD
-WORK_WORLD = cRoot:Get():GetDefaultWorld():GetName()
-WW_instance = cRoot:Get():GetDefaultWorld()
-WORLDS = {}
-
-
-
-
-
-function Initialize(Plugin)
- PLUGIN = Plugin
-
- PLUGIN:SetName("ChunkWorx")
- PLUGIN:SetVersion(6)
-
- cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick)
-
- Plugin:AddWebTab("(Re)Generation", HandleRequest_Generation)
-
- GENERATION_STATE = 0
- WW_instance = cRoot:Get():GetWorld(WORK_WORLD)
- if (WW_instance == nil) then
- LOG("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": NO WORLD found :(")
- end
-
- -- Read the stored values:
- local SettingsIni = cIniFile();
- SettingsIni:ReadFile("ChunkWorx.ini"); -- ignore any read errors
- AreaStartX = SettingsIni:GetValueSetI("Area data", "StartX", AreaStartX)
- AreaStartZ = SettingsIni:GetValueSetI("Area data", "StartZ", AreaStartZ)
- AreaEndX = SettingsIni:GetValueSetI("Area data", "EndX", AreaEndX)
- AreaEndZ = SettingsIni:GetValueSetI("Area data", "EndZ", AreaEndZ)
- RadialX = SettingsIni:GetValueSetI("Radial data", "RadialX", RadialX)
- RadialZ = SettingsIni:GetValueSetI("Radial data", "RadialZ", RadialZ)
- Radius = SettingsIni:GetValueSetI("Radial data", "Radius", Radius)
- SettingsIni:WriteFile("ChunkWorx.ini");
-
- LOG("Initialized " .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion())
- return true
-end
-
-
-
-
-
-function OnTick( DeltaTime )
- if (GENERATION_STATE == 1 or GENERATION_STATE == 3) then
- LOGINFO("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works STARTED!")
- LOGINFO("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": At world: " .. WORK_WORLD)
- WW_instance = cRoot:Get():GetWorld(WORK_WORLD)
- if (GENERATION_STATE == 1) then GENERATION_STATE = 2 end
- if (GENERATION_STATE == 3) then GENERATION_STATE = 4 end
-
- -- Changing in case coordinates are flipped
- local shifter = AreaEndX
- if (AreaStartX > AreaEndX) then
- AreaEndX = AreaStartX
- AreaStartX = shifter
- end
- shifter = AreaEndZ
- if (AreaStartZ > AreaEndZ) then
- AreaEndZ = AreaStartZ
- AreaStartZ = shifter
- end
-
- CX = AreaStartX
- CZ = AreaStartZ
- CURRENT = 0
-
- if (WW_instance == nil) then
- LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED")
- LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": NO WORLD found :(")
- GENERATION_STATE = 0
- end
- end
-
-
-
- if (GENERATION_STATE == 2 or GENERATION_STATE == 4) then
- if (WW_instance:GetGeneratorQueueLength() < 200
- and WW_instance:GetLightingQueueLength() < 200
- and (WW_instance:GetStorageSaveQueueLength() + WW_instance:GetStorageLoadQueueLength()) < 80) then
- local chunk_sum = (1+ AreaEndX - AreaStartX) * (1+ AreaEndZ - AreaStartZ)
- TOTAL = chunk_sum
- LOG("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": PROCESSING 100 chunks, (" .. CURRENT .. "/" .. chunk_sum .. ")")
- for C = 1, 100 do
- if (GENERATION_STATE == 2) then WW_instance:GenerateChunk(CX, CZ) end
- if (GENERATION_STATE == 4) then WW_instance:RegenerateChunk(CX, CZ) end
-
- CX = CX + 1
- CURRENT = CURRENT + 1
- if (CX > AreaEndX) then
- CX = AreaStartX
- CZ = CZ + 1
- if (CZ > AreaEndZ) then
- if (GENERATION_STATE == 2) then LOGINFO("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. " - generation ENDED!") end
- if (GENERATION_STATE == 4) then LOGINFO("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. " - REgeneration ENDED!") end
-
- GENERATION_STATE = 0
- break
- end
- end
- end
- WW_instance:QueueSaveAllChunks()
- WW_instance:QueueUnloadUnusedChunks()
- end
- end
-end \ No newline at end of file
diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
deleted file mode 100644
index 9aec38b12..000000000
--- a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua
+++ /dev/null
@@ -1,274 +0,0 @@
-
--- chunkworx_web.lua
-
--- WebAdmin-related functions
-
-
-
-
-
-local function Buttons_Player( Name )
- return "<form method='POST'><input type='hidden' name='PlayerName' value='"..Name.."'><input type='submit' name='PlayerExact' value='Exact'><input type='submit' name='Player3x3' value='3x3'></form>"
-end
-
-
-
-
-
-local function Button_World( Name )
- return "<form method='POST'><input type='hidden' name='WorldName' value='"..Name.."'><input type='submit' name='SelectWorld' value='Select'></form>"
-end
-
-
-
-
-
-local function SaveSettings()
- local SettingsIni = cIniFile()
- SettingsIni:SetValueI("Area data", "StartX", AreaStartX)
- SettingsIni:SetValueI("Area data", "StartZ", AreaStartZ)
- SettingsIni:SetValueI("Area data", "EndX", AreaEndX)
- SettingsIni:SetValueI("Area data", "EndZ", AreaEndZ)
- SettingsIni:SetValueI("Radial data", "RadialX", RadialX)
- SettingsIni:SetValueI("Radial data", "RadialZ", RadialZ)
- SettingsIni:SetValueI("Radial data", "Radius", Radius)
- SettingsIni:WriteFile("ChunkWorx.ini")
-end
-
-
-
-
-
-function HandleRequest_Generation( Request )
- local Content = ""
- if (Request.PostParams["AGHRRRR"] ~= nil) then
- GENERATION_STATE = 0
- WW_instance:QueueSaveAllChunks()
- WW_instance:QueueUnloadUnusedChunks()
- LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin")
- end
- --Content = Content .. "<head><meta http-equiv=\"refresh\" content=\"2;\"></head>"
- -- PROCESSING
- --------------------------------------------------------------------------------------------------
- local function ProcessingContent()
- local _small_content = ""
- _small_content = _small_content .. "<head><meta http-equiv=\"refresh\" content=\"2;\"></head>"
- _small_content = _small_content .. "<h4>World for operations:</h4>"..WORK_WORLD
- if (OPERATION_CODE == 0) then
- _small_content = _small_content .. "<h4>Operation:</h4>Generation"
- elseif (OPERATION_CODE == 1) then
- _small_content = _small_content .. "<h4>Operation:</h4>Regeneration"
- end
- _small_content = _small_content .. "<h4>Area: </h4>["..AreaStartX..":"..AreaStartZ.."] ["..AreaEndX..":"..AreaEndZ.."]"
- _small_content = _small_content .. "<h4>Progress:</h4>"..CURRENT.."/"..TOTAL
- _small_content = _small_content .. "<br>"
- _small_content = _small_content .. "<form method='POST'>"
- _small_content = _small_content .. "<input type='submit' name='AGHRRRR' value='Stop'>"
- _small_content = _small_content .. "</form>"
- return _small_content
- end
- if (GENERATION_STATE == 2 or GENERATION_STATE == 4) then
- Content = ProcessingContent()
- return Content
- end
- -- SELECTING
- --------------------------------------------------------------------------------------------------
- if ( Request.PostParams["FormSetWorld"] ) then
- WORK_WORLD = Request.PostParams["FormWorldName"]
- WW_instance = cRoot:Get():GetWorld(WORK_WORLD)
- end
-
- if( Request.PostParams["SelectWorld"] ~= nil
- and Request.PostParams["WorldName"] ~= nil ) then -- World is selected!
- WORK_WORLD = Request.PostParams["WorldName"]
- WW_instance = cRoot:Get():GetWorld(WORK_WORLD)
- end
-
- if(Request.PostParams["OperationGenerate"] ~= nil) then
- OPERATION_CODE = 0
- end
- if(Request.PostParams["OperationReGenerate"] ~= nil) then
- OPERATION_CODE = 1
- end
-
- if (GENERATION_STATE == 0) then
- if( Request.PostParams["FormAreaStartX"] ~= nil
- and Request.PostParams["FormAreaStartZ"] ~= nil
- and Request.PostParams["FormAreaEndX"] ~= nil
- and Request.PostParams["FormAreaEndZ"] ~= nil ) then --(Re)Generation valid!
- -- COMMON (Re)gen
- if( Request.PostParams["StartArea"]) then
- AreaStartX = tonumber(Request.PostParams["FormAreaStartX"])
- AreaStartZ = tonumber(Request.PostParams["FormAreaStartZ"])
- AreaEndX = tonumber(Request.PostParams["FormAreaEndX"])
- AreaEndZ = tonumber(Request.PostParams["FormAreaEndZ"])
- SaveSettings();
- if (OPERATION_CODE == 0) then
- GENERATION_STATE = 1
- elseif (OPERATION_CODE == 1) then
- GENERATION_STATE = 3
- end
- Content = ProcessingContent()
- return Content
- end
- end
- if( Request.PostParams["FormRadialX"] ~= nil
- and Request.PostParams["FormRadialZ"] ~= nil
- and Request.PostParams["FormRadius"] ~= nil ) then --(Re)Generation valid!
- -- COMMON (Re)gen
- if( Request.PostParams["StartRadial"]) then
- RadialX = tonumber(Request.PostParams["FormRadialX"]) or 0
- RadialZ = tonumber(Request.PostParams["FormRadialZ"]) or 0
- Radius = tonumber(Request.PostParams["FormRadius"]) or 10
- AreaStartX = RadialX - Radius
- AreaStartZ = RadialZ - Radius
- AreaEndX = RadialX + Radius
- AreaEndZ = RadialZ + Radius
- SaveSettings()
- if (OPERATION_CODE == 0) then
- GENERATION_STATE = 1
- elseif (OPERATION_CODE == 1) then
- GENERATION_STATE = 3
- end
- Content = ProcessingContent()
- return Content
- end
- end
- -- POINT REGEN!
- if( Request.PostParams["FormPointX"] ~= nil
- and Request.PostParams["FormPointZ"] ~= nil ) then --ReGeneration valid!
- -- EXACT
- if ( Request.PostParams["PointExact"] ~= nil) then
- AreaStartX = tonumber(Request.PostParams["FormPointX"])
- AreaStartZ = tonumber(Request.PostParams["FormPointZ"])
- AreaEndX = AreaStartX
- AreaEndZ = AreaStartZ
- GENERATION_STATE = 3
- Content = ProcessingContent()
- return Content
- end
- -- 3x3
- if ( Request.PostParams["Point3x3"] ~= nil) then
- AreaStartX = tonumber(Request.PostParams["FormPointX"]) - 1
- AreaStartZ = tonumber(Request.PostParams["FormPointZ"]) - 1
- AreaEndX = AreaStartX + 2
- AreaEndZ = AreaStartZ + 2
- GENERATION_STATE = 3
- Content = ProcessingContent()
- return Content
- end
- end
-
- local GetAreaByPlayer = function(Player)
- -- Player is valid only within this function, it cannot be stord and used later!
- AreaStartX = Player:GetChunkX()
- AreaStartZ = Player:GetChunkZ()
- end
- -- PLAYERS REGEN!
- if( Request.PostParams["PlayerExact"] ~= nil
- and Request.PostParams["PlayerName"] ~= nil ) then -- Making BOOM! I meant, regenereate...
- cRoot:Get():GetWorld(WORK_WORLD):DoWithPlayer(Request.PostParams["PlayerName"],GetAreaByPlayer)
- AreaEndX = AreaStartX
- AreaEndZ = AreaStartZ
- GENERATION_STATE = 3
- Content = ProcessingContent()
- return Content
- end
- if( Request.PostParams["Player3x3"] ~= nil
- and Request.PostParams["PlayerName"] ~= nil ) then -- Making BOOM! I meant, regenereate...
- cRoot:Get():GetWorld(WORK_WORLD):DoWithPlayer(Request.PostParams["PlayerName"],GetAreaByPlayer)
- AreaStartX = AreaStartX - 1
- AreaStartZ = AreaStartZ - 1
- AreaEndX = AreaStartX + 2
- AreaEndZ = AreaStartZ + 2
- GENERATION_STATE = 3
- Content = ProcessingContent()
- return Content
- end
- end
-
- --Content = Content .. "<h4>World for operations: " .. WORK_WORLD .. "</h4>"
- --Content = Content .. "<form method='POST'>"
- --Content = Content .. "<input type='text' name='FormWorldName' value='Input world name here'><input type='submit' name='FormSetWorld' value='Set world'>"
- --Content = Content .. "</form>"
-
- -- SELECTING WORK_WORLD
- Content = Content .. "<h4>World for operations: " .. WORK_WORLD .. "</h4>"
- Content = Content .. "<table>"
- local WorldNum = 0
- local AddWorldToTable = function(World)
- WorldNum = WorldNum + 1
- Content = Content .. "<tr>"
- Content = Content .. "<td style='width: 10px;'>" .. WorldNum .. ".</td>"
- Content = Content .. "<td>" .. World:GetName() .. "</td>"
- Content = Content .. "<td>" .. Button_World(World:GetName()) .. "</td>"
- Content = Content .. "</tr>"
- end
- cRoot:Get():ForEachWorld(AddWorldToTable)
- if( WorldNum == 0 ) then
- Content = Content .. "<tr><td>No worlds! O_O</td></tr>"
- end
- Content = Content .. "</table>"
- Content = Content .. "<br>"
-
- -- SELECTING OPERATION
- if (OPERATION_CODE == 0) then
- Content = Content .. "<h4>Operation: Generation</h4>"
- elseif (OPERATION_CODE == 1) then
- Content = Content .. "<h4>Operation: Regeneration</h4>"
- end
- Content = Content .. "<form method='POST'>"
- Content = Content .. "<input type='submit' name='OperationGenerate' value='Generation'>"
- Content = Content .. "<input type='submit' name='OperationReGenerate' value='Regeneration'>"
- Content = Content .. "</form>"
-
- -- SELECTING AREA
- Content = Content .. "<h4>Area: </h4>Start X, Start Z; End X, End Z"
- Content = Content .. "<form method='POST'>"
- Content = Content .. "<input type='text' name='FormAreaStartX' value='" .. AreaStartX .. "'><input type='text' name='FormAreaStartZ' value='" .. AreaStartZ .. "'>"
- Content = Content .. "<input type='text' name='FormAreaEndX' value='" .. AreaEndX .. "'><input type='text' name='FormAreaEndZ' value='" .. AreaEndZ .. "'>"
- Content = Content .. "<input type='submit' name='StartArea' value='Start'>"
- Content = Content .. "</form>"
-
- -- SELECTING RADIAL
- Content = Content .. "<h4>Radial: </h4>Center X, Center Z, Radius"
- Content = Content .. "<form method='POST'>"
- Content = Content .. "<input type='text' name='FormRadialX' value='" .. RadialX .. "'><input type='text' name='FormRadialZ' value='" .. RadialZ .. "'><input type='text' name='FormRadius' value='" .. Radius .. "'>"
- Content = Content .. "<input type='submit' name='StartRadial' value='Start'>"
- Content = Content .. "</form>"
- Content = Content .. "<br>"
- Content = Content .. "<br>"
- Content = Content .. "<br>"
-
- -- SELECTING POINT
- Content = Content .. "<h4>Point regeneration:</h4> X, Z"
- Content = Content .. "<form method='POST'>"
- Content = Content .. "<input type='text' name='FormPointX' value='0'><input type='text' name='FormPointZ' value='0'>"
- Content = Content .. "<input type='submit' name='PointExact' value='Exact'>"
- Content = Content .. "<input type='submit' name='Point3x3' value='3x3'>"
- Content = Content .. "</form>"
-
- -- SELECTING PLAYERS
- Content = Content .. "<h4>Player-based regeneration:</h4>"
- Content = Content .. "<table>"
- local PlayerNum = 0
- local AddPlayerToTable = function( Player )
- PlayerNum = PlayerNum + 1
- Content = Content .. "<tr>"
- Content = Content .. "<td style='width: 10px;'>" .. PlayerNum .. ".</td>"
- Content = Content .. "<td>" .. Player:GetName() .. "</td>"
- Content = Content .. "<td>" .. Buttons_Player(Player:GetName()) .. "</td>"
- Content = Content .. "</tr>"
- end
- if (cRoot:Get():GetWorld(WORK_WORLD) == nil) then
- Content = Content .. "<tr><td>Incorrect world selection</td></tr>"
- else
- cRoot:Get():GetWorld(WORK_WORLD):ForEachPlayer( AddPlayerToTable )
- if( PlayerNum == 0 ) then
- Content = Content .. "<tr><td>No connected players</td></tr>"
- end
- end
- Content = Content .. "</table>"
- Content = Content .. "<br>"
- return Content
-end \ No newline at end of file
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
-Subproject 3a0e0597b7a24c44bf87ec90beb9be48d0b9970
+Subproject f8c2531fbef9bfd0b6f024d4d3319384a70a083
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index f66ac76a0..3dcd4ebee 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -10,9 +10,6 @@ g_ShowFoodStats = false; -- When true, each player's food stats are sent to the
function Initialize(Plugin)
- Plugin:SetName("Debuggers")
- Plugin:SetVersion(1)
-
--[[
-- Test multiple hook handlers:
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick1);
@@ -68,6 +65,8 @@ function Initialize(Plugin)
PM:BindCommand("/rmitem", "debuggers", HandleRMItem, "- Remove the specified item from the inventory.");
PM:BindCommand("/pickups", "debuggers", HandlePickups, "- Spawns random pickups around you");
PM:BindCommand("/poof", "debuggers", HandlePoof, "- Nudges pickups close to you away from you");
+
+ PM:BindConsoleCommand("sched", HandleConsoleSchedule, "Tests the world scheduling");
Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
@@ -1630,3 +1629,17 @@ end
+
+function HandleConsoleSchedule(a_Split)
+ LOG("Scheduling a task for 2 seconds in the future")
+ cRoot:Get():GetDefaultWorld():ScheduleTask(40,
+ function ()
+ LOG("Scheduled function is called.")
+ end
+ )
+ return true, "Task scheduled"
+end
+
+
+
+
diff --git a/MCServer/Plugins/Handy b/MCServer/Plugins/Handy
new file mode 160000
+Subproject e64a04be39ac7790abcb09de3d4c7d8fc2a2a1e
diff --git a/MCServer/Plugins/Handy/handy.lua b/MCServer/Plugins/Handy/handy.lua
deleted file mode 100644
index e4e9d3f5f..000000000
--- a/MCServer/Plugins/Handy/handy.lua
+++ /dev/null
@@ -1,28 +0,0 @@
--- Global variables
-PLUGIN = {} -- Reference to own plugin object
-CHEST_WIDTH = 9
-HANDY_VERSION = 2
---[[
-
-Handy is a plugin for other plugins. It contain no commands, no hooks, but functions to ease plugins developers' life.
-
-API:
-
-
-TODO:
-1. GetChestSlot wrapper, so it will detect double chest neighbour chest and will be able to access it.
-]]
-
-function Initialize(Plugin)
- PLUGIN = Plugin
- PLUGIN:SetName("Handy")
- PLUGIN:SetVersion(HANDY_VERSION)
-
- PluginManager = cRoot:Get():GetPluginManager()
- LOG("Initialized " .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion())
- return true
-end
-
-function OnDisable()
- LOG(PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. " is shutting down...")
-end \ No newline at end of file
diff --git a/MCServer/Plugins/Handy/handy_functions.lua b/MCServer/Plugins/Handy/handy_functions.lua
deleted file mode 100644
index af43f663a..000000000
--- a/MCServer/Plugins/Handy/handy_functions.lua
+++ /dev/null
@@ -1,216 +0,0 @@
---[[
-General stuff
-]]
--- Returns Handy plugin version number
-function GetHandyVersion()
- return HANDY_VERSION
-end
--- Checks if handy is in proper version
-function CheckForRequiredVersion( inVersion )
- if( inVersion > HANDY_VERSION ) then return false end
- return true
-end
---[[
-MCS-specific _functions and nasty hacks :D
-]]
-function GetChestHeightCheat( inChest )
- local chestGrid = inChest:GetContents()
- LOGINFO( "This function serves no purpose now! You should consider chest:GetContents():GetHeight() now!" )
- LOGINFO( "Also, you might find Handy's new 'IsChestDouble()' useful for your case" )
- return chestGrid:GetHeight()
-end
-function IsChestDouble( inChest )
- local chestHeight = inChest:GetContents():GetHeight()
- if( chestHeight == 3 ) then
- return false
- end
- return true
-end
--- Those two checks how many items of given inItemID chest and player have, and how much they could fit inside them
-function ReadChestForItem( inChest, inItemID )
- return ReadGridForItems( inChest:GetContents(), inItemID )
-end
-function ReadPlayerForItem( inPlayer, inItemID )
- local inventoryFound, inventoryFree = ReadGridForItems( inPlayer:GetInventory():GetInventoryGrid(), inItemID )
- local hotbarFound, hotbarFree = ReadGridForItems( inPlayer:GetInventory():GetHotbarGrid(), inItemID )
- local itemsFound = inventoryFound + hotbarFound
- local freeSpace = inventoryFree + hotbarFree
- return itemsFound, freeSpace
-end
--- Following functions are for chest-related operations
--- BEWARE! Those assume you did checked if chest has items/space in it!
-function ReadGridForItems( inGrid, inItemID )
- local itemsFound = 0
- local freeSpace = 0
- local slotsCount = inGrid:GetNumSlots()
- local testerItem = cItem( inItemID )
- local maxStackSize = testerItem:GetMaxStackSize()
- for index = 0, (slotsCount - 1) do
- slotItem = inGrid:GetSlot( index )
- if( slotItem:IsEmpty() ) then
- freeSpace = freeSpace + maxStackSize
- else
- if( slotItem:IsStackableWith( testerItem ) ) then
- itemsFound = itemsFound + slotItem.m_ItemCount
- freeSpace = maxStackSize - slotItem.m_ItemCount
- end
- end
- end
- return itemsFound, freeSpace
-end
-
-function TakeItemsFromGrid( inGrid, inItem )
- local slotsCount = inGrid:GetNumSlots()
- local removedItem = cItem( inItem )
- for index = 0, (slotsCount - 1) do
- slotItem = inGrid:GetSlot( index )
- if( slotItem:IsSameType( removedItem ) ) then
- if( slotItem.m_ItemCount <= removedItem.m_ItemCount ) then
- removedItem.m_ItemCount = removedItem.m_ItemCount - slotItem.m_ItemCount
- inGrid:EmptySlot( index )
- else
- removedItem.m_ItemCount = slotItem.m_ItemCount - removedItem.m_ItemCount
- inGrid:SetSlot( index, removedItem )
- removedItem.m_ItemCount = 0
- end
- if( removedItem.m_ItemCount <= 0 ) then break end
- end
- end
- return removedItem.m_ItemCount
-end
---------------
-function TakeItemsFromChest( inChest, inItemID, inAmount ) -- MIGHT BE UNSAFE! CHECK FOR ITEMS FIRST!!
- local chestGrid = inChest:GetContents()
- local removedItem = cItem( inItemID, inAmount )
- TakeItemsFromGrid( chestGrid, removedItem )
-end
-function PutItemsToChest( inChest, inItemID, inAmount )
- local chestGrid = inChest:GetContents()
- local addedItem = cItem( inItemID, inAmount )
- chestGrid:AddItem( addedItem )
-end
--- Similar to chest-related.
-function TakeItemsFromPlayer( inPlayer, inItemID, inAmount ) -- MIGHT BE UNSAFE! CHECK FIRST!
- local removedItem = cItem( inItemID, inAmount )
- local inventoryGrid = inPlayer:GetInventory():GetInventoryGrid()
- local hotbarGrid = inPlayer:GetInventory():GetHotbarGrid()
- local itemsLeft = TakeItemsFromGrid( inventoryGrid, removedItem )
- if( itemsLeft > 0 ) then
- removedItem = cItem( inItemID, itemsLeft )
- TakeItemsFromGrid( hotbarGrid, removedItem )
- end
-end
-function GiveItemsToPlayer( inPlayer, inItemID, inAmount )
- local addedItem = cItem( inItemID, inAmount )
- local inventoryGrid = inPlayer:GetInventory():GetInventoryGrid()
- local hotbarGrid = inPlayer:GetInventory():GetHotbarGrid()
- local itemsAdded = inventoryGrid:AddItem( addedItem )
- if( itemsAdded < inAmount ) then
- addedItem.m_ItemCount = addedItem.m_ItemCount - itemsAdded
- hotbarGrid:AddItem( addedItem )
- end
-end
--- This function returns item max stack for a given itemID. It uses vanilla max stack size, and uses several non-common items notations;
--- Those are:
--- oneonerecord( because aparently 11record wasn't the best idea in lua scripting application )
--- carrotonastick( because it wasn't added to items.txt yet )
--- waitrecord( for same reason )
--- Feel free to ignore the difference, or to add those to items.txt
-function GetItemMaxStack( inItemID )
- local testerItem = cItem( inItemID )
- LOGINFO( "This function serves no real purpose now, maybe consider using cItem:GetMaxStackSize()?" )
- return testerItem:GetMaxStackSize()
-end
-function ItemIsArmor( inItemID, inCheckForHorseArmor )
- inCheckForHorseArmor = inCheckForHorseArmor or false
- if( inItemID == E_ITEM_LEATHER_CAP ) then return true end
- if( inItemID == E_ITEM_LEATHER_TUNIC ) then return true end
- if( inItemID == E_ITEM_LEATHER_PANTS ) then return true end
- if( inItemID == E_ITEM_LEATHER_BOOTS ) then return true end
-
- if( inItemID == E_ITEM_CHAIN_HELMET ) then return true end
- if( inItemID == E_ITEM_CHAIN_CHESTPLATE ) then return true end
- if( inItemID == E_ITEM_CHAIN_LEGGINGS ) then return true end
- if( inItemID == E_ITEM_CHAIN_BOOTS ) then return true end
-
- if( inItemID == E_ITEM_IRON_HELMET ) then return true end
- if( inItemID == E_ITEM_IRON_CHESTPLATE ) then return true end
- if( inItemID == E_ITEM_IRON_LEGGINGS ) then return true end
- if( inItemID == E_ITEM_IRON_BOOTS ) then return true end
-
- if( inItemID == E_ITEM_DIAMOND_HELMET ) then return true end
- if( inItemID == E_ITEM_DIAMOND_CHESTPLATE ) then return true end
- if( inItemID == E_ITEM_DIAMOND_LEGGINGS ) then return true end
- if( inItemID == E_ITEM_DIAMOND_BOOTS ) then return true end
-
- if( inItemID == E_ITEM_GOLD_HELMET ) then return true end
- if( inItemID == E_ITEM_GOLD_CHESTPLATE ) then return true end
- if( inItemID == E_ITEM_GOLD_LEGGINGS ) then return true end
- if( inItemID == E_ITEM_GOLD_BOOTS ) then return true end
-
- if( inCheckForHorseArmor ) then
- if( inItemID == E_ITEM_IRON_HORSE_ARMOR ) then return true end
- if( inItemID == E_ITEM_GOLD_HORSE_ARMOR ) then return true end
- if( inItemID == E_ITEM_DIAMOND_HORSE_ARMOR ) then return true end
- end
- return false
-end
--- Returns full-length playername for a short name( usefull for parsing commands )
-function GetExactPlayername( inPlayerName )
- local _result = inPlayerName
- local function SetProcessingPlayername( inPlayer )
- _result = inPlayer:GetName()
- end
- cRoot:Get():FindAndDoWithPlayer( inPlayerName, SetProcessingPlayername )
- return _result
-end
-function GetPlayerByName( inPlayerName )
- local _player
- local PlayerSetter = function( Player )
- _player = Player
- end
- cRoot:Get():FindAndDoWithPlayer( inPlayerName, PlayerSetter )
- return _player
-end
---[[
-Not-so-usual math _functions
-]]
--- Rounds floating point number. Because lua guys think this function doesn't deserve to be presented in lua's math
-function round( inX )
- if( inX%2 ~= 0.5 ) then
- return math.floor( inX + 0.5 )
- end
- return inX - 0.5
-end
---[[
-Functions I use for filework and stringswork
-]]
-function PluralString( inValue, inSingularString, inPluralString )
- local _value_string = tostring( inValue )
- if( _value_string[#_value_string] == "1" ) then
- return inSingularString
- end
- return inPluralString
-end
-function PluralItemName( inItemID, inAmount ) -- BEWARE! TEMPORAL SOLUTION THERE! :D
- local _value_string = tostring( inValue )
- local _name = ""
- if( _value_string[#_value_string] == "1" ) then
- -- singular names
- _name = ItemTypeToString( inItemID )
- else
- -- plural names
- _name = ItemTypeToString( inItemID ).."s"
- end
- return _name
-end
--- for filewriting purposes. 0 = false, 1 = true
-function StringToBool( inValue )
- if( inValue == "1" ) then return true end
- return false
-end
--- same, but reversal
-function BoolToString( inValue )
- if( inValue == true ) then return 1 end
- return 0
-end
diff --git a/MCServer/Plugins/InfoDump.lua b/MCServer/Plugins/InfoDump.lua
index c61f9c9e6..bc9bab767 100644
--- a/MCServer/Plugins/InfoDump.lua
+++ b/MCServer/Plugins/InfoDump.lua
@@ -20,8 +20,8 @@ only that one plugin's documentation. This mode of operation doesn't require Lua
-- Check Lua version. We use 5.1-specific construct when loading the plugin info, 5.2 is not compatible!
if (_VERSION ~= "Lua 5.1") then
- print("Unsupported Lua version. This script requires Lua version 5.1, this Lua is version " .. (_VERSION or "<nil>"));
- return;
+ print("Unsupported Lua version. This script requires Lua version 5.1, this Lua is version " .. (_VERSION or "<nil>"))
+ return
end
@@ -31,38 +31,38 @@ end
--- Replaces generic formatting with forum-specific formatting
-- Also removes the single line-ends
local function ForumizeString(a_Str)
- assert(type(a_Str) == "string");
+ assert(type(a_Str) == "string")
-- Remove the indentation, unless in the code tag:
-- Only one code or /code tag per line is supported!
- local IsInCode = false;
+ local IsInCode = false
local function RemoveIndentIfNotInCode(s)
if (IsInCode) then
-- we're in code section, check if this line terminates it
- IsInCode = (s:find("{%%/code}") ~= nil);
- return s .. "\n";
+ IsInCode = (s:find("{%%/code}") ~= nil)
+ return s .. "\n"
else
-- we're not in code section, check if this line starts it
- IsInCode = (s:find("{%%code}") ~= nil);
- return s:gsub("^%s*", "") .. "\n";
+ IsInCode = (s:find("{%%code}") ~= nil)
+ return s:gsub("^%s*", "") .. "\n"
end
end
- a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode);
+ a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode)
-- Replace multiple line ends with {%p} and single line ends with a space,
-- so that manual word-wrap in the Info.lua file doesn't wrap in the forum.
- a_Str = a_Str:gsub("\n\n", "{%%p}");
- a_Str = a_Str:gsub("\n", " ");
+ a_Str = a_Str:gsub("\n\n", "{%%p}")
+ a_Str = a_Str:gsub("\n", " ")
-- Replace the generic formatting:
- a_Str = a_Str:gsub("{%%p}", "\n\n");
- a_Str = a_Str:gsub("{%%b}", "[b]"):gsub("{%%/b}", "[/b]");
- a_Str = a_Str:gsub("{%%i}", "[i]"):gsub("{%%/i}", "[/i]");
- a_Str = a_Str:gsub("{%%list}", "[list]"):gsub("{%%/list}", "[/list]");
- a_Str = a_Str:gsub("{%%li}", "[*]"):gsub("{%%/li}", "");
+ a_Str = a_Str:gsub("{%%p}", "\n\n")
+ a_Str = a_Str:gsub("{%%b}", "[b]"):gsub("{%%/b}", "[/b]")
+ a_Str = a_Str:gsub("{%%i}", "[i]"):gsub("{%%/i}", "[/i]")
+ a_Str = a_Str:gsub("{%%list}", "[list]"):gsub("{%%/list}", "[/list]")
+ a_Str = a_Str:gsub("{%%li}", "[*]"):gsub("{%%/li}", "")
-- TODO: Other formatting
- return a_Str;
+ return a_Str
end
@@ -72,38 +72,38 @@ end
--- Replaces generic formatting with forum-specific formatting
-- Also removes the single line-ends
local function GithubizeString(a_Str)
- assert(type(a_Str) == "string");
+ assert(type(a_Str) == "string")
-- Remove the indentation, unless in the code tag:
-- Only one code or /code tag per line is supported!
- local IsInCode = false;
+ local IsInCode = false
local function RemoveIndentIfNotInCode(s)
if (IsInCode) then
-- we're in code section, check if this line terminates it
- IsInCode = (s:find("{%%/code}") ~= nil);
- return s .. "\n";
+ IsInCode = (s:find("{%%/code}") ~= nil)
+ return s .. "\n"
else
-- we're not in code section, check if this line starts it
- IsInCode = (s:find("{%%code}") ~= nil);
- return s:gsub("^%s*", "") .. "\n";
+ IsInCode = (s:find("{%%code}") ~= nil)
+ return s:gsub("^%s*", "") .. "\n"
end
end
- a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode);
+ a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode)
-- Replace multiple line ends with {%p} and single line ends with a space,
-- so that manual word-wrap in the Info.lua file doesn't wrap in the forum.
- a_Str = a_Str:gsub("\n\n", "{%%p}");
- a_Str = a_Str:gsub("\n", " ");
+ a_Str = a_Str:gsub("\n\n", "{%%p}")
+ a_Str = a_Str:gsub("\n", " ")
-- Replace the generic formatting:
- a_Str = a_Str:gsub("{%%p}", "\n\n");
- a_Str = a_Str:gsub("{%%b}", "**"):gsub("{%%/b}", "**");
- a_Str = a_Str:gsub("{%%i}", "*"):gsub("{%%/i}", "*");
- a_Str = a_Str:gsub("{%%list}", ""):gsub("{%%/list}", "");
- a_Str = a_Str:gsub("{%%li}", " - "):gsub("{%%/li}", "");
+ a_Str = a_Str:gsub("{%%p}", "\n\n")
+ a_Str = a_Str:gsub("{%%b}", "**"):gsub("{%%/b}", "**")
+ a_Str = a_Str:gsub("{%%i}", "*"):gsub("{%%/i}", "*")
+ a_Str = a_Str:gsub("{%%list}", ""):gsub("{%%/list}", "")
+ a_Str = a_Str:gsub("{%%li}", " - "):gsub("{%%/li}", "")
-- TODO: Other formatting
- return a_Str;
+ return a_Str
end
@@ -117,7 +117,7 @@ end
local function BuildCategories(a_PluginInfo)
-- The returned result
-- This will contain both an array and a dict of the categories, to allow fast search
- local res = {};
+ local res = {}
-- For each command add a reference to it into all of its categories:
local function AddCommands(a_CmdPrefix, a_Commands)
@@ -130,39 +130,39 @@ local function BuildCategories(a_PluginInfo)
if ((info.HelpString ~= nil) and (info.HelpString ~= "")) then
-- Add to each specified category:
- local Category = info.Category;
+ local Category = info.Category
if (type(Category) == "string") then
- Category = {Category};
+ Category = {Category}
end
for idx, cat in ipairs(Category or {""}) do
- local CatEntry = res[cat];
+ local CatEntry = res[cat]
if (CatEntry == nil) then
-- First time we came across this category, create it:
- local NewCat = {Name = cat, Description = "", Commands = {NewCmd}};
- table.insert(res, NewCat);
- res[cat] = NewCat;
+ local NewCat = {Name = cat, Description = "", Commands = {NewCmd}}
+ table.insert(res, NewCat)
+ res[cat] = NewCat
else
-- We already have this category, just add the command to its list of commands:
- table.insert(CatEntry.Commands, NewCmd);
+ table.insert(CatEntry.Commands, NewCmd)
end
end -- for idx, cat - Category[]
end -- if (HelpString valid)
-- Recurse all subcommands:
if (info.Subcommands ~= nil) then
- AddCommands(a_CmdPrefix .. cmd .. " ", info.Subcommands);
+ AddCommands(a_CmdPrefix .. cmd .. " ", info.Subcommands)
end
end -- for cmd, info - a_Commands[]
end -- AddCommands()
- AddCommands("", a_PluginInfo.Commands);
+ AddCommands("", a_PluginInfo.Commands)
-- Assign descriptions to categories:
for name, desc in pairs(a_PluginInfo.Categories or {}) do
- local CatEntry = res[name];
+ local CatEntry = res[name]
if (CatEntry ~= nil) then
-- The result has this category, add the description:
- CatEntry.Description = desc.Description;
+ CatEntry.Description = desc.Description
end
end
@@ -170,12 +170,12 @@ local function BuildCategories(a_PluginInfo)
for idx, cat in ipairs(res) do
table.sort(cat.Commands,
function (cmd1, cmd2)
- return (string.lower(cmd1.CommandString) < string.lower(cmd2.CommandString));
+ return (string.lower(cmd1.CommandString) < string.lower(cmd2.CommandString))
end
- );
+ )
end
- return res;
+ return res
end
@@ -188,9 +188,9 @@ end
-- colorizes command name blue and params green
local function GetCommandRefForum(a_Command)
if (type(a_Command) == "string") then
- return "[color=blue]" .. a_Command .. "[/color]";
+ return "[color=blue]" .. a_Command .. "[/color]"
end
- return "[color=blue]" .. a_Command.Name .. "[/color] [color=green]" .. (a_Command.Params or "") .. "[/color]";
+ return "[color=blue]" .. a_Command.Name .. "[/color] [color=green]" .. (a_Command.Params or "") .. "[/color]"
end
@@ -201,18 +201,18 @@ end
-- If a_CommandParams is nil, returns a_CommandName apostrophed
-- If a_CommandParams is a string, apostrophes a_CommandName with a_CommandParams
local function GetCommandRefGithub(a_CommandName, a_CommandParams)
- assert(type(a_CommandName) == "string");
+ assert(type(a_CommandName) == "string")
if (a_CommandParams == nil) then
- return "`" .. a_CommandName .. "`";
+ return "`" .. a_CommandName .. "`"
end
- assert(type(a_CommandParams) == "table");
+ assert(type(a_CommandParams) == "table")
if ((a_CommandParams.Params == nil) or (a_CommandParams.Params == "")) then
- return "`" .. a_CommandName .. "`";
+ return "`" .. a_CommandName .. "`"
end
- assert(type(a_CommandParams.Params) == "string");
- return "`" .. a_CommandName .. " " .. a_CommandParams.Params .. "`";
+ assert(type(a_CommandParams.Params) == "string")
+ return "`" .. a_CommandName .. " " .. a_CommandParams.Params .. "`"
end
@@ -221,25 +221,25 @@ end
--- Writes the specified command detailed help array to the output file, in the forum dump format
local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCombinations, f)
- assert(type(a_CmdString) == "string");
- assert(type(a_ParameterCombinations) == "table");
- assert(f ~= nil);
+ assert(type(a_CmdString) == "string")
+ assert(type(a_ParameterCombinations) == "table")
+ assert(f ~= nil)
if (#a_ParameterCombinations == 0) then
-- No explicit parameter combinations to write
- return;
+ return
end
- f:write("The following parameter combinations are recognized:\n");
+ f:write("The following parameter combinations are recognized:\n")
for idx, combination in ipairs(a_ParameterCombinations) do
- f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params or "", "[/color]");
+ f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params or "", "[/color]")
if (combination.Help ~= nil) then
- f:write(" - ", ForumizeString(combination.Help));
+ f:write(" - ", ForumizeString(combination.Help))
end
if (combination.Permission ~= nil) then
- f:write(" (Requires permission '[color=red]", combination.Permission, "[/color]')");
+ f:write(" (Requires permission '[color=red]", combination.Permission, "[/color]')")
end
- f:write("\n");
+ f:write("\n")
end
end
@@ -249,25 +249,25 @@ end
--- Writes the specified command detailed help array to the output file, in the forum dump format
local function WriteCommandParameterCombinationsGithub(a_CmdString, a_ParameterCombinations, f)
- assert(type(a_CmdString) == "string");
- assert(type(a_ParameterCombinations) == "table");
- assert(f ~= nil);
+ assert(type(a_CmdString) == "string")
+ assert(type(a_ParameterCombinations) == "table")
+ assert(f ~= nil)
if (#a_ParameterCombinations == 0) then
-- No explicit parameter combinations to write
- return;
+ return
end
- f:write("The following parameter combinations are recognized:\n\n");
+ f:write("The following parameter combinations are recognized:\n\n")
for idx, combination in ipairs(a_ParameterCombinations) do
- f:write(GetCommandRefGithub(a_CmdString, combination));
+ f:write(GetCommandRefGithub(a_CmdString, combination))
if (combination.Help ~= nil) then
- f:write(" - ", GithubizeString(combination.Help));
+ f:write(" - ", GithubizeString(combination.Help))
end
if (combination.Permission ~= nil) then
- f:write(" (Requires permission '**", combination.Permission, "**')");
+ f:write(" (Requires permission '**", combination.Permission, "**')")
end
- f:write("\n");
+ f:write("\n")
end
end
@@ -278,29 +278,29 @@ end
--- Writes all commands in the specified category to the output file, in the forum dump format
local function WriteCommandsCategoryForum(a_Category, f)
-- Write category name:
- local CategoryName = a_Category.Name;
+ local CategoryName = a_Category.Name
if (CategoryName == "") then
- CategoryName = "General";
+ CategoryName = "General"
end
- f:write("\n[size=Large]", ForumizeString(a_Category.DisplayName or CategoryName), "[/size]\n");
+ f:write("\n[size=Large]", ForumizeString(a_Category.DisplayName or CategoryName), "[/size]\n")
-- Write description:
if (a_Category.Description ~= "") then
- f:write(ForumizeString(a_Category.Description), "\n");
+ f:write(ForumizeString(a_Category.Description), "\n")
end
-- Write commands:
- f:write("\n[list]");
+ f:write("\n[list]")
for idx2, cmd in ipairs(a_Category.Commands) do
- f:write("\n[b]", cmd.CommandString, "[/b] - ", ForumizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n");
+ f:write("\n[b]", cmd.CommandString, "[/b] - ", ForumizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n")
if (cmd.Info.Permission ~= nil) then
- f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n");
+ f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n")
end
if (cmd.Info.DetailedDescription ~= nil) then
- f:write(ForumizeString(cmd.Info.DetailedDescription));
+ f:write(ForumizeString(cmd.Info.DetailedDescription))
end
if (cmd.Info.ParameterCombinations ~= nil) then
- WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f);
+ WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f)
end
end
f:write("[/list]\n\n")
@@ -313,23 +313,23 @@ end
--- Writes all commands in the specified category to the output file, in the Github dump format
local function WriteCommandsCategoryGithub(a_Category, f)
-- Write category name:
- local CategoryName = a_Category.Name;
+ local CategoryName = a_Category.Name
if (CategoryName == "") then
- CategoryName = "General";
+ CategoryName = "General"
end
- f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
+ f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n")
-- Write description:
if (a_Category.Description ~= "") then
- f:write(GithubizeString(a_Category.Description), "\n\n");
+ f:write(GithubizeString(a_Category.Description), "\n\n")
end
- f:write("| Command | Permission | Description | \n")
- f:write("| ------- | ---------- | ----------- | \n")
+ f:write("| Command | Permission | Description |\n")
+ f:write("| ------- | ---------- | ----------- |\n")
-- Write commands:
for idx2, cmd in ipairs(a_Category.Commands) do
- f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "| \n")
+ f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "|\n")
end
f:write("\n\n")
end
@@ -340,24 +340,24 @@ end
local function DumpCommandsForum(a_PluginInfo, f)
-- Copy all Categories from a dictionary into an array:
- local Categories = BuildCategories(a_PluginInfo);
+ local Categories = BuildCategories(a_PluginInfo)
-- Sort the categories by name:
table.sort(Categories,
function(cat1, cat2)
- return (string.lower(cat1.Name) < string.lower(cat2.Name));
+ return (string.lower(cat1.Name) < string.lower(cat2.Name))
end
- );
+ )
if (#Categories == 0) then
- return;
+ return
end
- f:write("\n[size=X-Large]Commands[/size]\n");
+ f:write("\n[size=X-Large]Commands[/size]\n")
-- Dump per-category commands:
for idx, cat in ipairs(Categories) do
- WriteCommandsCategoryForum(cat, f);
+ WriteCommandsCategoryForum(cat, f)
end
end
@@ -367,24 +367,24 @@ end
local function DumpCommandsGithub(a_PluginInfo, f)
-- Copy all Categories from a dictionary into an array:
- local Categories = BuildCategories(a_PluginInfo);
+ local Categories = BuildCategories(a_PluginInfo)
-- Sort the categories by name:
table.sort(Categories,
function(cat1, cat2)
- return (string.lower(cat1.Name) < string.lower(cat2.Name));
+ return (string.lower(cat1.Name) < string.lower(cat2.Name))
end
- );
+ )
if (#Categories == 0) then
- return;
+ return
end
- f:write("\n# Commands\n");
+ f:write("\n# Commands\n")
-- Dump per-category commands:
for idx, cat in ipairs(Categories) do
- WriteCommandsCategoryGithub(cat, f);
+ WriteCommandsCategoryGithub(cat, f)
end
end
@@ -393,16 +393,16 @@ end
local function DumpAdditionalInfoForum(a_PluginInfo, f)
- local AInfo = a_PluginInfo.AdditionalInfo;
+ local AInfo = a_PluginInfo.AdditionalInfo
if (type(AInfo) ~= "table") then
-- There is no AdditionalInfo in a_PluginInfo
- return;
+ return
end
for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do
if ((info.Title ~= nil) and (info.Contents ~= nil)) then
- f:write("\n[size=X-Large]", ForumizeString(info.Title), "[/size]\n");
- f:write(ForumizeString(info.Contents), "\n");
+ f:write("\n[size=X-Large]", ForumizeString(info.Title), "[/size]\n")
+ f:write(ForumizeString(info.Contents), "\n")
end
end
end
@@ -412,16 +412,16 @@ end
local function DumpAdditionalInfoGithub(a_PluginInfo, f)
- local AInfo = a_PluginInfo.AdditionalInfo;
+ local AInfo = a_PluginInfo.AdditionalInfo
if (type(AInfo) ~= "table") then
-- There is no AdditionalInfo in a_PluginInfo
- return;
+ return
end
for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do
if ((info.Title ~= nil) and (info.Contents ~= nil)) then
- f:write("\n# ", GithubizeString(info.Title), "\n");
- f:write(GithubizeString(info.Contents), "\n");
+ f:write("\n# ", GithubizeString(info.Title), "\n")
+ f:write(GithubizeString(info.Contents), "\n")
end
end
end
@@ -434,53 +434,53 @@ end
-- Each array item is {Name = "PermissionName", Info = { PermissionInfo }}
local function BuildPermissions(a_PluginInfo)
-- Collect all used permissions from Commands, reference the commands that use the permission:
- local Permissions = a_PluginInfo.Permissions or {};
+ local Permissions = a_PluginInfo.Permissions or {}
local function CollectPermissions(a_CmdPrefix, a_Commands)
for cmd, info in pairs(a_Commands) do
- CommandString = a_CmdPrefix .. cmd;
+ CommandString = a_CmdPrefix .. cmd
if ((info.Permission ~= nil) and (info.Permission ~= "")) then
-- Add the permission to the list of permissions:
- local Permission = Permissions[info.Permission] or {};
- Permissions[info.Permission] = Permission;
+ local Permission = Permissions[info.Permission] or {}
+ Permissions[info.Permission] = Permission
-- Add the command to the list of commands using this permission:
- Permission.CommandsAffected = Permission.CommandsAffected or {};
- table.insert(Permission.CommandsAffected, CommandString);
+ Permission.CommandsAffected = Permission.CommandsAffected or {}
+ table.insert(Permission.CommandsAffected, CommandString)
end
-- Process the command param combinations for permissions:
- local ParamCombinations = info.ParameterCombinations or {};
+ local ParamCombinations = info.ParameterCombinations or {}
for idx, comb in ipairs(ParamCombinations) do
if ((comb.Permission ~= nil) and (comb.Permission ~= "")) then
-- Add the permission to the list of permissions:
- local Permission = Permissions[comb.Permission] or {};
- Permissions[info.Permission] = Permission;
+ local Permission = Permissions[comb.Permission] or {}
+ Permissions[info.Permission] = Permission
-- Add the command to the list of commands using this permission:
- Permission.CommandsAffected = Permission.CommandsAffected or {};
- table.insert(Permission.CommandsAffected, {Name = CommandString, Params = comb.Params});
+ Permission.CommandsAffected = Permission.CommandsAffected or {}
+ table.insert(Permission.CommandsAffected, {Name = CommandString, Params = comb.Params})
end
end
-- Process subcommands:
if (info.Subcommands ~= nil) then
- CollectPermissions(CommandString .. " ", info.Subcommands);
+ CollectPermissions(CommandString .. " ", info.Subcommands)
end
end
end
- CollectPermissions("", a_PluginInfo.Commands);
+ CollectPermissions("", a_PluginInfo.Commands)
-- Copy the list of permissions to an array:
- local PermArray = {};
+ local PermArray = {}
for name, perm in pairs(Permissions) do
- table.insert(PermArray, {Name = name, Info = perm});
+ table.insert(PermArray, {Name = name, Info = perm})
end
-- Sort the permissions array:
table.sort(PermArray,
function(p1, p2)
- return (p1.Name < p2.Name);
+ return (p1.Name < p2.Name)
end
- );
- return PermArray;
+ )
+ return PermArray
end
@@ -489,32 +489,32 @@ end
local function DumpPermissionsForum(a_PluginInfo, f)
-- Get the processed sorted array of permissions:
- local Permissions = BuildPermissions(a_PluginInfo);
+ local Permissions = BuildPermissions(a_PluginInfo)
if ((Permissions == nil) or (#Permissions <= 0)) then
- return;
+ return
end
-- Dump the permissions:
- f:write("\n[size=X-Large]Permissions[/size]\n[list]\n");
+ f:write("\n[size=X-Large]Permissions[/size]\n[list]\n")
for idx, perm in ipairs(Permissions) do
- f:write(" - [color=red]", perm.Name, "[/color] - ");
- f:write(ForumizeString(perm.Info.Description or ""));
- local CommandsAffected = perm.Info.CommandsAffected or {};
+ f:write(" - [color=red]", perm.Name, "[/color] - ")
+ f:write(ForumizeString(perm.Info.Description or ""))
+ local CommandsAffected = perm.Info.CommandsAffected or {}
if (#CommandsAffected > 0) then
- f:write("\n[list] Commands affected:\n- ");
- local Affects = {};
+ f:write("\n[list] Commands affected:\n- ")
+ local Affects = {}
for idx2, cmd in ipairs(CommandsAffected) do
- table.insert(Affects, GetCommandRefForum(cmd));
+ table.insert(Affects, GetCommandRefForum(cmd))
end
- f:write(table.concat(Affects, "\n - "));
- f:write("\n[/list]");
+ f:write(table.concat(Affects, "\n - "))
+ f:write("\n[/list]")
end
if (perm.Info.RecommendedGroups ~= nil) then
- f:write("\n[list] Recommended groups: ", perm.Info.RecommendedGroups, "[/list]");
+ f:write("\n[list] Recommended groups: ", perm.Info.RecommendedGroups, "[/list]")
end
- f:write("\n");
+ f:write("\n")
end
- f:write("[/list]");
+ f:write("[/list]")
end
@@ -523,34 +523,35 @@ end
local function DumpPermissionsGithub(a_PluginInfo, f)
-- Get the processed sorted array of permissions:
- local Permissions = BuildPermissions(a_PluginInfo);
+ local Permissions = BuildPermissions(a_PluginInfo)
if ((Permissions == nil) or (#Permissions <= 0)) then
- return;
+ return
end
-- Dump the permissions:
- f:write("\n# Permissions\n");
+ f:write("\n# Permissions\n")
f:write("| Permissions | Description | Commands | Recommended groups |\n")
f:write("| ----------- | ----------- | -------- | ------------------ |\n")
for idx, perm in ipairs(Permissions) do
- f:write(perm.Name, " | ");
- f:write(GithubizeString(perm.Info.Description or ""), " | ");
- local CommandsAffected = perm.Info.CommandsAffected or {};
+ f:write("| ", perm.Name, " | ")
+ f:write(GithubizeString(perm.Info.Description or ""), " | ")
+ local CommandsAffected = perm.Info.CommandsAffected or {}
if (#CommandsAffected > 0) then
- local Affects = {};
+ local Affects = {}
for idx2, cmd in ipairs(CommandsAffected) do
if (type(cmd) == "string") then
- table.insert(Affects, GetCommandRefGithub(cmd));
+ table.insert(Affects, GetCommandRefGithub(cmd))
else
- table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd));
+ table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd))
end
end
- f:write(table.concat(Affects, ", "), " | ");
+ f:write(table.concat(Affects, ", "))
end
+ f:write(" | ")
if (perm.Info.RecommendedGroups ~= nil) then
- f:write(perm.Info.RecommendedGroups, " |");
+ f:write(perm.Info.RecommendedGroups)
end
- f:write("\n");
+ f:write(" |\n")
end
end
@@ -558,45 +559,53 @@ end
+--- Dumps the forum-format info for the plugin
+-- Returns true on success, nil and error message on failure
local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
-- Open the output file:
- local f, msg = io.open(a_PluginInfo.Name .. "_forum.txt", "w");
+ local f, msg = io.open(a_PluginFolder .. "/forum_info.txt", "w")
if (f == nil) then
- print("\tCannot dump forum info for plugin " .. a_PluginFolder .. ": " .. msg);
- return;
+ return nil, msg
end
-- Write the description:
- f:write(ForumizeString(a_PluginInfo.Description), "\n");
- DumpAdditionalInfoForum(a_PluginInfo, f);
- DumpCommandsForum(a_PluginInfo, f);
- DumpPermissionsForum(a_PluginInfo, f);
+ f:write(ForumizeString(a_PluginInfo.Description), "\n")
+ DumpAdditionalInfoForum(a_PluginInfo, f)
+ DumpCommandsForum(a_PluginInfo, f)
+ DumpPermissionsForum(a_PluginInfo, f)
if (a_PluginInfo.SourceLocation ~= nil) then
- f:write("[b][color=blue]Source:[/color] [url=", a_PluginInfo.SourceLocation, "]Link[/url][/b]");
+ f:write("[b][color=blue]Source:[/color] [url=", a_PluginInfo.SourceLocation, "]Link[/url][/b]")
end
-
- f:close();
+ f:close()
+ return true
end
+--- Dumps the README.md file into the plugin's folder with the GitHub Markdown format
+-- Returns true on success, nil and error message on failure
local function DumpPluginInfoGithub(a_PluginFolder, a_PluginInfo)
+ -- Check the params:
+ assert(type(a_PluginFolder) == "string")
+ assert(type(a_PluginInfo) == "table")
+
-- Open the output file:
- local f, msg = io.open(a_PluginInfo.Name .. ".md", "w"); -- TODO: Save to a_PluginFolder .. "/Readme.md" instead
+ local f, msg = io.open(a_PluginFolder .. "/README.md", "w")
if (f == nil) then
- print("\tCannot dump github info for plugin " .. a_PluginFolder .. ": " .. msg);
- return;
+ print("\tCannot dump github info for plugin " .. a_PluginFolder .. ": " .. msg)
+ return nil, msg
end
-- Write the description:
- f:write(GithubizeString(a_PluginInfo.Description), "\n");
- DumpAdditionalInfoGithub(a_PluginInfo, f);
- DumpCommandsGithub(a_PluginInfo, f);
- DumpPermissionsGithub(a_PluginInfo, f);
+ f:write(GithubizeString(a_PluginInfo.Description), "\n")
+ DumpAdditionalInfoGithub(a_PluginInfo, f)
+ DumpCommandsGithub(a_PluginInfo, f)
+ DumpPermissionsGithub(a_PluginInfo, f)
- f:close();
+ f:close()
+ return true
end
@@ -607,36 +616,50 @@ end
-- Returns the g_PluginInfo table on success, or nil and error message on failure
local function LoadPluginInfo(a_FolderName)
-- Load and compile the Info file:
- local cfg, err = loadfile(a_FolderName .. "/Info.lua");
+ local cfg, err = loadfile(a_FolderName .. "/Info.lua")
if (cfg == nil) then
- return nil, "Cannot open 'Info.lua': " .. err;
+ return nil, "Cannot open 'Info.lua': " .. err
end
-- Execute the loaded file in a sandbox:
-- This is Lua-5.1-specific and won't work in Lua 5.2!
- local Sandbox = {};
- setfenv(cfg, Sandbox);
- cfg();
+ local Sandbox = {}
+ setfenv(cfg, Sandbox)
+ cfg()
if (Sandbox.g_PluginInfo == nil) then
- return nil, "Info.lua doesn't contain the g_PluginInfo declaration";
+ return nil, "Info.lua doesn't contain the g_PluginInfo declaration"
end
- return Sandbox.g_PluginInfo;
+ return Sandbox.g_PluginInfo
end
+--- Processes the info for one plugin
+-- Returns true on success, nil and error message on failure
local function ProcessPluginFolder(a_FolderName)
- local PluginInfo, Msg = LoadPluginInfo(a_FolderName);
+ -- Load the plugin info:
+ local PluginInfo, Msg = LoadPluginInfo(a_FolderName)
if (PluginInfo == nil) then
- if (Msg ~= nil) then
- print("\t" .. Msg);
- end
- return;
+ return nil, "Cannot load info for plugin " .. a_FolderName .. ": " .. (Msg or "<unknown error>")
+ end
+
+ -- Dump the forum format:
+ local isSuccess
+ isSuccess, Msg = DumpPluginInfoForum(a_FolderName, PluginInfo)
+ if not(isSuccess) then
+ return nil, "Cannot dump forum info for plugin " .. a_FolderName .. ": " .. (Msg or "<unknown error>")
end
- DumpPluginInfoForum(a_FolderName, PluginInfo);
- DumpPluginInfoGithub(a_FolderName, PluginInfo);
+
+ -- Dump the GitHub format:
+ isSuccess, Msg = DumpPluginInfoGithub(a_FolderName, PluginInfo)
+ if not(isSuccess) then
+ return nil, "Cannot dump GitHub info for plugin " .. a_FolderName .. ": " .. (Msg or "<unknown error>")
+ end
+
+ -- All OK, return success
+ return true
end
@@ -650,7 +673,7 @@ local function LoadLFS()
function()
return require("lfs")
end
- );
+ )
-- ... rather, print a nice message with instructions:
if not(lfs) then
@@ -663,44 +686,50 @@ local function LoadLFS()
If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
sudo apt-get install luarocks (Ubuntu / Debian)
On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
- ]]);
+ ]])
- print("Original error text: ", err);
- return nil;
+ print("Original error text: ", err)
+ return nil
end
-- We now know that LFS is present, get it normally:
- return require("lfs");
+ return require("lfs")
end
-local Arg1 = ...;
+local Arg1 = arg[1]
if ((Arg1 ~= nil) and (Arg1 ~= "")) then
-- Called with a plugin folder name, export only that one
- ProcessPluginFolder(Arg1)
+ local isSuccess, msg = ProcessPluginFolder(Arg1)
+ if not(isSuccess) then
+ print(msg or "<unknown error>")
+ end
else
-- Called without any arguments, process all subfolders:
- local lfs = LoadLFS();
+ local lfs = LoadLFS()
if (lfs == nil) then
-- LFS not loaded, error has already been printed, just bail out
- return;
+ return
end
- print("Processing plugin subfolders:");
+ print("Processing plugin subfolders:")
for fnam in lfs.dir(".") do
if ((fnam ~= ".") and (fnam ~= "..")) then
- local Attributes = lfs.attributes(fnam);
+ local Attributes = lfs.attributes(fnam)
if (Attributes ~= nil) then
if (Attributes.mode == "directory") then
- print(fnam);
- ProcessPluginFolder(fnam);
+ print(fnam)
+ local isSuccess, msg = ProcessPluginFolder(fnam)
+ if not(isSuccess) then
+ print(" " .. (msg or "<unknown error>"))
+ end
end
end
end
end
end
-print("Done.");
+print("Done.")
diff --git a/MCServer/Plugins/MagicCarpet b/MCServer/Plugins/MagicCarpet
new file mode 160000
+Subproject 493f2dfa6d39f134e37c4c614cf8d6ffd10c825
diff --git a/MCServer/Plugins/MagicCarpet/objects.lua b/MCServer/Plugins/MagicCarpet/objects.lua
deleted file mode 100644
index 8d81623a5..000000000
--- a/MCServer/Plugins/MagicCarpet/objects.lua
+++ /dev/null
@@ -1,97 +0,0 @@
--- Location object
-cLocation = {}
-function cLocation:new( x, y, z )
- local object = { x = x, y = y, z = z }
- setmetatable(object, { __index = cLocation })
- return object
-end
-
--- Offsets
-cFibers = { }
-function cFibers:new()
- local object = {
- cLocation:new( 2, -1, 2 ),
- cLocation:new( 2, -1, 1 ),
- cLocation:new( 2, -1, 0 ),
- cLocation:new( 2, -1, -1 ),
- cLocation:new( 2, -1, -2 ),
- cLocation:new( 1, -1, 2 ),
- cLocation:new( 1, -1, 1 ),
- cLocation:new( 1, -1, 0 ),
- cLocation:new( 1, -1, -1 ),
- cLocation:new( 1, -1, -2 ),
- cLocation:new( 0, -1, 2 ),
- cLocation:new( 0, -1, 1 ),
- cLocation:new( 0, -1, 0 ),
- cLocation:new( 0, -1, -1 ),
- cLocation:new( 0, -1, -2 ),
- cLocation:new( -1, -1, 2 ),
- cLocation:new( -1, -1, 1 ),
- cLocation:new( -1, -1, 0 ),
- cLocation:new( -1, -1, -1 ),
- cLocation:new( -1, -1, -2 ),
- cLocation:new( -2, -1, 2 ),
- cLocation:new( -2, -1, 1 ),
- cLocation:new( -2, -1, 0 ),
- cLocation:new( -2, -1, -1 ),
- cLocation:new( -2, -1, -2 ),
- imadeit = false,
- }
- setmetatable(object, { __index = cFibers })
- return object;
-end
-
--- Carpet object
-cCarpet = {}
-function cCarpet:new()
- local object = { Location = cLocation:new(0,0,0),
- Fibers = cFibers:new(),
- }
- setmetatable(object, { __index = cCarpet })
- return object
-end
-
-function cCarpet:remove()
- local World = cRoot:Get():GetDefaultWorld()
- for i, fib in ipairs( self.Fibers ) do
- local x = self.Location.x + fib.x
- local y = self.Location.y + fib.y
- local z = self.Location.z + fib.z
- local BlockID = World:GetBlock( x, y, z )
- if( fib.imadeit == true and BlockID == E_BLOCK_GLASS ) then
- World:SetBlock( x, y, z, 0, 0 )
- fib.imadeit = false
- end
- end
-end
-
-function cCarpet:draw()
- local World = cRoot:Get():GetDefaultWorld()
- for i, fib in ipairs( self.Fibers ) do
- local x = self.Location.x + fib.x
- local y = self.Location.y + fib.y
- local z = self.Location.z + fib.z
- local BlockID = World:GetBlock( x, y, z )
- if( BlockID == 0 ) then
- fib.imadeit = true
- World:SetBlock( x, y, z, E_BLOCK_GLASS, 0 )
- else
- fib.imadeit = false
- end
- end
-end
-
-function cCarpet:moveTo( NewPos )
- local x = math.floor( NewPos.x )
- local y = math.floor( NewPos.y )
- local z = math.floor( NewPos.z )
- if( self.Location.x ~= x or self.Location.y ~= y or self.Location.z ~= z ) then
- self:remove()
- self.Location = cLocation:new( x, y, z )
- self:draw()
- end
-end
-
-function cCarpet:getY()
- return self.Location.y
-end \ No newline at end of file
diff --git a/MCServer/Plugins/MagicCarpet/plugin.lua b/MCServer/Plugins/MagicCarpet/plugin.lua
deleted file mode 100644
index 417ea0e02..000000000
--- a/MCServer/Plugins/MagicCarpet/plugin.lua
+++ /dev/null
@@ -1,81 +0,0 @@
-local Carpets = {}
-local PLUGIN
-
-function Initialize( Plugin )
- Plugin:SetName( "MagicCarpet" )
- Plugin:SetVersion( 2 )
-
- cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
- cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_DESTROYED, OnDisconnect)
-
- local PluginManager = cPluginManager:Get()
- PluginManager:BindCommand("/mc", "magiccarpet", HandleCarpetCommand, " - Spawns a magical carpet");
-
- PLUGIN = Plugin
-
- LOG( "Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion() )
- return true
-end
-
-
-
-
-
-function OnDisable()
- LOG( PLUGIN:GetName() .. " v." .. PLUGIN:GetVersion() .. " is shutting down..." )
- for i, Carpet in pairs( Carpets ) do
- Carpet:remove()
- end
-end
-
-
-
-
-
-function HandleCarpetCommand( Split, Player )
- Carpet = Carpets[ Player ]
-
- if( Carpet == nil ) then
- Carpets[ Player ] = cCarpet:new()
- Player:SendMessageSuccess("You're on a magic carpet!")
- Player:SendMessageInfo("Look straight down to descend. Jump to ascend.")
- else
- Carpet:remove()
- Carpets[ Player ] = nil
- Player:SendMessageSuccess("The carpet vanished!")
- end
-
- return true
-end
-
-
-
-
-
-function OnDisconnect( Reason, Player )
- local Carpet = Carpets[ Player ]
- if( Carpet ~= nil ) then
- Carpet:remove()
- end
- Carpets[ Player ] = nil
-end
-
-
-
-
-
-function OnPlayerMoving(Player)
- local Carpet = Carpets[ Player ]
- if( Carpet == nil ) then
- return
- end
-
- if( Player:GetPitch() == 90 ) then
- Carpet:moveTo( cLocation:new( Player:GetPosX(), Player:GetPosY() - 1, Player:GetPosZ() ) )
- else
- if( Player:GetPosY() < Carpet:getY() ) then
- Player:TeleportToCoords(Player:GetPosX(), Carpet:getY() + 0.2, Player:GetPosZ())
- end
- Carpet:moveTo( cLocation:new( Player:GetPosX(), Player:GetPosY(), Player:GetPosZ() ) )
- end
-end
diff --git a/MCServer/webadmin/(original).html b/MCServer/webadmin/(original).html
index 239a255e5..673a93ada 100644
--- a/MCServer/webadmin/(original).html
+++ b/MCServer/webadmin/(original).html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<link rel="icon" href="data:application/octet-stream;base64,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">
+<link rel="icon" href="files/favicon.ico">
<title>{TITLE}</title>
<style type="text/css" media="screen">
@@ -90,7 +90,7 @@
margin: 15px 0 10px 5px;
width: 180px;
height: 36px;
- background: url(data:image/png;base64,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) no-repeat left top;
+ background: url(files/logo.png) no-repeat left top;
}
h1 a {
@@ -114,7 +114,7 @@
#container {
- background: #fff url(data:image/gif;base64,R0lGODlhtAABAIAAAN3d3f///yH5BAAAAAAALAAAAAC0AAEAAAIMjI+py+0Po5y0WgYKADs%3D) repeat-y left top;
+ background: #fff url(files/background.gif) repeat-y left top;
border: 1px solid #ddd;
width: 918px;
@@ -155,7 +155,7 @@
margin-top:100px;
width: 180px;
height: 36px;
- background-image: url(data:image/png;base64,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);
+ background-image: url(files/logo.png);
}
#loginHolder {
diff --git a/MCServer/webadmin/files/style.css b/MCServer/webadmin/files/style.css
index e7ffe3999..7f01b34b2 100644
--- a/MCServer/webadmin/files/style.css
+++ b/MCServer/webadmin/files/style.css
@@ -1,326 +1,353 @@
-/* reset CSS */
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, font, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td {
- margin: 0;
+body, html
+{
+ font-family: "Open Sans", Tahoma, sans-serif;
padding: 0;
- border: 0;
- outline: 0;
- font-size: 100%;
- vertical-align: baseline;
- background: transparent;
+ margin: 0;
+ font-weight: 400;
+ background-color: #fbe9e7;
+ color: rgba(0, 0, 0, 0.87);
+}
+
+.light { font-weight: 300; }
+.bold { font-weight: 600; }
+
+#wrapper
+{
+ background-color: #ff5722;
+ margin: 40px auto;
+ width: 99%;
+ max-width: 1200px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-shadow: 0px 4px 5px rgba(0, 0, 0, 0.15);
+ color: rgba(0, 0, 0, 0.87);
+}
+
+.title
+{
+ font-size: 30pt;
+ padding: 10px 40px;
+ text-decoration: none;
+ color: white;
+ text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3);
+ display: block;
}
-body {
- line-height: 1;
+
+#sidebar
+{
+ float: left;
+ width: 20%;
}
-ol, ul {
+
+.sideNav
+{
list-style: none;
-}
-blockquote, q {
- quotes: none;
+ background-color: #fafafa;
+ margin: 20px 0;
+ padding: 5px 0;
+ width: 100%;
+ box-shadow: 1px 0px 10px rgba(0, 0, 0, 0.2);
}
-/* remember to define focus styles! */
-:focus {
- outline: 0;
+.sideNav li
+{
+ padding: 10px;
+ color: rgba(0, 0, 0, 0.54);
}
-/* remove textarea resize at Safari */
-textarea {
- resize: none;
+.sideNav li.link
+{
+ padding-left: 30px;
}
-/* remember to highlight inserts somehow! */
-ins {
+.sideNav li.link a
+{
text-decoration: none;
+ color: rgba(0, 0, 0, 0.87);
}
-del {
- text-decoration: line-through;
-}
-
-/* tables still need 'cellspacing="0"' in the markup */
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-/*
- Origional from http://www.perspectived.com/
- Modified by Ben Phelps
- Made for FakeTruth - MCServer
-*/
-
-/* Basic ---------------------------------------- */
-
-.clear { clear: both; }
-
-body {
- background: white;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 12px;
- color: #646464;
- text-align: center;
+#container
+{
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ background-color: #f5f5f5;
}
-#wrapper {
- text-align: left;
- width: 930px;
- margin: 0 auto;
+#main
+{
+ float: right;
+ width: 80%;
+ padding: 0 15px 20px 15px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
}
-/* Logo ---------------------------------------- */
-
-h1 {
- margin: 15px 0 10px 5px;
- width: 180px;
- height: 36px;
- background: url(logo.png) no-repeat left top;
+.clear
+{
+ clear: both;
}
-h1 a {
- display: block;
- width: 225px;
- height: 28px;
+table
+{
+ width: 100%;
+ border-collapse: collapse;
}
-h1 span { display: none; }
-
-a {
- color: #646464;
+table td
+{
+ padding: 5px;
}
-/* Container ---------------------------------------- */
-
-#containerHolder {
- background: #eee;
+table th
+{
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12);
padding: 5px;
+ text-align: center;
}
-
-#container {
- background: #fff url(background.gif) repeat-y left top;
- border: 1px solid #ddd;
- width: 918px;
-
+table tr:nth-child(odd)
+{
+ background-color: rgba(0, 0, 0, 0.015);
}
-#connectHolder {
- background: #eee;
- padding: 5px;
- margin-bottom:8px;
+p
+{
+ margin: 8px 0;
+ padding: 8px 3px;
}
-
-#connect {
- border: 1px solid #ddd;
- background-color: #fff;
- padding:5px;
- width: 908px;
+a
+{
+ text-decoration: none;
+ color: #0277bd;
+ -webkit-transition: color 0.1s linear;
+ -moz-transition: color 0.1s linear;
+ transition: color 0.1s linear;
}
-.pics {
- height: 375px;
- width: 600px;
-}
-
-.pics img {
- padding: 5px;
- border: 1px solid #ddd;
- background-color: #eee;
- width: 600px;
- height: 375px;
- margin-left: 15px;
+a:hover
+{
+ color: #01579b;
}
-/* Login -------------------------------------- */
-
-#loginLogo {
- margin: 0 auto;
- margin-top:100px;
- width: 180px;
- height: 36px;
- background-image: url(logo.png);
+.welcome-msg
+{
+ color: rgba(0, 0, 0, 0.54);
}
-#loginHolder {
- background: #eee;
- padding: 5px;
- width: 310px;
- margin: 0 auto;
- height: 90px;
- margin-top:20px;
+.username
+{
+ text-transform: capitalize;
+ color: rgba(0, 0, 0, 0.87);
}
-#login {
- padding:10px;
- width: 288px;
- height: 68px;
- border: 1px solid #ddd;
- background:#fff;
- text-align: left;
+a:hover
+{
+ color: black;
}
-
-/* Sidebar ---------------------------------------- */
-
-#sidebar {
- width: 179px;
- float: left;
+input, select
+{
+ padding: 8px;
}
-#sidebar .sideNav { width: 179px; }
+form
+{
+ padding: 4px;
+}
-#sidebar .sideNav li { border-bottom: 1px solid #ddd; width: 179px; }
+.info input[type="submit"], .info button, .info input[type="button"],
+.warn input[type="submit"], .warn button, .warn input[type="button"],
+.err input[type="submit"], .err button, .err input[type="button"]
+{
+ float: right;
+}
-#sidebar .sideNav li a {
+.err
+{
+ color: white;
display: block;
- color: #646464;
- background: #f6f6f6;
- text-decoration: none;
- height: 29px;
- line-height: 29px;
- padding: 0 19px;
- width: 141px;
+ background-color: #e51c23 !important;
+ padding: 15px;
+ line-height: 30px;
+ min-height: 30px;
}
-#sidebar .sideNav li a:hover { background: #fdfcf6; }
-
-#sidebar .sideNav li a.active, #sidebar .sideNav li a.active:hover {
- background: #f0f7fa;
- color: #c66653;
+.err:before
+{
+ content: "ERROR: ";
}
-/* Breadcrumb ---------------------------------------- */
-
-h2 {
- width: 718px;
- float: right;
- color: #646464;
- font-size: 16px;
- line-height: 16px;
- font-weight: bold;
- margin: 20px 0 0 0;
- padding: 0 0 10px 0;
- border-bottom: 1px solid #ddd;
+.warn
+{
+ color: white;
+ display: block;
+ background-color: #ff5722 !important;
+ padding: 15px;
+ line-height: 30px;
+ min-height: 30px;
}
-h2 a {
- color: #646464;
- text-decoration: none;
+.warn:before
+{
+ content: "WARNING: ";
}
-h2 a.active { color: #c66653; }
+.info
+{
+ color: white;
+ display: block;
+ background-color: #5677fc !important;
+ padding: 15px;
+ line-height: 30px;
+ min-height: 30px;
+}
-h2 a:hover { text-decoration: underline; }
+.info:before
+{
+ content: "INFORMATION: ";
+}
-/* Content ---------------------------------------- */
+#footer .fleft
+{
+ float: left;
+}
-#main {
- width: 700px;
+#footer .fright
+{
float: right;
- padding: 0 19px 0 0;
+ text-align: right;
}
-#main p {
-
+#footer
+{
+ margin: 0;
padding: 10px;
+ font-size: 9pt;
+ color: rgba(255, 255, 255, 0.8);
+ box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.2) inset;
+}
+#footer a
+{
+ text-transform: none;
+ color: white;
}
-h3 {
- font-size: 14px;
- line-height: 14px;
- font-weight: bold;
- color: #5494af;
- padding: 0 0 0 10px;
- margin: 20px 0 10px;
+input[type="submit"], button, input[type="button"]
+{
+ background-color: #ffc107;
+ padding: 8px 15px 8px 15px;
+ margin: 0 2px;
+ display: inline-block;
+ text-align: center;
+ color: black;
+ box-shadow: 0px 2px 3px rgba(0,0,0,0.2);
+ border: none;
+ outline: none;
+ cursor: pointer;
}
-h4 {
- padding: 0 0 0 10px;
- margin: 20px 0 10px;
+input[type="submit"]:hover, button:hover, input[type="button"]:hover
+{
+ background-color: #ffca28;
}
-#main ul {
- padding: 0 0 0 10px;
- list-style-type: circle;
- list-style-position: inside;
+input[type="submit"]:active, button:active, input[type="button"]:active
+{
+ background-color: #ffd54f;
+ -webkit-transform: translateY(1px);
+ -moz-transform: translateY(1px);
+ transform: translateY(1px);
}
-#main table {
- border-top: 1px solid #ddd;
- width: 700px;
+hr
+{
+ border: none;
+ height: 1px;
+ background-color: rgba(0, 0, 0, 0.12);
}
-#main table tr th {
- text-align: left;
- background: #f6f6f6;
- padding: 0px 20px;
- height: 20px;
- line-height: 20px;
- border-bottom: 1px solid #ddd;
+h4
+{
+ padding-bottom: 10px;
+ margin-bottom: 12px;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
-#main table tr td {
- background: #f6f6f6;
- padding: 0px 20px;
- height: 29px;
- line-height: 29px;
- border-bottom: 1px solid #ddd;
+
+/**** PAGE SPECIFIC CSS ****/
+
+/* remove the * for disabling: */
+
+.page-core-server-settings table td
+{
+ text-align: center;
+ width: 25%;
}
-#main table tr.odd td {
- background: #fbfbfb;
+.page-core-server-settings.no-param table td:nth-child(1) a,
+.page-core-server-settings.param-tab-general table td:nth-child(1) a
+{
+ font-weight: 600;
+ color: rgba(0, 0, 0, 0.87);
}
-#main table tr:hover td { background: #fdfcf6; }
+.page-core-server-settings.param-tab-monsters table td:nth-child(2) a
+{
+ font-weight: 600;
+ color: rgba(0, 0, 0, 0.87);
+}
-#main table .action {
- text-align: right;
- padding: 0 20px 0 10px;
+.page-core-server-settings.param-tab-worlds table td:nth-child(3) a
+{
+ font-weight: 600;
+ color: rgba(0, 0, 0, 0.87);
}
-#main table tr .action a { margin: 0 0 0 10px; text-decoration: none; color: #9b9b9b; }
-#main table tr:hover .action .edit { color: #c5a059; }
-#main table tr:hover .action .delete { color: #a02b2b; }
-#main table tr:hover .action .view { color: #55a34a; }
+.page-core-server-settings.param-tab-world table td:nth-child(4) a
+{
+ font-weight: 600;
+ color: rgba(0, 0, 0, 0.87);
+}
-#main table tr:hover .action a:hover { text-decoration: underline; }
+.page-core-permissions form table tr,
+.page-core-permissions form table td,
+.page-core-permissions form table th
+{
+ border: none;
+ background-color: transparent;
+}
-fieldset {
- border: 1px solid #ddd;
- padding: 19px;
- margin: 0 0 20px 0;
- background: #fbfbfb;
+.page-core-permissions form table tr:nth-child(1) th
+{
+ width: 35%;
}
-form p { margin: 0 0 14px 0; float: left; width: 100%; }
+.page-core-permissions form table tr:nth-child(1) td
+{
+ width: 65%;
+}
-label {
- display: block;
+.page-core-permissions form table td input
+{
width: 100%;
- margin: 0 0 7px 0;
- line-height: 12px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ margin: 0;
}
-/* Footer ---------------------------------------- */
-
-#footer {
- margin: 10px 0 30px 0;
- font-size: 11px;
- line-height: 11px;
- color: #9B9B9B;
- padding: 0 0 0 5px;
+#ChatDiv
+{
+ margin-bottom: 10px;
}
-#footer a { color: #9B9B9B; }
+#ChatMessage
+{
+ width: 100%;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+}
-#footer a:hover { text-decoration: none; }
+/**/
diff --git a/MCServer/webadmin/template.html b/MCServer/webadmin/template.html
index 822f73857..b0864e35d 100644
--- a/MCServer/webadmin/template.html
+++ b/MCServer/webadmin/template.html
@@ -1,129 +1,140 @@
<!DOCTYPE html>
<html>
-<head>
- <title>{TITLE} | {PLUGIN_NAME}</title>
- <style type="text/css">
- body {
- line-height: 1;
- background: #B8B8B8;
- }
-
- #maincontent {
- padding: 0px 25px 10px 25px;
- }
-
- #wrapper {
- min-width: 850px;
- width: 75%;
- margin: 10px auto;
- background-color: white;
- border: 4px #888888 solid;
- border-radius: 10px;
- font-family: Calibri, Trebuchet MS;
- }
-
- header {
- text-align:center;
- padding: 10px; 0px;
- }
-
- span {
- text-align: right;
- float: right;
- border-left: 2px #C8C8C8 solid;
- border-bottom: 2px #C8C8C8 solid;
- padding: 2px 10px;
- }
-
- footer {
- font-family: helvetica;
- font-size: 10px;
- text-align: center;
- border-top: 1px #000 dotted;
- padding: 1px 0px 1px 0px;
- }
-
- table {
- border-collapse: collapse;
- border-spacing: 10;
- }
-
- table {
- border-top: 1px solid #ddd;
- width: 700px;
- }
-
- table tr th {
- text-align: left;
- background: #f6f6f6;
- padding: 0px 20px;
- height: 25px;
- line-height: 25px;
- border: 1px solid #ddd;
- border-radius: 3px;
- }
-
- table tr td {
- background: #f6f6f6;
- padding: 0px 20px;
- height: 29px;
- line-height: 29px;
- border: 1px solid #ddd;
- border-radius: 3px;
- }
- #main table tr.odd td {
- background: #fbfbfb;
- }
-
- table tr:hover td { background: #fdfcf6; }
- table .action {
- text-align: right;
- padding: 0 20px 0 10px;
- }
-
- table tr .action a { color: #9b9b9b; }
-
- #cssmenu{ height:10px; display:table; padding:0; margin: 0 auto; border:1px #707070 solid; border-radius:5px; }
- #cssmenu > ul {list-style:inside none; padding:0; margin:0;}
- #cssmenu > ul > li {list-style:inside none; padding:0; margin:0; float:left; display:block; position:relative;}
- #cssmenu > ul > li > a{ outline:none; display:block; position:relative; color:#E8E8E8; padding:10px 10px; font:bold 13px/100% Arial, Helvetica, sans-serif; text-align:center; text-decoration:none; text-shadow:1px 1px 0 rgba(0,0,0, 0.4); }
- #cssmenu > ul > li:first-child > a{border-radius:5px 0 0 5px;}
- /* #cssmenu > ul > li > a:after{ content:''; position:absolute; border-right:1px solid #FFFFFF; top:-1px; bottom:-1px; right:-2px; z-index:99; } */
- #cssmenu ul li.has-sub:hover > a:after{top:0; bottom:0;}
- #cssmenu > ul > li.has-sub > a:before{ content:''; position:absolute; top:18px; right:6px; border:5px solid transparent; border-top:5px solid #707070; }
- #cssmenu > ul > li.has-sub:hover > a:before{top:19px;}
- #cssmenu ul li.has-sub:hover > a{ background:#3f3f3f; border-color:#707070; padding-bottom:13px; padding-top:13px; top:-1px; z-index:999; }
- #cssmenu ul li.has-sub:hover > ul, #cssmenu ul li.has-sub:hover > div{display:block;}
- #cssmenu ul li.has-sub > a:hover{background:#3f3f3f; border-color:#3f3f3f;}
- #cssmenu ul li > ul, #cssmenu ul li > div{ display:none; width:auto; position:absolute; top:38px; padding:10px 0; background:#3f3f3f; border-radius:0 0 5px 5px; z-index:999; }
- #cssmenu ul li > ul{width:200px;}
- #cssmenu ul li > ul li{display:block; list-style:inside none; padding:0; margin:0; position:relative;}
- #cssmenu ul li > ul li a{ outline:none; display:block; position:relative; margin:0; padding:8px 20px; font:10pt Arial, Helvetica, sans-serif; color:#fff; text-decoration:none; text-shadow:1px 1px 0 rgba(0,0,0, 0.5); }
- #cssmenu, #cssmenu > ul > li > ul > li a:hover{ background:#C8C8C8;}
- #cssmenu > ul > li > a{border-right:1px solid #707070; color:#FFFFFF;}
- #cssmenu > ul > li > a:after{border-color:#707070;}
- #cssmenu > ul > li > a:hover{background:#B8B8B8;}
- </style>
- <meta name="msapplication-tooltip" content="MCServer WebAdministrator"/>
- <meta name="msapplication-navbutton-color" content="#B8B8B8" />
- <link rel="shortcut icon" href="http://mc-server.org/favicon.ico" />
-</head>
-
-<body>
- <div id="wrapper">
- <span><b>Login: {USERNAME}</b></span><br />
- <header>
- <img alt="" src="data:image/png;base64,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" />
- </header>
- <nav id="cssmenu">
- <ul>
- {MENU}
- </ul>
- </nav>
- <div id="maincontent">
- {CONTENT}
+ <head>
+ <title>{TITLE} | {PLUGIN_NAME}</title>
+ <style type="text/css">
+ body {
+ line-height: 1;
+ background: #B8B8B8;
+ }
+
+ #maincontent {
+ padding: 0px 25px 10px 25px;
+ }
+
+ #wrapper {
+ min-width: 850px;
+ width: 75%;
+ margin: 10px auto;
+ background-color: white;
+ border: 4px #888888 solid;
+ border-radius: 10px;
+ font-family: Calibri, Trebuchet MS;
+ }
+
+ header {
+ text-align:center;
+ padding: 10px; 0px;
+ }
+
+ span {
+ text-align: right;
+ float: right;
+ border-left: 2px #C8C8C8 solid;
+ border-bottom: 2px #C8C8C8 solid;
+ padding: 2px 10px;
+ }
+
+ footer {
+ font-family: helvetica;
+ font-size: 10px;
+ text-align: center;
+ border-top: 1px #000 dotted;
+ padding: 1px 0px 1px 0px;
+ }
+
+ table {
+ border-collapse: collapse;
+ border-spacing: 10;
+ }
+
+ table {
+ border-top: 1px solid #ddd;
+ width: 700px;
+ }
+
+ table tr th {
+ text-align: left;
+ background: #f6f6f6;
+ padding: 0px 20px;
+ height: 25px;
+ line-height: 25px;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ }
+
+ table tr td {
+ background: #f6f6f6;
+ padding: 0px 20px;
+ height: 29px;
+ line-height: 29px;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ }
+
+ #main table tr.odd td {
+ background: #fbfbfb;
+ }
+
+ table tr:hover td {
+ background: #fdfcf6;
+ }
+
+ table .action {
+ text-align: right;
+ padding: 0 20px 0 10px;
+ }
+
+ table tr .action a {
+ color: #9b9b9b;
+ }
+
+ #cssmenu{ height:10px; display:table; padding:0; margin: 0 auto; border:1px #707070 solid; border-radius:5px; }
+ #cssmenu > ul {list-style:inside none; padding:0; margin:0;}
+ #cssmenu > ul > li {list-style:inside none; padding:0; margin:0; float:left; display:block; position:relative;}
+ #cssmenu > ul > li > a{ outline:none; display:block; position:relative; color:#E8E8E8; padding:10px 10px; font:bold 13px/100% Arial, Helvetica, sans-serif; text-align:center; text-decoration:none; text-shadow:1px 1px 0 rgba(0,0,0, 0.4); }
+ #cssmenu > ul > li:first-child > a{border-radius:5px 0 0 5px;}
+ /* #cssmenu > ul > li > a:after{ content:''; position:absolute; border-right:1px solid #FFFFFF; top:-1px; bottom:-1px; right:-2px; z-index:99; } */
+ #cssmenu ul li.has-sub:hover > a:after{top:0; bottom:0;}
+ #cssmenu > ul > li.has-sub > a:before{ content:''; position:absolute; top:18px; right:6px; border:5px solid transparent; border-top:5px solid #707070; }
+ #cssmenu > ul > li.has-sub:hover > a:before{top:19px;}
+ #cssmenu ul li.has-sub:hover > a{ background:#3f3f3f; border-color:#707070; padding-bottom:13px; padding-top:13px; top:-1px; z-index:999; }
+ #cssmenu ul li.has-sub:hover > ul, #cssmenu ul li.has-sub:hover > div{display:block;}
+ #cssmenu ul li.has-sub > a:hover{background:#3f3f3f; border-color:#3f3f3f;}
+ #cssmenu ul li > ul, #cssmenu ul li > div{ display:none; width:auto; position:absolute; top:38px; padding:10px 0; background:#3f3f3f; border-radius:0 0 5px 5px; z-index:999; }
+ #cssmenu ul li > ul{width:200px;}
+ #cssmenu ul li > ul li{display:block; list-style:inside none; padding:0; margin:0; position:relative;}
+ #cssmenu ul li > ul li a{ outline:none; display:block; position:relative; margin:0; padding:8px 20px; font:10pt Arial, Helvetica, sans-serif; color:#fff; text-decoration:none; text-shadow:1px 1px 0 rgba(0,0,0, 0.5); }
+ #cssmenu, #cssmenu > ul > li > ul > li a:hover{ background:#C8C8C8;}
+ #cssmenu > ul > li > a { border-right:1px solid #707070; color:#FFFFFF; }
+ #cssmenu > ul > li > a:after { border-color:#707070; }
+ #cssmenu > ul > li > a:hover { background:#B8B8B8; }
+ </style>
+ <meta name="msapplication-tooltip" content="MCServer WebAdministrator"/>
+ <meta name="msapplication-navbutton-color" content="#B8B8B8" />
+ <link rel="shortcut icon" href="http://mc-server.org/favicon.ico" />
+ </head>
+ <body>
+ <div id="wrapper">
+ <span>
+ <b>Login: {USERNAME}</b>
+ </span>
+ <br />
+ <header>
+ <img alt="" src="files/logo.png" />
+ </header>
+ <nav id="cssmenu">
+ <ul>
+ {MENU}
+ </ul>
+ </nav>
+ <div id="maincontent">
+ {CONTENT}
+ </div>
+ <footer>
+ <p>MCServer is using {MEM}MB of memory, with {NUMCHUNKS} chunks loaded.</p>
+ <p>Web Design by <a href="https://github.com/WebFreak001"@WebFreak001</a></p>
+ </footer>
</div>
- <footer><p>MCServer is using {MEM}MB of memory, with {NUMCHUNKS} chunks loaded.</p><p>Web Design by Tiger</p></footer>
- </div>
-</head>
+ </body>
</html>
diff --git a/MCServer/webadmin/template.lua b/MCServer/webadmin/template.lua
index a7480f83e..84a50b055 100644
--- a/MCServer/webadmin/template.lua
+++ b/MCServer/webadmin/template.lua
@@ -70,25 +70,33 @@ function ShowPage(WebAdmin, TemplateRequest)
PageContent, SubTitle = GetDefaultPage()
end
+ local reqParamsClass = ""
+
+ for key,value in pairs(TemplateRequest.Request.Params) do
+ reqParamsClass = reqParamsClass .. " param-" .. string.lower(string.gsub(key, "[^a-zA-Z0-9]+", "-") .. "-" .. string.gsub(value, "[^a-zA-Z0-9]+", "-"))
+ end
+
+ if (string.gsub(reqParamsClass, "%s", "") == "") then
+ reqParamsClass = " no-param"
+ end
+
Output([[
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="icon" href="/favicon.ico">
<title>]] .. Title .. [[</title>
-<link rel="stylesheet" type="text/css" media="screen" href="/style.css">
+<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,300' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" type="text/css" href="/style.css">
</head>
-
<body>
- <div id="wrapper">
- <!-- h1 tag stays for the logo, you can use the a tag for linking the index page -->
- <h1>
- <a href="]] .. BaseURL .. [["><span>MCServer</span></a>
- </h1>
- <div id="containerHolder">
- <div id="container">
- <div id="sidebar">
- <ul class="sideNav">
+<div id="wrapper">
+ <div id="containerHolder">
+ <a href="./" class="title light">MCServer</a>
+ <div id="container">
+ <div id="sidebar">
+ <ul class="sideNav">
+ <li class='link'><a href=']] .. BaseURL .. [['>Home</a></li>
]])
@@ -100,7 +108,7 @@ function ShowPage(WebAdmin, TemplateRequest)
Output("<li>"..PluginWebTitle.."</li>\n");
for webname,prettyname in pairs(TabNames) do
- Output("<li><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>\n")
+ Output("<li class='link'><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>\n")
end
end
end
@@ -108,30 +116,23 @@ function ShowPage(WebAdmin, TemplateRequest)
Output([[
</ul>
- <!-- // .sideNav -->
- </div>
- <!-- // #sidebar -->
- <!-- h2 stays for breadcrumbs -->
- <h2>Welcome ]] .. TemplateRequest.Request.Username .. [[</h2>
- <div id="main">
- <h3>]] .. SubTitle .. [[</h3>
- ]] .. PageContent .. [[
- </div>
- <!-- // #main -->
+ </div>
+
+ <div id="main" class="page-]] .. string.lower(PluginPage.PluginName .. "-" .. string.gsub(PluginPage.TabName, "[^a-zA-Z0-9]+", "-")) .. reqParamsClass .. [[">
+ <h2 class="welcome-msg">Welcome <span class="username">]] .. TemplateRequest.Request.Username .. [[</span></h2>
- <div class="clear"></div>
+ <hr/>
- </div>
- <!-- // #container -->
- </div>
- <!-- // #containerHolder -->
-
- <p id="footer">MCServer is using: ]] .. MemoryUsageKiB / 1024 .. [[ MiB of memory; Current chunk count: ]] .. NumChunks .. [[ </p>
+ <h3>]] .. SubTitle .. [[</h3>
+ ]] .. PageContent .. [[</div>
+ <div class="clear"></div>
+ </div>
</div>
- <!-- // #wrapper -->
+ <div id="footer"><div class="fleft">running MCServer using <span class="bold">]] .. MemoryUsageKiB / 1024 .. [[MB</span> of memory; <span class="bold">]] .. NumChunks .. [[</span> chunks</div><div class="fright">design by <a href="//www.github.com/WebFreak001">WebFreak001</a></div><div class="clear"></div></div>
+</div>
</body>
</html>
- ]])
+]])
return table.concat(SiteContent)
end
diff --git a/MCServer/webadmin/template_orig.lua b/MCServer/webadmin/template_orig.lua
new file mode 100644
index 000000000..a7480f83e
--- /dev/null
+++ b/MCServer/webadmin/template_orig.lua
@@ -0,0 +1,137 @@
+-- Use a table for fast concatenation of strings
+local SiteContent = {}
+function Output(String)
+ table.insert(SiteContent, String)
+end
+
+
+
+
+
+function GetTableSize(Table)
+ local Size = 0
+ for key,value in pairs(Table) do
+ Size = Size + 1
+ end
+ return Size
+end
+
+
+
+
+
+function GetDefaultPage()
+ local PM = cRoot:Get():GetPluginManager()
+
+ local SubTitle = "Current Game"
+ local Content = ""
+
+ Content = Content .. "<h4>Server Name:</h4>"
+ Content = Content .. "<p>" .. cRoot:Get():GetServer():GetServerID() .. "</p>"
+
+ Content = Content .. "<h4>Plugins:</h4><ul>"
+ local AllPlugins = PM:GetAllPlugins()
+ for key,value in pairs(AllPlugins) do
+ if( value ~= nil and value ~= false ) then
+ Content = Content .. "<li>" .. key .. " V." .. value:GetVersion() .. "</li>"
+ end
+ end
+
+ Content = Content .. "</ul>"
+ Content = Content .. "<h4>Players:</h4><ul>"
+
+ local AddPlayerToTable = function( Player )
+ Content = Content .. "<li>" .. Player:GetName() .. "</li>"
+ end
+ cRoot:Get():ForEachPlayer( AddPlayerToTable )
+
+ Content = Content .. "</ul><br>";
+
+ return Content, SubTitle
+end
+
+
+
+
+
+function ShowPage(WebAdmin, TemplateRequest)
+ SiteContent = {}
+ local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
+ local Title = "MCServer WebAdmin"
+ local MemoryUsageKiB = cRoot:GetPhysicalRAMUsage()
+ local NumChunks = cRoot:Get():GetTotalChunkCount()
+ local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
+ local PageContent = PluginPage.Content
+ local SubTitle = PluginPage.PluginName
+ if (PluginPage.TabName ~= "") then
+ SubTitle = PluginPage.PluginName .. " - " .. PluginPage.TabName
+ end
+ if (PageContent == "") then
+ PageContent, SubTitle = GetDefaultPage()
+ end
+
+ Output([[
+<!DOCTYPE html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<link rel="icon" href="/favicon.ico">
+<title>]] .. Title .. [[</title>
+<link rel="stylesheet" type="text/css" media="screen" href="/style.css">
+</head>
+
+<body>
+ <div id="wrapper">
+ <!-- h1 tag stays for the logo, you can use the a tag for linking the index page -->
+ <h1>
+ <a href="]] .. BaseURL .. [["><span>MCServer</span></a>
+ </h1>
+ <div id="containerHolder">
+ <div id="container">
+ <div id="sidebar">
+ <ul class="sideNav">
+ ]])
+
+
+ local AllPlugins = WebAdmin:GetPlugins()
+ for key,value in pairs(AllPlugins) do
+ local PluginWebTitle = value:GetWebTitle()
+ local TabNames = value:GetTabNames()
+ if (GetTableSize(TabNames) > 0) then
+ Output("<li>"..PluginWebTitle.."</li>\n");
+
+ for webname,prettyname in pairs(TabNames) do
+ Output("<li><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>\n")
+ end
+ end
+ end
+
+
+ Output([[
+ </ul>
+ <!-- // .sideNav -->
+ </div>
+ <!-- // #sidebar -->
+ <!-- h2 stays for breadcrumbs -->
+ <h2>Welcome ]] .. TemplateRequest.Request.Username .. [[</h2>
+ <div id="main">
+ <h3>]] .. SubTitle .. [[</h3>
+ ]] .. PageContent .. [[
+ </div>
+ <!-- // #main -->
+
+ <div class="clear"></div>
+
+ </div>
+ <!-- // #container -->
+ </div>
+ <!-- // #containerHolder -->
+
+ <p id="footer">MCServer is using: ]] .. MemoryUsageKiB / 1024 .. [[ MiB of memory; Current chunk count: ]] .. NumChunks .. [[ </p>
+ </div>
+ <!-- // #wrapper -->
+</body>
+</html>
+ ]])
+
+ return table.concat(SiteContent)
+end
diff --git a/README.md b/README.md
index b42467039..9e9751b35 100644
--- a/README.md
+++ b/README.md
@@ -3,26 +3,30 @@ MCServer [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](
MCServer is a Minecraft server that is written in C++ and designed to be efficient with memory and CPU, as well as having a flexible Lua Plugin API.
-MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis.
+MCServer can run on Windows, *nix and Android operating systems. This includes Android phones and tablets as well as Raspberry Pis.
-We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.8.
+We currently support Release 1.7 and 1.8 (not beta) Minecraft protocol versions.
Installation
------------
-Normally, you will want to download a pre-compiled version of MCServer from one of the buildservers:
+For Linux there is an easy installation method, just run this in your terminal:
- * [Windows and Linux](http://builds.mc-server.org)
- * [Raspberry Pi](http://ci.bearbin.net)
+ curl -s https://raw.githubusercontent.com/mc-server/MCServer/master/easyinstall.sh | sh
-You simply need to download and extract these files before you can use the server.
+For Windows, you just need to download a file and extract it:
-If you're a more advanced user, you may want to compile the server yourself for more performance. See the [COMPILING.md](https://github.com/mc-server/MCServer/blob/master/COMPILING.md) file for more details.
+ - [Windows 32 bit](http://builds.cuberite.org/job/MCServer%20Windows%20x86/lastSuccessfulBuild/artifact/Install/MCServer.zip)
+ - [Windows 64 bit](http://builds.cuberite.org/job/MCServer%20Windows%20x64/lastSuccessfulBuild/artifact/Install/MCServer.zip)
+
+For other operating systems you need to download and compile yourself. There is also an archive of binary builds on the buildserver: http://builds.cuberite.org
+
+Compiling the server yourself has other benefits: you may get better performance performance (1.5-3x as fast) and it supports more operating systems. See the [COMPILING.md](https://github.com/mc-server/MCServer/blob/master/COMPILING.md) file for more details.
Contributing
------------
-MCServer is licensed under the Apache license V2, and we welcome anybody to fork and submit a Pull Request back with their changes, and if you want to join as a permanent member we can add you to the team.
+MCServer is licensed under the Apache License V2, and we welcome anybody to fork and submit a Pull Request back with their changes, and if you want to join as a permanent member we can add you to the team.
Check out the [CONTRIBUTING.md](https://github.com/mc-server/MCServer/blob/master/CONTRIBUTING.md) file for more details.
@@ -33,7 +37,7 @@ For other stuff, including plugins and discussion, check the [forums](http://for
Earn bitcoins for commits or donate to reward the MCServer developers: [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
-Support Us on Gratipay: [![Support via Gittip](http://img.shields.io/gittip/mcs_team.svg)](https://www.gittip.com/mcs_team)
+Support Us on Gratipay: [![Support via Gratipay](http://img.shields.io/gittip/cuberite_team.svg)](https://www.gratipay.com/cuberite_team)
Travis CI: [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](https://travis-ci.org/mc-server/MCServer)
diff --git a/SetFlags.cmake b/SetFlags.cmake
index 1827a4b66..c0a021c25 100644
--- a/SetFlags.cmake
+++ b/SetFlags.cmake
@@ -59,12 +59,25 @@ 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)
- #on os x clang adds pthread for us but we need to add it for gcc
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+ endif()
+
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND (NOT GCC_VERSION VERSION_GREATER 4.6))
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++0x")
+ set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++0x")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x")
+ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
+ endif()
+ #on os x clang adds pthread for us but we need to add it for gcc
+ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_flags_cxx("-stdlib=libc++")
add_flags_lnk("-stdlib=libc++")
else()
@@ -77,8 +90,17 @@ macro(set_flags)
add_flags_cxx("-pthread")
endif()
- # Make CLang use C++11, otherwise MSVC2008-supported extensions don't work ("override" keyword etc.):
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+ endif()
+
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND (NOT GCC_VERSION VERSION_GREATER 4.6))
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++0x")
+ set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++0x")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x")
+ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
diff --git a/Tools/QtBiomeVisualiser/BiomeView.cpp b/Tools/QtBiomeVisualiser/BiomeView.cpp
index ce5a870cd..b44b935d7 100644
--- a/Tools/QtBiomeVisualiser/BiomeView.cpp
+++ b/Tools/QtBiomeVisualiser/BiomeView.cpp
@@ -42,8 +42,9 @@ BiomeView::BiomeView(QWidget * parent) :
// Add a chunk-update callback mechanism:
connect(&m_Cache, SIGNAL(chunkAvailable(int, int)), this, SLOT(chunkAvailable(int, int)));
- // Allow keyboard interaction:
+ // Allow mouse and keyboard interaction:
setFocusPolicy(Qt::StrongFocus);
+ setMouseTracking(true);
}
@@ -80,6 +81,27 @@ void BiomeView::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
+void BiomeView::setPosition(int a_BlockX, int a_BlockZ)
+{
+ m_X = a_BlockX;
+ m_Z = a_BlockZ;
+ redraw();
+}
+
+
+
+
+
+void BiomeView::setZoomLevel(double a_ZoomLevel)
+{
+ m_Zoom = a_ZoomLevel;
+ redraw();
+}
+
+
+
+
+
void BiomeView::redraw()
{
if (!hasData())
@@ -275,6 +297,12 @@ void BiomeView::mousePressEvent(QMouseEvent * a_Event)
void BiomeView::mouseMoveEvent(QMouseEvent * a_Event)
{
+ // If there's no data displayed, bail out:
+ if (!hasData())
+ {
+ return;
+ }
+
if (m_IsMouseDragging)
{
// The user is dragging the mouse, move the view around:
@@ -286,7 +314,15 @@ void BiomeView::mouseMoveEvent(QMouseEvent * a_Event)
return;
}
- // TODO: Update the status bar info for the biome currently pointed at
+ // Update the status bar info text:
+ int blockX = floor((a_Event->x() - width() / 2) / m_Zoom + m_X);
+ int blockZ = floor((a_Event->y() - height() / 2) / m_Zoom + m_Z);
+ int chunkX, chunkZ;
+ int relX = blockX, relY, relZ = blockZ;
+ cChunkDef::AbsoluteToRelative(relX, relY, relZ, chunkX, chunkZ);
+ auto chunk = m_Cache.fetch(chunkX, chunkZ);
+ int biome = (chunk.get() != nullptr) ? chunk->getBiome(relX, relZ) : biInvalidBiome;
+ emit hoverChanged(blockX, blockZ, biome);
}
@@ -307,12 +343,12 @@ void BiomeView::wheelEvent(QWheelEvent * a_Event)
m_MouseWheelDelta += a_Event->delta();
while (m_MouseWheelDelta >= DELTA_STEP)
{
- increaseZoom();
+ emit wheelUp();
m_MouseWheelDelta -= DELTA_STEP;
}
while (m_MouseWheelDelta <= -DELTA_STEP)
{
- decreaseZoom();
+ emit wheelDown();
m_MouseWheelDelta += DELTA_STEP;
}
}
@@ -360,14 +396,14 @@ void BiomeView::keyPressEvent(QKeyEvent * a_Event)
case Qt::Key_PageUp:
case Qt::Key_Q:
{
- increaseZoom();
+ emit increaseZoom();
break;
}
case Qt::Key_PageDown:
case Qt::Key_E:
{
- decreaseZoom();
+ emit decreaseZoom();
break;
}
}
@@ -376,52 +412,3 @@ void BiomeView::keyPressEvent(QKeyEvent * a_Event)
-
-void BiomeView::decreaseZoom()
-{
- if (m_Zoom > 1.001)
- {
- m_Zoom--;
- if (m_Zoom < 1.0)
- {
- // Just crossed the 100%, fixate the 100% threshold:
- m_Zoom = 1.0;
- }
- }
- else if (m_Zoom > 0.01)
- {
- m_Zoom = m_Zoom / 2;
- }
- redraw();
-}
-
-
-
-
-
-void BiomeView::increaseZoom()
-{
- if (m_Zoom > 0.99)
- {
- if (m_Zoom > 20.0)
- {
- // Zoom too large
- return;
- }
- m_Zoom++;
- }
- else
- {
- m_Zoom = m_Zoom * 2;
- if (m_Zoom > 1.0)
- {
- // Just crossed the 100%, fixate the 100% threshold:
- m_Zoom = 1.0;
- }
- }
- redraw();
-}
-
-
-
-
diff --git a/Tools/QtBiomeVisualiser/BiomeView.h b/Tools/QtBiomeVisualiser/BiomeView.h
index f0521571d..40d8b96ae 100644
--- a/Tools/QtBiomeVisualiser/BiomeView.h
+++ b/Tools/QtBiomeVisualiser/BiomeView.h
@@ -25,7 +25,27 @@ public:
The entire view is then invalidated and regenerated. */
void setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource);
+ /** Sets the position of the central pixel of the map to the specified point and redraws the view. */
+ void setPosition(int a_BlockX, int a_BlockZ);
+
+ /** Sets the zoom level to the specified value and redraws the view. */
+ void setZoomLevel(double a_ZoomLevel);
+
signals:
+ /** Signalled when the user uses the wheel to scroll upwards. */
+ void wheelUp();
+
+ /** Signalled when the user uses the wheel to scroll downwards. */
+ void wheelDown();
+
+ /** Signalled when the user presses a key to increase zoom. */
+ void increaseZoom();
+
+ /** Signalled when the user presses a key to decrease zoom. */
+ void decreaseZoom();
+
+ /** Emitted when the user moves the mouse, to reflect the current block under the cursor. */
+ void hoverChanged(int a_BlockX, int a_BlockZ, int a_Biome);
public slots:
/** Redraw the entire widget area. */
@@ -86,12 +106,6 @@ protected:
/** Called when the user presses a key. */
virtual void keyPressEvent(QKeyEvent * a_Event) override;
-
- /** Decreases the zoom level and queues a redraw. */
- void decreaseZoom();
-
- /** Increases the zoom level and queues a redraw. */
- void increaseZoom();
};
diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp
index 2d180f00f..e5cd7a75a 100644
--- a/Tools/QtBiomeVisualiser/ChunkSource.cpp
+++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp
@@ -10,135 +10,6 @@
-/** Map for converting biome values to colors. Initialized from biomeColors[]. */
-static uchar biomeToColor[256 * 4];
-
-/** Map for converting biome values to colors. Used to initialize biomeToColor[].*/
-static struct
-{
- EMCSBiome m_Biome;
- uchar m_Color[3];
-} biomeColors[] =
-{
- { biOcean, { 0x00, 0x00, 0x70 }, },
- { biPlains, { 0x8d, 0xb3, 0x60 }, },
- { biDesert, { 0xfa, 0x94, 0x18 }, },
- { biExtremeHills, { 0x60, 0x60, 0x60 }, },
- { biForest, { 0x05, 0x66, 0x21 }, },
- { biTaiga, { 0x0b, 0x66, 0x59 }, },
- { biSwampland, { 0x2f, 0xff, 0xda }, },
- { biRiver, { 0x30, 0x30, 0xaf }, },
- { biHell, { 0x7f, 0x00, 0x00 }, },
- { biSky, { 0x00, 0x7f, 0xff }, },
- { biFrozenOcean, { 0xa0, 0xa0, 0xdf }, },
- { biFrozenRiver, { 0xa0, 0xa0, 0xff }, },
- { biIcePlains, { 0xff, 0xff, 0xff }, },
- { biIceMountains, { 0xa0, 0xa0, 0xa0 }, },
- { biMushroomIsland, { 0xff, 0x00, 0xff }, },
- { biMushroomShore, { 0xa0, 0x00, 0xff }, },
- { biBeach, { 0xfa, 0xde, 0x55 }, },
- { biDesertHills, { 0xd2, 0x5f, 0x12 }, },
- { biForestHills, { 0x22, 0x55, 0x1c }, },
- { biTaigaHills, { 0x16, 0x39, 0x33 }, },
- { biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, },
- { biJungle, { 0x53, 0x7b, 0x09 }, },
- { biJungleHills, { 0x2c, 0x42, 0x05 }, },
-
- { biJungleEdge, { 0x62, 0x8b, 0x17 }, },
- { biDeepOcean, { 0x00, 0x00, 0x30 }, },
- { biStoneBeach, { 0xa2, 0xa2, 0x84 }, },
- { biColdBeach, { 0xfa, 0xf0, 0xc0 }, },
- { biBirchForest, { 0x30, 0x74, 0x44 }, },
- { biBirchForestHills, { 0x1f, 0x5f, 0x32 }, },
- { biRoofedForest, { 0x40, 0x51, 0x1a }, },
- { biColdTaiga, { 0x31, 0x55, 0x4a }, },
- { biColdTaigaHills, { 0x59, 0x7d, 0x72 }, },
- { biMegaTaiga, { 0x59, 0x66, 0x51 }, },
- { biMegaTaigaHills, { 0x59, 0x66, 0x59 }, },
- { biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, },
- { biSavanna, { 0xbd, 0xb2, 0x5f }, },
- { biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, },
- { biMesa, { 0xd9, 0x45, 0x15 }, },
- { biMesaPlateauF, { 0xb0, 0x97, 0x65 }, },
- { biMesaPlateau, { 0xca, 0x8c, 0x65 }, },
-
- // M variants:
- { biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, },
- { biDesertM, { 0xff, 0xbc, 0x40 }, },
- { biExtremeHillsM, { 0x88, 0x88, 0x88 }, },
- { biFlowerForest, { 0x2d, 0x8e, 0x49 }, },
- { biTaigaM, { 0x33, 0x8e, 0x81 }, },
- { biSwamplandM, { 0x07, 0xf9, 0xb2 }, },
- { biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, },
- { biJungleM, { 0x7b, 0xa3, 0x31 }, },
- { biJungleEdgeM, { 0x62, 0x8b, 0x17 }, },
- { biBirchForestM, { 0x58, 0x9c, 0x6c }, },
- { biBirchForestHillsM, { 0x47, 0x87, 0x5a }, },
- { biRoofedForestM, { 0x68, 0x79, 0x42 }, },
- { biColdTaigaM, { 0x24, 0x3f, 0x36 }, },
- { biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, },
- { biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, },
- { biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, },
- { biSavannaM, { 0xe5, 0xda, 0x87 }, },
- { biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, },
- { biMesaBryce, { 0xff, 0x6d, 0x3d }, },
- { biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, },
- { biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, },
-} ;
-
-
-
-
-
-static class BiomeColorsInitializer
-{
-public:
- BiomeColorsInitializer(void)
- {
- // Reset all colors to gray:
- for (size_t i = 0; i < ARRAYCOUNT(biomeToColor); i++)
- {
- biomeToColor[i] = 0x7f;
- }
-
- // Set known biomes to their colors:
- for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++)
- {
- uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome];
- color[0] = biomeColors[i].m_Color[2];
- color[1] = biomeColors[i].m_Color[1];
- color[2] = biomeColors[i].m_Color[0];
- color[3] = 0xff;
- }
- }
-} biomeColorInitializer;
-
-
-
-
-
-/** Converts biomes in an array into the chunk image data. */
-static void biomesToImage(cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image)
-{
- // Make sure the two arrays are of the same size, compile-time.
- // Note that a_Image is actually 4 items per pixel, so the array is 4 times bigger:
- static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1] = {};
- static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1] = {};
-
- // Convert the biomes into color:
- for (size_t i = 0; i < ARRAYCOUNT(a_Biomes); i++)
- {
- a_Image[4 * i + 0] = biomeToColor[4 * a_Biomes[i] + 0];
- a_Image[4 * i + 1] = biomeToColor[4 * a_Biomes[i] + 1];
- a_Image[4 * i + 2] = biomeToColor[4 * a_Biomes[i] + 2];
- a_Image[4 * i + 3] = biomeToColor[4 * a_Biomes[i] + 3];
- }
-}
-
-
-
-
-
////////////////////////////////////////////////////////////////////////////////
// BioGenSource:
@@ -160,9 +31,7 @@ void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChu
QMutexLocker lock(&m_Mtx);
m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
}
- Chunk::Image img;
- biomesToImage(biomes, img);
- a_DestChunk->setImage(img);
+ a_DestChunk->setBiomes(biomes);
}
@@ -331,10 +200,7 @@ void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChun
{
biomeMap[i] = (EMCSBiome)GetBEInt(beBiomes + 4 * i);
}
- // Render the biomes:
- Chunk::Image img;
- biomesToImage(biomeMap, img);
- a_DestChunk->setImage(img);
+ a_DestChunk->setBiomes(biomeMap);
return;
}
@@ -350,10 +216,7 @@ void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChun
{
biomeMap[i] = EMCSBiome(vanillaBiomes[i]);
}
- // Render the biomes:
- Chunk::Image img;
- biomesToImage(biomeMap, img);
- a_DestChunk->setImage(img);
+ a_DestChunk->setBiomes(biomeMap);
}
diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp
index eb45690c1..63d72f992 100644
--- a/Tools/QtBiomeVisualiser/MainWindow.cpp
+++ b/Tools/QtBiomeVisualiser/MainWindow.cpp
@@ -7,6 +7,7 @@
#include <QFileDialog>
#include <QSettings>
#include <QDirIterator>
+#include <QStatusBar>
#include "inifile/iniFile.h"
#include "ChunkSource.h"
#include "src/Generating/BioGen.h"
@@ -18,6 +19,15 @@
+const double MainWindow::m_ViewZooms[] =
+{
+ 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 24,
+};
+
+
+
+
+
MainWindow::MainWindow(QWidget * parent) :
QMainWindow(parent),
m_GeneratorSetup(nullptr),
@@ -26,6 +36,20 @@ MainWindow::MainWindow(QWidget * parent) :
initMinecraftPath();
m_BiomeView = new BiomeView();
+ connect(m_BiomeView, SIGNAL(increaseZoom()), this, SLOT(increaseZoom()));
+ connect(m_BiomeView, SIGNAL(decreaseZoom()), this, SLOT(decreaseZoom()));
+ connect(m_BiomeView, SIGNAL(wheelUp()), this, SLOT(increaseZoom()));
+ connect(m_BiomeView, SIGNAL(wheelDown()), this, SLOT(decreaseZoom()));
+
+ m_StatusBar = new QStatusBar();
+ this->setStatusBar(m_StatusBar);
+ m_StatusBlockX = new QLabel(tr("X"));
+ m_StatusBlockZ = new QLabel(tr("Z"));
+ m_StatusBiome = new QLabel(tr("B"));
+ m_StatusBar->addPermanentWidget(m_StatusBlockX);
+ m_StatusBar->addPermanentWidget(m_StatusBlockZ);
+ m_StatusBar->addPermanentWidget(m_StatusBiome);
+
m_MainLayout = new QHBoxLayout();
m_MainLayout->addWidget(m_BiomeView, 1);
m_MainLayout->setMenuBar(menuBar());
@@ -36,6 +60,8 @@ MainWindow::MainWindow(QWidget * parent) :
createActions();
createMenus();
+
+ connect(m_BiomeView, SIGNAL(hoverChanged(int, int, int)), this, SLOT(hoverChanged(int, int, int)));
}
@@ -129,6 +155,79 @@ void MainWindow::openVanillaWorld()
+void MainWindow::centerView()
+{
+ m_BiomeView->setPosition(0, 0);
+}
+
+
+
+
+
+void MainWindow::setViewZoom()
+{
+ // The zoom level is stored in the sender action's data, retrieve it:
+ QAction * action = qobject_cast<QAction *>(sender());
+ if (action == nullptr)
+ {
+ return;
+ }
+ double newZoom = m_ViewZooms[action->data().toInt()];
+ m_BiomeView->setZoomLevel(newZoom);
+ action->setChecked(true);
+}
+
+
+
+
+
+void MainWindow::increaseZoom()
+{
+ // If already at max zoom, bail out:
+ if (m_CurrentZoomLevel >= ARRAYCOUNT(m_ViewZooms) - 1)
+ {
+ return;
+ }
+
+ // Increase the zoom level:
+ m_CurrentZoomLevel += 1;
+ m_actViewZoom[m_CurrentZoomLevel]->setChecked(true);
+ m_BiomeView->setZoomLevel(m_ViewZooms[m_CurrentZoomLevel]);
+}
+
+
+
+
+
+void MainWindow::decreaseZoom()
+{
+ // If already at min zoom, bail out:
+ if (m_CurrentZoomLevel == 0)
+ {
+ return;
+ }
+
+ // Decrease the zoom level:
+ m_CurrentZoomLevel -= 1;
+ m_actViewZoom[m_CurrentZoomLevel]->setChecked(true);
+ m_BiomeView->setZoomLevel(m_ViewZooms[m_CurrentZoomLevel]);
+}
+
+
+
+
+
+void MainWindow::hoverChanged(int a_BlockX, int a_BlockZ, int a_Biome)
+{
+ m_StatusBlockX->setText(tr("X: %1").arg(a_BlockX));
+ m_StatusBlockZ->setText(tr("Z: %1").arg(a_BlockZ));
+ m_StatusBiome->setText (tr("B: %1 (%2)").arg(BiomeToString(a_Biome).c_str()).arg(a_Biome));
+}
+
+
+
+
+
void MainWindow::initMinecraftPath()
{
#ifdef Q_OS_MAC
@@ -147,6 +246,7 @@ void MainWindow::initMinecraftPath()
void MainWindow::createActions()
{
+ // Map menu:
createWorldActions();
m_actNewGen = new QAction(tr("&New generator"), this);
@@ -173,6 +273,26 @@ void MainWindow::createActions()
m_actExit->setShortcut(tr("Alt+X"));
m_actExit->setStatusTip(tr("Exit %1").arg(QApplication::instance()->applicationName()));
connect(m_actExit, SIGNAL(triggered()), this, SLOT(close()));
+
+ // View menu:
+ m_actViewCenter = new QAction(tr("&Reset to center"), this);
+ m_actViewCenter->setStatusTip(tr("Scrolls the view back to the map center"));
+ connect(m_actViewCenter, SIGNAL(triggered()), this, SLOT(centerView()));
+
+ QActionGroup * zoomGroup = new QActionGroup(this);
+ for (int i = 0; i < ARRAYCOUNT(m_ViewZooms); i++)
+ {
+ m_actViewZoom[i] = new QAction(tr("&Zoom %1%").arg(std::floor(m_ViewZooms[i] * 100)), this);
+ m_actViewZoom[i]->setCheckable(true);
+ if ((int)(m_ViewZooms[i] * 16) == 16)
+ {
+ m_actViewZoom[i]->setChecked(true);
+ m_CurrentZoomLevel = i;
+ }
+ m_actViewZoom[i]->setData(QVariant(i));
+ zoomGroup->addAction(m_actViewZoom[i]);
+ connect(m_actViewZoom[i], SIGNAL(triggered()), this, SLOT(setViewZoom()));
+ }
}
@@ -220,11 +340,12 @@ void MainWindow::createWorldActions()
void MainWindow::createMenus()
{
+ // Map menu:
QMenu * file = menuBar()->addMenu(tr("&Map"));
file->addAction(m_actNewGen);
file->addAction(m_actOpenGen);
file->addSeparator();
- QMenu * worlds = file->addMenu(tr("Open existing"));
+ QMenu * worlds = file->addMenu(tr("Open &existing"));
worlds->addActions(m_WorldActions);
if (m_WorldActions.empty())
{
@@ -235,6 +356,15 @@ void MainWindow::createMenus()
file->addAction(m_actReload);
file->addSeparator();
file->addAction(m_actExit);
+
+ // View menu:
+ QMenu * view = menuBar()->addMenu(tr("&View"));
+ view->addAction(m_actViewCenter);
+ view->addSeparator();
+ for (size_t i = 0; i < ARRAYCOUNT(m_actViewZoom); i++)
+ {
+ view->addAction(m_actViewZoom[i]);
+ }
}
diff --git a/Tools/QtBiomeVisualiser/MainWindow.h b/Tools/QtBiomeVisualiser/MainWindow.h
index 6490a937f..27faae7a8 100644
--- a/Tools/QtBiomeVisualiser/MainWindow.h
+++ b/Tools/QtBiomeVisualiser/MainWindow.h
@@ -4,6 +4,7 @@
#include <QList>
#include <QMainWindow>
#include <QHBoxLayout>
+#include <QLabel>
#include "BiomeView.h"
@@ -39,13 +40,33 @@ private slots:
/** Opens a vanilla world that is specified by the calling action. */
void openVanillaWorld();
+ /** Moves the view to the map's center. */
+ void centerView();
+
+ /** Sets the zoom level specified in the triggering action. */
+ void setViewZoom();
+
+ /** Sets a zoom level one step larger than current, if allowed. */
+ void increaseZoom();
+
+ /** Sets a zoom level one step smaller than current, if allowed. */
+ void decreaseZoom();
+
+ /** Updates the statusbar for the specified info about the current block under the cursor. */
+ void hoverChanged(int a_BlockX, int a_BlockZ, int a_Biome);
+
protected:
+ /** The zoom levels */
+ static const double m_ViewZooms[10];
+
// Actions:
QAction * m_actNewGen;
QAction * m_actOpenGen;
QAction * m_actOpenWorld;
QAction * m_actReload;
QAction * m_actExit;
+ QAction * m_actViewCenter;
+ QAction * m_actViewZoom[ARRAYCOUNT(m_ViewZooms)];
/** List of actions that open the specific vanilla world. */
QList<QAction *> m_WorldActions;
@@ -62,9 +83,19 @@ protected:
/** The layout for the window. */
QHBoxLayout * m_MainLayout;
+ /** The status bar that displays the current hover information. */
+ QStatusBar * m_StatusBar;
+
+ QLabel * m_StatusBlockX;
+ QLabel * m_StatusBlockZ;
+ QLabel * m_StatusBiome;
+
/** The separator line between biome view and generator setup. */
QWidget * m_LineSeparator;
+ /** Index into m_ViewZooms[] for the current zoom level. */
+ size_t m_CurrentZoomLevel;
+
/** Initializes the m_MinecraftPath based on the proper MC path */
void initMinecraftPath();
diff --git a/Tools/QtBiomeVisualiser/QtChunk.cpp b/Tools/QtBiomeVisualiser/QtChunk.cpp
index 80109b2f8..031aa3654 100644
--- a/Tools/QtBiomeVisualiser/QtChunk.cpp
+++ b/Tools/QtBiomeVisualiser/QtChunk.cpp
@@ -5,6 +5,138 @@
+/** Map for converting biome values to colors. Initialized from biomeColors[]. */
+static uchar biomeToColor[256 * 4];
+
+/** Map for converting biome values to colors. Used to initialize biomeToColor[].*/
+static struct
+{
+ EMCSBiome m_Biome;
+ uchar m_Color[3];
+} biomeColors[] =
+{
+ { biOcean, { 0x00, 0x00, 0x70 }, },
+ { biPlains, { 0x8d, 0xb3, 0x60 }, },
+ { biDesert, { 0xfa, 0x94, 0x18 }, },
+ { biExtremeHills, { 0x60, 0x60, 0x60 }, },
+ { biForest, { 0x05, 0x66, 0x21 }, },
+ { biTaiga, { 0x0b, 0x66, 0x59 }, },
+ { biSwampland, { 0x2f, 0xff, 0xda }, },
+ { biRiver, { 0x30, 0x30, 0xaf }, },
+ { biHell, { 0x7f, 0x00, 0x00 }, },
+ { biSky, { 0x00, 0x7f, 0xff }, },
+ { biFrozenOcean, { 0xa0, 0xa0, 0xdf }, },
+ { biFrozenRiver, { 0xa0, 0xa0, 0xff }, },
+ { biIcePlains, { 0xff, 0xff, 0xff }, },
+ { biIceMountains, { 0xa0, 0xa0, 0xa0 }, },
+ { biMushroomIsland, { 0xff, 0x00, 0xff }, },
+ { biMushroomShore, { 0xa0, 0x00, 0xff }, },
+ { biBeach, { 0xfa, 0xde, 0x55 }, },
+ { biDesertHills, { 0xd2, 0x5f, 0x12 }, },
+ { biForestHills, { 0x22, 0x55, 0x1c }, },
+ { biTaigaHills, { 0x16, 0x39, 0x33 }, },
+ { biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, },
+ { biJungle, { 0x53, 0x7b, 0x09 }, },
+ { biJungleHills, { 0x2c, 0x42, 0x05 }, },
+
+ { biJungleEdge, { 0x62, 0x8b, 0x17 }, },
+ { biDeepOcean, { 0x00, 0x00, 0x30 }, },
+ { biStoneBeach, { 0xa2, 0xa2, 0x84 }, },
+ { biColdBeach, { 0xfa, 0xf0, 0xc0 }, },
+ { biBirchForest, { 0x30, 0x74, 0x44 }, },
+ { biBirchForestHills, { 0x1f, 0x5f, 0x32 }, },
+ { biRoofedForest, { 0x40, 0x51, 0x1a }, },
+ { biColdTaiga, { 0x31, 0x55, 0x4a }, },
+ { biColdTaigaHills, { 0x59, 0x7d, 0x72 }, },
+ { biMegaTaiga, { 0x59, 0x66, 0x51 }, },
+ { biMegaTaigaHills, { 0x59, 0x66, 0x59 }, },
+ { biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, },
+ { biSavanna, { 0xbd, 0xb2, 0x5f }, },
+ { biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, },
+ { biMesa, { 0xd9, 0x45, 0x15 }, },
+ { biMesaPlateauF, { 0xb0, 0x97, 0x65 }, },
+ { biMesaPlateau, { 0xca, 0x8c, 0x65 }, },
+
+ // M variants:
+ { biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, },
+ { biDesertM, { 0xff, 0xbc, 0x40 }, },
+ { biExtremeHillsM, { 0x88, 0x88, 0x88 }, },
+ { biFlowerForest, { 0x2d, 0x8e, 0x49 }, },
+ { biTaigaM, { 0x33, 0x8e, 0x81 }, },
+ { biSwamplandM, { 0x07, 0xf9, 0xb2 }, },
+ { biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, },
+ { biJungleM, { 0x7b, 0xa3, 0x31 }, },
+ { biJungleEdgeM, { 0x62, 0x8b, 0x17 }, },
+ { biBirchForestM, { 0x58, 0x9c, 0x6c }, },
+ { biBirchForestHillsM, { 0x47, 0x87, 0x5a }, },
+ { biRoofedForestM, { 0x68, 0x79, 0x42 }, },
+ { biColdTaigaM, { 0x24, 0x3f, 0x36 }, },
+ { biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, },
+ { biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, },
+ { biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, },
+ { biSavannaM, { 0xe5, 0xda, 0x87 }, },
+ { biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, },
+ { biMesaBryce, { 0xff, 0x6d, 0x3d }, },
+ { biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, },
+ { biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, },
+} ;
+
+
+
+
+
+static class BiomeColorsInitializer
+{
+public:
+ BiomeColorsInitializer(void)
+ {
+ // Reset all colors to gray:
+ for (size_t i = 0; i < ARRAYCOUNT(biomeToColor); i++)
+ {
+ biomeToColor[i] = 0x7f;
+ }
+
+ // Set known biomes to their colors:
+ for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++)
+ {
+ uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome];
+ color[0] = biomeColors[i].m_Color[2];
+ color[1] = biomeColors[i].m_Color[1];
+ color[2] = biomeColors[i].m_Color[0];
+ color[3] = 0xff;
+ }
+ }
+} biomeColorInitializer;
+
+
+
+
+
+/** Converts biomes in an array into the chunk image data. */
+static void biomesToImage(const cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image)
+{
+ // Make sure the two arrays are of the same size, compile-time.
+ // Note that a_Image is actually 4 items per pixel, so the array is 4 times bigger:
+ static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1] = {};
+ static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1] = {};
+
+ // Convert the biomes into color:
+ for (size_t i = 0; i < ARRAYCOUNT(a_Biomes); i++)
+ {
+ a_Image[4 * i + 0] = biomeToColor[4 * a_Biomes[i] + 0];
+ a_Image[4 * i + 1] = biomeToColor[4 * a_Biomes[i] + 1];
+ a_Image[4 * i + 2] = biomeToColor[4 * a_Biomes[i] + 2];
+ a_Image[4 * i + 3] = biomeToColor[4 * a_Biomes[i] + 3];
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Chunk:
+
Chunk::Chunk() :
m_IsValid(false)
{
@@ -24,12 +156,35 @@ const uchar * Chunk::getImage(void) const
-void Chunk::setImage(const Image & a_Image)
+void Chunk::setBiomes(const cChunkDef::BiomeMap & a_Biomes)
{
- memcpy(m_Image, a_Image, sizeof(a_Image));
+ memcpy(m_Biomes, a_Biomes, sizeof(m_Biomes));
+ renderBiomes();
m_IsValid = true;
}
+
+EMCSBiome Chunk::getBiome(int a_RelX, int a_RelZ)
+{
+ if (!m_IsValid)
+ {
+ return biInvalidBiome;
+ }
+ return cChunkDef::GetBiome(m_Biomes, a_RelX, a_RelZ);
+}
+
+
+
+
+
+void Chunk::renderBiomes()
+{
+ biomesToImage(m_Biomes, m_Image);
+}
+
+
+
+
diff --git a/Tools/QtBiomeVisualiser/QtChunk.h b/Tools/QtBiomeVisualiser/QtChunk.h
index 03e7bd1b3..74321577a 100644
--- a/Tools/QtBiomeVisualiser/QtChunk.h
+++ b/Tools/QtBiomeVisualiser/QtChunk.h
@@ -21,8 +21,12 @@ public:
/** Returns the image of the chunk's biomes. Assumes that the chunk is valid. */
const uchar * getImage(void) const;
- /** Sets the image data for this chunk. */
- void setImage(const Image & a_Image);
+ /** Sets the biomes to m_Biomes and renders them into m_Image. */
+ void setBiomes(const cChunkDef::BiomeMap & a_Biomes);
+
+ /** Returns the biome at the specified relative coords, or biInvalidBiome if not valid.
+ Coords must be valid inside this chunk. */
+ EMCSBiome getBiome(int a_RelX, int a_RelZ);
protected:
/** Flag that specifies if the chunk data is valid - loaded or generated. */
@@ -30,6 +34,13 @@ protected:
/** Cached rendered image of this chunk's biomes. Updated in render(). */
Image m_Image;
+
+ /** Biomes comprising the chunk, in the X + 16 * Z ordering. */
+ cChunkDef::BiomeMap m_Biomes;
+
+
+ /** Renders biomes from m_Biomes into m_Image. */
+ void renderBiomes();
};
typedef std::shared_ptr<Chunk> ChunkPtr;
diff --git a/easyinstall.sh b/easyinstall.sh
new file mode 100755
index 000000000..77ffb2290
--- /dev/null
+++ b/easyinstall.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+PLATFORM=$(uname -m)
+
+echo "Identifying platform: $PLATFORM"
+case $PLATFORM in
+ "i686") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20x86/lastSuccessfulBuild/artifact/MCServer.tar" ;;
+ "x86_64") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20x64/lastSuccessfulBuild/artifact/MCServer.tar" ;;
+ # Assume that all arm devices are a raspi for now.
+ "arm*") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20armhf/lastSuccessfulBuild/artifact/MCServer.tar"
+esac
+
+echo "Downloading precompiled binaries."
+curl -s $DOWNLOADURL | tar -xzf -
+echo "Done."
+
+echo "MCServer is now installed, run using 'cd MCServer; ./MCServer'."
diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg
index 37e6aecd2..73de98e22 100644
--- a/src/Bindings/AllToLua.pkg
+++ b/src/Bindings/AllToLua.pkg
@@ -27,6 +27,7 @@ $cfile "WebPlugin.h"
$cfile "LuaWindow.h"
$cfile "../BlockID.h"
+$cfile "../Mobs/MonsterTypes.h"
$cfile "../BlockInfo.h"
$cfile "../StringUtils.h"
$cfile "../Defines.h"
diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp
index a3d3a8090..23da12f68 100644
--- a/src/Bindings/LuaChunkStay.cpp
+++ b/src/Bindings/LuaChunkStay.cpp
@@ -130,8 +130,11 @@ void cLuaChunkStay::Enable(cChunkMap & a_ChunkMap, int a_OnChunkAvailableStackPo
void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ)
{
- cPluginLua::cOperation Op(m_Plugin);
- Op().Call((int)m_OnChunkAvailable, a_ChunkX, a_ChunkZ);
+ if (m_OnChunkAvailable.IsValid())
+ {
+ cPluginLua::cOperation Op(m_Plugin);
+ Op().Call((int)m_OnChunkAvailable, a_ChunkX, a_ChunkZ);
+ }
}
@@ -140,6 +143,7 @@ void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ)
bool cLuaChunkStay::OnAllChunksAvailable(void)
{
+ if (m_OnAllChunksAvailable.IsValid())
{
// Call the callback:
cPluginLua::cOperation Op(m_Plugin);
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index ba2f3c5e0..85e3f9fc5 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -861,6 +861,11 @@ void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
{
+ if (lua_isnil(m_LuaState, a_StackPos))
+ {
+ a_ReturnedVal = NULL;
+ return;
+ }
tolua_Error err;
if (tolua_isusertype(m_LuaState, a_StackPos, "cBoundingBox", false, &err))
{
@@ -874,6 +879,11 @@ void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
{
+ if (lua_isnil(m_LuaState, a_StackPos))
+ {
+ a_ReturnedVal = NULL;
+ return;
+ }
tolua_Error err;
if (tolua_isusertype(m_LuaState, a_StackPos, "cWorld", false, &err))
{
@@ -1396,10 +1406,8 @@ void cLuaState::LogStack(const char * a_Header)
void cLuaState::LogStack(lua_State * a_LuaState, const char * a_Header)
{
- UNUSED(a_Header); // The param seems unused when compiling for release, so the compiler warns
-
// Format string consisting only of %s is used to appease the compiler
- LOGD("%s", (a_Header != NULL) ? a_Header : "Lua C API Stack contents:");
+ LOG("%s", (a_Header != NULL) ? a_Header : "Lua C API Stack contents:");
for (int i = lua_gettop(a_LuaState); i > 0; i--)
{
AString Value;
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 094a200e0..779760017 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -240,10 +240,24 @@ public:
/** Retrieve value at a_StackPos, if it is a valid cWorld class. If not, a_Value is unchanged */
void GetStackValue(int a_StackPos, pWorld & a_Value);
+ /** Call the specified Lua function.
+ Returns true if call succeeded, false if there was an error.
+ A special param of cRet & signifies the end of param list and the start of return values.
+ Example call: Call(Fn, Param1, Param2, Param3, cLuaState::Return, Ret1, Ret2) */
+ template <typename FnT, typename... Args>
+ bool Call(const FnT & a_Function, Args &&... args)
+ {
+ PushFunction(a_Function);
+ return PushCallPop(args...);
+ }
- // Include the cLuaState::Call() overload implementation that is generated by the gen_LuaState_Call.lua script:
- #include "LuaState_Call.inc"
-
+ /** Retrieves a list of values from the Lua stack, starting at the specified index. */
+ template <typename T, typename... Args>
+ inline void GetStackValues(int a_StartStackPos, T & a_Ret, Args &&... args)
+ {
+ GetStackValue(a_StartStackPos, a_Ret);
+ GetStackValues(a_StartStackPos + 1, args...);
+ }
/** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */
bool CheckParamUserTable(int a_StartParam, const char * a_UserTable, int a_EndParam = -1);
@@ -304,12 +318,13 @@ public:
void ToString(int a_StackPos, AString & a_String);
/** Logs all the elements' types on the API stack, with an optional header for the listing. */
- void LogStack(const char * a_Header);
+ void LogStack(const char * a_Header = NULL);
/** Logs all the elements' types on the API stack, with an optional header for the listing. */
static void LogStack(lua_State * a_LuaState, const char * a_Header = NULL);
protected:
+
lua_State * m_LuaState;
/** If true, the state is owned by this object and will be auto-Closed. False => attached state */
@@ -327,6 +342,63 @@ protected:
int m_NumCurrentFunctionArgs;
+ /** Variadic template terminator: Counting zero args returns zero. */
+ int CountArgs(void)
+ {
+ return 0;
+ }
+
+ /** Variadic template: Counting args means add one to the count of the rest. */
+ template <typename T, typename... Args>
+ int CountArgs(T, Args... args)
+ {
+ return 1 + CountArgs(args...);
+ }
+
+ /** Variadic template terminator: If there's nothing more to push / pop, just call the function.
+ Note that there are no return values either, because those are prefixed by a cRet value, so the arg list is never empty. */
+ bool PushCallPop(void)
+ {
+ return CallFunction(0);
+ }
+
+ /** Variadic template recursor: More params to push. Push them and recurse. */
+ template<typename T, typename... Args>
+ inline bool PushCallPop(T a_Param, Args &&... args)
+ {
+ Push(a_Param);
+ return PushCallPop(args...);
+ }
+
+ /** Variadic template terminator: If there's nothing more to push, but return values to collect, call the function and collect the returns. */
+ template <typename... Args>
+ bool PushCallPop(cLuaState::cRet, Args &&... args)
+ {
+ // Calculate the number of return values (number of args left):
+ int NumReturns = CountArgs(args...);
+
+ // Call the function:
+ if (!CallFunction(NumReturns))
+ {
+ return false;
+ }
+
+ // Collect the return values:
+ GetStackValues(-NumReturns, args...);
+ lua_pop(m_LuaState, NumReturns);
+
+ // All successful:
+ return true;
+ }
+
+ /** Variadic template terminator: If there are no more values to get, bail out.
+ This function is not available in the public API, because it's an error to request no values directly; only internal functions can do that.
+ If you get a compile error saying this function is not accessible, check your calling code, you aren't reading any stack values. */
+ void GetStackValues(int a_StartingStackPos)
+ {
+ // Do nothing
+ }
+
/** Pushes the function of the specified name onto the stack.
Returns true if successful. Logs a warning on failure (incl. m_SubsystemName)
*/
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index f4764447c..0558533ce 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -697,8 +697,12 @@ static int tolua_ForEachInBox(lua_State * tolua_S)
Ty1 * Self = NULL;
cBoundingBox * Box = NULL;
L.GetStackValues(1, Self, Box);
- ASSERT(Self != NULL); // We have verified the type at the top, so we should get valid objects here
- ASSERT(Box != NULL);
+ if ((Self == NULL) || (Box == NULL))
+ {
+ LOGWARNING("Invalid world (%p) or boundingbox (%p)", Self, Box);
+ L.LogStackTrace();
+ return 0;
+ }
// Create a reference for the function:
cLuaState::cRef FnRef(L, 3);
@@ -1156,7 +1160,7 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
- self->QueueTask(new cLuaWorldTask(*Plugin, FnRef));
+ self->QueueTask(make_unique<cLuaWorldTask>(*Plugin, FnRef));
return 0;
}
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index fb22dd33e..8cc9ff0cd 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -45,26 +45,26 @@ public:
virtual void Tick(float a_Dt) = 0;
/** Calls the specified hook with the params given. Returns the bool that the hook callback returns.*/
- virtual bool OnBlockSpread (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0;
- virtual bool OnBlockToPickups (cWorld * a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) = 0;
- virtual bool OnChat (cPlayer * a_Player, AString & a_Message) = 0;
- virtual bool OnChunkAvailable (cWorld * a_World, int a_ChunkX, int a_ChunkZ) = 0;
- virtual bool OnChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) = 0;
- virtual bool OnChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) = 0;
- virtual bool OnChunkUnloaded (cWorld * a_World, int a_ChunkX, int a_ChunkZ) = 0;
- virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) = 0;
- virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) = 0;
- virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
+ virtual bool OnBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0;
+ virtual bool OnBlockToPickups (cWorld & a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) = 0;
+ virtual bool OnChat (cPlayer & a_Player, AString & a_Message) = 0;
+ virtual bool OnChunkAvailable (cWorld & a_World, int a_ChunkX, int a_ChunkZ) = 0;
+ virtual bool OnChunkGenerated (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) = 0;
+ virtual bool OnChunkGenerating (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) = 0;
+ virtual bool OnChunkUnloaded (cWorld & a_World, int a_ChunkX, int a_ChunkZ) = 0;
+ virtual bool OnChunkUnloading (cWorld & a_World, int a_ChunkX, int a_ChunkZ) = 0;
+ virtual bool OnCollectingPickup (cPlayer & a_Player, cPickup & a_Pickup) = 0;
+ virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) = 0;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
- virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) = 0;
+ virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) = 0;
virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) = 0;
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0;
virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) = 0;
- virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) = 0;
+ virtual bool OnLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username) = 0;
virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) = 0;
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
@@ -89,8 +89,8 @@ public:
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
virtual bool OnPluginMessage (cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message) = 0;
virtual bool OnPluginsLoaded (void) = 0;
- virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
- virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
+ virtual bool OnPostCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) = 0;
+ virtual bool OnPreCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) = 0;
virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) = 0;
virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) = 0;
virtual bool OnServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) = 0;
@@ -99,8 +99,8 @@ public:
virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) = 0;
virtual bool OnSpawningMonster (cWorld & a_World, cMonster & a_Monster) = 0;
virtual bool OnTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) = 0;
- virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) = 0;
- virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) = 0;
+ virtual bool OnUpdatedSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) = 0;
+ virtual bool OnUpdatingSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) = 0;
virtual bool OnWeatherChanged (cWorld & a_World) = 0;
virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) = 0;
virtual bool OnWorldStarted (cWorld & a_World) = 0;
@@ -110,7 +110,7 @@ public:
Command permissions have already been checked.
Returns true if command handled successfully
*/
- virtual bool HandleCommand(const AStringVector & a_Split, cPlayer * a_Player) = 0;
+ virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player) = 0;
/** Handles the console command split into a_Split.
Returns true if command handled successfully. Output is to be sent to the a_Output callback.
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index 2629eb641..eec31e8a6 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -202,14 +202,14 @@ void cPluginLua::Tick(float a_Dt)
-bool cPluginLua::OnBlockSpread(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
+bool cPluginLua::OnBlockSpread(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_BLOCK_SPREAD];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Source, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_BlockX, a_BlockY, a_BlockZ, a_Source, cLuaState::Return, res);
if (res)
{
return true;
@@ -222,14 +222,14 @@ bool cPluginLua::OnBlockSpread(cWorld * a_World, int a_BlockX, int a_BlockY, int
-bool cPluginLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups)
+bool cPluginLua::OnBlockToPickups(cWorld & a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_BLOCK_TO_PICKUPS];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, &a_Pickups, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, &a_Pickups, cLuaState::Return, res);
if (res)
{
return true;
@@ -242,14 +242,14 @@ bool cPluginLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int a_Bl
-bool cPluginLua::OnChat(cPlayer * a_Player, AString & a_Message)
+bool cPluginLua::OnChat(cPlayer & a_Player, AString & a_Message)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHAT];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Player, a_Message, cLuaState::Return, res, a_Message);
+ m_LuaState.Call((int)(**itr), &a_Player, a_Message, cLuaState::Return, res, a_Message);
if (res)
{
return true;
@@ -262,14 +262,14 @@ bool cPluginLua::OnChat(cPlayer * a_Player, AString & a_Message)
-bool cPluginLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
+bool cPluginLua::OnChunkAvailable(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_AVAILABLE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
if (res)
{
return true;
@@ -282,14 +282,14 @@ bool cPluginLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
-bool cPluginLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
+bool cPluginLua::OnChunkGenerated(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_GENERATED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
if (res)
{
return true;
@@ -302,14 +302,14 @@ bool cPluginLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ,
-bool cPluginLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
+bool cPluginLua::OnChunkGenerating(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_GENERATING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
if (res)
{
return true;
@@ -322,14 +322,14 @@ bool cPluginLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ,
-bool cPluginLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
+bool cPluginLua::OnChunkUnloaded(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_UNLOADED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
if (res)
{
return true;
@@ -342,14 +342,14 @@ bool cPluginLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
-bool cPluginLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
+bool cPluginLua::OnChunkUnloading(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_UNLOADING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
if (res)
{
return true;
@@ -362,14 +362,14 @@ bool cPluginLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
-bool cPluginLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup)
+bool cPluginLua::OnCollectingPickup(cPlayer & a_Player, cPickup & a_Pickup)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_COLLECTING_PICKUP];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Player, a_Pickup, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, &a_Pickup, cLuaState::Return, res);
if (res)
{
return true;
@@ -382,14 +382,14 @@ bool cPluginLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup)
-bool cPluginLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
+bool cPluginLua::OnCraftingNoRecipe(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe * a_Recipe)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CRAFTING_NO_RECIPE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), (cPlayer *)a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, &a_Grid, &a_Recipe, cLuaState::Return, res);
if (res)
{
return true;
@@ -471,12 +471,12 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can
{
switch (a_Source)
{
- case esOther: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
- case esPrimedTNT: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cTNTEntity *)a_SourceData, cLuaState::Return, res); break;
- case esMonster: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cMonster *)a_SourceData, cLuaState::Return, res); break;
- case esBed: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
- case esEnderCrystal: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
- case esGhastFireball: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ case esOther: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ case esPrimedTNT: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cTNTEntity *)a_SourceData, cLuaState::Return, res); break;
+ case esMonster: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cMonster *)a_SourceData, cLuaState::Return, res); break;
+ case esBed: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
+ case esEnderCrystal: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
+ case esGhastFireball: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
case esWitherSkullBlack:
case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
@@ -536,14 +536,14 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool &
-bool cPluginLua::OnHandshake(cClientHandle * a_Client, const AString & a_Username)
+bool cPluginLua::OnHandshake(cClientHandle & a_Client, const AString & a_Username)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HANDSHAKE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Client, a_Username, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Client, a_Username, cLuaState::Return, res);
if (res)
{
return true;
@@ -617,14 +617,14 @@ bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInf
-bool cPluginLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username)
+bool cPluginLua::OnLogin(cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_LOGIN];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Client, a_ProtocolVersion, a_Username, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Client, a_ProtocolVersion, a_Username, cLuaState::Return, res);
if (res)
{
return true;
@@ -784,7 +784,7 @@ bool cPluginLua::OnPlayerFishing(cPlayer & a_Player, cItems & a_Reward)
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FISHING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), &a_Player, a_Reward, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, &a_Reward, cLuaState::Return, res);
if (res)
{
return true;
@@ -1115,14 +1115,14 @@ bool cPluginLua::OnPluginsLoaded(void)
-bool cPluginLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
+bool cPluginLua::OnPostCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_POST_CRAFTING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, &a_Grid, &a_Recipe, cLuaState::Return, res);
if (res)
{
return true;
@@ -1135,14 +1135,14 @@ bool cPluginLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGrid *
-bool cPluginLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
+bool cPluginLua::OnPreCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PRE_CRAFTING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, &a_Grid, &a_Recipe, cLuaState::Return, res);
if (res)
{
return true;
@@ -1316,7 +1316,7 @@ bool cPluginLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
bool cPluginLua::OnUpdatedSign(
- cWorld * a_World,
+ cWorld & a_World,
int a_BlockX, int a_BlockY, int a_BlockZ,
const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4,
cPlayer * a_Player
@@ -1327,7 +1327,7 @@ bool cPluginLua::OnUpdatedSign(
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_UPDATED_SIGN];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res);
if (res)
{
return true;
@@ -1341,7 +1341,7 @@ bool cPluginLua::OnUpdatedSign(
bool cPluginLua::OnUpdatingSign(
- cWorld * a_World,
+ cWorld & a_World,
int a_BlockX, int a_BlockY, int a_BlockZ,
AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4,
cPlayer * a_Player
@@ -1352,7 +1352,7 @@ bool cPluginLua::OnUpdatingSign(
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_UPDATING_SIGN];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res, a_Line1, a_Line2, a_Line3, a_Line4);
+ m_LuaState.Call((int)(**itr), &a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res, a_Line1, a_Line2, a_Line3, a_Line4);
if (res)
{
return true;
@@ -1435,7 +1435,7 @@ bool cPluginLua::OnWorldTick(cWorld & a_World, float a_Dt, int a_LastTickDuratio
-bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Player)
+bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer & a_Player)
{
ASSERT(!a_Split.empty());
CommandMap::iterator cmd = m_Commands.find(a_Split[0]);
@@ -1447,7 +1447,7 @@ bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Player
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(cmd->second, a_Split, a_Player, cLuaState::Return, res);
+ m_LuaState.Call(cmd->second, a_Split, &a_Player, cLuaState::Return, res);
return res;
}
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index eda65b76c..6bb134efc 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -69,26 +69,26 @@ public:
virtual void Tick(float a_Dt) override;
- virtual bool OnBlockSpread (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) override;
- virtual bool OnBlockToPickups (cWorld * a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) override;
- virtual bool OnChat (cPlayer * a_Player, AString & a_Message) override;
- virtual bool OnChunkAvailable (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override;
- virtual bool OnChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) override;
- virtual bool OnChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) override;
- virtual bool OnChunkUnloaded (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override;
- virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override;
- virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override;
- virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
+ virtual bool OnBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) override;
+ virtual bool OnBlockToPickups (cWorld & a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) override;
+ virtual bool OnChat (cPlayer & a_Player, AString & a_Message) override;
+ virtual bool OnChunkAvailable (cWorld & a_World, int a_ChunkX, int a_ChunkZ) override;
+ virtual bool OnChunkGenerated (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) override;
+ virtual bool OnChunkGenerating (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) override;
+ virtual bool OnChunkUnloaded (cWorld & a_World, int a_ChunkX, int a_ChunkZ) override;
+ virtual bool OnChunkUnloading (cWorld & a_World, int a_ChunkX, int a_ChunkZ) override;
+ virtual bool OnCollectingPickup (cPlayer & a_Player, cPickup & a_Pickup) override;
+ virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) override;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
- virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override;
+ virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) override;
virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) override;
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override;
virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) override;
- virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override;
+ virtual bool OnLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username) override;
virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) override;
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
@@ -113,8 +113,8 @@ public:
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool OnPluginMessage (cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message) override;
virtual bool OnPluginsLoaded (void) override;
- virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
- virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
+ virtual bool OnPostCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override;
+ virtual bool OnPreCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override;
virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) override;
virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) override;
virtual bool OnServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) override;
@@ -123,14 +123,14 @@ public:
virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) override;
virtual bool OnSpawningMonster (cWorld & a_World, cMonster & a_Monster) override;
virtual bool OnTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) override;
- virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override;
- virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override;
+ virtual bool OnUpdatedSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override;
+ virtual bool OnUpdatingSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnWeatherChanged (cWorld & a_World) override;
virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) override;
virtual bool OnWorldStarted (cWorld & a_World) override;
virtual bool OnWorldTick (cWorld & a_World, float a_Dt, int a_LastTickDurationMSec) override;
- virtual bool HandleCommand(const AStringVector & a_Split, cPlayer * a_Player) override;
+ virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player) override;
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) override;
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index e0faa838a..43507a5fb 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -225,7 +225,7 @@ void cPluginManager::Tick(float a_Dt)
-bool cPluginManager::CallHookBlockSpread(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
+bool cPluginManager::CallHookBlockSpread(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
{
FIND_HOOK(HOOK_BLOCK_SPREAD);
VERIFY_HOOK;
@@ -245,7 +245,7 @@ bool cPluginManager::CallHookBlockSpread(cWorld * a_World, int a_BlockX, int a_B
bool cPluginManager::CallHookBlockToPickups(
- cWorld * a_World, cEntity * a_Digger,
+ cWorld & a_World, cEntity * a_Digger,
int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
cItems & a_Pickups
)
@@ -267,7 +267,7 @@ bool cPluginManager::CallHookBlockToPickups(
-bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
+bool cPluginManager::CallHookChat(cPlayer & a_Player, AString & a_Message)
{
// Check if the message contains a command, execute it:
switch (HandleCommand(a_Player, a_Message, true))
@@ -288,14 +288,14 @@ bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
case crError:
{
// An error in the plugin has prevented the command from executing. Report the error to the player:
- a_Player->SendMessageFailure(Printf("Something went wrong while executing command \"%s\"", a_Message.c_str()));
+ a_Player.SendMessageFailure(Printf("Something went wrong while executing command \"%s\"", a_Message.c_str()));
return true;
}
case crNoPermission:
{
// The player is not allowed to execute this command
- a_Player->SendMessageFailure(Printf("Forbidden command; insufficient privileges: \"%s\"", a_Message.c_str()));
+ a_Player.SendMessageFailure(Printf("Forbidden command; insufficient privileges: \"%s\"", a_Message.c_str()));
return true;
}
@@ -311,8 +311,8 @@ bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
{
AStringVector Split(StringSplit(a_Message, " "));
ASSERT(!Split.empty()); // This should not happen - we know there's at least one char in the message so the split needs to be at least one item long
- a_Player->SendMessageInfo(Printf("Unknown command: \"%s\"", a_Message.c_str()));
- LOGINFO("Player %s issued an unknown command: \"%s\"", a_Player->GetName().c_str(), a_Message.c_str());
+ a_Player.SendMessageInfo(Printf("Unknown command: \"%s\"", a_Message.c_str()));
+ LOGINFO("Player %s issued an unknown command: \"%s\"", a_Player.GetName().c_str(), a_Message.c_str());
return true; // Cancel sending
}
@@ -334,7 +334,7 @@ bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
-bool cPluginManager::CallHookChunkAvailable(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
+bool cPluginManager::CallHookChunkAvailable(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
FIND_HOOK(HOOK_CHUNK_AVAILABLE);
VERIFY_HOOK;
@@ -353,7 +353,7 @@ bool cPluginManager::CallHookChunkAvailable(cWorld * a_World, int a_ChunkX, int
-bool cPluginManager::CallHookChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
+bool cPluginManager::CallHookChunkGenerated(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
FIND_HOOK(HOOK_CHUNK_GENERATED);
VERIFY_HOOK;
@@ -372,7 +372,7 @@ bool cPluginManager::CallHookChunkGenerated(cWorld * a_World, int a_ChunkX, int
-bool cPluginManager::CallHookChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
+bool cPluginManager::CallHookChunkGenerating(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
FIND_HOOK(HOOK_CHUNK_GENERATING);
VERIFY_HOOK;
@@ -391,7 +391,7 @@ bool cPluginManager::CallHookChunkGenerating(cWorld * a_World, int a_ChunkX, int
-bool cPluginManager::CallHookChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
+bool cPluginManager::CallHookChunkUnloaded(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
FIND_HOOK(HOOK_CHUNK_UNLOADED);
VERIFY_HOOK;
@@ -410,7 +410,7 @@ bool cPluginManager::CallHookChunkUnloaded(cWorld * a_World, int a_ChunkX, int a
-bool cPluginManager::CallHookChunkUnloading(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
+bool cPluginManager::CallHookChunkUnloading(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
FIND_HOOK(HOOK_CHUNK_UNLOADING);
VERIFY_HOOK;
@@ -429,14 +429,14 @@ bool cPluginManager::CallHookChunkUnloading(cWorld * a_World, int a_ChunkX, int
-bool cPluginManager::CallHookCollectingPickup(cPlayer * a_Player, cPickup & a_Pickup)
+bool cPluginManager::CallHookCollectingPickup(cPlayer & a_Player, cPickup & a_Pickup)
{
FIND_HOOK(HOOK_COLLECTING_PICKUP);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
- if ((*itr)->OnCollectingPickup(a_Player, &a_Pickup))
+ if ((*itr)->OnCollectingPickup(a_Player, a_Pickup))
{
return true;
}
@@ -448,7 +448,7 @@ bool cPluginManager::CallHookCollectingPickup(cPlayer * a_Player, cPickup & a_Pi
-bool cPluginManager::CallHookCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
+bool cPluginManager::CallHookCraftingNoRecipe(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe * a_Recipe)
{
FIND_HOOK(HOOK_CRAFTING_NO_RECIPE);
VERIFY_HOOK;
@@ -562,7 +562,7 @@ bool cPluginManager::CallHookExploding(cWorld & a_World, double & a_ExplosionSiz
-bool cPluginManager::CallHookHandshake(cClientHandle * a_ClientHandle, const AString & a_Username)
+bool cPluginManager::CallHookHandshake(cClientHandle & a_ClientHandle, const AString & a_Username)
{
FIND_HOOK(HOOK_HANDSHAKE);
VERIFY_HOOK;
@@ -638,7 +638,7 @@ bool cPluginManager::CallHookKilling(cEntity & a_Victim, cEntity * a_Killer, Tak
-bool cPluginManager::CallHookLogin(cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username)
+bool cPluginManager::CallHookLogin(cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username)
{
FIND_HOOK(HOOK_LOGIN);
VERIFY_HOOK;
@@ -1111,7 +1111,7 @@ bool cPluginManager::CallHookPluginsLoaded(void)
-bool cPluginManager::CallHookPostCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
+bool cPluginManager::CallHookPostCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
FIND_HOOK(HOOK_POST_CRAFTING);
VERIFY_HOOK;
@@ -1130,7 +1130,7 @@ bool cPluginManager::CallHookPostCrafting(const cPlayer * a_Player, const cCraft
-bool cPluginManager::CallHookPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
+bool cPluginManager::CallHookPreCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
FIND_HOOK(HOOK_PRE_CRAFTING);
VERIFY_HOOK;
@@ -1299,7 +1299,7 @@ bool cPluginManager::CallHookTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a
-bool cPluginManager::CallHookUpdatingSign(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player)
+bool cPluginManager::CallHookUpdatingSign(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player)
{
FIND_HOOK(HOOK_UPDATING_SIGN);
VERIFY_HOOK;
@@ -1318,7 +1318,7 @@ bool cPluginManager::CallHookUpdatingSign(cWorld * a_World, int a_BlockX, int a_
-bool cPluginManager::CallHookUpdatedSign(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player)
+bool cPluginManager::CallHookUpdatedSign(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player)
{
FIND_HOOK(HOOK_UPDATED_SIGN);
VERIFY_HOOK;
@@ -1413,10 +1413,8 @@ bool cPluginManager::CallHookWorldTick(cWorld & a_World, float a_Dt, int a_LastT
-cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
+cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
{
- ASSERT(a_Player != NULL);
-
AStringVector Split(StringSplit(a_Command, " "));
if (Split.empty())
{
@@ -1431,19 +1429,19 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer * a_Player,
}
// Ask plugins first if a command is okay to execute the command:
- if (CallHookExecuteCommand(a_Player, Split))
+ if (CallHookExecuteCommand(&a_Player, Split))
{
- LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player->GetName().c_str(), Split[0].c_str());
+ LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player.GetName().c_str(), Split[0].c_str());
return crBlocked;
}
if (
a_ShouldCheckPermissions &&
!cmd->second.m_Permission.empty() &&
- !a_Player->HasPermission(cmd->second.m_Permission)
+ !a_Player.HasPermission(cmd->second.m_Permission)
)
{
- LOGINFO("Player %s tried to execute forbidden command: \"%s\"", a_Player->GetName().c_str(), Split[0].c_str());
+ LOGINFO("Player %s tried to execute forbidden command: \"%s\"", a_Player.GetName().c_str(), Split[0].c_str());
return crNoPermission;
}
@@ -1652,7 +1650,7 @@ AString cPluginManager::GetCommandPermission(const AString & a_Command)
-cPluginManager::CommandResult cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Command)
+cPluginManager::CommandResult cPluginManager::ExecuteCommand(cPlayer & a_Player, const AString & a_Command)
{
return HandleCommand(a_Player, a_Command, true);
}
@@ -1661,7 +1659,7 @@ cPluginManager::CommandResult cPluginManager::ExecuteCommand(cPlayer * a_Player,
-cPluginManager::CommandResult cPluginManager::ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command)
+cPluginManager::CommandResult cPluginManager::ForceExecuteCommand(cPlayer & a_Player, const AString & a_Command)
{
return HandleCommand(a_Player, a_Command, false);
}
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index fff3bc323..c69850be6 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -178,26 +178,26 @@ public:
size_t GetNumPlugins() const; // tolua_export
// Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
- bool CallHookBlockSpread (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
- bool CallHookBlockToPickups (cWorld * a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups);
- bool CallHookChat (cPlayer * a_Player, AString & a_Message);
- bool CallHookChunkAvailable (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
- bool CallHookChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc);
- bool CallHookChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc);
- bool CallHookChunkUnloaded (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
- bool CallHookChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
- bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup);
- bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
+ bool CallHookBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
+ bool CallHookBlockToPickups (cWorld & a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups);
+ bool CallHookChat (cPlayer & a_Player, AString & a_Message);
+ bool CallHookChunkAvailable (cWorld & a_World, int a_ChunkX, int a_ChunkZ);
+ bool CallHookChunkGenerated (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc);
+ bool CallHookChunkGenerating (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc);
+ bool CallHookChunkUnloaded (cWorld & a_World, int a_ChunkX, int a_ChunkZ);
+ bool CallHookChunkUnloading (cWorld & a_World, int a_ChunkX, int a_ChunkZ);
+ bool CallHookCollectingPickup (cPlayer & a_Player, cPickup & a_Pickup);
+ bool CallHookCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier);
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == NULL, it is a console cmd
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
- bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username);
+ bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username);
bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum);
bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum);
bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI);
- bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);
+ bool CallHookLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username);
bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation);
bool CallHookPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
@@ -222,8 +222,8 @@ public:
bool CallHookPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
bool CallHookPluginMessage (cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message);
bool CallHookPluginsLoaded (void);
- bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
- bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
+ bool CallHookPostCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe);
+ bool CallHookPreCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe);
bool CallHookProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos);
bool CallHookProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity);
bool CallHookServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon);
@@ -232,8 +232,8 @@ public:
bool CallHookSpawningEntity (cWorld & a_World, cEntity & a_Entity);
bool CallHookSpawningMonster (cWorld & a_World, cMonster & a_Monster);
bool CallHookTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TDI);
- bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
- bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
+ bool CallHookUpdatedSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
+ bool CallHookUpdatingSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
bool CallHookWeatherChanged (cWorld & a_World);
bool CallHookWeatherChanging (cWorld & a_World, eWeather & a_NewWeather);
bool CallHookWorldStarted (cWorld & a_World);
@@ -264,10 +264,10 @@ public:
AString GetCommandPermission(const AString & a_Command); // tolua_export
/** Executes the command, as if it was requested by a_Player. Checks permissions first. Returns crExecuted if executed. */
- CommandResult ExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
+ CommandResult ExecuteCommand(cPlayer & a_Player, const AString & a_Command); // tolua_export
/** Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns crExecuted if executed. */
- CommandResult ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
+ CommandResult ForceExecuteCommand(cPlayer & a_Player, const AString & a_Command); // tolua_export
/** Removes all console command bindings that the specified plugin has made */
void RemovePluginConsoleCommands(cPlugin * a_Plugin);
@@ -341,7 +341,7 @@ private:
bool AddPlugin(cPlugin * a_Plugin);
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
- cPluginManager::CommandResult HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
+ CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
} ; // tolua_export
diff --git a/src/BlockID.cpp b/src/BlockID.cpp
index 9026d81f2..755c721db 100644
--- a/src/BlockID.cpp
+++ b/src/BlockID.cpp
@@ -253,57 +253,6 @@ AString ItemToFullString(const cItem & a_Item)
-int StringToMobType(const AString & a_MobString)
-{
- static struct
- {
- int m_MobType;
- const char * m_String;
- } MobMap [] =
- {
- {mtCreeper, "Creeper"},
- {mtSkeleton, "Skeleton"},
- {mtSpider, "Spider"},
- {mtGiant, "Giant"},
- {mtZombie, "Zombie"},
- {mtSlime, "Slime"},
- {mtGhast, "Ghast"},
- {mtZombiePigman, "ZombiePigman"},
- {mtEnderman, "Enderman"},
- {mtCaveSpider, "CaveSpider"},
- {mtSilverfish, "SilverFish"},
- {mtBlaze, "Blaze"},
- {mtMagmaCube, "MagmaCube"},
- {mtEnderDragon, "EnderDragon"},
- {mtWither, "Wither"},
- {mtBat, "Bat"},
- {mtWitch, "Witch"},
- {mtPig, "Pig"},
- {mtSheep, "Sheep"},
- {mtCow, "Cow"},
- {mtChicken, "Chicken"},
- {mtSquid, "Squid"},
- {mtWolf, "Wolf"},
- {mtMooshroom, "Mooshroom"},
- {mtSnowGolem, "SnowGolem"},
- {mtOcelot, "Ocelot"},
- {mtIronGolem, "IronGolem"},
- {mtVillager, "Villager"},
- };
- for (size_t i = 0; i < ARRAYCOUNT(MobMap); i++)
- {
- if (NoCaseCompare(MobMap[i].m_String, a_MobString) == 0)
- {
- return MobMap[i].m_MobType;
- }
- } // for i - MobMap[]
- return -1;
-}
-
-
-
-
-
eDimension StringToDimension(const AString & a_DimensionString)
{
// First try decoding as a number
diff --git a/src/BlockID.h b/src/BlockID.h
index 69b5e2fe0..bb06722d2 100644
--- a/src/BlockID.h
+++ b/src/BlockID.h
@@ -445,6 +445,21 @@ enum
////////////////////////////////////////////////////////////////////////////////
// Block metas:
+ // E_BLOCK_ANVIL metas
+ E_BLOCK_ANVIL_Z = 0,
+ E_BLOCK_ANVIL_X = 1,
+ E_BLOCK_ANVIL_NO_DAMAGE = 0,
+ E_BLOCK_ANVIL_LOW_DAMAGE = 4,
+ E_BLOCK_ANVIL_HIGH_DAMAGE = 8,
+
+ // E_BLOCK_BED metas:
+ E_BLOCK_BED_ZP = 0,
+ E_BLOCK_BED_XM = 1,
+ E_BLOCK_BED_ZM = 2,
+ E_BLOCK_BED_XP = 3,
+ E_BLOCK_BED_OCCUPIED = 4,
+ E_BLOCK_BED_BED_HEAD = 8,
+
// E_BLOCK_BIG_FLOWER metas:
E_META_BIG_FLOWER_SUNFLOWER = 0,
E_META_BIG_FLOWER_LILAC = 1,
@@ -453,6 +468,20 @@ enum
E_META_BIG_FLOWER_ROSE_BUSH = 4,
E_META_BIG_FLOWER_PEONY = 5,
+ // E_BLOCK_BREWING_STAND metas
+ E_META_BREWING_STAND_FILLED_SLOT_XP = 1,
+ E_META_BREWING_STAND_FILLED_SLOT_XM_ZP = 2,
+ E_META_BREWING_STAND_FILLED_SLOT_XM_ZM = 4,
+
+ // E_BLOCK_BUTTON metas
+ E_BLOCK_BUTTON_YM = 0,
+ E_BLOCK_BUTTON_XP = 1,
+ E_BLOCK_BUTTON_XM = 2,
+ E_BLOCK_BUTTON_ZP = 3,
+ E_BLOCK_BUTTON_ZM = 4,
+ E_BLOCK_BUTTON_YP = 5,
+ E_BLOCK_BUTTON_PRESSED = 8,
+
// E_BLOCK_CARPET metas:
E_META_CARPET_WHITE = 0,
E_META_CARPET_ORANGE = 1,
@@ -492,14 +521,17 @@ enum
E_META_DROPSPENSER_FACING_XP = 5,
// E_BLOCK_DOUBLE_STONE_SLAB metas:
- E_META_DOUBLE_STONE_SLAB_STONE = 0,
- E_META_DOUBLE_STONE_SLAB_SANDSTONE = 1,
- E_META_DOUBLE_STONE_SLAB_WOODEN = 2,
- E_META_DOUBLE_STONE_SLAB_COBBLESTONE = 3,
- E_META_DOUBLE_STONE_SLAB_BRICK = 4,
- E_META_DOUBLE_STONE_SLAB_STONE_BRICK = 5,
- E_META_DOUBLE_STONE_SLAB_NETHER_BRICK = 6,
- E_META_DOUBLE_STONE_SLAB_STONE_SECRET = 7,
+ E_META_DOUBLE_STONE_SLAB_STONE = 0,
+ E_META_DOUBLE_STONE_SLAB_SANDSTON = 1,
+ E_META_DOUBLE_STONE_SLAB_WOODEN = 2,
+ E_META_DOUBLE_STONE_SLAB_COBBLESTONE = 3,
+ E_META_DOUBLE_STONE_SLAB_BRICK = 4,
+ E_META_DOUBLE_STONE_SLAB_STONE_BRICK = 5,
+ E_META_DOUBLE_STONE_SLAB_NETHER_BRICK = 6,
+ E_META_DOUBLE_STONE_SLAB_QUARTZ = 7,
+ E_META_DOUBLE_STONE_SLAB_SMOOTH_STONE = 8,
+ E_META_DOUBLE_STONE_SLAB_SMOOTH_SANDSTONE = 9,
+ E_META_DOUBLE_STONE_SLAB_TILE_QUARTZ = 10,
// E_BLOCK_FLOWER metas:
E_META_FLOWER_POPPY = 0,
@@ -512,8 +544,8 @@ enum
E_META_FLOWER_OXEYE_DAISY = 8,
// E_BLOCK_JUKEBOX metas:
- E_META_JUKEBOX_OFF = 0,
- E_META_JUKEBOX_ON = 1,
+ E_META_JUKEBOX_OFF = 0,
+ E_META_JUKEBOX_ON = 1,
// E_BLOCK_HOPPER metas:
E_META_HOPPER_FACING_YM = 0,
@@ -524,10 +556,26 @@ enum
E_META_HOPPER_FACING_XP = 5,
// E_BLOCK_LEAVES metas:
- E_META_LEAVES_APPLE = 0,
- E_META_LEAVES_CONIFER = 1,
- E_META_LEAVES_BIRCH = 2,
- E_META_LEAVES_JUNGLE = 3,
+ E_META_LEAVES_APPLE = 0,
+ E_META_LEAVES_CONIFER = 1,
+ E_META_LEAVES_BIRCH = 2,
+ E_META_LEAVES_JUNGLE = 3,
+ E_META_LEAVES_APPLE_NO_DECAY = 4,
+ E_META_LEAVES_CONIFER_NO_DECAY = 5,
+ E_META_LEAVES_BIRCH_NO_DECAY = 6,
+ E_META_LEAVES_JUNGLE_NO_DECAY = 7,
+ E_META_LEAVES_APPLE_CHECK_DECAY = 8,
+ E_META_LEAVES_CONIFER_CHECK_DECAY = 9,
+ E_META_LEAVES_BIRCH_CHECK_DECAY = 10,
+ E_META_LEAVES_JUNGLE_CHECK_DECAY = 11,
+
+ // E_BLOCK_LEAVES meta cont. (Block ID 161):
+ E_META_NEWLEAVES_ACACIA = 0,
+ E_META_NEWLEAVES_DARK_OAK = 1,
+ E_META_NEWLEAVES_ACACIA_NO_DECAY = 4,
+ E_META_NEWLEAVES_DARK_OAK_NO_DECAY = 5,
+ E_META_NEWLEAVES_ACACIA_CHECK_DECAY = 8,
+ E_META_NEWLEAVES_DARK_OAK_CHECK_DECAY = 9,
// E_BLOCK_LOG metas:
E_META_LOG_APPLE = 0,
@@ -540,9 +588,19 @@ enum
E_META_NEW_LEAVES_DARK_OAK_WOOD = 1,
// E_BLOCK_NEW_LOG metas:
- E_META_NEW_LOG_ACACIA_WOOD = 0,
- E_META_NEW_LOG_DARK_OAK_WOOD = 1,
+ E_META_NEW_LOG_ACACIA_WOOD = 0,
+ E_META_NEW_LOG_DARK_OAK_WOOD = 1,
+ // E_BLOCK_PISTON metas:
+ E_META_PISTON_DOWN = 0,
+ E_META_PISTON_U = 1,
+ E_META_PISTON_ZM = 2,
+ E_META_PISTON_ZP = 3,
+ E_META_PISTON_XM = 4,
+ E_META_PISTON_XP = 5,
+ E_META_PISTON_HEAD_STICKY = 8,
+ E_META_PISTON_EXTENDED = 8,
+
// E_BLOCK_PLANKS metas:
E_META_PLANKS_APPLE = 0,
E_META_PLANKS_CONIFER = 1,
@@ -552,7 +610,7 @@ enum
E_META_PLANKS_DARK_OAK = 5,
// E_BLOCK_(XXX_WEIGHTED)_PRESSURE_PLATE metas:
- E_META_PRESSURE_PLATE_RAISED = 0,
+ E_META_PRESSURE_PLATE_RAISED = 0,
E_META_PRESSURE_PLATE_DEPRESSED = 1,
// E_BLOCK_PRISMARINE_BLOCK metas:
@@ -561,21 +619,21 @@ enum
E_META_PRISMARINE_BLOCK_DARK = 2,
// E_BLOCK_QUARTZ_BLOCK metas:
- E_META_QUARTZ_NORMAL = 0,
+ E_META_QUARTZ_NORMAL = 0,
E_META_QUARTZ_CHISELLED = 1,
- E_META_QUARTZ_PILLAR = 2,
-
- // E_BLOCK_RAIL metas:
- E_META_RAIL_ZM_ZP = 0,
- E_META_RAIL_XM_XP = 1,
- E_META_RAIL_ASCEND_XP = 2,
- E_META_RAIL_ASCEND_XM = 3,
- E_META_RAIL_ASCEND_ZM = 4,
- E_META_RAIL_ASCEND_ZP = 5,
- E_META_RAIL_CURVED_ZP_XP = 6,
- E_META_RAIL_CURVED_ZP_XM = 7,
- E_META_RAIL_CURVED_ZM_XM = 8,
- E_META_RAIL_CURVED_ZM_XP = 9,
+ E_META_QUARTZ_PILLAR = 2,
+
+ // E_BLOCK_RAIL metas
+ E_META_RAIL_ZM_ZP = 0,
+ E_META_RAIL_XM_XP = 1,
+ E_META_RAIL_ASCEND_XP = 2,
+ E_META_RAIL_ASCEND_XM = 3,
+ E_META_RAIL_ASCEND_ZM = 4,
+ E_META_RAIL_ASCEND_ZP = 5,
+ E_META_RAIL_CURVED_ZP_XP = 6,
+ E_META_RAIL_CURVED_ZP_XM = 7,
+ E_META_RAIL_CURVED_ZM_XM = 8,
+ E_META_RAIL_CURVED_ZM_XP = 9,
// E_BLOCK_RED_SANDSTONE metas:
E_META_RED_SANDSTONE_NORMAL = 0,
@@ -668,8 +726,15 @@ enum
E_META_STAINED_GLASS_PANE_RED = 14,
E_META_STAINED_GLASS_PANE_BLACK = 15,
+ // E_BLOCK_STAIRS metas:
+ E_BLOCK_STAIRS_XP = 0,
+ E_BLOCK_STAIRS_XM = 1,
+ E_BLOCK_STAIRS_ZP = 2,
+ E_BLOCK_STAIRS_ZM = 3,
+ E_BLOCK_STAIRS_UPSIDE_DOWN = 4,
+
// E_BLOCK_STONE metas:
- E_META_STONE = 0,
+ E_META_STONE_STONE = 0,
E_META_STONE_GRANITE = 1,
E_META_STONE_POLISHED_GRANITE = 2,
E_META_STONE_DIORITE = 3,
@@ -685,18 +750,19 @@ enum
E_META_STONE_SLAB_BRICK = 4,
E_META_STONE_SLAB_STONE_BRICK = 5,
E_META_STONE_SLAB_NETHER_BRICK = 6,
- E_META_STONE_SLAB_STONE_SECRET = 7,
+ E_META_STONE_SLAB_QUARTZ = 7,
// E_BLOCK_STONE_BRICKS metas:
- E_META_STONE_BRICK_NORMAL = 0,
- E_META_STONE_BRICK_MOSSY = 1,
- E_META_STONE_BRICK_CRACKED = 2,
- E_META_STONE_BRICK_ORNAMENT = 3,
+ E_META_STONE_BRICK_NORMAL = 0,
+ E_META_STONE_BRICK_MOSSY = 1,
+ E_META_STONE_BRICK_CRACKED = 2,
+ E_META_STONE_BRICK_ORNAMENT = 3,
// E_BLOCK_TALL_GRASS metas:
E_META_TALL_GRASS_DEAD_SHRUB = 0,
E_META_TALL_GRASS_GRASS = 1,
E_META_TALL_GRASS_FERN = 2,
+ E_META_TALL_GRASS_BIOME = 3,
// E_BLOCK_TORCH, E_BLOCK_REDSTONE_TORCH_OFF, E_BLOCK_REDSTONE_TORCH_ON metas:
E_META_TORCH_EAST = 1, // east face of the block, pointing east
@@ -704,26 +770,55 @@ enum
E_META_TORCH_SOUTH = 3,
E_META_TORCH_NORTH = 4,
E_META_TORCH_FLOOR = 5,
- E_META_TORCH_XM = 1, // Torch attached to the XM side of its block
- E_META_TORCH_XP = 2, // Torch attached to the XP side of its block
- E_META_TORCH_ZM = 3, // Torch attached to the ZM side of its block
- E_META_TORCH_ZP = 4, // Torch attached to the ZP side of its block
-
+ E_META_TORCH_XM = 1, // Torch attached to the XM side of its block
+ E_META_TORCH_XP = 2, // Torch attached to the XP side of its block
+ E_META_TORCH_ZM = 3, // Torch attached to the ZM side of its block
+ E_META_TORCH_ZP = 4, // Torch attached to the ZP side of its block
+
+ // E_META_LOG metas:
+ E_META_LOG_OAK_UP_DOWN = 0,
+ E_META_LOG_SPRUCE_UP_DOWN = 1,
+ E_META_LOG_BIRCH_UP_DOWN = 2,
+ E_META_LOG_JUNGLE_UP_DOWN = 3,
+ E_META_LOG_OAK_X = 4,
+ E_META_LOG_SPRUCE_X = 5,
+ E_META_LOG_BIRCH_X = 6,
+ E_META_LOG_JUNGLE_X = 7,
+ E_META_LOG_OAK_Z = 8,
+ E_META_LOG_SPRUCE_Z = 9,
+ E_META_LOG_BIRCH_Z = 10,
+ E_META_LOG_JUNGLE_Z = 11,
+ E_META_LOG_OAK_BARK_ONLY = 12,
+ E_META_LOG_SPRUCE_BARK_ONLY = 13,
+ E_META_LOG_BIRCH_BARK_ONLY = 14,
+ E_META_LOG_JUNGLE_BARK_ONLY = 15,
+
+ // E_META_LOG metas cont. (Block ID 162):
+ E_META_NEWLOG_ACACIA_UP_DOWN = 0,
+ E_META_NEWLOG_DARK_OAK_UP_DOWN = 1,
+ E_META_NEWLOG_ACACIA_X = 4,
+ E_META_NEWLOG_DARK_OAK_X = 5,
+ E_META_NEWLOG_ACACIA_Z = 8,
+ E_META_NEWLOG_DARK_OAK_Z = 9,
+ E_META_NEWLOG_ACACIA_BARK_ONLY = 12,
+ E_META_NEWLOG_DARK_OAK_BARK_ONLY = 13,
+
// E_BLOCK_WOODEN_DOUBLE_SLAB metas:
- E_META_WOODEN_DOUBLE_SLAB_APPLE = 0,
- E_META_WOODEN_DOUBLE_SLAB_CONIFER = 1,
- E_META_WOODEN_DOUBLE_SLAB_BIRCH = 2,
- E_META_WOODEN_DOUBLE_SLAB_JUNGLE = 3,
- E_META_WOODEN_DOUBLE_SLAB_ACACIA = 4,
- E_META_WOODEN_DOUBLE_SLAB_DARK_OAK = 5,
+ E_META_WOODEN_DOUBLE_SLAB_APPLE = 0,
+ E_META_WOODEN_DOUBLE_SLAB_CONIFER = 1,
+ E_META_WOODEN_DOUBLE_SLAB_BIRCH = 2,
+ E_META_WOODEN_DOUBLE_SLAB_JUNGLE = 3,
+ E_META_WOODEN_DOUBLE_SLAB_ACACIA = 4,
+ E_META_WOODEN_DOUBLE_SLAB_DARK_OAK = 5,
// E_BLOCK_WOODEN_SLAB metas:
- E_META_WOODEN_SLAB_APPLE = 0,
- E_META_WOODEN_SLAB_CONIFER = 1,
- E_META_WOODEN_SLAB_BIRCH = 2,
- E_META_WOODEN_SLAB_JUNGLE = 3,
- E_META_WOODEN_SLAB_ACACIA = 4,
- E_META_WOODEN_SLAB_DARK_OAK = 5,
+ E_META_WOODEN_SLAB_APPLE = 0,
+ E_META_WOODEN_SLAB_CONIFER = 1,
+ E_META_WOODEN_SLAB_BIRCH = 2,
+ E_META_WOODEN_SLAB_JUNGLE = 3,
+ E_META_WOODEN_SLAB_ACACIA = 4,
+ E_META_WOODEN_SLAB_DARK_OAK = 5,
+ E_META_WOODEN_SLAB_UPSIDE_DOWN = 8,
// E_BLOCK_WOOL metas:
E_META_WOOL_WHITE = 0,
@@ -1005,9 +1100,6 @@ extern AString ItemTypeToString(short a_ItemType);
/// Translates a full item into a fully-specified string (including meta and count). If the ItemType is not recognized, the ItemType number is output into the string.
extern AString ItemToFullString(const cItem & a_Item);
-/// Translates a mob string ("ocelot") to mobtype (E_ENTITY_TYPE_OCELOT)
-extern int StringToMobType(const AString & a_MobString);
-
/// Translates a dimension string to dimension enum. Takes either a number or a dimension alias (built-in). Returns dimOverworld on failure
extern eDimension StringToDimension(const AString & a_DimensionString);
diff --git a/src/BlockInServerPluginInterface.h b/src/BlockInServerPluginInterface.h
index e82435364..70c9944a8 100644
--- a/src/BlockInServerPluginInterface.h
+++ b/src/BlockInServerPluginInterface.h
@@ -6,14 +6,30 @@
#include "Root.h"
#include "Bindings/PluginManager.h"
-class cBlockInServerPluginInterface : public cBlockPluginInterface
+
+
+
+
+class cBlockInServerPluginInterface :
+ public cBlockPluginInterface
{
public:
cBlockInServerPluginInterface(cWorld & a_World) : m_World(a_World) {}
+
+ virtual bool CallHookBlockSpread(int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
+ {
+ return cPluginManager::Get()->CallHookBlockSpread(m_World, a_BlockX, a_BlockY, a_BlockZ, a_Source);
+ }
+
virtual bool CallHookBlockToPickups(cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) override
{
- return cRoot::Get()->GetPluginManager()->CallHookBlockToPickups(&m_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_Pickups);
+ return cPluginManager::Get()->CallHookBlockToPickups(m_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_Pickups);
}
+
private:
cWorld & m_World;
};
+
+
+
+
diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp
index 5e30514e2..bdd3a9c26 100644
--- a/src/BlockInfo.cpp
+++ b/src/BlockInfo.cpp
@@ -535,6 +535,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_LAPIS_ORE ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_LOG ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_MELON ].m_FullyOccupiesVoxel = true;
+ a_Info[E_BLOCK_MOB_SPAWNER ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_MOSSY_COBBLESTONE ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_MYCELIUM ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_NETHERRACK ].m_FullyOccupiesVoxel = true;
diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h
index 19f889372..89dfc963d 100644
--- a/src/Blocks/BlockDirt.h
+++ b/src/Blocks/BlockDirt.h
@@ -89,7 +89,7 @@ public:
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
{
- if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
+ if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
{
Chunk->FastSetBlock(BlockX, BlockY, BlockZ, E_BLOCK_GRASS, 0);
}
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index ff0b201e7..b6ef5dd6f 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -4,6 +4,7 @@
#include "../Item.h"
#include "../World.h"
#include "../Chunk.h"
+#include "BlockPluginInterface.h"
#include "BlockAnvil.h"
#include "BlockBed.h"
#include "BlockBigFlower.h"
@@ -36,7 +37,6 @@
#include "BlockGlass.h"
#include "BlockGlowstone.h"
#include "BlockGravel.h"
-#include "BlockHayBale.h"
#include "BlockMobHead.h"
#include "BlockHopper.h"
#include "BlockIce.h"
@@ -83,7 +83,6 @@
#include "BlockWorkbench.h"
-#include "BlockPluginInterface.h"
@@ -231,7 +230,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_GLASS_PANE: return new cBlockGlassHandler (a_BlockType);
case E_BLOCK_GRASS: return new cBlockDirtHandler (a_BlockType);
case E_BLOCK_GRAVEL: return new cBlockGravelHandler (a_BlockType);
- case E_BLOCK_HAY_BALE: return new cBlockHayBaleHandler (a_BlockType);
+ case E_BLOCK_HAY_BALE: return new cBlockSidewaysHandler (a_BlockType);
case E_BLOCK_HEAD: return new cBlockMobHeadHandler (a_BlockType);
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
case E_BLOCK_HOPPER: return new cBlockHopperHandler (a_BlockType);
diff --git a/src/Blocks/BlockHayBale.h b/src/Blocks/BlockHayBale.h
deleted file mode 100644
index 8150b10d3..000000000
--- a/src/Blocks/BlockHayBale.h
+++ /dev/null
@@ -1,22 +0,0 @@
-
-#pragma once
-
-#include "BlockSideways.h"
-
-
-
-
-
-class cBlockHayBaleHandler :
- public cBlockSidewaysHandler
-{
-public:
- cBlockHayBaleHandler(BLOCKTYPE a_BlockType)
- : cBlockSidewaysHandler(a_BlockType)
- {
- }
-} ;
-
-
-
-
diff --git a/src/Blocks/BlockPluginInterface.h b/src/Blocks/BlockPluginInterface.h
index 3a36c40b1..b769bcf3e 100644
--- a/src/Blocks/BlockPluginInterface.h
+++ b/src/Blocks/BlockPluginInterface.h
@@ -1,7 +1,11 @@
#pragma once
-/** This interface is used to decouple block handlers from the cPluginManager dependancy through cWorld.
+
+
+
+
+/** This interface is used to decouple block handlers from the cPluginManager dependency through cWorld.
The block handlers call this interface, which is then implemented by the specific classes that
the caller provides.
*/
@@ -10,5 +14,10 @@ class cBlockPluginInterface
public:
virtual ~cBlockPluginInterface() {}
+ virtual bool CallHookBlockSpread(int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0;
virtual bool CallHookBlockToPickups(cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) = 0;
};
+
+
+
+
diff --git a/src/Blocks/BlockStone.h b/src/Blocks/BlockStone.h
index e52599c0f..69cc8301b 100644
--- a/src/Blocks/BlockStone.h
+++ b/src/Blocks/BlockStone.h
@@ -18,7 +18,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- if (a_BlockMeta == E_META_STONE)
+ if (a_BlockMeta == E_META_STONE_STONE)
{
a_Pickups.push_back(cItem(E_BLOCK_COBBLESTONE, 1, 0));
return;
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index dd252f2a4..e77bbd1b8 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -24,32 +24,23 @@ public:
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
- // Find proper placement of torch
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
+ a_ChunkInterface.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
- if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
+ if (!CanBePlacedOn(Block, Meta, a_BlockFace)) // Try to preserve original direction
{
- a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face
+ // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
+
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
+ a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Set a_BlockFace to a valid direction which will be converted later to a metadata
if (a_BlockFace == BLOCK_FACE_NONE)
{
- // Client wouldn't have sent anything anyway, but whatever
+ // No attachable face found - don't place the torch
return false;
}
}
- else
- {
- // Not top or bottom faces, try to preserve whatever face was clicked
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
- if (!CanBePlacedOn(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace))
- {
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
- // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
- a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
- if (a_BlockFace == BLOCK_FACE_NONE)
- {
- return false;
- }
- }
- }
a_BlockType = m_BlockType;
a_BlockMeta = DirectionToMetaData(a_BlockFace);
@@ -97,46 +88,57 @@ public:
}
- static bool CanBePlacedOn(BLOCKTYPE a_BlockType, eBlockFace a_BlockFace)
+ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace)
{
- if (!cBlockInfo::FullyOccupiesVoxel(a_BlockType))
- {
- return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright (for glass, etc.); exceptions won't even be sent by client, no need to handle
- }
- else
+ switch (a_BlockType)
{
- return true;
+ case E_BLOCK_END_PORTAL_FRAME:
+ case E_BLOCK_SOULSAND:
+ {
+ // Exceptional vanilla behaviour
+ return true;
+ }
+ case E_BLOCK_GLASS:
+ case E_BLOCK_STAINED_GLASS:
+ case E_BLOCK_FENCE:
+ case E_BLOCK_NETHER_BRICK_FENCE:
+ case E_BLOCK_COBBLESTONE_WALL:
+ {
+ // Torches can only be placed on top of these blocks
+ return (a_BlockFace == BLOCK_FACE_YP);
+ }
+ case E_BLOCK_STONE_SLAB:
+ case E_BLOCK_WOODEN_SLAB:
+ {
+ // Toches can be placed on the top of these slabs only if the occupy the top half of the voxel
+ return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08));
+ }
+ default:
+ {
+ if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
+ {
+ // Torches can be placed on all sides of full blocks except the bottom
+ return (a_BlockFace != BLOCK_FACE_YM);
+ }
+ return false;
+ }
}
}
- /// Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure
+ /** Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure */
static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
{
for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all directions
{
eBlockFace Face = static_cast<eBlockFace>(i);
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, true);
- BLOCKTYPE BlockInQuestion = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
-
- // If on a block that can only hold a torch if torch is standing on it, return that face
- if (
- (
- (BlockInQuestion == E_BLOCK_GLASS) ||
- (BlockInQuestion == E_BLOCK_FENCE) ||
- (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
- (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL) ||
- (BlockInQuestion == E_BLOCK_STONE_SLAB) ||
- (BlockInQuestion == E_BLOCK_WOODEN_SLAB)
- ) &&
- (Face == BLOCK_FACE_TOP)
- )
- {
- return Face;
- }
- else if (cBlockInfo::FullyOccupiesVoxel(BlockInQuestion) && (i != BLOCK_FACE_BOTTOM))
+ BLOCKTYPE BlockInQuestion;
+ NIBBLETYPE BlockInQuestionMeta;
+ a_ChunkInterface.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockInQuestion, BlockInQuestionMeta);
+
+ if (CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face))
{
- // Otherwise, if block in that direction is torch placeable and we haven't gotten to it via the bottom face, return that face
return Face;
}
else
@@ -152,36 +154,16 @@ public:
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
eBlockFace Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
-
AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true);
+
BLOCKTYPE BlockInQuestion;
- a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockInQuestion);
-
- if (
- (BlockInQuestion == E_BLOCK_GLASS) ||
- (BlockInQuestion == E_BLOCK_STAINED_GLASS) ||
- (BlockInQuestion == E_BLOCK_FENCE) ||
- (BlockInQuestion == E_BLOCK_SOULSAND) ||
- (BlockInQuestion == E_BLOCK_MOB_SPAWNER) ||
- (BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
- (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
- (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL) ||
- (BlockInQuestion == E_BLOCK_STONE_SLAB) ||
- (BlockInQuestion == E_BLOCK_WOODEN_SLAB)
- )
- {
- // Torches can be placed on tops of glass and fences, despite them being 'untorcheable'
- // No need to check for upright orientation, it was done when the torch was placed
- return true;
- }
- else if (!cBlockInfo::FullyOccupiesVoxel(BlockInQuestion))
+ NIBBLETYPE BlockInQuestionMeta;
+ if (!a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockInQuestion, BlockInQuestionMeta))
{
return false;
}
- else
- {
- return true;
- }
+
+ return CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face);
}
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index 06d84f2d4..213324cc1 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -166,23 +166,31 @@ public:
return false;
}
+
virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
UNUSED(a_ChunkInterface);
UNUSED(a_WorldInterface);
- UNUSED(a_BlockPluginInterface);
+ // Vine cannot grow down if at the bottom:
+ if (a_RelY < 1)
+ {
+ return;
+ }
+
+ // Grow one block down, if possible:
BLOCKTYPE Block;
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, Block);
if (Block == E_BLOCK_AIR)
{
- if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY - 1, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, ssVineSpread))
+ if (!a_BlockPluginInterface.CallHookBlockSpread(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY - 1, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, ssVineSpread))
{
a_Chunk.UnboundedRelSetBlock(a_RelX, a_RelY - 1, a_RelZ, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
}
}
}
+
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
{
return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index 9f971a8bd..eed949aab 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -45,7 +45,6 @@ SET (HDRS
BlockGlowstone.h
BlockGravel.h
BlockHandler.h
- BlockHayBale.h
BlockHopper.h
BlockIce.h
BlockLadder.h
diff --git a/src/CheckBasicStyle.lua b/src/CheckBasicStyle.lua
index b244b1fbc..76ae8c325 100644
--- a/src/CheckBasicStyle.lua
+++ b/src/CheckBasicStyle.lua
@@ -41,6 +41,7 @@ local g_ShouldProcessExt =
--- The list of files not to be processed:
local g_IgnoredFiles =
{
+ "Bindings/Bindings.h",
"Bindings/Bindings.cpp",
"LeakFinder.cpp",
"LeakFinder.h",
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 98c8bc66a..d03e0bf21 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -119,7 +119,7 @@ cChunk::cChunk(
cChunk::~cChunk()
{
- cPluginManager::Get()->CallHookChunkUnloaded(m_World, m_PosX, m_PosZ);
+ cPluginManager::Get()->CallHookChunkUnloaded(*m_World, m_PosX, m_PosZ);
// LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId());
@@ -1750,11 +1750,11 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max
-void cChunk::CollectPickupsByPlayer(cPlayer * a_Player)
+void cChunk::CollectPickupsByPlayer(cPlayer & a_Player)
{
- double PosX = a_Player->GetPosX();
- double PosY = a_Player->GetPosY();
- double PosZ = a_Player->GetPosZ();
+ double PosX = a_Player.GetPosX();
+ double PosY = a_Player.GetPosY();
+ double PosZ = a_Player.GetPosZ();
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
diff --git a/src/Chunk.h b/src/Chunk.h
index 8e13ff00e..c50be263f 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -218,7 +218,7 @@ public:
Sends the chunk to all relevant clients. */
void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome);
- void CollectPickupsByPlayer(cPlayer * a_Player);
+ void CollectPickupsByPlayer(cPlayer & a_Player);
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 299fe0eca..6f56b23e0 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -954,7 +954,7 @@ void cChunkMap::SetChunkData(cSetChunkData & a_SetChunkData)
}
// Notify plugins of the chunk becoming available
- cPluginManager::Get()->CallHookChunkAvailable(m_World, ChunkX, ChunkZ);
+ cPluginManager::Get()->CallHookChunkAvailable(*m_World, ChunkX, ChunkZ);
}
@@ -1145,11 +1145,11 @@ void cChunkMap::FastSetBlocks(sSetBlockList & a_BlockList)
-void cChunkMap::CollectPickupsByPlayer(cPlayer * a_Player)
+void cChunkMap::CollectPickupsByPlayer(cPlayer & a_Player)
{
- int BlockX = (int)(a_Player->GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
- int BlockY = (int)(a_Player->GetPosY());
- int BlockZ = (int)(a_Player->GetPosZ());
+ int BlockX = (int)(a_Player.GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
+ int BlockY = (int)(a_Player.GetPosY());
+ int BlockZ = (int)(a_Player.GetPosZ());
int ChunkX = 0, ChunkZ = 0;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
int OtherChunkX = ChunkX + ((BlockX > 8) ? 1 : -1);
@@ -2973,7 +2973,7 @@ void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
if (
(m_Chunks[i] != NULL) && // Is valid
(m_Chunks[i]->CanUnload()) && // Can unload
- !cPluginManager::Get()->CallHookChunkUnloading(m_Parent->GetWorld(), m_Chunks[i]->GetPosX(), m_Chunks[i]->GetPosZ()) // Plugins agree
+ !cPluginManager::Get()->CallHookChunkUnloading(*(m_Parent->GetWorld()), m_Chunks[i]->GetPosX(), m_Chunks[i]->GetPosZ()) // Plugins agree
)
{
// The cChunk destructor calls our GetChunk() while removing its entities
@@ -2987,6 +2987,8 @@ void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
+
+
void cChunkMap::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CSFastSetBlock);
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 6e92833f1..38e7f4052 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -144,7 +144,7 @@ public:
void FastSetQueuedBlocks();
void FastSetBlocks (sSetBlockList & a_BlockList);
- void CollectPickupsByPlayer(cPlayer * a_Player);
+ void CollectPickupsByPlayer(cPlayer & a_Player);
BLOCKTYPE GetBlock (int a_BlockX, int a_BlockY, int a_BlockZ);
NIBBLETYPE GetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 359255a3e..f15d845ef 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -92,7 +92,8 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) :
m_NumBlockChangeInteractionsThisTick(0),
m_UniqueID(0),
m_HasSentPlayerChunk(false),
- m_Locale("en_GB")
+ m_Locale("en_GB"),
+ m_ProtocolVersion(0)
{
m_Protocol = new cProtocolRecognizer(this);
@@ -247,9 +248,12 @@ AString cClientHandle::GenerateOfflineUUID(const AString & a_Username)
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
// Note that we generate a short UUID (without the dashes)
+ // First make the username lowercase:
+ AString lcUsername = StrToLower(a_Username);
+
// Generate an md5 checksum, and use it as base for the ID:
unsigned char MD5[16];
- md5((const unsigned char *)a_Username.c_str(), a_Username.length(), MD5);
+ md5((const unsigned char *)lcUsername.c_str(), lcUsername.length(), MD5);
MD5[6] &= 0x0f; // Need to trim to 4 bits only...
MD5[8] &= 0x0f; // ... otherwise %01x overflows into two chars
return Printf("%02x%02x%02x%02x%02x%02x3%01x%02x8%01x%02x%02x%02x%02x%02x%02x%02x",
@@ -536,9 +540,11 @@ void cClientHandle::RemoveFromAllChunks()
}
{
+ // Reset all chunk lists:
cCSLock Lock(m_CSChunkLists);
m_LoadedChunks.clear();
m_ChunksToSend.clear();
+ m_SentChunks.clear();
// Also reset the LastStreamedChunk coords to bogus coords,
// so that all chunks are streamed in subsequent StreamChunks() call (FS #407)
@@ -583,15 +589,22 @@ void cClientHandle::HandlePing(void)
bool cClientHandle::HandleLogin(int a_ProtocolVersion, const AString & a_Username)
{
+ // If the protocol version hasn't been set yet, set it now:
+ if (m_ProtocolVersion == 0)
+ {
+ m_ProtocolVersion = a_ProtocolVersion;
+ }
+
m_Username = a_Username;
- if (cRoot::Get()->GetPluginManager()->CallHookLogin(this, a_ProtocolVersion, a_Username))
+ // Let the plugins know about this event, they may refuse the player:
+ if (cRoot::Get()->GetPluginManager()->CallHookLogin(*this, a_ProtocolVersion, a_Username))
{
Destroy();
return false;
}
- // Schedule for authentication; until then, let them wait (but do not block)
+ // Schedule for authentication; until then, let the player wait (but do not block)
m_State = csAuthenticating;
cRoot::Get()->GetAuthenticator().Authenticate(GetUniqueID(), GetUsername(), m_Protocol->GetAuthServerID());
return true;
@@ -1704,7 +1717,7 @@ void cClientHandle::HandleKeepAlive(int a_KeepAliveID)
bool cClientHandle::HandleHandshake(const AString & a_Username)
{
- if (!cRoot::Get()->GetPluginManager()->CallHookHandshake(this, a_Username))
+ if (!cRoot::Get()->GetPluginManager()->CallHookHandshake(*this, a_Username))
{
if (cRoot::Get()->GetServer()->GetNumPlayers() >= cRoot::Get()->GetServer()->GetMaxPlayers())
{
@@ -2016,7 +2029,17 @@ void cClientHandle::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_Block
void cClientHandle::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
- m_Protocol->SendBlockChange(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
+ int ChunkX, ChunkZ = 0;
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
+ cChunkCoords ChunkCoords = cChunkCoords(ChunkX, ChunkZ);
+
+ // Do not send block changes in chunks that weren't sent to the client yet:
+ cCSLock Lock(m_CSChunkLists);
+ if (std::find(m_SentChunks.begin(), m_SentChunks.end(), ChunkCoords) != m_SentChunks.end())
+ {
+ Lock.Unlock();
+ m_Protocol->SendBlockChange(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
+ }
}
@@ -2026,8 +2049,15 @@ void cClientHandle::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BL
void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes)
{
ASSERT(!a_Changes.empty()); // We don't want to be sending empty change packets!
-
- m_Protocol->SendBlockChanges(a_ChunkX, a_ChunkZ, a_Changes);
+
+ // Do not send block changes in chunks that weren't sent to the client yet:
+ cChunkCoords ChunkCoords = cChunkCoords(a_ChunkX, a_ChunkZ);
+ cCSLock Lock(m_CSChunkLists);
+ if (std::find(m_SentChunks.begin(), m_SentChunks.end(), ChunkCoords) != m_SentChunks.end())
+ {
+ Lock.Unlock();
+ m_Protocol->SendBlockChanges(a_ChunkX, a_ChunkZ, a_Changes);
+ }
}
@@ -2091,6 +2121,12 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
m_Protocol->SendChunkData(a_ChunkX, a_ChunkZ, a_Serializer);
+ // Add the chunk to the list of chunks sent to the player:
+ {
+ cCSLock Lock(m_CSChunkLists);
+ m_SentChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
+ }
+
// If it is the chunk the player's in, make them spawn (in the tick thread):
if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
{
@@ -2620,6 +2656,12 @@ void cClientHandle::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_D
void cClientHandle::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
{
+ // Remove the chunk from the list of chunks sent to the client:
+ {
+ cCSLock Lock(m_CSChunkLists);
+ m_SentChunks.remove(cChunkCoords(a_ChunkX, a_ChunkZ));
+ }
+
m_Protocol->SendUnloadChunk(a_ChunkX, a_ChunkZ);
}
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 674a8cafd..9733ff32d 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -316,6 +316,12 @@ public:
/** Called when the player will enchant a Item */
void HandleEnchantItem(Byte & a_WindowID, Byte & a_Enchantment);
+
+ /** Called by the protocol recognizer when the protocol version is known. */
+ void SetProtocolVersion(UInt32 a_ProtocolVersion) { m_ProtocolVersion = a_ProtocolVersion; }
+
+ /** Returns the protocol version number of the protocol that the client is talking. Returns zero if the protocol version is not (yet) known. */
+ UInt32 GetProtocolVersion(void) const { return m_ProtocolVersion; } // tolua_export
private:
@@ -337,6 +343,7 @@ private:
cCriticalSection m_CSChunkLists;
cChunkCoordsList m_LoadedChunks; // Chunks that the player belongs to
cChunkCoordsList m_ChunksToSend; // Chunks that need to be sent to the player (queued because they weren't generated yet or there's not enough time to send them)
+ cChunkCoordsList m_SentChunks; // Store the coordinates of the chunks that the client has loaded
cProtocol * m_Protocol;
@@ -427,6 +434,9 @@ private:
/** The brand identification of the client, as received in the MC|Brand plugin message or set from a plugin. */
AString m_ClientBrand;
+ /** The version of the protocol that the client is talking, or 0 if unknown. */
+ UInt32 m_ProtocolVersion;
+
/** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
void HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler);
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index ed3409207..0828a6c74 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -280,10 +280,10 @@ cCraftingRecipes::~cCraftingRecipes()
-void cCraftingRecipes::GetRecipe(const cPlayer * a_Player, const cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe)
+void cCraftingRecipes::GetRecipe(cPlayer & a_Player, cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe)
{
// Allow plugins to intercept recipes using a pre-craft hook:
- if (cRoot::Get()->GetPluginManager()->CallHookPreCrafting(a_Player, &a_CraftingGrid, &a_Recipe))
+ if (cRoot::Get()->GetPluginManager()->CallHookPreCrafting(a_Player, a_CraftingGrid, a_Recipe))
{
return;
}
@@ -294,7 +294,7 @@ void cCraftingRecipes::GetRecipe(const cPlayer * a_Player, const cCraftingGrid &
if (Recipe.get() == NULL)
{
// Allow plugins to intercept a no-recipe-found situation:
- cRoot::Get()->GetPluginManager()->CallHookCraftingNoRecipe(a_Player, &a_CraftingGrid, &a_Recipe);
+ cRoot::Get()->GetPluginManager()->CallHookCraftingNoRecipe(a_Player, a_CraftingGrid, &a_Recipe);
return;
}
for (cRecipeSlots::const_iterator itr = Recipe->m_Ingredients.begin(); itr != Recipe->m_Ingredients.end(); ++itr)
@@ -304,7 +304,7 @@ void cCraftingRecipes::GetRecipe(const cPlayer * a_Player, const cCraftingGrid &
a_Recipe.SetResult(Recipe->m_Result);
// Allow plugins to intercept recipes after they are processed:
- cRoot::Get()->GetPluginManager()->CallHookPostCrafting(a_Player, &a_CraftingGrid, &a_Recipe);
+ cRoot::Get()->GetPluginManager()->CallHookPostCrafting(a_Player, a_CraftingGrid, a_Recipe);
}
diff --git a/src/CraftingRecipes.h b/src/CraftingRecipes.h
index fe1e15817..5ebabe098 100644
--- a/src/CraftingRecipes.h
+++ b/src/CraftingRecipes.h
@@ -115,7 +115,7 @@ public:
~cCraftingRecipes();
/// Returns the recipe for current crafting grid. Doesn't modify the grid. Clears a_Recipe if no recipe found.
- void GetRecipe(const cPlayer * a_Player, const cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe);
+ void GetRecipe(cPlayer & a_Player, cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe);
protected:
diff --git a/src/Enchantments.cpp b/src/Enchantments.cpp
index 264878c22..80a9810b6 100644
--- a/src/Enchantments.cpp
+++ b/src/Enchantments.cpp
@@ -6,6 +6,7 @@
#include "Enchantments.h"
#include "WorldStorage/FastNBT.h"
#include "FastRandom.h"
+#include "Noise.h"
@@ -1019,3 +1020,30 @@ cEnchantments cEnchantments::GetRandomEnchantmentFromVector(cWeightedEnchantment
+
+cEnchantments cEnchantments::GenerateEnchantmentFromVector(cWeightedEnchantments & a_Enchantments, int a_Seed)
+{
+ int AllWeights = 0;
+ for (const auto Enchantment : a_Enchantments)
+ {
+ AllWeights += Enchantment.m_Weight;
+ }
+
+ cNoise Noise(a_Seed);
+ int RandomNumber = Noise.IntNoise1DInt(AllWeights) / 7 % AllWeights;
+
+ for (const auto Enchantment : a_Enchantments)
+ {
+ RandomNumber -= Enchantment.m_Weight;
+ if (RandomNumber < 0)
+ {
+ return Enchantment.m_Enchantments;
+ }
+ }
+
+ return cEnchantments();
+}
+
+
+
+
diff --git a/src/Enchantments.h b/src/Enchantments.h
index 824f6aa55..e4390a5f2 100644
--- a/src/Enchantments.h
+++ b/src/Enchantments.h
@@ -128,6 +128,9 @@ public:
/** Gets random enchantment from Vector and returns it */
static cEnchantments GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments);
+ /** Returns an enchantment from a Vector using cNoise. Mostly used for generators.*/
+ static cEnchantments GenerateEnchantmentFromVector(cWeightedEnchantments & a_Enchantments, int a_Seed);
+
/** Returns true if a_Other doesn't contain exactly the same enchantments and levels */
bool operator !=(const cEnchantments & a_Other) const;
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index c265c5043..7e429c62e 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -149,14 +149,14 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
-void cArrowEntity::CollectedBy(cPlayer * a_Dest)
+void cArrowEntity::CollectedBy(cPlayer & a_Dest)
{
- if (m_IsInGround && !m_bIsCollected && CanPickup(*a_Dest))
+ if (m_IsInGround && !m_bIsCollected && CanPickup(a_Dest))
{
// Do not add the arrow to the inventory when the player is in creative:
- if (!a_Dest->IsGameModeCreative())
+ if (!a_Dest.IsGameModeCreative())
{
- int NumAdded = a_Dest->GetInventory().AddItem(E_ITEM_ARROW);
+ int NumAdded = a_Dest.GetInventory().AddItem(E_ITEM_ARROW);
if (NumAdded == 0)
{
// No space in the inventory
@@ -164,7 +164,7 @@ void cArrowEntity::CollectedBy(cPlayer * a_Dest)
}
}
- GetWorld()->BroadcastCollectEntity(*this, *a_Dest);
+ GetWorld()->BroadcastCollectEntity(*this, a_Dest);
GetWorld()->BroadcastSoundEffect("random.pop", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
m_bIsCollected = true;
}
@@ -229,3 +229,7 @@ void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
}
}
}
+
+
+
+
diff --git a/src/Entities/ArrowEntity.h b/src/Entities/ArrowEntity.h
index a1e7a17e7..1e4d8eebb 100644
--- a/src/Entities/ArrowEntity.h
+++ b/src/Entities/ArrowEntity.h
@@ -97,7 +97,7 @@ protected:
// cProjectileEntity overrides:
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
- virtual void CollectedBy(cPlayer * a_Player) override;
+ virtual void CollectedBy(cPlayer & a_Player) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
}; // tolua_export
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 3fa7e80c1..f0577aba2 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -27,9 +27,9 @@
return super::GetClass(); \
}
-#define POSX_TOINT (int)floor(GetPosX())
-#define POSY_TOINT (int)floor(GetPosY())
-#define POSZ_TOINT (int)floor(GetPosZ())
+#define POSX_TOINT FloorC(GetPosX())
+#define POSY_TOINT FloorC(GetPosY())
+#define POSZ_TOINT FloorC(GetPosZ())
#define POS_TOINT Vector3i(POSXTOINT, POSYTOINT, POSZTOINT)
#define GET_AND_VERIFY_CURRENT_CHUNK(ChunkVarName, X, Z) cChunk * ChunkVarName = a_Chunk.GetNeighborChunk(X, Z); if ((ChunkVarName == NULL) || !ChunkVarName->IsValid()) { return; }
diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h
index 6b6ad36b5..ab906fd06 100644
--- a/src/Entities/Minecart.h
+++ b/src/Entities/Minecart.h
@@ -127,7 +127,7 @@ public:
ContentsWidth = 9,
};
- const cItem & GetSlot(int a_Idx) const { return m_Contents.GetSlot(a_Idx); }
+ const cItem & GetSlot(int a_Idx) const { return m_Contents.GetSlot(a_Idx); }
void SetSlot(size_t a_Idx, const cItem & a_Item) { m_Contents.SetSlot(a_Idx, a_Item); }
protected:
diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp
index 87b5bed07..e5e28446d 100644
--- a/src/Entities/Pickup.cpp
+++ b/src/Entities/Pickup.cpp
@@ -191,10 +191,8 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
-bool cPickup::CollectedBy(cPlayer * a_Dest)
+bool cPickup::CollectedBy(cPlayer & a_Dest)
{
- ASSERT(a_Dest != NULL);
-
if (m_bCollected)
{
// LOG("Pickup %d cannot be collected by \"%s\", because it has already been collected.", m_UniqueID, a_Dest->GetName().c_str());
@@ -214,21 +212,21 @@ bool cPickup::CollectedBy(cPlayer * a_Dest)
return false;
}
- int NumAdded = a_Dest->GetInventory().AddItem(m_Item);
+ int NumAdded = a_Dest.GetInventory().AddItem(m_Item);
if (NumAdded > 0)
{
// Check achievements
switch (m_Item.m_ItemType)
{
- case E_BLOCK_LOG: a_Dest->AwardAchievement(achMineWood); break;
- case E_ITEM_LEATHER: a_Dest->AwardAchievement(achKillCow); break;
- case E_ITEM_DIAMOND: a_Dest->AwardAchievement(achDiamonds); break;
- case E_ITEM_BLAZE_ROD: a_Dest->AwardAchievement(achBlazeRod); break;
+ case E_BLOCK_LOG: a_Dest.AwardAchievement(achMineWood); break;
+ case E_ITEM_LEATHER: a_Dest.AwardAchievement(achKillCow); break;
+ case E_ITEM_DIAMOND: a_Dest.AwardAchievement(achDiamonds); break;
+ case E_ITEM_BLAZE_ROD: a_Dest.AwardAchievement(achBlazeRod); break;
default: break;
}
m_Item.m_ItemCount -= NumAdded;
- m_World->BroadcastCollectEntity(*this, *a_Dest);
+ m_World->BroadcastCollectEntity(*this, a_Dest);
// Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
m_World->BroadcastSoundEffect("random.pop", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
if (m_Item.m_ItemCount <= 0)
diff --git a/src/Entities/Pickup.h b/src/Entities/Pickup.h
index 4d5250819..b3cbeee0b 100644
--- a/src/Entities/Pickup.h
+++ b/src/Entities/Pickup.h
@@ -32,7 +32,7 @@ public:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
- bool CollectedBy(cPlayer * a_Dest); // tolua_export
+ bool CollectedBy(cPlayer & a_Dest); // tolua_export
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 86ee4a32d..6bd0a3d20 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -245,7 +245,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
if (m_Health > 0) // make sure player is alive
{
- m_World->CollectPickupsByPlayer(this);
+ m_World->CollectPickupsByPlayer(*this);
if ((m_EatingFinishTick >= 0) && (m_EatingFinishTick <= m_World->GetWorldAge()))
{
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index acc9bd674..ab25ac30c 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -424,8 +424,12 @@ void cProjectileEntity::SpawnOn(cClientHandle & a_Client)
-void cProjectileEntity::CollectedBy(cPlayer * a_Dest)
+void cProjectileEntity::CollectedBy(cPlayer & a_Dest)
{
// Overriden in arrow
UNUSED(a_Dest);
}
+
+
+
+
diff --git a/src/Entities/ProjectileEntity.h b/src/Entities/ProjectileEntity.h
index 990136a32..03eda9739 100644
--- a/src/Entities/ProjectileEntity.h
+++ b/src/Entities/ProjectileEntity.h
@@ -59,7 +59,7 @@ public:
}
/// Called by Chunk when the projectile is eligible for player collection
- virtual void CollectedBy(cPlayer * a_Dest);
+ virtual void CollectedBy(cPlayer & a_Dest);
// tolua_begin
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp
index 8924a7999..9b3d4e98d 100644
--- a/src/Generating/BioGen.cpp
+++ b/src/Generating/BioGen.cpp
@@ -760,8 +760,8 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1];
for (int x = 0; x <= 4; x++) for (int z = 0; z <= 4; z++)
{
- float BlockX = BaseX + x * 4;
- float BlockZ = BaseZ + z * 4;
+ float BlockX = static_cast<float>(BaseX + x * 4);
+ float BlockZ = static_cast<float>(BaseZ + z * 4);
double NoiseX = m_AmpX1 * m_Noise1.CubicNoise2D(BlockX * m_FreqX1, BlockZ * m_FreqX1);
NoiseX += m_AmpX2 * m_Noise2.CubicNoise2D(BlockX * m_FreqX2, BlockZ * m_FreqX2);
NoiseX += m_AmpX3 * m_Noise3.CubicNoise2D(BlockX * m_FreqX3, BlockZ * m_FreqX3);
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index 4efcd1284..87461b944 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -422,7 +422,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
// Gravel vein
cStructGenOreNests::OreInfo GravelVein;
- GravelVein.BlockType = E_BLOCK_DIRT;
+ GravelVein.BlockType = E_BLOCK_GRAVEL;
GravelVein.MaxHeight = 127;
GravelVein.NumNests = 20;
GravelVein.NestSize = 32;
diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp
index c18c402da..bf8995dcb 100644
--- a/src/Generating/DistortedHeightmap.cpp
+++ b/src/Generating/DistortedHeightmap.cpp
@@ -540,10 +540,11 @@ void cDistortedHeightmap::InitializeCompoGen(cIniFile & a_IniFile)
int cDistortedHeightmap::GetHeightmapAt(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Z)
{
- int ChunkX = (int)floor(a_X / (NOISE_DATATYPE)16);
- int ChunkZ = (int)floor(a_Z / (NOISE_DATATYPE)16);
- int RelX = (int)(a_X - (NOISE_DATATYPE)ChunkX * cChunkDef::Width);
- int RelZ = (int)(a_Z - (NOISE_DATATYPE)ChunkZ * cChunkDef::Width);
+ int RelX = (int)std::floor(a_X);
+ int RelY = 0;
+ int RelZ = (int)std::floor(a_Z);
+ int ChunkX, ChunkZ;
+ cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
// If we're withing the same chunk, return the pre-cached heightmap:
if ((ChunkX == m_CurChunkX) && (ChunkZ == m_CurChunkZ))
diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp
index f213455d6..492bae129 100644
--- a/src/Generating/DungeonRoomsFinisher.cpp
+++ b/src/Generating/DungeonRoomsFinisher.cpp
@@ -6,6 +6,7 @@
#include "Globals.h"
#include "DungeonRoomsFinisher.h"
#include "../FastRandom.h"
+#include "../BlockEntities/ChestEntity.h"
@@ -175,7 +176,33 @@ protected:
}
a_ChunkDesc.SetBlockTypeMeta(RelX, m_FloorHeight + 1, RelZ, E_BLOCK_CHEST, (NIBBLETYPE)a_Chest.y);
- // TODO: Fill the chest with random loot
+ // Fill the chest with random loot
+ static const cLootProbab LootProbab[] =
+ {
+ // Item, MinAmount, MaxAmount, Weight
+ { cItem(E_ITEM_GOLDEN_APPLE), 1, 1, 1 },
+ { cItem(E_ITEM_DIAMOND_HORSE_ARMOR), 1, 1, 1 },
+ { cItem(E_ITEM_GOLD_HORSE_ARMOR), 1, 1, 2 },
+ { cItem(E_ITEM_13_DISC), 1, 1, 4 },
+ { cItem(E_ITEM_CAT_DISC), 1, 1, 4 },
+ { cItem(E_ITEM_IRON_HORSE_ARMOR), 1, 1, 5 },
+ { cItem(E_ITEM_IRON), 1, 4, 10 },
+ { cItem(E_ITEM_WHEAT), 1, 4, 10 },
+ { cItem(E_ITEM_GUNPOWDER), 1, 4, 10 },
+ { cItem(E_ITEM_STRING), 1, 4, 10 },
+ { cItem(E_ITEM_REDSTONE_DUST), 1, 4, 10 },
+ { cItem(E_ITEM_SADDLE), 1, 1, 10 },
+ { cItem(E_ITEM_BUCKET), 1, 1, 10 },
+ { cItem(E_ITEM_BREAD), 1, 1, 10 },
+ { cItem(E_ITEM_NAME_TAG), 1, 1, 10 },
+ } ;
+
+ cChestEntity * ChestEntity = (cChestEntity *)a_ChunkDesc.GetBlockEntity(RelX, m_FloorHeight + 1, RelZ);
+ ASSERT((ChestEntity != NULL) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST));
+ cNoise Noise(a_ChunkDesc.GetChunkX() ^ a_ChunkDesc.GetChunkZ());
+ int NumSlots = 3 + ((Noise.IntNoise3DInt(a_Chest.x, a_Chest.y, a_Chest.z) / 11) % 4);
+ int Seed = Noise.IntNoise2DInt(RelX, RelZ);
+ ChestEntity->GetContents().GenerateRandomLootWithBooks(LootProbab, ARRAYCOUNT(LootProbab), NumSlots, Seed);
}
@@ -193,6 +220,7 @@ protected:
// The chunk is not intersecting the room at all, bail out
return;
}
+
int b = m_FloorHeight + 1; // Bottom
int t = m_FloorHeight + 1 + ROOM_HEIGHT; // Top
ReplaceCuboidRandom(a_ChunkDesc, m_StartX, m_FloorHeight, m_StartZ, m_EndX + 1, b, m_EndZ + 1, E_BLOCK_MOSSY_COBBLESTONE, E_BLOCK_COBBLESTONE); // Floor
diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp
index 1b0f2dc14..7fd6d6f07 100644
--- a/src/Generating/Trees.cpp
+++ b/src/Generating/Trees.cpp
@@ -224,8 +224,6 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
case biMegaTaiga:
case biMegaTaigaHills:
case biExtremeHillsPlus:
- case biSavanna:
- case biSavannaPlateau:
case biMesa:
case biMesaPlateauF:
case biMesaPlateau:
@@ -241,8 +239,6 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
case biMegaSpruceTaiga:
case biMegaSpruceTaigaHills:
case biExtremeHillsPlusM:
- case biSavannaM:
- case biSavannaPlateauM:
case biMesaBryce:
case biMesaPlateauFM:
case biMesaPlateauM:
@@ -252,6 +248,15 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
return;
}
+ case biSavanna:
+ case biSavannaPlateau:
+ case biSavannaM:
+ case biSavannaPlateauM:
+ {
+ GetAcaciaTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
+ return;
+ }
+
case biRoofedForest:
case biRoofedForestM:
{
@@ -403,7 +408,72 @@ void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
{
- // TODO
+ // Calculate a base height
+ int Height = 2 + (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 11 % 3);
+
+ // Create the trunk
+ for (int i = 0; i < Height; i++)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD));
+ }
+
+ // Array with possible directions for a branch to go to.
+ const Vector3i AvailableDirections[] =
+ {
+ { -1, 1, 0 }, { 0, 1, -1 },
+ { -1, 1, 1 }, { -1, 1, -1 },
+ { 1, 1, 1 }, { 1, 1, -1 },
+ { 1, 1, 0 }, { 0, 1, 1 },
+ };
+
+ // Set the starting point of the branch
+ Vector3i BranchPos = Vector3i(a_BlockX, a_BlockY + Height - 1, a_BlockZ);
+
+ // Get a direction for the trunk to go to.
+ Vector3i BranchDirection = AvailableDirections[a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 8];
+
+ // Calculate a height for the branch between 1 and 3
+ int BranchHeight = a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 3 + 1;
+
+ // Place the logs of the branch.
+ for (int i = 0; i < BranchHeight; i++)
+ {
+ BranchPos = BranchPos + BranchDirection;
+ a_LogBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y, BranchPos.z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD));
+ }
+
+ // Add the leaves to the top of the branch
+ PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ a_OtherBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD));
+
+ // Choose if we have to add another branch
+ bool TwoTop = (a_Noise.IntNoise3D(a_BlockX, a_BlockY, a_BlockZ) < 0 ? true : false);
+ if (!TwoTop)
+ {
+ return;
+ }
+
+ // Reset the starting point of the branch
+ BranchPos = Vector3i(a_BlockX, a_BlockY + Height - 1, a_BlockZ);
+
+ // Invert the direction of the previous branch.
+ BranchDirection = Vector3d(-BranchDirection.x, 1, -BranchDirection.z);
+
+ // Calculate a new height for the second branch
+ BranchHeight = a_Noise.IntNoise3DInt(a_BlockX * a_Seq, a_BlockY * a_Seq * 10, a_BlockZ * a_Seq) % 3 + 1;
+
+ // Place the logs in the same way as the first branch
+ for (int i = 0; i < BranchHeight; i++)
+ {
+ BranchPos = BranchPos + BranchDirection;
+ a_LogBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y, BranchPos.z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD));
+ }
+
+ // And add the leaves ontop of the second branch
+ PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ a_OtherBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD));
}
diff --git a/src/Globals.h b/src/Globals.h
index 0926457da..b84607355 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -51,6 +51,9 @@
#define NORETURN __declspec(noreturn)
+ // Use non-standard defines in <cmath>
+ #define _USE_MATH_DEFINES
+
#elif defined(__GNUC__)
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
@@ -226,10 +229,10 @@ template class SizeChecker<UInt16, 2>;
// CRT stuff:
#include <sys/stat.h>
-#include <assert.h>
-#include <stdio.h>
-#include <math.h>
-#include <stdarg.h>
+#include <cassert>
+#include <cstdio>
+#include <cmath>
+#include <cstdarg>
@@ -400,6 +403,30 @@ T Clamp(T a_Value, T a_Min, T a_Max)
+/** Floors a value, then casts it to C (an int by default) */
+template <typename C = int, typename T>
+typename std::enable_if<std::is_arithmetic<T>::value, C>::type FloorC(T a_Value)
+{
+ return static_cast<C>(std::floor(a_Value));
+}
+
+/** Ceils a value, then casts it to C (an int by default) */
+template <typename C = int, typename T>
+typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
+{
+ return static_cast<C>(std::ceil(a_Value));
+}
+
+
+
+//temporary replacement for std::make_unique until we get c++14
+template <class T, class... Args>
+std::unique_ptr<T> make_unique(Args&&... args)
+{
+ return std::unique_ptr<T>(new T(args...));
+}
+
+
#ifndef TOLUA_TEMPLATE_BIND
#define TOLUA_TEMPLATE_BIND(x)
#endif
@@ -415,3 +442,4 @@ T Clamp(T a_Value, T a_Min, T a_Max)
#include "BlockInfo.h"
+
diff --git a/src/ItemGrid.cpp b/src/ItemGrid.cpp
index 2344dc0a5..0bd44bb0d 100644
--- a/src/ItemGrid.cpp
+++ b/src/ItemGrid.cpp
@@ -637,14 +637,35 @@ void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, s
int Rnd = (Noise.IntNoise1DInt(i) / 7);
int LootRnd = Rnd % TotalProbab;
Rnd >>= 8;
- cItem CurrentLoot = cItem(E_ITEM_BOOK, 1, 0); // TODO: enchantment
+ cItem CurrentLoot = cItem(E_ITEM_ENCHANTED_BOOK, 1, 0);
+
+ // Choose the enchantments
+ cWeightedEnchantments Enchantments;
+ cEnchantments::AddItemEnchantmentWeights(Enchantments, E_ITEM_BOOK, 24 + Noise.IntNoise2DInt(a_Seed, TotalProbab) % 7);
+ int NumEnchantments = Noise.IntNoise3DInt(TotalProbab, Rnd, a_Seed) % 5; // The number of enchantments this book wil get.
+
+ for (int j = 0; j <= NumEnchantments; j++)
+ {
+ cEnchantments Enchantment = cEnchantments::GenerateEnchantmentFromVector(Enchantments, Noise.IntNoise2DInt(NumEnchantments, i));
+ CurrentLoot.m_Enchantments.Add(Enchantment);
+ cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment);
+ cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment);
+ }
+
for (size_t j = 0; j < a_CountLootProbabs; j++)
{
- LootRnd -= a_LootProbabs[i].m_Weight;
+ LootRnd -= a_LootProbabs[j].m_Weight;
if (LootRnd < 0)
{
- CurrentLoot = a_LootProbabs[i].m_Item;
- CurrentLoot.m_ItemCount = a_LootProbabs[i].m_MinAmount + (Rnd % (a_LootProbabs[i].m_MaxAmount - a_LootProbabs[i].m_MinAmount));
+ CurrentLoot = a_LootProbabs[j].m_Item;
+ if ((a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount) > 0)
+ {
+ CurrentLoot.m_ItemCount = a_LootProbabs[j].m_MinAmount + (Rnd % (a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount));
+ }
+ else
+ {
+ CurrentLoot.m_ItemCount = a_LootProbabs[j].m_MinAmount;
+ }
Rnd >>= 8;
break;
}
diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt
index 2c092c15f..bbbb9287a 100644
--- a/src/Mobs/CMakeLists.txt
+++ b/src/Mobs/CMakeLists.txt
@@ -54,6 +54,7 @@ SET (HDRS
IronGolem.h
MagmaCube.h
Monster.h
+ MonsterTypes.h
Mooshroom.h
Ocelot.h
PassiveAggressiveMonster.h
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 12ca6bbbe..73dbcb3c3 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -62,6 +62,16 @@ static const struct
+eMonsterType StringToMobType(const AString & a_MobString)
+{
+ LOGWARNING("%s: Function is obsolete, use cMonster::StringToMobType() instead", __FUNCTION__);
+ return cMonster::StringToMobType(a_MobString);
+}
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cMonster:
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index a1f9c4a5b..9fd67d67c 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -25,9 +25,6 @@ class cMonster :
typedef cPawn super;
public:
- // Deprecated
- typedef eMonsterType eType;
-
enum eFamily
{
mfHostile = 0, // Spider, Zombies ...
diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h
index 7a73e99f4..852eb3446 100644
--- a/src/Mobs/MonsterTypes.h
+++ b/src/Mobs/MonsterTypes.h
@@ -37,5 +37,18 @@ enum eMonsterType
mtZombie = E_META_SPAWN_EGG_ZOMBIE,
mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN,
} ;
+
+
+
+
+
+/** Translates a mob string ("ocelot") to mobtype (mtOcelot).
+OBSOLETE, use cMonster::StringToMobType() instead.
+Implemented in Monster.cpp. */
+extern eMonsterType StringToMobType(const AString & a_MobString);
+
// tolua_end
+
+
+
diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt
index a42fcbed4..429949c59 100644
--- a/src/OSSupport/CMakeLists.txt
+++ b/src/OSSupport/CMakeLists.txt
@@ -39,6 +39,6 @@ if(NOT MSVC)
add_library(OSSupport ${SRCS} ${HDRS})
if(UNIX)
- target_link_libraries(OSSupport pthread)
+ target_link_libraries(OSSupport pthread rt)
endif()
endif()
diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp
index 74f823216..7cf8a826c 100644
--- a/src/OSSupport/Event.cpp
+++ b/src/OSSupport/Event.cpp
@@ -102,6 +102,53 @@ void cEvent::Wait(void)
+bool cEvent::Wait(int a_TimeoutMSec)
+{
+ #ifdef _WIN32
+ DWORD res = WaitForSingleObject(m_Event, (DWORD)a_TimeoutMSec);
+ switch (res)
+ {
+ case WAIT_OBJECT_0: return true; // Regular event signalled
+ case WAIT_TIMEOUT: return false; // Regular event timeout
+ default:
+ {
+ LOGWARN("cEvent: waiting for the event failed: %u, GLE = %u. Continuing, but server may be unstable.", (unsigned)res, (unsigned)GetLastError());
+ return false;
+ }
+ }
+ #else
+ // Get the current time:
+ timespec timeout;
+ if (clock_gettime(CLOCK_REALTIME, &timeout) == -1)
+ {
+ LOGWARN("cEvent: Getting current time failed: %i, err = %s. Continuing, but the server may be unstable.", errno, GetOSErrorString(errno).c_str());
+ return false;
+ }
+
+ // Add the specified timeout:
+ timeout.tv_sec += a_TimeoutMSec / 1000;
+ timeout.tv_nsec += (a_TimeoutMSec % 1000) * 1000000; // 1 msec = 1000000 usec
+
+ // Wait with timeout:
+ int res = sem_timedwait(m_Event, &timeout);
+ switch (res)
+ {
+ case 0: return true; // Regular event signalled
+ case ETIMEDOUT: return false; // Regular even timeout
+ default:
+ {
+ AString error = GetOSErrorString(errno);
+ LOGWARN("cEvent: waiting for the event failed: %i, err = %s. Continuing, but server may be unstable.", res, error.c_str());
+ return false;
+ }
+ }
+ #endif
+}
+
+
+
+
+
void cEvent::Set(void)
{
#ifdef _WIN32
diff --git a/src/OSSupport/Event.h b/src/OSSupport/Event.h
index 71f418c0c..e2fa65a05 100644
--- a/src/OSSupport/Event.h
+++ b/src/OSSupport/Event.h
@@ -24,6 +24,10 @@ public:
void Wait(void);
void Set (void);
+
+ /** Waits for the event until either it is signalled, or the (relative) timeout is passed.
+ Returns true if the event was signalled, false if the timeout was hit or there was an error. */
+ bool Wait(int a_TimeoutMSec);
private:
diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp
index 28da83c31..a4b4dbd3b 100644
--- a/src/Protocol/MojangAPI.cpp
+++ b/src/Protocol/MojangAPI.cpp
@@ -11,6 +11,8 @@
#include "json/json.h"
#include "PolarSSL++/BlockingSslClientSocket.h"
#include "../RankManager.h"
+#include "../OSSupport/IsThread.h"
+#include "../Root.h"
@@ -152,6 +154,41 @@ cMojangAPI::sProfile::sProfile(
////////////////////////////////////////////////////////////////////////////////
+// cMojangAPI::cUpdateThread:
+
+class cMojangAPI::cUpdateThread :
+ public cIsThread
+{
+ typedef cIsThread super;
+public:
+ cUpdateThread() :
+ super("cMojangAPI::cUpdateThread")
+ {
+ }
+
+ ~cUpdateThread()
+ {
+ m_evtNotify.Set();
+ Stop();
+ }
+
+protected:
+ cEvent m_evtNotify;
+
+ virtual void Execute(void) override
+ {
+ do
+ {
+ cRoot::Get()->GetMojangAPI().Update();
+ } while (!m_evtNotify.Wait(60 * 60 * 1000)); // Repeat every 60 minutes
+ }
+} ;
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cMojangAPI:
cMojangAPI::cMojangAPI(void) :
@@ -159,7 +196,8 @@ cMojangAPI::cMojangAPI(void) :
m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS),
m_UUIDToProfileServer(DEFAULT_UUID_TO_PROFILE_SERVER),
m_UUIDToProfileAddress(DEFAULT_UUID_TO_PROFILE_ADDRESS),
- m_RankMgr(NULL)
+ m_RankMgr(NULL),
+ m_UpdateThread(new cUpdateThread())
{
}
@@ -176,13 +214,17 @@ cMojangAPI::~cMojangAPI()
-void cMojangAPI::Start(cIniFile & a_SettingsIni)
+void cMojangAPI::Start(cIniFile & a_SettingsIni, bool a_ShouldAuth)
{
m_NameToUUIDServer = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER);
m_NameToUUIDAddress = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS);
m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
LoadCachesFromDisk();
+ if (a_ShouldAuth)
+ {
+ m_UpdateThread->Start();
+ }
}
@@ -465,21 +507,7 @@ void cMojangAPI::LoadCachesFromDisk(void)
db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
- // Clean up old entries:
- {
- SQLite::Statement stmt(db, "DELETE FROM PlayerNameToUUID WHERE DateTime < ?");
- Int64 LimitDateTime = time(NULL) - MAX_AGE;
- stmt.bind(1, LimitDateTime);
- stmt.exec();
- }
- {
- SQLite::Statement stmt(db, "DELETE FROM UUIDToProfile WHERE DateTime < ?");
- Int64 LimitDateTime = time(NULL) - MAX_AGE;
- stmt.bind(1, LimitDateTime);
- stmt.exec();
- }
-
- // Retrieve all remaining entries:
+ // Retrieve all entries:
{
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
while (stmt.executeStep())
@@ -596,18 +624,27 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
} // for itr - a_PlayerNames[]
} // Lock(m_CSNameToUUID)
- while (!NamesToQuery.empty())
+ QueryNamesToUUIDs(NamesToQuery);
+}
+
+
+
+
+
+void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
+{
+ while (!a_NamesToQuery.empty())
{
// Create the request body - a JSON containing up to MAX_PER_QUERY playernames:
Json::Value root;
int Count = 0;
- AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end();
+ AStringVector::iterator itr = a_NamesToQuery.begin(), end = a_NamesToQuery.end();
for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count)
{
Json::Value req(*itr);
root.append(req);
} // for itr - a_PlayerNames[]
- NamesToQuery.erase(NamesToQuery.begin(), itr);
+ a_NamesToQuery.erase(a_NamesToQuery.begin(), itr);
Json::FastWriter Writer;
AString RequestBody = Writer.write(root);
@@ -705,12 +742,22 @@ void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
// Check if already present:
{
+ cCSLock Lock(m_CSUUIDToProfile);
if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end())
{
return;
}
}
+ QueryUUIDToProfile(a_UUID);
+}
+
+
+
+
+
+void cMojangAPI::QueryUUIDToProfile(const AString & a_UUID)
+{
// Create the request address:
AString Address = m_UUIDToProfileAddress;
ReplaceString(Address, "%UUID%", a_UUID);
@@ -817,3 +864,51 @@ void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const AString & a_
+
+void cMojangAPI::Update(void)
+{
+ Int64 LimitDateTime = time(NULL) - MAX_AGE;
+
+ // Re-query all playernames that are stale:
+ AStringVector PlayerNames;
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
+ {
+ if (itr->second.m_DateTime < LimitDateTime)
+ {
+ PlayerNames.push_back(itr->first);
+ }
+ } // for itr - m_NameToUUID[]
+ }
+ if (!PlayerNames.empty())
+ {
+ LOG("cMojangAPI: Updating name-to-uuid cache for %u names", (unsigned)PlayerNames.size());
+ QueryNamesToUUIDs(PlayerNames);
+ }
+
+ // Re-query all profiles that are stale:
+ AStringVector ProfileUUIDs;
+ {
+ cCSLock Lock(m_CSUUIDToProfile);
+ for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
+ {
+ if (itr->second.m_DateTime < LimitDateTime)
+ {
+ ProfileUUIDs.push_back(itr->first);
+ }
+ } // for itr - m_UUIDToProfile[]
+ }
+ if (!ProfileUUIDs.empty())
+ {
+ LOG("cMojangAPI: Updating uuid-to-profile cache for %u uuids", (unsigned)ProfileUUIDs.size());
+ for (AStringVector::const_iterator itr = ProfileUUIDs.begin(), end = ProfileUUIDs.end(); itr != end; ++itr)
+ {
+ QueryUUIDToProfile(*itr);
+ }
+ }
+}
+
+
+
+
diff --git a/src/Protocol/MojangAPI.h b/src/Protocol/MojangAPI.h
index 252d32543..393fd4baa 100644
--- a/src/Protocol/MojangAPI.h
+++ b/src/Protocol/MojangAPI.h
@@ -38,7 +38,7 @@ public:
/** Initializes the API; reads the settings from the specified ini file.
Loads cached results from disk. */
- void Start(cIniFile & a_SettingsIni);
+ void Start(cIniFile & a_SettingsIni, bool a_ShouldAuth);
/** Connects to the specified server using SSL, sends the given request and receives the response.
Checks Mojang certificates using the hard-coded Starfield root CA certificate.
@@ -93,6 +93,10 @@ public:
void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; }
protected:
+ /** The thread that periodically checks for stale data and re-queries it from the server. */
+ class cUpdateThread;
+
+
/** Holds data for a single player profile. */
struct sProfile
{
@@ -177,6 +181,9 @@ protected:
/** Protects m_RankMgr agains simultaneous multi-threaded access. */
cCriticalSection m_CSRankMgr;
+
+ /** The thread that periodically updates the stale data in the DB from the Mojang servers. */
+ SharedPtr<cUpdateThread> m_UpdateThread;
/** Loads the caches from a disk storage. */
@@ -189,15 +196,29 @@ protected:
Names that are not valid are not added into the cache.
ASSUMEs that a_PlayerNames contains lowercased player names. */
void CacheNamesToUUIDs(const AStringVector & a_PlayerNames);
+
+ /** Queries all the specified names and stores them into the m_PlayerNameToUUID cache.
+ Names that are not valid are not added into the cache.
+ ASSUMEs that a_PlayerNames contans lowercased player names.
+ For performance reasons takes a non-const reference and modifies the list given to it, until empty. */
+ void QueryNamesToUUIDs(AStringVector & a_PlayerNames);
/** Makes sure the specified UUID is in the m_UUIDToProfile cache. If missing, downloads it from Mojang API servers.
UUIDs that are not valid will not be added into the cache.
ASSUMEs that a_UUID is a lowercased short UUID. */
void CacheUUIDToProfile(const AString & a_UUID);
+ /** Queries the specified UUID's profile and stores it in the m_UUIDToProfile cache. If already present, updates the cache entry.
+ UUIDs that are not valid will not be added into the cache.
+ ASSUMEs that a_UUID is a lowercased short UUID. */
+ void QueryUUIDToProfile(const AString & a_UUID);
+
/** Called for each name-uuid pairing that is discovered.
If assigned, notifies the m_RankManager of the event. */
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_PlayerUUID);
+
+ /** Updates the stale values in the DB from the Mojang servers. Called from the cUpdateThread, blocks on the HTTPS API calls. */
+ void Update(void);
} ; // tolua_export
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 0b829ac9e..0c1e83b67 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -905,6 +905,7 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
{
return false;
}
+ m_Client->SetProtocolVersion(ProtocolVersion);
switch (ProtocolVersion)
{
case PROTO_VERSION_1_7_2:
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index f60df4158..dcf653e75 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -134,7 +134,7 @@ protected:
/// Tries to recognize protocol based on m_Buffer contents; returns true if recognized
bool TryRecognizeProtocol(void);
- /** Tries to recognize a protocol in the leghted family (1.7+), based on m_Buffer; returns true if recognized.
+ /** Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer; returns true if recognized.
The packet length and type have already been read, type is 0
The number of bytes remaining in the packet is passed as a_PacketLengthRemaining
**/
diff --git a/src/Root.cpp b/src/Root.cpp
index b866e2369..02455518c 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -142,8 +142,9 @@ void cRoot::Start(void)
}
LOG("Starting server...");
- m_MojangAPI.Start(IniFile); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
- if (!m_Server->InitServer(IniFile))
+ bool ShouldAuthenticate = IniFile.GetValueSetB("Authentication", "Authenticate", true);
+ m_MojangAPI.Start(IniFile, ShouldAuthenticate); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
+ if (!m_Server->InitServer(IniFile, ShouldAuthenticate))
{
IniFile.WriteFile("settings.ini");
LOGERROR("Failure starting server, aborting...");
diff --git a/src/Server.cpp b/src/Server.cpp
index 969ffd693..8e5755a75 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -196,7 +196,7 @@ void cServer::PlayerDestroying(const cPlayer * a_Player)
-bool cServer::InitServer(cIniFile & a_SettingsIni)
+bool cServer::InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth)
{
m_Description = a_SettingsIni.GetValueSet("Server", "Description", "MCServer - in C++!");
m_MaxPlayers = a_SettingsIni.GetValueSetI("Server", "MaxPlayers", 100);
@@ -247,7 +247,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
m_bIsConnected = true;
m_ServerID = "-";
- m_ShouldAuthenticate = a_SettingsIni.GetValueSetB("Authentication", "Authenticate", true);
+ m_ShouldAuthenticate = a_ShouldAuth;
if (m_ShouldAuthenticate)
{
MTRand mtrand1;
@@ -450,7 +450,7 @@ bool cServer::Start(void)
bool cServer::Command(cClientHandle & a_Client, AString & a_Cmd)
{
- return cRoot::Get()->GetPluginManager()->CallHookChat(a_Client.GetPlayer(), a_Cmd);
+ return cRoot::Get()->GetPluginManager()->CallHookChat(*(a_Client.GetPlayer()), a_Cmd);
}
diff --git a/src/Server.h b/src/Server.h
index 6d659fa40..022794bbc 100644
--- a/src/Server.h
+++ b/src/Server.h
@@ -56,7 +56,7 @@ class cServer // tolua_export
public: // tolua_export
virtual ~cServer() {}
- bool InitServer(cIniFile & a_SettingsIni);
+ bool InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth);
// tolua_begin
diff --git a/src/Simulator/FireSimulator.cpp b/src/Simulator/FireSimulator.cpp
index 7ae84af7b..d3deee74a 100644
--- a/src/Simulator/FireSimulator.cpp
+++ b/src/Simulator/FireSimulator.cpp
@@ -333,7 +333,7 @@ void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int
int a_PosX = x + a_Chunk->GetPosX() * cChunkDef::Width;
int a_PosZ = z + a_Chunk->GetPosZ() * cChunkDef::Width;
- if (cRoot::Get()->GetPluginManager()->CallHookBlockSpread(&m_World, a_PosX, y, a_PosZ, ssFireSpread))
+ if (cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, a_PosX, y, a_PosZ, ssFireSpread))
{
return;
}
@@ -382,7 +382,7 @@ void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_Rel
}
bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance);
- if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(&m_World, AbsX, Y, AbsZ, ssFireSpread))
+ if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, AbsX, Y, AbsZ, ssFireSpread))
{
Neighbour->SetBlock(X, Y, Z, E_BLOCK_FIRE, 0);
}
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 999bed989..88d9f44fc 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -714,7 +714,7 @@ void cSlotAreaCrafting::UpdateRecipe(cPlayer & a_Player)
{
cCraftingGrid Grid(GetPlayerSlots(a_Player) + 1, m_GridSize, m_GridSize);
cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player);
- cRoot::Get()->GetCraftingRecipes()->GetRecipe(&a_Player, Grid, Recipe);
+ cRoot::Get()->GetCraftingRecipes()->GetRecipe(a_Player, Grid, Recipe);
SetSlot(0, a_Player, Recipe.GetResult());
m_ParentWindow.SendSlot(a_Player, this, 0);
}
@@ -736,7 +736,7 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
// Not found. Add a new one:
cCraftingGrid Grid(GetPlayerSlots(a_Player) + 1, m_GridSize, m_GridSize);
cCraftingRecipe Recipe(Grid);
- cRoot::Get()->GetCraftingRecipes()->GetRecipe(&a_Player, Grid, Recipe);
+ cRoot::Get()->GetCraftingRecipes()->GetRecipe(a_Player, Grid, Recipe);
m_Recipes.push_back(std::make_pair(a_Player.GetUniqueID(), Recipe));
return m_Recipes.back().second;
}
diff --git a/src/Vector3.h b/src/Vector3.h
index 1dcb38f64..1854e42e3 100644
--- a/src/Vector3.h
+++ b/src/Vector3.h
@@ -3,8 +3,6 @@
-#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
-#include <math.h>
#include <list>
#include <vector>
@@ -29,9 +27,9 @@ public:
// Hardcoded copy constructors (tolua++ does not support function templates .. yet)
- Vector3(const Vector3<float> & a_Rhs) : x((T) a_Rhs.x), y((T) a_Rhs.y), z((T) a_Rhs.z) {}
- Vector3(const Vector3<double> & a_Rhs) : x((T) a_Rhs.x), y((T) a_Rhs.y), z((T) a_Rhs.z) {}
- Vector3(const Vector3<int> & a_Rhs) : x((T) a_Rhs.x), y((T) a_Rhs.y), z((T) a_Rhs.z) {}
+ Vector3(const Vector3<float> & a_Rhs) : x(static_cast<T>(a_Rhs.x)), y(static_cast<T>(a_Rhs.y)), z(static_cast<T>(a_Rhs.z)) {}
+ Vector3(const Vector3<double> & a_Rhs) : x(static_cast<T>(a_Rhs.x)), y(static_cast<T>(a_Rhs.y)), z(static_cast<T>(a_Rhs.z)) {}
+ Vector3(const Vector3<int> & a_Rhs) : x(static_cast<T>(a_Rhs.x)), y(static_cast<T>(a_Rhs.y)), z(static_cast<T>(a_Rhs.z)) {}
// tolua_end
@@ -53,9 +51,9 @@ public:
{
double Len = 1.0 / Length();
- x = (T)(x * Len);
- y = (T)(y * Len);
- z = (T)(z * Len);
+ x = static_cast<T>(x * Len);
+ y = static_cast<T>(y * Len);
+ z = static_cast<T>(z * Len);
}
inline Vector3<T> NormalizeCopy(void) const
@@ -63,9 +61,9 @@ public:
double Len = 1.0 / Length();
return Vector3<T>(
- (T)(x * Len),
- (T)(y * Len),
- (T)(z * Len)
+ static_cast<T>(x * Len),
+ static_cast<T>(y * Len),
+ static_cast<T>(z * Len)
);
}
@@ -74,15 +72,15 @@ public:
double Len = 1.0 / Length();
a_Rhs.Set(
- (T)(x * Len),
- (T)(y * Len),
- (T)(z * Len)
+ static_cast<T>(x * Len),
+ static_cast<T>(y * Len),
+ static_cast<T>(z * Len)
);
}
inline double Length(void) const
{
- return sqrt((double)(x * x + y * y + z * z));
+ return sqrt(static_cast<double>(x * x + y * y + z * z));
}
inline double SqrLength(void) const
@@ -138,9 +136,9 @@ public:
inline Vector3<int> Floor(void) const
{
return Vector3<int>(
- (int)floor(x),
- (int)floor(y),
- (int)floor(z)
+ FloorC(x),
+ FloorC(y),
+ FloorC(z)
);
}
diff --git a/src/World.cpp b/src/World.cpp
index a3c804b44..1f9361386 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -256,14 +256,14 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin
m_IsDeepSnowEnabled(false),
m_ShouldLavaSpawnFire(true),
m_VillagersShouldHarvestCrops(true),
- m_SimulatorManager(NULL),
- m_SandSimulator(NULL),
+ m_SimulatorManager(),
+ m_SandSimulator(),
m_WaterSimulator(NULL),
- m_LavaSimulator(NULL),
- m_FireSimulator(NULL),
+ m_LavaSimulator(nullptr),
+ m_FireSimulator(),
m_RedstoneSimulator(NULL),
m_MaxPlayers(10),
- m_ChunkMap(NULL),
+ m_ChunkMap(),
m_bAnimals(true),
m_Weather(eWeather_Sunny),
m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :)
@@ -303,11 +303,8 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin
cWorld::~cWorld()
{
- delete m_SimulatorManager; m_SimulatorManager = NULL;
- delete m_SandSimulator; m_SandSimulator = NULL;
delete m_WaterSimulator; m_WaterSimulator = NULL;
delete m_LavaSimulator; m_LavaSimulator = NULL;
- delete m_FireSimulator; m_FireSimulator = NULL;
delete m_RedstoneSimulator; m_RedstoneSimulator = NULL;
UnloadUnusedChunks();
@@ -319,8 +316,6 @@ cWorld::~cWorld()
Serializer.Save();
m_MapManager.SaveMapData();
-
- delete m_ChunkMap;
}
@@ -631,7 +626,7 @@ void cWorld::Start(void)
InitialiseAndLoadMobSpawningValues(IniFile);
SetTimeOfDay(IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay));
- m_ChunkMap = new cChunkMap(this);
+ m_ChunkMap = make_unique<cChunkMap>(this);
m_LastSave = 0;
m_LastUnload = 0;
@@ -641,16 +636,16 @@ void cWorld::Start(void)
m_BlockTickQueueCopy.reserve(1000);
// Simulators:
- m_SimulatorManager = new cSimulatorManager(*this);
+ m_SimulatorManager = make_unique<cSimulatorManager>(*this);
m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
- m_SandSimulator = new cSandSimulator(*this, IniFile);
- m_FireSimulator = new cFireSimulator(*this, IniFile);
+ m_SandSimulator = make_unique<cSandSimulator>(*this, IniFile);
+ m_FireSimulator = make_unique<cFireSimulator>(*this, IniFile);
m_RedstoneSimulator = InitializeRedstoneSimulator(IniFile);
// Water, Lava and Redstone simulators get registered in their initialize function.
- m_SimulatorManager->RegisterSimulator(m_SandSimulator, 1);
- m_SimulatorManager->RegisterSimulator(m_FireSimulator, 1);
+ m_SimulatorManager->RegisterSimulator(m_SandSimulator.get(), 1);
+ m_SimulatorManager->RegisterSimulator(m_FireSimulator.get(), 1);
m_Lighting.Start(this);
m_Storage.Start(this, m_StorageSchema, m_StorageCompressionFactor);
@@ -1059,7 +1054,6 @@ void cWorld::TickQueuedTasks(void)
for (cTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
{
(*itr)->Run(*this);
- delete *itr;
} // for itr - m_Tasks[]
}
@@ -1069,14 +1063,28 @@ void cWorld::TickQueuedTasks(void)
void cWorld::TickScheduledTasks(void)
{
- // Make a copy of the tasks to avoid deadlocks on accessing m_Tasks
+ // Move the tasks to be executed to a seperate vector to avoid deadlocks on accessing m_Tasks
cScheduledTasks Tasks;
{
cCSLock Lock(m_CSScheduledTasks);
- while (!m_ScheduledTasks.empty() && (m_ScheduledTasks.front()->m_TargetTick < m_WorldAge))
+ auto WorldAge = m_WorldAge;
+
+ // Move all the due tasks from m_ScheduledTasks into Tasks:
+ for (auto itr = m_ScheduledTasks.begin(); itr != m_ScheduledTasks.end();) // Cannot use range-basd for, we're modifying the container
{
- Tasks.push_back(m_ScheduledTasks.front());
- m_ScheduledTasks.pop_front();
+ if ((*itr)->m_TargetTick < WorldAge)
+ {
+ auto next = itr;
+ ++next;
+ Tasks.push_back(std::move(*itr));
+ m_ScheduledTasks.erase(itr);
+ itr = next;
+ }
+ else
+ {
+ // All the eligible tasks have been moved, bail out now
+ break;
+ }
}
}
@@ -1084,7 +1092,6 @@ void cWorld::TickScheduledTasks(void)
for (cScheduledTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
{
(*itr)->m_Task->Run(*this);
- delete *itr;
} // for itr - m_Tasks[]
}
@@ -2593,14 +2600,14 @@ void cWorld::UnloadUnusedChunks(void)
void cWorld::QueueUnloadUnusedChunks(void)
{
- QueueTask(new cWorld::cTaskUnloadUnusedChunks);
+ QueueTask(make_unique<cWorld::cTaskUnloadUnusedChunks>());
}
-void cWorld::CollectPickupsByPlayer(cPlayer * a_Player)
+void cWorld::CollectPickupsByPlayer(cPlayer & a_Player)
{
m_ChunkMap->CollectPickupsByPlayer(a_Player);
}
@@ -2902,13 +2909,13 @@ bool cWorld::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AStrin
AString Line2(a_Line2);
AString Line3(a_Line3);
AString Line4(a_Line4);
- if (cRoot::Get()->GetPluginManager()->CallHookUpdatingSign(this, a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4, a_Player))
+ if (cRoot::Get()->GetPluginManager()->CallHookUpdatingSign(*this, a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4, a_Player))
{
return false;
}
if (m_ChunkMap->SetSignLines(a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4))
{
- cRoot::Get()->GetPluginManager()->CallHookUpdatedSign(this, a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4, a_Player);
+ cRoot::Get()->GetPluginManager()->CallHookUpdatedSign(*this, a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4, a_Player);
return true;
}
return false;
@@ -3049,17 +3056,17 @@ void cWorld::SaveAllChunks(void)
void cWorld::QueueSaveAllChunks(void)
{
- QueueTask(new cWorld::cTaskSaveAllChunks);
+ QueueTask(make_unique<cWorld::cTaskSaveAllChunks>());
}
-void cWorld::QueueTask(cTask * a_Task)
+void cWorld::QueueTask(std::unique_ptr<cTask> a_Task)
{
cCSLock Lock(m_CSTasks);
- m_Tasks.push_back(a_Task);
+ m_Tasks.push_back(std::move(a_Task));
}
@@ -3076,11 +3083,11 @@ void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task)
{
if ((*itr)->m_TargetTick >= TargetTick)
{
- m_ScheduledTasks.insert(itr, new cScheduledTask(TargetTick, a_Task));
+ m_ScheduledTasks.insert(itr, make_unique<cScheduledTask>(TargetTick, a_Task));
return;
}
}
- m_ScheduledTasks.push_back(new cScheduledTask(TargetTick, a_Task));
+ m_ScheduledTasks.push_back(make_unique<cScheduledTask>(TargetTick, a_Task));
}
@@ -3633,7 +3640,7 @@ bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_Ch
void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerating(cChunkDesc & a_ChunkDesc)
{
cPluginManager::Get()->CallHookChunkGenerating(
- m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
+ *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
);
}
@@ -3644,7 +3651,7 @@ void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerating(cChunkDesc & a_Ch
void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_ChunkDesc)
{
cPluginManager::Get()->CallHookChunkGenerated(
- m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
+ *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
);
}
diff --git a/src/World.h b/src/World.h
index 90dada259..bb43d7fba 100644
--- a/src/World.h
+++ b/src/World.h
@@ -103,7 +103,7 @@ public:
virtual void Run(cWorld & a_World) = 0;
} ;
- typedef std::vector<cTask *> cTasks;
+ typedef std::vector<std::unique_ptr<cTask>> cTasks;
class cTaskSaveAllChunks :
@@ -298,7 +298,7 @@ public:
/** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/
void QueueUnloadUnusedChunks(void); // tolua_export
- void CollectPickupsByPlayer(cPlayer * a_Player);
+ void CollectPickupsByPlayer(cPlayer & a_Player);
/** Adds the player to the world.
Uses a queue to store the player object until the Tick thread processes the addition event.
@@ -506,7 +506,7 @@ public:
// tolua_end
- inline cSimulatorManager * GetSimulatorManager(void) { return m_SimulatorManager; }
+ inline cSimulatorManager * GetSimulatorManager(void) { return m_SimulatorManager.get(); }
inline cFluidSimulator * GetWaterSimulator(void) { return m_WaterSimulator; }
inline cFluidSimulator * GetLavaSimulator (void) { return m_LavaSimulator; }
@@ -671,7 +671,7 @@ public:
void QueueSaveAllChunks(void); // tolua_export
/** 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
+ void QueueTask(std::unique_ptr<cTask> a_Task); // Exported in ManualBindings.cpp
/** Queues a task onto the tick thread, with the specified delay.
The task object will be deleted once the task is finished */
@@ -764,7 +764,7 @@ public:
cChunkGenerator & GetGenerator(void) { return m_Generator; }
cWorldStorage & GetStorage (void) { return m_Storage; }
- cChunkMap * GetChunkMap (void) { return m_ChunkMap; }
+ cChunkMap * GetChunkMap (void) { return m_ChunkMap.get(); }
/** Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call */
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
@@ -861,7 +861,8 @@ private:
}
};
- typedef std::list<cScheduledTask *> cScheduledTasks;
+ typedef std::unique_ptr<cScheduledTask> cScheduledTaskPtr;
+ typedef std::list<cScheduledTaskPtr> cScheduledTasks;
AString m_WorldName;
@@ -913,11 +914,11 @@ private:
std::vector<BlockTickQueueItem *> m_BlockTickQueue;
std::vector<BlockTickQueueItem *> m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue
- cSimulatorManager * m_SimulatorManager;
- cSandSimulator * m_SandSimulator;
- cFluidSimulator * m_WaterSimulator;
- cFluidSimulator * m_LavaSimulator;
- cFireSimulator * m_FireSimulator;
+ std::unique_ptr<cSimulatorManager> m_SimulatorManager;
+ std::unique_ptr<cSandSimulator> m_SandSimulator;
+ cFluidSimulator * m_WaterSimulator;
+ cFluidSimulator * m_LavaSimulator;
+ std::unique_ptr<cFireSimulator> m_FireSimulator;
cRedstoneSimulator<cChunk, cWorld> * m_RedstoneSimulator;
cCriticalSection m_CSPlayers;
@@ -927,7 +928,7 @@ private:
unsigned int m_MaxPlayers;
- cChunkMap * m_ChunkMap;
+ std::unique_ptr<cChunkMap> m_ChunkMap;
bool m_bAnimals;
std::set<eMonsterType> m_AllowedMobs;