diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua index 7b90c9f..ac29ace 100644 --- a/mesecons_mvps/init.lua +++ b/mesecons_mvps/init.lua @@ -133,31 +133,65 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky) return nodes end -function mesecon.mvps_push(pos, dir, maximum) - return mesecon.mvps_push_or_pull(pos, dir, dir, maximum) +local function prot_deny() return true end +local function prot_allow() return false end + +local function make_is_protected(player_name) + local mode = mesecon.setting("mvps_protection_mode", "normal") + if mode == "ignore" then + return prot_allow + end + if player_name == "" or not player_name then -- legacy MVPS + if mode == "normal" then + player_name = "$unknown" -- sentinel, for checking for *any* protection + elseif mode == "compat" then + return prot_allow + elseif mode == "restrict" then + return prot_deny + else + error("Invalid protection mode") + end + end + local is_protected = minetest.is_protected + return function(pos) + return is_protected(pos, player_name) + end end -function mesecon.mvps_pull_all(pos, dir, maximum) - return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, true) +function mesecon.mvps_push(pos, dir, maximum, player_name) + return mesecon.mvps_push_or_pull(pos, dir, dir, maximum, false, player_name) end -function mesecon.mvps_pull_single(pos, dir, maximum) - return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum) +function mesecon.mvps_pull_all(pos, dir, maximum, player_name) + return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, true, player_name) end --- pos: pos of mvps; stackdir: direction of building the stack +function mesecon.mvps_pull_single(pos, dir, maximum, player_name) + return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, false, player_name) +end + +-- pos: pos of mvps +-- stackdir: direction of building the stack -- movedir: direction of actual movement -- maximum: maximum nodes to be pushed -- all_pull_sticky: All nodes are sticky in the direction that they are pulled from -function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sticky) +-- player_name: Player responsible for the action. +-- - empty string means legacy MVPS, actual check depends on configuration +-- - "$unknown" is a sentinel for forcing the check +function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sticky, player_name) local nodes = mesecon.mvps_get_stack(pos, movedir, maximum, all_pull_sticky) if not nodes then return end -- determine if one of the nodes blocks the push / pull + local is_protected = make_is_protected(player_name) for id, n in ipairs(nodes) do if mesecon.is_mvps_stopper(n.node, movedir, nodes, id) then return end + if is_protected(n.pos) then + minetest.record_protection_violation(n.pos, player_name) + return + end end -- remove all nodes diff --git a/settingtypes.txt b/settingtypes.txt index 9259a83..6aab9da 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -28,6 +28,17 @@ mesecon.luacontroller_memsize (Controller memory limit) int 100000 10000 1000000 # IID is ignored and at most one interrupt may be queued if this setting is enabled. mesecon.luacontroller_lightweight_interrupts (Lightweight interrupts) bool false +[mesecons_mvps] + +# In pre-existing world, MVPS may not be labelled with the owner. +# Protection handling for them is configurable. +# - normal: allow legacy MVPS to work in unprotected areas only +# - compat: allow legacy MVPS to work everywhere +# - ignore: allow all MVPS to work everywhere +# - restrict: disallow legacy MVPS +# Note that new unowned (e.g. machine-placed) MVPS are always +# handled as in `normal` mode. +mesecon.mvps_protection_mode (MVPS [movestones, pistons] protection handling) enum normal normal,compat,ignore,restrict [mesecons_movestones]