Merge pull request #2257 from myk002/myk_class3example
Extend documentation in skeleton plugin, add example plugin structures for class 1, 2, and 3 pluginsdevelop
commit
eef0824cef
@ -0,0 +1,166 @@
|
|||||||
|
// This template is appropriate for plugins that periodically check game state
|
||||||
|
// and make some sort of automated change. These types of plugins typically
|
||||||
|
// provide a command that can be used to configure the plugin behavior and
|
||||||
|
// require a world to be loaded before they can function. This kind of plugin
|
||||||
|
// should persist its state in the savegame and auto-re-enable itself when a
|
||||||
|
// savegame that had this plugin enabled is loaded.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "df/world.h"
|
||||||
|
|
||||||
|
#include "Core.h"
|
||||||
|
#include "Debug.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
|
||||||
|
#include "modules/Persistence.h"
|
||||||
|
#include "modules/World.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
DFHACK_PLUGIN("persistent_per_save_example");
|
||||||
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
||||||
|
|
||||||
|
REQUIRE_GLOBAL(world);
|
||||||
|
|
||||||
|
// logging levels can be dynamically controlled with the `debugfilter` command.
|
||||||
|
namespace DFHack {
|
||||||
|
// for configuration-related logging
|
||||||
|
DBG_DECLARE(persistent_per_save_example, status, DebugCategory::LINFO);
|
||||||
|
// for logging during the periodic scan
|
||||||
|
DBG_DECLARE(persistent_per_save_example, cycle, DebugCategory::LINFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string CONFIG_KEY = string(plugin_name) + "/config";
|
||||||
|
static PersistentDataItem config;
|
||||||
|
enum ConfigValues {
|
||||||
|
CONFIG_IS_ENABLED = 0,
|
||||||
|
CONFIG_CYCLE_TICKS = 1,
|
||||||
|
};
|
||||||
|
static int get_config_val(int index) {
|
||||||
|
if (!config.isValid())
|
||||||
|
return -1;
|
||||||
|
return config.ival(index);
|
||||||
|
}
|
||||||
|
static bool get_config_bool(int index) {
|
||||||
|
return get_config_val(index) == 1;
|
||||||
|
}
|
||||||
|
static void set_config_val(int index, int value) {
|
||||||
|
if (config.isValid())
|
||||||
|
config.ival(index) = value;
|
||||||
|
}
|
||||||
|
static void set_config_bool(int index, bool value) {
|
||||||
|
set_config_val(index, value ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t cycle_timestamp = 0; // world->frame_counter at last cycle
|
||||||
|
|
||||||
|
static command_result do_command(color_ostream &out, vector<string> ¶meters);
|
||||||
|
static void do_cycle(color_ostream &out);
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init(color_ostream &out, std::vector <PluginCommand> &commands) {
|
||||||
|
DEBUG(status,out).print("initializing %s\n", plugin_name);
|
||||||
|
|
||||||
|
// provide a configuration interface for the plugin
|
||||||
|
commands.push_back(PluginCommand(
|
||||||
|
plugin_name,
|
||||||
|
"Short (~54 character) description of command.",
|
||||||
|
do_command));
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
|
||||||
|
if (!Core::getInstance().isWorldLoaded()) {
|
||||||
|
out.printerr("Cannot enable %s without a loaded world.\n", plugin_name);
|
||||||
|
return CR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable != is_enabled) {
|
||||||
|
is_enabled = enable;
|
||||||
|
DEBUG(status,out).print("%s from the API; persisting\n",
|
||||||
|
is_enabled ? "enabled" : "disabled");
|
||||||
|
set_config_bool(CONFIG_IS_ENABLED, is_enabled);
|
||||||
|
} else {
|
||||||
|
DEBUG(status,out).print("%s from the API, but already %s; no action\n",
|
||||||
|
is_enabled ? "enabled" : "disabled",
|
||||||
|
is_enabled ? "enabled" : "disabled");
|
||||||
|
}
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_shutdown (color_ostream &out) {
|
||||||
|
DEBUG(status,out).print("shutting down %s\n", plugin_name);
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_load_data (color_ostream &out) {
|
||||||
|
config = World::GetPersistentData(CONFIG_KEY);
|
||||||
|
|
||||||
|
if (!config.isValid()) {
|
||||||
|
DEBUG(status,out).print("no config found in this save; initializing\n");
|
||||||
|
config = World::AddPersistentData(CONFIG_KEY);
|
||||||
|
set_config_bool(CONFIG_IS_ENABLED, is_enabled);
|
||||||
|
set_config_val(CONFIG_CYCLE_TICKS, 6000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have to copy our enabled flag into the global plugin variable, but
|
||||||
|
// all the other state we can directly read/modify from the persistent
|
||||||
|
// data structure.
|
||||||
|
is_enabled = get_config_bool(CONFIG_IS_ENABLED);
|
||||||
|
DEBUG(status,out).print("loading persisted enabled state: %s\n",
|
||||||
|
is_enabled ? "true" : "false");
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) {
|
||||||
|
if (event == DFHack::SC_WORLD_UNLOADED) {
|
||||||
|
if (is_enabled) {
|
||||||
|
DEBUG(status,out).print("world unloaded; disabling %s\n",
|
||||||
|
plugin_name);
|
||||||
|
is_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_onupdate(color_ostream &out) {
|
||||||
|
if (is_enabled && world->frame_counter - cycle_timestamp >= get_config_val(CONFIG_CYCLE_TICKS))
|
||||||
|
do_cycle(out);
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static command_result do_command(color_ostream &out, vector<string> ¶meters) {
|
||||||
|
// be sure to suspend the core if any DF state is read or modified
|
||||||
|
CoreSuspender suspend;
|
||||||
|
|
||||||
|
if (!Core::getInstance().isWorldLoaded()) {
|
||||||
|
out.printerr("Cannot run %s without a loaded world.\n", plugin_name);
|
||||||
|
return CR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: configuration logic
|
||||||
|
// simple commandline parsing can be done in C++, but there are lua libraries
|
||||||
|
// that can easily handle more complex commandlines. see the blueprint plugin
|
||||||
|
// for an example.
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
// cycle logic
|
||||||
|
//
|
||||||
|
|
||||||
|
static void do_cycle(color_ostream &out) {
|
||||||
|
// mark that we have recently run
|
||||||
|
cycle_timestamp = world->frame_counter;
|
||||||
|
|
||||||
|
DEBUG(cycle,out).print("running %s cycle\n", plugin_name);
|
||||||
|
|
||||||
|
// TODO: logic that runs every get_config_val(CONFIG_CYCLE_TICKS) ticks
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
// This template is appropriate for plugins that simply provide one or more
|
||||||
|
// commands, but don't need to be "enabled" to function.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
DFHACK_PLUGIN("simple_command_example");
|
||||||
|
|
||||||
|
namespace DFHack {
|
||||||
|
DBG_DECLARE(simple_command_example, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
static command_result do_command(color_ostream &out, vector<string> ¶meters);
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init(color_ostream &out, std::vector <PluginCommand> &commands) {
|
||||||
|
DEBUG(log,out).print("initializing %s\n", plugin_name);
|
||||||
|
|
||||||
|
commands.push_back(PluginCommand(
|
||||||
|
plugin_name,
|
||||||
|
"Short (~54 character) description of command.",
|
||||||
|
do_command));
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static command_result do_command(color_ostream &out, vector<string> ¶meters) {
|
||||||
|
// be sure to suspend the core if any DF state is read or modified
|
||||||
|
CoreSuspender suspend;
|
||||||
|
|
||||||
|
// TODO: command logic
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
@ -0,0 +1,193 @@
|
|||||||
|
// This is an example plugin that documents and implements all the plugin
|
||||||
|
// callbacks and features. You can include it in the regular build by setting
|
||||||
|
// the BUILD_SKELETON option in CMake to ON. Play with loading and unloading
|
||||||
|
// the plugin in various game states (e.g. with and without a world loaded),
|
||||||
|
// and see the debug messages get printed to the console.
|
||||||
|
//
|
||||||
|
// See the other example plugins in this directory for plugins that are
|
||||||
|
// configured for specific use cases (but don't come with as many comments as
|
||||||
|
// this one does).
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "df/world.h"
|
||||||
|
|
||||||
|
#include "Core.h"
|
||||||
|
#include "Debug.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
|
||||||
|
#include "modules/Persistence.h"
|
||||||
|
#include "modules/World.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
// Expose the plugin name to the DFHack core, as well as metadata like the
|
||||||
|
// DFHack version that this plugin was compiled with. This macro provides a
|
||||||
|
// variable for the plugin name as const char * plugin_name.
|
||||||
|
// The name provided must correspond to the filename --
|
||||||
|
// skeleton.plug.so, skeleton.plug.dylib, or skeleton.plug.dll in this case
|
||||||
|
DFHACK_PLUGIN("skeleton");
|
||||||
|
|
||||||
|
// The identifier declared with this macro (i.e. is_enabled) is used to track
|
||||||
|
// whether the plugin is in an "enabled" state. If you don't need enablement
|
||||||
|
// for your plugin, you don't need this line. This variable will also be read
|
||||||
|
// by the `plug` builtin command; when true the plugin will be shown as enabled.
|
||||||
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
||||||
|
|
||||||
|
// Any globals a plugin requires (e.g. world) should be listed here.
|
||||||
|
// For example, this line expands to "using df::global::world" and prevents the
|
||||||
|
// plugin from being loaded if df::global::world is null (i.e. missing from
|
||||||
|
// symbols.xml).
|
||||||
|
REQUIRE_GLOBAL(world);
|
||||||
|
|
||||||
|
// logging levels can be dynamically controlled with the `debugfilter` command.
|
||||||
|
// Actual plugins will likely want to set the default level to LINFO or LWARNING
|
||||||
|
// instead of the LDEBUG used here.
|
||||||
|
namespace DFHack {
|
||||||
|
// for configuration-related logging
|
||||||
|
DBG_DECLARE(skeleton, status, DebugCategory::LDEBUG);
|
||||||
|
// for plugin_onupdate logging
|
||||||
|
DBG_DECLARE(skeleton, onupdate, DebugCategory::LDEBUG);
|
||||||
|
// for command-related logging
|
||||||
|
DBG_DECLARE(skeleton, command, DebugCategory::LDEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static command_result command_callback1(color_ostream &out, vector<string> ¶meters);
|
||||||
|
|
||||||
|
// run when the plugin is loaded
|
||||||
|
DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginCommand> &commands) {
|
||||||
|
DEBUG(status,out).print("initializing %s\n", plugin_name);
|
||||||
|
|
||||||
|
// For in-tree plugins, don't use the "usage" parameter of PluginCommand.
|
||||||
|
// Instead, add an .rst file with the same name as the plugin to the
|
||||||
|
// docs/plugins/ directory.
|
||||||
|
commands.push_back(PluginCommand(
|
||||||
|
"skeleton",
|
||||||
|
"Short (~54 character) description of command.", // to use one line in the ``[DFHack]# ls`` output
|
||||||
|
command_callback1));
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run when the plugin is unloaded
|
||||||
|
DFhackCExport command_result plugin_shutdown(color_ostream &out) {
|
||||||
|
DEBUG(status,out).print("shutting down %s\n", plugin_name);
|
||||||
|
|
||||||
|
// You *MUST* kill all threads you created before this returns.
|
||||||
|
// If everything fails, just return CR_FAILURE. Your plugin will be
|
||||||
|
// in a zombie state, but things won't crash.
|
||||||
|
return CR_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// run when the `enable` or `disable` command is run with this plugin name as
|
||||||
|
// an argument
|
||||||
|
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
|
||||||
|
DEBUG(status,out).print("%s from the API\n", enable ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
// you have to maintain the state of the is_enabled variable yourself. it
|
||||||
|
// doesn't happen automatically.
|
||||||
|
is_enabled = enable;
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called to notify the plugin about important state changes.
|
||||||
|
// Invoked with DF suspended, and always before the matching plugin_onupdate.
|
||||||
|
// More event codes may be added in the future.
|
||||||
|
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) {
|
||||||
|
switch (event) {
|
||||||
|
case SC_UNKNOWN:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_UNKNOWN\n");
|
||||||
|
break;
|
||||||
|
case SC_WORLD_LOADED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_WORLD_LOADED\n");
|
||||||
|
break;
|
||||||
|
case SC_WORLD_UNLOADED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_WORLD_UNLOADED\n");
|
||||||
|
break;
|
||||||
|
case SC_MAP_LOADED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_MAP_LOADED\n");
|
||||||
|
break;
|
||||||
|
case SC_MAP_UNLOADED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_MAP_UNLOADED\n");
|
||||||
|
break;
|
||||||
|
case SC_VIEWSCREEN_CHANGED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_VIEWSCREEN_CHANGED\n");
|
||||||
|
break;
|
||||||
|
case SC_CORE_INITIALIZED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_CORE_INITIALIZED\n");
|
||||||
|
break;
|
||||||
|
case SC_BEGIN_UNLOAD:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_BEGIN_UNLOAD\n");
|
||||||
|
break;
|
||||||
|
case SC_PAUSED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_PAUSED\n");
|
||||||
|
break;
|
||||||
|
case SC_UNPAUSED:
|
||||||
|
DEBUG(status,out).print("game state changed: SC_UNPAUSED\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whatever you put here will be done in each game frame refresh. Don't abuse it.
|
||||||
|
// Note that if the plugin implements the enabled API, this function is only called
|
||||||
|
// if the plugin is enabled.
|
||||||
|
DFhackCExport command_result plugin_onupdate (color_ostream &out) {
|
||||||
|
DEBUG(onupdate,out).print(
|
||||||
|
"onupdate called (run 'debugfilter set info skeleton onupdate' to stop"
|
||||||
|
" seeing these messages)\n");
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you need to save or load world-specific data, define these functions.
|
||||||
|
// plugin_save_data is called when the game might be about to save the world,
|
||||||
|
// and plugin_load_data is called whenever a new world is loaded. If the plugin
|
||||||
|
// is loaded or unloaded while a world is active, plugin_save_data or
|
||||||
|
// plugin_load_data will be called immediately.
|
||||||
|
DFhackCExport command_result plugin_save_data (color_ostream &out) {
|
||||||
|
DEBUG(status,out).print("save or unload is imminent; time to persist state\n");
|
||||||
|
|
||||||
|
// Call functions in the Persistence module here. If your PersistantDataItem
|
||||||
|
// objects are already up to date, then they will get persisted with the
|
||||||
|
// save automatically and there is nothing extra you need to do here.
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_load_data (color_ostream &out) {
|
||||||
|
DEBUG(status,out).print("world is loading; time to load persisted state\n");
|
||||||
|
|
||||||
|
// Call functions in the Persistence module here. See
|
||||||
|
// persistent_per_save_example.cpp for an example.
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the callback we registered in plugin_init. Note that while plugin
|
||||||
|
// callbacks are called with the core suspended, command callbacks are called
|
||||||
|
// from a different thread and need to explicity suspend the core if they
|
||||||
|
// interact with Lua or DF game state (most commands do at least one of these).
|
||||||
|
static command_result command_callback1(color_ostream &out, vector<string> ¶meters) {
|
||||||
|
DEBUG(command,out).print("%s command called with %zu parameters\n",
|
||||||
|
plugin_name, parameters.size());
|
||||||
|
|
||||||
|
// I'll say it again: always suspend the core in command callbacks unless
|
||||||
|
// all your data is local.
|
||||||
|
CoreSuspender suspend;
|
||||||
|
|
||||||
|
// Return CR_WRONG_USAGE to print out your help text. The help text is
|
||||||
|
// sourced from the associated rst file in docs/plugins/. The same help will
|
||||||
|
// also be returned by 'help your-command'.
|
||||||
|
|
||||||
|
// simple commandline parsing can be done in C++, but there are lua libraries
|
||||||
|
// that can easily handle more complex commandlines. see the blueprint plugin
|
||||||
|
// for an example.
|
||||||
|
|
||||||
|
// TODO: do something according to the flags set in the options struct
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
// This template is appropriate for plugins that can be enabled to make some
|
||||||
|
// specific persistent change to the game, but don't need a world to be loaded
|
||||||
|
// before they are enabled. These types of plugins typically register some sort
|
||||||
|
// of hook on enable and clear the hook on disable. They are generally enabled
|
||||||
|
// from dfhack.init and do not need to persist and reload their enabled state.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "df/viewscreen_titlest.h"
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
#include "VTableInterpose.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
DFHACK_PLUGIN("ui_addition_example");
|
||||||
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
||||||
|
|
||||||
|
namespace DFHack {
|
||||||
|
DBG_DECLARE(ui_addition_example, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// example of hooking a screen so the plugin code will run whenever the screen
|
||||||
|
// is visible
|
||||||
|
struct title_version_hook : df::viewscreen_titlest {
|
||||||
|
typedef df::viewscreen_titlest interpose_base;
|
||||||
|
|
||||||
|
DEFINE_VMETHOD_INTERPOSE(void, render, ()) {
|
||||||
|
INTERPOSE_NEXT(render)();
|
||||||
|
|
||||||
|
// TODO: injected render logic here
|
||||||
|
}
|
||||||
|
};
|
||||||
|
IMPLEMENT_VMETHOD_INTERPOSE(title_version_hook, render);
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_shutdown (color_ostream &out) {
|
||||||
|
DEBUG(log,out).print("shutting down %s\n", plugin_name);
|
||||||
|
INTERPOSE_HOOK(title_version_hook, render).remove();
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_enable (color_ostream &out, bool enable) {
|
||||||
|
if (enable != is_enabled) {
|
||||||
|
DEBUG(log,out).print("%s %s\n", plugin_name,
|
||||||
|
is_enabled ? "enabled" : "disabled");
|
||||||
|
if (!INTERPOSE_HOOK(title_version_hook, render).apply(enable))
|
||||||
|
return CR_FAILURE;
|
||||||
|
|
||||||
|
is_enabled = enable;
|
||||||
|
}
|
||||||
|
return CR_OK;
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
project(skeleton)
|
|
||||||
# A list of source files
|
|
||||||
set(PROJECT_SRCS
|
|
||||||
skeleton.cpp
|
|
||||||
)
|
|
||||||
# A list of headers
|
|
||||||
set(PROJECT_HDRS
|
|
||||||
skeleton.h
|
|
||||||
)
|
|
||||||
set_source_files_properties(${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE)
|
|
||||||
|
|
||||||
# mash them together (headers are marked as headers and nothing will try to compile them)
|
|
||||||
list(APPEND PROJECT_SRCS ${PROJECT_HDRS})
|
|
||||||
|
|
||||||
# option to use a thread for no particular reason
|
|
||||||
option(SKELETON_THREAD "Use threads in the skeleton plugin." ON)
|
|
||||||
if(UNIX)
|
|
||||||
if(APPLE)
|
|
||||||
set(PROJECT_LIBS
|
|
||||||
# add any extra mac libraries here
|
|
||||||
${PROJECT_LIBS}
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set(PROJECT_LIBS
|
|
||||||
# add any extra linux libraries here
|
|
||||||
${PROJECT_LIBS}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(PROJECT_LIBS
|
|
||||||
# add any extra windows libraries here
|
|
||||||
${PROJECT_LIBS}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
# this makes sure all the stuff is put in proper places and linked to dfhack
|
|
||||||
dfhack_plugin(skeleton ${PROJECT_SRCS} LINK_LIBRARIES ${PROJECT_LIBS})
|
|
@ -1,171 +0,0 @@
|
|||||||
// This is a generic plugin that does nothing useful apart from acting as an example... of a plugin that does nothing :D
|
|
||||||
|
|
||||||
// some headers required for a plugin. Nothing special, just the basics.
|
|
||||||
#include "Core.h"
|
|
||||||
#include <Console.h>
|
|
||||||
#include <Export.h>
|
|
||||||
#include <PluginManager.h>
|
|
||||||
#include <modules/EventManager.h>
|
|
||||||
// If you need to save data per-world:
|
|
||||||
//#include "modules/Persistence.h"
|
|
||||||
|
|
||||||
// DF data structure definition headers
|
|
||||||
#include "DataDefs.h"
|
|
||||||
//#include "df/world.h"
|
|
||||||
|
|
||||||
// our own, empty header.
|
|
||||||
#include "skeleton.h"
|
|
||||||
|
|
||||||
using namespace DFHack;
|
|
||||||
using namespace df::enums;
|
|
||||||
|
|
||||||
// Expose the plugin name to the DFHack core, as well as metadata like the DFHack version.
|
|
||||||
// The name string provided must correspond to the filename -
|
|
||||||
// skeleton.plug.so, skeleton.plug.dylib, or skeleton.plug.dll in this case
|
|
||||||
DFHACK_PLUGIN("skeleton");
|
|
||||||
|
|
||||||
// The identifier declared with this macro (ie. enabled) can be specified by the user
|
|
||||||
// and subsequently used to manage the plugin's operations.
|
|
||||||
// This will also be tracked by `plug`; when true the plugin will be shown as enabled.
|
|
||||||
DFHACK_PLUGIN_IS_ENABLED(enabled);
|
|
||||||
|
|
||||||
// Any globals a plugin requires (e.g. world) should be listed here.
|
|
||||||
// For example, this line expands to "using df::global::world" and prevents the
|
|
||||||
// plugin from being loaded if df::global::world is null (i.e. missing from symbols.xml):
|
|
||||||
//
|
|
||||||
REQUIRE_GLOBAL(world);
|
|
||||||
|
|
||||||
// You may want some compile time debugging options
|
|
||||||
// one easy system just requires you to cache the color_ostream &out into a global debug variable
|
|
||||||
//#define P_DEBUG 1
|
|
||||||
//uint16_t maxTickFreq = 1200; //maybe you want to use some events
|
|
||||||
|
|
||||||
command_result command_callback1(color_ostream &out, std::vector<std::string> ¶meters);
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginCommand> &commands) {
|
|
||||||
commands.push_back(PluginCommand("skeleton",
|
|
||||||
"~54 character description of plugin", //to use one line in the ``[DFHack]# ls`` output
|
|
||||||
command_callback1,
|
|
||||||
false,
|
|
||||||
"example usage"
|
|
||||||
" skeleton <option> <args>\n"
|
|
||||||
" explanation of plugin/command\n"
|
|
||||||
"\n"
|
|
||||||
" skeleton\n"
|
|
||||||
" what happens when using the command\n"
|
|
||||||
"\n"
|
|
||||||
" skeleton option1\n"
|
|
||||||
" what happens when using the command with option1\n"
|
|
||||||
"\n"));
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_shutdown(color_ostream &out) {
|
|
||||||
// You *MUST* kill all threads you created before this returns.
|
|
||||||
// If everything fails, just return CR_FAILURE. Your plugin will be
|
|
||||||
// in a zombie state, but things won't crash.
|
|
||||||
return CR_OK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
|
|
||||||
namespace EM = EventManager;
|
|
||||||
if (enable && !enabled) {
|
|
||||||
//using namespace EM::EventType;
|
|
||||||
//EM::EventHandler eventHandler(onNewEvent, maxTickFreq);
|
|
||||||
//EM::registerListener(EventType::JOB_COMPLETED, eventHandler, plugin_self);
|
|
||||||
//out.print("plugin enabled!\n");
|
|
||||||
} else if (!enable && enabled) {
|
|
||||||
EM::unregisterAll(plugin_self);
|
|
||||||
//out.print("plugin disabled!\n");
|
|
||||||
}
|
|
||||||
enabled = enable;
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* OPTIONAL *
|
|
||||||
// Called to notify the plugin about important state changes.
|
|
||||||
// Invoked with DF suspended, and always before the matching plugin_onupdate.
|
|
||||||
// More event codes may be added in the future.
|
|
||||||
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) {
|
|
||||||
if (enabled) {
|
|
||||||
switch (event) {
|
|
||||||
case SC_UNKNOWN:
|
|
||||||
break;
|
|
||||||
case SC_WORLD_LOADED:
|
|
||||||
break;
|
|
||||||
case SC_WORLD_UNLOADED:
|
|
||||||
break;
|
|
||||||
case SC_MAP_LOADED:
|
|
||||||
break;
|
|
||||||
case SC_MAP_UNLOADED:
|
|
||||||
break;
|
|
||||||
case SC_VIEWSCREEN_CHANGED:
|
|
||||||
break;
|
|
||||||
case SC_CORE_INITIALIZED:
|
|
||||||
break;
|
|
||||||
case SC_BEGIN_UNLOAD:
|
|
||||||
break;
|
|
||||||
case SC_PAUSED:
|
|
||||||
break;
|
|
||||||
case SC_UNPAUSED:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whatever you put here will be done in each game step. Don't abuse it.
|
|
||||||
DFhackCExport command_result plugin_onupdate ( color_ostream &out )
|
|
||||||
{
|
|
||||||
// whetever. You don't need to suspend DF execution here.
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you need to save or load world-specific data, define these functions.
|
|
||||||
// plugin_save_data is called when the game might be about to save the world,
|
|
||||||
// and plugin_load_data is called whenever a new world is loaded. If the plugin
|
|
||||||
// is loaded or unloaded while a world is active, plugin_save_data or
|
|
||||||
// plugin_load_data will be called immediately.
|
|
||||||
DFhackCExport command_result plugin_save_data (color_ostream &out)
|
|
||||||
{
|
|
||||||
// Call functions in the Persistence module here.
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_load_data (color_ostream &out)
|
|
||||||
{
|
|
||||||
// Call functions in the Persistence module here.
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
* OPTIONAL */
|
|
||||||
|
|
||||||
|
|
||||||
// A command! It sits around and looks pretty. And it's nice and friendly.
|
|
||||||
command_result command_callback1(color_ostream &out, std::vector<std::string> ¶meters) {
|
|
||||||
// It's nice to print a help message you get invalid options
|
|
||||||
// from the user instead of just acting strange.
|
|
||||||
// This can be achieved by adding the extended help string to the
|
|
||||||
// PluginCommand registration as show above, and then returning
|
|
||||||
// CR_WRONG_USAGE from the function. The same string will also
|
|
||||||
// be used by 'help your-command'.
|
|
||||||
if (!parameters.empty()) {
|
|
||||||
return CR_WRONG_USAGE; //or maybe you want it to do something else
|
|
||||||
}
|
|
||||||
// Commands are called from threads other than the DF one.
|
|
||||||
// Suspend this thread until DF has time for us.
|
|
||||||
// **If you use CoreSuspender** it'll automatically resume DF when
|
|
||||||
// execution leaves the current scope.
|
|
||||||
CoreSuspender suspend;
|
|
||||||
// Actually do something here. Yay.
|
|
||||||
|
|
||||||
// process parameters
|
|
||||||
if (parameters.size() == 1 && parameters[0] == "option1") {
|
|
||||||
// stuff
|
|
||||||
} else {
|
|
||||||
return CR_FAILURE;
|
|
||||||
}
|
|
||||||
// Give control back to DF.
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
#pragma once
|
|
@ -1,61 +0,0 @@
|
|||||||
#include "Core.h"
|
|
||||||
#include <Console.h>
|
|
||||||
#include <Export.h>
|
|
||||||
#include <PluginManager.h>
|
|
||||||
#include <modules/EventManager.h>
|
|
||||||
|
|
||||||
//#include "df/world.h"
|
|
||||||
|
|
||||||
using namespace DFHack;
|
|
||||||
using namespace df::enums;
|
|
||||||
|
|
||||||
DFHACK_PLUGIN("skeleton2");
|
|
||||||
DFHACK_PLUGIN_IS_ENABLED(enabled);
|
|
||||||
//REQUIRE_GLOBAL(world);
|
|
||||||
|
|
||||||
command_result skeleton2 (color_ostream &out, std::vector <std::string> & parameters);
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) {
|
|
||||||
commands.push_back(PluginCommand("skeleton2",
|
|
||||||
"~54 character description of plugin", //to use one line in the ``[DFHack]# ls`` output
|
|
||||||
skeleton2,
|
|
||||||
false,
|
|
||||||
"example usage"
|
|
||||||
" skeleton2 <option> <args>\n"
|
|
||||||
" explanation of plugin/command\n"
|
|
||||||
"\n"
|
|
||||||
" skeleton2\n"
|
|
||||||
" what happens when using the command\n"
|
|
||||||
"\n"
|
|
||||||
" skeleton2 option1\n"
|
|
||||||
" what happens when using the command with option1\n"
|
|
||||||
"\n"));
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_shutdown (color_ostream &out) {
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
|
|
||||||
namespace EM = EventManager;
|
|
||||||
if (enable && !enabled) {
|
|
||||||
//using namespace EM::EventType;
|
|
||||||
//EM::EventHandler eventHandler(onNewEvent, maxTickFreq);
|
|
||||||
//EM::registerListener(EventType::JOB_COMPLETED, eventHandler, plugin_self);
|
|
||||||
//out.print("plugin enabled!\n");
|
|
||||||
} else if (!enable && enabled) {
|
|
||||||
EM::unregisterAll(plugin_self);
|
|
||||||
//out.print("plugin disabled!\n");
|
|
||||||
}
|
|
||||||
enabled = enable;
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
command_result skeleton2 (color_ostream &out, std::vector <std::string> & parameters) {
|
|
||||||
if (!parameters.empty())
|
|
||||||
return CR_WRONG_USAGE;
|
|
||||||
CoreSuspender suspend;
|
|
||||||
out.print("blah");
|
|
||||||
return CR_OK;
|
|
||||||
}
|
|
Loading…
Reference in New Issue