OpenComputers Von Neumann Machine Programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
4.8 KiB

local net = require("net")
local component = require("component")
local sides = require("sides")
local os = require("os")
-- location of eeprom in computer case
local EEPROM_SLOT = 10
local transposer = component.transposer
-- Waits for a SYN from a worker and responds with an ACK
-- Returns the workers address
local function meetWorker(port)
print("Waiting for worker")
local function syn(name, ...)
-- local addr, remote addr, port, distance, msg
local t = {...}
return t[5] == "SYN"
end
-- Wait for a SYN
local pkt, err = net.recv{port, filter = syn}
-- ACK the worker
net.send(pkt.raddr, port, "ACK")
print("Found worker", pkt.raddr)
return pkt.raddr
end
-- Checks if the top chest is filled
local function isFilled()
local i = 1
for k in transposer.getAllStacks(sides.top) do
if k.size == nil then break end
i = i + 1
end
return i >= 27
end
-- Moves the EEPROM from the worker into the top chest
-- Optionally include the slot
-- Returns the slot the eeprom was moved to
local function removeEEPROM(sink_slot)
print("REMOVING - ", sink_slot)
if sink_slot == nil then
local i = 1
for k in transposer.getAllStacks(sides.top) do
if k.size == nil then break end
i = i + 1
end
if i == 27 then
return nil, "Inventory filled"
end
sink_slot = i
end
-- Remove the OpenOS Bios and store it in the top chest
transposer.transferItem(sides.left, sides.top, 1, EEPROM_SLOT, sink_slot)
return sink_slot
end
-- Moves a blank EEPROM from storage into the worker
local function loadNewEEPROM()
print("LOADING")
-- Find largest inventory slot in the storage with an eeprom
local i = 1
local last = nil
for k in transposer.getAllStacks(sides.right) do
if k.size ~= nil then
last = i
end
i = i + 1
end
if last == nil then
return nil, "No EEPROMS"
end
-- Move the new EEPROM into computer
transposer.transferItem(sides.right, sides.left, 1, last, EEPROM_SLOT)
return true
end
local function flashEEPROM(worker, port, data, label)
print("Send", worker, port, "flash", label)
net.send(worker, port, "flash", data, label)
local function fromWorker(name, ...)
t = {...}
return t[2] == worker
end
local pkt, error = net.recv{port, filter=fromWorker}
if pkt.msg == "flash-good" then
return true
else
return nil, pkt.msg
end
end
local function respond(pkt, code, error)
print("SEND", pkt.raddr, pkt.port, code, error)
net.send(pkt.raddr, pkt.port, code, error)
computer.beep(200)
end
-- Waits to recv a message
local function waitForJob(port, worker)
local pkt, err = net.recv{port}
if pkt == nil and err ~= "interrupted" then
return pkt
end
-- "eeprom-flash file-contents"
if pkt.msg == "eeprom-flash" then
-- 4k is the largest an eeprom can hold
if #pkt.data[2] > 4096 then
respond(pkt, 400, "file too large")
return pkt
end
if isFilled() then respond(pkt, 500, "inventory filled") return end
-- Remove the OpenOS Bios and store it in the last slot of top chest
local res, err = removeEEPROM(27)
if res == nil then respond(pkt, 500, err) return end
computer.beep(100)
local res, err = loadNewEEPROM()
if res == nil then respond(pkt, 500, err) return end
computer.beep(100)
if pkt.data[3] == nil then
pkt.data[3] = "Flashed EEPROM"
end
local res, err = flashEEPROM(worker, port, pkt.data[2], pkt.data[3])
if res == nil then respond(pkt, 500, err) return end
-- Now the NBT data of the eeprom will update on the next auto save
-- To detect this we're going to check the item stack every few seconds until the labels match
local i = 0
while transposer.getStackInSlot(sides.left, EEPROM_SLOT).label ~= pkt.data[3] do
print("Checking for autosave...")
computer.beep(500)
os.sleep(2.5)
i = i + 1
end
print("Autosave detected! Took " .. tostring(2.5 * i) .. " seconds")
computer.beep(1000)
local location, err = removeEEPROM()
if location == nil then respond(pkt, 500, err) return end
computer.beep(100)
-- Load the old EERPOM
transposer.transferItem(sides.top, sides.left, 1, 27, EEPROM_SLOT)
computer.beep(100)
respond(pkt, 200, location)
computer.beep(1000)
end
end
local function startServer(port)
worker = meetWorker(port)
while true do
print(waitForJob(port, worker))
end
end
startServer(10)