Add built-in enable and disable commands.

develop
Alexander Gavrilov 2013-09-30 13:19:51 +04:00
parent a487ede2b9
commit d7e35c2d23
37 changed files with 607 additions and 114 deletions

@ -209,6 +209,25 @@ or is a prefix ending at a '/' boundary would be considered for execution, i.e.
for context ``foo/bar/baz``, possible matches are any of ``@foo/bar/baz``, ``@foo/bar``,
``@foo`` or none.
Enabling plugins
================
Many plugins can be in a distinct enabled or disabled state. Some of
them activate and deactivate automatically depending on the contents
of the world raws. Others store their state in world data. However a
number of them have to be enabled globally, and the init file is the
right place to do it.
Most of such plugins support the built-in ``enable`` and ``disable``
commands. Calling them at any time without arguments prints a list
of enabled and disabled plugins, and shows whether that can be changed
through the same commands.
To enable or disable plugins that support this, use their names as
arguments for the command::
enable manipulator search
========
Commands

@ -150,8 +150,24 @@ tweak military-training
# prevent crash if bees die in a hive with ungathered products by insta-gathering them
tweak hive-crash
# enable autoSyndrome
autoSyndrome enable
###########################
# Globally acting plugins #
###########################
# Dwarf Manipulator (simple in-game Dwarf Therapist replacement)
enable manipulator
# Search tool in various screens (by falconne)
enable search
# Improved build material selection interface (by falconne)
enable automaterial
# Other interface improvement tools
#enable dwarfmonitor mousequery autotrade buildingplan resume zone
# Auto Syndrome
#autoSyndrome enable
###########
# Scripts #

@ -544,6 +544,56 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
}
}
}
else if( first == "enable" || first == "disable" )
{
CoreSuspender suspend;
bool enable = (first == "enable");
if(parts.size())
{
command_result res = CR_OK;
for (size_t i = 0; i < parts.size(); i++)
{
Plugin * plug = plug_mgr->getPluginByName(parts[i]);
if(!plug)
{
res = CR_NOT_FOUND;
con.printerr("No such plugin: %s\n", parts[i].c_str());
}
else if (!plug->can_set_enabled())
{
res = CR_NOT_IMPLEMENTED;
con.printerr("Cannot %s plugin: %s\n", first.c_str(), parts[i].c_str());
}
else
{
res = plug->set_enabled(con, enable);
if (res != CR_OK || plug->is_enabled() != enable)
con.printerr("Could not %s plugin: %s\n", first.c_str(), parts[i].c_str());
}
}
return res;
}
else
{
for(size_t i = 0; i < plug_mgr->size();i++)
{
Plugin * plug = (plug_mgr->operator[](i));
if (!plug->can_be_enabled()) continue;
con.print(
"%20s\t%-3s%s\n",
(plug->getName()+":").c_str(),
plug->is_enabled() ? "on" : "off",
plug->can_set_enabled() ? "" : " (controlled elsewhere)"
);
}
}
}
else if(first == "ls" || first == "dir")
{
bool all = false;
@ -584,6 +634,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
" load PLUGIN|all - Load a plugin by name or load all possible plugins.\n"
" unload PLUGIN|all - Unload a plugin or all loaded plugins.\n"
" reload PLUGIN|all - Reload a plugin or all loaded plugins.\n"
" enable/disable PLUGIN - Enable or disable a plugin if supported.\n"
"\n"
"plugins:\n"
);

