Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if not term.isColor() then
- print("Advanced computer required")
- exit()
- end
- print("loading...")
- monitor_textScale = 0.5
- Style = {
- CDefault = colors.white,
- BGDefault = colors.blue,
- CTitle = colors.black,
- BGTitle = colors.cyan,
- CWarning = colors.white,
- BGWarning = colors.red,
- CSuccess = colors.white,
- BGSuccess = colors.lime,
- CDisabled = colors.gray,
- BGDisabled = colors.blue
- }
- ----------- Monitor support
- function SetMonitorColorFrontBack(frontColor, backgroundColor)
- term.setBackgroundColor(backgroundColor)
- term.setTextColor(frontColor)
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- monitor.setTextColor(frontColor)
- monitor.setBackgroundColor(backgroundColor)
- end
- end
- end
- function Write(text)
- term.write(text)
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- if key ~= data.radar_monitorIndex then
- monitor.write(text)
- end
- end
- end
- end
- function SetCursorPos(x, y)
- term.setCursorPos(x, y)
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- if key ~= data.radar_monitorIndex then
- monitor.setCursorPos(x, y)
- end
- end
- end
- end
- function SetColorDefault()
- SetMonitorColorFrontBack(Style.CDefault, Style.BGDefault)
- end
- function SetColorTitle()
- SetMonitorColorFrontBack(Style.CTitle, Style.BGTitle)
- end
- function SetColorWarning()
- SetMonitorColorFrontBack(Style.CWarning, Style.BGWarning)
- end
- function SetColorSuccess()
- SetMonitorColorFrontBack(Style.CSuccess, Style.BGSuccess)
- end
- function SetColorDisabled()
- SetMonitorColorFrontBack(Style.CDisabled, Style.BGDisabled)
- end
- function Clear()
- clearWarningTick = -1
- SetColorDefault()
- term.clear()
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- if key ~= data.radar_monitorIndex then
- monitor.clear()
- end
- end
- end
- SetCursorPos(1, 1)
- end
- function ClearLine()
- SetColorDefault()
- term.clearLine()
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- if key ~= data.radar_monitorIndex then
- monitor.clearLine()
- end
- end
- end
- SetCursorPos(1, 1)
- end
- function WriteLn(text)
- Write(text)
- local x, y = term.getCursorPos()
- local width, height = term.getSize()
- if y > height - 1 then
- y = 1
- end
- SetCursorPos(1, y + 1)
- end
- function WriteCentered(y, text)
- SetCursorPos((51 - text:len()) / 2, y)
- term.write(text)
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- if key ~= data.radar_monitorIndex then
- local sizeX, sizeY = monitor.getSize()
- monitor.setCursorPos((sizeX - text:len()) / 2, y)
- monitor.write(text)
- end
- end
- end
- local xt, yt = term.getCursorPos()
- SetCursorPos(1, yt + 1)
- end
- function ShowTitle(text)
- Clear()
- SetColorTitle()
- WriteCentered(1, text)
- SetColorDefault()
- end
- function ShowMenu(text)
- Write(text)
- local sizeX, sizeY = term.getSize()
- local xt, yt = term.getCursorPos()
- for i = xt, sizeX do
- Write(" ")
- end
- SetCursorPos(1, yt + 1)
- end
- local clearWarningTick = -1
- function ShowWarning(text)
- local sizeX, sizeY = term.getSize()
- SetCursorPos(1, sizeY)
- ClearLine()
- SetColorWarning()
- SetCursorPos((sizeX - text:len() - 2) / 2, sizeY)
- Write(" " .. text .. " ")
- SetColorDefault()
- clearWarningTick = 5
- end
- function ClearWarning()
- if clearWarningTick > 0 then
- clearWarningTick = clearWarningTick - 1
- elseif clearWarningTick == 0 then
- SetColorDefault()
- local sizeX, sizeY = term.getSize()
- SetCursorPos(1, sizeY)
- ClearLine()
- clearWarningTick = -1
- end
- end
- ----------- Formatting & popups
- function FormatFloat(value, nbchar)
- local str = "?"
- if value ~= nil then
- str = string.format("%g", value)
- end
- if nbchar ~= nil then
- str = string.sub(" " .. str, -nbchar)
- end
- return str
- end
- function FormatInteger(value, nbchar)
- local str = "?"
- if value ~= nil then
- str = string.format("%d", value)
- end
- if nbchar ~= nil then
- str = string.sub(" " .. str, -nbchar)
- end
- return str
- end
- function boolToYesNo(bool)
- if bool then
- return "YES"
- else
- return "no"
- end
- end
- function readInputNumber(currentValue)
- local inputAbort = false
- local input = string.format(currentValue)
- if input == "0" then
- input = ""
- end
- local x, y = term.getCursorPos()
- repeat
- ClearWarning()
- SetColorDefault()
- SetCursorPos(x, y)
- Write(input .. " ")
- input = string.sub(input, -9)
- local params = { os.pullEventRaw() }
- local eventName = params[1]
- local address = params[2]
- if address == nil then address = "none" end
- if eventName == "key" then
- local keycode = params[2]
- if keycode >= 2 and keycode <= 10 then -- 1 to 9
- input = input .. string.format(keycode - 1)
- elseif keycode == 11 or keycode == 82 then -- 0 & keypad 0
- input = input .. "0"
- elseif keycode >= 79 and keycode <= 81 then -- keypad 1 to 3
- input = input .. string.format(keycode - 78)
- elseif keycode >= 75 and keycode <= 77 then -- keypad 4 to 6
- input = input .. string.format(keycode - 71)
- elseif keycode >= 71 and keycode <= 73 then -- keypad 7 to 9
- input = input .. string.format(keycode - 64)
- elseif keycode == 14 then -- Backspace
- input = string.sub(input, 1, string.len(input) - 1)
- elseif keycode == 211 then -- Delete
- input = ""
- elseif keycode == 28 then -- Enter
- inputAbort = true
- elseif keycode == 74 or keycode == 12 or keycode == 49 then -- - on numeric keypad or - on US top or n letter
- if string.sub(input, 1, 1) == "-" then
- input = string.sub(input, 2)
- else
- input = "-" .. input
- end
- elseif keycode == 78 then -- +
- if string.sub(input, 1, 1) == "-" then
- input = string.sub(input, 2)
- end
- else
- ShowWarning("Key " .. keycode .. " is invalid")
- end
- elseif eventName == "terminate" then
- inputAbort = true
- elseif not common_event(eventName, params[2]) then
- ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported")
- end
- until inputAbort
- SetCursorPos(1, y + 1)
- if input == "" or input == "-" then
- return currentValue
- else
- return tonumber(input)
- end
- end
- function readInputText(currentValue)
- local inputAbort = false
- local input = string.format(currentValue)
- local x, y = term.getCursorPos()
- Write(input)
- os.pullEventRaw() -- skip first char event
- repeat
- ClearWarning()
- SetColorDefault()
- SetCursorPos(x, y)
- Write(input .. " ")
- input = string.sub(input, -30)
- local params = { os.pullEventRaw() }
- local eventName = params[1]
- local address = params[2]
- if address == nil then address = "none" end
- if eventName == "key" then
- local keycode = params[2]
- if keycode == 14 then -- Backspace
- input = string.sub(input, 1, string.len(input) - 1)
- elseif keycode == 211 then -- Delete
- input = ""
- elseif keycode == 28 then -- Enter
- inputAbort = true
- else
- ShowWarning("Key " .. keycode .. " is invalid")
- end
- elseif eventName == "char" then
- local char = params[2]
- if char >= ' ' and char <= '~' then -- 1 to 9
- input = input .. char
- else
- ShowWarning("Char #" .. string.byte(char) .. " is invalid")
- end
- elseif eventName == "terminate" then
- inputAbort = true
- elseif not common_event(eventName, params[2]) then
- ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported")
- end
- until inputAbort
- SetCursorPos(1, y + 1)
- if input == "" then
- return currentValue
- else
- return input
- end
- end
- function readConfirmation(msg)
- if msg == nil then
- ShowWarning("Are you sure? (y/n)")
- else
- ShowWarning(msg)
- end
- repeat
- local params = { os.pullEventRaw() }
- local eventName = params[1]
- local address = params[2]
- if address == nil then address = "none" end
- if eventName == "key" then
- local keycode = params[2]
- if keycode == 21 then -- Y
- return true
- else
- return false
- end
- elseif eventName == "terminate" then
- return false
- elseif not common_event(eventName, params[2]) then
- ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported")
- end
- until false
- end
- ----------- commons: menu, event handlers, etc.
- function common_event(eventName, param)
- if eventName == "redstone" then
- redstone_event(param)
- elseif eventName == "timer" then
- elseif eventName == "shipCoreCooldownDone" then
- ShowWarning("Ship core cooldown done")
- elseif eventName == "char" then
- elseif eventName == "key_up" then
- elseif eventName == "mouse_click" then
- elseif eventName == "mouse_up" then
- elseif eventName == "mouse_drag" then
- elseif eventName == "monitor_touch" then
- elseif eventName == "monitor_resize" then
- elseif eventName == "peripheral" then
- elseif eventName == "peripheral_detach" then
- else
- return false
- end
- return true
- end
- function menu_common()
- SetCursorPos(1, 18)
- SetColorTitle()
- ShowMenu("0 Connections, 1 Ship core, X Exit")
- end
- ----------- Redstone support
- local tblRedstoneState = {-- Remember redstone state on each side
- ["top"] = rs.getInput("top"),
- ["front"] = rs.getInput("front"),
- ["left"] = rs.getInput("left"),
- ["right"] = rs.getInput("right"),
- ["back"] = rs.getInput("back"),
- ["bottom"] = rs.getInput("bottom"),
- }
- local tblSides = {-- list all sides and offset coordinates
- ["top" ] = { 3, 1},
- ["front" ] = { 1, 3},
- ["left" ] = { 3, 3},
- ["right" ] = { 5, 3},
- ["back" ] = { 5, 5},
- ["bottom"] = { 3, 5},
- }
- function redstone_event()
- -- Event only returns nil so we need to check sides manually
- local message = ""
- for side, state in pairs(tblRedstoneState) do
- if rs.getInput(side) ~= state then
- -- print(side .. " is now " .. tostring(rs.getInput(side)))
- message = message .. side .. " "
- tblRedstoneState[side] = rs.getInput(side)
- end
- end
- if message ~= "" then
- message = "Redstone changed on " .. message
- showWarning(message)
- end
- end
- ----------- Configuration
- function data_save()
- local file = fs.open("shipdata.txt", "w")
- if file ~= nil then
- file.writeLine(textutils.serialize(data))
- file.close()
- else
- ShowWarning("No file system")
- os.sleep(3)
- end
- end
- function data_read()
- data = { }
- if fs.exists("shipdata.txt") then
- local file = fs.open("shipdata.txt", "r")
- data = textutils.unserialize(file.readAll())
- file.close()
- if data == nil then data = {}; end
- end
- if data.core_summon == nil then data.core_summon = false; end
- end
- function data_setName()
- if ship ~= nil then
- ShowTitle("<==== Set ship name ====>")
- else
- ShowTitle("<==== Set name ====>")
- end
- SetCursorPos(1, 2)
- Write("Enter ship name: ")
- label = readInputText(label)
- os.setComputerLabel(label)
- if ship ~= nil then
- ship.coreFrequency(label)
- end
- os.reboot()
- end
- function string_split(source, sep)
- local sep = sep or ":"
- local fields = {}
- local pattern = string.format("([^%s]+)", sep)
- source:gsub(pattern, function(c) fields[#fields + 1] = c end)
- return fields
- end
- ----------- Ship support
- source = {0,1,0}
- dest = {0,1,0}
- lock_power = 0
- power_boost = 0
- energy_required = 0
- function transporterBoot()
- Write("Booting Transporter")
- WriteLn("...")
- energy_required = transporter.getEnergyRequired()
- lock_power = transporter.lockStrength()
- transporter_source = { transporter.source() }
- transporter_dest = { transporter.dest() }
- function core_writeMovement()
- local message = " Movement = "
- local count = 0
- if core_movement[1] > 0 then
- message = message .. core_movement[1] .. " front"
- count = count + 1
- elseif core_movement[1] < 0 then
- message = message .. (- core_movement[1]) .. " back"
- count = count + 1
- end
- if core_movement[2] > 0 then
- if count > 0 then message = message .. ", "; end
- message = message .. core_movement[2] .. " up"
- count = count + 1
- elseif core_movement[2] < 0 then
- if count > 0 then message = message .. ", "; end
- message = message .. (- core_movement[2]) .. " down"
- count = count + 1
- end
- if core_movement[3] > 0 then
- if count > 0 then message = message .. ", "; end
- message = message .. core_movement[3] .. " right"
- count = count + 1
- elseif core_movement[3] < 0 then
- if count > 0 then message = message .. ", "; end
- message = message .. (- core_movement[3]) .. " left"
- count = count + 1
- end
- if core_rotationSteps == 1 then
- if count > 0 then message = message .. ", "; end
- message = message .. "Turn right"
- count = count + 1
- elseif core_rotationSteps == 2 then
- if count > 0 then message = message .. ", "; end
- message = message .. "Turn back"
- count = count + 1
- elseif core_rotationSteps == 3 then
- if count > 0 then message = message .. ", "; end
- message = message .. "Turn left"
- count = count + 1
- end
- if count == 0 then
- message = message .. "(none)"
- end
- WriteLn(message)
- end
- function core_writeRotation()
- if core_rotationSteps == 0 then
- WriteLn(" Rotation = Front")
- elseif core_rotationSteps == 1 then
- WriteLn(" Rotation = Right +90")
- elseif core_rotationSteps == 2 then
- WriteLn(" Rotation = Back 180")
- elseif core_rotationSteps == 3 then
- WriteLn(" Rotation = Left -90")
- end
- end
- function core_computeNewCoordinates(cx, cy, cz)
- local res = { x = cx, y = cy, z = cz }
- local dx, dy, dz = ship.getOrientation()
- local worldMovement = { x = 0, y = 0, z = 0 }
- worldMovement.x = dx * core_movement[1] - dz * core_movement[3]
- worldMovement.y = core_movement[2]
- worldMovement.z = dz * core_movement[1] + dx * core_movement[3]
- core_actualDistance = math.ceil(math.sqrt(worldMovement.x * worldMovement.x + worldMovement.y * worldMovement.y + worldMovement.z * worldMovement.z))
- energy_required = transporter.energyRequired()
- res.x = res.x + worldMovement.x
- res.y = res.y + worldMovement.y
- res.z = res.z + worldMovement.z
- return res
- end
- function core_warp()
- -- rs.setOutput(alarm_side, true)
- if readConfirmation() then
- -- rs.setOutput(alarm_side, false)
- transporter.source(transporter_source[1], transporter_source[2], transporter_source[3])
- transporter.dest(transporter_dest[1], transporter_dest[2], transporter_dest[3])
- transporter.energize()
- -- ship = nil
- end
- -- rs.setOutput(alarm_side, false)
- end
- function core_page_setMovement()
- ShowTitle("<==== Set dest ====>")
- SetCursorPos(1, 15)
- SetColorTitle()
- ShowMenu("Enter 0 to keep position on that axis")
- ShowMenu("Use - or n keys to move in opposite direction")
- ShowMenu("Press Enter to confirm")
- SetColorDefault()
- SetCursorPos(1, 3)
- core_movement[1] = core_page_setDistanceAxis(2, "Forward" , "Front", "Back", core_movement[1], math.abs(core_front + core_back + 1))
- core_movement[2] = core_page_setDistanceAxis(4, "Vertical", "Up" , "Down", core_movement[2], math.abs(core_up + core_down + 1))
- core_movement[3] = core_page_setDistanceAxis(6, "Lateral" , "Right", "Left", core_movement[3], math.abs(core_left + core_right + 1))
- core_movement = { ship.movement(core_movement[1], core_movement[2], core_movement[3]) }
- end
- function core_page_setDistanceAxis(line, axis, positive, negative, userEntry, shipLength)
- local maximumDistance = shipLength + 127
- if core_isInHyper and line ~= 3 then
- maximumDistance = shipLength + 127 * 100
- end
- SetColorDisabled()
- SetCursorPos(3, line + 1)
- Write(positive .. " is " .. ( shipLength + 1) .. ", maximum is " .. maximumDistance .. " ")
- SetCursorPos(3, line + 2)
- Write(negative .. " is " .. (-shipLength - 1) .. ", maximum is " .. -maximumDistance .. " ")
- SetColorDefault()
- repeat
- SetCursorPos(1, line)
- Write(axis .. " movement: ")
- userEntry = readInputNumber(userEntry)
- if userEntry ~= 0 and (math.abs(userEntry) <= shipLength or math.abs(userEntry) > maximumDistance) then
- ShowWarning("Wrong distance. Try again.")
- end
- until userEntry == 0 or (math.abs(userEntry) > shipLength and math.abs(userEntry) <= maximumDistance)
- SetCursorPos(1, line + 1)
- ClearLine()
- SetCursorPos(1, line + 2)
- ClearLine()
- return userEntry
- end
- function core_page()
- ShowTitle(label .. " - Transporter status")
- if ship ~= nil then
- -- WriteLn("")
- X, Y, Z = transporter.source()
- WriteLn("Source:")
- WriteLn(" x, y, z = " .. X .. ", " .. Y .. ", " .. Z)
- X, Y, Z = transporter.dest()
- WriteLn("Destination:")
- WriteLn(" x, y, z = " .. X .. ", " .. Y .. ", " .. Z)
- local energy_required = transporter.energyRequired()
- WriteLn(" Energy = " .. energy_required .. " % (" .. energy .. "EU)")
- -- WriteLn("")
- -- WriteLn("")
- WriteLn("Transport data:")
- core_writeMovement()
- local dest = core_computeNewCoordinates(X, Y, Z)
- WriteLn(" Distance = " .. core_actualDistance .. " (" .. core_jumpCost .. "EU, " .. math.floor(energy / core_jumpCost) .. " jumps)")
- WriteLn(" Dest.coordinates = " .. FormatInteger(dest.x) .. ", " .. FormatInteger(dest.y) .. ", " .. FormatInteger(dest.z))
- if data.core_summon then
- WriteLn(" Summon after = Yes")
- else
- WriteLn(" Summon after = No")
- end
- else
- ShowWarning("No ship controller detected")
- end
- SetCursorPos(1, 15)
- SetColorTitle()
- ShowMenu("D - Dimensions, N - set ship Name, M - set Movement")
- ShowMenu("J - Jump, G - jump through Gate, B - jump to Beacon")
- ShowMenu("H - Hyperspace, C - summon Crew, T - Toggle summon")
- end
- function core_key(char, keycode)
- if keycode == 50 then -- M
- core_page_setMovement()
- core_page_setRotation()
- return true
- elseif keycode == 20 then -- T
- if data.core_summon then
- data.core_summon = false
- else
- data.core_summon = true
- end
- data_save()
- return true
- elseif keycode == 32 then -- D
- core_page_setDimensions()
- return true
- elseif keycode == 36 then -- J
- core_warp()
- return true
- elseif keycode == 46 then -- C
- core_page_summon()
- return true
- elseif keycode == 48 then -- B
- core_page_jumpToBeacon()
- return true
- elseif keycode == 34 then -- G
- core_page_jumpToGate()
- return true
- elseif keycode == 35 then -- H
- -- rs.setOutput(alarm_side, true)
- if readConfirmation() then
- -- rs.setOutput(alarm_side, false)
- ship.mode(5)
- ship.jump()
- -- ship = nil
- end
- -- rs.setOutput(alarm_side, false)
- return true
- elseif keycode == 49 then
- data_setName()
- return true
- end
- return false
- end
- ----------- Boot sequence
- math.randomseed(os.time())
- label = os.getComputerLabel()
- if not label then
- label = "" .. os.getComputerID()
- end
- -- read configuration
- data_read()
- Clear()
- print("data_read...")
- -- initial scanning
- monitors = {}
- ShowTitle(label .. " - Connecting...")
- WriteLn("")
- sides = peripheral.getNames()
- ship = nil
- for key,side in pairs(sides) do
- os.sleep(0)
- Write("Checking " .. side .. " ")
- local componentType = peripheral.getType(side)
- Write(componentType .. " ")
- if componentType == "monitor" then
- Write("wrapping!")
- lmonitor = peripheral.wrap(side)
- table.insert(monitors, lmonitor)
- lmonitor.setTextScale(monitor_textScale)
- elseif componentType == "warpdriveShipController" then
- Write("wrapping!")
- ship = peripheral.wrap(side)
- end
- WriteLn("")
- end
- if not os.getComputerLabel() and ship ~= nil then
- data_setName()
- end
- -- peripherals status
- function connections_page()
- ShowTitle(label .. " - Connections")
- WriteLn("")
- if ship == nil then
- SetColorDisabled()
- WriteLn("No ship controller detected")
- else
- SetColorSuccess()
- WriteLn("Ship controller detected")
- end
- WriteLn("")
- SetColorTitle()
- WriteLn("Please refer to below menu for keyboard controls")
- WriteLn("For example, press 1 to access Ship core page")
- end
- -- peripheral boot up
- Clear()
- connections_page()
- SetColorDefault()
- WriteLn("")
- os.sleep(0)
- core_boot()
- os.sleep(0)
- -- main loop
- abort = false
- refresh = true
- page = connections_page
- keyHandler = nil
- repeat
- ClearWarning()
- if refresh then
- Clear()
- page()
- menu_common()
- refresh = false
- end
- params = { os.pullEventRaw() }
- eventName = params[1]
- address = params[2]
- if address == nil then address = "none" end
- -- WriteLn("...")
- -- WriteLn("Event '" .. eventName .. "', " .. address .. ", " .. params[3] .. ", " .. params[4] .. " received")
- -- os.sleep(0.2)
- if eventName == "key" then
- keycode = params[2]
- if char == 88 or char == 120 or keycode == 45 then -- x for eXit
- os.pullEventRaw()
- abort = true
- elseif char == 48 or keycode == 11 or keycode == 82 then -- 0
- page = connections_page
- keyHandler = nil
- refresh = true
- elseif char == 49 or keycode == 2 or keycode == 79 then -- 1
- page = core_page
- keyHandler = core_key
- refresh = true
- elseif keyHandler ~= nil and keyHandler(char, keycode) then
- refresh = true
- os.sleep(0)
- elseif char == 0 then -- control chars
- refresh = false
- os.sleep(0)
- else
- ShowWarning("Key " .. keycode .. " is invalid")
- os.sleep(0.2)
- end
- elseif eventName == "terminate" then
- abort = true
- elseif not common_event(eventName, params[2]) then
- ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported")
- refresh = true
- os.sleep(0.2)
- end
- until abort
- -- exiting
- if data.core_summon then
- data.core_summon = false
- data_save()
- end
- if ship ~= nil then
- ship.mode(0)
- end
- -- clear screens on exit
- SetMonitorColorFrontBack(colors.white, colors.black)
- term.clear()
- if monitors ~= nil then
- for key,monitor in pairs(monitors) do
- monitor.clear()
- end
- end
- SetCursorPos(1, 1)
- WriteLn("Program terminated")
- WriteLn("Type startup to restart it")
Add Comment
Please, Sign In to add comment