From 53e22b11857fed62e2313d6d84d90f88ed412ffb Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 29 Jul 2013 12:13:03 +0100 Subject: Changed everyting to Unix line endings. --- MCServer/Plugins/ChatLog/plugin.lua | 62 +- MCServer/Plugins/ChunkWorx/chunkworx_web.lua | 512 +++---- MCServer/Plugins/Debuggers/Debuggers.lua | 1488 ++++++++++---------- MCServer/Plugins/DiamondMover/DiamondMover.lua | 164 +-- MCServer/Plugins/Handy/handy.lua | 54 +- MCServer/Plugins/Handy/handy_functions.lua | 708 +++++----- MCServer/Plugins/HookNotify/HookNotify.lua | 808 +++++------ MCServer/Plugins/MagicCarpet/objects.lua | 192 +-- .../Plugins/ProtectionAreas/CommandHandlers.lua | 644 ++++----- MCServer/Plugins/ProtectionAreas/CommandState.lua | 242 ++-- MCServer/Plugins/ProtectionAreas/Config.lua | 108 +- MCServer/Plugins/ProtectionAreas/CurrentLng.lua | 152 +- MCServer/Plugins/ProtectionAreas/HookHandlers.lua | 278 ++-- MCServer/Plugins/ProtectionAreas/LICENSE.txt | 14 +- MCServer/Plugins/ProtectionAreas/PlayerAreas.lua | 218 +-- .../Plugins/ProtectionAreas/ProtectionAreas.lua | 142 +- MCServer/Plugins/ProtectionAreas/Storage.lua | 1036 +++++++------- MCServer/Plugins/SquirrelChatLog.nut | 26 +- MCServer/crafting.txt | 784 +++++------ MCServer/furnace.txt | 150 +- MCServer/groups.ini | 32 +- MCServer/hg.supp | 44 +- MCServer/items.ini | 1086 +++++++------- MCServer/monsters.ini | 220 +-- MCServer/settings.ini | 62 +- MCServer/terrain.ini | 16 +- MCServer/users.ini | 44 +- MCServer/webadmin.ini | 10 +- MCServer/webadmin/template.html | 290 ++-- 29 files changed, 4793 insertions(+), 4793 deletions(-) (limited to 'MCServer') diff --git a/MCServer/Plugins/ChatLog/plugin.lua b/MCServer/Plugins/ChatLog/plugin.lua index c8358a6d3..c2f6fb81a 100644 --- a/MCServer/Plugins/ChatLog/plugin.lua +++ b/MCServer/Plugins/ChatLog/plugin.lua @@ -1,32 +1,32 @@ - --- 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) - - PluginManager = cRoot:Get():GetPluginManager() - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT) - - LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) - return true -end - - - - - -function OnChat(Player, Message) - -- Lets get loggin' - LOGINFO("[" .. Player:GetName() .. "]: " .. StripColorCodes(Message)); - - return false + +-- 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) + + PluginManager = cRoot:Get():GetPluginManager() + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT) + + 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/chunkworx_web.lua b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua index aeccb9719..e9a930c92 100644 --- a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua +++ b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua @@ -1,257 +1,257 @@ -local function Buttons_Player( Name ) - return "
" -end - -local function Button_World( Name ) - return "
" -end - -function HandleRequest_Generation( Request ) - local Content = "" - if (Request.PostParams["AGHRRRR"] ~= nil) then - GENERATION_STATE = 0 - WW_instance:SaveAllChunks() - WW_instance:UnloadUnusedChunks() - LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin") - end - --Content = Content .. "" - -- PROCESSING - -------------------------------------------------------------------------------------------------- - local function ProcessingContent() - local _small_content = "" - _small_content = _small_content .. "" - _small_content = _small_content .. "

World for operations:

"..WORK_WORLD - if (OPERATION_CODE == 0) then - _small_content = _small_content .. "

Operation:

Generation" - elseif (OPERATION_CODE == 1) then - _small_content = _small_content .. "

Operation:

Regeneration" - end - _small_content = _small_content .. "

Area:

["..AreaStartX..":"..AreaStartZ.."] ["..AreaEndX..":"..AreaEndZ.."]" - _small_content = _small_content .. "

Progress:

"..CURRENT.."/"..TOTAL - _small_content = _small_content .. "
" - _small_content = _small_content .. "
" - _small_content = _small_content .. "" - _small_content = _small_content .. "
" - 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"]) - - PLUGIN.IniFile:DeleteValue("Area data", "StartX") - PLUGIN.IniFile:DeleteValue("Area data", "StartZ") - PLUGIN.IniFile:DeleteValue("Area data", "EndX") - PLUGIN.IniFile:DeleteValue("Area data", "EndZ") - PLUGIN.IniFile:SetValueI("Area data", "StartX", AreaStartX) - PLUGIN.IniFile:SetValueI("Area data", "StartZ", AreaStartZ) - PLUGIN.IniFile:SetValueI("Area data", "EndX", AreaEndX) - PLUGIN.IniFile:SetValueI("Area data", "EndZ", AreaEndZ) - if (OPERATION_CODE == 0) then - GENERATION_STATE = 1 - elseif (OPERATION_CODE == 1) then - GENERATION_STATE = 3 - end - PLUGIN.IniFile:WriteFile() - 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"]) - RadialZ = tonumber(Request.PostParams["FormRadialZ"]) - Radius = tonumber(Request.PostParams["FormRadius"]) - AreaStartX = RadialX - Radius - AreaStartZ = RadialZ - Radius - AreaEndX = RadialX + Radius - AreaEndZ = RadialZ + Radius - - PLUGIN.IniFile:DeleteValue("Radial data", "RadialX") - PLUGIN.IniFile:DeleteValue("Radial data", "RadialZ") - PLUGIN.IniFile:DeleteValue("Radial data", "Radius") - PLUGIN.IniFile:SetValueI("Radial data", "RadialX", RadialX) - PLUGIN.IniFile:SetValueI("Radial data", "RadialZ", RadialZ) - PLUGIN.IniFile:SetValueI("Radial data", "Radius", Radius) - if (OPERATION_CODE == 0) then - GENERATION_STATE = 1 - elseif (OPERATION_CODE == 1) then - GENERATION_STATE = 3 - end - PLUGIN.IniFile:WriteFile() - 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 .. "

World for operations: " .. WORK_WORLD .. "

" - --Content = Content .. "
" - --Content = Content .. "" - --Content = Content .. "
" - - -- SELECTING WORK_WORLD - Content = Content .. "

World for operations: " .. WORK_WORLD .. "

" - Content = Content .. "" - local WorldNum = 0 - local AddWorldToTable = function(World) - WorldNum = WorldNum + 1 - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - end - cRoot:Get():ForEachWorld(AddWorldToTable) - if( WorldNum == 0 ) then - Content = Content .. "" - end - Content = Content .. "
" .. WorldNum .. "." .. World:GetName() .. "" .. Button_World(World:GetName()) .. "
No worlds! O_O
" - Content = Content .. "
" - - -- SELECTING OPERATION - if (OPERATION_CODE == 0) then - Content = Content .. "

Operation: Generation

" - elseif (OPERATION_CODE == 1) then - Content = Content .. "

Operation: Regeneration

" - end - Content = Content .. "
" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "
" - - -- SELECTING AREA - Content = Content .. "

Area:

Start X, Start Z; End X, End Z" - Content = Content .. "
" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "
" - - -- SELECTING RADIAL - Content = Content .. "

Radial:

Center X, Center Z, Raduis (0 to any)" - Content = Content .. "
" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "
" - Content = Content .. "
" - Content = Content .. "
" - Content = Content .. "
" - - -- SELECTING POINT - Content = Content .. "

Point regeneration:

X, Z" - Content = Content .. "
" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "
" - - -- SELECTING PLAYERS - Content = Content .. "

Player-based regeneration:

" - Content = Content .. "" - local PlayerNum = 0 - local AddPlayerToTable = function( Player ) - PlayerNum = PlayerNum + 1 - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - Content = Content .. "" - end - if (cRoot:Get():GetWorld(WORK_WORLD) == nil) then - Content = Content .. "" - else - cRoot:Get():GetWorld(WORK_WORLD):ForEachPlayer( AddPlayerToTable ) - if( PlayerNum == 0 ) then - Content = Content .. "" - end - end - Content = Content .. "
" .. PlayerNum .. "." .. Player:GetName() .. "" .. Buttons_Player(Player:GetName()) .. "
Incorrect world selection
No connected players
" - Content = Content .. "
" - return Content +local function Buttons_Player( Name ) + return "
" +end + +local function Button_World( Name ) + return "
" +end + +function HandleRequest_Generation( Request ) + local Content = "" + if (Request.PostParams["AGHRRRR"] ~= nil) then + GENERATION_STATE = 0 + WW_instance:SaveAllChunks() + WW_instance:UnloadUnusedChunks() + LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin") + end + --Content = Content .. "" + -- PROCESSING + -------------------------------------------------------------------------------------------------- + local function ProcessingContent() + local _small_content = "" + _small_content = _small_content .. "" + _small_content = _small_content .. "

World for operations:

"..WORK_WORLD + if (OPERATION_CODE == 0) then + _small_content = _small_content .. "

Operation:

Generation" + elseif (OPERATION_CODE == 1) then + _small_content = _small_content .. "

Operation:

Regeneration" + end + _small_content = _small_content .. "

Area:

["..AreaStartX..":"..AreaStartZ.."] ["..AreaEndX..":"..AreaEndZ.."]" + _small_content = _small_content .. "

Progress:

"..CURRENT.."/"..TOTAL + _small_content = _small_content .. "
" + _small_content = _small_content .. "
" + _small_content = _small_content .. "" + _small_content = _small_content .. "
" + 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"]) + + PLUGIN.IniFile:DeleteValue("Area data", "StartX") + PLUGIN.IniFile:DeleteValue("Area data", "StartZ") + PLUGIN.IniFile:DeleteValue("Area data", "EndX") + PLUGIN.IniFile:DeleteValue("Area data", "EndZ") + PLUGIN.IniFile:SetValueI("Area data", "StartX", AreaStartX) + PLUGIN.IniFile:SetValueI("Area data", "StartZ", AreaStartZ) + PLUGIN.IniFile:SetValueI("Area data", "EndX", AreaEndX) + PLUGIN.IniFile:SetValueI("Area data", "EndZ", AreaEndZ) + if (OPERATION_CODE == 0) then + GENERATION_STATE = 1 + elseif (OPERATION_CODE == 1) then + GENERATION_STATE = 3 + end + PLUGIN.IniFile:WriteFile() + 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"]) + RadialZ = tonumber(Request.PostParams["FormRadialZ"]) + Radius = tonumber(Request.PostParams["FormRadius"]) + AreaStartX = RadialX - Radius + AreaStartZ = RadialZ - Radius + AreaEndX = RadialX + Radius + AreaEndZ = RadialZ + Radius + + PLUGIN.IniFile:DeleteValue("Radial data", "RadialX") + PLUGIN.IniFile:DeleteValue("Radial data", "RadialZ") + PLUGIN.IniFile:DeleteValue("Radial data", "Radius") + PLUGIN.IniFile:SetValueI("Radial data", "RadialX", RadialX) + PLUGIN.IniFile:SetValueI("Radial data", "RadialZ", RadialZ) + PLUGIN.IniFile:SetValueI("Radial data", "Radius", Radius) + if (OPERATION_CODE == 0) then + GENERATION_STATE = 1 + elseif (OPERATION_CODE == 1) then + GENERATION_STATE = 3 + end + PLUGIN.IniFile:WriteFile() + 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 .. "

World for operations: " .. WORK_WORLD .. "

" + --Content = Content .. "
" + --Content = Content .. "" + --Content = Content .. "
" + + -- SELECTING WORK_WORLD + Content = Content .. "

World for operations: " .. WORK_WORLD .. "

" + Content = Content .. "" + local WorldNum = 0 + local AddWorldToTable = function(World) + WorldNum = WorldNum + 1 + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + end + cRoot:Get():ForEachWorld(AddWorldToTable) + if( WorldNum == 0 ) then + Content = Content .. "" + end + Content = Content .. "
" .. WorldNum .. "." .. World:GetName() .. "" .. Button_World(World:GetName()) .. "
No worlds! O_O
" + Content = Content .. "
" + + -- SELECTING OPERATION + if (OPERATION_CODE == 0) then + Content = Content .. "

Operation: Generation

" + elseif (OPERATION_CODE == 1) then + Content = Content .. "

Operation: Regeneration

" + end + Content = Content .. "
" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "
" + + -- SELECTING AREA + Content = Content .. "

Area:

Start X, Start Z; End X, End Z" + Content = Content .. "
" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "
" + + -- SELECTING RADIAL + Content = Content .. "

Radial:

Center X, Center Z, Raduis (0 to any)" + Content = Content .. "
" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "
" + Content = Content .. "
" + Content = Content .. "
" + Content = Content .. "
" + + -- SELECTING POINT + Content = Content .. "

Point regeneration:

X, Z" + Content = Content .. "
" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "
" + + -- SELECTING PLAYERS + Content = Content .. "

Player-based regeneration:

