Merge pull request #2773 from myk002/myk_nestboxes
[nestboxes] update and simplify; persist statedevelop
						commit
						c312a88bea
					
				| @ -1,120 +1,153 @@ | ||||
| #include "Core.h" | ||||
| #include "Console.h" | ||||
| #include "Export.h" | ||||
| #include "Debug.h" | ||||
| #include "PluginManager.h" | ||||
| 
 | ||||
| #include "DataDefs.h" | ||||
| #include "modules/Persistence.h" | ||||
| #include "modules/World.h" | ||||
| 
 | ||||
| #include "df/world.h" | ||||
| #include "df/plotinfost.h" | ||||
| #include "df/building_nest_boxst.h" | ||||
| #include "df/building_type.h" | ||||
| #include "df/buildings_other_id.h" | ||||
| #include "df/global_objects.h" | ||||
| #include "df/item.h" | ||||
| #include "df/unit.h" | ||||
| #include "df/building.h" | ||||
| #include "df/items_other_id.h" | ||||
| #include "df/creature_raw.h" | ||||
| #include "modules/MapCache.h" | ||||
| #include "modules/Items.h" | ||||
| 
 | ||||
| 
 | ||||
| using std::vector; | ||||
| using std::string; | ||||
| using std::endl; | ||||
| using namespace DFHack; | ||||
| using namespace df::enums; | ||||
| 
 | ||||
| using df::global::world; | ||||
| using df::global::plotinfo; | ||||
| DFHACK_PLUGIN("nestboxes"); | ||||
| DFHACK_PLUGIN_IS_ENABLED(is_enabled); | ||||
| 
 | ||||
| static command_result nestboxes(color_ostream &out, vector <string> & parameters); | ||||
| REQUIRE_GLOBAL(world); | ||||
| 
 | ||||
| DFHACK_PLUGIN("nestboxes"); | ||||
| namespace DFHack { | ||||
|     // for configuration-related logging
 | ||||
|     DBG_DECLARE(nestboxes, config, DebugCategory::LINFO); | ||||
|     // for logging during the periodic scan
 | ||||
|     DBG_DECLARE(nestboxes, cycle, DebugCategory::LINFO); | ||||
| } | ||||
| 
 | ||||
| DFHACK_PLUGIN_IS_ENABLED(enabled); | ||||
| static const string CONFIG_KEY = string(plugin_name) + "/config"; | ||||
| static PersistentDataItem config; | ||||
| 
 | ||||
