fix: improve monitor alias detection and registration for better peripheral handling

This commit is contained in:
MayaTheShy
2026-03-29 00:23:59 -04:00
parent 4be2d7be8f
commit bb15c78ca9

View File

@@ -120,94 +120,135 @@ end
-- Monitor setup
-------------------------------------------------
--- Check whether two peripheral names refer to the same physical block.
-- Needed because a monitor placed adjacent to the computer AND connected
-- via wired modem appears under both its side name (e.g. "left") and its
-- network name (e.g. "monitor_0"). A simple string comparison misses this.
local function sameMonitor(a, b)
if not a or not b then return false end
if a == b then return true end
-- Write a distinctive cursor position via one name and read it back
-- via the other; if they share state, they are the same peripheral.
local ok1 = pcall(peripheral.call, a, "setCursorPos", 9876, 5432)
if not ok1 then return false end
local ok2, x, y = pcall(peripheral.call, b, "getCursorPos")
pcall(peripheral.call, a, "setCursorPos", 1, 1)
return ok2 and x == 9876 and y == 5432
--- Track peripheral names already assigned to a role.
-- A single physical monitor can appear under multiple names (e.g. "left"
-- AND "monitor_0") when it is both side-attached and on a wired modem.
-- We detect aliases by mutating text scale on one name and checking
-- whether a known monitor's getSize() changes.
D._usedMonitorNames = {} -- set of names known to be taken
--- Detect whether 'candidateName' is the same physical block as 'knownMon'
-- (a wrapped peripheral table). We temporarily set the candidate's text
-- scale to an extreme value and check whether the known monitor reports a
-- size change. If it does, they share the same hardware.
local function isMonitorAlias(candidateName, knownMon)
if not candidateName or not knownMon then return false end
local refW, refH = knownMon.getSize()
-- Save candidate's current scale (getTextScale available CC:T 1.94+)
local ok, origScale = pcall(peripheral.call, candidateName, "getTextScale")
if not ok then origScale = 1 end
-- Pick a test scale far from the current one
local testScale = (origScale >= 3) and 0.5 or 5
pcall(peripheral.call, candidateName, "setTextScale", testScale)
local newW, newH = knownMon.getSize()
-- Restore
pcall(peripheral.call, candidateName, "setTextScale", origScale)
return newW ~= refW or newH ~= refH
end
local function findMonitor(side, excludeNames)
excludeNames = excludeNames or {}
local mon = peripheral.wrap(side)
local monName
if mon and mon.setTextScale then
monName = side
else
mon = nil
end
if not mon then
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" then
local dominated = false
for _, ex in ipairs(excludeNames) do
if sameMonitor(name, ex) then dominated = true; break end
end
if not dominated then
mon = peripheral.wrap(name)
monName = name
break
end
--- Register all peripheral names that refer to the same physical block as
-- 'knownName' / 'knownMon'. This populates D._usedMonitorNames so that
-- later auto-detection can skip aliases by simple table lookup.
local function registerMonitorAliases(knownName, knownMon)
D._usedMonitorNames[knownName] = true
for _, name in ipairs(peripheral.getNames()) do
if name ~= knownName and peripheral.getType(name) == "monitor" then
if isMonitorAlias(name, knownMon) then
D._usedMonitorNames[name] = true
log.debug("DISPLAY", "Monitor alias: %s => %s", name, knownName)
end
end
end
return mon, monName
end
function D.setupMonitor()
D.mon, D.monName = findMonitor(cfg.MONITOR_SIDE, { cfg.SMELTER_MONITOR_SIDE })
local mon = peripheral.wrap(cfg.MONITOR_SIDE)
if not mon or not mon.setTextScale then
-- Fallback: find any monitor
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" then
mon = peripheral.wrap(name)
if mon and mon.setTextScale then
D.mon = mon
D.monName = name
break
end
mon = nil
end
end
else
D.mon = mon
D.monName = cfg.MONITOR_SIDE
end
if not D.mon then return false end
mainDevice = UI.Device({
device = D.mon,
textScale = 0.5,
})
-- Register this monitor and all its aliases as taken
registerMonitorAliases(D.monName, D.mon)
return true
end
function D.setupSmelterMonitor()
D.smelterMon, D.smelterMonName = findMonitor(cfg.SMELTER_MONITOR_SIDE, { D.monName })
if not D.smelterMon then return false end
-- Try configured side first
local mon = peripheral.wrap(cfg.SMELTER_MONITOR_SIDE)
local monName = cfg.SMELTER_MONITOR_SIDE
if not mon or not mon.setTextScale or D._usedMonitorNames[monName] then
mon = nil
monName = nil
-- Fallback: find any unused monitor
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and not D._usedMonitorNames[name] then
mon = peripheral.wrap(name)
if mon and mon.setTextScale then
monName = name
break
end
mon = nil
end
end
end
if not mon then return false end
D.smelterMon = mon
D.smelterMonName = monName
smelterDevice = UI.Device({
device = D.smelterMon,
textScale = 0.5,
})
-- Register this monitor and all its aliases as taken
registerMonitorAliases(D.smelterMonName, D.smelterMon)
return true
end
function D.setupBillboardMonitor()
-- If explicitly configured, use that name
local scale = cfg.BILLBOARD_TEXT_SCALE or 1
-- If explicitly configured, use that name
if cfg.BILLBOARD_MONITOR and cfg.BILLBOARD_MONITOR ~= "" then
local mon = peripheral.wrap(cfg.BILLBOARD_MONITOR)
if mon and mon.setTextScale then
D.billboardMon = mon
D.billboardMonName = cfg.BILLBOARD_MONITOR
D.billboardMon.setTextScale(scale)
registerMonitorAliases(D.billboardMonName, D.billboardMon)
return true
end
return false
end
-- Auto-detect: find any monitor not already used by main/smelter
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor"
and not sameMonitor(name, D.monName)
and not sameMonitor(name, D.smelterMonName) then
if peripheral.getType(name) == "monitor" and not D._usedMonitorNames[name] then
local mon = peripheral.wrap(name)
if mon and mon.setTextScale then
D.billboardMon = mon
D.billboardMonName = name
D.billboardMon.setTextScale(scale)
registerMonitorAliases(D.billboardMonName, D.billboardMon)
return true
end
end