diff --git a/plugins/lua/stockpiles.lua b/plugins/lua/stockpiles.lua index 6770c044e..1a92e2c0c 100644 --- a/plugins/lua/stockpiles.lua +++ b/plugins/lua/stockpiles.lua @@ -92,6 +92,12 @@ local function export_stockpile(name, opts) end end + if includedElements == 0 then + for _,v in pairs(included_elements) do + includedElements = includedElements | v + end + end + stockpiles_export(name, get_sp_id(opts), includedElements) end @@ -142,14 +148,14 @@ local function process_args(opts, args) opts.filter = '' return argparse.processArgsGetopt(args, { - {'f', 'filter', has_arg=true, + {'f', 'filter', hasArg=true, handler=function(arg) opts.filter = arg end}, {'h', 'help', handler=function() opts.help = true end}, - {'i', 'include', has_arg=true, + {'i', 'include', hasArg=true, handler=function(arg) opts.includes = parse_include(arg) end}, - {'m', 'mode', has_arg=true, + {'m', 'mode', hasArg=true, handler=function(arg) opts.mode = parse_mode(arg) end}, - {'s', 'stockpile', has_arg=true, + {'s', 'stockpile', hasArg=true, handler=function(arg) opts.id = argparse.nonnegativeInt(arg, 'stockpile') end}, }) end diff --git a/plugins/stockpiles/StockpileSerializer.cpp b/plugins/stockpiles/StockpileSerializer.cpp index 3b2849333..2d72aa822 100644 --- a/plugins/stockpiles/StockpileSerializer.cpp +++ b/plugins/stockpiles/StockpileSerializer.cpp @@ -10,6 +10,7 @@ // df #include "df/building_stockpilest.h" +#include "df/creature_raw.h" #include "df/inorganic_raw.h" #include "df/item_quality.h" #include @@ -520,7 +521,7 @@ static void unserialize_list_material(FuncMaterialAllowed is_allowed, } template -static void write_cat(bool include_types, uint32_t cat_flags, +static void write_cat(const char *name, bool include_types, uint32_t cat_flags, enum df::stockpile_group_set::Mask cat_mask, std::function mutable_cat_fn, std::function write_cat_fn) { @@ -528,13 +529,17 @@ static void write_cat(bool include_types, uint32_t cat_flags, return; T_cat_set* cat_set = mutable_cat_fn(); + if (!include_types) { + DEBUG(log).print("including all for %s since only category is being recorded\n", name); cat_set->set_all(true); return; } if (write_cat_fn(cat_set)) { - // all fields were set. might as well clear them and use the "all" flag + // all fields were set. clear them and use the "all" flag instead so "all" can be applied + // to other worlds with other generated types + DEBUG(log).print("including all for %s since all fields were enabled\n", name); cat_set->Clear(); cat_set->set_all(true); } @@ -554,90 +559,90 @@ void StockpileSerializer::write(uint32_t includedElements) { bool include_types = 0 != (includedElements & INCLUDED_ELEMENTS_TYPES); - write_cat(include_types, + write_cat("ammo", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_ammo, - std::bind(&StockpileSettings::mutable_ammo, mBuffer), + std::bind(&StockpileSettings::mutable_ammo, &mBuffer), std::bind(&StockpileSerializer::write_ammo, this, _1)); - write_cat(include_types, + write_cat("animals", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_animals, - std::bind(&StockpileSettings::mutable_animals, mBuffer), + std::bind(&StockpileSettings::mutable_animals, &mBuffer), std::bind(&StockpileSerializer::write_animals, this, _1)); - write_cat(include_types, + write_cat("armor", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_armor, - std::bind(&StockpileSettings::mutable_armor, mBuffer), + std::bind(&StockpileSettings::mutable_armor, &mBuffer), std::bind(&StockpileSerializer::write_armor, this, _1)); - write_cat(include_types, + write_cat("bars_blocks", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_bars_blocks, - std::bind(&StockpileSettings::mutable_barsblocks, mBuffer), + std::bind(&StockpileSettings::mutable_barsblocks, &mBuffer), std::bind(&StockpileSerializer::write_bars_blocks, this, _1)); - write_cat(include_types, + write_cat("cloth", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_cloth, - std::bind(&StockpileSettings::mutable_cloth, mBuffer), + std::bind(&StockpileSettings::mutable_cloth, &mBuffer), std::bind(&StockpileSerializer::write_cloth, this, _1)); - write_cat(include_types, + write_cat("coin", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_coins, - std::bind(&StockpileSettings::mutable_coin, mBuffer), + std::bind(&StockpileSettings::mutable_coin, &mBuffer), std::bind(&StockpileSerializer::write_coins, this, _1)); - write_cat(include_types, + write_cat("finished_goods", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_finished_goods, - std::bind(&StockpileSettings::mutable_finished_goods, mBuffer), + std::bind(&StockpileSettings::mutable_finished_goods, &mBuffer), std::bind(&StockpileSerializer::write_finished_goods, this, _1)); - write_cat(include_types, + write_cat("food", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_food, - std::bind(&StockpileSettings::mutable_food, mBuffer), + std::bind(&StockpileSettings::mutable_food, &mBuffer), std::bind(&StockpileSerializer::write_food, this, _1)); - write_cat(include_types, + write_cat("furniture", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_furniture, - std::bind(&StockpileSettings::mutable_furniture, mBuffer), + std::bind(&StockpileSettings::mutable_furniture, &mBuffer), std::bind(&StockpileSerializer::write_furniture, this, _1)); - write_cat(include_types, + write_cat("gems", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_gems, - std::bind(&StockpileSettings::mutable_gems, mBuffer), + std::bind(&StockpileSettings::mutable_gems, &mBuffer), std::bind(&StockpileSerializer::write_gems, this, _1)); - write_cat(include_types, + write_cat("leather", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_leather, - std::bind(&StockpileSettings::mutable_leather, mBuffer), + std::bind(&StockpileSettings::mutable_leather, &mBuffer), std::bind(&StockpileSerializer::write_leather, this, _1)); - write_cat(include_types, + write_cat("corpses", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_corpses, - std::bind(&StockpileSettings::mutable_corpses_v50, mBuffer), + std::bind(&StockpileSettings::mutable_corpses_v50, &mBuffer), std::bind(&StockpileSerializer::write_corpses, this, _1)); - write_cat(include_types, + write_cat("refuse", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_refuse, - std::bind(&StockpileSettings::mutable_refuse, mBuffer), + std::bind(&StockpileSettings::mutable_refuse, &mBuffer), std::bind(&StockpileSerializer::write_refuse, this, _1)); - write_cat(include_types, + write_cat("sheet", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_sheet, - std::bind(&StockpileSettings::mutable_sheet, mBuffer), + std::bind(&StockpileSettings::mutable_sheet, &mBuffer), std::bind(&StockpileSerializer::write_sheet, this, _1)); - write_cat(include_types, + write_cat("stone", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_stone, - std::bind(&StockpileSettings::mutable_stone, mBuffer), + std::bind(&StockpileSettings::mutable_stone, &mBuffer), std::bind(&StockpileSerializer::write_stone, this, _1)); - write_cat(include_types, + write_cat("weapons", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_weapons, - std::bind(&StockpileSettings::mutable_weapons, mBuffer), + std::bind(&StockpileSettings::mutable_weapons, &mBuffer), std::bind(&StockpileSerializer::write_weapons, this, _1)); - write_cat(include_types, + write_cat("wood", include_types, mPile->settings.flags.whole, mPile->settings.flags.mask_wood, - std::bind(&StockpileSettings::mutable_wood, mBuffer), + std::bind(&StockpileSettings::mutable_wood, &mBuffer), std::bind(&StockpileSerializer::write_wood, this, _1)); } @@ -672,6 +677,7 @@ void StockpileSerializer::read(DeserializeMode mode, const std::string& filter) } void StockpileSerializer::write_containers() { + DEBUG(log).print("writing container settings\n"); mBuffer.set_max_bins(mPile->max_bins); mBuffer.set_max_barrels(mPile->max_barrels); mBuffer.set_max_wheelbarrows(mPile->max_wheelbarrows); @@ -682,18 +688,10 @@ static void read_elem(const char *name, DeserializeMode mode, std::function has_elem_fn, std::function elem_fn, T_elem &setting) { - bool has_elem = has_elem_fn(); - bool is_set = has_elem && elem_fn() != 0; - bool just_disable = is_set && mode == DESERIALIZE_MODE_DISABLE; - - if (mode == DESERIALIZE_MODE_SET || just_disable) { - DEBUG(log).print("clearing %s\n", name); - setting = 0; - } - - if (!has_elem || just_disable) + if (!has_elem_fn()) return; + bool is_set = elem_fn() != 0; if (mode == DESERIALIZE_MODE_SET || is_set) { T_elem val = (mode == DESERIALIZE_MODE_DISABLE) ? 0 : elem_fn(); DEBUG(log).print("setting %s=%d\n", name, val); @@ -728,11 +726,30 @@ static void read_category(const char *name, DeserializeMode mode, if (mode == DESERIALIZE_MODE_SET || mode == DESERIALIZE_MODE_ENABLE) cat_flags |= cat_mask; - bool force = mode == DESERIALIZE_MODE_SET || all; char val = (mode == DESERIALIZE_MODE_DISABLE) ? (char)0 : (char)1; DEBUG(log).print("setting %s %s elements to %d\n", all ? "all" : "marked", name, val); - set_fn(force, val); + set_fn(all, val); +} + +static void set_elem(bool all, char val, bool enabled, bool& elem) { + if (all || enabled) + elem = val; +} + +static bool matches_filter(const std::string& filter, const std::string& name) { + if (!filter.size()) + return true; + return std::search(name.begin(), name.end(), filter.begin(), filter.end(), + [](unsigned char ch1, unsigned char ch2) { return std::toupper(ch1) == std::toupper(ch2); } + ) != name.end(); +} + +static void set_filter_elem(const std::string& filter, char val, df::creature_raw* r, char& elem) { + if (matches_filter(filter, r->name[0])) { + DEBUG(log).print("setting %s (%s) to %d\n", r->name[0].c_str(), r->creature_id.c_str(), val); + elem = val; + } } void StockpileSerializer::read_containers(DeserializeMode mode) { @@ -751,6 +768,7 @@ void StockpileSerializer::read_containers(DeserializeMode mode) { } void StockpileSerializer::write_general() { + DEBUG(log).print("writing general settings\n"); mBuffer.set_use_links_only(mPile->use_links_only); mBuffer.set_allow_inorganic(mPile->settings.allow_inorganic); mBuffer.set_allow_organic(mPile->settings.allow_organic); @@ -776,22 +794,17 @@ static bool ammo_mat_is_allowed(const MaterialInfo& mi) { } bool StockpileSerializer::write_ammo(StockpileSettings::AmmoSet* ammo) { - bool all = true; - - // ammo type - all = serialize_list_itemdef( + bool all = serialize_list_itemdef( [=](const std::string& token) { ammo->add_type(token); }, mPile->settings.ammo.type, std::vector(world->raws.itemdefs.ammo.begin(), world->raws.itemdefs.ammo.end()), - item_type::AMMO) && all; + item_type::AMMO); - // metal all = serialize_list_material( ammo_mat_is_allowed, [=](const std::string& token) { ammo->add_mats(token); }, mPile->settings.ammo.mats) && all; - // other mats - only wood and bone are expected if (mPile->settings.ammo.other_mats.size() > 2) { WARN(log).print("ammo other materials > 2: %zd\n", mPile->settings.ammo.other_mats.size()); @@ -809,12 +822,10 @@ bool StockpileSerializer::write_ammo(StockpileSettings::AmmoSet* ammo) { DEBUG(log).print("other mats %zd is %s\n", i, token.c_str()); } - // quality core all = serialize_list_quality( [=](const std::string& token) { ammo->add_quality_core(token); }, mPile->settings.ammo.quality_core) && all; - // quality total all = serialize_list_quality( [=](const std::string& token) { ammo->add_quality_total(token); }, mPile->settings.ammo.quality_total) && all; @@ -823,13 +834,13 @@ bool StockpileSerializer::write_ammo(StockpileSettings::AmmoSet* ammo) { } void StockpileSerializer::read_ammo(DeserializeMode mode, const std::string& filter) { + auto & pammo = mPile->settings.ammo; read_category("ammo", mode, std::bind(&StockpileSettings::has_ammo, mBuffer), std::bind(&StockpileSettings::ammo, mBuffer), mPile->settings.flags.whole, mPile->settings.flags.mask_ammo, [&]() { - auto & pammo = mPile->settings.ammo; pammo.type.clear(); pammo.mats.clear(); pammo.other_mats.clear(); @@ -838,18 +849,15 @@ void StockpileSerializer::read_ammo(DeserializeMode mode, const std::string& fil }, [&](bool force, char val) { auto & bammo = mBuffer.ammo(); - auto & pammo = mPile->settings.ammo; - // ammo type + unserialize_list_itemdef( - [=](const size_t& idx) -> const std::string& { return bammo.type(idx); }, + [&](const size_t& idx) -> const std::string& { return bammo.type(idx); }, bammo.type_size(), &pammo.type, item_type::AMMO); - // materials metals unserialize_list_material(ammo_mat_is_allowed, - [=](const size_t& idx) -> const std::string& { return bammo.mats(idx); }, + [&](const size_t& idx) -> const std::string& { return bammo.mats(idx); }, bammo.mats_size(), &pammo.mats); - // others pammo.other_mats.clear(); pammo.other_mats.resize(2, '\0'); if (bammo.other_mats_size() > 0) { @@ -859,16 +867,15 @@ void StockpileSerializer::read_ammo(DeserializeMode mode, const std::string& fil const int32_t idx = token == "WOOD" ? 0 : token == "BONE" ? 1 : -1; DEBUG(log).print("other mats %d is %s\n", idx, token.c_str()); - if (idx != -1) - pammo.other_mats.at(idx) = 1; + if (idx == -1) + continue; + pammo.other_mats.at(idx) = 1; } } - // core quality unserialize_list_quality([=](const size_t& idx) -> const std::string& { return bammo.quality_core(idx); }, bammo.quality_core_size(), pammo.quality_core); - // total quality unserialize_list_quality([=](const size_t& idx) -> const std::string& { return bammo.quality_total(idx); }, bammo.quality_total_size(), pammo.quality_total); }); @@ -886,43 +893,47 @@ bool StockpileSerializer::write_animals(StockpileSettings::AnimalsSet* animals) continue; } df::creature_raw* r = find_creature(i); - DEBUG(log).print("creature %s %zd\n", r->creature_id.c_str(), i); + if (r->flags.is_set(creature_raw_flags::GENERATED) + || r->creature_id == "EQUIPMENT_WAGON") + continue; + DEBUG(log).print("saving creature %s\n", r->creature_id.c_str()); animals->add_enabled(r->creature_id); } return all; } void StockpileSerializer::read_animals(DeserializeMode mode, const std::string& filter) { + auto & panimals = mPile->settings.animals; read_category("animals", mode, std::bind(&StockpileSettings::has_animals, mBuffer), std::bind(&StockpileSettings::animals, mBuffer), mPile->settings.flags.whole, mPile->settings.flags.mask_animals, [&]() { - auto & panimals = mPile->settings.animals; panimals.empty_cages = false; panimals.empty_traps = false; panimals.enabled.clear(); }, - [&](bool force, char val) { + [&](bool all, char val) { auto & banimals = mBuffer.animals(); - auto & panimals = mPile->settings.animals; - if (force || banimals.empty_cages()) - panimals.empty_cages = banimals.empty_cages() && val; - if (force || banimals.empty_traps()) - panimals.empty_traps = banimals.empty_traps() && val; - - panimals.enabled.resize(world->raws.creatures.all.size(), '\0'); - for (auto i = 0; i < banimals.enabled_size(); ++i) { - const std::string& id = banimals.enabled(i); - int idx = find_creature(id); - DEBUG(log).print("%s %d\n", id.c_str(), idx); - if (idx < 0 || size_t(idx) >= panimals.enabled.size()) { - WARN(log).print("animal index invalid: %d\n", idx); - continue; + set_elem(all, val, banimals.empty_cages(), panimals.empty_cages); + set_elem(all, val, banimals.empty_traps(), panimals.empty_traps); + + size_t num_animals = world->raws.creatures.all.size(); + panimals.enabled.resize(num_animals, '\0'); + if (all) { + for (auto idx = 0; idx < num_animals; ++idx) + set_filter_elem(filter, val, find_creature(idx), panimals.enabled.at(idx)); + } else { + for (auto i = 0; i < banimals.enabled_size(); ++i) { + const std::string& id = banimals.enabled(i); + int idx = find_creature(id); + if (idx < 0 || size_t(idx) >= num_animals) { + WARN(log).print("animal index invalid: %d\n", idx); + continue; + } + set_filter_elem(filter, val, find_creature(idx), panimals.enabled.at(idx)); } - if (!filter.size() || id.find(filter) != id.npos) - panimals.enabled.at(idx) = val; } }); }