@ -172,6 +172,8 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f
plugin_onupdate = 0;
plugin_onstatechange = 0;
plugin_rpcconnect = 0;
plugin_enable = 0;
plugin_is_enabled = 0;
state = PS_UNLOADED;
access = new RefLock();
}
@ -245,6 +247,8 @@ bool Plugin::load(color_ostream &con)
plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown");
plugin_onstatechange = (command_result (*)(color_ostream &, state_change_event)) LookupPlugin(plug, "plugin_onstatechange");
plugin_rpcconnect = (RPCService* (*)(color_ostream &)) LookupPlugin(plug, "plugin_rpcconnect");
plugin_enable = (command_result (*)(color_ostream &,bool)) LookupPlugin(plug, "plugin_enable");
plugin_is_enabled = (bool*) LookupPlugin(plug, "plugin_is_enabled");
plugin_eval_ruby = (command_result (*)(color_ostream &, const char*)) LookupPlugin(plug, "plugin_eval_ruby");
index_lua(plug);
this->name = *plug_name;
@ -254,11 +258,15 @@ bool Plugin::load(color_ostream &con)
{
state = PS_LOADED;
parent->registerCommands(this);
if ((plugin_onupdate || plugin_enable) && !plugin_is_enabled)
con.printerr("Plugin %s has no enabled var!\n", name.c_str());
return true;
}
else
{
con.printerr("Plugin %s has failed to initialize properly.\n", filename.c_str());
plugin_is_enabled = 0;
plugin_onupdate = 0;
reset_lua();
ClosePlugin(plugin_lib);
state = PS_BROKEN;
@ -294,6 +302,8 @@ bool Plugin::unload(color_ostream &con)
if(plugin_shutdown)
cr = plugin_shutdown(con);
// cleanup...
plugin_is_enabled = 0;
plugin_onupdate = 0;
reset_lua();
parent->unregisterCommands(this);
commands.clear();
@ -408,6 +418,12 @@ bool Plugin::can_invoke_hotkey(const std::string & command, df::viewscreen *top
command_result Plugin::on_update(color_ostream &out)
{
// Check things that are implicitly protected by the suspend lock
if (!plugin_onupdate)
return CR_NOT_IMPLEMENTED;
if (plugin_is_enabled && !*plugin_is_enabled)
return CR_OK;
// Grab mutex and call the thing
command_result cr = CR_NOT_IMPLEMENTED;
access->lock_add();
if(state == PS_LOADED && plugin_onupdate)
@ -419,6 +435,21 @@ command_result Plugin::on_update(color_ostream &out)
return cr;
}
command_result Plugin::set_enabled(color_ostream &out, bool enable)
{
command_result cr = CR_NOT_IMPLEMENTED;
access->lock_add();
if(state == PS_LOADED && plugin_is_enabled && plugin_enable)
{
cr = plugin_enable(out, enable);
if (cr == CR_OK && enable != is_enabled())
cr = CR_FAILURE;
}
access->lock_sub();
return cr;
}
command_result Plugin::on_state_change(color_ostream &out, state_change_event event)
{
command_result cr = CR_NOT_IMPLEMENTED;
@ -524,6 +555,37 @@ void Plugin::reset_lua()
}
}
int Plugin::lua_is_enabled(lua_State *state)
{
auto obj = (Plugin*)lua_touserdata(state, lua_upvalueindex(1));
RefAutoinc lock(obj->access);
if (obj->state == PS_LOADED && obj->plugin_is_enabled)
lua_pushboolean(state, obj->is_enabled());
else
lua_pushnil(state);
return 1;
}
int Plugin::lua_set_enabled(lua_State *state)
{
lua_settop(state, 1);
bool val = lua_toboolean(state, 1);
auto obj = (Plugin*)lua_touserdata(state, lua_upvalueindex(1));
RefAutoinc lock(obj->access);
color_ostream *out = Lua::GetOutput(state);
if (obj->state == PS_LOADED && obj->plugin_enable)
lua_pushboolean(state, obj->set_enabled(*out, val) == CR_OK);
else
luaL_error(state, "plugin %s unloaded, cannot enable or disable", obj->name.c_str());
return 1;
}
int Plugin::lua_cmd_wrapper(lua_State *state)
{
auto cmd = (LuaCommand*)lua_touserdata(state, lua_upvalueindex(1));
@ -561,6 +623,19 @@ void Plugin::open_lua(lua_State *state, int table)
RefAutolock lock(access);
if (plugin_is_enabled)
{
lua_pushlightuserdata(state, this);
lua_pushcclosure(state, lua_is_enabled, 1);
lua_setfield(state, table, "isEnabled");
}
if (plugin_enable)
{
lua_pushlightuserdata(state, this);
lua_pushcclosure(state, lua_set_enabled, 1);
lua_setfield(state, table, "setEnabled");
}
for (auto it = lua_commands.begin(); it != lua_commands.end(); ++it)
{
lua_pushlightuserdata(state, it->second);

@ -144,6 +144,11 @@ namespace DFHack
bool unload(color_ostream &out);
bool reload(color_ostream &out);
bool can_be_enabled() { return plugin_is_enabled != 0; }
bool is_enabled() { return plugin_is_enabled && *plugin_is_enabled; }
bool can_set_enabled() { return plugin_is_enabled != 0 && plugin_enable; }
command_result set_enabled(color_ostream &out, bool enable);
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 );
plugin_state getState () const;
@ -184,17 +189,22 @@ namespace DFHack
static int lua_fun_wrapper(lua_State *state);
void push_function(lua_State *state, LuaFunction *fn);
static int lua_is_enabled(lua_State *state);
static int lua_set_enabled(lua_State *state);
struct LuaEvent;
std::map<std::string, LuaEvent*> lua_events;
void index_lua(DFLibrary *lib);
void reset_lua();
bool *plugin_is_enabled;
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);
command_result (*plugin_enable)(color_ostream &, bool);
RPCService* (*plugin_rpcconnect)(color_ostream &);
command_result (*plugin_eval_ruby)(color_ostream &, const char*);
};
@ -250,6 +260,10 @@ namespace DFHack
DFhackDataExport const char * name = plugin_name;\
DFhackDataExport Plugin *plugin_self = NULL;
#define DFHACK_PLUGIN_IS_ENABLED(varname) \
DFhackDataExport bool plugin_is_enabled = false; \
bool &varname = plugin_is_enabled;
#define DFHACK_PLUGIN_LUA_COMMANDS \
DFhackCExport const DFHack::CommandReg plugin_lua_commands[] =
#define DFHACK_PLUGIN_LUA_FUNCTIONS \

