Cleanup Kitchen module (and the seedwatch plugin which uses it)

develop
Quietust 2020-06-29 19:35:07 -06:00 committed by Myk
parent 9f8a477f09
commit aa1bc3fe52
3 changed files with 114 additions and 162 deletions

@ -43,12 +43,6 @@ namespace DFHack
{ {
namespace Kitchen namespace Kitchen
{ {
const unsigned int seedLimit = 400; // a limit on the limits which can be placed on seeds
const t_itemSubtype organicSubtype = -1; // seems to fixed
const df::enums::item_type::item_type limitType = df::enums::item_type::BAR; // used to store limit as an entry in the exclusion list. 0 = BAR
const t_itemSubtype limitSubtype = 0; // used to store limit as an entry in the exclusion list
const df::kitchen_exc_type limitExclusion = df::kitchen_exc_type(4); // used to store limit as an entry in the exclusion list
/** /**
* Kitchen exclusions manipulator. Currently geared towards plants and seeds. * Kitchen exclusions manipulator. Currently geared towards plants and seeds.
* \ingroup grp_modules * \ingroup grp_modules
@ -58,20 +52,23 @@ const df::kitchen_exc_type limitExclusion = df::kitchen_exc_type(4); // used to
// print the exclusion list, with the material index also translated into its token (for organics) - for debug really // print the exclusion list, with the material index also translated into its token (for organics) - for debug really
DFHACK_EXPORT void debug_print(color_ostream &out); DFHACK_EXPORT void debug_print(color_ostream &out);
// remove this material from the exclusion list if it is in it // remove this plant from the exclusion list if it is in it
DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex); DFHACK_EXPORT void allowPlantSeedCookery(int32_t plant_id);
// add this material to the exclusion list, if it is not already in it // add this plant to the exclusion list, if it is not already in it
DFHACK_EXPORT void denyPlantSeedCookery(t_materialIndex materialIndex); DFHACK_EXPORT void denyPlantSeedCookery(int32_t plant_id);
// fills a map with info from the limit info storage entries in the exclusion list // fills a map with info from the limit info storage entries in the exclusion list
DFHACK_EXPORT void fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap); DFHACK_EXPORT void fillWatchMap(std::map<int32_t, int16_t>& watchMap);
// Finds the index of a limit info storage entry. Returns -1 if not found.
DFHACK_EXPORT int findLimit(int32_t plant_id);
// removes a limit info storage entry from the exclusion list if it's present // removes a limit info storage entry from the exclusion list if it's present
DFHACK_EXPORT void removeLimit(t_materialIndex materialIndex); DFHACK_EXPORT bool removeLimit(int32_t plant_id);
// add a limit info storage item to the exclusion list, or alters an existing one // add a limit info storage item to the exclusion list, or alters an existing one
DFHACK_EXPORT void setLimit(t_materialIndex materialIndex, unsigned int limit); DFHACK_EXPORT bool setLimit(int32_t plant_id, int16_t limit);
// clears all limit info storage items from the exclusion list // clears all limit info storage items from the exclusion list
DFHACK_EXPORT void clearLimits(); DFHACK_EXPORT void clearLimits();

@ -28,6 +28,12 @@ using namespace df::enums;
using df::global::world; using df::global::world;
using df::global::ui; using df::global::ui;
// 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) void Kitchen::debug_print(color_ostream &out)
{ {
out.print("Kitchen Exclusions\n"); out.print("Kitchen Exclusions\n");
@ -46,150 +52,108 @@ void Kitchen::debug_print(color_ostream &out)
out.print("\n"); out.print("\n");
} }
void Kitchen::allowPlantSeedCookery(t_materialIndex materialIndex) void Kitchen::allowPlantSeedCookery(int32_t plant_id)
{ {
bool match = false; df::plant_raw *type = world->raws.plants.all[plant_id];
do
{ removeExclusion(df::kitchen_exc_type::Cook, item_type::SEEDS, -1,
match = false; type->material_defs.type[plant_material_def::seed],
std::size_t matchIndex = 0; type->material_defs.idx[plant_material_def::seed]);
for(std::size_t i = 0; i < size(); ++i)
{ removeExclusion(df::kitchen_exc_type::Cook, item_type::PLANT, -1,
if(ui->kitchen.mat_indices[i] == materialIndex type->material_defs.type[plant_material_def::basic_mat],
&& (ui->kitchen.item_types[i] == item_type::SEEDS || ui->kitchen.item_types[i] == item_type::PLANT) type->material_defs.idx[plant_material_def::basic_mat]);
&& ui->kitchen.exc_types[i] == df::kitchen_exc_type::Cook
)
{
match = true;
matchIndex = i;
}
}
if(match)
{
ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex);
ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex);
ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex);
ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex);
ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex);
}
} while(match);
} }
void Kitchen::denyPlantSeedCookery(t_materialIndex materialIndex) void Kitchen::denyPlantSeedCookery(int32_t plant_id)
{ {
df::plant_raw *type = world->raws.plants.all[materialIndex]; df::plant_raw *type = world->raws.plants.all[plant_id];
bool SeedAlreadyIn = false;
bool PlantAlreadyIn = false; addExclusion(df::kitchen_exc_type::Cook, item_type::SEEDS, -1,
for(std::size_t i = 0; i < size(); ++i) type->material_defs.type[plant_material_def::seed],
{ type->material_defs.idx[plant_material_def::seed]);
if(ui->kitchen.mat_indices[i] == materialIndex
&& ui->kitchen.exc_types[i] == df::kitchen_exc_type::Cook) addExclusion(df::kitchen_exc_type::Cook, item_type::PLANT, -1,
{ type->material_defs.type[plant_material_def::basic_mat],
if(ui->kitchen.item_types[i] == item_type::SEEDS) type->material_defs.idx[plant_material_def::basic_mat]);
SeedAlreadyIn = true;
else if (ui->kitchen.item_types[i] == item_type::PLANT)
PlantAlreadyIn = true;
}
}
if(!SeedAlreadyIn)
{
ui->kitchen.item_types.push_back(item_type::SEEDS);
ui->kitchen.item_subtypes.push_back(organicSubtype);
ui->kitchen.mat_types.push_back(type->material_defs.type[plant_material_def::seed]);
ui->kitchen.mat_indices.push_back(materialIndex);
ui->kitchen.exc_types.push_back(df::kitchen_exc_type::Cook);
}
if(!PlantAlreadyIn)
{
ui->kitchen.item_types.push_back(item_type::PLANT);
ui->kitchen.item_subtypes.push_back(organicSubtype);
ui->kitchen.mat_types.push_back(type->material_defs.type[plant_material_def::basic_mat]);
ui->kitchen.mat_indices.push_back(materialIndex);
ui->kitchen.exc_types.push_back(df::kitchen_exc_type::Cook);
}
} }
void Kitchen::fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap) void Kitchen::fillWatchMap(std::map<int32_t, int16_t>& watchMap)
{ {
watchMap.clear(); watchMap.clear();
for(std::size_t i = 0; i < size(); ++i) for (std::size_t i = 0; i < size(); ++i)
{ {
if(ui->kitchen.item_subtypes[i] == (short)limitType && ui->kitchen.item_subtypes[i] == (short)limitSubtype && ui->kitchen.exc_types[i] == limitExclusion) if (ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMTYPE &&
ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
ui->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
{ {
watchMap[ui->kitchen.mat_indices[i]] = (unsigned int) ui->kitchen.mat_types[i]; watchMap[ui->kitchen.mat_indices[i]] = ui->kitchen.mat_types[i];
} }
} }
} }
void Kitchen::removeLimit(t_materialIndex materialIndex) int Kitchen::findLimit(int32_t plant_id)
{ {
bool match = false; for (size_t i = 0; i < size(); ++i)
do
{
match = false;
std::size_t matchIndex = 0;
for(std::size_t i = 0; i < size(); ++i)
{ {
if(ui->kitchen.item_types[i] == limitType if (ui->kitchen.item_types[i] == SEEDLIMIT_ITEMTYPE &&
&& ui->kitchen.item_subtypes[i] == limitSubtype ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
&& ui->kitchen.mat_indices[i] == materialIndex ui->kitchen.mat_indices[i] == plant_id &&
&& ui->kitchen.exc_types[i] == limitExclusion) ui->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
{ {
match = true; return int(i);
matchIndex = i;
}
} }
if(match)
{
ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex);
ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex);
ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex);
ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex);
ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex);
} }
} while(match); return -1;
} }
void Kitchen::setLimit(t_materialIndex materialIndex, unsigned int limit) bool Kitchen::removeLimit(int32_t plant_id)
{ {
removeLimit(materialIndex); int i = findLimit(plant_id);
if(limit > seedLimit) if (i < 0)
return false;
ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + i);
ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + i);
ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + i);
ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + i);
ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + i);
return true;
}
bool Kitchen::setLimit(int32_t plant_id, int16_t limit)
{
if (limit > SEEDLIMIT_MAX)
limit = SEEDLIMIT_MAX;
int i = findLimit(plant_id);
if (i < 0)
{
ui->kitchen.item_types.push_back(SEEDLIMIT_ITEMTYPE);
ui->kitchen.item_subtypes.push_back(SEEDLIMIT_ITEMSUBTYPE);
ui->kitchen.mat_types.push_back(limit);
ui->kitchen.mat_indices.push_back(plant_id);
ui->kitchen.exc_types.push_back(SEEDLIMIT_EXCTYPE);
}
else
{ {
limit = seedLimit; ui->kitchen.mat_types[i] = limit;
} }
ui->kitchen.item_types.push_back(limitType); return true;
ui->kitchen.item_subtypes.push_back(limitSubtype);
ui->kitchen.mat_indices.push_back(materialIndex);
ui->kitchen.mat_types.push_back((t_materialType) (limit < seedLimit) ? limit : seedLimit);
ui->kitchen.exc_types.push_back(limitExclusion);
} }
void Kitchen::clearLimits() void Kitchen::clearLimits()
{ {
bool match = false; for (size_t i = 0; i < size(); ++i)
do
{
match = false;
std::size_t matchIndex;
for(std::size_t i = 0; i < size(); ++i)
{ {
if(ui->kitchen.item_types[i] == limitType if (ui->kitchen.item_types[i] == SEEDLIMIT_ITEMTYPE &&
&& ui->kitchen.item_subtypes[i] == limitSubtype ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
&& ui->kitchen.exc_types[i] == limitExclusion) ui->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
{ {
match = true; removeLimit(ui->kitchen.mat_indices[i]);
matchIndex = i; --i;
}
} }
if(match)
{
ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex);
ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex);
ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex);
ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex);
ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex);
} }
} while(match);
} }
size_t Kitchen::size() size_t Kitchen::size()

@ -1,4 +1,8 @@
// With thanks to peterix for DFHack and Quietust for information http://www.bay12forums.com/smf/index.php?topic=91166.msg2605147#msg2605147 // Dynamically enables and disables cooking restrictions for plants and seeds
// in order to limit the number of seeds available for each crop type
// With thanks to peterix for DFHack and Quietust for information
// http://www.bay12forums.com/smf/index.php?topic=91166.msg2605147#msg2605147
#include <map> #include <map>
#include <string> #include <string>
@ -8,6 +12,7 @@
#include "Export.h" #include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/World.h" #include "modules/World.h"
#include "modules/Materials.h"
#include "modules/Kitchen.h" #include "modules/Kitchen.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "df/world.h" #include "df/world.h"
@ -124,10 +129,10 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
{ {
CoreSuspender suspend; CoreSuspender suspend;
map<string, t_materialIndex> materialsReverser; map<string, int32_t> plantIDs;
for(size_t i = 0; i < world->raws.plants.all.size(); ++i) for(size_t i = 0; i < world->raws.plants.all.size(); ++i)
{ {
materialsReverser[world->raws.plants.all[i]->id] = i; plantIDs[world->raws.plants.all[i]->id] = i;
} }
t_gamemodes gm; t_gamemodes gm;
@ -181,7 +186,7 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
{ {
out.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); out.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n");
} }
map<t_materialIndex, unsigned int> watchMap; map<int32_t, int16_t> watchMap;
Kitchen::fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
if(watchMap.empty()) if(watchMap.empty())
{ {
@ -190,7 +195,7 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
else else
{ {
out.print("The watch list is:\n"); out.print("The watch list is:\n");
for(map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) for(auto i = watchMap.begin(); i != watchMap.end(); ++i)
{ {
out.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second); out.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second);
} }
@ -198,33 +203,16 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
} }
else if(par == "debug") else if(par == "debug")
{ {
map<t_materialIndex, unsigned int> watchMap; map<int32_t, int16_t> watchMap;
Kitchen::fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
Kitchen::debug_print(out); Kitchen::debug_print(out);
} }
/*
else if(par == "dumpmaps")
{
out.print("Plants:\n");
for(auto i = plantMaterialTypes.begin(); i != plantMaterialTypes.end(); i++)
{
auto t = materialsModule.df_organic->at(i->first);
out.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat);
}
out.print("Seeds:\n");
for(auto i = seedMaterialTypes.begin(); i != seedMaterialTypes.end(); i++)
{
auto t = materialsModule.df_organic->at(i->first);
out.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed);
}
}
*/
else else
{ {
string token = searchAbbreviations(par); string token = searchAbbreviations(par);
if(materialsReverser.count(token) > 0) if(plantIDs.count(token) > 0)
{ {
Kitchen::removeLimit(materialsReverser[token]); Kitchen::removeLimit(plantIDs[token]);
out.print("%s is not being watched\n", token.c_str()); out.print("%s is not being watched\n", token.c_str());
} }
else else
@ -238,17 +226,17 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
if(limit < 0) limit = 0; if(limit < 0) limit = 0;
if(parameters[0] == "all") if(parameters[0] == "all")
{ {
for(map<string, string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) for(auto i = abbreviations.begin(); i != abbreviations.end(); ++i)
{ {
if(materialsReverser.count(i->second) > 0) Kitchen::setLimit(materialsReverser[i->second], limit); if(plantIDs.count(i->second) > 0) Kitchen::setLimit(plantIDs[i->second], limit);
} }
} }
else else
{ {
string token = searchAbbreviations(parameters[0]); string token = searchAbbreviations(parameters[0]);
if(materialsReverser.count(token) > 0) if(plantIDs.count(token) > 0)
{ {
Kitchen::setLimit(materialsReverser[token], limit); Kitchen::setLimit(plantIDs[token], limit);
out.print("%s is being watched.\n", token.c_str()); out.print("%s is being watched.\n", token.c_str());
} }
else else
@ -289,7 +277,7 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginComman
abbreviations["sb"] = "BERRY_SUN"; abbreviations["sb"] = "BERRY_SUN";
abbreviations["sp"] = "POD_SWEET"; abbreviations["sp"] = "POD_SWEET";
abbreviations["vh"] = "HERB_VALLEY"; abbreviations["vh"] = "HERB_VALLEY";
abbreviations["ws"] = "BERRIES_STRAW_WILD"; abbreviations["ws"] = "BERRIES_STRAW";
abbreviations["wv"] = "VINE_WHIP"; abbreviations["wv"] = "VINE_WHIP";
return CR_OK; return CR_OK;
} }
@ -326,17 +314,20 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
return CR_OK; return CR_OK;
} }
// this is dwarf mode, continue // this is dwarf mode, continue
map<t_materialIndex, unsigned int> seedCount; // the number of seeds map<int32_t, int16_t> seedCount; // the number of seeds
// count all seeds and plants by RAW material // count all seeds and plants by RAW material
for(size_t i = 0; i < world->items.other[items_other_id::SEEDS].size(); ++i) for(size_t i = 0; i < world->items.other[items_other_id::SEEDS].size(); ++i)
{ {
df::item * item = world->items.other[items_other_id::SEEDS][i]; df::item *item = world->items.other[items_other_id::SEEDS][i];
t_materialIndex materialIndex = item->getMaterialIndex(); MaterialInfo mat(item);
if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex]; if (!mat.isPlant())
continue;
if (!ignoreSeeds(item->flags))
++seedCount[mat.plant->index];
} }
map<t_materialIndex, unsigned int> watchMap; map<int32_t, int16_t> watchMap;
Kitchen::fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
for(auto i = watchMap.begin(); i != watchMap.end(); ++i) for(auto i = watchMap.begin(); i != watchMap.end(); ++i)
{ {