mirror of
https://github.com/theFox6/microexpansion.git
synced 2024-11-30 02:43:49 +01:00
258 lines
6.8 KiB
Lua
258 lines
6.8 KiB
Lua
local me = microexpansion
|
|
me.networks = {}
|
|
local networks = me.networks
|
|
local path = microexpansion.get_module_path("network")
|
|
local storage = minetest.get_mod_storage()
|
|
|
|
dofile(path.."/constants.lua")
|
|
|
|
--deprecated: use ItemStack(x) instead
|
|
--[[
|
|
local function split_stack_values(stack)
|
|
if type(stack) == "string" then
|
|
local split_string = stack:split(" ")
|
|
if (#split_string < 1) then
|
|
return "",0,0,nil
|
|
end
|
|
local stack_name = split_string[1]
|
|
if (#split_string < 2) then
|
|
return stack_name,1,0,nil
|
|
end
|
|
local stack_count = tonumber(split_string[2])
|
|
if (#split_string < 3) then
|
|
return stack_name,stack_count,0,nil
|
|
end
|
|
local stack_wear = tonumber(split_string[3])
|
|
if (#split_string < 4) then
|
|
return stack_name,stack_count,stack_wear,nil
|
|
end
|
|
return stack_name,stack_count,stack_wear,true
|
|
else
|
|
return stack:get_name(), stack:get_count(), stack:get_wear(), stack:get_meta()
|
|
end
|
|
end
|
|
--]]
|
|
|
|
function me.insert_item(stack, inv, listname)
|
|
if me.settings.huge_stacks == false then
|
|
return inv:add_item(listname, stack)
|
|
end
|
|
local to_insert = type(stack) == "userdata" and stack or ItemStack(stack)
|
|
local found = false
|
|
for i = 0, inv:get_size(listname) do
|
|
local inside = inv:get_stack(listname, i)
|
|
if inside:get_name() == to_insert:get_name() and inside:get_wear() == to_insert:get_wear() then
|
|
if inside:get_meta():equals(to_insert:get_meta()) then
|
|
local total_count = inside:get_count() + to_insert:get_count()
|
|
-- bigger item count is not possible, we only have unsigned 16 bit
|
|
if total_count <= math.pow(2,16) then
|
|
if not inside:set_count(total_count) then
|
|
microexpansion.log("adding items to stack in microexpansion network failed","error")
|
|
print("stack is now " .. inside:to_string())
|
|
end
|
|
inv:set_stack(listname, i, inside)
|
|
found = true
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if not found then
|
|
return inv:add_item(listname, stack)
|
|
end
|
|
end
|
|
|
|
dofile(path.."/network.lua") -- Network Management
|
|
|
|
-- generate iterator to find all connected nodes
|
|
function me.connected_nodes(start_pos,include_ctrl)
|
|
-- nodes to be checked
|
|
local open_list = {{pos = start_pos}}
|
|
-- nodes that were checked
|
|
local closed_set = {}
|
|
-- local connected nodes function to reduce table lookups
|
|
local adjacent_connected_nodes = me.network.adjacent_connected_nodes
|
|
-- return the generated iterator
|
|
return function ()
|
|
-- start looking for next pos
|
|
local open = false
|
|
-- pos to be checked
|
|
local current
|
|
-- find next unclosed
|
|
while not open do
|
|
-- get unchecked pos
|
|
current = table.remove(open_list)
|
|
-- none are left
|
|
if current == nil then return end
|
|
-- assume it's open
|
|
open = true
|
|
-- check the closed positions
|
|
for _,closed in pairs(closed_set) do
|
|
-- if current is unclosed
|
|
if vector.equals(closed,current.pos) then
|
|
--found one was closed
|
|
open = false
|
|
end
|
|
end
|
|
end
|
|
-- get all connected nodes
|
|
local nodes = adjacent_connected_nodes(current.pos,include_ctrl)
|
|
-- iterate through them
|
|
for _,n in pairs(nodes) do
|
|
-- mark position to be checked
|
|
table.insert(open_list,n)
|
|
end
|
|
-- add this one to the closed set
|
|
table.insert(closed_set,current.pos)
|
|
-- return the one to be checked
|
|
return current.pos,current.name
|
|
end
|
|
end
|
|
|
|
-- get network connected to position
|
|
function me.get_connected_network(start_pos)
|
|
for npos,nn in me.connected_nodes(start_pos,true) do
|
|
if nn == "microexpansion:ctrl" then
|
|
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
|
|
return network,npos
|
|
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)
|
|
microexpansion.log("updating connected machines","action")
|
|
local ev = event or {type = "n/a"}
|
|
local sn = microexpansion.get_node(start_pos)
|
|
local sd = minetest.registered_nodes[sn.name]
|
|
local sm = sd.machine or {}
|
|
ev.origin = {
|
|
pos = start_pos,
|
|
name = sn.name,
|
|
type = sm.type
|
|
}
|
|
--print(dump2(ev,"event"))
|
|
for npos in me.connected_nodes(start_pos) do
|
|
if include_start or not vector.equals(npos,start_pos) then
|
|
me.update_node(npos,ev)
|
|
end
|
|
end
|
|
end
|
|
|
|
function me.send_event(spos,type,data)
|
|
local d = data or {}
|
|
local event = {
|
|
type = type,
|
|
net = d.net,
|
|
payload = d.payload
|
|
}
|
|
me.update_connected_machines(spos,event,false)
|
|
end
|
|
|
|
function me.get_network(pos)
|
|
for i,net in pairs(networks) do
|
|
if net.controller_pos then
|
|
if vector.equals(pos, net.controller_pos) then
|
|
return net,i
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
dofile(path.."/ctrl.lua") -- Controller/wires
|
|
dofile(path.."/security.lua") --Security Terminal
|
|
|
|
-- load networks
|
|
function me.load()
|
|
local res = storage:get_string("networks")
|
|
if res == "" then
|
|
local f = io.open(me.worldpath.."/microexpansion_networks", "r")
|
|
if f then
|
|
me.log("loading network data from file","action")
|
|
res = minetest.deserialize(f:read("*all"))
|
|
f:close()
|
|
else
|
|
me.log("no network data loaded","action")
|
|
return
|
|
end
|
|
else
|
|
me.log("loading network data from mod storage","action")
|
|
res = minetest.deserialize(res)
|
|
end
|
|
if type(res) == "table" then
|
|
for _,n in pairs(res) do
|
|
local net = me.network.new(n)
|
|
net:load()
|
|
table.insert(me.networks,net)
|
|
end
|
|
else
|
|
me.log("network data in unexpected format","error")
|
|
end
|
|
end
|
|
|
|
-- load now
|
|
me.load()
|
|
|
|
-- save networks
|
|
function me.save()
|
|
local data = {}
|
|
for _,v in pairs(me.networks) do
|
|
table.insert(data,v:serialize())
|
|
end
|
|
if storage then
|
|
me.log("saving network data to mod storage","info")
|
|
storage:set_string("networks", minetest.serialize(data))
|
|
else
|
|
me.log("saving network data to file","info")
|
|
local f = io.open(me.worldpath.."/microexpansion_networks", "w")
|
|
f:write(minetest.serialize(data))
|
|
f:close()
|
|
end
|
|
end
|
|
|
|
function me.do_autosave()
|
|
me.last_autosave = -1
|
|
minetest.after(1, function()
|
|
--print("autosaving ME Networks")
|
|
me.save()
|
|
me.last_autosave = minetest.get_server_uptime()
|
|
end)
|
|
end
|
|
|
|
function me.autosave()
|
|
--TODO: make max autosave interval settable
|
|
if not me.last_autosave then
|
|
me.do_autosave()
|
|
elseif me.last_autosave == -1 then
|
|
return
|
|
elseif minetest.get_server_uptime() - me.last_autosave >= 600 then
|
|
me.do_autosave()
|
|
end
|
|
end
|
|
|
|
-- save on server shutdown
|
|
minetest.register_on_shutdown(me.save)
|