summaryrefslogtreecommitdiffstats
path: root/MCServer/Plugins
diff options
context:
space:
mode:
authorTycho <work.tycho+git@gmail.com>2014-01-07 13:57:34 +0100
committerTycho <work.tycho+git@gmail.com>2014-01-07 13:57:34 +0100
commit0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f (patch)
treed2593b129bf0e83d72937cf52e8a9283c85be46a /MCServer/Plugins
parentMerge branch 'master' of github.com:mc-server/MCServer (diff)
parentAdded Base64Encode(). (diff)
downloadcuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.tar
cuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.tar.gz
cuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.tar.bz2
cuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.tar.lz
cuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.tar.xz
cuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.tar.zst
cuberite-0b79ad0d5dd9d2ddcbff4f7351ebd83ce22fb53f.zip
Diffstat (limited to 'MCServer/Plugins')
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua2
-rw-r--r--MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html6
-rw-r--r--MCServer/Plugins/APIDump/main_APIDump.lua2
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua19
-rw-r--r--MCServer/Plugins/InfoDump.deproj6
-rw-r--r--MCServer/Plugins/InfoDump.lua361
6 files changed, 391 insertions, 5 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index d388d15dd..26537918e 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -1713,7 +1713,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "bool", Notes = "Same as ExecuteCommand, but doesn't check permissions" },
ForEachCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function(Command, Permission, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
ForEachConsoleCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function (Command, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
- Get = { Params = "", Return = "cPluginManager", Notes = "Returns the single instance of the plugin manager" },
+ Get = { Params = "", Return = "cPluginManager", Notes = "(STATIC) Returns the single instance of the plugin manager" },
GetAllPlugins = { Params = "", Return = "table", Notes = "Returns a table (dictionary) of all plugins, [name => {{cPlugin}}] pairing." },
GetCommandPermission = { Params = "Command", Return = "Permission", Notes = "Returns the permission needed for executing the specified command" },
GetCurrentPlugin = { Params = "", Return = "{{cPlugin}}", Notes = "Returns the {{cPlugin}} object for the calling plugin. This is the same object that the Initialize function receives as the argument." },
diff --git a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
index 50e39d533..0e07cebdf 100644
--- a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
+++ b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
@@ -84,7 +84,7 @@ end
To register a hook, insert the following code template into the "-- Hooks" area in the previous code example.
</p>
<pre class="prettyprint lang-lua">
-cPluginManager.AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
+cPluginManager:AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
</pre>
<p>
What does this code do?
@@ -102,7 +102,7 @@ function Initialize(Plugin)
Plugin:SetName("DerpyPlugin")
Plugin:SetVersion(1)
- cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
+ cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
local PluginManager = cPluginManager:Get()
-- Command bindings
@@ -200,7 +200,7 @@ function Initialize(Plugin)
local PluginManager = cPluginManager:Get()
PluginManager:BindCommand("/explode", "derpyplugin.explode", Explode, " ~ Explode a player");
- cPluginManager.AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup)
+ cPluginManager:AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup)
LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
return true
diff --git a/MCServer/Plugins/APIDump/main_APIDump.lua b/MCServer/Plugins/APIDump/main_APIDump.lua
index b3a95eb22..bd509dcb6 100644
--- a/MCServer/Plugins/APIDump/main_APIDump.lua
+++ b/MCServer/Plugins/APIDump/main_APIDump.lua
@@ -1177,7 +1177,7 @@ function WriteHtmlHook(a_Hook, a_HookNav)
f:write("</table>\n<p>" .. (a_Hook.Returns or "") .. "</p>\n\n");
f:write([[<hr /><h1>Code examples</h1><h2>Registering the callback</h2>]]);
f:write("<pre class=\"prettyprint lang-lua\">\n");
- f:write([[cPluginManager.AddHook(cPluginManager.]] .. a_Hook.Name .. ", My" .. a_Hook.DefaultFnName .. [[);]]);
+ f:write([[cPluginManager:AddHook(cPluginManager.]] .. a_Hook.Name .. ", My" .. a_Hook.DefaultFnName .. [[);]]);
f:write("</pre>\n\n");
local Examples = a_Hook.CodeExamples or {};
for i, example in ipairs(Examples) do
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 8f2fa3682..c769edc3e 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -963,3 +963,22 @@ end
+
+-- Test the hook adding formats in #121 and #401
+local function DoNothing()
+end
+
+LOG("Trying cPluginManager:AddHook()");
+cPluginManager:AddHook(cPluginManager.HOOK_CHAT, DoNothing);
+
+LOG("Trying cPluginManager.AddHook()");
+cPluginManager.AddHook(cPluginManager.HOOK_CHAT, DoNothing);
+
+LOG("Trying cPluginManager:Get():AddHook()");
+cPluginManager:Get():AddHook(cPluginManager.HOOK_CHAT, DoNothing);
+
+LOG("Trying cPluginManager:Get():AddHook(Plugin, Hook)");
+cPluginManager:Get():AddHook(cPluginManager:GetCurrentPlugin(), cPluginManager.HOOK_CHAT);
+
+LOG("Trying cPluginManager.AddHook(Plugin, Hook)");
+cPluginManager.AddHook(cPluginManager:GetCurrentPlugin(), cPluginManager.HOOK_CHAT);
diff --git a/MCServer/Plugins/InfoDump.deproj b/MCServer/Plugins/InfoDump.deproj
new file mode 100644
index 000000000..30003c36d
--- /dev/null
+++ b/MCServer/Plugins/InfoDump.deproj
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project>
+ <file>
+ <filename>InfoDump.lua</filename>
+ </file>
+</project>
diff --git a/MCServer/Plugins/InfoDump.lua b/MCServer/Plugins/InfoDump.lua
new file mode 100644
index 000000000..df47d566b
--- /dev/null
+++ b/MCServer/Plugins/InfoDump.lua
@@ -0,0 +1,361 @@
+#!/usr/bin/lua
+
+-- InfoDump.lua
+
+-- Goes through all subfolders, loads Info.lua and dumps its g_PluginInfo into various text formats
+-- This is used for generating plugin documentation for the forum and for GitHub's INFO.md files
+
+-- This script requires LuaRocks with LFS installed, instructions are printed when this is not present.
+
+
+
+
+
+-- Check Lua version. We use 5.1-specific construct when loading the plugin info, 5.2 is not compatible!
+if (_VERSION ~= "Lua 5.1") then
+ print("Unsupported Lua version. This script requires Lua version 5.1, this Lua is version " .. (_VERSION or "<nil>"));
+ return;
+end
+
+-- Try to load lfs, do not abort if not found
+local lfs, err = pcall(
+ function()
+ return require("lfs")
+ end
+);
+
+-- Rather, print a nice message with instructions:
+if not(lfs) then
+ print([[
+Cannot load LuaFileSystem
+Install it through luarocks by executing the following command:
+ sudo luarocks install luafilesystem
+
+If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
+ sudo apt-get install luarocks
+On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
+]]);
+
+ print("Original error text: ", err);
+ return;
+end
+
+-- We now know that LFS is present, get it normally:
+lfs = require("lfs");
+
+
+
+
+
+
+--- Replaces generic formatting with forum-specific formatting
+-- Also removes the single line-ends
+local function ForumizeString(a_Str)
+ assert(type(a_Str) == "string");
+
+ -- Remove the indentation, unless in the code tag:
+ -- Only one code or /code tag per line is supported!
+ local IsInCode = false;
+ local function RemoveIndentIfNotInCode(s)
+ if (IsInCode) then
+ -- we're in code section, check if this line terminates it
+ IsInCode = (s:find("{%%/code}") ~= nil);
+ return s .. "\n";
+ else
+ -- we're not in code section, check if this line starts it
+ IsInCode = (s:find("{%%code}") ~= nil);
+ return s:gsub("^%s*", "") .. "\n";
+ end
+ end
+ a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode);
+
+ -- Replace multiple line ends with {%p} and single line ends with a space,
+ -- so that manual word-wrap in the Info.lua file doesn't wrap in the forum.
+ a_Str = a_Str:gsub("\n\n", "{%%p}");
+ a_Str = a_Str:gsub("\n", " ");
+
+ -- Replace the generic formatting:
+ a_Str = a_Str:gsub("{%%p}", "\n\n");
+ a_Str = a_Str:gsub("{%%b}", "[b]"):gsub("{%%/b}", "[/b]");
+ a_Str = a_Str:gsub("{%%i}", "[i]"):gsub("{%%/i}", "[/i]");
+ a_Str = a_Str:gsub("{%%list}", "[list]"):gsub("{%%/list}", "[/list]");
+ a_Str = a_Str:gsub("{%%li}", "[*]"):gsub("{%%/li}", "");
+ -- TODO: Other formatting
+
+ return a_Str;
+end
+
+
+
+
+
+--- Builds an array of categories, each containing all the commands belonging to the category,
+-- and the category description, if available.
+-- Returns the array table, each item has the following format:
+-- { Name = "CategoryName", Description = "CategoryDescription", Commands = {{CommandString = "/cmd verb", Info = {...}}, ...}}
+local function BuildCategories(a_PluginInfo)
+ -- The returned result
+ -- This will contain both an array and a dict of the categories, to allow fast search
+ local res = {};
+
+ -- For each command add a reference to it into all of its categories:
+ local function AddCommands(a_CmdPrefix, a_Commands)
+ for cmd, info in pairs(a_Commands) do
+ local NewCmd =
+ {
+ CommandString = a_CmdPrefix .. cmd,
+ Info = info,
+ }
+
+ if ((info.HelpString ~= nil) and (info.HelpString ~= "")) then
+ -- Add to each specified category:
+ local Category = info.Category;
+ if (type(Category) == "string") then
+ Category = {Category};
+ end
+ for idx, cat in ipairs(Category or {""}) do
+ local CatEntry = res[cat];
+ if (CatEntry == nil) then
+ -- First time we came across this category, create it:
+ local NewCat = {Name = cat, Description = "", Commands = {NewCmd}};
+ table.insert(res, NewCat);
+ res[cat] = NewCat;
+ else
+ -- We already have this category, just add the command to its list of commands:
+ table.insert(CatEntry.Commands, NewCmd);
+ end
+ end -- for idx, cat - Category[]
+ end -- if (HelpString valid)
+
+ -- Recurse all subcommands:
+ if (info.Subcommands ~= nil) then
+ AddCommands(a_CmdPrefix .. cmd .. " ", info.Subcommands);
+ end
+ end -- for cmd, info - a_Commands[]
+ end -- AddCommands()
+
+ AddCommands("", a_PluginInfo.Commands);
+
+ -- Assign descriptions to categories:
+ for name, desc in pairs(a_PluginInfo.Categories or {}) do
+ local CatEntry = res[name];
+ if (CatEntry ~= nil) then
+ -- The result has this category, add the description:
+ CatEntry.Description = desc.Description;
+ end
+ end
+
+ -- Alpha-sort each category's command list:
+ for idx, cat in ipairs(res) do
+ table.sort(cat.Commands,
+ function (cmd1, cmd2)
+ return (string.lower(cmd1.CommandString) < string.lower(cmd2.CommandString));
+ end
+ );
+ end
+
+ return res;
+end
+
+
+
+
+
+--- Writes the specified command detailed help array to the output file, in the forum dump format
+local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCombinations, f)
+ assert(type(a_CmdString) == "string");
+ assert(type(a_ParameterCombinations) == "table");
+ assert(f ~= nil);
+
+ if (#a_ParameterCombinations == 0) then
+ -- No explicit parameter combinations to write
+ return;
+ end
+
+ f:write("The following parameter combinations are recognized:\n");
+ for idx, combination in ipairs(a_ParameterCombinations) do
+ f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params, "[/color]");
+ if (combination.Help ~= nil) then
+ f:write(" - ", ForumizeString(combination.Help));
+ end
+ if (combination.Permission ~= nil) then
+ f:write(" (Requires permission '[color=red]", combination.Permission, "[/color]')");
+ end
+ f:write("\n");
+ end
+end
+
+
+
+
+
+--- Writes all commands in the specified category to the output file, in the forum dump format
+local function WriteCommandsCategoryForum(a_Category, f)
+ -- Write category name:
+ local CategoryName = a_Category.Name;
+ if (CategoryName == "") then
+ CategoryName = "General";
+ end
+ f:write("\n[size=Large]", ForumizeString(a_Category.DisplayName or CategoryName), "[/size]\n");
+
+ -- Write description:
+ if (a_Category.Description ~= "") then
+ f:write(ForumizeString(a_Category.Description), "\n");
+ end
+
+ -- Write commands:
+ f:write("\n[list]");
+ for idx2, cmd in ipairs(a_Category.Commands) do
+ f:write("\n[b]", cmd.CommandString, "[/b] - ", ForumizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n");
+ if (cmd.Info.Permission ~= nil) then
+ f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n");
+ end
+ if (cmd.Info.DetailedDescription ~= nil) then
+ f:write(cmd.Info.DetailedDescription);
+ end
+ if (cmd.Info.ParameterCombinations ~= nil) then
+ WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f);
+ end
+ end
+ f:write("[/list]\n\n")
+end
+
+
+
+
+
+local function DumpCommandsForum(a_PluginInfo, f)
+ -- Copy all Categories from a dictionary into an array:
+ local Categories = BuildCategories(a_PluginInfo);
+
+ -- Sort the categories by name:
+ table.sort(Categories,
+ function(cat1, cat2)
+ return (string.lower(cat1.Name) < string.lower(cat2.Name));
+ end
+ );
+
+ if (#Categories == 0) then
+ return;
+ end
+
+ f:write("\n[size=X-Large]Commands[/size]\n");
+
+ -- Dump per-category commands:
+ for idx, cat in ipairs(Categories) do
+ WriteCommandsCategoryForum(cat, f);
+ end
+end
+
+
+
+
+
+local function DumpAdditionalInfoForum(a_PluginInfo, f)
+ local AInfo = a_PluginInfo.AdditionalInfo;
+ if ((AInfo == nil) or (type(AInfo) ~= "table")) then
+ -- There is no AdditionalInfo in a_PluginInfo
+ return;
+ end
+
+ for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do
+ if ((info.Title ~= nil) and (info.Contents ~= nil)) then
+ f:write("\n[size=X-Large]", ForumizeString(info.Title), "[/size]\n");
+ f:write(ForumizeString(info.Contents), "\n");
+ end
+ end
+end
+
+
+
+
+
+local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
+ -- Open the output file:
+ local f, msg = io.open(a_PluginInfo.Name .. "_forum.txt", "w");
+ if (f == nil) then
+ print("\tCannot dump forum info for plugin " .. a_PluginFolder .. ": " .. msg);
+ return;
+ end
+
+ -- Write the description:
+ f:write(ForumizeString(a_PluginInfo.Description), "\n");
+ DumpAdditionalInfoForum(a_PluginInfo, f);
+ DumpCommandsForum(a_PluginInfo, f);
+
+ f:close();
+end
+
+
+
+
+
+local function DumpPluginInfoGitHub()
+ -- TODO
+end
+
+
+
+
+
+--- Tries to load the g_PluginInfo from the plugin's Info.lua file
+-- Returns the g_PluginInfo table on success, or nil and error message on failure
+local function LoadPluginInfo(a_FolderName)
+ -- Check if the Info file is present at all:
+ local Attribs = lfs.attributes(a_FolderName .. "/Info.lua");
+ if ((Attribs == nil) or (Attribs.mode ~= "file")) then
+ return nil;
+ end
+
+ -- Load and compile the Info file:
+ local cfg, err = loadfile(a_FolderName .. "/Info.lua");
+ if (cfg == nil) then
+ return nil, "Cannot open 'Info.lua': " .. err;
+ end
+
+ -- Execute the loaded file in a sandbox:
+ -- This is Lua-5.1-specific and won't work in Lua 5.2!
+ local Sandbox = {};
+ setfenv(cfg, Sandbox);
+ cfg();
+ if (Sandbox.g_PluginInfo == nil) then
+ return nil, "Info.lua doesn't contain the g_PluginInfo declaration";
+ end
+ return Sandbox.g_PluginInfo;
+end
+
+
+
+
+
+local function ProcessPluginFolder(a_FolderName)
+ local PluginInfo, Msg = LoadPluginInfo(a_FolderName);
+ if (PluginInfo == nil) then
+ if (Msg ~= nil) then
+ print("\tCannot load Info.lua: " .. Msg);
+ end
+ return;
+ end
+ DumpPluginInfoForum(a_FolderName, PluginInfo);
+end
+
+
+
+
+
+print("Processing plugin subfolders:");
+for fnam in lfs.dir(".") do
+ if ((fnam ~= ".") and (fnam ~= "..")) then
+ local Attributes = lfs.attributes(fnam);
+ if (Attributes ~= nil) then
+ if (Attributes.mode == "directory") then
+ print(fnam);
+ ProcessPluginFolder(fnam);
+ end
+ end
+ end
+end
+
+
+
+