| static void eggscan(color_ostream &out) | ||||
| { | ||||
|     CoreSuspender suspend; | ||||
| enum ConfigValues { | ||||
|     CONFIG_IS_ENABLED = 0, | ||||
| }; | ||||
| 
 | ||||
|     for (df::building *build : world->buildings.other[df::buildings_other_id::NEST_BOX]) | ||||
|     { | ||||
|         auto type = build->getType(); | ||||
|         if (df::enums::building_type::NestBox == type) | ||||
|         { | ||||
|             bool fertile = false; | ||||
|             df::building_nest_boxst *nb = virtual_cast<df::building_nest_boxst>(build); | ||||
|             if (nb->claimed_by != -1) | ||||
|             { | ||||
|                 df::unit* u = df::unit::find(nb->claimed_by); | ||||
|                 if (u && u->pregnancy_timer > 0) | ||||
|                     fertile = true; | ||||
|             } | ||||
|             for (size_t j = 1; j < nb->contained_items.size(); j++) | ||||
|             { | ||||
|                 df::item* item = nb->contained_items[j]->item; | ||||
|                 if (item->flags.bits.forbid != fertile) | ||||
|                 { | ||||
|                     item->flags.bits.forbid = fertile; | ||||
|                     out << item->getStackSize() << " eggs " << (fertile ? "forbidden" : "unforbidden.") << endl; | ||||
| static int get_config_val(PersistentDataItem &c, int index) { | ||||
|     if (!c.isValid()) | ||||
|         return -1; | ||||
|     return c.ival(index); | ||||
| } | ||||
| static bool get_config_bool(PersistentDataItem &c, int index) { | ||||
|     return get_config_val(c, index) == 1; | ||||
| } | ||||
| static void set_config_val(PersistentDataItem &c, int index, int value) { | ||||
|     if (c.isValid()) | ||||
|         c.ival(index) = value; | ||||
| } | ||||
| static void set_config_bool(PersistentDataItem &c, int index, bool value) { | ||||
|     set_config_val(c, index, value ? 1 : 0); | ||||
| } | ||||
| 
 | ||||
| static const int32_t CYCLE_TICKS = 100; // need to react quickly if eggs are unforbidden
 | ||||
| static int32_t cycle_timestamp = 0;  // world->frame_counter at last cycle
 | ||||
| 
 | ||||
| static void do_cycle(color_ostream &out, int32_t *num_enabled_seeds, int32_t *num_disabled_seeds); | ||||
| 
 | ||||
| DFhackCExport command_result plugin_init(color_ostream &out, std::vector <PluginCommand> &commands) { | ||||
|     DEBUG(config,out).print("initializing %s\n", plugin_name); | ||||
| 
 | ||||
|     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; | ||||
|     } | ||||
| 
 | ||||
| DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) | ||||
| { | ||||
|     if (world && plotinfo) { | ||||
|         commands.push_back( | ||||
|             PluginCommand( | ||||
|                 "nestboxes", | ||||
|                 "Protect fertile eggs incubating in a nestbox.", | ||||
|                 nestboxes)); | ||||
|     if (enable != is_enabled) { | ||||
|         is_enabled = enable; | ||||
|         DEBUG(config,out).print("%s from the API; persisting\n", | ||||
|                                 is_enabled ? "enabled" : "disabled"); | ||||
|         set_config_bool(config, CONFIG_IS_ENABLED, is_enabled); | ||||
|     } else { | ||||
|         DEBUG(config,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 ) | ||||
| { | ||||
| DFhackCExport command_result plugin_shutdown (color_ostream &out) { | ||||
|     DEBUG(config,out).print("shutting down %s\n", plugin_name); | ||||
| 
 | ||||
|     return CR_OK; | ||||
| } | ||||
| 
 | ||||
| DFhackCExport command_result plugin_onupdate(color_ostream &out) | ||||
| { | ||||
|     if (!enabled) | ||||
|         return CR_OK; | ||||
| DFhackCExport command_result plugin_load_data (color_ostream &out) { | ||||
|     config = World::GetPersistentData(CONFIG_KEY); | ||||
| 
 | ||||
|     static unsigned cnt = 0; | ||||
|     if ((++cnt % 5) != 0) | ||||
|         return CR_OK; | ||||
|     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); | ||||
|     } | ||||
| 
 | ||||
|     eggscan(out); | ||||
|     is_enabled = get_config_bool(config, CONFIG_IS_ENABLED); | ||||
|     DEBUG(config,out).print("loading persisted enabled state: %s\n", | ||||
|                             is_enabled ? "true" : "false"); | ||||
| 
 | ||||
|     return CR_OK; | ||||
| } | ||||
| 
 | ||||
| DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) | ||||
| { | ||||
|     enabled = enable; | ||||
| DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { | ||||
|     if (event == DFHack::SC_WORLD_UNLOADED) { | ||||
|         if (is_enabled) { | ||||
|             DEBUG(config,out).print("world unloaded; disabling %s\n", | ||||
|                                     plugin_name); | ||||
|             is_enabled = false; | ||||
|         } | ||||
|     } | ||||
|     return CR_OK; | ||||
| } | ||||
| 
 | ||||
| static command_result nestboxes(color_ostream &out, vector <string> & parameters) | ||||
| { | ||||
|     CoreSuspender suspend; | ||||
| 
 | ||||
|     if (parameters.size() == 1) { | ||||
|         if (parameters[0] == "enable") | ||||
|             enabled = true; | ||||
|         else if (parameters[0] == "disable") | ||||
|             enabled = false; | ||||
|         else | ||||
|             return CR_WRONG_USAGE; | ||||
|     } else { | ||||
|         out << "Plugin " << (enabled ? "enabled" : "disabled") << "." << endl; | ||||
| DFhackCExport command_result plugin_onupdate(color_ostream &out) { | ||||
|     if (is_enabled && world->frame_counter - cycle_timestamp >= CYCLE_TICKS) { | ||||
|         int32_t num_enabled_seeds, num_disabled_seeds; | ||||
|         do_cycle(out, &num_enabled_seeds, &num_disabled_seeds); | ||||
|         if (0 < num_enabled_seeds) | ||||
|             out.print("%s: enabled %d seed types for cooking\n", | ||||
|                     plugin_name, num_enabled_seeds); | ||||
|         if (0 < num_disabled_seeds) | ||||
|             out.print("%s: protected %d seed types from cooking\n", | ||||
|                     plugin_name, num_disabled_seeds); | ||||
|     } | ||||
|     return CR_OK; | ||||
| } | ||||
| 
 | ||||
| /////////////////////////////////////////////////////
 | ||||
| // cycle logic
 | ||||
| //
 | ||||
| 
 | ||||
| static void do_cycle(color_ostream &out, int32_t *num_enabled_seed_types, int32_t *num_disabled_seed_types) { | ||||
|     DEBUG(cycle,out).print("running %s cycle\n", plugin_name); | ||||
| 
 | ||||
|     // mark that we have recently run
 | ||||
|     cycle_timestamp = world->frame_counter; | ||||
| 
 | ||||
|     for (df::building_nest_boxst *nb : world->buildings.other.NEST_BOX) { | ||||
|         bool fertile = false; | ||||
|         if (nb->claimed_by != -1) { | ||||
|             df::unit *u = df::unit::find(nb->claimed_by); | ||||
|             if (u && u->pregnancy_timer > 0) | ||||
|                 fertile = true; | ||||
|         } | ||||
|         for (auto &contained_item : nb->contained_items) { | ||||
|             df::item *item = contained_item->item; | ||||
|             if (item->flags.bits.forbid != fertile) { | ||||
|                 item->flags.bits.forbid = fertile; | ||||
|                 out.print("%d eggs %s.\n", item->getStackSize(), fertile ? "forbidden" : "unforbidden"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue