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.
This commit is contained in:
parent
646711fe8e
commit
a1b2df3941
@ -1,6 +1,6 @@
|
||||
-- LUALOCALS < ---------------------------------------------------------
|
||||
local math, minetest, nodecore, string, tonumber
|
||||
= math, minetest, nodecore, string, tonumber
|
||||
local math, minetest, nodecore, string, tonumber, vector
|
||||
= math, minetest, nodecore, string, tonumber, vector
|
||||
local math_floor, string_format
|
||||
= math.floor, string.format
|
||||
-- LUALOCALS > ---------------------------------------------------------
|
||||
@ -11,17 +11,74 @@ local chunksize = tonumber(minetest.get_mapgen_setting("chunksize")) or 5
|
||||
chunksize = chunksize * 16
|
||||
local limitchunks = math_floor(limit / chunksize)
|
||||
|
||||
nodecore.map_limit_min = (-limitchunks + 0.5) * chunksize + 7.5
|
||||
nodecore.map_limit_max = (limitchunks - 0.5) * chunksize + 7.5
|
||||
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 >= nodecore.map_limit_min
|
||||
and pos.y >= nodecore.map_limit_min
|
||||
and pos.z >= nodecore.map_limit_min
|
||||
and pos.x <= nodecore.map_limit_max
|
||||
and pos.y <= nodecore.map_limit_max
|
||||
and pos.z <= nodecore.map_limit_max
|
||||
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
|
||||
|
@ -404,10 +404,6 @@ function nodecore.grav_air_accel_ent(obj)
|
||||
return obj:set_acceleration(new)
|
||||
end
|
||||
|
||||
function nodecore.near_unloaded(pos, radius)
|
||||
return minetest.find_node_near(pos, radius or 1, {"ignore"}, true)
|
||||
end
|
||||
|
||||
function nodecore.get_objects_at_pos(pos)
|
||||
pos = vector.round(pos)
|
||||
local t = {}
|
||||
|
17
mods/nc_api_active/abmarea.lua
Normal file
17
mods/nc_api_active/abmarea.lua
Normal file
@ -0,0 +1,17 @@
|
||||
-- LUALOCALS < ---------------------------------------------------------
|
||||
local minetest, nodecore
|
||||
= minetest, nodecore
|
||||
-- LUALOCALS > ---------------------------------------------------------
|
||||
|
||||
local oldreg = minetest.register_abm
|
||||
function minetest.register_abm(def)
|
||||
if def.arealoaded then
|
||||
local dist = def.arealoaded
|
||||
local oldact = def.action
|
||||
def.action = function(pos, node, ...)
|
||||
if nodecore.near_unloaded(pos, node, dist) then return end
|
||||
return oldact(pos, node, ...)
|
||||
end
|
||||
end
|
||||
return oldreg(def)
|
||||
end
|
@ -13,6 +13,7 @@ end
|
||||
|
||||
include("abmmux")
|
||||
include("abminvert")
|
||||
include("abmarea")
|
||||
include("stasis")
|
||||
include("dnts")
|
||||
include("aism")
|
||||
|
@ -96,6 +96,7 @@ function nodecore.register_cook_abm(def)
|
||||
def.label = def.label or "cook " .. minetest.write_json(def.nodenames)
|
||||
def.interval = def.interval or 1
|
||||
def.chance = def.chance or 1
|
||||
def.arealoaded = def.arealoaded or 1
|
||||
def.action = cookcheck
|
||||
nodecore.group_expand(def.nodenames, function(k) cooknames[k] = true end)
|
||||
minetest.register_abm(def)
|
||||
|
@ -83,6 +83,7 @@ nodecore.register_soaking_abm({
|
||||
fieldname = "repack",
|
||||
nodenames = {"group:loose_repack"},
|
||||
interval = 10,
|
||||
arealoaded = 1,
|
||||
soakrate = function(pos, node)
|
||||
local def = minetest.registered_items[node.name] or {}
|
||||
if def.no_repack or def.no_self_repack then return end
|
||||
|
@ -81,6 +81,7 @@ minetest.register_abm({
|
||||
neighbors = {"air"},
|
||||
interval = 2,
|
||||
chance = 5,
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
if not reposeq then
|
||||
reposeq = {}
|
||||
|
@ -89,6 +89,7 @@ nodecore.register_soaking_abm({
|
||||
interval = 1,
|
||||
nodenames = {"group:concrete_etchable"},
|
||||
fieldname = "plycuring",
|
||||
arealoaded = 1,
|
||||
soakrate = function(pos)
|
||||
if minetest.find_node_near(pos,
|
||||
1, {"group:concrete_flow", "group:water"}) then
|
||||
|
@ -103,6 +103,7 @@ nodecore.register_soaking_abm({
|
||||
interval = 5,
|
||||
nodenames = {"group:concrete_source"},
|
||||
fieldname = "curing",
|
||||
arealoaded = 1,
|
||||
soakrate = function(pos)
|
||||
if minetest.find_node_near(pos,
|
||||
1, {"group:concrete_flow", "group:water"}) then
|
||||
|
@ -48,6 +48,7 @@ do
|
||||
label = "fire consume",
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
arealoaded = 1,
|
||||
nodenames = {modname .. ":fire"},
|
||||
action = function(pos)
|
||||
sparks_add(pos)
|
||||
@ -75,6 +76,7 @@ minetest.register_abm({
|
||||
nodenames = {"group:flammable"},
|
||||
neighbors = {"group:igniter"},
|
||||
neighbors_invert = true,
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
nodecore.fire_check_ignite(pos)
|
||||
end
|
||||
@ -85,6 +87,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
nodenames = {"group:ember"},
|
||||
arealoaded = 1,
|
||||
action = function(pos, node)
|
||||
local snuff, vents = nodecore.fire_check_snuff(pos, node)
|
||||
if snuff or not vents then return end
|
||||
|
@ -184,6 +184,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 100,
|
||||
nodenames = {"group:flower_living"},
|
||||
arealoaded = 2,
|
||||
action = function(pos, node)
|
||||
local function die()
|
||||
local wilt = minetest.registered_items[node.name].flower_wilts_to
|
||||
|
@ -99,6 +99,7 @@ minetest.register_abm({
|
||||
label = "rush drying/spreading",
|
||||
interval = 1,
|
||||
chance = 50,
|
||||
arealoaded = 2,
|
||||
nodenames = {modname .. ":rush"},
|
||||
action = function(pos)
|
||||
local subst, below = rushcheck(pos)
|
||||
|
@ -113,6 +113,7 @@ minetest.register_abm({
|
||||
label = "sedge growth/death",
|
||||
interval = 2,
|
||||
chance = 250,
|
||||
arealoaded = 1,
|
||||
nodenames = {"group:flora_sedges"},
|
||||
action = function(pos, node)
|
||||
local below = {x = pos.x, y = pos.y - 1, z = pos.z}
|
||||
|
@ -72,6 +72,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 2,
|
||||
nodenames = {"group:amalgam"},
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
if nodecore.quenched(pos) then return end
|
||||
return nodecore.set_loud(pos, {name = lavasrc})
|
||||
|
@ -52,6 +52,7 @@ minetest.register_abm({
|
||||
chance = 2,
|
||||
nodenames = {pumname},
|
||||
neighbors = {"group:lava"},
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
if math_random() < 0.95 and nodecore.quenched(pos) then return end
|
||||
nodecore.set_loud(pos, {name = "nc_terrain:lava_flowing", param2 = 7})
|
||||
|
@ -51,6 +51,7 @@ minetest.register_abm({
|
||||
nodenames = {"group:visinv"},
|
||||
interval = 2,
|
||||
chance = 1,
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
if nevermatch[nodecore.stack_get(pos):get_name()] then return end
|
||||
return nodecore.dnt_set(pos, dntname)
|
||||
|
@ -29,6 +29,7 @@ minetest.register_abm({
|
||||
nodenames = {cracked},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
if nodecore.quenched(pos) or #nodecore.find_nodes_around(
|
||||
pos, "group:flame", 1) < 1 then
|
||||
|
@ -72,6 +72,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 2,
|
||||
nodenames = {modname .. ":flux_source"},
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
for _, v in pairs(indirs) do
|
||||
local p = vector.add(pos, v)
|
||||
|
@ -8,6 +8,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 2,
|
||||
nodenames = {"group:lux_cobble"},
|
||||
arealoaded = 1,
|
||||
action = function(pos, node)
|
||||
local qty = nodecore.lux_react_qty(pos)
|
||||
local name = node.name:gsub("cobble%d", "cobble" .. qty)
|
||||
|
@ -10,6 +10,7 @@ nodecore.register_soaking_abm({
|
||||
fieldname = "lavalux",
|
||||
interval = 10,
|
||||
nodenames = {"group:amalgam"},
|
||||
arealoaded = 14,
|
||||
soakrate = nodecore.lux_soak_rate,
|
||||
soakcheck = function(data, pos)
|
||||
if data.total < 12500 then return end
|
||||
|
@ -11,6 +11,7 @@ minetest.register_abm({
|
||||
chance = 1,
|
||||
nodenames = {"group:" .. modname},
|
||||
ignore_stasis = true,
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
local data = minetest.get_meta(pos):get_string("data")
|
||||
if (not data) or (data == "") then
|
||||
|
@ -54,6 +54,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 100,
|
||||
nodenames = {modname .. ":sponge_wet"},
|
||||
arealoaded = 1,
|
||||
action = function(pos)
|
||||
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
|
||||
if nodecore.is_full_sun(above) and #findwater(pos) < 1 then
|
||||
|
@ -76,6 +76,7 @@ minetest.register_abm({
|
||||
interval = 1,
|
||||
chance = 10,
|
||||
nodenames = {living},
|
||||
arealoaded = 1,
|
||||
action = function(pos, node)
|
||||
if not spongesurvive({pos = pos, node = node}) then
|
||||
nodecore.set_loud(pos, {name = wet})
|
||||
@ -109,9 +110,9 @@ nodecore.register_soaking_abm({
|
||||
nodenames = {living},
|
||||
interval = 5,
|
||||
chance = 2,
|
||||
arealoaded = 6,
|
||||
soakrate = function() return 2 end,
|
||||
soakcheck = function(data, pos)
|
||||
if nodecore.near_unloaded(pos) then return end
|
||||
if data.total < basecost then return end
|
||||
|
||||
local count = 0
|
||||
|
@ -72,6 +72,7 @@ minetest.register_abm({
|
||||
label = "artificial water check",
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
arealoaded = 1,
|
||||
nodenames = {graywatersrc},
|
||||
action = function(pos) return nodecore.artificial_water_check(pos) end
|
||||
})
|
||||
|
@ -38,9 +38,9 @@ nodecore.register_soaking_abm({
|
||||
fieldname = "eggcorn",
|
||||
nodenames = {modname .. ":eggcorn_planted"},
|
||||
interval = 10,
|
||||
arealoaded = 1,
|
||||
soakrate = nodecore.tree_growth_rate,
|
||||
soakcheck = function(data, pos)
|
||||
if nodecore.near_unloaded(pos) then return end
|
||||
if data.total >= sproutcost then
|
||||
nodecore.node_sound(pos, "dig")
|
||||
nodecore.set_loud(pos, {name = modname .. ":root"})
|
||||
@ -77,9 +77,9 @@ nodecore.register_soaking_abm({
|
||||
fieldname = "treegrow",
|
||||
nodenames = {modname .. ":tree_bud"},
|
||||
interval = 10,
|
||||
arealoaded = 1,
|
||||
soakrate = nodecore.tree_trunk_growth_rate,
|
||||
soakcheck = function(data, pos, node)
|
||||
if nodecore.near_unloaded(pos) then return end
|
||||
if data.total < trunkcost then
|
||||
return growparticles(pos, data.rate, 0.45)
|
||||
end
|
||||
@ -131,12 +131,12 @@ nodecore.register_soaking_abm({
|
||||
nodenames = {modname .. ":leaves_bud"},
|
||||
fieldname = "leafgrow",
|
||||
interval = 10,
|
||||
arealoaded = 1,
|
||||
soakrate = function(pos)
|
||||
local rate = minetest.get_meta(pos):get_float("growrate") or 0
|
||||
return rate and rate ~= 0 and rate or 10
|
||||
end,
|
||||
soakcheck = function(data, pos, node)
|
||||
if nodecore.near_unloaded(pos) then return end
|
||||
if data.total < leafcost then return end
|
||||
|
||||
nodecore.set_loud(pos, nodecore.calc_leaves(pos))
|
||||
|
@ -22,6 +22,7 @@ function nodecore.register_dirt_leaching(fromnode, tonode, rate)
|
||||
fieldname = "leach",
|
||||
nodenames = {fromnode},
|
||||
interval = 5,
|
||||
arealoaded = 1,
|
||||
quickcheck = function(pos)
|
||||
return waterat(pos, 0, 1, 0)
|
||||
end,
|
||||
|
Loading…
x
Reference in New Issue
Block a user