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
{
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.
* \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
DFHACK_EXPORT void debug_print(color_ostream &out);
// remove this material from the exclusion list if it is in it
DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex);
// remove this plant from the exclusion list if it is in it
DFHACK_EXPORT void allowPlantSeedCookery(int32_t plant_id);
// add this material to the exclusion list, if it is not already in it
DFHACK_EXPORT void denyPlantSeedCookery(t_materialIndex materialIndex);
// add this plant to the exclusion list, if it is not already in it
DFHACK_EXPORT void denyPlantSeedCookery(int32_t plant_id);
// 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
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
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
DFHACK_EXPORT void clearLimits();

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

@ -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 <string>
@ -8,6 +12,7 @@
#include "Export.h"
#include "PluginManager.h"
#include "modules/World.h"
#include "modules/Materials.h"
#include "modules/Kitchen.h"
#include "VersionInfo.h"
#include "df/world.h"
@ -124,10 +129,10 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
{
CoreSuspender suspend;
map<string, t_materialIndex> materialsReverser;
map<string, int32_t> plantIDs;
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;
@ -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");
}
map<t_materialIndex, unsigned int> watchMap;
map<int32_t, int16_t> watchMap;
Kitchen::fillWatchMap(watchMap);
if(watchMap.empty())
{
@ -190,7 +195,7 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
else
{
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);
}
@ -198,33 +203,16 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
}
else if(par == "debug")
{
map<t_materialIndex, unsigned int> watchMap;
map<int32_t, int16_t> watchMap;
Kitchen::fillWatchMap(watchMap);
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
{
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());
}
else
@ -238,17 +226,17 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
if(limit < 0) limit = 0;
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
{
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());
}
else
@ -289,7 +277,7 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginComman
abbreviations["sb"] = "BERRY_SUN";
abbreviations["sp"] = "POD_SWEET";
abbreviations["vh"] = "HERB_VALLEY";
abbreviations["ws"] = "BERRIES_STRAW_WILD";
abbreviations["ws"] = "BERRIES_STRAW";
abbreviations["wv"] = "VINE_WHIP";
return CR_OK;
}
@ -326,17 +314,20 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
return CR_OK;
}
// 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
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];
t_materialIndex materialIndex = item->getMaterialIndex();
if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex];
df::item *item = world->items.other[items_other_id::SEEDS][i];
MaterialInfo mat(item);
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);
for(auto i = watchMap.begin(); i != watchMap.end(); ++i)
{