diff --git a/library/include/modules/World.h b/library/include/modules/World.h index 01ad231d0..50feb1495 100644 --- a/library/include/modules/World.h +++ b/library/include/modules/World.h @@ -80,6 +80,30 @@ namespace DFHack GameType g_type; }; class DFContextShared; + + class DFHACK_EXPORT PersistentDataItem { + friend class World; + + int id; + std::string key_value; + + std::string *str_value; + int *int_values; + public: + static const int NumInts = 7; + + bool isValid() { return id != 0; } + + const std::string &key() { return key_value; } + + std::string &val() { return *str_value; } + int &ival(int i) { return int_values[i]; } + + PersistentDataItem() : id(0), str_value(0), int_values(0) {} + PersistentDataItem(int id, const std::string &key, std::string *sv, int *iv) + : id(id), key_value(key), str_value(sv), int_values(iv) {} + }; + /** * The World module * \ingroup grp_modules @@ -108,6 +132,14 @@ namespace DFHack bool ReadGameMode(t_gamemodes& rd); bool WriteGameMode(const t_gamemodes & wr); // this is very dangerous std::string ReadWorldFolder(); + + // Store data in fake historical figure names. + // This ensures that the values are stored in save games. + PersistentDataItem AddPersistentData(const std::string &key); + PersistentDataItem GetPersistentData(const std::string &key); + void GetPersistentData(std::vector *vec, const std::string &key); + void DeletePersistentData(const PersistentDataItem &item); + private: struct Private; Private *d; diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 5d1292a9e..4dea79c2b 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -38,6 +38,12 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" +#include "MiscUtils.h" + +#include "DataDefs.h" +#include "df/world.h" +#include "df/historical_figure.h" + using namespace DFHack; Module* DFHack::createWorld() @@ -241,3 +247,71 @@ string World::ReadWorldFolder() } return string(""); } + +static PersistentDataItem dataFromHFig(df::historical_figure *hfig) +{ + return PersistentDataItem(hfig->id, hfig->name.first_name, &hfig->name.nickname, hfig->name.words); +} + +PersistentDataItem World::AddPersistentData(const std::string &key) +{ + std::vector &hfvec = df::historical_figure::get_vector(); + + int new_id = -100; + if (hfvec.size() > 0 && hfvec[0]->id <= new_id) + new_id = hfvec[0]->id-1; + + df::historical_figure *hfig = new df::historical_figure(); + hfig->id = new_id; + hfig->name.has_name = true; + hfig->name.first_name = key; + memset(hfig->name.words, 0, sizeof(hfig->name.words)); + + hfvec.insert(hfvec.begin(), hfig); + return dataFromHFig(hfig); +} + +PersistentDataItem World::GetPersistentData(const std::string &key) +{ + std::vector &hfvec = df::historical_figure::get_vector(); + for (unsigned i = 0; i < hfvec.size(); i++) + { + df::historical_figure *hfig = hfvec[i]; + + if (hfig->id >= 0) + break; + + if (hfig->name.has_name && hfig->name.first_name == key) + return dataFromHFig(hfig); + } + + return PersistentDataItem(); +} + +void World::GetPersistentData(std::vector *vec, const std::string &key) +{ + std::vector &hfvec = df::historical_figure::get_vector(); + for (unsigned i = 0; i < hfvec.size(); i++) + { + df::historical_figure *hfig = hfvec[i]; + + if (hfig->id >= 0) + break; + + if (hfig->name.has_name && hfig->name.first_name == key) + vec->push_back(dataFromHFig(hfig)); + } +} + +void World::DeletePersistentData(const PersistentDataItem &item) +{ + if (item.id > -100) + return; + + std::vector &hfvec = df::historical_figure::get_vector(); + int idx = binsearch_index(hfvec, item.id); + if (idx >= 0) { + delete hfvec[idx]; + hfvec.erase(hfvec.begin()+idx); + } +}