Guest User

main.lua

a guest
May 27th, 2025
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 56.51 KB | None | 0 0
  1. term.clear()
  2. -- API Initialization
  3. if api then os.unloadAPI("api.lua") end
  4. if not os.loadAPI("api.lua") then error("missing Des/warpdrive/api") end
  5. local w = api.w
  6.  
  7. local data
  8.  
  9. --THIS PROGRAM HAS BEEN MODIFIED TO SUPPORT MULTIPLE WARPDRIVE CORES.
  10. --THIS PROGRAM HAS BEEN MODIFIED TO INCLUDE AN AUTOPILOT THAT IS NOT PROPERLY IMPLEMENTED
  11. --modified by discord@thisismylegacy
  12. debug = false
  13.  
  14. ----------- Ship support
  15.  
  16. local ship
  17. local ship_front = 0
  18. local ship_right = 0
  19. local ship_up = 0
  20. local ship_back = 0
  21. local ship_left = 0
  22. local ship_down = 0
  23. local ship_isInHyper = false
  24. local ship_x, ship_y, ship_z = 0, 0, 0
  25. local ship_xTarget, ship_yTarget, ship_zTarget = 0, 0, 0
  26. local ship_actualDistance = 0
  27. local ship_energyRequired = 0
  28. local ship_movement = { 0, 0, 0 }
  29. local ship_rotationSteps = 0
  30. local ship_indexPlayer = 0
  31. local ship_arrayPlayers = { }
  32. local ship_indexTarget = 0
  33. local ship_indexCore = 0
  34. local name = "<@>" -- Discord ID
  35. local uri = "https://disco" -- Discord Uri
  36. local lever = "front" -- format: front,back,left,right,top,bottom ONLY
  37. local failping = 0 -- format: Will ping on Failed node execution 0 = Dont Ping, 1 = Ping
  38. local navdatafile = ".navdata"
  39. local navbackup = ".navbackup"
  40. local navdata={} -- format: {{dx,dy,dz},{dx,dy,dz},...} -- these are ship coords (forward, up, right)
  41. local cores = {} -- cores table for multicore processing
  42. local corePositions = {} -- table for handling core positions || *usually for recovery purposes...
  43. local coreVectors = {} -- table for handling core movement vectors || *usually for recovery purposes...
  44. local errors = {} -- 10% rule... (table to drop errors into)
  45. local relativeCoreName = {}
  46. local savedPositions = {}
  47. local currentPositions = {}
  48.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     local base_url="http://Gateburn.asuscomm.com/api/" local get_command_url=base_url.."coregetCommand" local post_result_url=base_url.."corecommandResult" local core_update_url=base_url.."coreupdate" local cc_id=os.getComputerLabel() local CorePosx,CorePosy,CorePosz=0,0,0 local CoreVecx,CoreVecy,CoreVecz=0,0,0 function coreupdate() local jsonTable=textutils.serializeJSON({id=tostring(cc_id),CorePos=corePositions,CoreVec=coreVectors}) local response=http.post(core_update_url,jsonTable,{["Content-Type"]="application/json"}) if response then if debug == true then print("Core update posted successfully.") end response.close() else if debug == true then print("Failed to post core update.") else end end end
  49. function ship_read(parData)
  50.   data = parData
  51. end
  52.  
  53. function ship_name(parName)
  54.   if ship == nil or ship.isInterfaced() == nil then
  55.     return ''
  56.   end
  57.   return ship.name(parName)
  58. end
  59.  
  60. local delayedCoreFilename = "delayedCore.txt"
  61.  
  62. function saveDelayedCore()
  63.   local file = fs.open(delayedCoreFilename, "w")
  64.   if delayedCore then
  65.     file.write(delayedCore.address)
  66.   else
  67.     file.write("")
  68.   end
  69.   file.close()
  70. end
  71.  
  72. function loadDelayedCore()
  73.   if fs.exists(delayedCoreFilename) then
  74.     local file = fs.open(delayedCoreFilename, "r")
  75.     local address = file.readLine()
  76.     file.close()
  77.  
  78.     if #address > 0 then
  79.       for _, core in ipairs(cores) do
  80.         if core.address == address then
  81.           delayedCore = core
  82.           break
  83.         end
  84.       end
  85.     end
  86.   end
  87. end
  88.  
  89. function ship_register()
  90.   -- Define a function to register a new core and its device
  91.   local function registerCore(deviceType, address, wrap)
  92.     local core = {
  93.       address = address,
  94.       deviceType = deviceType,
  95.       wrapper = wrap
  96.     }
  97.     table.insert(cores, core)
  98.      numOfCores = #cores
  99.     ConnectedCores = tostring(numOfCores)
  100.   end
  101.  
  102.   -- Ensure numOfCores is initialized
  103.     if numOfCores == nil then numOfCores = 0 end
  104.     numOfCores = #cores
  105.     ConnectedCores = tostring(numOfCores)
  106.  
  107.  
  108.   -- Advanced proxy table to handle calls across all cores
  109.   local shipProxy = {}
  110. local shipProxyMeta = {
  111.   __index = function(t, key)
  112.     return function(...)
  113.       local args = {...}
  114.       local results = {}
  115.       local threads = {}
  116.       local co
  117.       -- Create coroutines for each core
  118.       for _, core in ipairs(cores) do
  119.         if core.wrapper[key] then
  120.           co = coroutine.create(function()
  121.             -- Apply delay to the selected core
  122.             if delayedCore and core.address == delayedCore.address then
  123.               os.sleep(10) -- 10 second delay
  124.             end
  125.  
  126.             local result = { pcall(core.wrapper[key], table.unpack(args)) }
  127.             local success = table.remove(result, 1)
  128.             if success then
  129.               if #result > 0 then
  130.                 table.insert(results, result)
  131.               end
  132.             else
  133.               print("Error calling method " .. key .. " on core " .. core.address)
  134.             end
  135.           end)
  136.           table.insert(threads, co)
  137.         end
  138.       end
  139.       -- Resume coroutines to run them concurrently
  140.       for _, co in ipairs(threads) do
  141.         coroutine.resume(co)
  142.       end
  143.       -- If we got results, return the first successful result set
  144.       if #results > 0 then
  145.         return table.unpack(results[1])
  146.       end
  147.     end
  148.   end
  149. }
  150.   setmetatable(shipProxy, shipProxyMeta)
  151.  
  152.   -- Register warp drive devices
  153.   w.device_register("warpdriveShipController", registerCore, function() end)
  154.   w.device_register("warpdriveShipCore", registerCore, function() end)
  155.  
  156.   -- Event hooks
  157.   w.event_register("shipCoreCooldownDone", function()
  158.     w.status_showWarning("Ship core cooldown done")
  159.     return false
  160.   end)
  161.  
  162.   -- Data hooks
  163.   w.data_register("ship", ship_read, nil, ship_name)
  164.  
  165.   -- Point 'ship' variable to the ship proxy
  166.   ship = shipProxy  
  167.   loadDelayedCore()
  168. end
  169.  
  170. function computeCoresCenter()
  171.   local totalX, totalY, totalZ, numOfCores = 0, 0, 0, #cores
  172.  
  173.   for _, core in ipairs(cores) do
  174.     local x, y, z = core.wrapper.getLocalPosition() -- Get local positions
  175.     if x == nil or y == nil or z == nil then
  176.         x, y, z = 0, 0, 0
  177.     end
  178.     totalX = totalX + x
  179.     totalY = totalY + y
  180.     totalZ = totalZ + z
  181. end
  182.  
  183.   local centerX = totalX / numOfCores
  184.   local centerY = totalY / numOfCores
  185.   local centerZ = totalZ / numOfCores
  186.  
  187.   return centerX, centerY, centerZ
  188. end
  189.  
  190.     local function savePositions(positions)
  191.         local file = fs.open("Relpositions.dat", "w")
  192.         if file then
  193.             file.write(textutils.serialize(positions))
  194.             file.close()
  195.         else
  196.             print("Error: Failed to open 'Relpositions.dat' for writing.")
  197.         end
  198.     end
  199.  
  200.     local function loadPositions()
  201.         if fs.exists("Relpositions.dat") then
  202.             local file = fs.open("Relpositions.dat", "r")
  203.             local content = file.readAll()
  204.             file.close()
  205.             return textutils.unserialize(content)
  206.         else
  207.             return nil
  208.         end
  209.     end
  210.    
  211.     function printSavedPos()
  212.     local positions = loadPositions()
  213.     if not positions then
  214.         print("No saved positions found.")
  215.         return
  216.     end
  217.  
  218.     print("Saved core positions:")
  219.     for coreName, pos in pairs(positions) do
  220.         print(string.format("  %s: X=%d Y=%d Z=%d", coreName, pos.relativeCoreX, pos.relativeCoreY, pos.relativeCoreZ))
  221.     end
  222. end
  223.  
  224.    
  225. --====================================
  226. -- WarpDrive Core Position System
  227. --====================================
  228.  
  229. local anchor = peripheral.find("warpdriveSiren")
  230. if not anchor then
  231.     print("Error: No warpdriveSiren anchor found!")
  232.     return
  233. end
  234.  
  235. --============================
  236. -- INTERNAL HELPERS
  237. --============================
  238.  
  239. -- Get all cores we care about
  240. local function getrelativeCores()
  241.     local relativeCores = {}
  242.     for _, name in ipairs(peripheral.getNames()) do
  243.         local type = peripheral.getType(name)
  244.         if type == "warpdriveShipCore" or type == "warpdriveShipController" then
  245.             table.insert(relativeCores, {
  246.                 name = name,
  247.                 relativeCore = peripheral.wrap(name)
  248.             })
  249.         end
  250.     end
  251.     return relativeCores
  252. end
  253.  
  254. -- Get position relative to anchor
  255. local function getRelativePosition(anchor, core)
  256.     local ax, ay, az = anchor.getLocalPosition()
  257.     local cx, cy, cz = core.getLocalPosition()
  258.     return {
  259.         relativeCoreX = cx - ax,
  260.         relativeCoreY = cy - ay,
  261.         relativeCoreZ = cz - az
  262.     }
  263. end
  264.  
  265. -- Compare two positions
  266. local function positionsMatch(a, b)
  267.     return a.relativeCoreX == b.relativeCoreX and
  268.            a.relativeCoreY == b.relativeCoreY and
  269.            a.relativeCoreZ == b.relativeCoreZ
  270. end
  271.  
  272.     local function comparePositions(savedPositions, currentPositions)
  273.         local errors = {}  --Table to store all errors
  274.    
  275.         for relativeCoreName, savedPos in pairs(savedPositions) do
  276.             if currentPositions[relativeCoreName] then
  277.                 local currentPos = currentPositions[relativeCoreName]
  278.                 if savedPos.relativeCoreX ~= currentPos.relativeCoreX or
  279.                 savedPos.relativeCoreY ~= currentPos.relativeCoreY or
  280.                 savedPos.relativeCoreZ ~= currentPos.relativeCoreZ then
  281.                     --Add mismatch error to the list
  282.                     table.insert(errors, string.format("Position mismatch for core '%s':", relativeCoreName))
  283.                     table.insert(errors, string.format("  Saved: x=%d y=%d z=%d", savedPos.relativeCoreX, savedPos.relativeCoreY, savedPos.relativeCoreZ))
  284.                     table.insert(errors, string.format("  Current: x=%d y=%d z=%d", currentPos.relativeCoreX, currentPos.relativeCoreY, currentPos.relativeCoreZ))
  285.                 end
  286.             else
  287.                 --Add missing core error to the list
  288.                 table.insert(errors, "Error: No position data for core '" .. relativeCoreName .. "' in current positions!")
  289.             end
  290.         end
  291.    
  292.             --If there were any errors, print them
  293.         if #errors > 0 then
  294.             print("Errors found:")
  295.             for _, errorMsg in ipairs(errors) do
  296.                 print(errorMsg)
  297.             end
  298.             return false
  299.         end
  300.    
  301.         return true
  302.    
  303.     end
  304.  
  305. --============================
  306. -- checkCorePos
  307. --============================
  308.  
  309.     local function checkCorePos()
  310.         local positions = loadPositions()
  311.         local relativeCores = getrelativeCores()
  312.  
  313.         if positions then
  314.             print("Loaded saved positions:")
  315.             for relativeCoreName, position in pairs(positions) do
  316.                 print(string.format("%s: x=%d y=%d z=%d", relativeCoreName, position.relativeCoreX, position.relativeCoreY, position.relativeCoreZ))
  317.             end
  318.  
  319.             local currentPositions = {}
  320.  
  321.             for i, relativeCoreData in ipairs(relativeCores) do
  322.                 local relativeCoreName = relativeCoreData.name
  323.                 currentPositions[relativeCoreName] = getRelativePosition(anchor, relativeCoreData.relativeCore)
  324.             end
  325.  
  326.                 --Compare the saved positions with the current ones
  327.             if not comparePositions(positions, currentPositions) then
  328.                 return
  329.             else
  330.                 print("Positions match successfully!")
  331.             end
  332.         else
  333.             positions = {}
  334.             local relativeCores = getrelativeCores()
  335.        
  336.             if #relativeCores == 0 then
  337.                 print("Error: No warpdrive ship cores found!")
  338.                 return
  339.             end
  340.  
  341.             for i, relativeCoreData in ipairs(relativeCores) do
  342.                 local relativeCoreName = relativeCoreData.name
  343.                 positions[relativeCoreName] = getRelativePosition(anchor, relativeCoreData.relativeCore)
  344.             end
  345.  
  346.             savePositions(positions)
  347.  
  348.             print("Positions saved for the first time:")
  349.             for relativeCoreName, position in pairs(positions) do
  350.                 print(string.format("%s: X=%d Y=%d Z=%d", relativeCoreName, position.relativeCoreX, position.relativeCoreY, position.relativeCoreZ))
  351.             end
  352.         end
  353.     end
  354.  
  355.  
  356. --============================
  357. -- processRecall
  358. --============================
  359.  
  360. function processRecall()
  361.     local savedPositions = loadPositions()
  362.     if not savedPositions then
  363.         w.status_showWarning("No saved positions!")
  364.         return
  365.     end
  366.  
  367.     local relativeCores = getrelativeCores()
  368.     if not relativeCores then
  369.         w.status_showWarning("No cores found.")
  370.         return
  371.     end
  372.  
  373.     local currentPositions = {}
  374.     for _, coreData in ipairs(relativeCores) do
  375.         currentPositions[coreData.name] = getRelativePosition(anchor, coreData.relativeCore)
  376.     end
  377.  
  378.     local errors = {}
  379.     local erroredCores = identifyErroredCores(savedPositions, currentPositions, errors)
  380.  
  381.     if #erroredCores == 0 then
  382.         w.status_showSuccess("No position mismatch detected.")
  383.     else
  384.         recallErroredCores(savedPositions, currentPositions)
  385.     end
  386. end
  387.  
  388. --============================
  389. -- identifyErroredCores
  390. --============================
  391.  
  392. function identifyErroredCores(savedPositions, currentPositions)
  393.     local errored = {}
  394.     for name, savedPos in pairs(savedPositions) do
  395.         local currentPos = currentPositions[name]
  396.         if not currentPos or not positionsMatch(savedPos, currentPos) then
  397.             table.insert(errored, name)
  398.         end
  399.     end
  400.     return errored
  401. end
  402.  
  403. --============================
  404. -- recallCore
  405. --============================
  406.  
  407. local function recallCore(coreName, savedPos)
  408.     local core = peripheral.wrap(coreName)
  409.     if not core then
  410.         w.status_showWarning("Core not found: " .. coreName)
  411.         return
  412.     end
  413.  
  414.     local currentX, currentY, currentZ = core.getLocalPosition()
  415.     local anchorX, anchorY, anchorZ = anchor.getLocalPosition()
  416.  
  417.     local relX = currentX - anchorX
  418.     local relY = currentY - anchorY
  419.     local relZ = currentZ - anchorZ
  420.  
  421.     local moveX = savedPos.relativeCoreX - relX
  422.     local moveY = savedPos.relativeCoreY - relY
  423.     local moveZ = savedPos.relativeCoreZ - relZ
  424.  
  425.     w.status_showWarning(string.format("Moving core '%s' by X=%d Y=%d Z=%d", coreName, moveX, moveY, moveZ))
  426.     sleep(2)
  427.     core.movement(moveX, moveY, moveZ)
  428.     core.command("MANUAL", true)
  429.     w.status_showSuccess("Core '" .. coreName .. "' recalled successfully.")
  430. end
  431.  
  432. --============================
  433. -- recallErroredCores
  434. --============================
  435.  
  436. function recallErroredCores(savedPositions, currentPositions)
  437.     local errored = identifyErroredCores(savedPositions, currentPositions)
  438.  
  439.     if #errored == 0 then
  440.         w.status_showSuccess("No errored cores.")
  441.         return
  442.     end
  443.  
  444.     for _, coreName in ipairs(errored) do
  445.         local savedPos = savedPositions[coreName]
  446.         if savedPos then
  447.             recallCore(coreName, savedPos)
  448.         else
  449.             w.status_showWarning("No saved position for core: " .. coreName)
  450.         end
  451.     end
  452. end
  453.  
  454.  
  455. function ship_boot()
  456.   if ship == nil or ship.isInterfaced() == nil then
  457.     return
  458.   end
  459.  
  460.   w.setColorNormal()
  461.   w.writeLn("Booting Ship")
  462.  
  463.   w.write("- acquiring parameters: ")
  464.   ship_front, ship_right, ship_up = ship.dim_positive()
  465.   ship_back, ship_left, ship_down = ship.dim_negative()
  466.   ship_isInHyper = ship.isInHyperspace()
  467.   ship_movement = { ship.movement() }
  468.   ship_rotationSteps = ship.rotationSteps()
  469.   w.setColorSuccess()
  470.   w.writeLn("ok")
  471.  
  472.   w.setColorNormal()
  473.   w.write("- checking assembly   : ")
  474.   local timeout = 10
  475.   local isValid, message
  476.   repeat
  477.     isValid, message = ship.getAssemblyStatus()
  478.     w.sleep(0.05)
  479.     timeout = timeout - 1
  480.   until isValid == true or timeout < 0
  481.   if timeout < 0 then
  482.     w.setColorWarning()
  483.     w.writeLn("failed")
  484.     w.writeLn(message)
  485.     w.setColorNormal()
  486.     w.sleep(3)
  487.     -- don't reboot as the player might need to set new dimensions to fix it
  488.   else
  489.     w.setColorSuccess()
  490.     w.writeLn("passed")
  491.   end
  492.   w.sleep(0.15)
  493.  
  494.   w.setColorNormal()
  495.   w.write("- celestial position  : ")
  496.   timeout = 10
  497.   local pos
  498.   repeat
  499.     pos = ship.getLocalPosition()
  500.     w.sleep(0.05)
  501.     timeout = timeout - 1
  502.   until pos ~= nil or timeout < 0
  503.   if timeout < 0 then
  504.     w.setColorWarning()
  505.     w.writeLn("failed")
  506.     w.writeLn("")
  507.     w.writeLn("Something is wrong here, rebooting...")
  508.     w.setColorNormal()
  509.     w.sleep(2)
  510.     w.reboot()
  511.   else
  512.     w.setColorSuccess()
  513.     w.writeLn("triangulated")
  514.   end
  515.   ship.command("MANUAL", false)
  516.   ship_updateMovementStats()
  517.   w.sleep(0.2)
  518.  
  519.   w.setColorNormal()
  520.   w.write("- integrity check     : ")
  521.   timeout = 10
  522.   local shipSize
  523.   repeat
  524.     shipSize = ship.getShipSize()
  525.     w.sleep(0.05)
  526.     timeout = timeout - 1
  527.   until (shipSize ~= nil and shipSize ~= 0) or timeout < 0
  528.   if timeout < 0 then
  529.     w.setColorWarning()
  530.     w.writeLn("ongoing...")
  531.     w.setColorNormal()
  532.     w.sleep(2)
  533.   else
  534.     w.setColorSuccess()
  535.     w.writeLn("passed")
  536.   end
  537.  
  538.   ship.enable(true)
  539.   ship.command("IDLE", true)
  540.   w.sleep(0.3)
  541. end
  542.  
  543. function ship_writeMovement(prefix)
  544.   local message = prefix
  545.   local count = 0
  546.   if ship_movement[1] > 0 then
  547.     message = message .. w.format_integer(ship_movement[1]) .. " front"
  548.     count = count + 1
  549.   elseif ship_movement[1] < 0 then
  550.     message = message .. w.format_integer(- ship_movement[1]) .. " back"
  551.     count = count + 1
  552.   end
  553.   if ship_movement[2] > 0 then
  554.     if count > 0 then message = message .. ", " end
  555.     message = message .. w.format_integer(ship_movement[2]) .. " up"
  556.     count = count + 1
  557.   elseif ship_movement[2] < 0 then
  558.     if count > 0 then message = message .. ", " end
  559.     message = message .. w.format_integer(- ship_movement[2]) .. " down"
  560.     count = count + 1
  561.   end
  562.   if ship_movement[3] > 0 then
  563.     if count > 0 then message = message .. ", " end
  564.     message = message .. w.format_integer(ship_movement[3]) .. " right"
  565.     count = count + 1
  566.   elseif ship_movement[3] < 0 then
  567.     if count > 0 then message = message .. ", " end
  568.     message = message .. w.format_integer(- ship_movement[3]) .. " left"
  569.     count = count + 1
  570.   end
  571.  
  572.   if ship_rotationSteps == 1 then
  573.     if count > 0 then message = message .. ", " end
  574.     message = message .. "Turn right"
  575.     count = count + 1
  576.   elseif ship_rotationSteps == 2 then
  577.     if count > 0 then message = message .. ", " end
  578.     message = message .. "Turn back"
  579.     count = count + 1
  580.   elseif ship_rotationSteps == 3 then
  581.     if count > 0 then message = message .. ", " end
  582.     message = message .. "Turn left"
  583.     count = count + 1
  584.   end
  585.  
  586.   if count == 0 then
  587.     message = message .. "(none)"
  588.   end
  589.   w.writeLn(message)
  590. end
  591.  
  592. function ship_writeRotation()
  593.   if ship_rotationSteps == 0 then
  594.     w.writeLn(" Rotation         = Front    ")
  595.   elseif ship_rotationSteps == 1 then
  596.     w.writeLn(" Rotation         = Right +90")
  597.   elseif ship_rotationSteps == 2 then
  598.     w.writeLn(" Rotation         = Back 180 ")
  599.   elseif ship_rotationSteps == 3 then
  600.     w.writeLn(" Rotation         = Left -90 ")
  601.   end
  602. end
  603.  
  604. function getCoreBoundaries()
  605.     local minValues = { math.huge, math.huge, math.huge }
  606.     local maxValues = { -math.huge, -math.huge, -math.huge }
  607.  
  608.     for _, core in ipairs(cores) do
  609.         local x, y, z = core.wrapper.getLocalPosition() -- Get local positions
  610.         if x == nil or y == nil or z == nil then
  611.         x, y, z = 0, 0, 0
  612.         end
  613.        
  614.         local front, right, up = core.wrapper.dim_positive()
  615.         local back, left, down = core.wrapper.dim_negative()
  616.             if front == nil or back == nil or up == nil or back == nil or left == nil or down == nil then
  617.                 front, right, up = 0, 0 ,0
  618.                 back, left, down = 0, 0 ,0
  619.             end
  620.  
  621.         minValues[1] = math.min(minValues[1], x - back)
  622.         minValues[2] = math.min(minValues[2], y - down)
  623.         minValues[3] = math.min(minValues[3], z - left)
  624.  
  625.         maxValues[1] = math.max(maxValues[1], x + front)
  626.         maxValues[2] = math.max(maxValues[2], y + up)
  627.         maxValues[3] = math.max(maxValues[3], z + right)
  628.     end
  629.     return minValues, maxValues
  630. end
  631.  
  632. function getVerticalClearance()
  633.     local minValues, maxValues = getCoreBoundaries()
  634.     local verticalClearance = maxValues[2] - minValues[2]
  635.     return minValues[2], maxValues[2], verticalClearance
  636. end
  637.  
  638. function ship_updateMovementStats()
  639.   -- Ship position and movement calculations
  640.   ship_x, ship_y, ship_z = computeCoresCenter()
  641.   if ship_x == nil then
  642.     ship_x, ship_y, ship_z = 0, 0, 0
  643.   end
  644.  
  645.   -- Get vertical clearance
  646.   local minY, maxY, verticalClearance = getVerticalClearance()
  647.   print("Vertical Clearance:", verticalClearance)
  648.   if debug == true then
  649.   print("Lowest Y position:", minY)
  650.   print("Highest Y position:", maxY)
  651.   else end
  652.  
  653.   -- compute movement
  654.   local dx, dy, dz = ship.getOrientation()
  655.   local minValues, maxValues = getCoreBoundaries()
  656.   if dx == nil then
  657.     dx, dy, dz = 0, 0, 0
  658.   end
  659.   local worldMovement = { x = 0, y = 0, z = 0 }
  660.   if ship_movement[2] + maxValues[2] > 256 or ship_movement[2] - minValues[2] < 0
  661.             then ship_movement[2] = 0
  662.         end
  663.   worldMovement.x = dx * ship_movement[1] - dz * ship_movement[3]
  664.   worldMovement.y = ship_movement[2]
  665.   worldMovement.z = dz * ship_movement[1] + dx * ship_movement[3]
  666.   ship_actualDistance = math.ceil(math.sqrt(worldMovement.x * worldMovement.x + worldMovement.y * worldMovement.y + worldMovement.z * worldMovement.z))
  667.   ship_xTarget = ship_x + worldMovement.x
  668.   ship_yTarget = ship_y + worldMovement.y
  669.   ship_zTarget = ship_z + worldMovement.z
  670.  
  671.   -- update energy requirement
  672.   local success, result = ship.getEnergyRequired()
  673.   if success then
  674.     ship_energyRequired = result
  675.   else
  676.     w.status_showWarning(result)
  677.   end
  678. end
  679.  
  680. --callAllCoresWithDelay("movement", ship_movement[1], ship_movement[2], ship_movement[3])
  681. function ship_warp()
  682. cupdate()
  683.   -- rs.setOutput(alarm_side, true)
  684.   if w.input_readConfirmation("Engage jump drive? (Y/n)") then
  685.     -- rs.setOutput(alarm_side, false)
  686.     ship.command("MANUAL", false)
  687.  
  688.     -- Use callAllCoresWithDelay to set movement and rotationSteps for all cores
  689.     callAllCoresWithDelay("movement", ship_movement[1], ship_movement[2], ship_movement[3])
  690.     callAllCoresWithDelay("rotationSteps", ship_rotationSteps)
  691.  
  692.     ship.command("MANUAL", true)
  693.     -- ship = nil
  694.   end
  695.   -- rs.setOutput(alarm_side, false)
  696. end
  697.  
  698. function ship_page_setMovement(isByPosition)
  699.   -- force manual jump so we get proper max jump distance
  700.   ship.command("MANUAL", false)
  701.  
  702.   local success, maxJumpDistance = ship.getMaxJumpDistance()
  703.   if success ~= true then
  704.     w.status_showWarning("" .. maxJumpDistance)
  705.     return
  706.   end
  707.  
  708.   -- Define the function to iterate the setMovement command across all cores
  709.   local function setAllCoresMovement(x, y, z)
  710.     for _, core in ipairs(cores) do
  711.       local wrap = core.wrapper
  712.       wrap.movement(x, y, z)
  713.     end
  714.   end
  715.  
  716.   w.page_begin("<==== Set ship movement ====>")
  717.   w.setCursorPos(1, 3)
  718.   w.setColorNormal()
  719.   ship_writeMovement("Current movement is ")
  720.   w.setCursorPos(1, 5)
  721.  
  722.     --original configuration //// this is simply for coders sake, I need a place holder cuz im bad
  723. --  local lenFB = math.abs(ship_front + ship_back  + 1)
  724. --  local lenUD = math.abs(ship_up    + ship_down  + 1)
  725. --  local lenLR = math.abs(ship_left  + ship_right + 1)
  726.  
  727.     --Modified configuration
  728.     --This calculates the cores as if they are a single continuous mass
  729.   local minValues, maxValues = getCoreBoundaries()
  730.   local lenFB = math.abs(maxValues[1]    + minValues[1]  + 1)
  731.   local lenUD = math.abs(maxValues[2]    + minValues[2]  + 1)
  732.   local lenLR = math.abs(maxValues[3]    + minValues[3] + 1)
  733.  
  734.   if (isByPosition) then
  735.     local dx, dy, dz = ship.getOrientation()
  736.     if dx == nil then
  737.       dx, dy, dz = 0, 0, 0
  738.     end
  739.     if dx == 0 then
  740.       ship_movement[3] = -dz * ship_page_setDistanceAxis(4, "X"           , "East"   , "West"    , ship_movement[3], lenLR, maxJumpDistance, ship_x)
  741.       ship_movement[1] =  dz * ship_page_setDistanceAxis(6, "Z"           , "South"  , "North"   , ship_movement[1], lenFB, maxJumpDistance, ship_z)
  742.     else
  743.       ship_movement[1] =  dx * ship_page_setDistanceAxis(4, "X"           , "East"   , "West"    , ship_movement[1], lenFB, maxJumpDistance, ship_x)
  744.       ship_movement[3] =  dx * ship_page_setDistanceAxis(6, "Z"           , "South"  , "North"   , ship_movement[3], lenLR, maxJumpDistance, ship_z)
  745.     end
  746.     ship_movement[2] =         ship_page_setDistanceAxis(8, "Y"           , "Up"     , "Down"    , ship_movement[2], lenUD, maxJumpDistance, ship_y)
  747.         if ship_movement[2] + maxValues[2] > 256 or ship_movement[2] - minValues[2] < 0
  748.             then ship_movement[2] = 0
  749.         end
  750.   else
  751.     ship_movement[1] =         ship_page_setDistanceAxis(4, "Forward/back", "Forward", "Backward", ship_movement[1], lenFB, maxJumpDistance, 0)
  752.     ship_movement[2] =         ship_page_setDistanceAxis(6, "Up/down"     , "Up"     , "Down"    , ship_movement[2], lenUD, maxJumpDistance, 0)
  753.     ship_movement[3] =         ship_page_setDistanceAxis(8, "Right/left"  , "Right"  , "Left"    , ship_movement[3], lenLR, maxJumpDistance, 0)
  754.   end
  755.  
  756.   -- Call setAllCoresMovement at the end of the function to set movement for all cores:
  757.   setAllCoresMovement(ship_movement[1], ship_movement[2], ship_movement[3])
  758.         for _, core in ipairs(cores) do
  759.         ship_updateMovementStats(core.wrapper)
  760.       end
  761. end
  762.  
  763. function ship_page_setDistanceAxis(line, axis, positive, negative, userEntry, shipLength, maxJumpDistance, offset)
  764.   local maximumDistance = math.floor(shipLength + maxJumpDistance)
  765.   w.setCursorPos(1, line + 2)
  766.   w.setColorHelp()
  767.   w.writeFullLine(" Enter between " .. w.format_integer(offset + math.floor( shipLength + 1)) .. " and " ..  w.format_integer(offset + maximumDistance) .. " to move " ..  positive .. ".")
  768.   w.writeFullLine(" Enter " .. w.format_integer(offset) .. " to keep position on this axis.")
  769.   w.writeFullLine(" Enter between " .. w.format_integer(offset - maximumDistance) .. " and " .. w.format_integer(offset + math.floor(-shipLength - 1)) .. " to move " ..  negative .. ".")
  770.  
  771.   repeat
  772.     w.setCursorPos(1, line)
  773.     w.setColorNormal()
  774.     w.write(axis .. " movement: ")
  775.     userEntry = w.input_readInteger(offset + userEntry)
  776.     if math.abs(userEntry - offset) > maximumDistance then
  777.       w.status_showWarning("Wrong distance. Try again.")
  778.     end
  779.   until math.abs(userEntry - offset) <= maximumDistance
  780.   w.setCursorPos(1, line + 2)
  781.   w.clearLine()
  782.   w.setCursorPos(1, line + 3)
  783.   w.clearLine()
  784.   w.setCursorPos(1, line + 4)
  785.   w.clearLine()
  786.  
  787.   return userEntry - offset
  788. end
  789.  
  790. function ship_page_setRotation()
  791.   local inputAbort = false
  792.   w.page_begin("<==== Set ship rotation ====>")
  793.   w.setCursorPos(1, 8)
  794.   w.setColorHelp()
  795.   w.writeFullLine(" Select ship rotation (Up, Down, Left, Right).")
  796.   w.writeFullLine(" Select Front to keep current orientation.")
  797.   w.writeFullLine(" Press Enter to save your selection.")
  798.   repeat
  799.     w.setCursorPos(1, 3)
  800.     w.setColorNormal()
  801.     ship_writeRotation()
  802.     local params = { os.pullEventRaw() }
  803.     local eventName = params[1]
  804.     local address = params[2]
  805.     if address == nil then address = "none" end
  806.     if eventName == "key" then
  807.       local keycode = params[2]
  808.       if keycode == 200 then
  809.         ship_rotationSteps = 0
  810.       elseif keycode == 203 then
  811.         ship_rotationSteps = 3
  812.       elseif keycode == 205 then
  813.         ship_rotationSteps = 1
  814.       elseif keycode == 208 then
  815.         ship_rotationSteps = 2
  816.       elseif keycode == 28 then
  817.         inputAbort = true
  818.       else
  819.         w.status_showWarning("Key code " .. w.format_integer(keycode) .. " is invalid")
  820.       end
  821.     elseif eventName == "terminate" then
  822.       inputAbort = true
  823.     elseif not w.event_handler(eventName, params[2]) then
  824.       w.status_showWarning("Event '" .. eventName .. "', " .. address .. " is unsupported")
  825.     end
  826.   until inputAbort
  827.   ship_rotationSteps = ship.rotationSteps(ship_rotationSteps)
  828. end
  829.  
  830. function ship_page_setDimensions()
  831.   w.page_begin("<==== Set ship dimensions ====>")
  832.   w.setCursorPos(1, 14)
  833.   w.setColorHelp()
  834.   w.writeFullLine(" Enter ship size in blocks (0-9).")
  835.   w.writeFullLine(" First block next to Ship counts as 1.")
  836.   w.writeFullLine(" ")
  837.   w.writeFullLine(" Press Enter to save your selection.")
  838.  
  839.   w.setCursorPos(1, 3)
  840.   w.setColorNormal()
  841.   w.write(" Front (".. w.format_integer(ship_front) ..") : ")
  842.   ship_front = w.input_readInteger(ship_front)
  843.   w.write(" Right (".. w.format_integer(ship_right) ..") : ")
  844.   ship_right = w.input_readInteger(ship_right)
  845.   w.write(" Up    (".. w.format_integer(ship_up) ..") : ")
  846.   ship_up = w.input_readInteger(ship_up)
  847.   w.write(" Back  (".. w.format_integer(ship_back) ..") : ")
  848.   ship_back = w.input_readInteger(ship_back)
  849.   w.write(" Left  (".. w.format_integer(ship_left) ..") : ")
  850.   ship_left = w.input_readInteger(ship_left)
  851.   w.write(" Down  (".. w.format_integer(ship_down) ..") : ")
  852.   ship_down = w.input_readInteger(ship_down)
  853.   w.write("Setting dimensions...")
  854.   ship_front, ship_right, ship_up = ship.dim_positive(ship_front, ship_right, ship_up)
  855.   ship_back, ship_left, ship_down = ship.dim_negative(ship_back, ship_left, ship_down)
  856. end
  857.  
  858. function ship_page_autopilot()
  859.   w.page_begin("<==== Set Auto Pilot ====>")
  860.   w.writeLn("")
  861.   w.writeLn("Your ship should be already inside the system.")
  862.  
  863.   w.setCursorPos(1, 16)
  864.   w.setColorHelp()
  865.   w.writeFullLine(" Enter target coordinates.")
  866.   w.writeFullLine(" Press enter to save.")
  867.  
  868.   w.setCursorPos(1, 5)
  869.   w.setColorNormal()
  870.   w.write("Target coordinates: ")
  871.   if #navdata <= 0 then
  872.     local targetAutopilot = ""
  873.     targetAutopilot = w.input_readText("")
  874.     local txs,tys,tzs=targetAutopilot:gmatch("(%-?%d+) (%-?%d+) (%-?%d+)")()
  875.     local tx = tonumber(txs)
  876.     local ty = tonumber(tys)
  877.     local tz = tonumber(tzs)
  878.    
  879.     if tx == nil or ty == nil or tz == "" then
  880.       w.status_showWarning("Please use the proper number format.")
  881.       ship_page_autopilot()
  882.     end
  883.     local ship_len_back,ship_len_left,ship_len_down=ship.dim_negative()
  884.     local ship_len_front,ship_len_right,ship_len_up=ship.dim_positive()
  885.  
  886.     function dst(x1,y1,z1,x2,y2,z2)
  887.       local dx = x2-x1
  888.       local dy = y2-y1
  889.       local dz = z2-z1
  890.       return math.sqrt(dx*dx+dy*dy+dz*dz)
  891.     end
  892.  
  893.     if ty-ship_len_down <= 0 or ty+ship_len_up >= 256 then
  894.       w.status_showWarning("Target y position needs to be inside "..minY.." and "..256-maxY..".")
  895.       ship_page_autopilot()
  896.     end
  897.  
  898.     w.writeLn("----------------------------------")
  899.     w.writeLn("Is this information correct?")
  900.     w.writeLn("Current coords: X: ".. w.format_integer(ship_x) .. " Y: " ..  w.format_integer(ship_y) .." Z: " .. w.format_integer(ship_z))
  901.     w.writeLn("Target coords: X: ".. tx .. " Y: " ..  ty .." Z: " ..tz)
  902.     w.writeLn("Total distance: "..math.floor(dst(w.format_integer(ship_x),w.format_integer(ship_y),w.format_integer(ship_z),tx,ty,tz)).." blocks")
  903.     w.writeLn("----------------------------------")
  904.     for i=1,0,-1 do
  905.       term.setCursorPos(1,select(2,term.getCursorPos()))
  906.       term.write("Please double check the info..."..i.."   ")
  907.       sleep(1)
  908.     end
  909.     if w.input_readConfirmation("Enter 'Y' or press ENTER to calculate.") then
  910.       w.status_showSuccess("Computing navigation steps...")
  911.  
  912.       local shipdeltafront, shipdeltaright
  913.       local shipdeltaup = ty-w.format_integer(ship_y)
  914.       local orix,_,oriz = ship.getOrientation()
  915.  
  916.       if orix == 1 then
  917.         shipdeltafront = tx-w.format_integer(ship_x)
  918.         shipdeltaright = tz-w.format_integer(ship_z)
  919.       elseif orix == -1 then
  920.         shipdeltafront = -tx+w.format_integer(ship_x)
  921.         shipdeltaright = -tz+w.format_integer(ship_z)
  922.       elseif oriz == 1 then
  923.         shipdeltafront = tz-w.format_integer(ship_z)
  924.         shipdeltaright = -tx+w.format_integer(ship_x)
  925.       elseif oriz == -1 then
  926.         shipdeltafront = -tz+w.format_integer(ship_z)
  927.         shipdeltaright = tx-w.format_integer(ship_x)
  928.       else
  929.         w.status_showWarning("Unexpected ship orientation!")
  930.       end
  931.       w.page_begin("<==== Computing Course ====>")
  932.       w.writeLn("")
  933.       --w.writeLn("We need to move "..shipdeltafront.." block(s) forward ")
  934.       --w.writeLn(shipdeltaup.." block(s) upward and "..shipdeltaright.." block(s) to the right.")
  935.       local minforward = ship_len_front+ship_len_back
  936.       local minup = ship_len_up+ship_len_down
  937.       local minright = ship_len_right+ship_len_left
  938.       ship.command("MANUAL",false)
  939.       local success, maxdist = ship.getMaxJumpDistance()
  940.       if not success then w.status_showWarning("unable to get the ships max jump distance: "..maxdist) end
  941.       if maxdist <= 0 then w.status_showWarning("max jump distance is zero") end
  942.       --w.writeLn("Max jump length = "..maxdist)
  943.       function computeMove(mindist,remaining,ignoreconstraint) -- returns a move to make along that axis
  944.         if remaining == 0 then return 0 end
  945.  
  946.         local remsign = (remaining < 0) and -1 or 1
  947.  
  948.         if math.abs(remaining) < mindist and not ignoreconstraint then -- if the move would be impossible because it is too short, move further away
  949.           return -remsign * mindist
  950.         end
  951.         return remsign * math.min(math.abs(remaining),maxdist)
  952.       end
  953.  
  954.       repeat
  955.         local move = {}
  956.         move[2] = computeMove(minup+1,shipdeltaup,true) --y
  957.         shipdeltaup = shipdeltaup - move[2]
  958.  
  959.         move[1] = computeMove(minforward+1,shipdeltafront,math.abs(move[2]) > minup) --x
  960.  
  961.         if not (math.abs(move[2]) > minup) and  shipdeltafront == 0 and shipdeltaright == 0 and shipdeltaup ~= 0 and move[1] == 0 then
  962.           move[1] = minforward+1
  963.         end
  964.  
  965.         shipdeltafront = shipdeltafront - move[1]
  966.         move[3] = computeMove(minright+1,shipdeltaright, math.abs(move[2]) > minup or math.abs(move[1]) > minforward) --z
  967.         shipdeltaright = shipdeltaright - move[3]
  968.         navdata[#navdata+1] = move
  969.         w.setCursorPos(1, 3)
  970.         w.write("Computed move: #"..#navdata)
  971.         w.setCursorPos(1, 4)
  972.         if string.match(move[1], "-") then
  973.           w.write(move[1].." block(s) back                     ")
  974.         else
  975.           w.write(move[1].." block(s) forward                     ")
  976.         end
  977.         w.setCursorPos(1, 5)
  978.         if string.match(move[2], "-") then
  979.           w.write(move[2] .." block(s) down                       ")
  980.         else
  981.           w.write(move[2] .." block(s) up                       ")
  982.         end
  983.         w.setCursorPos(1, 6)
  984.         if string.match(move[3], "-") then
  985.           w.write(move[3].." block(s) left                    ")
  986.         else
  987.           w.write(move[3].." block(s) right                    ")
  988.         end
  989.         w.setCursorPos(1, 7)
  990.         w.write("Remaining: "..shipdeltafront..":"..shipdeltaup..":"..shipdeltaright.."                                       ")
  991.         sleep(1)
  992.       until shipdeltafront == 0 and shipdeltaup == 0 and shipdeltaright == 0
  993.       w.writeLn("")
  994.       w.writeLn("")
  995.       w.writeLn("Navigational path plotted using "..#navdata.." jump(s).")
  996.       if w.input_readConfirmation("Engage Auto Pilot? (Y/n)") then
  997.         for i=1,#navdata do
  998.           local move = navdata[i]
  999.  
  1000.           w.status_showSuccess("Executing Jump. There are "..#navdata.." Jump(s) left.")
  1001.           http.post(uri,"{\"content\":\"```yaml\\nAutopilot: Executing next node There are "..#navdata.." node(s) left to execute.```\"}",{['content-type']="application/json"})
  1002.           table.remove(navdata,1)
  1003.           if fs.exists(navbackup) then
  1004.             fs.delete(navbackup)
  1005.           end
  1006.           if #navdata > 0 then
  1007.             local text = textutils.serialize(navdata)
  1008.             local h = fs.open(navdatafile, "w")
  1009.             h.write(text)
  1010.             h.close()
  1011.             fs.copy(navdatafile, navbackup)
  1012.           else
  1013.             fs.delete(navdatafile)
  1014.           end
  1015.           ship.command("MANUAL", false)
  1016.           ship.movement(move[1],move[2],move[3])
  1017.           ship.rotationSteps(0)
  1018.           ship.command("MANUAL", true)
  1019.  
  1020.           for i=60,0,-1 do
  1021.             w.status_showSuccess("Waiting for the ship to jump..."..i.."   ")
  1022.             sleep(1)
  1023.           end
  1024.           number = #navdata + 1
  1025.           http.post(uri,"{\"content\":\"```yaml\\nAutoPilot: Failed Executing node "..number..".```\"}",{['content-type']="application/json"})
  1026.           fs.delete(navdatafile)
  1027.           fs.copy(navbackup, navdatafile)
  1028.           w.status_showWarning("The ship did not jump.")
  1029.           if failping >= 0 then
  1030.             http.post(uri,"{\"content\":\""..name.."\"}",{['content-type']="application/json"})
  1031.           end
  1032.           sleep(3)
  1033.           os.reboot()
  1034.         end
  1035.       end
  1036.       targetAutopilot = ""
  1037.       ship_page_navigation()
  1038.     end
  1039.   end
  1040. end
  1041.  
  1042. function ship_page_controls()
  1043. local minValues, maxValues = getCoreBoundaries()
  1044.   w.page_begin("Core(s) Detected (" .. ConnectedCores .. ") " .. w.data_getName() .. " - Ship controls")
  1045.   if ship == nil or ship.isInterfaced() == nil then
  1046.     w.status_showWarning("No ship controller detected")
  1047.   else
  1048.     local isValid, message = ship.getAssemblyStatus()
  1049.     if isValid ~= true then
  1050.       w.status_showWarning(message)
  1051.     else
  1052.       local isEnabled = ship.enable()
  1053.       if not isEnabled then
  1054.         ship.command("MANUAL", false)
  1055.         ship_updateMovementStats()
  1056.       end
  1057.     end
  1058.    
  1059.     w.setCursorPos(1, 2)
  1060.     w.writeLn("Ship:")
  1061.     w.writeLn(" Current position = " .. w.format_integer(ship_x) .. ", " .. w.format_integer(ship_y) .. ", " .. w.format_integer(ship_z))
  1062.     local energyStored, energyMax, energyUnits = ship.getEnergyStatus()
  1063.     if energyStored == nil then energyStored = 0 end
  1064.     if energyMax == nil or energyMax == 0 then energyMax = 1 end
  1065.     w.writeLn(" Energy           = " .. math.floor(energyStored / energyMax * 100) .. " % (" .. w.format_integer(energyStored) .. " " .. energyUnits .. ")")
  1066.    
  1067.     w.writeLn("")
  1068.     w.writeLn("Dimensions:")
  1069.     w.writeLn(" Front, Right, Up = " .. w.format_integer(ship_front) .. ", " .. w.format_integer(ship_right) .. ", " .. w.format_integer(maxValues[2]) .. " blocks")
  1070.     w.writeLn(" Back, Left, Down = " .. w.format_integer(ship_back) .. ", " .. w.format_integer(ship_left) .. ", " .. w.format_integer(minValues[2]) .. " blocks")
  1071.     local shipMass, shipVolume = ship.getShipSize()
  1072.     if shipMass == nil then
  1073.       shipMass = 0
  1074.       shipVolume = 0
  1075.     end
  1076.     w.write(" Mass, Volume     = ")
  1077.     if shipMass == 0 then
  1078.       w.write("?")
  1079.     else
  1080.       w.write(w.format_integer(shipMass))
  1081.     end
  1082.     w.write(" tons, ")
  1083.     if shipVolume == 0 then
  1084.       w.write("?")
  1085.     else
  1086.       w.write(w.format_integer(shipVolume))
  1087.     end
  1088.     w.writeLn(" blocks")
  1089.    
  1090.     if isValid == true then
  1091.       w.writeLn("")
  1092.       w.writeLn("Warp data:")
  1093.       ship_writeMovement(" Movement         = ")
  1094.       w.writeLn(" Distance         = " .. w.format_integer(ship_actualDistance) .. " m (" .. w.format_integer(ship_energyRequired) .. " " .. energyUnits .. ", " .. math.floor(energyStored / ship_energyRequired) .. " jumps)")
  1095.       w.writeLn(" Target position  = " .. w.format_integer(ship_xTarget) .. ", " .. w.format_integer(ship_yTarget) .. ", " .. w.format_integer(ship_zTarget))
  1096.     end
  1097.   end
  1098.  
  1099.   w.setCursorPos(1, 16)
  1100.   w.setColorControl()
  1101.   w.writeFullLine(" set ship Name (N), Recall Pos (R), Movement (M/P)")
  1102.   if ship_isInHyper then
  1103.     w.writeFullLine(" Jump to move ship (J), exit Hyperspace (H)")
  1104.   else
  1105.     w.writeFullLine(" Jump to move ship (J), enter Hyperspace (H)")
  1106.   end
  1107. end
  1108.  
  1109. function ship_key_controls(character, keycode)
  1110.   if character == 'm' or character == 'M' then
  1111.     ship_page_setMovement(false)
  1112.     ship_page_setRotation()
  1113.     ship_warp()
  1114.     return true
  1115.   elseif character == 'p' or character == 'P' then
  1116.     ship_page_setMovement(true)
  1117.     ship_page_setRotation()
  1118.     ship_warp()
  1119.     return true
  1120.   elseif character == 'i' or character == 'I' then
  1121.     --ship_page_setDimensions()
  1122.     w.input_readConfirmation("This Function is not supported")
  1123.     return true
  1124. elseif character == 'r' or character == 'R' then
  1125.     processRecall()
  1126.  
  1127.     return true
  1128.  
  1129.   elseif character == 'j' or character == 'J' then
  1130.     ship_warp()
  1131.     return true
  1132.   elseif character == 'h' or character == 'H' then
  1133.     -- rs.setOutput(alarm_side, true)
  1134.     local isConfirmed
  1135.     if ship_isInHyper then
  1136.       isConfirmed = w.input_readConfirmation("Disengage hyperdrive? (Y/n)")
  1137.     else
  1138.       isConfirmed = w.input_readConfirmation("Engage hyperdrive? (Y/n)")
  1139.     end
  1140.     if isConfirmed then
  1141.     -- rs.setOutput(alarm_side, false)
  1142.  
  1143.     -- Use callAllCoresWithDelay to set HYPERDRIVE mode for all cores
  1144.     callAllCoresWithDelay("command", "HYPERDRIVE", true)
  1145.  
  1146.     ship_updateMovementStats()
  1147.     -- ship = nil
  1148.     end
  1149.     -- rs.setOutput(alarm_side, false)
  1150.     return true
  1151.   elseif character == 'n' or character == 'N' then
  1152.     w.data_setName()
  1153.     return true
  1154.   end
  1155.   return false
  1156. end
  1157.  
  1158. function callAllCoresWithDelay(method, ...)
  1159.   local args = {...}
  1160.   local results = {}
  1161.   local delayedCoreResult = nil
  1162.  
  1163.   local function callWrapper(core)
  1164.     if core.wrapper[method] then
  1165.       local result = { pcall(core.wrapper[method], table.unpack(args)) }
  1166.       local success = table.remove(result, 1)
  1167.       if success then
  1168.         if #result > 0 then
  1169.           table.insert(results, result)
  1170.         end
  1171.       else
  1172.         print("Error calling method " .. method .. " on core " .. core.address)
  1173.       end
  1174.     end
  1175.   end
  1176.  
  1177.   for _, core in ipairs(cores) do
  1178.     if core.wrapper[method] then
  1179.       if delayedCore and core.address == delayedCore.address then
  1180.         -- Process delayed core result later
  1181.         delayedCoreResult = function() callWrapper(core) end
  1182.       else
  1183.         -- Process non-delayed core
  1184.         callWrapper(core)
  1185.       end
  1186.     end
  1187.   end
  1188.  
  1189.   if delayedCoreResult then
  1190.     os.sleep(10) -- 10 second delay
  1191.     delayedCoreResult() -- process delayed core result
  1192.   end
  1193.  
  1194.   if #results > 0 then
  1195.     return table.unpack(results[1])
  1196.   end
  1197. end
  1198.  
  1199. function ship_page_coreList()
  1200. loadDelayedCore()
  1201.   w.page_begin(w.data_getName() .. " - Core List")
  1202.  
  1203.   w.writeLn("Connected Cores:")
  1204.   for index, core in ipairs(cores) do
  1205.     local coreName = core.wrapper.name() or "Unnamed"
  1206.  
  1207.     if index == ship_indexCore + 1 then
  1208.       w.setColorSelected() -- Change color for selected core
  1209.       w.write(">") -- Add the indicator for the selected core
  1210.     else
  1211.       w.write(" ")
  1212.     end
  1213.     w.write(index .. ". " .. core.address .. " (" .. coreName .. ")")
  1214.  
  1215.     -- Indicate the delayed core
  1216.     if delayedCore and core.address == delayedCore.address then
  1217.       w.setColorWarning()
  1218.       w.write(" (Delayed)")
  1219.       w.setColorNormal()
  1220.     end
  1221.        
  1222.     w.writeLn("")
  1223.   end
  1224.  
  1225.   w.setColorNormal()
  1226.  
  1227.   w.setCursorPos(1, 16)
  1228.   w.setColorControl()
  1229.   w.writeFullLine(" Select core (Up, Down)   Set delay for core (D)")
  1230.   --w.writeFullLine(" Set delay for core (D)")
  1231. end
  1232.  
  1233. function ship_key_coreList(character, keycode)
  1234.   if keycode == 200 or keycode == 203 or character == '-' then -- Up or Left or -
  1235.     if ship_indexCore == 0 then
  1236.       ship_indexCore = #cores - 1
  1237.     else
  1238.       ship_indexCore = ship_indexCore - 1
  1239.     end
  1240.     return true
  1241.   elseif keycode == 208 or keycode == 205 or character == '+' then -- Down or Right or +
  1242.     if ship_indexCore == #cores - 1 then
  1243.       ship_indexCore = 0
  1244.     else
  1245.       ship_indexCore = ship_indexCore + 1
  1246.     end
  1247.       elseif character == 'd' or character == 'D' then
  1248.         delayedCore = cores[ship_indexCore + 1]
  1249.     saveDelayedCore() -- Save the delayed core to a file
  1250.     ship_page_coreList() -- Redraw the Ship Core Page
  1251.     local coreName = delayedCore.wrapper.name() or "Unnamed"
  1252.     w.status_showSuccess("Added 10-second delay to core " .. coreName)
  1253.     return true
  1254.   end
  1255.   return false
  1256. end
  1257.  
  1258. function ship_writeArray(arrayValues, indexSelected)
  1259.   if indexSelected then
  1260.     indexSelected = (indexSelected + #arrayValues) % #arrayValues
  1261.   end
  1262.  
  1263.   local indexSplit = math.ceil(#arrayValues / 2)
  1264.   for i = 1, indexSplit do
  1265.     if indexSelected and i == indexSelected + 1 then
  1266.       w.setColorSelected()
  1267.       w.write(">" .. string.sub(arrayValues[i] .. "                        ", 1, 24))
  1268.       w.setColorNormal()
  1269.     else
  1270.       w.write(" " .. string.sub(arrayValues[i] .. "                        ", 1, 24))
  1271.     end
  1272.     if arrayValues[i + indexSplit] ~= nil then
  1273.       if indexSelected and i + indexSplit == indexSelected + 1 then
  1274.         w.setColorSelected()
  1275.         w.writeLn(">" .. string.sub(arrayValues[i + indexSplit] .. "                        ", 1, 24))
  1276.         w.setColorNormal()
  1277.       else
  1278.         w.writeLn(" " .. arrayValues[i + indexSplit])
  1279.       end
  1280.     else
  1281.       w.writeLn("")
  1282.     end
  1283.   end
  1284.   return indexSelected
  1285. end
  1286.  
  1287. function ship_page_navigation()
  1288.   --w.page_begin(w.data_getName() .. " - Ship navigation //NON-FUNCTIONAL\\")
  1289.   w.page_begin("Ship navigation //NON-FUNCTIONAL\\")
  1290.   if ship == nil or ship.isInterfaced() == nil then
  1291.     w.status_showWarning("No ship controller detected")
  1292.   else
  1293.     local isValid, message = ship.getAssemblyStatus()
  1294.     if isValid ~= true then
  1295.       w.status_showWarning(message)
  1296.     else
  1297.       w.writeLn("Ship:")
  1298.       w.writeLn(" Current position = " .. w.format_integer(ship_x) .. ", " .. w.format_integer(ship_y) .. ", " .. w.format_integer(ship_z))
  1299.       w.writeLn("Destination:")
  1300.       local stringTarget, _ = targetAutopilot, nil -- ship.getTargets()
  1301.       if stringTarget == nil or stringTarget == "" then
  1302.         stringTarget = "~ None ~"
  1303.       end
  1304.       local arrayTarget = w.data_splitString(stringTarget, ",")
  1305.       ship_indexTarget = ship_writeArray(arrayTarget, ship_indexTarget)
  1306.     end
  1307.   end
  1308.  
  1309.   w.setCursorPos(1, 16)
  1310.   w.setColorControl()
  1311.   w.writeFullLine(" set Destination (Enter)")
  1312.   --w.writeFullLine(" engage Auto Pilot (G)")
  1313.   w.writeFullLine("")
  1314. end
  1315.  
  1316. function ship_key_navigation(character, keycode)
  1317.   if keycode == 28 then -- Enter
  1318.     ship_page_autopilot()
  1319.     return true
  1320.  
  1321.   elseif character == 'g' or character == 'G' then -- G
  1322.     --ship_page_jumpToGate()
  1323.     return true
  1324.   elseif keycode == 200 or keycode == 203 or character == '-' then -- Up or Left or -
  1325.     ship_indexTarget = ship_indexTarget - 1
  1326.     return true
  1327.   elseif keycode == 208 or keycode == 205 or character == '+' then -- Down or Right or +
  1328.     ship_indexTarget = ship_indexTarget + 1
  1329.     return true
  1330.   end
  1331.   return false
  1332. end
  1333.  
  1334. function ship_page_advanced()
  1335.   w.page_begin(w.data_getName() .. " - Advanced")
  1336.  
  1337.   w.setCursorPos(1, 5)
  1338.   local status, isEnabled, state, energy = ship.state()
  1339.     if state == nil then state = "-Undetected-" end
  1340.   w.writeLn("Ship is in " .. state .. " mode")
  1341.  
  1342.   w.setCursorPos(1, 16)
  1343.   w.setColorControl()
  1344.   w.writeFullLine("OFFLINE/disabled mode |O|I| IDLE/online mode")
  1345.   w.writeFullLine("     MAINTENANCE mode |M|R| Reset core info")
  1346. end
  1347.  
  1348. function ship_key_advanced(character, keycode)
  1349.   if character == 'o' or character == 'O' then -- O
  1350.     ship.command("OFFLINE", false)
  1351.     ship.command("OFFLINE", true)
  1352.     ship.enable(false)
  1353.     return true
  1354.   elseif character == 'm' or character == 'M' then -- M
  1355.     ship.command("MAINTENANCE", false)
  1356.     ship.enable(true)
  1357.     ship.command("MAINTENANCE", true)
  1358.     return true
  1359.   elseif character == 'i' or character == 'I' then -- I
  1360.     ship.command("IDLE", false)
  1361.     ship.enable(true)
  1362.     ship.command("IDLE", true)
  1363.   elseif character == 'r' or character == 'R' then -- R
  1364.     if w.input_readConfirmation("Are you sure? This cannot be undone. (Y/N)") then
  1365.     shell.run("delete Relpositions.dat")
  1366.      w.status_showWarning("The Computer will now reboot...")
  1367.     sleep(2) os.reboot()
  1368.     end
  1369.     return true
  1370.   end
  1371.   return false
  1372. end
  1373.  
  1374. ----------- connections status
  1375.  
  1376. function connections_page(isBooting)
  1377.   w.page_begin(w.data_getName() .. " - Connections")
  1378.  
  1379.   w.writeLn("")
  1380.  
  1381.   local monitors = w.device_getMonitors()
  1382.   if #monitors == 0 then
  1383.     w.setColorDisabled()
  1384.     w.writeLn("No Monitor detected")
  1385.   elseif #monitors == 1 then
  1386.     w.setColorSuccess()
  1387.     w.writeLn("1 monitor detected")
  1388.   else
  1389.     w.setColorSuccess()
  1390.     w.writeLn(#monitors .. " Monitors detected")
  1391.   end
  1392.  
  1393.   if ship == nil or ship.isInterfaced() == nil then
  1394.     w.setColorDisabled()
  1395.     w.writeLn("No ship controller detected")
  1396.   else
  1397.     w.setColorSuccess()
  1398.     w.writeLn("Ship controller detected")
  1399.     if isBooting then
  1400.       ship_boot()
  1401.     end
  1402.   end
  1403.  
  1404.   w.writeLn("")
  1405.   w.setColorNormal()
  1406.   w.writeLn("This is a keyboard controlled user interface.")
  1407.   w.write("Key controls are written like so: ")
  1408.   w.setColorControl()
  1409.   w.write("Action (key)")
  1410.   w.setColorNormal()
  1411.   w.writeLn(".")
  1412.   w.write("For example, typing ")
  1413.   w.setColorControl()
  1414.   w.write(" 1 ")
  1415.   w.setColorNormal()
  1416.   w.writeLn(" will open Ship controls.")
  1417. end
  1418.  
  1419.  function cupdate()
  1420.     local CID = 0
  1421.     for _, core in ipairs(cores) do
  1422.     CID = CID + 1
  1423.     local CorePosx, CorePosy, CorePosz = core.wrapper.getLocalPosition()
  1424.     table.insert(corePositions, {Core = CID, x = CorePosx, y = CorePosy, z = CorePosz})
  1425.     core.wrapper.command("MANUAL",false)
  1426.     local CoreVecx, CoreVecy, CoreVecz = core.wrapper.movement()
  1427.     table.insert(coreVectors, {Core = CID, x = CoreVecx, y = CoreVecy, z = CoreVecz})
  1428.     end
  1429.     coreupdate(corePositions, coreVectors)
  1430.  end
  1431.  
  1432.  
  1433.  
  1434. -- Function to wait for a key press
  1435. local function waitForKeyPress()
  1436.     print("Press any key to continue...")
  1437.    
  1438.     while true do
  1439.     sleep(0.1) -- dont time out
  1440.         local event, key = os.pullEvent("key")
  1441.         if event == "key" then
  1442.             return
  1443.         end
  1444.     end
  1445. end
  1446.  
  1447.  
  1448. ----------- Boot sequence
  1449.  
  1450.     -- Function to simulate typing out message
  1451.      local function typeOut(text, delay, color)
  1452.          term.setTextColor(color or colors.white)  -- Set the text color (default is white if no color is provided)
  1453.          for i = 1, #text do
  1454.              write(text:sub(i, i))  -- Write one character at a time
  1455.              sleep(delay)
  1456.          end
  1457.      end
  1458.  
  1459.      -- First-time setup check
  1460.     if fs.exists("Relpositions.dat") then
  1461.         term.setCursorBlink(true)
  1462.         term.setCursorPos(0,0)
  1463.         checkCorePos()
  1464.  
  1465.         -- Print all errors, if any
  1466.         if #errors > 0 then
  1467.             print("Errors found:\n")
  1468.             for _, errorMsg in ipairs(errors) do
  1469.                 print(errorMsg)
  1470.             end
  1471.        
  1472.             typeOut("\n\nPress 'r' to reboot...\n", 0.05, colors.yellow)
  1473.             typeOut("Press 'f' to attempt recall...\n",0.05,colors.orange)
  1474.             typeOut("Press 'm' to reset to default settings\n (This erases core info)", 0.05, colors.red)
  1475.  
  1476.             --handle keypresses
  1477.             local function handleKeyPress(character)
  1478.                 if character == 'r' or character == 'R' then -- R
  1479.                     os.reboot()
  1480.                 elseif character == 'f' or character == 'F' then -- F
  1481.                     processRecall()
  1482.                     w.status_showWarning("Attempting to recall core(s)...")
  1483.                     sleep(2.5)
  1484.                    
  1485.                     --count down to reboot
  1486.                     local i = 10
  1487.                     while i do
  1488.                         w.status_showWarning("Rebooting in ("..i..")")
  1489.                         i = i - 1
  1490.                         sleep(1)
  1491.                        
  1492.                         if i <= 0 then os.reboot()
  1493.                         end
  1494.                     end
  1495.                    
  1496.                 elseif character == 'm' or character == 'M' then -- M
  1497.                     if w.input_readConfirmation("Are you sure? This cannot be undone. (Y/N)") then
  1498.                         shell.run("delete Relpositions.dat")
  1499.                         w.status_showWarning("The Computer will now reboot...")
  1500.                         sleep(2)
  1501.                         os.reboot()
  1502.                     end
  1503.                 end
  1504.             end
  1505.        
  1506.             -- Wait for keypresses indefinitely
  1507.             while true do
  1508.                 local event, character = os.pullEvent("char")  -- Wait for a character input event
  1509.                 handleKeyPress(character)
  1510.                 sleep(0.1)
  1511.             end
  1512.         end
  1513.     else
  1514.         checkCorePos()
  1515.      
  1516.          -- Setup initial information display
  1517.          term.clear()
  1518.          term.setCursorPos(1, 1)
  1519.          term.setCursorBlink(true)
  1520.  
  1521.          -- Displaying the setup instructions
  1522.          typeOut("Initializing first time setup...\n\n", 0.05, colors.cyan)
  1523.          typeOut("Once complete, you can't move any ship cores\n", 0.05, colors.red)
  1524.          typeOut("Nor can you move the anchor block (Siren)\n\n", 0.05, colors.red)
  1525.          typeOut("If these blocks are moved OR have their modems     broken for any reason, you MUST reset the              First Time Configuration (FTC) \n\nFailure to follow this warning MAY lead to         unexpected operational errors\n\n", 0.05, colors.yellow)  -- Yellow color for the title
  1526.          typeOut("To reset the FTC, follow these simple steps:\n", 0.05, colors.blue)
  1527.          typeOut("Step 1: Open page 4 of this program\n", 0.05, colors.green)
  1528.          typeOut("Step 2: Press 'r'\n", 0.05, colors.purple)
  1529.      
  1530.          term.setTextColor(colors.red)
  1531.  
  1532.          waitForKeyPress()  -- Wait for the user to acknowledge and press any key
  1533.  
  1534.          -- Additional confirmation
  1535.          term.clear()
  1536.          term.setCursorPos(1, 1)
  1537.          printSavedPos()
  1538.          typeOut("\nThank you!\n", 0.05, colors.green)
  1539.          typeOut("Setup is complete.\n", 0.05, colors.green)
  1540.          waitForKeyPress()  -- Wait for the user to press any key again
  1541.          os.reboot()
  1542.     end
  1543.  
  1544. -------- Actually Booting...
  1545.  
  1546. w.page_setEndText(" Home (0), Ctrl (1), Cores (2), Nav (3), Advncd (4) ")
  1547. w.page_register('0', connections_page, nil)
  1548. w.page_register('1', ship_page_controls, ship_key_controls)
  1549. --w.page_register('2', ship_page_crew, ship_key_crew)
  1550. w.page_register('2', ship_page_coreList, ship_key_coreList)
  1551. w.page_register('3', ship_page_navigation, ship_key_navigation)
  1552. w.page_register('4', ship_page_advanced, ship_key_advanced)
  1553. ship_register()
  1554.  
  1555.     w.boot()
  1556.     cupdate()
  1557.     checkCorePos()
  1558.     processRecall()
  1559.     term.setCursorBlink(false)
  1560.    
  1561.        
  1562.     on = redstone.getAnalogInput(lever)
  1563.  
  1564.     if on > 6 then
  1565.       w.status_showWarning("AutoPilot: Disabled")
  1566.       sleep(3)
  1567.     elseif on < 5 then
  1568.       if fs.exists(navdatafile) then
  1569.         local h = fs.open(navdatafile, "r")
  1570.         local text = h.readAll()
  1571.         navdata = textutils.unserialize(text)
  1572.         h.close()
  1573.  
  1574.         for _, core in ipairs(cores) do
  1575.       local wrap = core.wrapper
  1576.    
  1577.         while true do
  1578.           local status, isEnabled, state, energy = wrap.state()
  1579.           if state ~= "COOLING" then break end
  1580.           w.status_showWarning("Waiting Ship is in " .. state .. " mode")
  1581.           sleep(5)
  1582.         end
  1583.        
  1584.     while true do
  1585.             local status, isEnabled, state, energy = wrap.state()
  1586.             if state ~= "-NotDetected-" then break end
  1587.             w.status_showWarning("Waiting to connect to core(s)...")
  1588.             sleep(5)
  1589.         end
  1590.     end
  1591.         --------------------------------------AUTO PILOT
  1592.         for i=1,#navdata do
  1593.           local move = navdata[i]
  1594.  
  1595.           w.status_showSuccess("Executing Jump. There are "..#navdata.." Jump(s) left.")
  1596.           http.post(uri,"{\"content\":\"```yaml\\nAutopilot: Executing next node There are "..#navdata.." node(s) left to execute.```\"}",{['content-type']="application/json"})
  1597.           table.remove(navdata,1)
  1598.           if fs.exists(navbackup) then
  1599.             fs.delete(navbackup)
  1600.             fs.copy(navdatafile, navbackup)
  1601.           end
  1602.           if #navdata > 0 then
  1603.             local text = textutils.serialize(navdata)
  1604.             local h = fs.open(navdatafile, "w")
  1605.             h.write(text)
  1606.             h.close()
  1607.           else
  1608.             fs.delete(navdatafile)
  1609.           end
  1610.           ship.command("MANUAL", false)
  1611.           ship.movement(move[1],move[2],move[3])
  1612.           ship.rotationSteps(0)
  1613.           ship.command("MANUAL", true)
  1614.           sleep(10)
  1615.           for i=50,0,-1 do
  1616.             w.status_showWarning("Waiting for the ship to jump..."..i.."   ")
  1617.             sleep(1)
  1618.           end
  1619.           number = #navdata + 1
  1620.           http.post(uri,"{\"content\":\"```yaml\\nAutoPilot: Failed Executing node "..number..".```\"}",{['content-type']="application/json"})
  1621.           fs.delete(navdatafile)
  1622.           fs.copy(navbackup, navdatafile)
  1623.           w.status_showWarning("AutoPilot: Failed Executing node " .. number)
  1624.           if failping >= 0 then
  1625.             http.post(uri,"{\"content\":\""..name.."\"}",{['content-type']="application/json"})
  1626.           end
  1627.           sleep(3)
  1628.           os.reboot()
  1629.         end
  1630.  
  1631.         --------------------------------------AUTO PILOT
  1632.       end
  1633.     end
  1634.    
  1635.     -- while true do
  1636.         -- local status, isEnabled, state, energy = ship.state()
  1637.         -- if state == "COOLING" then
  1638.             -- w.status_showWarning("Waiting Ship is in " .. state .. " mode")
  1639.             -- sleep(5)
  1640.         -- elseif state == "-NotDetected-" then
  1641.             -- w.status_showWarning("Waiting to connect to core(s)...")
  1642.             -- sleep(5)
  1643.         -- else
  1644.             -- break
  1645.         -- end
  1646.     -- end
  1647.    
  1648.     for _, core in ipairs(cores) do
  1649.       local wrap = core.wrapper
  1650.    
  1651.         while true do
  1652.           local status, isEnabled, state, energy = wrap.state()
  1653.           if state ~= "COOLING" then break end
  1654.           w.status_showWarning("Waiting Ship is in " .. state .. " mode")
  1655.           sleep(5)
  1656.         end
  1657.        
  1658.     while true do
  1659.             local status, isEnabled, state, energy = wrap.state()
  1660.             if state ~= "-NotDetected-" then break end
  1661.             w.status_showWarning("Waiting to connect to core(s)...")
  1662.             sleep(5)
  1663.         end
  1664.     end
  1665.        
  1666.     local success, message = pcall(w.run)
  1667.     if not success then
  1668.       print("failed with message")
  1669.       print(message)
  1670.       w.sleep(5)
  1671.       print("rebooting...")
  1672.       w.reboot()
  1673.     else
  1674.       if ship ~= nil then
  1675.         ship.command("OFFLINE", true)
  1676.         ship.enable(false)
  1677.       end
  1678.  
  1679.       w.close()
  1680.     end
  1681.    
  1682.    
Advertisement
Add Comment
Please, Sign In to add comment