From d23335e6dbc7d867b6d5c510820a58489d015811 Mon Sep 17 00:00:00 2001 From: Sokomine Date: Wed, 14 Sep 2022 21:54:25 +0200 Subject: [PATCH] moved all minetest.register_on_* calls into register_once.lua and removed obsolete *.lua files --- add_generic_dialogs.lua | 59 ++++++++++++ command_npc_talk_debug.lua | 75 --------------- command_npc_talk_generic.lua | 63 ------------- command_npc_talk_privs.lua | 75 --------------- command_npc_talk_style.lua | 35 ------- fs_decorated.lua | 32 ++++++- functions.lua | 12 --- init.lua | 30 +++--- inventory.lua | 2 +- npc_privs.lua | 143 +++++++++++++++++++++++++++++ npc_talk_debug.lua | 74 +++++++++++++++ privs.lua | 98 -------------------- register_node_punch.lua | 16 ---- register_once.lua | 171 +++++++++++++++++++++++++++++++++++ show_fs.lua | 5 +- trade_simple.lua | 5 +- 16 files changed, 498 insertions(+), 397 deletions(-) delete mode 100644 command_npc_talk_debug.lua delete mode 100644 command_npc_talk_generic.lua delete mode 100644 command_npc_talk_privs.lua delete mode 100644 command_npc_talk_style.lua create mode 100644 npc_privs.lua create mode 100644 npc_talk_debug.lua delete mode 100644 privs.lua delete mode 100644 register_node_punch.lua create mode 100644 register_once.lua diff --git a/add_generic_dialogs.lua b/add_generic_dialogs.lua index b29b530..db25526 100644 --- a/add_generic_dialogs.lua +++ b/add_generic_dialogs.lua @@ -11,6 +11,65 @@ yl_speak_up.generic_dialog_conditions = {} -- dialogs that follow this start dialog are stored in dialog -- "d_generic_start_dialog" + +-- a chat command to grant or deny or disallow npc these privs; +-- it is not checked if the NPC exists +-- used by register_once.lua +yl_speak_up.command_npc_talk_generic = function(pname, param) + if(not(param) or param == "") then + minetest.chat_send_player(pname, "Usage: [list|add|remove|reload] ") + return + end + local parts = string.split(param, " ") + local s = yl_speak_up.modstorage:get_string("generic_npc_list") or "" + local generic_npc_list = string.split(s, " ") + if((parts[1] == "add" or parts[1] == "remove") and #parts == 2) then + local do_reload = false + local i = table.indexof(generic_npc_list, parts[2]) + if(parts[1] == "add" and i == -1) then + local n_id = parts[2] + table.insert(generic_npc_list, n_id) + local dialog = yl_speak_up.load_dialog(n_id, false) + local res = yl_speak_up.check_and_add_as_generic_dialog(dialog, n_id) + minetest.chat_send_player(pname, "Adding NPC "..tostring(n_id).."..: "..tostring(res)) + do_reload = true + elseif(parts[1] == "add" and i ~= -1) then + minetest.chat_send_player(pname, "NPC "..tostring(parts[2]).. + " is already registered as a generic NPC. You may try to ".. + "remove and add it again if something went wrong.") + elseif(parts[1] == "remove" and i ~= -1) then + table.remove(generic_npc_list, i) + minetest.chat_send_player(pname, "Removing NPC "..tostring(parts[2]).." ..") + do_reload = true + yl_speak_up.generic_dialogs[parts[2]] = nil + yl_speak_up.generic_dialog_conditions[parts[2]] = nil + elseif(parts[1] == "reload") then + do_reload = true + end + -- actually reload the NPC list + if(do_reload) then + -- store the updated version + yl_speak_up.modstorage:set_string("generic_npc_list", + table.concat(generic_npc_list, " ")) + yl_speak_up.load_generic_dialogs() + end + elseif(parts[1] ~= "list" and parts[1] ~= "reload") then + minetest.chat_send_player(pname, "Usage: [list|add|remove|reload] ") + return + end + local liste = {} + for n_id, v in pairs(yl_speak_up.generic_dialogs) do + table.insert(liste, n_id) + end + if(#liste < 1) then + minetest.chat_send_player(pname, "No NPC provides generic dialogs.") + else + minetest.chat_send_player(pname, "These NPC provide generic dialogs: ".. + table.concat(liste, ", ")..".") + end +end + + -- this is similar to the function -- yl_speak_up.calculate_displayable_options -- in exec_eval_preconditions.lua diff --git a/command_npc_talk_debug.lua b/command_npc_talk_debug.lua deleted file mode 100644 index a86899c..0000000 --- a/command_npc_talk_debug.lua +++ /dev/null @@ -1,75 +0,0 @@ - - --- store which player is monitoring the NPC (for preconditions and --- effects) -yl_speak_up.debug_mode_set_by_player = {} - --- for sending debug information about preconditions and effects to --- the player who is monitoring the NPC --- (sometimes it is not easy/obvious to see why something failed) -yl_speak_up.debug_msg = function(player, n_id, o_id, text) - local dname = yl_speak_up.debug_mode_set_by_player[ n_id ] - -- nobody cares - if(not(dname)) then - return - end - local pname = player:get_player_name() - local d_id = yl_speak_up.speak_to[pname].d_id - minetest.chat_send_player(dname, "[NPC "..tostring(n_id)..": ".. - tostring(pname).."] <"..tostring(d_id).." "..tostring(o_id).. - "> "..tostring(text)) -end - - --- a chat command for entering and leaving debug mode; needs to be a chat command --- because the player may have wandered off from his NPC and get too many messages --- without a quick way to get rid of them otherwise -minetest.register_chatcommand( 'npc_talk_debug', { - description = "Sets you as debugger for the yl_speak_up-NPC with the ID .\n".. - " lists the NPC you are currently debugging.\n".. - " turns debug mode off again.", - privs = {npc_talk_owner = true}, - func = function(pname, param) - if(param and param == "off") then - local count = 0 - for k, v in pairs(yl_speak_up.debug_mode_set_by_player) do - if(v and v == pname) then - yl_speak_up.debug_mode_set_by_player[ k ] = nil - count = count + 1 - minetest.chat_send_player(pname, "You are no longer ".. - "debugging the NPC with the ID "..tostring(k)..".") - end - end - minetest.chat_send_player(pname, "Removed you as debugger of ".. - tostring(count).." NPCs.") - return - elseif(not(param) or param == "" or param == "list") then - local count = 0 - local text = "You are currently debugging the NPCs with the following IDs:\n" - for k, v in pairs(yl_speak_up.debug_mode_set_by_player) do - if(v and v == pname) then - count = count + 1 - text = text.." "..tostring(k) - end - end - if(count == 0) then - text = text.." - none -" - else - text = text.."\nTo turn debugging off, call this command with the ".. - "parameter ." - end - minetest.chat_send_player(pname, text) - return - elseif(not(yl_speak_up.may_edit_npc(minetest.get_player_by_name(pname), param))) then - minetest.chat_send_player(pname, "You do not have the necessary privs to ".. - "edit that NPC.") - return - else - yl_speak_up.debug_mode_set_by_player[ param ] = pname - minetest.chat_send_player(pname, "You are now receiving debug information ".. - "for NPC "..tostring(param)..".\nTo turn that off, type ".. - "\"/npc_talk_debug off\".") - end - end -}); - diff --git a/command_npc_talk_generic.lua b/command_npc_talk_generic.lua deleted file mode 100644 index 1deffa8..0000000 --- a/command_npc_talk_generic.lua +++ /dev/null @@ -1,63 +0,0 @@ --- this is used by add_generic_dialogs.lua - --- a chat command to grant or deny or disallow npc these privs; --- it is not checked if the NPC exists -minetest.register_chatcommand( 'npc_talk_generic', { - description = "Lists, add or removes the dialogs of NPC as generic dialogs.\n".. - "Call: [list|add|remove|reload] []", - privs = {privs = true}, - func = function(pname, param) - if(not(param) or param == "") then - minetest.chat_send_player(pname, "Usage: [list|add|remove|reload] ") - return - end - local parts = string.split(param, " ") - local s = yl_speak_up.modstorage:get_string("generic_npc_list") or "" - local generic_npc_list = string.split(s, " ") - if((parts[1] == "add" or parts[1] == "remove") and #parts == 2) then - local do_reload = false - local i = table.indexof(generic_npc_list, parts[2]) - if(parts[1] == "add" and i == -1) then - local n_id = parts[2] - table.insert(generic_npc_list, n_id) - local dialog = yl_speak_up.load_dialog(n_id, false) - local res = yl_speak_up.check_and_add_as_generic_dialog(dialog, n_id) - minetest.chat_send_player(pname, "Adding NPC "..tostring(n_id).."..: "..tostring(res)) - do_reload = true - elseif(parts[1] == "add" and i ~= -1) then - minetest.chat_send_player(pname, "NPC "..tostring(parts[2]).. - " is already registered as a generic NPC. You may try to ".. - "remove and add it again if something went wrong.") - elseif(parts[1] == "remove" and i ~= -1) then - table.remove(generic_npc_list, i) - minetest.chat_send_player(pname, "Removing NPC "..tostring(parts[2]).." ..") - do_reload = true - yl_speak_up.generic_dialogs[parts[2]] = nil - yl_speak_up.generic_dialog_conditions[parts[2]] = nil - elseif(parts[1] == "reload") then - do_reload = true - end - -- actually reload the NPC list - if(do_reload) then - -- store the updated version - yl_speak_up.modstorage:set_string("generic_npc_list", - table.concat(generic_npc_list, " ")) - yl_speak_up.load_generic_dialogs() - end - elseif(parts[1] ~= "list" and parts[1] ~= "reload") then - minetest.chat_send_player(pname, "Usage: [list|add|remove|reload] ") - return - end - local liste = {} - for n_id, v in pairs(yl_speak_up.generic_dialogs) do - table.insert(liste, n_id) - end - if(#liste < 1) then - minetest.chat_send_player(pname, "No NPC provides generic dialogs.") - else - minetest.chat_send_player(pname, "These NPC provide generic dialogs: ".. - table.concat(liste, ", ")..".") - end - return - end -}) diff --git a/command_npc_talk_privs.lua b/command_npc_talk_privs.lua deleted file mode 100644 index d184da5..0000000 --- a/command_npc_talk_privs.lua +++ /dev/null @@ -1,75 +0,0 @@ --- used by privs.lua - --- a chat command to grant or deny or disallow npc these privs; --- it is not checked if the NPC exists -minetest.register_chatcommand( 'npc_talk_privs', { - description = "Grants or revokes the privilege to the ".. - "yl_speak_up-NPC with the ID .\n".. - "Call: [grant|revoke] \n".. - "If called with parameter [list], all granted privs for all NPC are shown.", - privs = {privs = true}, - func = function(pname, param) - if(not(param) or param == "") then - minetest.chat_send_player(pname, - "Usage: [grant|revoke|list] \n".. - "The following privilege exist:\n\t".. - table.concat(yl_speak_up.npc_priv_names, ", ")..".") - return - end - local parts = string.split(param, " ") - if(parts[1] == "list") then - local text = "This list contains the privs of each NPC in the form of ".. - ": " - -- create list of all existing extra privs for npc - for n_id, v in pairs(yl_speak_up.npc_priv_table) do - text = text..".\n"..tostring(n_id)..":" - local found = false - for priv, w in pairs(v) do - text = text.." "..tostring(priv) - found = true - end - if(not(found)) then - text = text.." " - end - end - minetest.chat_send_player(pname, text..".") - return - end - if((parts[1] ~= "grant" and parts[1] ~= "revoke") or #parts ~= 3) then - minetest.chat_send_player(pname, "Usage: [grant|revoke] ") - return - end - local command = parts[1] - local n_id = parts[2] - local priv = parts[3] - if(table.indexof(yl_speak_up.npc_priv_names, priv) == -1) then - minetest.chat_send_player(pname, - "Unknown priv \""..tostring(priv).."\".\n".. - "The following privilege exist:\n\t".. - table.concat(yl_speak_up.npc_priv_names, ", ")..".") - return - end - if(command == "grant" and not(yl_speak_up.npc_priv_table[n_id])) then - yl_speak_up.npc_priv_table[n_id] = {} - end - if(command == "grant") then - yl_speak_up.npc_priv_table[n_id][priv] = true - elseif(yl_speak_up.npc_priv_table[n_id]) then - yl_speak_up.npc_priv_table[n_id][priv] = nil - end - local text = "New privs of NPC "..tostring(n_id)..":" - local found = false - if(yl_speak_up.npc_priv_table[n_id]) then - for k, v in pairs(yl_speak_up.npc_priv_table[n_id]) do - text = text.." "..tostring(k) - found = true - end - end - if(not(found)) then - text = text.." " - yl_speak_up.npc_priv_table[n_id] = nil - end - minetest.chat_send_player(pname, text..".") - yl_speak_up.npc_privs_store() - end -}) diff --git a/command_npc_talk_style.lua b/command_npc_talk_style.lua deleted file mode 100644 index eaf11e8..0000000 --- a/command_npc_talk_style.lua +++ /dev/null @@ -1,35 +0,0 @@ --- change the formspec style used in fs_decorated.lua - --- because the player may have wandered off from his NPC and get too many messages --- without a quick way to get rid of them otherwise -minetest.register_chatcommand( 'npc_talk_style', { - description = "This command sets your formspec version ".. - "for the yl_speak_up NPC to value .\n".. - " Version 1: For very old clients. Not recommended.\n".. - " Version 2: Adds extra scroll buttons. Perhaps you like this more.\n".. - " Version 3: Default version.", - privs = {}, - func = function(pname, param) - -- set a default value - if(not(yl_speak_up.fs_version[pname])) then - yl_speak_up.fs_version[pname] = 3 - end - if(param and param == "1") then - yl_speak_up.fs_version[pname] = 1 - elseif(param and param == "2") then - yl_speak_up.fs_version[pname] = 2 - elseif(param and param == "3") then - yl_speak_up.fs_version[pname] = 3 - else - minetest.chat_send_player(pname, "This command sets your formspec version ".. - "for the yl_speak_up NPC to value .\n".. - " Version 1: For very old clients. Not recommended.\n".. - " Version 2: Adds extra scroll buttons.\n".. - " Version 3: Default (recommended) version.") - end - minetest.chat_send_player(pname, "Your formspec version for the yl_speak_up NPC ".. - "has been set to version "..tostring(yl_speak_up.fs_version[pname]).. - " for this session.") - end - }) - diff --git a/fs_decorated.lua b/fs_decorated.lua index 4303dd9..7f575ca 100644 --- a/fs_decorated.lua +++ b/fs_decorated.lua @@ -1,8 +1,38 @@ -- the formspec menu used for talking to the NPC can also used for -- the trading formspec and similar things --- the chat command npc_talk_style found in command_npc_talk_style.lua +-- the chat command npc_talk_style defined in register_once.lua -- can be used to switch formspec style. +-- change the formspec style used in fs_decorated.lua; +--minetest.register_chatcommand( 'npc_talk_style', { +-- description = "This command sets your formspec version ".. +-- "for the yl_speak_up NPC to value .\n".. +-- " Version 1: For very old clients. Not recommended.\n".. +-- " Version 2: Adds extra scroll buttons. Perhaps you like this more.\n".. +-- " Version 3: Default version.", +-- privs = {}, +yl_speak_up.command_npc_talk_style = function(pname, param) + -- set a default value + if(not(yl_speak_up.fs_version[pname])) then + yl_speak_up.fs_version[pname] = 3 + end + if(param and param == "1") then + yl_speak_up.fs_version[pname] = 1 + elseif(param and param == "2") then + yl_speak_up.fs_version[pname] = 2 + elseif(param and param == "3") then + yl_speak_up.fs_version[pname] = 3 + else + minetest.chat_send_player(pname, "This command sets your formspec version ".. + "for the yl_speak_up NPC to value .\n".. + " Version 1: For very old clients. Not recommended.\n".. + " Version 2: Adds extra scroll buttons.\n".. + " Version 3: Default (recommended) version.") + end + minetest.chat_send_player(pname, "Your formspec version for the yl_speak_up NPC ".. + "has been set to version "..tostring(yl_speak_up.fs_version[pname]).. + " for this session.") +end -- helper function for yl_speak_up.show_fs_decorated diff --git a/functions.lua b/functions.lua index 6b26863..8b29a69 100644 --- a/functions.lua +++ b/functions.lua @@ -41,18 +41,6 @@ yl_speak_up.reset_vars_for_player = function(pname, reset_fs_version) end end -minetest.register_on_leaveplayer( - function(player) - yl_speak_up.reset_vars_for_player(player:get_player_name(), true) - end -) - -minetest.register_on_joinplayer( - function(player) - yl_speak_up.reset_vars_for_player(player:get_player_name(), true) - end -) - --### -- Debug --### diff --git a/init.lua b/init.lua index 0e6c096..c94f3d2 100644 --- a/init.lua +++ b/init.lua @@ -10,9 +10,12 @@ yl_speak_up.modstorage = minetest.get_mod_storage() -- 0: NPCs may speak -- 1: NPCs may not speak -- 2: NPCs must selfdestruct on load. Their dialogs remain safed - yl_speak_up.status = yl_speak_up.modstorage:get_int("status") or 0 + +-- needed for assigning individual IDs (n_id) to NPC yl_speak_up.number_of_npcs = yl_speak_up.modstorage:get_int("amount") or 0 + +-- which player (key) is talking to which NPC? yl_speak_up.speak_to = {} -- allow to request the highest possible version number for formspec_version @@ -30,20 +33,14 @@ yl_speak_up.custom_server_functions = {} dofile(modpath .. "config.lua") -- logging and showing the log dofile(modpath .. "fs_show_log.lua") --- players *and* npc need privs for certain things -dofile(modpath .. "privs.lua") --- contains the command to hand out privs to NPC -dofile(modpath .. "command_npc_talk_privs.lua") +-- players *and* npc need privs for certain things; this here handles the NPC side of things +dofile(modpath .. "npc_privs.lua") -- add generic dialogs dofile(modpath .. "add_generic_dialogs.lua") --- the actual command to add or remove generic npc dialogs -dofile(modpath .. "command_npc_talk_generic.lua") -- handle on_player_receive_fields and showing of formspecs dofile(modpath .. "show_fs.lua") -- general decoration part for main formspec, trade window etc. dofile(modpath .. "fs_decorated.lua") --- command for switching the formspec version of the player -dofile(modpath .. "command_npc_talk_style.lua") -- the formspec and input handling for the main dialog dofile(modpath .. "fs_talkdialog.lua") -- ask if the player wants to save, discard or go back in edit mode @@ -66,8 +63,8 @@ dofile(modpath .. "print_as_table.lua") dofile(modpath .. "formspec_helpers.lua") -- handle alternate text for dialogs dofile(modpath .. "fs_alternate_text.lua") --- implementation of chat command npc_talk_debug: -dofile(modpath .. "command_npc_talk_debug.lua") +-- debugging - extended information about what (your own) NPC does +dofile(modpath .. "npc_talk_debug.lua") -- execute lua code directly (preconditions and effects) - requires priv dofile(modpath .. "eval_and_execute_function.lua") -- common functions for editing preconditions and effects @@ -103,10 +100,6 @@ dofile(modpath .. "fs_show_all_var_values.lua") dofile(modpath .. "fs_manage_variables.lua") -- handle variables for quests for player-owned NPC dofile(modpath .. "quest_api.lua") --- editing the npc with the staff: -if(yl_speak_up.enable_staff_based_editing) then - dofile(modpath .. "staff_based_editing.lua") -end -- setting skin, wielded item etc. dofile(modpath .. "fs_fashion.lua") -- properties for NPC without specific dialogs that want to make use of @@ -114,10 +107,11 @@ dofile(modpath .. "fs_fashion.lua") dofile(modpath .. "fs_properties.lua") -- the main functionality of the mod dofile(modpath .. "functions.lua") --- a way of determining a node position -dofile(modpath .. "register_node_punch.lua") -- the staffs (requires npc_master priv) if(yl_speak_up.enable_staff_based_editing) then + -- editing the npc with the staff: + dofile(modpath .. "staff_based_editing.lua") + -- defining the staffs: dofile(modpath .. "tools.lua") end -- mobs registered as yl_speak_up-mobs (based on mobs_redo) @@ -128,11 +122,13 @@ if(yl_speak_up.enable_yl_mobs) then dofile(modpath .. "mobs.lua") end --dofile(modpath .. "debug.lua") +dofile(modpath .. "register_once.lua") minetest.mkdir(yl_speak_up.worldpath..yl_speak_up.path) minetest.mkdir(yl_speak_up.worldpath..yl_speak_up.inventory_path) minetest.mkdir(yl_speak_up.worldpath..yl_speak_up.log_path) + yl_speak_up.mob_table = yl_speak_up.init_mob_table() or {} -- initialize and load all registered generic dialogs diff --git a/inventory.lua b/inventory.lua index c8d6fae..39f230b 100644 --- a/inventory.lua +++ b/inventory.lua @@ -113,7 +113,7 @@ end -- helper function for yl_speak_up.load_npc_inventory and --- minetest.register_on_joinplayer +-- for yl_speak_up.player_joined_add_trade_inv yl_speak_up.inventory_allow_item = function(player, stack, input_to) if(not(player) or not(stack) or not(input_to)) then return 0 diff --git a/npc_privs.lua b/npc_privs.lua new file mode 100644 index 0000000..b0cdf93 --- /dev/null +++ b/npc_privs.lua @@ -0,0 +1,143 @@ +-- NPC also need privs to execute more dangerous commands + +-- this table will hold the actual privs in the form of +-- indices of the form t[][] = True +yl_speak_up.npc_priv_table = {} + +-- where shall the privs be stored so that they will be available after server restart? +yl_speak_up.npc_priv_path = minetest.get_worldpath().."/yl_speak_up_npc_privs.data" + +-- these are deemed dangerous and checked +yl_speak_up.npc_priv_names = { + "precon_exec_lua", + "effect_exec_lua", "effect_give_item", "effect_take_item", "effect_move_player", +} + +-- either the npc with n_id *or* if generic_npc_id is set the generic npc with the +-- id generic_npc_id needs to have been granted priv_name +yl_speak_up.npc_has_priv = function(n_id, priv_name, generic_npc_id) + -- fallback: disallow + if(not(n_id) or not(priv_name)) then + return false + end + -- remove the leading "_" from the n_id: + if(generic_npc_id) then + generic_npc_id = string.sub(generic_npc_id, 2) + end + -- if the precondition or effect come from a generic_npc and that + -- generic npc has the desired priv, then the priv has been granted + if(generic_npc_id + and yl_speak_up.npc_priv_table[generic_npc_id] + and yl_speak_up.npc_priv_table[generic_npc_id][priv_name]) then + return true + end + if(not(yl_speak_up.npc_priv_table[n_id]) + or not(yl_speak_up.npc_priv_table[n_id][priv_name])) then + yl_speak_up.log_change("-", n_id, + "error: NPC was denied priv priv "..tostring(priv_name)..".") + return false + end + return true +end + + +yl_speak_up.npc_privs_load = function() + local file,err = io.open( yl_speak_up.npc_priv_path, "rb") + if (file == nil) then + yl_speak_up.npc_priv_table = {} + return + end + local data = file:read("*all") + file:close() + yl_speak_up.npc_priv_table = minetest.deserialize(data) +end + + +yl_speak_up.npc_privs_store = function() + local file,err = io.open( yl_speak_up.npc_priv_path, "wb") + if (file == nil) then + return + end + file:write(minetest.serialize(yl_speak_up.npc_priv_table)) + file:close() +end + + +-- the privs for NPC can be set via the chat command defined in register_once.lua; +-- here is the implementation for that chat command: +-- a chat command to grant or deny or disallow npc these privs; +-- it is not checked if the NPC exists +--minetest.register_chatcommand( 'npc_talk_privs', { +-- description = "Grants or revokes the privilege to the ".. +-- "yl_speak_up-NPC with the ID .\n".. +-- "Call: [grant|revoke] \n".. +-- "If called with parameter [list], all granted privs for all NPC are shown.", +-- privs = {privs = true}, +yl_speak_up.command_npc_talk_privs = function(pname, param) + if(not(param) or param == "") then + minetest.chat_send_player(pname, + "Usage: [grant|revoke|list] \n".. + "The following privilege exist:\n\t".. + table.concat(yl_speak_up.npc_priv_names, ", ")..".") + return + end + local parts = string.split(param, " ") + if(parts[1] == "list") then + local text = "This list contains the privs of each NPC in the form of ".. + ": " + -- create list of all existing extra privs for npc + for n_id, v in pairs(yl_speak_up.npc_priv_table) do + text = text..".\n"..tostring(n_id)..":" + local found = false + for priv, w in pairs(v) do + text = text.." "..tostring(priv) + found = true + end + if(not(found)) then + text = text.." " + end + end + minetest.chat_send_player(pname, text..".") + return + end + if((parts[1] ~= "grant" and parts[1] ~= "revoke") or #parts ~= 3) then + minetest.chat_send_player(pname, "Usage: [grant|revoke] ") + return + end + local command = parts[1] + local n_id = parts[2] + local priv = parts[3] + if(table.indexof(yl_speak_up.npc_priv_names, priv) == -1) then + minetest.chat_send_player(pname, + "Unknown priv \""..tostring(priv).."\".\n".. + "The following privilege exist:\n\t".. + table.concat(yl_speak_up.npc_priv_names, ", ")..".") + return + end + if(command == "grant" and not(yl_speak_up.npc_priv_table[n_id])) then + yl_speak_up.npc_priv_table[n_id] = {} + end + if(command == "grant") then + yl_speak_up.npc_priv_table[n_id][priv] = true + elseif(yl_speak_up.npc_priv_table[n_id]) then + yl_speak_up.npc_priv_table[n_id][priv] = nil + end + local text = "New privs of NPC "..tostring(n_id)..":" + local found = false + if(yl_speak_up.npc_priv_table[n_id]) then + for k, v in pairs(yl_speak_up.npc_priv_table[n_id]) do + text = text.." "..tostring(k) + found = true + end + end + if(not(found)) then + text = text.." " + yl_speak_up.npc_priv_table[n_id] = nil + end + minetest.chat_send_player(pname, text..".") + yl_speak_up.npc_privs_store() +end + +-- when the game is started: load the npc privs +yl_speak_up.npc_privs_load() + diff --git a/npc_talk_debug.lua b/npc_talk_debug.lua new file mode 100644 index 0000000..954f386 --- /dev/null +++ b/npc_talk_debug.lua @@ -0,0 +1,74 @@ + + +-- store which player is monitoring the NPC (for preconditions and +-- effects) +yl_speak_up.debug_mode_set_by_player = {} + +-- for sending debug information about preconditions and effects to +-- the player who is monitoring the NPC +-- (sometimes it is not easy/obvious to see why something failed) +yl_speak_up.debug_msg = function(player, n_id, o_id, text) + local dname = yl_speak_up.debug_mode_set_by_player[ n_id ] + -- nobody cares + if(not(dname)) then + return + end + local pname = player:get_player_name() + local d_id = yl_speak_up.speak_to[pname].d_id + minetest.chat_send_player(dname, "[NPC "..tostring(n_id)..": ".. + tostring(pname).."] <"..tostring(d_id).." "..tostring(o_id).. + "> "..tostring(text)) +end + + +-- a chat command for entering and leaving debug mode; needs to be a chat command +-- because the player may have wandered off from his NPC and get too many messages +-- without a quick way to get rid of them otherwise +-- registered in register_once.lua +--minetest.register_chatcommand( 'npc_talk_debug', { +-- description = "Sets you as debugger for the yl_speak_up-NPC with the ID .\n".. +-- " lists the NPC you are currently debugging.\n".. +-- " turns debug mode off again.", +-- privs = {npc_talk_owner = true}, +yl_speak_up.command_npc_talk_debug = function(pname, param) + if(param and param == "off") then + local count = 0 + for k, v in pairs(yl_speak_up.debug_mode_set_by_player) do + if(v and v == pname) then + yl_speak_up.debug_mode_set_by_player[ k ] = nil + count = count + 1 + minetest.chat_send_player(pname, "You are no longer ".. + "debugging the NPC with the ID "..tostring(k)..".") + end + end + minetest.chat_send_player(pname, "Removed you as debugger of ".. + tostring(count).." NPCs.") + return + elseif(not(param) or param == "" or param == "list") then + local count = 0 + local text = "You are currently debugging the NPCs with the following IDs:\n" + for k, v in pairs(yl_speak_up.debug_mode_set_by_player) do + if(v and v == pname) then + count = count + 1 + text = text.." "..tostring(k) + end + end + if(count == 0) then + text = text.." - none -" + else + text = text.."\nTo turn debugging off, call this command with the ".. + "parameter ." + end + minetest.chat_send_player(pname, text) + return + elseif(not(yl_speak_up.may_edit_npc(minetest.get_player_by_name(pname), param))) then + minetest.chat_send_player(pname, "You do not have the necessary privs to ".. + "edit that NPC.") + return + else + yl_speak_up.debug_mode_set_by_player[ param ] = pname + minetest.chat_send_player(pname, "You are now receiving debug information ".. + "for NPC "..tostring(param)..".\nTo turn that off, type ".. + "\"/npc_talk_debug off\".") + end +end diff --git a/privs.lua b/privs.lua deleted file mode 100644 index f8358ee..0000000 --- a/privs.lua +++ /dev/null @@ -1,98 +0,0 @@ --- the privs players need some privs --- npc_talk_owner is required to set up an NPC; --- npc_talk_master allows to edit NPC of other players; --- npc_master allows to set dangerous commands like execute lua code - -local npc_master_priv_definition = { - description="Can use the staffs to command NPCs", - give_to_singleplayer = false, - give_to_admin = true, -} -minetest.register_privilege("npc_master", npc_master_priv_definition) - - -local npc_talk_owner_priv_definition = { - description="Can edit the dialogs of his/her own NPCs", - give_to_singleplayer = false, - give_to_admin = true, -} -minetest.register_privilege("npc_talk_owner", npc_talk_owner_priv_definition) - - -local npc_talk_master_priv_definition = { - description="Can edit the dialogs of NPCs independent of owner", - give_to_singleplayer = false, - give_to_admin = true, -} -minetest.register_privilege("npc_talk_master", npc_talk_master_priv_definition) - - --- NPC also need privs to execute more dangerous commands - --- this table will hold the actual privs in the form of --- indices of the form t[][] = True -yl_speak_up.npc_priv_table = {} - --- where shall the privs be stored so that they will be available after server restart? -yl_speak_up.npc_priv_path = minetest.get_worldpath().."/yl_speak_up_npc_privs.data" - --- these are deemed dangerous and checked -yl_speak_up.npc_priv_names = { - "precon_exec_lua", - "effect_exec_lua", "effect_give_item", "effect_take_item", "effect_move_player", -} - --- either the npc with n_id *or* if generic_npc_id is set the generic npc with the --- id generic_npc_id needs to have been granted priv_name -yl_speak_up.npc_has_priv = function(n_id, priv_name, generic_npc_id) - -- fallback: disallow - if(not(n_id) or not(priv_name)) then - return false - end - -- remove the leading "_" from the n_id: - if(generic_npc_id) then - generic_npc_id = string.sub(generic_npc_id, 2) - end - -- if the precondition or effect come from a generic_npc and that - -- generic npc has the desired priv, then the priv has been granted - if(generic_npc_id - and yl_speak_up.npc_priv_table[generic_npc_id] - and yl_speak_up.npc_priv_table[generic_npc_id][priv_name]) then - return true - end - if(not(yl_speak_up.npc_priv_table[n_id]) - or not(yl_speak_up.npc_priv_table[n_id][priv_name])) then - yl_speak_up.log_change("-", n_id, - "error: NPC was denied priv priv "..tostring(priv_name)..".") - return false - end - return true -end - - -yl_speak_up.npc_privs_load = function() - local file,err = io.open( yl_speak_up.npc_priv_path, "rb") - if (file == nil) then - yl_speak_up.npc_priv_table = {} - return - end - local data = file:read("*all") - file:close() - yl_speak_up.npc_priv_table = minetest.deserialize(data) -end - - -yl_speak_up.npc_privs_store = function() - local file,err = io.open( yl_speak_up.npc_priv_path, "wb") - if (file == nil) then - return - end - file:write(minetest.serialize(yl_speak_up.npc_priv_table)) - file:close() -end - - --- when the game is started: load the npc privs -yl_speak_up.npc_privs_load() - --- the privs for NPC can be set via the chat command in command_npc_talk_priv.lua diff --git a/register_node_punch.lua b/register_node_punch.lua deleted file mode 100644 index f5de76f..0000000 --- a/register_node_punch.lua +++ /dev/null @@ -1,16 +0,0 @@ - --- some formspecs need a position; let the player punch the node -minetest.register_on_punchnode(function(pos, node, puncher) - local pname = puncher:get_player_name() - if(pname and pname ~= "" - and yl_speak_up.speak_to[pname] - and yl_speak_up.speak_to[pname].expect_block_punch) then - local fs_name = yl_speak_up.speak_to[pname].expect_block_punch - -- the block was punched successfully - yl_speak_up.speak_to[pname].expect_block_punch = nil - -- store *which* block has been punched - yl_speak_up.speak_to[pname].block_punched = pos - -- show the formspec again - yl_speak_up.show_fs(puncher, fs_name) - end -end) diff --git a/register_once.lua b/register_once.lua new file mode 100644 index 0000000..1f99f92 --- /dev/null +++ b/register_once.lua @@ -0,0 +1,171 @@ +----------------------------------------------------------------------------- +-- This file is for calling all the necessary minetest.register_* functions. +----------------------------------------------------------------------------- +-- These functions shall be called only *once* after the server is started +-- and the mod is loaded. +-- Other files may be reloaded on the fly - but better not this one. +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- the privs: players need some privs +----------------------------------------------------------------------------- +-- npc_talk_owner is required to set up an NPC; +-- npc_talk_master allows to edit NPC of other players; +-- npc_master allows to set dangerous commands like execute lua code + +local npc_master_priv_definition = { + description="Can use the staffs to command NPCs", + give_to_singleplayer = false, + give_to_admin = true, +} +minetest.register_privilege("npc_master", npc_master_priv_definition) + + +local npc_talk_owner_priv_definition = { + description="Can edit the dialogs of his/her own NPCs", + give_to_singleplayer = false, + give_to_admin = true, +} +minetest.register_privilege("npc_talk_owner", npc_talk_owner_priv_definition) + + +local npc_talk_master_priv_definition = { + description="Can edit the dialogs of NPCs independent of owner", + give_to_singleplayer = false, + give_to_admin = true, +} +minetest.register_privilege("npc_talk_master", npc_talk_master_priv_definition) + + +----------------------------------------------------------------------------- +-- players joining or leaving +----------------------------------------------------------------------------- +-- some variables - especially which NPC the player is talking to - need +-- to be reset when a player joins or leaves; +-- handled in functions.lua +minetest.register_on_leaveplayer( + function(player) + yl_speak_up.reset_vars_for_player(player:get_player_name(), true) + end +) + +minetest.register_on_joinplayer( + function(player) + yl_speak_up.reset_vars_for_player(player:get_player_name(), true) + end +) + + +----------------------------------------------------------------------------- +-- chat commands +----------------------------------------------------------------------------- +-- create a detached inventory for the *player* for trading with the npcs; +-- handled in trade_simple.lua +minetest.register_on_joinplayer(function(player, last_login) + return yl_speak_up.player_joined_add_trade_inv(player, last_login) +end) + + +-- react to player input in formspecs; +-- handled in show_fs.lua +minetest.register_on_player_receive_fields( function(player, formname, fields) + return yl_speak_up.input_handler(player, formname, fields) +end) + + + +-- chat commands + +-- set which NPC provides generic dialogs (=dialogs that are added to all non-generic NPC) +-- handled in add_generic_dialogs.lua +minetest.register_chatcommand( 'npc_talk_generic', { + description = "Lists, add or removes the dialogs of NPC as generic dialogs.\n".. + "Call: [list|add|remove|reload] []", + privs = {privs = true}, + func = function(pname, param) + return yl_speak_up.command_npc_talk_generic(pname, param) + end +}) + + +-- contains the command to hand out privs to NPC; +-- a chat command to grant or deny or disallow npc these privs; +-- it is not checked if the NPC exists +-- handled in npc_privs.lua +minetest.register_chatcommand( 'npc_talk_privs', { + description = "Grants or revokes the privilege to the ".. + "yl_speak_up-NPC with the ID .\n".. + "Call: [grant|revoke] \n".. + "If called with parameter [list], all granted privs for all NPC are shown.", + privs = {privs = true}, + func = function(pname, param) + return yl_speak_up.command_npc_talk_privs(pname, param) + end, +}) + + +-- a chat command for entering and leaving debug mode; needs to be a chat command +-- because the player may have wandered off from his NPC and get too many messages +-- without a quick way to get rid of them otherwise +-- handled in npc_talk_debug.lua +minetest.register_chatcommand( 'npc_talk_debug', { + description = "Sets you as debugger for the yl_speak_up-NPC with the ID .\n".. + " lists the NPC you are currently debugging.\n".. + " turns debug mode off again.", + privs = {npc_talk_owner = true}, + func = function(pname, param) + return yl_speak_up.command_npc_talk_debug(pname, param) + end, +}); + + +-- change the formspec style used in fs_decorated.lua +-- because the player may have wandered off from his NPC and get too many messages +-- without a quick way to get rid of them otherwise +-- handled in fs_decorated.lua +minetest.register_chatcommand( 'npc_talk_style', { + description = "This command sets your formspec version ".. + "for the yl_speak_up NPC to value .\n".. + " Version 1: For very old clients. Not recommended.\n".. + " Version 2: Adds extra scroll buttons. Perhaps you like this more.\n".. + " Version 3: Default version.", + privs = {}, + func = function(pname, param) + return yl_speak_up.command_npc_talk_style(pname, param) + end, +}) + + +----------------------------------------------------------------------------- +-- some node positions can be set by punching a node +----------------------------------------------------------------------------- +-- some formspecs need a position; let the player punch the node +minetest.register_on_punchnode(function(pos, node, puncher) + local pname = puncher:get_player_name() + if(pname and pname ~= "" + and yl_speak_up.speak_to[pname] + and yl_speak_up.speak_to[pname].expect_block_punch) then + local fs_name = yl_speak_up.speak_to[pname].expect_block_punch + -- the block was punched successfully + yl_speak_up.speak_to[pname].expect_block_punch = nil + -- store *which* block has been punched + yl_speak_up.speak_to[pname].block_punched = pos + -- show the formspec again + yl_speak_up.show_fs(puncher, fs_name) + end +end) + +----------------------------------------------------------------------------- +-- other register_on_* functions that might be helpful for the quest api +-- later on but which are not used yet +----------------------------------------------------------------------------- +-- TODO minetest.register_on_chat_message(function(name, message)) +-- TODO minetest.register_on_chat_message(function(name, message)) +-- TODO minetest.register_on_chatcommand(function(name, command, params)) +-- TODO minetest.register_on_player_receive_fields(function(player, formname, fields)) +-- TODO minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)) +-- TODO minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)) +-- TODO minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)) +-- +-- TODO minetest.hash_node_position(pos) (has an inverse function as well) +-- TODO minetest.global_exists(name) diff --git a/show_fs.lua b/show_fs.lua index ef2139e..e2a2f4c 100644 --- a/show_fs.lua +++ b/show_fs.lua @@ -1,7 +1,8 @@ -- route player input to the right functions; -- return true when the right function has been found -minetest.register_on_player_receive_fields( function(player, formname, fields) +-- called in minetest.register_on_player_receive_fields +yl_speak_up.input_handler = function(player, formname, fields) if formname == "yl_speak_up:optiondialog" then yl_speak_up.input_optiondialog(player, formname, fields) return true @@ -100,7 +101,7 @@ minetest.register_on_player_receive_fields( function(player, formname, fields) yl_speak_up.input_fs_show_what_points_to_this_dialog(player, formname, fields) return true end -end) +end -- show formspec with highest possible version information for the player diff --git a/trade_simple.lua b/trade_simple.lua index 33ef9cd..5767f94 100644 --- a/trade_simple.lua +++ b/trade_simple.lua @@ -850,7 +850,8 @@ end -- create a detached inventory for the *player* for trading with the npcs -minetest.register_on_joinplayer(function(player, last_login) +-- (called in minetest.register_on_joinplayer) +yl_speak_up.player_joined_add_trade_inv = function(player, last_login) local pname = player:get_player_name() -- create the detached inventory; @@ -947,4 +948,4 @@ minetest.register_on_joinplayer(function(player, last_login) trade_inv:set_size("npc_wants", 1) -- for setting wielded items (left and right) trade_inv:set_size("wield", 2) -end) +end