Skip to content

Instantly share code, notes, and snippets.

@HybridDog
Created March 23, 2016 10:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HybridDog/e1145141ca4b1c012a87 to your computer and use it in GitHub Desktop.
Save HybridDog/e1145141ca4b1c012a87 to your computer and use it in GitHub Desktop.
-- 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