osmarks

spatial TP

Jun 7th, 2021 (edited)
115
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local m = peripheral.find("modem", function(_, o) return o.isWireless() end)
  2. local ec_oc = peripheral.find "ender_chest"
  3. local ec_cc = peripheral.find "minecraft:ender chest"
  4. local spatial = "back"
  5. local spatialp = peripheral.wrap(spatial)
  6. local name = os.getComputerLabel()
  7. local channel = 236
  8. local spatial_ec_loc = settings.get "spatial_ec_loc" or "east"
  9. local busy = false
  10. local needed_energy = 34000
  11.  
  12. local function send(x)
  13.     print("->", unpack(x))
  14.     m.transmit(channel, channel, x)
  15. end
  16.  
  17. local function recv_filter(fn)
  18.     while true do
  19.         local _, _, c, rc, msg = os.pullEvent "modem_message"
  20.         print("<-", unpack(msg))
  21.         if type(msg) == "table" and fn(msg) then return msg end
  22.     end
  23. end
  24.  
  25. local function pick_channel()
  26.     return math.random(0xA00, 0xC00)
  27. end
  28.  
  29. local function run_spatial()
  30.     rs.setOutput(spatial, true)
  31.     sleep(0.1)
  32.     rs.setOutput(spatial, false)
  33.     sleep(0.1)
  34.     print "Run spatial"
  35. end
  36.  
  37. local function run_transfer(trg)
  38.     busy = true
  39.     local function run_transfer_internal()
  40.         if spatialp.getNetworkEnergyStored() < needed_energy then print "Insufficient energy" return end
  41.         print "Pinging"
  42.         send { "ping", trg }
  43.         if (recv_filter(function(m) return m[1] == "pong" and m[2] == trg end))[3] then print "Remote busy" return end
  44.         print "Destination available"
  45.         local ec_channel = pick_channel()
  46.         ec_oc.setFrequency(ec_channel)
  47.         send { "transfer", trg, ec_channel }
  48.         if not (recv_filter(function(m) return m[1] == "transfer_ack" and m[2] == trg end))[3] then print "Remote denied transfer" return end
  49.         print "Ack received"
  50.         run_spatial()
  51.         spatialp.pushItems(spatial_ec_loc, 2, 1, 1)
  52.         print "Sent item to remote"
  53.         repeat
  54.             sleep(0.1)
  55.         until ec_cc.getItemMeta(27) ~= nil
  56.         print("Remote sent item")
  57.         spatialp.pullItems(spatial_ec_loc, 27, 1, 1)
  58.         run_spatial()
  59.         spatialp.pullItems("self", 2, 1, 1)
  60.         print "Done"
  61.     end
  62.     parallel.waitForAny(run_transfer_internal, function() sleep(5) print "Transfer timed out" end)
  63.     busy = false
  64. end
  65.  
  66. local pings_timer = nil
  67. local function list_all()
  68.     pings_timer = os.startTimer(1)
  69.     send { "ping" }
  70. end
  71.  
  72. local function inbound()
  73.     local function run_transfer_recv(msg)
  74.         print("Transfer request from", msg[2])
  75.         if spatialp.getNetworkEnergyStored() < needed_energy then print "Insufficient energy" send { "transfer_ack", msg[2], false } return end
  76.         if busy then print "Already busy, cannot accept transfer" send { "transfer_ack", msg[2], false } return end
  77.         busy = true
  78.         send { "transfer_ack", msg[2], true }
  79.         print("Accepting transfer from", msg[2])
  80.         ec_oc.setFrequency(msg[3])
  81.         repeat
  82.             sleep(0.1)
  83.         until ec_cc.getItemMeta(1) ~= nil
  84.         print "Remote sent item"
  85.         run_spatial()
  86.         spatialp.pullItems(spatial_ec_loc, 1, 1, 1)
  87.         spatialp.pushItems(spatial_ec_loc, 2, 1, 27)
  88.         print "Sent item to remote"
  89.         run_spatial()
  90.         spatialp.pullItems("self", 2, 1, 1)
  91.         print "Done"
  92.     end
  93.  
  94.     local function process(msg)
  95.         local cmd = msg[1]
  96.         if cmd == "ping" and (msg[2] == nil or msg[2] == name) then
  97.             send { "pong", name, busy }
  98.         elseif pings_timer and cmd == "pong" then
  99.             print(msg[2])
  100.         elseif cmd == "transfer" and msg[2] == name and type(msg[3]) == "number" then
  101.             parallel.waitForAny(function() run_transfer_recv(msg) end, function() sleep(5) print "Inbound transfer timed out" end)
  102.             busy = false
  103.         end
  104.     end
  105.  
  106.     m.open(channel)
  107.     while true do
  108.         local ev, timer, c, rc, msg = os.pullEvent()
  109.         if ev == "modem_message" and c == channel and rc == channel and type(msg) == "table" then
  110.             local ok, err = pcall(process, msg)
  111.             if not ok then printError(err) end
  112.         elseif ev == "timer" and timer == pings_timer then
  113.             pings_timer = nil
  114.         end
  115.     end
  116. end
  117.  
  118. local function split_at_spaces(s)
  119.     local t = {}
  120.     for i in string.gmatch(s, "%S+") do
  121.        table.insert(t, i)
  122.     end
  123.     return t
  124. end
  125.  
  126. local function update_self()
  127.     print "Downloading update."
  128.     local h = http.get "https://pastebin.com/raw/R4HrijSg"
  129.     local t = h.readAll()
  130.     h.close()
  131.     local fn, err = load(t, "@program")
  132.     if not fn then printError("Not updating: syntax error in new version:\n" .. err) return end
  133.     local f = fs.open("startup", "w")
  134.     f.write(t)
  135.     f.close()
  136.     os.reboot()
  137. end
  138.  
  139. local function ui()
  140.     local history = {}
  141.     while true do
  142.         write "|> "
  143.         local input = read(nil, history)
  144.         table.insert(history, input)
  145.         local tokens = split_at_spaces(input)
  146.         if tokens[1] == "list" then
  147.             list_all()
  148.             sleep(1)
  149.         elseif tokens[1] == "update" then
  150.             update_self()
  151.         elseif tokens[1] == "tp" then
  152.             table.remove(tokens, 1)
  153.             run_transfer(table.concat(tokens, " "))
  154.         else
  155.             printError "Not found"
  156.         end
  157.     end
  158. end
  159.  
  160. parallel.waitForAll(ui, inbound)
RAW Paste Data