mirror of
https://github.com/theFox6/microexpansion.git
synced 2024-08-21 13:34:05 +02:00
added the security terminal to control access to the network
also added support for multiple controllers within one network
This commit is contained in:
parent
f5aee436d0
commit
6428b89a84
57
modules/network/constants.lua
Normal file
57
modules/network/constants.lua
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
local me = microexpansion
|
||||||
|
if not me.constants then
|
||||||
|
me.constants = {}
|
||||||
|
end
|
||||||
|
local constants = me.constants
|
||||||
|
|
||||||
|
local access_levels = {
|
||||||
|
-- cannot interact at all with the network or it's components
|
||||||
|
blocked = 0,
|
||||||
|
-- can only look into the network but not move, modify, etc.
|
||||||
|
view = 20,
|
||||||
|
-- can use chests, craft terminals, etc.
|
||||||
|
interact = 40,
|
||||||
|
-- can use all components except security, can build and dig (except core)
|
||||||
|
modify = 60,
|
||||||
|
-- can use security terminal, can modify all players with less access
|
||||||
|
manage = 80,
|
||||||
|
-- can modify all players with less access and self
|
||||||
|
full = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
local access_level_descriptions = {}
|
||||||
|
access_level_descriptions[access_levels.blocked] = {
|
||||||
|
name = "Blocked",
|
||||||
|
color = "gray",
|
||||||
|
index = 1
|
||||||
|
}
|
||||||
|
access_level_descriptions[access_levels.view] = {
|
||||||
|
name = "View",
|
||||||
|
color = "orange",
|
||||||
|
index = 2
|
||||||
|
}
|
||||||
|
access_level_descriptions[access_levels.interact] = {
|
||||||
|
color = "yellow",
|
||||||
|
name = "Interact",
|
||||||
|
index = 3
|
||||||
|
}
|
||||||
|
access_level_descriptions[access_levels.modify] = {
|
||||||
|
name = "Modify",
|
||||||
|
color = "yellowgreen",
|
||||||
|
index = 4
|
||||||
|
}
|
||||||
|
access_level_descriptions[access_levels.manage] = {
|
||||||
|
name = "Manage",
|
||||||
|
color = "green",
|
||||||
|
index = 5
|
||||||
|
}
|
||||||
|
access_level_descriptions[access_levels.full] = {
|
||||||
|
name = "Full",
|
||||||
|
color = "blue",
|
||||||
|
index = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
constants.security = {
|
||||||
|
access_levels = access_levels,
|
||||||
|
access_level_descriptions = access_level_descriptions
|
||||||
|
}
|
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
local me = microexpansion
|
local me = microexpansion
|
||||||
local network = me.network
|
local network = me.network
|
||||||
|
local access_level = microexpansion.constants.security.access_levels
|
||||||
--FIXME: accept multiple controllers in one network
|
|
||||||
|
|
||||||
-- [register node] Controller
|
-- [register node] Controller
|
||||||
me.register_node("ctrl", {
|
me.register_node("ctrl", {
|
||||||
@ -45,6 +44,10 @@ me.register_node("ctrl", {
|
|||||||
groups = { cracky = 1, me_connect = 1, },
|
groups = { cracky = 1, me_connect = 1, },
|
||||||
connect_sides = "nobottom",
|
connect_sides = "nobottom",
|
||||||
me_update = function(pos,_,ev)
|
me_update = function(pos,_,ev)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
if meta:get_string("source") ~= "" then
|
||||||
|
return
|
||||||
|
end
|
||||||
local cnet = me.get_network(pos)
|
local cnet = me.get_network(pos)
|
||||||
if cnet == nil then
|
if cnet == nil then
|
||||||
microexpansion.log("no network for ctrl at pos "..minetest.pos_to_string(pos),"error")
|
microexpansion.log("no network for ctrl at pos "..minetest.pos_to_string(pos),"error")
|
||||||
@ -54,30 +57,70 @@ me.register_node("ctrl", {
|
|||||||
end,
|
end,
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local net = network.new({controller_pos = pos})
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if net then
|
||||||
|
meta:set_string("source", vector.to_string(cp))
|
||||||
|
else
|
||||||
|
net = network.new({controller_pos = pos})
|
||||||
table.insert(me.networks,net)
|
table.insert(me.networks,net)
|
||||||
|
end
|
||||||
me.send_event(pos,"connect",{net=net})
|
me.send_event(pos,"connect",{net=net})
|
||||||
|
|
||||||
meta:set_string("infotext", "Network Controller")
|
meta:set_string("infotext", "Network Controller")
|
||||||
end,
|
end,
|
||||||
after_place_node = function(pos, player)
|
after_place_node = function(pos, player)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("infotext", "Network Controller (owned by "..name..")")
|
meta:set_string("infotext", "Network Controller")
|
||||||
meta:set_string("owner", name)
|
meta:set_string("owner", name)
|
||||||
|
local net,idx = me.get_network(pos)
|
||||||
|
if net then
|
||||||
|
net:set_access_level(name, me.constants.security.access_levels.full)
|
||||||
|
elseif meta:get_string("source") == "" then
|
||||||
|
me.log("no network after placing controller", "warning")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
if not player then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local net
|
||||||
|
if meta:get_string("source") == "" then
|
||||||
|
net = me.get_network(pos)
|
||||||
|
else
|
||||||
|
net = me.get_connected_network(pos)
|
||||||
|
end
|
||||||
|
if not net then
|
||||||
|
me.log("ME Network Controller without Network","error")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return net:get_access_level(name) >= access_level.full
|
||||||
end,
|
end,
|
||||||
on_destruct = function(pos)
|
on_destruct = function(pos)
|
||||||
local net,idx = me.get_network(pos)
|
local net,idx = me.get_network(pos)
|
||||||
--disconnect all those who need the network
|
--disconnect all those who need the network
|
||||||
me.send_event(pos,"disconnect",{net=net})
|
me.send_event(pos,"disconnect",{net=net})
|
||||||
if net then
|
if net then
|
||||||
|
if me.promote_controller(pos,net) then
|
||||||
|
--reconnect with new controller
|
||||||
|
me.send_event(pos,"reconnect",{net=net})
|
||||||
|
else
|
||||||
net:destruct()
|
net:destruct()
|
||||||
end
|
|
||||||
if idx then
|
if idx then
|
||||||
table.remove(me.networks,idx)
|
table.remove(me.networks,idx)
|
||||||
end
|
end
|
||||||
--disconnect all those that haven't realized the network is gone
|
--disconnect all those that haven't realized the network is gone
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- disconnect just in case
|
||||||
|
me.send_event(pos,"disconnect")
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
--disconnect all those that haven't realized the controller was disconnected
|
--disconnect all those that haven't realized the controller was disconnected
|
||||||
@ -114,10 +157,47 @@ me.register_machine("cable", {
|
|||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
groups = { crumbly = 1, },
|
groups = { crumbly = 1, },
|
||||||
--TODO: move these functions into the registration
|
--TODO: move these functions into the registration
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
if not player then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if not net then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return net:get_access_level(name) >= access_level.modify
|
||||||
|
end,
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
me.send_event(pos,"connect")
|
me.send_event(pos,"connect")
|
||||||
end,
|
end,
|
||||||
|
after_place_node = function(pos, placer)
|
||||||
|
if not placer then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local name = placer:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
--protection probably handles this itself
|
||||||
|
--minetest.remove_node(pos)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if not net then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if net:get_access_level(name) < access_level.modify then
|
||||||
|
-- prevent placing cables on a network that a player doesn't have access to
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
|
--FIXME: write drives before disconnecting
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
me_update = function(pos,_,ev)
|
me_update = function(pos,_,ev)
|
||||||
|
@ -3,6 +3,8 @@ me.networks = {}
|
|||||||
local networks = me.networks
|
local networks = me.networks
|
||||||
local path = microexpansion.get_module_path("network")
|
local path = microexpansion.get_module_path("network")
|
||||||
|
|
||||||
|
dofile(path.."/constants.lua")
|
||||||
|
|
||||||
--deprecated: use ItemStack(x) instead
|
--deprecated: use ItemStack(x) instead
|
||||||
--[[
|
--[[
|
||||||
local function split_stack_values(stack)
|
local function split_stack_values(stack)
|
||||||
@ -110,7 +112,13 @@ end
|
|||||||
function me.get_connected_network(start_pos)
|
function me.get_connected_network(start_pos)
|
||||||
for npos,nn in me.connected_nodes(start_pos,true) do
|
for npos,nn in me.connected_nodes(start_pos,true) do
|
||||||
if nn == "microexpansion:ctrl" then
|
if nn == "microexpansion:ctrl" then
|
||||||
local network = me.get_network(npos)
|
local source = minetest.get_meta(npos):get_string("source")
|
||||||
|
local network
|
||||||
|
if source == "" then
|
||||||
|
network = me.get_network(npos)
|
||||||
|
else
|
||||||
|
network = me.get_network(vector.from_string(source))
|
||||||
|
end
|
||||||
if network then
|
if network then
|
||||||
return network,npos
|
return network,npos
|
||||||
end
|
end
|
||||||
@ -118,6 +126,22 @@ function me.get_connected_network(start_pos)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function me.promote_controller(start_pos,net)
|
||||||
|
local promoted = false
|
||||||
|
for npos,nn in me.connected_nodes(start_pos,true) do
|
||||||
|
if nn == "microexpansion:ctrl" and npos ~= start_pos then
|
||||||
|
if promoted then
|
||||||
|
minetest.get_meta(npos):set_string("source", promoted)
|
||||||
|
else
|
||||||
|
promoted = vector.to_string(npos)
|
||||||
|
minetest.get_meta(npos):set_string("source", "")
|
||||||
|
net.controller_pos = npos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return promoted and true or false
|
||||||
|
end
|
||||||
|
|
||||||
function me.update_connected_machines(start_pos,event,include_start)
|
function me.update_connected_machines(start_pos,event,include_start)
|
||||||
microexpansion.log("updating connected machines","action")
|
microexpansion.log("updating connected machines","action")
|
||||||
local ev = event or {type = "n/a"}
|
local ev = event or {type = "n/a"}
|
||||||
@ -158,6 +182,7 @@ function me.get_network(pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
dofile(path.."/ctrl.lua") -- Controller/wires
|
dofile(path.."/ctrl.lua") -- Controller/wires
|
||||||
|
dofile(path.."/security.lua") --Security Terminal
|
||||||
|
|
||||||
-- load networks
|
-- load networks
|
||||||
function me.load()
|
function me.load()
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
--- Microexpansion network
|
--- Microexpansion network
|
||||||
-- @type network
|
-- @type network
|
||||||
-- @field #table controller_pos the position of the controller
|
-- @field #table controller_pos the position of the controller
|
||||||
|
-- @field #table access a table of players and their respective access levels
|
||||||
|
-- @field #number default_access_level the access level of unlisted players
|
||||||
-- @field #number power_load the power currently provided to the network
|
-- @field #number power_load the power currently provided to the network
|
||||||
-- @field #number power_storage the power that can be stored for the next tick
|
-- @field #number power_storage the power that can be stored for the next tick
|
||||||
local network = {
|
local network = {
|
||||||
|
default_access_level = microexpansion.constants.security.access_levels.view,
|
||||||
power_load = 0,
|
power_load = 0,
|
||||||
power_storage = 0
|
power_storage = 0
|
||||||
}
|
}
|
||||||
local me = microexpansion
|
local me = microexpansion
|
||||||
me.network = network
|
me.network = network
|
||||||
|
|
||||||
|
local access_level = microexpansion.constants.security.access_levels
|
||||||
|
|
||||||
--- construct a new network
|
--- construct a new network
|
||||||
-- @function [parent=#network] new
|
-- @function [parent=#network] new
|
||||||
-- @param #table o the object to become a network or nil
|
-- @param #table o the object to become a network or nil
|
||||||
@ -72,6 +77,65 @@ function network.adjacent_connected_nodes(pos, include_ctrl)
|
|||||||
return nodes
|
return nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function network:get_access_level(player)
|
||||||
|
local name
|
||||||
|
if not player then
|
||||||
|
return self.default_access_level
|
||||||
|
elseif type(player) == "string" then
|
||||||
|
name = player
|
||||||
|
else
|
||||||
|
name = player:get_player_name()
|
||||||
|
end
|
||||||
|
if not self.access then
|
||||||
|
return self.default_access_level
|
||||||
|
end
|
||||||
|
return self.access[name] or self.default_access_level
|
||||||
|
end
|
||||||
|
|
||||||
|
function network:set_access_level(player, level)
|
||||||
|
local name
|
||||||
|
if not player then
|
||||||
|
self.default_access_level = level
|
||||||
|
elseif type(player) == "string" then
|
||||||
|
name = player
|
||||||
|
else
|
||||||
|
name = player:get_player_name()
|
||||||
|
end
|
||||||
|
if not self.access then
|
||||||
|
self.access = {}
|
||||||
|
end
|
||||||
|
self.access[name] = level
|
||||||
|
self:fallback_access()
|
||||||
|
end
|
||||||
|
|
||||||
|
function network:fallback_access()
|
||||||
|
local full_access = access_level.full
|
||||||
|
if not self.access then
|
||||||
|
--something must have gone badly wrong
|
||||||
|
me.log("no network access table in fallback method","error")
|
||||||
|
self.access = {}
|
||||||
|
end
|
||||||
|
for _,l in pairs(self.access) do
|
||||||
|
if l == full_access then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local meta = minetest.get_meta(self.controller_pos)
|
||||||
|
local owner = meta:get_string("owner")
|
||||||
|
if owner == "" then
|
||||||
|
me.log("ME Network Controller without owner at: " .. vector.to_string(self.controller_pos), "warning")
|
||||||
|
else
|
||||||
|
self.access[owner] = full_access
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function network:list_access()
|
||||||
|
if not self.access then
|
||||||
|
self.access = {}
|
||||||
|
end
|
||||||
|
return self.access
|
||||||
|
end
|
||||||
|
|
||||||
--- provide power to the network
|
--- provide power to the network
|
||||||
-- @function [parent=#network] provide
|
-- @function [parent=#network] provide
|
||||||
-- @param #number power the amount of power provided
|
-- @param #number power the amount of power provided
|
||||||
@ -205,7 +269,10 @@ end
|
|||||||
local function create_inventory(net)
|
local function create_inventory(net)
|
||||||
local invname = net:get_inventory_name()
|
local invname = net:get_inventory_name()
|
||||||
net.inv = minetest.create_detached_inventory(invname, {
|
net.inv = minetest.create_detached_inventory(invname, {
|
||||||
allow_put = function(inv, listname, index, stack)
|
allow_put = function(inv, listname, index, stack, player)
|
||||||
|
if net:get_access_level(player) < access_level.interact then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
local inside_stack = inv:get_stack(listname, index)
|
local inside_stack = inv:get_stack(listname, index)
|
||||||
local stack_name = stack:get_name()
|
local stack_name = stack:get_name()
|
||||||
if minetest.get_item_group(stack_name, "microexpansion_cell") > 0 then
|
if minetest.get_item_group(stack_name, "microexpansion_cell") > 0 then
|
||||||
@ -238,7 +305,10 @@ local function create_inventory(net)
|
|||||||
me.insert_item(stack, inv, listname)
|
me.insert_item(stack, inv, listname)
|
||||||
net:set_storage_space(true)
|
net:set_storage_space(true)
|
||||||
end,
|
end,
|
||||||
allow_take = function(_, _, _, stack)
|
allow_take = function(_, _, _, stack, player)
|
||||||
|
if net:get_access_level(player) < access_level.interact then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
return math.min(stack:get_count(),stack:get_stack_max())
|
return math.min(stack:get_count(),stack:get_stack_max())
|
||||||
end,
|
end,
|
||||||
on_take = function()
|
on_take = function()
|
||||||
|
275
modules/network/security.lua
Normal file
275
modules/network/security.lua
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
-- microexpansion/network/security.lua
|
||||||
|
|
||||||
|
local me = microexpansion
|
||||||
|
local access_level = me.constants.security.access_levels
|
||||||
|
local access_desc = me.constants.security.access_level_descriptions
|
||||||
|
|
||||||
|
-- [me security] Get formspec
|
||||||
|
local function security_formspec(pos, player, rule, q)
|
||||||
|
local list
|
||||||
|
local buttons
|
||||||
|
local logout = true
|
||||||
|
local query = q or ""
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if player and cp then
|
||||||
|
local access = net:get_access_level(player)
|
||||||
|
if access < access_level.manage then -- Blocked dialog
|
||||||
|
logout = false
|
||||||
|
list = "label[2.5,3;"..minetest.colorize("red", "Access Denied").."]"
|
||||||
|
buttons = "button[3.5,6;2,1;logout;back]"
|
||||||
|
elseif (not rule) or rule == "" then -- Main Screen
|
||||||
|
--TODO: show button or entry for default access level
|
||||||
|
list = "tablecolumns[color,span=1;text;color,span=1;text]"
|
||||||
|
.. "table[0.5,2;6,7;access_table;"
|
||||||
|
local first = true
|
||||||
|
--TODO: filter
|
||||||
|
local name_list = {}
|
||||||
|
for p,l in pairs(net:list_access()) do
|
||||||
|
if first then
|
||||||
|
first = false
|
||||||
|
else
|
||||||
|
list = list .. ","
|
||||||
|
end
|
||||||
|
table.insert(name_list, p)
|
||||||
|
local desc = access_desc[l] or {name = "Unknown", color = "red"}
|
||||||
|
list = list .. "cyan," .. p .. "," .. desc.color .. "," .. desc.name
|
||||||
|
end
|
||||||
|
list = list .. ";]"
|
||||||
|
minetest.get_meta(pos):set_string("table_index", minetest.serialize(name_list))
|
||||||
|
|
||||||
|
list = list .. [[
|
||||||
|
field[0.5,1;2,0.5;filter;;]]..query..[[]
|
||||||
|
button[3,1;0.8,0.5;search;?]
|
||||||
|
button[4,1;0.8,0.5;clear;X]
|
||||||
|
tooltip[search;Search]
|
||||||
|
tooltip[clear;Reset]
|
||||||
|
field_close_on_enter[filter;false]
|
||||||
|
]]
|
||||||
|
buttons = [[
|
||||||
|
button[7,7;1.5,0.8;new;new rule]
|
||||||
|
button[7,8;1.5,0.8;edit_sel;edit rule]
|
||||||
|
]]
|
||||||
|
--button[7,6;1.5,0.8;del_sel;delete rule]
|
||||||
|
elseif rule == "<new>" then -- Creation screen
|
||||||
|
logout = false
|
||||||
|
local players = ""
|
||||||
|
for _,p in pairs(minetest.get_connected_players()) do
|
||||||
|
if players ~= "" then
|
||||||
|
players = players .. ","
|
||||||
|
end
|
||||||
|
players = players .. p:get_player_name()
|
||||||
|
end
|
||||||
|
--TODO: add a text field (maybe toggelable)
|
||||||
|
list = [[
|
||||||
|
dropdown[3,2.75;5,0.5;new_player;]]..players..[[;]
|
||||||
|
label[1.5,3;rule for:]
|
||||||
|
]]
|
||||||
|
buttons = [[
|
||||||
|
button[2,6;2,0.8;edit;add/edit]
|
||||||
|
button[5,6;2,0.8;back;cancel]
|
||||||
|
]]
|
||||||
|
elseif (access < access_level.full and net:get_access_level(rule) >= access_level.manage) or (player ~= rule and access >= access_level.full and net:get_access_level(rule) >= access_level.full) then
|
||||||
|
-- low access dialog
|
||||||
|
list = "label[1,3;"..minetest.colorize("red", "You can only modify rules with lower access than yourself.").."]"
|
||||||
|
buttons = "button[3.5,6;2,1;back;back]"
|
||||||
|
else
|
||||||
|
local rule_level = net:get_access_level(rule)
|
||||||
|
local current = rule_level == access_level.blocked and "1" or
|
||||||
|
rule_level == access_level.view and "2" or
|
||||||
|
rule_level == access_level.interact and "3" or
|
||||||
|
rule_level == access_level.modify and "4" or
|
||||||
|
rule_level == access_level.manage and "5" or
|
||||||
|
rule_level == access_level.full and "6" or ""
|
||||||
|
list = [[
|
||||||
|
label[1,3;rule for:]].."\t"..minetest.colorize("cyan", rule)..[[]
|
||||||
|
label[1,4;access level:]
|
||||||
|
dropdown[3,3.75;2,0.5;access;Blocked,View,Interact,Modify,Manage,Full;]]..current..[[]
|
||||||
|
]]
|
||||||
|
buttons = [[
|
||||||
|
button[1,6;1,0.8;save;save]
|
||||||
|
button[3,6;2,0.8;reset;reset to default]
|
||||||
|
button[6,6;1,0.8;back;cancel]
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
elseif cp then
|
||||||
|
logout = false
|
||||||
|
list = "label[2.5,3;Welcome to the security Terminal!]"
|
||||||
|
buttons = [[
|
||||||
|
button[3.5,6;2,1;login;login]
|
||||||
|
button_exit[8,0.5;0.5,0.5;close;x]
|
||||||
|
]]
|
||||||
|
else
|
||||||
|
logout = false
|
||||||
|
list = "label[2.5,3;" .. minetest.colorize("red", "No connected network!") .. "]"
|
||||||
|
buttons = "button_exit[3,6;2,1;close;close]"
|
||||||
|
end
|
||||||
|
|
||||||
|
return [[
|
||||||
|
formspec_version[2]
|
||||||
|
size[9,9.5]
|
||||||
|
]]..
|
||||||
|
microexpansion.gui_bg ..
|
||||||
|
list ..
|
||||||
|
(logout and "button[7.5,0.5;1,0.5;logout;logout]" or "") ..
|
||||||
|
"label[0.5,0.5;ME Security Terminal]" ..
|
||||||
|
buttons
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update_security(pos,_,ev)
|
||||||
|
--for now all events matter
|
||||||
|
|
||||||
|
local network = me.get_connected_network(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
if network == nil then
|
||||||
|
meta:set_string("editing_rule", "")
|
||||||
|
meta:set_string("formspec", security_formspec(pos))
|
||||||
|
end
|
||||||
|
meta:set_string("formspec", security_formspec(pos))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- [me chest] Register node
|
||||||
|
microexpansion.register_node("security", {
|
||||||
|
description = "ME Security Terminal",
|
||||||
|
usedfor = "Allows controlling access to ME networks",
|
||||||
|
tiles = {
|
||||||
|
"security_bottom",
|
||||||
|
"security_bottom",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side",
|
||||||
|
"security_front",
|
||||||
|
},
|
||||||
|
recipe = {
|
||||||
|
{ 1, {
|
||||||
|
{"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"},
|
||||||
|
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
|
||||||
|
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = { cracky = 1, me_connect = 1 },
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
me_update = update_security,
|
||||||
|
on_construct = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
me.send_event(pos,"connect",{net=net})
|
||||||
|
update_security(pos)
|
||||||
|
end,
|
||||||
|
after_destruct = function(pos)
|
||||||
|
me.send_event(pos,"disconnect")
|
||||||
|
end,
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
if not player then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if not net then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return net:get_access_level(name) >= access_level.manage
|
||||||
|
end,
|
||||||
|
on_receive_fields = function(pos, _, fields, sender)
|
||||||
|
if fields.close then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if net then
|
||||||
|
if cp then
|
||||||
|
microexpansion.log("network and ctrl_pos","info")
|
||||||
|
else
|
||||||
|
microexpansion.log("network but no ctrl_pos","warning")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if cp then
|
||||||
|
microexpansion.log("no network but ctrl_pos","warning")
|
||||||
|
else
|
||||||
|
microexpansion.log("no network and no ctrl_pos","info")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local name = sender:get_player_name()
|
||||||
|
if not net then
|
||||||
|
microexpansion.log("no network connected to security terminal","warning")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if fields.logout then
|
||||||
|
meta:set_string("formspec", security_formspec(pos))
|
||||||
|
elseif fields.login or fields.back then
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name))
|
||||||
|
elseif fields.search or fields.key_enter_field == "filter" then
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name), false, fields.filter)
|
||||||
|
elseif fields.clear then
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name))
|
||||||
|
elseif fields.new then
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name, "<new>"))
|
||||||
|
elseif fields.edit then
|
||||||
|
local access = net:get_access_level(name)
|
||||||
|
if not fields.new_player then
|
||||||
|
me.log("edit button without new player field","warning")
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if net:get_access_level(fields.new_player) == nil then
|
||||||
|
if access >= access_level.manage then
|
||||||
|
net:set_access_level(fields.new_player, net:get_access_level())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
meta:set_string("editing_rule", fields.new_player)
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name, fields.new_player))
|
||||||
|
elseif fields.edit_sel then
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name, meta:get_string("editing_rule")))
|
||||||
|
elseif fields.access_table then
|
||||||
|
local ev = minetest.explode_table_event(fields.access_table)
|
||||||
|
local table_index = minetest.deserialize(meta:get_string("table_index"))
|
||||||
|
local edit_player = table_index[ev.row]
|
||||||
|
if net:get_access_level(edit_player) == nil then
|
||||||
|
me.log("playerlist changed before editing","warning")
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name))
|
||||||
|
return
|
||||||
|
else
|
||||||
|
meta:set_string("editing_rule", edit_player)
|
||||||
|
if ev.type == "DCL" then
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name, edit_player))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif fields.reset then
|
||||||
|
local rule = meta:get_string("editing_rule")
|
||||||
|
local access = net:get_access_level(name)
|
||||||
|
local old_level = net:get_access_level(rule)
|
||||||
|
local new_level = net.default_access_level
|
||||||
|
if (access > old_level or name == rule) and (access > new_level or access >= access_level.full) then
|
||||||
|
net:set_access_level(rule, nil)
|
||||||
|
--TODO: show fail dialog if access violation
|
||||||
|
end
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name))
|
||||||
|
elseif fields.save then
|
||||||
|
local rule = meta:get_string("editing_rule")
|
||||||
|
local access = net:get_access_level(name)
|
||||||
|
local old_level = net:get_access_level(rule)
|
||||||
|
local new_level = fields.access == "Blocked" and access_level.blocked or
|
||||||
|
fields.access == "View" and access_level.view or
|
||||||
|
fields.access == "Interact" and access_level.interact or
|
||||||
|
fields.access == "Modify" and access_level.modify or
|
||||||
|
fields.access == "Manage" and access_level.manage or
|
||||||
|
fields.access == "Full" and access_level.full
|
||||||
|
if not new_level then
|
||||||
|
me.log("unknown access level selection " .. fields.access, "error")
|
||||||
|
--TODO: show fail dialog
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if (access > old_level or name == rule) and access > new_level then
|
||||||
|
net:set_access_level(rule, new_level)
|
||||||
|
--TODO: show fail dialog if access violation
|
||||||
|
end
|
||||||
|
meta:set_string("formspec", security_formspec(pos, name))
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
@ -1,6 +1,7 @@
|
|||||||
-- microexpansion/machines.lua
|
-- microexpansion/machines.lua
|
||||||
|
|
||||||
local me = microexpansion
|
local me = microexpansion
|
||||||
|
local access_level = microexpansion.constants.security.access_levels
|
||||||
|
|
||||||
local netdrives
|
local netdrives
|
||||||
|
|
||||||
@ -312,7 +313,19 @@ microexpansion.register_node("drive", {
|
|||||||
me.send_event(pos,"connect")
|
me.send_event(pos,"connect")
|
||||||
end,
|
end,
|
||||||
can_dig = function(pos, player)
|
can_dig = function(pos, player)
|
||||||
if minetest.is_protected(pos, player) then
|
if not player then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if not net then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if net:get_access_level(name) < access_level.modify then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
@ -322,8 +335,17 @@ microexpansion.register_node("drive", {
|
|||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
allow_metadata_inventory_put = function(_, _, _, stack)
|
allow_metadata_inventory_put = function(pos, _, _, stack, player)
|
||||||
if minetest.is_protected(pos, player) or minetest.get_item_group(stack:get_name(), "microexpansion_cell") == 0 then
|
local network = me.get_connected_network(pos)
|
||||||
|
if network then
|
||||||
|
if network:get_access_level(player) < access_level.interact then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
elseif minetest.is_protected(pos, player) then
|
||||||
|
minetest.record_protection_violation(pos, player)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if minetest.get_item_group(stack:get_name(), "microexpansion_cell") == 0 then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@ -349,11 +371,16 @@ microexpansion.register_node("drive", {
|
|||||||
me.send_event(pos,"items",{net=network})
|
me.send_event(pos,"items",{net=network})
|
||||||
end,
|
end,
|
||||||
allow_metadata_inventory_take = function(pos,_,_,stack, player) --args: pos, listname, index, stack, player
|
allow_metadata_inventory_take = function(pos,_,_,stack, player) --args: pos, listname, index, stack, player
|
||||||
if minetest.is_protected(pos, player) then
|
local network = me.get_connected_network(pos)
|
||||||
|
if network then
|
||||||
|
write_drive_cells(pos,network)
|
||||||
|
if network:get_access_level(player) < access_level.interact then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
elseif minetest.is_protected(pos, player) then
|
||||||
|
minetest.record_protection_violation(pos, player)
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
local network = me.get_connected_network(pos)
|
|
||||||
write_drive_cells(pos,network)
|
|
||||||
return stack:get_count()
|
return stack:get_count()
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_take = function(pos, _, _, stack)
|
on_metadata_inventory_take = function(pos, _, _, stack)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
local me = microexpansion
|
local me = microexpansion
|
||||||
local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
|
local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
|
||||||
|
local access_level = microexpansion.constants.security.access_levels
|
||||||
|
|
||||||
-- [me chest] Get formspec
|
-- [me chest] Get formspec
|
||||||
local function chest_formspec(pos, start_id, listname, page_max, q)
|
local function chest_formspec(pos, start_id, listname, page_max, q)
|
||||||
@ -121,13 +122,52 @@ microexpansion.register_node("term", {
|
|||||||
update_chest(pos)
|
update_chest(pos)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
if not player then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
if not net then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return net:get_access_level(name) >= access_level.modify
|
||||||
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
|
allow_metadata_inventory_put = function(pos, _, _, stack, player)
|
||||||
|
local network = me.get_connected_network(pos)
|
||||||
|
if network then
|
||||||
|
if network:get_access_level(player) < access_level.interact then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
elseif minetest.is_protected(pos, player) then
|
||||||
|
minetest.record_protection_violation(pos, player)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return stack:get_count()
|
||||||
|
end,
|
||||||
on_metadata_inventory_put = function(pos, listname, _, stack)
|
on_metadata_inventory_put = function(pos, listname, _, stack)
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
local inv = net:get_inventory()
|
local inv = net:get_inventory()
|
||||||
me.insert_item(stack, inv, "main")
|
me.insert_item(stack, inv, "main")
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_take = function(pos,_,_,stack, player)
|
||||||
|
local network = me.get_connected_network(pos)
|
||||||
|
if network then
|
||||||
|
if network:get_access_level(player) < access_level.interact then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
elseif minetest.is_protected(pos, player) then
|
||||||
|
minetest.record_protection_violation(pos, player)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return math.min(stack:get_count(),stack:get_stack_max())
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_take = function(pos, listname, _, stack)
|
on_metadata_inventory_take = function(pos, listname, _, stack)
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
@ -242,6 +282,9 @@ microexpansion.register_node("term", {
|
|||||||
meta:set_string("inv_name", "main")
|
meta:set_string("inv_name", "main")
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
elseif fields.tochest then
|
elseif fields.tochest then
|
||||||
|
if net:get_access_level(sender) < access_level.interact then
|
||||||
|
return
|
||||||
|
end
|
||||||
local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()})
|
local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()})
|
||||||
net:set_storage_space(pinv:get_size("main"))
|
net:set_storage_space(pinv:get_size("main"))
|
||||||
local space = net:get_item_capacity()
|
local space = net:get_item_capacity()
|
||||||
|
BIN
textures/microexpansion_security_bottom.png
Normal file
BIN
textures/microexpansion_security_bottom.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.7 KiB |
BIN
textures/microexpansion_security_front.png
Normal file
BIN
textures/microexpansion_security_front.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
Loading…
Reference in New Issue
Block a user