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