Fix broken spawner initialization

Add support for regenerating lost spawners (only around players)
master
sapier 2014-08-19 19:25:18 +02:00
parent 39593f3674
commit 4d65ac72af
5 changed files with 136 additions and 5 deletions

View File

@ -189,8 +189,22 @@ Statistics:
}
}
Settings:
adv_spawning_validate_spawners = false
^ make advanced_spawning check area around active players for lost spawner seeds
Changelog:
0.0.9
-Fix broken spawner initialization
-Add support for regenerating spawner seeds (only around active players)
set >>adv_spawning_validate_spawners<< to true if you want advanced spawning
to do this.
Note: this might need some additional cpu time
0.0.8
-Fix large steps caused by uninterruptable spawn seed initialization within activation
0.0.7
-handle time steps backward without assertion

View File

@ -26,6 +26,9 @@ function adv_spawning.register(spawner_name,spawning_def)
adv_spawning.spawner_definitions[spawner_name] = spawning_def
adv_spawning.dbg_log(0, "registering spawner \"" .. spawner_name .. "\"")
adv_spawning.dbg_log(0, "now handling: " ..
adv_spawning.table_count(adv_spawning.spawner_definitions) ..
" spawner definitions")
return true
else
return false

View File

@ -8,7 +8,7 @@
--
-------------------------------------------------------------------------------
local version = "0.0.8"
local version = "0.0.9"
if adv_spawning ~= nil then
core.log("error", "MOD: adv_spawning requires adv_spawning variable to be available")

View File

@ -65,6 +65,8 @@ function adv_spawning.initialize()
adv_spawning.max_mapgen_tries_per_step = 3
adv_spawning.spawner_warned = {}
adv_spawning.loglevel = 0
adv_spawning.spawner_validation_delta = 0
adv_spawning.spawner_validation_interval = 30
adv_spawning.active_range = minetest.setting_get("active_block_range")
@ -216,6 +218,32 @@ function adv_spawning.global_onstep(dtime)
(adv_spawning.statistics.session.steps-1)) +
adv_spawning.statistics.load.cur) /
adv_spawning.statistics.session.steps
if core.is_yes(
core.setting_get("adv_spawning_validate_spawners")) then
adv_spawning.spawner_validation_delta =
adv_spawning.spawner_validation_delta + dtime
if adv_spawning.spawner_validation_delta >
adv_spawning.spawner_validation_interval then
if adv_spawning.quota_enter() then
local playerlist = core.get_connected_players()
for k,v in ipairs(playerlist) do
if not adv_spawning.time_over(10) then
adv_spawning.refresh_spawners(v:getpos())
else
break
end
end
adv_spawning.spawner_validation_delta = 0
end
end
end
--reduce following quota by overtime from last step
if adv_spawning.quota_left < 0 then
@ -1491,4 +1519,65 @@ function adv_spawning.dbg_log(loglevel, message)
if (adv_spawning.loglevel >= loglevel ) then
core.log("action", "ADV_SPAWNING: " .. message)
end
end
--------------------------------------------------------------------------------
-- @function [parent=#adv_spawning] refresh_spawners
-- @param pos to refresh spawners around
--------------------------------------------------------------------------------
function adv_spawning.refresh_spawners(pos)
local min = {x=pos.x-32, y=pos.y-32, z=pos.z-32}
local max = {x=pos.x+32, y=pos.y+32, z=pos.z+32}
core.log("action", "Checking spawners from: " .. core.pos_to_string(min) ..
" to " .. core.pos_to_string(max))
local start_x =
math.floor(min.x/adv_spawning.spawner_distance)
* adv_spawning.spawner_distance
local start_y =
(math.floor(min.y/adv_spawning.spawner_distance)
* adv_spawning.spawner_distance)
+ adv_spawning.spawner_y_offset
local start_z =
math.floor(min.z/adv_spawning.spawner_distance)
* adv_spawning.spawner_distance
for x=start_x,max.x,adv_spawning.spawner_distance do
for y=start_y,max.y,adv_spawning.spawner_distance do
for z=start_z,max.z,adv_spawning.spawner_distance do
core.log("action", "Checking: (" .. x .. "," .. y .. "," .. z .. ")")
if x > min.x and
y > min.y and
z > min.z then
if not adv_spawning.quota_leave() then
adv_spawning.dbg_log(2,
"adv_spawning: refresh_spawners did use way too much time 1")
end
minetest.add_entity({x=x,y=y,z=z},"adv_spawning:spawn_seed")
adv_spawning.quota_enter(true)
adv_spawning.log("info", "adv_spawning: adding spawner entity at "
.. core.pos_to_string({x=x,y=y,z=z}))
adv_spawning.statistics.session.spawners_created =
adv_spawning.statistics.session.spawners_created +1
end
end
end
end
end
--------------------------------------------------------------------------------
-- @function [parent=#adv_spawning] table_count
-- @param tocount table to get number of elements from
--------------------------------------------------------------------------------
function adv_spawning.table_count(tocount)
local retval = 0
for k,v in pairs(tocount) do
retval = retval +1
end
return retval
end

View File

@ -35,6 +35,7 @@ function adv_spawning.seed_step(self,dtime)
self.pending_spawners = {}
adv_spawning.seed_countdown_spawners(self,self.mydtime)
self.mydtime = 0
--check quota again
@ -48,7 +49,7 @@ function adv_spawning.seed_step(self,dtime)
while #self.pending_spawners > 0 and
per_step_count < adv_spawning.max_spawns_per_spawner and
adv_spawning.time_over(10) do
(not adv_spawning.time_over(10)) do
local rand_spawner = math.random(1,#self.pending_spawners)
key = self.pending_spawners[rand_spawner]
@ -132,7 +133,9 @@ end
--------------------------------------------------------------------------------
function adv_spawning.on_rightclick(self, clicker)
if adv_spawning.debug then
print("ADV_SPAWNING: Spawner may spawn following mobs:")
print("ADV_SPAWNING: time till next spawn: " .. self.mydtime)
print("ADV_SPAWNING: pending spawners: " .. #self.pending_spawners)
print("ADV_SPAWNING: Spawner may spawn " .. adv_spawning.table_count(self.spawning_data) .. " mobs:")
local index = 1
for key,value in pairs(self.spawning_data) do
print(string.format("%3d:",index) .. string.format("%30s ",key) .. string.format("%3d s", value))
@ -165,6 +168,7 @@ function adv_spawning.seed_initialize()
self.activated = false
self.mydtime = dtime_s
self.serialized_data = staticdata
self.object:set_armor_groups({ immortal=100 })
adv_spawning.seed_activate(self)
end,
on_step = adv_spawning.seed_step,
@ -210,7 +214,27 @@ end
-- @return true/false
--------------------------------------------------------------------------------
function adv_spawning.seed_check_for_collision(self)
--TODO check if there already is another spawner at exactly this position
assert(self ~= nil)
local pos = self.object:getpos()
local objects = minetest.get_objects_inside_radius(pos, 0.5)
if objects == nil then
return false
end
-- check if any of those found objects is a spawning seed
for k,v in ipairs(objects) do
local entity = v:get_luaentity()
if entity ~= nil then
if entity.name == "adv_spawning:spawn_seed" and
entity.object ~= self.object then
self.object:remove()
return true
end
end
end
return false
end
@ -221,7 +245,8 @@ end
--------------------------------------------------------------------------------
function adv_spawning.seed_scan_for_applyable_spawners(self)
if self.initialized_spawners >= #adv_spawning.spawner_definitions then
if self.initialized_spawners >=
adv_spawning.table_count(adv_spawning.spawner_definitions) then
return true
end