fix(multiplayer): normalize CRN BlockReader NBT structure with unwrapNbtObject helper to handle SP vs MP differences (single-player wraps every nested object as { [1] = obj } one-element arrays, while multiplayer uses direct maps without [1] wrapper)
- New unwrapNbtObject(obj): detects whether the table actually has a [1] wrapper AND outer table has exactly 1 key AND the inner [1] is useful, then returns inner object; otherwise returns obj unchanged - works transparently for both SP and MP structures - Replace ALL hard-coded [1] dereferences in BlockReader parsing: - stop.Station -> unwrapNbtObject(stop.Station) - st.RealTimeStation -> unwrapNbtObject(st.RealTimeStation) - st.ScheduledStation -> unwrapNbtObject(st.ScheduledStation) - rtStation.StationInfo -> unwrapNbtObject(rtStation.StationInfo) - schStation.StationInfo -> unwrapNbtObject(schStation.StationInfo) - stop.Train -> unwrapNbtObject(stop.Train) - stop.Stopovers[i] entries: deep-unwrap if table, try StationName/Name fields to get string destination from potential NBT compound stopovers - tr.Status entries: unwrap each element before reading as string - This eliminates the MP-only failure where st=nil (because SP-style Station[1] didn't exist) causing the whole TrainStop loop to skip inserting anything into newUpcoming and render UPCOMING as ??? Bump to v1.0.76
This commit is contained in:
+45
-14
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
-- 1. Configuration & Constants
|
-- 1. Configuration & Constants
|
||||||
local APP_VERSION_TEXT = "v1.0.75"
|
local APP_VERSION_TEXT = "v1.0.76"
|
||||||
|
|
||||||
local CONFIG = {
|
local CONFIG = {
|
||||||
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
||||||
@@ -3141,6 +3141,23 @@ local function isStationDestination(destName)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function unwrapNbtObject(obj)
|
||||||
|
if type(obj) ~= "table" then return obj end
|
||||||
|
if obj[1] == nil then return obj end
|
||||||
|
local inner = obj[1]
|
||||||
|
local isInnerUseful = false
|
||||||
|
if type(inner) == "table" then
|
||||||
|
for _ in pairs(inner) do isInnerUseful = true break end
|
||||||
|
elseif inner ~= nil then
|
||||||
|
isInnerUseful = true
|
||||||
|
end
|
||||||
|
if not isInnerUseful then return obj end
|
||||||
|
local outerKeyCount = 0
|
||||||
|
for _ in pairs(obj) do outerKeyCount = outerKeyCount + 1 end
|
||||||
|
if outerKeyCount == 1 then return inner end
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
local function extractAlphaNumCodes(text)
|
local function extractAlphaNumCodes(text)
|
||||||
if not text then return {} end
|
if not text then return {} end
|
||||||
local s = tostring(text)
|
local s = tostring(text)
|
||||||
@@ -3431,18 +3448,29 @@ function Main.loop()
|
|||||||
|
|
||||||
for i, stop in ipairs(data.TrainStops) do
|
for i, stop in ipairs(data.TrainStops) do
|
||||||
local okStop, err = pcall(function()
|
local okStop, err = pcall(function()
|
||||||
local st = type(stop.Station) == "table" and stop.Station[1] or stop.Station
|
local st = unwrapNbtObject(stop.Station)
|
||||||
if st then
|
if st then
|
||||||
local trainName = st.TrainName or "Unknown"
|
local trainName = st.TrainName or "Unknown"
|
||||||
local rtStation = type(st.RealTimeStation) == "table" and st.RealTimeStation[1] or nil
|
local rtStation = unwrapNbtObject(st.RealTimeStation)
|
||||||
local schStation = type(st.ScheduledStation) == "table" and st.ScheduledStation[1] or nil
|
local schStation = unwrapNbtObject(st.ScheduledStation)
|
||||||
local rtStationName = rtStation and rtStation.StationName or nil
|
local rtStationName = type(rtStation) == "table" and rtStation.StationName or nil
|
||||||
local schStationName = schStation and schStation.StationName or nil
|
local schStationName = type(schStation) == "table" and schStation.StationName or nil
|
||||||
local isLast = (stop.IsLast == 1 or stop.IsLast == true)
|
local isLast = (stop.IsLast == 1 or stop.IsLast == true)
|
||||||
|
|
||||||
local destination = st.Destination or "Unknown"
|
local destination = st.Destination or "Unknown"
|
||||||
if type(stop.Stopovers) == "table" and #stop.Stopovers > 0 then
|
if type(stop.Stopovers) == "table" and #stop.Stopovers > 0 then
|
||||||
local lastStopover = stop.Stopovers[#stop.Stopovers]
|
local lastStopover_raw = stop.Stopovers[#stop.Stopovers]
|
||||||
|
local lastStopover
|
||||||
|
if type(lastStopover_raw) == "table" then
|
||||||
|
local unwrapped = unwrapNbtObject(lastStopover_raw)
|
||||||
|
if type(unwrapped) == "table" then
|
||||||
|
lastStopover = unwrapped.StationName or unwrapped.Name or unwrapped[1] or lastStopover_raw
|
||||||
|
else
|
||||||
|
lastStopover = unwrapped or lastStopover_raw
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lastStopover = lastStopover_raw
|
||||||
|
end
|
||||||
if looksLikeValidDestinationText(lastStopover) then
|
if looksLikeValidDestinationText(lastStopover) then
|
||||||
destination = lastStopover
|
destination = lastStopover
|
||||||
elseif not looksLikeValidDestinationText(destination) then
|
elseif not looksLikeValidDestinationText(destination) then
|
||||||
@@ -3466,11 +3494,11 @@ function Main.loop()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local platform = "1"
|
local platform = "1"
|
||||||
local rtStationInfo = rtStation and type(rtStation.StationInfo) == "table" and rtStation.StationInfo[1] or nil
|
local rtStationInfo = type(rtStation) == "table" and unwrapNbtObject(rtStation.StationInfo) or nil
|
||||||
local schStationInfo = schStation and type(schStation.StationInfo) == "table" and schStation.StationInfo[1] or nil
|
local schStationInfo = type(schStation) == "table" and unwrapNbtObject(schStation.StationInfo) or nil
|
||||||
if schStationInfo and schStationInfo.Platform then
|
if type(schStationInfo) == "table" and schStationInfo.Platform then
|
||||||
platform = schStationInfo.Platform
|
platform = schStationInfo.Platform
|
||||||
elseif rtStationInfo and rtStationInfo.Platform then
|
elseif type(rtStationInfo) == "table" and rtStationInfo.Platform then
|
||||||
platform = rtStationInfo.Platform
|
platform = rtStationInfo.Platform
|
||||||
else
|
else
|
||||||
platform = State.stationPlatform or "1"
|
platform = State.stationPlatform or "1"
|
||||||
@@ -3479,13 +3507,16 @@ function Main.loop()
|
|||||||
if isStationDestination(destination) then
|
if isStationDestination(destination) then
|
||||||
local cancelled = false
|
local cancelled = false
|
||||||
local reason = nil
|
local reason = nil
|
||||||
local tr = type(stop.Train) == "table" and stop.Train[1] or stop.Train
|
local tr = unwrapNbtObject(stop.Train)
|
||||||
if tr then
|
if type(tr) == "table" then
|
||||||
cancelled = tr.Cancelled == 1 or tr.Cancelled == true
|
cancelled = tr.Cancelled == 1 or tr.Cancelled == true
|
||||||
local status = tr.Status
|
local status = tr.Status
|
||||||
if type(status) == "table" then
|
if type(status) == "table" then
|
||||||
for _, s in ipairs(status) do
|
for _, s in ipairs(status) do
|
||||||
if type(s) == "string" then
|
local unwrapped_s = unwrapNbtObject(s)
|
||||||
|
if type(unwrapped_s) == "string" then
|
||||||
|
reason = mapTrainStatusReason(unwrapped_s) or reason
|
||||||
|
elseif type(s) == "string" then
|
||||||
reason = mapTrainStatusReason(s) or reason
|
reason = mapTrainStatusReason(s) or reason
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user