From a34b34d3cbae47ecf2e0f2760b3ffecc53aac73b Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 12 May 2018 11:51:36 -0400 Subject: [PATCH] Move a few item functions from autotrade/stocks into DFHack::Items --- docs/Lua API.rst | 15 ++++++ docs/changelog.txt | 6 +++ docs/gen_changelog.py | 10 +++- library/LuaApi.cpp | 3 ++ library/include/modules/Items.h | 8 ++++ library/modules/Items.cpp | 84 ++++++++++++++++++++++++++++++++ library/xml | 2 +- plugins/autotrade.cpp | 32 ++----------- plugins/stocks.cpp | 85 +-------------------------------- 9 files changed, 130 insertions(+), 115 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 2429efde1..be935c822 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1290,6 +1290,21 @@ Items module Calculates the Basic Value of an item, as seen in the View Item screen. +* ``dfhack.items.createItem(item_type, item_subtype, mat_type, mat_index, unit)`` + + Creates an item, similar to the `createitem` plugin. + +* ``dfhack.items.checkMandates(item)`` + + Returns true if the item is free from mandates, or false if mandates prevent trading the item. + +* ``dfhack.items.canTrade(item)`` + + Checks whether the item can be traded. + +* ``dfhack.items.canTradeWithContents(item)`` + + Checks whether the item and all items it contains, if any, can be traded. Maps module ----------- diff --git a/docs/changelog.txt b/docs/changelog.txt index cc6bb191a..b5fa62a9f 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -37,6 +37,12 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ================================================================================ # Future +## API +- New functions (all available to Lua as well): + - ``Items::checkMandates()`` + - ``Items::canTrade()`` + - ``Items::canTradeWithContents()`` + # 0.44.10-beta1 ## New Scripts diff --git a/docs/gen_changelog.py b/docs/gen_changelog.py index 5456be6bb..89db98052 100644 --- a/docs/gen_changelog.py +++ b/docs/gen_changelog.py @@ -13,6 +13,7 @@ CHANGELOG_SECTIONS = [ 'Fixes', 'Misc Improvements', 'Removed', + 'API', 'Internals', 'Structures', 'Lua', @@ -23,6 +24,12 @@ REPLACEMENTS = { '`search`': '`search-plugin`', } +def to_title_case(word): + if word == word.upper(): + # Preserve acronyms + return word + return word[0].upper() + word[1:].lower() + def find_all_indices(string, substr): start = 0 while True: @@ -54,8 +61,7 @@ class ChangelogEntry(object): def __init__(self, text, section, stable_version, dev_version): text = text.lstrip('- ') # normalize section to title case - self.section = ' '.join(word[0].upper() + word[1:].lower() - for word in section.strip().split()) + self.section = ' '.join(map(to_title_case, section.strip().split())) self.stable_version = stable_version self.dev_version = dev_version self.dev_only = text.startswith('@') diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index b78d621ce..9e5ddd1ea 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1755,6 +1755,9 @@ static const LuaWrapper::FunctionReg dfhack_items_module[] = { WRAPM(Items, getItemBaseValue), WRAPM(Items, getValue), WRAPM(Items, createItem), + WRAPM(Items, checkMandates), + WRAPM(Items, canTrade), + WRAPM(Items, canTradeWithContents), WRAPN(moveToGround, items_moveToGround), WRAPN(moveToContainer, items_moveToContainer), WRAPN(moveToInventory, items_moveToInventory), diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index d77b5b369..a09900ddf 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -182,6 +182,14 @@ DFHACK_EXPORT int getItemBaseValue(int16_t item_type, int16_t item_subtype, int1 DFHACK_EXPORT int getValue(df::item *item); DFHACK_EXPORT int32_t createItem(df::item_type type, int16_t item_subtype, int16_t mat_type, int32_t mat_index, df::unit* creator); + +/// Returns true if the item is free from mandates, or false if mandates prevent trading the item +DFHACK_EXPORT bool checkMandates(df::item *item); +/// Checks whether the item can be traded +DFHACK_EXPORT bool canTrade(df::item *item); +/// Checks whether the item and all items it contains, if any, can be traded +DFHACK_EXPORT bool canTradeWithContents(df::item *item); + } } diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 654345e34..5c08065f9 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -75,6 +75,7 @@ using namespace std; #include "df/itemdef_trapcompst.h" #include "df/itemdef_weaponst.h" #include "df/job_item.h" +#include "df/mandate.h" #include "df/map_block.h" #include "df/proj_itemst.h" #include "df/proj_list_link.h" @@ -1401,3 +1402,86 @@ int32_t Items::createItem(df::item_type item_type, int16_t item_subtype, int16_t return out_items[0]->id; } +/* + * Trade Info + */ + +bool Items::checkMandates(df::item *item) +{ + CHECK_NULL_POINTER(item); + + for (df::mandate *mandate : world->mandates) + { + if (mandate->mode != df::mandate::T_mode::Export) + continue; + + if (item->getType() != mandate->item_type || + (mandate->item_subtype != -1 && item->getSubtype() != mandate->item_subtype)) + continue; + + if (mandate->mat_type != -1 && item->getMaterial() != mandate->mat_type) + continue; + + if (mandate->mat_index != -1 && item->getMaterialIndex() != mandate->mat_index) + continue; + + return false; + } + + return true; +} + +bool Items::canTrade(df::item *item) +{ + CHECK_NULL_POINTER(item); + + if (item->flags.bits.owned || item->flags.bits.artifact || item->flags.bits.spider_web || item->flags.bits.in_job) + return false; + + for (df::general_ref *ref : item->general_refs) + { + switch (ref->getType()) + { + case general_ref_type::UNIT_HOLDER: + return false; + + case general_ref_type::BUILDING_HOLDER: + return false; + + default: + break; + } + } + + for (df::specific_ref *ref : item->specific_refs) + { + if (ref->type == specific_ref_type::JOB) + { + // Ignore any items assigned to a job + return false; + } + } + + return checkMandates(item); +} + +bool Items::canTradeWithContents(df::item *item) +{ + CHECK_NULL_POINTER(item); + + if (item->flags.bits.in_inventory) + return false; + + if (!canTrade(item)) + return false; + + vector contained_items; + getContainedItems(item, &contained_items); + for (df::item *cit : contained_items) + { + if (!canTrade(cit)) + return false; + } + + return true; +} diff --git a/library/xml b/library/xml index 03eedecfb..6c4020d5a 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 03eedecfb3bb0eb3d71986e7e897770d9be0fad6 +Subproject commit 6c4020d5a0ebca365fe3074087110cc8b0f12168 diff --git a/plugins/autotrade.cpp b/plugins/autotrade.cpp index c4257c195..ca3f456ec 100644 --- a/plugins/autotrade.cpp +++ b/plugins/autotrade.cpp @@ -134,33 +134,9 @@ static TradeDepotInfo depot_info; * Item Manipulation */ -static bool check_mandates(df::item *item) -{ - for (auto it = world->mandates.begin(); it != world->mandates.end(); it++) - { - auto mandate = *it; - - if (mandate->mode != 0) - continue; - - if (item->getType() != mandate->item_type || - (mandate->item_subtype != -1 && item->getSubtype() != mandate->item_subtype)) - continue; - - if (mandate->mat_type != -1 && item->getMaterial() != mandate->mat_type) - continue; - - if (mandate->mat_index != -1 && item->getMaterialIndex() != mandate->mat_index) - continue; - - return false; - } - - return true; -} - static bool is_valid_item(df::item *item) { + // Similar to Items::canTrade() with a few checks changed for (size_t i = 0; i < item->general_refs.size(); i++) { df::general_ref *ref = item->general_refs[i]; @@ -192,7 +168,7 @@ static bool is_valid_item(df::item *item) } } - if (!check_mandates(item)) + if (!Items::checkMandates(item)) return false; return true; @@ -236,9 +212,9 @@ static void mark_all_in_stockpiles(vector &stockpiles) bool mandates_ok = true; vector contained_items; Items::getContainedItems(item, &contained_items); - for (auto cit = contained_items.begin(); cit != contained_items.end(); cit++) + for (df::item *cit : contained_items) { - if (!check_mandates(*cit)) + if (!Items::checkMandates(cit)) { mandates_ok = false; break; diff --git a/plugins/stocks.cpp b/plugins/stocks.cpp index 83eb01c4e..a533f4669 100644 --- a/plugins/stocks.cpp +++ b/plugins/stocks.cpp @@ -72,89 +72,6 @@ static df::item *get_container_of(df::unit *unit) * Trade Info */ -static bool check_mandates(df::item *item) -{ - for (auto it = world->mandates.begin(); it != world->mandates.end(); it++) - { - auto mandate = *it; - - if (mandate->mode != 0) - continue; - - if (item->getType() != mandate->item_type || - (mandate->item_subtype != -1 && item->getSubtype() != mandate->item_subtype)) - continue; - - if (mandate->mat_type != -1 && item->getMaterial() != mandate->mat_type) - continue; - - if (mandate->mat_index != -1 && item->getMaterialIndex() != mandate->mat_index) - continue; - - return false; - } - - return true; -} - -static bool can_trade_item(df::item *item) -{ - if (item->flags.bits.owned || item->flags.bits.artifact || item->flags.bits.spider_web || item->flags.bits.in_job) - return false; - - for (size_t i = 0; i < item->general_refs.size(); i++) - { - df::general_ref *ref = item->general_refs[i]; - - switch (ref->getType()) - { - case general_ref_type::UNIT_HOLDER: - return false; - - case general_ref_type::BUILDING_HOLDER: - return false; - - default: - break; - } - } - - for (size_t i = 0; i < item->specific_refs.size(); i++) - { - df::specific_ref *ref = item->specific_refs[i]; - - if (ref->type == specific_ref_type::JOB) - { - // Ignore any items assigned to a job - return false; - } - } - - return check_mandates(item); -} - -static bool can_trade_item_and_container(df::item *item) -{ - item = get_container_of(item); - - if (item->flags.bits.in_inventory) - return false; - - if (!can_trade_item(item)) - return false; - - vector contained_items; - Items::getContainedItems(item, &contained_items); - for (auto cit = contained_items.begin(); cit != contained_items.end(); cit++) - { - if (!can_trade_item(*cit)) - return false; - } - - return true; -} - - class TradeDepotInfo { public: @@ -185,7 +102,7 @@ public: { auto item = *it; item = get_container_of(item); - if (!can_trade_item_and_container(item)) + if (!Items::canTradeWithContents(item)) return false; auto href = df::allocate();