Fix spawnegg initial environment check may cause major lag spikes
parent
b9608c029f
commit
9d7e4279f4
2
init.lua
2
init.lua
|
@ -8,7 +8,7 @@
|
||||||
--
|
--
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
local version = "0.0.11"
|
local version = "0.0.12"
|
||||||
|
|
||||||
if adv_spawning ~= nil then
|
if adv_spawning ~= nil then
|
||||||
core.log("error", "MOD: adv_spawning requires adv_spawning variable to be available")
|
core.log("error", "MOD: adv_spawning requires adv_spawning variable to be available")
|
||||||
|
|
80
internal.lua
80
internal.lua
|
@ -105,6 +105,7 @@ function adv_spawning.initialize()
|
||||||
adv_spawning.gettime = function() return os.clock() * 1000 end
|
adv_spawning.gettime = function() return os.clock() * 1000 end
|
||||||
|
|
||||||
if type(minetest.get_us_time) == "function" then
|
if type(minetest.get_us_time) == "function" then
|
||||||
|
adv_spawning.log("action", "Using minetest.get_us_time() for quota calc")
|
||||||
adv_spawning.gettime = function()
|
adv_spawning.gettime = function()
|
||||||
return minetest.get_us_time() / 1000
|
return minetest.get_us_time() / 1000
|
||||||
end
|
end
|
||||||
|
@ -113,6 +114,7 @@ function adv_spawning.initialize()
|
||||||
local status, module = pcall(require, 'socket')
|
local status, module = pcall(require, 'socket')
|
||||||
|
|
||||||
if status and type(module.gettime) == "function" then
|
if status and type(module.gettime) == "function" then
|
||||||
|
adv_spawning.log("action", "Using socket.gettime() for quota calc")
|
||||||
adv_spawning.gettime = function()
|
adv_spawning.gettime = function()
|
||||||
return socket.gettime()*1000
|
return socket.gettime()*1000
|
||||||
end
|
end
|
||||||
|
@ -1603,3 +1605,81 @@ function adv_spawning.table_count(tocount)
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function adv_spawning.build_shell(pos, d)
|
||||||
|
local retval = {}
|
||||||
|
|
||||||
|
-- build top face
|
||||||
|
for x = -d , d , 1 do
|
||||||
|
for z = -d, d, 1 do
|
||||||
|
retval[#retval+1] = { x = pos.x + x, y = pos.y + d, z = pos.z + z}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- build bottom face
|
||||||
|
for x = -d , d , 1 do
|
||||||
|
for z = -d, d, 1 do
|
||||||
|
retval[#retval+1] = { x = pos.x + x, y = pos.y -d, z = pos.z + z}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- build x- face
|
||||||
|
for z = -d , d , 1 do
|
||||||
|
for y = - (d -1) , (d -1), 1 do
|
||||||
|
retval[#retval+1] = { x = pos.x -d, y = pos.y + y, z = pos.z + z}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- build x+ face
|
||||||
|
for z = -d , d , 1 do
|
||||||
|
for y = - (d -1) , (d -1), 1 do
|
||||||
|
retval[#retval+1] = { x = pos.x + d, y = pos.y + y, z = pos.z + z}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- build z- face
|
||||||
|
for x = - (d -1) , (d -1) , 1 do
|
||||||
|
for y = - (d -1) , (d -1), 1 do
|
||||||
|
retval[#retval+1] = { x = pos.x + x, y = pos.y + y, z = pos.z - d}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- build z+ face
|
||||||
|
for x = -(d -1) , (d -1) , 1 do
|
||||||
|
for y = - (d -1) , (d -1), 1 do
|
||||||
|
retval[#retval+1] = { x = pos.x + x, y = pos.y + y, z = pos.z + d}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- @function [parent=#adv_spawning] table_count
|
||||||
|
-- @param tocount table to get number of elements from
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function adv_spawning.find_nodes_in(pos, min_range, max_range, nodetypes)
|
||||||
|
|
||||||
|
if type(nodetypes) == "string" then
|
||||||
|
local templist = { nodetypes }
|
||||||
|
nodetypes = templist
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = min_range, max_range, 1 do
|
||||||
|
local positions = adv_spawning.build_shell(pos, i)
|
||||||
|
|
||||||
|
for i = 1, #positions, 1 do
|
||||||
|
local node = minetest.get_node_or_nil(positions[i])
|
||||||
|
|
||||||
|
if node ~= nil then
|
||||||
|
for i = 1, #nodetypes, 1 do
|
||||||
|
if node.name == nodetypes[i] then
|
||||||
|
return positions[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
151
spawn_seed.lua
151
spawn_seed.lua
|
@ -16,7 +16,9 @@
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function adv_spawning.seed_step(self,dtime)
|
function adv_spawning.seed_step(self,dtime)
|
||||||
if not self.activated then
|
if not self.activated then
|
||||||
|
local starttime = adv_spawning.gettime()
|
||||||
adv_spawning.seed_activate(self)
|
adv_spawning.seed_activate(self)
|
||||||
|
adv_spawning.check_time(starttime, "Initializing spawner on_step took way too much time")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ function adv_spawning.seed_step(self,dtime)
|
||||||
if not adv_spawning.seed_scan_for_applyable_spawners(self) then
|
if not adv_spawning.seed_scan_for_applyable_spawners(self) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if adv_spawning.quota_enter() then
|
if adv_spawning.quota_enter() then
|
||||||
self.pending_spawners = {}
|
self.pending_spawners = {}
|
||||||
|
|
||||||
|
@ -46,10 +48,13 @@ function adv_spawning.seed_step(self,dtime)
|
||||||
|
|
||||||
local per_step_count = 0
|
local per_step_count = 0
|
||||||
local key = nil
|
local key = nil
|
||||||
|
|
||||||
|
local starttime = adv_spawning.gettime()
|
||||||
|
|
||||||
while #self.pending_spawners > 0 and
|
while #self.pending_spawners > 0 and
|
||||||
per_step_count < adv_spawning.max_spawns_per_spawner and
|
per_step_count < adv_spawning.max_spawns_per_spawner and
|
||||||
(not adv_spawning.time_over(10)) do
|
(not adv_spawning.time_over(10)) do
|
||||||
|
|
||||||
|
|
||||||
local rand_spawner = math.random(1,#self.pending_spawners)
|
local rand_spawner = math.random(1,#self.pending_spawners)
|
||||||
key = self.pending_spawners[rand_spawner]
|
key = self.pending_spawners[rand_spawner]
|
||||||
|
@ -84,7 +89,11 @@ function adv_spawning.seed_step(self,dtime)
|
||||||
|
|
||||||
tries = tries -1
|
tries = tries -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
starttime = adv_spawning.check_time(starttime, key .. " for " ..
|
||||||
|
adv_spawning.spawner_definitions[key].spawnee .. " did use way too much time")
|
||||||
|
|
||||||
table.remove(self.pending_spawners,rand_spawner)
|
table.remove(self.pending_spawners,rand_spawner)
|
||||||
per_step_count = per_step_count +1
|
per_step_count = per_step_count +1
|
||||||
end
|
end
|
||||||
|
@ -258,6 +267,90 @@ function adv_spawning.seed_check_for_collision(self)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function adv_spawning.init_spawner(self, pos, name, spawnerdef)
|
||||||
|
local starttime = adv_spawning.gettime()
|
||||||
|
|
||||||
|
if self.spawner_init_state ~= nil then
|
||||||
|
self.spawner_init_state = "initial"
|
||||||
|
end
|
||||||
|
|
||||||
|
local starttime = adv_spawning.gettime()
|
||||||
|
if self.spawner_init_state == "initial" then
|
||||||
|
|
||||||
|
--check if cyclic spawning is enabled
|
||||||
|
if spawnerdef.cyclic_spawning ~= nil and
|
||||||
|
spawnerdef.cyclic_spawning == false then
|
||||||
|
self.spawning_data[name] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
self.spawner_init_state = "abs_height"
|
||||||
|
end
|
||||||
|
|
||||||
|
starttime = adv_spawning.check_time(starttime, name .. "cyclic check")
|
||||||
|
if self.spawner_init_state == "abs_height" then
|
||||||
|
--if spawner is far away from spawn area don't even try to spawn
|
||||||
|
if spawnerdef.absolute_height ~= nil then
|
||||||
|
if spawnerdef.absolute_height.min ~= nil and
|
||||||
|
spawnerdef.absolute_height.min
|
||||||
|
> pos.y + (adv_spawning.spawner_distance/2) then
|
||||||
|
self.spawning_data[name] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if spawnerdef.absolute_height.max ~= nil
|
||||||
|
and spawnerdef.absolute_height.max
|
||||||
|
< pos.y - (adv_spawning.spawner_distance/2) then
|
||||||
|
self.spawning_data[name] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.spawner_init_state = "environment"
|
||||||
|
end
|
||||||
|
|
||||||
|
starttime = adv_spawning.check_time(starttime, name .. "height check")
|
||||||
|
if self.spawner_init_state == "environment" then
|
||||||
|
|
||||||
|
local runidx = 1
|
||||||
|
local radius = adv_spawning.spawner_distance / 2
|
||||||
|
|
||||||
|
if self.spawnerinit_env_radius ~= nil then
|
||||||
|
runidx = self.spawnerinit_env_radius
|
||||||
|
end
|
||||||
|
|
||||||
|
local found = false
|
||||||
|
|
||||||
|
for i = runidx , radius, 1 do
|
||||||
|
adv_spawning.quota_leave()
|
||||||
|
|
||||||
|
if not adv_spawning.quota_enter() then
|
||||||
|
self.spawnerinit_env_radius = runidx
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local resultpos = adv_spawning.find_nodes_in(pos, runidx, runidx, spawnerdef.spawn_inside)
|
||||||
|
|
||||||
|
if (resultpos ~= nil) then
|
||||||
|
local node = minetest.get_node_or_nil(resultpos)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
starttime = adv_spawning.check_time(starttime, name ..
|
||||||
|
" at environment check radius was: " .. radius ..
|
||||||
|
" env: " .. dump(spawnerdef.spawn_inside))
|
||||||
|
|
||||||
|
if not found then
|
||||||
|
self.spawning_data[name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.spawner_init_state = "initial"
|
||||||
|
self.spawning_data[name] = spawnerdef.spawn_interval * math.random()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- @function [parent=#adv_spawning] seed_scan_for_applyable_spawners
|
-- @function [parent=#adv_spawning] seed_scan_for_applyable_spawners
|
||||||
-- @param self spawner entity
|
-- @param self spawner entity
|
||||||
|
@ -271,12 +364,17 @@ function adv_spawning.seed_scan_for_applyable_spawners(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
local runindex = 0
|
local runindex = 0
|
||||||
|
|
||||||
|
if self.spawner_init_idx ~= nil then
|
||||||
|
runindex = self.spawner_init_idx
|
||||||
|
end
|
||||||
|
|
||||||
local pos = self.object:getpos()
|
local pos = self.object:getpos()
|
||||||
for key,value in pairs(adv_spawning.spawner_definitions) do
|
for key,value in pairs(adv_spawning.spawner_definitions) do
|
||||||
if not adv_spawning.quota_enter() then
|
if not adv_spawning.quota_enter() then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local starttime = adv_spawning.gettime()
|
|
||||||
local continue = false
|
local continue = false
|
||||||
|
|
||||||
if runindex >= self.initialized_spawners then
|
if runindex >= self.initialized_spawners then
|
||||||
|
@ -285,50 +383,15 @@ function adv_spawning.seed_scan_for_applyable_spawners(self)
|
||||||
continue = true
|
continue = true
|
||||||
end
|
end
|
||||||
|
|
||||||
runindex = runindex + 1
|
|
||||||
|
|
||||||
--check if cyclic spawning is enabled
|
|
||||||
if not continue and
|
|
||||||
value.cyclic_spawning ~= nil and
|
|
||||||
value.cyclic_spawning == false then
|
|
||||||
continue = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--if spawner is far away from spawn area don't even try to spawn
|
|
||||||
if not continue and
|
|
||||||
value.absolute_height ~= nil then
|
|
||||||
if value.absolute_height.min ~= nil and
|
|
||||||
value.absolute_height.min
|
|
||||||
> pos.y + (adv_spawning.spawner_distance/2) then
|
|
||||||
continue = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if value.absolute_height.max ~= nil
|
|
||||||
and value.absolute_height.max
|
|
||||||
< pos.y - (adv_spawning.spawner_distance/2) then
|
|
||||||
continue = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
starttime = adv_spawning.check_time(starttime, key .. " at spawn range check")
|
|
||||||
|
|
||||||
--check for presence of environment
|
|
||||||
if not continue then
|
if not continue then
|
||||||
local radius =
|
runindex = runindex + 1
|
||||||
math.sqrt(adv_spawning.spawner_distance*
|
if not adv_spawning.init_spawner(self, pos, key, value) then
|
||||||
adv_spawning.spawner_distance*2)/2
|
return false
|
||||||
|
|
||||||
if minetest.find_node_near(pos,radius,
|
|
||||||
value.spawn_inside) == nil then
|
|
||||||
continue = false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
starttime = adv_spawning.check_time(starttime, key .. " at environment check")
|
|
||||||
|
adv_spawning.quota_leave()
|
||||||
if not continue then
|
|
||||||
self.spawning_data[key] = value.spawn_interval * math.random()
|
|
||||||
else
|
|
||||||
self.spawning_data[key] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self.initialized_spawners == #adv_spawning.spawner_definitions
|
return self.initialized_spawners == #adv_spawning.spawner_definitions
|
||||||
|
|
Loading…
Reference in New Issue