From 15e743629e60fd7b588383c4fd855d51d1859693 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 20 Sep 2019 23:04:52 +0000 Subject: Respect protection in MVPS (#466) --- mesecons_mvps/init.lua | 85 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'mesecons_mvps/init.lua') diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua index 7b90c9f..1b300aa 100644 --- a/mesecons_mvps/init.lua +++ b/mesecons_mvps/init.lua @@ -133,31 +133,100 @@ 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) +function mesecon.mvps_set_owner(pos, placer) + local meta = minetest.get_meta(pos) + local owner = placer and placer.get_player_name and placer:get_player_name() + if owner and owner ~= "" then + meta:set_string("owner", owner) + else + meta:set_string("owner", "$unknown") -- to distinguish from older pistons + 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_claim(pos, player_name) + if not player_name or player_name == "" then return end + local meta = minetest.get_meta(pos) + if meta:get_string("infotext") == "" then return end + if meta:get_string("owner") == player_name then return end -- already owned + if minetest.is_protected(pos, player_name) then + minetest.chat_send_player(player_name, "Can't reclaim: protected") + return + end + meta:set_string("owner", player_name) + meta:set_string("infotext", "") + return true end -function mesecon.mvps_pull_single(pos, dir, maximum) - return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum) +local function add_pos(positions, pos) + local hash = minetest.hash_node_position(pos) + positions[hash] = pos +end + +local function are_protected(positions, player_name) + local mode = mesecon.setting("mvps_protection_mode", "normal") + if mode == "ignore" then + return false + end + local name = player_name + if player_name == "" or not player_name then -- legacy MVPS + if mode == "normal" then + name = "$unknown" -- sentinel, for checking for *any* protection + elseif mode == "compat" then + return false + elseif mode == "restrict" then + return true + else + error("Invalid protection mode") + end + end + local is_protected = minetest.is_protected + for _, pos in pairs(positions) do + if is_protected(pos, name) then + return true + end + end + return false end --- pos: pos of mvps; stackdir: direction of building the stack +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_all(pos, dir, maximum, player_name) + return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, true, player_name) +end + +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 + + local protection_check_set = {} + if vector.equals(stackdir, movedir) then -- pushing + add_pos(protection_check_set, pos) + end -- determine if one of the nodes blocks the push / pull for id, n in ipairs(nodes) do if mesecon.is_mvps_stopper(n.node, movedir, nodes, id) then return end + add_pos(protection_check_set, n.pos) + add_pos(protection_check_set, vector.add(n.pos, movedir)) + end + if are_protected(protection_check_set, player_name) then + return false, "protected" end -- remove all nodes -- cgit v1.2.3