@ -48,6 +48,7 @@ using df::global::ui;
typedef df::reaction_product_item_improvementst improvement_product;
DFHACK_PLUGIN("add-spatter");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct ReagentSource {
int idx;
@ -390,6 +391,7 @@ static bool find_reactions(color_ostream &out)
static void enable_hooks(bool enable)
{
is_enabled = enable;
INTERPOSE_HOOK(item_hook, isImprovable).apply(enable);
INTERPOSE_HOOK(product_hook, produce).apply(enable);
}

@ -99,7 +99,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
df::nemesis_record *getPlayerNemesis(color_ostream &out, bool restore_swap);
static bool in_transient_swap = false;
DFHACK_PLUGIN_IS_ENABLED(in_transient_swap);
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{

@ -98,7 +98,7 @@ reaction_duck
Next, start a new fort in a new world, build a duck workshop, then have someone become a duck.
*/
bool enabled = false;
DFHACK_PLUGIN_IS_ENABLED(enabled);
DFHACK_PLUGIN("autoSyndrome");
@ -139,37 +139,45 @@ DFhackCExport command_result plugin_shutdown(color_ostream& out) {
return CR_OK;
}*/
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (enabled == enable)
return CR_OK;
enabled = enable;
Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("autoSyndrome");
if ( enabled ) {
EventManager::EventHandler handle(processJob, 5);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, handle, me);
} else {
EventManager::unregisterAll(me);
}
return CR_OK;
}
command_result autoSyndrome(color_ostream& out, vector<string>& parameters) {
if ( parameters.size() > 1 )
return CR_WRONG_USAGE;
bool wasEnabled = enabled;
bool enable = false;
if ( parameters.size() == 1 ) {
if ( parameters[0] == "enable" ) {
enabled = true;
enable = true;
} else if ( parameters[0] == "disable" ) {
enabled = false;
enable = false;
} else {
int32_t a = atoi(parameters[0].c_str());
if ( a < 0 || a > 1 )
return CR_WRONG_USAGE;
enabled = (bool)a;
enable = (bool)a;
}
}
out.print("autoSyndrome is %s\n", enabled ? "enabled" : "disabled");
if ( enabled == wasEnabled )
return CR_OK;
Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("autoSyndrome");
if ( enabled ) {
EventManager::EventHandler handle(processJob, 5);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, handle, me);
} else {
EventManager::unregisterAll(me);
}
return CR_OK;
out.print("autoSyndrome is %s\n", enable ? "enabled" : "disabled");
return plugin_enable(out, enable);
}
bool maybeApply(color_ostream& out, df::syndrome* syndrome, int32_t workerId, df::unit* unit) {

@ -76,7 +76,7 @@ using df::global::world;
* (mining, hunting, and woodcutting) need to be handled carefully to minimize churn.
*/
static int enable_autolabor = 0;
DFHACK_PLUGIN_IS_ENABLED(enable_autolabor);
static bool print_debug = 0;
@ -535,6 +535,7 @@ static void setOptionEnabled(ConfigFlags flag, bool on)
static void cleanup_state()
{
enable_autolabor = false;
labor_infos.clear();
}
@ -1297,6 +1298,27 @@ void print_labor (df::unit_labor labor, color_ostream &out)
}
}
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable )
{
if (!Core::getInstance().isWorldLoaded()) {
out.printerr("World is not loaded: please load a game first.\n");
return CR_FAILURE;
}
if (enable && !enable_autolabor)
{
enable_plugin(out);
}
else if(!enable && enable_autolabor)
{
enable_autolabor = false;
setOptionEnabled(CF_ENABLED, false);
out << "Autolabor is disabled." << endl;
}
return CR_OK;
}
command_result autolabor (color_ostream &out, std::vector <std::string> & parameters)
{
@ -1312,19 +1334,8 @@ command_result autolabor (color_ostream &out, std::vector <std::string> & parame
parameters[0] == "1" || parameters[0] == "disable"))
{
bool enable = (parameters[0] == "1" || parameters[0] == "enable");
if (enable && !enable_autolabor)
{
enable_plugin(out);
}
else if(!enable && enable_autolabor)
{
enable_autolabor = false;
setOptionEnabled(CF_ENABLED, false);
out << "The plugin is disabled." << endl;
}
return CR_OK;
return plugin_enable(out, enable);
}
else if (parameters.size() == 2 && parameters[0] == "haulpct")
{

@ -1179,11 +1179,27 @@ color_ostream_proxy console_out(Core::getInstance().getConsole());
IMPLEMENT_VMETHOD_INTERPOSE(jobutils_hook, feed);
IMPLEMENT_VMETHOD_INTERPOSE(jobutils_hook, render);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
if (!gps || !INTERPOSE_HOOK(jobutils_hook, feed).apply() || !INTERPOSE_HOOK(jobutils_hook, render).apply())
out.printerr("Could not insert jobutils hooks!\n");
if (!gps)
return CR_FAILURE;
if (enable != is_enabled)
{
if (!INTERPOSE_HOOK(jobutils_hook, feed).apply(enable) ||
!INTERPOSE_HOOK(jobutils_hook, render).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
hotkeys[construction_type::Wall] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_WALL;
hotkeys[construction_type::Floor] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_FLOOR;
hotkeys[construction_type::Ramp] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_RAMP;

@ -583,7 +583,6 @@ static command_result autotrade_cmd(color_ostream &out, vector <string> & parame
return CR_OK;
}
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{
switch (event)
@ -600,11 +599,30 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (!gps || !INTERPOSE_HOOK(trade_hook, feed).apply() || !INTERPOSE_HOOK(trade_hook, render).apply())
out.printerr("Could not insert autotrade hooks!\n");
if (!gps)
return CR_FAILURE;
if (enable != is_enabled)
{
depot_info.reset();
monitor.reset();
if (!INTERPOSE_HOOK(trade_hook, feed).apply(enable) ||
!INTERPOSE_HOOK(trade_hook, render).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(
PluginCommand(
"autotrade", "Automatically send items in marked stockpiles to trade depot, when trading is possible.",

@ -1153,12 +1153,29 @@ static command_result buildingplan_cmd(color_ostream &out, vector <string> & par
return CR_OK;
}
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (!gps || !INTERPOSE_HOOK(buildingplan_hook, feed).apply() || !INTERPOSE_HOOK(buildingplan_hook, render).apply())
out.printerr("Could not insert buildingplan hooks!\n");
if (!gps)
return CR_FAILURE;
if (enable != is_enabled)
{
planner.reset(out);
if (!INTERPOSE_HOOK(buildingplan_hook, feed).apply(enable) ||
!INTERPOSE_HOOK(buildingplan_hook, render).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(
PluginCommand(
"buildingplan", "Place furniture before it's built",

@ -221,7 +221,8 @@ static void detect_digging(color_ostream &out)
}
}
static bool active = false;
DFHACK_PLUGIN_IS_ENABLED(active);
static bool auto_grow = false;
static std::vector<int> grow_burrows;

@ -76,7 +76,7 @@ using df::global::world;
#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
static int enable_autolabor = 0;
DFHACK_PLUGIN_IS_ENABLED(enable_autolabor);
static bool print_debug = 0;
@ -1375,6 +1375,7 @@ static void setOptionEnabled(ConfigFlags flag, bool on)
static void cleanup_state()
{
enable_autolabor = false;
labor_infos.clear();
}
@ -2384,6 +2385,27 @@ df::unit_labor lookup_labor_by_name (std::string& name)
return labor;
}
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable )
{
if (!Core::getInstance().isWorldLoaded()) {
out.printerr("World is not loaded: please load a game first.\n");
return CR_FAILURE;
}
if (enable && !enable_autolabor)
{
enable_plugin(out);
}
else if(!enable && enable_autolabor)
{
enable_autolabor = false;
setOptionEnabled(CF_ENABLED, false);
out << "Autolabor is disabled." << endl;
}
return CR_OK;
}
command_result autolabor (color_ostream &out, std::vector <std::string> & parameters)
{
@ -2398,19 +2420,7 @@ command_result autolabor (color_ostream &out, std::vector <std::string> & parame
(parameters[0] == "enable" || parameters[0] == "disable"))
{
bool enable = (parameters[0] == "enable");
if (enable && !enable_autolabor)
{
enable_plugin(out);
}
else if(!enable && enable_autolabor)
{
enable_autolabor = false;
setOptionEnabled(CF_ENABLED, false);
out << "The plugin is disabled." << endl;
}
return CR_OK;
return plugin_enable(out, enable);
}
else if (parameters.size() == 3 &&
(parameters[0] == "max" || parameters[0] == "priority"))

@ -16,6 +16,8 @@ using std::vector;
using std::string;
using namespace DFHack;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
//FIXME: possible race conditions with calling kittens from the IO thread and shutdown from Core.
bool shutdown_flag = false;
bool final_flag = true;
@ -141,6 +143,7 @@ command_result trackmenu (color_ostream &out, vector <string> & parameters)
if(df::global::ui)
{
trackmenu_flg = true;
is_enabled = true;
last_menu = df::global::ui->main.mode;
out.print("Menu: %d\n",last_menu);
return CR_OK;
@ -155,6 +158,7 @@ command_result trackmenu (color_ostream &out, vector <string> & parameters)
command_result trackpos (color_ostream &out, vector <string> & parameters)
{
trackpos_flg = !trackpos_flg;
is_enabled = true;
return CR_OK;
}
@ -214,6 +218,7 @@ command_result ktimer (color_ostream &out, vector <string> & parameters)
// harmless potential data race here...
timeLast = timeend;
timering = true;
is_enabled = true;
return CR_OK;
}

@ -15,6 +15,8 @@ using namespace DFHack;
uint64_t timeLast=0;
static tthread::mutex* mymutex=0;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct memory_data
{
void * addr;
@ -96,6 +98,7 @@ void Deinit()
{
if(memdata.state==STATE_ON)
{
is_enabled = false;
memdata.state=STATE_OFF;
delete [] memdata.buf;
delete [] memdata.lbuf;
@ -140,6 +143,7 @@ command_result memview (color_ostream &out, vector <string> & parameters)
{
Deinit();
memdata.state=STATE_OFF;
is_enabled = false;
mymutex->unlock();
return CR_OK;
}
@ -156,6 +160,7 @@ command_result memview (color_ostream &out, vector <string> & parameters)
mymutex->unlock();
return CR_OK;
}
is_enabled = true;
memdata.state=STATE_ON;
}
if(parameters.size()>1)

@ -31,7 +31,7 @@ static command_result nestboxes(color_ostream &out, vector <string> & parameters
DFHACK_PLUGIN("nestboxes");
static bool enabled = false;
DFHACK_PLUGIN_IS_ENABLED(enabled);
static void eggscan(color_ostream &out)
{
@ -97,6 +97,12 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
return CR_OK;
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
enabled = enable;
return CR_OK;
}
static command_result nestboxes(color_ostream &out, vector <string> & parameters)
{
CoreSuspender suspend;

@ -23,6 +23,8 @@ using df::global::gps;
DFHACK_PLUGIN("vshook");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct title_hook : df::viewscreen_titlest {
typedef df::viewscreen_titlest interpose_base;
@ -37,17 +39,30 @@ struct title_hook : df::viewscreen_titlest {
IMPLEMENT_VMETHOD_INTERPOSE(title_hook, render);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
if (gps)
if (!gps)
return CR_FAILURE;
if (enable != is_enabled)
{
if (!INTERPOSE_HOOK(title_hook, render).apply())
out.printerr("Could not interpose viewscreen_titlest::render\n");
if (!INTERPOSE_HOOK(title_hook, render).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
// DON'T DO THIS IN NON-EXAMPLE PLUGINS
plugin_enable(out, true);
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
INTERPOSE_HOOK(title_hook, render).remove();

@ -1179,11 +1179,15 @@ IMPLEMENT_VMETHOD_INTERPOSE(dwarf_monitor_hook, feed);
IMPLEMENT_VMETHOD_INTERPOSE(dwarf_monitor_hook, render);
DFHACK_PLUGIN("dwarfmonitor");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
static bool set_monitoring_mode(const string &mode, const bool &state)
{
bool mode_recognized = false;
if (!is_enabled)
return false;
if (mode == "work" || mode == "all")
{
mode_recognized = true;
@ -1201,6 +1205,24 @@ static bool set_monitoring_mode(const string &mode, const bool &state)
return mode_recognized;
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (!gps)
return CR_FAILURE;
if (is_enabled != enable)
{
if (!INTERPOSE_HOOK(dwarf_monitor_hook, feed).apply(enable) ||
!INTERPOSE_HOOK(dwarf_monitor_hook, render).apply(enable))
return CR_FAILURE;
reset();
is_enabled = enable;
}
return CR_OK;
}
static command_result dwarfmonitor_cmd(color_ostream &out, vector <string> & parameters)
{
bool show_help = false;
@ -1222,6 +1244,9 @@ static command_result dwarfmonitor_cmd(color_ostream &out, vector <string> & par
}
else if ((cmd == 'e' || cmd == 'E') && !mode.empty())
{
if (!is_enabled)
plugin_enable(out, true);
if (set_monitoring_mode(mode, true))
{
out << "Monitoring enabled: " << mode << endl;
@ -1257,9 +1282,6 @@ static command_result dwarfmonitor_cmd(color_ostream &out, vector <string> & par
DFhackCExport command_result plugin_init(color_ostream &out, std::vector <PluginCommand> &commands)
{
if (!gps || !INTERPOSE_HOOK(dwarf_monitor_hook, feed).apply() || !INTERPOSE_HOOK(dwarf_monitor_hook, render).apply())
out.printerr("Could not insert dwarfmonitor hooks!\n");
activity_labels[JOB_IDLE] = "Idle";
activity_labels[JOB_MILITARY] = "Military Duty";
activity_labels[JOB_LEISURE] = "Leisure";

@ -19,6 +19,8 @@ using df::global::world;
// dfhack interface
DFHACK_PLUGIN("fastdwarf");
DFHACK_PLUGIN_IS_ENABLED(active);
static bool enable_fastdwarf = false;
static bool enable_teledwarf = false;
@ -152,6 +154,8 @@ static command_result fastdwarf (color_ostream &out, vector <string> & parameter
return CR_WRONG_USAGE;
}
active = enable_fastdwarf || enable_teledwarf;
out.print("Current state: fast = %d, teleport = %d.\n",
(df::global::debug_turbospeed && *df::global::debug_turbospeed) ? 2 : (enable_fastdwarf ? 1 : 0),
enable_teledwarf ? 1 : 0);
@ -159,6 +163,17 @@ static command_result fastdwarf (color_ostream &out, vector <string> & parameter
return CR_OK;
}
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable )
{
if (active != enable)
{
active = enable_fastdwarf = enable;
enable_teledwarf = false;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("fastdwarf",

@ -698,7 +698,7 @@ static void try_store_ammo(df::squad *squad)
}
}
static bool is_enabled = false;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_onupdate(color_ostream &out, state_change_event event)
{
@ -810,6 +810,21 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
return CR_OK;
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (!Core::getInstance().isWorldLoaded()) {
out.printerr("World is not loaded: please load a game first.\n");
return CR_FAILURE;
}
if (enable)
enable_plugin(out);
else
disable_plugin(out);
return CR_OK;
}
static command_result fix_armory(color_ostream &out, vector <string> &parameters)
{
CoreSuspender suspend;
@ -820,13 +835,9 @@ static command_result fix_armory(color_ostream &out, vector <string> &parameters
string cmd = parameters[0];
if (cmd == "enable")
{
enable_plugin(out);
}
return plugin_enable(out, true);
else if (cmd == "disable")
{
disable_plugin(out);
}
return plugin_enable(out, false);
else
return CR_WRONG_USAGE;

@ -24,6 +24,7 @@ int32_t prevX, prevY, prevZ;
uint8_t prevMenuWidth;
DFHACK_PLUGIN("follow");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
@ -53,6 +54,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
followedUnit = 0;
prevX=prevY=prevZ = -1;
prevMenuWidth = 0;
is_enabled = false;
break;
default:
break;
@ -97,6 +99,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
}
else if((prevX != x || prevY != y || prevZ != z) && prevMenuWidth == menu_width) //User has manually moved the window, stop following the unit
{
is_enabled = false;
followedUnit = 0;
prevX=prevY=prevZ = -1;
prevMenuWidth = 0;
@ -146,6 +149,7 @@ command_result follow (color_ostream &out, std::vector <std::string> & parameter
followedUnit = Gui::getSelectedUnit(out);
if (followedUnit)
{
is_enabled = true;
std::ostringstream ss;
ss << "Unpause to begin following " << df::global::world->raws.creatures.all[followedUnit->race]->name[0];
if (followedUnit->name.has_name) ss << " " << followedUnit->name.first_name;
@ -153,5 +157,6 @@ command_result follow (color_ostream &out, std::vector <std::string> & parameter
out.print(ss.str().c_str());
}
else followedUnit = 0;
is_enabled = (followedUnit != NULL);
return CR_OK;
}

@ -71,7 +71,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
*/
static size_t constructionSize = 0;
static bool enabled = false;
DFHACK_PLUGIN_IS_ENABLED(enabled);
void doInfiniteSky(color_ostream& out, int32_t howMany);
DFhackCExport command_result plugin_onupdate ( color_ostream &out )
@ -155,6 +155,12 @@ void doInfiniteSky(color_ostream& out, int32_t howMany) {
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
enabled = enable;
return CR_OK;
}
command_result infiniteSky (color_ostream &out, std::vector <std::string> & parameters)
{
if ( parameters.size() > 1 )

@ -1209,10 +1209,27 @@ IMPLEMENT_VMETHOD_INTERPOSE(unitlist_hook, render);
DFHACK_PLUGIN("manipulator");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (!gps)
return CR_FAILURE;
if (enable != is_enabled)
{
if (!INTERPOSE_HOOK(unitlist_hook, feed).apply(enable) ||
!INTERPOSE_HOOK(unitlist_hook, render).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{
if (!gps || !INTERPOSE_HOOK(unitlist_hook, feed).apply() || !INTERPOSE_HOOK(unitlist_hook, render).apply())
out.printerr("Could not insert Dwarf Manipulator hooks!\n");
return CR_OK;
}

@ -15,6 +15,8 @@ using namespace std;
using namespace DFHack;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
static int factor = 1;
static map<int, int> processedThoughtCountTable;
@ -38,6 +40,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
if ( wasLoaded ) {
//we just unloaded the game: clear all data
factor = 1;
is_enabled = false;
processedThoughtCountTable.clear();
fakeThoughts.clear();
wasLoaded = false;
@ -138,6 +141,17 @@ DFhackCExport command_result plugin_init(color_ostream& out, vector<PluginComman
return CR_OK;
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (enable != is_enabled)
{
is_enabled = enable;
factor = enable ? 2 : 1;
}
return CR_OK;
}
command_result misery(color_ostream &out, vector<string>& parameters) {
if ( !df::global::world || !df::global::world->map.block_index ) {
out.printerr("misery can only be enabled in fortress mode with a fully-loaded game.\n");
@ -153,15 +167,18 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
return CR_WRONG_USAGE;
}
factor = 1;
is_enabled = false;
return CR_OK;
} else if ( parameters[0] == "enable" ) {
is_enabled = true;
factor = 2;
if ( parameters.size() == 2 ) {
factor = atoi(parameters[1].c_str());
if ( factor < 1 ) {
int a = atoi(parameters[1].c_str());
if ( a <= 1 ) {
out.printerr("Second argument must be a positive integer.\n");
return CR_WRONG_USAGE;
}
factor = a;
}
} else if ( parameters[0] == "clear" ) {
for ( size_t a = 0; a < fakeThoughts.size(); a++ ) {
@ -176,6 +193,7 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
return CR_WRONG_USAGE;
}
factor = a;
is_enabled = factor > 1;
}
return CR_OK;

@ -33,12 +33,6 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
return CR_OK;
}
DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{
// add tracking here
return CR_OK;
}
void printCurrentModes(t_gamemodes gm, Console & con)
{
con << "Current game type:\t" << gm.g_type << " (";

@ -239,12 +239,28 @@ struct mousequery_hook : public df::viewscreen_dwarfmodest
IMPLEMENT_VMETHOD_INTERPOSE(mousequery_hook, feed);
DFHACK_PLUGIN("mousequery");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
if (!gps || !INTERPOSE_HOOK(mousequery_hook, feed).apply())
out.printerr("Could not insert mousequery hooks!\n");
if (!gps)
return CR_FAILURE;
if (is_enabled != enable)
{
last_x = last_y = last_z = -1;
if (!INTERPOSE_HOOK(mousequery_hook, feed).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
last_x = last_y = last_z = -1;
return CR_OK;

@ -160,7 +160,7 @@ IMPLEMENT_VMETHOD_INTERPOSE(trap_hook, getName);
IMPLEMENT_VMETHOD_INTERPOSE(trap_hook, updateAction);
IMPLEMENT_VMETHOD_INTERPOSE(trap_hook, drawBuilding);
static bool enabled = false;
DFHACK_PLUGIN_IS_ENABLED(enabled);
static void enable_hooks(bool enable)
{

@ -55,6 +55,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
static command_result rename(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("rename");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
@ -174,6 +175,9 @@ KNOWN_BUILDINGS
static bool enable_building_rename(char code, bool enable)
{
if (enable)
is_enabled = true;
if (code == 'Z')
INTERPOSE_HOOK(dwarf_render_zone_hook, render).apply(enable);
@ -189,6 +193,7 @@ KNOWN_BUILDINGS
static void disable_building_rename()
{
is_enabled = false;
INTERPOSE_HOOK(dwarf_render_zone_hook, render).remove();
#define BUILDING(code, cname, tag) \

@ -107,7 +107,7 @@ struct SuspendedBuilding
}
};
static bool enabled = false;
DFHACK_PLUGIN_IS_ENABLED(enabled);
static bool buildings_scanned = false;
static vector<SuspendedBuilding> suspended_buildings, resumed_buildings;
@ -234,6 +234,23 @@ struct resume_hook : public df::viewscreen_dwarfmodest
IMPLEMENT_VMETHOD_INTERPOSE(resume_hook, render);
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
if (!gps)
return CR_FAILURE;
if (enabled != enable)
{
clear_scanned();
if (!INTERPOSE_HOOK(resume_hook, render).apply(enable))
return CR_FAILURE;
enabled = enable;
}
return CR_OK;
}
static command_result resume_cmd(color_ostream &out, vector <string> & parameters)
{
@ -251,12 +268,12 @@ static command_result resume_cmd(color_ostream &out, vector <string> & parameter
}
else if (cmd == 's')
{
enabled = true;
plugin_enable(out, true);
out << "Overlay enabled" << endl;
}
else if (cmd == 'h')
{
enabled = false;
plugin_enable(out, false);
out << "Overlay disabled" << endl;
}
else if (cmd == 'a')
@ -275,12 +292,8 @@ static command_result resume_cmd(color_ostream &out, vector <string> & parameter
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
if (!gps || !INTERPOSE_HOOK(resume_hook, render).apply())
out.printerr("Could not insert resume hooks!\n");
commands.push_back(
PluginCommand(
"resume", "A plugin to help display and resume suspended constructions conveniently",

@ -85,6 +85,8 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
return CR_OK;
}
DFHACK_PLUGIN_IS_ENABLED(is_active);
DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{
t_gamemodes gm;
@ -117,6 +119,7 @@ command_result nopause (color_ostream &out, vector <string> & parameters)
nopause_state = 0;
else
nopause_state = 1;
is_active = nopause_state || (revealed == REVEALED);
out.print("nopause %sactivated.\n", (nopause_state ? "" : "de"));
}
else
@ -237,6 +240,7 @@ command_result reveal(color_ostream &out, vector<string> & params)
else
revealed = DEMON_REVEALED;
}
is_active = nopause_state || (revealed == REVEALED);
con.print("Map revealed.\n");
if(!no_hell)
con.print("Unpausing can unleash the forces of hell, so it has been temporarily disabled.\n");
@ -296,6 +300,7 @@ command_result unreveal(color_ostream &out, vector<string> & params)
// give back memory.
hidesaved.clear();
revealed = NOT_REVEALED;
is_active = nopause_state || (revealed == REVEALED);
con.print("Map hidden!\n");
return CR_OK;
}
@ -490,6 +495,7 @@ command_result revforget(color_ostream &out, vector<string> & params)
// give back memory.
hidesaved.clear();
revealed = NOT_REVEALED;
is_active = nopause_state || (revealed == REVEALED);
con.print("Reveal data forgotten!\n");
return CR_OK;
}

@ -1609,6 +1609,7 @@ IMPLEMENT_HOOKS(df::viewscreen_dwarfmodest, burrow_search);
DFHACK_PLUGIN("search");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
#define SEARCH_HOOKS \
HOOK_ACTION(unitlist_search_hook) \
@ -1624,15 +1625,28 @@ DFHACK_PLUGIN("search");
HOOK_ACTION(burrow_search_hook) \
HOOK_ACTION(stockpile_search_hook)
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
if (!gps || !gview)
return CR_FAILURE;
if (is_enabled != enable)
{
#define HOOK_ACTION(hook) \
!INTERPOSE_HOOK(hook, feed).apply() || \
!INTERPOSE_HOOK(hook, render).apply() ||
!INTERPOSE_HOOK(hook, feed).apply(enable) || \
!INTERPOSE_HOOK(hook, render).apply(enable) ||
if (SEARCH_HOOKS 0)
return CR_FAILURE;
is_enabled = enable;
}
if (!gps || !gview || SEARCH_HOOKS 0)
out.printerr("Could not insert Search hooks!\n");
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{
#undef HOOK_ACTION
const string a[] = {"Meager Quarters", "Modest Quarters", "Quarters", "Decent Quarters", "Fine Quarters", "Great Bedroom", "Grand Bedroom", "Royal Bedroom"};

@ -22,7 +22,7 @@ using namespace df::enums;
using df::global::world;
const int buffer = 20; // seed number buffer - 20 is reasonable
bool running = false; // whether seedwatch is counting the seeds or not
DFHACK_PLUGIN_IS_ENABLED(running); // whether seedwatch is counting the seeds or not
// abbreviations for the standard plants
map<string, string> abbreviations;
@ -96,6 +96,12 @@ string searchAbbreviations(string in)
}
};
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
running = enable;
return CR_OK;
}
command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
{
CoreSuspender suspend;

@ -1766,7 +1766,7 @@ DFHACK_PLUGIN_LUA_COMMANDS {
DFHACK_LUA_END
};
static bool is_enabled = false;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
static void enable_hooks(bool enable)
{
@ -1809,6 +1809,25 @@ static void clear_caches(color_ostream &out)
}
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (gamemode && *gamemode != game_mode::DWARF)
return CR_FAILURE;
if (enable != is_enabled)
{
if (enable)
enable_plugin();
else
{
World::DeletePersistentData(World::GetPersistentData("siege-engine/enabled"));
enable_hooks(false);
}
}
return CR_OK;
}
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{
switch (event) {

@ -950,8 +950,12 @@ static bool find_engines(color_ostream &out)
return !engines.empty();
}
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
static void enable_hooks(bool enable)
{
is_enabled = enable;
INTERPOSE_HOOK(liquid_hook, getItemDescription).apply(enable);
INTERPOSE_HOOK(liquid_hook, adjustTemperature).apply(enable);
INTERPOSE_HOOK(liquid_hook, checkTemperatureDamage).apply(enable);

@ -402,7 +402,8 @@ public:
* GLOBAL VARIABLES *
******************************/
static bool enabled = false;
DFHACK_PLUGIN_IS_ENABLED(enabled);
static PersistentDataItem config;
static int last_tick_frame_count = 0;
@ -1387,10 +1388,13 @@ static void update_data_structures(color_ostream &out)
* LUA API *
*************/
static bool isEnabled() { return enabled; }
static void setEnabled(color_ostream &out, bool enable)
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
{
if (!Core::getInstance().isWorldLoaded()) {
out.printerr("World is not loaded: please load a game first.\n");
return CR_FAILURE;
}
if (enable && !enabled)
{
enable_plugin(out);
@ -1401,6 +1405,8 @@ static void setEnabled(color_ostream &out, bool enable)
setOptionEnabled(CF_ENABLED, false);
stop_protect(out);
}
return CR_OK;
}
static void push_count_history(lua_State *L, ItemConstraint *icv)
@ -1591,8 +1597,6 @@ static int getCountHistory(lua_State *L)
DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(isEnabled),
DFHACK_LUA_FUNCTION(setEnabled),
DFHACK_LUA_FUNCTION(deleteConstraint),
DFHACK_LUA_END
};
@ -1767,10 +1771,10 @@ static command_result workflow_cmd(color_ostream &out, vector <string> & paramet
{
bool enable = (cmd == "enable");
if (enable)
setEnabled(out, true);
plugin_enable(out, true);
else if (parameters.size() == 1)
{
setEnabled(out, false);
plugin_enable(out, false);
out << "The plugin is disabled." << endl;
return CR_OK;
@ -1805,7 +1809,10 @@ static command_result workflow_cmd(color_ostream &out, vector <string> & paramet
}
if (!enabled)
out << "Note: the plugin is not enabled." << endl;
{
out.printerr("Error: the plugin is not enabled.\n");
return CR_WRONG_USAGE;
}
if (cmd == "jobs")
{

@ -88,6 +88,10 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("zone");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable);
const string zone_help =
"Allows easier management of pens/pastures, pits and cages.\n"
"Options:\n"
@ -3015,6 +3019,7 @@ command_result df_autobutcher(color_ostream &out, vector <string> & parameters)
}
else if (p == "start")
{
plugin_enable(out, true);
enable_autobutcher = true;
start_autobutcher(out);
return autoButcher(out, verbose);
@ -3485,6 +3490,7 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
command_result start_autobutcher(color_ostream &out)
{
plugin_enable(out, true);
enable_autobutcher = true;
if (!config_autobutcher.isValid())
@ -3545,6 +3551,7 @@ command_result init_autobutcher(color_ostream &out)
if(!enable_autobutcher)
return CR_OK;
plugin_enable(out, true);
// read watchlist from save
std::vector<PersistentDataItem> items;
@ -3579,6 +3586,7 @@ command_result cleanup_autobutcher(color_ostream &out)
command_result start_autonestbox(color_ostream &out)
{
plugin_enable(out, true);
enable_autonestbox = true;
if (!config_autonestbox.isValid())
@ -3620,6 +3628,8 @@ command_result init_autonestbox(color_ostream &out)
sleep_autonestbox = config_autonestbox.ival(1);
}
}
if (enable_autonestbox)
plugin_enable(out, true);
return CR_OK;
}
@ -3856,6 +3866,9 @@ static void autobutcher_setEnabled(color_ostream &out, bool enable)
config_autobutcher.ival(0) = enable_autobutcher;
out << "Autobutcher stopped." << endl;
}
if (enable)
plugin_enable(out, true);
}
static void autowatch_setEnabled(color_ostream &out, bool enable)
@ -4455,12 +4468,25 @@ IMPLEMENT_VMETHOD_INTERPOSE(zone_hook, feed);
IMPLEMENT_VMETHOD_INTERPOSE(zone_hook, render);
//END zone filters
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
if (!gps)
return CR_FAILURE;
if (enable != is_enabled)
{
if (!INTERPOSE_HOOK(zone_hook, feed).apply(enable) ||
!INTERPOSE_HOOK(zone_hook, render).apply(enable))
return CR_FAILURE;
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
if (!gps || !INTERPOSE_HOOK(zone_hook, feed).apply() || !INTERPOSE_HOOK(zone_hook, render).apply())
out.printerr("Could not insert jobutils hooks!\n");
commands.push_back(PluginCommand(
"zone", "manage activity zones.",
df_zone, false,