forked from MineClone5/MineClone5
Add limitations to respawn search algorithm to make it work faster
This commit is contained in:
parent
427ac03a4d
commit
81c27363a3
|
@ -9,6 +9,9 @@ local storage = minetest.get_mod_storage()
|
|||
|
||||
local respawn_search_interval = 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 biomes_white_list = {
|
||||
"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 dir_step = storage:get_int("mcl_spawn_dir_step") or 0
|
||||
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'.
|
||||
-- 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)
|
||||
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 pos0 = {x = pos.x, y = pos.y - 1, 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 (not player and minetest.get_node_light(pos1, 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
|
||||
return false
|
||||
end
|
||||
|
@ -128,9 +150,15 @@ local function good_for_respawn(pos, player)
|
|||
(def1.damage_per_second == nil or def2.damage_per_second <= 0)
|
||||
end
|
||||
|
||||
local function can_find_tree(pos1)
|
||||
local trees = minetest.find_nodes_in_area(vector.subtract(pos1,half_res), vector.add(pos1,half_res), {"group:tree"}, false)
|
||||
for _, pos2 in ipairs(trees) do
|
||||
local function can_find_tree(pos1, trees)
|
||||
if not emerge_pos1 or not emerge_pos2 then return false end
|
||||
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 pos2.x < pos1.x then
|
||||
pos2.x = pos2.x + 1
|
||||
|
@ -151,6 +179,29 @@ local function can_find_tree(pos1)
|
|||
return false
|
||||
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()
|
||||
if edge_dist >= edge_len then
|
||||
edge_dist = 1
|
||||
|
@ -208,16 +259,20 @@ end
|
|||
|
||||
local function ecb_search_continue(blockpos, action, calls_remaining, param)
|
||||
if calls_remaining <= 0 then
|
||||
local 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}
|
||||
local nodes = minetest.find_nodes_in_area_under_air(pos1, pos2, node_groups_white_list)
|
||||
emerge_pos1 = {x = wsp.x-half_res, y = alt_min, 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(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")
|
||||
if nodes then
|
||||
for i=1, #nodes do
|
||||
wsp = nodes[i]
|
||||
local trees = get_trees(emerge_pos1, emerge_pos2)
|
||||
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
|
||||
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))
|
||||
searched = true
|
||||
success = true
|
||||
|
@ -225,6 +280,22 @@ local function ecb_search_continue(blockpos, action, calls_remaining, param)
|
|||
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
|
||||
next_pos()
|
||||
mcl_spawn.search()
|
||||
|
|
Loading…
Reference in New Issue