2011-06-24 21:35:29 -06:00
|
|
|
/*
|
|
|
|
https://github.com/peterix/dfhack
|
|
|
|
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any
|
|
|
|
damages arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any
|
|
|
|
purpose, including commercial applications, and to alter it and
|
|
|
|
redistribute it freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must
|
|
|
|
not claim that you wrote the original software. If you use this
|
|
|
|
software in a product, an acknowledgment in the product documentation
|
|
|
|
would be appreciated but is not required.
|
|
|
|
|
|
|
|
2. Altered source versions must be plainly marked as such, and
|
|
|
|
must not be misrepresented as being the original software.
|
|
|
|
|
|
|
|
3. This notice may not be removed or altered from any source
|
|
|
|
distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2011-12-31 04:48:42 -07:00
|
|
|
#include "Export.h"
|
|
|
|
#include "Hooks.h"
|
2012-03-10 04:55:42 -07:00
|
|
|
#include "ColorText.h"
|
2011-06-24 21:35:29 -06:00
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2012-03-14 09:57:29 -06:00
|
|
|
|
|
|
|
#include "RemoteClient.h"
|
|
|
|
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
typedef struct lua_State lua_State;
|
|
|
|
|
2011-06-24 21:35:29 -06:00
|
|
|
struct DFLibrary;
|
2011-07-26 21:59:09 -06:00
|
|
|
namespace tthread
|
|
|
|
{
|
|
|
|
class mutex;
|
|
|
|
class condition_variable;
|
|
|
|
}
|
2011-12-30 12:25:50 -07:00
|
|
|
namespace df
|
|
|
|
{
|
|
|
|
struct viewscreen;
|
|
|
|
}
|
2011-06-24 21:35:29 -06:00
|
|
|
namespace DFHack
|
|
|
|
{
|
|
|
|
class Core;
|
|
|
|
class PluginManager;
|
2012-01-11 07:54:54 -07:00
|
|
|
class virtual_identity;
|
2012-03-15 03:01:23 -06:00
|
|
|
class RPCService;
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
class function_identity_base;
|
2011-12-30 12:25:50 -07:00
|
|
|
|
2011-12-30 07:12:15 -07:00
|
|
|
enum state_change_event
|
|
|
|
{
|
2012-03-31 18:56:54 -06:00
|
|
|
SC_WORLD_LOADED,
|
|
|
|
SC_WORLD_UNLOADED,
|
|
|
|
SC_MAP_LOADED,
|
|
|
|
SC_MAP_UNLOADED,
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
SC_VIEWSCREEN_CHANGED,
|
|
|
|
SC_CORE_INITIALIZED,
|
|
|
|
SC_BEGIN_UNLOAD
|
|
|
|
};
|
|
|
|
struct DFHACK_EXPORT CommandReg {
|
|
|
|
const char *name;
|
|
|
|
int (*command)(lua_State*);
|
|
|
|
};
|
|
|
|
struct DFHACK_EXPORT FunctionReg {
|
|
|
|
const char *name;
|
|
|
|
function_identity_base *identity;
|
2011-12-30 07:12:15 -07:00
|
|
|
};
|
2011-12-30 12:25:50 -07:00
|
|
|
struct DFHACK_EXPORT PluginCommand
|
2011-06-24 21:35:29 -06:00
|
|
|
{
|
2012-03-10 04:55:42 -07:00
|
|
|
typedef command_result (*command_function)(color_ostream &out, std::vector <std::string> &);
|
|
|
|
typedef bool (*command_hotkey_guard)(df::viewscreen *);
|
2011-12-31 02:25:46 -07:00
|
|
|
|
2011-08-05 20:37:29 -06:00
|
|
|
/// create a command with a name, description, function pointer to its code
|
|
|
|
/// and saying if it needs an interactive terminal
|
|
|
|
/// Most commands shouldn't require an interactive terminal!
|
2011-06-24 21:35:29 -06:00
|
|
|
PluginCommand(const char * _name,
|
|
|
|
const char * _description,
|
2011-12-30 12:25:50 -07:00
|
|
|
command_function function_,
|
2011-12-31 02:25:46 -07:00
|
|
|
bool interactive_ = false,
|
|
|
|
const char * usage_ = ""
|
2011-06-24 21:35:29 -06:00
|
|
|
)
|
2011-12-30 12:25:50 -07:00
|
|
|
: name(_name), description(_description),
|
|
|
|
function(function_), interactive(interactive_),
|
2011-12-31 02:25:46 -07:00
|
|
|
guard(NULL), usage(usage_)
|
2011-06-24 21:35:29 -06:00
|
|
|
{
|
|
|
|
}
|
2011-12-30 12:25:50 -07:00
|
|
|
|
|
|
|
PluginCommand(const char * _name,
|
|
|
|
const char * _description,
|
|
|
|
command_function function_,
|
|
|
|
command_hotkey_guard guard_,
|
2011-12-31 02:25:46 -07:00
|
|
|
const char * usage_ = "")
|
2011-12-30 12:25:50 -07:00
|
|
|
: name(_name), description(_description),
|
|
|
|
function(function_), interactive(false),
|
2011-12-31 02:25:46 -07:00
|
|
|
guard(guard_), usage(usage_)
|
2011-06-24 21:35:29 -06:00
|
|
|
{
|
|
|
|
}
|
2011-12-30 12:25:50 -07:00
|
|
|
|
2011-12-31 02:25:46 -07:00
|
|
|
bool isHotkeyCommand() const { return guard != NULL; }
|
|
|
|
|
2011-06-24 21:35:29 -06:00
|
|
|
std::string name;
|
|
|
|
std::string description;
|
2011-12-30 12:25:50 -07:00
|
|
|
command_function function;
|
2011-08-05 20:37:29 -06:00
|
|
|
bool interactive;
|
2011-12-30 12:25:50 -07:00
|
|
|
command_hotkey_guard guard;
|
2011-12-31 02:25:46 -07:00
|
|
|
std::string usage;
|
2011-06-24 21:35:29 -06:00
|
|
|
};
|
|
|
|
class Plugin
|
|
|
|
{
|
2011-07-18 08:22:49 -06:00
|
|
|
struct RefLock;
|
2012-02-21 10:19:17 -07:00
|
|
|
struct RefAutolock;
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
struct RefAutoinc;
|
2011-07-18 08:22:49 -06:00
|
|
|
enum plugin_state
|
|
|
|
{
|
|
|
|
PS_UNLOADED,
|
|
|
|
PS_LOADED,
|
|
|
|
PS_BROKEN
|
|
|
|
};
|
2011-06-24 21:35:29 -06:00
|
|
|
friend class PluginManager;
|
2012-03-15 03:01:23 -06:00
|
|
|
friend class RPCService;
|
2011-07-18 08:22:49 -06:00
|
|
|
Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm);
|
2011-06-24 21:35:29 -06:00
|
|
|
~Plugin();
|
2012-03-10 04:55:42 -07:00
|
|
|
command_result on_update(color_ostream &out);
|
|
|
|
command_result on_state_change(color_ostream &out, state_change_event event);
|
2012-03-15 03:01:23 -06:00
|
|
|
void detach_connection(RPCService *svc);
|
2011-07-18 08:22:49 -06:00
|
|
|
public:
|
2012-03-15 03:01:23 -06:00
|
|
|
bool load(color_ostream &out);
|
|
|
|
bool unload(color_ostream &out);
|
|
|
|
bool reload(color_ostream &out);
|
|
|
|
|
|
|
|
command_result invoke(color_ostream &out, const std::string & command, std::vector <std::string> & parameters);
|
|
|
|
bool can_invoke_hotkey(const std::string & command, df::viewscreen *top );
|
2011-07-18 08:22:49 -06:00
|
|
|
plugin_state getState () const;
|
2012-03-15 03:01:23 -06:00
|
|
|
|
|
|
|
RPCService *rpc_connect(color_ostream &out);
|
|
|
|
|
2011-06-26 20:49:56 -06:00
|
|
|
const PluginCommand& operator[] (std::size_t index) const
|
2011-06-25 00:05:17 -06:00
|
|
|
{
|
|
|
|
return commands[index];
|
|
|
|
};
|
2011-06-26 20:49:56 -06:00
|
|
|
std::size_t size() const
|
2011-06-25 00:05:17 -06:00
|
|
|
{
|
|
|
|
return commands.size();
|
|
|
|
}
|
2011-06-26 20:49:56 -06:00
|
|
|
const std::string & getName() const
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
|
|
|
|
void open_lua(lua_State *state, int table);
|
|
|
|
|
2011-06-24 21:35:29 -06:00
|
|
|
private:
|
2011-07-18 08:22:49 -06:00
|
|
|
RefLock * access;
|
2011-06-24 21:35:29 -06:00
|
|
|
std::vector <PluginCommand> commands;
|
2012-03-15 03:01:23 -06:00
|
|
|
std::vector <RPCService*> services;
|
2011-06-24 21:35:29 -06:00
|
|
|
std::string filename;
|
|
|
|
std::string name;
|
|
|
|
DFLibrary * plugin_lib;
|
2011-07-18 08:22:49 -06:00
|
|
|
PluginManager * parent;
|
|
|
|
plugin_state state;
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
|
|
|
|
struct LuaCommand {
|
|
|
|
Plugin *owner;
|
|
|
|
std::string name;
|
|
|
|
int (*command)(lua_State *state);
|
|
|
|
};
|
|
|
|
std::map<std::string, LuaCommand*> lua_commands;
|
|
|
|
static int lua_cmd_wrapper(lua_State *state);
|
|
|
|
|
|
|
|
struct LuaFunction {
|
|
|
|
Plugin *owner;
|
|
|
|
std::string name;
|
|
|
|
function_identity_base *identity;
|
|
|
|
};
|
|
|
|
std::map<std::string, LuaFunction*> lua_functions;
|
|
|
|
static int lua_fun_wrapper(lua_State *state);
|
|
|
|
|
|
|
|
void index_lua(DFLibrary *lib);
|
|
|
|
void reset_lua();
|
|
|
|
|
2012-03-10 04:55:42 -07:00
|
|
|
command_result (*plugin_init)(color_ostream &, std::vector <PluginCommand> &);
|
|
|
|
command_result (*plugin_status)(color_ostream &, std::string &);
|
|
|
|
command_result (*plugin_shutdown)(color_ostream &);
|
|
|
|
command_result (*plugin_onupdate)(color_ostream &);
|
|
|
|
command_result (*plugin_onstatechange)(color_ostream &, state_change_event);
|
2012-03-15 03:01:23 -06:00
|
|
|
RPCService* (*plugin_rpcconnect)(color_ostream &);
|
2011-06-24 21:35:29 -06:00
|
|
|
};
|
|
|
|
class DFHACK_EXPORT PluginManager
|
|
|
|
{
|
2011-07-09 03:33:58 -06:00
|
|
|
// PRIVATE METHODS
|
|
|
|
friend class Core;
|
2011-07-18 08:22:49 -06:00
|
|
|
friend class Plugin;
|
2011-06-24 21:35:29 -06:00
|
|
|
PluginManager(Core * core);
|
|
|
|
~PluginManager();
|
2012-03-10 04:55:42 -07:00
|
|
|
void OnUpdate(color_ostream &out);
|
|
|
|
void OnStateChange(color_ostream &out, state_change_event event);
|
2011-07-18 08:22:49 -06:00
|
|
|
void registerCommands( Plugin * p );
|
|
|
|
void unregisterCommands( Plugin * p );
|
2011-07-09 03:33:58 -06:00
|
|
|
// PUBLIC METHODS
|
|
|
|
public:
|
2011-07-18 08:22:49 -06:00
|
|
|
Plugin *getPluginByName (const std::string & name);
|
2011-12-30 12:25:50 -07:00
|
|
|
Plugin *getPluginByCommand (const std::string &command);
|
2012-03-15 03:01:23 -06:00
|
|
|
command_result InvokeCommand(color_ostream &out, const std::string & command, std::vector <std::string> & parameters);
|
|
|
|
bool CanInvokeHotkey(const std::string &command, df::viewscreen *top);
|
2011-07-18 08:22:49 -06:00
|
|
|
Plugin* operator[] (std::size_t index)
|
2011-06-25 00:05:17 -06:00
|
|
|
{
|
|
|
|
if(index >= all_plugins.size())
|
|
|
|
return 0;
|
|
|
|
return all_plugins[index];
|
|
|
|
};
|
|
|
|
std::size_t size()
|
|
|
|
{
|
|
|
|
return all_plugins.size();
|
|
|
|
}
|
2011-07-09 03:33:58 -06:00
|
|
|
// DATA
|
2011-06-24 21:35:29 -06:00
|
|
|
private:
|
2011-07-26 21:59:09 -06:00
|
|
|
tthread::mutex * cmdlist_mutex;
|
2011-07-18 08:22:49 -06:00
|
|
|
std::map <std::string, Plugin *> belongs;
|
2011-06-24 21:35:29 -06:00
|
|
|
std::vector <Plugin *> all_plugins;
|
|
|
|
std::string plugin_path;
|
|
|
|
};
|
2011-12-30 12:25:50 -07:00
|
|
|
|
2012-03-03 06:38:24 -07:00
|
|
|
namespace Gui
|
|
|
|
{
|
|
|
|
// Predefined hotkey guards
|
2012-03-10 04:55:42 -07:00
|
|
|
DFHACK_EXPORT bool default_hotkey(df::viewscreen *);
|
|
|
|
DFHACK_EXPORT bool dwarfmode_hotkey(df::viewscreen *);
|
|
|
|
DFHACK_EXPORT bool cursor_hotkey(df::viewscreen *);
|
2012-03-03 06:38:24 -07:00
|
|
|
}
|
2012-02-21 10:19:17 -07:00
|
|
|
};
|
2011-06-24 21:35:29 -06:00
|
|
|
|
2012-02-21 10:19:17 -07:00
|
|
|
/// You have to have this in every plugin you write - just once. Ideally on top of the main file.
|
Allow plugins to export functions to lua with safe reload support.
- To ensure reload safety functions have to be wrapped. Every call
checks the loaded state and locks a mutex in Plugin. If the plugin
is unloaded, calling its functions throws a lua error. Therefore,
plugins may not create closures or export yieldable functions.
- The set of function argument and return types supported by
LuaWrapper is severely limited when compared to being compiled
inside the main library.
Currently supported types: numbers, bool, std::string, df::foo,
df::foo*, std::vector<bool>, std::vector<df::foo*>.
- To facilitate postponing initialization until after all plugins
have been loaded, the core sends a SC_CORE_INITIALIZED event.
- As an example, the burrows plugin now exports its functions.
2012-04-14 09:44:07 -06:00
|
|
|
#define DFHACK_PLUGIN(plugin_name) \
|
|
|
|
DFhackDataExport const char * version = DFHACK_VERSION;\
|
|
|
|
DFhackDataExport const char * name = plugin_name;
|
|
|
|
|
|
|
|
#define DFHACK_PLUGIN_LUA_COMMANDS \
|
|
|
|
DFhackCExport const DFHack::CommandReg plugin_lua_commands[] =
|
|
|
|
#define DFHACK_PLUGIN_LUA_FUNCTIONS \
|
|
|
|
DFhackCExport const DFHack::FunctionReg plugin_lua_functions[] =
|
|
|
|
|
|
|
|
#define DFHACK_LUA_COMMAND(name) { #name, name }
|
|
|
|
#define DFHACK_LUA_FUNCTION(name) { #name, df::wrap_function(name) }
|
|
|
|
#define DFHACK_LUA_END { NULL, NULL }
|