fix(gate): 修复区块加载时检票机屏幕无显示问题 - 新增 monitor 握手阶段,所有 termDev 渲染调用加 pcall 保护,启动后 20 秒持续重绘热修复,修复 setServerConnected 重复定义丢失 queueEvent 的 bug (v1.5.30)
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
local DEFAULT_SERVER_BASE = "https://ticket.fse-media.group"
|
||||
local DEFAULT_SERVER_PATH = "/api/tickets/check"
|
||||
local GATE_OPEN_SECONDS = 2
|
||||
local VERSION = "v1.5.29"
|
||||
local VERSION = "v1.5.30"
|
||||
local VERSION_CHECK_INTERVAL = 5
|
||||
local PERIPHERAL_WAIT_INTERVAL = 0.5
|
||||
local PERIPHERAL_WAIT_MAX_RETRIES = 40
|
||||
local MONITOR_HANDSHAKE_RETRIES = 20
|
||||
local STARTUP_REDRAW_DURATION = 20
|
||||
local STARTUP_REDRAW_INTERVAL = 0.5
|
||||
|
||||
local serverURL = nil
|
||||
|
||||
@@ -118,11 +121,22 @@ end
|
||||
local function waitForPeripherals(requireInspection)
|
||||
local attempts = 0
|
||||
local lastDrawMsg = nil
|
||||
local handshakeDone = false
|
||||
while attempts < PERIPHERAL_WAIT_MAX_RETRIES do
|
||||
local hadChange = false
|
||||
if not monitor then
|
||||
local m, ms = safeFindPeripheral("monitor", monitorSide)
|
||||
if m then monitor = m; monitorSide = ms; hadChange = true end
|
||||
if m then
|
||||
monitor = m
|
||||
monitorSide = ms
|
||||
hadChange = true
|
||||
end
|
||||
end
|
||||
if monitor and (hadChange or not handshakeDone) then
|
||||
termDev = monitor
|
||||
local ok = false
|
||||
pcall(function() ok = handshakeMonitor(monitor) end)
|
||||
if ok then handshakeDone = true end
|
||||
end
|
||||
if not speaker then
|
||||
local s, _ = safeFindPeripheral("speaker")
|
||||
@@ -135,12 +149,17 @@ local function waitForPeripherals(requireInspection)
|
||||
local ok = true
|
||||
if not monitor then ok = false end
|
||||
if requireInspection and not inspection then ok = false end
|
||||
if ok then return true end
|
||||
if ok and handshakeDone then return true end
|
||||
if ok and not handshakeDone then
|
||||
local ok2 = false
|
||||
pcall(function() ok2 = handshakeMonitor(monitor) end)
|
||||
if ok2 then handshakeDone = true; return true end
|
||||
end
|
||||
local msg = nil
|
||||
if not monitor and requireInspection and not inspection then
|
||||
msg = "Waiting for monitor + gate..."
|
||||
elseif not monitor then
|
||||
if not monitor then
|
||||
msg = "Waiting for monitor..."
|
||||
elseif not handshakeDone then
|
||||
msg = "Waking monitor..."
|
||||
elseif requireInspection and not inspection then
|
||||
msg = "Waiting for gate peripheral..."
|
||||
end
|
||||
@@ -171,7 +190,7 @@ local function waitForPeripherals(requireInspection)
|
||||
sleep(PERIPHERAL_WAIT_INTERVAL)
|
||||
attempts = attempts + 1
|
||||
end
|
||||
return false
|
||||
return not not monitor
|
||||
end
|
||||
|
||||
pcall(function() waitForPeripherals(false) end)
|
||||
@@ -248,33 +267,81 @@ local function jsonDecode(str)
|
||||
if ok then return res else return nil end
|
||||
end
|
||||
|
||||
local function setServerConnected(ok)
|
||||
if serverConnected == ok then return end
|
||||
serverConnected = ok
|
||||
serverLastChangeTs = os.epoch("utc")
|
||||
end
|
||||
|
||||
local termDev = nativeTerm
|
||||
if peripheral and type(peripheral.getName) == "function" and monitor then
|
||||
pcall(function() monitorSide = peripheral.getName(monitor) end)
|
||||
end
|
||||
|
||||
local function safeCallTerm(method, ...)
|
||||
if not termDev or type(termDev[method]) ~= "function" then return nil end
|
||||
local ok, r1, r2, r3 = pcall(termDev[method], ...)
|
||||
if not ok then return nil end
|
||||
return r1, r2, r3
|
||||
end
|
||||
|
||||
local function safeCallMonitor(target, method, ...)
|
||||
if not target or type(target[method]) ~= "function" then return false end
|
||||
local ok, r1 = pcall(target[method], ...)
|
||||
if not ok then return false end
|
||||
return r1 ~= false
|
||||
end
|
||||
|
||||
local function handshakeMonitor(target)
|
||||
if not target then return false end
|
||||
local scaleOk = false
|
||||
local getSizeOk = false
|
||||
local w, h = nil, nil
|
||||
for _ = 1, MONITOR_HANDSHAKE_RETRIES do
|
||||
if safeCallMonitor(target, "setTextScale", 0.5) then scaleOk = true end
|
||||
w, h = safeCallTerm("getSize")
|
||||
if type(w) == "number" and type(h) == "number" and w >= 2 and h >= 2 then
|
||||
getSizeOk = true
|
||||
end
|
||||
if scaleOk and getSizeOk then
|
||||
local cOk = safeCallMonitor(target, "setBackgroundColor", colors.black)
|
||||
local c2Ok = safeCallMonitor(target, "setTextColor", colors.white)
|
||||
local clearOk = safeCallMonitor(target, "clear")
|
||||
if clearOk then return true end
|
||||
end
|
||||
sleep(PERIPHERAL_WAIT_INTERVAL)
|
||||
local rewrapOk, rewrapped = pcall(function()
|
||||
if monitorSide and peripheral and type(peripheral.isPresent) == "function" and peripheral.isPresent(monitorSide) and type(peripheral.wrap) == "function" then
|
||||
local okW, wd = pcall(peripheral.wrap, monitorSide)
|
||||
if okW and wd then return wd end
|
||||
end
|
||||
if peripheral and type(peripheral.find) == "function" then
|
||||
return peripheral.find("monitor")
|
||||
end
|
||||
return nil
|
||||
end)
|
||||
if rewrapOk and rewrapped then
|
||||
target = rewrapped
|
||||
monitor = rewrapped
|
||||
termDev = rewrapped
|
||||
end
|
||||
end
|
||||
return scaleOk or getSizeOk
|
||||
end
|
||||
|
||||
local function refreshDisplayTarget()
|
||||
local nextMonitor = nil
|
||||
local nextMonitorSide = monitorSide
|
||||
if peripheral then
|
||||
if nextMonitorSide and type(peripheral.isPresent) == "function" and peripheral.isPresent(nextMonitorSide) and type(peripheral.wrap) == "function" then
|
||||
local okWrap, wrapped = pcall(peripheral.wrap, nextMonitorSide)
|
||||
if okWrap and wrapped then
|
||||
nextMonitor = wrapped
|
||||
if nextMonitorSide and type(peripheral.isPresent) == "function" then
|
||||
local okPres, pres = pcall(peripheral.isPresent, nextMonitorSide)
|
||||
if okPres and pres and type(peripheral.wrap) == "function" then
|
||||
local okWrap, wrapped = pcall(peripheral.wrap, nextMonitorSide)
|
||||
if okWrap and wrapped then nextMonitor = wrapped end
|
||||
end
|
||||
end
|
||||
if not nextMonitor and type(peripheral.find) == "function" then
|
||||
local foundName = nil
|
||||
local found = peripheral.find("monitor", function(name, wrapped)
|
||||
foundName = name
|
||||
nextMonitor = wrapped
|
||||
return true
|
||||
local found = nil
|
||||
pcall(function()
|
||||
found = peripheral.find("monitor", function(name, wrapped)
|
||||
foundName = name
|
||||
return true
|
||||
end)
|
||||
end)
|
||||
if found then
|
||||
nextMonitor = found
|
||||
@@ -284,10 +351,18 @@ local function refreshDisplayTarget()
|
||||
end
|
||||
end
|
||||
end
|
||||
monitor = nextMonitor
|
||||
monitorSide = nextMonitorSide
|
||||
if nextMonitor and nextMonitor ~= monitor then
|
||||
monitor = nextMonitor
|
||||
monitorSide = nextMonitorSide
|
||||
pcall(function() handshakeMonitor(nextMonitor) end)
|
||||
elseif nextMonitor then
|
||||
monitor = nextMonitor
|
||||
monitorSide = nextMonitorSide
|
||||
end
|
||||
if monitor then
|
||||
pcall(monitor.setTextScale, 0.5)
|
||||
if not safeCallMonitor(monitor, "setTextScale", 0.5) then
|
||||
pcall(function() handshakeMonitor(monitor) end)
|
||||
end
|
||||
termDev = monitor
|
||||
else
|
||||
termDev = nativeTerm or term
|
||||
@@ -296,52 +371,48 @@ local function refreshDisplayTarget()
|
||||
end
|
||||
|
||||
local function clear()
|
||||
refreshDisplayTarget()
|
||||
termDev.setBackgroundColor(colors.black)
|
||||
termDev.setTextColor(colors.white)
|
||||
termDev.clear()
|
||||
termDev.setCursorPos(1, 1)
|
||||
pcall(refreshDisplayTarget)
|
||||
if not termDev then return end
|
||||
safeCallTerm("setBackgroundColor", colors.black)
|
||||
safeCallTerm("setTextColor", colors.white)
|
||||
safeCallTerm("clear")
|
||||
safeCallTerm("setCursorPos", 1, 1)
|
||||
end
|
||||
|
||||
local function centerText(y, text, color)
|
||||
local w = termDev.getSize()
|
||||
termDev.setTextColor(color or colors.white)
|
||||
local x = math.max(1, math.floor((w - #text) / 2) + 1)
|
||||
termDev.setCursorPos(x, y)
|
||||
termDev.write(text)
|
||||
if not termDev then return end
|
||||
local w = safeCallTerm("getSize")
|
||||
w = tonumber(w) or 0
|
||||
if w < 2 then return end
|
||||
safeCallTerm("setTextColor", color or colors.white)
|
||||
local x = math.max(1, math.floor((w - #tostring(text or "")) / 2) + 1)
|
||||
safeCallTerm("setCursorPos", x, y)
|
||||
safeCallTerm("write", tostring(text or ""))
|
||||
end
|
||||
|
||||
local function splitDisplayLines(text)
|
||||
local out = {}
|
||||
text = tostring(text or "")
|
||||
if #text == 0 then return out end
|
||||
for line in text:gmatch("([^\n]*)\n?") do
|
||||
if line == "" and #out > 0 and text:sub(-1) ~= "\n" then break end
|
||||
if #line > 0 then table.insert(out, line) end
|
||||
end
|
||||
return out
|
||||
end
|
||||
local lastStartupRedrawAt = 0
|
||||
|
||||
local function drawServerStatusIndicator(w)
|
||||
w = tonumber(w) or 0
|
||||
if w < 2 then return end
|
||||
local col = colors.yellow
|
||||
if serverConnected == true then col = colors.lime
|
||||
elseif serverConnected == false then col = colors.red end
|
||||
termDev.setBackgroundColor(colors.black)
|
||||
termDev.setTextColor(col)
|
||||
termDev.setCursorPos(w - 1, 1)
|
||||
termDev.write("S")
|
||||
termDev.setCursorPos(w, 1)
|
||||
termDev.write("*")
|
||||
termDev.setTextColor(colors.white)
|
||||
safeCallTerm("setBackgroundColor", colors.black)
|
||||
safeCallTerm("setTextColor", col)
|
||||
safeCallTerm("setCursorPos", w - 1, 1)
|
||||
safeCallTerm("write", "S")
|
||||
safeCallTerm("setCursorPos", w, 1)
|
||||
safeCallTerm("write", "*")
|
||||
safeCallTerm("setTextColor", colors.white)
|
||||
end
|
||||
|
||||
local lastUpdateError = nil
|
||||
|
||||
local function drawVersionIndicator(w)
|
||||
w = tonumber(w) or 0
|
||||
local s = tostring(VERSION or "")
|
||||
if #s == 0 then return end
|
||||
if w < #s then return end
|
||||
if #s == 0 or w < #s then return end
|
||||
local markerColor = colors.lime
|
||||
local markerText = "* "
|
||||
if isUpdating then
|
||||
@@ -351,25 +422,31 @@ local function drawVersionIndicator(w)
|
||||
markerColor = colors.red
|
||||
markerText = "* "
|
||||
end
|
||||
termDev.setBackgroundColor(colors.black)
|
||||
termDev.setTextColor(colors.gray)
|
||||
termDev.setCursorPos(1, 1)
|
||||
termDev.write(s)
|
||||
termDev.setTextColor(markerColor)
|
||||
termDev.write(markerText)
|
||||
|
||||
safeCallTerm("setBackgroundColor", colors.black)
|
||||
safeCallTerm("setTextColor", colors.gray)
|
||||
safeCallTerm("setCursorPos", 1, 1)
|
||||
safeCallTerm("write", s)
|
||||
safeCallTerm("setTextColor", markerColor)
|
||||
safeCallTerm("write", markerText)
|
||||
|
||||
if lastUpdateError then
|
||||
termDev.setCursorPos(1, 2)
|
||||
termDev.setTextColor(colors.red)
|
||||
termDev.write(string.sub(tostring(lastUpdateError), 1, w))
|
||||
safeCallTerm("setCursorPos", 1, 2)
|
||||
safeCallTerm("setTextColor", colors.red)
|
||||
safeCallTerm("write", string.sub(tostring(lastUpdateError), 1, w))
|
||||
end
|
||||
|
||||
termDev.setTextColor(colors.white)
|
||||
|
||||
safeCallTerm("setTextColor", colors.white)
|
||||
end
|
||||
|
||||
local _cachedDrawArgHash = nil
|
||||
|
||||
local function draw(statusLine1, statusLine2, statusColor)
|
||||
clear()
|
||||
local w, h = termDev.getSize()
|
||||
if not termDev then return end
|
||||
local w, h = safeCallTerm("getSize")
|
||||
w = tonumber(w) or 0
|
||||
h = tonumber(h) or 0
|
||||
if w < 2 or h < 2 then return end
|
||||
centerText(2, "GATE", colors.cyan)
|
||||
drawVersionIndicator(w)
|
||||
drawServerStatusIndicator(w)
|
||||
@@ -385,9 +462,9 @@ local function draw(statusLine1, statusLine2, statusColor)
|
||||
centerText(y, line, statusColor or colors.white)
|
||||
end
|
||||
end
|
||||
termDev.setCursorPos(1, h)
|
||||
termDev.setTextColor(colors.gray)
|
||||
termDev.write(string.rep(" ", w))
|
||||
safeCallTerm("setCursorPos", 1, h)
|
||||
safeCallTerm("setTextColor", colors.gray)
|
||||
safeCallTerm("write", string.rep(" ", w))
|
||||
end
|
||||
|
||||
local function pulseLeftRedstone(seconds)
|
||||
@@ -1726,6 +1803,23 @@ local function mainLoop()
|
||||
drawReadyScreen()
|
||||
elseif ev[1] == "peripheral" or ev[1] == "peripheral_detach" or ev[1] == "monitor_resize" or ev[1] == "config_updated" then
|
||||
pcall(drawReadyScreen)
|
||||
elseif ev[1] == "timer" then
|
||||
pcall(drawReadyScreen)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function startupRedrawTask()
|
||||
local startTs = (os.epoch and os.epoch("utc")) or (os.time() * 3600000)
|
||||
local endTs = startTs + STARTUP_REDRAW_DURATION * 1000
|
||||
local nextRedraw = startTs
|
||||
while true do
|
||||
local now = (os.epoch and os.epoch("utc")) or (os.time() * 3600000)
|
||||
if now <= endTs then
|
||||
pcall(drawReadyScreen)
|
||||
sleep(STARTUP_REDRAW_INTERVAL)
|
||||
else
|
||||
sleep(60)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1797,4 +1891,4 @@ local function backgroundSyncTask()
|
||||
end
|
||||
end
|
||||
|
||||
parallel.waitForAny(mainLoop, backgroundSyncTask)
|
||||
parallel.waitForAny(mainLoop, startupRedrawTask, backgroundSyncTask)
|
||||
|
||||
Reference in New Issue
Block a user