Advertisement
TechManDylan

subcomputersorgan

Jun 9th, 2025 (edited)
449
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.99 KB | None | 0 0
  1. -- startup.lua (sub-computer listener/player)
  2. local json = textutils
  3. local modem = peripheral.find("modem") or error("No modem found!")
  4.  
  5. -- Load instrument name from file
  6. local function load_instrument()
  7.     if not fs.exists("instrument.txt") then
  8.         error("Missing instrument.txt!")
  9.     end
  10.     local file = fs.open("instrument.txt", "r")
  11.     local instrument = file.readLine()
  12.     file.close()
  13.     return instrument
  14. end
  15.  
  16. -- Instrument to port mapping
  17. local instrumentPorts = {
  18.     gedeckt = 1000,
  19.     steam_whistle = 1001,
  20.     diapason = 1002,
  21.     gamba = 1003,
  22.     posaune = 1004,
  23.     subbass = 1005,
  24.     trompette = 1006,
  25.     vox_humana = 1007,
  26.     piccolo = 1008,
  27.     nassard = 1009
  28. }
  29.  
  30. -- Note color map
  31. local noteColors = {
  32.     ["F#"] = colors.blue,
  33.     ["F"]  = colors.purple,
  34.     ["E"]  = colors.cyan,
  35.     ["D#"] = colors.lightGray,
  36.     ["D"]  = colors.gray,
  37.     ["C#"] = colors.pink,
  38.     ["C"]  = colors.lime,
  39.     ["B"]  = colors.yellow,
  40.     ["A#"] = colors.lightBlue,
  41.     ["A"]  = colors.magenta,
  42.     ["G#"] = colors.orange,
  43.     ["G"]  = colors.white,
  44. }
  45.  
  46. -- Valid octave names and side mapping
  47. local validOctaves = { "lowest", "lower", "mid", "high", "highest" }
  48. local octaveSides = {
  49.     lowest  = "right",
  50.     lower   = "left",
  51.     mid     = "front",
  52.     high    = "back",
  53.     highest = "bottom"
  54. }
  55.  
  56. -- Clamp invalid octaves
  57. local function clamp_octave(octave)
  58.     for _, valid in ipairs(validOctaves) do
  59.         if valid == octave then
  60.             return octave
  61.         end
  62.     end
  63.     print("[WARN] Invalid octave: " .. tostring(octave) .. ", clamping to 'mid'")
  64.     return "mid"
  65. end
  66.  
  67. -- Bundled redstone note player
  68. function play_notes(notes)
  69.     print("[PLAYBACK] Playing notes via bundled redstone...")
  70.     for _, note in ipairs(notes) do
  71.         local color = noteColors[note.note]
  72.         local side = octaveSides[clamp_octave(note.octave)]
  73.         local delay = tonumber(note.start) or 0
  74.         local duration = tonumber(note.duration) or 0.25
  75.  
  76.         if color and side then
  77.             sleep(delay)
  78.             redstone.setBundledOutput(side, color)
  79.             sleep(duration)
  80.             redstone.setBundledOutput(side, 0)
  81.         else
  82.             print("[WARN] Skipping invalid note: " .. tostring(note.note))
  83.         end
  84.     end
  85. end
  86.  
  87. -- Init
  88. local instrument = load_instrument()
  89. local port = instrumentPorts[instrument]
  90. if not port then error("Invalid instrument: " .. tostring(instrument)) end
  91.  
  92. modem.open(port)
  93. print("[LISTENING] " .. instrument .. " on port " .. port)
  94.  
  95. if not fs.exists("songs") then fs.makeDir("songs") end
  96.  
  97. -- Event loop
  98. while true do
  99.     local event, side, sender, replyPort, message, distance = os.pullEvent("modem_message")
  100.     if type(message) == "table" and message.type then
  101.         if message.type == "song_data" and message.instrument == instrument then
  102.             local path = "songs/" .. message.title .. ".json"
  103.             local file = fs.open(path, "w")
  104.             file.write(json.serialize(message))
  105.             file.close()
  106.             print("[RECEIVED] Saved song: " .. message.title)
  107.  
  108.         elseif message.type == "play_request" and message.title then
  109.             local path = "songs/" .. message.title .. ".json"
  110.             if fs.exists(path) then
  111.                 local file = fs.open(path, "r")
  112.                 local songData = json.unserialize(file.readAll())
  113.                 file.close()
  114.  
  115.                 if songData.instrument == instrument then
  116.                     local now = os.time()
  117.                     local start_at = message.start_at or now
  118.                     local wait = start_at - now
  119.                     if wait > 0 then
  120.                         print(string.format("[SYNC] Waiting %.2f seconds to start...", wait))
  121.                         sleep(wait)
  122.                     end
  123.                     play_notes(songData.notes)
  124.                 end
  125.             else
  126.                 print("[WARN] Song not found: " .. message.title)
  127.             end
  128.         end
  129.     end
  130. end
  131.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement