daily pastebin goal
22%
SHARE
TWEET

PROTECTOR 20

a guest Jun 13th, 2018 53 in 8 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Zeg9's protector mod
  2. -- based on glomie's mod of the same name
  3. -- Released under WTFPL
  4.  
  5.  
  6. -- FIXME: use a mesh instead of the buggy wielditem, for protector:display
  7. -- but that isn't possible yet since models won't take care of the texture's alpha channel...
  8.  
  9.  
  10. minetest.register_privilege("delprotect","Delete other's protection by sneaking")
  11.  
  12. protector = {}
  13.  
  14. protector.node = "protector:protect"
  15. protector.item = "protector:stick"
  16.  
  17. protector.get_member_list = function(meta)
  18.     local s = meta:get_string("members")
  19.     local list = s:split(" ")
  20.     return list
  21. end
  22.  
  23. protector.set_member_list = function(meta, list)
  24.     meta:set_string("members", table.concat(list, " "))
  25. end
  26.  
  27. protector.is_member = function (meta, name)
  28.     local list = protector.get_member_list(meta)
  29.     for _, n in ipairs(list) do
  30.         if n == name then
  31.             return true
  32.         end
  33.     end
  34.     return false
  35. end
  36.  
  37. protector.add_member = function(meta, name)
  38.     if protector.is_member(meta, name) then return end
  39.     local list = protector.get_member_list(meta)
  40.     table.insert(list,name)
  41.     protector.set_member_list(meta,list)
  42. end
  43.  
  44. protector.del_member = function(meta,name)
  45.     local list = protector.get_member_list(meta)
  46.     for i, n in ipairs(list) do
  47.         if n == name then
  48.             table.remove(list, i)
  49.             break
  50.         end
  51.     end
  52.     protector.set_member_list(meta,list)
  53. end
  54.  
  55. protector.generate_formspec = function (meta)
  56.     if meta:get_int("page") == nil then meta:set_int("page",0) end
  57.     local formspec = "size[8,8]"
  58.         .."label[0,0;-- Protector interface --]"
  59.         .."label[0,1;Punch the node to show the protected area.]"
  60.         .."label[0,2;Current members:]"
  61.     members = protector.get_member_list(meta)
  62.    
  63.     local npp = 15 -- names per page, for the moment is 4*4 (-1 for the + button)
  64.     local s = 0
  65.     local i = 0
  66.     for _, member in ipairs(members) do
  67.         if s < meta:get_int("page")*15 then s = s +1 else
  68.             if i < 15 then
  69.                 formspec = formspec .. "button["..(i%4*2)..","..math.floor(i/4+3)..";1.5,.5;protector_member;"..member.."]"
  70.                 formspec = formspec .. "button["..(i%4*2+1.25)..","..math.floor(i/4+3)..";.75,.5;protector_del_member_"..member..";X]"
  71.             end
  72.             i = i +1
  73.         end
  74.     end
  75.     local add_i = i
  76.     if add_i > npp then add_i = npp end
  77.     formspec = formspec
  78.         .."field["..(add_i%4*2+1/3)..","..(math.floor(add_i/4+3)+1/3)..";1.433,.5;protector_add_member;;]"
  79.         .."button["..(add_i%4*2+1.25)..","..math.floor(add_i/4+3)..";.75,.5;protector_submit;+]"
  80.    
  81.     if s > 0 then
  82.         formspec = formspec .. "button[0,7;1,1;protector_page_prev;<<]"
  83.     end
  84.     if i > npp then
  85.         formspec = formspec .. "button[1,7;1,1;protector_page_next;>>]"
  86.     end
  87.     formspec = formspec .. "label[2,7;Page "..(meta:get_int("page")+1).."/"..math.floor((s+i-1)/15+1).."]"
  88.     return formspec
  89. end
  90.  
  91. -- r: radius to check for protects
  92. -- Infolevel:
  93. -- * 0 for no info
  94. -- * 1 for "This area is owned by <owner> !" if you can't dig
  95. -- * 2 for "This area is owned by <owner>.
  96. --   Members are: <members>.", even if you can dig
  97. protector.can_dig = function(r,pos,digger,onlyowner,infolevel)
  98.     if infolevel == nil then infolevel = 1 end
  99.     if not digger or not digger.get_player_name then return false end
  100.     -- Delprotect privileged users can override protections by holding sneak
  101.     if minetest.get_player_privs(digger:get_player_name()).delprotect and
  102.        digger:get_player_control().sneak then
  103.         return true end
  104.     -- Find the protector nodes
  105.     local positions = minetest.find_nodes_in_area(
  106.         {x=pos.x-r, y=pos.y-r, z=pos.z-r},
  107.         {x=pos.x+r, y=pos.y+r, z=pos.z+r},
  108.         protector.node)
  109.     for _, pos in ipairs(positions) do
  110.         local meta = minetest.env:get_meta(pos)
  111.         local owner = meta:get_string("owner")
  112.         if owner ~= digger:get_player_name() then
  113.             if onlyowner or not protector.is_member(meta, digger:get_player_name()) then
  114.                 if infolevel == 1 then
  115.                     minetest.chat_send_player(digger:get_player_name(), "This area is owned by "..owner.." !")
  116.                 elseif infolevel == 2 then
  117.                     minetest.chat_send_player(digger:get_player_name(),"This area is owned by "..meta:get_string("owner")..".")
  118.                     if meta:get_string("members") ~= "" then
  119.                         minetest.chat_send_player(digger:get_player_name(),"Members are: "..meta:get_string("members")..".")
  120.                     end
  121.                 end
  122.                 return false
  123.             end
  124.         end
  125.     end
  126.     if infolevel == 2 then
  127.         if #positions < 1 then
  128.             minetest.chat_send_player(digger:get_player_name(),"This area is not protected.")
  129.         else
  130.             local meta = minetest.env:get_meta(positions[1])
  131.             minetest.chat_send_player(digger:get_player_name(),"This area is owned by "..meta:get_string("owner")..".")
  132.             if meta:get_string("members") ~= "" then
  133.                 minetest.chat_send_player(digger:get_player_name(),"Members are: "..meta:get_string("members")..".")
  134.             end
  135.         end
  136.         minetest.chat_send_player(digger:get_player_name(),"You can build here.")
  137.     end
  138.     return true
  139. end
  140.  
  141. local old_node_dig = minetest.node_dig
  142. function minetest.node_dig(pos, node, digger)
  143.     local ok=true
  144.     if node.name ~= protector.node then
  145.         ok = protector.can_dig(20,pos,digger)
  146.     else
  147.         ok = protector.can_dig(20,pos,digger,true)
  148.     end
  149.     if ok == true then
  150.         old_node_dig(pos, node, digger)
  151.     end
  152. end
  153.  
  154. local old_node_place = minetest.item_place
  155. function minetest.item_place(itemstack, placer, pointed_thing)
  156.     if itemstack:get_definition().type == "node" then
  157.         local ok=true
  158.         if itemstack:get_name() ~= protector.node then
  159.             local pos = pointed_thing.above
  160.             ok = protector.can_dig(20,pos,placer)
  161.         else
  162.             local pos = pointed_thing.above
  163.             ok = protector.can_dig(40,pos,placer,true)
  164.         end
  165.         if ok == true then
  166.             return old_node_place(itemstack, placer, pointed_thing)
  167.         else
  168.             return
  169.         end
  170.     end
  171.     return old_node_place(itemstack, placer, pointed_thing)
  172. end
  173. local protect = {}
  174. minetest.register_node(protector.node, {
  175.     description = "Protection",
  176.     tiles = {"protector_top.png","protector_top.png","protector_side.png"},
  177.     sounds = default.node_sound_stone_defaults(),
  178.     groups = {dig_immediate=2},
  179.     drawtype = "nodebox",
  180.     node_box = {
  181.         type="fixed",
  182.         fixed = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
  183.     },
  184.     selection_box = { type="regular" },
  185.     paramtype = "light",
  186.     after_place_node = function(pos, placer)
  187.         local meta = minetest.env:get_meta(pos)
  188.         meta:set_string("owner", placer:get_player_name() or "")
  189.         meta:set_string("infotext", "Protection (owned by "..
  190.                 meta:get_string("owner")..")")
  191.         meta:set_string("members", "")
  192.         --meta:set_string("formspec",protector.generate_formspec(meta))
  193.     end,
  194.     on_rightclick = function(pos, node, clicker, itemstack)
  195.         local meta = minetest.env:get_meta(pos)
  196.         if protector.can_dig(1,pos,clicker,true) then
  197.             minetest.show_formspec(
  198.                 clicker:get_player_name(),
  199.                 "protector_"..minetest.pos_to_string(pos),
  200.                 protector.generate_formspec(meta)
  201.             )
  202.         end
  203.     end,
  204.     on_punch = function(pos, node, puncher)
  205.         if not protector.can_dig(1,pos,puncher,true) then
  206.             return
  207.         end
  208.         local objs = minetest.env:get_objects_inside_radius(pos,.5) -- a radius of .5 since the entity serialization seems to be not that precise
  209.         local removed = false
  210.         for _, o in pairs(objs) do
  211.             if (not o:is_player()) and o:get_luaentity().name == "protector:display" then
  212.                 o:remove()
  213.                 removed = true
  214.             end
  215.         end
  216.         if not removed then -- nothing was removed: there wasn't the entity
  217.             minetest.env:add_entity(pos, "protector:display")
  218.         end
  219.     end,
  220. })
  221. -- remove formspecs from older versions of the mod
  222. minetest.register_abm({
  223.     nodenames = {protector.node},
  224.     interval = 5.0,
  225.     chance = 1,
  226.     action = function(pos,...)
  227.         local meta = minetest.env:get_meta(pos)
  228.         meta:set_string("formspec","")
  229.     end,
  230. })
  231. minetest.register_on_player_receive_fields(function(player,formname,fields)
  232.     if string.sub(formname,0,string.len("protector_")) == "protector_" then
  233.         local pos_s = string.sub(formname,string.len("protector_")+1)
  234.         local pos = minetest.string_to_pos(pos_s)
  235.         local meta = minetest.env:get_meta(pos)
  236.         if meta:get_int("page") == nil then meta:set_int("page",0) end
  237.         if not protector.can_dig(1,pos,player,true) then
  238.             return
  239.         end
  240.         if fields.protector_add_member then
  241.             for _, i in ipairs(fields.protector_add_member:split(" ")) do
  242.                 protector.add_member(meta,i)
  243.             end
  244.         end
  245.         for field, value in pairs(fields) do
  246.             if string.sub(field,0,string.len("protector_del_member_"))=="protector_del_member_" then
  247.                 protector.del_member(meta, string.sub(field,string.len("protector_del_member_")+1))
  248.             end
  249.         end
  250.         if fields.protector_page_prev then
  251.             meta:set_int("page",meta:get_int("page")-1)
  252.         end
  253.         if fields.protector_page_next then
  254.             meta:set_int("page",meta:get_int("page")+1)
  255.         end
  256.         if not fields.quit then
  257.             minetest.show_formspec(
  258.                 player:get_player_name(), formname,
  259.                 protector.generate_formspec(meta)
  260.             )
  261.         end
  262.     end
  263. end)
  264.  
  265. minetest.register_craftitem(protector.item, {
  266.     description = "Protection tool",
  267.     inventory_image = "protector_stick.png",
  268.     on_use = function(itemstack, user, pointed_thing)
  269.         if pointed_thing.type ~= "node" then
  270.             return
  271.         end
  272.         protector.can_dig(20,pointed_thing.under,user,false,2)
  273.     end,
  274. })
  275.  
  276. minetest.register_craft({
  277.     output = protector.node .. " 4",
  278.     recipe = {
  279.         {"default:stone","default:stone","default:stone"},
  280.         {"default:stone","default:steel_ingot","default:stone"},
  281.         {"default:stone","default:stone","default:stone"},
  282.     }
  283. })
  284. minetest.register_craft({
  285.     output = protector.item,
  286.     recipe = {
  287.         {protector.node},
  288.         {'default:stick'},
  289.     }
  290. })
  291.  
  292. minetest.register_entity("protector:display", {
  293.     physical = false,
  294.     collisionbox = {0,0,0,0,0,0},
  295.     visual = "wielditem",
  296.     visual_size = {x=1.0/1.5,y=1.0/1.5}, -- wielditem seems to be scaled to 1.5 times original node size
  297.     textures = {"protector:display_node"},
  298.     on_step = function(self, dtime)
  299.         if minetest.get_node(self.object:getpos()).name ~= protector.node then
  300.             self.object:remove()
  301.             return
  302.         end
  303.     end,
  304. })
  305.  
  306. -- Display-zone node.
  307. -- Do NOT place the display as a node
  308. -- it is made to be used as an entity (see above)
  309. minetest.register_node("protector:display_node", {
  310.     tiles = {"protector_display.png"},
  311.     use_texture_alpha = true,
  312.     walkable = false,
  313.     drawtype = "nodebox",
  314.     node_box = {
  315.         type = "fixed",
  316.         fixed = {
  317.             -- sides
  318.             {-5.55, -5.55, -5.55, -5.45, 5.55, 5.55},
  319.             {-5.55, -5.55, 5.45, 5.55, 5.55, 5.55},
  320.             {5.45, -5.55, -5.55, 5.55, 5.55, 5.55},
  321.             {-5.55, -5.55, -5.55, 5.55, 5.55, -5.45},
  322.             -- top
  323.             {-5.55, 5.45, -5.55, 5.55, 5.55, 5.55},
  324.             -- bottom
  325.             {-5.55, -5.55, -5.55, 5.55, -5.45, 5.55},
  326.             -- middle (surround protector)
  327.             {-.55,-.55,-.55, .55,.55,.55},
  328.         },
  329.     },
  330.     selection_box = {
  331.         type = "regular",
  332.     },
  333.     paramtype = "light",
  334.     groups = {dig_immediate=3,not_in_creative_inventory=1},
  335.     drop = "",
  336. })
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top