Support sorting items in the trade screens.

Caveat: sorts items in containers independently from the container.
develop
Alexander Gavrilov 2012-05-18 19:18:49 +04:00
parent e2f39368b1
commit 4aa6dbdd00
5 changed files with 208 additions and 9 deletions

@ -446,6 +446,13 @@ Lua::ObjectClass Lua::IsDFObject(lua_State *state, int val_index)
return ok ? cls : Lua::OBJ_INVALID;
}
static const char *const primitive_types[] = {
"string", NULL
};
static type_identity *const primitive_identities[] = {
df::identity_traits<std::string>::get(), NULL
};
/**
* Given a DF object reference or type, safely retrieve its identity pointer.
*/
@ -453,6 +460,12 @@ type_identity *LuaWrapper::get_object_identity(lua_State *state, int objidx,
const char *ctx, bool allow_type,
bool keep_metatable)
{
if (allow_type && !keep_metatable && lua_isstring(state, objidx))
{
int idx = luaL_checkoption(state, objidx, NULL, primitive_types);
return primitive_identities[idx];
}
if (!lua_getmetatable(state, objidx))
luaL_error(state, "Invalid object in %s", ctx);

@ -2,9 +2,11 @@ local _ENV = mkmodule('plugins.sort')
local utils = require('utils')
local units = require('plugins.sort.units')
local items = require('plugins.sort.items')
orders = orders or {}
orders.units = units.orders
orders.items = items.orders
function parse_ordering_spec(type,...)
local group = orders[type]

@ -0,0 +1,62 @@
local _ENV = mkmodule('plugins.sort.items')
local utils = require('utils')
orders = orders or {}
-- Relies on NULL being auto-translated to NULL, and then sorted
orders.exists = {
key = function(item)
return 1
end
}
orders.type = {
key = function(item)
return item:getType()
end
}
orders.description = {
key = function(item)
return dfhack.with_temp_object(
df.new "string",
function(str,item)
item:getItemDescription(str,0)
return str.value
end,
item
)
end
}
orders.quality = {
key = function(item)
return item:getQuality()
end
}
orders.improvement = {
key = function(item)
return item:getImprovementQuality()
end
}
orders.wear = {
key = function(item)
return item:getWear()
end
}
orders.material = {
key = function(item)
local mattype = item:getActualMaterial()
local matindex = item:getActualMaterialIndex()
local info = dfhack.matinfo.decode(mattype, matindex)
if info then
return info:toString()
end
end
}
return _ENV

@ -109,4 +109,10 @@ orders.squad_position = {
end
}
orders.happiness = {
key = function(unit)
return unit.status.happiness
end
}
return _ENV

@ -18,9 +18,12 @@
#include "df/viewscreen_layer_workshop_profilest.h"
#include "df/viewscreen_layer_noblelistst.h"
#include "df/viewscreen_layer_overall_healthst.h"
#include "df/viewscreen_layer_assigntradest.h"
#include "df/viewscreen_tradegoodsst.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/viewscreen_petst.h"
#include "df/layer_object_listst.h"
#include "df/assign_trade_status.h"
#include "MiscUtils.h"
@ -42,8 +45,10 @@ using df::global::ui_building_assign_units;
using df::global::ui_building_assign_items;
static bool unit_list_hotkey(df::viewscreen *top);
static bool item_list_hotkey(df::viewscreen *top);
static command_result sort_units(color_ostream &out, vector <string> & parameters);
static command_result sort_items(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("sort");
@ -59,6 +64,16 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" name, age, arrival, squad, squad_position, profession\n"
"The orderings are defined in hack/lua/plugins/sort/*.lua\n"
));
commands.push_back(PluginCommand(
"sort-items", "Sort the visible item list.", sort_items, item_list_hotkey,
" sort-items order [order...]\n"
" Sort the item list using the given sequence of comparisons.\n"
" The '<' prefix for an order makes undefined values sort first.\n"
" The '>' prefix reverses the sort order for defined values.\n"
" Item order examples:\n"
" description, material, wear, type, quality\n"
"The orderings are defined in hack/lua/plugins/sort/*.lua\n"
));
return CR_OK;
}
@ -179,7 +194,7 @@ bool compute_order(color_ostream &out, lua_State *L, int base, std::vector<unsig
static bool ParseSpec(color_ostream &out, lua_State *L, const char *type, vector<string> &params)
{
if (!parse_ordering_spec(out, L, "units", params))
if (!parse_ordering_spec(out, L, type, params))
{
out.printerr("Invalid ordering specification for %s.\n", type);
return false;
@ -191,6 +206,20 @@ static bool ParseSpec(color_ostream &out, lua_State *L, const char *type, vector
#define PARSE_SPEC(type, params) \
if (!ParseSpec(*pout, L, type, params)) return false;
static bool prepare_sort(color_ostream *pout, lua_State *L)
{
if (L)
{
if (!Lua::PushModulePublic(*pout, L, "plugins.sort", "make_sort_order"))
{
pout->printerr("Cannot access the sorter function.\n");
return false;
}
}
return true;
}
static void sort_null_first(vector<string> &parameters)
{
vector_insert_at(parameters, 0, std::string("<exists"));
@ -206,14 +235,8 @@ static bool maybe_sort_units(color_ostream *pout, lua_State *L,
{
Lua::StackUnwinder top(L);
if (L)
{
if (!Lua::PushModulePublic(*pout, L, "plugins.sort", "make_sort_order"))
{
pout->printerr("Cannot access the sorter function.\n");
return false;
}
}
if (!prepare_sort(pout, L))
return false;
std::vector<unsigned> order;
@ -526,3 +549,96 @@ static command_result sort_units(color_ostream &out, vector <string> &parameters
return CR_OK;
}
static bool maybe_sort_items(color_ostream *pout, lua_State *L,
df::viewscreen *screen, vector<string> &parameters)
{
Lua::StackUnwinder top(L);
if (!prepare_sort(pout, L))
return false;
std::vector<unsigned> order;
if (auto trade = strict_virtual_cast<df::viewscreen_tradegoodsst>(screen))
{
if (!L) return true;
PARSE_SPEC("items", parameters);
if (trade->in_right_pane)
{
if (compute_order(*pout, L, top, &order, trade->broker_items))
{
reorder_cursor(&trade->broker_cursor, order);
reorder_vector(&trade->broker_items, order);
reorder_vector(&trade->broker_selected, order);
reorder_vector(&trade->broker_count, order);
}
}
else
{
if (compute_order(*pout, L, top, &order, trade->trader_items))
{
reorder_cursor(&trade->trader_cursor, order);
reorder_vector(&trade->trader_items, order);
reorder_vector(&trade->trader_selected, order);
reorder_vector(&trade->trader_count, order);
}
}
return true;
}
else if (auto bring = strict_virtual_cast<df::viewscreen_layer_assigntradest>(screen))
{
auto list1 = getLayerList(bring, 0);
auto list2 = getLayerList(bring, 1);
if (!list1 || !list2 || !list2->bright)
return false;
int list_idx = vector_get(bring->visible_lists, list1->cursor, (int16_t)-1);
unsigned num_lists = sizeof(bring->lists)/sizeof(std::vector<int32_t>);
if (unsigned(list_idx) >= num_lists)
return false;
if (!L) return true;
PARSE_SPEC("items", parameters);
auto &vec = bring->lists[list_idx];
std::vector<df::item*> items;
for (size_t i = 0; i < vec.size(); i++)
items.push_back(bring->info[vec[i]]->item);
if (compute_order(*pout, L, top, &order, items))
{
reorder_cursor(&list2->cursor, order);
reorder_vector(&vec, order);
}
return true;
}
else
return false;
}
static bool item_list_hotkey(df::viewscreen *screen)
{
vector<string> dummy;
return maybe_sort_items(NULL, NULL, screen, dummy);
}
static command_result sort_items(color_ostream &out, vector <string> &parameters)
{
if (parameters.empty())
return CR_WRONG_USAGE;
auto L = Lua::Core::State;
auto screen = Core::getInstance().getTopViewscreen();
if (!maybe_sort_items(&out, L, screen, parameters))
return CR_WRONG_USAGE;
return CR_OK;
}