Merge pull request 'mcl_mobs spawning cleanup and performance optimization' () from mcl_mobs_cleanup into master

Reviewed-on: https://git.minetest.land/VoxeLibre/VoxeLibre/pulls/4468
Reviewed-by: kno10 <kno10@noreply.git.minetest.land>
This commit is contained in:
the-real-herowl 2025-01-20 18:37:09 +01:00
commit 62efc371a1
10 changed files with 728 additions and 588 deletions

View file

@ -25,6 +25,7 @@ read_globals = {
"indexof",
"insert_all",
"key_value_swap",
"shuffle",
}
},

View file

@ -4,66 +4,7 @@ local modname = core.get_current_modname()
local modpath = core.get_modpath(modname)
dofile(modpath.."/roman_numerals.lua")
dofile(modpath.."/nodes.lua")
-- Updates all values in t using values from to*.
function table.update(t, ...)
for _, to in ipairs {...} do
for k, v in pairs(to) do
t[k] = v
end
end
return t
end
-- Updates nil values in t using values from to*.
function table.update_nil(t, ...)
for _, to in ipairs {...} do
for k, v in pairs(to) do
if t[k] == nil then
t[k] = v
end
end
end
return t
end
---Works the same as `pairs`, but order returned by keys
---
---Taken from https://www.lua.org/pil/19.3.html
---@generic T: table, K, V, C
---@param t T
---@param f? fun(a: C, b: C):boolean
---@return fun():K, V
function table.pairs_by_keys(t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local function iter() -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
return a[i], t[a[i]]
end
end
return iter
end
-- Removes one element randomly selected from the array section of the table and
-- returns it, or nil if there are no elements in the array section of the table
function table.remove_random_element(table)
local count = #table
if count == 0 then return nil end
local idx = math.random(count)
local res = table[idx]
table[idx] = table[count]
table[count] = nil
count = count - 1
return res
end
dofile(modpath.."/table.lua")
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false)
local LOG_MODULE = "[MCL2]"

View file

