Merge pull request #1875 from mc-server/PluginFolders
Split the plugin names and plugin folders to avoid confusing them.
This commit is contained in:
commit
ba6f5aea4c
@ -1917,157 +1917,6 @@ a_Player:OpenWindow(Window);
|
|||||||
Inherits = "cPawn",
|
Inherits = "cPawn",
|
||||||
}, -- cPlayer
|
}, -- cPlayer
|
||||||
|
|
||||||
cPlugin =
|
|
||||||
{
|
|
||||||
Desc = [[cPlugin describes a Lua plugin. This page is dedicated to new-style plugins and contain their functions. Each plugin has its own Plugin object.
|
|
||||||
]],
|
|
||||||
Functions =
|
|
||||||
{
|
|
||||||
Call = { Params = "Function name, [All the parameters divided with commas]", Notes = "(<b>OBSOLETE</b>) This function allows you to call a function from another plugin. It can only use pass: integers, booleans, strings and usertypes (cPlayer, cEntity, cCuboid, etc.).<br /><br /><b>This function is obsolete and unsafe, use {{cPluginManager}}:CallPlugin() instead!</b>" },
|
|
||||||
GetDirectory = { Return = "string", Notes = "Returns the name of the folder where the plugin's files are. (APIDump)" },
|
|
||||||
GetLocalDirectory = { Notes = "OBSOLETE use GetLocalFolder instead." },
|
|
||||||
GetLocalFolder = { Return = "string", Notes = "Returns the path where the plugin's files are. (Plugins/APIDump)" },
|
|
||||||
GetName = { Return = "string", Notes = "Returns the name of the plugin." },
|
|
||||||
SetName = { Params = "string", Notes = "Sets the name of the Plugin." },
|
|
||||||
GetVersion = { Return = "number", Notes = "Returns the version of the plugin." },
|
|
||||||
SetVersion = { Params = "number", Notes = "Sets the version of the plugin." },
|
|
||||||
GetFileName = { Return = "string" },
|
|
||||||
CreateWebPlugin = { Notes = "{{cWebPlugin|cWebPlugin}}" },
|
|
||||||
},
|
|
||||||
}, -- cPlugin
|
|
||||||
|
|
||||||
cPluginLua =
|
|
||||||
{
|
|
||||||
Desc = "",
|
|
||||||
Functions = {},
|
|
||||||
Inherits = "cPlugin",
|
|
||||||
}, -- cPluginLua
|
|
||||||
|
|
||||||
cPluginManager =
|
|
||||||
{
|
|
||||||
Desc = [[
|
|
||||||
This class is used for generic plugin-related functionality. The plugin manager has a list of all
|
|
||||||
plugins, can enable or disable plugins, manages hooks and in-game console commands.</p>
|
|
||||||
<p>
|
|
||||||
There is one instance of cPluginManager in MCServer, to get it, call either
|
|
||||||
{{cRoot|cRoot}}:Get():GetPluginManager() or cPluginManager:Get() function.</p>
|
|
||||||
<p>
|
|
||||||
Note that some functions are "static", that means that they are called using a dot operator instead
|
|
||||||
of the colon operator. For example:
|
|
||||||
<pre class="prettyprint lang-lua">
|
|
||||||
cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
|
|
||||||
</pre></p>
|
|
||||||
]],
|
|
||||||
Functions =
|
|
||||||
{
|
|
||||||
AddHook =
|
|
||||||
{
|
|
||||||
{ Params = "HookType, [HookFunction]", Return = "", Notes = "(STATIC) Informs the plugin manager that it should call the specified function when the specified hook event occurs. If a function is not specified, a default function name is looked up, based on the hook type" },
|
|
||||||
{ Params = "{{cPlugin|Plugin}}, HookType, [HookFunction]", Return = "", Notes = "(STATIC, <b>DEPRECATED</b>) Informs the plugin manager that it should call the specified function when the specified hook event occurs. If a function is not specified, a default function name is looked up, based on the hook type. NOTE: This format is deprecated and the server outputs a warning if it is used!" },
|
|
||||||
},
|
|
||||||
BindCommand =
|
|
||||||
{
|
|
||||||
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split, {{cPlayer|Player}})</pre> The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented)." },
|
|
||||||
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split, {{cPlayer|Player}})</pre> The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented)." },
|
|
||||||
},
|
|
||||||
BindConsoleCommand =
|
|
||||||
{
|
|
||||||
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
|
|
||||||
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
|
|
||||||
},
|
|
||||||
CallPlugin = { Params = "PluginName, FunctionName, [FunctionArgs...]", Return = "[FunctionRets]", Notes = "(STATIC) Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils and classes can be used for parameters and return values; tables and functions cannot be copied across plugins." },
|
|
||||||
DisablePlugin = { Params = "PluginName", Return = "bool", Notes = "Disables a plugin specified by its name. Returns true if the plugin was disabled, false if it wasn't found or wasn't active." },
|
|
||||||
ExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Executes the command as if given by the specified Player. Checks permissions." },
|
|
||||||
FindPlugins = { Params = "", Return = "", Notes = "Refreshes the list of plugins to include all folders inside the Plugins folder (potentially new disabled plugins)" },
|
|
||||||
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", 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 = "(STATIC) Returns the single instance of the plugin manager" },
|
|
||||||
GetAllPlugins = { Params = "", Return = "table", Notes = "Returns a table (dictionary) of all plugins, [name => value], where value is a valid {{cPlugin}} if the plugin is loaded, or the bool value false if the plugin is not loaded." },
|
|
||||||
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." },
|
|
||||||
GetNumPlugins = { Params = "", Return = "number", Notes = "Returns the number of plugins, including the disabled ones" },
|
|
||||||
GetPlugin = { Params = "PluginName", Return = "{{cPlugin}}", Notes = "(<b>DEPRECATED, UNSAFE</b>) Returns a plugin handle of the specified plugin, or nil if such plugin is not loaded. Note thatdue to multithreading the handle is not guaranteed to be safe for use when stored - a single-plugin reload may have been triggered in the mean time for the requested plugin." },
|
|
||||||
GetPluginsPath = { Params = "", Return = "string", Notes = "Returns the path where the individual plugin folders are located. Doesn't include the path separator at the end of the returned string." },
|
|
||||||
IsCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if in-game Command is already bound (by any plugin)" },
|
|
||||||
IsConsoleCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if console Command is already bound (by any plugin)" },
|
|
||||||
LoadPlugin = { Params = "PluginFolder", Return = "", Notes = "(<b>DEPRECATED</b>) Loads a plugin from the specified folder. NOTE: Loading plugins may be an unsafe operation and may result in a deadlock or a crash. This API is deprecated and might be removed." },
|
|
||||||
LogStackTrace = { Params = "", Return = "", Notes = "(STATIC) Logs a current stack trace of the Lua engine to the server console log. Same format as is used when the plugin fails." },
|
|
||||||
ReloadPlugins = { Params = "", Return = "", Notes = "Reloads all active plugins" },
|
|
||||||
},
|
|
||||||
ConstantGroups=
|
|
||||||
{
|
|
||||||
CommandResult =
|
|
||||||
{
|
|
||||||
Include = "^cr.*",
|
|
||||||
TextBefore = [[
|
|
||||||
Results that the (Force)ExecuteCommand return. This gives information if the command is executed or not and the reason.
|
|
||||||
]],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Constants =
|
|
||||||
{
|
|
||||||
crBlocked = { Notes = "When a plugin stopped the command using the OnExecuteCommand hook" },
|
|
||||||
crError = { Notes = "When the command handler for the given command results in an error" },
|
|
||||||
crExecuted = { Notes = "When the command is successfully executed." },
|
|
||||||
crNoPermission = { Notes = "When the player doesn't have permission to execute the given command." },
|
|
||||||
crUnknownCommand = { Notes = "When the given command doesn't exist." },
|
|
||||||
HOOK_BLOCK_SPREAD = { Notes = "Called when a block spreads based on world conditions" },
|
|
||||||
HOOK_BLOCK_TO_PICKUPS = { Notes = "Called when a block has been dug and is being converted to pickups. The server has provided the default pickups and the plugins may modify them." },
|
|
||||||
HOOK_CHAT = { Notes = "Called when a client sends a chat message that is not a command. The plugin may modify the chat message" },
|
|
||||||
HOOK_CHUNK_AVAILABLE = { Notes = "Called when a chunk is loaded or generated and becomes available in the {{cWorld|world}}." },
|
|
||||||
HOOK_CHUNK_GENERATED = { Notes = "Called after a chunk is generated. A plugin may do last modifications on the generated chunk before it is handed of to the {{cWorld|world}}." },
|
|
||||||
HOOK_CHUNK_GENERATING = { Notes = "Called before a chunk is generated. A plugin may override some parts of the generation algorithm." },
|
|
||||||
HOOK_CHUNK_UNLOADED = { Notes = "Called after a chunk has been unloaded from a {{cWorld|world}}." },
|
|
||||||
HOOK_CHUNK_UNLOADING = { Notes = "Called before a chunk is unloaded from a {{cWorld|world}}. The chunk has already been saved." },
|
|
||||||
HOOK_COLLECTING_PICKUP = { Notes = "Called when a player is about to collect a pickup." },
|
|
||||||
HOOK_CRAFTING_NO_RECIPE = { Notes = "Called when a player has items in the crafting slots and the server cannot locate any recipe. Plugin may provide a recipe." },
|
|
||||||
HOOK_DISCONNECT = { Notes = "Called after the player has disconnected." },
|
|
||||||
HOOK_EXECUTE_COMMAND = { Notes = "Called when a client sends a chat message that is recognized as a command, before handing that command to the regular command handler. A plugin may stop the command from being handled. This hook is called even when the player doesn't have permissions for the command." },
|
|
||||||
HOOK_EXPLODED = { Notes = "Called after an explosion has been processed in a {{cWorld|world}}." },
|
|
||||||
HOOK_EXPLODING = { Notes = "Called before an explosion is processed in a {{cWorld|world}}. A plugin may alter the explosion parameters or cancel the explosion altogether." },
|
|
||||||
HOOK_HANDSHAKE = { Notes = "Called when a Handshake packet is received from a client." },
|
|
||||||
HOOK_HOPPER_PULLING_ITEM = { Notes = "Called when a hopper is pulling an item from the container above it." },
|
|
||||||
HOOK_HOPPER_PUSHING_ITEM = { Notes = "Called when a hopper is pushing an item into the container it is aimed at." },
|
|
||||||
HOOK_KILLING = { Notes = "Called when an entity has just been killed. A plugin may resurrect the entity by setting its health to above zero." },
|
|
||||||
HOOK_LOGIN = { Notes = "Called when a Login packet is sent to the client, before the client is queued for authentication." },
|
|
||||||
HOOK_PLAYER_ANIMATION = { Notes = "Called when a client send the Animation packet." },
|
|
||||||
HOOK_PLAYER_BREAKING_BLOCK = { Notes = "Called when a player is about to break a block. A plugin may cancel the event." },
|
|
||||||
HOOK_PLAYER_BROKEN_BLOCK = { Notes = "Called after a player has broken a block." },
|
|
||||||
HOOK_PLAYER_EATING = { Notes = "Called when the player starts eating a held item. Plugins may abort the eating." },
|
|
||||||
HOOK_PLAYER_FISHED = { Notes = "Called when the player reels the fishing rod back in, after the server decides the player's fishing reward." },
|
|
||||||
HOOK_PLAYER_FISHING = { Notes = "Called when the player reels the fishing rod back in, plugins may alter the fishing reward." },
|
|
||||||
HOOK_PLAYER_JOINED = { Notes = "Called when the player entity has been created. It has not yet been fully initialized." },
|
|
||||||
HOOK_PLAYER_LEFT_CLICK = { Notes = "Called when the client sends the LeftClick packet." },
|
|
||||||
HOOK_PLAYER_MOVING = { Notes = "Called when the player has moved and the movement is now being applied." },
|
|
||||||
HOOK_PLAYER_PLACED_BLOCK = { Notes = "Called when the player has just placed a block" },
|
|
||||||
HOOK_PLAYER_PLACING_BLOCK = { Notes = "Called when the player is about to place a block. A plugin may cancel the event." },
|
|
||||||
HOOK_PLAYER_RIGHT_CLICK = { Notes = "Called when the client sends the RightClick packet." },
|
|
||||||
HOOK_PLAYER_RIGHT_CLICKING_ENTITY = { Notes = "Called when the client sends the UseEntity packet." },
|
|
||||||
HOOK_PLAYER_SHOOTING = { Notes = "Called when the player releases the mouse button to fire their bow." },
|
|
||||||
HOOK_PLAYER_SPAWNED = { Notes = "Called after the player entity has been created. The entity is fully initialized and is spawning in the {{cWorld|world}}." },
|
|
||||||
HOOK_PLAYER_TOSSING_ITEM = { Notes = "Called when the player is tossing the held item (keypress Q)" },
|
|
||||||
HOOK_PLAYER_USED_BLOCK = { Notes = "Called after the player has right-clicked a block" },
|
|
||||||
HOOK_PLAYER_USED_ITEM = { Notes = "Called after the player has right-clicked with a usable item in their hand." },
|
|
||||||
HOOK_PLAYER_USING_BLOCK = { Notes = "Called when the player is about to use (right-click) a block" },
|
|
||||||
HOOK_PLAYER_USING_ITEM = { Notes = "Called when the player is about to right-click with a usable item in their hand." },
|
|
||||||
HOOK_POST_CRAFTING = { Notes = "Called after a valid recipe has been chosen for the current contents of the crafting grid. Plugins may modify the recipe." },
|
|
||||||
HOOK_PRE_CRAFTING = { Notes = "Called before a recipe is searched for the current contents of the crafting grid. Plugins may provide a recipe and cancel the built-in search." },
|
|
||||||
HOOK_SERVER_PING = { Notes = "Called when a client pings the server from the server list. Plugins may change the favicon, server description, players online and maximum players values." },
|
|
||||||
HOOK_SPAWNED_ENTITY = { Notes = "Called after an entity is spawned in a {{cWorld|world}}. The entity is already part of the world." },
|
|
||||||
HOOK_SPAWNED_MONSTER = { Notes = "Called after a mob is spawned in a {{cWorld|world}}. The mob is already part of the world." },
|
|
||||||
HOOK_SPAWNING_ENTITY = { Notes = "Called just before an entity is spawned in a {{cWorld|world}}." },
|
|
||||||
HOOK_SPAWNING_MONSTER = { Notes = "Called just before a mob is spawned in a {{cWorld|world}}." },
|
|
||||||
HOOK_TAKE_DAMAGE = { Notes = "Called when an entity is taking any kind of damage. Plugins may modify the damage value, effects, source or cancel the damage." },
|
|
||||||
HOOK_TICK = { Notes = "Called when the main server thread ticks - 20 times a second." },
|
|
||||||
HOOK_UPDATED_SIGN = { Notes = "Called after a {{cSignEntity|sign}} text has been updated, either by a player or by any external means." },
|
|
||||||
HOOK_UPDATING_SIGN = { Notes = "Called before a {{cSignEntity|sign}} text is updated, either by a player or by any external means." },
|
|
||||||
HOOK_WEATHER_CHANGED = { Notes = "Called after the weather has changed." },
|
|
||||||
HOOK_WEATHER_CHANGING = { Notes = "Called just before the weather changes" },
|
|
||||||
HOOK_WORLD_TICK = { Notes = "Called in each world's tick thread when the game logic is about to tick (20 times a second)." },
|
|
||||||
},
|
|
||||||
}, -- cPluginManager
|
|
||||||
|
|
||||||
cRankManager =
|
cRankManager =
|
||||||
{
|
{
|
||||||
Desc = [[
|
Desc = [[
|
||||||
|
205
MCServer/Plugins/APIDump/Classes/Plugins.lua
Normal file
205
MCServer/Plugins/APIDump/Classes/Plugins.lua
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
return
|
||||||
|
{
|
||||||
|
cPlugin =
|
||||||
|
{
|
||||||
|
Desc = [[cPlugin describes a Lua plugin. This page is dedicated to new-style plugins and contain their functions. Each plugin has its own Plugin object.
|
||||||
|
]],
|
||||||
|
Functions =
|
||||||
|
{
|
||||||
|
GetDirectory = { Return = "string", Notes = "<b>OBSOLETE</b>, use GetFolderName() instead!" },
|
||||||
|
GetFolderName = { Params = "", Return = "string", Notes = "Returns the name of the folder where the plugin's files are. (APIDump)" },
|
||||||
|
GetLoadError = { Params = "", Return = "string", Notes = "If the plugin failed to load, returns the error message for the failure." },
|
||||||
|
GetLocalDirectory = { Notes = "<b>OBSOLETE</b>, use GetLocalFolder instead." },
|
||||||
|
GetLocalFolder = { Return = "string", Notes = "Returns the path where the plugin's files are. (Plugins/APIDump)" },
|
||||||
|
GetName = { Return = "string", Notes = "Returns the name of the plugin." },
|
||||||
|
GetStatus = { Params = "", Return = "{{cPluginManager#PluginStatus|PluginStatus}}", Notes = "Returns the status of the plugin (loaded, disabled, unloaded, error, not found)" },
|
||||||
|
GetVersion = { Return = "number", Notes = "Returns the version of the plugin." },
|
||||||
|
IsLoaded = { Params = "", Return = "", Notes = "" },
|
||||||
|
SetName = { Params = "string", Notes = "Sets the name of the Plugin." },
|
||||||
|
SetVersion = { Params = "number", Notes = "Sets the version of the plugin." },
|
||||||
|
},
|
||||||
|
}, -- cPlugin
|
||||||
|
|
||||||
|
cPluginLua =
|
||||||
|
{
|
||||||
|
Desc = "",
|
||||||
|
Functions =
|
||||||
|
{
|
||||||
|
AddWebTab = { Params = "", Return = "", Notes = "Adds a new webadmin tab" },
|
||||||
|
},
|
||||||
|
Inherits = "cPlugin",
|
||||||
|
}, -- cPluginLua
|
||||||
|
|
||||||
|
cPluginManager =
|
||||||
|
{
|
||||||
|
Desc = [[
|
||||||
|
This class is used for generic plugin-related functionality. The plugin manager has a list of all
|
||||||
|
plugins, can enable or disable plugins, manages hooks and in-game console commands.</p>
|
||||||
|
<p>
|
||||||
|
Plugins can be identified by either the PluginFolder or PluginName. Note that these two can differ,
|
||||||
|
refer to <a href="http://forum.mc-server.org/showthread.php?tid=1877">the forum</a> for detailed discussion.
|
||||||
|
<p>
|
||||||
|
There is one instance of cPluginManager in MCServer, to get it, call either
|
||||||
|
{{cRoot|cRoot}}:Get():GetPluginManager() or cPluginManager:Get() function.</p>
|
||||||
|
<p>
|
||||||
|
Note that some functions are "static", that means that they are called using a dot operator instead
|
||||||
|
of the colon operator. For example:
|
||||||
|
<pre class="prettyprint lang-lua">
|
||||||
|
cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
|
||||||
|
</pre></p>
|
||||||
|
]],
|
||||||
|
Functions =
|
||||||
|
{
|
||||||
|
AddHook =
|
||||||
|
{
|
||||||
|
{ Params = "{{cPluginManager#Hooks|HookType}}, [HookFunction]", Return = "", Notes = "(STATIC) Informs the plugin manager that it should call the specified function when the specified hook event occurs. If a function is not specified, a default global function name is looked up, based on the hook type" },
|
||||||
|
{ Params = "{{cPlugin|Plugin}}, {{cPluginManager#Hooks|HookType}}, [HookFunction]", Return = "", Notes = "(STATIC, <b>DEPRECATED</b>) Informs the plugin manager that it should call the specified function when the specified hook event occurs. If a function is not specified, a default function name is looked up, based on the hook type. NOTE: This format is deprecated and the server outputs a warning if it is used!" },
|
||||||
|
},
|
||||||
|
BindCommand =
|
||||||
|
{
|
||||||
|
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split, {{cPlayer|Player}})</pre> The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented)." },
|
||||||
|
{ Params = "Command, Permission, Callback, HelpString", Return = "[bool]", Notes = "Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split, {{cPlayer|Player}})</pre> The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented)." },
|
||||||
|
},
|
||||||
|
BindConsoleCommand =
|
||||||
|
{
|
||||||
|
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "(STATIC) Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
|
||||||
|
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
|
||||||
|
},
|
||||||
|
CallPlugin = { Params = "PluginName, FunctionName, [FunctionArgs...]", Return = "[FunctionRets]", Notes = "(STATIC) Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils and classes can be used for parameters and return values; tables and functions cannot be copied across plugins." },
|
||||||
|
ExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Executes the command as if given by the specified Player. Checks permissions." },
|
||||||
|
FindPlugins = { Params = "", Return = "", Notes = "<b>OBSOLETE</b>, use RefreshPluginList() instead"},
|
||||||
|
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", 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." },
|
||||||
|
ForEachPlugin = { 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 ({{cPlugin|Plugin}})</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 = "(STATIC) Returns the single instance of the plugin manager" },
|
||||||
|
GetAllPlugins = { Params = "", Return = "table", Notes = "Returns a table (dictionary) of all plugins, [name => value], where value is a valid {{cPlugin}} if the plugin is loaded, or the bool value false if the plugin is not loaded." },
|
||||||
|
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." },
|
||||||
|
GetNumLoadedPlugins = { Params = "", Return = "number", Notes = "Returns the number of loaded plugins (psLoaded only)" },
|
||||||
|
GetNumPlugins = { Params = "", Return = "number", Notes = "Returns the number of plugins, including the disabled, errored, unloaded and not-found ones" },
|
||||||
|
GetPlugin = { Params = "PluginName", Return = "{{cPlugin}}", Notes = "(<b>DEPRECATED, UNSAFE</b>) Returns a plugin handle of the specified plugin, or nil if such plugin is not loaded. Note thatdue to multithreading the handle is not guaranteed to be safe for use when stored - a single-plugin reload may have been triggered in the mean time for the requested plugin." },
|
||||||
|
GetPluginsPath = { Params = "", Return = "string", Notes = "Returns the path where the individual plugin folders are located. Doesn't include the path separator at the end of the returned string." },
|
||||||
|
IsCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if in-game Command is already bound (by any plugin)" },
|
||||||
|
IsConsoleCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if console Command is already bound (by any plugin)" },
|
||||||
|
IsPluginLoaded = { Params = "PluginName", Return = "", Notes = "Returns true if the specified plugin is loaded." },
|
||||||
|
LoadPlugin = { Params = "PluginFolder", Return = "", Notes = "(<b>DEPRECATED</b>) Loads a plugin from the specified folder. NOTE: Loading plugins may be an unsafe operation and may result in a deadlock or a crash. This API is deprecated and might be removed." },
|
||||||
|
LogStackTrace = { Params = "", Return = "", Notes = "(STATIC) Logs a current stack trace of the Lua engine to the server console log. Same format as is used when the plugin fails." },
|
||||||
|
RefreshPluginList = { Params = "", Return = "", Notes = "Refreshes the list of plugins to include all folders inside the Plugins folder (potentially new disabled plugins)" },
|
||||||
|
ReloadPlugins = { Params = "", Return = "", Notes = "Reloads all active plugins" },
|
||||||
|
UnloadPlugin = { Params = "PluginName", Return = "", Notes = "Queues the specified plugin to be unloaded. To avoid deadlocks, the unloading happens in the main tick thread asynchronously." },
|
||||||
|
},
|
||||||
|
ConstantGroups=
|
||||||
|
{
|
||||||
|
CommandResult =
|
||||||
|
{
|
||||||
|
Include = "^cr.*",
|
||||||
|
TextBefore = [[
|
||||||
|
Results that the (Force)ExecuteCommand return. This gives information if the command is executed or not and the reason.
|
||||||
|
]],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Constants =
|
||||||
|
{
|
||||||
|
crBlocked = { Notes = "When a plugin stopped the command using the OnExecuteCommand hook" },
|
||||||
|
crError = { Notes = "When the command handler for the given command results in an error" },
|
||||||
|
crExecuted = { Notes = "When the command is successfully executed." },
|
||||||
|
crNoPermission = { Notes = "When the player doesn't have permission to execute the given command." },
|
||||||
|
crUnknownCommand = { Notes = "When the given command doesn't exist." },
|
||||||
|
HOOK_BLOCK_SPREAD = { Notes = "Called when a block spreads based on world conditions" },
|
||||||
|
HOOK_BLOCK_TO_PICKUPS = { Notes = "Called when a block has been dug and is being converted to pickups. The server has provided the default pickups and the plugins may modify them." },
|
||||||
|
HOOK_CHAT = { Notes = "Called when a client sends a chat message that is not a command. The plugin may modify the chat message" },
|
||||||
|
HOOK_CHUNK_AVAILABLE = { Notes = "Called when a chunk is loaded or generated and becomes available in the {{cWorld|world}}." },
|
||||||
|
HOOK_CHUNK_GENERATED = { Notes = "Called after a chunk is generated. A plugin may do last modifications on the generated chunk before it is handed of to the {{cWorld|world}}." },
|
||||||
|
HOOK_CHUNK_GENERATING = { Notes = "Called before a chunk is generated. A plugin may override some parts of the generation algorithm." },
|
||||||
|
HOOK_CHUNK_UNLOADED = { Notes = "Called after a chunk has been unloaded from a {{cWorld|world}}." },
|
||||||
|
HOOK_CHUNK_UNLOADING = { Notes = "Called before a chunk is unloaded from a {{cWorld|world}}. The chunk has already been saved." },
|
||||||
|
HOOK_COLLECTING_PICKUP = { Notes = "Called when a player is about to collect a pickup." },
|
||||||
|
HOOK_CRAFTING_NO_RECIPE = { Notes = "Called when a player has items in the crafting slots and the server cannot locate any recipe. Plugin may provide a recipe." },
|
||||||
|
HOOK_DISCONNECT = { Notes = "Called after the player has disconnected." },
|
||||||
|
HOOK_ENTITY_ADD_EFFECT = { Notes = "Called when an effect is being added to an {{cEntity|entity}}. Plugin may refuse the effect." },
|
||||||
|
HOOK_ENTITY_TELEPORT = { Notes = "Called when an {{cEntity|entity}} is being teleported. Plugin may refuse the teleportation." },
|
||||||
|
HOOK_EXECUTE_COMMAND = { Notes = "Called when a client sends a chat message that is recognized as a command, before handing that command to the regular command handler. A plugin may stop the command from being handled. This hook is called even when the player doesn't have permissions for the command." },
|
||||||
|
HOOK_EXPLODED = { Notes = "Called after an explosion has been processed in a {{cWorld|world}}." },
|
||||||
|
HOOK_EXPLODING = { Notes = "Called before an explosion is processed in a {{cWorld|world}}. A plugin may alter the explosion parameters or cancel the explosion altogether." },
|
||||||
|
HOOK_HANDSHAKE = { Notes = "Called when a Handshake packet is received from a client." },
|
||||||
|
HOOK_HOPPER_PULLING_ITEM = { Notes = "Called when a hopper is pulling an item from the container above it." },
|
||||||
|
HOOK_HOPPER_PUSHING_ITEM = { Notes = "Called when a hopper is pushing an item into the container it is aimed at." },
|
||||||
|
HOOK_KILLING = { Notes = "Called when an entity has just been killed. A plugin may resurrect the entity by setting its health to above zero." },
|
||||||
|
HOOK_LOGIN = { Notes = "Called when a Login packet is sent to the client, before the client is queued for authentication." },
|
||||||
|
HOOK_PLAYER_ANIMATION = { Notes = "Called when a client send the Animation packet." },
|
||||||
|
HOOK_PLAYER_BREAKING_BLOCK = { Notes = "Called when a player is about to break a block. A plugin may cancel the event." },
|
||||||
|
HOOK_PLAYER_BROKEN_BLOCK = { Notes = "Called after a player has broken a block." },
|
||||||
|
HOOK_PLAYER_DESTROYED = { Notes = "Called when the {{cPlayer}} object is destroyed - a player has disconnected." },
|
||||||
|
HOOK_PLAYER_EATING = { Notes = "Called when the player starts eating a held item. Plugins may abort the eating." },
|
||||||
|
HOOK_PLAYER_FISHED = { Notes = "Called when the player reels the fishing rod back in, after the server decides the player's fishing reward." },
|
||||||
|
HOOK_PLAYER_FISHING = { Notes = "Called when the player reels the fishing rod back in, plugins may alter the fishing reward." },
|
||||||
|
HOOK_PLAYER_FOOD_LEVEL_CHANGE = { Notes = "Called when the player's food level is changing. Plugins may refuse the change." },
|
||||||
|
HOOK_PLAYER_JOINED = { Notes = "Called when the player entity has been created. It has not yet been fully initialized." },
|
||||||
|
HOOK_PLAYER_LEFT_CLICK = { Notes = "Called when the client sends the LeftClick packet." },
|
||||||
|
HOOK_PLAYER_MOVING = { Notes = "Called when the player has moved and the movement is now being applied." },
|
||||||
|
HOOK_PLAYER_PLACED_BLOCK = { Notes = "Called when the player has just placed a block" },
|
||||||
|
HOOK_PLAYER_PLACING_BLOCK = { Notes = "Called when the player is about to place a block. A plugin may cancel the event." },
|
||||||
|
HOOK_PLAYER_RIGHT_CLICK = { Notes = "Called when the client sends the RightClick packet." },
|
||||||
|
HOOK_PLAYER_RIGHT_CLICKING_ENTITY = { Notes = "Called when the client sends the UseEntity packet." },
|
||||||
|
HOOK_PLAYER_SHOOTING = { Notes = "Called when the player releases the mouse button to fire their bow." },
|
||||||
|
HOOK_PLAYER_SPAWNED = { Notes = "Called after the player entity has been created. The entity is fully initialized and is spawning in the {{cWorld|world}}." },
|
||||||
|
HOOK_PLAYER_TOSSING_ITEM = { Notes = "Called when the player is tossing the held item (keypress Q)" },
|
||||||
|
HOOK_PLAYER_USED_BLOCK = { Notes = "Called after the player has right-clicked a block" },
|
||||||
|
HOOK_PLAYER_USED_ITEM = { Notes = "Called after the player has right-clicked with a usable item in their hand." },
|
||||||
|
HOOK_PLAYER_USING_BLOCK = { Notes = "Called when the player is about to use (right-click) a block" },
|
||||||
|
HOOK_PLAYER_USING_ITEM = { Notes = "Called when the player is about to right-click with a usable item in their hand." },
|
||||||
|
HOOK_PLUGINS_LOADED = { Notes = "Called after all plugins have loaded." },
|
||||||
|
HOOK_PLUGIN_MESSAGE = { Notes = "Called when a PluginMessage packet is received from a client." },
|
||||||
|
HOOK_POST_CRAFTING = { Notes = "Called after a valid recipe has been chosen for the current contents of the crafting grid. Plugins may modify the recipe." },
|
||||||
|
HOOK_PRE_CRAFTING = { Notes = "Called before a recipe is searched for the current contents of the crafting grid. Plugins may provide a recipe and cancel the built-in search." },
|
||||||
|
HOOK_PROJECTILE_HIT_BLOCK = { Notes = "Called when a {{cProjectileEntity|projectile}} hits a block." },
|
||||||
|
HOOK_PROJECTILE_HIT_ENTITY = { Notes = "Called when a {{cProjectileEntity|projectile}} hits an {{cEntity|entity}}." },
|
||||||
|
HOOK_SERVER_PING = { Notes = "Called when a client pings the server from the server list. Plugins may change the favicon, server description, players online and maximum players values." },
|
||||||
|
HOOK_SPAWNED_ENTITY = { Notes = "Called after an entity is spawned in a {{cWorld|world}}. The entity is already part of the world." },
|
||||||
|
HOOK_SPAWNED_MONSTER = { Notes = "Called after a mob is spawned in a {{cWorld|world}}. The mob is already part of the world." },
|
||||||
|
HOOK_SPAWNING_ENTITY = { Notes = "Called just before an entity is spawned in a {{cWorld|world}}." },
|
||||||
|
HOOK_SPAWNING_MONSTER = { Notes = "Called just before a mob is spawned in a {{cWorld|world}}." },
|
||||||
|
HOOK_TAKE_DAMAGE = { Notes = "Called when an entity is taking any kind of damage. Plugins may modify the damage value, effects, source or cancel the damage." },
|
||||||
|
HOOK_TICK = { Notes = "Called when the main server thread ticks - 20 times a second." },
|
||||||
|
HOOK_UPDATED_SIGN = { Notes = "Called after a {{cSignEntity|sign}} text has been updated, either by a player or by any external means." },
|
||||||
|
HOOK_UPDATING_SIGN = { Notes = "Called before a {{cSignEntity|sign}} text is updated, either by a player or by any external means." },
|
||||||
|
HOOK_WEATHER_CHANGED = { Notes = "Called after the weather has changed." },
|
||||||
|
HOOK_WEATHER_CHANGING = { Notes = "Called just before the weather changes" },
|
||||||
|
HOOK_WORLD_STARTED = { Notes = "Called when a world has been started." },
|
||||||
|
HOOK_WORLD_TICK = { Notes = "Called in each world's tick thread when the game logic is about to tick (20 times a second)." },
|
||||||
|
|
||||||
|
psDisabled = { Notes = "The plugin is not enabled in settings.ini" },
|
||||||
|
psError = { Notes = "The plugin is enabled in settings.ini, but it has run into an error while loading. Use {{cPlugin}}:GetLoadError() to identify the error." },
|
||||||
|
psLoaded = { Notes = "The plugin is enabled and loaded." },
|
||||||
|
psNotFound = { Notes = "The plugin has been loaded, but is no longer present on disk." },
|
||||||
|
psUnloaded = { Notes = "The plugin is enabled in settings.ini, but it has been unloaded (by a command)." },
|
||||||
|
}, -- constants
|
||||||
|
|
||||||
|
ConstantGroups =
|
||||||
|
{
|
||||||
|
Hooks =
|
||||||
|
{
|
||||||
|
Include = {"HOOK_.*"},
|
||||||
|
TextBefore = [[
|
||||||
|
These constants identify individual hooks. To register the plugin to receive notifications on hooks, use the
|
||||||
|
cPluginManager:AddHook() function. For detailed description of each hook, see the <a href='index.html#hooks'>
|
||||||
|
hooks reference</a>.]],
|
||||||
|
},
|
||||||
|
PluginStatus =
|
||||||
|
{
|
||||||
|
Include = {"ps.*"},
|
||||||
|
TextBefore = [[
|
||||||
|
These constants are used to report status of individual plugins. Use {{cPlugin}}:GetStatus() to query the
|
||||||
|
status of a plugin; use cPluginManager::ForEachPlugin() to iterate over plugins.]],
|
||||||
|
},
|
||||||
|
CommandResult =
|
||||||
|
{
|
||||||
|
Include = {"cr.*"},
|
||||||
|
TextBefore = [[
|
||||||
|
These constants are returned by the ExecuteCommand() function to identify the exact outcome of the
|
||||||
|
operation.]],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, -- cPluginManager
|
||||||
|
}
|
@ -1,375 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
<link rel="icon" href="files/favicon.ico">
|
|
||||||
<title>{TITLE}</title>
|
|
||||||
|
|
||||||
<style type="text/css" media="screen">
|
|
||||||
|
|
||||||
/* reset CSS */
|
|
||||||
|
|
||||||
html, body, div, span, applet, object, iframe,
|
|
||||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
|
||||||
a, abbr, acronym, address, big, cite, code,
|
|
||||||
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
|
||||||
small, strike, strong, sub, sup, tt, var,
|
|
||||||
b, u, i, center,
|
|
||||||
dl, dt, dd, ol, ul, li,
|
|
||||||
fieldset, form, label, legend,
|
|
||||||
table, caption, tbody, tfoot, thead, tr, th, td {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
outline: 0;
|
|
||||||
font-size: 100%;
|
|
||||||
vertical-align: baseline;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
ol, ul {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
blockquote, q {
|
|
||||||
quotes: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remember to define focus styles! */
|
|
||||||
:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove textarea resize at Safari */
|
|
||||||
textarea {
|
|
||||||
resize: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remember to highlight inserts somehow! */
|
|
||||||
ins {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
del {
|
|
||||||
text-decoration: line-through;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tables still need 'cellspacing="0"' in the markup */
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Origional from http://www.perspectived.com/
|
|
||||||
Modified by Ben Phelps
|
|
||||||
Made for FakeTruth - MCServer
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Basic ---------------------------------------- */
|
|
||||||
|
|
||||||
.clear { clear: both; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: white;
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #646464;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#wrapper {
|
|
||||||
text-align: left;
|
|
||||||
width: 930px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Logo ---------------------------------------- */
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin: 15px 0 10px 5px;
|
|
||||||
width: 180px;
|
|
||||||
height: 36px;
|
|
||||||
background: url(files/logo.png) no-repeat left top;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 a {
|
|
||||||
display: block;
|
|
||||||
width: 225px;
|
|
||||||
height: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 span { display: none; }
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #646464;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Container ---------------------------------------- */
|
|
||||||
|
|
||||||
#containerHolder {
|
|
||||||
background: #eee;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#container {
|
|
||||||
background: #fff url(files/background.gif) repeat-y left top;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
width: 918px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#connectHolder {
|
|
||||||
background: #eee;
|
|
||||||
padding: 5px;
|
|
||||||
margin-bottom:8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#connect {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background-color: #fff;
|
|
||||||
padding:5px;
|
|
||||||
width: 908px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pics {
|
|
||||||
height: 375px;
|
|
||||||
width: 600px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pics img {
|
|
||||||
padding: 5px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background-color: #eee;
|
|
||||||
width: 600px;
|
|
||||||
height: 375px;
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Login -------------------------------------- */
|
|
||||||
|
|
||||||
#loginLogo {
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-top:100px;
|
|
||||||
width: 180px;
|
|
||||||
height: 36px;
|
|
||||||
background-image: url(files/logo.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
#loginHolder {
|
|
||||||
background: #eee;
|
|
||||||
padding: 5px;
|
|
||||||
width: 310px;
|
|
||||||
margin: 0 auto;
|
|
||||||
height: 90px;
|
|
||||||
margin-top:20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login {
|
|
||||||
padding:10px;
|
|
||||||
width: 288px;
|
|
||||||
height: 68px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background:#fff;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Sidebar ---------------------------------------- */
|
|
||||||
|
|
||||||
#sidebar {
|
|
||||||
width: 179px;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .sideNav { width: 179px; }
|
|
||||||
|
|
||||||
#sidebar .sideNav li { border-bottom: 1px solid #ddd; width: 179px; }
|
|
||||||
|
|
||||||
#sidebar .sideNav li a {
|
|
||||||
display: block;
|
|
||||||
color: #646464;
|
|
||||||
background: #f6f6f6;
|
|
||||||
text-decoration: none;
|
|
||||||
height: 29px;
|
|
||||||
line-height: 29px;
|
|
||||||
padding: 0 19px;
|
|
||||||
width: 141px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .sideNav li a:hover { background: #fdfcf6; }
|
|
||||||
|
|
||||||
#sidebar .sideNav li a.active, #sidebar .sideNav li a.active:hover {
|
|
||||||
background: #f0f7fa;
|
|
||||||
color: #c66653;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Breadcrumb ---------------------------------------- */
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
width: 718px;
|
|
||||||
float: right;
|
|
||||||
color: #646464;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 20px 0 0 0;
|
|
||||||
padding: 0 0 10px 0;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 a {
|
|
||||||
color: #646464;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 a.active { color: #c66653; }
|
|
||||||
|
|
||||||
h2 a:hover { text-decoration: underline; }
|
|
||||||
|
|
||||||
/* Content ---------------------------------------- */
|
|
||||||
|
|
||||||
#main {
|
|
||||||
width: 700px;
|
|
||||||
float: right;
|
|
||||||
padding: 0 19px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main p {
|
|
||||||
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #5494af;
|
|
||||||
padding: 0 0 0 10px;
|
|
||||||
margin: 20px 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
padding: 0 0 0 10px;
|
|
||||||
margin: 20px 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main ul {
|
|
||||||
padding: 0 0 0 10px;
|
|
||||||
list-style-type: circle;
|
|
||||||
list-style-position: inside;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main table {
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
width: 700px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main table tr th {
|
|
||||||
text-align: left;
|
|
||||||
background: #f6f6f6;
|
|
||||||
padding: 0px 20px;
|
|
||||||
height: 20px;
|
|
||||||
line-height: 20px;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main table tr td {
|
|
||||||
background: #f6f6f6;
|
|
||||||
padding: 0px 20px;
|
|
||||||
height: 29px;
|
|
||||||
line-height: 29px;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main table tr.odd td {
|
|
||||||
background: #fbfbfb;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main table tr:hover td { background: #fdfcf6; }
|
|
||||||
|
|
||||||
#main table .action {
|
|
||||||
text-align: right;
|
|
||||||
padding: 0 20px 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main table tr .action a { margin: 0 0 0 10px; text-decoration: none; color: #9b9b9b; }
|
|
||||||
#main table tr:hover .action .edit { color: #c5a059; }
|
|
||||||
#main table tr:hover .action .delete { color: #a02b2b; }
|
|
||||||
#main table tr:hover .action .view { color: #55a34a; }
|
|
||||||
|
|
||||||
#main table tr:hover .action a:hover { text-decoration: underline; }
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
padding: 19px;
|
|
||||||
margin: 0 0 20px 0;
|
|
||||||
background: #fbfbfb;
|
|
||||||
}
|
|
||||||
|
|
||||||
form p { margin: 0 0 14px 0; float: left; width: 100%; }
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 0 7px 0;
|
|
||||||
line-height: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Footer ---------------------------------------- */
|
|
||||||
|
|
||||||
#footer {
|
|
||||||
margin: 10px 0 30px 0;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 11px;
|
|
||||||
color: #9B9B9B;
|
|
||||||
padding: 0 0 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer a { color: #9B9B9B; }
|
|
||||||
|
|
||||||
#footer a:hover { text-decoration: none; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="wrapper">
|
|
||||||
<!-- h1 tag stays for the logo, you can use the a tag for linking the index page -->
|
|
||||||
<h1><a href="./"><span>{TITLE}</span></a></h1>
|
|
||||||
|
|
||||||
<div id="containerHolder">
|
|
||||||
<div id="container">
|
|
||||||
<div id="sidebar">
|
|
||||||
<ul class="sideNav">
|
|
||||||
{MENU}
|
|
||||||
</ul>
|
|
||||||
<!-- // .sideNav -->
|
|
||||||
</div>
|
|
||||||
<!-- // #sidebar -->
|
|
||||||
|
|
||||||
<!-- h2 stays for breadcrumbs -->
|
|
||||||
<h2>Welcome {USERNAME}</h2>
|
|
||||||
|
|
||||||
<div id="main">
|
|
||||||
<h3>{PLUGIN_NAME}</h3>
|
|
||||||
|
|
||||||
{CONTENT}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- // #main -->
|
|
||||||
|
|
||||||
<div class="clear"></div>
|
|
||||||
</div>
|
|
||||||
<!-- // #container -->
|
|
||||||
</div>
|
|
||||||
<!-- // #containerHolder -->
|
|
||||||
|
|
||||||
<p id="footer">MCServer is using: {MEM}MB of memory; Current chunk count: {NUMCHUNKS} </p>
|
|
||||||
</div>
|
|
||||||
<!-- // #wrapper -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -30,20 +30,22 @@ function GetDefaultPage()
|
|||||||
Content = Content .. "<p>" .. cRoot:Get():GetServer():GetServerID() .. "</p>"
|
Content = Content .. "<p>" .. cRoot:Get():GetServer():GetServerID() .. "</p>"
|
||||||
|
|
||||||
Content = Content .. "<h4>Plugins:</h4><ul>"
|
Content = Content .. "<h4>Plugins:</h4><ul>"
|
||||||
local AllPlugins = PM:GetAllPlugins()
|
PM:ForEachPlugin(
|
||||||
for key,value in pairs(AllPlugins) do
|
function (a_CBPlugin)
|
||||||
if( value ~= nil and value ~= false ) then
|
if (a_CBPlugin:IsLoaded()) then
|
||||||
Content = Content .. "<li>" .. key .. " (version " .. value:GetVersion() .. ")</li>"
|
Content = Content .. "<li>" .. a_CBPlugin:GetName() .. " (version " .. a_CBPlugin:GetVersion() .. ")</li>"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
)
|
||||||
|
|
||||||
Content = Content .. "</ul>"
|
Content = Content .. "</ul>"
|
||||||
Content = Content .. "<h4>Players:</h4><ul>"
|
Content = Content .. "<h4>Players:</h4><ul>"
|
||||||
|
|
||||||
local AddPlayerToTable = function( Player )
|
cRoot:Get():ForEachPlayer(
|
||||||
Content = Content .. "<li>" .. Player:GetName() .. "</li>"
|
function(a_CBPlayer)
|
||||||
end
|
Content = Content .. "<li>" .. Player:GetName() .. "</li>"
|
||||||
cRoot:Get():ForEachPlayer( AddPlayerToTable )
|
end
|
||||||
|
)
|
||||||
|
|
||||||
Content = Content .. "</ul><br>";
|
Content = Content .. "</ul><br>";
|
||||||
|
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
-- Use a table for fast concatenation of strings
|
|
||||||
local SiteContent = {}
|
|
||||||
function Output(String)
|
|
||||||
table.insert(SiteContent, String)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function GetTableSize(Table)
|
|
||||||
local Size = 0
|
|
||||||
for key,value in pairs(Table) do
|
|
||||||
Size = Size + 1
|
|
||||||
end
|
|
||||||
return Size
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function GetDefaultPage()
|
|
||||||
local PM = cRoot:Get():GetPluginManager()
|
|
||||||
|
|
||||||
local SubTitle = "Current Game"
|
|
||||||
local Content = ""
|
|
||||||
|
|
||||||
Content = Content .. "<h4>Server Name:</h4>"
|
|
||||||
Content = Content .. "<p>" .. cRoot:Get():GetServer():GetServerID() .. "</p>"
|
|
||||||
|
|
||||||
Content = Content .. "<h4>Plugins:</h4><ul>"
|
|
||||||
local AllPlugins = PM:GetAllPlugins()
|
|
||||||
for key,value in pairs(AllPlugins) do
|
|
||||||
if( value ~= nil and value ~= false ) then
|
|
||||||
Content = Content .. "<li>" .. key .. " V." .. value:GetVersion() .. "</li>"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Content = Content .. "</ul>"
|
|
||||||
Content = Content .. "<h4>Players:</h4><ul>"
|
|
||||||
|
|
||||||
local AddPlayerToTable = function( Player )
|
|
||||||
Content = Content .. "<li>" .. Player:GetName() .. "</li>"
|
|
||||||
end
|
|
||||||
cRoot:Get():ForEachPlayer( AddPlayerToTable )
|
|
||||||
|
|
||||||
Content = Content .. "</ul><br>";
|
|
||||||
|
|
||||||
return Content, SubTitle
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ShowPage(WebAdmin, TemplateRequest)
|
|
||||||
SiteContent = {}
|
|
||||||
local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
|
|
||||||
local Title = "MCServer WebAdmin"
|
|
||||||
local MemoryUsageKiB = cRoot:GetPhysicalRAMUsage()
|
|
||||||
local NumChunks = cRoot:Get():GetTotalChunkCount()
|
|
||||||
local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
|
|
||||||
local PageContent = PluginPage.Content
|
|
||||||
local SubTitle = PluginPage.PluginName
|
|
||||||
if (PluginPage.TabName ~= "") then
|
|
||||||
SubTitle = PluginPage.PluginName .. " - " .. PluginPage.TabName
|
|
||||||
end
|
|
||||||
if (PageContent == "") then
|
|
||||||
PageContent, SubTitle = GetDefaultPage()
|
|
||||||
end
|
|
||||||
|
|
||||||
Output([[
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
<link rel="icon" href="/favicon.ico">
|
|
||||||
<title>]] .. Title .. [[</title>
|
|
||||||
<link rel="stylesheet" type="text/css" media="screen" href="/style.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="wrapper">
|
|
||||||
<!-- h1 tag stays for the logo, you can use the a tag for linking the index page -->
|
|
||||||
<h1>
|
|
||||||
<a href="]] .. BaseURL .. [["><span>MCServer</span></a>
|
|
||||||
</h1>
|
|
||||||
<div id="containerHolder">
|
|
||||||
<div id="container">
|
|
||||||
<div id="sidebar">
|
|
||||||
<ul class="sideNav">
|
|
||||||
]])
|
|
||||||
|
|
||||||
|
|
||||||
local AllPlugins = WebAdmin:GetPlugins()
|
|
||||||
for key,value in pairs(AllPlugins) do
|
|
||||||
local PluginWebTitle = value:GetWebTitle()
|
|
||||||
local TabNames = value:GetTabNames()
|
|
||||||
if (GetTableSize(TabNames) > 0) then
|
|
||||||
Output("<li>"..PluginWebTitle.."</li>\n");
|
|
||||||
|
|
||||||
for webname,prettyname in pairs(TabNames) do
|
|
||||||
Output("<li><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
Output([[
|
|
||||||
</ul>
|
|
||||||
<!-- // .sideNav -->
|
|
||||||
</div>
|
|
||||||
<!-- // #sidebar -->
|
|
||||||
<!-- h2 stays for breadcrumbs -->
|
|
||||||
<h2>Welcome ]] .. TemplateRequest.Request.Username .. [[</h2>
|
|
||||||
<div id="main">
|
|
||||||
<h3>]] .. SubTitle .. [[</h3>
|
|
||||||
]] .. PageContent .. [[
|
|
||||||
</div>
|
|
||||||
<!-- // #main -->
|
|
||||||
|
|
||||||
<div class="clear"></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- // #container -->
|
|
||||||
</div>
|
|
||||||
<!-- // #containerHolder -->
|
|
||||||
|
|
||||||
<p id="footer">MCServer is using: ]] .. MemoryUsageKiB / 1024 .. [[ MiB of memory; Current chunk count: ]] .. NumChunks .. [[ </p>
|
|
||||||
</div>
|
|
||||||
<!-- // #wrapper -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
]])
|
|
||||||
|
|
||||||
return table.concat(SiteContent)
|
|
||||||
end
|
|
@ -513,7 +513,7 @@ static int tolua_DoWith(lua_State* tolua_S)
|
|||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
|
||||||
}
|
}
|
||||||
if (!lua_isfunction( tolua_S, 3))
|
if (!lua_isfunction(tolua_S, 3))
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
|
||||||
}
|
}
|
||||||
@ -539,20 +539,21 @@ static int tolua_DoWith(lua_State* tolua_S)
|
|||||||
class cLuaCallback : public cItemCallback<Ty2>
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
|
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef):
|
||||||
: LuaState( a_LuaState)
|
LuaState(a_LuaState),
|
||||||
, FuncRef( a_FuncRef)
|
FuncRef(a_FuncRef),
|
||||||
, TableRef( a_TableRef)
|
TableRef(a_TableRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
||||||
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
||||||
if (TableRef != LUA_REFNIL)
|
if (TableRef != LUA_REFNIL)
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
||||||
@ -633,7 +634,8 @@ static int tolua_DoWithID(lua_State* tolua_S)
|
|||||||
LuaState(a_LuaState),
|
LuaState(a_LuaState),
|
||||||
FuncRef(a_FuncRef),
|
FuncRef(a_FuncRef),
|
||||||
TableRef(a_TableRef)
|
TableRef(a_TableRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
@ -699,7 +701,7 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
|
|||||||
int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
|
int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
|
||||||
int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
|
int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
|
||||||
int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
|
int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
|
||||||
if (!lua_isfunction( tolua_S, 5))
|
if (!lua_isfunction(tolua_S, 5))
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
|
||||||
}
|
}
|
||||||
@ -725,20 +727,21 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
|
|||||||
class cLuaCallback : public cItemCallback<Ty2>
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
|
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef):
|
||||||
: LuaState( a_LuaState)
|
LuaState(a_LuaState),
|
||||||
, FuncRef( a_FuncRef)
|
FuncRef(a_FuncRef),
|
||||||
, TableRef( a_TableRef)
|
TableRef(a_TableRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
||||||
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
||||||
if (TableRef != LUA_REFNIL)
|
if (TableRef != LUA_REFNIL)
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
||||||
@ -794,7 +797,7 @@ static int tolua_ForEachInChunk(lua_State * tolua_S)
|
|||||||
int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0));
|
int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0));
|
||||||
int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0));
|
int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0));
|
||||||
|
|
||||||
if (!lua_isfunction( tolua_S, 4))
|
if (!lua_isfunction(tolua_S, 4))
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #3");
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #3");
|
||||||
}
|
}
|
||||||
@ -820,20 +823,21 @@ static int tolua_ForEachInChunk(lua_State * tolua_S)
|
|||||||
class cLuaCallback : public cItemCallback<Ty2>
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
|
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef):
|
||||||
: LuaState( a_LuaState)
|
LuaState(a_LuaState),
|
||||||
, FuncRef( a_FuncRef)
|
FuncRef(a_FuncRef),
|
||||||
, TableRef( a_TableRef)
|
TableRef(a_TableRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
||||||
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
||||||
if (TableRef != LUA_REFNIL)
|
if (TableRef != LUA_REFNIL)
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
||||||
@ -908,7 +912,8 @@ static int tolua_ForEachInBox(lua_State * tolua_S)
|
|||||||
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) :
|
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) :
|
||||||
m_LuaState(a_LuaState),
|
m_LuaState(a_LuaState),
|
||||||
m_FnRef(a_FuncRef)
|
m_FnRef(a_FuncRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// cItemCallback<Ty2> overrides:
|
// cItemCallback<Ty2> overrides:
|
||||||
@ -960,7 +965,7 @@ static int tolua_ForEach(lua_State * tolua_S)
|
|||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lua_isfunction( tolua_S, 2))
|
if (!lua_isfunction(tolua_S, 2))
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
|
||||||
}
|
}
|
||||||
@ -986,20 +991,21 @@ static int tolua_ForEach(lua_State * tolua_S)
|
|||||||
class cLuaCallback : public cItemCallback<Ty2>
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
|
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef):
|
||||||
: LuaState( a_LuaState)
|
LuaState(a_LuaState),
|
||||||
, FuncRef( a_FuncRef)
|
FuncRef(a_FuncRef),
|
||||||
, TableRef( a_TableRef)
|
TableRef(a_TableRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
||||||
tolua_pushusertype( LuaState, a_Item, Ty2::GetClassStatic());
|
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
||||||
if (TableRef != LUA_REFNIL)
|
if (TableRef != LUA_REFNIL)
|
||||||
{
|
{
|
||||||
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
||||||
@ -1010,7 +1016,7 @@ static int tolua_ForEach(lua_State * tolua_S)
|
|||||||
|
|
||||||
if (lua_isboolean(LuaState, -1))
|
if (lua_isboolean(LuaState, -1))
|
||||||
{
|
{
|
||||||
return (tolua_toboolean( LuaState, -1, 0) > 0);
|
return (tolua_toboolean(LuaState, -1, 0) > 0);
|
||||||
}
|
}
|
||||||
return false; /* Continue enumeration */
|
return false; /* Continue enumeration */
|
||||||
}
|
}
|
||||||
@ -1447,29 +1453,12 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
|
|||||||
|
|
||||||
static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
|
static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, nullptr);
|
// API function no longer available:
|
||||||
|
LOGWARNING("cPluginManager:GetAllPlugins() is no longer available, use cPluginManager:ForEachPlugin() instead");
|
||||||
const cPluginManager::PluginMap & AllPlugins = self->GetAllPlugins();
|
cLuaState::LogStackTrace(tolua_S);
|
||||||
|
|
||||||
|
// Return an empty table:
|
||||||
lua_newtable(tolua_S);
|
lua_newtable(tolua_S);
|
||||||
int index = 1;
|
|
||||||
cPluginManager::PluginMap::const_iterator iter = AllPlugins.begin();
|
|
||||||
while (iter != AllPlugins.end())
|
|
||||||
{
|
|
||||||
const cPlugin* Plugin = iter->second;
|
|
||||||
tolua_pushstring(tolua_S, iter->first.c_str());
|
|
||||||
if (Plugin != nullptr)
|
|
||||||
{
|
|
||||||
tolua_pushusertype(tolua_S, (void *)Plugin, "const cPlugin");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tolua_pushboolean(tolua_S, 0);
|
|
||||||
}
|
|
||||||
lua_rawset(tolua_S, -3);
|
|
||||||
++iter;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1493,6 +1482,18 @@ static int tolua_cPluginManager_GetCurrentPlugin(lua_State * S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cPluginManager_GetPlugin(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// API function no longer available:
|
||||||
|
LOGWARNING("cPluginManager:GetPlugin() is no longer available. Use cPluginManager:DoWithPlugin() or cPluginManager:CallPlugin() instead.");
|
||||||
|
cLuaState::LogStackTrace(tolua_S);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cPluginManager_LogStackTrace(lua_State * S)
|
static int tolua_cPluginManager_LogStackTrace(lua_State * S)
|
||||||
{
|
{
|
||||||
cLuaState::LogStackTrace(S);
|
cLuaState::LogStackTrace(S);
|
||||||
@ -1694,10 +1695,11 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
|
|||||||
class cLuaCallback : public cPluginManager::cCommandEnumCallback
|
class cLuaCallback : public cPluginManager::cCommandEnumCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State * a_LuaState, int a_FuncRef)
|
cLuaCallback(lua_State * a_LuaState, int a_FuncRef):
|
||||||
: LuaState( a_LuaState)
|
LuaState(a_LuaState),
|
||||||
, FuncRef( a_FuncRef)
|
FuncRef(a_FuncRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
|
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
|
||||||
@ -1717,7 +1719,7 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
|
|||||||
|
|
||||||
if (lua_isboolean(LuaState, -1))
|
if (lua_isboolean(LuaState, -1))
|
||||||
{
|
{
|
||||||
return (tolua_toboolean( LuaState, -1, 0) > 0);
|
return (tolua_toboolean(LuaState, -1, 0) > 0);
|
||||||
}
|
}
|
||||||
return false; /* Continue enumeration */
|
return false; /* Continue enumeration */
|
||||||
}
|
}
|
||||||
@ -1771,10 +1773,11 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
|
|||||||
class cLuaCallback : public cPluginManager::cCommandEnumCallback
|
class cLuaCallback : public cPluginManager::cCommandEnumCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State * a_LuaState, int a_FuncRef)
|
cLuaCallback(lua_State * a_LuaState, int a_FuncRef):
|
||||||
: LuaState( a_LuaState)
|
LuaState(a_LuaState),
|
||||||
, FuncRef( a_FuncRef)
|
FuncRef(a_FuncRef)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
|
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
|
||||||
@ -1794,7 +1797,7 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
|
|||||||
|
|
||||||
if (lua_isboolean(LuaState, -1))
|
if (lua_isboolean(LuaState, -1))
|
||||||
{
|
{
|
||||||
return (tolua_toboolean( LuaState, -1, 0) > 0);
|
return (tolua_toboolean(LuaState, -1, 0) > 0);
|
||||||
}
|
}
|
||||||
return false; /* Continue enumeration */
|
return false; /* Continue enumeration */
|
||||||
}
|
}
|
||||||
@ -2011,7 +2014,11 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
|
|||||||
|
|
||||||
virtual bool Item(cPlugin * a_Plugin) override
|
virtual bool Item(cPlugin * a_Plugin) override
|
||||||
{
|
{
|
||||||
m_NumReturns = ((cPluginLua *)a_Plugin)->CallFunctionFromForeignState(
|
if (!a_Plugin->IsLoaded())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_NumReturns = static_cast<cPluginLua *>(a_Plugin)->CallFunctionFromForeignState(
|
||||||
m_FunctionName, m_SrcLuaState, 4, lua_gettop(m_SrcLuaState)
|
m_FunctionName, m_SrcLuaState, 4, lua_gettop(m_SrcLuaState)
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
@ -2019,9 +2026,6 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
|
|||||||
} Callback(FunctionName, L);
|
} Callback(FunctionName, L);
|
||||||
if (!cPluginManager::Get()->DoWithPlugin(PluginName, Callback))
|
if (!cPluginManager::Get()->DoWithPlugin(PluginName, Callback))
|
||||||
{
|
{
|
||||||
// TODO 2014_01_20 _X: This might be too much logging, plugins cannot know if other plugins are loaded (async)
|
|
||||||
LOGWARNING("cPluginManager::CallPlugin: No such plugin name (\"%s\")", PluginName.c_str());
|
|
||||||
L.LogStackTrace();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return Callback.m_NumReturns;
|
return Callback.m_NumReturns;
|
||||||
@ -2031,6 +2035,21 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cPluginManager_FindPlugins(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// API function no longer exists:
|
||||||
|
LOGWARNING("cPluginManager:FindPlugins() is obsolete, use cPluginManager:RefreshPluginList() instead!");
|
||||||
|
cLuaState::LogStackTrace(tolua_S);
|
||||||
|
|
||||||
|
// Still, do the actual work performed by the API function when it existed:
|
||||||
|
cPluginManager::Get()->RefreshPluginList();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
|
static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
/* Function signature:
|
/* Function signature:
|
||||||
@ -2337,40 +2356,40 @@ static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cPluginLua_AddTab(lua_State* tolua_S)
|
static int tolua_cPlugin_GetDirectory(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
cPluginLua * self = (cPluginLua *) tolua_tousertype(tolua_S, 1, nullptr);
|
cLuaState L(tolua_S);
|
||||||
LOGWARN("WARNING: Using deprecated function AddTab()! Use AddWebTab() instead. (plugin \"%s\" in folder \"%s\")",
|
|
||||||
self->GetName().c_str(), self->GetDirectory().c_str()
|
// Log the obsoletion warning:
|
||||||
);
|
LOGWARNING("cPlugin:GetDirectory() is obsolete, use cPlugin:GetFolderName() instead.");
|
||||||
return tolua_cPluginLua_AddWebTab( tolua_S);
|
L.LogStackTrace();
|
||||||
|
|
||||||
|
// Retrieve the params:
|
||||||
|
cPlugin * Plugin = static_cast<cPluginLua *>(tolua_tousertype(tolua_S, 1, nullptr));
|
||||||
|
|
||||||
|
// Get the folder name:
|
||||||
|
L.Push(Plugin->GetFolderName());
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cPlugin_Call(lua_State * tolua_S)
|
static int tolua_cPlugin_GetLocalDirectory(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
cLuaState L(tolua_S);
|
cLuaState L(tolua_S);
|
||||||
|
|
||||||
// Log the obsoletion warning:
|
// Log the obsoletion warning:
|
||||||
LOGWARNING("cPlugin:Call() is obsolete and unsafe, use cPluginManager:CallPlugin() instead.");
|
LOGWARNING("cPlugin:GetLocalDirectory() is obsolete, use cPlugin:GetLocalFolder() instead.");
|
||||||
L.LogStackTrace();
|
L.LogStackTrace();
|
||||||
|
|
||||||
// Retrieve the params: plugin and the function name to call
|
// Retrieve the params:
|
||||||
cPluginLua * TargetPlugin = (cPluginLua *) tolua_tousertype(tolua_S, 1, nullptr);
|
cPlugin * Plugin = static_cast<cPluginLua *>(tolua_tousertype(tolua_S, 1, nullptr));
|
||||||
AString FunctionName = tolua_tostring(tolua_S, 2, "");
|
|
||||||
|
|
||||||
// Call the function:
|
// Get the folder:
|
||||||
int NumReturns = TargetPlugin->CallFunctionFromForeignState(FunctionName, L, 3, lua_gettop(L));
|
L.Push(Plugin->GetLocalFolder());
|
||||||
if (NumReturns < 0)
|
return 1;
|
||||||
{
|
|
||||||
LOGWARNING("cPlugin::Call() failed to call destination function");
|
|
||||||
L.LogStackTrace();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return NumReturns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2628,22 +2647,16 @@ static int tolua_AllToLua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S)
|
|||||||
|
|
||||||
static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
|
static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
cWebPlugin* self = (cWebPlugin*) tolua_tousertype(tolua_S, 1, nullptr);
|
// Returns a map of (SafeTitle -> Title) for the plugin's web tabs.
|
||||||
|
auto self = reinterpret_cast<cWebPlugin *>(tolua_tousertype(tolua_S, 1, nullptr));
|
||||||
const cWebPlugin::TabNameList & TabNames = self->GetTabNames();
|
auto TabNames = self->GetTabNames();
|
||||||
|
|
||||||
lua_newtable(tolua_S);
|
lua_newtable(tolua_S);
|
||||||
int index = 1;
|
int index = 1;
|
||||||
cWebPlugin::TabNameList::const_iterator iter = TabNames.begin();
|
for (auto itr = TabNames.cbegin(), end = TabNames.cend(); itr != end; ++itr)
|
||||||
while (iter != TabNames.end())
|
|
||||||
{
|
{
|
||||||
const AString & FancyName = iter->first;
|
tolua_pushstring(tolua_S, itr->second.c_str()); // Because the SafeTitle is supposed to be unique, use it as key
|
||||||
const AString & WebName = iter->second;
|
tolua_pushstring(tolua_S, itr->first.c_str());
|
||||||
tolua_pushstring( tolua_S, WebName.c_str()); // Because the WebName is supposed to be unique, use it as key
|
|
||||||
tolua_pushstring( tolua_S, FancyName.c_str());
|
|
||||||
//
|
|
||||||
lua_rawset(tolua_S, -3);
|
lua_rawset(tolua_S, -3);
|
||||||
++iter;
|
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -3792,7 +3805,8 @@ void ManualBindings::Bind(lua_State * tolua_S)
|
|||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
tolua_beginmodule(tolua_S, "cPlugin");
|
tolua_beginmodule(tolua_S, "cPlugin");
|
||||||
tolua_function(tolua_S, "Call", tolua_cPlugin_Call);
|
tolua_function(tolua_S, "GetDirectory", tolua_cPlugin_GetDirectory);
|
||||||
|
tolua_function(tolua_S, "GetLocalDirectory", tolua_cPlugin_GetLocalDirectory);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
tolua_beginmodule(tolua_S, "cPluginManager");
|
tolua_beginmodule(tolua_S, "cPluginManager");
|
||||||
@ -3800,10 +3814,13 @@ void ManualBindings::Bind(lua_State * tolua_S)
|
|||||||
tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand);
|
tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand);
|
||||||
tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand);
|
tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand);
|
||||||
tolua_function(tolua_S, "CallPlugin", tolua_cPluginManager_CallPlugin);
|
tolua_function(tolua_S, "CallPlugin", tolua_cPluginManager_CallPlugin);
|
||||||
|
tolua_function(tolua_S, "FindPlugins", tolua_cPluginManager_FindPlugins);
|
||||||
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
|
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
|
||||||
tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand);
|
tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand);
|
||||||
|
tolua_function(tolua_S, "ForEachPlugin", tolua_ForEach<cPluginManager, cPlugin, &cPluginManager::ForEachPlugin>);
|
||||||
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
|
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
|
||||||
tolua_function(tolua_S, "GetCurrentPlugin", tolua_cPluginManager_GetCurrentPlugin);
|
tolua_function(tolua_S, "GetCurrentPlugin", tolua_cPluginManager_GetCurrentPlugin);
|
||||||
|
tolua_function(tolua_S, "GetPlugin", tolua_cPluginManager_GetPlugin);
|
||||||
tolua_function(tolua_S, "LogStackTrace", tolua_cPluginManager_LogStackTrace);
|
tolua_function(tolua_S, "LogStackTrace", tolua_cPluginManager_LogStackTrace);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
@ -3819,7 +3836,6 @@ void ManualBindings::Bind(lua_State * tolua_S)
|
|||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
tolua_beginmodule(tolua_S, "cPluginLua");
|
tolua_beginmodule(tolua_S, "cPluginLua");
|
||||||
tolua_function(tolua_S, "AddTab", tolua_cPluginLua_AddTab);
|
|
||||||
tolua_function(tolua_S, "AddWebTab", tolua_cPluginLua_AddWebTab);
|
tolua_function(tolua_S, "AddWebTab", tolua_cPluginLua_AddWebTab);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPlugin::cPlugin(const AString & a_PluginDirectory) :
|
cPlugin::cPlugin(const AString & a_FolderName) :
|
||||||
m_Language(E_CPP),
|
m_Status(cPluginManager::psDisabled),
|
||||||
m_Name(a_PluginDirectory),
|
m_Name(a_FolderName),
|
||||||
m_Version(0),
|
m_Version(0),
|
||||||
m_Directory(a_PluginDirectory)
|
m_FolderName(a_FolderName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,9 +28,33 @@ cPlugin::~cPlugin()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString cPlugin::GetLocalFolder(void) const
|
void cPlugin::Unload(void)
|
||||||
{
|
{
|
||||||
return std::string("Plugins/") + m_Directory;
|
auto pm = cPluginManager::Get();
|
||||||
|
pm->RemovePluginCommands(this);
|
||||||
|
pm->RemovePluginConsoleCommands(this);
|
||||||
|
pm->RemoveHooks(this);
|
||||||
|
OnDisable();
|
||||||
|
m_Status = cPluginManager::psUnloaded;
|
||||||
|
m_LoadError.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cPlugin::GetLocalFolder(void) const
|
||||||
|
{
|
||||||
|
return std::string("Plugins/") + m_FolderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPlugin::SetLoadError(const AString & a_LoadError)
|
||||||
|
{
|
||||||
|
m_Status = cPluginManager::psError;
|
||||||
|
m_LoadError = a_LoadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,30 +1,16 @@
|
|||||||
|
|
||||||
|
// Plugin.h
|
||||||
|
|
||||||
|
// Declares the cPlugin class representing an interface that a plugin implementation needs to expose, with some helping functions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
class cCommandOutputCallback;
|
|
||||||
class cItems;
|
|
||||||
class cHopperEntity;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cBlockEntityWithItems;
|
|
||||||
class cClientHandle;
|
|
||||||
class cPickup;
|
|
||||||
class cPlayer;
|
|
||||||
class cProjectileEntity;
|
|
||||||
class cEntity;
|
|
||||||
class cMonster;
|
|
||||||
class cWorld;
|
|
||||||
class cChunkDesc;
|
|
||||||
struct TakeDamageInfo;
|
|
||||||
|
|
||||||
|
|
||||||
// fwd: CraftingRecipes.h
|
|
||||||
class cCraftingGrid;
|
|
||||||
class cCraftingRecipe;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -35,11 +21,23 @@ class cPlugin
|
|||||||
public:
|
public:
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
cPlugin( const AString & a_PluginDirectory);
|
/** Creates a new instance.
|
||||||
|
a_FolderName is the name of the folder (in the Plugins folder) from which the plugin is loaded.
|
||||||
|
The plugin's name defaults to the folder name. */
|
||||||
|
cPlugin(const AString & a_FolderName);
|
||||||
|
|
||||||
virtual ~cPlugin();
|
virtual ~cPlugin();
|
||||||
|
|
||||||
|
/** Called as the last call into the plugin before it is unloaded. */
|
||||||
virtual void OnDisable(void) {}
|
virtual void OnDisable(void) {}
|
||||||
virtual bool Initialize(void) = 0;
|
|
||||||
|
/** Loads and initializes the plugin. Sets m_Status to psLoaded or psError accordingly.
|
||||||
|
Returns true if the initialization succeeded, false otherwise. */
|
||||||
|
virtual bool Load(void) = 0;
|
||||||
|
|
||||||
|
/** Unloads the plugin. Sets m_Status to psDisabled.
|
||||||
|
The default implementation removes the plugin's associations with cPluginManager, descendants should call it as well. */
|
||||||
|
virtual void Unload(void);
|
||||||
|
|
||||||
// Called each tick
|
// Called each tick
|
||||||
virtual void Tick(float a_Dt) = 0;
|
virtual void Tick(float a_Dt) = 0;
|
||||||
@ -109,19 +107,17 @@ public:
|
|||||||
|
|
||||||
/** Handles the command split into a_Split, issued by player a_Player.
|
/** Handles the command split into a_Split, issued by player a_Player.
|
||||||
Command permissions have already been checked.
|
Command permissions have already been checked.
|
||||||
Returns true if command handled successfully
|
Returns true if command handled successfully. */
|
||||||
*/
|
|
||||||
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand) = 0;
|
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand) = 0;
|
||||||
|
|
||||||
/** Handles the console command split into a_Split.
|
/** Handles the console command split into a_Split.
|
||||||
Returns true if command handled successfully. Output is to be sent to the a_Output callback.
|
Returns true if command handled successfully. Output is to be sent to the a_Output callback. */
|
||||||
*/
|
|
||||||
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand) = 0;
|
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand) = 0;
|
||||||
|
|
||||||
/// All bound commands are to be removed, do any language-dependent cleanup here
|
/** All bound commands are to be removed, do any language-dependent cleanup here */
|
||||||
virtual void ClearCommands(void) {}
|
virtual void ClearCommands(void) {}
|
||||||
|
|
||||||
/// All bound console commands are to be removed, do any language-dependent cleanup here
|
/** All bound console commands are to be removed, do any language-dependent cleanup here */
|
||||||
virtual void ClearConsoleCommands(void) {}
|
virtual void ClearConsoleCommands(void) {}
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
@ -131,28 +127,43 @@ public:
|
|||||||
int GetVersion(void) const { return m_Version; }
|
int GetVersion(void) const { return m_Version; }
|
||||||
void SetVersion(int a_Version) { m_Version = a_Version; }
|
void SetVersion(int a_Version) { m_Version = a_Version; }
|
||||||
|
|
||||||
const AString & GetDirectory(void) const {return m_Directory; }
|
/** Returns the name of the folder (in the Plugins folder) from which the plugin is loaded. */
|
||||||
AString GetLocalDirectory(void) const {return GetLocalFolder(); } // OBSOLETE, use GetLocalFolder() instead
|
const AString & GetFolderName(void) const {return m_FolderName; }
|
||||||
|
|
||||||
|
/** Returns the folder relative to the MCS Executable, from which the plugin is loaded. */
|
||||||
AString GetLocalFolder(void) const;
|
AString GetLocalFolder(void) const;
|
||||||
|
|
||||||
|
/** Returns the error encountered while loading the plugin. Only valid if m_Status == psError. */
|
||||||
|
const AString & GetLoadError(void) const { return m_LoadError; }
|
||||||
|
|
||||||
|
cPluginManager::ePluginStatus GetStatus(void) const { return m_Status; }
|
||||||
|
|
||||||
|
bool IsLoaded(void) const { return (m_Status == cPluginManager::psLoaded); }
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
// Needed for ManualBindings' tolua_ForEach<>
|
||||||
|
static const char * GetClassStatic(void) { return "cPlugin"; }
|
||||||
|
|
||||||
/* This should not be exposed to scripting languages */
|
protected:
|
||||||
enum PluginLanguage
|
friend class cPluginManager;
|
||||||
{
|
|
||||||
E_CPP,
|
|
||||||
E_LUA,
|
|
||||||
E_SQUIRREL, // OBSOLETE, but kept in place to remind us of the horrors lurking in the history
|
|
||||||
};
|
|
||||||
PluginLanguage GetLanguage() { return m_Language; }
|
|
||||||
void SetLanguage( PluginLanguage a_Language) { m_Language = a_Language; }
|
|
||||||
|
|
||||||
private:
|
cPluginManager::ePluginStatus m_Status;
|
||||||
PluginLanguage m_Language;
|
|
||||||
|
/** The name of the plugin, used to identify the plugin in the system and for inter-plugin calls. */
|
||||||
AString m_Name;
|
AString m_Name;
|
||||||
|
|
||||||
int m_Version;
|
int m_Version;
|
||||||
|
|
||||||
AString m_Directory;
|
/** Name of the folder (in the Plugins folder) from which the plugin is loaded. */
|
||||||
|
AString m_FolderName;
|
||||||
|
|
||||||
|
/** The error encountered while loading the plugin.
|
||||||
|
Only valid if m_Status == psError. */
|
||||||
|
AString m_LoadError;
|
||||||
|
|
||||||
|
|
||||||
|
/** Sets m_LoadError to the specified string and m_Status to psError. */
|
||||||
|
void SetLoadError(const AString & a_LoadError);
|
||||||
}; // tolua_export
|
}; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ void cPluginLua::Close(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginLua::Initialize(void)
|
bool cPluginLua::Load(void)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
if (!m_LuaState.IsValid())
|
if (!m_LuaState.IsValid())
|
||||||
@ -144,6 +144,7 @@ bool cPluginLua::Initialize(void)
|
|||||||
// Warn if there are no Lua files in the plugin folder:
|
// Warn if there are no Lua files in the plugin folder:
|
||||||
if (LuaFiles.empty())
|
if (LuaFiles.empty())
|
||||||
{
|
{
|
||||||
|
SetLoadError("No lua files found, plugin is probably missing.");
|
||||||
LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str());
|
LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
@ -155,6 +156,7 @@ bool cPluginLua::Initialize(void)
|
|||||||
AString Path = PluginPath + *itr;
|
AString Path = PluginPath + *itr;
|
||||||
if (!m_LuaState.LoadFile(Path))
|
if (!m_LuaState.LoadFile(Path))
|
||||||
{
|
{
|
||||||
|
SetLoadError(Printf("Failed to load file %s.", itr->c_str()));
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -164,6 +166,8 @@ bool cPluginLua::Initialize(void)
|
|||||||
AString Path = PluginPath + "Info.lua";
|
AString Path = PluginPath + "Info.lua";
|
||||||
if (!m_LuaState.LoadFile(Path))
|
if (!m_LuaState.LoadFile(Path))
|
||||||
{
|
{
|
||||||
|
SetLoadError("Failed to load file Info.lua.");
|
||||||
|
m_Status = cPluginManager::psError;
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -173,17 +177,20 @@ bool cPluginLua::Initialize(void)
|
|||||||
bool res = false;
|
bool res = false;
|
||||||
if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res))
|
if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res))
|
||||||
{
|
{
|
||||||
|
SetLoadError("Cannot call the Initialize() function.");
|
||||||
LOGWARNING("Error in plugin %s: Cannot call the Initialize() function. Plugin is temporarily disabled.", GetName().c_str());
|
LOGWARNING("Error in plugin %s: Cannot call the Initialize() function. Plugin is temporarily disabled.", GetName().c_str());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
|
SetLoadError("The Initialize() function failed.");
|
||||||
LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str());
|
LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_Status = cPluginManager::psLoaded;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +198,17 @@ bool cPluginLua::Initialize(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPluginLua::Unload(void)
|
||||||
|
{
|
||||||
|
ClearTabs();
|
||||||
|
super::Unload();
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPluginLua::OnDisable(void)
|
void cPluginLua::OnDisable(void)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
@ -1983,40 +2001,29 @@ void cPluginLua::AddResettable(cPluginLua::cResettablePtr a_Resettable)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request)
|
AString cPluginLua::HandleWebRequest(const HTTPRequest & a_Request)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
// Find the tab to use for the request:
|
||||||
std::string RetVal = "";
|
auto TabName = GetTabNameForRequest(a_Request);
|
||||||
|
AString SafeTabTitle = TabName.second;
|
||||||
std::pair< std::string, std::string > TabName = GetTabNameForRequest(a_Request);
|
if (SafeTabTitle.empty())
|
||||||
std::string SafeTabName = TabName.second;
|
{
|
||||||
if (SafeTabName.empty())
|
return "";
|
||||||
|
}
|
||||||
|
auto Tab = GetTabBySafeTitle(SafeTabTitle);
|
||||||
|
if (Tab == nullptr)
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
sWebPluginTab * Tab = 0;
|
// Get the page content from the plugin:
|
||||||
for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
|
cCSLock Lock(m_CriticalSection);
|
||||||
|
AString Contents = Printf("WARNING: WebPlugin tab '%s' did not return a string!", Tab->m_Title.c_str());
|
||||||
|
if (!m_LuaState.Call(Tab->m_UserData, &a_Request, cLuaState::Return, Contents))
|
||||||
{
|
{
|
||||||
if ((*itr)->SafeTitle.compare(SafeTabName) == 0) // This is the one! Rawr
|
return "Lua encountered error while processing the page request";
|
||||||
{
|
|
||||||
Tab = *itr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Contents;
|
||||||
if (Tab != nullptr)
|
|
||||||
{
|
|
||||||
AString Contents = Printf("WARNING: WebPlugin tab '%s' did not return a string!", Tab->Title.c_str());
|
|
||||||
if (!m_LuaState.Call(Tab->UserData, a_Request, cLuaState::Return, Contents))
|
|
||||||
{
|
|
||||||
return "Lua encountered error while processing the page request";
|
|
||||||
}
|
|
||||||
|
|
||||||
RetVal += Contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RetVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2031,13 +2038,7 @@ bool cPluginLua::AddWebTab(const AString & a_Title, lua_State * a_LuaState, int
|
|||||||
LOGERROR("Only allowed to add a tab to a WebPlugin of your own Plugin!");
|
LOGERROR("Only allowed to add a tab to a WebPlugin of your own Plugin!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sWebPluginTab * Tab = new sWebPluginTab();
|
AddNewWebTab(a_Title, a_FunctionReference);
|
||||||
Tab->Title = a_Title;
|
|
||||||
Tab->SafeTitle = SafeString(a_Title);
|
|
||||||
|
|
||||||
Tab->UserData = a_FunctionReference;
|
|
||||||
|
|
||||||
GetTabs().push_back(Tab);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ class cPluginLua :
|
|||||||
public cPlugin,
|
public cPlugin,
|
||||||
public cWebPlugin
|
public cWebPlugin
|
||||||
{
|
{
|
||||||
|
typedef cPlugin super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
@ -96,7 +98,8 @@ public:
|
|||||||
~cPluginLua();
|
~cPluginLua();
|
||||||
|
|
||||||
virtual void OnDisable(void) override;
|
virtual void OnDisable(void) override;
|
||||||
virtual bool Initialize(void) override;
|
virtual bool Load(void) override;
|
||||||
|
virtual void Unload(void) override;
|
||||||
|
|
||||||
virtual void Tick(float a_Dt) override;
|
virtual void Tick(float a_Dt) override;
|
||||||
|
|
||||||
@ -173,12 +176,13 @@ public:
|
|||||||
/** Returns true if the plugin contains the function for the specified hook type, using the old-style registration (#121) */
|
/** Returns true if the plugin contains the function for the specified hook type, using the old-style registration (#121) */
|
||||||
bool CanAddOldStyleHook(int a_HookType);
|
bool CanAddOldStyleHook(int a_HookType);
|
||||||
|
|
||||||
// cWebPlugin override
|
// cWebPlugin overrides
|
||||||
virtual const AString GetWebTitle(void) const {return GetName(); }
|
virtual const AString GetWebTitle(void) const {return GetName(); }
|
||||||
|
virtual AString HandleWebRequest(const HTTPRequest & a_Request) override;
|
||||||
|
|
||||||
// cWebPlugin and WebAdmin stuff
|
/** Adds a new web tab to webadmin.
|
||||||
virtual AString HandleWebRequest(const HTTPRequest * a_Request) override;
|
Displaying the tab calls the referenced function. */
|
||||||
bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // >> EXPORTED IN MANUALBINDINGS <<
|
bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // Exported in ManualBindings.cpp
|
||||||
|
|
||||||
/** Binds the command to call the function specified by a Lua function reference. Simply adds to CommandMap. */
|
/** Binds the command to call the function specified by a Lua function reference. Simply adds to CommandMap. */
|
||||||
void BindCommand(const AString & a_Command, int a_FnRef);
|
void BindCommand(const AString & a_Command, int a_FnRef);
|
||||||
|
@ -59,39 +59,48 @@ void cPluginManager::ReloadPlugins(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPluginManager::FindPlugins(void)
|
void cPluginManager::RefreshPluginList(void)
|
||||||
{
|
{
|
||||||
|
// Get a list of currently available folders:
|
||||||
AString PluginsPath = GetPluginsPath() + "/";
|
AString PluginsPath = GetPluginsPath() + "/";
|
||||||
|
AStringVector Contents = cFile::GetFolderContents(PluginsPath.c_str());
|
||||||
// First get a clean list of only the currently running plugins, we don't want to mess those up
|
AStringVector Folders;
|
||||||
for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
|
for (auto & item: Contents)
|
||||||
{
|
{
|
||||||
if (itr->second == nullptr)
|
if ((item == ".") || (item == "..") || (!cFile::IsFolder(PluginsPath + item)))
|
||||||
{
|
|
||||||
PluginMap::iterator thiz = itr;
|
|
||||||
++thiz;
|
|
||||||
m_Plugins.erase( itr);
|
|
||||||
itr = thiz;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
|
|
||||||
AStringVector Files = cFile::GetFolderContents(PluginsPath.c_str());
|
|
||||||
for (AStringVector::const_iterator itr = Files.begin(); itr != Files.end(); ++itr)
|
|
||||||
{
|
|
||||||
if ((*itr == ".") || (*itr == "..") || (!cFile::IsFolder(PluginsPath + *itr)))
|
|
||||||
{
|
{
|
||||||
// We only want folders, and don't want "." or ".."
|
// We only want folders, and don't want "." or ".."
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Folders.push_back(item);
|
||||||
|
} // for item - Contents[]
|
||||||
|
|
||||||
// Add plugin name/directory to the list
|
// Set all plugins with invalid folders as psNotFound:
|
||||||
if (m_Plugins.find(*itr) == m_Plugins.end())
|
for (auto & plugin: m_Plugins)
|
||||||
|
{
|
||||||
|
if (std::find(Folders.cbegin(), Folders.cend(), plugin->GetFolderName()) == Folders.end())
|
||||||
{
|
{
|
||||||
m_Plugins[*itr] = nullptr;
|
plugin->m_Status = psNotFound;
|
||||||
}
|
}
|
||||||
}
|
} // for plugin - m_Plugins[]
|
||||||
|
|
||||||
|
// Add all newly discovered plugins:
|
||||||
|
for (auto & folder: Folders)
|
||||||
|
{
|
||||||
|
bool hasFound = false;
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
|
{
|
||||||
|
if (plugin->GetFolderName() == folder)
|
||||||
|
{
|
||||||
|
hasFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // for plugin - m_Plugins[]
|
||||||
|
if (!hasFound)
|
||||||
|
{
|
||||||
|
m_Plugins.push_back(std::make_shared<cPluginLua>(folder));
|
||||||
|
}
|
||||||
|
} // for folder - Folders[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -112,57 +121,23 @@ void cPluginManager::ReloadPluginsNow(void)
|
|||||||
void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
|
void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
|
||||||
{
|
{
|
||||||
LOG("-- Loading Plugins --");
|
LOG("-- Loading Plugins --");
|
||||||
|
|
||||||
|
// Unload any existing plugins:
|
||||||
m_bReloadPlugins = false;
|
m_bReloadPlugins = false;
|
||||||
UnloadPluginsNow();
|
UnloadPluginsNow();
|
||||||
|
|
||||||
FindPlugins();
|
// Refresh the list of plugins to load new ones from disk / remove the deleted ones:
|
||||||
|
RefreshPluginList();
|
||||||
|
|
||||||
cServer::BindBuiltInConsoleCommands();
|
// Load the plugins:
|
||||||
|
AStringVector ToLoad = GetFoldersToLoad(a_SettingsIni);
|
||||||
// Check if the Plugins section exists.
|
for (auto & pluginFolder: ToLoad)
|
||||||
int KeyNum = a_SettingsIni.FindKey("Plugins");
|
|
||||||
|
|
||||||
if (KeyNum == -1)
|
|
||||||
{
|
{
|
||||||
InsertDefaultPlugins(a_SettingsIni);
|
LoadPlugin(pluginFolder);
|
||||||
KeyNum = a_SettingsIni.FindKey("Plugins");
|
} // for pluginFolder - ToLoad[]
|
||||||
}
|
|
||||||
|
|
||||||
// How many plugins are there?
|
// Log a report of the loading process
|
||||||
int NumPlugins = a_SettingsIni.GetNumValues(KeyNum);
|
size_t NumLoadedPlugins = GetNumLoadedPlugins();
|
||||||
|
|
||||||
for (int i = 0; i < NumPlugins; i++)
|
|
||||||
{
|
|
||||||
AString ValueName = a_SettingsIni.GetValueName(KeyNum, i);
|
|
||||||
if (ValueName.compare("Plugin") == 0)
|
|
||||||
{
|
|
||||||
AString PluginFile = a_SettingsIni.GetValue(KeyNum, i);
|
|
||||||
if (!PluginFile.empty())
|
|
||||||
{
|
|
||||||
if (m_Plugins.find(PluginFile) != m_Plugins.end())
|
|
||||||
{
|
|
||||||
LoadPlugin(PluginFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Remove invalid plugins from the PluginMap.
|
|
||||||
for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
|
|
||||||
{
|
|
||||||
if (itr->second == nullptr)
|
|
||||||
{
|
|
||||||
PluginMap::iterator thiz = itr;
|
|
||||||
++thiz;
|
|
||||||
m_Plugins.erase(itr);
|
|
||||||
itr = thiz;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t NumLoadedPlugins = GetNumPlugins();
|
|
||||||
if (NumLoadedPlugins == 0)
|
if (NumLoadedPlugins == 0)
|
||||||
{
|
{
|
||||||
LOG("-- No Plugins Loaded --");
|
LOG("-- No Plugins Loaded --");
|
||||||
@ -173,7 +148,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins);
|
LOG("-- Loaded %u Plugins --", static_cast<unsigned>(NumLoadedPlugins));
|
||||||
}
|
}
|
||||||
CallHookPluginsLoaded();
|
CallHookPluginsLoaded();
|
||||||
}
|
}
|
||||||
@ -200,12 +175,39 @@ void cPluginManager::InsertDefaultPlugins(cIniFile & a_SettingsIni)
|
|||||||
|
|
||||||
void cPluginManager::Tick(float a_Dt)
|
void cPluginManager::Tick(float a_Dt)
|
||||||
{
|
{
|
||||||
while (!m_DisablePluginList.empty())
|
// Unload plugins that have been scheduled for unloading:
|
||||||
|
AStringVector PluginsToUnload;
|
||||||
{
|
{
|
||||||
RemovePlugin(m_DisablePluginList.front());
|
cCSLock Lock(m_CSPluginsToUnload);
|
||||||
m_DisablePluginList.pop_front();
|
std::swap(m_PluginsToUnload, PluginsToUnload);
|
||||||
}
|
}
|
||||||
|
for (auto & folder: PluginsToUnload)
|
||||||
|
{
|
||||||
|
bool HasUnloaded = false;
|
||||||
|
bool HasFound = false;
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
|
{
|
||||||
|
if (plugin->GetFolderName() == folder)
|
||||||
|
{
|
||||||
|
HasFound = true;
|
||||||
|
if (plugin->IsLoaded())
|
||||||
|
{
|
||||||
|
plugin->Unload();
|
||||||
|
HasUnloaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!HasFound)
|
||||||
|
{
|
||||||
|
LOG("Cannot unload plugin in folder \"%s\", there's no such plugin folder", folder.c_str());
|
||||||
|
}
|
||||||
|
else if (!HasUnloaded)
|
||||||
|
{
|
||||||
|
LOG("Cannot unload plugin in folder \"%s\", it has not been loaded.", folder.c_str());
|
||||||
|
}
|
||||||
|
} // for plugin - m_Plugins[]
|
||||||
|
|
||||||
|
// If a plugin reload has been scheduled, reload now:
|
||||||
if (m_bReloadPlugins)
|
if (m_bReloadPlugins)
|
||||||
{
|
{
|
||||||
ReloadPluginsNow();
|
ReloadPluginsNow();
|
||||||
@ -1477,68 +1479,56 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPlugin * cPluginManager::GetPlugin(const AString & a_Plugin) const
|
|
||||||
{
|
|
||||||
for (PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
|
|
||||||
{
|
|
||||||
if (itr->second == nullptr)
|
|
||||||
{
|
|
||||||
// The plugin is currently unloaded
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itr->second->GetName().compare(a_Plugin) == 0)
|
|
||||||
{
|
|
||||||
return itr->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const cPluginManager::PluginMap & cPluginManager::GetAllPlugins() const
|
|
||||||
{
|
|
||||||
return m_Plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPluginManager::UnloadPluginsNow()
|
void cPluginManager::UnloadPluginsNow()
|
||||||
{
|
{
|
||||||
|
// Remove all bindings:
|
||||||
m_Hooks.clear();
|
m_Hooks.clear();
|
||||||
|
|
||||||
while (!m_Plugins.empty())
|
|
||||||
{
|
|
||||||
RemovePlugin(m_Plugins.begin()->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Commands.clear();
|
m_Commands.clear();
|
||||||
m_ConsoleCommands.clear();
|
m_ConsoleCommands.clear();
|
||||||
|
|
||||||
|
// Re-bind built-in console commands:
|
||||||
|
cServer::BindBuiltInConsoleCommands();
|
||||||
|
|
||||||
|
// Unload all loaded plugins:
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
|
{
|
||||||
|
if (plugin->IsLoaded())
|
||||||
|
{
|
||||||
|
plugin->Unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::DisablePlugin(const AString & a_PluginName)
|
void cPluginManager::UnloadPlugin(const AString & a_PluginFolder)
|
||||||
{
|
{
|
||||||
PluginMap::iterator itr = m_Plugins.find(a_PluginName);
|
cCSLock Lock(m_CSPluginsToUnload);
|
||||||
if (itr == m_Plugins.end())
|
m_PluginsToUnload.push_back(a_PluginFolder);
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itr->first.compare(a_PluginName) == 0) // _X 2013_02_01: wtf? Isn't this supposed to be what find() does?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginManager::LoadPlugin(const AString & a_FolderName)
|
||||||
|
{
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
{
|
{
|
||||||
m_DisablePluginList.push_back(itr->second);
|
if (plugin->GetFolderName() == a_FolderName)
|
||||||
itr->second = nullptr; // Get rid of this thing right away
|
{
|
||||||
return true;
|
if (!plugin->IsLoaded())
|
||||||
}
|
{
|
||||||
|
return plugin->Load();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // for plugin - m_Plugins[]
|
||||||
|
|
||||||
|
// Plugin not found
|
||||||
|
LOG("Cannot load plugin, folder \"%s\" not found.", a_FolderName.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1546,15 +1536,6 @@ bool cPluginManager::DisablePlugin(const AString & a_PluginName)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::LoadPlugin(const AString & a_PluginName)
|
|
||||||
{
|
|
||||||
return AddPlugin(new cPluginLua(a_PluginName.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
|
void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
|
||||||
{
|
{
|
||||||
for (HookMap::iterator itr = m_Hooks.begin(), end = m_Hooks.end(); itr != end; ++itr)
|
for (HookMap::iterator itr = m_Hooks.begin(), end = m_Hooks.end(); itr != end; ++itr)
|
||||||
@ -1567,32 +1548,6 @@ void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPluginManager::RemovePlugin(cPlugin * a_Plugin)
|
|
||||||
{
|
|
||||||
for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
|
|
||||||
{
|
|
||||||
if (itr->second == a_Plugin)
|
|
||||||
{
|
|
||||||
m_Plugins.erase(itr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RemovePluginCommands(a_Plugin);
|
|
||||||
RemovePluginConsoleCommands(a_Plugin);
|
|
||||||
RemoveHooks(a_Plugin);
|
|
||||||
if (a_Plugin != nullptr)
|
|
||||||
{
|
|
||||||
a_Plugin->OnDisable();
|
|
||||||
}
|
|
||||||
delete a_Plugin;
|
|
||||||
a_Plugin = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
|
void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
|
||||||
{
|
{
|
||||||
if (a_Plugin != nullptr)
|
if (a_Plugin != nullptr)
|
||||||
@ -1619,6 +1574,22 @@ void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginManager::IsPluginLoaded(const AString & a_PluginName)
|
||||||
|
{
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
|
{
|
||||||
|
if (plugin->GetName() == a_PluginName)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString)
|
bool cPluginManager::BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString)
|
||||||
{
|
{
|
||||||
CommandMap::iterator cmd = m_Commands.find(a_Command);
|
CommandMap::iterator cmd = m_Commands.find(a_Command);
|
||||||
@ -1836,31 +1807,31 @@ bool cPluginManager::IsValidHookType(int a_HookType)
|
|||||||
bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback)
|
bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback)
|
||||||
{
|
{
|
||||||
// TODO: Implement locking for plugins
|
// TODO: Implement locking for plugins
|
||||||
PluginMap::iterator itr = m_Plugins.find(a_PluginName);
|
for (auto & plugin: m_Plugins)
|
||||||
if ((itr == m_Plugins.end()) || (itr->second == nullptr))
|
|
||||||
{
|
{
|
||||||
return false;
|
if (plugin->GetName() == a_PluginName)
|
||||||
|
{
|
||||||
|
return a_Callback.Item(plugin.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return a_Callback.Item(itr->second);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
|
bool cPluginManager::ForEachPlugin(cPluginCallback & a_Callback)
|
||||||
{
|
{
|
||||||
m_Plugins[a_Plugin->GetDirectory()] = a_Plugin;
|
// TODO: Implement locking for plugins
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
if (a_Plugin->Initialize())
|
|
||||||
{
|
{
|
||||||
// Initialization OK
|
if (a_Callback.Item(plugin.get()))
|
||||||
return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// Initialization failed
|
|
||||||
RemovePlugin(a_Plugin); // Also undoes any registrations that Initialize() might have made
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1869,21 +1840,23 @@ bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
|
|||||||
|
|
||||||
void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook)
|
void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook)
|
||||||
{
|
{
|
||||||
if (!a_Plugin)
|
if (a_Plugin == nullptr)
|
||||||
{
|
{
|
||||||
LOGWARN("Called cPluginManager::AddHook() with a_Plugin == nullptr");
|
LOGWARN("Called cPluginManager::AddHook() with a_Plugin == nullptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PluginList & Plugins = m_Hooks[a_Hook];
|
PluginList & Plugins = m_Hooks[a_Hook];
|
||||||
Plugins.remove(a_Plugin);
|
if (std::find(Plugins.cbegin(), Plugins.cend(), a_Plugin) == Plugins.cend())
|
||||||
Plugins.push_back(a_Plugin);
|
{
|
||||||
|
Plugins.push_back(a_Plugin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
size_t cPluginManager::GetNumPlugins() const
|
size_t cPluginManager::GetNumPlugins(void) const
|
||||||
{
|
{
|
||||||
return m_Plugins.size();
|
return m_Plugins.size();
|
||||||
}
|
}
|
||||||
@ -1891,3 +1864,53 @@ size_t cPluginManager::GetNumPlugins() const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t cPluginManager::GetNumLoadedPlugins(void) const
|
||||||
|
{
|
||||||
|
size_t res = 0;
|
||||||
|
for (auto & plugin: m_Plugins)
|
||||||
|
{
|
||||||
|
if (plugin->IsLoaded())
|
||||||
|
{
|
||||||
|
res += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AStringVector cPluginManager::GetFoldersToLoad(cIniFile & a_SettingsIni)
|
||||||
|
{
|
||||||
|
// Check if the Plugins section exists.
|
||||||
|
int KeyNum = a_SettingsIni.FindKey("Plugins");
|
||||||
|
if (KeyNum == -1)
|
||||||
|
{
|
||||||
|
InsertDefaultPlugins(a_SettingsIni);
|
||||||
|
KeyNum = a_SettingsIni.FindKey("Plugins");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of plugins to load:
|
||||||
|
AStringVector res;
|
||||||
|
int NumPlugins = a_SettingsIni.GetNumValues(KeyNum);
|
||||||
|
for (int i = 0; i < NumPlugins; i++)
|
||||||
|
{
|
||||||
|
AString ValueName = a_SettingsIni.GetValueName(KeyNum, i);
|
||||||
|
if (ValueName.compare("Plugin") == 0)
|
||||||
|
{
|
||||||
|
AString PluginFile = a_SettingsIni.GetValue(KeyNum, i);
|
||||||
|
if (!PluginFile.empty())
|
||||||
|
{
|
||||||
|
res.push_back(PluginFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // for i - ini values
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,61 +6,38 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cPlugin;
|
|
||||||
|
|
||||||
// fwd: World.h
|
|
||||||
class cWorld;
|
|
||||||
|
|
||||||
// fwd: ChunkDesc.h
|
// fwd:
|
||||||
|
class cBlockEntityWithItems;
|
||||||
class cChunkDesc;
|
class cChunkDesc;
|
||||||
|
class cClientHandle;
|
||||||
// fwd: Entities/Entity.h
|
class cCommandOutputCallback;
|
||||||
class cEntity;
|
|
||||||
|
|
||||||
// fwd: Entities/ProjectileEntity.h
|
|
||||||
class cProjectileEntity;
|
|
||||||
|
|
||||||
// fwd: Mobs/Monster.h
|
|
||||||
class cMonster;
|
|
||||||
|
|
||||||
// fwd: Player.h
|
|
||||||
class cPlayer;
|
|
||||||
|
|
||||||
// fwd: CraftingRecipes.h
|
|
||||||
class cCraftingGrid;
|
class cCraftingGrid;
|
||||||
class cCraftingRecipe;
|
class cCraftingRecipe;
|
||||||
|
class cEntity;
|
||||||
// fwd: Pickup.h
|
class cHopperEntity;
|
||||||
|
class cItems;
|
||||||
|
class cMonster;
|
||||||
class cPickup;
|
class cPickup;
|
||||||
|
class cPlayer;
|
||||||
// fwd: Pawn.h
|
class cPlugin;
|
||||||
|
class cProjectileEntity;
|
||||||
|
class cWorld;
|
||||||
struct TakeDamageInfo;
|
struct TakeDamageInfo;
|
||||||
|
|
||||||
// fwd: CommandOutput.h
|
typedef SharedPtr<cPlugin> cPluginPtr;
|
||||||
class cCommandOutputCallback;
|
typedef std::vector<cPluginPtr> cPluginPtrs;
|
||||||
|
|
||||||
// fwd: BlockEntities/HopperEntity.h
|
|
||||||
class cHopperEntity;
|
|
||||||
|
|
||||||
// fwd: BlockEntities/BlockEntityWithItems.h
|
|
||||||
class cBlockEntityWithItems;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cItems;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
class cPluginManager
|
class cPluginManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// tolua_end
|
|
||||||
|
|
||||||
// Called each tick
|
|
||||||
virtual void Tick(float a_Dt);
|
|
||||||
|
|
||||||
// tolua_begin
|
|
||||||
enum CommandResult
|
enum CommandResult
|
||||||
{
|
{
|
||||||
crExecuted,
|
crExecuted,
|
||||||
@ -70,6 +47,29 @@ public:
|
|||||||
crNoPermission,
|
crNoPermission,
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
/** Defines the status of a single plugin - whether it is loaded, disabled or errored. */
|
||||||
|
enum ePluginStatus
|
||||||
|
{
|
||||||
|
/** The plugin has been loaded successfully. */
|
||||||
|
psLoaded,
|
||||||
|
|
||||||
|
/** The plugin is disabled in settings.ini. */
|
||||||
|
psDisabled,
|
||||||
|
|
||||||
|
/** The plugin is enabled in settings.ini but has been unloaded (by a command). */
|
||||||
|
psUnloaded,
|
||||||
|
|
||||||
|
/** The plugin is enabled in settings.ini but has failed to load.
|
||||||
|
m_LoadError is the description of the error. */
|
||||||
|
psError,
|
||||||
|
|
||||||
|
/** The plugin has been loaded before, but after a folder refresh it is no longer present.
|
||||||
|
The plugin will be unloaded in the next call to ReloadPlugins(). */
|
||||||
|
psNotFound,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
enum PluginHook
|
enum PluginHook
|
||||||
{
|
{
|
||||||
HOOK_BLOCK_SPREAD,
|
HOOK_BLOCK_SPREAD,
|
||||||
@ -160,24 +160,31 @@ public:
|
|||||||
/** The interface used for enumerating and extern-calling plugins */
|
/** The interface used for enumerating and extern-calling plugins */
|
||||||
typedef cItemCallback<cPlugin> cPluginCallback;
|
typedef cItemCallback<cPlugin> cPluginCallback;
|
||||||
|
|
||||||
|
typedef std::list<cPlugin *> PluginList;
|
||||||
|
|
||||||
|
|
||||||
|
/** Called each tick, calls the plugins' OnTick hook, as well as processes plugin events (addition, removal) */
|
||||||
|
void Tick(float a_Dt);
|
||||||
|
|
||||||
/** Returns the instance of the Plugin Manager (there is only ever one) */
|
/** Returns the instance of the Plugin Manager (there is only ever one) */
|
||||||
static cPluginManager * Get(void); // tolua_export
|
static cPluginManager * Get(void); // tolua_export
|
||||||
|
|
||||||
typedef std::map< AString, cPlugin * > PluginMap;
|
/** Refreshes the m_Plugins list based on the current contents of the Plugins folder.
|
||||||
typedef std::list< cPlugin * > PluginList;
|
If an active plugin's folder is not found anymore, the plugin is set as psNotFound, but not yet unloaded. */
|
||||||
cPlugin * GetPlugin( const AString & a_Plugin) const; // tolua_export
|
void RefreshPluginList(); // tolua_export
|
||||||
const PluginMap & GetAllPlugins() const; // >> EXPORTED IN MANUALBINDINGS <<
|
|
||||||
|
|
||||||
// tolua_begin
|
/** Schedules a reload of the plugins to happen within the next call to Tick(). */
|
||||||
void FindPlugins();
|
void ReloadPlugins(); // tolua_export
|
||||||
void ReloadPlugins();
|
|
||||||
// tolua_end
|
|
||||||
|
|
||||||
/** Adds the plugin to the list of plugins called for the specified hook type. Handles multiple adds as a single add */
|
/** Adds the plugin to the list of plugins called for the specified hook type.
|
||||||
|
If a plugin adds multiple handlers for a single hook, it is added only once (ignore-duplicates). */
|
||||||
void AddHook(cPlugin * a_Plugin, int a_HookType);
|
void AddHook(cPlugin * a_Plugin, int a_HookType);
|
||||||
|
|
||||||
|
/** Returns the number of all plugins in m_Plugins (includes disabled, unloaded and errored plugins). */
|
||||||
size_t GetNumPlugins() const; // tolua_export
|
size_t GetNumPlugins() const; // tolua_export
|
||||||
|
|
||||||
|
/** Returns the number of plugins that are psLoaded. */
|
||||||
|
size_t GetNumLoadedPlugins(void) const; // tolua_export
|
||||||
|
|
||||||
// Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
|
// Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
|
||||||
bool CallHookBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
|
bool CallHookBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
|
||||||
@ -242,18 +249,26 @@ public:
|
|||||||
bool CallHookWorldStarted (cWorld & a_World);
|
bool CallHookWorldStarted (cWorld & a_World);
|
||||||
bool CallHookWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
|
bool CallHookWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
|
||||||
|
|
||||||
bool DisablePlugin(const AString & a_PluginName); // tolua_export
|
/** Queues the specified plugin to be unloaded in the next call to Tick().
|
||||||
bool LoadPlugin (const AString & a_PluginName); // tolua_export
|
Note that this function returns before the plugin is unloaded, to avoid deadlocks. */
|
||||||
|
void UnloadPlugin(const AString & a_PluginFolder); // tolua_export
|
||||||
|
|
||||||
|
/** Loads the plugin from the specified plugin folder.
|
||||||
|
Returns true if the plugin was loaded successfully or was already loaded before, false otherwise. */
|
||||||
|
bool LoadPlugin(const AString & a_PluginFolder); // tolua_export
|
||||||
|
|
||||||
/** Removes all hooks the specified plugin has registered */
|
/** Removes all hooks the specified plugin has registered */
|
||||||
void RemoveHooks(cPlugin * a_Plugin);
|
void RemoveHooks(cPlugin * a_Plugin);
|
||||||
|
|
||||||
/** Removes the plugin from the internal structures and deletes its object. */
|
/** Removes the plugin of the specified name from the internal structures and deletes its object. */
|
||||||
void RemovePlugin(cPlugin * a_Plugin);
|
void RemovePlugin(const AString & a_PluginName);
|
||||||
|
|
||||||
/** Removes all command bindings that the specified plugin has made */
|
/** Removes all command bindings that the specified plugin has made */
|
||||||
void RemovePluginCommands(cPlugin * a_Plugin);
|
void RemovePluginCommands(cPlugin * a_Plugin);
|
||||||
|
|
||||||
|
/** Returns true if the specified plugin is loaded. */
|
||||||
|
bool IsPluginLoaded(const AString & a_PluginName); // tolua_export
|
||||||
|
|
||||||
/** Binds a command to the specified plugin. Returns true if successful, false if command already bound. */
|
/** Binds a command to the specified plugin. Returns true if successful, false if command already bound. */
|
||||||
bool BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString); // Exported in ManualBindings.cpp, without the a_Plugin param
|
bool BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString); // Exported in ManualBindings.cpp, without the a_Plugin param
|
||||||
|
|
||||||
@ -296,8 +311,12 @@ public:
|
|||||||
static bool IsValidHookType(int a_HookType);
|
static bool IsValidHookType(int a_HookType);
|
||||||
|
|
||||||
/** Calls the specified callback with the plugin object of the specified plugin.
|
/** Calls the specified callback with the plugin object of the specified plugin.
|
||||||
Returns false if plugin not found, and the value that the callback has returned otherwise. */
|
Returns false if plugin not found, otherwise returns the value that the callback has returned. */
|
||||||
bool DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback);
|
bool DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback);
|
||||||
|
|
||||||
|
/** Calls the specified callback for each plugin in m_Plugins.
|
||||||
|
Returns true if all plugins have been reported, false if the callback has aborted the enumeration by returning true. */
|
||||||
|
bool ForEachPlugin(cPluginCallback & a_Callback);
|
||||||
|
|
||||||
/** Returns the path where individual plugins' folders are expected.
|
/** Returns the path where individual plugins' folders are expected.
|
||||||
The path doesn't end in a slash. */
|
The path doesn't end in a slash. */
|
||||||
@ -317,14 +336,26 @@ private:
|
|||||||
typedef std::map<int, cPluginManager::PluginList> HookMap;
|
typedef std::map<int, cPluginManager::PluginList> HookMap;
|
||||||
typedef std::map<AString, cCommandReg> CommandMap;
|
typedef std::map<AString, cCommandReg> CommandMap;
|
||||||
|
|
||||||
PluginList m_DisablePluginList;
|
|
||||||
PluginMap m_Plugins;
|
/** FolderNames of plugins that should be unloaded.
|
||||||
|
The plugins will be unloaded within the next call to Tick(), to avoid multithreading issues.
|
||||||
|
Protected against multithreaded access by m_CSPluginsToUnload. */
|
||||||
|
AStringVector m_PluginsToUnload;
|
||||||
|
|
||||||
|
/** Protects m_PluginsToUnload against multithreaded access. */
|
||||||
|
mutable cCriticalSection m_CSPluginsToUnload;
|
||||||
|
|
||||||
|
/** All plugins that have been found in the Plugins folder. */
|
||||||
|
cPluginPtrs m_Plugins;
|
||||||
|
|
||||||
HookMap m_Hooks;
|
HookMap m_Hooks;
|
||||||
CommandMap m_Commands;
|
CommandMap m_Commands;
|
||||||
CommandMap m_ConsoleCommands;
|
CommandMap m_ConsoleCommands;
|
||||||
|
|
||||||
|
/** If set to true, all the plugins will be reloaded within the next call to Tick(). */
|
||||||
bool m_bReloadPlugins;
|
bool m_bReloadPlugins;
|
||||||
|
|
||||||
|
|
||||||
cPluginManager();
|
cPluginManager();
|
||||||
virtual ~cPluginManager();
|
virtual ~cPluginManager();
|
||||||
|
|
||||||
@ -340,11 +371,11 @@ private:
|
|||||||
/** Handles writing default plugins if 'Plugins' key not found using a cIniFile object expected to be intialised to settings.ini */
|
/** Handles writing default plugins if 'Plugins' key not found using a cIniFile object expected to be intialised to settings.ini */
|
||||||
void InsertDefaultPlugins(cIniFile & a_SettingsIni);
|
void InsertDefaultPlugins(cIniFile & a_SettingsIni);
|
||||||
|
|
||||||
/** Adds the plugin into the internal list of plugins and initializes it. If initialization fails, the plugin is removed again. */
|
|
||||||
bool AddPlugin(cPlugin * a_Plugin);
|
|
||||||
|
|
||||||
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
|
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
|
||||||
CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
|
CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
|
||||||
|
|
||||||
|
/** Returns the folders that are specified in the settings ini to load plugins from. */
|
||||||
|
AStringVector GetFoldersToLoad(cIniFile & a_SettingsIni);
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,32 +24,26 @@ cWebPlugin::cWebPlugin()
|
|||||||
|
|
||||||
cWebPlugin::~cWebPlugin()
|
cWebPlugin::~cWebPlugin()
|
||||||
{
|
{
|
||||||
|
ASSERT(m_Tabs.empty()); // Has ClearTabs() been called?
|
||||||
|
|
||||||
|
// Remove from WebAdmin:
|
||||||
cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin();
|
cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin();
|
||||||
if (WebAdmin != nullptr)
|
if (WebAdmin != nullptr)
|
||||||
{
|
{
|
||||||
WebAdmin->RemovePlugin(this);
|
WebAdmin->RemovePlugin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TabList::iterator itr = m_Tabs.begin(); itr != m_Tabs.end(); ++itr)
|
|
||||||
{
|
|
||||||
delete *itr;
|
|
||||||
}
|
|
||||||
m_Tabs.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::list<std::pair<AString, AString> > cWebPlugin::GetTabNames(void)
|
cWebPlugin::cTabNames cWebPlugin::GetTabNames(void) const
|
||||||
{
|
{
|
||||||
std::list< std::pair< AString, AString > > NameList;
|
std::list< std::pair<AString, AString>> NameList;
|
||||||
for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
|
for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
std::pair< AString, AString > StringPair;
|
NameList.push_back(std::make_pair((*itr)->m_Title, (*itr)->m_SafeTitle));
|
||||||
StringPair.first = (*itr)->Title;
|
|
||||||
StringPair.second = (*itr)->SafeTitle;
|
|
||||||
NameList.push_back( StringPair);
|
|
||||||
}
|
}
|
||||||
return NameList;
|
return NameList;
|
||||||
}
|
}
|
||||||
@ -58,41 +52,54 @@ std::list<std::pair<AString, AString> > cWebPlugin::GetTabNames(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::pair< AString, AString > cWebPlugin::GetTabNameForRequest(const HTTPRequest * a_Request)
|
cWebPlugin::cTabPtr cWebPlugin::GetTabBySafeTitle(const AString & a_SafeTitle) const
|
||||||
{
|
{
|
||||||
std::pair< AString, AString > Names;
|
cCSLock Lock(m_CSTabs);
|
||||||
AStringVector Split = StringSplit(a_Request->Path, "/");
|
for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr)
|
||||||
|
|
||||||
if (Split.size() > 1)
|
|
||||||
{
|
{
|
||||||
sWebPluginTab * Tab = nullptr;
|
if ((*itr)->m_SafeTitle == a_SafeTitle)
|
||||||
if (Split.size() > 2) // If we got the tab name, show that page
|
|
||||||
{
|
{
|
||||||
for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
|
return *itr;
|
||||||
{
|
|
||||||
if ((*itr)->SafeTitle.compare(Split[2]) == 0) // This is the one!
|
|
||||||
{
|
|
||||||
Tab = *itr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Otherwise show the first tab
|
|
||||||
{
|
|
||||||
if (GetTabs().size() > 0)
|
|
||||||
{
|
|
||||||
Tab = *GetTabs().begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tab != nullptr)
|
|
||||||
{
|
|
||||||
Names.first = Tab->Title;
|
|
||||||
Names.second = Tab->SafeTitle;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return Names;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<AString, AString> cWebPlugin::GetTabNameForRequest(const HTTPRequest & a_Request)
|
||||||
|
{
|
||||||
|
AStringVector Split = StringSplit(a_Request.Path, "/");
|
||||||
|
if (Split.empty())
|
||||||
|
{
|
||||||
|
return std::make_pair(AString(), AString());
|
||||||
|
}
|
||||||
|
|
||||||
|
cCSLock Lock(m_CSTabs);
|
||||||
|
cTabPtr Tab;
|
||||||
|
if (Split.size() > 2) // If we got the tab name, show that page
|
||||||
|
{
|
||||||
|
for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->m_SafeTitle.compare(Split[2]) == 0) // This is the one!
|
||||||
|
{
|
||||||
|
return std::make_pair((*itr)->m_Title, (*itr)->m_SafeTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Tab name not found, display an "empty" page:
|
||||||
|
return std::make_pair(AString(), AString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the first tab:
|
||||||
|
if (!m_Tabs.empty())
|
||||||
|
{
|
||||||
|
return std::make_pair(m_Tabs.front()->m_SafeTitle, m_Tabs.front()->m_SafeTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No tabs at all:
|
||||||
|
return std::make_pair(AString(), AString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -101,14 +108,16 @@ std::pair< AString, AString > cWebPlugin::GetTabNameForRequest(const HTTPRequest
|
|||||||
AString cWebPlugin::SafeString(const AString & a_String)
|
AString cWebPlugin::SafeString(const AString & a_String)
|
||||||
{
|
{
|
||||||
AString RetVal;
|
AString RetVal;
|
||||||
for (unsigned int i = 0; i < a_String.size(); ++i)
|
auto len = a_String.size();
|
||||||
|
RetVal.reserve(len);
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
{
|
{
|
||||||
char c = a_String[i];
|
char c = a_String[i];
|
||||||
if (c == ' ')
|
if (c == ' ')
|
||||||
{
|
{
|
||||||
c = '_';
|
c = '_';
|
||||||
}
|
}
|
||||||
RetVal.push_back( c);
|
RetVal.push_back(c);
|
||||||
}
|
}
|
||||||
return RetVal;
|
return RetVal;
|
||||||
}
|
}
|
||||||
@ -116,3 +125,28 @@ AString cWebPlugin::SafeString(const AString & a_String)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cWebPlugin::AddNewWebTab(const AString & a_Title, int a_UserData)
|
||||||
|
{
|
||||||
|
auto Tab = std::make_shared<cTab>(a_Title, a_UserData);
|
||||||
|
cCSLock Lock(m_CSTabs);
|
||||||
|
m_Tabs.push_back(Tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cWebPlugin::ClearTabs(void)
|
||||||
|
{
|
||||||
|
// Remove the webadmin tabs:
|
||||||
|
cTabPtrs Tabs;
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSTabs);
|
||||||
|
std::swap(Tabs, m_Tabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,34 +12,67 @@ class cWebPlugin
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
struct cTab
|
||||||
|
{
|
||||||
|
AString m_Title;
|
||||||
|
AString m_SafeTitle;
|
||||||
|
int m_UserData;
|
||||||
|
|
||||||
|
cTab(const AString & a_Title, int a_UserData):
|
||||||
|
m_Title(a_Title),
|
||||||
|
m_SafeTitle(cWebPlugin::SafeString(a_Title)),
|
||||||
|
m_UserData(a_UserData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SharedPtr<cTab> cTabPtr;
|
||||||
|
typedef std::list<cTabPtr> cTabPtrs;
|
||||||
|
typedef std::list<std::pair<AString, AString>> cTabNames;
|
||||||
|
|
||||||
|
|
||||||
cWebPlugin();
|
cWebPlugin();
|
||||||
|
|
||||||
virtual ~cWebPlugin();
|
virtual ~cWebPlugin();
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
|
/** Returns the title of the plugin, as it should be presented in the webadmin's pages tree. */
|
||||||
virtual const AString GetWebTitle(void) const = 0;
|
virtual const AString GetWebTitle(void) const = 0;
|
||||||
|
|
||||||
virtual AString HandleWebRequest(const HTTPRequest * a_Request) = 0;
|
/** Sanitizes the input string, replacing spaces with underscores. */
|
||||||
|
static AString SafeString(const AString & a_String);
|
||||||
|
|
||||||
static AString SafeString( const AString & a_String);
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
struct sWebPluginTab
|
virtual AString HandleWebRequest(const HTTPRequest & a_Request) = 0;
|
||||||
{
|
|
||||||
std::string Title;
|
|
||||||
std::string SafeTitle;
|
|
||||||
|
|
||||||
int UserData;
|
/** Adds a new web tab with the specified contents. */
|
||||||
};
|
void AddNewWebTab(const AString & a_Title, int a_UserData);
|
||||||
|
|
||||||
typedef std::list< sWebPluginTab* > TabList;
|
/** Removes all the tabs. */
|
||||||
TabList & GetTabs() { return m_Tabs; }
|
void ClearTabs(void);
|
||||||
|
|
||||||
typedef std::list< std::pair<AString, AString> > TabNameList;
|
/** Returns all the tabs that this plugin has registered. */
|
||||||
TabNameList GetTabNames(); // >> EXPORTED IN MANUALBINDINGS <<
|
const cTabPtrs & GetTabs(void) const { return m_Tabs; }
|
||||||
std::pair< AString, AString > GetTabNameForRequest(const HTTPRequest* a_Request);
|
|
||||||
|
/** Returns all of the tabs that this plugin has registered. */
|
||||||
|
cTabNames GetTabNames(void) const; // Exported in ManualBindings.cpp
|
||||||
|
|
||||||
|
/** Returns the tab that has the specified SafeTitle.
|
||||||
|
Returns nullptr if no such tab. */
|
||||||
|
cTabPtr GetTabBySafeTitle(const AString & a_SafeTitle) const;
|
||||||
|
|
||||||
|
std::pair<AString, AString> GetTabNameForRequest(const HTTPRequest & a_Request);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TabList m_Tabs;
|
/** All tabs that this plugin has registered.
|
||||||
|
Protected against multithreaded access by m_CSTabs. */
|
||||||
|
cTabPtrs m_Tabs;
|
||||||
|
|
||||||
|
/** Protects m_Tabs against multithreaded access. */
|
||||||
|
mutable cCriticalSection m_CSTabs;
|
||||||
}; // tolua_export
|
}; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
@ -464,22 +464,12 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
|
|||||||
{
|
{
|
||||||
if (split.size() > 1)
|
if (split.size() > 1)
|
||||||
{
|
{
|
||||||
cPluginManager::PluginMap map = cPluginManager::Get()->GetAllPlugins();
|
cPluginManager::Get()->RefreshPluginList(); // Refresh the plugin list, so that if the plugin was added just now, it is loadable
|
||||||
|
|
||||||
for (auto plugin_entry : map)
|
|
||||||
{
|
|
||||||
if (plugin_entry.first == split[1])
|
|
||||||
{
|
|
||||||
a_Output.Out("Error! Plugin is already loaded!");
|
|
||||||
a_Output.Finished();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a_Output.Out(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin");
|
a_Output.Out(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a_Output.Out("Usage: load <pluginname>");
|
a_Output.Out("Usage: load <PluginFolder>");
|
||||||
}
|
}
|
||||||
a_Output.Finished();
|
a_Output.Finished();
|
||||||
return;
|
return;
|
||||||
@ -488,12 +478,12 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
|
|||||||
{
|
{
|
||||||
if (split.size() > 1)
|
if (split.size() > 1)
|
||||||
{
|
{
|
||||||
cPluginManager::Get()->RemovePlugin(cPluginManager::Get()->GetPlugin(split[1]));
|
cPluginManager::Get()->UnloadPlugin(split[1]);
|
||||||
a_Output.Out("Plugin unloaded");
|
a_Output.Out("Plugin unload scheduled");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a_Output.Out("Usage: unload <pluginname>");
|
a_Output.Out("Usage: unload <PluginFolder>");
|
||||||
}
|
}
|
||||||
a_Output.Finished();
|
a_Output.Finished();
|
||||||
return;
|
return;
|
||||||
|
@ -464,10 +464,10 @@ sWebAdminPage cWebAdmin::GetPage(const HTTPRequest & a_Request)
|
|||||||
{
|
{
|
||||||
if ((*itr)->GetWebTitle() == Split[1])
|
if ((*itr)->GetWebTitle() == Split[1])
|
||||||
{
|
{
|
||||||
Page.Content = (*itr)->HandleWebRequest(&a_Request);
|
Page.Content = (*itr)->HandleWebRequest(a_Request);
|
||||||
cWebPlugin * WebPlugin = *itr;
|
cWebPlugin * WebPlugin = *itr;
|
||||||
FoundPlugin = WebPlugin->GetWebTitle();
|
FoundPlugin = WebPlugin->GetWebTitle();
|
||||||
AString TabName = WebPlugin->GetTabNameForRequest(&a_Request).first;
|
AString TabName = WebPlugin->GetTabNameForRequest(a_Request).first;
|
||||||
Page.PluginName = FoundPlugin;
|
Page.PluginName = FoundPlugin;
|
||||||
Page.TabName = TabName;
|
Page.TabName = TabName;
|
||||||
break;
|
break;
|
||||||
@ -489,20 +489,32 @@ AString cWebAdmin::GetDefaultPage(void)
|
|||||||
Content += "<h4>Server Name:</h4>";
|
Content += "<h4>Server Name:</h4>";
|
||||||
Content += "<p>" + AString( cRoot::Get()->GetServer()->GetServerID()) + "</p>";
|
Content += "<p>" + AString( cRoot::Get()->GetServer()->GetServerID()) + "</p>";
|
||||||
|
|
||||||
|
// Display a list of all plugins:
|
||||||
Content += "<h4>Plugins:</h4><ul>";
|
Content += "<h4>Plugins:</h4><ul>";
|
||||||
cPluginManager * PM = cPluginManager::Get();
|
struct cPluginCallback:
|
||||||
const cPluginManager::PluginMap & List = PM->GetAllPlugins();
|
public cPluginManager::cPluginCallback
|
||||||
for (cPluginManager::PluginMap::const_iterator itr = List.begin(); itr != List.end(); ++itr)
|
|
||||||
{
|
{
|
||||||
if (itr->second == nullptr)
|
AString & m_Content;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
AppendPrintf(Content, "<li>%s V.%i</li>", itr->second->GetName().c_str(), itr->second->GetVersion());
|
|
||||||
}
|
|
||||||
Content += "</ul>";
|
|
||||||
Content += "<h4>Players:</h4><ul>";
|
|
||||||
|
|
||||||
|
cPluginCallback(AString & a_Content):
|
||||||
|
m_Content(a_Content)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cPlugin * a_Plugin) override
|
||||||
|
{
|
||||||
|
if (a_Plugin->IsLoaded())
|
||||||
|
{
|
||||||
|
AppendPrintf(m_Content, "<li>%s V.%i</li>", a_Plugin->GetName().c_str(), a_Plugin->GetVersion());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} Callback(Content);
|
||||||
|
cPluginManager::Get()->ForEachPlugin(Callback);
|
||||||
|
Content += "</ul>";
|
||||||
|
|
||||||
|
// Display a list of all players:
|
||||||
|
Content += "<h4>Players:</h4><ul>";
|
||||||
cPlayerAccum PlayerAccum;
|
cPlayerAccum PlayerAccum;
|
||||||
cWorld * World = cRoot::Get()->GetDefaultWorld(); // TODO - Create a list of worlds and players
|
cWorld * World = cRoot::Get()->GetDefaultWorld(); // TODO - Create a list of worlds and players
|
||||||
if (World != nullptr)
|
if (World != nullptr)
|
||||||
|
Loading…
Reference in New Issue
Block a user