added npc_force_restore command for lost npc
This commit is contained in:
parent
0585dd4b77
commit
b9c8e3c345
@ -79,6 +79,14 @@ and set its name).
|
||||
NPC, the priv will be considered granted if either the
|
||||
executing NPC or the the generic NPC has the priv.
|
||||
|
||||
#### `/npc_talk force_restore_npc <id> [<copy_from_id>]` Restore an NPC that got lost.
|
||||
It may have got lost due to someone having misplaced its egg.
|
||||
Or it might have been killed somehow.
|
||||
The optional parameter `<copy_from_id>` is only used when the NPC
|
||||
is *not* listed in `/npc_talk list`. You won't need it. It's for legacy NPC.
|
||||
WARNING: If the egg or the NPC turns up elsewhere, be sure to have only
|
||||
*ONE* NPC with that ID standing around! Else you'll get chaos.
|
||||
|
||||
#### `/npc_talk generic` Add or remove NPC from the list of generic dialog providers.
|
||||
`/npc_talk generic list` Lists all generic NPC
|
||||
`/npc_talk generic add n_3` Adds the dialog from NPC as a
|
||||
|
@ -33,6 +33,16 @@ yl_speak_up.command_npc_talk = function(pname, param)
|
||||
end
|
||||
-- implemented in add_generic_dialogs.lua:
|
||||
return yl_speak_up.command_npc_talk_generic(pname, rest)
|
||||
-- restore an NPC that got lost
|
||||
elseif(cmd and cmd == "force_restore_npc") then
|
||||
if(not(minetest.check_player_privs(pname, {npc_talk_admin = true}))) then
|
||||
minetest.chat_send_player(pname, "This command is used for restoring "..
|
||||
"NPC that somehow got lost (egg destroyed, killed, ..). You "..
|
||||
"lack the \"npc_talk_admin\" priv required to run this command.")
|
||||
return
|
||||
end
|
||||
-- implemented in fs_npc_list.lua:
|
||||
return yl_speak_up.command_npc_force_restore_npc(pname, rest)
|
||||
elseif(cmd and cmd == "privs") then
|
||||
-- TODO: make this available for npc_talk_admin?
|
||||
if(not(minetest.check_player_privs(pname, {privs = true}))) then
|
||||
@ -54,8 +64,9 @@ yl_speak_up.command_npc_talk = function(pname, param)
|
||||
" list shows a list of NPC that you can edit\n"..
|
||||
" debug debug a particular NPC\n"..
|
||||
" force_edit forces edit mode for any NPC you talk to\n"..
|
||||
" generic [requores npc_talk_admin priv] list, add or remove NPC as generic NPC\n"..
|
||||
" privs [requires privs priv] list, grant or revoke privs for an NPC\n"..
|
||||
" generic [requores npc_talk_admin priv] list, add or remove NPC as generic NPC\n"..
|
||||
" force_restore_npc [requires npc_talk_admin priv] restore NPC that got lost\n"..
|
||||
" privs [requires privs priv] list, grant or revoke privs for an NPC\n"..
|
||||
-- reload is fully handled in register_once
|
||||
"Note: /npc_talk_reload [requires privs priv] reloads the code of the mod without server "..
|
||||
"restart.")
|
||||
|
140
fs_npc_list.lua
140
fs_npc_list.lua
@ -84,6 +84,8 @@ yl_speak_up.update_npc_data = function(self, dialog, force_store)
|
||||
properties = properties,
|
||||
created_at = created_at,
|
||||
muted = self.yl_speak_up.talk,
|
||||
animation = self.yl_speak_up.animation,
|
||||
skin = self.yl_speak_up.skin,
|
||||
}
|
||||
-- the current object will change after deactivate; there is no point in storing
|
||||
-- it over server restart
|
||||
@ -117,6 +119,144 @@ yl_speak_up.npc_list_store = function()
|
||||
end
|
||||
|
||||
|
||||
-- emergency restore NPC that got lost (egg deleted, killed, ...)
|
||||
yl_speak_up.command_npc_force_restore_npc = function(pname, rest)
|
||||
if(not(pname)) then
|
||||
return
|
||||
end
|
||||
if(not(minetest.check_player_privs(pname, {npc_talk_admin = true}))) then
|
||||
minetest.chat_send_player(pname, "This command is used for restoring "..
|
||||
"NPC that somehow got lost (egg destroyed, killed, ..). You "..
|
||||
"lack the \"npc_talk_admin\" priv required to run this command.")
|
||||
return
|
||||
end
|
||||
if(not(rest) or rest == "" or rest == "help" or rest == "?") then
|
||||
minetest.chat_send_player(pname, "This command is used for restoring "..
|
||||
"NPC that somehow got lost (egg destroyed, killed, ..).\n"..
|
||||
"WARNING: If the egg is found again later on, make sure that "..
|
||||
"this restored NPC and the NPC from the egg are not both placed!\n"..
|
||||
" There can only be one NPC per ID.\n"..
|
||||
"Syntax: /npc_talk force_restore_npc <id> [<copy_from_id>]\n"..
|
||||
" <id> is the ID (number! Without \"n_\") of the NPC to be restored.\n"..
|
||||
" <copy_from_id> is only needed if the NPC is not listed in "..
|
||||
"\"/npc_talk list\" (=extremly old NPC).")
|
||||
return
|
||||
end
|
||||
local parts = string.split(rest or "", " ", false, 1)
|
||||
local id = tonumber(parts[1] or "")
|
||||
if(not(id)) then
|
||||
minetest.chat_send_player(pname, "Please provide the ID (number!) of the NPC "..
|
||||
"you wish to restore.")
|
||||
return
|
||||
elseif(not(yl_speak_up.number_of_npcs) or yl_speak_up.number_of_npcs < 1
|
||||
or id > yl_speak_up.number_of_npcs) then
|
||||
minetest.chat_send_player(pname, "That ID is larger than the amount of existing NPC. "..
|
||||
"Restoring is for old NPC that got lost.")
|
||||
return
|
||||
elseif(id < 1) then
|
||||
minetest.chat_send_player(pname, "That ID is smaller than 1. Can't restore negative NPC.")
|
||||
return
|
||||
end
|
||||
local player = minetest.get_player_by_name(pname)
|
||||
if(not(player)) then
|
||||
return
|
||||
end
|
||||
-- if we've seen the NPC before: make sure he's not just unloaded because nobody is where he is
|
||||
if(yl_speak_up.npc_list[id] and yl_speak_up.npc_list[id].pos
|
||||
and yl_speak_up.npc_list[id].pos.x
|
||||
and yl_speak_up.npc_list[id].pos.y
|
||||
and yl_speak_up.npc_list[id].pos.z) then
|
||||
local v_npc = vector.new(yl_speak_up.npc_list[id].pos)
|
||||
local v_pl = vector.new(player:get_pos())
|
||||
if(vector.distance(v_npc, v_pl) > 6) then
|
||||
minetest.chat_send_player(pname, "You are more than 6 m away from the last "..
|
||||
"known position of this NPC at "..
|
||||
minetest.pos_to_string(yl_speak_up.npc_list[id].pos)..
|
||||
". Please move closer to make sure the NPC isn't just not loaded "..
|
||||
"due to nobody beeing near!")
|
||||
return
|
||||
end
|
||||
end
|
||||
-- check the currently loaded mobs to make sure he wasn't loaded since last update of our list
|
||||
for k,v in pairs(minetest.luaentities) do
|
||||
if(v and v.yl_speak_up and v.yl_speak_up.id and v.yl_speak_up.id == id) then
|
||||
minetest.chat_send_player(pname, "An NPC with the ID "..tostring(id)..
|
||||
" is currently loaded. No restoring required!")
|
||||
return
|
||||
end
|
||||
end
|
||||
local data = nil
|
||||
-- do we need a donator NPC because we have never seen this NPC and have no data?
|
||||
local copy_from_id = tonumber(parts[2] or "")
|
||||
if(not(yl_speak_up.npc_list[id])) then
|
||||
if(not(copy_from_id) or not(yl_speak_up.npc_list[copy_from_id])) then
|
||||
minetest.chat_send_player(pname, "We have no data on NPC "..tostring(id)..
|
||||
". Please provide the ID of an EXISTING NPC from which necessary "..
|
||||
"data can be copied!")
|
||||
return
|
||||
end
|
||||
minetest.chat_send_player(pname, "Will use the data of the NPC with ID "..
|
||||
tostring(copy_from_id).." to set up the new/restored NPC.")
|
||||
data = yl_speak_up.npc_list[copy_from_id]
|
||||
else
|
||||
data = yl_speak_up.npc_list[id]
|
||||
end
|
||||
-- ok..the NPC is not loaded. Perhaps he really got lost.
|
||||
minetest.chat_send_player(pname, "Will try to restore the NPC with the ID "..tostring(id)..".")
|
||||
|
||||
if(not(data.typ) or not(minetest.registered_entities[data.typ or "?"])) then
|
||||
minetest.chat_send_player(pname, "Error: No NPC entity prototype found for \""..
|
||||
tostring(data.name).."\". Aborting.")
|
||||
return
|
||||
end
|
||||
|
||||
-- this is an emergency fallback restore - so it's ok to drop the NPC where the admin is standing
|
||||
local mob = minetest.add_entity(player:get_pos(), data.typ)
|
||||
local ent = mob and mob:get_luaentity()
|
||||
if(not(ent)) then
|
||||
minetest.chat_send_player(pname, "Failed to create a new NPC entity of type \""..
|
||||
tostring(data.name).."\". Aborting.")
|
||||
return
|
||||
end
|
||||
-- set up the new NPC
|
||||
local npc_name = data.name
|
||||
local npc_desc = data.npc_description
|
||||
local npc_owner = data.owner
|
||||
-- the dialog includes the trades, n_may_edit and other data
|
||||
local dialog = yl_speak_up.load_dialog(id, nil)
|
||||
-- restore name and description from dialog if possible
|
||||
if(dialog and dialog.n_npc) then
|
||||
npc_name = dialog.n_npc
|
||||
npc_desc = dialog.n_description
|
||||
npc_owner = dialog.npc_owner or data.owner
|
||||
end
|
||||
ent.yl_speak_up = {
|
||||
id = id,
|
||||
talk = data.muted,
|
||||
properties = data.properties,
|
||||
npc_name = npc_name,
|
||||
npc_description = npc_desc,
|
||||
infotext = yl_speak_up.infotext, -- will be set automaticly later
|
||||
animation = data.animation,
|
||||
}
|
||||
-- This is at least useful for mobs_redo. Other mob mods may require adjustments.
|
||||
ent.owner = npc_owner
|
||||
ent.tamed = true
|
||||
-- update nametag, infotext etc.
|
||||
yl_speak_up.update_nametag(ent)
|
||||
if(data.animation and ent.object) then
|
||||
ent.object:set_animation(data.animation)
|
||||
end
|
||||
if(data.skin and ent.object) then
|
||||
ent.object:set_properties({textures = table.copy(data.skin)})
|
||||
end
|
||||
-- update the NPC list
|
||||
yl_speak_up.update_npc_data(ent, dialog, true)
|
||||
minetest.chat_send_player(pname, "Placed the restored NPC ID "..tostring(id)..
|
||||
", named "..tostring(data.name)..", right where you stand.")
|
||||
end
|
||||
|
||||
|
||||
-- provides a list of NPC the player can edit
|
||||
yl_speak_up.command_npc_talk_list = function(pname, rest)
|
||||
if(not(pname)) then
|
||||
|
Loading…
Reference in New Issue
Block a user