-- load static configuration dofile(minetest.get_modpath("node_ownership").."/settings.lua") if _STATIC_DEBUG then print("node_ownership: DEBUG: true") end -- declare local variables minetest.register_privilege("griefing", { description = "Griefing Mode", give_to_singleplayer = true }) --// exportstring( string ) --// returns a "Lua" portable version of the string local function exportstring( s ) s = string.format( "%q",s ) -- to replace s = string.gsub( s,"\\\n","\\n" ) s = string.gsub( s,"\r","\\r" ) s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" ) return s end --// The Save Function local function table_save( tbl,filename ) local charS,charE = " ","\n" local file,err -- create a pseudo file that writes to a string and return the string if not filename then file = { write = function( self,newstr ) self.str = self.str..newstr end, str = "" } charS,charE = "","" -- write table to tmpfile elseif filename == true or filename == 1 then charS,charE,file = "","",io.tmpfile() -- write table to file -- use io.open here rather than io.output, since in windows when clicking on a file opened with io.output will create an error else file,err = io.open( filename, "w" ) if err then return _,err end end -- initiate variables for save procedure local tables,lookup = { tbl },{ [tbl] = 1 } file:write( "return {"..charE ) for idx,t in ipairs( tables ) do if filename and filename ~= true and filename ~= 1 then file:write( "-- Table: {"..idx.."}"..charE ) end file:write( "{"..charE ) local thandled = {} for i,v in ipairs( t ) do thandled[i] = true -- escape functions and userdata if type( v ) ~= "userdata" then -- only handle value if type( v ) == "table" then if not lookup[v] then table.insert( tables, v ) lookup[v] = #tables end file:write( charS.."{"..lookup[v].."},"..charE ) elseif type( v ) == "function" then file:write( charS.."loadstring("..exportstring(string.dump( v )).."),"..charE ) else local value = ( type( v ) == "string" and exportstring( v ) ) or tostring( v ) file:write( charS..value..","..charE ) end end end for i,v in pairs( t ) do -- escape functions and userdata if (not thandled[i]) and type( v ) ~= "userdata" then -- handle index if type( i ) == "table" then if not lookup[i] then table.insert( tables,i ) lookup[i] = #tables end file:write( charS.."[{"..lookup[i].."}]=" ) else local index = ( type( i ) == "string" and "["..exportstring( i ).."]" ) or string.format( "[%d]",i ) file:write( charS..index.."=" ) end -- handle value if type( v ) == "table" then if not lookup[v] then table.insert( tables,v ) lookup[v] = #tables end file:write( "{"..lookup[v].."},"..charE ) elseif type( v ) == "function" then file:write( "loadstring("..exportstring(string.dump( v )).."),"..charE ) else local value = ( type( v ) == "string" and exportstring( v ) ) or tostring( v ) file:write( value..","..charE ) end end end file:write( "},"..charE ) end file:write( "}" ) -- Return Values -- return stringtable from string if not filename then -- set marker for stringtable return file.str.."--|" -- return stringttable from file elseif filename == true or filename == 1 then file:seek ( "set" ) -- no need to close file, it gets closed and removed automatically -- set marker for stringtable return file:read( "*a" ).."--|" -- close file and return 1 else file:close() return 1 end end --// The Load Function local function table_load( sfile ) -- catch marker for stringtable if string.sub( sfile,-3,-1 ) == "--|" then tables,err = loadstring( sfile ) else tables,err = loadfile( sfile ) end if err then return _,err end tables = tables() for idx = 1,#tables do local tolinkv,tolinki = {},{} for i,v in pairs( tables[idx] ) do if type( v ) == "table" and tables[v[1]] then table.insert( tolinkv,{ i,tables[v[1]] } ) end if type( i ) == "table" and tables[i[1]] then table.insert( tolinki,{ i,tables[i[1]] } ) end end -- link values, first due to possible changes of indices for _,v in ipairs( tolinkv ) do tables[idx][v[1]] = v[2] end -- link indices for _,v in ipairs( tolinki ) do tables[idx][v[2]],tables[idx][v[1]] = tables[idx][v[1]],nil end end return tables[1] end local owners_db_filename = minetest.get_worldpath("node_ownership") .. "/owners.tbl" owner_defs = table_load(owners_db_filename) if type(owner_defs) ~= "table" then owner_defs = {} end function IsPlayerNodeOwner(pos, name) r = false for _,def in pairs(owner_defs) do if pos.x >= def.x1 and pos.x <= def.x2 or pos.x <= def.x1 and pos.x >= def.x2 then if pos.y >= def.y1 and pos.y <= def.y2 or pos.y <= def.y1 and pos.y >= def.y2 then if pos.z >= def.z1 and pos.z <= def.z2 or pos.z <= def.z1 and pos.z >= def.z2 then if name == def.owner then return true else r = false end end end end end return r end function GetNodeOwnerName(pos) r = false for _,def in pairs(owner_defs) do if pos.x >= def.x1 and pos.x <= def.x2 or pos.x <= def.x1 and pos.x >= def.x2 then if pos.y >= def.y1 and pos.y <= def.y2 or pos.y <= def.y1 and pos.y >= def.y2 then if pos.z >= def.z1 and pos.z <= def.z2 or pos.z <= def.z1 and pos.z >= def.z2 then if def.owner == nil then r = false else return def.owner end end end end end return r end function HasOwner(pos) for _,def in pairs(owner_defs) do if pos.x >= def.x1 and pos.x <= def.x2 or pos.x <= def.x1 and pos.x >= def.x2 then if pos.y >= def.y1 and pos.y <= def.y2 or pos.y <= def.y1 and pos.y >= def.y2 then if pos.z >= def.z1 and pos.z <= def.z2 or pos.z <= def.z1 and pos.z >= def.z2 then return true end end end end return false end local old_node_place = minetest.item_place function minetest.item_place(itemstack, placer, pointed_thing) if itemstack:get_definition().type == "node" then local pos = pointed_thing.above if not minetest.check_player_privs(placer:get_player_name(), {griefing=true}) then if HasOwner(pos) then if not ( IsPlayerNodeOwner(pos, placer:get_player_name()) or IsPlayerNodeOwner(pos, "Sandbox") ) then minetest.chat_send_player(placer:get_player_name(), "You need a concession to place nodes here - Grantor: ".._STATIC_grantor.." - ".."Concessionaire: "..GetNodeOwnerName(pos).." (X"..pos.x.." Y"..pos.y.." Z"..pos.z..") ") return itemstack end else minetest.chat_send_player(placer:get_player_name(), "You need a concession to place nodes here - Grantor: ".._STATIC_grantor.." (X"..pos.x.." Y"..pos.y.." Z"..pos.z..")") return itemstack end end return old_node_place(itemstack, placer, pointed_thing) end return old_node_place(itemstack, placer, pointed_thing) end local old_node_dig = minetest.node_dig function minetest.node_dig(pos, node, digger) if not minetest.check_player_privs(digger:get_player_name(), {griefing=true}) then if HasOwner(pos) then if not ( IsPlayerNodeOwner(pos, digger:get_player_name()) or IsPlayerNodeOwner(pos, "Sandbox") ) then minetest.chat_send_player(digger:get_player_name(), "You need a concession to dig nodes here - Grantor: ".._STATIC_grantor.." - ".."Concessionaire: "..GetNodeOwnerName(pos).." (X"..pos.x.." Y"..pos.y.." Z"..pos.z..")") return end else minetest.chat_send_player(digger:get_player_name(), "You need a concession to dig nodes here - Grantor: ".._STATIC_grantor.." (X"..pos.x.." Y"..pos.y.." Z"..pos.z..")") return end end old_node_dig(pos, node, digger) end local old_node_punch = minetest.node_punch function minetest.node_punch(pos, node, puncher) -- print (string.sub(node.name,1,17)) if string.sub(node.name,1,17) == "mesecons_delayer:" then if not minetest.check_player_privs(puncher:get_player_name(), {griefing=true}) then if HasOwner(pos) then if not ( IsPlayerNodeOwner(pos, puncher:get_player_name()) or IsPlayerNodeOwner(pos, "Sandbox") ) then minetest.chat_send_player(puncher:get_player_name(), "You need a concession to punch this node here - Grantor: ".._STATIC_grantor.." - ".."Concessionaire: "..GetNodeOwnerName(pos).." (X"..pos.x.." Y"..pos.y.." Z"..pos.z..")") return end else minetest.chat_send_player(puncher:get_player_name(), "You need a concession to punch this node here - Grantor: ".._STATIC_grantor.." (X"..pos.x.." Y"..pos.y.." Z"..pos.z..")") return end end end old_node_punch(pos, node, puncher) end function CheckCollisions(pos1, pos2) -- Find all 8 cube corners and make sure all 8 are not already in someone elses zone pos3 = {x=pos2.x,y=pos1.y,z=pos1.z} pos4 = {x=pos1.x,y=pos2.y,z=pos1.z} pos5 = {x=pos1.x,y=pos2.y,z=pos2.z} pos6 = {x=pos1.x,y=pos1.y,z=pos2.z} pos7 = {x=pos2.x,y=pos2.y,z=pos1.z} pos8 = {x=pos2.x,y=pos1.y,z=pos2.z} if HasOwner(pos1) == false and HasOwner(pos2) == false and HasOwner(pos3) == false and HasOwner(pos4) == false and HasOwner(pos5) == false and HasOwner(pos6) == false and HasOwner(pos7) == false and HasOwner(pos8) == false then return false end return true end function RemoveTableEntry(r_id) --Find child entries and remove them local nomorechild = true repeat nomorechild = true for n,def in pairs(owner_defs) do if def.parent == r_id then table.remove(owner_defs, n) --RemoveTableEntryRe(def.id) nomorechild = false break end end until nomorechild -- now remove main entry for n,def in pairs(owner_defs) do if def.id == r_id then table.remove(owner_defs, n) break end end --Re-number ids to match place in table for n,ndef in pairs(owner_defs) do if ndef.id ~= n then for p,pdef in pairs(owner_defs) do if pdef.parent == ndef.id then pdef.parent = n end end ndef.id = n end end table_save( owner_defs, owners_db_filename ) end minetest.register_on_chat_message(function(name, message) local cmd = "/set_owner" if message:sub(0, #cmd) == cmd then if not minetest.check_player_privs(name, {privs=true}) then minetest.chat_send_player(name, "you don't have permission to do this") return true -- Handled chat message end local ownername, sx, sy, sz, ex, ey, ez = string.match(message, cmd.." (.-) ([0-9%-]-)%,([0-9%-]-)%,([0-9%-]-) ([0-9%-]-)%,([0-9%-]-)%,([0-9%-]*)") if ownername == nil or string.len(ownername) == 0 or sx == nil or string.len(sx) == 0 or sy == nil or string.len(sy) == 0 or sz == nil or string.len(sz) == 0 or ex == nil or string.len(ex) == 0 or ey == nil or string.len(ey) == 0 or ez == nil or string.len(ez) == 0 then minetest.chat_send_player(name, 'usage: '..cmd..' playername startpos endpos') return true -- Handled chat message end if _STATIC_DEBUG then print("WARNING: Please look inside code for comment to fix this soon "..name..ownername) end -- Problem: If the Playername is not online at the moment it wont set. this should be fixed. but dont remove the function because it protects against bad strings local player = minetest.env:get_player_by_name(ownername) if ownername == "Sandbox" then player = "Sandbox" end if player == nil then print("player is nil") return true -- Handled chat message end print(cmd.." invoked, owner=" .. ownername .. " startpos=" .. sx .. "," .. sy .. "," .. sz .. " endpos=" .. ex .. "," .. ey .. "," .. ez) sx = tonumber(sx) sy = tonumber(sy) sz = tonumber(sz) ex = tonumber(ex) ey = tonumber(ey) ez = tonumber(ez) if (CheckCollisions({x=sx,y=sy,z=sz}, {x=ex,y=ey,z=ez})) == true then minetest.chat_send_player(name, "Owner Collision") return true -- Handled chat message end table.insert(owner_defs, {x1=sx, y1=sy, z1=sz, x2=ex, y2=ey, z2=ez, owner=ownername}) owner_defs[table.maxn(owner_defs)].id = table.maxn(owner_defs) table_save( owner_defs, owners_db_filename ) minetest.chat_send_player(ownername, "A concession has been granted to you! Type /list_areas to show your concessions.") minetest.chat_send_player(name, "You granted "..ownername.." a concession successfully!") return true -- Handled chat message end local cmd = "/add_owner" if message:sub(0, #cmd) == cmd then local new_ownername, sx, sy, sz, ex, ey, ez = string.match(message, cmd.." (.-) ([0-9%-]-)%,([0-9%-]-)%,([0-9%-]-) ([0-9%-]-)%,([0-9%-]-)%,([0-9%-]*)") if new_ownername == nil or string.len(new_ownername) == 0 or sx == nil or string.len(sx) == 0 or sy == nil or string.len(sy) == 0 or sz == nil or string.len(sz) == 0 or ex == nil or string.len(ex) == 0 or ey == nil or string.len(ey) == 0 or ez == nil or string.len(ez) == 0 then minetest.chat_send_player(name, 'usage: '..cmd..' playername startpos endpos') return true -- Handled chat message end local player = minetest.env:get_player_by_name(new_ownername) if new_ownername == "Sandbox" then player = "Sandbox" end if player == nil then print("player is nil") return true -- Handled chat message end print(cmd.." invoked, new_ownername=" .. new_ownername .. " startpos=" .. sx .. "," .. sy .. "," .. sz .. " endpos=" .. ex .. "," .. ey .. "," .. ez) sx = tonumber(sx) sy = tonumber(sy) sz = tonumber(sz) ex = tonumber(ex) ey = tonumber(ey) ez = tonumber(ez) area_pos1 = {x=sx, y=sy, z=sz} area_pos2 = {x=ex, y=ey, z=ez} p=nil --Look to see if this new area is inside an area owned by the player using this function for n,def in pairs(owner_defs) do if (area_pos1.x >= def.x1 and area_pos1.x <= def.x2 or area_pos1.x <= def.x1 and area_pos1.x >= def.x2) and (area_pos2.x >= def.x1 and area_pos2.x <= def.x2 or area_pos2.x <= def.x1 and area_pos2.x >= def.x2) then if (area_pos1.y >= def.y1 and area_pos1.y <= def.y2 or area_pos1.y <= def.y1 and area_pos1.y >= def.y2) and (area_pos2.y >= def.y1 and area_pos2.y <= def.y2 or area_pos2.y <= def.y1 and area_pos2.y >= def.y2) then if (area_pos1.z >= def.z1 and area_pos1.z <= def.z2 or area_pos1.z <= def.z1 and area_pos1.z >= def.z2) and (area_pos2.z >= def.z1 and area_pos2.z <= def.z2 or area_pos2.z <= def.z1 and area_pos2.z >= def.z2) then --OK, found entry that has both area_poss if def.owner == name or minetest.check_player_privs(name, {privs=true}) then p=def.id if _STATIC_DEBUG then print ("DEBUG (add_owner): Owner ID is: "..def.id) end if def.parent ~= nil then p=nil --disallow child of childs if _STATIC_DEBUG then print("DEBUG (add_owner): Owner Parent is: "..def.parent) end else print("DEBUG (add_owner): Unset Parent") end break end end end end end if p == nil then minetest.chat_send_player(name, "You don't have permission to do this") return true -- Handled chat message end table.insert(owner_defs, {x1=sx, y1=sy, z1=sz, x2=ex, y2=ey, z2=ez, owner=new_ownername}) if p ~= nil then owner_defs[table.maxn(owner_defs)].parent = p end owner_defs[table.maxn(owner_defs)].id = table.maxn(owner_defs) table_save( owner_defs, owners_db_filename ) minetest.chat_send_player(new_ownername, name.." granted you a subconcession!") minetest.chat_send_player(name, "You granted "..new_ownername.." a subconcession successfully!") return true -- Handled chat message end local cmd = "/list_areas" if message:sub(0, #cmd) == cmd then show_all = false if minetest.get_player_privs(name)["privs"] then show_all = true minetest.chat_send_player(name, "Showing all owner entries") for n,def in pairs(owner_defs) do entry = def.id .. ": " .. def.owner .. " (" .. def.x1 .. "," .. def.y1 .. "," .. def.z1 .. ") (" .. def.x2 .. "," .. def.y2 .. "," .. def.z2 .. ")" if def.parent ~= nil then entry = entry .. " parent: " .. def.parent end minetest.chat_send_player(name, entry) end else minetest.chat_send_player(name, "Showing your owner entries (You can delete only these)") for n,def in pairs(owner_defs) do if def.owner == name then entry = def.id .. ": " .. def.owner .. " (" .. def.x1 .. "," .. def.y1 .. "," .. def.z1 .. ") (" .. def.x2 .. "," .. def.y2 .. "," .. def.z2 .. ")" if def.parent ~= nil then entry = entry .. " parent: " .. def.parent end minetest.chat_send_player(name, entry) for n,defc in pairs(owner_defs) do if defc.parent == def.id then entry = "->" .. defc.id .. ": " .. defc.owner .. " (" .. defc.x1 .. "," .. defc.y1 .. "," .. defc.z1 .. ") (" .. defc.x2 .. "," .. defc.y2 .. "," .. defc.z2 .. ")" if defc.parent ~= nil then entry = entry .. " parent: " .. defc.parent end minetest.chat_send_player(name, entry) end end end end end return true -- Handled chat message end local cmd = "/remove_areas" if message:sub(0, #cmd) == cmd then your_ids = {} for n,def in pairs(owner_defs) do if def.owner == name or minetest.check_player_privs(name, {privs=true}) then table.insert(your_ids, def.id) for n,defc in pairs(owner_defs) do if defc.parent == def.id then table.insert(your_ids, defc.id) end end end end local e = string.match(message, cmd.." (.*)") if e == nil or string.len(e) == 0 then minetest.chat_send_player(name, 'usage: '..cmd..' entry_number') minetest.chat_send_player(name, 'use /list_areas to see entries') return true -- Handled chat message end e = tonumber(e) found = false for _,k in pairs(your_ids) do if k == e then RemoveTableEntry(e) table_save( owner_defs, owners_db_filename ) return true -- Handled chat message end end return true -- Handled chat message end local cmd = "/change_area_owner" if message:sub(0, #cmd) == cmd then your_ids = {} for n,def in pairs(owner_defs) do if def.owner == name or minetest.check_player_privs(name, {privs=true}) then table.insert(your_ids, def.id) for n,defc in pairs(owner_defs) do if defc.parent == def.id then table.insert(your_ids, defc.id) end end end end local e, new_owner = string.match(message, cmd.." (.-) (.*)") if e == nil or new_owner == nil or string.len(e) == 0 or string.len(new_owner) == 0 then minetest.chat_send_player(name, 'usage: '..cmd..' entry_number new_owner') minetest.chat_send_player(name, 'use /list_areas to see entries') return true -- Handled chat message end local player = minetest.env:get_player_by_name(new_owner) if player == nil then print("new_owner is nil") return true -- Handled chat message end e = tonumber(e) found = false for _,k in pairs(your_ids) do if k == e then for n,def in pairs(owner_defs) do if def.id == e then owner_defs[n].owner = new_owner table_save( owner_defs, owners_db_filename ) return true -- Handled chat message end end end end return true -- Handled chat message end end)