@ -0,0 +1,77 @@
-- Updates all values in t using values from to*.
function table.update(t, ...)
for _, to in ipairs {...} do
for k, v in pairs(to) do
t[k] = v
end
end
return t
end
-- Updates nil values in t using values from to*.
function table.update_nil(t, ...)
for _, to in ipairs {...} do
for k, v in pairs(to) do
if t[k] == nil then
t[k] = v
end
end
end
return t
end
---Works the same as `pairs`, but order returned by keys
---
---Taken from https://www.lua.org/pil/19.3.html
---@generic T: table, K, V, C
---@param t T
---@param f? fun(a: C, b: C):boolean
---@return fun():K, V
function table.pairs_by_keys(t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local function iter() -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
return a[i], t[a[i]]
end
end
return iter
end
---@param a table
---@param b table
---@return table
function table.intersect(a, b)
local values_map = {}
for _,v in pairs(a) do values_map[v] = 1 end
-- Get all the values that are in both tables
local result = {}
for _,v in pairs(b) do
if values_map[v] then
result[#result + 1] = v
end
end
return result
end
-- Removes one element randomly selected from the array section of the table and
-- returns it, or nil if there are no elements in the array section of the table
function table.remove_random_element(table)
local count = #table
if count == 0 then return nil end
local idx = math.random(count)
local res = table[idx]
table[idx] = table[count]
table[count] = nil
count = count - 1
return res
end

View file

@ -36,13 +36,13 @@ end
-- nil, "void"
function mcl_worlds.y_to_layer(y)
if y >= mcl_vars.mg_overworld_min then
return y - mcl_vars.mg_overworld_min, "overworld"
return y - mcl_vars.mg_overworld_min, "overworld", 0
elseif y >= mcl_vars.mg_nether_min and y <= mcl_vars.mg_nether_max+128 then
return y - mcl_vars.mg_nether_min, "nether"
return y - mcl_vars.mg_nether_min, "nether", 1
elseif y >= mcl_vars.mg_end_min and y <= mcl_vars.mg_end_max then
return y - mcl_vars.mg_end_min, "end"
return y - mcl_vars.mg_end_min, "end", 2
else
return nil, "void"
return nil, "void", 3
end
end
@ -50,8 +50,8 @@ local y_to_layer = mcl_worlds.y_to_layer
-- Takes a pos and returns the dimension it belongs to (same as above)
function mcl_worlds.pos_to_dimension(pos)
local _, dim = y_to_layer(pos.y)
return dim
local _, dim, dim_id = y_to_layer(pos.y)
return dim, dim_id
end
local pos_to_dimension = mcl_worlds.pos_to_dimension

View file

@ -0,0 +1,27 @@
local default_seethru = {air = true}
---@param origin vector.Vector
---@param target vector.Vector
---@param seethru? {[string]: boolean} Set (look-up table) of nodes to treat as seethrough. Defaults to {air: true}
---@return boolean True if line-of-sight is blocked, false otherwise
function mcl_mobs.check_line_of_sight(origin, target, seethru)
seethru = seethru or default_seethru
local raycast = core.raycast(origin, target, false, true)
local los_blocked = false
for hitpoint in raycast do
if hitpoint.type == "node" then
--TODO: type object could block vision, for example minecarts
local node = core.get_node(core.get_pointed_thing_position(hitpoint))
if not seethru[node.name] then
local nodef = core.registered_nodes[node.name]
if nodef and nodef.walkable then
los_blocked = true
break
end
end
end
end
return not los_blocked
end

View file

@ -18,6 +18,7 @@ local node_ok = function(pos, fallback)
return minetest.registered_nodes[fallback]
end
mcl_mobs.node_ok = node_ok
dofile(path .. "/functions.lua")
--api and helpers
-- effects: sounds and particles mostly

View file

@ -28,6 +28,7 @@ local vector_zero = vector.zero
local vector_copy = vector.copy
local vector_offset = vector.offset
local vector_distance = vector.distance
local raycast_line_of_sight = mcl_mobs.check_line_of_sight
local registered_fallback_node = minetest.registered_nodes[mcl_mobs.fallback_node]
@ -63,26 +64,6 @@ function mob_class:is_node_waterhazard(nodename)
end
local function raycast_line_of_sight(origin, target)
local raycast = minetest.raycast(origin, target, false, true)
local los_blocked = false
for hitpoint in raycast do
if hitpoint.type == "node" then
--TODO type object could block vision, for example chests
local node = minetest.get_node(minetest.get_pointed_thing_position(hitpoint))
if node.name ~= "air" then
local nodef = minetest.registered_nodes[node.name]
if nodef and nodef.walkable then
los_blocked = true
break
end
end
end
end
return not los_blocked
end
function mob_class:target_visible(origin)
if not origin then return end
if not self.attack then return end

File diff suppressed because it is too large Load diff

View file

@ -99,7 +99,19 @@ mcl_mobs.register_mob("mobs_mc:guardian", {
view_range = 16,
})
mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10, mobs_mc.water_level)
mcl_mobs:spawn_specific(
"mobs_mc:guardian", -- name
"overworld", -- dimension
"water", -- type_of_spawning
{}, -- no biomes, only spawn in structures
0, -- min_light
core.LIGHT_MAX+1, -- max_light
30, -- interval
25000, -- chance
2, -- aoc
mcl_vars.mg_overworld_min, -- min_height
mobs_mc.water_level - 10 -- max_height
)
mcl_mobs:non_spawn_specific("mobs_mc:guardian","overworld",0,minetest.LIGHT_MAX+1)
-- spawn eggs
mcl_mobs.register_egg("mobs_mc:guardian", S("Guardian"), "#5a8272", "#f17d31", 0)

View file

@ -112,7 +112,19 @@ mcl_mobs.register_mob("mobs_mc:guardian_elder", {
},
})
mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18, mobs_mc.water_level)
mcl_mobs:spawn_specific(
"mobs_mc:guardian_elder", -- name
"overworld", -- dimension
"water", -- type_of_spawning
{}, -- no biomes, only spawn in structures
0, -- min_light
core.LIGHT_MAX+1, -- max_light
30, -- interval
40000, -- chance
2, -- aoc
mcl_vars.mg_overworld_min, -- min_height
mobs_mc.water_level - 18 -- max_height
)
-- spawn eggs
mcl_mobs.register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "#ceccba", "#747693", 0)