From c6bbf39c6c906a1600b9597f96da2760d6be7dd4 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sat, 25 Jan 2020 12:43:02 +0100 Subject: [PATCH 1/3] Issue #1262. Added Items::getTitle and used in stocks --- docs/changelog.txt | 8 ++++ library/include/modules/Items.h | 5 ++ library/modules/Items.cpp | 81 +++++++++++++++++++++++++++++++++ plugins/stocks.cpp | 14 ++++-- 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 5c1b37561..9e4bef7a0 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -35,6 +35,14 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ======== IMPORTANT: rename this, and add a new "future" section, BEFORE ======== ======== making a new DFHack release! ======== ================================================================================ +# Future + +## Fixes +- `stocks`: fixed display of titles by using the new ``Items::`getTitle`` operation before the original one, issue 1262 + +## API +- Added ``Items::`getTitle`` to get titles of "books". Catches titles buried in improvements, unlike getDescription. + # 0.44.12-r3 ## New Plugins diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 776e935eb..e232bc953 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -159,6 +159,11 @@ DFHACK_EXPORT df::unit *getHolderUnit(df::item *item); /// Returns the true position of the item. DFHACK_EXPORT df::coord getPosition(df::item *item); +/// Returns the title of a codex or "tool", either as the codex title or as the title of the +/// first page or writing it has that has a non blank title. An empty string is returned if +/// no title is found (which is the casee for everything that isn't a "book"). +DFHACK_EXPORT std::string getTitle(df::item *item); + /// Returns the description string of the item. DFHACK_EXPORT std::string getDescription(df::item *item, int type = 0, bool decorate = false); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index a1b4ace4d..f102bcc78 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -59,6 +59,8 @@ using namespace std; #include "df/general_ref_unit_holderst.h" #include "df/historical_entity.h" #include "df/item.h" +#include "df/item_bookst.h" +#include "df/item_toolst.h" #include "df/item_type.h" #include "df/itemdef_ammost.h" #include "df/itemdef_armorst.h" @@ -74,6 +76,9 @@ using namespace std; #include "df/itemdef_toyst.h" #include "df/itemdef_trapcompst.h" #include "df/itemdef_weaponst.h" +#include "df/itemimprovement.h" +#include "df/itemimprovement_pagesst.h" +#include "df/itemimprovement_writingst.h" #include "df/job_item.h" #include "df/mandate.h" #include "df/map_block.h" @@ -90,6 +95,7 @@ using namespace std; #include "df/viewscreen_itemst.h" #include "df/world.h" #include "df/world_site.h" +#include "df/written_content.h" using namespace DFHack; using namespace df::enums; @@ -681,6 +687,81 @@ static void addQuality(std::string &tmp, int quality) } } +// It's not impossible the functionality of this operation is provided by one of the unmapped item functions. +std::string Items::getTitle(df::item *item) +{ + CHECK_NULL_POINTER(item); + + std::string tmp; + + if (item->getType() == df::item_type::BOOK) + { + if (virtual_cast(item)->title != "") + { + return virtual_cast(item)->title; + } + else + { + for (size_t i = 0; i < virtual_cast(item)->improvements.size(); i++) + { + if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::PAGES) + { + for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + { + df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; + if (contents->title != "") + { + return contents->title; + } + } + } + else if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::WRITING) + { + for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + { + df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; + if (contents->title != "") + { + return contents->title; + } + } + } + } + } + } + else if (item->getType() == df::item_type::TOOL && + virtual_cast(item)->hasToolUse(df::tool_uses::CONTAIN_WRITING)) + { + for (size_t i = 0; i < virtual_cast(item)->improvements.size(); i++) + { + if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::PAGES) + { + for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + { + df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; + if (contents->title != "") + { + return contents->title; + } + } + } + else if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::WRITING) + { + for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + { + df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; + if (contents->title != "") + { + return contents->title; + } + } + } + } + } + + return ""; +} + std::string Items::getDescription(df::item *item, int type, bool decorate) { CHECK_NULL_POINTER(item); diff --git a/plugins/stocks.cpp b/plugins/stocks.cpp index b5831d159..e44cbb431 100644 --- a/plugins/stocks.cpp +++ b/plugins/stocks.cpp @@ -30,7 +30,7 @@ #include "df/ui_advmode.h" DFHACK_PLUGIN("stocks"); -#define PLUGIN_VERSION 0.12 +#define PLUGIN_VERSION 0.13 REQUIRE_GLOBAL(world); @@ -248,7 +248,11 @@ static string get_keywords(df::item *item) static string get_item_label(df::item *item, bool trim = false) { - auto label = Items::getDescription(item, 0, false); + auto label = Items::getTitle(item); + if (label == "") + { + label = Items::getDescription(item, 0, false); + } if (trim && item->getType() == item_type::BIN) { auto pos = label.find("<#"); @@ -562,7 +566,11 @@ class StockListColumn : public ListColumn if (!ListColumn::showEntry(entry, search_tokens)) return false; - string item_name = toLower(Items::getDescription(entry->elem->entries[0], 0, false)); + string item_name = toLower(Items::getTitle(entry->elem->entries[0])); + if (item_name == "") + { + item_name = toLower(Items::getDescription(entry->elem->entries[0], 0, false)); + } if ((match_start || match_end) && raw_search.size() > item_name.size()) return false; From 876ac6c056a0a9f0ce91ea2a06fe46efa8f01953 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sat, 25 Jan 2020 21:46:10 +0100 Subject: [PATCH 2/3] Renamed to getBookTitle, cut down on virtual_cast --- library/include/modules/Items.h | 2 +- library/modules/Items.cpp | 56 ++++++++++++++++++--------------- plugins/stocks.cpp | 4 +-- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index e232bc953..838104bfe 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -162,7 +162,7 @@ DFHACK_EXPORT df::coord getPosition(df::item *item); /// Returns the title of a codex or "tool", either as the codex title or as the title of the /// first page or writing it has that has a non blank title. An empty string is returned if /// no title is found (which is the casee for everything that isn't a "book"). -DFHACK_EXPORT std::string getTitle(df::item *item); +DFHACK_EXPORT std::string getBookTitle(df::item *item); /// Returns the description string of the item. DFHACK_EXPORT std::string getDescription(df::item *item, int type = 0, bool decorate = false); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index f102bcc78..14700f9e7 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -688,7 +688,7 @@ static void addQuality(std::string &tmp, int quality) } // It's not impossible the functionality of this operation is provided by one of the unmapped item functions. -std::string Items::getTitle(df::item *item) +std::string Items::getBookTitle(df::item *item) { CHECK_NULL_POINTER(item); @@ -696,30 +696,32 @@ std::string Items::getTitle(df::item *item) if (item->getType() == df::item_type::BOOK) { - if (virtual_cast(item)->title != "") + auto book = virtual_cast(item); + + if (book->title != "") { - return virtual_cast(item)->title; + return book->title; } else { - for (size_t i = 0; i < virtual_cast(item)->improvements.size(); i++) + for (size_t i = 0; i < book->improvements.size(); i++) { - if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::PAGES) + if (auto page = virtual_cast(book->improvements[i])) { - for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + for (size_t k = 0; k < page->contents.size(); k++) { - df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; + df::written_content *contents = world->written_contents.all[page->contents[k]]; if (contents->title != "") { return contents->title; } } } - else if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::WRITING) + else if (auto writing = virtual_cast(book->improvements[i])) { - for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + for (size_t k = 0; k < writing->contents.size(); k++) { - df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; + df::written_content *contents = world->written_contents.all[writing->contents[k]]; if (contents->title != "") { return contents->title; @@ -729,30 +731,34 @@ std::string Items::getTitle(df::item *item) } } } - else if (item->getType() == df::item_type::TOOL && - virtual_cast(item)->hasToolUse(df::tool_uses::CONTAIN_WRITING)) + else if (item->getType() == df::item_type::TOOL) { - for (size_t i = 0; i < virtual_cast(item)->improvements.size(); i++) + auto book = virtual_cast(item); + + if (book->hasToolUse(df::tool_uses::CONTAIN_WRITING)) { - if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::PAGES) + for (size_t i = 0; i < book->improvements.size(); i++) { - for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + if (auto page = virtual_cast(book->improvements[i])) { - df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; - if (contents->title != "") + for (size_t k = 0; k < page->contents.size(); k++) { - return contents->title; + df::written_content *contents = world->written_contents.all[page->contents[k]]; + if (contents->title != "") + { + return contents->title; + } } } - } - else if (virtual_cast(item)->improvements[i]->getType() == df::improvement_type::WRITING) - { - for (size_t k = 0; k < virtual_cast(virtual_cast(item)->improvements[i])->contents.size(); k++) + else if (auto writing = virtual_cast(book->improvements[i])) { - df::written_content *contents = world->written_contents.all[virtual_cast(virtual_cast(item)->improvements[i])->contents[k]]; - if (contents->title != "") + for (size_t k = 0; k < writing->contents.size(); k++) { - return contents->title; + df::written_content *contents = world->written_contents.all[writing->contents[k]]; + if (contents->title != "") + { + return contents->title; + } } } } diff --git a/plugins/stocks.cpp b/plugins/stocks.cpp index e44cbb431..4439d820a 100644 --- a/plugins/stocks.cpp +++ b/plugins/stocks.cpp @@ -248,7 +248,7 @@ static string get_keywords(df::item *item) static string get_item_label(df::item *item, bool trim = false) { - auto label = Items::getTitle(item); + auto label = Items::getBookTitle(item); if (label == "") { label = Items::getDescription(item, 0, false); @@ -566,7 +566,7 @@ class StockListColumn : public ListColumn if (!ListColumn::showEntry(entry, search_tokens)) return false; - string item_name = toLower(Items::getTitle(entry->elem->entries[0])); + string item_name = toLower(Items::getBookTitle(entry->elem->entries[0])); if (item_name == "") { item_name = toLower(Items::getDescription(entry->elem->entries[0], 0, false)); From 121497a466df789cac5a6d9ecf206538c01d0cb7 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 26 Jan 2020 11:47:47 +0100 Subject: [PATCH 3/3] Propagated getBookTitle to Lua --- docs/Lua API.rst | 6 ++++++ docs/changelog.txt | 4 ++-- library/LuaApi.cpp | 1 + library/include/modules/Items.h | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index a4130096b..d7e94b92a 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1292,6 +1292,12 @@ Items module Returns true *x,y,z* of the item, or *nil* if invalid; may be not equal to item.pos if in inventory. +* ``dfhack.items.getBookTitle(item)`` + + Returns the title of the "book" item, or an empty string if the item isn't a "book" or it doesn't + have a title. A "book" is a codex or a tool item that has page or writings improvements, such as + scrolls and quires. + * ``dfhack.items.getDescription(item, type[, decorate])`` Returns the string description of the item, as produced by the ``getItemDescription`` diff --git a/docs/changelog.txt b/docs/changelog.txt index 9e4bef7a0..36ac237be 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -38,10 +38,10 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future ## Fixes -- `stocks`: fixed display of titles by using the new ``Items::`getTitle`` operation before the original one, issue 1262 +- `stocks`: fixed display of titles by using the new ``Items::getBookTitle`` operation before the original one ## API -- Added ``Items::`getTitle`` to get titles of "books". Catches titles buried in improvements, unlike getDescription. +- Added ``Items::getBookTitle`` to get titles of "books". Catches titles buried in improvements, unlike getDescription. # 0.44.12-r3 diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 7c3ef965d..1d127930e 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1766,6 +1766,7 @@ static const LuaWrapper::FunctionReg dfhack_items_module[] = { WRAPM(Items, getContainer), WRAPM(Items, getHolderBuilding), WRAPM(Items, getHolderUnit), + WRAPM(Items, getBookTitle), WRAPM(Items, getDescription), WRAPM(Items, isCasteMaterial), WRAPM(Items, getSubtypeCount), diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 838104bfe..33feea222 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -161,7 +161,7 @@ DFHACK_EXPORT df::coord getPosition(df::item *item); /// Returns the title of a codex or "tool", either as the codex title or as the title of the /// first page or writing it has that has a non blank title. An empty string is returned if -/// no title is found (which is the casee for everything that isn't a "book"). +/// no title is found (which is the case for everything that isn't a "book"). DFHACK_EXPORT std::string getBookTitle(df::item *item); /// Returns the description string of the item.