功能(站点广播): 实现延误与停运列车的双语广播功能

添加所有中日文广播所需的音频资源文件
将应用版本更新至v1.0.37
修复列车状态原因映射逻辑,补充广播所需的缺失字段
实现根据延误、停运状态生成对应双语广播序列的逻辑
更新测试脚本以适配区块阅读器并正确解析CRN的NBT数据
添加示例NBT转储文件作为参考
This commit is contained in:
2026-08-02 18:50:49 +08:00
parent f922ace154
commit 39dc446958
40 changed files with 190 additions and 75 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+27 -15
View File
@@ -1865,8 +1865,11 @@ function handleTrainApproaching(ws, data) {
const cleanPlatform = String(platform).replace(/\D/g, ''); // 提取数字部分
const finalPlatform = cleanPlatform || '1';
const lineCode = data.lineCode || (stationCode ? stationCode.split('-')[0] : 'UNK');
const destCode = data.destCode || getStationCodeFromName(data.destination) || 'UNK';
const delay = Number(data.delay) || 0; // 获取延误信息(分钟)
const delay = Math.max(0, Number(data.delay) || 0); // 获取延误信息(分钟)
const cancelled = Boolean(data.cancelled);
const rawReason = String(data.reason || '').trim();
log('INFO', `Train ${trainId} approaching ${stationName} (Delay: ${delay} min). Broadcasting pre-arrival...`);
@@ -1877,24 +1880,33 @@ function handleTrainApproaching(ws, data) {
trainId
}));
// Pre-arrival Audio Logic
// 提示音:ksts
// 日文:ja-fc1 + ja-站台编号 + ja-fc2 + ja-终点编号 + ja-fc3
// 中文:ch-fc1 + ch-fc2 + ch-fc3 + ch-终点编号 + ch-fc4
const seq = ['ksts'];
// 拼接日文
seq.push('ja-fc1', `ja-${finalPlatform}`, 'ja-fc2', `ja-${destCode}`, 'ja-fc3');
if (delay > 0) {
// TODO: 根据用户的延误音频设计在这里插入日文延误播报
// 例如: seq.push('ja-delay-prefix', `ja-${delay}`, 'ja-delay-suffix');
}
// 拼接中文
seq.push('ch-fc1', 'ch-fc2', 'ch-fc3', `ch-${destCode}`, 'ch-fc4');
if (delay > 0) {
// TODO: 根据用户的延误音频设计在这里插入中文延误播报
// 例如: seq.push('ch-delay-prefix', `ch-${delay}`, 'ch-delay-suffix');
const normalizeReason = (reason, lang) => {
let r = String(reason || '').trim();
if (!r || r === 'delay') r = 'default_delay';
if (lang === 'ch' && r === 'train') r = 'delaytrain';
return r;
};
if (cancelled) {
seq.push(
'ksts',
'ja-cancel1', `ja-${lineCode}`, 'ja-cancel2',
'ch-cancel1', `ch-${lineCode}`, 'ch-cancel2'
);
} else if (delay > 0) {
const d = Math.max(1, Math.round(delay));
const jaReason = normalizeReason(rawReason, 'ja');
const chReason = normalizeReason(rawReason, 'ch');
seq.push(
'ksts',
'ja-delay1', `ja-${lineCode}`, `ja-${jaReason}`, 'ja-delay2', `ja-${d}min`, 'ja-delay3',
'ch-delay1', `ch-${lineCode}`, 'ch-delay2', `ch-${chReason}`, 'ch-delay3', `ch-${d}`, 'ch-min', 'ch-delay4'
);
}
enqueueHlsPush(stationName, seq);
+122
View File
@@ -0,0 +1,122 @@
{
IsController = 1,
Platform = "",
TrainStops = {
{
IsLast = 1,
State = 2,
FirstStop = "HC-01 1",
Stopovers = {
"HC-02 2",
},
Train = {
Carriages = 1,
StateData = {
[ "1" ] = {
CategoryId = {
0,
0,
0,
0,
},
Color = 0,
LineId = {
0,
0,
0,
0,
},
DisplayName = "[Local]1123",
},
[ "0" ] = {
CategoryId = {
0,
0,
0,
0,
},
Color = 0,
LineId = {
0,
0,
0,
0,
},
DisplayName = "[Local]1123",
},
},
Status = {
"createrailwaysnavigator:delay_from_previous_journey",
},
Cancelled = 0,
Icon = "create:traditional",
Id = {
768288300,
-1947906833,
-1592998865,
1043383053,
},
},
IsPrevSectionExcluded = 0,
IsNextSectionExcluded = 0,
Station = {
ScheduledStation = {
Id = {
0,
0,
0,
0,
},
StationInfo = {
Platform = "",
},
StationName = "HC-01 1",
TagName = "HC-01 1",
},
RealTimeDeparture = 122228,
ScheduledArrival = 122029,
RealTimeStation = {
Id = {
0,
0,
0,
0,
},
StationInfo = {
Platform = "",
},
StationName = "HC-01 1",
TagName = "HC-01 1",
},
RealTimeArrival = 123428,
Index = 0,
ScheduledDeparture = 123229,
Destination = "HC-01 1",
TrainName = "[Local]1123",
},
IsFirst = 1,
},
},
DisplaySettings = {
FontColor = -1,
BackColor = 0,
PlatformWidthNextStop = -1,
TimeDisplay = 1,
TrainNameWidth = 12,
ShowLineColor = 1,
TrainNameWidthNextStop = -1,
ShowTrainMultipleTimes = 1,
TrainText = 0,
PlatformWidth = -1,
},
Glowing = 0,
LastRefreshed = 122113,
YSize = 1,
Filter = "HC-01 1",
Material = {
Name = "create:copycat_base",
},
XSize = 3,
DisplayId = "createrailwaysnavigator:platform/focus",
Item = {},
}
+6 -4
View File
@@ -2,7 +2,7 @@
-- ============================================================================
-- 1. Configuration & Constants
-- ============================================================================
local APP_VERSION_TEXT = "v1.0.36"
local APP_VERSION_TEXT = "v1.0.37"
local CONFIG = {
CLOUD_URL = "ws://stabadmin.fse-media.group",
@@ -2403,8 +2403,8 @@ local function mapTrainStatusReason(statusId)
operational_disruption = "ops",
special_journey = "special",
out_of_service = "oos",
default_delay = "delay",
cancelled = "cancel"
default_delay = "default_delay",
cancelled = "cancelled"
}
return known[tail] or tail
end
@@ -2537,7 +2537,9 @@ function Main.loop()
destination = destination,
eta = tostring(etaSeconds) .. "s",
etaSeconds = etaSeconds,
delay = delayMinutes
delay = delayMinutes,
cancelled = cancelled,
reason = reason
})
end
end
+34 -55
View File
@@ -1,68 +1,47 @@
local target = peripheral.find("create_target")
if not target then
print("Error: Target block not found! Please check if Wired Modem is connected and activated (red ring).")
local reader = peripheral.find("blockReader")
if not reader then
print("Error: Block Reader not found!")
return
end
pcall(target.resize, 80, 10)
-- A helper function to parse the Create station summary line
-- Example input: "1 ?? [Local]1123 HC-02 2"
local function parseTrainLine(line)
-- Format we are parsing:
-- "<Time_Number> <Time_Unit> <Train_Name> <Destination>"
-- Example: "1 ?? [Local]1123 HC-02 2"
-- Example: "现在 ?? [Local]1123 HC-02 2" (assuming "现在" might replace the number and unit)
local timeValue, timeUnit, trainName, destination
-- Try parsing format with a number first (e.g., "1 ?? ...")
timeValue, timeUnit, trainName, destination = string.match(line, "^(%d+)%s+(.-)%s+(%[.-%][^%s]*)%s+(.*)$")
-- If that fails, it might be the "Now" (现在) format which might not have digits at the start
if not trainName then
timeValue, timeUnit, trainName, destination = string.match(line, "^([^%s]+)%s+(.-)%s+(%[.-%][^%s]*)%s+(.*)$")
end
-- Fallback for extremely weird formatting
if not trainName then
timeValue, timeUnit, trainName, destination = string.match(line, "^([^%s]+)%s+(.-)%s+([^%s]+)%s+(.*)$")
end
return {
eta_value = timeValue or "N/A",
eta_unit = timeUnit or "N/A",
trainName = trainName or "N/A",
destination = destination or "N/A",
raw = line
}
end
while true do
term.clear()
term.setCursorPos(1,1)
print("=== Receiving Station Data ===")
print("=== CRN Advanced Display Parser ===")
local lines = target.dump()
local hasData = false
local success, data = pcall(reader.getBlockData)
for i, lineText in pairs(lines) do
if lineText and lineText ~= "" and lineText:match("[%w%?%[]") then
print("--- Line " .. i .. " ---")
print("Raw: " .. lineText)
if success and data and data.TrainStops then
local now = os.epoch("utc") / 50 -- Minecraft ticks (approx)
local parsed = parseTrainLine(lineText)
print(" Train Name : " .. parsed.trainName)
print(" Destination: " .. parsed.destination)
print(" ETA Value : " .. parsed.eta_value)
print(" ETA Unit : " .. parsed.eta_unit)
hasData = true
for i, stop in ipairs(data.TrainStops) do
local st = stop.Station
if st then
local trainName = st.TrainName or "Unknown"
local dest = st.Destination or "Unknown"
-- 时间计算
local scheduledArrival = st.ScheduledArrival or 0
local realArrival = st.RealTimeArrival or 0
-- 计算 ETA (秒)
local etaTicks = realArrival - data.LastRefreshed
local etaSeconds = math.floor(etaTicks / 20)
if etaSeconds < 0 then etaSeconds = 0 end
-- 计算 Delay (分钟)
local delayTicks = realArrival - scheduledArrival
local delayMinutes = math.floor(delayTicks / (20 * 60))
if delayMinutes < 0 then delayMinutes = 0 end
print(string.format("[%d] Train: %s -> %s", i, trainName, dest))
print(string.format(" ETA: %d seconds", etaSeconds))
print(string.format(" Delay: %d minutes", delayMinutes))
print("---------------------------------")
end
end
end
if not hasData then
print("No active trains incoming/departing...")
else
print("Waiting for CRN data...")
end
os.sleep(1)