forked from Sokomine/yl_speak_up
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
|
NPC, the priv will be considered granted if either the
|
||||||
executing NPC or the the generic NPC has the priv.
|
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` Add or remove NPC from the list of generic dialog providers.
|
||||||
`/npc_talk generic list` Lists all generic NPC
|
`/npc_talk generic list` Lists all generic NPC
|
||||||
`/npc_talk generic add n_3` Adds the dialog from NPC as a
|
`/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
|
end
|
||||||
-- implemented in add_generic_dialogs.lua:
|
-- implemented in add_generic_dialogs.lua:
|
||||||
return yl_speak_up.command_npc_talk_generic(pname, rest)
|
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
|
elseif(cmd and cmd == "privs") then
|
||||||
-- TODO: make this available for npc_talk_admin?
|
-- TODO: make this available for npc_talk_admin?
|
||||||
if(not(minetest.check_player_privs(pname, {privs = true}))) then
|
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"..
|
" list shows a list of NPC that you can edit\n"..
|
||||||
" debug debug a particular NPC\n"..
|
" debug debug a particular NPC\n"..
|
||||||
" force_edit forces edit mode for any NPC you talk to\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"..
|
" 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"..
|
" 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
|
-- reload is fully handled in register_once
|
||||||
"Note: /npc_talk_reload [requires privs priv] reloads the code of the mod without server "..
|
"Note: /npc_talk_reload [requires privs priv] reloads the code of the mod without server "..
|
||||||
"restart.")
|
"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,
|
properties = properties,
|
||||||
created_at = created_at,
|
created_at = created_at,
|
||||||
muted = self.yl_speak_up.talk,
|
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
|
-- the current object will change after deactivate; there is no point in storing
|
||||||
-- it over server restart
|
-- it over server restart
|
||||||
@ -117,6 +119,144 @@ yl_speak_up.npc_list_store = function()
|
|||||||
end
|
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
|
-- provides a list of NPC the player can edit
|
||||||
yl_speak_up.command_npc_talk_list = function(pname, rest)
|
yl_speak_up.command_npc_talk_list = function(pname, rest)
|
||||||
if(not(pname)) then
|
if(not(pname)) then
|
||||||
|
Loading…
Reference in New Issue
Block a user