Created
March 23, 2016 10:34
-
-
Save HybridDog/e1145141ca4b1c012a87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- maximum distance a protector can have | |
local MAX_DISTANCE = 10 | |
local function get(tab, pname,z,y,x) | |
local data = tab[pname] | |
if data then | |
local data = tab[z] | |
if data then | |
data = data[y] | |
if data then | |
return data[x] | |
end | |
end | |
end | |
end | |
function set(tab, pname,z,y,x, data) | |
if tab[pname] then | |
if tab[pname][z] then | |
if tab[pname][z][y] then | |
tab[pname][z][y][x] = data | |
return | |
end | |
tab[pname][z][y] = {[x] = data} | |
return | |
end | |
tab[pname][z] = {[y] = {[x] = data}} | |
return | |
end | |
tab[pname] = {[z] = {[y] = {[x] = data}}} | |
end | |
local function remove(tab, pname,z,y,x) | |
if vector.get_data_from_pos(tab, pname,z,y,x) == nil then | |
return | |
end | |
tab[pname][z][y][x] = nil | |
if not next(tab[pname][z][y]) then | |
tab[pname][z][y] = nil | |
end | |
if not next(tab[pname][z]) then | |
tab[pname][z] = nil | |
end | |
if not next(tab[pname]) then | |
tab[pname] = nil | |
end | |
end | |
local cached_protectors = {} | |
local function set_protector(pos, pname, range, members) | |
set(cached_protectors, pname,pos.z,pos.y,pos.x, {range, members}) | |
end | |
local function remove_protector(pos, pname) | |
remove(cached_protectors, pname,pos.z,pos.y,pos.x) | |
end | |
local function table_find(t, v) | |
for i = 1,#t do | |
if t[i] == v then | |
return true | |
end | |
end | |
return false | |
end | |
local function is_protected(pos, pname) | |
local pz,py,px = vector.unpack(pos) | |
for name,zyxs in pairs(cached_protectors) do | |
-- test if it doesn't belong to you | |
if name ~= pname then | |
-- test if the protector is near enough | |
for z,yxs in pairs(zyxs) do | |
local dist = math.abs(pz-z) | |
if dist <= MAX_DISTANCE then | |
for y,xs in pairs(yxs) do | |
local yrel = math.abs(py-y) | |
if yrel <= MAX_DISTANCE then | |
dist = math.min(dist, yrel) | |
for x,prot in pairs(xs) do | |
-- test the range of the protector | |
if math.min(dist, math.abs(px-x)) <= prot[1] | |
-- test if you aren't a member | |
and not table_find(prot[2], pname) then | |
return true | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
return false | |
end | |
-- add the small protector with range 3 | |
minetest.register_node("protector:small", { | |
description = "small protector", | |
after_place_node = function(pos, player) | |
if not pos | |
or not player then | |
minetest.log("error", "[protector] something went wrong after placing a protector") | |
return | |
end | |
local pname = player:get_player_name() | |
minetest.get_meta(pos):set_string("owner", pname) | |
set_protector(pos, pname, 3, {}) | |
end, | |
on_destruct = function(pos) | |
remove_protector(pos, minetest.get_meta(pos):get_string("owner")) | |
end, | |
}) | |
-- cache it when it gets loaded | |
minetest.register_lbm({ | |
name = "protector:load_small", | |
nodenames = { "protector:small"}, | |
action = function(pos) | |
local meta = minetest.get_meta(pos) | |
local owner = meta:get_string("owner") | |
if owner == "" then | |
minetest.log("error", "[protector] protector at "..minetest.pos_to_string(pos).." seems to be owned by nobody") | |
return | |
end | |
set_protector(pos, owner, 3, string.split(meta:get_string("members"), " ")) | |
end | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment