From 430cbd65bb41658028776179fad11433384eddde Mon Sep 17 00:00:00 2001 From: Sokomine Date: Mon, 26 Jul 2021 19:39:31 +0200 Subject: [PATCH] players can now add others that may edit their npc with just npc_talk_owner priv --- fs_initial_config.lua | 95 +++++++++++++++++++++++++++++++++++++++---- functions.lua | 23 ++++++++--- 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/fs_initial_config.lua b/fs_initial_config.lua index 771d5b1..cf85460 100644 --- a/fs_initial_config.lua +++ b/fs_initial_config.lua @@ -5,6 +5,11 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) local pname = player:get_player_name() local n_id = yl_speak_up.speak_to[pname].n_id + -- not in edit mode? then abort + if(yl_speak_up.edit_mode[pname] ~= n_id or not(n_id)) then + return + end + if(fields.back_from_error_msg) then -- no point in showing the formspec or error message again if we did so already if(not(yl_speak_up.may_edit_npc(player, n_id))) then @@ -16,7 +21,7 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) return end - if(not(fields.save_initial_config)) then + if(not(fields.save_initial_config) and (fields.quit or fields.exit)) then -- is the player editing the npc? then leaving this config -- dialog has to lead back to the talk dialog if(yl_speak_up.edit_mode[pname] == n_id and n_id) then @@ -34,6 +39,7 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) if(fields.n_npc) then fields.n_npc = fields.n_npc:match("^%s*(.-)%s*$") end + local dialog = yl_speak_up.speak_to[pname].dialog -- the player is trying to save the initial configuration -- is the player allowed to initialize this npc? if(not(yl_speak_up.may_edit_npc(player, n_id))) then @@ -56,6 +62,55 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) "have the \"npc_talk_owner\" priv. Else the\n".. "new owner could not edit his own NPC." end + -- want to change who may edit this npc? + -- delete a player from the list of those allowed to edit the NPC + elseif(fields.delete_may_edit and fields.delete_may_edit ~= "" + and fields.list_may_edit and fields.list_may_edit ~= "") then + if(pname ~= yl_speak_up.npc_owner[ n_id ]) then + error_msg = "Only the owner of the NPC\ncan change this." + elseif(not(dialog)) then + error_msg = "Please set a name for your NPC first!" + else + -- actually delete the player from the list + dialog.n_may_edit[ fields.list_may_edit ] = nil + -- show the next entry + yl_speak_up.speak_to[pname].tmp_index = math.max(1, + yl_speak_up.speak_to[pname].tmp_index-1) + end + -- add a player who may edit this NPC + elseif(fields.add_may_edit and fields.add_may_edit ~= "") then + if(pname ~= yl_speak_up.npc_owner[ n_id ]) then + error_msg = "Only the owner of the NPC\ncan change this." + elseif(fields.add_may_edit == pname) then + error_msg = "You are already the owner of this NPC!\nNo need to add you extra here." + elseif(not(minetest.check_player_privs(fields.add_may_edit, {interact=true}))) then + error_msg = "Player \""..minetest.formspec_escape(fields.add_may_edit).. + "\" not found." + elseif(not(dialog)) then + error_msg = "Please set a name for the NPC first!" + else + if(not(dialog.n_may_edit)) then + dialog.n_may_edit = {} + end + dialog.n_may_edit[ fields.add_may_edit ] = true + -- jump to the index with this player so that the player sees that he has been added + local tmp_list = yl_speak_up.sort_keys(dialog.n_may_edit, true) + local index = table.indexof(tmp_list, fields.add_may_edit) + if(index and index > 0) then + -- "Add player:" is added before all other names, so +1 + yl_speak_up.speak_to[pname].tmp_index = index + 1 + end + end + -- selected a player name in the why may edit this NPC dropdown? + elseif(fields.list_may_edit and fields.list_may_edit ~= "") then + local tmp_list = yl_speak_up.sort_keys(dialog.n_may_edit, true) + local index = table.indexof(tmp_list, fields.list_may_edit) + if(fields.list_may_edit == "Add player:") then + index = 0 + end + if(index and index > -1) then + yl_speak_up.speak_to[pname].tmp_index = index + 1 + end end if(error_msg) then yl_speak_up.show_fs(player, "msg", { input_to = "yl_speak_up:initial_config", @@ -65,7 +120,6 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) return end - local dialog = yl_speak_up.speak_to[pname].dialog local d_id = yl_speak_up.speak_to[pname].d_id local count = 0 if(dialog and dialog.n_dialogs) then @@ -102,11 +156,12 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) local dialog = yl_speak_up.fields_to_dialog(pname, f) yl_speak_up.save_dialog(n_id, dialog) yl_speak_up.speak_to[pname].dialog = dialog + dialog.n_may_edit = {} yl_speak_up.log_change(pname, n_id, "Initial config saved. ".. "NPC name: \""..tostring(fields.n_npc).. - "\" Description: \""..tostring(fields.n_description).."\"") + "\" Description: \""..tostring(fields.n_description).."\".") -- just change name and description else dialog = yl_speak_up.speak_to[pname].dialog @@ -117,7 +172,9 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) yl_speak_up.log_change(pname, n_id, "Name and/or description changed. ".. "NPC name: \""..tostring(fields.n_npc).. - "\" Description: \""..tostring(fields.n_description).."\"") + "\" Description: \""..tostring(fields.n_description).. + "\" May be edited by: \"".. + table.concat(yl_speak_up.sort_keys(dialog.n_may_edit, true), " ").."\".") end dialog = yl_speak_up.speak_to[pname].dialog @@ -138,6 +195,11 @@ yl_speak_up.input_fs_initial_config = function(player, formname, fields) end end + if(not(save_initial_config)) then + yl_speak_up.show_fs(player, "initial_config", + {n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false}) + return + end -- actually start a chat with our new npc yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id}) end @@ -159,14 +221,20 @@ yl_speak_up.get_fs_initial_config = function(player, n_id, d_id, is_initial_conf local tmp_descr = "A new NPC without description" local tmp_text = "Please provide your new NPC with a name and description!" local tmp_owner = (yl_speak_up.npc_owner[ n_id ] or "- none -") + local table_of_names = {} -- use existing name and description as presets when just editing if(not(is_initial_config)) then local dialog = yl_speak_up.speak_to[pname].dialog tmp_name = (dialog.n_npc or tmp_name) tmp_descr = (dialog.n_description or tmp_descr) tmp_text = "You can change the name and description of your NPC." + -- dialog.n_may_edit was a string for a short time in development + if(not(dialog.n_may_edit) or type(dialog.n_may_edit) ~= "table") then + dialog.n_may_edit = {} + end + table_of_names = dialog.n_may_edit end - local formspec = "size[10,5]".. + local formspec = "size[10,6]".. "label[0.2,0.2;"..tmp_text.."]".. -- name of the npc "label[0.2,1.05;Name:]".. @@ -181,10 +249,21 @@ yl_speak_up.get_fs_initial_config = function(player, n_id, d_id, is_initial_conf "field[2.0,3.2;8,0.9;n_owner;;"..minetest.formspec_escape(tmp_owner).."]".. "tooltip[n_owner;The owner of the NPC. This can only be changed\n".. "if you have the npc_talk_master priv.;#FFFFFF;#000000]".. + -- who can edit this NPC? + "label[0.2,4.05;May be edited by:]".. + -- offer a dropdown list and a text input field for player names for adding + yl_speak_up.create_dropdown_playerlist(player, pname, + table_of_names, yl_speak_up.speak_to[pname].tmp_index, + 2.5, 3.9, "list_may_edit", + "add_may_edit", "edit your NPC.\n".. + "The player needs at least the npc_talk_owner priv\n".. + "in order to actually edit the NPC.", + "delete_may_edit", + "edit your NPC." + ).. -- save and exit buttons - "button_exit[3.2,4.2;2,0.9;save_initial_config;Save]".. - "button_exit[5.4,4.2;2,0.9;exit;Exit]" + "button_exit[3.2,5.2;2,0.9;save_initial_config;Save]".. + "button_exit[5.4,5.2;2,0.9;exit;Exit]" -- show the formspec to the player return formspec end - diff --git a/functions.lua b/functions.lua index eb679df..b895152 100644 --- a/functions.lua +++ b/functions.lua @@ -1037,16 +1037,21 @@ end -- simple sort of keys of a table numericly; -- this is not efficient - but that doesn't matter: the lists are small and -- it is only executed when configuring an NPC -yl_speak_up.sort_keys = function(t) +-- simple: if the parameter is true, the keys will just be sorted (i.e. player names) - which is +-- not enough for d_, o_ etc. (which need more care when sorting) +yl_speak_up.sort_keys = function(t, simple) local keys = {} for k, v in pairs(t) do -- add a prefix so that p_2 ends up before p_10 - if(string.len(k) == 3) then + if(not(simple) and string.len(k) == 3) then k = "a"..k end table.insert(keys, k) end table.sort(keys) + if(simple) then + return keys + end for i,k in ipairs(keys) do -- avoid cutting the single a from a_1 (action 1) if(k and string.sub(k, 1, 1) == "a" and string.sub(k, 2, 2) ~= "_") then @@ -1830,6 +1835,13 @@ function yl_speak_up.talk(self, clicker) yl_speak_up.speak_to[pname].option_index = 1 yl_speak_up.speak_to[pname].obj = self.object + -- is this player explicitly allowed to edit this npc? + if(yl_speak_up.speak_to[pname].dialog + and yl_speak_up.speak_to[pname].dialog.n_may_edit + and yl_speak_up.speak_to[pname].dialog.n_may_edit[pname] ) then + yl_speak_up.speak_to[pname].may_edit_this_npc = true + end + yl_speak_up.show_fs(clicker, "talk", {n_id = n_id}) local dialog = yl_speak_up.speak_to[pname].dialog @@ -1885,10 +1897,11 @@ yl_speak_up.may_edit_npc = function(player, n_id) end local pname = player:get_player_name() -- is the player allowed to edit this npc? - return (yl_speak_up.npc_owner[ n_id ] == pname - and minetest.check_player_privs(player, {npc_talk_owner=true}) + return ((yl_speak_up.npc_owner[ n_id ] == pname + and minetest.check_player_privs(player, {npc_talk_owner=true})) or minetest.check_player_privs(player, {npc_talk_master=true}) - or minetest.check_player_privs(player, {npc_master=true})) + or minetest.check_player_privs(player, {npc_master=true}) + or yl_speak_up.speak_to[pname].may_edit_this_npc) end