fyrkantis

StationPA

Feb 20th, 2025 (edited)
1,344
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local LONG_PING = 5
  2. local MEDIUM_PING = 1
  3. local SHORT_PING = 0.
  4.  
  5. local RANDOM_MIN = 60
  6. local RANDOM_MAX = 120
  7.  
  8. local AUDIO_PATH = "audio/transit/"
  9.  
  10. local VOLUME = 2.0
  11. local inst1 = "pling"
  12. local inst2 = "iron_xylophone"
  13. local inst3 = "bass"
  14.  
  15. local JINGLES = {
  16.     arrival = {
  17.         {duration=0.5, notes={{inst1, VOLUME, 20}, {inst2, VOLUME, 20}, {inst3, VOLUME, 4}}},
  18.         {duration=0.5, notes={{inst1, VOLUME, 16}, {inst2, VOLUME, 16}, {inst3, VOLUME, 8}}},
  19.         {duration=0.5, notes={{inst1, VOLUME, 18}, {inst2, VOLUME, 18}, {inst3, VOLUME, 6}}},
  20.         {duration=0.5, notes={{inst1, VOLUME, 11}, {inst2, VOLUME, 11}, {inst3, VOLUME, 11}}}
  21.     },
  22.     random = {
  23.         {duration=0.4, notes={{inst1, VOLUME, 4}, {inst2, VOLUME, 4}, {inst3, VOLUME, 16}}},
  24.         {duration=0.4, notes={{inst1, VOLUME, 8}, {inst2, VOLUME, 8}, {inst3, VOLUME, 11}}},
  25.         {duration=0.4, notes={{inst1, VOLUME, 11}, {inst2, VOLUME, 11}, {inst3, VOLUME, 8}}}
  26.     }
  27. }
  28.  
  29. function splitWord(target, word)
  30.     local i, j = string.find(target, word)
  31.     if i == nil then return target end
  32.     return string.sub(target, 1, i - 1), string.sub(target, j + 1, -1)
  33. end
  34. function getName(name)
  35.     return string.gfind(string.gsub(name, "%s%d", ""), "[%a%s%p]+")()
  36. end
  37. function getFilename(name)
  38.     return string.gsub(getName(name), "%s", "_")
  39. end
  40. function getNumber(name)
  41.     return tonumber(string.gfind(name, "%d+$")())
  42. end
  43.  
  44. local decoder = require("cc.audio.dfpwm").make_decoder()
  45. local speaker = peripheral.find("speaker")
  46. local stations = {}
  47. for _, name in pairs(peripheral.getNames()) do
  48.     pType = peripheral.getType(name)
  49.     if pType == "Create_Station" then
  50.         local station = peripheral.wrap(name)
  51.         station.fullName = station.getStationName()
  52.         station.name=getName(station.fullName)
  53.         station.platform=getNumber(station.fullName)
  54.         station.present=station.isTrainPresent()
  55.         table.insert(stations, station)
  56.     end
  57. end
  58.  
  59. shell.run("clear")
  60.  
  61. local pingTimer = os.startTimer(SHORT_PING)
  62. local randomTimer = os.startTimer(math.random(RANDOM_MIN, RANDOM_MAX))
  63. local soundTasks = {}
  64. function addSoundTasks(newTasks)
  65.     for i=1, #newTasks do
  66.         if newTasks[i].filename ~= nil then
  67.             for chunk in io.lines(AUDIO_PATH..newTasks[i].filename, 16*1024) do
  68.                 soundTasks[#soundTasks+1] = {buffer=chunk}
  69.             end
  70.         else
  71.             soundTasks[#soundTasks+1] = newTasks[i]
  72.         end
  73.     end
  74. end
  75. local soundTaskIndex = 1
  76. local soundTaskTimer = nil
  77. local soundPlaying = false
  78. while true do
  79.     local event, id = os.pullEvent()
  80.     local startSound = false
  81.     if event == "timer" and id == pingTimer then
  82.         local newTime = LONG_PING
  83.         for i, station in pairs(stations) do
  84.             if station.isTrainPresent() then
  85.                 if not station.present then
  86.                     stations[i].present = true
  87.                     newTime = math.min(newTime, MEDIUM_PING)
  88.                     local name = station.getTrainName()
  89.                     write(name)
  90.                    
  91.                     if not soundPlaying then
  92.                         addSoundTasks(JINGLES.arrival)
  93.                     end
  94.                    
  95.                     local lineFilename = "lines/"..getFilename(name)..".dfpwm"
  96.                     if fs.exists(AUDIO_PATH..lineFilename) then
  97.                         addSoundTasks({{filename=lineFilename}})
  98.                     else
  99.                         addSoundTasks({{filename="Train.dfpwm"}})
  100.                     end
  101.                     if station.hasSchedule() then
  102.                         local schedule = station.getSchedule()
  103.                         local entries = schedule.entries
  104.                         local progress = schedule.progress -- BUG: This value is often incorrect.
  105.                         if progress == nil then progress = 1 end
  106.                         for i=1, #entries do
  107.                             if entries[i].instruction.id == "create:destination" and entries[i].instruction.data.text == station.fullName then
  108.                                 progress = i
  109.                                 break
  110.                             end
  111.                         end
  112.                         local stations = {}
  113.                         local label = nil
  114.                         local index = math.mod(progress, #entries) + 1
  115.                         while index ~= progress do
  116.                             --write(index..": ")
  117.                             local entry = entries[index]
  118.                             if entry.instruction.id == "create:destination" then
  119.                                 stations[#stations + 1] = entry.instruction.data.text
  120.                                 --print(stations[#stations])
  121.                             elseif entry.instruction.id == "create:rename" then
  122.                                 label = entry.instruction.data.text
  123.                                 --print("-> "..label)
  124.                             end
  125.                             index = math.mod(index, #entries) + 1
  126.                         end
  127.                        
  128.                         if label ~= nil then
  129.                             write(" to "..label)
  130.                             local name, andName = splitWord(label, " and ")
  131.                             local isVia = false
  132.                             if andName == nil then
  133.                                 isVia = true
  134.                                 name, andName = splitWord(label, " via ")
  135.                             end
  136.                             addSoundTasks({
  137.                                 {filename="To.dfpwm"},
  138.                                 {duration=0.4},
  139.                                 {filename="stations/"..getFilename(name)..".dfpwm"}
  140.                             })
  141.                             if andName ~= nil then
  142.                                 addSoundTasks({{duration=0.2}})
  143.                                 if isVia then addSoundTasks({{filename="Via.dfpwm"}})
  144.                                 else addSoundTasks({{filename="And.dfpwm"}}) end
  145.                                 addSoundTasks({{duration=0.2}, {filename="stations/"..getFilename(andName)..".dfpwm"}})
  146.                             end
  147.                         end
  148.                     end
  149.                     addSoundTasks({{filename="ArrivesNowOnTrack.dfpwm"}})
  150.                     addSoundTasks({
  151.                         {duration=0.2},
  152.                         {filename="numbers/"..station.platform..".dfpwm"},
  153.                         {duration=1.0}
  154.                     })
  155.                     startSound = true
  156.                     randomTimer = os.startTimer(math.random(RANDOM_MIN, RANDOM_MAX))
  157.                    
  158.                     print(" arrived on platform "..station.platform)
  159.                 end
  160.             else
  161.                 stations[i].present = false
  162.                 if station.isTrainEnroute() then
  163.                     newTime = math.min(newTime, MEDIUM_PING)
  164.                 elseif station.isTrainImminent() then
  165.                     newTime = math.min(newTime, SHORT_PING)
  166.                     randomTimer = nil
  167.                 end
  168.             end
  169.         end
  170.         pingTimer = os.startTimer(newTime)
  171.     end
  172.     if event == "timer" and id == randomTimer then
  173.         local filenames = fs.list(AUDIO_PATH.."random")
  174.         local randomFile = filenames[math.random(#filenames)]
  175.         print("Playing announcment \""..randomFile.."\"...")
  176.         addSoundTasks(JINGLES.random)
  177.         addSoundTasks({{filename="random/"..randomFile}})
  178.         startSound = true
  179.         randomTimer = os.startTimer(math.random(RANDOM_MIN, RANDOM_MAX))
  180.     end
  181.     if (event == "timer" and id == soundTaskTimer) or (event == "speaker_audio_empty") or (startSound and not soundPlaying) then
  182.         soundPlaying = true
  183.         local soundTask = soundTasks[soundTaskIndex]
  184.         if soundTask == nil then
  185.             soundPlaying = false
  186.             soundTasks = {}
  187.             soundTaskIndex = 1
  188.         else
  189.             if soundTask.notes ~= nil then
  190.                 for _, note in pairs(soundTask.notes) do
  191.                     speaker.playNote(unpack(note))
  192.                 end
  193.             elseif soundTask.buffer ~= nil then
  194.                 speaker.playAudio(decoder(soundTask.buffer), VOLUME)
  195.             end
  196.             if soundTask.duration ~= nil then
  197.                 soundTaskTimer = os.startTimer(soundTask.duration)
  198.             end
  199.             soundTaskIndex = soundTaskIndex + 1
  200.         end
  201.     end
  202. end
Advertisement
Add Comment
Please, Sign In to add comment