split fs_npc_list.lua into api/ and fs/
This commit is contained in:
parent
d2e5362cf9
commit
fad536a0a4
@ -120,6 +120,93 @@ yl_speak_up.npc_list_store = function()
|
|||||||
end
|
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
|
||||||
|
-- fallback if something went wrong with the position (or it's unknown)
|
||||||
|
local pos_str = '- unknown -'
|
||||||
|
if(not(data.pos) or not(data.pos.x) or not(data.pos.y) or not(data.pos.z)) then
|
||||||
|
data.pos = {x=0, y=0, z=0}
|
||||||
|
end
|
||||||
|
pos_str = minetest.formspec_escape(minetest.pos_to_string(data.pos))
|
||||||
|
|
||||||
|
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 = pos_str,
|
||||||
|
priv_list = priv_list,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- emergency restore NPC that got lost (egg deleted, killed, ...)
|
-- emergency restore NPC that got lost (egg deleted, killed, ...)
|
||||||
yl_speak_up.command_npc_force_restore_npc = function(pname, rest)
|
yl_speak_up.command_npc_force_restore_npc = function(pname, rest)
|
||||||
if(not(pname)) then
|
if(not(pname)) then
|
||||||
@ -291,357 +378,3 @@ yl_speak_up.command_npc_talk_list = function(pname, rest)
|
|||||||
end
|
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()
|
|
||||||
-- teleport to NPC
|
|
||||||
if(fields.teleport
|
|
||||||
and fields.selected_id
|
|
||||||
and yl_speak_up.cache_npc_list_per_player[pname]
|
|
||||||
and minetest.check_player_privs(pname, {teleport=true})) then
|
|
||||||
local id = tonumber(fields.selected_id)
|
|
||||||
if(not(id) or id < 0
|
|
||||||
or not(yl_speak_up.npc_list[id])
|
|
||||||
or table.indexof(yl_speak_up.cache_npc_list_per_player[pname], id) < 1) then
|
|
||||||
minetest.chat_send_player(pname, "Sorry. Cannot find that NPC.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- try cached position
|
|
||||||
local pos = yl_speak_up.npc_list[id].pos
|
|
||||||
local obj = yl_speak_up.npc_list_objects[id]
|
|
||||||
if(obj) then
|
|
||||||
pos = obj:get_pos()
|
|
||||||
end
|
|
||||||
if(not(pos) or not(pos.x) or not(pos.y) or not(pos.z)) then
|
|
||||||
pos = yl_speak_up.npc_list[id].pos
|
|
||||||
end
|
|
||||||
if(not(pos) or not(pos.x) or not(pos.y) or not(pos.z)) then
|
|
||||||
minetest.chat_send_player(pname, "Sorry. Cannot find position of that NPC.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
player:set_pos(pos)
|
|
||||||
minetest.chat_send_player(pname, "Teleporting to NPC with ID "..
|
|
||||||
tostring(fields.selected_id)..': '..
|
|
||||||
tostring(yl_speak_up.npc_list[id].name)..'.')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- sort by column or select an NPC
|
|
||||||
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
|
|
||||||
else
|
|
||||||
-- show details about a specific NPC
|
|
||||||
yl_speak_up.show_fs_ver(pname, "yl_speak_up:show_npc_list",
|
|
||||||
yl_speak_up.get_fs_show_npc_list(pname, selected.row))
|
|
||||||
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
|
|
||||||
-- fallback if something went wrong with the position (or it's unknown)
|
|
||||||
local pos_str = '- unknown -'
|
|
||||||
if(not(data.pos) or not(data.pos.x) or not(data.pos.y) or not(data.pos.z)) then
|
|
||||||
data.pos = {x=0, y=0, z=0}
|
|
||||||
end
|
|
||||||
pos_str = minetest.formspec_escape(minetest.pos_to_string(data.pos))
|
|
||||||
|
|
||||||
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 = pos_str,
|
|
||||||
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, selected_row)
|
|
||||||
-- 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})
|
|
||||||
or minetest.check_player_privs(pname, {npc_talk_admin=true})) then
|
|
||||||
level = 2
|
|
||||||
elseif(minetest.check_player_privs(pname, {npc_talk_owner=true})) then
|
|
||||||
level = 1
|
|
||||||
end
|
|
||||||
if(level < 1) then
|
|
||||||
return "size[5,1]label[0,0;Error: You do not have the npc_talk_owner priv.]"
|
|
||||||
end
|
|
||||||
|
|
||||||
local formspec_start = 'size[18,14.7]'..
|
|
||||||
'label[4.5,0.5;List of all NPC (that you can edit)]'..
|
|
||||||
'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;'
|
|
||||||
-- add information about a specific NPC (selected row)
|
|
||||||
local info_current_row = ''
|
|
||||||
if(selected_row
|
|
||||||
and selected_row > 1
|
|
||||||
and yl_speak_up.cache_npc_list_per_player[pname]
|
|
||||||
and yl_speak_up.cache_npc_list_per_player[pname][selected_row-1]) then
|
|
||||||
local k = yl_speak_up.cache_npc_list_per_player[pname][selected_row-1]
|
|
||||||
local data = yl_speak_up.npc_list[k]
|
|
||||||
local line = yl_speak_up.cache_general_npc_list_lines[k]
|
|
||||||
if(data) then
|
|
||||||
local edit_list = {data.owner}
|
|
||||||
if(data.may_edit) then
|
|
||||||
for e, t in pairs(data.may_edit or {}) do
|
|
||||||
table.insert(edit_list, e)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local n_id = 'n_'..tostring(k)
|
|
||||||
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
|
|
||||||
table.insert(priv_list, priv)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
priv_list = {'- none -'}
|
|
||||||
end
|
|
||||||
local prop_text = 'label[3.0,2.0;- none -]'
|
|
||||||
if(data.properties) then
|
|
||||||
local prop_list = {}
|
|
||||||
for k, v in pairs(data.properties) do
|
|
||||||
table.insert(prop_list, minetest.formspec_escape(
|
|
||||||
tostring(k)..' = '..tostring(v)))
|
|
||||||
end
|
|
||||||
if(#prop_list > 0) then
|
|
||||||
prop_text = 'dropdown[3.0,1.8;8,0.6;properties;'..
|
|
||||||
table.concat(prop_list, ',')..';;]'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local first_seen_at = '- unknown -'
|
|
||||||
if(data.created_at and data.created_at ~= "") then
|
|
||||||
first_seen_at = minetest.formspec_escape(os.date("%m/%d/%y", data.created_at))
|
|
||||||
end
|
|
||||||
-- allow those with teleport priv to easily visit their NPC
|
|
||||||
local teleport_button = ''
|
|
||||||
if(minetest.check_player_privs(pname, {teleport=true})) then
|
|
||||||
-- the ID of the NPC we want to visit is hidden in a field; this is unsafe,
|
|
||||||
-- but the actual check needs to happen when the teleport button is pressed
|
|
||||||
-- anyway
|
|
||||||
teleport_button = 'field[40,40;0,0;selected_id;;'..tostring(k)..']'..
|
|
||||||
'button_exit[12.1,1.8;5,0.6;teleport;Teleport to this NPC]'
|
|
||||||
end
|
|
||||||
info_current_row =
|
|
||||||
'container[0.1,11.2]'..
|
|
||||||
'label[0.1,0.0;Name, Desc:]'..
|
|
||||||
'label[3.0,0.0;'..tostring(line.n_name)..']'..
|
|
||||||
'label[0.1,0.5;Typ:]'..
|
|
||||||
'label[3.0,0.5;'..
|
|
||||||
minetest.formspec_escape(tostring(data.typ or '- ? -'))..']'..
|
|
||||||
'label[12.1,0.5;First seen at:]'..
|
|
||||||
'label[14.4,0.5;'..
|
|
||||||
first_seen_at..']'..
|
|
||||||
'label[0.1,1.0;Can be edited by:]'..
|
|
||||||
'label[3.0,1.0;'..
|
|
||||||
minetest.formspec_escape(table.concat(edit_list, ', '))..']'..
|
|
||||||
'label[0.1,1.5;Has the privs:]'..
|
|
||||||
'label[3.0,1.5;'..
|
|
||||||
minetest.formspec_escape(table.concat(priv_list, ', '))..']'..
|
|
||||||
'label[0.1,2.0;Properties:]'..
|
|
||||||
prop_text..
|
|
||||||
teleport_button..
|
|
||||||
'container_end[]'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
selected_row = 1
|
|
||||||
info_current_row = 'label[0.1,11.2;Click on a column name/header in order to sort by '..
|
|
||||||
'that column. Click it again in order to reverse sort order.\n'..
|
|
||||||
'Click on a row to get more information about a specific NPC.\n'..
|
|
||||||
'Only NPC that can be edited by you are shown.\n'..
|
|
||||||
'Legend: \"G\": is generic NPC. '..
|
|
||||||
'\"#Tr\", \"#Pr\": Number of trades or properties the NPC offers.\n'..
|
|
||||||
' \"#Ed\": Number of players that can edit the NPC. '..
|
|
||||||
'\"Privs\": List of abbreviated names of privs the NPC has.]'
|
|
||||||
end
|
|
||||||
local formspec = {}
|
|
||||||
|
|
||||||
-- TODO: blocks may also be talked to
|
|
||||||
|
|
||||||
local tmp_liste = {}
|
|
||||||
for k, v in pairs(yl_speak_up.npc_list) do
|
|
||||||
-- show only NPC - not blocks
|
|
||||||
if(type(k) == "number" and (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
|
|
||||||
|
|
||||||
-- 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[pname] = tmp_liste
|
|
||||||
|
|
||||||
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, ";"..selected_row.."]")
|
|
||||||
return table.concat({formspec_start,
|
|
||||||
table.concat(formspec, ','),
|
|
||||||
info_current_row,
|
|
||||||
'button_exit[0.1,14;19.6,0.6;exit;Exit]'}, '')
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- at load/reload of the mod: read the list of existing NPC
|
|
||||||
yl_speak_up.npc_list_load()
|
|
265
fs/fs_npc_list.lua
Normal file
265
fs/fs_npc_list.lua
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
-- 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()
|
||||||
|
-- teleport to NPC
|
||||||
|
if(fields.teleport
|
||||||
|
and fields.selected_id
|
||||||
|
and yl_speak_up.cache_npc_list_per_player[pname]
|
||||||
|
and minetest.check_player_privs(pname, {teleport=true})) then
|
||||||
|
local id = tonumber(fields.selected_id)
|
||||||
|
if(not(id) or id < 0
|
||||||
|
or not(yl_speak_up.npc_list[id])
|
||||||
|
or table.indexof(yl_speak_up.cache_npc_list_per_player[pname], id) < 1) then
|
||||||
|
minetest.chat_send_player(pname, "Sorry. Cannot find that NPC.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- try cached position
|
||||||
|
local pos = yl_speak_up.npc_list[id].pos
|
||||||
|
local obj = yl_speak_up.npc_list_objects[id]
|
||||||
|
if(obj) then
|
||||||
|
pos = obj:get_pos()
|
||||||
|
end
|
||||||
|
if(not(pos) or not(pos.x) or not(pos.y) or not(pos.z)) then
|
||||||
|
pos = yl_speak_up.npc_list[id].pos
|
||||||
|
end
|
||||||
|
if(not(pos) or not(pos.x) or not(pos.y) or not(pos.z)) then
|
||||||
|
minetest.chat_send_player(pname, "Sorry. Cannot find position of that NPC.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
player:set_pos(pos)
|
||||||
|
minetest.chat_send_player(pname, "Teleporting to NPC with ID "..
|
||||||
|
tostring(fields.selected_id)..': '..
|
||||||
|
tostring(yl_speak_up.npc_list[id].name)..'.')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- sort by column or select an NPC
|
||||||
|
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
|
||||||
|
else
|
||||||
|
-- show details about a specific NPC
|
||||||
|
yl_speak_up.show_fs_ver(pname, "yl_speak_up:show_npc_list",
|
||||||
|
yl_speak_up.get_fs_show_npc_list(pname, selected.row))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
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, selected_row)
|
||||||
|
-- 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})
|
||||||
|
or minetest.check_player_privs(pname, {npc_talk_admin=true})) then
|
||||||
|
level = 2
|
||||||
|
elseif(minetest.check_player_privs(pname, {npc_talk_owner=true})) then
|
||||||
|
level = 1
|
||||||
|
end
|
||||||
|
if(level < 1) then
|
||||||
|
return "size[5,1]label[0,0;Error: You do not have the npc_talk_owner priv.]"
|
||||||
|
end
|
||||||
|
|
||||||
|
local formspec_start = 'size[18,14.7]'..
|
||||||
|
'label[4.5,0.5;List of all NPC (that you can edit)]'..
|
||||||
|
'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;'
|
||||||
|
-- add information about a specific NPC (selected row)
|
||||||
|
local info_current_row = ''
|
||||||
|
if(selected_row
|
||||||
|
and selected_row > 1
|
||||||
|
and yl_speak_up.cache_npc_list_per_player[pname]
|
||||||
|
and yl_speak_up.cache_npc_list_per_player[pname][selected_row-1]) then
|
||||||
|
local k = yl_speak_up.cache_npc_list_per_player[pname][selected_row-1]
|
||||||
|
local data = yl_speak_up.npc_list[k]
|
||||||
|
local line = yl_speak_up.cache_general_npc_list_lines[k]
|
||||||
|
if(data) then
|
||||||
|
local edit_list = {data.owner}
|
||||||
|
if(data.may_edit) then
|
||||||
|
for e, t in pairs(data.may_edit or {}) do
|
||||||
|
table.insert(edit_list, e)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local n_id = 'n_'..tostring(k)
|
||||||
|
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
|
||||||
|
table.insert(priv_list, priv)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
priv_list = {'- none -'}
|
||||||
|
end
|
||||||
|
local prop_text = 'label[3.0,2.0;- none -]'
|
||||||
|
if(data.properties) then
|
||||||
|
local prop_list = {}
|
||||||
|
for k, v in pairs(data.properties) do
|
||||||
|
table.insert(prop_list, minetest.formspec_escape(
|
||||||
|
tostring(k)..' = '..tostring(v)))
|
||||||
|
end
|
||||||
|
if(#prop_list > 0) then
|
||||||
|
prop_text = 'dropdown[3.0,1.8;8,0.6;properties;'..
|
||||||
|
table.concat(prop_list, ',')..';;]'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local first_seen_at = '- unknown -'
|
||||||
|
if(data.created_at and data.created_at ~= "") then
|
||||||
|
first_seen_at = minetest.formspec_escape(os.date("%m/%d/%y", data.created_at))
|
||||||
|
end
|
||||||
|
-- allow those with teleport priv to easily visit their NPC
|
||||||
|
local teleport_button = ''
|
||||||
|
if(minetest.check_player_privs(pname, {teleport=true})) then
|
||||||
|
-- the ID of the NPC we want to visit is hidden in a field; this is unsafe,
|
||||||
|
-- but the actual check needs to happen when the teleport button is pressed
|
||||||
|
-- anyway
|
||||||
|
teleport_button = 'field[40,40;0,0;selected_id;;'..tostring(k)..']'..
|
||||||
|
'button_exit[12.1,1.8;5,0.6;teleport;Teleport to this NPC]'
|
||||||
|
end
|
||||||
|
info_current_row =
|
||||||
|
'container[0.1,11.2]'..
|
||||||
|
'label[0.1,0.0;Name, Desc:]'..
|
||||||
|
'label[3.0,0.0;'..tostring(line.n_name)..']'..
|
||||||
|
'label[0.1,0.5;Typ:]'..
|
||||||
|
'label[3.0,0.5;'..
|
||||||
|
minetest.formspec_escape(tostring(data.typ or '- ? -'))..']'..
|
||||||
|
'label[12.1,0.5;First seen at:]'..
|
||||||
|
'label[14.4,0.5;'..
|
||||||
|
first_seen_at..']'..
|
||||||
|
'label[0.1,1.0;Can be edited by:]'..
|
||||||
|
'label[3.0,1.0;'..
|
||||||
|
minetest.formspec_escape(table.concat(edit_list, ', '))..']'..
|
||||||
|
'label[0.1,1.5;Has the privs:]'..
|
||||||
|
'label[3.0,1.5;'..
|
||||||
|
minetest.formspec_escape(table.concat(priv_list, ', '))..']'..
|
||||||
|
'label[0.1,2.0;Properties:]'..
|
||||||
|
prop_text..
|
||||||
|
teleport_button..
|
||||||
|
'container_end[]'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
selected_row = 1
|
||||||
|
info_current_row = 'label[0.1,11.2;Click on a column name/header in order to sort by '..
|
||||||
|
'that column. Click it again in order to reverse sort order.\n'..
|
||||||
|
'Click on a row to get more information about a specific NPC.\n'..
|
||||||
|
'Only NPC that can be edited by you are shown.\n'..
|
||||||
|
'Legend: \"G\": is generic NPC. '..
|
||||||
|
'\"#Tr\", \"#Pr\": Number of trades or properties the NPC offers.\n'..
|
||||||
|
' \"#Ed\": Number of players that can edit the NPC. '..
|
||||||
|
'\"Privs\": List of abbreviated names of privs the NPC has.]'
|
||||||
|
end
|
||||||
|
local formspec = {}
|
||||||
|
|
||||||
|
-- TODO: blocks may also be talked to
|
||||||
|
|
||||||
|
local tmp_liste = {}
|
||||||
|
for k, v in pairs(yl_speak_up.npc_list) do
|
||||||
|
-- show only NPC - not blocks
|
||||||
|
if(type(k) == "number" and (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
|
||||||
|
|
||||||
|
-- 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[pname] = tmp_liste
|
||||||
|
|
||||||
|
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, ";"..selected_row.."]")
|
||||||
|
return table.concat({formspec_start,
|
||||||
|
table.concat(formspec, ','),
|
||||||
|
info_current_row,
|
||||||
|
'button_exit[0.1,14;19.6,0.6;exit;Exit]'}, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- at load/reload of the mod: read the list of existing NPC
|
||||||
|
yl_speak_up.npc_list_load()
|
5
init.lua
5
init.lua
@ -202,7 +202,7 @@ yl_speak_up.reload = function(modpath, log_entry)
|
|||||||
-- set name, description and owner (owner only with npc_talk_master priv)
|
-- set name, description and owner (owner only with npc_talk_master priv)
|
||||||
dofile(modpath .. "fs/fs_initial_config.lua")
|
dofile(modpath .. "fs/fs_initial_config.lua")
|
||||||
-- inspect and accept items the player gave to the NPC
|
-- inspect and accept items the player gave to the NPC
|
||||||
dofile(modpath .. "fs_player_offers_item.lua")
|
dofile(modpath .. "fs/fs_player_offers_item.lua")
|
||||||
-- inventory management, trading and handling of quest items:
|
-- inventory management, trading and handling of quest items:
|
||||||
dofile(modpath .. "inventory.lua")
|
dofile(modpath .. "inventory.lua")
|
||||||
-- limit how much the NPC shall buy and sell
|
-- limit how much the NPC shall buy and sell
|
||||||
@ -250,7 +250,8 @@ yl_speak_up.reload = function(modpath, log_entry)
|
|||||||
dofile(modpath .. "fs/fs_notes.lua")
|
dofile(modpath .. "fs/fs_notes.lua")
|
||||||
|
|
||||||
-- show a list of all NPC the player can edit
|
-- show a list of all NPC the player can edit
|
||||||
dofile(modpath .. "fs_npc_list.lua")
|
dofile(modpath .. "api/api_npc_list.lua")
|
||||||
|
dofile(modpath .. "fs/fs_npc_list.lua")
|
||||||
|
|
||||||
-- some general functions that are useful for mobs_redo
|
-- some general functions that are useful for mobs_redo
|
||||||
-- (react to right-click, nametag color etc.)
|
-- (react to right-click, nametag color etc.)
|
||||||
|
Loading…
Reference in New Issue
Block a user