From 8c7be9a8c2c5c047eef2bf096536ea648c0e8025 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Thu, 2 Feb 2023 23:33:24 -0800 Subject: [PATCH] don't use negative plant indices and clean up the Kitchen module a bit more --- library/include/modules/Kitchen.h | 3 +++ library/modules/Kitchen.cpp | 32 +++++++++++++++++++++++++------ plugins/seedwatch.cpp | 17 +++++++++++++--- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/library/include/modules/Kitchen.h b/library/include/modules/Kitchen.h index ed8eb95b1..ab064ac39 100644 --- a/library/include/modules/Kitchen.h +++ b/library/include/modules/Kitchen.h @@ -53,6 +53,9 @@ DFHACK_EXPORT void allowPlantSeedCookery(int32_t plant_id); // add this plant to the exclusion list, if it is not already in it DFHACK_EXPORT void denyPlantSeedCookery(int32_t plant_id); +DFHACK_EXPORT bool isPlantCookeryAllowed(int32_t plant_id); +DFHACK_EXPORT bool isSeedCookeryAllowed(int32_t plant_id); + DFHACK_EXPORT std::size_t size(); // Finds the index of a kitchen exclusion in plotinfo.kitchen.exc_types. Returns -1 if not found. diff --git a/library/modules/Kitchen.cpp b/library/modules/Kitchen.cpp index 5bbc2ee7c..4fedf0bab 100644 --- a/library/modules/Kitchen.cpp +++ b/library/modules/Kitchen.cpp @@ -28,12 +28,6 @@ using namespace df::enums; using df::global::world; using df::global::plotinfo; -// Special values used by "seedwatch" plugin to store seed limits -const df::enums::item_type::item_type SEEDLIMIT_ITEMTYPE = df::enums::item_type::BAR; -const int16_t SEEDLIMIT_ITEMSUBTYPE = 0; -const int16_t SEEDLIMIT_MAX = 400; // Maximum permitted seed limit -const df::kitchen_exc_type SEEDLIMIT_EXCTYPE = df::kitchen_exc_type(4); - void Kitchen::debug_print(color_ostream &out) { out.print("Kitchen Exclusions\n"); @@ -54,6 +48,9 @@ void Kitchen::debug_print(color_ostream &out) void Kitchen::allowPlantSeedCookery(int32_t plant_id) { + if (plant_id < 0 || plant_id >= world->raws.plants.all.size()) + return; + df::plant_raw *type = world->raws.plants.all[plant_id]; removeExclusion(df::kitchen_exc_type::Cook, item_type::SEEDS, -1, @@ -67,6 +64,9 @@ void Kitchen::allowPlantSeedCookery(int32_t plant_id) void Kitchen::denyPlantSeedCookery(int32_t plant_id) { + if (plant_id < 0 || plant_id >= world->raws.plants.all.size()) + return; + df::plant_raw *type = world->raws.plants.all[plant_id]; addExclusion(df::kitchen_exc_type::Cook, item_type::SEEDS, -1, @@ -78,6 +78,26 @@ void Kitchen::denyPlantSeedCookery(int32_t plant_id) type->material_defs.idx[plant_material_def::basic_mat]); } +bool Kitchen::isPlantCookeryAllowed(int32_t plant_id) { + if (plant_id < 0 || plant_id >= world->raws.plants.all.size()) + return false; + + df::plant_raw *type = world->raws.plants.all[plant_id]; + return findExclusion(df::kitchen_exc_type::Cook, item_type::PLANT, -1, + type->material_defs.type[plant_material_def::basic_mat], + type->material_defs.idx[plant_material_def::basic_mat]) < 0; +} + +bool Kitchen::isSeedCookeryAllowed(int32_t plant_id) { + if (plant_id < 0 || plant_id >= world->raws.plants.all.size()) + return false; + + df::plant_raw *type = world->raws.plants.all[plant_id]; + return findExclusion(df::kitchen_exc_type::Cook, item_type::SEEDS, -1, + type->material_defs.type[plant_material_def::seed], + type->material_defs.idx[plant_material_def::seed]) < 0; +} + size_t Kitchen::size() { return plotinfo->kitchen.item_types.size(); diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 03ea4f268..fed563a84 100644 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -301,7 +301,7 @@ static void scan_seeds(color_ostream &out, unordered_map *acce for (auto &item : world->items.other[items_other_id::SEEDS]) { MaterialInfo mat(item); - if (!mat.isPlant()) + if (mat.plant->index < 0 || !mat.isPlant()) continue; if ((bad_flags.whole & item->flags.whole) || !is_accessible_item(item, citizens)) { if (inaccessible_counts) @@ -329,13 +329,19 @@ static void do_cycle(color_ostream &out, int32_t *num_enabled_seed_types, int32_ for (auto &entry : watched_seeds) { int32_t id = entry.first; + if (id < 0 || id >= world->raws.plants.all.size()) + continue; int32_t target = get_config_val(entry.second, SEED_CONFIG_TARGET); - if (accessible_counts[id] <= target) { + if (accessible_counts[id] <= target && + (Kitchen::isPlantCookeryAllowed(id) || + Kitchen::isSeedCookeryAllowed(id))) { DEBUG(cycle,out).print("disabling seed mat: %d\n", id); if (num_disabled_seed_types) ++*num_disabled_seed_types; Kitchen::denyPlantSeedCookery(id); - } else if (target + TARGET_BUFFER < accessible_counts[id]) { + } else if (target + TARGET_BUFFER < accessible_counts[id] && + (!Kitchen::isPlantCookeryAllowed(id) || + !Kitchen::isSeedCookeryAllowed(id))) { DEBUG(cycle,out).print("enabling seed mat: %d\n", id); if (num_enabled_seed_types) ++*num_enabled_seed_types; @@ -353,6 +359,11 @@ static void set_target(color_ostream &out, int32_t id, int32_t target) { if (target == 0) remove_seed_config(out, id); else { + if (id < 0 || id >= world->raws.plants.all.size()) { + WARN(config,out).print( + "cannot set target for unknown plant id: %d\n", id); + return; + } PersistentDataItem &c = ensure_seed_config(out, id); set_config_val(c, SEED_CONFIG_TARGET, target); }