mirror of
https://github.com/osmarks/random-stuff
synced 2024-12-29 11:30:35 +00:00
160 lines
4.6 KiB
Lua
160 lines
4.6 KiB
Lua
|
local m = peripheral.find("modem", function(_, o) return o.isWireless() end)
|
||
|
local ec_oc = peripheral.find "ender_chest"
|
||
|
local ec_cc = peripheral.find "minecraft:ender chest"
|
||
|
local spatial = "back"
|
||
|
local spatialp = peripheral.wrap(spatial)
|
||
|
local name = os.getComputerLabel()
|
||
|
local channel = 236
|
||
|
local spatial_ec_loc = settings.get "spatial_ec_loc" or "east"
|
||
|
local busy = false
|
||
|
local needed_energy = 34000
|
||
|
|
||
|
local function send(x)
|
||
|
print("->", unpack(x))
|
||
|
m.transmit(channel, channel, x)
|
||
|
end
|
||
|
|
||
|
local function recv_filter(fn)
|
||
|
while true do
|
||
|
local _, _, c, rc, msg = os.pullEvent "modem_message"
|
||
|
print("<-", unpack(msg))
|
||
|
if type(msg) == "table" and fn(msg) then return msg end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function pick_channel()
|
||
|
return math.random(0xA00, 0xC00)
|
||
|
end
|
||
|
|
||
|
local function run_spatial()
|
||
|
rs.setOutput(spatial, true)
|
||
|
sleep(0.1)
|
||
|
rs.setOutput(spatial, false)
|
||
|
sleep(0.1)
|
||
|
print "Run spatial"
|
||
|
end
|
||
|
|
||
|
local function run_transfer(trg)
|
||
|
busy = true
|
||
|
local function run_transfer_internal()
|
||
|
if spatialp.getNetworkEnergyStored() < needed_energy then print "Insufficient energy" return end
|
||
|
print "Pinging"
|
||
|
send { "ping", trg }
|
||
|
if (recv_filter(function(m) return m[1] == "pong" and m[2] == trg end))[3] then print "Remote busy" return end
|
||
|
print "Destination available"
|
||
|
local ec_channel = pick_channel()
|
||
|
ec_oc.setFrequency(ec_channel)
|
||
|
send { "transfer", trg, ec_channel }
|
||
|
if not (recv_filter(function(m) return m[1] == "transfer_ack" and m[2] == trg end))[3] then print "Remote denied transfer" return end
|
||
|
print "Ack received"
|
||
|
run_spatial()
|
||
|
spatialp.pushItems(spatial_ec_loc, 2, 1, 1)
|
||
|
print "Sent item to remote"
|
||
|
repeat
|
||
|
sleep(0.1)
|
||
|
until ec_cc.getItemMeta(27) ~= nil
|
||
|
print("Remote sent item")
|
||
|
spatialp.pullItems(spatial_ec_loc, 27, 1, 1)
|
||
|
run_spatial()
|
||
|
spatialp.pullItems("self", 2, 1, 1)
|
||
|
print "Done"
|
||
|
end
|
||
|
parallel.waitForAny(run_transfer_internal, function() sleep(5) print "Transfer timed out" end)
|
||
|
busy = false
|
||
|
end
|
||
|
|
||
|
local pings_timer = nil
|
||
|
local function list_all()
|
||
|
pings_timer = os.startTimer(1)
|
||
|
send { "ping" }
|
||
|
end
|
||
|
|
||
|
local function inbound()
|
||
|
local function run_transfer_recv(msg)
|
||
|
print("Transfer request from", msg[2])
|
||
|
if spatialp.getNetworkEnergyStored() < needed_energy then print "Insufficient energy" send { "transfer_ack", msg[2], false } return end
|
||
|
if busy then print "Already busy, cannot accept transfer" send { "transfer_ack", msg[2], false } return end
|
||
|
busy = true
|
||
|
send { "transfer_ack", msg[2], true }
|
||
|
print("Accepting transfer from", msg[2])
|
||
|
ec_oc.setFrequency(msg[3])
|
||
|
repeat
|
||
|
sleep(0.1)
|
||
|
until ec_cc.getItemMeta(1) ~= nil
|
||
|
print "Remote sent item"
|
||
|
run_spatial()
|
||
|
spatialp.pullItems(spatial_ec_loc, 1, 1, 1)
|
||
|
spatialp.pushItems(spatial_ec_loc, 2, 1, 27)
|
||
|
print "Sent item to remote"
|
||
|
run_spatial()
|
||
|
spatialp.pullItems("self", 2, 1, 1)
|
||
|
print "Done"
|
||
|
end
|
||
|
|
||
|
local function process(msg)
|
||
|
local cmd = msg[1]
|
||
|
if cmd == "ping" and (msg[2] == nil or msg[2] == name) then
|
||
|
send { "pong", name, busy }
|
||
|
elseif pings_timer and cmd == "pong" then
|
||
|
print(msg[2])
|
||
|
elseif cmd == "transfer" and msg[2] == name and type(msg[3]) == "number" then
|
||
|
parallel.waitForAny(function() run_transfer_recv(msg) end, function() sleep(5) print "Inbound transfer timed out" end)
|
||
|
busy = false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
m.open(channel)
|
||
|
while true do
|
||
|
local ev, timer, c, rc, msg = os.pullEvent()
|
||
|
if ev == "modem_message" and c == channel and rc == channel and type(msg) == "table" then
|
||
|
local ok, err = pcall(process, msg)
|
||
|
if not ok then printError(err) end
|
||
|
elseif ev == "timer" and timer == pings_timer then
|
||
|
pings_timer = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function split_at_spaces(s)
|
||
|
local t = {}
|
||
|
for i in string.gmatch(s, "%S+") do
|
||
|
table.insert(t, i)
|
||
|
end
|
||
|
return t
|
||
|
end
|
||
|
|
||
|
local function update_self()
|
||
|
print "Downloading update."
|
||
|
local h = http.get "https://pastebin.com/raw/R4HrijSg"
|
||
|
local t = h.readAll()
|
||
|
h.close()
|
||
|
local fn, err = load(t, "@program")
|
||
|
if not fn then printError("Not updating: syntax error in new version:\n" .. err) return end
|
||
|
local f = fs.open("startup", "w")
|
||
|
f.write(t)
|
||
|
f.close()
|
||
|
os.reboot()
|
||
|
end
|
||
|
|
||
|
local function ui()
|
||
|
local history = {}
|
||
|
while true do
|
||
|
write "|> "
|
||
|
local input = read(nil, history)
|
||
|
table.insert(history, input)
|
||
|
local tokens = split_at_spaces(input)
|
||
|
if tokens[1] == "list" then
|
||
|
list_all()
|
||
|
sleep(1)
|
||
|
elseif tokens[1] == "update" then
|
||
|
update_self()
|
||
|
elseif tokens[1] == "tp" then
|
||
|
table.remove(tokens, 1)
|
||
|
run_transfer(table.concat(tokens, " "))
|
||
|
else
|
||
|
printError "Not found"
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
parallel.waitForAll(ui, inbound)
|