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.

212 lines
5.5 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. local Socket = Socket or require("socket")
  2. local net = net or require("net")
  3. local component = component or require("component")
  4. local computer = computer or require("computer")
  5. local event = event or require("event")
  6. local sides = sides or require("sides")
  7. local os = os or require("os")
  8. -- location of eeprom in computer case
  9. local EEPROM_SLOT = 10
  10. local transposer = component.transposer
  11. -- Waits for a SYN from the worker and responds with an ACK
  12. -- Returns a socket connected to the worker
  13. local function meetWorker(port)
  14. print("Waiting for worker...")
  15. local function syn(name, ...)
  16. -- local addr, remote addr, port, distance, msg
  17. local t = {...}
  18. return t[5] == "SYN"
  19. end
  20. -- Wait for a SYN
  21. local pkt, err = net.recv{port, filter = syn}
  22. -- ACK the worker
  23. local s = Socket(pkt.raddr, port)
  24. s:send("ACK")
  25. print("Found worker " .. pkt.raddr)
  26. return s
  27. end
  28. -- Checks if the top chest is filled
  29. local function isFilled()
  30. local i = 1
  31. for k in transposer.getAllStacks(sides.top) do
  32. if k.size == nil then break end
  33. i = i + 1
  34. end
  35. return i >= 27
  36. end
  37. -- Moves the EEPROM from the worker into the top chest
  38. -- Optionally include the slot
  39. -- Returns the slot the eeprom was moved to
  40. local function removeEEPROM(sink_slot)
  41. if sink_slot == nil then
  42. local i = 1
  43. for k in transposer.getAllStacks(sides.top) do
  44. for m, n in pairs(k) do print(m, n) end
  45. if k.size == nil then break end
  46. i = i + 1
  47. end
  48. if i == 27 then
  49. print("Inventory filled")
  50. return nil, "Inventory filled"
  51. end
  52. sink_slot = i
  53. end
  54. print("Moving EEPROM to slot " .. tostring(sink_slot))
  55. -- Remove the OpenOS Bios and store it in the top chest
  56. transposer.transferItem(sides.left, sides.top, 1, EEPROM_SLOT, sink_slot)
  57. print("Move complete")
  58. return sink_slot
  59. end
  60. -- Moves a blank EEPROM from storage into the worker
  61. local function loadNewEEPROM()
  62. print("Loading new EEPROM...")
  63. -- Find largest inventory slot in the storage with an eeprom
  64. local i = 1
  65. local last = nil
  66. for k in transposer.getAllStacks(sides.right) do
  67. if k.size ~= nil then
  68. last = i
  69. end
  70. i = i + 1
  71. end
  72. if last == nil then
  73. print("No blank EEPROMS")
  74. return nil, "No EEPROMS"
  75. end
  76. -- Move the new EEPROM into computer
  77. print("Loading complete")
  78. transposer.transferItem(sides.right, sides.left, 1, last, EEPROM_SLOT)
  79. return true
  80. end
  81. local function flashEEPROM(worker, data, label)
  82. print("Asking worker to flash " .. "...")
  83. worker:send("flash", data, label)
  84. local pkt = worker:recieve(true)
  85. for k, v in pairs(pkt) do print(k, v) end
  86. print("Flash complete " .. pkt.msg)
  87. if pkt.msg == "flash-good" then
  88. return true
  89. else
  90. return nil, pkt.msg
  91. end
  92. end
  93. -- Waits to recv a message
  94. local function waitForJob(port, worker)
  95. local function ignore(_, _, raddr) return raddr ~= net.addr and raddr ~= worker.raddr end
  96. local pkt, err = net.recv{port, filter=ignore}
  97. if pkt == nil and err ~= "interrupted" then
  98. return pkt
  99. end
  100. -- Create a new socket
  101. local client = Socket(pkt.raddr, port)
  102. -- "eeprom-flash file-contents label"
  103. if pkt.msg == "webflash" then
  104. -- 4k is the largest an eeprom can hold
  105. if #pkt.data[2] > 4096 then
  106. client:send(400, "file too large")
  107. return pkt
  108. end
  109. if isFilled() then client:send(500, "inventory filled") return end
  110. -- Remove the OpenOS Bios and store it in the last slot of top chest
  111. local res, err = removeEEPROM(27)
  112. if res == nil then client:send(500, err) return end
  113. computer.beep(100)
  114. local res, err = loadNewEEPROM()
  115. if res == nil then client:send(500, err) return end
  116. computer.beep(100)
  117. if pkt.data[3] == nil then
  118. pkt.data[3] = "Flashed EEPROM"
  119. end
  120. local res, err = flashEEPROM(worker, pkt.data[2], pkt.data[3])
  121. if res == nil then client:send(500, err) return end
  122. -- Now the NBT data of the eeprom will update on the next auto save
  123. -- To detect this we're going to check the item stack every few seconds until the labels match
  124. local i = 0
  125. while transposer.getStackInSlot(sides.left, EEPROM_SLOT).label ~= pkt.data[3] do
  126. print("Checking for autosave...")
  127. computer.beep(500)
  128. os.sleep(2.5)
  129. i = i + 1
  130. end
  131. print("Autosave detected! Took " .. tostring(2.5 * i) .. " seconds")
  132. computer.beep(1000)
  133. local location, err = removeEEPROM()
  134. if location == nil then client:send(500, err) return end
  135. computer.beep(100)
  136. -- Load the old EERPOM
  137. transposer.transferItem(sides.top, sides.left, 1, 27, EEPROM_SLOT)
  138. computer.beep(100)
  139. client:send(200, location)
  140. computer.beep(1000)
  141. print("Success!")
  142. else
  143. client:send(404)
  144. end
  145. client:close()
  146. end
  147. local function startServer(port)
  148. print("I am " .. net.addr)
  149. local worker = meetWorker(port)
  150. local interrupted = false
  151. -- Soft interrupt
  152. local interruptID = event.listen("interrupted", function() interrupted = true end)
  153. while not interrupted do
  154. waitForJob(port, worker)
  155. end
  156. -- Don't forget to close sockets!
  157. worker:close()
  158. event.cancel(interruptID)
  159. end
  160. startServer(10)