nodecore-cd2025/mods/nc_api/mapgen_limits.lua
Aaron Suen a1b2df3941 Begin standardization of unload bounds check
- New near_unloaded API that supports custom
  distance parameter, map bounds check, and
  some optimizations.
- Add area automatic unload check support to ABM
  API and add to applicable ABMs, replacing many
  old manual checks.

Note that the explicit unload check is only strictly
necessary when something will happen due to
a node NOT being present in the area, e.g. something
igniting due to absent coolant, or soaking quantity
being reset due to missing sources.  In simple cases
where the absence of a thing causes the ABM to do
nothing, then the standard check can work because
the default action is to do nothing anyway.
2021-12-18 11:28:14 -05:00

85 lines
2.4 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore, string, tonumber, vector
= math, minetest, nodecore, string, tonumber, vector
local math_floor, string_format
= math.floor, string.format
-- LUALOCALS > ---------------------------------------------------------
local limit = tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000
local chunksize = tonumber(minetest.get_mapgen_setting("chunksize")) or 5
chunksize = chunksize * 16
local limitchunks = math_floor(limit / chunksize)
local min = (-limitchunks + 0.5) * chunksize + 7.5
nodecore.map_limit_min = min
local max = (limitchunks - 0.5) * chunksize + 7.5
nodecore.map_limit_max = max
nodecore.log("info", string_format("mapgen limit: %d, chunk: %d, bounds: %0.1f to %0.1f",
limit, chunksize, nodecore.map_limit_min, nodecore.map_limit_max))
function nodecore.within_map_limits(pos)
return pos.x >= min
and pos.y >= min
and pos.z >= min
and pos.x <= max
and pos.y <= max
and pos.z <= max
end
function nodecore.near_unloaded(pos, node, dist)
pos = vector.floor(pos)
if not (node or minetest.get_node_or_nil(pos)) then return true end
if (not dist) or (dist < 1) then return end
dist = math_floor(dist)
-- Clamp area to check to map bounds; areas outside the map
-- are always considered "loaded" and their ignores are
-- treated as canonical.
local zmin = pos.z - dist
if zmin < min then zmin = min end
local zmax = pos.z + dist
if zmax > max then zmax = max end
local ymin = pos.y - dist
if ymin < min then ymin = min end
local ymax = pos.y + dist
if ymax > max then ymax = max end
local xmin = pos.x - dist
if xmin < min then xmin = min end
local xmax = pos.x + dist
if xmax > max then xmax = max end
-- Check corners of area
local step = dist * 2
for z = zmin, zmax, step do
pos.z = z
for y = ymin, ymax, step do
pos.y = y
for x = xmin, xmax, step do
pos.x = x
if not minetest.get_node_or_nil(pos) then return true end
end
end
end
-- If area is wide enough to have entire mapblocks not
-- covered by the center and corners, then check each
-- mapblock in case internal ones are unloaded.
if dist <= 16 then return end
for z = zmin, zmax, 16 do
pos.z = z
for y = ymin, ymax, 16 do
pos.y = y
for x = xmin, xmax, 16 do
pos.x = x
if not minetest.get_node_or_nil(pos) then return true end
end
end
end
end