From 6dbf7b83bd51a9f0f5ed23f86d04dea507c2d6c3 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 6 Feb 2023 04:02:18 -0800 Subject: [PATCH] update auto plugin example, use new best practices --- plugins/autochop.cpp | 2 + plugins/autoslab.cpp | 2 + .../examples/persistent_per_save_example.cpp | 72 ++++++++++++++----- plugins/nestboxes.cpp | 2 + plugins/seedwatch.cpp | 23 +++--- 5 files changed, 74 insertions(+), 27 deletions(-) diff --git a/plugins/autochop.cpp b/plugins/autochop.cpp index 5b1cdf97e..bf7540e29 100644 --- a/plugins/autochop.cpp +++ b/plugins/autochop.cpp @@ -143,6 +143,8 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { DEBUG(status,out).print("%s from the API; persisting\n", is_enabled ? "enabled" : "disabled"); set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); + if (enable) + do_cycle(out, true); } else { DEBUG(status,out).print("%s from the API, but already %s; no action\n", is_enabled ? "enabled" : "disabled", diff --git a/plugins/autoslab.cpp b/plugins/autoslab.cpp index 9b0848470..e17ce72c8 100644 --- a/plugins/autoslab.cpp +++ b/plugins/autoslab.cpp @@ -90,6 +90,8 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) 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); + if (enable) + do_cycle(out); } else { diff --git a/plugins/examples/persistent_per_save_example.cpp b/plugins/examples/persistent_per_save_example.cpp index a8421949b..f066be6ef 100644 --- a/plugins/examples/persistent_per_save_example.cpp +++ b/plugins/examples/persistent_per_save_example.cpp @@ -6,6 +6,7 @@ // savegame that had this plugin enabled is loaded. #include +#include #include #include "df/world.h" @@ -18,6 +19,7 @@ #include "modules/World.h" using std::string; +using std::unordered_map; using std::vector; using namespace DFHack; @@ -38,25 +40,50 @@ namespace DFHack { } static const string CONFIG_KEY = string(plugin_name) + "/config"; +static const string ELEM_CONFIG_KEY_PREFIX = string(plugin_name) + "/elem/"; static PersistentDataItem config; +static unordered_map elems; + enum ConfigValues { CONFIG_IS_ENABLED = 0, CONFIG_SOMETHING_ELSE = 1, }; -static int get_config_val(int index) { - if (!config.isValid()) + +enum ElemConfigValues { + ELEM_CONFIG_ID = 0, + ELEM_CONFIG_SOMETHING_ELSE = 1, +}; + +static int get_config_val(PersistentDataItem &c, int index) { + if (!c.isValid()) return -1; - return config.ival(index); + return c.ival(index); +} +static bool get_config_bool(PersistentDataItem &c, int index) { + return get_config_val(c, index) == 1; } -static bool get_config_bool(int index) { - return get_config_val(index) == 1; +static void set_config_val(PersistentDataItem &c, int index, int value) { + if (c.isValid()) + c.ival(index) = value; } -static void set_config_val(int index, int value) { - if (config.isValid()) - config.ival(index) = value; +static void set_config_bool(PersistentDataItem &c, int index, bool value) { + set_config_val(c, index, value ? 1 : 0); } -static void set_config_bool(int index, bool value) { - set_config_val(index, value ? 1 : 0); + +static PersistentDataItem & ensure_elem_config(color_ostream &out, int id) { + if (elems.count(id)) + return elems[id]; + string keyname = ELEM_CONFIG_KEY_PREFIX + int_to_string(id); + DEBUG(config,out).print("creating new persistent key for elem id %d\n", id); + elems.emplace(id, World::GetPersistentData(keyname, NULL)); + return elems[id]; +} +static void remove_elem_config(color_ostream &out, int id) { + if (!elems.count(id)) + return; + DEBUG(config,out).print("removing persistent key for elem id %d\n", id); + World::DeletePersistentData(elems[id]); + elems.erase(id); } static const int32_t CYCLE_TICKS = 1200; // one day @@ -87,7 +114,9 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { is_enabled = enable; DEBUG(config,out).print("%s from the API; persisting\n", is_enabled ? "enabled" : "disabled"); - set_config_bool(CONFIG_IS_ENABLED, is_enabled); + set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); + if (enable) + do_cycle(out); } else { DEBUG(config,out).print("%s from the API, but already %s; no action\n", is_enabled ? "enabled" : "disabled", @@ -109,16 +138,27 @@ DFhackCExport command_result plugin_load_data (color_ostream &out) { if (!config.isValid()) { DEBUG(config,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_SOMETHING_ELSE, 6000); + set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); + set_config_val(config, CONFIG_SOMETHING_ELSE, 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); + is_enabled = get_config_bool(config, CONFIG_IS_ENABLED); DEBUG(config,out).print("loading persisted enabled state: %s\n", is_enabled ? "true" : "false"); + + // load other config elements, if applicable + elems.clear(); + vector elem_configs; + World::GetPersistentData(&elem_configs, ELEM_CONFIG_KEY_PREFIX, true); + const size_t num_elem_configs = elem_configs.size(); + for (size_t idx = 0; idx < num_elem_configs; ++idx) { + auto &c = elem_configs[idx]; + elems.emplace(get_config_val(c, ELEM_CONFIG_ID), c); + } + return CR_OK; } @@ -150,8 +190,8 @@ static command_result do_command(color_ostream &out, vector ¶meters) // 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. + // that can easily handle more complex commandlines. see the seedwatch plugin + // for a simple example. return CR_OK; } diff --git a/plugins/nestboxes.cpp b/plugins/nestboxes.cpp index 98e557075..b67101614 100644 --- a/plugins/nestboxes.cpp +++ b/plugins/nestboxes.cpp @@ -70,6 +70,8 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { DEBUG(config,out).print("%s from the API; persisting\n", is_enabled ? "enabled" : "disabled"); set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); + if (enable) + do_cycle(out); } else { DEBUG(config,out).print("%s from the API, but already %s; no action\n", is_enabled ? "enabled" : "disabled", diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index aee167258..551ec36dc 100644 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -99,7 +99,7 @@ static const int32_t CYCLE_TICKS = 1200; static int32_t cycle_timestamp = 0; // world->frame_counter at last cycle static command_result do_command(color_ostream &out, vector ¶meters); -static void do_cycle(color_ostream &out, int32_t *num_enabled_seeds, int32_t *num_disabled_seeds); +static void do_cycle(color_ostream &out, int32_t *num_enabled_seeds = NULL, int32_t *num_disabled_seeds = NULL); static void seedwatch_setTarget(color_ostream &out, string name, int32_t num); DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) { @@ -149,7 +149,7 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { is_enabled ? "enabled" : "disabled"); set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); if (enable) - seedwatch_setTarget(out, "all", DEFAULT_TARGET); + do_cycle(out); } else { DEBUG(config,out).print("%s from the API, but already %s; no action\n", is_enabled ? "enabled" : "disabled", @@ -174,26 +174,27 @@ DFhackCExport command_result plugin_load_data (color_ostream &out) { world_plant_ids[plant->id] = i; } + watched_seeds.clear(); + vector seed_configs; + World::GetPersistentData(&seed_configs, SEED_CONFIG_KEY_PREFIX, true); + const size_t num_seed_configs = seed_configs.size(); + for (size_t idx = 0; idx < num_seed_configs; ++idx) { + auto &c = seed_configs[idx]; + watched_seeds.emplace(get_config_val(c, SEED_CONFIG_ID), c); + } + config = World::GetPersistentData(CONFIG_KEY); if (!config.isValid()) { DEBUG(config,out).print("no config found in this save; initializing\n"); config = World::AddPersistentData(CONFIG_KEY); set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); + seedwatch_setTarget(out, "all", DEFAULT_TARGET); } is_enabled = get_config_bool(config, CONFIG_IS_ENABLED); DEBUG(config,out).print("loading persisted enabled state: %s\n", is_enabled ? "true" : "false"); - watched_seeds.clear(); - vector seed_configs; - World::GetPersistentData(&seed_configs, SEED_CONFIG_KEY_PREFIX, true); - const size_t num_seed_configs = seed_configs.size(); - for (size_t idx = 0; idx < num_seed_configs; ++idx) { - auto &c = seed_configs[idx]; - watched_seeds.emplace(get_config_val(c, SEED_CONFIG_ID), c); - } - return CR_OK; }