From 61be3413e3a933b6fa27250b1f7a3554f2be1bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 27 Oct 2011 03:31:13 +0200 Subject: [PATCH] Make seedwatch work on linux, still with ugly hacks. --- library/include/dfhack/modules/Items.h | 11 +- plugins/seedwatch.cpp | 830 +++++++++++++------------ 2 files changed, 451 insertions(+), 390 deletions(-) diff --git a/library/include/dfhack/modules/Items.h b/library/include/dfhack/modules/Items.h index c7fda099e..b74111d6f 100644 --- a/library/include/dfhack/modules/Items.h +++ b/library/include/dfhack/modules/Items.h @@ -107,7 +107,12 @@ struct t_itemref : public t_virtual struct df_contaminant { - // fixme: figure it out + int16_t material; + int32_t mat_index; + int16_t mat_state; // FIXME: enum or document in text + int16_t temperature; + int16_t temperature_fraction; // maybe... + int32_t size; ///< 1-24=spatter, 25-49=smear, 50-* = coating }; /** @@ -146,6 +151,10 @@ public: int32_t mystery5; // 5C L, 64 W - pointer to vector of contaminants std::vector * contaminants; + // 60 L, 6C W - temperature in Urists + int16_t temperature; + // 62 L, 6E W - temperature fraction (maybe, just a guess) + int16_t temperature_fraction; public: // 0x0 virtual int32_t getType(); diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 70aa876e0..c579df54c 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -13,15 +13,13 @@ #include "dfhack/modules/Materials.h" typedef int32_t t_materialIndex; -typedef int16_t t_materialSubindex, t_itemType, t_itemSubtype; +typedef int16_t t_material, t_itemType, t_itemSubtype; typedef int8_t t_exclusionType; const unsigned int seedLimit = 400; // a limit on the limits which can be placed on seeds -const t_itemType seedType = 52; // from df.magmawiki.com/index.php/Item_token -const t_itemType plantType = 53; // from df.magmawiki.com/index.php/Item_token const t_itemSubtype organicSubtype = -1; // seems to fixed const t_exclusionType cookingExclusion = 1; // seems to be fixed -const t_itemType limitType = 0; // used to store limit as an entry in the exclusion list +const t_itemType limitType = 0; // 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 t_exclusionType limitExclusion = 4; // used to store limit as an entry in the exclusion list const int buffer = 20; // seed number buffer - 20 is reasonable @@ -31,428 +29,482 @@ std::map abbreviations; // abbreviations for the stand bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags should not be counted { - return - f.dump || - f.forbid || - f.garbage_colect || - f.hidden || - f.hostile || - f.on_fire || - f.rotten || - f.trader || - f.in_building || - f.in_job; + return + f.dump || + f.forbid || + f.garbage_colect || + f.hidden || + f.hostile || + f.on_fire || + f.rotten || + f.trader || + f.in_building || + f.in_job; }; -void updateCountAndSubindices(DFHack::Core& core, std::map& seedCount, std::map& seedSubindices, std::map& plantSubindices) // fills seedCount, seedSubindices and plantSubindices +void updateCountAndSubindices(DFHack::Core& core, std::map& seedCount, std::map& seedSubindices, std::map& plantSubindices) // fills seedCount, seedSubindices and plantSubindices { - DFHack::Items& itemsModule = *core.getItems(); - itemsModule.Start(); - std::vector items; - itemsModule.readItemVector(items); + DFHack::Items& itemsModule = *core.getItems(); + itemsModule.Start(); + std::vector items; + itemsModule.readItemVector(items); - DFHack::dfh_item item; - std::size_t size = items.size(); - for(std::size_t i = 0; i < size; ++i) - { - itemsModule.readItem(items[i], item); - t_materialIndex materialIndex = item.matdesc.index; - switch(item.matdesc.itemType) - { - case seedType: - seedSubindices[materialIndex] = item.matdesc.subIndex; - if(!ignoreSeeds(item.base->flags)) ++seedCount[materialIndex]; - break; - case plantType: - plantSubindices[materialIndex] = item.matdesc.subIndex; - break; - } - } + DFHack::df_item * item; + std::size_t size = items.size(); + for(std::size_t i = 0; i < size; ++i) + { + item = items[i]; + t_materialIndex materialIndex = item->getMaterialIndex(); + switch(item->getType()) + { + case DFHack::Items::SEEDS: + seedSubindices[materialIndex] = item->getMaterial(); + if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex]; + break; + case DFHack::Items::PLANT: + plantSubindices[materialIndex] = item->getMaterial(); + break; + } + } - itemsModule.Finish(); + itemsModule.Finish(); }; void printHelp(DFHack::Core& core) // prints help { - core.con.print("\ne.g. #seedwatch MUSHROOM_HELMET_PLUMP 30\n"); - core.con.print("This is how to add an item to the watch list.\n"); - core.con.print("MUSHROOM_HELMET_PLUMP is the plant token for plump helmets (found in raws)\n"); - core.con.print("The number of available plump helmet seeds is counted each tick\n"); - core.con.print("If it falls below 30, plump helmets and plump helmet seeds will be excluded from cookery.\n"); - core.con.print("%i is the buffer, therefore if the number rises above 30 + %i, then cooking will be allowed.\n", buffer, buffer); - if(!abbreviations.empty()) - { - core.con.print("You can use these abbreviations for the plant tokens:\n"); - for(std::map::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) - { - core.con.print("%s -> %s\n", i->first.c_str(), i->second.c_str()); - } - } - core.con.print("e.g. #seedwatch ph 30\nis the same as #seedwatch MUSHROOM_HELMET_PLUMP 30\n\n"); - core.con.print("e.g. #seedwatch all 30\nAdds all which are in the abbreviation list to the watch list, the limit being 30.\n\n"); - core.con.print("e.g. #seedwatch MUSHROOM_HELMET_PLUMP\nRemoves MUSHROOM_HELMET_PLUMP from the watch list.\n\n"); - core.con.print("#seedwatch all\nClears the watch list.\n\n"); - core.con.print("#seedwatch start\nStart seedwatch watch.\n\n"); - core.con.print("#seedwatch stop\nStop seedwatch watch.\n\n"); - core.con.print("#seedwatch info\nDisplay whether seedwatch is watching, and the watch list.\n\n"); - core.con.print("#seedwatch clear\nClears the watch list.\n"); + core.con.print( + "\ne.g. #seedwatch MUSHROOM_HELMET_PLUMP 30\n" + "This is how to add an item to the watch list.\n" + "MUSHROOM_HELMET_PLUMP is the plant token for plump helmets (found in raws)\n" + "The number of available plump helmet seeds is counted each tick\n" + "If it falls below 30, plump helmets and plump helmet seeds will be excluded from cookery.\n" + "%i is the buffer, therefore if the number rises above 30 + %i, then cooking will be allowed.\n", buffer, buffer); + if(!abbreviations.empty()) + { + core.con.print("You can use these abbreviations for the plant tokens:\n"); + for(std::map::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) + { + core.con.print("%s -> %s\n", i->first.c_str(), i->second.c_str()); + } + } + core.con.print( + "e.g. #seedwatch ph 30\nis the same as #seedwatch MUSHROOM_HELMET_PLUMP 30\n\n" + "e.g. #seedwatch all 30\nAdds all which are in the abbreviation list to the watch list, the limit being 30.\n\n" + "e.g. #seedwatch MUSHROOM_HELMET_PLUMP\nRemoves MUSHROOM_HELMET_PLUMP from the watch list.\n\n" + "#seedwatch all\nClears the watch list.\n\n" + "#seedwatch start\nStart seedwatch watch.\n\n" + "#seedwatch stop\nStop seedwatch watch.\n\n" + "#seedwatch info\nDisplay whether seedwatch is watching, and the watch list.\n\n" + "#seedwatch clear\nClears the watch list.\n" + ); }; -std::string searchAbbreviations(std::string in) // searches abbreviations, returns expansion if so, returns original if not + +// searches abbreviations, returns expansion if so, returns original if not +std::string searchAbbreviations(std::string in) { - if(abbreviations.count(in) > 0) return abbreviations[in]; - return in; + if(abbreviations.count(in) > 0) + { + return abbreviations[in]; + } + else + { + return in; + } }; -class t_kitchenExclusions // helps to organise access to the cooking exclusions +// helps to organise access to the cooking exclusions +class t_kitchenExclusions { public: - t_kitchenExclusions(DFHack::Core& core_) // constructor - : core(core_) - , itemTypes (*((std::vector*)(start(core_) ))) // using the kludge in start - , itemSubtypes (*((std::vector*)(start(core_) + 0x10))) // further kludge offset - , materialSubindices(*((std::vector*)(start(core_) + 0x20))) // further kludge offset - , materialIndices (*((std::vector*)(start(core_) + 0x30))) // further kludge offset - , exclusionTypes (*((std::vector*)(start(core_) + 0x40))) // further kludge offset - { - }; - void print() // print the exclusion list, with the material index also translated into its token (for organics) - for debug really - { - core.con.print("Kitchen Exclusions\n"); - DFHack::Materials& materialsModule= *core.getMaterials(); - materialsModule.ReadOrganicMaterials(); - for(std::size_t i = 0; i < size(); ++i) - { - core.con.print("%2u: IT:%2i IS:%i MI:%2i MS:%3i ET:%i %s\n", i, itemTypes[i], itemSubtypes[i], materialIndices[i], materialSubindices[i], exclusionTypes[i], materialsModule.organic[materialIndices[i]].id.c_str()); - } - core.con.print("\n"); - }; - void allowCookery(t_materialIndex materialIndex) // remove this material from the exclusion list if it is in it - { - bool match = false; - do - { - match = false; - std::size_t matchIndex = 0; - for(std::size_t i = 0; i < size(); ++i) - { - if(materialIndices[i] == materialIndex && (itemTypes[i] == seedType || itemTypes[i] == plantType) && exclusionTypes[i] == cookingExclusion) - { - match = true; - matchIndex = i; - } - } - if(match) - { - itemTypes.erase(itemTypes.begin() + matchIndex); - itemSubtypes.erase(itemSubtypes.begin() + matchIndex); - materialIndices.erase(materialIndices.begin() + matchIndex); - materialSubindices.erase(materialSubindices.begin() + matchIndex); - exclusionTypes.erase(exclusionTypes.begin() + matchIndex); - } - } while(match); - }; - void denyCookery(t_materialIndex materialIndex, std::map& seedSubindices, std::map& plantSubindices) // add this material to the exclusion list, if it is not already in it - { - if(seedSubindices.count(materialIndex) > 0) - { - bool alreadyIn = false; - for(std::size_t i = 0; i < size(); ++i) - { - if(materialIndices[i] == materialIndex && itemTypes[i] == seedType && exclusionTypes[i] == cookingExclusion) - { - alreadyIn = true; - } - } - if(!alreadyIn) - { - itemTypes.push_back(seedType); - itemSubtypes.push_back(organicSubtype); - materialIndices.push_back(materialIndex); - materialSubindices.push_back(seedSubindices[materialIndex]); - exclusionTypes.push_back(cookingExclusion); - } - } - if(plantSubindices.count(materialIndex) > 0) - { - bool alreadyIn = false; - for(std::size_t i = 0; i < size(); ++i) - { - if(materialIndices[i] == materialIndex && itemTypes[i] == plantType && exclusionTypes[i] == cookingExclusion) - { - alreadyIn = true; - } - } - if(!alreadyIn) - { - itemTypes.push_back(plantType); - itemSubtypes.push_back(organicSubtype); - materialIndices.push_back(materialIndex); - materialSubindices.push_back(plantSubindices[materialIndex]); - exclusionTypes.push_back(cookingExclusion); - } - } - }; - void fillWatchMap(std::map& watchMap) // fills a map with info from the limit info storage entries in the exclusion list - { - watchMap.clear(); - for(std::size_t i = 0; i < size(); ++i) - { - if(itemTypes[i] == limitType && itemSubtypes[i] == limitSubtype && exclusionTypes[i] == limitExclusion) - { - watchMap[materialIndices[i]] = (unsigned int) materialSubindices[i]; - } - } - }; - void removeLimit(t_materialIndex materialIndex) // removes a limit info storage entry from the exclusion list if it is in it - { - bool match = false; - do - { - match = false; - std::size_t matchIndex = 0; - for(std::size_t i = 0; i < size(); ++i) - { - if(itemTypes[i] == limitType && itemSubtypes[i] == limitSubtype && materialIndices[i] == materialIndex && exclusionTypes[i] == limitExclusion) - { - match = true; - matchIndex = i; - } - } - if(match) - { - itemTypes.erase(itemTypes.begin() + matchIndex); - itemSubtypes.erase(itemSubtypes.begin() + matchIndex); - materialIndices.erase(materialIndices.begin() + matchIndex); - materialSubindices.erase(materialSubindices.begin() + matchIndex); - exclusionTypes.erase(exclusionTypes.begin() + matchIndex); - } - } while(match); - }; - void setLimit(t_materialIndex materialIndex, unsigned int limit) // add a limit info storage item to the exclusion list, or alters an existing one - { - removeLimit(materialIndex); - if(limit > seedLimit) limit = seedLimit; + t_kitchenExclusions(DFHack::Core& core_) // constructor + : core(core_) + , itemTypes (*((std::vector*)(addr(core_,0)))) + , itemSubtypes (*((std::vector*)(addr(core_,1)))) + , materials (*((std::vector*)(addr(core_,2)))) + , materialIndices (*((std::vector*)(addr(core_,3)))) + , exclusionTypes (*((std::vector*)(addr(core_,4)))) + { + }; + void print() // print the exclusion list, with the material index also translated into its token (for organics) - for debug really + { + core.con.print("Kitchen Exclusions\n"); + DFHack::Materials& materialsModule= *core.getMaterials(); + materialsModule.ReadOrganicMaterials(); + for(std::size_t i = 0; i < size(); ++i) + { + core.con.print("%2u: IT:%2i IS:%i MI:%2i MS:%3i ET:%i %s\n", i, itemTypes[i], itemSubtypes[i], materialIndices[i], materials[i], exclusionTypes[i], materialsModule.organic[materialIndices[i]].id.c_str()); + } + core.con.print("\n"); + }; + void allowCookery(t_materialIndex materialIndex) // remove this material from the exclusion list if it is in it + { + bool match = false; + do + { + match = false; + std::size_t matchIndex = 0; + for(std::size_t i = 0; i < size(); ++i) + { + if(materialIndices[i] == materialIndex + && (itemTypes[i] == DFHack::Items::SEEDS || itemTypes[i] == DFHack::Items::PLANT) + && exclusionTypes[i] == cookingExclusion + ) + { + match = true; + matchIndex = i; + } + } + if(match) + { + itemTypes.erase(itemTypes.begin() + matchIndex); + itemSubtypes.erase(itemSubtypes.begin() + matchIndex); + materialIndices.erase(materialIndices.begin() + matchIndex); + materials.erase( materials.begin() + matchIndex); + exclusionTypes.erase(exclusionTypes.begin() + matchIndex); + } + } while(match); + }; + + // add this material to the exclusion list, if it is not already in it + void denyCookery(t_materialIndex materialIndex, std::map& seedMaterials, std::map& plantMaterials) + { + if( seedMaterials.count(materialIndex) > 0) + { + bool alreadyIn = false; + for(std::size_t i = 0; i < size(); ++i) + { + if(materialIndices[i] == materialIndex + && itemTypes[i] == DFHack::Items::SEEDS + && exclusionTypes[i] == cookingExclusion) + { + alreadyIn = true; + } + } + if(!alreadyIn) + { + itemTypes.push_back(DFHack::Items::SEEDS); + itemSubtypes.push_back(organicSubtype); + materials.push_back( seedMaterials[materialIndex]); + materialIndices.push_back(materialIndex); + exclusionTypes.push_back(cookingExclusion); + } + } + if( plantMaterials.count(materialIndex) > 0) + { + bool alreadyIn = false; + for(std::size_t i = 0; i < size(); ++i) + { + if(materialIndices[i] == materialIndex + && itemTypes[i] == DFHack::Items::PLANT + && exclusionTypes[i] == cookingExclusion) + { + alreadyIn = true; + } + } + if(!alreadyIn) + { + itemTypes.push_back(DFHack::Items::PLANT); + itemSubtypes.push_back(organicSubtype); + materials.push_back(plantMaterials[materialIndex]); + materialIndices.push_back(materialIndex); + exclusionTypes.push_back(cookingExclusion); + } + } + }; + + // fills a map with info from the limit info storage entries in the exclusion list + void fillWatchMap(std::map& watchMap) + { + watchMap.clear(); + for(std::size_t i = 0; i < size(); ++i) + { + if(itemTypes[i] == limitType && itemSubtypes[i] == limitSubtype && exclusionTypes[i] == limitExclusion) + { + watchMap[materialIndices[i]] = (unsigned int) materials[i]; + } + } + }; + + // removes a limit info storage entry from the exclusion list if it is in it + void removeLimit(t_materialIndex materialIndex) + { + bool match = false; + do + { + match = false; + std::size_t matchIndex = 0; + for(std::size_t i = 0; i < size(); ++i) + { + if(itemTypes[i] == limitType + && itemSubtypes[i] == limitSubtype + && materialIndices[i] == materialIndex + && exclusionTypes[i] == limitExclusion) + { + match = true; + matchIndex = i; + } + } + if(match) + { + itemTypes.erase(itemTypes.begin() + matchIndex); + itemSubtypes.erase(itemSubtypes.begin() + matchIndex); + materials.erase(materials.begin() + matchIndex); + materialIndices.erase(materialIndices.begin() + matchIndex); + exclusionTypes.erase(exclusionTypes.begin() + matchIndex); + } + } while(match); + }; + // add a limit info storage item to the exclusion list, or alters an existing one + void setLimit(t_materialIndex materialIndex, unsigned int limit) + { + removeLimit(materialIndex); + if(limit > seedLimit) limit = seedLimit; - itemTypes.push_back(limitType); - itemSubtypes.push_back(limitSubtype); - materialIndices.push_back(materialIndex); - materialSubindices.push_back((t_materialSubindex) (limit < seedLimit) ? limit : seedLimit); - exclusionTypes.push_back(limitExclusion); - }; - void clearLimits() // clears all limit info storage items from the exclusion list - { - bool match = false; - do - { - match = false; - std::size_t matchIndex; - for(std::size_t i = 0; i < size(); ++i) - { - if(itemTypes[i] == limitType && itemSubtypes[i] == limitSubtype && exclusionTypes[i] == limitExclusion) - { - match = true; - matchIndex = i; - } - } - if(match) - { - itemTypes.erase(itemTypes.begin() + matchIndex); - itemSubtypes.erase(itemSubtypes.begin() + matchIndex); - materialIndices.erase(materialIndices.begin() + matchIndex); - materialSubindices.erase(materialSubindices.begin() + matchIndex); - exclusionTypes.erase(exclusionTypes.begin() + matchIndex); - } - } while(match); - }; + itemTypes.push_back(limitType); + itemSubtypes.push_back(limitSubtype); + materialIndices.push_back(materialIndex); + materials.push_back((t_material) (limit < seedLimit) ? limit : seedLimit); + exclusionTypes.push_back(limitExclusion); + }; + void clearLimits() // clears all limit info storage items from the exclusion list + { + bool match = false; + do + { + match = false; + std::size_t matchIndex; + for(std::size_t i = 0; i < size(); ++i) + { + if(itemTypes[i] == limitType + && itemSubtypes[i] == limitSubtype + && exclusionTypes[i] == limitExclusion) + { + match = true; + matchIndex = i; + } + } + if(match) + { + itemTypes.erase(itemTypes.begin() + matchIndex); + itemSubtypes.erase(itemSubtypes.begin() + matchIndex); + materialIndices.erase(materialIndices.begin() + matchIndex); + materials.erase( materials.begin() + matchIndex); + exclusionTypes.erase(exclusionTypes.begin() + matchIndex); + } + } while(match); + }; private: - DFHack::Core& core; - std::vector& itemTypes; // the item types vector of the kitchen exclusion list - std::vector& itemSubtypes; // the item subtype vector of the kitchen exclusion list - std::vector& materialSubindices; // the material subindex vector of the kitchen exclusion list - std::vector& materialIndices; // the material index vector of the kitchen exclusion list - std::vector& exclusionTypes; // the exclusion type vector of the kitchen excluions list - std::size_t size() // the size of the exclusions vectors (they are all the same size - if not, there is a problem!) - { - return itemTypes.size(); - }; - static uint32_t start(const DFHack::Core& core) // the kludge for the exclusion position in memory - { - return core.p->getBase() + 0x014F0BB4 - 0x400000; - }; + DFHack::Core& core; + std::vector& itemTypes; // the item types vector of the kitchen exclusion list + std::vector& itemSubtypes; // the item subtype vector of the kitchen exclusion list + std::vector& materials; // the material subindex vector of the kitchen exclusion list + std::vector& materialIndices; // the material index vector of the kitchen exclusion list + std::vector& exclusionTypes; // the exclusion type vector of the kitchen excluions list + std::size_t size() // the size of the exclusions vectors (they are all the same size - if not, there is a problem!) + { + return itemTypes.size(); + }; + //FIXME: ugly, ugly hack. Use memory.xml instead. + static uint32_t addr(const DFHack::Core& core, int index) + { + #ifdef LINUX_BUILD + return 0x93f2b00 + 0xC * index; + #else + return core.p->getBase() + 0x014F0BB4 - 0x400000 + 0x10 * index; + #endif + }; }; DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vector& parameters) { - DFHack::Core& core = *pCore; - if(!core.isValid()) return DFHack::CR_FAILURE; - core.Suspend(); + DFHack::Core& core = *pCore; + if(!core.isValid()) + { + return DFHack::CR_FAILURE; + } + core.Suspend(); - DFHack::Materials& materialsModule = *core.getMaterials(); - materialsModule.ReadOrganicMaterials(); - std::vector& organics = materialsModule.organic; + DFHack::Materials& materialsModule = *core.getMaterials(); + materialsModule.ReadOrganicMaterials(); + std::vector& organics = materialsModule.organic; - std::map materialsReverser; - for(std::size_t i = 0; i < organics.size(); ++i) - { - materialsReverser[organics[i].id] = i; - } + std::map materialsReverser; + for(std::size_t i = 0; i < organics.size(); ++i) + { + materialsReverser[organics[i].id] = i; + } - std::string par; - int limit; - switch(parameters.size()) - { - case 0: - printHelp(core); - break; - case 1: - par = parameters[0]; - if(par == "help") printHelp(core); - else if(par == "?") printHelp(core); - else if(par == "start") - { - running = true; - core.con.print("seedwatch supervision started.\n"); - } - else if(par == "stop") - { - running = false; - core.con.print("seedwatch supervision stopped.\n"); - } - else if(par == "clear") - { - t_kitchenExclusions kitchenExclusions(core); - kitchenExclusions.clearLimits(); - core.con.print("seedwatch watchlist cleared\n"); - } - else if(par == "info") - { - core.con.print("seedwatch Info:\n"); - if(running) core.con.print("seedwatch is supervising. Use 'seedwatch stop' to stop supervision.\n"); - else core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); - t_kitchenExclusions kitchenExclusions(core); - std::map watchMap; - kitchenExclusions.fillWatchMap(watchMap); - if(watchMap.empty()) core.con.print("The watch list is empty.\n"); - else - { - core.con.print("The watch list is:\n"); - for(std::map::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) - { - core.con.print("%s : %u\n", organics[i->first].id.c_str(), i->second); - } - } - /*kitchenExclusions.print();*/ - } - else - { - std::string token = searchAbbreviations(par); - if(materialsReverser.count(token) > 0) - { - t_kitchenExclusions kitchenExclusions(core); - kitchenExclusions.removeLimit(materialsReverser[token]); - core.con.print("%s is not being watched\n", token.c_str()); - } - else - { - core.con.print("%s has not been found as a material.\n", token.c_str()); - } - } - break; - case 2: - limit = atoi(parameters[1].c_str()); - if(limit < 0) limit = 0; - if(parameters[0] == "all") - { - for(std::map::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) - { - t_kitchenExclusions kitchenExclusions(core); - if(materialsReverser.count(i->second) > 0) kitchenExclusions.setLimit(materialsReverser[i->second], limit); - } - } - else - { - std::string token = searchAbbreviations(parameters[0]); - if(materialsReverser.count(token) > 0) - { - t_kitchenExclusions kitchenExclusions(core); - kitchenExclusions.setLimit(materialsReverser[token], limit); - core.con.print("%s is being watched.\n", token.c_str()); - } - else - { - core.con.print("%s has not been found as a material.\n", token.c_str()); - } - } - break; - default: - printHelp(core); - break; - } + std::string par; + int limit; + switch(parameters.size()) + { + case 0: + printHelp(core); + break; + case 1: + par = parameters[0]; + if(par == "help") printHelp(core); + else if(par == "?") printHelp(core); + else if(par == "start") + { + running = true; + core.con.print("seedwatch supervision started.\n"); + } + else if(par == "stop") + { + running = false; + core.con.print("seedwatch supervision stopped.\n"); + } + else if(par == "clear") + { + t_kitchenExclusions kitchenExclusions(core); + kitchenExclusions.clearLimits(); + core.con.print("seedwatch watchlist cleared\n"); + } + else if(par == "info") + { + core.con.print("seedwatch Info:\n"); + if(running) + { + core.con.print("seedwatch is supervising. Use 'seedwatch stop' to stop supervision.\n"); + } + else + { + core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); + } + t_kitchenExclusions kitchenExclusions(core); + std::map watchMap; + kitchenExclusions.fillWatchMap(watchMap); + if(watchMap.empty()) + { + core.con.print("The watch list is empty.\n"); + } + else + { + core.con.print("The watch list is:\n"); + for(std::map::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) + { + core.con.print("%s : %u\n", organics[i->first].id.c_str(), i->second); + } + } + } + else if(par == "debug") + { + t_kitchenExclusions kitchenExclusions(core); + std::map watchMap; + kitchenExclusions.fillWatchMap(watchMap); + kitchenExclusions.print(); + } + else + { + std::string token = searchAbbreviations(par); + if(materialsReverser.count(token) > 0) + { + t_kitchenExclusions kitchenExclusions(core); + kitchenExclusions.removeLimit(materialsReverser[token]); + core.con.print("%s is not being watched\n", token.c_str()); + } + else + { + core.con.print("%s has not been found as a material.\n", token.c_str()); + } + } + break; + case 2: + limit = atoi(parameters[1].c_str()); + if(limit < 0) limit = 0; + if(parameters[0] == "all") + { + for(std::map::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) + { + t_kitchenExclusions kitchenExclusions(core); + if(materialsReverser.count(i->second) > 0) kitchenExclusions.setLimit(materialsReverser[i->second], limit); + } + } + else + { + std::string token = searchAbbreviations(parameters[0]); + if(materialsReverser.count(token) > 0) + { + t_kitchenExclusions kitchenExclusions(core); + kitchenExclusions.setLimit(materialsReverser[token], limit); + core.con.print("%s is being watched.\n", token.c_str()); + } + else + { + core.con.print("%s has not been found as a material.\n", token.c_str()); + } + } + break; + default: + printHelp(core); + break; + } - core.Resume(); - return DFHack::CR_OK; + core.Resume(); + return DFHack::CR_OK; } DFhackCExport const char* plugin_name(void) { - return "seedwatch"; + return "seedwatch"; } DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vector& commands) { - commands.clear(); - commands.push_back(DFHack::PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); - // fill in the abbreviations map, with abbreviations for the standard plants - abbreviations["bs"] = "SLIVER_BARB"; - abbreviations["bt"] = "TUBER_BLOATED"; - abbreviations["bw"] = "WEED_BLADE"; - abbreviations["cw"] = "GRASS_WHEAT_CAVE"; - abbreviations["dc"] = "MUSHROOM_CUP_DIMPLE"; - abbreviations["fb"] = "BERRIES_FISHER"; - abbreviations["hr"] = "ROOT_HIDE"; - abbreviations["kb"] = "BULB_KOBOLD"; - abbreviations["lg"] = "GRASS_LONGLAND"; - abbreviations["mr"] = "ROOT_MUCK"; - abbreviations["pb"] = "BERRIES_PRICKLE"; - abbreviations["ph"] = "MUSHROOM_HELMET_PLUMP"; - abbreviations["pt"] = "GRASS_TAIL_PIG"; - abbreviations["qb"] = "BUSH_QUARRY"; - abbreviations["rr"] = "REED_ROPE"; - abbreviations["rw"] = "WEED_RAT"; - abbreviations["sb"] = "BERRY_SUN"; - abbreviations["sp"] = "POD_SWEET"; - abbreviations["vh"] = "HERB_VALLEY"; - abbreviations["ws"] = "BERRIES_STRAW_WILD"; - abbreviations["wv"] = "VINE_WHIP"; - return DFHack::CR_OK; + commands.clear(); + commands.push_back(DFHack::PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); + // fill in the abbreviations map, with abbreviations for the standard plants + abbreviations["bs"] = "SLIVER_BARB"; + abbreviations["bt"] = "TUBER_BLOATED"; + abbreviations["bw"] = "WEED_BLADE"; + abbreviations["cw"] = "GRASS_WHEAT_CAVE"; + abbreviations["dc"] = "MUSHROOM_CUP_DIMPLE"; + abbreviations["fb"] = "BERRIES_FISHER"; + abbreviations["hr"] = "ROOT_HIDE"; + abbreviations["kb"] = "BULB_KOBOLD"; + abbreviations["lg"] = "GRASS_LONGLAND"; + abbreviations["mr"] = "ROOT_MUCK"; + abbreviations["pb"] = "BERRIES_PRICKLE"; + abbreviations["ph"] = "MUSHROOM_HELMET_PLUMP"; + abbreviations["pt"] = "GRASS_TAIL_PIG"; + abbreviations["qb"] = "BUSH_QUARRY"; + abbreviations["rr"] = "REED_ROPE"; + abbreviations["rw"] = "WEED_RAT"; + abbreviations["sb"] = "BERRY_SUN"; + abbreviations["sp"] = "POD_SWEET"; + abbreviations["vh"] = "HERB_VALLEY"; + abbreviations["ws"] = "BERRIES_STRAW_WILD"; + abbreviations["wv"] = "VINE_WHIP"; + return DFHack::CR_OK; } DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) { - if(running) - { - DFHack::Core& core = *pCore; - std::map seedCount; // the number of seeds - std::map seedSubindices; // holds information needed to add entries to the cooking exclusions - std::map plantSubindices; // holds information need to add entries to the cooking exclusions - updateCountAndSubindices(core, seedCount, seedSubindices, plantSubindices); - t_kitchenExclusions kitchenExclusions(core); - std::map watchMap; - kitchenExclusions.fillWatchMap(watchMap); - for(std::map::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) - { - if(seedCount[i->first] <= i->second) - { - kitchenExclusions.denyCookery(i->first, seedSubindices, plantSubindices); - } - else if(i->second + buffer < seedCount[i->first]) - { - kitchenExclusions.allowCookery(i->first); - } - } - } - return DFHack::CR_OK; + if(running) + { + DFHack::Core& core = *pCore; + std::map seedCount; // the number of seeds + std::map seedSubindices; // holds information needed to add entries to the cooking exclusions + std::map plantSubindices; // holds information need to add entries to the cooking exclusions + updateCountAndSubindices(core, seedCount, seedSubindices, plantSubindices); + t_kitchenExclusions kitchenExclusions(core); + std::map watchMap; + kitchenExclusions.fillWatchMap(watchMap); + for(std::map::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) + { + if(seedCount[i->first] <= i->second) + { + kitchenExclusions.denyCookery(i->first, seedSubindices, plantSubindices); + } + else if(i->second + buffer < seedCount[i->first]) + { + kitchenExclusions.allowCookery(i->first); + } + } + } + return DFHack::CR_OK; } DFhackCExport DFHack::command_result plugin_shutdown(DFHack::Core* pCore) { - return DFHack::CR_OK; + return DFHack::CR_OK; }