Fix spawners could be moved to non integer positions causing relative y-pos check to always faile
Add comments Show reason why spawner didn't spawn last time in spawner debug info
This commit is contained in:
parent
15e5a72a9a
commit
ba0b80282e
2
init.lua
2
init.lua
@ -8,7 +8,7 @@
|
|||||||
--
|
--
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
local version = "0.0.9"
|
local version = "0.0.10"
|
||||||
|
|
||||||
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")
|
||||||
|
78
internal.lua
78
internal.lua
@ -373,7 +373,7 @@ end
|
|||||||
-- @param minp (OPTIONAL) override spawner defaults
|
-- @param minp (OPTIONAL) override spawner defaults
|
||||||
-- @param maxp (OPTIONAL) override spawner defaults
|
-- @param maxp (OPTIONAL) override spawner defaults
|
||||||
-- @param ignore_active_area set to true for mapgen spawning
|
-- @param ignore_active_area set to true for mapgen spawning
|
||||||
-- @return successfull true/false, permanent_error true,false
|
-- @return successfull true/false, permanent_error true,false, reason_string
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_active_area)
|
function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_active_area)
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
|
|
||||||
if not adv_spawning.check_daytime(spawndef.daytimes) then
|
if not adv_spawning.check_daytime(spawndef.daytimes) then
|
||||||
adv_spawning.log("info","didn't meet daytime check")
|
adv_spawning.log("info","didn't meet daytime check")
|
||||||
return false,nil
|
return false,nil, "daytimecheck failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
local max_x = spawnerpos.x + adv_spawning.spawner_distance/2
|
local max_x = spawnerpos.x + adv_spawning.spawner_distance/2
|
||||||
@ -412,15 +412,16 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
new_pos.x = math.random(min_x,max_x)
|
new_pos.x = math.random(min_x,max_x)
|
||||||
new_pos.z = math.random(min_z,max_z)
|
new_pos.z = math.random(min_z,max_z)
|
||||||
|
|
||||||
|
local yreason = "ukn"
|
||||||
|
|
||||||
--check if entity is configured to spawn at surface
|
--check if entity is configured to spawn at surface
|
||||||
if spawndef.relative_height == nil or
|
if spawndef.relative_height == nil or
|
||||||
(spawndef.relative_height.max ~= nil and
|
(spawndef.relative_height.max ~= nil and
|
||||||
spawndef.relative_height.max <= 1) then
|
spawndef.relative_height.max <= 1) then
|
||||||
new_pos.y = adv_spawning.get_surface(lower_y,upper_y,new_pos,
|
new_pos.y, yreason = adv_spawning.get_surface(lower_y,upper_y,new_pos,
|
||||||
spawndef.spawn_inside)
|
spawndef.spawn_inside)
|
||||||
else
|
else
|
||||||
new_pos.y = adv_spawning.get_relative_pos(lower_y,upper_y,new_pos,
|
new_pos.y, yreason = adv_spawning.get_relative_pos(lower_y,upper_y,new_pos,
|
||||||
spawndef.spawn_inside,
|
spawndef.spawn_inside,
|
||||||
spawndef.relative_height,
|
spawndef.relative_height,
|
||||||
spawndef.absolute_height)
|
spawndef.absolute_height)
|
||||||
@ -432,21 +433,22 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't find a suitable y pos "
|
minetest.pos_to_string(new_pos) .. " didn't find a suitable y pos "
|
||||||
.. lower_y .. "<-->" .. upper_y )
|
.. lower_y .. "<-->" .. upper_y )
|
||||||
return false,nil
|
return false, nil, "didn't find a valid ypos at " .. minetest.pos_to_string(new_pos)
|
||||||
|
.. " " .. lower_y .. "<-->" .. upper_y .. " rsn: " .. yreason
|
||||||
end
|
end
|
||||||
|
|
||||||
--check absolute height
|
--check absolute height
|
||||||
if not adv_spawning.check_absolute_height(new_pos,spawndef.absolute_height) then
|
if not adv_spawning.check_absolute_height(new_pos,spawndef.absolute_height) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet absolute height check")
|
minetest.pos_to_string(new_pos) .. " didn't meet absolute height check")
|
||||||
return false,true
|
return false, true, "absolute height check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check active area
|
--check active area
|
||||||
if not ignore_active_area and not adv_spawning.check_active_block(new_pos) then
|
if not ignore_active_area and not adv_spawning.check_active_block(new_pos) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet active area check")
|
minetest.pos_to_string(new_pos) .. " didn't meet active area check")
|
||||||
return false,nil
|
return false, nil , "area check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check surface
|
--check surface
|
||||||
@ -459,7 +461,7 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
minetest.pos_to_string(new_pos) ..
|
minetest.pos_to_string(new_pos) ..
|
||||||
" didn't meet surface check, is: " ..
|
" didn't meet surface check, is: " ..
|
||||||
minetest.get_node({x=new_pos.x,z=new_pos.z,y=new_pos.y-1}).name)
|
minetest.get_node({x=new_pos.x,z=new_pos.z,y=new_pos.y-1}).name)
|
||||||
return false,nil
|
return false, nil, "surface check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--flat area check
|
--flat area check
|
||||||
@ -470,7 +472,7 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
spawndef.surfaces) then
|
spawndef.surfaces) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet flat area check")
|
minetest.pos_to_string(new_pos) .. " didn't meet flat area check")
|
||||||
return false,nil
|
return false, nil, "flat area check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check collisionbox
|
--check collisionbox
|
||||||
@ -485,28 +487,28 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
if not checkresult then
|
if not checkresult then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet collisionbox check")
|
minetest.pos_to_string(new_pos) .. " didn't meet collisionbox check")
|
||||||
return false,nil
|
return false, nil, "collision box check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check entities around
|
--check entities around
|
||||||
if not adv_spawning.check_entities_around(new_pos,spawndef.entities_around) then
|
if not adv_spawning.check_entities_around(new_pos,spawndef.entities_around) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet entities check")
|
minetest.pos_to_string(new_pos) .. " didn't meet entities check")
|
||||||
return false,nil
|
return false, nil, "entitie around check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check nodes around
|
--check nodes around
|
||||||
if not adv_spawning.check_nodes_around(new_pos,spawndef.nodes_around) then
|
if not adv_spawning.check_nodes_around(new_pos,spawndef.nodes_around) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet nodes check")
|
minetest.pos_to_string(new_pos) .. " didn't meet nodes check")
|
||||||
return false,nil
|
return false, nil, "nodes around check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check light around
|
--check light around
|
||||||
if not adv_spawning.check_light_around(new_pos,spawndef.light_around) then
|
if not adv_spawning.check_light_around(new_pos,spawndef.light_around) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet light check")
|
minetest.pos_to_string(new_pos) .. " didn't meet light check")
|
||||||
return false,nil
|
return false, nil, "light check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ONLY use this if you have luajit
|
-- ONLY use this if you have luajit
|
||||||
@ -514,31 +516,37 @@ function adv_spawning.handlespawner(spawnername,spawnerpos,minp,maxp,ignore_acti
|
|||||||
-- if not adv_spawning.check_light_around_voxel(new_pos,spawndef.light_around) then
|
-- if not adv_spawning.check_light_around_voxel(new_pos,spawndef.light_around) then
|
||||||
-- adv_spawning.log("info",
|
-- adv_spawning.log("info",
|
||||||
-- minetest.pos_to_string(new_pos) .. " didn't meet light check")
|
-- minetest.pos_to_string(new_pos) .. " didn't meet light check")
|
||||||
-- return false,nil
|
-- return false, nil, "luajit light check failed"
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
--check humidity
|
--check humidity
|
||||||
if not adv_spawning.check_humidity_around(new_pos,spawndef.humidity_around) then
|
if not adv_spawning.check_humidity_around(new_pos,spawndef.humidity_around) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet humidity check")
|
minetest.pos_to_string(new_pos) .. " didn't meet humidity check")
|
||||||
return false,nil
|
return false, nil, "humidity check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--check temperature
|
--check temperature
|
||||||
if not adv_spawning.check_temperature_around(new_pos,spawndef.temperature_around) then
|
if not adv_spawning.check_temperature_around(new_pos,spawndef.temperature_around) then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet temperature check")
|
minetest.pos_to_string(new_pos) .. " didn't meet temperature check")
|
||||||
return false,nil
|
return false, nil, "temperature check failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
--custom check
|
--custom check
|
||||||
if (spawndef.custom_check ~= nil and
|
if (spawndef.custom_check ~= nil and
|
||||||
type(spawndef.custom_check) == "function") then
|
type(spawndef.custom_check) == "function") then
|
||||||
|
|
||||||
if not spawndef.custom_check(new_pos,spawndef) then
|
local retval, reason = spawndef.custom_check(new_pos,spawndef)
|
||||||
|
|
||||||
|
if not reason then
|
||||||
|
reason = "custom check failed"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not retval then
|
||||||
adv_spawning.log("info",
|
adv_spawning.log("info",
|
||||||
minetest.pos_to_string(new_pos) .. " didn't meet custom check")
|
minetest.pos_to_string(new_pos) .. " didn't meet custom check")
|
||||||
return false,nil
|
return false, nil, reason
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -570,30 +578,47 @@ function adv_spawning.get_surface(y_min,y_max,new_pos,spawn_inside)
|
|||||||
local top_pos = { x=new_pos.x, z=new_pos.z, y=y_max}
|
local top_pos = { x=new_pos.x, z=new_pos.z, y=y_max}
|
||||||
local bottom_pos = { x=new_pos.x, z=new_pos.z, y=y_min}
|
local bottom_pos = { x=new_pos.x, z=new_pos.z, y=y_min}
|
||||||
|
|
||||||
|
-- get list of all nodes within our y-range we could spawn within
|
||||||
local spawnable_nodes =
|
local spawnable_nodes =
|
||||||
minetest.find_nodes_in_area(bottom_pos, top_pos, spawn_inside)
|
minetest.find_nodes_in_area(bottom_pos, top_pos, spawn_inside)
|
||||||
|
|
||||||
|
-- if there ain't a single node to spawn within get out of here
|
||||||
if #spawnable_nodes == 0 then
|
if #spawnable_nodes == 0 then
|
||||||
return nil
|
return nil, "no spawnable nodes at all"
|
||||||
end
|
end
|
||||||
|
|
||||||
local spawnable_node_passed = false
|
local spawnable_node_passed = false
|
||||||
|
|
||||||
|
-- loop from topmost position to bottom
|
||||||
for i=y_max, y_min, -1 do
|
for i=y_max, y_min, -1 do
|
||||||
|
-- get current position
|
||||||
local pos = { x=new_pos.x,z=new_pos.z,y=i}
|
local pos = { x=new_pos.x,z=new_pos.z,y=i}
|
||||||
|
|
||||||
|
-- if the node at current position ain't one of those we can spawn within
|
||||||
if not adv_spawning.contains_pos(spawnable_nodes,pos) then
|
if not adv_spawning.contains_pos(spawnable_nodes,pos) then
|
||||||
|
|
||||||
|
-- get more information about this node
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
|
|
||||||
|
local text = "false"
|
||||||
|
|
||||||
|
if spawnable_node_passed then
|
||||||
|
text = "true"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if node ain't unloaded and we did already see a spawnable node above
|
||||||
|
-- return position above as pos to spawn
|
||||||
if node.name ~= "ignore" and
|
if node.name ~= "ignore" and
|
||||||
spawnable_node_passed then
|
spawnable_node_passed then
|
||||||
return i+1
|
return i+1, "pos found"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
-- set marker about having seen a spawnable node above
|
||||||
spawnable_node_passed = true
|
spawnable_node_passed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil, "no matching node, nodecnt: " .. #spawnable_nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -612,7 +637,8 @@ function adv_spawning.get_relative_pos(y_min,y_max,new_pos,spawn_inside,relative
|
|||||||
if y_val == nil then
|
if y_val == nil then
|
||||||
if (relative_height.min ~= nil or
|
if (relative_height.min ~= nil or
|
||||||
relative_height.max ~= nil) then
|
relative_height.max ~= nil) then
|
||||||
return nil
|
return nil, "y_pos not witing range of "
|
||||||
|
.. relative_height.min .. "<-->" .. relative_height.max
|
||||||
else
|
else
|
||||||
y_val = y_min
|
y_val = y_min
|
||||||
end
|
end
|
||||||
@ -636,17 +662,17 @@ function adv_spawning.get_relative_pos(y_min,y_max,new_pos,spawn_inside,relative
|
|||||||
|
|
||||||
if top_pos.y < bottom_pos.y then
|
if top_pos.y < bottom_pos.y then
|
||||||
--print("Invalid interval: " .. bottom_pos.y .. "<-->" .. top_pos.y)
|
--print("Invalid interval: " .. bottom_pos.y .. "<-->" .. top_pos.y)
|
||||||
return nil
|
return nil, "invalid interval: " .. bottom_pos.y .. "<-->" .. top_pos.y
|
||||||
end
|
end
|
||||||
|
|
||||||
local spawnable_nodes =
|
local spawnable_nodes =
|
||||||
minetest.find_nodes_in_area(bottom_pos, top_pos, spawn_inside)
|
minetest.find_nodes_in_area(bottom_pos, top_pos, spawn_inside)
|
||||||
|
|
||||||
if #spawnable_nodes > 0 then
|
if #spawnable_nodes > 0 then
|
||||||
return spawnable_nodes[math.random(1,#spawnable_nodes)].y
|
return spawnable_nodes[math.random(1,#spawnable_nodes)].y, "rpos found"
|
||||||
else
|
else
|
||||||
--print("no suitable nodes" .. bottom_pos.y .. "<-->" .. top_pos.y)
|
--print("no suitable nodes" .. bottom_pos.y .. "<-->" .. top_pos.y)
|
||||||
return nil
|
return nil, "no spawnable nodes found around"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1225,7 +1251,7 @@ function adv_spawning.check_flat_area(new_pos,flat_area,spawn_inside,surfaces)
|
|||||||
|
|
||||||
local required_nodes = (range*2+1)*(range*2+1) - current_deviation
|
local required_nodes = (range*2+1)*(range*2+1) - current_deviation
|
||||||
|
|
||||||
if surface == nil then
|
if surfaces == nil then
|
||||||
local ground_nodes =
|
local ground_nodes =
|
||||||
minetest.find_nodes_in_area(back_left, front_right, spawn_inside)
|
minetest.find_nodes_in_area(back_left, front_right, spawn_inside)
|
||||||
|
|
||||||
|
@ -61,13 +61,17 @@ function adv_spawning.seed_step(self,dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
while tries > 0 do
|
while tries > 0 do
|
||||||
|
local successfull, permanent_error, reason =
|
||||||
|
adv_spawning.handlespawner(key,self.object:getpos())
|
||||||
|
|
||||||
if adv_spawning.handlespawner(key,self.object:getpos()) then
|
if successfull then
|
||||||
self.spawning_data[key] =
|
self.spawning_data[key] =
|
||||||
adv_spawning.spawner_definitions[key].spawn_interval
|
adv_spawning.spawner_definitions[key].spawn_interval
|
||||||
|
self.spawn_fail_reasons[key] = "successfull spawned"
|
||||||
else
|
else
|
||||||
self.spawning_data[key] =
|
self.spawning_data[key] =
|
||||||
adv_spawning.spawner_definitions[key].spawn_interval/4
|
adv_spawning.spawner_definitions[key].spawn_interval/4
|
||||||
|
self.spawn_fail_reasons[key] = reason
|
||||||
end
|
end
|
||||||
|
|
||||||
--check quota again
|
--check quota again
|
||||||
@ -117,9 +121,19 @@ function adv_spawning.seed_activate(self)
|
|||||||
adv_spawning.seed_validate_spawndata(self)
|
adv_spawning.seed_validate_spawndata(self)
|
||||||
|
|
||||||
self.pending_spawners = {}
|
self.pending_spawners = {}
|
||||||
|
self.spawn_fail_reasons = {}
|
||||||
self.initialized_spawners = 0
|
self.initialized_spawners = 0
|
||||||
self.activated = true
|
self.activated = true
|
||||||
|
|
||||||
|
-- fix unaligned own pos
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
|
||||||
|
pos.x = math.floor(pos.x + 0.5)
|
||||||
|
pos.y = math.floor(pos.y + 0.5)
|
||||||
|
pos.z = math.floor(pos.z + 0.5)
|
||||||
|
|
||||||
|
self.object:setpos(pos)
|
||||||
|
|
||||||
if not adv_spawning.quota_leave() then
|
if not adv_spawning.quota_leave() then
|
||||||
adv_spawning.dbg_log(2, "on activate " .. self.name .. " did use way too much time")
|
adv_spawning.dbg_log(2, "on activate " .. self.name .. " did use way too much time")
|
||||||
end
|
end
|
||||||
@ -138,7 +152,13 @@ function adv_spawning.on_rightclick(self, clicker)
|
|||||||
print("ADV_SPAWNING: Spawner may spawn " .. adv_spawning.table_count(self.spawning_data) .. " mobs:")
|
print("ADV_SPAWNING: Spawner may spawn " .. adv_spawning.table_count(self.spawning_data) .. " mobs:")
|
||||||
local index = 1
|
local index = 1
|
||||||
for key,value in pairs(self.spawning_data) do
|
for key,value in pairs(self.spawning_data) do
|
||||||
print(string.format("%3d:",index) .. string.format("%30s ",key) .. string.format("%3d s", value))
|
local reason = "unknown"
|
||||||
|
|
||||||
|
if self.spawn_fail_reasons[key] then
|
||||||
|
reason = self.spawn_fail_reasons[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
print(string.format("%3d:",index) .. string.format("%30s ",key) .. string.format("%3d s (", value) .. reason .. ")")
|
||||||
index = index +1
|
index = index +1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user