diff --git a/README.md b/README.md index 847a52f..bb1f636 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Protector Redo mod [protect] Protector redo for minetest is a mod that protects a players builds by placing a block that stops other players from digging or placing blocks in that area. -based on glomie's mod, remade by Zeg9 and reworked by TenPlus1. +based on glomie's mod, remade by Zeg9 and rewritten by TenPlus1. https://forum.minetest.net/viewtopic.php?f=11&t=9376 @@ -39,6 +39,8 @@ Change log: added support for "protection_bypass" privelage. 1.8 - Added 'protector_flip' setting to stop players using lag to grief into another players house, it flips them around to stop them digging. +1.9 - Renamed 'protector_pvp_spawn' setting to 'protector_spawn' which protects + an area around static spawnpoint. (note: previous name can still be used) Usage: (requires server privelage) @@ -66,8 +68,8 @@ protector_radius = 5 protector_pvp = true - true or false this setting disabled pvp inside of protected areas for all players apart from those listed on the protector node. -protector_pvp_spawn = 10 -- Sets an area 10 nodes around spawn where pvp is disabled completely. +protector_spawn = 10 +- Sets an area 10 nodes around static spawnpoint that is protected. protector_drop = true - When true players who dig inside a protected area will automatically drop tools to stop them going any further. diff --git a/doors_chest.lua b/doors_chest.lua index 074cf87..c7ba8de 100644 --- a/doors_chest.lua +++ b/doors_chest.lua @@ -1,7 +1,7 @@ -- Since the doors mod has changed in the latest daily builds I have taken the -- WTFPL licenced code from the old doors mod and included an edited version --- of it within this mod for local use. +-- within this mod for local use. local S = protector.intllib diff --git a/init.lua b/init.lua index 23ba87b..3d66fec 100644 --- a/init.lua +++ b/init.lua @@ -1,12 +1,20 @@ +-- older privelage for admins to rbypass protected nodes, do not use anymore +-- instead grant admin 'protection_bypass' privelage. minetest.register_privilege("delprotect","Ignore player protection") +-- get minetest.conf settings protector = {} protector.mod = "redo" -protector.radius = (tonumber(minetest.setting_get("protector_radius")) or 5) +protector.radius = tonumber(minetest.setting_get("protector_radius")) or 5 protector.drop = minetest.setting_getbool("protector_drop") or false protector.flip = minetest.setting_getbool("protector_flip") or false -protector.hurt = (tonumber(minetest.setting_get("protector_hurt")) or 0) +protector.hurt = tonumber(minetest.setting_get("protector_hurt")) or 0 +protector.spawn = tonumber(minetest.setting_get("protector_spawn") + or minetest.setting_get("protector_pvp_spawn")) or 0 + +-- get static spawn position +local statspawn = minetest.setting_get_pos("static_spawnpoint") or {x = 0, y = 2, z = 0} -- Intllib local S @@ -30,16 +38,19 @@ else end protector.intllib = S +-- return list of members as a table protector.get_member_list = function(meta) return meta:get_string("members"):split(" ") end +-- write member list table in protector meta as string protector.set_member_list = function(meta, list) meta:set_string("members", table.concat(list, " ")) end +-- check if player name is a member protector.is_member = function (meta, name) for _, n in pairs(protector.get_member_list(meta)) do @@ -52,6 +63,7 @@ protector.is_member = function (meta, name) return false end +-- add player name to table as member protector.add_member = function(meta, name) if protector.is_member(meta, name) then @@ -65,6 +77,7 @@ protector.add_member = function(meta, name) protector.set_member_list(meta, list) end +-- remove player name from table protector.del_member = function(meta, name) local list = protector.get_member_list(meta) @@ -80,8 +93,7 @@ protector.del_member = function(meta, name) protector.set_member_list(meta, list) end --- Protector Interface - +-- protector interface protector.generate_formspec = function(meta) local formspec = "size[8,7]" @@ -94,7 +106,7 @@ protector.generate_formspec = function(meta) .. "button_exit[2.5,6.2;3,0.5;close_me;" .. S("Close") .. "]" local members = protector.get_member_list(meta) - local npp = 12 -- max users added onto protector list + local npp = 12 -- max users added to protector list local i = 0 for n = 1, #members do @@ -131,6 +143,26 @@ protector.generate_formspec = function(meta) return formspec end +-- check if pos is inside a protected spawn area +local function inside_spawn(pos, radius) + + if protector.spawn <= 0 then + return false + end + + if pos.x < statspawn.x + radius + and pos.x > statspawn.x - radius + and pos.y < statspawn.y + radius + and pos.y > statspawn.y - radius + and pos.z < statspawn.z + radius + and pos.z > statspawn.z - radius then + + return true + end + + return false +end + -- Infolevel: -- 0 for no info -- 1 for "This area is owned by !" if you can't dig @@ -144,18 +176,27 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) return false end - -- Delprotect privileged users can override protections - + -- delprotect and protector_bypass privileged users can override protection if ( minetest.check_player_privs(digger, {delprotect = true}) or minetest.check_player_privs(digger, {protection_bypass = true}) ) and infolevel == 1 then return true end + -- infolevel 3 is only used to bypass priv check, change to 1 now if infolevel == 3 then infolevel = 1 end - -- Find the protector nodes + -- is spawn area protected ? + if inside_spawn(pos, protector.spawn) then + minetest.chat_send_player(digger, + S("Spawn @1 has been protected up to a @2 block radius.", + minetest.pos_to_string(statspawn), protector.spawn)) + + return false + end + + -- find the protector nodes local pos = minetest.find_nodes_in_area( {x = pos.x - r, y = pos.y - r, z = pos.z - r}, {x = pos.x + r, y = pos.y + r, z = pos.z + r}, @@ -169,35 +210,22 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) owner = meta:get_string("owner") or "" members = meta:get_string("members") or "" - if owner ~= digger then + -- node change and digger isn't owner + if owner ~= digger + and infolevel == 1 then + -- and you aren't on the member list if onlyowner or not protector.is_member(meta, digger) then - if infolevel == 1 then - - minetest.chat_send_player(digger, + minetest.chat_send_player(digger, S("This area is owned by @1!", owner)) - elseif infolevel == 2 then - - minetest.chat_send_player(digger, - S("This area is owned by @1.", owner)) - - minetest.chat_send_player(digger, - S("Protection located at: @1", minetest.pos_to_string(pos[n]))) - - if members ~= "" then - - minetest.chat_send_player(digger, - S("Members: @1.", members)) - end - end - - return false + return false end end + -- when using protector as tool, show protector information if infolevel == 2 then minetest.chat_send_player(digger, @@ -217,6 +245,7 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) end + -- show when you can build on unprotected area if infolevel == 2 then if #pos < 1 then @@ -231,12 +260,13 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) return true end --- Can node be added or removed, if so return node else true (for protected) protector.old_is_protected = minetest.is_protected +-- check for protected area, return true if protected and digger isn't on list function minetest.is_protected(pos, digger) + -- is area protected against digger? if not protector.can_dig(protector.radius, pos, digger, false, 1) then local player = minetest.get_player_by_name(digger) @@ -308,33 +338,45 @@ function minetest.is_protected(pos, digger) return true end + -- otherwise can dig or place return protector.old_is_protected(pos, digger) end --- Make sure protection block doesn't overlap another protector's area - +-- make sure protection block doesn't overlap another protector's area function protector.check_overlap(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" then return itemstack end - if not protector.can_dig(protector.radius * 2, pointed_thing.above, + local pos = pointed_thing.above + + -- make sure protector doesn't overlap onto protected spawn area + if inside_spawn(pos, protector.spawn + protector.radius) then + + minetest.chat_send_player(placer:get_player_name(), + S("Spawn @1 has been protected up to a @2 block radius.", + minetest.pos_to_string(statspawn), protector.spawn)) + + return itemstack + end + + -- make sure protector doesn't overlap any other player's area + if not protector.can_dig(protector.radius * 2, pos, placer:get_player_name(), true, 3) then minetest.chat_send_player(placer:get_player_name(), S("Overlaps into above players protected area")) - return + return itemstack end return minetest.item_place(itemstack, placer, pointed_thing) end ---= Protection Block - +-- protection node minetest.register_node("protector:protect", { description = S("Protection Block"), drawtype = "nodebox", @@ -413,8 +455,7 @@ minetest.register_craft({ } }) ---= Protection Logo - +-- protection logo minetest.register_node("protector:protect2", { description = S("Protection Logo"), tiles = {"protector_logo.png"}, @@ -494,20 +535,22 @@ minetest.register_craft({ } }) --- If name entered or button press - +-- check formspec buttons or when name entered minetest.register_on_player_receive_fields(function(player, formname, fields) + -- protector formspec found if string.sub(formname, 0, string.len("protector:node_")) == "protector:node_" then local pos_s = string.sub(formname, string.len("protector:node_") + 1) local pos = minetest.string_to_pos(pos_s) local meta = minetest.get_meta(pos) + -- only owner can add names if not protector.can_dig(1, pos, player:get_player_name(), true, 1) then return end + -- add member [+] if fields.protector_add_member then for _, i in pairs(fields.protector_add_member:split(" ")) do @@ -515,23 +558,25 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end end + -- remove member [x] for field, value in pairs(fields) do - if string.sub(field, 0, string.len("protector_del_member_")) == "protector_del_member_" then - protector.del_member(meta, string.sub(field,string.len("protector_del_member_") + 1)) + if string.sub(field, 0, + string.len("protector_del_member_")) == "protector_del_member_" then + + protector.del_member(meta, + string.sub(field,string.len("protector_del_member_") + 1)) end end - + + -- reset formspec until close button pressed if not fields.close_me then minetest.show_formspec(player:get_player_name(), formname, protector.generate_formspec(meta)) end - end - end) --- Display entity shown when protector node is punched - +-- display entity shown when protector node is punched minetest.register_entity("protector:display", { physical = false, collisionbox = {0, 0, 0, 0, 0, 0}, @@ -554,6 +599,7 @@ minetest.register_entity("protector:display", { self.timer = self.timer + dtime + -- remove after 5 seconds if self.timer > 5 then self.object:remove() end diff --git a/pvp.lua b/pvp.lua index 5a6cc8b..6cc5407 100644 --- a/pvp.lua +++ b/pvp.lua @@ -2,13 +2,12 @@ local S = protector.intllib -- get static spawn position -local statspawn = (minetest.setting_get_pos("static_spawnpoint") or {x = 0, y = 2, z = 0}) +local statspawn = minetest.setting_get_pos("static_spawnpoint") or {x = 0, y = 2, z = 0} --- is pvp protection enabled and spawn protected +-- is pvp protection enabled protector.pvp = minetest.setting_getbool("protector_pvp") -protector.spawn = (tonumber(minetest.setting_get("protector_pvp_spawn")) or 0) --- Disable PVP in your own protected areas +-- disables PVP in your own protected areas if minetest.setting_getbool("enable_pvp") and protector.pvp then if minetest.register_on_punchplayer then