make data persistant for idlers and fix a multi-spawn bug
parent
25dec928ca
commit
1b3995345b
|
@ -197,6 +197,7 @@ mobs.npcs.messages.get_list_from_file = function(basename)
|
|||
end
|
||||
|
||||
-- Fill messages array when server start.
|
||||
--
|
||||
local default_messages_file_name = "mobs_npc_messages"
|
||||
|
||||
local messages_default = mobs.npcs.messages.get_list_from_file("mobs_npc_messages")
|
||||
|
@ -227,6 +228,6 @@ mobs.npcs.messages.get_random = function()
|
|||
end
|
||||
|
||||
mobs.npcs.messages.get_random_from_string = function(str)
|
||||
arr = string.lines_to_table(str)
|
||||
local arr = string.lines_to_table(str)
|
||||
return table.random(arr)
|
||||
end
|
||||
|
|
308
npc_custom.lua
308
npc_custom.lua
|
@ -6,6 +6,7 @@
|
|||
local S = mobs.translator
|
||||
|
||||
local vlog = mobs.vlog or "action" --"info"
|
||||
local vlog = "action" --"info"
|
||||
-- Mod related infos
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
@ -13,7 +14,16 @@ local modpath = minetest.get_modpath(modname)
|
|||
local mob_name = "npc_idler"
|
||||
local icprefix=modname..'_icon_'
|
||||
|
||||
mobs.npcs.mob_data = {}
|
||||
local mod_storage = minetest.get_mod_storage()
|
||||
|
||||
local serialized_mob_data = mod_storage:get_string('mob_data')
|
||||
mobs.npcs.mob_data = minetest.deserialize(serialized_mob_data) or {}
|
||||
|
||||
-- ------------------
|
||||
--
|
||||
-- helper function
|
||||
--
|
||||
|
||||
|
||||
local function find_in_array(needle,stack)
|
||||
if needle and stack then
|
||||
|
@ -25,16 +35,78 @@ local function find_in_array(needle,stack)
|
|||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
data_values = {
|
||||
"nametag_color",
|
||||
"nametag",
|
||||
"infotext",
|
||||
"textures",
|
||||
"infotext",
|
||||
"wield_item",
|
||||
"visual_size",
|
||||
"action",
|
||||
}
|
||||
data_serialize = {
|
||||
textures = true,
|
||||
action = true,
|
||||
}
|
||||
|
||||
local function save_node_meta(pos,data)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
for _,v in ipairs(data_values) do
|
||||
if data_serialize[v] then
|
||||
local szv = minetest.serialize(data[v])
|
||||
meta:set_string(v,szv)
|
||||
else
|
||||
meta:set_string(v,data[v])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local function get_data_from_node_meta(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local data = {}
|
||||
|
||||
for _,v in ipairs(data_values) do
|
||||
if data_serialize[v] then
|
||||
data[v] = minetest.deserialize(meta:get_string(v))
|
||||
else
|
||||
data[v] = meta:get_string(v)
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
local function get_mob_data(pos)
|
||||
local key = minetest.pos_to_string(pos)
|
||||
return mobs.npcs.mob_data[key]
|
||||
return mobs.npcs.mob_data[key] or get_data_from_node_meta(pos)
|
||||
end
|
||||
|
||||
local function set_mob_data(pos,data)
|
||||
local key = minetest.pos_to_string(pos)
|
||||
mobs.npcs.mob_data[key] = data
|
||||
save_node_meta(pos,data)
|
||||
-- local sz = minetest.serialize(mobs.npcs.mob_data)
|
||||
-- mod_storage:set_string('mob_data',sz)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ------------------
|
||||
--
|
||||
-- helper function
|
||||
--
|
||||
|
||||
-- ------------------
|
||||
--
|
||||
-- helper function
|
||||
--
|
||||
|
||||
|
||||
mobs.npcs.interactions = {
|
||||
default = {
|
||||
icon = icprefix..'chat_random.png',
|
||||
|
@ -103,33 +175,6 @@ if textures then
|
|||
mob_def.textures = textures
|
||||
end
|
||||
|
||||
-- Set on_right_click interaction
|
||||
mob_def.on_rightclick = function(self, clicker)
|
||||
|
||||
-- Look at the player
|
||||
mobs.npcs.turn_to_player(self, clicker)
|
||||
|
||||
-- Grab specific data from spawner
|
||||
local spawner_pos = self._spawner_pos
|
||||
if spawner_pos then
|
||||
-- Do custom action
|
||||
local data = get_mob_data(spawner_pos) or {}
|
||||
if data.action and data.action.id then
|
||||
local id = data.action.id
|
||||
local ref = mobs.npcs.interactions
|
||||
if ref[id] and ref[id].on_rightclick then
|
||||
return ref[id].on_rightclick(self, clicker, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Or at least say something
|
||||
local mobname = mobs.npcs.get_mobname(self)
|
||||
local clickername = clicker:get_player_name()
|
||||
local msg = mobs.npcs.messages.get_random()
|
||||
mobs.npcs.send_chat_message(clickername,msg,mobname)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -270,6 +315,7 @@ local function get_npc_formspec(pos,n)
|
|||
|
||||
forms[4] =
|
||||
'textarea[0.3,'.. iy+1.6 ..';'..fw..',1.6;infotext;'..S('InfoText')..';'..dv.infotext..']'..
|
||||
'button_exit['.. ww - 1 ..','.. wh - 1 ..';1,1;ok;ok]'..
|
||||
''
|
||||
|
||||
|
||||
|
@ -302,19 +348,27 @@ local function get_npc_formspec(pos,n)
|
|||
return formspec
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Function to initialize spawner : add entity and update metadata
|
||||
-- Call after place node and on rightclick
|
||||
-- Called after place node and on rightclick
|
||||
|
||||
|
||||
|
||||
mobs.npcs.update_cmob_properties = function(pos, player, mob)
|
||||
|
||||
minetest.log(vlog, '['..modname..'] '..'Updating mob properties from data at '..minetest.pos_to_string(pos))
|
||||
local data = get_mob_data(pos) or {}
|
||||
|
||||
if not mob and data.obj then mob = data.obj end
|
||||
if data.obj and not mob then mob = data.obj end
|
||||
|
||||
--- -- FIXEME: Seem to return true even when entity isn't there
|
||||
--- -- Probably because it's there just before being removed by the do_custom funtion
|
||||
local self
|
||||
if mob then self = mob:get_luaentity() end
|
||||
if not self then return false end
|
||||
|
||||
-- mob:set_pos({ x= pos.x, y= pos.y + 1, z= pos.z, })
|
||||
minetest.log(vlog, '['..modname..'] '..'Mob entity exist')
|
||||
|
||||
|
||||
|
@ -322,8 +376,12 @@ mobs.npcs.update_cmob_properties = function(pos, player, mob)
|
|||
|
||||
-- Set owner
|
||||
-- TODO: check that node is the correct node
|
||||
local player_name = player:get_player_name()
|
||||
|
||||
local player_name
|
||||
if not player then
|
||||
player_name = data.owner
|
||||
else
|
||||
player_name = player:get_player_name()
|
||||
end
|
||||
-- Set node meta
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner_name = data.owner or player_name
|
||||
|
@ -347,6 +405,7 @@ mobs.npcs.update_cmob_properties = function(pos, player, mob)
|
|||
wield_item = data.wield_item or self.wield_item,
|
||||
visual_size = data.visual_size or self.visual_size,
|
||||
})
|
||||
-- self = mob:get_luaentity()
|
||||
self._mobname = data.nametag or nil
|
||||
self._owner = owner_name
|
||||
self._spawner_pos = pos
|
||||
|
@ -354,6 +413,8 @@ mobs.npcs.update_cmob_properties = function(pos, player, mob)
|
|||
data.obj = mob
|
||||
-- Register to global table
|
||||
set_mob_data(pos,data)
|
||||
|
||||
print(dump(self))
|
||||
|
||||
end
|
||||
|
||||
|
@ -391,6 +452,8 @@ end
|
|||
|
||||
mobs.npcs.add_cmob = function(pos, player, _)
|
||||
|
||||
minetest.log(vlog, '['..modname..'] '..'Adding new mob at :'..minetest.pos_to_string(pos))
|
||||
|
||||
-- Place mob
|
||||
local above = { x=pos.x, y=pos.y+1, z=pos.z }
|
||||
local mob = minetest.add_entity(above, modname..':'..mob_name,minetest.write_json({_spawner_pos = pos}))
|
||||
|
@ -419,6 +482,52 @@ mobs.npcs.add_cmob = function(pos, player, _)
|
|||
end
|
||||
|
||||
|
||||
local function cmob_data_update(pos,player,itemstack,mob)
|
||||
|
||||
-- Update mob properties
|
||||
mobs.npcs.update_cmob_properties(pos, player, mob)
|
||||
local data = mobs.npcs.update_cmob_data(pos)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string('owner')
|
||||
|
||||
-- Re-call the after_place_node function if needed
|
||||
if not ( data and data.obj ) then
|
||||
|
||||
-- Get infos about the owner
|
||||
local powner = minetest.get_player_by_name(owner)
|
||||
if player and (not powner) then
|
||||
powner = player
|
||||
end
|
||||
|
||||
|
||||
-- Call the function
|
||||
--~ local spw_init = minetest.registered_nodes[node.name].after_place_node
|
||||
--~ if spw_init and player then
|
||||
--~ spw_init(pos, player, itemstack)
|
||||
--~ end
|
||||
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
if obj:get_luaentity().name == mob_id then
|
||||
obj:remove()
|
||||
end
|
||||
end
|
||||
mobs.npcs.add_cmob(pos, powner, itemstack)
|
||||
end
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
local function cmob_show_formspec(pos,player,data)
|
||||
local tab = 1
|
||||
if data and data.last_tab then
|
||||
tab = data.last_tab
|
||||
end
|
||||
minetest.after(0.2,
|
||||
minetest.show_formspec,
|
||||
player:get_player_name(),
|
||||
modname..':'..mob_name..'_form0'..tab,
|
||||
get_npc_formspec(pos,tab))
|
||||
end
|
||||
--
|
||||
-- Register Npc
|
||||
--
|
||||
|
@ -426,24 +535,95 @@ end
|
|||
mob_def.walk_chance = 0
|
||||
mob_def.jump = false
|
||||
mob_def.do_custom = function(self, dtime)
|
||||
-- Get mob pos
|
||||
--- Get mob pos
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
-- Make sure that it is still on the spawner (or at least 'in' it, or 'above' it)
|
||||
for i=-1,1 do
|
||||
local spos = { x= pos.x, y= pos.y + i, z= pos.z, }
|
||||
if ( minetest.get_node(spos).name == spawner_id ) then
|
||||
-- Stop function when spawner is found
|
||||
return false
|
||||
end
|
||||
local spawner_pos = self._spawner_pos
|
||||
|
||||
--- Look for reasons to remove the mob:
|
||||
--- Spawner pos is not set...
|
||||
--- ... try to find it
|
||||
-- if not spawner_pos then
|
||||
-- for i=-1,1 do
|
||||
-- local spos = { x= pos.x, y= pos.y + i, z= pos.z, }
|
||||
-- if ( minetest.get_node(spos).name == spawner_id ) then
|
||||
-- spawner_pos = spos
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
--- Spawner pos is not set...
|
||||
if ( not spawner_pos )
|
||||
--- Or mob if too far from spawner
|
||||
or ( vector.distance(pos, spawner_pos) > 2 )
|
||||
--- Or spawner has been removed
|
||||
or ( minetest.get_node(spawner_pos).name ~= spawner_id )
|
||||
then
|
||||
self.object:remove()
|
||||
return false
|
||||
end
|
||||
|
||||
-- local meta = minetest.get_meta(spawner_pos)
|
||||
local data = get_mob_data(spawner_pos)
|
||||
if not data.obj then
|
||||
self.object:remove()
|
||||
mobs.npcs.add_cmob(spawner_pos, data.owner)
|
||||
end
|
||||
-- set_mob_data(spawner_pos,data)
|
||||
-- mobs.npcs.update_cmob_properties(spawner_pos, _, self.obj)
|
||||
|
||||
-- Make sure that it is still on the spawner (or at least 'in' it, or 'above' it)
|
||||
-- for i=-1,1 do
|
||||
-- local spos = { x= pos.x, y= pos.y + i, z= pos.z, }
|
||||
-- if ( minetest.get_node(spos).name == spawner_id ) then
|
||||
-- --- Stop function when spawner is found
|
||||
-- mobs.npcs.update_cmob_properties(pos, _, self.obj)
|
||||
-- return false
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- Remove mob if it is away from spawner
|
||||
self.object:remove()
|
||||
-- self.object:remove()
|
||||
return false
|
||||
end
|
||||
--~ mob_def.on_spawn = function(self,pos)
|
||||
--~ local data =
|
||||
--~ end
|
||||
|
||||
-- Set on_right_click interaction
|
||||
mob_def.on_rightclick = function(self, clicker)
|
||||
|
||||
-- Look at the player
|
||||
mobs.npcs.turn_to_player(self, clicker)
|
||||
|
||||
-- Find spawner
|
||||
local spawner_pos = self._spawner_pos
|
||||
|
||||
-- Edit and update
|
||||
local edit_key = 'sneak'
|
||||
if spawner_pos and clicker:get_player_control()[edit_key] then
|
||||
data = cmob_data_update(spawner_pos,clicker,nil,self.object)
|
||||
cmob_show_formspec(spawner_pos,clicker,data)
|
||||
return
|
||||
end
|
||||
|
||||
if spawner_pos then
|
||||
-- Do custom action
|
||||
local data = get_mob_data(spawner_pos) or {}
|
||||
if data.action and data.action.id then
|
||||
local id = data.action.id
|
||||
local ref = mobs.npcs.interactions
|
||||
if ref[id] and ref[id].on_rightclick then
|
||||
return ref[id].on_rightclick(self, clicker, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Or at least say something
|
||||
local mobname = mobs.npcs.get_mobname(self)
|
||||
local clickername = clicker:get_player_name()
|
||||
local msg = mobs.npcs.messages.get_random()
|
||||
mobs.npcs.send_chat_message(clickername,msg,mobname)
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
mobs:register_mob(mob_id, mob_def)
|
||||
|
@ -482,27 +662,10 @@ minetest.register_node(spawner_id, {
|
|||
end,
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
|
||||
|
||||
-- --
|
||||
-- Check that the npc is still there
|
||||
-- --
|
||||
local data = mobs.npcs.update_cmob_data(pos)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string('owner')
|
||||
|
||||
-- Re-call the after_place_node function if needed
|
||||
if not ( data and data.obj ) then
|
||||
-- Get infos about the owner
|
||||
local powner = minetest.get_player_by_name(owner)
|
||||
if not powner then powner = clicker end
|
||||
-- Call the function
|
||||
--~ local spw_init = minetest.registered_nodes[node.name].after_place_node
|
||||
--~ if spw_init and player then
|
||||
--~ spw_init(pos, player, itemstack)
|
||||
--~ end
|
||||
mobs.npcs.add_cmob(pos, powner, itemstack)
|
||||
end
|
||||
local data = cmob_data_update(pos, clicker, itemstack)
|
||||
|
||||
-- --
|
||||
-- Stop there if not allowed to interact
|
||||
|
@ -512,16 +675,7 @@ minetest.register_node(spawner_id, {
|
|||
end
|
||||
|
||||
-- Show customisation form
|
||||
-- minetest.show_formspec(playername, formname, formspec)
|
||||
local tab = 1
|
||||
if data and data.last_tab then
|
||||
tab = data.last_tab
|
||||
end
|
||||
minetest.after(0.2,
|
||||
minetest.show_formspec,
|
||||
clicker:get_player_name(),
|
||||
modname..':'..mob_name..'_form0'..tab,
|
||||
get_npc_formspec(pos,tab))
|
||||
cmob_show_formspec(pos,clicker,data)
|
||||
end,
|
||||
|
||||
-- on_receive_fields = function(pos, formname, fields, sender)
|
||||
|
@ -530,7 +684,7 @@ minetest.register_node(spawner_id, {
|
|||
|
||||
|
||||
-- Register egg
|
||||
mobs:register_egg(mob_id, "npc", "character_lambda_inv.png", 0)
|
||||
-- mobs:register_egg(mob_id, "npc", "character_lambda_inv.png", 0)
|
||||
--~ mobs:doc_identifier_compat(mob_id, longdesc, usagehelp)
|
||||
|
||||
mobs:alias_mob("mobs:"..mob_name, mob_id) -- compatibility
|
||||
|
@ -553,7 +707,7 @@ local on_receive_fields = function(player, formname, fields)
|
|||
if not pos then return false end
|
||||
local data = get_mob_data(pos) or {}
|
||||
|
||||
-- Update data without overrinding it
|
||||
-- Update data without overiding it
|
||||
if fields.texture then data.textures = { fields.texture } end
|
||||
if fields.action_id then
|
||||
-- if fields.action_id and (( not data.action ) or ( fields.action_id ~= data.action.id )) then
|
||||
|
@ -584,7 +738,7 @@ local on_receive_fields = function(player, formname, fields)
|
|||
|
||||
|
||||
set_mob_data(pos,data)
|
||||
mobs.npcs.update_cmob_properties(pos,player, data.obj)
|
||||
mobs.npcs.update_cmob_properties(pos,player,data.obj)
|
||||
|
||||
local tb = data.last_tab
|
||||
if ( fields.tab or fields.action_id ) and not fields.quit then
|
||||
|
|
Loading…
Reference in New Issue