Add support for offline mob accounting
Fix bug orphaned lifebars stay forever Fix crash due to invalid data passed to path based movegen
This commit is contained in:
parent
09df9aa431
commit
60fb792151
@ -196,6 +196,9 @@ function mobf_init_framework()
|
||||
minetest.log(LOGLEVEL_NOTICE,"MOBF: Initialize lifebar subsystem..")
|
||||
mobf_lifebar.init()
|
||||
|
||||
minetest.log(LOGLEVEL_NOTICE,"MOBF: Initialize spawning subsystem..")
|
||||
spawning.init()
|
||||
|
||||
minetest.log(LOGLEVEL_NOTICE,"MOBF: Initialize mobf supplied modules..")
|
||||
mobf_init_modules()
|
||||
|
||||
|
@ -46,14 +46,18 @@ function mobf_lifebar.init()
|
||||
initialized = false,
|
||||
|
||||
on_step = function (self,dtime)
|
||||
self.lifetime = self.lifetime + dtime
|
||||
if not self.initialized then
|
||||
self.lifetime = self.lifetime + dtime
|
||||
|
||||
if self.lifetime > 1 then
|
||||
dbg_mobf.lifebar_lvl3("MOBF: lifebar not attached deleting")
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
--parent will reset lifetime while it's active
|
||||
if self.lifetime > 5 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
})
|
||||
|
@ -467,7 +467,7 @@ function mobf.activate_handler(self,staticdata)
|
||||
mobf_assert_backtrace(self.dynamic_data.current_movement_gen ~= nil)
|
||||
|
||||
--initialize movegen entity,current time, permanent data
|
||||
self.dynamic_data.current_movement_gen.init_dynamic_data(self,now,retval)
|
||||
self.dynamic_data.current_movement_gen.init_dynamic_data(self,now,preserved_data)
|
||||
|
||||
--call enter state fct
|
||||
if self.dynamic_data.state.current.HANDLER_enter_state ~= nil then
|
||||
@ -632,6 +632,10 @@ function mobf.register_entity(name, graphics, mob)
|
||||
return
|
||||
end
|
||||
|
||||
if self.lifebar ~= nil then
|
||||
self.lifebar:get_luaentity().lifetime = 0
|
||||
end
|
||||
|
||||
--check lifetime
|
||||
if spawning.lifecycle_callback(self,now) == false then
|
||||
mobf_warn_long_fct(starttime,"on_step_total_lifecycle","on_step_total")
|
||||
@ -703,6 +707,9 @@ function mobf.register_entity(name, graphics, mob)
|
||||
--make sure entity is in loaded area at initialization
|
||||
local pos = self.object:getpos()
|
||||
|
||||
--remove from mob offline storage
|
||||
spawning.activate_mob(self.data.modname .. ":" .. self.data.name,pos)
|
||||
|
||||
if pos ~= nil and
|
||||
entity_at_loaded_pos(pos,self.data.name) then
|
||||
mobf.activate_handler(self,staticdata)
|
||||
@ -741,9 +748,12 @@ function mobf.register_entity(name, graphics, mob)
|
||||
end,
|
||||
|
||||
--prepare permanent data
|
||||
get_staticdata = function(self)
|
||||
return mobf_serialize_permanent_entity_data(self)
|
||||
end,
|
||||
--NOTE this isn't called if a object is deleted
|
||||
get_staticdata = function(self)
|
||||
--add to mob offline storage
|
||||
spawning.deactivate_mob(self.data.modname .. ":" .. self.data.name,self.object:getpos())
|
||||
return mobf_serialize_permanent_entity_data(self)
|
||||
end,
|
||||
|
||||
--custom variables for each mob
|
||||
data = mob,
|
||||
|
@ -35,6 +35,153 @@ mobf_assert_backtrace(mobf_spawn_algorithms == nil)
|
||||
--! @private
|
||||
mobf_spawn_algorithms = {}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: init()
|
||||
-- @function [parent=#spawning] init
|
||||
--
|
||||
--! @brief initialize spawning data
|
||||
--! @memberof spawning
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.init()
|
||||
--read from file
|
||||
local world_path = minetest.get_worldpath()
|
||||
|
||||
local file,error = io.open(world_path .. "/mobf_spawning_data","r")
|
||||
|
||||
if file ~= nil then
|
||||
local data_raw = file:read("*a")
|
||||
file:close()
|
||||
|
||||
if data_raw ~= nil then
|
||||
spawning.mob_spawn_data = minetest.deserialize(data_raw)
|
||||
end
|
||||
end
|
||||
|
||||
if spawning.mob_spawn_data == nil then
|
||||
spawning.mob_spawn_data = {}
|
||||
end
|
||||
|
||||
--register spawndata persistent storer to globalstep
|
||||
minetest.after(300,spawning.preserve_spawn_data,true)
|
||||
|
||||
--register cleanup handler
|
||||
minetest.register_on_shutdown(function(dstep) spawning.preserve_spawn_data(false) end)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: preserve_spawn_data()
|
||||
-- @function [parent=#spawning] preserve_spawn_data
|
||||
--
|
||||
--! @brief save data on regular base
|
||||
--! @memberof spawning
|
||||
--
|
||||
--! @param force
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.preserve_spawn_data(cyclic)
|
||||
|
||||
local world_path = minetest.get_worldpath()
|
||||
local file,error = io.open(world_path .. "/mobf_spawning_data","w")
|
||||
|
||||
if error ~= nil then
|
||||
minetest.log(LOGLEVEL_ERROR,"MOBF: failed to spawning preserve file")
|
||||
end
|
||||
mobf_assert_backtrace(file ~= nil)
|
||||
|
||||
local serialized_data = minetest.serialize(spawning.mob_spawn_data)
|
||||
|
||||
file:write(serialized_data)
|
||||
|
||||
if cyclic then
|
||||
minetest.after(300,spawning.preserve_spawn_data,cyclic)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: total_offline_mobs()
|
||||
-- @function [parent=#spawning] total_offline_mobs
|
||||
--
|
||||
--! @brief count total number of offline mobs
|
||||
--! @memberof spawning
|
||||
--
|
||||
--! @return number of mobs
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.total_offline_mobs()
|
||||
local count = 0
|
||||
for key,value in pairs(spawning.mob_spawn_data) do
|
||||
for hash,v in pairs(value) do
|
||||
count = count +1
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: count_deactivated_mobs(name,pos,range)
|
||||
-- @function [parent=#spawning] count_deactivated_mobs
|
||||
--
|
||||
--! @brief count number of mobs of specific type within a certain range
|
||||
--! @memberof spawning
|
||||
--
|
||||
--! @param name name of mob to count
|
||||
--! @param pos to check distance to
|
||||
--! @param range to check
|
||||
--
|
||||
--! @return number of mobs
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.count_deactivated_mobs(name,pos,range)
|
||||
local count = 0
|
||||
if spawning.mob_spawn_data[name] ~= nil then
|
||||
for hash,v in pairs(spawning.mob_spawn_data[name]) do
|
||||
local mobpos = mobf_hash_to_pos(hash)
|
||||
local distance = vector.distance(pos,mobpos)
|
||||
if distance < range then
|
||||
count = count +1
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: deactivate_mob(entity)
|
||||
-- @function [parent=#spawning] deactivate_mob
|
||||
--
|
||||
--! @brief add mob to deactivated list
|
||||
--! @memberof spawning
|
||||
--
|
||||
--! @param entity to deactivate
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.deactivate_mob(name,pos)
|
||||
if spawning.mob_spawn_data[name] == nil then
|
||||
spawning.mob_spawn_data[name] = {}
|
||||
end
|
||||
|
||||
local rounded_pos = vector.round(pos)
|
||||
local hash = minetest.hash_node_position(rounded_pos)
|
||||
--assert (mobf_pos_is_same(mobf_hash_to_pos(hash),rounded_pos))
|
||||
spawning.mob_spawn_data[name][hash] = true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: activate_mob(name,pos)
|
||||
-- @function [parent=#spawning] preserve_spawn_data
|
||||
--
|
||||
--! @brief save data on regular base
|
||||
--! @memberof spawning
|
||||
--
|
||||
--! @param force
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.activate_mob(name,pos)
|
||||
if spawning.mob_spawn_data[name] ~= nil then
|
||||
local rounded_pos = vector.round(pos)
|
||||
local hash = minetest.hash_node_position(rounded_pos)
|
||||
--assert(mobf_pos_is_same(mobf_hash_to_pos(hash),rounded_pos))
|
||||
spawning.mob_spawn_data[name][hash] = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: remove_uninitialized(entity,staticdata)
|
||||
@ -198,7 +345,7 @@ function spawning.population_density_check(entity,now)
|
||||
mob_count .. " mobs of same type around")
|
||||
entity.removed = true
|
||||
minetest.log(LOGLEVEL_WARNING,"MOBF: Too many ".. mob_count .. " "..
|
||||
entity.data.name.." at one place dying: " ..
|
||||
entity.data.name.." at one place dieing: " ..
|
||||
tostring(entity.dynamic_data.spawning.player_spawned))
|
||||
spawning.remove(entity, "population density check")
|
||||
return false
|
||||
|
@ -733,4 +733,28 @@ function mobf_is_pos(value)
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_hash_to_pos(hash)
|
||||
--
|
||||
--! @brief restore a position from a pos hash value
|
||||
--
|
||||
--! @param hash to restore pos from
|
||||
--
|
||||
--! @return posistion reconstructed from hash
|
||||
-------------------------------------------------------------------------------
|
||||
function mobf_hash_to_pos(hash)
|
||||
local retval = {}
|
||||
|
||||
local raw_x = (hash % 65536)
|
||||
local raw_y = ((hash - raw_x) % (65536*65536)) / 65536
|
||||
local raw_z = ((hash - raw_x - raw_y) / 65536) / 65536
|
||||
|
||||
local mobpos = {}
|
||||
retval.x = raw_x - 32768
|
||||
retval.y = raw_y - 32768
|
||||
retval.z = math.floor(raw_z - 32768)
|
||||
|
||||
return retval
|
||||
end
|
||||
|
||||
--!@}
|
||||
|
Loading…
x
Reference in New Issue
Block a user