" + Content = Content .. "" + local PlayerNum = 0 + local AddPlayerToTable = function( Player ) + PlayerNum = PlayerNum + 1 + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + Content = Content .. "" + end + if (cRoot:Get():GetWorld(WORK_WORLD) == nil) then + Content = Content .. "" + else + cRoot:Get():GetWorld(WORK_WORLD):ForEachPlayer( AddPlayerToTable ) + if( PlayerNum == 0 ) then + Content = Content .. "" + end + end + Content = Content .. "
" .. PlayerNum .. "." .. Player:GetName() .. "" .. Buttons_Player(Player:GetName()) .. "
Incorrect world selection
No connected players
" + Content = Content .. "
" + return Content end \ No newline at end of file diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index 1bc625c35..53b192656 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -1,744 +1,744 @@ - --- Global variables -PLUGIN = {}; -- Reference to own plugin object -ShouldDumpFunctions = true; -- If set to true, all available functions are written to the API.txt file upon plugin initialization - -g_DropSpensersToActivate = {}; -- A list of dispensers and droppers (as {World, X, Y Z} quadruplets) that are to be activated every tick - -g_HungerReportTick = 10; - - - - - -function Initialize(Plugin) - PLUGIN = Plugin - - Plugin:SetName("Debuggers") - Plugin:SetVersion(1) - - PluginManager = cRoot:Get():GetPluginManager() - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_ITEM); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_TAKE_DAMAGE); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_TICK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT); - - PluginManager:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "Shows a list of all the loaded entities"); - PluginManager:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "Kills all the loaded entities"); - PluginManager:BindCommand("/wool", "debuggers", HandleWoolCmd, "Sets all your armor to blue wool"); - PluginManager:BindCommand("/testwnd", "debuggers", HandleTestWndCmd, "Opens up a window using plugin API"); - PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "Activates the Lua garbage collector"); - PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "Switches between fast and normal movement speed"); - PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "Switches between fast and normal sprinting speed"); - PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "Lists the current hunger-related variables"); - PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "Sets food-poisoning for 15 seconds"); - PluginManager:BindCommand("/starve", "debuggers", HandleStarveCmd, "Sets the food level to zero"); - PluginManager:BindCommand("/fl", "debuggers", HandleFoodLevelCmd, "Sets the food level to the given value"); - - -- Enable the following line for BlockArea / Generator interface testing: - -- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); - - LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) - - -- dump all available API functions and objects: - if (ShouldDumpFunctions) then - DumpAPI(); - end - - - -- TestBlockAreas(); - -- TestSQLiteBindings(); - -- TestExpatBindings(); - - return true -end; - - - - - -function DumpAPI() - LOG("Dumping all available functions to API.txt..."); - function dump (prefix, a, Output) - for i, v in pairs (a) do - if (type(v) == "table") then - if (GetChar(i, 1) ~= ".") then - if (v == _G) then - LOG(prefix .. i .. " == _G, CYCLE, ignoring"); - elseif (v == _G.package) then - LOG(prefix .. i .. " == _G.package, ignoring"); - else - dump(prefix .. i .. ".", v, Output) - end - end - elseif (type(v) == "function") then - if (string.sub(i, 1, 2) ~= "__") then - table.insert(Output, prefix .. i .. "()"); - end - end - end - end - - local Output = {}; - dump("", _G, Output); - - table.sort(Output); - local f = io.open("API.txt", "w"); - for i, n in ipairs(Output) do - f:write(n, "\n"); - end - f:close(); - LOG("API.txt written."); -end - - - - - -function TestBlockAreas() - LOG("Testing block areas..."); - - -- Debug block area merging: - local BA1 = cBlockArea(); - local BA2 = cBlockArea(); - if (BA1:LoadFromSchematicFile("schematics/test.schematic")) then - if (BA2:LoadFromSchematicFile("schematics/fountain.schematic")) then - BA2:SetRelBlockType(0, 0, 0, E_BLOCK_LAPIS_BLOCK); - BA2:SetRelBlockType(1, 0, 0, E_BLOCK_LAPIS_BLOCK); - BA2:SetRelBlockType(2, 0, 0, E_BLOCK_LAPIS_BLOCK); - BA1:Merge(BA2, 1, 10, 1, cBlockArea.msImprint); - BA1:SaveToSchematicFile("schematics/merge.schematic"); - end - else - BA1:Create(16, 16, 16); - end - - -- Debug block area cuboid filling: - BA1:FillRelCuboid(2, 9, 2, 8, 2, 8, cBlockArea.baTypes, E_BLOCK_GOLD_BLOCK); - BA1:RelLine(2, 2, 2, 9, 8, 8, cBlockArea.baTypes or cBlockArea.baMetas, E_BLOCK_SAPLING, E_META_SAPLING_BIRCH); - BA1:SaveToSchematicFile("schematics/fillrel.schematic"); - - -- Debug block area mirroring: - if (BA1:LoadFromSchematicFile("schematics/lt.schematic")) then - BA1:MirrorXYNoMeta(); - BA1:SaveToSchematicFile("schematics/lt_XY.schematic"); - BA1:MirrorXYNoMeta(); - BA1:SaveToSchematicFile("schematics/lt_XY2.schematic"); - - BA1:MirrorXZNoMeta(); - BA1:SaveToSchematicFile("schematics/lt_XZ.schematic"); - BA1:MirrorXZNoMeta(); - BA1:SaveToSchematicFile("schematics/lt_XZ2.schematic"); - - BA1:MirrorYZNoMeta(); - BA1:SaveToSchematicFile("schematics/lt_YZ.schematic"); - BA1:MirrorYZNoMeta(); - BA1:SaveToSchematicFile("schematics/lt_YZ2.schematic"); - end - - -- Debug block area rotation: - if (BA1:LoadFromSchematicFile("schematics/rot.schematic")) then - BA1:RotateCWNoMeta(); - BA1:SaveToSchematicFile("schematics/rot1.schematic"); - BA1:RotateCWNoMeta(); - BA1:SaveToSchematicFile("schematics/rot2.schematic"); - BA1:RotateCWNoMeta(); - BA1:SaveToSchematicFile("schematics/rot3.schematic"); - BA1:RotateCWNoMeta(); - BA1:SaveToSchematicFile("schematics/rot4.schematic"); - end - - -- Debug block area rotation: - if (BA1:LoadFromSchematicFile("schematics/rotm.schematic")) then - BA1:RotateCCW(); - BA1:SaveToSchematicFile("schematics/rotm1.schematic"); - BA1:RotateCCW(); - BA1:SaveToSchematicFile("schematics/rotm2.schematic"); - BA1:RotateCCW(); - BA1:SaveToSchematicFile("schematics/rotm3.schematic"); - BA1:RotateCCW(); - BA1:SaveToSchematicFile("schematics/rotm4.schematic"); - end - - -- Debug block area mirroring: - if (BA1:LoadFromSchematicFile("schematics/ltm.schematic")) then - BA1:MirrorXY(); - BA1:SaveToSchematicFile("schematics/ltm_XY.schematic"); - BA1:MirrorXY(); - BA1:SaveToSchematicFile("schematics/ltm_XY2.schematic"); - - BA1:MirrorXZ(); - BA1:SaveToSchematicFile("schematics/ltm_XZ.schematic"); - BA1:MirrorXZ(); - BA1:SaveToSchematicFile("schematics/ltm_XZ2.schematic"); - - BA1:MirrorYZ(); - BA1:SaveToSchematicFile("schematics/ltm_YZ.schematic"); - BA1:MirrorYZ(); - BA1:SaveToSchematicFile("schematics/ltm_YZ2.schematic"); - end - - LOG("Block areas test ended"); -end - - - - - - -function TestSQLiteBindings() - LOG("Testing SQLite bindings..."); - - -- Debug SQLite binding - local TestDB, ErrCode, ErrMsg = sqlite3.open("test.sqlite"); - if (TestDB ~= nil) then - local function ShowRow(UserData, NumCols, Values, Names) - assert(UserData == 'UserData'); - LOG("New row"); - for i = 1, NumCols do - LOG(" " .. Names[i] .. " = " .. Values[i]); - end - return 0; - end - local sql = [=[ - CREATE TABLE numbers(num1,num2,str); - INSERT INTO numbers VALUES(1, 11, "ABC"); - INSERT INTO numbers VALUES(2, 22, "DEF"); - INSERT INTO numbers VALUES(3, 33, "UVW"); - INSERT INTO numbers VALUES(4, 44, "XYZ"); - SELECT * FROM numbers; - ]=] - local Res = TestDB:exec(sql, ShowRow, 'UserData'); - if (Res ~= sqlite3.OK) then - LOG("TestDB:exec() failed: " .. Res .. " (" .. TestDB:errmsg() .. ")"); - end; - TestDB:close(); - else - -- This happens if for example SQLite cannot open the file (eg. a folder with the same name exists) - LOG("SQLite3 failed to open DB! (" .. ErrCode .. ", " .. ErrMsg ..")"); - end - - LOG("SQLite bindings test ended"); -end - - - - - -function TestExpatBindings() - LOG("Testing Expat bindings..."); - - -- Debug LuaExpat bindings: - local count = 0 - callbacks = { - StartElement = function (parser, name) - LOG("+ " .. string.rep(" ", count) .. name); - count = count + 1; - end, - EndElement = function (parser, name) - count = count - 1; - LOG("- " .. string.rep(" ", count) .. name); - end - } - - local p = lxp.new(callbacks); - p:parse("\nnext line\nanother line"); - p:parse("text\n"); - p:parse("\n"); - p:parse("more text"); - p:parse(""); - p:parse("\n"); - p:parse(); -- finishes the document - p:close(); -- closes the parser - - LOG("Expat bindings test ended"); -end - - - - - -function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) - -- Magic rod of query: show block types and metas for both neighbors of the pointed face - local Type, Meta, Valid = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ, Type, Meta); - - if (Type == E_BLOCK_AIR) then - Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta); - else - local TempItem = cItem(Type, 1, Meta); - Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")"); - end - - local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace); - Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z, Type, Meta); - if (Type == E_BLOCK_AIR) then - Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta); - else - local TempItem = cItem(Type, 1, Meta); - Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")"); - end - return false; -end - - - - - -function OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) - -- Rclk with a diamond to test block area cropping and expanding - local Area = cBlockArea(); - Area:Read(Player:GetWorld(), - BlockX - 19, BlockX + 19, - BlockY - 7, BlockY + 7, - BlockZ - 19, BlockZ + 19 - ); - - LOG("Size before cropping: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("crop0.dat"); - - Area:Crop(2, 3, 0, 0, 0, 0); - LOG("Size after cropping 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("crop1.dat"); - - Area:Crop(2, 3, 0, 0, 0, 0); - LOG("Size after cropping 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("crop2.dat"); - - Area:Expand(2, 3, 0, 0, 0, 0); - LOG("Size after expanding 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("expand1.dat"); - - Area:Expand(3, 2, 1, 1, 0, 0); - LOG("Size after expanding 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("expand2.dat"); - - Area:Crop(0, 0, 0, 0, 3, 2); - LOG("Size after cropping 3: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("crop3.dat"); - - Area:Crop(0, 0, 3, 2, 0, 0); - LOG("Size after cropping 4: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); - Area:DumpToRawFile("crop4.dat"); - - LOG("Crop test done"); - Player:SendMessage("Crop / expand test done."); - return false; -end - - - - - -function OnUsingEyeOfEnder(Player, BlockX, BlockY, BlockZ) - -- Rclk with an eye of ender places a predefined schematic at the cursor - local Area = cBlockArea(); - if not(Area:LoadFromSchematicFile("schematics/test.schematic")) then - LOG("Loading failed"); - return false; - end - LOG("Schematic loaded, placing now."); - Area:Write(Player:GetWorld(), BlockX, BlockY, BlockZ); - LOG("Done."); - return false; -end - - - - - -function OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) - -- Rclk with an ender pearl saves a predefined area around the cursor into a .schematic file. Also tests area copying - local Area = cBlockArea(); - if not(Area:Read(Player:GetWorld(), - BlockX - 8, BlockX + 8, BlockY - 8, BlockY + 8, BlockZ - 8, BlockZ + 8) - ) then - LOG("LUA: Area couldn't be read"); - return false; - end - LOG("LUA: Area read, copying now."); - local Area2 = cBlockArea(); - Area2:CopyFrom(Area); - LOG("LUA: Copied, now saving."); - if not(Area2:SaveToSchematicFile("schematics/test.schematic")) then - LOG("LUA: Cannot save schematic file."); - return false; - end - LOG("LUA: Done."); - return false; -end - - - - - -function OnUsingRedstoneTorch(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) - -- Redstone torch activates a rapid dispenser / dropper discharge (at every tick): - local BlockType = Player:GetWorld():GetBlock(BlockX, BlockY, BlockZ); - if (BlockType == E_BLOCK_DISPENSER) then - table.insert(g_DropSpensersToActivate, {World = Player:GetWorld(), x = BlockX, y = BlockY, z = BlockZ}); - Player:SendMessage("Dispenser at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging"); - return true; - elseif (BlockType == E_BLOCK_DROPPER) then - table.insert(g_DropSpensersToActivate, {World = Player:GetWorld(), x = BlockX, y = BlockY, z = BlockZ}); - Player:SendMessage("Dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging"); - return true; - else - Player:SendMessage("Neither a dispenser nor a dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. BlockType); - end - return false; -end - - - - - -function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) - - -- dont check if the direction is in the air - if (BlockFace == BLOCK_FACE_NONE) then - return false - end - - local HeldItem = Player:GetEquippedItem(); - local HeldItemType = HeldItem.m_ItemType; - - if (HeldItemType == E_ITEM_STICK) then - -- Magic sTick of ticking: set the pointed block for ticking at the next tick - Player:SendMessage(cChatColor.LightGray .. "Setting next block tick to {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}") - Player:GetWorld():SetNextBlockTick(BlockX, BlockY, BlockZ); - return true - elseif (HeldItemType == E_ITEM_BLAZE_ROD) then - return OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); - elseif (HeldItemType == E_ITEM_DIAMOND) then - return OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); - elseif (HeldItemType == E_ITEM_EYE_OF_ENDER) then - return OnUsingEyeOfEnder(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); - elseif (HeldItemType == E_ITEM_ENDER_PEARL) then - return OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); - end - return false; -end - - - - - -function OnPlayerUsingBlock(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ, BlockType, BlockMeta) - -- dont check if the direction is in the air - if (BlockFace == BLOCK_FACE_NONE) then - return false - end - - local HeldItem = Player:GetEquippedItem(); - local HeldItemType = HeldItem.m_ItemType; - - if (HeldItemType == E_BLOCK_REDSTONE_TORCH_ON) then - return OnUsingRedstoneTorch(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); - end -end - - - - - -function OnTakeDamage(Receiver, TDI) - -- Receiver is cPawn - -- TDI is TakeDamageInfo - - LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)"); - return false; -end - - - - - ---- When set to a positive number, the following OnTick() will perform GC and decrease until 0 again -GCOnTick = 0; - - - - - -function OnTick() - -- Activate all dropspensers in the g_DropSpensersToActivate list: - local ActivateDrSp = function(DropSpenser) - if (DropSpenser:GetContents():GetFirstUsedSlot() == -1) then - return true; - end - DropSpenser:Activate(); - return false; - end - -- Walk the list backwards, because we're removing some items - local idx = #g_DropSpensersToActivate; - for i = idx, 1, -1 do - local DrSp = g_DropSpensersToActivate[i]; - if not(DrSp.World:DoWithDropSpenserAt(DrSp.x, DrSp.y, DrSp.z, ActivateDrSp)) then - table.remove(g_DropSpensersToActivate, i); - end - end - - - -- If GCOnTick > 0, do a garbage-collect and decrease by one - if (GCOnTick > 0) then - collectgarbage(); - GCOnTick = GCOnTick - 1; - end - - --[[ - if (g_HungerReportTick > 0) then - g_HungerReportTick = g_HungerReportTick - 1; - else - g_HungerReportTick = 10; - cRoot:Get():GetDefaultWorld():ForEachPlayer( - function(a_Player) - a_Player:SendMessage("FoodStat: " .. a_Player:GetFoodLevel() .. " / " .. a_Player:GetFoodExhaustionLevel()); - end - ); - end - ]] - - return false; -end - - - - - -function OnChunkGenerated(World, ChunkX, ChunkZ, ChunkDesc) - -- Test ChunkDesc / BlockArea interaction - local BlockArea = cBlockArea(); - ChunkDesc:ReadBlockArea(BlockArea, 0, 15, 50, 70, 0, 15); - - -- BlockArea:SaveToSchematicFile("ChunkBlocks_" .. ChunkX .. "_" .. ChunkZ .. ".schematic"); - - ChunkDesc:WriteBlockArea(BlockArea, 5, 115, 5); - return false; -end - - - - - -function OnChat(a_Player, a_Message) - return false, "blabla " .. a_Message; -end - - - - - --- Function "round" copied from http://lua-users.org/wiki/SimpleRound -function round(num, idp) - local mult = 10^(idp or 0) - if num >= 0 then return math.floor(num * mult + 0.5) / mult - else return math.ceil(num * mult - 0.5) / mult end -end - - - - - -function HandleListEntitiesCmd(Split, Player) - local NumEntities = 0; - - local ListEntity = function(Entity) - if (Entity:IsDestroyed()) then - -- The entity has already been destroyed, don't list it - return false; - end; - Player:SendMessage(" " .. Entity:GetUniqueID() .. ": " .. Entity:GetClass() .. " {" .. round(Entity:GetPosX(), 2) .. ", " .. round(Entity:GetPosY(), 2) .. ", " .. round(Entity:GetPosZ(), 2) .."}"); - NumEntities = NumEntities + 1; - end - - Player:SendMessage("Listing all entities..."); - Player:GetWorld():ForEachEntity(ListEntity); - Player:SendMessage("List finished, " .. NumEntities .. " entities listed"); - return true; -end - - - - - -function HandleKillEntitiesCmd(Split, Player) - local NumEntities = 0; - - local KillEntity = function(Entity) - -- kill everything except for players: - if (Entity:GetEntityType() ~= cEntity.etPlayer) then - Entity:Destroy(); - NumEntities = NumEntities + 1; - end; - end - - Player:SendMessage("Killing all entities..."); - Player:GetWorld():ForEachEntity(KillEntity); - Player:SendMessage("Killed " .. NumEntities .. " entities."); - return true; -end - - - - - -function HandleWoolCmd(Split, Player) - local Wool = cItem(E_BLOCK_WOOL, 1, E_META_WOOL_BLUE); - Player:GetInventory():SetArmorSlot(0, Wool); - Player:GetInventory():SetArmorSlot(1, Wool); - Player:GetInventory():SetArmorSlot(2, Wool); - Player:GetInventory():SetArmorSlot(3, Wool); - Player:SendMessage("You have been bluewooled :)"); - return true; -end - - - - - -function HandleTestWndCmd(a_Split, a_Player) - local WindowType = cWindow.Hopper; - local WindowSizeX = 5; - local WindowSizeY = 1; - if (#a_Split == 4) then - WindowType = tonumber(a_Split[2]); - WindowSizeX = tonumber(a_Split[3]); - WindowSizeY = tonumber(a_Split[4]); - elseif (#a_Split ~= 1) then - a_Player:SendMessage("Usage: /testwnd [WindowType WindowSizeX WindowSizeY]"); - return true; - end - - -- Test out the OnClosing callback's ability to refuse to close the window - local attempt = 1; - local OnClosing = function(Window, Player, CanRefuse) - Player:SendMessage("Window closing attempt #" .. attempt .. "; CanRefuse = " .. tostring(CanRefuse)); - attempt = attempt + 1; - return CanRefuse and (attempt <= 3); -- refuse twice, then allow, unless CanRefuse is set to true - end - - -- Log the slot changes - local OnSlotChanged = function(Window, SlotNum) - LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed."); - end - - local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd"); - local Item2 = cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1"); - local Item3 = cItem(E_ITEM_DIAMOND_SHOVEL); - Item3.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 4); - local Item4 = cItem(Item3); -- Copy - Item4.m_Enchantments:SetLevel(cEnchantments.enchEfficiency, 3); -- Add enchantment - Item4.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 5); -- Overwrite existing level - local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3"); - Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64)); - Window:SetSlot(a_Player, 1, Item2); - Window:SetSlot(a_Player, 2, Item3); - Window:SetSlot(a_Player, 3, Item4); - Window:SetSlot(a_Player, 4, Item5); - Window:SetOnClosing(OnClosing); - Window:SetOnSlotChanged(OnSlotChanged); - - a_Player:OpenWindow(Window); - - -- To make sure that the object has the correct life-management in Lua, - -- let's garbage-collect in the following few ticks - GCOnTick = 10; - - return true; -end - - - - - -function HandleGCCmd(a_Split, a_Player) - collectgarbage(); - return true; -end - - - - - - -function HandleFastCmd(a_Split, a_Player) - if (a_Player:GetNormalMaxSpeed() <= 0.11) then - -- The player has normal speed, set double speed: - a_Player:SetNormalMaxSpeed(0.2); - a_Player:SendMessage("You are now fast"); - else - -- The player has fast speed, set normal speed: - a_Player:SetNormalMaxSpeed(0.1); - a_Player:SendMessage("Back to normal speed"); - end - return true; -end - - - - - -function HandleDashCmd(a_Split, a_Player) - if (a_Player:GetSprintingMaxSpeed() <= 0.14) then - -- The player has normal sprinting speed, set double Sprintingspeed: - a_Player:SetSprintingMaxSpeed(0.4); - a_Player:SendMessage("You can now sprint very fast"); - else - -- The player has fast sprinting speed, set normal sprinting speed: - a_Player:SetSprintingMaxSpeed(0.13); - a_Player:SendMessage("Back to normal sprinting"); - end - return true; -end; - - - - - -function HandleHungerCmd(a_Split, a_Player) - a_Player:SendMessage("FoodLevel: " .. a_Player:GetFoodLevel()); - a_Player:SendMessage("FoodSaturationLevel: " .. a_Player:GetFoodSaturationLevel()); - a_Player:SendMessage("FoodTickTimer: " .. a_Player:GetFoodTickTimer()); - a_Player:SendMessage("FoodExhaustionLevel: " .. a_Player:GetFoodExhaustionLevel()); - a_Player:SendMessage("FoodPoisonedTicksRemaining: " .. a_Player:GetFoodPoisonedTicksRemaining()); - return true; -end - - - - - -function HandlePoisonCmd(a_Split, a_Player) - a_Player:FoodPoison(15 * 20); - return true; -end - - - - - -function HandleStarveCmd(a_Split, a_Player) - a_Player:SetFoodLevel(0); - a_Player:SendMessage("You are now starving"); - return true; -end - - - - - -function HandleFoodLevelCmd(a_Split, a_Player) - if (#a_Split ~= 2) then - a_Player:SendMessage("Missing an argument: the food level to set"); - return true; - end - - a_Player:SetFoodLevel(tonumber(a_Split[2])); - a_Player:SendMessage("Food level set to " .. a_Player:GetFoodLevel()); - return true; -end - - - - + +-- Global variables +PLUGIN = {}; -- Reference to own plugin object +ShouldDumpFunctions = true; -- If set to true, all available functions are written to the API.txt file upon plugin initialization + +g_DropSpensersToActivate = {}; -- A list of dispensers and droppers (as {World, X, Y Z} quadruplets) that are to be activated every tick + +g_HungerReportTick = 10; + + + + + +function Initialize(Plugin) + PLUGIN = Plugin + + Plugin:SetName("Debuggers") + Plugin:SetVersion(1) + + PluginManager = cRoot:Get():GetPluginManager() + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_ITEM); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_TAKE_DAMAGE); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_TICK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT); + + PluginManager:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "Shows a list of all the loaded entities"); + PluginManager:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "Kills all the loaded entities"); + PluginManager:BindCommand("/wool", "debuggers", HandleWoolCmd, "Sets all your armor to blue wool"); + PluginManager:BindCommand("/testwnd", "debuggers", HandleTestWndCmd, "Opens up a window using plugin API"); + PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "Activates the Lua garbage collector"); + PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "Switches between fast and normal movement speed"); + PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "Switches between fast and normal sprinting speed"); + PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "Lists the current hunger-related variables"); + PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "Sets food-poisoning for 15 seconds"); + PluginManager:BindCommand("/starve", "debuggers", HandleStarveCmd, "Sets the food level to zero"); + PluginManager:BindCommand("/fl", "debuggers", HandleFoodLevelCmd, "Sets the food level to the given value"); + + -- Enable the following line for BlockArea / Generator interface testing: + -- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); + + LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) + + -- dump all available API functions and objects: + if (ShouldDumpFunctions) then + DumpAPI(); + end + + + -- TestBlockAreas(); + -- TestSQLiteBindings(); + -- TestExpatBindings(); + + return true +end; + + + + + +function DumpAPI() + LOG("Dumping all available functions to API.txt..."); + function dump (prefix, a, Output) + for i, v in pairs (a) do + if (type(v) == "table") then + if (GetChar(i, 1) ~= ".") then + if (v == _G) then + LOG(prefix .. i .. " == _G, CYCLE, ignoring"); + elseif (v == _G.package) then + LOG(prefix .. i .. " == _G.package, ignoring"); + else + dump(prefix .. i .. ".", v, Output) + end + end + elseif (type(v) == "function") then + if (string.sub(i, 1, 2) ~= "__") then + table.insert(Output, prefix .. i .. "()"); + end + end + end + end + + local Output = {}; + dump("", _G, Output); + + table.sort(Output); + local f = io.open("API.txt", "w"); + for i, n in ipairs(Output) do + f:write(n, "\n"); + end + f:close(); + LOG("API.txt written."); +end + + + + + +function TestBlockAreas() + LOG("Testing block areas..."); + + -- Debug block area merging: + local BA1 = cBlockArea(); + local BA2 = cBlockArea(); + if (BA1:LoadFromSchematicFile("schematics/test.schematic")) then + if (BA2:LoadFromSchematicFile("schematics/fountain.schematic")) then + BA2:SetRelBlockType(0, 0, 0, E_BLOCK_LAPIS_BLOCK); + BA2:SetRelBlockType(1, 0, 0, E_BLOCK_LAPIS_BLOCK); + BA2:SetRelBlockType(2, 0, 0, E_BLOCK_LAPIS_BLOCK); + BA1:Merge(BA2, 1, 10, 1, cBlockArea.msImprint); + BA1:SaveToSchematicFile("schematics/merge.schematic"); + end + else + BA1:Create(16, 16, 16); + end + + -- Debug block area cuboid filling: + BA1:FillRelCuboid(2, 9, 2, 8, 2, 8, cBlockArea.baTypes, E_BLOCK_GOLD_BLOCK); + BA1:RelLine(2, 2, 2, 9, 8, 8, cBlockArea.baTypes or cBlockArea.baMetas, E_BLOCK_SAPLING, E_META_SAPLING_BIRCH); + BA1:SaveToSchematicFile("schematics/fillrel.schematic"); + + -- Debug block area mirroring: + if (BA1:LoadFromSchematicFile("schematics/lt.schematic")) then + BA1:MirrorXYNoMeta(); + BA1:SaveToSchematicFile("schematics/lt_XY.schematic"); + BA1:MirrorXYNoMeta(); + BA1:SaveToSchematicFile("schematics/lt_XY2.schematic"); + + BA1:MirrorXZNoMeta(); + BA1:SaveToSchematicFile("schematics/lt_XZ.schematic"); + BA1:MirrorXZNoMeta(); + BA1:SaveToSchematicFile("schematics/lt_XZ2.schematic"); + + BA1:MirrorYZNoMeta(); + BA1:SaveToSchematicFile("schematics/lt_YZ.schematic"); + BA1:MirrorYZNoMeta(); + BA1:SaveToSchematicFile("schematics/lt_YZ2.schematic"); + end + + -- Debug block area rotation: + if (BA1:LoadFromSchematicFile("schematics/rot.schematic")) then + BA1:RotateCWNoMeta(); + BA1:SaveToSchematicFile("schematics/rot1.schematic"); + BA1:RotateCWNoMeta(); + BA1:SaveToSchematicFile("schematics/rot2.schematic"); + BA1:RotateCWNoMeta(); + BA1:SaveToSchematicFile("schematics/rot3.schematic"); + BA1:RotateCWNoMeta(); + BA1:SaveToSchematicFile("schematics/rot4.schematic"); + end + + -- Debug block area rotation: + if (BA1:LoadFromSchematicFile("schematics/rotm.schematic")) then + BA1:RotateCCW(); + BA1:SaveToSchematicFile("schematics/rotm1.schematic"); + BA1:RotateCCW(); + BA1:SaveToSchematicFile("schematics/rotm2.schematic"); + BA1:RotateCCW(); + BA1:SaveToSchematicFile("schematics/rotm3.schematic"); + BA1:RotateCCW(); + BA1:SaveToSchematicFile("schematics/rotm4.schematic"); + end + + -- Debug block area mirroring: + if (BA1:LoadFromSchematicFile("schematics/ltm.schematic")) then + BA1:MirrorXY(); + BA1:SaveToSchematicFile("schematics/ltm_XY.schematic"); + BA1:MirrorXY(); + BA1:SaveToSchematicFile("schematics/ltm_XY2.schematic"); + + BA1:MirrorXZ(); + BA1:SaveToSchematicFile("schematics/ltm_XZ.schematic"); + BA1:MirrorXZ(); + BA1:SaveToSchematicFile("schematics/ltm_XZ2.schematic"); + + BA1:MirrorYZ(); + BA1:SaveToSchematicFile("schematics/ltm_YZ.schematic"); + BA1:MirrorYZ(); + BA1:SaveToSchematicFile("schematics/ltm_YZ2.schematic"); + end + + LOG("Block areas test ended"); +end + + + + + + +function TestSQLiteBindings() + LOG("Testing SQLite bindings..."); + + -- Debug SQLite binding + local TestDB, ErrCode, ErrMsg = sqlite3.open("test.sqlite"); + if (TestDB ~= nil) then + local function ShowRow(UserData, NumCols, Values, Names) + assert(UserData == 'UserData'); + LOG("New row"); + for i = 1, NumCols do + LOG(" " .. Names[i] .. " = " .. Values[i]); + end + return 0; + end + local sql = [=[ + CREATE TABLE numbers(num1,num2,str); + INSERT INTO numbers VALUES(1, 11, "ABC"); + INSERT INTO numbers VALUES(2, 22, "DEF"); + INSERT INTO numbers VALUES(3, 33, "UVW"); + INSERT INTO numbers VALUES(4, 44, "XYZ"); + SELECT * FROM numbers; + ]=] + local Res = TestDB:exec(sql, ShowRow, 'UserData'); + if (Res ~= sqlite3.OK) then + LOG("TestDB:exec() failed: " .. Res .. " (" .. TestDB:errmsg() .. ")"); + end; + TestDB:close(); + else + -- This happens if for example SQLite cannot open the file (eg. a folder with the same name exists) + LOG("SQLite3 failed to open DB! (" .. ErrCode .. ", " .. ErrMsg ..")"); + end + + LOG("SQLite bindings test ended"); +end + + + + + +function TestExpatBindings() + LOG("Testing Expat bindings..."); + + -- Debug LuaExpat bindings: + local count = 0 + callbacks = { + StartElement = function (parser, name) + LOG("+ " .. string.rep(" ", count) .. name); + count = count + 1; + end, + EndElement = function (parser, name) + count = count - 1; + LOG("- " .. string.rep(" ", count) .. name); + end + } + + local p = lxp.new(callbacks); + p:parse("\nnext line\nanother line"); + p:parse("text\n"); + p:parse("\n"); + p:parse("more text"); + p:parse(""); + p:parse("\n"); + p:parse(); -- finishes the document + p:close(); -- closes the parser + + LOG("Expat bindings test ended"); +end + + + + + +function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) + -- Magic rod of query: show block types and metas for both neighbors of the pointed face + local Type, Meta, Valid = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ, Type, Meta); + + if (Type == E_BLOCK_AIR) then + Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta); + else + local TempItem = cItem(Type, 1, Meta); + Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")"); + end + + local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace); + Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z, Type, Meta); + if (Type == E_BLOCK_AIR) then + Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta); + else + local TempItem = cItem(Type, 1, Meta); + Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")"); + end + return false; +end + + + + + +function OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) + -- Rclk with a diamond to test block area cropping and expanding + local Area = cBlockArea(); + Area:Read(Player:GetWorld(), + BlockX - 19, BlockX + 19, + BlockY - 7, BlockY + 7, + BlockZ - 19, BlockZ + 19 + ); + + LOG("Size before cropping: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("crop0.dat"); + + Area:Crop(2, 3, 0, 0, 0, 0); + LOG("Size after cropping 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("crop1.dat"); + + Area:Crop(2, 3, 0, 0, 0, 0); + LOG("Size after cropping 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("crop2.dat"); + + Area:Expand(2, 3, 0, 0, 0, 0); + LOG("Size after expanding 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("expand1.dat"); + + Area:Expand(3, 2, 1, 1, 0, 0); + LOG("Size after expanding 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("expand2.dat"); + + Area:Crop(0, 0, 0, 0, 3, 2); + LOG("Size after cropping 3: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("crop3.dat"); + + Area:Crop(0, 0, 3, 2, 0, 0); + LOG("Size after cropping 4: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); + Area:DumpToRawFile("crop4.dat"); + + LOG("Crop test done"); + Player:SendMessage("Crop / expand test done."); + return false; +end + + + + + +function OnUsingEyeOfEnder(Player, BlockX, BlockY, BlockZ) + -- Rclk with an eye of ender places a predefined schematic at the cursor + local Area = cBlockArea(); + if not(Area:LoadFromSchematicFile("schematics/test.schematic")) then + LOG("Loading failed"); + return false; + end + LOG("Schematic loaded, placing now."); + Area:Write(Player:GetWorld(), BlockX, BlockY, BlockZ); + LOG("Done."); + return false; +end + + + + + +function OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) + -- Rclk with an ender pearl saves a predefined area around the cursor into a .schematic file. Also tests area copying + local Area = cBlockArea(); + if not(Area:Read(Player:GetWorld(), + BlockX - 8, BlockX + 8, BlockY - 8, BlockY + 8, BlockZ - 8, BlockZ + 8) + ) then + LOG("LUA: Area couldn't be read"); + return false; + end + LOG("LUA: Area read, copying now."); + local Area2 = cBlockArea(); + Area2:CopyFrom(Area); + LOG("LUA: Copied, now saving."); + if not(Area2:SaveToSchematicFile("schematics/test.schematic")) then + LOG("LUA: Cannot save schematic file."); + return false; + end + LOG("LUA: Done."); + return false; +end + + + + + +function OnUsingRedstoneTorch(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) + -- Redstone torch activates a rapid dispenser / dropper discharge (at every tick): + local BlockType = Player:GetWorld():GetBlock(BlockX, BlockY, BlockZ); + if (BlockType == E_BLOCK_DISPENSER) then + table.insert(g_DropSpensersToActivate, {World = Player:GetWorld(), x = BlockX, y = BlockY, z = BlockZ}); + Player:SendMessage("Dispenser at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging"); + return true; + elseif (BlockType == E_BLOCK_DROPPER) then + table.insert(g_DropSpensersToActivate, {World = Player:GetWorld(), x = BlockX, y = BlockY, z = BlockZ}); + Player:SendMessage("Dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging"); + return true; + else + Player:SendMessage("Neither a dispenser nor a dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. BlockType); + end + return false; +end + + + + + +function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) + + -- dont check if the direction is in the air + if (BlockFace == BLOCK_FACE_NONE) then + return false + end + + local HeldItem = Player:GetEquippedItem(); + local HeldItemType = HeldItem.m_ItemType; + + if (HeldItemType == E_ITEM_STICK) then + -- Magic sTick of ticking: set the pointed block for ticking at the next tick + Player:SendMessage(cChatColor.LightGray .. "Setting next block tick to {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}") + Player:GetWorld():SetNextBlockTick(BlockX, BlockY, BlockZ); + return true + elseif (HeldItemType == E_ITEM_BLAZE_ROD) then + return OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); + elseif (HeldItemType == E_ITEM_DIAMOND) then + return OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); + elseif (HeldItemType == E_ITEM_EYE_OF_ENDER) then + return OnUsingEyeOfEnder(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); + elseif (HeldItemType == E_ITEM_ENDER_PEARL) then + return OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); + end + return false; +end + + + + + +function OnPlayerUsingBlock(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ, BlockType, BlockMeta) + -- dont check if the direction is in the air + if (BlockFace == BLOCK_FACE_NONE) then + return false + end + + local HeldItem = Player:GetEquippedItem(); + local HeldItemType = HeldItem.m_ItemType; + + if (HeldItemType == E_BLOCK_REDSTONE_TORCH_ON) then + return OnUsingRedstoneTorch(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); + end +end + + + + + +function OnTakeDamage(Receiver, TDI) + -- Receiver is cPawn + -- TDI is TakeDamageInfo + + LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)"); + return false; +end + + + + + +--- When set to a positive number, the following OnTick() will perform GC and decrease until 0 again +GCOnTick = 0; + + + + + +function OnTick() + -- Activate all dropspensers in the g_DropSpensersToActivate list: + local ActivateDrSp = function(DropSpenser) + if (DropSpenser:GetContents():GetFirstUsedSlot() == -1) then + return true; + end + DropSpenser:Activate(); + return false; + end + -- Walk the list backwards, because we're removing some items + local idx = #g_DropSpensersToActivate; + for i = idx, 1, -1 do + local DrSp = g_DropSpensersToActivate[i]; + if not(DrSp.World:DoWithDropSpenserAt(DrSp.x, DrSp.y, DrSp.z, ActivateDrSp)) then + table.remove(g_DropSpensersToActivate, i); + end + end + + + -- If GCOnTick > 0, do a garbage-collect and decrease by one + if (GCOnTick > 0) then + collectgarbage(); + GCOnTick = GCOnTick - 1; + end + + --[[ + if (g_HungerReportTick > 0) then + g_HungerReportTick = g_HungerReportTick - 1; + else + g_HungerReportTick = 10; + cRoot:Get():GetDefaultWorld():ForEachPlayer( + function(a_Player) + a_Player:SendMessage("FoodStat: " .. a_Player:GetFoodLevel() .. " / " .. a_Player:GetFoodExhaustionLevel()); + end + ); + end + ]] + + return false; +end + + + + + +function OnChunkGenerated(World, ChunkX, ChunkZ, ChunkDesc) + -- Test ChunkDesc / BlockArea interaction + local BlockArea = cBlockArea(); + ChunkDesc:ReadBlockArea(BlockArea, 0, 15, 50, 70, 0, 15); + + -- BlockArea:SaveToSchematicFile("ChunkBlocks_" .. ChunkX .. "_" .. ChunkZ .. ".schematic"); + + ChunkDesc:WriteBlockArea(BlockArea, 5, 115, 5); + return false; +end + + + + + +function OnChat(a_Player, a_Message) + return false, "blabla " .. a_Message; +end + + + + + +-- Function "round" copied from http://lua-users.org/wiki/SimpleRound +function round(num, idp) + local mult = 10^(idp or 0) + if num >= 0 then return math.floor(num * mult + 0.5) / mult + else return math.ceil(num * mult - 0.5) / mult end +end + + + + + +function HandleListEntitiesCmd(Split, Player) + local NumEntities = 0; + + local ListEntity = function(Entity) + if (Entity:IsDestroyed()) then + -- The entity has already been destroyed, don't list it + return false; + end; + Player:SendMessage(" " .. Entity:GetUniqueID() .. ": " .. Entity:GetClass() .. " {" .. round(Entity:GetPosX(), 2) .. ", " .. round(Entity:GetPosY(), 2) .. ", " .. round(Entity:GetPosZ(), 2) .."}"); + NumEntities = NumEntities + 1; + end + + Player:SendMessage("Listing all entities..."); + Player:GetWorld():ForEachEntity(ListEntity); + Player:SendMessage("List finished, " .. NumEntities .. " entities listed"); + return true; +end + + + + + +function HandleKillEntitiesCmd(Split, Player) + local NumEntities = 0; + + local KillEntity = function(Entity) + -- kill everything except for players: + if (Entity:GetEntityType() ~= cEntity.etPlayer) then + Entity:Destroy(); + NumEntities = NumEntities + 1; + end; + end + + Player:SendMessage("Killing all entities..."); + Player:GetWorld():ForEachEntity(KillEntity); + Player:SendMessage("Killed " .. NumEntities .. " entities."); + return true; +end + + + + + +function HandleWoolCmd(Split, Player) + local Wool = cItem(E_BLOCK_WOOL, 1, E_META_WOOL_BLUE); + Player:GetInventory():SetArmorSlot(0, Wool); + Player:GetInventory():SetArmorSlot(1, Wool); + Player:GetInventory():SetArmorSlot(2, Wool); + Player:GetInventory():SetArmorSlot(3, Wool); + Player:SendMessage("You have been bluewooled :)"); + return true; +end + + + + + +function HandleTestWndCmd(a_Split, a_Player) + local WindowType = cWindow.Hopper; + local WindowSizeX = 5; + local WindowSizeY = 1; + if (#a_Split == 4) then + WindowType = tonumber(a_Split[2]); + WindowSizeX = tonumber(a_Split[3]); + WindowSizeY = tonumber(a_Split[4]); + elseif (#a_Split ~= 1) then + a_Player:SendMessage("Usage: /testwnd [WindowType WindowSizeX WindowSizeY]"); + return true; + end + + -- Test out the OnClosing callback's ability to refuse to close the window + local attempt = 1; + local OnClosing = function(Window, Player, CanRefuse) + Player:SendMessage("Window closing attempt #" .. attempt .. "; CanRefuse = " .. tostring(CanRefuse)); + attempt = attempt + 1; + return CanRefuse and (attempt <= 3); -- refuse twice, then allow, unless CanRefuse is set to true + end + + -- Log the slot changes + local OnSlotChanged = function(Window, SlotNum) + LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed."); + end + + local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd"); + local Item2 = cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1"); + local Item3 = cItem(E_ITEM_DIAMOND_SHOVEL); + Item3.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 4); + local Item4 = cItem(Item3); -- Copy + Item4.m_Enchantments:SetLevel(cEnchantments.enchEfficiency, 3); -- Add enchantment + Item4.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 5); -- Overwrite existing level + local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3"); + Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64)); + Window:SetSlot(a_Player, 1, Item2); + Window:SetSlot(a_Player, 2, Item3); + Window:SetSlot(a_Player, 3, Item4); + Window:SetSlot(a_Player, 4, Item5); + Window:SetOnClosing(OnClosing); + Window:SetOnSlotChanged(OnSlotChanged); + + a_Player:OpenWindow(Window); + + -- To make sure that the object has the correct life-management in Lua, + -- let's garbage-collect in the following few ticks + GCOnTick = 10; + + return true; +end + + + + + +function HandleGCCmd(a_Split, a_Player) + collectgarbage(); + return true; +end + + + + + + +function HandleFastCmd(a_Split, a_Player) + if (a_Player:GetNormalMaxSpeed() <= 0.11) then + -- The player has normal speed, set double speed: + a_Player:SetNormalMaxSpeed(0.2); + a_Player:SendMessage("You are now fast"); + else + -- The player has fast speed, set normal speed: + a_Player:SetNormalMaxSpeed(0.1); + a_Player:SendMessage("Back to normal speed"); + end + return true; +end + + + + + +function HandleDashCmd(a_Split, a_Player) + if (a_Player:GetSprintingMaxSpeed() <= 0.14) then + -- The player has normal sprinting speed, set double Sprintingspeed: + a_Player:SetSprintingMaxSpeed(0.4); + a_Player:SendMessage("You can now sprint very fast"); + else + -- The player has fast sprinting speed, set normal sprinting speed: + a_Player:SetSprintingMaxSpeed(0.13); + a_Player:SendMessage("Back to normal sprinting"); + end + return true; +end; + + + + + +function HandleHungerCmd(a_Split, a_Player) + a_Player:SendMessage("FoodLevel: " .. a_Player:GetFoodLevel()); + a_Player:SendMessage("FoodSaturationLevel: " .. a_Player:GetFoodSaturationLevel()); + a_Player:SendMessage("FoodTickTimer: " .. a_Player:GetFoodTickTimer()); + a_Player:SendMessage("FoodExhaustionLevel: " .. a_Player:GetFoodExhaustionLevel()); + a_Player:SendMessage("FoodPoisonedTicksRemaining: " .. a_Player:GetFoodPoisonedTicksRemaining()); + return true; +end + + + + + +function HandlePoisonCmd(a_Split, a_Player) + a_Player:FoodPoison(15 * 20); + return true; +end + + + + + +function HandleStarveCmd(a_Split, a_Player) + a_Player:SetFoodLevel(0); + a_Player:SendMessage("You are now starving"); + return true; +end + + + + + +function HandleFoodLevelCmd(a_Split, a_Player) + if (#a_Split ~= 2) then + a_Player:SendMessage("Missing an argument: the food level to set"); + return true; + end + + a_Player:SetFoodLevel(tonumber(a_Split[2])); + a_Player:SendMessage("Food level set to " .. a_Player:GetFoodLevel()); + return true; +end + + + + diff --git a/MCServer/Plugins/DiamondMover/DiamondMover.lua b/MCServer/Plugins/DiamondMover/DiamondMover.lua index eaced1058..c89a3394f 100644 --- a/MCServer/Plugins/DiamondMover/DiamondMover.lua +++ b/MCServer/Plugins/DiamondMover/DiamondMover.lua @@ -1,83 +1,83 @@ - --- DiamondMover.lua - --- An example Lua plugin using the cBlockArea object --- When a player rclks with a diamond in their hand, an area around the clicked block is moved in the direction the player is facing - - - - - --- Global variables -PLUGIN = {} -- Reference to own plugin object -MOVER_SIZE_X = 4; -MOVER_SIZE_Y = 4; -MOVER_SIZE_Z = 4; - - - - - -function Initialize(Plugin) - PLUGIN = Plugin; - - Plugin:SetName("DiamondMover"); - Plugin:SetVersion(1); - - PluginManager = cRoot:Get():GetPluginManager(); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USED_ITEM); - return true; -end - - - - - -function OnPlayerUsedItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) - - -- Don't check if the direction is in the air - if (BlockFace == -1) then - return false; - end; - - if (Player:HasPermission("diamondmover.move") == false) then - return true; - end; - - -- Rclk with a diamond to push in the direction the player is facing - if (Player:GetEquippedItem().m_ItemType == E_ITEM_DIAMOND) then - local Area = cBlockArea(); - Area:Read(Player:GetWorld(), - BlockX - MOVER_SIZE_X, BlockX + MOVER_SIZE_X, - BlockY - MOVER_SIZE_Y, BlockY + MOVER_SIZE_Y, - BlockZ - MOVER_SIZE_Z, BlockZ + MOVER_SIZE_Z - ); - - local PlayerPitch = Player:GetPitch(); - if (PlayerPitch < -70) then -- looking up - BlockY = BlockY + 1; - else - if (PlayerPitch > 70) then -- looking down - BlockY = BlockY - 1; - else - local PlayerRot = Player:GetRotation() + 180; -- Convert [-180, 180] into [0, 360] for simpler conditions - if ((PlayerRot < 45) or (PlayerRot > 315)) then - BlockZ = BlockZ - 1; - else - if (PlayerRot < 135) then - BlockX = BlockX + 1; - else - if (PlayerRot < 225) then - BlockZ = BlockZ + 1; - else - BlockX = BlockX - 1; - end; - end; - end; - end; - end; - - Area:Write(Player:GetWorld(), BlockX - MOVER_SIZE_X, BlockY - MOVER_SIZE_Y, BlockZ - MOVER_SIZE_Z); - return false; - end + +-- DiamondMover.lua + +-- An example Lua plugin using the cBlockArea object +-- When a player rclks with a diamond in their hand, an area around the clicked block is moved in the direction the player is facing + + + + + +-- Global variables +PLUGIN = {} -- Reference to own plugin object +MOVER_SIZE_X = 4; +MOVER_SIZE_Y = 4; +MOVER_SIZE_Z = 4; + + + + + +function Initialize(Plugin) + PLUGIN = Plugin; + + Plugin:SetName("DiamondMover"); + Plugin:SetVersion(1); + + PluginManager = cRoot:Get():GetPluginManager(); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USED_ITEM); + return true; +end + + + + + +function OnPlayerUsedItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) + + -- Don't check if the direction is in the air + if (BlockFace == -1) then + return false; + end; + + if (Player:HasPermission("diamondmover.move") == false) then + return true; + end; + + -- Rclk with a diamond to push in the direction the player is facing + if (Player:GetEquippedItem().m_ItemType == E_ITEM_DIAMOND) then + local Area = cBlockArea(); + Area:Read(Player:GetWorld(), + BlockX - MOVER_SIZE_X, BlockX + MOVER_SIZE_X, + BlockY - MOVER_SIZE_Y, BlockY + MOVER_SIZE_Y, + BlockZ - MOVER_SIZE_Z, BlockZ + MOVER_SIZE_Z + ); + + local PlayerPitch = Player:GetPitch(); + if (PlayerPitch < -70) then -- looking up + BlockY = BlockY + 1; + else + if (PlayerPitch > 70) then -- looking down + BlockY = BlockY - 1; + else + local PlayerRot = Player:GetRotation() + 180; -- Convert [-180, 180] into [0, 360] for simpler conditions + if ((PlayerRot < 45) or (PlayerRot > 315)) then + BlockZ = BlockZ - 1; + else + if (PlayerRot < 135) then + BlockX = BlockX + 1; + else + if (PlayerRot < 225) then + BlockZ = BlockZ + 1; + else + BlockX = BlockX - 1; + end; + end; + end; + end; + end; + + Area:Write(Player:GetWorld(), BlockX - MOVER_SIZE_X, BlockY - MOVER_SIZE_Y, BlockZ - MOVER_SIZE_Z); + return false; + end end \ No newline at end of file diff --git a/MCServer/Plugins/Handy/handy.lua b/MCServer/Plugins/Handy/handy.lua index c2330abab..6d226ccaf 100644 --- a/MCServer/Plugins/Handy/handy.lua +++ b/MCServer/Plugins/Handy/handy.lua @@ -1,28 +1,28 @@ --- Global variables -PLUGIN = {} -- Reference to own plugin object -CHEST_WIDTH = 9 -HANDY_VERSION = 1 ---[[ - -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...") +-- Global variables +PLUGIN = {} -- Reference to own plugin object +CHEST_WIDTH = 9 +HANDY_VERSION = 1 +--[[ + +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 index f8423312f..a76980c6e 100644 --- a/MCServer/Plugins/Handy/handy_functions.lua +++ b/MCServer/Plugins/Handy/handy_functions.lua @@ -1,355 +1,355 @@ ---[[ -General stuff -]] --- Returns Handy plugin version number -function GetHandyVersion() - return HANDY_VERSION -end --- Checks if handy is in proper version -function CheckForRequiedVersion(IN_version) - if (IN_version > HANDY_VERSION) then return false end - return true -end ---[[ -MCS-specific _functions and nasty hacks :D -]] --- There's a "GetChestHeight" function inside source code, but it's not lua-exported -function GetChestHeightCheat(IN_chest) - if (IN_chest:GetSlot(28) == nil) then -- this means we're trying to get double chest slot and FAIL - LOGWARN("HANDY: single chest checked") - return 3 - end - LOGWARN("HANDY: double chest checked") - return 6 -end --- Those two checks how many items of given IN_itemID chest and player have, and how much they could fit inside them -function ReadChestForItem(IN_chest, IN_itemID) - local _items_found = 0 - local _free_space = 0 - -- stalk through chest slots... - local _slot_counter = 0 - local _slot_item - local _item_max_stack = GetItemMaxStack(IN_itemID) - while true do - _slot_item = IN_chest:GetSlot(_slot_counter) - if (_slot_item ~= nil) then - if (_slot_item.m_ItemID == IN_itemID) then - _items_found = _items_found + _slot_item.m_ItemCount - _free_space = _free_space + (_item_max_stack - _slot_item.m_ItemCount) - end - if (_slot_item:IsEmpty() == true) then - _free_space = _free_space + _item_max_stack - end - end - _slot_counter = _slot_counter + 1 - if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then - break - end - end - return _items_found, _free_space -end -function ReadPlayerForItem(IN_player, IN_itemID) - local _items_found = 0 - local _free_space = 0 - -- stalk through IN_player inventory slots... - local _slot_counter = 9 - if (ItemIsArmor(IN_itemID) == true) then _slot_counter = 5 end - local _slot_item - local _item_max_stack = GetItemMaxStack(IN_itemID) - while true do - _slot_item = IN_player:GetInventory():GetSlot(_slot_counter) - if (_slot_item ~= nil) then - if (_slot_item.m_ItemID == IN_itemID) then - _items_found = _items_found + _slot_item.m_ItemCount - _free_space = _free_space + (_item_max_stack - _slot_item.m_ItemCount) - end - if (_slot_item:IsEmpty() == true) then - _free_space = _free_space + _item_max_stack - end - end - _slot_counter = _slot_counter + 1 - if (_slot_counter == 45) then - break - end - end - return _items_found, _free_space -end --- Following functions are for chest-related operations (since noone was bothered writing them in MCS code) --- BEWARE! Those assume you did checked if chest has items/space in it! -function TakeItemsFromChest(IN_chest, IN_itemID, IN_ammount) -- UNSAFE! CHECK FOR ITEMS FIRST!! - -- stalk through chest slots... - local _slot_counter = 0 - local _slot_item - local _take_count = IN_ammount - while true do - _slot_item = IN_chest:GetSlot(_slot_counter) - if (_slot_item ~= nil) then - if (_slot_item.m_ItemID == IN_itemID) then - -- assuming player have enought money - if (_take_count > 0) then - if (_take_count > _slot_item.m_ItemCount) then - _take_count = _take_count - _slot_item.m_ItemCount - IN_chest:SetSlot(_slot_counter, cItem()) -- a bit hacky, can't make cItem:Clear() work( - else - local _left_count = _slot_item.m_ItemCount - _take_count - IN_chest:SetSlot(_slot_counter, cItem(_slot_item.m_ItemID, _left_count)) -- a bit hacky - _take_count = 0 - end - end - if (_take_count == 0) then - break - end - end - end - _slot_counter = _slot_counter + 1 - if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then - break - end - end -end -function PutItemsToChest(IN_chest, IN_itemID, IN_ammount) -- UNSAFE! CHECK FOR SPACE FIRST!! - -- stalk through chest slots... - local _slot_counter = 0 - local _slot_item - local _put_count = IN_ammount - local _max_stack = GetItemMaxStack(IN_itemID) - while true do - _slot_item = IN_chest:GetSlot(_slot_counter) - local _portion = 0 - local _ammount_to_set = 0 - if (_slot_item ~= nil) then - if (_slot_item:IsEmpty() == true) then - _portion = math.min(_max_stack, _put_count) - _ammount_to_set = _portion - else - if (_slot_item.m_ItemID == IN_itemID) then - -- choose between how much we need to put and how much free space left - _portion = math.min(_put_count, _max_stack - _slot_item.m_ItemCount) - _ammount_to_set = _slot_item.m_ItemCount + _portion - end - end - end - IN_chest:SetSlot(_slot_counter, cItem(IN_itemID, _ammount_to_set)) -- we add max stack to chest - _put_count = _put_count - _portion - if (_put_count == 0) then break end - _slot_counter = _slot_counter + 1 - if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then - break - end - end -end --- Similar to chest-related. -function TakeItemsFromPlayer(IN_player, IN_itemID, IN_ammount) -- UNSAFE! CHECK FIRST! - local _put_count = IN_ammount - local _max_stack = GetItemMaxStack(IN_itemID) - while true do - local _portion = math.min(_max_stack, _put_count) - IN_player:GetInventory():RemoveItem(cItem(IN_itemID, _portion)) - _put_count = _put_count - _portion - if (_put_count == 0) then break end - end -end -function GiveItemsToPlayer(IN_player, IN_itemID, IN_ammount) -- UNSAFE! CHECK FIRST! - local _put_count = IN_ammount - local _max_stack = GetItemMaxStack(IN_itemID) - while true do - local _portion = math.min(_max_stack, _put_count) - IN_player:GetInventory():AddItem(cItem(IN_itemID, _portion)) - _put_count = _put_count - _portion - if (_put_count == 0) then break end - 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(IN_itemID) - local _result = 64 - -- Tools and swords - if (IN_itemID == woodensword) then _result = 1 end - if (IN_itemID == woodenshovel) then _result = 1 end - if (IN_itemID == woodenpickaxe) then _result = 1 end - if (IN_itemID == woodenaxe) then _result = 1 end - if (IN_itemID == woodenhoe) then _result = 1 end - if (IN_itemID == stonesword) then _result = 1 end - if (IN_itemID == stoneshovel) then _result = 1 end - if (IN_itemID == stonepickaxe) then _result = 1 end - if (IN_itemID == stoneaxe) then _result = 1 end - if (IN_itemID == stonehoe) then _result = 1 end - if (IN_itemID == ironsword) then _result = 1 end - if (IN_itemID == ironshovel) then _result = 1 end - if (IN_itemID == ironpickaxe) then _result = 1 end - if (IN_itemID == ironaxe) then _result = 1 end - if (IN_itemID == ironhoe) then _result = 1 end - if (IN_itemID == diamondsword) then _result = 1 end - if (IN_itemID == diamondshovel) then _result = 1 end - if (IN_itemID == diamondpickaxe) then _result = 1 end - if (IN_itemID == diamondaxe) then _result = 1 end - if (IN_itemID == diamondhoe) then _result = 1 end - if (IN_itemID == goldensword) then _result = 1 end - if (IN_itemID == goldenshovel) then _result = 1 end - if (IN_itemID == goldenpickaxe) then _result = 1 end - if (IN_itemID == goldenaxe) then _result = 1 end - if (IN_itemID == goldenhoe) then _result = 1 end - - if (IN_itemID == flintandsteel) then _result = 1 end - if (IN_itemID == bow) then _result = 1 end - if (IN_itemID == sign) then _result = 16 end - if (IN_itemID == woodendoor) then _result = 1 end - if (IN_itemID == irondoor) then _result = 1 end - if (IN_itemID == cake) then _result = 1 end - if (IN_itemID == cauldron) then _result = 1 end - if (IN_itemID == mushroomstew) then _result = 1 end - if (IN_itemID == painting) then _result = 1 end - if (IN_itemID == bucket) then _result = 16 end - if (IN_itemID == waterbucket) then _result = 1 end - if (IN_itemID == lavabucket) then _result = 1 end - if (IN_itemID == minecart) then _result = 1 end - if (IN_itemID == saddle) then _result = 1 end - if (IN_itemID == snowball) then _result = 16 end - if (IN_itemID == boat) then _result = 1 end - if (IN_itemID == milkbucket) then _result = 1 end - if (IN_itemID == storageminecart) then _result = 1 end - if (IN_itemID == poweredminecart) then _result = 1 end - if (IN_itemID == egg) then _result = 16 end - if (IN_itemID == fishingrod) then _result = 1 end - if (IN_itemID == bed) then _result = 1 end - if (IN_itemID == map) then _result = 1 end - if (IN_itemID == shears) then _result = 1 end - if (IN_itemID == enderpearl) then _result = 16 end - if (IN_itemID == potion) then _result = 1 end - if (IN_itemID == spawnegg) then _result = 1 end - if (IN_itemID == bookandquill) then _result = 1 end - if (IN_itemID == writtenbook) then _result = 1 end - if (IN_itemID == carrotonastick) then _result = 1 end - - if (IN_itemID == goldrecord) then _result = 1 end - if (IN_itemID == greenrecord) then _result = 1 end - if (IN_itemID == blocksrecord) then _result = 1 end - if (IN_itemID == chirprecord) then _result = 1 end - if (IN_itemID == farrecord) then _result = 1 end - if (IN_itemID == mallrecord) then _result = 1 end - if (IN_itemID == mellohirecord) then _result = 1 end - if (IN_itemID == stalrecord) then _result = 1 end - if (IN_itemID == stradrecord) then _result = 1 end - if (IN_itemID == wardrecord) then _result = 1 end - if (IN_itemID == oneonerecord) then _result = 1 end - if (IN_itemID == waitrecord) then _result = 1 end - - --if (IN_itemID == xxxxxxxxx) then _result = 1 end - - if (IN_itemID == leatherhelmet) then _result = 1 end - if (IN_itemID == leatherchestplate) then _result = 1 end - if (IN_itemID == leatherpants) then _result = 1 end - if (IN_itemID == leatherboots) then _result = 1 end - - if (IN_itemID == chainmailhelmet) then _result = 1 end - if (IN_itemID == chainmailchestplate) then _result = 1 end - if (IN_itemID == chainmailpants) then _result = 1 end - if (IN_itemID == chainmailboots) then _result = 1 end - - if (IN_itemID == ironhelmet) then _result = 1 end - if (IN_itemID == ironchestplate) then _result = 1 end - if (IN_itemID == ironpants) then _result = 1 end - if (IN_itemID == ironboots) then _result = 1 end - - if (IN_itemID == diamondhelmet) then _result = 1 end - if (IN_itemID == diamondchestplate) then _result = 1 end - if (IN_itemID == diamondpants) then _result = 1 end - if (IN_itemID == diamondboots) then _result = 1 end - - if (IN_itemID == goldenhelmet) then _result = 1 end - if (IN_itemID == goldenchestplate) then _result = 1 end - if (IN_itemID == goldenpants) then _result = 1 end - if (IN_itemID == goldenboots) then _result = 1 end - return _result -end -function ItemIsArmor(IN_itemID) - local _result = false - if (IN_itemID == leatherhelmet) then _result = true end - if (IN_itemID == leatherchestplate) then _result = true end - if (IN_itemID == leatherpants) then _result = true end - if (IN_itemID == leatherboots) then _result = true end - - if (IN_itemID == chainmailhelmet) then _result = true end - if (IN_itemID == chainmailchestplate) then _result = true end - if (IN_itemID == chainmailpants) then _result = true end - if (IN_itemID == chainmailboots) then _result = true end - - if (IN_itemID == ironhelmet) then _result = true end - if (IN_itemID == ironchestplate) then _result = true end - if (IN_itemID == ironpants) then _result = true end - if (IN_itemID == ironboots) then _result = true end - - if (IN_itemID == diamondhelmet) then _result = true end - if (IN_itemID == diamondchestplate) then _result = true end - if (IN_itemID == diamondpants) then _result = true end - if (IN_itemID == diamondboots) then _result = true end - - if (IN_itemID == goldenhelmet) then _result = true end - if (IN_itemID == goldenchestplate) then _result = true end - if (IN_itemID == goldenpants) then _result = true end - if (IN_itemID == goldenboots) then _result = true end - return _result -end --- Returns full-length playername for a short name (usefull for parsing commands) -function GetExactPlayername(IN_playername) - local _result = IN_playername - local function SetProcessingPlayername(IN_player) - _result = IN_player:GetName() - end - cRoot:Get():FindAndDoWithPlayer(IN_playername, SetProcessingPlayername) - return _result -end -function GetPlayerByName(IN_playername) - local _player - local PlayerSetter = function (Player) - _player = Player - end - cRoot:Get():FindAndDoWithPlayer(IN_playername, 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(IN_x) - if (IN_x%2 ~= 0.5) then - return math.floor(IN_x+0.5) - end - return IN_x-0.5 -end ---[[ -Functions I use for filework and stringswork -]] -function PluralString(IN_value, IN_singular_string, IN_plural_string) - local _value_string = tostring(IN_value) - if (_value_string[#_value_string] == "1") then - return IN_singular_string - end - return IN_plural_string -end -function PluralItemName(IN_itemID, IN_ammount) -- BEWARE! TEMPORAL SOLUTION THERE! :D - local _value_string = tostring(IN_value) - local _name = "" - if (_value_string[#_value_string] == "1") then - -- singular names - _name = ItemTypeToString(IN_itemID) - else - -- plural names - _name = ItemTypeToString(IN_itemID).."s" - end - return _name -end --- for filewriting purposes. 0 = false, 1 = true -function StringToBool(value) - if value=="1" then return true end - return false -end --- same, but reversal -function BoolToString(value) - if value==true then return 1 end - return 0 +--[[ +General stuff +]] +-- Returns Handy plugin version number +function GetHandyVersion() + return HANDY_VERSION +end +-- Checks if handy is in proper version +function CheckForRequiedVersion(IN_version) + if (IN_version > HANDY_VERSION) then return false end + return true +end +--[[ +MCS-specific _functions and nasty hacks :D +]] +-- There's a "GetChestHeight" function inside source code, but it's not lua-exported +function GetChestHeightCheat(IN_chest) + if (IN_chest:GetSlot(28) == nil) then -- this means we're trying to get double chest slot and FAIL + LOGWARN("HANDY: single chest checked") + return 3 + end + LOGWARN("HANDY: double chest checked") + return 6 +end +-- Those two checks how many items of given IN_itemID chest and player have, and how much they could fit inside them +function ReadChestForItem(IN_chest, IN_itemID) + local _items_found = 0 + local _free_space = 0 + -- stalk through chest slots... + local _slot_counter = 0 + local _slot_item + local _item_max_stack = GetItemMaxStack(IN_itemID) + while true do + _slot_item = IN_chest:GetSlot(_slot_counter) + if (_slot_item ~= nil) then + if (_slot_item.m_ItemID == IN_itemID) then + _items_found = _items_found + _slot_item.m_ItemCount + _free_space = _free_space + (_item_max_stack - _slot_item.m_ItemCount) + end + if (_slot_item:IsEmpty() == true) then + _free_space = _free_space + _item_max_stack + end + end + _slot_counter = _slot_counter + 1 + if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then + break + end + end + return _items_found, _free_space +end +function ReadPlayerForItem(IN_player, IN_itemID) + local _items_found = 0 + local _free_space = 0 + -- stalk through IN_player inventory slots... + local _slot_counter = 9 + if (ItemIsArmor(IN_itemID) == true) then _slot_counter = 5 end + local _slot_item + local _item_max_stack = GetItemMaxStack(IN_itemID) + while true do + _slot_item = IN_player:GetInventory():GetSlot(_slot_counter) + if (_slot_item ~= nil) then + if (_slot_item.m_ItemID == IN_itemID) then + _items_found = _items_found + _slot_item.m_ItemCount + _free_space = _free_space + (_item_max_stack - _slot_item.m_ItemCount) + end + if (_slot_item:IsEmpty() == true) then + _free_space = _free_space + _item_max_stack + end + end + _slot_counter = _slot_counter + 1 + if (_slot_counter == 45) then + break + end + end + return _items_found, _free_space +end +-- Following functions are for chest-related operations (since noone was bothered writing them in MCS code) +-- BEWARE! Those assume you did checked if chest has items/space in it! +function TakeItemsFromChest(IN_chest, IN_itemID, IN_ammount) -- UNSAFE! CHECK FOR ITEMS FIRST!! + -- stalk through chest slots... + local _slot_counter = 0 + local _slot_item + local _take_count = IN_ammount + while true do + _slot_item = IN_chest:GetSlot(_slot_counter) + if (_slot_item ~= nil) then + if (_slot_item.m_ItemID == IN_itemID) then + -- assuming player have enought money + if (_take_count > 0) then + if (_take_count > _slot_item.m_ItemCount) then + _take_count = _take_count - _slot_item.m_ItemCount + IN_chest:SetSlot(_slot_counter, cItem()) -- a bit hacky, can't make cItem:Clear() work( + else + local _left_count = _slot_item.m_ItemCount - _take_count + IN_chest:SetSlot(_slot_counter, cItem(_slot_item.m_ItemID, _left_count)) -- a bit hacky + _take_count = 0 + end + end + if (_take_count == 0) then + break + end + end + end + _slot_counter = _slot_counter + 1 + if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then + break + end + end +end +function PutItemsToChest(IN_chest, IN_itemID, IN_ammount) -- UNSAFE! CHECK FOR SPACE FIRST!! + -- stalk through chest slots... + local _slot_counter = 0 + local _slot_item + local _put_count = IN_ammount + local _max_stack = GetItemMaxStack(IN_itemID) + while true do + _slot_item = IN_chest:GetSlot(_slot_counter) + local _portion = 0 + local _ammount_to_set = 0 + if (_slot_item ~= nil) then + if (_slot_item:IsEmpty() == true) then + _portion = math.min(_max_stack, _put_count) + _ammount_to_set = _portion + else + if (_slot_item.m_ItemID == IN_itemID) then + -- choose between how much we need to put and how much free space left + _portion = math.min(_put_count, _max_stack - _slot_item.m_ItemCount) + _ammount_to_set = _slot_item.m_ItemCount + _portion + end + end + end + IN_chest:SetSlot(_slot_counter, cItem(IN_itemID, _ammount_to_set)) -- we add max stack to chest + _put_count = _put_count - _portion + if (_put_count == 0) then break end + _slot_counter = _slot_counter + 1 + if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then + break + end + end +end +-- Similar to chest-related. +function TakeItemsFromPlayer(IN_player, IN_itemID, IN_ammount) -- UNSAFE! CHECK FIRST! + local _put_count = IN_ammount + local _max_stack = GetItemMaxStack(IN_itemID) + while true do + local _portion = math.min(_max_stack, _put_count) + IN_player:GetInventory():RemoveItem(cItem(IN_itemID, _portion)) + _put_count = _put_count - _portion + if (_put_count == 0) then break end + end +end +function GiveItemsToPlayer(IN_player, IN_itemID, IN_ammount) -- UNSAFE! CHECK FIRST! + local _put_count = IN_ammount + local _max_stack = GetItemMaxStack(IN_itemID) + while true do + local _portion = math.min(_max_stack, _put_count) + IN_player:GetInventory():AddItem(cItem(IN_itemID, _portion)) + _put_count = _put_count - _portion + if (_put_count == 0) then break end + 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(IN_itemID) + local _result = 64 + -- Tools and swords + if (IN_itemID == woodensword) then _result = 1 end + if (IN_itemID == woodenshovel) then _result = 1 end + if (IN_itemID == woodenpickaxe) then _result = 1 end + if (IN_itemID == woodenaxe) then _result = 1 end + if (IN_itemID == woodenhoe) then _result = 1 end + if (IN_itemID == stonesword) then _result = 1 end + if (IN_itemID == stoneshovel) then _result = 1 end + if (IN_itemID == stonepickaxe) then _result = 1 end + if (IN_itemID == stoneaxe) then _result = 1 end + if (IN_itemID == stonehoe) then _result = 1 end + if (IN_itemID == ironsword) then _result = 1 end + if (IN_itemID == ironshovel) then _result = 1 end + if (IN_itemID == ironpickaxe) then _result = 1 end + if (IN_itemID == ironaxe) then _result = 1 end + if (IN_itemID == ironhoe) then _result = 1 end + if (IN_itemID == diamondsword) then _result = 1 end + if (IN_itemID == diamondshovel) then _result = 1 end + if (IN_itemID == diamondpickaxe) then _result = 1 end + if (IN_itemID == diamondaxe) then _result = 1 end + if (IN_itemID == diamondhoe) then _result = 1 end + if (IN_itemID == goldensword) then _result = 1 end + if (IN_itemID == goldenshovel) then _result = 1 end + if (IN_itemID == goldenpickaxe) then _result = 1 end + if (IN_itemID == goldenaxe) then _result = 1 end + if (IN_itemID == goldenhoe) then _result = 1 end + + if (IN_itemID == flintandsteel) then _result = 1 end + if (IN_itemID == bow) then _result = 1 end + if (IN_itemID == sign) then _result = 16 end + if (IN_itemID == woodendoor) then _result = 1 end + if (IN_itemID == irondoor) then _result = 1 end + if (IN_itemID == cake) then _result = 1 end + if (IN_itemID == cauldron) then _result = 1 end + if (IN_itemID == mushroomstew) then _result = 1 end + if (IN_itemID == painting) then _result = 1 end + if (IN_itemID == bucket) then _result = 16 end + if (IN_itemID == waterbucket) then _result = 1 end + if (IN_itemID == lavabucket) then _result = 1 end + if (IN_itemID == minecart) then _result = 1 end + if (IN_itemID == saddle) then _result = 1 end + if (IN_itemID == snowball) then _result = 16 end + if (IN_itemID == boat) then _result = 1 end + if (IN_itemID == milkbucket) then _result = 1 end + if (IN_itemID == storageminecart) then _result = 1 end + if (IN_itemID == poweredminecart) then _result = 1 end + if (IN_itemID == egg) then _result = 16 end + if (IN_itemID == fishingrod) then _result = 1 end + if (IN_itemID == bed) then _result = 1 end + if (IN_itemID == map) then _result = 1 end + if (IN_itemID == shears) then _result = 1 end + if (IN_itemID == enderpearl) then _result = 16 end + if (IN_itemID == potion) then _result = 1 end + if (IN_itemID == spawnegg) then _result = 1 end + if (IN_itemID == bookandquill) then _result = 1 end + if (IN_itemID == writtenbook) then _result = 1 end + if (IN_itemID == carrotonastick) then _result = 1 end + + if (IN_itemID == goldrecord) then _result = 1 end + if (IN_itemID == greenrecord) then _result = 1 end + if (IN_itemID == blocksrecord) then _result = 1 end + if (IN_itemID == chirprecord) then _result = 1 end + if (IN_itemID == farrecord) then _result = 1 end + if (IN_itemID == mallrecord) then _result = 1 end + if (IN_itemID == mellohirecord) then _result = 1 end + if (IN_itemID == stalrecord) then _result = 1 end + if (IN_itemID == stradrecord) then _result = 1 end + if (IN_itemID == wardrecord) then _result = 1 end + if (IN_itemID == oneonerecord) then _result = 1 end + if (IN_itemID == waitrecord) then _result = 1 end + + --if (IN_itemID == xxxxxxxxx) then _result = 1 end + + if (IN_itemID == leatherhelmet) then _result = 1 end + if (IN_itemID == leatherchestplate) then _result = 1 end + if (IN_itemID == leatherpants) then _result = 1 end + if (IN_itemID == leatherboots) then _result = 1 end + + if (IN_itemID == chainmailhelmet) then _result = 1 end + if (IN_itemID == chainmailchestplate) then _result = 1 end + if (IN_itemID == chainmailpants) then _result = 1 end + if (IN_itemID == chainmailboots) then _result = 1 end + + if (IN_itemID == ironhelmet) then _result = 1 end + if (IN_itemID == ironchestplate) then _result = 1 end + if (IN_itemID == ironpants) then _result = 1 end + if (IN_itemID == ironboots) then _result = 1 end + + if (IN_itemID == diamondhelmet) then _result = 1 end + if (IN_itemID == diamondchestplate) then _result = 1 end + if (IN_itemID == diamondpants) then _result = 1 end + if (IN_itemID == diamondboots) then _result = 1 end + + if (IN_itemID == goldenhelmet) then _result = 1 end + if (IN_itemID == goldenchestplate) then _result = 1 end + if (IN_itemID == goldenpants) then _result = 1 end + if (IN_itemID == goldenboots) then _result = 1 end + return _result +end +function ItemIsArmor(IN_itemID) + local _result = false + if (IN_itemID == leatherhelmet) then _result = true end + if (IN_itemID == leatherchestplate) then _result = true end + if (IN_itemID == leatherpants) then _result = true end + if (IN_itemID == leatherboots) then _result = true end + + if (IN_itemID == chainmailhelmet) then _result = true end + if (IN_itemID == chainmailchestplate) then _result = true end + if (IN_itemID == chainmailpants) then _result = true end + if (IN_itemID == chainmailboots) then _result = true end + + if (IN_itemID == ironhelmet) then _result = true end + if (IN_itemID == ironchestplate) then _result = true end + if (IN_itemID == ironpants) then _result = true end + if (IN_itemID == ironboots) then _result = true end + + if (IN_itemID == diamondhelmet) then _result = true end + if (IN_itemID == diamondchestplate) then _result = true end + if (IN_itemID == diamondpants) then _result = true end + if (IN_itemID == diamondboots) then _result = true end + + if (IN_itemID == goldenhelmet) then _result = true end + if (IN_itemID == goldenchestplate) then _result = true end + if (IN_itemID == goldenpants) then _result = true end + if (IN_itemID == goldenboots) then _result = true end + return _result +end +-- Returns full-length playername for a short name (usefull for parsing commands) +function GetExactPlayername(IN_playername) + local _result = IN_playername + local function SetProcessingPlayername(IN_player) + _result = IN_player:GetName() + end + cRoot:Get():FindAndDoWithPlayer(IN_playername, SetProcessingPlayername) + return _result +end +function GetPlayerByName(IN_playername) + local _player + local PlayerSetter = function (Player) + _player = Player + end + cRoot:Get():FindAndDoWithPlayer(IN_playername, 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(IN_x) + if (IN_x%2 ~= 0.5) then + return math.floor(IN_x+0.5) + end + return IN_x-0.5 +end +--[[ +Functions I use for filework and stringswork +]] +function PluralString(IN_value, IN_singular_string, IN_plural_string) + local _value_string = tostring(IN_value) + if (_value_string[#_value_string] == "1") then + return IN_singular_string + end + return IN_plural_string +end +function PluralItemName(IN_itemID, IN_ammount) -- BEWARE! TEMPORAL SOLUTION THERE! :D + local _value_string = tostring(IN_value) + local _name = "" + if (_value_string[#_value_string] == "1") then + -- singular names + _name = ItemTypeToString(IN_itemID) + else + -- plural names + _name = ItemTypeToString(IN_itemID).."s" + end + return _name +end +-- for filewriting purposes. 0 = false, 1 = true +function StringToBool(value) + if value=="1" then return true end + return false +end +-- same, but reversal +function BoolToString(value) + if value==true then return 1 end + return 0 end \ No newline at end of file diff --git a/MCServer/Plugins/HookNotify/HookNotify.lua b/MCServer/Plugins/HookNotify/HookNotify.lua index ed463c5ca..09759451d 100644 --- a/MCServer/Plugins/HookNotify/HookNotify.lua +++ b/MCServer/Plugins/HookNotify/HookNotify.lua @@ -1,404 +1,404 @@ - --- Global variables -PLUGIN = {} -- Reference to own plugin object - - - - - -function Initialize(Plugin) - PLUGIN = Plugin - - Plugin:SetName("HookNotify"); - Plugin:SetVersion(1); - - PluginManager = cPluginManager:Get(); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_BLOCK_TO_PICKUPS); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_AVAILABLE); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_UNLOADED); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_UNLOADING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_COLLECTING_PICKUP); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_CRAFTING_NO_RECIPE); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_DISCONNECT); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_EXECUTE_COMMAND); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_HANDSHAKE); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_KILLING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_LOGIN); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_BREAKING_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_BROKEN_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_EATING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_JOINED); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_LEFT_CLICK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_MOVING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_PLACED_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_PLACING_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_SHOOTING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_SPAWNED); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_TOSSING_ITEM); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USED_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USED_ITEM); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_BLOCK); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_ITEM); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_POST_CRAFTING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_PRE_CRAFTING); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_TAKE_DAMAGE); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_UPDATED_SIGN); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_UPDATING_SIGN); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_WEATHER_CHANGED); - PluginManager:AddHook(Plugin, cPluginManager.HOOK_WEATHER_CHANGING); - - LOGINFO("HookNotify plugin is installed, beware, the log output may be quite large!"); - LOGINFO("You want this plugin enabled only when developing another plugin, not for regular gameplay."); - - return true -end - - - - - -function LogHook(FnName, ...) - LOG(FnName .. "("); - for i, v in ipairs(arg) do - local vt = tostring(v); - local TypeString = type(v); - if (type(v) == "userdata") then - TypeString = tolua.type(v); - end; - LOG(" " .. tostring(i) .. ": " .. TypeString .. ": " .. tostring(v)); - end - LOG(")"); -end - - - - - -function OnBlockToPickups(...) - LogHook("OnBlockToPickups", unpack(arg)); - local World, Digger, BlockX, BlockY, BlockZ, BlockType, BlockMeta, Pickups = unpack(arg); - if (Pickups ~= nil) then - local Name = "NULL"; - if (Digger ~= nil) then - Name = Digger:GetName() - end - LOG("Got cItems from " .. Name .. ", trying to manipulate them."); - Pickups:Add(cItem:new(E_ITEM_DIAMOND_SHOVEL, 1)); - LOG("Current size: " .. Pickups:Size()); - end; -end; - - - - - -function OnChat(...) - LogHook("OnChat", unpack(arg)); -end - - - - - -function OnChunkAvailable(...) - LogHook("OnChunkAvailable", unpack(arg)); -end - - - - - -function OnChunkGenerated(...) - LogHook("OnChunkGenerated", unpack(arg)); -end - - - - - -function OnChunkGenerating(...) - LogHook("OnChunkGenerating", unpack(arg)); -end - - - - - -function OnChunkUnloaded(...) - LogHook("OnChunkUnloaded", unpack(arg)); -end - - - - - -function OnChunkUnloading(...) - LogHook("OnChunkUnloading", unpack(arg)); -end - - - - - -function OnPlayerUsingItem(...) - LogHook("OnPlayerUsingItem", unpack(arg)); -end - - - - - -function OnCollectingPickup(...) - LogHook("OnCollectingPickup", unpack(arg)); -end - - - - -function OnCraftingNoRecipe(...) - LogHook("OnCraftingNoRecipe", unpack(arg)); -end - - - - - -function OnDisconnect(...) - LogHook("OnDisconnect", unpack(arg)); -end - - - - - -function OnExecuteCommand(...) - LogHook("OnExecuteCommand", unpack(arg)); - - -- For some reason logging doesn't work for this callback, so list some stuff manually to verify: - LOG("arg1 type: " .. type(arg[1])); - if (arg[1] ~= nil) then - LOG("Player name: " .. arg[1]:GetName()); - end - LOG("Command: " .. arg[2][1]); -end - - - - - -function OnHandshake(...) - LogHook("OnHandshake", unpack(arg)); -end - - - - - -function OnKilling(...) - LogHook("OnKilling", unpack(arg)); -end - - - - - -function OnLogin(...) - LogHook("OnLogin", unpack(arg)); -end - - - - - -function OnPlayerBreakingBlock(...) - LogHook("OnPlayerBreakingBlock", unpack(arg)); -end - - - - - -function OnPlayerBrokenBlock(...) - LogHook("OnPlayerBrokenBlock", unpack(arg)); -end - - - - - -function OnPlayerEating(...) - LogHook("OnPlayerEating", unpack(arg)); -end - - - - - -function OnPlayerJoined(...) - LogHook("OnPlayerJoined", unpack(arg)); -end - - - - - -function OnPlayerLeftClick(...) - LogHook("OnPlayerLeftClick", unpack(arg)); -end - - - - - -function OnPlayerMoving(...) - LogHook("OnPlayerMoving", unpack(arg)); -end - - - - - -function OnPlayerPlacedBlock(...) - LogHook("OnPlayerPlacedBlock", unpack(arg)); -end - - - - - -function OnPlayerPlacingBlock(...) - LogHook("OnPlayerPlacingBlock", unpack(arg)); -end - - - - - -function OnPlayerRightClick(...) - LogHook("OnPlayerRightClick", unpack(arg)); -end - - - - - -function OnPlayerShooting(...) - LogHook("OnPlayerShooting", unpack(arg)); -end - - - - - -function OnPlayerSpawned(...) - LogHook("OnPlayerSpawned", unpack(arg)); -end - - - - - -function OnPlayerTossingItem(...) - LogHook("OnPlayerTossingItem", unpack(arg)); -end - - - - - -function OnPlayerUsedBlock(...) - LogHook("OnPlayerUsedBlock", unpack(arg)); -end - - - - - -function OnPlayerUsedItem(...) - LogHook("OnPlayerUsedItem", unpack(arg)); -end - - - - - -function OnPlayerUsingBlock(...) - LogHook("OnPlayerUsingBlock", unpack(arg)); -end - - - - - -function OnPlayerUsingItem(...) - LogHook("OnPlayerUsingItem", unpack(arg)); -end - - - - - -function OnPostCrafting(...) - LogHook("OnPostCrafting", unpack(arg)); -end - - - - - -function OnPreCrafting(...) - LogHook("OnPreCrafting", unpack(arg)); -end - - - - - -function OnUpdatedSign(...) - LogHook("OnUpdatedSign", unpack(arg)); -end - - - - - -function OnUpdatingSign(...) - LogHook("OnUpdatingSign", unpack(arg)); -end - - - - - -function OnWeatherChanged(...) - LogHook("OnWeatherChanged", unpack(arg)); -end - - - - - -function OnWeatherChanging(...) - LogHook("OnWeatherChanging", unpack(arg)); -end - - - - - ------------------------------------------------------------------- --- Special handling for OnTakeDamage to print the contents of TDI: - -function OnTakeDamage(Receiver, TDI) - -- Receiver is cPawn - -- TDI is TakeDamageInfo - - LOG("OnTakeDamage(): " .. Receiver:GetClass() .. " was dealt RawDamage " .. TDI.RawDamage .. ", FinalDamage " .. TDI.FinalDamage .. " (that is, " .. (TDI.RawDamage - TDI.FinalDamage) .. " HPs covered by armor)"); -end - - - + +-- Global variables +PLUGIN = {} -- Reference to own plugin object + + + + + +function Initialize(Plugin) + PLUGIN = Plugin + + Plugin:SetName("HookNotify"); + Plugin:SetVersion(1); + + PluginManager = cPluginManager:Get(); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_BLOCK_TO_PICKUPS); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_AVAILABLE); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_UNLOADED); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_UNLOADING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_COLLECTING_PICKUP); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_CRAFTING_NO_RECIPE); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_DISCONNECT); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_EXECUTE_COMMAND); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_HANDSHAKE); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_KILLING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_LOGIN); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_BREAKING_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_BROKEN_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_EATING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_JOINED); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_LEFT_CLICK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_MOVING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_PLACED_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_PLACING_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_SHOOTING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_SPAWNED); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_TOSSING_ITEM); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USED_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USED_ITEM); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_BLOCK); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_ITEM); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_POST_CRAFTING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_PRE_CRAFTING); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_TAKE_DAMAGE); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_UPDATED_SIGN); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_UPDATING_SIGN); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_WEATHER_CHANGED); + PluginManager:AddHook(Plugin, cPluginManager.HOOK_WEATHER_CHANGING); + + LOGINFO("HookNotify plugin is installed, beware, the log output may be quite large!"); + LOGINFO("You want this plugin enabled only when developing another plugin, not for regular gameplay."); + + return true +end + + + + + +function LogHook(FnName, ...) + LOG(FnName .. "("); + for i, v in ipairs(arg) do + local vt = tostring(v); + local TypeString = type(v); + if (type(v) == "userdata") then + TypeString = tolua.type(v); + end; + LOG(" " .. tostring(i) .. ": " .. TypeString .. ": " .. tostring(v)); + end + LOG(")"); +end + + + + + +function OnBlockToPickups(...) + LogHook("OnBlockToPickups", unpack(arg)); + local World, Digger, BlockX, BlockY, BlockZ, BlockType, BlockMeta, Pickups = unpack(arg); + if (Pickups ~= nil) then + local Name = "NULL"; + if (Digger ~= nil) then + Name = Digger:GetName() + end + LOG("Got cItems from " .. Name .. ", trying to manipulate them."); + Pickups:Add(cItem:new(E_ITEM_DIAMOND_SHOVEL, 1)); + LOG("Current size: " .. Pickups:Size()); + end; +end; + + + + + +function OnChat(...) + LogHook("OnChat", unpack(arg)); +end + + + + + +function OnChunkAvailable(...) + LogHook("OnChunkAvailable", unpack(arg)); +end + + + + + +function OnChunkGenerated(...) + LogHook("OnChunkGenerated", unpack(arg)); +end + + + + + +function OnChunkGenerating(...) + LogHook("OnChunkGenerating", unpack(arg)); +end + + + + + +function OnChunkUnloaded(...) + LogHook("OnChunkUnloaded", unpack(arg)); +end + + + + + +function OnChunkUnloading(...) + LogHook("OnChunkUnloading", unpack(arg)); +end + + + + + +function OnPlayerUsingItem(...) + LogHook("OnPlayerUsingItem", unpack(arg)); +end + + + + + +function OnCollectingPickup(...) + LogHook("OnCollectingPickup", unpack(arg)); +end + + + + +function OnCraftingNoRecipe(...) + LogHook("OnCraftingNoRecipe", unpack(arg)); +end + + + + + +function OnDisconnect(...) + LogHook("OnDisconnect", unpack(arg)); +end + + + + + +function OnExecuteCommand(...) + LogHook("OnExecuteCommand", unpack(arg)); + + -- For some reason logging doesn't work for this callback, so list some stuff manually to verify: + LOG("arg1 type: " .. type(arg[1])); + if (arg[1] ~= nil) then + LOG("Player name: " .. arg[1]:GetName()); + end + LOG("Command: " .. arg[2][1]); +end + + + + + +function OnHandshake(...) + LogHook("OnHandshake", unpack(arg)); +end + + + + + +function OnKilling(...) + LogHook("OnKilling", unpack(arg)); +end + + + + + +function OnLogin(...) + LogHook("OnLogin", unpack(arg)); +end + + + + + +function OnPlayerBreakingBlock(...) + LogHook("OnPlayerBreakingBlock", unpack(arg)); +end + + + + + +function OnPlayerBrokenBlock(...) + LogHook("OnPlayerBrokenBlock", unpack(arg)); +end + + + + + +function OnPlayerEating(...) + LogHook("OnPlayerEating", unpack(arg)); +end + + + + + +function OnPlayerJoined(...) + LogHook("OnPlayerJoined", unpack(arg)); +end + + + + + +function OnPlayerLeftClick(...) + LogHook("OnPlayerLeftClick", unpack(arg)); +end + + + + + +function OnPlayerMoving(...) + LogHook("OnPlayerMoving", unpack(arg)); +end + + + + + +function OnPlayerPlacedBlock(...) + LogHook("OnPlayerPlacedBlock", unpack(arg)); +end + + + + + +function OnPlayerPlacingBlock(...) + LogHook("OnPlayerPlacingBlock", unpack(arg)); +end + + + + + +function OnPlayerRightClick(...) + LogHook("OnPlayerRightClick", unpack(arg)); +end + + + + + +function OnPlayerShooting(...) + LogHook("OnPlayerShooting", unpack(arg)); +end + + + + + +function OnPlayerSpawned(...) + LogHook("OnPlayerSpawned", unpack(arg)); +end + + + + + +function OnPlayerTossingItem(...) + LogHook("OnPlayerTossingItem", unpack(arg)); +end + + + + + +function OnPlayerUsedBlock(...) + LogHook("OnPlayerUsedBlock", unpack(arg)); +end + + + + + +function OnPlayerUsedItem(...) + LogHook("OnPlayerUsedItem", unpack(arg)); +end + + + + + +function OnPlayerUsingBlock(...) + LogHook("OnPlayerUsingBlock", unpack(arg)); +end + + + + + +function OnPlayerUsingItem(...) + LogHook("OnPlayerUsingItem", unpack(arg)); +end + + + + + +function OnPostCrafting(...) + LogHook("OnPostCrafting", unpack(arg)); +end + + + + + +function OnPreCrafting(...) + LogHook("OnPreCrafting", unpack(arg)); +end + + + + + +function OnUpdatedSign(...) + LogHook("OnUpdatedSign", unpack(arg)); +end + + + + + +function OnUpdatingSign(...) + LogHook("OnUpdatingSign", unpack(arg)); +end + + + + + +function OnWeatherChanged(...) + LogHook("OnWeatherChanged", unpack(arg)); +end + + + + + +function OnWeatherChanging(...) + LogHook("OnWeatherChanging", unpack(arg)); +end + + + + + +------------------------------------------------------------------ +-- Special handling for OnTakeDamage to print the contents of TDI: + +function OnTakeDamage(Receiver, TDI) + -- Receiver is cPawn + -- TDI is TakeDamageInfo + + LOG("OnTakeDamage(): " .. Receiver:GetClass() .. " was dealt RawDamage " .. TDI.RawDamage .. ", FinalDamage " .. TDI.FinalDamage .. " (that is, " .. (TDI.RawDamage - TDI.FinalDamage) .. " HPs covered by armor)"); +end + + + diff --git a/MCServer/Plugins/MagicCarpet/objects.lua b/MCServer/Plugins/MagicCarpet/objects.lua index 7c19fc232..8d81623a5 100644 --- a/MCServer/Plugins/MagicCarpet/objects.lua +++ b/MCServer/Plugins/MagicCarpet/objects.lua @@ -1,97 +1,97 @@ --- 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 +-- 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/ProtectionAreas/CommandHandlers.lua b/MCServer/Plugins/ProtectionAreas/CommandHandlers.lua index b943df060..26df73075 100644 --- a/MCServer/Plugins/ProtectionAreas/CommandHandlers.lua +++ b/MCServer/Plugins/ProtectionAreas/CommandHandlers.lua @@ -1,322 +1,322 @@ - --- CommandHandlers.lua --- Defines the individual command handlers - - - - - -function InitializeCommandHandlers() - local PlgMgr = cRoot:Get():GetPluginManager(); - for idx, Cmd in ipairs(CommandReg()) do - PlgMgr:BindCommand(Cmd[2], Cmd[3], Cmd[1], Cmd[4]); - end -end - - - - - ---- Handles the ProtAdd command -function HandleAddArea(a_Split, a_Player) - -- Command syntax: ProtAdd username1 [username2] [username3] ... - if (#a_Split < 2) then - a_Player:SendMessage(g_Msgs.ErrExpectedListOfUsernames); - return true; - end - - -- Get the cuboid that the player had selected - local CmdState = GetCommandStateForPlayer(a_Player); - if (CmdState == nil) then - a_Player:SendMessage(g_Msgs.ErrCmdStateNilAddArea); - return true; - end - local Cuboid = CmdState:GetCurrentCuboid(); - if (Cuboid == nil) then - a_Player:SendMessage(g_Msgs.ErrNoAreaWanded); - return true; - end - - -- Put all allowed players into a table: - AllowedNames = {}; - for i = 2, #a_Split do - table.insert(AllowedNames, a_Split[i]); - end - - -- Add the area to the storage - local AreaID = g_Storage:AddArea(Cuboid, a_Player:GetWorld():GetName(), a_Player:GetName(), AllowedNames); - a_Player:SendMessage(string.format(g_Msgs.AreaAdded, AreaID)); - - -- Reload all currently logged in players - ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); - - return true; -end - - - - - -function HandleAddAreaCoords(a_Split, a_Player) - -- Command syntax: ProtAddCoords x1 z1 x2 z2 username1 [username2] [username3] ... - if (#a_Split < 6) then - a_Player:SendMessage(g_Msgs.ErrExpectedCoordsUsernames); - return true; - end - - -- Convert the coords to a cCuboid - local x1, z1 = tonumber(a_Split[2]), tonumber(a_Split[3]); - local x2, z2 = tonumber(a_Split[4]), tonumber(a_Split[5]); - if ((x1 == nil) or (z1 == nil) or (x2 == nil) or (z2 == nil)) then - a_Player:SendMessage(g_Msgs.ErrParseCoords); - return true; - end - local Cuboid = cCuboid(x1, 0, z1, x2, 255, z1); - Cuboid:Sort(); - - -- Put all allowed players into a table: - AllowedNames = {}; - for i = 6, #a_Split do - table.insert(AllowedNames, a_Split[i]); - end - - -- Add the area to the storage - local AreaID = g_Storage:AddArea(Cuboid, a_Player:GetWorld():GetName(), a_Player:GetName(), AllowedNames); - a_Player:SendMessage(string.format(g_Msgs.AreaAdded, AreaID)); - - -- Reload all currently logged in players - ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); - - return true; -end - - - - - -function HandleAddAreaUser(a_Split, a_Player) - -- Command syntax: ProtAddUser AreaID username1 [username2] [username3] ... - if (#a_Split < 3) then - a_Player:SendMessage(g_Msgs.ErrExpectedAreaIDUsernames); - return true; - end - - -- Put all allowed players into a table: - AllowedNames = {}; - for i = 3, #a_Split do - table.insert(AllowedNames, a_Split[i]); - end - - -- Add the area to the storage - if (not(g_Storage:AddAreaUsers( - tonumber(a_Split[2]), a_Player:GetWorld():GetName(), a_Player:GetName(), AllowedNames)) - ) then - LOGWARNING("g_Storage:AddAreaUsers failed"); - a_Player:SendMessage(g_Msgs.ErrDBFailAddUsers); - return true; - end - if (#AllowedNames == 0) then - a_Player:SendMessage(g_Msgs.AllUsersAlreadyAllowed); - else - a_Player:SendMessage(string.format(g_Msgs.UsersAdded, table.concat(AllowedNames, ", "))); - end - - -- Reload all currently logged in players - ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); - - return true; -end - - - - - -function HandleDelArea(a_Split, a_Player) - -- Command syntax: ProtDelArea AreaID - if (#a_Split ~= 2) then - a_Player:SendMessage(g_Msgs.ErrExpectedAreaID); - return true; - end - - -- Parse the AreaID - local AreaID = tonumber(a_Split[2]); - if (AreaID == nil) then - a_Player:SendMessage(g_Msgs.ErrParseAreaID); - return true; - end - - -- Delete the area - g_Storage:DelArea(a_Player:GetWorld():GetName(), AreaID); - - a_Player:SendMessage(string.format(g_Msgs.AreaDeleted, AreaID)); - -- Reload all currently logged in players - ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); - - return true; -end - - - - - -function HandleGiveWand(a_Split, a_Player) - local NumGiven = a_Player:GetInventory():AddItem(cConfig:GetWandItem()); - if (NumGiven == 1) then - a_Player:SendMessage(g_Msgs.WandGiven); - else - a_Player:SendMessage(g_Msgs.ErrNoSpaceForWand); - end - return true; -end - - - - - -function HandleListAreas(a_Split, a_Player) - -- Command syntax: ProtListAreas [x, z] - - local x, z; - if (#a_Split == 1) then - -- Get the last "wanded" coord - local CmdState = GetCommandStateForPlayer(a_Player); - if (CmdState == nil) then - a_Player:SendMessage(g_Msgs.ErrCmdStateNilListAreas); - return true; - end - x, z = CmdState:GetLastCoords(); - if ((x == nil) or (z == nil)) then - a_Player:SendMessage(g_Msgs.ErrListNotWanded); - return true; - end - elseif (#a_Split == 3) then - -- Parse the coords from the command params - x = tonumber(a_Split[2]); - z = tonumber(a_Split[3]); - if ((x == nil) or (z == nil)) then - a_Player:SendMessage(g_Msgs.ErrParseCoordsListAreas); - return true; - end - else - -- Wrong number of params, report back to the user - a_Player:SendMessage(g_Msgs.ErrSyntaxErrorListAreas); - return true; - end - - a_Player:SendMessage(string.format(g_Msgs.ListAreasHeader, x, z)); - - -- List areas intersecting the coords - local PlayerName = a_Player:GetName(); - local WorldName = a_Player:GetWorld():GetName(); - g_Storage:ForEachArea(x, z, WorldName, - function(AreaID, MinX, MinZ, MaxX, MaxZ, CreatorName) - local Coords = string.format("%s: {%d, %d} - {%d, %d} ", AreaID, MinX, MinZ, MaxX, MaxZ); - local Allowance; - if (g_Storage:IsAreaAllowed(AreaID, PlayerName, WorldName)) then - Allowance = g_Msgs.AreaAllowed; - else - Allowance = g_Msgs.AreaNotAllowed; - end - a_Player:SendMessage(string.format(g_Msgs.ListAreasRow, Coords, Allowance, CreatorName)); - end - ); - - a_Player:SendMessage(g_Msgs.ListAreasFooter); - return true; -end - - - - ---- Lists all allowed users for a particular area -function HandleListUsers(a_Split, a_Player) - -- Command syntax: ProtListUsers AreaID - if (#a_Split ~= 2) then - a_Player:SendMessage(g_Msgs.ErrExpectedAreaID); - end - - -- Get the general info about the area - local AreaID = a_Split[2]; - local WorldName = a_Player:GetWorld():GetName(); - local MinX, MinZ, MaxX, MaxZ, CreatorName = g_Storage:GetArea(AreaID, WorldName); - if (MinX == nil) then - a_Player:SendMessage(string.format(g_Msgs.ErrNoSuchArea, AreaID)); - return true; - end - - -- Send the header - a_Player:SendMessage(string.format(g_Msgs.ListUsersHeader, AreaID, MinX, MinZ, MaxX, MaxZ, CreatorName)); - - -- List and count the allowed users - local NumUsers = 0; - g_Storage:ForEachUserInArea(AreaID, WorldName, - function(UserName) - a_Player:SendMessage(string.format(g_Msgs.ListUsersRow, UserName)); - NumUsers = NumUsers + 1; - end - ); - - -- Send the footer - a_Player:SendMessage(string.format(g_Msgs.ListUsersFooter, AreaID, NumUsers)); - - return true; -end - - - - - -function HandleRemoveUser(a_Split, a_Player) - -- Command syntax: ProtRemUser AreaID UserName - if (#a_Split ~= 3) then - a_Player:SendMessage(g_Msgs.ErrExpectedAreaIDUserName); - return true; - end - - -- Parse the AreaID - local AreaID = tonumber(a_Split[2]); - if (AreaID == nil) then - a_Player:SendMessage(g_Msgs.ErrParseAreaID); - return true; - end - - -- Remove the user from the DB - local UserName = a_Split[3]; - g_Storage:RemoveUser(AreaID, UserName, a_Player:GetWorld():GetName()); - - -- Send confirmation - a_Player:SendMessage(string.format(g_Msgs.RemovedUser, UserName, AreaID)); - - -- Reload all currently logged in players - ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); - - return true; -end - - - - - -function HandleRemoveUserAll(a_Split, a_Player) - -- Command syntax: ProtRemUserAll UserName - if (#a_Split ~= 2) then - a_Player:SendMessage(g_Msgs.ErrExpectedUserName); - return true; - end - - -- Remove the user from the DB - g_Storage:RemoveUserAll(a_Split[2], a_Player:GetWorld():GetName()); - - -- Send confirmation - a_Player:SendMessage(string.format(g_Msgs.RemovedUserAll, UserName)); - - -- Reload all currently logged in players - ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); - - return true; -end - - - - - + +-- CommandHandlers.lua +-- Defines the individual command handlers + + + + + +function InitializeCommandHandlers() + local PlgMgr = cRoot:Get():GetPluginManager(); + for idx, Cmd in ipairs(CommandReg()) do + PlgMgr:BindCommand(Cmd[2], Cmd[3], Cmd[1], Cmd[4]); + end +end + + + + + +--- Handles the ProtAdd command +function HandleAddArea(a_Split, a_Player) + -- Command syntax: ProtAdd username1 [username2] [username3] ... + if (#a_Split < 2) then + a_Player:SendMessage(g_Msgs.ErrExpectedListOfUsernames); + return true; + end + + -- Get the cuboid that the player had selected + local CmdState = GetCommandStateForPlayer(a_Player); + if (CmdState == nil) then + a_Player:SendMessage(g_Msgs.ErrCmdStateNilAddArea); + return true; + end + local Cuboid = CmdState:GetCurrentCuboid(); + if (Cuboid == nil) then + a_Player:SendMessage(g_Msgs.ErrNoAreaWanded); + return true; + end + + -- Put all allowed players into a table: + AllowedNames = {}; + for i = 2, #a_Split do + table.insert(AllowedNames, a_Split[i]); + end + + -- Add the area to the storage + local AreaID = g_Storage:AddArea(Cuboid, a_Player:GetWorld():GetName(), a_Player:GetName(), AllowedNames); + a_Player:SendMessage(string.format(g_Msgs.AreaAdded, AreaID)); + + -- Reload all currently logged in players + ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); + + return true; +end + + + + + +function HandleAddAreaCoords(a_Split, a_Player) + -- Command syntax: ProtAddCoords x1 z1 x2 z2 username1 [username2] [username3] ... + if (#a_Split < 6) then + a_Player:SendMessage(g_Msgs.ErrExpectedCoordsUsernames); + return true; + end + + -- Convert the coords to a cCuboid + local x1, z1 = tonumber(a_Split[2]), tonumber(a_Split[3]); + local x2, z2 = tonumber(a_Split[4]), tonumber(a_Split[5]); + if ((x1 == nil) or (z1 == nil) or (x2 == nil) or (z2 == nil)) then + a_Player:SendMessage(g_Msgs.ErrParseCoords); + return true; + end + local Cuboid = cCuboid(x1, 0, z1, x2, 255, z1); + Cuboid:Sort(); + + -- Put all allowed players into a table: + AllowedNames = {}; + for i = 6, #a_Split do + table.insert(AllowedNames, a_Split[i]); + end + + -- Add the area to the storage + local AreaID = g_Storage:AddArea(Cuboid, a_Player:GetWorld():GetName(), a_Player:GetName(), AllowedNames); + a_Player:SendMessage(string.format(g_Msgs.AreaAdded, AreaID)); + + -- Reload all currently logged in players + ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); + + return true; +end + + + + + +function HandleAddAreaUser(a_Split, a_Player) + -- Command syntax: ProtAddUser AreaID username1 [username2] [username3] ... + if (#a_Split < 3) then + a_Player:SendMessage(g_Msgs.ErrExpectedAreaIDUsernames); + return true; + end + + -- Put all allowed players into a table: + AllowedNames = {}; + for i = 3, #a_Split do + table.insert(AllowedNames, a_Split[i]); + end + + -- Add the area to the storage + if (not(g_Storage:AddAreaUsers( + tonumber(a_Split[2]), a_Player:GetWorld():GetName(), a_Player:GetName(), AllowedNames)) + ) then + LOGWARNING("g_Storage:AddAreaUsers failed"); + a_Player:SendMessage(g_Msgs.ErrDBFailAddUsers); + return true; + end + if (#AllowedNames == 0) then + a_Player:SendMessage(g_Msgs.AllUsersAlreadyAllowed); + else + a_Player:SendMessage(string.format(g_Msgs.UsersAdded, table.concat(AllowedNames, ", "))); + end + + -- Reload all currently logged in players + ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); + + return true; +end + + + + + +function HandleDelArea(a_Split, a_Player) + -- Command syntax: ProtDelArea AreaID + if (#a_Split ~= 2) then + a_Player:SendMessage(g_Msgs.ErrExpectedAreaID); + return true; + end + + -- Parse the AreaID + local AreaID = tonumber(a_Split[2]); + if (AreaID == nil) then + a_Player:SendMessage(g_Msgs.ErrParseAreaID); + return true; + end + + -- Delete the area + g_Storage:DelArea(a_Player:GetWorld():GetName(), AreaID); + + a_Player:SendMessage(string.format(g_Msgs.AreaDeleted, AreaID)); + -- Reload all currently logged in players + ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); + + return true; +end + + + + + +function HandleGiveWand(a_Split, a_Player) + local NumGiven = a_Player:GetInventory():AddItem(cConfig:GetWandItem()); + if (NumGiven == 1) then + a_Player:SendMessage(g_Msgs.WandGiven); + else + a_Player:SendMessage(g_Msgs.ErrNoSpaceForWand); + end + return true; +end + + + + + +function HandleListAreas(a_Split, a_Player) + -- Command syntax: ProtListAreas [x, z] + + local x, z; + if (#a_Split == 1) then + -- Get the last "wanded" coord + local CmdState = GetCommandStateForPlayer(a_Player); + if (CmdState == nil) then + a_Player:SendMessage(g_Msgs.ErrCmdStateNilListAreas); + return true; + end + x, z = CmdState:GetLastCoords(); + if ((x == nil) or (z == nil)) then + a_Player:SendMessage(g_Msgs.ErrListNotWanded); + return true; + end + elseif (#a_Split == 3) then + -- Parse the coords from the command params + x = tonumber(a_Split[2]); + z = tonumber(a_Split[3]); + if ((x == nil) or (z == nil)) then + a_Player:SendMessage(g_Msgs.ErrParseCoordsListAreas); + return true; + end + else + -- Wrong number of params, report back to the user + a_Player:SendMessage(g_Msgs.ErrSyntaxErrorListAreas); + return true; + end + + a_Player:SendMessage(string.format(g_Msgs.ListAreasHeader, x, z)); + + -- List areas intersecting the coords + local PlayerName = a_Player:GetName(); + local WorldName = a_Player:GetWorld():GetName(); + g_Storage:ForEachArea(x, z, WorldName, + function(AreaID, MinX, MinZ, MaxX, MaxZ, CreatorName) + local Coords = string.format("%s: {%d, %d} - {%d, %d} ", AreaID, MinX, MinZ, MaxX, MaxZ); + local Allowance; + if (g_Storage:IsAreaAllowed(AreaID, PlayerName, WorldName)) then + Allowance = g_Msgs.AreaAllowed; + else + Allowance = g_Msgs.AreaNotAllowed; + end + a_Player:SendMessage(string.format(g_Msgs.ListAreasRow, Coords, Allowance, CreatorName)); + end + ); + + a_Player:SendMessage(g_Msgs.ListAreasFooter); + return true; +end + + + + +--- Lists all allowed users for a particular area +function HandleListUsers(a_Split, a_Player) + -- Command syntax: ProtListUsers AreaID + if (#a_Split ~= 2) then + a_Player:SendMessage(g_Msgs.ErrExpectedAreaID); + end + + -- Get the general info about the area + local AreaID = a_Split[2]; + local WorldName = a_Player:GetWorld():GetName(); + local MinX, MinZ, MaxX, MaxZ, CreatorName = g_Storage:GetArea(AreaID, WorldName); + if (MinX == nil) then + a_Player:SendMessage(string.format(g_Msgs.ErrNoSuchArea, AreaID)); + return true; + end + + -- Send the header + a_Player:SendMessage(string.format(g_Msgs.ListUsersHeader, AreaID, MinX, MinZ, MaxX, MaxZ, CreatorName)); + + -- List and count the allowed users + local NumUsers = 0; + g_Storage:ForEachUserInArea(AreaID, WorldName, + function(UserName) + a_Player:SendMessage(string.format(g_Msgs.ListUsersRow, UserName)); + NumUsers = NumUsers + 1; + end + ); + + -- Send the footer + a_Player:SendMessage(string.format(g_Msgs.ListUsersFooter, AreaID, NumUsers)); + + return true; +end + + + + + +function HandleRemoveUser(a_Split, a_Player) + -- Command syntax: ProtRemUser AreaID UserName + if (#a_Split ~= 3) then + a_Player:SendMessage(g_Msgs.ErrExpectedAreaIDUserName); + return true; + end + + -- Parse the AreaID + local AreaID = tonumber(a_Split[2]); + if (AreaID == nil) then + a_Player:SendMessage(g_Msgs.ErrParseAreaID); + return true; + end + + -- Remove the user from the DB + local UserName = a_Split[3]; + g_Storage:RemoveUser(AreaID, UserName, a_Player:GetWorld():GetName()); + + -- Send confirmation + a_Player:SendMessage(string.format(g_Msgs.RemovedUser, UserName, AreaID)); + + -- Reload all currently logged in players + ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); + + return true; +end + + + + + +function HandleRemoveUserAll(a_Split, a_Player) + -- Command syntax: ProtRemUserAll UserName + if (#a_Split ~= 2) then + a_Player:SendMessage(g_Msgs.ErrExpectedUserName); + return true; + end + + -- Remove the user from the DB + g_Storage:RemoveUserAll(a_Split[2], a_Player:GetWorld():GetName()); + + -- Send confirmation + a_Player:SendMessage(string.format(g_Msgs.RemovedUserAll, UserName)); + + -- Reload all currently logged in players + ReloadAllPlayersInWorld(a_Player:GetWorld():GetName()); + + return true; +end + + + + + diff --git a/MCServer/Plugins/ProtectionAreas/CommandState.lua b/MCServer/Plugins/ProtectionAreas/CommandState.lua index 2911688a8..f6d33d356 100644 --- a/MCServer/Plugins/ProtectionAreas/CommandState.lua +++ b/MCServer/Plugins/ProtectionAreas/CommandState.lua @@ -1,121 +1,121 @@ - --- CommandState.lua - --- Implements the cCommandState class representing a command state for each VIP player - ---[[ -The command state holds internal info, such as the coords they selected using the wand -The command state needs to be held in a per-entity manner, so that we can support multiple logins -from the same account (just for the fun of it) -The OOP class implementation follows the PiL 16.1 - -Also, a global table g_CommandStates is the map of PlayerEntityID -> cCommandState ---]] - - - - - -cCommandState = { - -- Default coords - m_Coords1 = {x = 0, z = 0}; -- lclk coords - m_Coords2 = {x = 0, z = 0}; -- rclk coords - m_LastCoords = 0; -- When Coords1 or Coords2 is set, this gets set to 1 or 2, signifying the last changed set of coords - m_HasCoords1 = false; -- Set to true when m_Coords1 has been set by the user - m_HasCoords2 = false; -- Set to true when m_Coords2 has been set by the user -}; - -g_CommandStates = {}; - - - - - -function cCommandState:new(obj) - obj = obj or {}; - setmetatable(obj, self); - self.__index = self; - return obj; -end - - - - - ---- Returns the current coord pair as a cCuboid object -function cCommandState:GetCurrentCuboid() - if (not(self.m_HasCoords1) or not(self.m_HasCoords2)) then - -- Some of the coords haven't been set yet - return nil; - end - - local res = cCuboid( - self.m_Coords1.x, 0, self.m_Coords1.z, - self.m_Coords2.x, 255, self.m_Coords2.z - ); - res:Sort(); - return res; -end - - - - - ---- Returns the x, z coords that were the set last, --- That is, either m_Coords1 or m_Coords2, based on m_LastCoords member --- Returns nothing if no coords were set yet -function cCommandState:GetLastCoords() - if (self.m_LastCoords == 0) then - -- No coords have been set yet - return; - elseif (self.m_LastCoords == 1) then - return self.m_Coords1.x, self.m_Coords1.z; - elseif (self.m_LastCoords == 2) then - return self.m_Coords2.x, self.m_Coords2.z; - else - LOGWARNING(PluginPrefix .. "cCommandState is in an unexpected state, m_LastCoords == " .. self.m_LastCoords); - return; - end -end - - - - - ---- Sets the first set of coords (upon rclk with a wand) -function cCommandState:SetCoords1(a_BlockX, a_BlockZ) - self.m_Coords1.x = a_BlockX; - self.m_Coords1.z = a_BlockZ; - self.m_LastCoords = 1; - self.m_HasCoords1 = true; -end - - - - - ---- Sets the second set of coords (upon lclk with a wand) -function cCommandState:SetCoords2(a_BlockX, a_BlockZ) - self.m_Coords2.x = a_BlockX; - self.m_Coords2.z = a_BlockZ; - self.m_LastCoords = 2; - self.m_HasCoords2 = true; -end - - - - - ---- Returns the cCommandState for the specified player; creates one if not existant -function GetCommandStateForPlayer(a_Player) - local res = g_CommandStates[a_Player:GetUniqueID()]; - if (res == nil) then - res = cCommandState:new(); - g_CommandStates[a_Player:GetUniqueID()] = res; - end - return res; -end; - - - - + +-- CommandState.lua + +-- Implements the cCommandState class representing a command state for each VIP player + +--[[ +The command state holds internal info, such as the coords they selected using the wand +The command state needs to be held in a per-entity manner, so that we can support multiple logins +from the same account (just for the fun of it) +The OOP class implementation follows the PiL 16.1 + +Also, a global table g_CommandStates is the map of PlayerEntityID -> cCommandState +--]] + + + + + +cCommandState = { + -- Default coords + m_Coords1 = {x = 0, z = 0}; -- lclk coords + m_Coords2 = {x = 0, z = 0}; -- rclk coords + m_LastCoords = 0; -- When Coords1 or Coords2 is set, this gets set to 1 or 2, signifying the last changed set of coords + m_HasCoords1 = false; -- Set to true when m_Coords1 has been set by the user + m_HasCoords2 = false; -- Set to true when m_Coords2 has been set by the user +}; + +g_CommandStates = {}; + + + + + +function cCommandState:new(obj) + obj = obj or {}; + setmetatable(obj, self); + self.__index = self; + return obj; +end + + + + + +--- Returns the current coord pair as a cCuboid object +function cCommandState:GetCurrentCuboid() + if (not(self.m_HasCoords1) or not(self.m_HasCoords2)) then + -- Some of the coords haven't been set yet + return nil; + end + + local res = cCuboid( + self.m_Coords1.x, 0, self.m_Coords1.z, + self.m_Coords2.x, 255, self.m_Coords2.z + ); + res:Sort(); + return res; +end + + + + + +--- Returns the x, z coords that were the set last, +-- That is, either m_Coords1 or m_Coords2, based on m_LastCoords member +-- Returns nothing if no coords were set yet +function cCommandState:GetLastCoords() + if (self.m_LastCoords == 0) then + -- No coords have been set yet + return; + elseif (self.m_LastCoords == 1) then + return self.m_Coords1.x, self.m_Coords1.z; + elseif (self.m_LastCoords == 2) then + return self.m_Coords2.x, self.m_Coords2.z; + else + LOGWARNING(PluginPrefix .. "cCommandState is in an unexpected state, m_LastCoords == " .. self.m_LastCoords); + return; + end +end + + + + + +--- Sets the first set of coords (upon rclk with a wand) +function cCommandState:SetCoords1(a_BlockX, a_BlockZ) + self.m_Coords1.x = a_BlockX; + self.m_Coords1.z = a_BlockZ; + self.m_LastCoords = 1; + self.m_HasCoords1 = true; +end + + + + + +--- Sets the second set of coords (upon lclk with a wand) +function cCommandState:SetCoords2(a_BlockX, a_BlockZ) + self.m_Coords2.x = a_BlockX; + self.m_Coords2.z = a_BlockZ; + self.m_LastCoords = 2; + self.m_HasCoords2 = true; +end + + + + + +--- Returns the cCommandState for the specified player; creates one if not existant +function GetCommandStateForPlayer(a_Player) + local res = g_CommandStates[a_Player:GetUniqueID()]; + if (res == nil) then + res = cCommandState:new(); + g_CommandStates[a_Player:GetUniqueID()] = res; + end + return res; +end; + + + + diff --git a/MCServer/Plugins/ProtectionAreas/Config.lua b/MCServer/Plugins/ProtectionAreas/Config.lua index b6fe34535..b40be0c75 100644 --- a/MCServer/Plugins/ProtectionAreas/Config.lua +++ b/MCServer/Plugins/ProtectionAreas/Config.lua @@ -1,55 +1,55 @@ - --- Config.lua - --- Implements the cConfig class that holds the general plugin configuration - - - - - -cConfig = { - m_Wand = cItem(E_ITEM_STICK, 1, 1); -- The item to be used as the selection wand - m_AllowInteractNoArea = true; -- If there's no area, is a player allowed to build / dig? -}; - - - - - ---- Initializes the cConfig object, loads the configuration from an INI file -function InitializeConfig() - local ini = cIniFile("ProtectionAreas.ini"); - if (not(ini:ReadFile())) then - LOGINFO(PluginPrefix .. "Cannot read ProtectionAreas.ini, all plugin configuration is set to defaults"); - end - local WandItem = cItem(); - if ( - StringToItem(ini:GetValueSet("ProtectionAreas", "WandItem", ItemToString(cConfig.m_Wand)), WandItem) and - IsValidItem(WandItem.m_ItemType) - ) then - cConfig.m_Wand = WandItem; - end - cConfig.m_AllowInteractNoArea = ini:GetValueSetB("ProtectionAreas", "AllowInteractNoArea", cConfig.m_AllowInteractNoArea); - ini:WriteFile(); -end - - - - - ---- Returns true if a_Item is the wand tool item -function cConfig:IsWand(a_Item) - return ( - (a_Item.m_ItemType == self.m_Wand.m_ItemType) and - (a_Item.m_ItemDamage == self.m_Wand.m_ItemDamage) - ); -end - - - - - ---- Returns the wand tool item as a cItem object -function cConfig:GetWandItem() - return self.m_Wand; + +-- Config.lua + +-- Implements the cConfig class that holds the general plugin configuration + + + + + +cConfig = { + m_Wand = cItem(E_ITEM_STICK, 1, 1); -- The item to be used as the selection wand + m_AllowInteractNoArea = true; -- If there's no area, is a player allowed to build / dig? +}; + + + + + +--- Initializes the cConfig object, loads the configuration from an INI file +function InitializeConfig() + local ini = cIniFile("ProtectionAreas.ini"); + if (not(ini:ReadFile())) then + LOGINFO(PluginPrefix .. "Cannot read ProtectionAreas.ini, all plugin configuration is set to defaults"); + end + local WandItem = cItem(); + if ( + StringToItem(ini:GetValueSet("ProtectionAreas", "WandItem", ItemToString(cConfig.m_Wand)), WandItem) and + IsValidItem(WandItem.m_ItemType) + ) then + cConfig.m_Wand = WandItem; + end + cConfig.m_AllowInteractNoArea = ini:GetValueSetB("ProtectionAreas", "AllowInteractNoArea", cConfig.m_AllowInteractNoArea); + ini:WriteFile(); +end + + + + + +--- Returns true if a_Item is the wand tool item +function cConfig:IsWand(a_Item) + return ( + (a_Item.m_ItemType == self.m_Wand.m_ItemType) and + (a_Item.m_ItemDamage == self.m_Wand.m_ItemDamage) + ); +end + + + + + +--- Returns the wand tool item as a cItem object +function cConfig:GetWandItem() + return self.m_Wand; end \ No newline at end of file diff --git a/MCServer/Plugins/ProtectionAreas/CurrentLng.lua b/MCServer/Plugins/ProtectionAreas/CurrentLng.lua index b0ad3863c..37ff135c5 100644 --- a/MCServer/Plugins/ProtectionAreas/CurrentLng.lua +++ b/MCServer/Plugins/ProtectionAreas/CurrentLng.lua @@ -1,76 +1,76 @@ - --- CurrentLng.lua --- This file provides all the translatable strings --- The expectation is that the translators will create copies of this file, translate the texts and then the users will overwrite this file with a specific language version --- Note that the individual languages must not have ".lua" extension, otherwise MCServer will load them and the plugin won't work! - - - - --- Individual commands, and their help strings. Don't touch the first symbol on each line! --- This needs to be implemented as a function, because it references other functions which might not yet be loaded while Lua is processing the globals - -function CommandReg() - return { - -- Handler function | Command | Permission | Help text - {HandleAddArea, "/ProtAdd", "Prot.Add", " - Adds a new protected area"}, - {HandleAddAreaCoords, "/ProtAddCoords", "Prot.Add", " - Adds a new protected area by coords"}, - {HandleAddAreaUser, "/ProtAddUser", "Prot.AddUser", " - Adds new users to an existing protected area"}, - {HandleDelArea, "/ProtDelID", "Prot.Del", " - Deletes a protected area by ID"}, - {HandleGiveWand, "/ProtWand", "Prot.Wand", " - Gives you the wand used for protection"}, - {HandleListAreas, "/ProtList", "Prot.List", "[ ] - Lists all areas for the marked block or given coords"}, - {HandleListUsers, "/ProtUsers", "Prot.List", " - Lists all allowed users for a given area ID"}, - {HandleRemoveUser, "/ProtRemUser", "Prot.RemUser", " - Removes a user from the protected area"}, - {HandleRemoveUserAll, "/ProtRemUserAll", "Prot.RemUser", " - Removes a user from all protected areas"}, - }; -end; - - - - - ---- Messages sent to players -g_Msgs = -{ - AllUsersAlreadyAllowed = "All the specified users were already allowed."; - AreaAdded = "Area added, ID %s"; - AreaAllowed = "Allowed"; - AreaDeleted = "Area ID %s deleted"; - AreaNotAllowed = "NOT allowed"; - Coords1Set = "Coords1 set as {%d, %d}"; - Coords2Set = "Coords2 set as {%d, %d}"; - ErrCmdStateNilAddArea = "Cannot add area, internal plugin error (CmdState == nil)"; - ErrCmdStateNilListAreas = "Cannot list areas, internal plugin error (CmdState == nil)"; - ErrDBFailAddUsers = "Cannot add users, DB failure"; - ErrExpectedAreaID = "Parameter mismatch. Expected ."; - ErrExpectedAreaIDUserName = "Parameter mismatch. Expected ."; - ErrExpectedAreaIDUsernames = "Not enough parameters. Expected and a list of usernames."; - ErrExpectedCoordsUsernames = "Not enough parameters. Expected coords and a list of usernames."; - ErrExpectedListOfUsernames = "Not enough parameters. Expected a list of usernames."; - ErrExpectedUserName = "Parameter mismatch. Expected ."; - ErrListNotWanded = "Cannot list areas, no query point has been selected. Use a ProtWand lclk / rclk to select a point first"; - ErrNoAreaWanded = "Cannot add area, no area has been selected. Use a ProtWand lclk / rclk to select area first"; - ErrNoSpaceForWand = "Cannot give wand, no space in your inventory"; - ErrNoSuchArea = "No such area: %s"; - ErrParseAreaID = "Cannot parse ."; - ErrParseCoords = "Cannot parse coords."; - ErrParseCoordsListAreas = "Cannot list areas, cannot parse coords in params"; - ErrSyntaxErrorListAreas = "Cannot list areas, syntax error. Expected either no params or ."; - ListAreasFooter = "Area list finished"; - ListAreasHeader = "Listing protection areas intersecting block column {%d, %d}:"; - ListAreasRow = " %s, %s, created by %s"; - ListUsersFooter = "End of area %s user list, total %d users"; - ListUsersHeader = "Area ID %s: {%d, %d} - {%d, %d}, created by %s; allowed users:"; - ListUsersRow = " %s"; - NotAllowedToBuild = "You are not allowed to build here!"; - NotAllowedToDig = "You are not allowed to dig here!"; - RemovedUser = "Removed %s from area %d"; - RemovedUserAll = "Removed %s from all areas"; - UsersAdded = "Users added: %s"; - WandGiven = "Wand given"; -} ; - - - - - + +-- CurrentLng.lua +-- This file provides all the translatable strings +-- The expectation is that the translators will create copies of this file, translate the texts and then the users will overwrite this file with a specific language version +-- Note that the individual languages must not have ".lua" extension, otherwise MCServer will load them and the plugin won't work! + + + + +-- Individual commands, and their help strings. Don't touch the first symbol on each line! +-- This needs to be implemented as a function, because it references other functions which might not yet be loaded while Lua is processing the globals + +function CommandReg() + return { + -- Handler function | Command | Permission | Help text + {HandleAddArea, "/ProtAdd", "Prot.Add", " - Adds a new protected area"}, + {HandleAddAreaCoords, "/ProtAddCoords", "Prot.Add", " - Adds a new protected area by coords"}, + {HandleAddAreaUser, "/ProtAddUser", "Prot.AddUser", " - Adds new users to an existing protected area"}, + {HandleDelArea, "/ProtDelID", "Prot.Del", " - Deletes a protected area by ID"}, + {HandleGiveWand, "/ProtWand", "Prot.Wand", " - Gives you the wand used for protection"}, + {HandleListAreas, "/ProtList", "Prot.List", "[ ] - Lists all areas for the marked block or given coords"}, + {HandleListUsers, "/ProtUsers", "Prot.List", " - Lists all allowed users for a given area ID"}, + {HandleRemoveUser, "/ProtRemUser", "Prot.RemUser", " - Removes a user from the protected area"}, + {HandleRemoveUserAll, "/ProtRemUserAll", "Prot.RemUser", " - Removes a user from all protected areas"}, + }; +end; + + + + + +--- Messages sent to players +g_Msgs = +{ + AllUsersAlreadyAllowed = "All the specified users were already allowed."; + AreaAdded = "Area added, ID %s"; + AreaAllowed = "Allowed"; + AreaDeleted = "Area ID %s deleted"; + AreaNotAllowed = "NOT allowed"; + Coords1Set = "Coords1 set as {%d, %d}"; + Coords2Set = "Coords2 set as {%d, %d}"; + ErrCmdStateNilAddArea = "Cannot add area, internal plugin error (CmdState == nil)"; + ErrCmdStateNilListAreas = "Cannot list areas, internal plugin error (CmdState == nil)"; + ErrDBFailAddUsers = "Cannot add users, DB failure"; + ErrExpectedAreaID = "Parameter mismatch. Expected ."; + ErrExpectedAreaIDUserName = "Parameter mismatch. Expected ."; + ErrExpectedAreaIDUsernames = "Not enough parameters. Expected and a list of usernames."; + ErrExpectedCoordsUsernames = "Not enough parameters. Expected coords and a list of usernames."; + ErrExpectedListOfUsernames = "Not enough parameters. Expected a list of usernames."; + ErrExpectedUserName = "Parameter mismatch. Expected ."; + ErrListNotWanded = "Cannot list areas, no query point has been selected. Use a ProtWand lclk / rclk to select a point first"; + ErrNoAreaWanded = "Cannot add area, no area has been selected. Use a ProtWand lclk / rclk to select area first"; + ErrNoSpaceForWand = "Cannot give wand, no space in your inventory"; + ErrNoSuchArea = "No such area: %s"; + ErrParseAreaID = "Cannot parse ."; + ErrParseCoords = "Cannot parse coords."; + ErrParseCoordsListAreas = "Cannot list areas, cannot parse coords in params"; + ErrSyntaxErrorListAreas = "Cannot list areas, syntax error. Expected either no params or ."; + ListAreasFooter = "Area list finished"; + ListAreasHeader = "Listing protection areas intersecting block column {%d, %d}:"; + ListAreasRow = " %s, %s, created by %s"; + ListUsersFooter = "End of area %s user list, total %d users"; + ListUsersHeader = "Area ID %s: {%d, %d} - {%d, %d}, created by %s; allowed users:"; + ListUsersRow = " %s"; + NotAllowedToBuild = "You are not allowed to build here!"; + NotAllowedToDig = "You are not allowed to dig here!"; + RemovedUser = "Removed %s from area %d"; + RemovedUserAll = "Removed %s from all areas"; + UsersAdded = "Users added: %s"; + WandGiven = "Wand given"; +} ; + + + + + diff --git a/MCServer/Plugins/ProtectionAreas/HookHandlers.lua b/MCServer/Plugins/ProtectionAreas/HookHandlers.lua index 18fd4fa03..ded64d298 100644 --- a/MCServer/Plugins/ProtectionAreas/HookHandlers.lua +++ b/MCServer/Plugins/ProtectionAreas/HookHandlers.lua @@ -1,139 +1,139 @@ - --- HookHandlers.lua --- Implements the handlers for individual hooks - - - - - ---- Registers all the hooks that the plugin needs to know about -function InitializeHooks(a_Plugin) - local PlgMgr = cRoot:Get():GetPluginManager(); - PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_DISCONNECT); - PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_LEFT_CLICK); - PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_MOVING); - PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICK); - PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_SPAWNED); -end - - - - - ---- Called by MCS when a player's connectino is lost - either they disconnected or timed out -function OnDisconnect(a_Player, a_Reason) - -- Remove the player's cProtectionArea object - g_PlayerAreas[a_Player:GetUniqueID()] = nil; - - -- If the player is a VIP, they had a command state, remove that as well - g_CommandStates[a_Player:GetUniqueID()] = nil; - - return false; -end; - - - - - ---- Called by MCS whenever a player enters a world (is spawned) -function OnPlayerSpawned(a_Player) - -- Create a new cPlayerAreas object for this player - if (g_PlayerAreas[a_Player:GetUniqueID()] == nil) then - LoadPlayerAreas(a_Player); - end; - - return false; -end - - - - - ---- Called by MCS whenever a player is moving (at most once every tick) -function OnPlayerMoving(a_Player) - local PlayerID = a_Player:GetUniqueID(); - - -- If for some reason we don't have a cPlayerAreas object for this player, load it up - local PlayerAreas = g_PlayerAreas[PlayerID]; - if (PlayerAreas == nil) then - LoadPlayerAreas(a_Player); - return false; - end; - - -- If the player is outside their areas' safe space, reload - if (not(PlayerAreas:IsInSafe(a_Player:GetPosX(), a_Player:GetPosZ()))) then - LoadPlayerAreas(a_Player); - end - return false; -end - - - - - ---- Called by MCS when a player left-clicks -function OnPlayerLeftClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status) - -- If the player has lclked with the wand; regardless of their permissions, let's set the coords: - if (cConfig:IsWand(a_Player:GetEquippedItem())) then - -- BlockFace < 0 means "use item", for which the coords are not given by the client - if (a_BlockFace < 0) then - return true; - end - - -- Convert the clicked coords into the block space - a_BlockX, a_BlockY, a_BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - -- Set the coords in the CommandState - GetCommandStateForPlayer(a_Player):SetCoords1(a_BlockX, a_BlockZ); - a_Player:SendMessage(string.format(g_Msgs.Coords1Set, a_BlockX, a_BlockZ)); - return true; - end; - - -- Check the player areas to see whether to disable this action - local Areas = g_PlayerAreas[a_Player:GetUniqueID()]; - if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then - a_Player:SendMessage(g_Msgs.NotAllowedToDig); - return true; - end - - -- Allow interaction - return false; -end - - - - - ---- Called by MCS when a player right-clicks -function OnPlayerRightClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_Status) - - -- BlockFace < 0 means "use item", for which the coords are not given by the client - if (a_BlockFace < 0) then - return true; - end - - -- Convert the clicked coords into the block space - a_BlockX, a_BlockY, a_BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - -- If the player has rclked with the wand; regardless of their permissions, let's set the coords - if (cConfig:IsWand(a_Player:GetEquippedItem())) then - -- Set the coords in the CommandState - GetCommandStateForPlayer(a_Player):SetCoords2(a_BlockX, a_BlockZ); - a_Player:SendMessage(string.format(g_Msgs.Coords2Set, a_BlockX, a_BlockZ)); - return true; - end; - - -- Check the player areas to see whether to disable this action - local Areas = g_PlayerAreas[a_Player:GetUniqueID()]; - if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then - a_Player:SendMessage(g_Msgs.NotAllowedToBuild); - return true; - end - - -- Allow interaction - return false; -end - - - - + +-- HookHandlers.lua +-- Implements the handlers for individual hooks + + + + + +--- Registers all the hooks that the plugin needs to know about +function InitializeHooks(a_Plugin) + local PlgMgr = cRoot:Get():GetPluginManager(); + PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_DISCONNECT); + PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_LEFT_CLICK); + PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_MOVING); + PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICK); + PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_SPAWNED); +end + + + + + +--- Called by MCS when a player's connectino is lost - either they disconnected or timed out +function OnDisconnect(a_Player, a_Reason) + -- Remove the player's cProtectionArea object + g_PlayerAreas[a_Player:GetUniqueID()] = nil; + + -- If the player is a VIP, they had a command state, remove that as well + g_CommandStates[a_Player:GetUniqueID()] = nil; + + return false; +end; + + + + + +--- Called by MCS whenever a player enters a world (is spawned) +function OnPlayerSpawned(a_Player) + -- Create a new cPlayerAreas object for this player + if (g_PlayerAreas[a_Player:GetUniqueID()] == nil) then + LoadPlayerAreas(a_Player); + end; + + return false; +end + + + + + +--- Called by MCS whenever a player is moving (at most once every tick) +function OnPlayerMoving(a_Player) + local PlayerID = a_Player:GetUniqueID(); + + -- If for some reason we don't have a cPlayerAreas object for this player, load it up + local PlayerAreas = g_PlayerAreas[PlayerID]; + if (PlayerAreas == nil) then + LoadPlayerAreas(a_Player); + return false; + end; + + -- If the player is outside their areas' safe space, reload + if (not(PlayerAreas:IsInSafe(a_Player:GetPosX(), a_Player:GetPosZ()))) then + LoadPlayerAreas(a_Player); + end + return false; +end + + + + + +--- Called by MCS when a player left-clicks +function OnPlayerLeftClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status) + -- If the player has lclked with the wand; regardless of their permissions, let's set the coords: + if (cConfig:IsWand(a_Player:GetEquippedItem())) then + -- BlockFace < 0 means "use item", for which the coords are not given by the client + if (a_BlockFace < 0) then + return true; + end + + -- Convert the clicked coords into the block space + a_BlockX, a_BlockY, a_BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + + -- Set the coords in the CommandState + GetCommandStateForPlayer(a_Player):SetCoords1(a_BlockX, a_BlockZ); + a_Player:SendMessage(string.format(g_Msgs.Coords1Set, a_BlockX, a_BlockZ)); + return true; + end; + + -- Check the player areas to see whether to disable this action + local Areas = g_PlayerAreas[a_Player:GetUniqueID()]; + if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then + a_Player:SendMessage(g_Msgs.NotAllowedToDig); + return true; + end + + -- Allow interaction + return false; +end + + + + + +--- Called by MCS when a player right-clicks +function OnPlayerRightClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_Status) + + -- BlockFace < 0 means "use item", for which the coords are not given by the client + if (a_BlockFace < 0) then + return true; + end + + -- Convert the clicked coords into the block space + a_BlockX, a_BlockY, a_BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + + -- If the player has rclked with the wand; regardless of their permissions, let's set the coords + if (cConfig:IsWand(a_Player:GetEquippedItem())) then + -- Set the coords in the CommandState + GetCommandStateForPlayer(a_Player):SetCoords2(a_BlockX, a_BlockZ); + a_Player:SendMessage(string.format(g_Msgs.Coords2Set, a_BlockX, a_BlockZ)); + return true; + end; + + -- Check the player areas to see whether to disable this action + local Areas = g_PlayerAreas[a_Player:GetUniqueID()]; + if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then + a_Player:SendMessage(g_Msgs.NotAllowedToBuild); + return true; + end + + -- Allow interaction + return false; +end + + + + diff --git a/MCServer/Plugins/ProtectionAreas/LICENSE.txt b/MCServer/Plugins/ProtectionAreas/LICENSE.txt index c46949f66..86c9130cc 100644 --- a/MCServer/Plugins/ProtectionAreas/LICENSE.txt +++ b/MCServer/Plugins/ProtectionAreas/LICENSE.txt @@ -1,7 +1,7 @@ - -ProtectionAreas license -======================= - -The ProtectionAreas plugin is written by _Xoft(o) / Mattes and is hereby released as public domain. - -If you like it, I'd really appreciate a postcard, or something tiny typical from your country :) The current snailmail address is at my personal web, http://xoft.cz . + +ProtectionAreas license +======================= + +The ProtectionAreas plugin is written by _Xoft(o) / Mattes and is hereby released as public domain. + +If you like it, I'd really appreciate a postcard, or something tiny typical from your country :) The current snailmail address is at my personal web, http://xoft.cz . diff --git a/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua b/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua index 5627f4d5f..f6106ee77 100644 --- a/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua +++ b/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua @@ -1,109 +1,109 @@ - --- PlayerAreas.lua --- Implements the cPlayerAreas class representing the per-player area storage object - ---[[ -Each player instance is expected to have a separate object of type cPlayerAreas. -Each object has an array of {cuboid, IsAllowed} tables, one for each area that is "within reach" -The code can then ask each object, whether the player can interact with a certain block or not. -A player can interact with a block if either one of these is true: -1, There are no areas covering the block -2, There is at least one area covering the block with IsAllowed set to true -The object also has a m_SafeCuboid object that specified the area within which the player may move -without the PlayerAreas needing a re-query. - -Also, a global table g_PlayerAreas is the actual map of PlayerID -> cPlayerAreas ---]] - - - - -cPlayerAreas = {}; - -g_PlayerAreas = {}; - - - - - -function cPlayerAreas:new(a_SafeMinX, a_SafeMinZ, a_SafeMaxX, a_SafeMaxZ) - assert(a_SafeMinX); - assert(a_SafeMinZ); - assert(a_SafeMaxX); - assert(a_SafeMaxZ); - - local obj = {}; - setmetatable(obj, self); - self.__index = self; - self.m_SafeCuboid = cCuboid(a_SafeMinX, 0, a_SafeMinZ, a_SafeMaxX, 255, a_SafeMaxZ); - return obj; -end - - - - --- Adds a new cuboid to the area list, where the player is either allowed or not, depending on the IsAllowed param -function cPlayerAreas:AddArea(a_Cuboid, a_IsAllowed) - table.insert(self, {m_Cuboid = a_Cuboid, m_IsAllowed = a_IsAllowed}); -end - - - - - ---- returns true if the player owning this object can interact with the specified block -function cPlayerAreas:CanInteractWithBlock(a_BlockX, a_BlockZ) - assert(self); - - -- iterate through all the stored areas: - local IsInsideAnyArea = false; - for idx, Area in ipairs(self) do - if (Area.m_Cuboid:IsInside(a_BlockX, 1, a_BlockZ)) then -- We don't care about Y coords, so use a dummy value - if (Area.m_IsAllowed) then - return true; - end - -- The coords are inside a cuboid for which the player doesn't have access, take a note of it - IsInsideAnyArea = true; - end - end - - if (IsInsideAnyArea) then - -- The specified coords are inside at least one area, but none of them allow the player to interact - return false; - end - - -- The coords are not inside any area - return cConfig.m_AllowInteractNoArea; -end - - - - - ---- Calls the specified callback for each area contained within --- a_Callback has a signature: function(a_Cuboid, a_IsAllowed) --- Returns true if all areas have been enumerated, false if the callback has aborted by returning true -function cPlayerAreas:ForEachArea(a_Callback) - assert(self); - - for idx, Area in ipairs(self) do - if (a_Callback(Area.m_Cuboid, Area.m_IsAllowed)) then - return false; - end - end - return true; -end - - - - - ---- Returns true if the player is withing the safe cuboid (no need to re-query the areas) -function cPlayerAreas:IsInSafe(a_BlockX, a_BlockZ) - assert(self); - return self.m_SafeCuboid:IsInside(a_BlockX, 0, a_BlockZ); -end - - - - + +-- PlayerAreas.lua +-- Implements the cPlayerAreas class representing the per-player area storage object + +--[[ +Each player instance is expected to have a separate object of type cPlayerAreas. +Each object has an array of {cuboid, IsAllowed} tables, one for each area that is "within reach" +The code can then ask each object, whether the player can interact with a certain block or not. +A player can interact with a block if either one of these is true: +1, There are no areas covering the block +2, There is at least one area covering the block with IsAllowed set to true +The object also has a m_SafeCuboid object that specified the area within which the player may move +without the PlayerAreas needing a re-query. + +Also, a global table g_PlayerAreas is the actual map of PlayerID -> cPlayerAreas +--]] + + + + +cPlayerAreas = {}; + +g_PlayerAreas = {}; + + + + + +function cPlayerAreas:new(a_SafeMinX, a_SafeMinZ, a_SafeMaxX, a_SafeMaxZ) + assert(a_SafeMinX); + assert(a_SafeMinZ); + assert(a_SafeMaxX); + assert(a_SafeMaxZ); + + local obj = {}; + setmetatable(obj, self); + self.__index = self; + self.m_SafeCuboid = cCuboid(a_SafeMinX, 0, a_SafeMinZ, a_SafeMaxX, 255, a_SafeMaxZ); + return obj; +end + + + + +-- Adds a new cuboid to the area list, where the player is either allowed or not, depending on the IsAllowed param +function cPlayerAreas:AddArea(a_Cuboid, a_IsAllowed) + table.insert(self, {m_Cuboid = a_Cuboid, m_IsAllowed = a_IsAllowed}); +end + + + + + +--- returns true if the player owning this object can interact with the specified block +function cPlayerAreas:CanInteractWithBlock(a_BlockX, a_BlockZ) + assert(self); + + -- iterate through all the stored areas: + local IsInsideAnyArea = false; + for idx, Area in ipairs(self) do + if (Area.m_Cuboid:IsInside(a_BlockX, 1, a_BlockZ)) then -- We don't care about Y coords, so use a dummy value + if (Area.m_IsAllowed) then + return true; + end + -- The coords are inside a cuboid for which the player doesn't have access, take a note of it + IsInsideAnyArea = true; + end + end + + if (IsInsideAnyArea) then + -- The specified coords are inside at least one area, but none of them allow the player to interact + return false; + end + + -- The coords are not inside any area + return cConfig.m_AllowInteractNoArea; +end + + + + + +--- Calls the specified callback for each area contained within +-- a_Callback has a signature: function(a_Cuboid, a_IsAllowed) +-- Returns true if all areas have been enumerated, false if the callback has aborted by returning true +function cPlayerAreas:ForEachArea(a_Callback) + assert(self); + + for idx, Area in ipairs(self) do + if (a_Callback(Area.m_Cuboid, Area.m_IsAllowed)) then + return false; + end + end + return true; +end + + + + + +--- Returns true if the player is withing the safe cuboid (no need to re-query the areas) +function cPlayerAreas:IsInSafe(a_BlockX, a_BlockZ) + assert(self); + return self.m_SafeCuboid:IsInside(a_BlockX, 0, a_BlockZ); +end + + + + diff --git a/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua b/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua index 8c2db1387..cbe3fa94d 100644 --- a/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua +++ b/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua @@ -1,71 +1,71 @@ - --- ProtectionAreas.lua --- Defines the main plugin entrypoint, as well as some utility functions - - - - - ---- Prefix for all messages logged to the server console -PluginPrefix = "ProtectionAreas: "; - ---- Bounds for the area loading. Areas less this far in any direction from the player will be loaded into cPlayerAreas -g_AreaBounds = 48; - ---- If a player moves this close to the PlayerAreas bounds, the PlayerAreas will be re-queried -g_AreaSafeEdge = 12; - - - - - ---- Called by MCS when the plugin loads --- Returns true if initialization successful, false otherwise -function Initialize(a_Plugin) - a_Plugin:SetName("ProtectionAreas"); - a_Plugin:SetVersion(1); - - InitializeConfig(); - if (not(InitializeStorage())) then - LOGWARNING(PluginPrefix .. "failed to initialize Storage, plugin is disabled"); - return false; - end - InitializeHooks(a_Plugin); - InitializeCommandHandlers(); - - -- We might be reloading, so there may be players already present in the server; reload all of them - cRoot:Get():ForEachWorld( - function(a_World) - ReloadAllPlayersInWorld(a_World:GetName()); - end - ); - - return true; -end - - - - - ---- Loads a cPlayerAreas object from the DB for the player, and assigns it to the player map -function LoadPlayerAreas(a_Player) - local PlayerID = a_Player:GetUniqueID(); - local PlayerX = math.floor(a_Player:GetPosX()); - local PlayerZ = math.floor(a_Player:GetPosZ()); - local WorldName = a_Player:GetWorld():GetName(); - g_PlayerAreas[PlayerID] = g_Storage:LoadPlayerAreas(a_Player:GetName(), PlayerX, PlayerZ, WorldName); -end - - - - - -function ReloadAllPlayersInWorld(a_WorldName) - local World = cRoot:Get():GetWorld(a_WorldName); - World:ForEachPlayer(LoadPlayerAreas); -end - - - - - + +-- ProtectionAreas.lua +-- Defines the main plugin entrypoint, as well as some utility functions + + + + + +--- Prefix for all messages logged to the server console +PluginPrefix = "ProtectionAreas: "; + +--- Bounds for the area loading. Areas less this far in any direction from the player will be loaded into cPlayerAreas +g_AreaBounds = 48; + +--- If a player moves this close to the PlayerAreas bounds, the PlayerAreas will be re-queried +g_AreaSafeEdge = 12; + + + + + +--- Called by MCS when the plugin loads +-- Returns true if initialization successful, false otherwise +function Initialize(a_Plugin) + a_Plugin:SetName("ProtectionAreas"); + a_Plugin:SetVersion(1); + + InitializeConfig(); + if (not(InitializeStorage())) then + LOGWARNING(PluginPrefix .. "failed to initialize Storage, plugin is disabled"); + return false; + end + InitializeHooks(a_Plugin); + InitializeCommandHandlers(); + + -- We might be reloading, so there may be players already present in the server; reload all of them + cRoot:Get():ForEachWorld( + function(a_World) + ReloadAllPlayersInWorld(a_World:GetName()); + end + ); + + return true; +end + + + + + +--- Loads a cPlayerAreas object from the DB for the player, and assigns it to the player map +function LoadPlayerAreas(a_Player) + local PlayerID = a_Player:GetUniqueID(); + local PlayerX = math.floor(a_Player:GetPosX()); + local PlayerZ = math.floor(a_Player:GetPosZ()); + local WorldName = a_Player:GetWorld():GetName(); + g_PlayerAreas[PlayerID] = g_Storage:LoadPlayerAreas(a_Player:GetName(), PlayerX, PlayerZ, WorldName); +end + + + + + +function ReloadAllPlayersInWorld(a_WorldName) + local World = cRoot:Get():GetWorld(a_WorldName); + World:ForEachPlayer(LoadPlayerAreas); +end + + + + + diff --git a/MCServer/Plugins/ProtectionAreas/Storage.lua b/MCServer/Plugins/ProtectionAreas/Storage.lua index 07825b172..a6cf564bf 100644 --- a/MCServer/Plugins/ProtectionAreas/Storage.lua +++ b/MCServer/Plugins/ProtectionAreas/Storage.lua @@ -1,518 +1,518 @@ - --- Storage.lua --- Implements the storage access object, shielding the rest of the code away from the DB - ---[[ -The cStorage class is the interface to the underlying storage, the SQLite database. -This class knows how to load player areas from the DB, how to add or remove areas in the DB -and other such operations. - -Also, a g_Storage global variable is declared, it holds the single instance of the storage. ---]] - - - - - -cStorage = {}; - -g_Storage = {}; - - - - - ---- Initializes the storage subsystem, creates the g_Storage object --- Returns true if successful, false if not -function InitializeStorage() - g_Storage = cStorage:new(); - if (not(g_Storage:OpenDB())) then - return false; - end - - return true; -end - - - - - -function cStorage:new(obj) - obj = obj or {}; - setmetatable(obj, self); - self.__index = self; - return obj; -end - - - - ---- Opens the DB and makes sure it has all the columns needed --- Returns true if successful, false otherwise -function cStorage:OpenDB() - local ErrCode, ErrMsg; - self.DB, ErrCode, ErrMsg = sqlite3.open("ProtectionAreas.sqlite"); - if (self.DB == nil) then - LOGWARNING(PluginPrefix .. "Cannot open ProtectionAreas.sqlite, error " .. ErrCode .. " (" .. ErrMsg ..")"); - return false; - end - - if ( - not(self:CreateTable("Areas", {"ID INTEGER PRIMARY KEY AUTOINCREMENT", "MinX", "MaxX", "MinZ", "MaxZ", "WorldName", "CreatorUserName"})) or - not(self:CreateTable("AllowedUsers", {"AreaID", "UserName"})) - ) then - LOGWARNING(PluginPrefix .. "Cannot create DB tables!"); - return false; - end - - return true; -end - - - - - ---- Executes the SQL command given, calling the a_Callback for each result --- If the SQL command fails, prints it out on the server console and returns false --- Returns true on success -function cStorage:DBExec(a_SQL, a_Callback, a_CallbackParam) - local ErrCode = self.DB:exec(a_SQL, a_Callback, a_CallbackParam); - if (ErrCode ~= sqlite3.OK) then - LOGWARNING(PluginPrefix .. "Error " .. ErrCode .. " (" .. self.DB:errmsg() .. - ") while processing SQL command >>" .. a_SQL .. "<<" - ); - return false; - end - return true; -end - - - - - ---- Creates the table of the specified name and columns[] --- If the table exists, any columns missing are added; existing data is kept -function cStorage:CreateTable(a_TableName, a_Columns) - -- Try to create the table first - local sql = "CREATE TABLE IF NOT EXISTS '" .. a_TableName .. "' ("; - sql = sql .. table.concat(a_Columns, ", "); - sql = sql .. ")"; - if (not(self:DBExec(sql))) then - LOGWARNING(PluginPrefix .. "Cannot create DB Table " .. a_TableName); - return false; - end - -- SQLite doesn't inform us if it created the table or not, so we have to continue anyway - - -- Check each column whether it exists - -- Remove all the existing columns from a_Columns: - local RemoveExistingColumn = function(UserData, NumCols, Values, Names) - -- Remove the received column from a_Columns. Search for column name in the Names[] / Values[] pairs - for i = 1, NumCols do - if (Names[i] == "name") then - local ColumnName = Values[i]:lower(); - -- Search the a_Columns if they have that column: - for j = 1, #a_Columns do - -- Cut away all column specifiers (after the first space), if any: - local SpaceIdx = string.find(a_Columns[j], " "); - if (SpaceIdx ~= nil) then - SpaceIdx = SpaceIdx - 1; - end - local ColumnTemplate = string.lower(string.sub(a_Columns[j], 1, SpaceIdx)); - -- If it is a match, remove from a_Columns: - if (ColumnTemplate == ColumnName) then - table.remove(a_Columns, j); - break; -- for j - end - end -- for j - a_Columns[] - end - end -- for i - Names[] / Values[] - return 0; - end - if (not(self:DBExec("PRAGMA table_info(" .. a_TableName .. ")", RemoveExistingColumn))) then - LOGWARNING(PluginPrefix .. "Cannot query DB table structure"); - return false; - end - - -- Create the missing columns - -- a_Columns now contains only those columns that are missing in the DB - if (#a_Columns > 0) then - LOGINFO(PluginPrefix .. "Database table \"" .. a_TableName .. "\" is missing " .. #a_Columns .. " columns, fixing now."); - for idx, ColumnName in ipairs(a_Columns) do - if (not(self:DBExec("ALTER TABLE '" .. a_TableName .. "' ADD COLUMN " .. ColumnName))) then - LOGWARNING(PluginPrefix .. "Cannot add DB table \"" .. a_TableName .. "\" column \"" .. ColumnName .. "\""); - return false; - end - end - LOGINFO(PluginPrefix .. "Database table \"" .. a_TableName .. "\" columns fixed."); - end - - return true; -end - - - - - ---- Returns true if the specified area is allowed for the specified player -function cStorage:IsAreaAllowed(a_AreaID, a_PlayerName, a_WorldName) - assert(a_AreaID); - assert(a_PlayerName); - assert(a_WorldName); - assert(self); - - local lcPlayerName = string.lower(a_PlayerName); - local res = false; - local sql = "SELECT COUNT(*) FROM AllowedUsers WHERE (AreaID = " .. a_AreaID .. - ") AND (UserName ='" .. lcPlayerName .. "')"; - local function SetResTrue(UserData, NumValues, Values, Names) - res = (tonumber(Values[1]) > 0); - return 0; - end - if (not(self:DBExec(sql, SetResTrue))) then - LOGWARNING("SQL error while determining area allowance"); - return false; - end - return res; -end - - - - - ---- Loads cPlayerAreas for the specified player from the DB. Returns a cPlayerAreas object -function cStorage:LoadPlayerAreas(a_PlayerName, a_PlayerX, a_PlayerZ, a_WorldName) - assert(a_PlayerName); - assert(a_PlayerX); - assert(a_PlayerZ); - assert(a_WorldName); - assert(self); - - -- Bounds for which the areas are loaded - local BoundsMinX = a_PlayerX - g_AreaBounds; - local BoundsMaxX = a_PlayerX + g_AreaBounds; - local BoundsMinZ = a_PlayerZ - g_AreaBounds; - local BoundsMaxZ = a_PlayerZ + g_AreaBounds; - - local res = cPlayerAreas:new( - BoundsMinX + g_AreaSafeEdge, BoundsMinZ + g_AreaSafeEdge, - BoundsMaxX - g_AreaSafeEdge, BoundsMaxZ - g_AreaSafeEdge - ); - - --[[ - LOG("Loading protection areas for player " .. a_PlayerName .. " centered around {" .. a_PlayerX .. ", " .. a_PlayerZ .. - "}, bounds are {" .. BoundsMinX .. ", " .. BoundsMinZ .. "} - {" .. - BoundsMaxX .. ", " .. BoundsMaxZ .. "}" - ); - --]] - - -- Load the areas from the DB, based on the player's location - local lcWorldName = string.lower(a_WorldName); - local sql = - "SELECT ID, MinX, MaxX, MinZ, MaxZ FROM Areas WHERE " .. - "MinX < " .. BoundsMaxX .. " AND MaxX > " .. BoundsMinX .. " AND " .. - "MinZ < " .. BoundsMaxZ .. " AND MaxZ > " .. BoundsMinZ .. " AND " .. - "WorldName = '" .. lcWorldName .."'"; - - local function AddAreas(UserData, NumValues, Values, Names) - if ((NumValues < 5) or ((Values[1] and Values[2] and Values[3] and Values[4] and Values[5]) == nil)) then - LOGWARNING("SQL query didn't return all data"); - return 0; - end - res:AddArea(cCuboid(Values[2], 0, Values[4], Values[3], 255, Values[5]), self:IsAreaAllowed(Values[1], a_PlayerName, a_WorldName)); - return 0; - end - - if (not(self:DBExec(sql, AddAreas))) then - LOGWARNING("SQL error while querying areas"); - return res; - end - - return res; -end - - - - - ---- Adds a new area into the DB. a_AllowedNames is a table listing all the players that are allowed in the area --- Returns the ID of the new area, or -1 on failure -function cStorage:AddArea(a_Cuboid, a_WorldName, a_CreatorName, a_AllowedNames) - assert(a_Cuboid); - assert(a_WorldName); - assert(a_CreatorName); - assert(a_AllowedNames); - assert(self); - - -- Store the area in the DB - local ID = -1; - local function RememberID(UserData, NumCols, Values, Names) - for i = 1, NumCols do - if (Names[i] == "ID") then - ID = Values[i]; - end - end - return 0; - end - local lcWorldName = string.lower(a_WorldName); - local lcCreatorName = string.lower(a_CreatorName); - local sql = - "INSERT INTO Areas (ID, MinX, MaxX, MinZ, MaxZ, WorldName, CreatorUserName) VALUES (NULL, " .. - a_Cuboid.p1.x .. ", " .. a_Cuboid.p2.x .. ", " .. a_Cuboid.p1.z .. ", " .. a_Cuboid.p2.z .. - ", '" .. lcWorldName .. "', '" .. lcCreatorName .. - "'); SELECT last_insert_rowid() AS ID"; - if (not(self:DBExec(sql, RememberID))) then - LOGWARNING(PluginPrefix .. "SQL Error while inserting new area"); - return -1; - end - if (ID == -1) then - LOGWARNING(PluginPrefix .. "SQL Error while retrieving INSERTion ID"); - return -1; - end - - -- Store each allowed player in the DB - for idx, Name in ipairs(a_AllowedNames) do - local lcName = string.lower(Name); - local sql = "INSERT INTO AllowedUsers (AreaID, UserName) VALUES (" .. ID .. ", '" .. lcName .. "')"; - if (not(self:DBExec(sql))) then - LOGWARNING(PluginPrefix .. "SQL Error while inserting new area's allowed player " .. Name); - end - end - return ID; -end - - - - - -function cStorage:DelArea(a_WorldName, a_AreaID) - assert(a_WorldName); - assert(a_AreaID); - assert(self); - - -- Since all areas are stored in a single DB (for now), the worldname parameter isn't used at all - -- Later if we change to a per-world DB, we'll need the world name - - -- Delete from both tables simultaneously - local sql = - "DELETE FROM Areas WHERE ID = " .. a_AreaID .. ";" .. - "DELETE FROM AllowedUsers WHERE AreaID = " .. a_AreaID; - if (not(self:DBExec(sql))) then - LOGWARNING(PluginPrefix .. "SQL error while deleting area " .. a_AreaID .. " from world \"" .. a_WorldName .. "\""); - return false; - end - - return true; -end - - - - - ---- Removes the user from the specified area -function cStorage:RemoveUser(a_AreaID, a_UserName, a_WorldName) - assert(a_AreaID); - assert(a_UserName); - assert(a_WorldName); - assert(self); - - -- WorldName is not used yet, because all the worlds share the same DB in this version - - local lcUserName = string.lower(a_UserName); - local sql = "DELETE FROM AllowedUsers WHERE " .. - "AreaID = " .. a_AreaID .. " AND UserName = '" .. lcUserName .. "'"; - if (not(self:DBExec(sql))) then - LOGWARNING("SQL error while removing user " .. a_UserName .. " from area ID " .. a_AreaID); - return false; - end - return true; -end - - - - - ---- Removes the user from all areas in the specified world -function cStorage:RemoveUserAll(a_UserName, a_WorldName) - assert(a_UserName); - assert(a_WorldName); - assert(self); - - local lcUserName = string.lower(a_UserName); - local sql = "DELETE FROM AllowedUsers WHERE UserName = '" .. lcUserName .."'"; - if (not(self:DBExec(sql))) then - LOGWARNING("SQL error while removing user " .. a_UserName .. " from all areas"); - return false; - end - return true; -end - - - - - ---- Calls the callback for each area intersecting the specified coords --- Callback signature: function(ID, MinX, MinZ, MaxX, MaxZ, CreatorName) -function cStorage:ForEachArea(a_BlockX, a_BlockZ, a_WorldName, a_Callback) - assert(a_BlockX); - assert(a_BlockZ); - assert(a_WorldName); - assert(a_Callback); - assert(self); - - -- SQL callback that parses the values and calls our callback - function CallCallback(UserData, NumValues, Values, Names) - if (NumValues ~= 6) then - -- Not enough values returned, skip this row - return 0; - end - local ID = Values[1]; - local MinX = Values[2]; - local MinZ = Values[3]; - local MaxX = Values[4]; - local MaxZ = Values[5]; - local CreatorName = Values[6]; - a_Callback(ID, MinX, MinZ, MaxX, MaxZ, CreatorName); - return 0; - end - - local lcWorldName = string.lower(a_WorldName); - local sql = "SELECT ID, MinX, MinZ, MaxX, MaxZ, CreatorUserName FROM Areas WHERE " .. - "MinX <= " .. a_BlockX .. " AND MaxX >= " .. a_BlockX .. " AND " .. - "MinZ <= " .. a_BlockZ .. " AND MaxZ >= " .. a_BlockZ .. " AND " .. - "WorldName = '" .. lcWorldName .. "'"; - if (not(self:DBExec(sql, CallCallback))) then - LOGWARNING("SQL Error while iterating through areas (cStorage:ForEachArea())"); - return false; - end - return true; -end - - - - - ---- Returns the info on the specified area --- Returns MinX, MinZ, MaxX, MaxZ, CreatorName on success, or nothing on failure -function cStorage:GetArea(a_AreaID, a_WorldName) - assert(a_AreaID); - assert(a_WorldName); - assert(self); - - local MinX, MinZ, MaxX, MaxZ, CreatorName; - local HasValues = false; - - -- SQL callback that parses the values and remembers them in variables - function RememberValues(UserData, NumValues, Values, Names) - if (NumValues ~= 5) then - -- Not enough values returned, skip this row - return 0; - end - MinX = Values[1]; - MinZ = Values[2]; - MaxX = Values[3]; - MaxZ = Values[4]; - CreatorName = Values[5]; - HasValues = true; - return 0; - end - - local lcWorldName = string.lower(a_WorldName); - local sql = "SELECT MinX, MinZ, MaxX, MaxZ, CreatorUserName FROM Areas WHERE " .. - "ID = " .. a_AreaID .. " AND WorldName = '" .. lcWorldName .. "'"; - if (not(self:DBExec(sql, RememberValues))) then - LOGWARNING("SQL Error while getting area info (cStorage:ForEachArea())"); - return; - end - - -- If no data has been retrieved, return nothing - if (not(HasValues)) then - return; - end - - return MinX, MinZ, MaxX, MaxZ, CreatorName; -end - - - - - ---- Calls the callback for each allowed user for the specified area --- Callback signature: function(UserName) -function cStorage:ForEachUserInArea(a_AreaID, a_WorldName, a_Callback) - assert(a_AreaID); - assert(a_WorldName); - assert(a_Callback); - assert(self); - - -- Since in this version all the worlds share a single DB, the a_WorldName parameter is not actually used - -- But this may change in the future, when we have a per-world DB - - local function CallCallback(UserData, NumValues, Values) - if (NumValues ~= 1) then - return 0; - end - a_Callback(Values[1]); - return 0; - end - local sql = "SELECT UserName FROM AllowedUsers WHERE AreaID = " .. a_AreaID; - if (not(self:DBExec(sql, CallCallback))) then - LOGWARNING("SQL error while iterating area users for AreaID" .. a_AreaID); - return false; - end - return true; -end - - - - - ---- Adds the specified usernames to the specified area, if not already present --- a_Users is an array table of usernames to add -function cStorage:AddAreaUsers(a_AreaID, a_WorldName, a_AddedBy, a_Users) - assert(a_AreaID); - assert(a_WorldName); - assert(a_Users); - assert(self); - - -- Convert all usernames to lowercase - for idx, Name in ipairs(a_Users) do - a_Users[idx] = string.lower(Name); - end - - -- Remove from a_Users the usernames already present in the area - local sql = "SELECT UserName FROM AllowedUsers WHERE AreaID = " .. a_AreaID; - local function RemovePresent(UserData, NumValues, Values, Names) - if (NumValues ~= 1) then - -- Invalid response format - return 0; - end - local DBName = Values[1]; - -- Remove the name from a_Users, if exists - for idx, Name in ipairs(a_Users) do - if (Name == DBName) then - table.remove(a_Users, idx); - return 0; - end - end - return 0; - end - if (not(self:DBExec(sql, RemovePresent))) then - LOGWARNING("SQL error while iterating through users"); - return false; - end - - -- Add the users - for idx, Name in ipairs(a_Users) do - local sql = "INSERT INTO AllowedUsers (AreaID, UserName) VALUES (" .. a_AreaID .. ", '" .. Name .. "')"; - if (not(self:DBExec(sql))) then - LOGWARNING("SQL error while adding user " .. Name .. " to area " .. a_AreaID); - end - end - - return true; -end - - - - - + +-- Storage.lua +-- Implements the storage access object, shielding the rest of the code away from the DB + +--[[ +The cStorage class is the interface to the underlying storage, the SQLite database. +This class knows how to load player areas from the DB, how to add or remove areas in the DB +and other such operations. + +Also, a g_Storage global variable is declared, it holds the single instance of the storage. +--]] + + + + + +cStorage = {}; + +g_Storage = {}; + + + + + +--- Initializes the storage subsystem, creates the g_Storage object +-- Returns true if successful, false if not +function InitializeStorage() + g_Storage = cStorage:new(); + if (not(g_Storage:OpenDB())) then + return false; + end + + return true; +end + + + + + +function cStorage:new(obj) + obj = obj or {}; + setmetatable(obj, self); + self.__index = self; + return obj; +end + + + + +--- Opens the DB and makes sure it has all the columns needed +-- Returns true if successful, false otherwise +function cStorage:OpenDB() + local ErrCode, ErrMsg; + self.DB, ErrCode, ErrMsg = sqlite3.open("ProtectionAreas.sqlite"); + if (self.DB == nil) then + LOGWARNING(PluginPrefix .. "Cannot open ProtectionAreas.sqlite, error " .. ErrCode .. " (" .. ErrMsg ..")"); + return false; + end + + if ( + not(self:CreateTable("Areas", {"ID INTEGER PRIMARY KEY AUTOINCREMENT", "MinX", "MaxX", "MinZ", "MaxZ", "WorldName", "CreatorUserName"})) or + not(self:CreateTable("AllowedUsers", {"AreaID", "UserName"})) + ) then + LOGWARNING(PluginPrefix .. "Cannot create DB tables!"); + return false; + end + + return true; +end + + + + + +--- Executes the SQL command given, calling the a_Callback for each result +-- If the SQL command fails, prints it out on the server console and returns false +-- Returns true on success +function cStorage:DBExec(a_SQL, a_Callback, a_CallbackParam) + local ErrCode = self.DB:exec(a_SQL, a_Callback, a_CallbackParam); + if (ErrCode ~= sqlite3.OK) then + LOGWARNING(PluginPrefix .. "Error " .. ErrCode .. " (" .. self.DB:errmsg() .. + ") while processing SQL command >>" .. a_SQL .. "<<" + ); + return false; + end + return true; +end + + + + + +--- Creates the table of the specified name and columns[] +-- If the table exists, any columns missing are added; existing data is kept +function cStorage:CreateTable(a_TableName, a_Columns) + -- Try to create the table first + local sql = "CREATE TABLE IF NOT EXISTS '" .. a_TableName .. "' ("; + sql = sql .. table.concat(a_Columns, ", "); + sql = sql .. ")"; + if (not(self:DBExec(sql))) then + LOGWARNING(PluginPrefix .. "Cannot create DB Table " .. a_TableName); + return false; + end + -- SQLite doesn't inform us if it created the table or not, so we have to continue anyway + + -- Check each column whether it exists + -- Remove all the existing columns from a_Columns: + local RemoveExistingColumn = function(UserData, NumCols, Values, Names) + -- Remove the received column from a_Columns. Search for column name in the Names[] / Values[] pairs + for i = 1, NumCols do + if (Names[i] == "name") then + local ColumnName = Values[i]:lower(); + -- Search the a_Columns if they have that column: + for j = 1, #a_Columns do + -- Cut away all column specifiers (after the first space), if any: + local SpaceIdx = string.find(a_Columns[j], " "); + if (SpaceIdx ~= nil) then + SpaceIdx = SpaceIdx - 1; + end + local ColumnTemplate = string.lower(string.sub(a_Columns[j], 1, SpaceIdx)); + -- If it is a match, remove from a_Columns: + if (ColumnTemplate == ColumnName) then + table.remove(a_Columns, j); + break; -- for j + end + end -- for j - a_Columns[] + end + end -- for i - Names[] / Values[] + return 0; + end + if (not(self:DBExec("PRAGMA table_info(" .. a_TableName .. ")", RemoveExistingColumn))) then + LOGWARNING(PluginPrefix .. "Cannot query DB table structure"); + return false; + end + + -- Create the missing columns + -- a_Columns now contains only those columns that are missing in the DB + if (#a_Columns > 0) then + LOGINFO(PluginPrefix .. "Database table \"" .. a_TableName .. "\" is missing " .. #a_Columns .. " columns, fixing now."); + for idx, ColumnName in ipairs(a_Columns) do + if (not(self:DBExec("ALTER TABLE '" .. a_TableName .. "' ADD COLUMN " .. ColumnName))) then + LOGWARNING(PluginPrefix .. "Cannot add DB table \"" .. a_TableName .. "\" column \"" .. ColumnName .. "\""); + return false; + end + end + LOGINFO(PluginPrefix .. "Database table \"" .. a_TableName .. "\" columns fixed."); + end + + return true; +end + + + + + +--- Returns true if the specified area is allowed for the specified player +function cStorage:IsAreaAllowed(a_AreaID, a_PlayerName, a_WorldName) + assert(a_AreaID); + assert(a_PlayerName); + assert(a_WorldName); + assert(self); + + local lcPlayerName = string.lower(a_PlayerName); + local res = false; + local sql = "SELECT COUNT(*) FROM AllowedUsers WHERE (AreaID = " .. a_AreaID .. + ") AND (UserName ='" .. lcPlayerName .. "')"; + local function SetResTrue(UserData, NumValues, Values, Names) + res = (tonumber(Values[1]) > 0); + return 0; + end + if (not(self:DBExec(sql, SetResTrue))) then + LOGWARNING("SQL error while determining area allowance"); + return false; + end + return res; +end + + + + + +--- Loads cPlayerAreas for the specified player from the DB. Returns a cPlayerAreas object +function cStorage:LoadPlayerAreas(a_PlayerName, a_PlayerX, a_PlayerZ, a_WorldName) + assert(a_PlayerName); + assert(a_PlayerX); + assert(a_PlayerZ); + assert(a_WorldName); + assert(self); + + -- Bounds for which the areas are loaded + local BoundsMinX = a_PlayerX - g_AreaBounds; + local BoundsMaxX = a_PlayerX + g_AreaBounds; + local BoundsMinZ = a_PlayerZ - g_AreaBounds; + local BoundsMaxZ = a_PlayerZ + g_AreaBounds; + + local res = cPlayerAreas:new( + BoundsMinX + g_AreaSafeEdge, BoundsMinZ + g_AreaSafeEdge, + BoundsMaxX - g_AreaSafeEdge, BoundsMaxZ - g_AreaSafeEdge + ); + + --[[ + LOG("Loading protection areas for player " .. a_PlayerName .. " centered around {" .. a_PlayerX .. ", " .. a_PlayerZ .. + "}, bounds are {" .. BoundsMinX .. ", " .. BoundsMinZ .. "} - {" .. + BoundsMaxX .. ", " .. BoundsMaxZ .. "}" + ); + --]] + + -- Load the areas from the DB, based on the player's location + local lcWorldName = string.lower(a_WorldName); + local sql = + "SELECT ID, MinX, MaxX, MinZ, MaxZ FROM Areas WHERE " .. + "MinX < " .. BoundsMaxX .. " AND MaxX > " .. BoundsMinX .. " AND " .. + "MinZ < " .. BoundsMaxZ .. " AND MaxZ > " .. BoundsMinZ .. " AND " .. + "WorldName = '" .. lcWorldName .."'"; + + local function AddAreas(UserData, NumValues, Values, Names) + if ((NumValues < 5) or ((Values[1] and Values[2] and Values[3] and Values[4] and Values[5]) == nil)) then + LOGWARNING("SQL query didn't return all data"); + return 0; + end + res:AddArea(cCuboid(Values[2], 0, Values[4], Values[3], 255, Values[5]), self:IsAreaAllowed(Values[1], a_PlayerName, a_WorldName)); + return 0; + end + + if (not(self:DBExec(sql, AddAreas))) then + LOGWARNING("SQL error while querying areas"); + return res; + end + + return res; +end + + + + + +--- Adds a new area into the DB. a_AllowedNames is a table listing all the players that are allowed in the area +-- Returns the ID of the new area, or -1 on failure +function cStorage:AddArea(a_Cuboid, a_WorldName, a_CreatorName, a_AllowedNames) + assert(a_Cuboid); + assert(a_WorldName); + assert(a_CreatorName); + assert(a_AllowedNames); + assert(self); + + -- Store the area in the DB + local ID = -1; + local function RememberID(UserData, NumCols, Values, Names) + for i = 1, NumCols do + if (Names[i] == "ID") then + ID = Values[i]; + end + end + return 0; + end + local lcWorldName = string.lower(a_WorldName); + local lcCreatorName = string.lower(a_CreatorName); + local sql = + "INSERT INTO Areas (ID, MinX, MaxX, MinZ, MaxZ, WorldName, CreatorUserName) VALUES (NULL, " .. + a_Cuboid.p1.x .. ", " .. a_Cuboid.p2.x .. ", " .. a_Cuboid.p1.z .. ", " .. a_Cuboid.p2.z .. + ", '" .. lcWorldName .. "', '" .. lcCreatorName .. + "'); SELECT last_insert_rowid() AS ID"; + if (not(self:DBExec(sql, RememberID))) then + LOGWARNING(PluginPrefix .. "SQL Error while inserting new area"); + return -1; + end + if (ID == -1) then + LOGWARNING(PluginPrefix .. "SQL Error while retrieving INSERTion ID"); + return -1; + end + + -- Store each allowed player in the DB + for idx, Name in ipairs(a_AllowedNames) do + local lcName = string.lower(Name); + local sql = "INSERT INTO AllowedUsers (AreaID, UserName) VALUES (" .. ID .. ", '" .. lcName .. "')"; + if (not(self:DBExec(sql))) then + LOGWARNING(PluginPrefix .. "SQL Error while inserting new area's allowed player " .. Name); + end + end + return ID; +end + + + + + +function cStorage:DelArea(a_WorldName, a_AreaID) + assert(a_WorldName); + assert(a_AreaID); + assert(self); + + -- Since all areas are stored in a single DB (for now), the worldname parameter isn't used at all + -- Later if we change to a per-world DB, we'll need the world name + + -- Delete from both tables simultaneously + local sql = + "DELETE FROM Areas WHERE ID = " .. a_AreaID .. ";" .. + "DELETE FROM AllowedUsers WHERE AreaID = " .. a_AreaID; + if (not(self:DBExec(sql))) then + LOGWARNING(PluginPrefix .. "SQL error while deleting area " .. a_AreaID .. " from world \"" .. a_WorldName .. "\""); + return false; + end + + return true; +end + + + + + +--- Removes the user from the specified area +function cStorage:RemoveUser(a_AreaID, a_UserName, a_WorldName) + assert(a_AreaID); + assert(a_UserName); + assert(a_WorldName); + assert(self); + + -- WorldName is not used yet, because all the worlds share the same DB in this version + + local lcUserName = string.lower(a_UserName); + local sql = "DELETE FROM AllowedUsers WHERE " .. + "AreaID = " .. a_AreaID .. " AND UserName = '" .. lcUserName .. "'"; + if (not(self:DBExec(sql))) then + LOGWARNING("SQL error while removing user " .. a_UserName .. " from area ID " .. a_AreaID); + return false; + end + return true; +end + + + + + +--- Removes the user from all areas in the specified world +function cStorage:RemoveUserAll(a_UserName, a_WorldName) + assert(a_UserName); + assert(a_WorldName); + assert(self); + + local lcUserName = string.lower(a_UserName); + local sql = "DELETE FROM AllowedUsers WHERE UserName = '" .. lcUserName .."'"; + if (not(self:DBExec(sql))) then + LOGWARNING("SQL error while removing user " .. a_UserName .. " from all areas"); + return false; + end + return true; +end + + + + + +--- Calls the callback for each area intersecting the specified coords +-- Callback signature: function(ID, MinX, MinZ, MaxX, MaxZ, CreatorName) +function cStorage:ForEachArea(a_BlockX, a_BlockZ, a_WorldName, a_Callback) + assert(a_BlockX); + assert(a_BlockZ); + assert(a_WorldName); + assert(a_Callback); + assert(self); + + -- SQL callback that parses the values and calls our callback + function CallCallback(UserData, NumValues, Values, Names) + if (NumValues ~= 6) then + -- Not enough values returned, skip this row + return 0; + end + local ID = Values[1]; + local MinX = Values[2]; + local MinZ = Values[3]; + local MaxX = Values[4]; + local MaxZ = Values[5]; + local CreatorName = Values[6]; + a_Callback(ID, MinX, MinZ, MaxX, MaxZ, CreatorName); + return 0; + end + + local lcWorldName = string.lower(a_WorldName); + local sql = "SELECT ID, MinX, MinZ, MaxX, MaxZ, CreatorUserName FROM Areas WHERE " .. + "MinX <= " .. a_BlockX .. " AND MaxX >= " .. a_BlockX .. " AND " .. + "MinZ <= " .. a_BlockZ .. " AND MaxZ >= " .. a_BlockZ .. " AND " .. + "WorldName = '" .. lcWorldName .. "'"; + if (not(self:DBExec(sql, CallCallback))) then + LOGWARNING("SQL Error while iterating through areas (cStorage:ForEachArea())"); + return false; + end + return true; +end + + + + + +--- Returns the info on the specified area +-- Returns MinX, MinZ, MaxX, MaxZ, CreatorName on success, or nothing on failure +function cStorage:GetArea(a_AreaID, a_WorldName) + assert(a_AreaID); + assert(a_WorldName); + assert(self); + + local MinX, MinZ, MaxX, MaxZ, CreatorName; + local HasValues = false; + + -- SQL callback that parses the values and remembers them in variables + function RememberValues(UserData, NumValues, Values, Names) + if (NumValues ~= 5) then + -- Not enough values returned, skip this row + return 0; + end + MinX = Values[1]; + MinZ = Values[2]; + MaxX = Values[3]; + MaxZ = Values[4]; + CreatorName = Values[5]; + HasValues = true; + return 0; + end + + local lcWorldName = string.lower(a_WorldName); + local sql = "SELECT MinX, MinZ, MaxX, MaxZ, CreatorUserName FROM Areas WHERE " .. + "ID = " .. a_AreaID .. " AND WorldName = '" .. lcWorldName .. "'"; + if (not(self:DBExec(sql, RememberValues))) then + LOGWARNING("SQL Error while getting area info (cStorage:ForEachArea())"); + return; + end + + -- If no data has been retrieved, return nothing + if (not(HasValues)) then + return; + end + + return MinX, MinZ, MaxX, MaxZ, CreatorName; +end + + + + + +--- Calls the callback for each allowed user for the specified area +-- Callback signature: function(UserName) +function cStorage:ForEachUserInArea(a_AreaID, a_WorldName, a_Callback) + assert(a_AreaID); + assert(a_WorldName); + assert(a_Callback); + assert(self); + + -- Since in this version all the worlds share a single DB, the a_WorldName parameter is not actually used + -- But this may change in the future, when we have a per-world DB + + local function CallCallback(UserData, NumValues, Values) + if (NumValues ~= 1) then + return 0; + end + a_Callback(Values[1]); + return 0; + end + local sql = "SELECT UserName FROM AllowedUsers WHERE AreaID = " .. a_AreaID; + if (not(self:DBExec(sql, CallCallback))) then + LOGWARNING("SQL error while iterating area users for AreaID" .. a_AreaID); + return false; + end + return true; +end + + + + + +--- Adds the specified usernames to the specified area, if not already present +-- a_Users is an array table of usernames to add +function cStorage:AddAreaUsers(a_AreaID, a_WorldName, a_AddedBy, a_Users) + assert(a_AreaID); + assert(a_WorldName); + assert(a_Users); + assert(self); + + -- Convert all usernames to lowercase + for idx, Name in ipairs(a_Users) do + a_Users[idx] = string.lower(Name); + end + + -- Remove from a_Users the usernames already present in the area + local sql = "SELECT UserName FROM AllowedUsers WHERE AreaID = " .. a_AreaID; + local function RemovePresent(UserData, NumValues, Values, Names) + if (NumValues ~= 1) then + -- Invalid response format + return 0; + end + local DBName = Values[1]; + -- Remove the name from a_Users, if exists + for idx, Name in ipairs(a_Users) do + if (Name == DBName) then + table.remove(a_Users, idx); + return 0; + end + end + return 0; + end + if (not(self:DBExec(sql, RemovePresent))) then + LOGWARNING("SQL error while iterating through users"); + return false; + end + + -- Add the users + for idx, Name in ipairs(a_Users) do + local sql = "INSERT INTO AllowedUsers (AreaID, UserName) VALUES (" .. a_AreaID .. ", '" .. Name .. "')"; + if (not(self:DBExec(sql))) then + LOGWARNING("SQL error while adding user " .. Name .. " to area " .. a_AreaID); + end + end + + return true; +end + + + + + diff --git a/MCServer/Plugins/SquirrelChatLog.nut b/MCServer/Plugins/SquirrelChatLog.nut index 4ef0fd595..d90cef126 100644 --- a/MCServer/Plugins/SquirrelChatLog.nut +++ b/MCServer/Plugins/SquirrelChatLog.nut @@ -1,13 +1,13 @@ -class SquirrelChatLog extends Plugin -{ - function Initialize() - { - this.AddHook(Hook.Chat); - return true; - } - - function OnChat(Message, Player) - { - ::print(Player.GetName() + ": " + Message); - } -} +class SquirrelChatLog extends Plugin +{ + function Initialize() + { + this.AddHook(Hook.Chat); + return true; + } + + function OnChat(Message, Player) + { + ::print(Player.GetName() + ": " + Message); + } +} diff --git a/MCServer/crafting.txt b/MCServer/crafting.txt index 9e044dbec..41672ddda 100644 --- a/MCServer/crafting.txt +++ b/MCServer/crafting.txt @@ -1,392 +1,392 @@ - -# This file describes the crafting recipes that MCServer knows. -# The syntax is as follows: -# = # -# = = | | ... | -# = , : , : , ..., : -# = [^] -# , = "1" .. "3", or "*" for any value. "*:*" can be replaced by a single "*". -# = [^] [, ] -# -# The Xn, Yn coordinates are a reference to the crafting grid: -# 1:1 | 2:1 | 3:1 -# 1:2 | 2:2 | 3:2 -# 1:3 | 2:3 | 3:3 -# -# can be either a number, or an item name (checked against items.ini) -# -# ^ is optional, if not present, any damage value is matched for ingredients and zero is produced for the result -# -# Ingredients with an asterisk for a coord will not match already matched crafting grid items. This enables simplifying some of the recipes, -# e. g. hoe: "Iron, 2:1, *:1" -# -- this means "one iron at 2:1, and another one at either 1:1 or 3:1" -# -# To require multiple items of the same type in a slot, specify the slot number several times: -# "Iron, 1:1, 2:2, 2:2" -# -- this means "take one iron from slot 1:1 and two irons from slot 2:2" -# Note that asterisked items cannot require multiple items in a single slot. -# -# Note that due to technical problems, it is NOT advised to use asterisked ingredients in crossing directions, such as "*:1, "2:*". -# The parser may be unable to match such a recipe to the crafting grid! -# -# Whitespace is optional. Use it reasonably. Please do NOT use Tabs in the middle of lines! - - - - - -#******************************************************# -# Basic Crafts -# - -# Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0) -ApplePlanks, 4 = AppleLog, * -ConiferPlanks, 4 = ConiferLog, * -BirchPlanks, 4 = BirchLog, * -JunglePlanks, 4 = JungleLog, * -Stick, 4 = Planks, 2:2, 2:3 -Torch, 4 = Stick, 1:2 | Coal, 1:1 -Workbench = Planks, 1:1, 1:2, 2:1, 2:2 -Chest = Planks, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -TrappedChest = TripWireHook, 1:1 | Chest, 2:1 -EnderChest = EyeOfEnder, 2:2 | Obsidian, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -Furnace = Cobblestone, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 - - - - - -#******************************************************# -# Blocks -# -IronBlock = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -GoldBlock = GoldIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -DiamondBlock = Diamond, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -LapisBlock = LapisLazuli, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -EmeraldBlock = Emerald, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -RedstoneBlock = RedstoneDust, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -QuartzBlock = NetherQuartz, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -NetherBrick = netherbrickitem, 1:1, 1:2, 2:1, 2:2 -Glowstone = GlowstoneDust, 1:1, 1:2, 2:1, 2:2 -Wool = String, 1:1, 1:2, 2:1, 2:2 -TNT = Gunpowder, 1:1, 3:1, 2:2, 1:3, 3:3 | Sand, 2:1, 1:2, 3:2, 2:3 -PillarQuartzBlock = QuartzSlab, 1:1, 1:2 -ChiseledQuartzBlock, 2 = QuartzBlock, 1:1, 1:2 - -# Slabs: -StoneSlab, 6 = Stone, 1:1, 2:1, 3:1 -SandstoneSlab, 6 = Sandstone, 1:1, 2:1, 3:1 -WoodSlab, 6 = Planks, 1:1, 2:1, 3:1 -CobblestoneSlab, 6 = Cobblestone, 1:1, 2:1, 3:1 -BrickSlab, 6 = BrickBlock, 1:1, 2:1, 3:1 -StonebrickSlab, 6 = StoneBrick, 1:1, 2:1, 3:1 -NetherbrickSlab, 6 = NetherBrick, 1:1, 2:1, 3:1 -Quartzslab, 6 = QuartzBlock, 1:1, 2:1, 3:1 -snow, 6 = SnowBlock, 1:1, 2:1, 3:1 - -# Stairs: -WoodStairs, 4 = Planks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 -WoodStairs, 4 = Planks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -cobblestoneStairs, 4 = Cobblestone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 -cobblestoneStairs, 4 = Cobblestone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -BrickStairs, 4 = BrickBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 -BrickStairs, 4 = BrickBlock, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -SandstoneStairs, 4 = Sandstone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 -SandstoneStairs, 4 = Sandstone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -NetherBrickStairs, 4 = NetherBrick, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 -quartzstairs, 4 = QuartzBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 -SnowBlock = SnowBall, 1:1, 1:2, 2:1, 2:2 -ClayBlock = Clay, 1:1, 1:2, 2:1, 2:2 -BrickBlock = Brick, 1:1, 1:2, 2:1, 2:2 -StoneBrick, 4 = Stone, 1:1, 1:2, 2:1, 2:2 -BookShelf = Planks, 1:1, 2:1, 3:1, 1:3, 2:3, 3:3 | Book, 1:2, 2:2, 3:2 -Sandstone, 4 = Sand, 1:1, 1:2, 2:1, 2:2 -SmoothSandstone, 4 = Sandstone, 1:1, 1:2, 2:1, 2:2 -OrnamentSandstone = SandstoneSlab, 1:1, 1:2 -JackOLantern = Pumpkin, 1:1 | Torch, 1:2 - - - - - -#******************************************************# -# Tools -# - -# Axes: -WoodenAxe = Stick, 2:2, 2:3 | Planks, 2:1, 1:1, 1:2 -WoodenAxe = Stick, 2:2, 2:3 | Planks, 2:1, 3:1, 3:2 -StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 1:1, 1:2 -StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 3:1, 3:2 -GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 1:1, 1:2 -GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 3:1, 3:2 -IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 1:1, 1:2 -IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 3:1, 3:2 -DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 1:1, 1:2 -DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 3:1, 3:2 - -# Pickaxes: -WoodenPickaxe = Stick, 2:2, 2:3 | Planks, 1:1, 2:1, 3:1 -StonePickaxe = Stick, 2:2, 2:3 | Cobblestone, 1:1, 2:1, 3:1 -GoldenPickaxe = Stick, 2:2, 2:3 | GoldIngot, 1:1, 2:1, 3:1 -IronPickaxe = Stick, 2:2, 2:3 | IronIngot, 1:1, 2:1, 3:1 -DiamondPickaxe = Stick, 2:2, 2:3 | Diamond, 1:1, 2:1, 3:1 - -# Shovels: -WoodenShovel = Stick, 2:2, 2:3 | Planks, 2:1 -StoneShovel = Stick, 2:2, 2:3 | Cobblestone, 2:1 -GoldenShovel = Stick, 2:2, 2:3 | GoldIngot, 2:1 -IronShovel = Stick, 2:2, 2:3 | IronIngot, 2:1 -DiamondShovel = Stick, 2:2, 2:3 | Diamond, 2:1 - -# Hoes: -WoodenHoe = Stick, 2:2, 2:3 | Planks, 2:1, *:1 -StoneHoe = Stick, 2:2, 2:3 | Cobblestone, 2:1, *:1 -GoldenHoe = Stick, 2:2, 2:3 | GoldIngot, 2:1, *:1 -IronHoe = Stick, 2:2, 2:3 | IronIngot, 2:1, *:1 -DiamondHoe = Stick, 2:2, 2:3 | Diamond, 2:1, *:1 - -Lighter = IronIngot, 1:1 | Flint, 2:2 -Lighter = IronIngot, 2:1 | Flint, 1:2 -Bucket = IronIngot, 1:1, 2:2, 3:1 -Compass = IronIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 -Map = Paper, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Compass, 2:2 -Watch = GoldIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 -FishingRod = Stick, 1:3, 2:2, 3:1 | String, 3:2, 3:3 -FishingRod = Stick, 3:3, 2:2, 1:1 | String, 1:2, 1:3 -Shears = IronIngot, 1:1, 2:2 -Shears = IronIngot, 2:1, 1:2 -FireCharge = BlazePowder, * | Coal, * | Gunpowder, * - - - - - -#******************************************************# -# Weapons -# -WoodenSword = Stick, 2:3 | Planks, 2:1, 2:2 -StoneSword = Stick, 2:3 | Cobblestone, 2:1, 2:2 -GoldenSword = Stick, 2:3 | GoldIngot, 2:1, 2:2 -IronSword = Stick, 2:3 | IronIngot, 2:1, 2:2 -DiamondSword = Stick, 2:3 | Diamond, 2:1, 2:2 -Bow = Stick, 2:1, 1:2, 2:3 | String, 3:1, 3:2, 3:3 -Bow = Stick, 2:1, 3:2, 2:3 | String, 1:1, 1:2, 1:3 -Arrow, 4 = Flint, 1:1 | Stick, 1:2 | Feather, 1:3 - - - - - - -#******************************************************# -# Armor -# - -# Helmets: -LeatherHelmet = Leather, 1:1, 2:1, 3:1, 1:2, 3:2 -ChainmailHelmet = Fire, 1:1, 2:1, 3:1, 1:2, 3:2 -GoldenHelmet = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2 -IronHelmet = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2 -DiamondHelmet = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2 - -# Chestplates: -LeatherChestplate = Leather, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -ChainmailChestplate = Fire, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -GoldenChestplate = GoldIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -IronChestplate = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -DiamondChestplate = Diamond, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 - -# Leggins: -LeatherPants = Leather, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -ChainmailPants = Fire, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -GoldenPants = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -IronPants = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -DiamondPants = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 - -# Boots: -LeatherBoots = Leather, 1:1, 3:1, 1:2, 3:2 -ChainmailBoots = Fire, 1:1, 3:1, 1:2, 3:2 -GoldenBoots = GoldIngot, 1:1, 3:1, 1:2, 3:2 -IronBoots = IronIngot, 1:1, 3:1, 1:2, 3:2 -DiamondBoots = Diamond, 1:1, 3:1, 1:2, 3:2 - - - - - -#******************************************************# -# Transportation -# -CarrotOnAStick = FishingRod, 1:2 | Carrot, 2:3 -Minecart = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2 -PoweredMinecart = Minecart, * | Furnace, * -StorageMinecart = Minecart, * | Chest, * -TNTMinecart = Minecart, * | TNT, * -hopperminecart = Minecart, * | Hopper, * -Rails, 16 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 -PoweredRail, 6 = GoldIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 | RedstoneDust, 2:3 -DetectorRail, 6 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | StonePlate, 2:2 | RedstoneDust, 2:3 -Boat = Planks, 1:1, 3:1, 1:2, 2:2, 3:2 -ActivatorRail, 6 = IronIngot, 1:1, 1:2, 1:3, 3:1, 3:2, 3:3 | Stick, 2:1, 2:3 | RedstoneTorchon, 2:2 - - - - -#******************************************************# -# Mechanisms -# -WoodenDoor = Planks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -IronDoor = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -TrapDoor, 2 = Planks, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -WoodPlate = Planks, 1:1, 2:1 -StonePlate = Stone, 1:1, 2:1 -StoneButton = Stone, 1:1 -WoodenButton = Planks, 1:1 -RedstoneTorchOn = Stick, 1:2 | RedstoneDust, 1:1 -Lever = Cobblestone, 1:2 | Stick, 1:1 -NoteBlock = Planks, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedstoneDust, 2:2 -Jukebox = Planks, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Diamond, 2:2 -Dispenser = Cobblestone, 1:1, 1:2, 1:3, 2:1, 3:1, 3:2, 3:3 | RedstoneDust, 2:3 | Bow, 2:2 -Dropper = Cobblestone, 1:1, 2:1, 3:1, 1:2, 1:3, 3:2, 3:3 | Hopper, 2:2 | RedstoneDust, 2:3 -Repeater = Stone, 1:2, 2:2, 3:2 | RedstoneTorchOn, 1:1, 3:1 | RedstoneDust, 2:1 -Comparator = RedstoneTorchOn, 2:1, 1:2, 3:2 | NetherQuartz, 2:2 | Stone, 1:3, 2:3, 3:3 -DaylightSensor = Glass, 1:1, 2:1, 3:1 | NetherQuartz, 1:2, 2:2, 3:2 | Woodslab, 1:3, 2:3, 3:3 -Hopper = Ironbars, 1:1, 3:1, 1:2, 3:2, 2:3 | Chest, 2:2 -Piston = Planks, 1:1, 2:1, 3:1 | RedstoneDust, 2:3 | Cobblestone, 1:2, 3:2, 1:3, 3:3 | IronIngot, 2:2 -StickyPiston = Piston, * | SlimeBall, * -RedstoneLamp = RedstoneDust, 2:1, 1:2, 3:2, 2:3 | Glowstone, 2:2 -tripwirehook, 2 = planks, 2:3 | stick, 2:2 | ironbar, 2:1 - - - - - -#******************************************************# -# Food -# -Bowl, 4 = Planks, 1:1, 2:2, 3:1 -MushroomStew = Bowl, * | BrownMushroom, * | RedMushroom, * -Bread = Wheat, 1:1, 2:1, 3:1 -Sugar = Sugarcane, * -Cake = MilkBucket, 1:1, 2:1, 3:1 | Sugar, 1:2, 3:2 | Egg, 2:2 | Wheat, 1:3, 2:3, 3:3 -Cookie = Wheat, *, * | CocoaBeans, * -GoldenApple = RedApple, 2:2 | GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -EnchantedGoldenApple = RedApple, 2:2 | GoldBlock, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -Melon = MelonSlice, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -MelonSeeds = MelonSlice, * -PumpkinSeeds, 4 = Pumpkin, * -PumpkinPie = Pumpkin, * | Sugar, * | egg, * - - - - - -#******************************************************# -# Miscellaneous -# - -# Minerals: -IronIngot, 9 = IronBlock, * -GoldIngot, 9 = GoldBlock, * -Diamond, 9 = DiamondBlock, * -LapisLazuli, 9 = LapisBlock, * -Emerald, 9 = EmeraldBlock, * -RedstoneDust, 9 = RedstoneBlock, * - -Painting = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Wool, 2:2 -ItemFrame = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Leather, 2:2 -Sign = Planks, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 | Stick, 2:3 -Ladder, 3 = Stick, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 3:3 -GlassPane, 16 = Glass, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -IronBars, 16 = IronIngot, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -Paper, 3 = Sugarcane, 1:1, 2:1, 3:1 -Book = Paper, *, *, * | leather, * -Bookandquill = Book, * | feather, * | inksac, * -Fence, 2 = Stick, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -Cobblestonewall, 6 = cobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -mossycobblestonewall, 6 = mossycobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -NetherBrickFence, 6 = NetherBrick, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -FenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | Planks, 2:1, 2:2 -Bed = Planks, 1:2, 2:2, 3:2 | Wool, 1:1, 2:1, 3:1 -GoldIngot = GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -EyeOfEnder = EnderPearl, * | BlazePowder, * -Beacon = Glass, 1:1, 1:2, 2:1, 3:1, 3:2 | Obsidian, 1:3, 2:3, 3:3 | NetherStar, 2:2 -Anvil = IronBlock, 1:1, 2:1, 3:1 | IronIngot, 2:2, 1:3, 2:3, 3:3 -FlowerPot = Brick, 1:2, 2:3, 3:2 - - - - - -#******************************************************# -# Dyes -# - -WhiteDye, 3 = Bone, * -RedDye, 2 = Rose, * -YellowDye, 2 = Flower, * - -# Color mixing, duals: -OrangeDye, 2 = YellowDye, * | RedDye, * -CyanDye, 2 = GreenDye, * | BlueDye, * -PurpleDye, 2 = RedDye, * | BlueDye, * -GrayDye, 2 = BlackDye, * | WhiteDye, * -LtBlueDye, 2 = BlueDye, * | WhiteDye, * -PinkDye, 2 = RedDye, * | WhiteDye, * -LimeDye, 2 = GreenDye, * | WhiteDye, * -MagentaDye, 2 = PurpleDye, * | PinkDye, * -LtGrayDye, 2 = GrayDye, * | WhiteDye, * - -# triplets: -LtGrayDye, 3 = BlackDye, * | WhiteDye, *, * -MagentaDye, 3 = BlueDye, * | PinkDye, * | RedDye, * - -# quads: -MagentaDye, 4 = BlueDye, * | WhiteDye, * | RedDye, *, * - - - - - -#******************************************************# -# Colored wool: -# -WhiteWool = Wool, * | BoneMeal, * -OrangeWool = Wool, * | OrangeDye, * -MagentaWool = Wool, * | MagentaDye, * -LightBlueWool = Wool, * | LightBlueDye, * -YellowWool = Wool, * | YellowDye, * -LimeWool = Wool, * | LimeDye, * -PinkWool = Wool, * | PinkDye, * -GrayWool = Wool, * | GrayDye, * -LightGrayWool = Wool, * | LightGrayDye, * -CyanWool = Wool, * | CyanDye, * -VioletWool = Wool, * | VioletDye, * -BlueWool = Wool, * | BlueDye, * -BrownWool = Wool, * | BrownDye, * -GreenWool = Wool, * | GreenDye, * -RedWool = Wool, * | RedDye, * -BlackWool = Wool, * | BlackDye, * - - - - - -#******************************************************# -# Enchantment & Brewing -# -GlassBottle, 3 = Glass, 1:1, 2:2, 3:1 -Cauldron = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 2:3, 3:3 -BrewingStand = Cobblestone, 1:2, 2:2, 3:2 | BlazeRod, 2:1 -BlazePowder, 2 = BlazeRod, * -MagmaCream = SlimeBall, * | BlazePowder, * -FermentedSpiderEye = SpiderEye, * | Sugar, * | BrownMushroom, * -GlisteringMelon = MelonSlice, * | GoldNugget, * -GoldNugget, 9 = GoldIngot, * -EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1 - - - - - + +# This file describes the crafting recipes that MCServer knows. +# The syntax is as follows: +# = # +# = = | | ... | +# = , : , : , ..., : +# = [^] +# , = "1" .. "3", or "*" for any value. "*:*" can be replaced by a single "*". +# = [^] [, ] +# +# The Xn, Yn coordinates are a reference to the crafting grid: +# 1:1 | 2:1 | 3:1 +# 1:2 | 2:2 | 3:2 +# 1:3 | 2:3 | 3:3 +# +# can be either a number, or an item name (checked against items.ini) +# +# ^ is optional, if not present, any damage value is matched for ingredients and zero is produced for the result +# +# Ingredients with an asterisk for a coord will not match already matched crafting grid items. This enables simplifying some of the recipes, +# e. g. hoe: "Iron, 2:1, *:1" +# -- this means "one iron at 2:1, and another one at either 1:1 or 3:1" +# +# To require multiple items of the same type in a slot, specify the slot number several times: +# "Iron, 1:1, 2:2, 2:2" +# -- this means "take one iron from slot 1:1 and two irons from slot 2:2" +# Note that asterisked items cannot require multiple items in a single slot. +# +# Note that due to technical problems, it is NOT advised to use asterisked ingredients in crossing directions, such as "*:1, "2:*". +# The parser may be unable to match such a recipe to the crafting grid! +# +# Whitespace is optional. Use it reasonably. Please do NOT use Tabs in the middle of lines! + + + + + +#******************************************************# +# Basic Crafts +# + +# Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0) +ApplePlanks, 4 = AppleLog, * +ConiferPlanks, 4 = ConiferLog, * +BirchPlanks, 4 = BirchLog, * +JunglePlanks, 4 = JungleLog, * +Stick, 4 = Planks, 2:2, 2:3 +Torch, 4 = Stick, 1:2 | Coal, 1:1 +Workbench = Planks, 1:1, 1:2, 2:1, 2:2 +Chest = Planks, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +TrappedChest = TripWireHook, 1:1 | Chest, 2:1 +EnderChest = EyeOfEnder, 2:2 | Obsidian, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +Furnace = Cobblestone, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 + + + + + +#******************************************************# +# Blocks +# +IronBlock = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +GoldBlock = GoldIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +DiamondBlock = Diamond, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +LapisBlock = LapisLazuli, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +EmeraldBlock = Emerald, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +RedstoneBlock = RedstoneDust, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +QuartzBlock = NetherQuartz, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +NetherBrick = netherbrickitem, 1:1, 1:2, 2:1, 2:2 +Glowstone = GlowstoneDust, 1:1, 1:2, 2:1, 2:2 +Wool = String, 1:1, 1:2, 2:1, 2:2 +TNT = Gunpowder, 1:1, 3:1, 2:2, 1:3, 3:3 | Sand, 2:1, 1:2, 3:2, 2:3 +PillarQuartzBlock = QuartzSlab, 1:1, 1:2 +ChiseledQuartzBlock, 2 = QuartzBlock, 1:1, 1:2 + +# Slabs: +StoneSlab, 6 = Stone, 1:1, 2:1, 3:1 +SandstoneSlab, 6 = Sandstone, 1:1, 2:1, 3:1 +WoodSlab, 6 = Planks, 1:1, 2:1, 3:1 +CobblestoneSlab, 6 = Cobblestone, 1:1, 2:1, 3:1 +BrickSlab, 6 = BrickBlock, 1:1, 2:1, 3:1 +StonebrickSlab, 6 = StoneBrick, 1:1, 2:1, 3:1 +NetherbrickSlab, 6 = NetherBrick, 1:1, 2:1, 3:1 +Quartzslab, 6 = QuartzBlock, 1:1, 2:1, 3:1 +snow, 6 = SnowBlock, 1:1, 2:1, 3:1 + +# Stairs: +WoodStairs, 4 = Planks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +WoodStairs, 4 = Planks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 +cobblestoneStairs, 4 = Cobblestone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +cobblestoneStairs, 4 = Cobblestone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 +BrickStairs, 4 = BrickBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +BrickStairs, 4 = BrickBlock, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 +SandstoneStairs, 4 = Sandstone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +SandstoneStairs, 4 = Sandstone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 +NetherBrickStairs, 4 = NetherBrick, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +quartzstairs, 4 = QuartzBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +SnowBlock = SnowBall, 1:1, 1:2, 2:1, 2:2 +ClayBlock = Clay, 1:1, 1:2, 2:1, 2:2 +BrickBlock = Brick, 1:1, 1:2, 2:1, 2:2 +StoneBrick, 4 = Stone, 1:1, 1:2, 2:1, 2:2 +BookShelf = Planks, 1:1, 2:1, 3:1, 1:3, 2:3, 3:3 | Book, 1:2, 2:2, 3:2 +Sandstone, 4 = Sand, 1:1, 1:2, 2:1, 2:2 +SmoothSandstone, 4 = Sandstone, 1:1, 1:2, 2:1, 2:2 +OrnamentSandstone = SandstoneSlab, 1:1, 1:2 +JackOLantern = Pumpkin, 1:1 | Torch, 1:2 + + + + + +#******************************************************# +# Tools +# + +# Axes: +WoodenAxe = Stick, 2:2, 2:3 | Planks, 2:1, 1:1, 1:2 +WoodenAxe = Stick, 2:2, 2:3 | Planks, 2:1, 3:1, 3:2 +StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 1:1, 1:2 +StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 3:1, 3:2 +GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 1:1, 1:2 +GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 3:1, 3:2 +IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 1:1, 1:2 +IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 3:1, 3:2 +DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 1:1, 1:2 +DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 3:1, 3:2 + +# Pickaxes: +WoodenPickaxe = Stick, 2:2, 2:3 | Planks, 1:1, 2:1, 3:1 +StonePickaxe = Stick, 2:2, 2:3 | Cobblestone, 1:1, 2:1, 3:1 +GoldenPickaxe = Stick, 2:2, 2:3 | GoldIngot, 1:1, 2:1, 3:1 +IronPickaxe = Stick, 2:2, 2:3 | IronIngot, 1:1, 2:1, 3:1 +DiamondPickaxe = Stick, 2:2, 2:3 | Diamond, 1:1, 2:1, 3:1 + +# Shovels: +WoodenShovel = Stick, 2:2, 2:3 | Planks, 2:1 +StoneShovel = Stick, 2:2, 2:3 | Cobblestone, 2:1 +GoldenShovel = Stick, 2:2, 2:3 | GoldIngot, 2:1 +IronShovel = Stick, 2:2, 2:3 | IronIngot, 2:1 +DiamondShovel = Stick, 2:2, 2:3 | Diamond, 2:1 + +# Hoes: +WoodenHoe = Stick, 2:2, 2:3 | Planks, 2:1, *:1 +StoneHoe = Stick, 2:2, 2:3 | Cobblestone, 2:1, *:1 +GoldenHoe = Stick, 2:2, 2:3 | GoldIngot, 2:1, *:1 +IronHoe = Stick, 2:2, 2:3 | IronIngot, 2:1, *:1 +DiamondHoe = Stick, 2:2, 2:3 | Diamond, 2:1, *:1 + +Lighter = IronIngot, 1:1 | Flint, 2:2 +Lighter = IronIngot, 2:1 | Flint, 1:2 +Bucket = IronIngot, 1:1, 2:2, 3:1 +Compass = IronIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 +Map = Paper, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Compass, 2:2 +Watch = GoldIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 +FishingRod = Stick, 1:3, 2:2, 3:1 | String, 3:2, 3:3 +FishingRod = Stick, 3:3, 2:2, 1:1 | String, 1:2, 1:3 +Shears = IronIngot, 1:1, 2:2 +Shears = IronIngot, 2:1, 1:2 +FireCharge = BlazePowder, * | Coal, * | Gunpowder, * + + + + + +#******************************************************# +# Weapons +# +WoodenSword = Stick, 2:3 | Planks, 2:1, 2:2 +StoneSword = Stick, 2:3 | Cobblestone, 2:1, 2:2 +GoldenSword = Stick, 2:3 | GoldIngot, 2:1, 2:2 +IronSword = Stick, 2:3 | IronIngot, 2:1, 2:2 +DiamondSword = Stick, 2:3 | Diamond, 2:1, 2:2 +Bow = Stick, 2:1, 1:2, 2:3 | String, 3:1, 3:2, 3:3 +Bow = Stick, 2:1, 3:2, 2:3 | String, 1:1, 1:2, 1:3 +Arrow, 4 = Flint, 1:1 | Stick, 1:2 | Feather, 1:3 + + + + + + +#******************************************************# +# Armor +# + +# Helmets: +LeatherHelmet = Leather, 1:1, 2:1, 3:1, 1:2, 3:2 +ChainmailHelmet = Fire, 1:1, 2:1, 3:1, 1:2, 3:2 +GoldenHelmet = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2 +IronHelmet = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2 +DiamondHelmet = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2 + +# Chestplates: +LeatherChestplate = Leather, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +ChainmailChestplate = Fire, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +GoldenChestplate = GoldIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +IronChestplate = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +DiamondChestplate = Diamond, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 + +# Leggins: +LeatherPants = Leather, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +ChainmailPants = Fire, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +GoldenPants = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +IronPants = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +DiamondPants = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 + +# Boots: +LeatherBoots = Leather, 1:1, 3:1, 1:2, 3:2 +ChainmailBoots = Fire, 1:1, 3:1, 1:2, 3:2 +GoldenBoots = GoldIngot, 1:1, 3:1, 1:2, 3:2 +IronBoots = IronIngot, 1:1, 3:1, 1:2, 3:2 +DiamondBoots = Diamond, 1:1, 3:1, 1:2, 3:2 + + + + + +#******************************************************# +# Transportation +# +CarrotOnAStick = FishingRod, 1:2 | Carrot, 2:3 +Minecart = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2 +PoweredMinecart = Minecart, * | Furnace, * +StorageMinecart = Minecart, * | Chest, * +TNTMinecart = Minecart, * | TNT, * +hopperminecart = Minecart, * | Hopper, * +Rails, 16 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 +PoweredRail, 6 = GoldIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 | RedstoneDust, 2:3 +DetectorRail, 6 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | StonePlate, 2:2 | RedstoneDust, 2:3 +Boat = Planks, 1:1, 3:1, 1:2, 2:2, 3:2 +ActivatorRail, 6 = IronIngot, 1:1, 1:2, 1:3, 3:1, 3:2, 3:3 | Stick, 2:1, 2:3 | RedstoneTorchon, 2:2 + + + + +#******************************************************# +# Mechanisms +# +WoodenDoor = Planks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +IronDoor = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +TrapDoor, 2 = Planks, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +WoodPlate = Planks, 1:1, 2:1 +StonePlate = Stone, 1:1, 2:1 +StoneButton = Stone, 1:1 +WoodenButton = Planks, 1:1 +RedstoneTorchOn = Stick, 1:2 | RedstoneDust, 1:1 +Lever = Cobblestone, 1:2 | Stick, 1:1 +NoteBlock = Planks, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedstoneDust, 2:2 +Jukebox = Planks, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Diamond, 2:2 +Dispenser = Cobblestone, 1:1, 1:2, 1:3, 2:1, 3:1, 3:2, 3:3 | RedstoneDust, 2:3 | Bow, 2:2 +Dropper = Cobblestone, 1:1, 2:1, 3:1, 1:2, 1:3, 3:2, 3:3 | Hopper, 2:2 | RedstoneDust, 2:3 +Repeater = Stone, 1:2, 2:2, 3:2 | RedstoneTorchOn, 1:1, 3:1 | RedstoneDust, 2:1 +Comparator = RedstoneTorchOn, 2:1, 1:2, 3:2 | NetherQuartz, 2:2 | Stone, 1:3, 2:3, 3:3 +DaylightSensor = Glass, 1:1, 2:1, 3:1 | NetherQuartz, 1:2, 2:2, 3:2 | Woodslab, 1:3, 2:3, 3:3 +Hopper = Ironbars, 1:1, 3:1, 1:2, 3:2, 2:3 | Chest, 2:2 +Piston = Planks, 1:1, 2:1, 3:1 | RedstoneDust, 2:3 | Cobblestone, 1:2, 3:2, 1:3, 3:3 | IronIngot, 2:2 +StickyPiston = Piston, * | SlimeBall, * +RedstoneLamp = RedstoneDust, 2:1, 1:2, 3:2, 2:3 | Glowstone, 2:2 +tripwirehook, 2 = planks, 2:3 | stick, 2:2 | ironbar, 2:1 + + + + + +#******************************************************# +# Food +# +Bowl, 4 = Planks, 1:1, 2:2, 3:1 +MushroomStew = Bowl, * | BrownMushroom, * | RedMushroom, * +Bread = Wheat, 1:1, 2:1, 3:1 +Sugar = Sugarcane, * +Cake = MilkBucket, 1:1, 2:1, 3:1 | Sugar, 1:2, 3:2 | Egg, 2:2 | Wheat, 1:3, 2:3, 3:3 +Cookie = Wheat, *, * | CocoaBeans, * +GoldenApple = RedApple, 2:2 | GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +EnchantedGoldenApple = RedApple, 2:2 | GoldBlock, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +Melon = MelonSlice, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +MelonSeeds = MelonSlice, * +PumpkinSeeds, 4 = Pumpkin, * +PumpkinPie = Pumpkin, * | Sugar, * | egg, * + + + + + +#******************************************************# +# Miscellaneous +# + +# Minerals: +IronIngot, 9 = IronBlock, * +GoldIngot, 9 = GoldBlock, * +Diamond, 9 = DiamondBlock, * +LapisLazuli, 9 = LapisBlock, * +Emerald, 9 = EmeraldBlock, * +RedstoneDust, 9 = RedstoneBlock, * + +Painting = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Wool, 2:2 +ItemFrame = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Leather, 2:2 +Sign = Planks, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 | Stick, 2:3 +Ladder, 3 = Stick, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 3:3 +GlassPane, 16 = Glass, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +IronBars, 16 = IronIngot, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +Paper, 3 = Sugarcane, 1:1, 2:1, 3:1 +Book = Paper, *, *, * | leather, * +Bookandquill = Book, * | feather, * | inksac, * +Fence, 2 = Stick, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +Cobblestonewall, 6 = cobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +mossycobblestonewall, 6 = mossycobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +NetherBrickFence, 6 = NetherBrick, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +FenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | Planks, 2:1, 2:2 +Bed = Planks, 1:2, 2:2, 3:2 | Wool, 1:1, 2:1, 3:1 +GoldIngot = GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +EyeOfEnder = EnderPearl, * | BlazePowder, * +Beacon = Glass, 1:1, 1:2, 2:1, 3:1, 3:2 | Obsidian, 1:3, 2:3, 3:3 | NetherStar, 2:2 +Anvil = IronBlock, 1:1, 2:1, 3:1 | IronIngot, 2:2, 1:3, 2:3, 3:3 +FlowerPot = Brick, 1:2, 2:3, 3:2 + + + + + +#******************************************************# +# Dyes +# + +WhiteDye, 3 = Bone, * +RedDye, 2 = Rose, * +YellowDye, 2 = Flower, * + +# Color mixing, duals: +OrangeDye, 2 = YellowDye, * | RedDye, * +CyanDye, 2 = GreenDye, * | BlueDye, * +PurpleDye, 2 = RedDye, * | BlueDye, * +GrayDye, 2 = BlackDye, * | WhiteDye, * +LtBlueDye, 2 = BlueDye, * | WhiteDye, * +PinkDye, 2 = RedDye, * | WhiteDye, * +LimeDye, 2 = GreenDye, * | WhiteDye, * +MagentaDye, 2 = PurpleDye, * | PinkDye, * +LtGrayDye, 2 = GrayDye, * | WhiteDye, * + +# triplets: +LtGrayDye, 3 = BlackDye, * | WhiteDye, *, * +MagentaDye, 3 = BlueDye, * | PinkDye, * | RedDye, * + +# quads: +MagentaDye, 4 = BlueDye, * | WhiteDye, * | RedDye, *, * + + + + + +#******************************************************# +# Colored wool: +# +WhiteWool = Wool, * | BoneMeal, * +OrangeWool = Wool, * | OrangeDye, * +MagentaWool = Wool, * | MagentaDye, * +LightBlueWool = Wool, * | LightBlueDye, * +YellowWool = Wool, * | YellowDye, * +LimeWool = Wool, * | LimeDye, * +PinkWool = Wool, * | PinkDye, * +GrayWool = Wool, * | GrayDye, * +LightGrayWool = Wool, * | LightGrayDye, * +CyanWool = Wool, * | CyanDye, * +VioletWool = Wool, * | VioletDye, * +BlueWool = Wool, * | BlueDye, * +BrownWool = Wool, * | BrownDye, * +GreenWool = Wool, * | GreenDye, * +RedWool = Wool, * | RedDye, * +BlackWool = Wool, * | BlackDye, * + + + + + +#******************************************************# +# Enchantment & Brewing +# +GlassBottle, 3 = Glass, 1:1, 2:2, 3:1 +Cauldron = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 2:3, 3:3 +BrewingStand = Cobblestone, 1:2, 2:2, 3:2 | BlazeRod, 2:1 +BlazePowder, 2 = BlazeRod, * +MagmaCream = SlimeBall, * | BlazePowder, * +FermentedSpiderEye = SpiderEye, * | Sugar, * | BrownMushroom, * +GlisteringMelon = MelonSlice, * | GoldNugget, * +GoldNugget, 9 = GoldIngot, * +EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1 + + + + + diff --git a/MCServer/furnace.txt b/MCServer/furnace.txt index b25c79ab7..e5d4ca70f 100644 --- a/MCServer/furnace.txt +++ b/MCServer/furnace.txt @@ -1,75 +1,75 @@ -#*****************# -# Furnace Recipes # -#*****************# -# -# -#******************************************************# -# Basic Notation Help -# -# **** Item Definition **** -# An Item is defined by an Item Type, an amount (and damage) -# The damage is optional, and if not specified it's assumed to be 0 -# -# -Cactus Green: -# 351 : 1 ( : 2 ) -# ItemType : Amount ( : Damage ) -# -# -# **** Recipe and result **** -# -# 4:1@200=1:1 -> Produces 1 smooth stone from 1 cobblestone in 200 ticks (10 seconds) -# -# 4 : 1 @ 200 = 1 : 1 -# ItemType : Amount @ ticks = ItemID : Amount -# -# -# **** Fuel **** -# -# !17:1 = 300 -> 1 Wood burns for 300 ticks (15 s) -# -# ! 17 : 1 = 300 -# Fuel ItemType : Amount = ticks -# -#******************************************************# - - - - - -#-------------------------- -# Smelting recipes - -4:1 @ 200 = 1:1 # 1 Cobblestone -> 1 Rock -15:1 @ 200 = 265:1 # 1 Iron Ore -> 1 Iron Ingot -14:1 @ 200 = 266:1 # 1 Gold Ore -> 1 Gold Ingot -153:1 @ 200 = 406:1 # 1 Quartz Ore -> 1 Quartz -12:1 @ 200 = 20:1 # 1 Sand -> 1 Glass -319:1 @ 200 = 320:1 # 1 Raw Pork -> 1 Cooked Pork -363:1 @ 200 = 364:1 # 1 Raw Beef -> 1 Cooked Beef (steak) -365:1 @ 200 = 366:1 # 1 Raw Chicken -> 1 Cooked Chicken -337:1 @ 200 = 336:1 # 1 Clay -> 1 Clay Brick -87:1 @ 200 = 405:1 # 1 NetherRack -> 1 NetherBrick -349:1 @ 200 = 350:1 # 1 Raw Fish -> 1 Cooked Fish -17:1 @ 200 = 263:1:1 # 1 Log -> 1 Charcoal -81:1 @ 200 = 351:1:2 # 1 Cactus -> 1 Green Dye - - - - - -#-------------------------- -# Fuels - -! 263:1 = 1600 # 1 Charcoal -> 80 sec -! 42:126:1 = 150 # 1 Halfslab -> 7.5 seconds -! 5:1 = 300 # 1 Planks -> 15 sec -! 280:1 = 100 # 1 Stick -> 5 sec -! 85:1 = 300 # 1 Fence -> 15 sec -! 53:1 = 300 # 1 Wooden Stairs -> 15 sec -! 58:1 = 300 # 1 Crafting Table -> 15 sec -! 47:1 = 300 # 1 Bookshelf -> 15 sec -! 54:1 = 300 # 1 Chest -> 15 sec -! 84:1 = 300 # 1 Jukebox -> 15 sec -! 327:1 = 200000 # 1 Lava Bucket -> 1000 sec -! 17:1 = 300 # 1 Wood -> 15 sec -! 6:1 = 100 # 1 Sapling -> 5 sec +#*****************# +# Furnace Recipes # +#*****************# +# +# +#******************************************************# +# Basic Notation Help +# +# **** Item Definition **** +# An Item is defined by an Item Type, an amount (and damage) +# The damage is optional, and if not specified it's assumed to be 0 +# +# -Cactus Green: +# 351 : 1 ( : 2 ) +# ItemType : Amount ( : Damage ) +# +# +# **** Recipe and result **** +# +# 4:1@200=1:1 -> Produces 1 smooth stone from 1 cobblestone in 200 ticks (10 seconds) +# +# 4 : 1 @ 200 = 1 : 1 +# ItemType : Amount @ ticks = ItemID : Amount +# +# +# **** Fuel **** +# +# !17:1 = 300 -> 1 Wood burns for 300 ticks (15 s) +# +# ! 17 : 1 = 300 +# Fuel ItemType : Amount = ticks +# +#******************************************************# + + + + + +#-------------------------- +# Smelting recipes + +4:1 @ 200 = 1:1 # 1 Cobblestone -> 1 Rock +15:1 @ 200 = 265:1 # 1 Iron Ore -> 1 Iron Ingot +14:1 @ 200 = 266:1 # 1 Gold Ore -> 1 Gold Ingot +153:1 @ 200 = 406:1 # 1 Quartz Ore -> 1 Quartz +12:1 @ 200 = 20:1 # 1 Sand -> 1 Glass +319:1 @ 200 = 320:1 # 1 Raw Pork -> 1 Cooked Pork +363:1 @ 200 = 364:1 # 1 Raw Beef -> 1 Cooked Beef (steak) +365:1 @ 200 = 366:1 # 1 Raw Chicken -> 1 Cooked Chicken +337:1 @ 200 = 336:1 # 1 Clay -> 1 Clay Brick +87:1 @ 200 = 405:1 # 1 NetherRack -> 1 NetherBrick +349:1 @ 200 = 350:1 # 1 Raw Fish -> 1 Cooked Fish +17:1 @ 200 = 263:1:1 # 1 Log -> 1 Charcoal +81:1 @ 200 = 351:1:2 # 1 Cactus -> 1 Green Dye + + + + + +#-------------------------- +# Fuels + +! 263:1 = 1600 # 1 Charcoal -> 80 sec +! 42:126:1 = 150 # 1 Halfslab -> 7.5 seconds +! 5:1 = 300 # 1 Planks -> 15 sec +! 280:1 = 100 # 1 Stick -> 5 sec +! 85:1 = 300 # 1 Fence -> 15 sec +! 53:1 = 300 # 1 Wooden Stairs -> 15 sec +! 58:1 = 300 # 1 Crafting Table -> 15 sec +! 47:1 = 300 # 1 Bookshelf -> 15 sec +! 54:1 = 300 # 1 Chest -> 15 sec +! 84:1 = 300 # 1 Jukebox -> 15 sec +! 327:1 = 200000 # 1 Lava Bucket -> 1000 sec +! 17:1 = 300 # 1 Wood -> 15 sec +! 6:1 = 100 # 1 Sapling -> 5 sec diff --git a/MCServer/groups.ini b/MCServer/groups.ini index 7f061204b..87b28b70d 100644 --- a/MCServer/groups.ini +++ b/MCServer/groups.ini @@ -1,17 +1,17 @@ -[Admins] -Permissions=* -Color=c - -[Mods] -Color=5 -Inherits=Vips -Permissions=core.time,core.item - -[Vips] -Permissions=core.teleport -Color=2 -Inherits=Default - -[Default] -Permissions=core.build,core.help,core.playerlist,core.pluginlist,core.spawn +[Admins] +Permissions=* +Color=c + +[Mods] +Color=5 +Inherits=Vips +Permissions=core.time,core.item + +[Vips] +Permissions=core.teleport +Color=2 +Inherits=Default + +[Default] +Permissions=core.build,core.help,core.playerlist,core.pluginlist,core.spawn Color=7 \ No newline at end of file diff --git a/MCServer/hg.supp b/MCServer/hg.supp index 048f1382f..27eb8c27a 100644 --- a/MCServer/hg.supp +++ b/MCServer/hg.supp @@ -1,22 +1,22 @@ -# This is a valgrind suppressions file for running helgrind on MCServer -# Use by adding "--suppressions=hg.supp" to the helgrind commandline - - - - - - -# This covers GCC bug 40518, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518 -# "Erasing an empty string causes a global value write / race condition warning in helgrind" -# Original suppression authored by Jonathan Wakely: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518#c20 -# Modified by Mattes to match the mangled function name used on Ubuntu - -{ - libstdcxx_std_string_race_pr40518 - Helgrind:Race - fun:_ZNSs9_M_mutateEjjj -} - - - - +# This is a valgrind suppressions file for running helgrind on MCServer +# Use by adding "--suppressions=hg.supp" to the helgrind commandline + + + + + + +# This covers GCC bug 40518, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518 +# "Erasing an empty string causes a global value write / race condition warning in helgrind" +# Original suppression authored by Jonathan Wakely: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518#c20 +# Modified by Mattes to match the mangled function name used on Ubuntu + +{ + libstdcxx_std_string_race_pr40518 + Helgrind:Race + fun:_ZNSs9_M_mutateEjjj +} + + + + diff --git a/MCServer/items.ini b/MCServer/items.ini index ec518cb0a..c9bd6df53 100644 --- a/MCServer/items.ini +++ b/MCServer/items.ini @@ -1,543 +1,543 @@ -[Items] -rock=1 -stone=1 -grass=2 -dirt=3 -cobblestone=4 -cobble=4 -planks=5 -appleplanks=5:0 -oakplanks=5:0 -coniferplanks=5:1 -pineplanks=5:1 -spruceplanks=5:1 -darkplanks=5:1 -birchplanks=5:2 -lightplanks=5:2 -jungleplanks=5:3 -redplanks=5:3 - -; Obsolete: do not use "wood", as its meaning is not clear - wiki uses log as wood, we use planks as wood. -wood=5 - -sapling=6 -applesapling=6:0 -oaksapling=6:0 -conifersapling=6:1 -pinesapling=6:1 -sprucesapling=6:1 -birchsapling=6:2 -junglesapling=6:3 -adminium=7 -bedrock=7 -water=8 -stillwater=9 -swater=9 -stationarywater=9 -lava=10 -stilllava=11 -slava=11 -stationarylava=11 -sand=12 -gravel=13 -goldore=14 -ironore=15 -coalore=16 -tree=17 -log=17 -applelog=17:0 -oaklog=17:0 -coniferlog=17:1 -pinelog=17:1 -sprucelog=17:1 -darklog=17:1 -birchlog=17:2 -whitelog=17:2 -junglelog=17:3 -leaves=18 -appleleaves=18:0 -oakleaves=18:0 -coniferleaves=18:1 -pineleaves=18:1 -spruceleaves=18:1 -birchleaves=18:2 -jungleleaves=18:3 -sponge=19 -glass=20 -lapisore=21 -lapisblock=22 -dispenser=23 -sandstone=24 -normalsandstone=24:0 -ornamentsandstone=24:1 -decorativesandstone=24:1 -smoothsandstone=24:2 -noteblock=25 -bedblock=26 -poweredrail=27 -detectorrail=28 -stickypiston=29 -cobweb=30 -tallgrass=31 -tallgrassone=31:1 -tallgrasstwo=31:2 -deadbush=32 -piston=33 -pistonextension=34 -pistonhead=34 -cloth=35 -wool=35 -whitewool=35:0 -orangewool=35:1 -magentawool=35:2 -lightbluewool=35:3 -yellowwool=35:4 -limewool=35:5 -lightgreenwool=35:5 -ltgreenwool=35:5 -pinkwool=35:6 -graywool=35:7 -greywool=35:7 -darkgraywool=35:7 -darkgreywool=35:7 -dkgraywool=35:7 -dkgreywool=35:7 -lightgraywool=35:8 -lightgreywool=35:8 -ltgraywool=35:8 -ltgreywool=35:8 -cyanwool=35:9 -purplewool=35:10 -violetwool=35:10 -bluewool=35:11 -darkbluewool=35:11 -brownwool=35:12 -greenwool=35:13 -darkgreenwool=35:13 -dkgreenwool=35:13 -redwool=35:14 -blackwool=35:15 -flower=37 -rose=38 -brownmushroom=39 -redmushroom=40 -gold=41 -goldblock=41 -iron=42 -ironblock=42 -doubleslab=43 -stonedoubleslab=43:0 -sandstonedoubleslab=43:1 -wooddoubleslab=43:2 -cobblestonedoubleslab=43:3 -brickdoubleslab=43:4 -stonebrickdoubleslab=43:5 -netherbrickdoubleslab=43:6 -quartzdoubleslab=43:7 -slab=44 -step=44 -stoneslab=44:0 -sandstoneslab=44:1 -woodslab=44:2 -cobblestoneslab=44:3 -brickslab=44:4 -stonebrickslab=44:5 -netherbrickslab=44:6 -quartzslab=44:7 -brickblock=45 -brickwall=45 -tnt=46 -bookshelf=47 -bookcase=47 -mossycobblestone=48 -mossy=48 -obsidian=49 -torch=50 -fire=51 -mobspawner=52 -woodstairs=53 -chest=54 -redstonedust=55 -redstonewire=55 -diamondore=56 -diamondblock=57 -workbench=58 -crop=59 -crops=59 -soil=60 -furnace=61 -litfurnace=62 -signblock=63 -wooddoorblock=64 -ladder=65 -rails=66 -rail=66 -track=66 -tracks=66 -cobblestonestairs=67 -stairs=67 -signblocktop=68 -wallsign=68 -lever=69 -rockplate=70 -stoneplate=70 -irondoorblock=71 -woodplate=72 -redstoneore=73 -redstoneorealt=74 -redstonetorchoff=75 -redstonetorchon=76 -stonebutton=77 -snow=78 -ice=79 -snowblock=80 -cactus=81 -clayblock=82 -reedblock=83 -jukebox=84 -fence=85 -pumpkin=86 -netherstone=87 -netherrack=87 -hellrock=87 -slowsand=88 -soulsand=88 -lightstone=89 -glowstone=89 -portal=90 -jackolantern=91 -jacko=91 -cakeblock=92 -lockedchest=95 -trapdoor=96 -silverfishblock=97 -stonebricks=98 -stonebrick=98 -mossystonebrick=98:1 -crackedstonebrick=98:2 -chiseledstonebrick=98:3 -hugebrownmushroom=99 -hugeredmushroom=100 -ironbars=101 -glasspane=102 -melon=103 -pumpkinstem=104 -melonstem=105 -vines=106 -fencegate=107 -brickstairs=108 -stonebrickstairs=109 -mycelium=110 -lilypad=111 -netherbrick=112 -netherbrickfence=113 -netherbrickstairs=114 -netherwartblock=115 -enchantmenttable=116 -brewingstandblock=117 -cauldronblock=118 -endportal=119 -endportalframe=120 -endstone=121 -dragonegg=122 -redstonelamp=123 -redstonelampoff=123 -redstonelampon=124 -woodendoubleslab=125 -woodenslab=126 -sandstonestairs=128 -emeraldore=129 -enderchest=130 -tripwirehook=131 -tripwire=132 -emeraldblock=133 -commandblock=137 -beacon=138 -cobblestonewall=139 -mossycobblestonewall=139:1 -flowerpotblock=140 -carrotcrop=141 -potatocrop=142 -woodenbutton=143 -skeletonhead=144 -witherhead=144:1 -zombiehead=144:2 -humanhead=144:3 -stevehead=144:3 -creeperhead=144:4 -anvil=145 -trappedchest=146 -lightweightedpressureplate=147 -heavyweightedpressureplate=148 -inactivecomparator=149 -activecomparator=150 -daylightsensor=151 -redstoneblock=152 -netherquartzore=153 -hopper=154 -quartzblock=155 -chiseledquartzblock=155:1 -pillarquartzblock=155:2 -quartzstairs=156 -activatorrail=157 -dropper=158 - -ironshovel=256 -ironspade=256 -ironpickaxe=257 -ironpick=257 -ironaxe=258 -flintandsteel=259 -lighter=259 -apple=260 -redapple=260 -bow=261 -arrow=262 -coal=263 -charcoal=263:1 -diamond=264 -ironingot=265 -ironbar=265 -goldingot=266 -goldeningot=266 -goldbar=266 -goldenbar=266 -ironsword=267 -woodensword=268 -woodsword=268 -woodenshovel=269 -woodshovel=269 -woodenspade=269 -woodspade=269 -woodenpickaxe=270 -woodpickaxe=270 -woodenpick=270 -woodpick=270 -woodenaxe=271 -woodaxe=271 -stonesword=272 -stoneshovel=273 -stonespade=273 -stonepickaxe=274 -stonepick=274 -stoneaxe=275 -diamondsword=276 -diamondshovel=277 -diamondspade=277 -diamondpickaxe=278 -diamondpick=278 -diamondaxe=279 -stick=280 -bowl=281 -mushroomstew=282 -bowlwithsoup=282 -soupbowl=282 -soup=282 -goldensword=283 -goldsword=283 -goldenshovel=284 -goldshovel=284 -goldenspade=284 -goldspade=284 -goldenpickaxe=285 -goldpickaxe=285 -goldenpick=285 -goldpick=285 -goldenaxe=286 -goldaxe=286 -string=287 -feather=288 -gunpowder=289 -woodhoe=290 -woodenhoe=290 -stonehoe=291 -ironhoe=292 -diamondhoe=293 -goldhoe=294 -goldenhoe=294 -seeds=295 -wheat=296 -bread=297 -leatherhelmet=298 -leatherchestplate=299 -leatherpants=300 -leatherboots=301 -chainmailhelmet=302 -chainmailchestplate=303 -chainmailpants=304 -chainmailboots=305 -ironhelmet=306 -ironchestplate=307 -ironpants=308 -ironboots=309 -diamondhelmet=310 -diamondchestplate=311 -diamondpants=312 -diamondboots=313 -goldenhelmet=314 -goldhelmet=314 -goldenchestplate=315 -goldchestplate=315 -goldenpants=316 -goldpants=316 -goldenboots=317 -goldboots=317 -flint=318 -meat=319 -pork=319 -cookedmeat=320 -cookedpork=320 -painting=321 -paintings=321 -goldenapple=322 -goldapple=322 -enchantedgoldenapple=322:1 -enchantedgoldapple=322:1 -sign=323 -wooddoor=324 -woodendoor=324 -bucket=325 -waterbucket=326 -lavabucket=327 -minecart=328 -saddle=329 -irondoor=330 -redstonedust=331 -snowball=332 -boat=333 -leather=334 -milkbucket=335 -brick=336 -clay=337 -reed=338 -sugarcane=338 -paper=339 -book=340 -slimeorb=341 -slimeball=341 -storageminecart=342 -poweredminecart=343 -egg=344 -compass=345 -fishingrod=346 -watch=347 -lightstonedust=348 -lightdust=348 -glowstonedust=348 -glowdust=348 -rawfish=349 -fish=349 -cookedfish=350 -dye=351 -inksac=351:0 -blackdye=351:0 -reddye=351:1 -rosered=351:1 -greendye=351:2 -cactusgreen=351:2 -cocoabeans=351:3 -browndye=351:3 -lapislazuli=351:4 -bluedye=351:4 -darkbluedye=351:4 -dkbluedye=351:4 -purpledye=351:5 -violetdye=351:5 -cyandye=351:6 -lightgreydye=351:7 -lightgraydye=351:7 -ltgreydye=351:7 -ltgraydye=351:7 -greydye=351:8 -graydye=351:8 -darkgreydye=351:8 -darkgraydye=351:8 -dkgreydye=351:8 -dkgraydye=351:8 -pinkdye=351:9 -limedye=351:10 -lightgreendye=351:10 -ltgreendye=351:10 -dandellionyellow=351:11 -yellowdye=351:11 -lightbluedye=351:12 -ltbluedye=351:12 -magentadye=351:13 -orangedye=351:14 -bonemeal=351:15 -whitedye=351:15 -bone=352 -sugar=353 -cake=354 -bed=355 -repeater=356 -diode=356 -cookie=357 -map=358 -shears=359 -melonslice=360 -pumpkinseeds=361 -melonseeds=362 -rawbeef=363 -steak=364 -rawchicken=365 -cookedchicken=366 -rottenflesh=367 -enderpearl=368 -blazerod=369 -ghasttear=370 -goldnugget=371 -netherwart=372 -potion=373 -glassbottle=374 -spidereye=375 -fermentedspidereye=376 -blazepowder=377 -magmacream=378 -brewingstand=379 -cauldron=380 -eyeofender=381 -glisteringmelon=382 -spawnegg=383 -bottleoenchanting=384 -firecharge=385 -bookandquill=386 -writtenbook=387 -emerald=388 -itemframe=389 -flowerpot=390 -carrot=391 -potato=392 -bakedpotato=393 -poisonouspotato=394 -emptymap=395 -goldencarrot=396 -skeletonhead=397 -witherhead=397:1 -zombiehead=397:2 -stevehead=397:3 -creeperhead=397:4 -carrotonastick=398 -netherstar=399 -pumpkinpie=400 -fireworkrocket=401 -fireworkstar=402 -enchantedbook=403 -comparator=404 -netherbrickitem=405 -netherquartz=406 -tntminecart=407 -hopperminecart=408 - -goldrecord=2256 -greenrecord=2257 -blocksrecord=2258 -chirprecord=2259 -farrecord=2260 -mallrecord=2261 -mellohirecord=2262 -stalrecord=2263 -stradrecord=2264 -wardrecord=2265 -11record=2266 - +[Items] +rock=1 +stone=1 +grass=2 +dirt=3 +cobblestone=4 +cobble=4 +planks=5 +appleplanks=5:0 +oakplanks=5:0 +coniferplanks=5:1 +pineplanks=5:1 +spruceplanks=5:1 +darkplanks=5:1 +birchplanks=5:2 +lightplanks=5:2 +jungleplanks=5:3 +redplanks=5:3 + +; Obsolete: do not use "wood", as its meaning is not clear - wiki uses log as wood, we use planks as wood. +wood=5 + +sapling=6 +applesapling=6:0 +oaksapling=6:0 +conifersapling=6:1 +pinesapling=6:1 +sprucesapling=6:1 +birchsapling=6:2 +junglesapling=6:3 +adminium=7 +bedrock=7 +water=8 +stillwater=9 +swater=9 +stationarywater=9 +lava=10 +stilllava=11 +slava=11 +stationarylava=11 +sand=12 +gravel=13 +goldore=14 +ironore=15 +coalore=16 +tree=17 +log=17 +applelog=17:0 +oaklog=17:0 +coniferlog=17:1 +pinelog=17:1 +sprucelog=17:1 +darklog=17:1 +birchlog=17:2 +whitelog=17:2 +junglelog=17:3 +leaves=18 +appleleaves=18:0 +oakleaves=18:0 +coniferleaves=18:1 +pineleaves=18:1 +spruceleaves=18:1 +birchleaves=18:2 +jungleleaves=18:3 +sponge=19 +glass=20 +lapisore=21 +lapisblock=22 +dispenser=23 +sandstone=24 +normalsandstone=24:0 +ornamentsandstone=24:1 +decorativesandstone=24:1 +smoothsandstone=24:2 +noteblock=25 +bedblock=26 +poweredrail=27 +detectorrail=28 +stickypiston=29 +cobweb=30 +tallgrass=31 +tallgrassone=31:1 +tallgrasstwo=31:2 +deadbush=32 +piston=33 +pistonextension=34 +pistonhead=34 +cloth=35 +wool=35 +whitewool=35:0 +orangewool=35:1 +magentawool=35:2 +lightbluewool=35:3 +yellowwool=35:4 +limewool=35:5 +lightgreenwool=35:5 +ltgreenwool=35:5 +pinkwool=35:6 +graywool=35:7 +greywool=35:7 +darkgraywool=35:7 +darkgreywool=35:7 +dkgraywool=35:7 +dkgreywool=35:7 +lightgraywool=35:8 +lightgreywool=35:8 +ltgraywool=35:8 +ltgreywool=35:8 +cyanwool=35:9 +purplewool=35:10 +violetwool=35:10 +bluewool=35:11 +darkbluewool=35:11 +brownwool=35:12 +greenwool=35:13 +darkgreenwool=35:13 +dkgreenwool=35:13 +redwool=35:14 +blackwool=35:15 +flower=37 +rose=38 +brownmushroom=39 +redmushroom=40 +gold=41 +goldblock=41 +iron=42 +ironblock=42 +doubleslab=43 +stonedoubleslab=43:0 +sandstonedoubleslab=43:1 +wooddoubleslab=43:2 +cobblestonedoubleslab=43:3 +brickdoubleslab=43:4 +stonebrickdoubleslab=43:5 +netherbrickdoubleslab=43:6 +quartzdoubleslab=43:7 +slab=44 +step=44 +stoneslab=44:0 +sandstoneslab=44:1 +woodslab=44:2 +cobblestoneslab=44:3 +brickslab=44:4 +stonebrickslab=44:5 +netherbrickslab=44:6 +quartzslab=44:7 +brickblock=45 +brickwall=45 +tnt=46 +bookshelf=47 +bookcase=47 +mossycobblestone=48 +mossy=48 +obsidian=49 +torch=50 +fire=51 +mobspawner=52 +woodstairs=53 +chest=54 +redstonedust=55 +redstonewire=55 +diamondore=56 +diamondblock=57 +workbench=58 +crop=59 +crops=59 +soil=60 +furnace=61 +litfurnace=62 +signblock=63 +wooddoorblock=64 +ladder=65 +rails=66 +rail=66 +track=66 +tracks=66 +cobblestonestairs=67 +stairs=67 +signblocktop=68 +wallsign=68 +lever=69 +rockplate=70 +stoneplate=70 +irondoorblock=71 +woodplate=72 +redstoneore=73 +redstoneorealt=74 +redstonetorchoff=75 +redstonetorchon=76 +stonebutton=77 +snow=78 +ice=79 +snowblock=80 +cactus=81 +clayblock=82 +reedblock=83 +jukebox=84 +fence=85 +pumpkin=86 +netherstone=87 +netherrack=87 +hellrock=87 +slowsand=88 +soulsand=88 +lightstone=89 +glowstone=89 +portal=90 +jackolantern=91 +jacko=91 +cakeblock=92 +lockedchest=95 +trapdoor=96 +silverfishblock=97 +stonebricks=98 +stonebrick=98 +mossystonebrick=98:1 +crackedstonebrick=98:2 +chiseledstonebrick=98:3 +hugebrownmushroom=99 +hugeredmushroom=100 +ironbars=101 +glasspane=102 +melon=103 +pumpkinstem=104 +melonstem=105 +vines=106 +fencegate=107 +brickstairs=108 +stonebrickstairs=109 +mycelium=110 +lilypad=111 +netherbrick=112 +netherbrickfence=113 +netherbrickstairs=114 +netherwartblock=115 +enchantmenttable=116 +brewingstandblock=117 +cauldronblock=118 +endportal=119 +endportalframe=120 +endstone=121 +dragonegg=122 +redstonelamp=123 +redstonelampoff=123 +redstonelampon=124 +woodendoubleslab=125 +woodenslab=126 +sandstonestairs=128 +emeraldore=129 +enderchest=130 +tripwirehook=131 +tripwire=132 +emeraldblock=133 +commandblock=137 +beacon=138 +cobblestonewall=139 +mossycobblestonewall=139:1 +flowerpotblock=140 +carrotcrop=141 +potatocrop=142 +woodenbutton=143 +skeletonhead=144 +witherhead=144:1 +zombiehead=144:2 +humanhead=144:3 +stevehead=144:3 +creeperhead=144:4 +anvil=145 +trappedchest=146 +lightweightedpressureplate=147 +heavyweightedpressureplate=148 +inactivecomparator=149 +activecomparator=150 +daylightsensor=151 +redstoneblock=152 +netherquartzore=153 +hopper=154 +quartzblock=155 +chiseledquartzblock=155:1 +pillarquartzblock=155:2 +quartzstairs=156 +activatorrail=157 +dropper=158 + +ironshovel=256 +ironspade=256 +ironpickaxe=257 +ironpick=257 +ironaxe=258 +flintandsteel=259 +lighter=259 +apple=260 +redapple=260 +bow=261 +arrow=262 +coal=263 +charcoal=263:1 +diamond=264 +ironingot=265 +ironbar=265 +goldingot=266 +goldeningot=266 +goldbar=266 +goldenbar=266 +ironsword=267 +woodensword=268 +woodsword=268 +woodenshovel=269 +woodshovel=269 +woodenspade=269 +woodspade=269 +woodenpickaxe=270 +woodpickaxe=270 +woodenpick=270 +woodpick=270 +woodenaxe=271 +woodaxe=271 +stonesword=272 +stoneshovel=273 +stonespade=273 +stonepickaxe=274 +stonepick=274 +stoneaxe=275 +diamondsword=276 +diamondshovel=277 +diamondspade=277 +diamondpickaxe=278 +diamondpick=278 +diamondaxe=279 +stick=280 +bowl=281 +mushroomstew=282 +bowlwithsoup=282 +soupbowl=282 +soup=282 +goldensword=283 +goldsword=283 +goldenshovel=284 +goldshovel=284 +goldenspade=284 +goldspade=284 +goldenpickaxe=285 +goldpickaxe=285 +goldenpick=285 +goldpick=285 +goldenaxe=286 +goldaxe=286 +string=287 +feather=288 +gunpowder=289 +woodhoe=290 +woodenhoe=290 +stonehoe=291 +ironhoe=292 +diamondhoe=293 +goldhoe=294 +goldenhoe=294 +seeds=295 +wheat=296 +bread=297 +leatherhelmet=298 +leatherchestplate=299 +leatherpants=300 +leatherboots=301 +chainmailhelmet=302 +chainmailchestplate=303 +chainmailpants=304 +chainmailboots=305 +ironhelmet=306 +ironchestplate=307 +ironpants=308 +ironboots=309 +diamondhelmet=310 +diamondchestplate=311 +diamondpants=312 +diamondboots=313 +goldenhelmet=314 +goldhelmet=314 +goldenchestplate=315 +goldchestplate=315 +goldenpants=316 +goldpants=316 +goldenboots=317 +goldboots=317 +flint=318 +meat=319 +pork=319 +cookedmeat=320 +cookedpork=320 +painting=321 +paintings=321 +goldenapple=322 +goldapple=322 +enchantedgoldenapple=322:1 +enchantedgoldapple=322:1 +sign=323 +wooddoor=324 +woodendoor=324 +bucket=325 +waterbucket=326 +lavabucket=327 +minecart=328 +saddle=329 +irondoor=330 +redstonedust=331 +snowball=332 +boat=333 +leather=334 +milkbucket=335 +brick=336 +clay=337 +reed=338 +sugarcane=338 +paper=339 +book=340 +slimeorb=341 +slimeball=341 +storageminecart=342 +poweredminecart=343 +egg=344 +compass=345 +fishingrod=346 +watch=347 +lightstonedust=348 +lightdust=348 +glowstonedust=348 +glowdust=348 +rawfish=349 +fish=349 +cookedfish=350 +dye=351 +inksac=351:0 +blackdye=351:0 +reddye=351:1 +rosered=351:1 +greendye=351:2 +cactusgreen=351:2 +cocoabeans=351:3 +browndye=351:3 +lapislazuli=351:4 +bluedye=351:4 +darkbluedye=351:4 +dkbluedye=351:4 +purpledye=351:5 +violetdye=351:5 +cyandye=351:6 +lightgreydye=351:7 +lightgraydye=351:7 +ltgreydye=351:7 +ltgraydye=351:7 +greydye=351:8 +graydye=351:8 +darkgreydye=351:8 +darkgraydye=351:8 +dkgreydye=351:8 +dkgraydye=351:8 +pinkdye=351:9 +limedye=351:10 +lightgreendye=351:10 +ltgreendye=351:10 +dandellionyellow=351:11 +yellowdye=351:11 +lightbluedye=351:12 +ltbluedye=351:12 +magentadye=351:13 +orangedye=351:14 +bonemeal=351:15 +whitedye=351:15 +bone=352 +sugar=353 +cake=354 +bed=355 +repeater=356 +diode=356 +cookie=357 +map=358 +shears=359 +melonslice=360 +pumpkinseeds=361 +melonseeds=362 +rawbeef=363 +steak=364 +rawchicken=365 +cookedchicken=366 +rottenflesh=367 +enderpearl=368 +blazerod=369 +ghasttear=370 +goldnugget=371 +netherwart=372 +potion=373 +glassbottle=374 +spidereye=375 +fermentedspidereye=376 +blazepowder=377 +magmacream=378 +brewingstand=379 +cauldron=380 +eyeofender=381 +glisteringmelon=382 +spawnegg=383 +bottleoenchanting=384 +firecharge=385 +bookandquill=386 +writtenbook=387 +emerald=388 +itemframe=389 +flowerpot=390 +carrot=391 +potato=392 +bakedpotato=393 +poisonouspotato=394 +emptymap=395 +goldencarrot=396 +skeletonhead=397 +witherhead=397:1 +zombiehead=397:2 +stevehead=397:3 +creeperhead=397:4 +carrotonastick=398 +netherstar=399 +pumpkinpie=400 +fireworkrocket=401 +fireworkstar=402 +enchantedbook=403 +comparator=404 +netherbrickitem=405 +netherquartz=406 +tntminecart=407 +hopperminecart=408 + +goldrecord=2256 +greenrecord=2257 +blocksrecord=2258 +chirprecord=2259 +farrecord=2260 +mallrecord=2261 +mellohirecord=2262 +stalrecord=2263 +stradrecord=2264 +wardrecord=2265 +11record=2266 + diff --git a/MCServer/monsters.ini b/MCServer/monsters.ini index 6634c5bef..80a0c7dde 100644 --- a/MCServer/monsters.ini +++ b/MCServer/monsters.ini @@ -1,111 +1,111 @@ -[Spider] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=10 - -[Chicken] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=4 - -[Cow] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=10 - -[Pig] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=10 - -[Sheep] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=8 - -[Squid] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=10 - -[Enderman] -AttackRange=5.0 -AttackRate=1 -AttackDamage=4.0 -SightDistance=25.0 -MaxHealth=40 - -[Zombiepigman] -AttackRange=5.0 -AttackRate=1 -AttackDamage=5.0 -SightDistance=25.0 -MaxHealth=20 - -[Cavespider] -AttackRange=5.0 -AttackRate=1 -AttackDamage=2.0 -SightDistance=25.0 -MaxHealth=12 - -[Creeper] -AttackRange=5.0 -AttackRate=1 -AttackDamage=0.0 -SightDistance=25.0 -MaxHealth=20 - -[Ghast] -AttackRange=5.0 -AttackRate=1 -AttackDamage=0.0 -SightDistance=25.0 -MaxHealth=10 - -[Silverfish] -AttackRange=5.0 -AttackRate=1 -AttackDamage=1.0 -SightDistance=25.0 -MaxHealth=8 - -[Skeleton] -AttackRange=5.0 -AttackRate=1 -AttackDamage=4.0 -SightDistance=25.0 -MaxHealth=20 - -[Slime] -AttackRange=5.0 -AttackRate=1 -AttackDamage=10.0 -SightDistance=25.0 -MaxHealth=32 - -[Spider] -AttackRange=5.0 -AttackRate=1 -AttackDamage=2.0 -SightDistance=25.0 -MaxHealth=16 - -[Zombie] -AttackRange=5.0 -AttackRate=1 -AttackDamage=4.0 -SightDistance=25.0 +[Spider] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=10 + +[Chicken] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=4 + +[Cow] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=10 + +[Pig] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=10 + +[Sheep] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=8 + +[Squid] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=10 + +[Enderman] +AttackRange=5.0 +AttackRate=1 +AttackDamage=4.0 +SightDistance=25.0 +MaxHealth=40 + +[Zombiepigman] +AttackRange=5.0 +AttackRate=1 +AttackDamage=5.0 +SightDistance=25.0 +MaxHealth=20 + +[Cavespider] +AttackRange=5.0 +AttackRate=1 +AttackDamage=2.0 +SightDistance=25.0 +MaxHealth=12 + +[Creeper] +AttackRange=5.0 +AttackRate=1 +AttackDamage=0.0 +SightDistance=25.0 +MaxHealth=20 + +[Ghast] +AttackRange=5.0 +AttackRate=1 +AttackDamage=0.0 +SightDistance=25.0 +MaxHealth=10 + +[Silverfish] +AttackRange=5.0 +AttackRate=1 +AttackDamage=1.0 +SightDistance=25.0 +MaxHealth=8 + +[Skeleton] +AttackRange=5.0 +AttackRate=1 +AttackDamage=4.0 +SightDistance=25.0 +MaxHealth=20 + +[Slime] +AttackRange=5.0 +AttackRate=1 +AttackDamage=10.0 +SightDistance=25.0 +MaxHealth=32 + +[Spider] +AttackRange=5.0 +AttackRate=1 +AttackDamage=2.0 +SightDistance=25.0 +MaxHealth=16 + +[Zombie] +AttackRange=5.0 +AttackRate=1 +AttackDamage=4.0 +SightDistance=25.0 MaxHealth=20 \ No newline at end of file diff --git a/MCServer/settings.ini b/MCServer/settings.ini index 5e6ed4e2b..e2505368d 100644 --- a/MCServer/settings.ini +++ b/MCServer/settings.ini @@ -1,31 +1,31 @@ -; This is the main server configuration -; For help, please visit the Wiki page: http://www.mc-server.org/wiki/doku.php?id=configure:settings.ini -; Most of these settings can also be set using the webadmin interface, if it is enabled. - -[Server] -Port=25565 -MaxPlayers=100 -Description=MCServer - in C++ -DefaultViewDistance=9 - -[Worlds] -DefaultWorld=world - -[Plugins] -; Plugin=Debuggers -; Plugin=DiamondMover -; Plugin=HookNotify -Plugin=Core -Plugin=ChunkWorx -Plugin=ChatLog - -[Monsters] -AnimalsOn=0 -AnimalSpawnInterval=10 -Types=Spider,Chicken,Cow,Pig,Sheep,Squid,Enderman,Zombiepigman,Cavespider,Creeper,Ghast,Silverfish,Skeleton,Slime,Spider,Zombie - -[Authentication] -Server=session.minecraft.net -Address=/game/checkserver.jsp?user=%USERNAME%&serverId=%SERVERID% -Authenticate=0 - +; This is the main server configuration +; For help, please visit the Wiki page: http://www.mc-server.org/wiki/doku.php?id=configure:settings.ini +; Most of these settings can also be set using the webadmin interface, if it is enabled. + +[Server] +Port=25565 +MaxPlayers=100 +Description=MCServer - in C++ +DefaultViewDistance=9 + +[Worlds] +DefaultWorld=world + +[Plugins] +; Plugin=Debuggers +; Plugin=DiamondMover +; Plugin=HookNotify +Plugin=Core +Plugin=ChunkWorx +Plugin=ChatLog + +[Monsters] +AnimalsOn=0 +AnimalSpawnInterval=10 +Types=Spider,Chicken,Cow,Pig,Sheep,Squid,Enderman,Zombiepigman,Cavespider,Creeper,Ghast,Silverfish,Skeleton,Slime,Spider,Zombie + +[Authentication] +Server=session.minecraft.net +Address=/game/checkserver.jsp?user=%USERNAME%&serverId=%SERVERID% +Authenticate=0 + diff --git a/MCServer/terrain.ini b/MCServer/terrain.ini index a917223f9..0d86376c5 100644 --- a/MCServer/terrain.ini +++ b/MCServer/terrain.ini @@ -1,8 +1,8 @@ -[Terrain] -HeightFreq1=0.100000 -HeightFreq2=1.000000 -HeightFreq3=2.000000 -HeightAmp1=1.000000 -HeightAmp2=0.500000 -HeightAmp3=0.500000 - +[Terrain] +HeightFreq1=0.100000 +HeightFreq2=1.000000 +HeightFreq3=2.000000 +HeightAmp1=1.000000 +HeightAmp2=0.500000 +HeightAmp3=0.500000 + diff --git a/MCServer/users.ini b/MCServer/users.ini index 1015527cc..6726c0bf8 100644 --- a/MCServer/users.ini +++ b/MCServer/users.ini @@ -1,23 +1,23 @@ -[FakeTruth] -Groups=Admins - -[Duralex] -Groups=Admins - -[Luthrandel] -Groups=Admins - -[cruisecho] -Groups=Admins - -[Kwen] -Groups=Admins - -[aloe_vera] -Groups=Admins - -[xoft] -Groups=Admins - -[Player] +[FakeTruth] +Groups=Admins + +[Duralex] +Groups=Admins + +[Luthrandel] +Groups=Admins + +[cruisecho] +Groups=Admins + +[Kwen] +Groups=Admins + +[aloe_vera] +Groups=Admins + +[xoft] +Groups=Admins + +[Player] Groups=Admins \ No newline at end of file diff --git a/MCServer/webadmin.ini b/MCServer/webadmin.ini index 7384f0bde..8597225bb 100644 --- a/MCServer/webadmin.ini +++ b/MCServer/webadmin.ini @@ -1,6 +1,6 @@ -[WebAdmin] -Enabled=1 -Port=8081 - -[User:admin] +[WebAdmin] +Enabled=1 +Port=8081 + +[User:admin] Password=admin \ No newline at end of file diff --git a/MCServer/webadmin/template.html b/MCServer/webadmin/template.html index 26337c364..03de23360 100644 --- a/MCServer/webadmin/template.html +++ b/MCServer/webadmin/template.html @@ -1,145 +1,145 @@ - - - - {TITLE} | {PLUGIN_NAME} - - - - - - - - - -
-
- -

MCServer, the Minecraft Server coded in C++!

-
- -
-

Welcome {USERNAME}, to the Control Panel! :D

- {CONTENT} -
-

MCServer is using {MEM}MB of memory, with {NUMCHUNKS} chunks loaded.

Web Design by Tiger

-
- - + + + + {TITLE} | {PLUGIN_NAME} + + + + + + + + + +
+
+ +

MCServer, the Minecraft Server coded in C++!

+
+ +
+

Welcome {USERNAME}, to the Control Panel! :D

+ {CONTENT} +
+ +
+ + -- cgit v1.2.3