diff options
Diffstat (limited to 'MCServer')
-rw-r--r-- | MCServer/.gitignore | 3 | ||||
-rw-r--r-- | MCServer/Plugins/APIDump/APIDesc.lua | 68 | ||||
-rw-r--r-- | MCServer/Plugins/APIDump/APIDump.deproj | 9 | ||||
-rw-r--r-- | MCServer/Plugins/APIDump/main.lua | 283 | ||||
-rw-r--r-- | MCServer/Plugins/Debuggers/Debuggers.lua | 22 |
5 files changed, 373 insertions, 12 deletions
diff --git a/MCServer/.gitignore b/MCServer/.gitignore index ac226a77d..ff0517cfa 100644 --- a/MCServer/.gitignore +++ b/MCServer/.gitignore @@ -4,7 +4,9 @@ MCServer logs players world* +API/ API.txt +API_wiki.txt *.dat schematics *.schematic @@ -15,3 +17,4 @@ memdump* ProtectionAreas.sqlite helgrind.log motd.txt +*.deuser diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua new file mode 100644 index 000000000..44981fdd7 --- /dev/null +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -0,0 +1,68 @@ + +-- APIDesc.lua + +-- Contains the API objects' descriptions + + + + +g_APIDesc = +{ + Classes = + { + cBlockArea = + { + Desc = [[ + This class is used when multiple adjacent blocks are to be manipulated. Because of chunking + and multithreading, manipulating single blocks using {{api:cWorld|cWorld:SetBlock}}() is a rather + time-consuming operation (locks for exclusive access need to be obtained, chunk lookup is done + for each block), so whenever you need to manipulate multiple adjacent blocks, it's better to wrap + the operation into a cBlockArea access. cBlockArea is capable of reading / writing across chunk + boundaries, has no chunk lookups for get and set operations and is not subject to multithreading + locking (because it is not shared among threads).</p> + <p> + cBlockArea remembers its origin (MinX, MinY, MinZ coords in the Read() call) and therefore supports + absolute as well as relative get / set operations. Despite that, the contents of a cBlockArea can + be written back into the world at any coords.</p> + <p> + cBlockArea can hold any combination of the following datatypes:<ul> + <li>block types</li> + <li>block metas</li> + <li>blocklight</li> + <li>skylight</li> + </ul> + Read() and Write() functions have parameters that tell the class which datatypes to read / write. + Note that a datatype that has not been read cannot be written (FIXME).</p> + <p> + Typical usage:<ul> + <li>Create cBlockArea object</li> + <li>Read an area from the world</li> + <li>Modify blocks inside cBlockArea</li> + <li>Write the area back to a world</li> + </ul></p> + ]], + Functions = + { + Clear = { Notes = "Clears the object, resets it to zero size" }, + CopyFrom = { Params = "{{cBlockArea|BlockAreaSrc}}", Notes = "Copies contents from BlockAreaSrc into self"}, + CopyTo = { Params = "{{cBlockArea|BlockAreaDst}}", Notes = "Copies contents from self into BlockAreaDst"}, + GetBlockLight = { Params = "BlockX, BlockY, BlockZ", Return = "NIBBLETYPE", Notes = "Returns the blocklight at the specified absolute coords"}, + }, + }, + + cBlockEntity = + { + } + }, + + IgnoreFunctions = + { + "globals.assert", + "globals.collectgarbage", + "globals.xpcall", + } +} ; + + + + diff --git a/MCServer/Plugins/APIDump/APIDump.deproj b/MCServer/Plugins/APIDump/APIDump.deproj new file mode 100644 index 000000000..9ee9170f2 --- /dev/null +++ b/MCServer/Plugins/APIDump/APIDump.deproj @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<project> + <file> + <filename>APIDesc.lua</filename> + </file> + <file> + <filename>main.lua</filename> + </file> +</project> diff --git a/MCServer/Plugins/APIDump/main.lua b/MCServer/Plugins/APIDump/main.lua index 853ff6301..c13611d2e 100644 --- a/MCServer/Plugins/APIDump/main.lua +++ b/MCServer/Plugins/APIDump/main.lua @@ -1,5 +1,14 @@ --- Global variables -PLUGIN = {}; -- Reference to own plugin object + +-- main.lua + +-- Implements the plugin entrypoint (in this case the entire plugin) + + + + + +-- Global variables: +g_Plugin = nil; @@ -7,7 +16,7 @@ PLUGIN = {}; -- Reference to own plugin object function Initialize(Plugin) - PLUGIN = Plugin + g_Plugin = Plugin; Plugin:SetName("APIDump") Plugin:SetVersion(1) @@ -16,8 +25,11 @@ function Initialize(Plugin) LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) -- dump all available API functions and objects: - DumpAPI(); - + -- DumpAPITxt(); + + -- Dump all available API object in HTML format into a subfolder: + DumpAPIHtml(); + return true end @@ -26,16 +38,16 @@ end -function DumpAPI() +function DumpAPITxt() 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"); + -- LOG(prefix .. i .. " == _G, CYCLE, ignoring"); elseif (v == _G.package) then - LOG(prefix .. i .. " == _G.package, ignoring"); + -- LOG(prefix .. i .. " == _G.package, ignoring"); else dump(prefix .. i .. ".", v, Output) end @@ -59,3 +71,258 @@ function DumpAPI() f:close(); LOG("API.txt written."); end + + + + + +function CreateAPITables() + --[[ + We want an API table of the following shape: + local API = { + { + Name = "cCuboid", + Functions = { + {Name = "Sort"}, + {Name = "IsInside"} + }, + Constants = { + } + }}, + { + Name = "cBlockArea", + Functions = { + {Name = "Clear"}, + {Name = "CopyFrom"}, + ... + } + Constants = { + {Name = "baTypes", Value = 0}, + {Name = "baMetas", Value = 1}, + ... + } + ... + }} + }; + local Globals = { + Functions = { + ... + }, + Constants = { + ... + } + }; + --]] + + local Globals = {Functions = {}, Constants = {}}; + local API = {}; + + local function Add(a_APIContainer, a_ClassName, a_ClassObj) + if (type(a_ClassObj) == "function") then + table.insert(a_APIContainer.Functions, {Name = a_ClassName}); + elseif (type(a_ClassObj) == "number") then + table.insert(a_APIContainer.Constants, {Name = a_ClassName, Value = a_ClassObj}); + end + end + + local function SortClass(a_ClassAPI) + -- Sort the function list and constant lists: + table.sort(a_ClassAPI.Functions, + function(f1, f2) + return (f1.Name < f2.Name); + end + ); + table.sort(a_ClassAPI.Constants, + function(c1, c2) + return (c1.Name < c2.Name); + end + ); + end; + + local function ParseClass(a_ClassName, a_ClassObj) + local res = {Name = a_ClassName, Functions = {}, Constants = {}}; + for i, v in pairs(a_ClassObj) do + Add(res, i, v); + end + + SortClass(res); + return res; + end + + for i, v in pairs(_G) do + if (type(v) == "table") then + -- It is a table - probably a class + local StartLetter = GetChar(i, 0); + if (StartLetter == "c") then + -- Starts with a "c", handle it as a MCS API class + table.insert(API, ParseClass(i, v)); + end + else + Add(Globals, i, v); + end + end + SortClass(Globals); + table.sort(API, + function(c1, c2) + return (c1.Name < c2.Name); + end + ); + + return API, Globals; +end + + + + + +function DumpAPIHtml() + LOG("Dumping all available functions and constants to API subfolder..."); + + local API, Globals = CreateAPITables(); + Globals.Name = "Globals"; + table.insert(API, Globals); + + -- Read in the descriptions: + ReadDescriptions(API); + + -- Create the output folder: + os.execute("mkdir API"); + + -- Create a "class index" file, write each class as a link to that file, + -- then dump class contents into class-specific file + local f = io.open("API/index.html", "w"); + f:write([[<html><head><title>MCServer API - class index</title> + <link rel="stylesheet" type="text/css" href="main.css" /> + </head><body> + <ul> + ]]); + for i, cls in ipairs(API) do + f:write("<li><a href=\"" .. cls.Name .. ".html\">" .. cls.Name .. "</a></li>\n"); + WriteHtmlClass(cls); + end + f:write("</ul></body></html>"); + f:close(); +end + + + + + +function ReadDescriptions(a_API) + local UnexportedDocumented = {}; -- List of API objects that are documented but not exported, simply a list of names + for i, cls in ipairs(a_API) do + local APIDesc = g_APIDesc.Classes[cls.Name]; + if (APIDesc ~= nil) then + cls.Desc = APIDesc.Desc; + + if (APIDesc.Functions ~= nil) then + -- Assign function descriptions: + for j, func in ipairs(cls.Functions) do + -- func is {"FuncName"}, add Parameters, Return and Notes from g_APIDesc + local FnDesc = APIDesc.Functions[func.Name]; + if (FnDesc ~= nil) then + func.Params = FnDesc.Params; + func.Return = FnDesc.Return; + func.Notes = FnDesc.Notes; + FnDesc.IsExported = true; + end + end -- for j, func + + -- Add all non-exported function descriptions to UnexportedDocumented: + for j, func in pairs(APIDesc.Functions) do + -- TODO + end + end -- if (APIDesc.Functions ~= nil) + + if (APIDesc.Constants ~= nil) then + -- Assign constant descriptions: + for j, cons in ipairs(cls.Constants) do + local CnDesc = APIDesc.Constants[cons.Name]; + if (CnDesc ~= nil) then + cons.Notes = CnDesc.Notes; + CnDesc.IsExported = true; + end + end -- for j, cons + + -- Add all non-exported constant descriptions to UnexportedDocumented: + for j, cons in pairs(APIDesc.Constants) do + -- TODO + end + end -- if (APIDesc.Constants ~= nil) + + end + end -- for i, class +end + + + + + +function WriteHtmlClass(a_ClassAPI) + local cf, err = io.open("API/" .. a_ClassAPI.Name .. ".html", "w"); + if (cf == nil) then + return; + end + + local function LinkifyString(a_String) + -- TODO: Make a link out of anything with the special linkifying syntax {{link|title}} + -- a_String:gsub("{{([^|]*)|[^}]*}}", "<a href=\"%1\">%2</a>"); + return a_String; + end + + cf:write([[<html><head><title>MCServer API - ]] .. a_ClassAPI.Name .. [[</title> + <link rel="stylesheet" type="text/css" href="main.css" /> + </head><body> + <h1>Contents</h1> + <ul> + ]]); + + -- Write the table of contents: + if (#a_ClassAPI.Constants > 0) then + cf:write("<li><a href=\"#constants\">Constants</a></li>\n"); + end + if (#a_ClassAPI.Functions > 0) then + cf:write("<li><a href=\"#functions\">Functions</a></li>\n"); + end + cf:write("</ul>"); + + -- Write the class description: + cf:write("<a name=\"desc\"><h1>" .. a_ClassAPI.Name .. "</h1></a>\n"); + if (a_ClassAPI.Desc ~= nil) then + cf:write("<p>"); + cf:write(a_ClassAPI.Desc); + cf:write("</p>\n"); + end; + + -- Write the constants: + if (#a_ClassAPI.Constants > 0) then + cf:write("<a name=\"constants\"><h1>Constants</h1></a>\n"); + cf:write("<table><tr><th>Name</th><th>Value</th><th>Notes</th></tr>\n"); + for i, cons in ipairs(a_ClassAPI.Constants) do + cf:write("<tr><td>" .. cons.Name .. "</td>"); + cf:write("<td>" .. cons.Value .. "</td>"); + cf:write("<td>" .. LinkifyString(cons.Notes or "") .. "</td></tr>\n"); + end + cf:write("</table>\n"); + end + + -- Write the functions: + if (#a_ClassAPI.Functions > 0) then + cf:write("<a name=\"functions\"><h1>Functions</h1></a>\n"); + cf:write("<table><tr><th>Name</th><th>Parameters</th><th>Return value</th><th>Notes</th></tr>\n"); + for i, func in ipairs(a_ClassAPI.Functions) do + cf:write("<tr><td>" .. func.Name .. "</td>"); + cf:write("<td>" .. LinkifyString(func.Params or "").. "</td>"); + cf:write("<td>" .. LinkifyString(func.Return or "").. "</td>"); + cf:write("<td>" .. LinkifyString(func.Notes or "") .. "</td></tr>\n"); + end + cf:write("</table>\n"); + end + + cf:write("</body></html>"); + cf:close(); +end + + + + diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index be16e3465..b895da05e 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -1,6 +1,5 @@ --- Global variables -PLUGIN = {}; -- Reference to own plugin object +-- Global variables g_DropSpensersToActivate = {}; -- A list of dispensers and droppers (as {World, X, Y Z} quadruplets) that are to be activated every tick g_HungerReportTick = 10; g_ShowFoodStats = false; -- When true, each player's food stats are sent to them every 10 ticks @@ -11,8 +10,6 @@ g_ShowFoodStats = false; -- When true, each player's food stats are sent to the function Initialize(Plugin) - PLUGIN = Plugin - Plugin:SetName("Debuggers") Plugin:SetVersion(1) @@ -46,6 +43,7 @@ function Initialize(Plugin) PluginManager:BindCommand("/ench", "debuggers", HandleEnchCmd, "- Provides an instant dummy enchantment window"); PluginManager:BindCommand("/fs", "debuggers", HandleFoodStatsCmd, "- Turns regular foodstats message on or off"); PluginManager:BindCommand("/arr", "debuggers", HandleArrowCmd, "- Creates an arrow going away from the player"); + PluginManager:BindCommand("/fb", "debuggers", HandleFireballCmd, "- Creates a ghast fireball as if shot by the player"); -- Enable the following line for BlockArea / Generator interface testing: -- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); @@ -480,6 +478,7 @@ end function OnWorldTick(a_World, a_Dt) + -- Report food stats, if switched on: local Tick = a_World:GetWorldAge(); if (not(g_ShowFoodStats) or (math.mod(Tick, 10) ~= 0)) then return false; @@ -825,3 +824,18 @@ end + +function HandleFireballCmd(a_Split, a_Player) + local World = a_Player:GetWorld(); + local Pos = a_Player:GetEyePosition(); + local Speed = a_Player:GetLookVector(); + Speed:Normalize(); + Pos = Pos + Speed * 2; + + World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkGhastFireball, a_Player, Speed * 10); + return true; +end + + + + |