a1b2df3941
- 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.
85 lines
2.4 KiB
Lua
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
|