2023-02-13 19:45:26 -07:00
|
|
|
#include "plannedbuilding.h"
|
|
|
|
#include "buildingplan.h"
|
|
|
|
|
|
|
|
#include "Debug.h"
|
2023-02-15 20:10:42 -07:00
|
|
|
#include "MiscUtils.h"
|
2023-02-13 19:45:26 -07:00
|
|
|
|
|
|
|
#include "modules/World.h"
|
|
|
|
|
2023-02-15 20:10:42 -07:00
|
|
|
#include "df/job.h"
|
|
|
|
|
2023-02-13 19:45:26 -07:00
|
|
|
namespace DFHack {
|
|
|
|
DBG_EXTERN(buildingplan, status);
|
|
|
|
}
|
|
|
|
|
2023-03-02 18:50:12 -07:00
|
|
|
using std::set;
|
2023-02-15 20:10:42 -07:00
|
|
|
using std::string;
|
|
|
|
using std::vector;
|
2023-03-02 18:50:12 -07:00
|
|
|
|
2023-02-13 19:45:26 -07:00
|
|
|
using namespace DFHack;
|
|
|
|
|
2023-02-15 20:10:42 -07:00
|
|
|
static vector<vector<df::job_item_vector_id>> get_vector_ids(color_ostream &out, int bld_id) {
|
|
|
|
vector<vector<df::job_item_vector_id>> ret;
|
|
|
|
|
|
|
|
df::building *bld = df::building::find(bld_id);
|
|
|
|
|
|
|
|
if (!bld || bld->jobs.size() != 1)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
auto &job = bld->jobs[0];
|
|
|
|
for (auto &jitem : job->job_items) {
|
|
|
|
ret.emplace_back(getVectorIds(out, jitem));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-02-21 19:05:15 -07:00
|
|
|
static vector<vector<df::job_item_vector_id>> deserialize_vector_ids(color_ostream &out, PersistentDataItem &bld_config) {
|
2023-02-15 20:10:42 -07:00
|
|
|
vector<vector<df::job_item_vector_id>> ret;
|
|
|
|
|
2023-02-21 19:05:15 -07:00
|
|
|
vector<string> rawstrs;
|
|
|
|
split_string(&rawstrs, bld_config.val(), "|");
|
|
|
|
const string &serialized = rawstrs[0];
|
|
|
|
|
|
|
|
DEBUG(status,out).print("deserializing vector ids for building %d: %s\n",
|
|
|
|
get_config_val(bld_config, BLD_CONFIG_ID), serialized.c_str());
|
2023-02-15 20:10:42 -07:00
|
|
|
|
|
|
|
vector<string> joined;
|
2023-02-21 19:05:15 -07:00
|
|
|
split_string(&joined, serialized, ";");
|
2023-02-15 20:10:42 -07:00
|
|
|
for (auto &str : joined) {
|
|
|
|
vector<string> lst;
|
|
|
|
split_string(&lst, str, ",");
|
|
|
|
vector<df::job_item_vector_id> ids;
|
|
|
|
for (auto &s : lst)
|
|
|
|
ids.emplace_back(df::job_item_vector_id(string_to_int(s)));
|
|
|
|
ret.emplace_back(ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ret.size())
|
|
|
|
ret = get_vector_ids(out, get_config_val(bld_config, BLD_CONFIG_ID));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-03-02 18:50:12 -07:00
|
|
|
static vector<ItemFilter> get_item_filters(color_ostream &out, PersistentDataItem &bld_config) {
|
2023-02-21 19:05:15 -07:00
|
|
|
vector<string> rawstrs;
|
|
|
|
split_string(&rawstrs, bld_config.val(), "|");
|
|
|
|
if (rawstrs.size() < 2)
|
2023-03-02 18:50:12 -07:00
|
|
|
return vector<ItemFilter>();
|
2023-02-22 16:08:11 -07:00
|
|
|
return deserialize_item_filters(out, rawstrs[1]);
|
2023-02-21 19:05:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static string serialize(const vector<vector<df::job_item_vector_id>> &vector_ids, const vector<ItemFilter> &item_filters) {
|
2023-02-15 20:10:42 -07:00
|
|
|
vector<string> joined;
|
|
|
|
for (auto &vec_list : vector_ids) {
|
|
|
|
joined.emplace_back(join_strings(",", vec_list));
|
|
|
|
}
|
2023-02-21 19:05:15 -07:00
|
|
|
std::ostringstream out;
|
2023-02-22 16:08:11 -07:00
|
|
|
out << join_strings(";", joined) << "|" << serialize_item_filters(item_filters);
|
2023-02-21 19:05:15 -07:00
|
|
|
return out.str();
|
2023-02-15 20:10:42 -07:00
|
|
|
}
|
|
|
|
|
2023-02-21 19:05:15 -07:00
|
|
|
PlannedBuilding::PlannedBuilding(color_ostream &out, df::building *bld, HeatSafety heat, const vector<ItemFilter> &item_filters)
|
|
|
|
: id(bld->id), vector_ids(get_vector_ids(out, id)), heat_safety(heat),
|
|
|
|
item_filters(item_filters) {
|
2023-02-13 19:45:26 -07:00
|
|
|
DEBUG(status,out).print("creating persistent data for building %d\n", id);
|
|
|
|
bld_config = World::AddPersistentData(BLD_CONFIG_KEY);
|
|
|
|
set_config_val(bld_config, BLD_CONFIG_ID, id);
|
2023-02-19 01:57:30 -07:00
|
|
|
set_config_val(bld_config, BLD_CONFIG_HEAT, heat_safety);
|
2023-02-21 19:05:15 -07:00
|
|
|
bld_config.val() = serialize(vector_ids, item_filters);
|
2023-02-15 20:10:42 -07:00
|
|
|
DEBUG(status,out).print("serialized state for building %d: %s\n", id, bld_config.val().c_str());
|
2023-02-13 19:45:26 -07:00
|
|
|
}
|
|
|
|
|
2023-02-15 20:10:42 -07:00
|
|
|
PlannedBuilding::PlannedBuilding(color_ostream &out, PersistentDataItem &bld_config)
|
|
|
|
: id(get_config_val(bld_config, BLD_CONFIG_ID)),
|
2023-02-21 19:05:15 -07:00
|
|
|
vector_ids(deserialize_vector_ids(out, bld_config)),
|
2023-02-19 01:57:30 -07:00
|
|
|
heat_safety((HeatSafety)get_config_val(bld_config, BLD_CONFIG_HEAT)),
|
2023-02-22 16:08:11 -07:00
|
|
|
item_filters(get_item_filters(out, bld_config)),
|
2023-02-15 20:10:42 -07:00
|
|
|
bld_config(bld_config) { }
|
2023-02-13 19:45:26 -07:00
|
|
|
|
|
|
|
// Ensure the building still exists and is in a valid state. It can disappear
|
|
|
|
// for lots of reasons, such as running the game with the buildingplan plugin
|
|
|
|
// disabled, manually removing the building, modifying it via the API, etc.
|
2023-03-10 02:04:23 -07:00
|
|
|
df::building * PlannedBuilding::getBuildingIfValidOrRemoveIfNot(color_ostream &out, bool skip_remove) {
|
2023-02-13 19:45:26 -07:00
|
|
|
auto bld = df::building::find(id);
|
|
|
|
bool valid = bld && bld->getBuildStage() == 0;
|
|
|
|
if (!valid) {
|
2023-03-10 02:04:23 -07:00
|
|
|
if (!skip_remove)
|
|
|
|
remove(out);
|
2023-02-13 19:45:26 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return bld;
|
|
|
|
}
|