introduced privs for npc

This commit is contained in:
Sokomine 2022-04-16 22:05:35 +02:00
parent 05ea4b90cc
commit ed17ea34fd
4 changed files with 176 additions and 3 deletions

View File

@ -13,6 +13,12 @@ Chat commands
/npc_talk_debug Allows to debug dialogs.
/npc_talk_privs grant, revoke or list the privs of NPC. NPC need privs for
some dangerous things like executing lua code. Examples:
/npc_talk_privs list lists the privs of all NPC
/npc_talk_privs grant n_3 effect_exec_lua
grants NPC n_3 the right to execute
lua code as an effect/result
Terminology
===========
@ -65,6 +71,20 @@ npc_master allows players to edit *any* NPC supported by this mod.
code without restrictions.
Only grant this to staff members you really trust.
NPC can have privs as well. The NPC...
precon_exec_lua ..is allowed to excecute lua code as a precondition
effect_exec_lua ..is allowed to execute lua code as an effect
effect_give_item ..can give items to the player, created out of thin air
effect_take_item ..can accept and destroy items given to it by a player
effect_move_player ..can move the player to another position
Tools
=====
There are diffrent staffs for diffrent functionality:
@ -207,6 +227,8 @@ take a look at
In order to add custom functions, you need to be able to edit that file or
execute Lua code on the server.
NPC may need extra privs for some actions.
Alternate Text
==============
Sometimes you may encounter a situation where your NPC ought to answer to

View File

@ -307,12 +307,18 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
return true
elseif(r.r_type == "function") then
-- this can only be set and edited with the staff
if(not(yl_speak_up.npc_has_priv(n_id, "effect_exec_lua"))) then
return false
end
return yl_speak_up.eval_and_execute_function(player, r, "r_")
-- this can only be set and edited with the staff
elseif(r.r_type == "give_item") then
if(not(r.r_value)) then
return false
end
if(not(yl_speak_up.npc_has_priv(n_id, "effect_give_item"))) then
return false
end
local item = ItemStack(r.r_value)
if(not(minetest.registered_items[item:get_name()])) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
@ -328,6 +334,9 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
return true
-- this can only be set and edited with the staff
elseif(r.r_type == "take_item") then
if(not(yl_speak_up.npc_has_priv(n_id, "effect_take_item"))) then
return false
end
if(not(r.r_value)) then
return false
end
@ -346,6 +355,9 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
return true
-- this can only be set and edited with the staff
elseif(r.r_type == "move") then
if(not(yl_speak_up.npc_has_priv(n_id, "effect_move_player"))) then
return false
end
-- copeid/moved here from AliasAlreadyTakens code in functions.lua
local target_pos = nil
local target_pos_valid = false

View File

@ -87,6 +87,9 @@ yl_speak_up.eval_precondition = function(player, n_id, p, other_options_true_or_
-- a precondition set by using the staff; kept for compatibility
return true
elseif(p.p_type == "function") then
if(not(yl_speak_up.npc_has_priv(n_id, "precon_exec_lua"))) then
return false
end
-- a precondition set by using the staff;
-- extremly powerful (executes any lua code)
return yl_speak_up.eval_and_execute_function(player, p, "p_")

142
privs.lua
View File

@ -1,23 +1,159 @@
-- 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[<npc_name>][<priv_name>] = 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",
}
yl_speak_up.npc_has_priv = function(n_id, priv_name)
-- fallback: disallow
if(not(n_id) or not(priv_name)) then
return false
end
if(not(yl_speak_up.npc_priv_table[n_id])
or not(yl_speak_up.npc_priv_table[n_id][priv_name])) then
minetest.log(
"action",
"[MOD] yl_speak_up: NPC with ID "..tostring(n_id)..
" was denied the NPC 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
-- 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 <priv> to the "..
"yl_speak_up-NPC with the ID <n_id>.\n"..
"Call: [grant|revoke] <n_id> <priv>\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_id> <priv>\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 "..
"<npc_name>: <list of privs>"
-- 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.." <none>"
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] <n_id> <priv>")
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.." <none>"
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()