Add limitations to respawn search algorithm to make it work faster
This commit is contained in:
parent
427ac03a4d
commit
81c27363a3
1 changed files with 86 additions and 15 deletions
|
@ -9,6 +9,9 @@ local storage = minetest.get_mod_storage()
|
||||||
|
|
||||||
local respawn_search_interval = 30 -- seconds
|
local respawn_search_interval = 30 -- seconds
|
||||||
local respawn_search_initial_delay = 30 -- seconds
|
local respawn_search_initial_delay = 30 -- seconds
|
||||||
|
local trees_distance_max = 30 -- nodes
|
||||||
|
local attempts_to_find_pos = 50
|
||||||
|
local attempts_to_find_trees = 50
|
||||||
local node_groups_white_list = {"group:soil"}
|
local node_groups_white_list = {"group:soil"}
|
||||||
local biomes_white_list = {
|
local biomes_white_list = {
|
||||||
"ColdTaiga",
|
"ColdTaiga",
|
||||||
|
@ -74,6 +77,7 @@ local edge_len = storage:get_int("mcl_spawn_edge_len") or 1
|
||||||
local edge_dist = storage:get_int("mcl_spawn_edge_dist") or 0
|
local edge_dist = storage:get_int("mcl_spawn_edge_dist") or 0
|
||||||
local dir_step = storage:get_int("mcl_spawn_dir_step") or 0
|
local dir_step = storage:get_int("mcl_spawn_dir_step") or 0
|
||||||
local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1
|
local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1
|
||||||
|
local emerge_pos1, emerge_pos2
|
||||||
|
|
||||||
-- Get world 'mapgen_limit' and 'chunksize' to calculate 'spawn_limit'.
|
-- Get world 'mapgen_limit' and 'chunksize' to calculate 'spawn_limit'.
|
||||||
-- This accounts for how mapchunks are not generated if they or their shell exceed
|
-- This accounts for how mapchunks are not generated if they or their shell exceed
|
||||||
|
@ -96,6 +100,21 @@ local function get_far_node(pos)
|
||||||
return minetest.get_node(pos)
|
return minetest.get_node(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function get_trees(pos, pos2)
|
||||||
|
if emerge_pos1 and emerge_pos2 and pos then
|
||||||
|
if not pos2 then
|
||||||
|
local b1 = {x = math.max(pos.x-trees_distance_max, emerge_pos1.x), y = math.max(pos.y-trees_distance_max, emerge_pos1.y), z = math.max(pos.z-trees_distance_max, emerge_pos1.z)}
|
||||||
|
local b2 = {x = math.min(pos.x+trees_distance_max, emerge_pos2.x), y = math.min(pos.y+trees_distance_max, emerge_pos2.y), z = math.min(pos.z+trees_distance_max, emerge_pos2.z)}
|
||||||
|
return minetest.find_nodes_in_area(b1, b2, {"group:tree"}, false)
|
||||||
|
else
|
||||||
|
local b1 = {x = math.max(pos.x , emerge_pos1.x), y = math.max(pos.y , emerge_pos1.y), z = math.max(pos.z, emerge_pos1.z)}
|
||||||
|
local b2 = {x = math.min(pos2.x, emerge_pos2.x), y = math.min(pos2.y, emerge_pos2.y), z = math.min(pos2.z, emerge_pos2.z)}
|
||||||
|
return minetest.find_nodes_in_area(b1, b2, {"group:tree"}, false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function good_for_respawn(pos, player)
|
local function good_for_respawn(pos, player)
|
||||||
local pos0 = {x = pos.x, y = pos.y - 1, z = pos.z}
|
local pos0 = {x = pos.x, y = pos.y - 1, z = pos.z}
|
||||||
local pos1 = {x = pos.x, y = pos.y, z = pos.z}
|
local pos1 = {x = pos.x, y = pos.y, z = pos.z}
|
||||||
|
@ -116,6 +135,9 @@ local function good_for_respawn(pos, player)
|
||||||
or minetest.is_protected(pos2, player or "")
|
or minetest.is_protected(pos2, player or "")
|
||||||
or (not player and minetest.get_node_light(pos1, 0.5) < 8)
|
or (not player and minetest.get_node_light(pos1, 0.5) < 8)
|
||||||
or (not player and minetest.get_node_light(pos2, 0.5) < 8)
|
or (not player and minetest.get_node_light(pos2, 0.5) < 8)
|
||||||
|
or nn0 == "ignore"
|
||||||
|
or nn1 == "ignore"
|
||||||
|
or nn2 == "ignore"
|
||||||
then
|
then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -128,9 +150,15 @@ local function good_for_respawn(pos, player)
|
||||||
(def1.damage_per_second == nil or def2.damage_per_second <= 0)
|
(def1.damage_per_second == nil or def2.damage_per_second <= 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function can_find_tree(pos1)
|
local function can_find_tree(pos1, trees)
|
||||||
local trees = minetest.find_nodes_in_area(vector.subtract(pos1,half_res), vector.add(pos1,half_res), {"group:tree"}, false)
|
if not emerge_pos1 or not emerge_pos2 then return false end
|
||||||
for _, pos2 in ipairs(trees) do
|
local trees = trees or get_trees(pos1)
|
||||||
|
if not trees then return false end
|
||||||
|
|
||||||
|
if (attempts_to_find_trees * 3 < #trees) then
|
||||||
|
-- random search
|
||||||
|
for i = 1, attempts_to_find_trees do
|
||||||
|
local pos2 = trees[math.random(1,#trees)]
|
||||||
if not minetest.is_protected(pos2, "") then
|
if not minetest.is_protected(pos2, "") then
|
||||||
if pos2.x < pos1.x then
|
if pos2.x < pos1.x then
|
||||||
pos2.x = pos2.x + 1
|
pos2.x = pos2.x + 1
|
||||||
|
@ -151,6 +179,29 @@ local function can_find_tree(pos1)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for i, pos2 in ipairs(trees) do
|
||||||
|
-- full search
|
||||||
|
if not minetest.is_protected(pos2, "") then
|
||||||
|
if pos2.x < pos1.x then
|
||||||
|
pos2.x = pos2.x + 1
|
||||||
|
elseif pos2.x > pos1.x then
|
||||||
|
pos2.x = pos2.x - 1
|
||||||
|
end
|
||||||
|
if pos2.z < pos1.z then
|
||||||
|
pos2.z = pos2.z + 1
|
||||||
|
elseif pos2.z > pos1.z then
|
||||||
|
pos2.z = pos2.z - 1
|
||||||
|
end
|
||||||
|
local way = minetest.find_path(pos1, pos2, res, 1, 3, "A*_noprefetch")
|
||||||
|
if way then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if i > attempts_to_find_trees then return false end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local function next_pos()
|
local function next_pos()
|
||||||
if edge_dist >= edge_len then
|
if edge_dist >= edge_len then
|
||||||
edge_dist = 1
|
edge_dist = 1
|
||||||
|
@ -208,16 +259,20 @@ end
|
||||||
|
|
||||||
local function ecb_search_continue(blockpos, action, calls_remaining, param)
|
local function ecb_search_continue(blockpos, action, calls_remaining, param)
|
||||||
if calls_remaining <= 0 then
|
if calls_remaining <= 0 then
|
||||||
local pos1 = {x = wsp.x-half_res, y = alt_min, z = wsp.z-half_res}
|
emerge_pos1 = {x = wsp.x-half_res, y = alt_min, z = wsp.z-half_res}
|
||||||
local pos2 = {x = wsp.x+half_res, y = alt_max, z = wsp.z+half_res}
|
emerge_pos2 = {x = wsp.x+half_res, y = alt_max, z = wsp.z+half_res}
|
||||||
local nodes = minetest.find_nodes_in_area_under_air(pos1, pos2, node_groups_white_list)
|
local nodes = minetest.find_nodes_in_area_under_air(emerge_pos1, emerge_pos2, node_groups_white_list)
|
||||||
minetest.log("verbose", "[mcl_spawn] Data emerge callback: "..minetest.pos_to_string(wsp).." - "..tostring(nodes and #nodes) .. " node(s) found under air")
|
minetest.log("verbose", "[mcl_spawn] Data emerge callback: "..minetest.pos_to_string(wsp).." - "..tostring(nodes and #nodes) .. " node(s) found under air")
|
||||||
if nodes then
|
if nodes then
|
||||||
for i=1, #nodes do
|
local trees = get_trees(emerge_pos1, emerge_pos2)
|
||||||
wsp = nodes[i]
|
if trees then
|
||||||
|
if attempts_to_find_pos * 3 < #nodes then
|
||||||
|
-- random
|
||||||
|
for i=1, attempts_to_find_pos do
|
||||||
|
wsp = nodes[math.random(1,#nodes)]
|
||||||
if wsp then
|
if wsp then
|
||||||
wsp.y = wsp.y + 1
|
wsp.y = wsp.y + 1
|
||||||
if good_for_respawn(wsp) and can_find_tree(wsp) then
|
if good_for_respawn(wsp) and can_find_tree(wsp, trees) then
|
||||||
minetest.log("action", "[mcl_spawn] Dynamic world spawn determined to be "..minetest.pos_to_string(wsp))
|
minetest.log("action", "[mcl_spawn] Dynamic world spawn determined to be "..minetest.pos_to_string(wsp))
|
||||||
searched = true
|
searched = true
|
||||||
success = true
|
success = true
|
||||||
|
@ -225,6 +280,22 @@ local function ecb_search_continue(blockpos, action, calls_remaining, param)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
-- in a sequence
|
||||||
|
for i=1, math.min(#nodes, attempts_to_find_pos) do
|
||||||
|
wsp = nodes[i]
|
||||||
|
if wsp then
|
||||||
|
wsp.y = wsp.y + 1
|
||||||
|
if good_for_respawn(wsp) and can_find_tree(wsp, trees) then
|
||||||
|
minetest.log("action", "[mcl_spawn] Dynamic world spawn determined to be "..minetest.pos_to_string(wsp))
|
||||||
|
searched = true
|
||||||
|
success = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
next_pos()
|
next_pos()
|
||||||
mcl_spawn.search()
|
mcl_spawn.search()
|
||||||
|
|
Reference in a new issue