diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index d8f7a638..8b37dcc5 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -148,6 +148,49 @@ function core.record_protection_violation(pos, name) end end +-- Checks if specified volume intersects a protected volume +-- Backport from Minetest 5.0 + +function core.intersects_protection(minp, maxp, player_name, interval) + -- 'interval' is the largest allowed interval for the 3D lattice of checks. + + -- Compute the optimal float step 'd' for each axis so that all corners and + -- borders are checked. 'd' will be smaller or equal to 'interval'. + -- Subtracting 1e-4 ensures that the max co-ordinate will be reached by the + -- for loop (which might otherwise not be the case due to rounding errors). + + -- Default to 4 + interval = interval or 4 + local d = {} + + for _, c in pairs({"x", "y", "z"}) do + if maxp[c] > minp[c] then + d[c] = (maxp[c] - minp[c]) / + math.ceil((maxp[c] - minp[c]) / interval) - 1e-4 + elseif maxp[c] == minp[c] then + d[c] = 1 -- Any value larger than 0 to avoid division by zero + else -- maxp[c] < minp[c], print error and treat as protection intersected + minetest.log("error", "maxp < minp in 'minetest.intersects_protection()'") + return true + end + end + + for zf = minp.z, maxp.z, d.z do + local z = math.floor(zf + 0.5) + for yf = minp.y, maxp.y, d.y do + local y = math.floor(yf + 0.5) + for xf = minp.x, maxp.x, d.x do + local x = math.floor(xf + 0.5) + if core.is_protected({x = x, y = y, z = z}, player_name) then + return true + end + end + end + end + + return false +end + local raillike_ids = {} local raillike_cur_id = 0 function core.raillike_group(name) @@ -186,4 +229,3 @@ end function core.cancel_shutdown_requests() core.request_shutdown("", false, -1) end -