forked from your-land-mirror/yl_speak_up
implemented '/npc_talk list' including sorting
This commit is contained in:
parent
e2ecb7de4b
commit
79797ee27c
279
fs_npc_list.lua
279
fs_npc_list.lua
@ -9,6 +9,16 @@ yl_speak_up.npc_list_objects = {}
|
||||
-- file to store the list of NPC for the "/npc_talk list" command
|
||||
yl_speak_up.npc_list_path = minetest.get_worldpath().."/yl_speak_up_npc_list.data"
|
||||
|
||||
-- pre-calculated lines for the NPC list (only which ones are shown and how some columns
|
||||
-- are colored varies per player)
|
||||
yl_speak_up.cache_general_npc_list_lines = {}
|
||||
|
||||
-- we need to remember which NPC was shown to the player in which order; index: player name
|
||||
yl_speak_up.cache_npc_list_per_player = {}
|
||||
|
||||
-- which table column is the player using for sorting?
|
||||
yl_speak_up.sort_npc_list_per_player = {}
|
||||
|
||||
-- add/update data about NPC self with dialog dialog (optional)
|
||||
-- force_store ought to be true if something important has been changed
|
||||
yl_speak_up.update_npc_data = function(self, dialog, force_store)
|
||||
@ -32,7 +42,7 @@ yl_speak_up.update_npc_data = function(self, dialog, force_store)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif(is_knwon) then
|
||||
elseif(is_known) then
|
||||
local old = yl_speak_up.npc_list[self.yl_speak_up.id]
|
||||
may_edit = old.may_edit
|
||||
desc = old.desc
|
||||
@ -47,9 +57,13 @@ yl_speak_up.update_npc_data = function(self, dialog, force_store)
|
||||
local pos = {}
|
||||
if(self.object) then
|
||||
pos = self.object:get_pos()
|
||||
pos.x = math.floor(pos.x or 0)
|
||||
pos.y = math.floor(pos.y or 0)
|
||||
pos.z = math.floor(pos.z or 0)
|
||||
if(pos) then
|
||||
pos = { x = math.floor(pos.x or 0),
|
||||
y = math.floor(pos.y or 0),
|
||||
z = math.floor(pos.z or 0)}
|
||||
else
|
||||
pos = { x=0, y=0, z=0}
|
||||
end
|
||||
end
|
||||
-- only store real, important properties
|
||||
local properties = {}
|
||||
@ -68,6 +82,8 @@ yl_speak_up.update_npc_data = function(self, dialog, force_store)
|
||||
trades = trades,
|
||||
pos = pos,
|
||||
properties = properties,
|
||||
created_at = created_at,
|
||||
muted = self.yl_speak_up.talk,
|
||||
}
|
||||
-- the current object will change after deactivate; there is no point in storing
|
||||
-- it over server restart
|
||||
@ -106,6 +122,143 @@ yl_speak_up.command_npc_talk_list = function(pname, rest)
|
||||
if(not(pname)) then
|
||||
return
|
||||
end
|
||||
|
||||
-- check if there are any loaded entities handled by yl_speak_up that
|
||||
-- are *not* in the list yet
|
||||
local liste = {}
|
||||
for k,v in pairs(minetest.luaentities) do
|
||||
if(v and v.yl_speak_up and v.yl_speak_up.id) then
|
||||
if(not(yl_speak_up.npc_list[v.yl_speak_up.id])) then
|
||||
local dialog = yl_speak_up.load_dialog(v.yl_speak_up.id, nil)
|
||||
yl_speak_up.update_npc_data(v, dialog, false)
|
||||
else
|
||||
yl_speak_up.update_npc_data(v, nil, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- store the updated list
|
||||
yl_speak_up.npc_list_store()
|
||||
-- update the information for display
|
||||
yl_speak_up.build_cache_general_npc_list_lines()
|
||||
-- clear the stored NPC list and calculate it anew
|
||||
yl_speak_up.cache_npc_list_per_player[pname] = {}
|
||||
-- Note: show_fs cannot be used here as that expects the player to be talking to an actual npc
|
||||
yl_speak_up.show_fs_ver(pname, "yl_speak_up:show_npc_list",
|
||||
yl_speak_up.get_fs_show_npc_list(pname, nil))
|
||||
end
|
||||
|
||||
|
||||
-- allow to sort the npc list, display more info on one NPC etc.
|
||||
yl_speak_up.input_show_npc_list = function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
if(fields.show_npc_list) then
|
||||
local selected = minetest.explode_table_event(fields.show_npc_list)
|
||||
-- sort by column
|
||||
if(selected.row == 1) then
|
||||
local old_sort = yl_speak_up.sort_npc_list_per_player[pname] or 0
|
||||
-- reverse sort
|
||||
if(old_sort == selected.column) then
|
||||
yl_speak_up.sort_npc_list_per_player[pname] = -1 * selected.column
|
||||
else -- sort by new col
|
||||
yl_speak_up.sort_npc_list_per_player[pname] = selected.column
|
||||
end
|
||||
-- show the update
|
||||
yl_speak_up.show_fs_ver(pname, "yl_speak_up:show_npc_list",
|
||||
yl_speak_up.get_fs_show_npc_list(pname, nil))
|
||||
return
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- the entries for the "/npc_talk list" NPC list are generally the same for all
|
||||
-- - except that not all lines are shown to each player and that some
|
||||
-- lines might be colored diffrently
|
||||
yl_speak_up.build_cache_general_npc_list_lines = function()
|
||||
|
||||
-- small helper function to suppress the display of zeros
|
||||
local show_if_bigger_null = function(value, do_count)
|
||||
if(do_count and value) then
|
||||
local anz = 0
|
||||
for k, v in pairs(value) do
|
||||
anz = anz + 1
|
||||
end
|
||||
value = anz
|
||||
end
|
||||
if(value and value > 0) then
|
||||
return tostring(value)
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
-- the real priv names would be far too long
|
||||
local short_priv_name = {
|
||||
precon_exec_lua = 'pX',
|
||||
effect_exec_lua = 'eX',
|
||||
effect_give_item = 'eG',
|
||||
effect_take_item = 'eT',
|
||||
effect_move_player = 'eM',
|
||||
}
|
||||
|
||||
yl_speak_up.cache_general_npc_list_lines = {}
|
||||
|
||||
for k, data in pairs(yl_speak_up.npc_list) do
|
||||
local data = yl_speak_up.npc_list[k]
|
||||
local n = (data.name or "- ? -")
|
||||
if(data.desc and data.desc ~= "") then
|
||||
n = n..', '..(data.desc or "")
|
||||
end
|
||||
-- is the NPC muted?
|
||||
local npc_color = (yl_speak_up.nametag_color_when_not_muted or '#FFFFFF')
|
||||
if(data.muted ~= nil and data.muted == false) then
|
||||
npc_color = (yl_speak_up.nametag_color_when_muted or '#FFFFFF')
|
||||
end
|
||||
-- is the NPC loaded?
|
||||
local is_loaded_color = '#777777'
|
||||
if(yl_speak_up.npc_list_objects[k]) then
|
||||
is_loaded_color = '#FFFFFF'
|
||||
end
|
||||
-- is it a generic NPC?
|
||||
local n_id = 'n_'..tostring(k)
|
||||
local is_generic = ''
|
||||
if(yl_speak_up.generic_dialogs[n_id]) then
|
||||
is_generic = 'G'
|
||||
end
|
||||
-- does the NPC have extra privs?
|
||||
local priv_list = ''
|
||||
if(yl_speak_up.npc_priv_table[n_id]) then
|
||||
for priv, has_it in pairs(yl_speak_up.npc_priv_table[n_id]) do
|
||||
priv_list = priv_list..tostring(short_priv_name[priv])..' '
|
||||
end
|
||||
end
|
||||
|
||||
yl_speak_up.cache_general_npc_list_lines[k] = {
|
||||
id = k, -- keep for sorting
|
||||
is_loaded_color = is_loaded_color,
|
||||
n_id = n_id,
|
||||
is_generic = is_generic,
|
||||
npc_color = npc_color, -- muted or not
|
||||
-- npc_color is diffrent for each player
|
||||
n_name = minetest.formspec_escape(n),
|
||||
owner = minetest.formspec_escape(data.owner or '- ? -'),
|
||||
is_loaded_color = is_loaded_color,
|
||||
anz_trades = show_if_bigger_null(#data.trades),
|
||||
anz_properties = show_if_bigger_null(data.properties, true),
|
||||
anz_editors = show_if_bigger_null(data.may_edit, true),
|
||||
pos = minetest.formspec_escape(minetest.pos_to_string(data.pos)),
|
||||
priv_list = priv_list,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- allow to toggle between trade entries and full log
|
||||
-- Note: takes pname instead of player(object) as first parameter
|
||||
yl_speak_up.get_fs_show_npc_list = function(pname, param)
|
||||
-- which NPC can the player edit?
|
||||
local level = 0
|
||||
if( minetest.check_player_privs(pname, {npc_master=true})
|
||||
or minetest.check_player_privs(pname, {npc_talk_master=true})
|
||||
@ -115,32 +268,114 @@ yl_speak_up.command_npc_talk_list = function(pname, rest)
|
||||
level = 1
|
||||
end
|
||||
if(level < 1) then
|
||||
minetest.chat_send_player(pname, "This command requires the npc_talk_owner priv or above.")
|
||||
return
|
||||
return "size[5,1]label[0,0;Error: You do not have the npc_talk_owner priv.]"
|
||||
end
|
||||
|
||||
minetest.chat_send_player(pname, "OK...building list.")
|
||||
local formspec_start = 'size[18,12]'..
|
||||
-- 'button[0.5,11.1;17,0.8;',
|
||||
-- back_link,
|
||||
-- ']'..
|
||||
'label[4.5,0.5;List of all NPC (that you can edit)]'..
|
||||
-- 'button[0.5,0.1;3,0.8;',
|
||||
-- log_type_switch,
|
||||
-- ']',
|
||||
'tablecolumns[' ..
|
||||
'color;text,align=right;'.. -- the ID
|
||||
'color;text,align=center;'.. -- is the NPC a generic one?
|
||||
'color;text,align=left;'.. -- the name of the NPC
|
||||
'color;text,align=center;'.. -- the name of the owner of the NPC
|
||||
'color;text,align=right;'.. -- number of trades offered
|
||||
'color;text,align=right;'.. -- number of properties set
|
||||
'color;text,align=right;'.. -- number of people who can edit NPC
|
||||
'color;text,align=center;'.. -- last known position
|
||||
'color;text,align=center]'.. -- does he have extra privs?
|
||||
'table[0.1,1.0;17.8,9.8;show_npc_list;'
|
||||
local formspec = {}
|
||||
|
||||
-- sort by default by id descending?
|
||||
-- TODO: blocks may also be talked to
|
||||
-- TODO desc as mouseover?, created_at?
|
||||
-- TODO: created_at, typ (race?)?
|
||||
|
||||
-- check if there are any loaded entities handled by yl_speak_up that
|
||||
-- are *not* in the list yet
|
||||
local liste = {}
|
||||
for k,v in pairs(minetest.luaentities) do
|
||||
if(v and v.yl_speak_up and v.yl_speak_up.id
|
||||
and not(yl_speak_up.npc_list[v.yl_speak_up.id])) then
|
||||
local dialog = yl_speak_up.load_dialog(v.yl_speak_up.id, nil)
|
||||
yl_speak_up.update_npc_data(v, dialog, true)
|
||||
|
||||
local tmp_liste = {}
|
||||
for k, v in pairs(yl_speak_up.npc_list) do
|
||||
if(level == 2
|
||||
or (v.owner and v.owner == pname)
|
||||
or (v.may_edit and v.may_edit[pname])) then
|
||||
table.insert(tmp_liste, k)
|
||||
end
|
||||
end
|
||||
-- TODO: blocks may also be talked to
|
||||
|
||||
for k, v in pairs(yl_speak_up.npc_list) do
|
||||
-- possible editors: dialog.n_may_edit[pname]
|
||||
minetest.chat_send_player(pname, tostring(k).." "..
|
||||
tostring(v.name).." "..tostring(v.owner)..
|
||||
" "..minetest.pos_to_string(v.pos))
|
||||
-- the columns with the colors count as well even though they can't be selected
|
||||
-- (don't sort the first column by n_<id> STRING - sort by <id> NUMBER)
|
||||
local col_names = {"id", "id", "is_generic", "is_generic", "n_name", "n_name",
|
||||
"owner", "owner", "anz_trades", "anz_trades",
|
||||
"anz_properties", "anz_properties", "anz_editors", "anz_editors",
|
||||
"pos", "pos", "priv_list", "priv_list"}
|
||||
local sort_col = yl_speak_up.sort_npc_list_per_player[pname]
|
||||
if(not(sort_col) or sort_col == 0) then
|
||||
table.sort(tmp_liste)
|
||||
elseif(sort_col > 0) then
|
||||
-- it is often more helpful to sort in descending order
|
||||
local col_name = col_names[sort_col]
|
||||
table.sort(tmp_liste, function(a, b)
|
||||
return yl_speak_up.cache_general_npc_list_lines[a][col_name]
|
||||
> yl_speak_up.cache_general_npc_list_lines[b][col_name]
|
||||
end)
|
||||
else
|
||||
local col_name = col_names[sort_col * -1]
|
||||
table.sort(tmp_liste, function(a, b)
|
||||
return yl_speak_up.cache_general_npc_list_lines[a][col_name]
|
||||
< yl_speak_up.cache_general_npc_list_lines[b][col_name]
|
||||
end)
|
||||
end
|
||||
|
||||
local col_headers = {'n_id', 'G', 'Name', 'Owner', '#Tr', '#Pr', '#Ed', 'Position', 'Privs'}
|
||||
for i, k in ipairs(col_headers) do
|
||||
if( sort_col and sort_col == (i * 2)) then
|
||||
table.insert(formspec, 'yellow')
|
||||
table.insert(formspec, 'v '..k..' v')
|
||||
elseif(sort_col and sort_col == (i * -2)) then
|
||||
table.insert(formspec, 'yellow')
|
||||
table.insert(formspec, '^ '..k..' ^')
|
||||
else
|
||||
table.insert(formspec, '#FFFFFF')
|
||||
table.insert(formspec, k)
|
||||
end
|
||||
end
|
||||
yl_speak_up.cache_npc_list_per_player = tmp_list
|
||||
|
||||
for i, k in ipairs(tmp_liste) do
|
||||
local data = yl_speak_up.npc_list[k]
|
||||
local line = yl_speak_up.cache_general_npc_list_lines[k]
|
||||
-- own NPC are colored green, others white
|
||||
local owner_color = '#FFFFFF'
|
||||
if(data.owner == pname) then
|
||||
owner_color = '#00FF00'
|
||||
elseif (data.may_edit and data.may_edit[pname]) then
|
||||
owner_color = '#FFFF00'
|
||||
end
|
||||
table.insert(formspec, line.is_loaded_color)
|
||||
table.insert(formspec, line.n_id)
|
||||
table.insert(formspec, 'orange')
|
||||
table.insert(formspec, line.is_generic)
|
||||
table.insert(formspec, line.npc_color)
|
||||
table.insert(formspec, line.n_name)
|
||||
table.insert(formspec, owner_color) -- diffrent for each player
|
||||
table.insert(formspec, line.owner)
|
||||
table.insert(formspec, line.is_loaded_color)
|
||||
table.insert(formspec, line.anz_trades)
|
||||
table.insert(formspec, line.is_loaded_color)
|
||||
table.insert(formspec, line.anz_properties)
|
||||
table.insert(formspec, owner_color) -- diffrent for each player
|
||||
table.insert(formspec, line.anz_editors)
|
||||
table.insert(formspec, line.is_loaded_color)
|
||||
table.insert(formspec, line.pos)
|
||||
table.insert(formspec, line.is_loaded_color)
|
||||
table.insert(formspec, line.priv_list)
|
||||
end
|
||||
table.insert(formspec, ";1]")
|
||||
return formspec_start..table.concat(formspec, ',')
|
||||
end
|
||||
|
||||
|
||||
|
@ -60,6 +60,9 @@ yl_speak_up.input_handler = function(player, formname, fields)
|
||||
elseif formname == "yl_speak_up:show_log" then
|
||||
yl_speak_up.input_show_log(player, formname, fields)
|
||||
return true
|
||||
elseif formname == "yl_speak_up:show_npc_list" then
|
||||
yl_speak_up.input_show_npc_list(player, formname, fields)
|
||||
return true
|
||||
elseif formname == "yl_speak_up:edit_trade_limit" then
|
||||
yl_speak_up.input_edit_trade_limit(player, formname, fields)
|
||||
return true
|
||||
@ -342,6 +345,11 @@ yl_speak_up.show_fs = function(player, fs_name, param)
|
||||
yl_speak_up.show_fs_ver(pname, "yl_speak_up:show_log",
|
||||
yl_speak_up.get_fs_show_log(player, param.log_type))
|
||||
|
||||
elseif(fs_name == "show_npc_list") then
|
||||
yl_speak_up.show_fs_ver(pname, "yl_speak_up:show_npc_list",
|
||||
yl_speak_up.get_fs_show_npc_list(player, nil))
|
||||
|
||||
|
||||
elseif(fs_name == "edit_trade_limit") then
|
||||
if(not(param)) then
|
||||
param = {}
|
||||
|
Loading…
Reference in New Issue
Block a user