diff --git a/plugins/buildingplan-planner.cpp b/plugins/buildingplan-planner.cpp index 42c84f4dc..963d13153 100644 --- a/plugins/buildingplan-planner.cpp +++ b/plugins/buildingplan-planner.cpp @@ -20,6 +20,7 @@ static const std::string planned_building_persistence_key_v1 = "buildingplan/constraints"; static const std::string planned_building_persistence_key_v2 = "buildingplan/constraints2"; +static const std::string global_settings_persistence_key = "buildingplan/global"; /* * ItemFilter @@ -501,13 +502,69 @@ void migrateV1ToV2() } } -static void init_global_settings(std::map & settings) +// assumes no setting has '=' or '|' characters +static std::string serialize_settings(std::map & settings) +{ + std::ostringstream ser; + for (auto & entry : settings) + { + ser << entry.first << "=" << (entry.second ? "1" : "0") << "|"; + } + return ser.str(); +} + +static void deserialize_settings(std::map & settings, + std::string ser) +{ + std::vector tokens; + split_string(&tokens, ser, "|"); + for (auto token : tokens) + { + if (token.empty()) + continue; + + std::vector parts; + split_string(&parts, token, "="); + if (parts.size() != 2) + { + debug("invalid serialized setting format: '%s'", token.c_str()); + continue; + } + std::string key = parts[0]; + if (settings.count(key) == 0) + { + debug("unknown serialized setting: '%s", key.c_str()); + continue; + } + settings[key] = static_cast(atoi(parts[1].c_str())); + debug("deserialized setting: %s = %d", key.c_str(), settings[key]); + } +} + +static DFHack::PersistentDataItem init_global_settings( + std::map & settings) { settings.clear(); settings["blocks"] = true; settings["boulders"] = true; settings["logs"] = true; settings["bars"] = false; + + // load persistent global settings if they exist; otherwise create them + std::vector items; + DFHack::World::GetPersistentData(&items, global_settings_persistence_key); + if (items.size() == 1) + { + DFHack::PersistentDataItem & config = items[0]; + deserialize_settings(settings, config.val()); + return config; + } + + debug("initializing persistent global settings"); + DFHack::PersistentDataItem config = + DFHack::World::AddPersistentData(global_settings_persistence_key); + config.val() = serialize_settings(settings); + return config; } const std::map & Planner::getGlobalSettings() const @@ -525,6 +582,8 @@ bool Planner::setGlobalSetting(std::string name, bool value) debug("global setting '%s' %d -> %d", name.c_str(), global_settings[name], value); global_settings[name] = value; + if (config.isValid()) + config.val() = serialize_settings(global_settings); return true; } @@ -535,7 +594,7 @@ void Planner::reset() planned_buildings.clear(); tasks.clear(); - init_global_settings(global_settings); + config = init_global_settings(global_settings); migrateV1ToV2(); diff --git a/plugins/buildingplan-planner.h b/plugins/buildingplan-planner.h index 18cfaf0b1..7b1615704 100644 --- a/plugins/buildingplan-planner.h +++ b/plugins/buildingplan-planner.h @@ -120,6 +120,7 @@ public: void doCycle(); private: + DFHack::PersistentDataItem config; std::map global_settings; std::unordered_map, diff --git a/plugins/buildingplan.cpp b/plugins/buildingplan.cpp index 52bd5118f..a89c6c8fd 100644 --- a/plugins/buildingplan.cpp +++ b/plugins/buildingplan.cpp @@ -7,6 +7,7 @@ #include "modules/Maps.h" #include "modules/World.h" +#include "Core.h" #include "LuaTools.h" #include "PluginManager.h" @@ -814,6 +815,33 @@ IMPLEMENT_VMETHOD_INTERPOSE(buildingplan_query_hook, render); IMPLEMENT_VMETHOD_INTERPOSE(buildingplan_place_hook, render); IMPLEMENT_VMETHOD_INTERPOSE(buildingplan_room_hook, render); +static DFHack::PersistentDataItem get_ui_settings_config() +{ + static const std::string settings_persistence_key = + "buildingplan/ui_settings"; + + bool added; + DFHack::PersistentDataItem config = + DFHack::World::GetPersistentData(settings_persistence_key, &added); + if (added) + { + config.ival(0) = quickfort_mode; + } + return config; +} + +static void load_settings() +{ + DFHack::PersistentDataItem config = get_ui_settings_config(); + quickfort_mode = config.ival(0); +} + +static void save_settings() +{ + DFHack::PersistentDataItem config = get_ui_settings_config(); + config.ival(0) = quickfort_mode; +} + static command_result buildingplan_cmd(color_ostream &out, vector & parameters) { if (!parameters.empty()) @@ -841,7 +869,11 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) if (enable != is_enabled) { - planner.reset(); + if (DFHack::Core::getInstance().isMapLoaded()) + { + load_settings(); + planner.reset(); + } if (!INTERPOSE_HOOK(buildingplan_query_hook, feed).apply(enable) || !INTERPOSE_HOOK(buildingplan_place_hook, feed).apply(enable) || @@ -871,6 +903,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan { switch (event) { case SC_MAP_LOADED: + load_settings(); planner.reset(); roomMonitor.reset(out); break; @@ -928,6 +961,7 @@ static void setSetting(std::string name, bool value) { { debug("setting quickfort_mode %d -> %d", quickfort_mode, value); quickfort_mode = value; + save_settings(); return; } planner.setGlobalSetting(name, value);