Blackhome

Notes

Oct 26th, 2025
1,677
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.36 KB | Gaming | 0 0
  1. -- Musikcomputer.lua
  2. -- CC:Tweaked Musiksystem (mit BPM, Filterung & synchronisiertem Start)
  3. -- Version 2.0
  4.  
  5. local CONFIG_FILE = "config.txt"
  6. local CONTROL_FILE = "disk/control.txt"
  7. local SONG_PATH_PREFIX = "disk/song_"
  8. local instrumentConfig = {}
  9.  
  10. -- -----------------------------
  11. -- Hilfsfunktionen
  12. -- -----------------------------
  13. local function fileExists(path)
  14.     local f = fs.open(path, "r")
  15.     if f then f.close() return true else return false end
  16. end
  17.  
  18. local function saveConfig(config)
  19.     local f = fs.open(CONFIG_FILE, "w")
  20.     for k, v in pairs(config) do
  21.         f.writeLine(k .. "=" .. v)
  22.     end
  23.     f.close()
  24. end
  25.  
  26. local function loadConfig()
  27.     local config = {}
  28.     local f = fs.open(CONFIG_FILE, "r")
  29.     if not f then return nil end
  30.     for line in f.readLine do
  31.         local key, value = line:match("^(.-)=(.*)$")
  32.         if key and value then
  33.             config[key] = value
  34.         end
  35.     end
  36.     f.close()
  37.     return config
  38. end
  39.  
  40. -- -----------------------------
  41. -- Initialisierung
  42. -- -----------------------------
  43. local function initialize()
  44.     print("Keine Konfiguration gefunden. Initialisierung startet...")
  45.     local config = {}
  46.  
  47.     write("Instrumentname: ")
  48.     config.name = read()
  49.  
  50.     local sides = {"front", "right", "back", "left"}
  51.     for _, side in ipairs(sides) do
  52.         write("Ton an Seite '" .. side .. "' (z.B. C#2 oder none): ")
  53.         config[side] = read()
  54.     end
  55.  
  56.     saveConfig(config)
  57.     print("Konfiguration gespeichert.")
  58.     return config
  59. end
  60.  
  61. -- -----------------------------
  62. -- Lied laden (inkl. BPM)
  63. -- -----------------------------
  64. local function loadSong(instrumentName)
  65.     local songPath = SONG_PATH_PREFIX .. instrumentName .. ".txt"
  66.     if not fs.exists(songPath) then
  67.         error("Songdatei nicht gefunden: " .. songPath)
  68.     end
  69.  
  70.     local f = fs.open(songPath, "r")
  71.     local bpm = 120
  72.     local notes = {}
  73.  
  74.     while true do
  75.         local line = f.readLine()
  76.         if not line then break end
  77.  
  78.         if line:match("^BPM=") then
  79.             bpm = tonumber(line:match("BPM=(%d+)"))
  80.         elseif not (line:match("^#") or line == "") then
  81.             local tonePart, length = line:match("^(.-)|(%d+)$")
  82.             if tonePart and length then
  83.                 local tones = {}
  84.                 for tone in string.gmatch(tonePart, "([^,]+)") do
  85.                     table.insert(tones, tone)
  86.                 end
  87.                 table.insert(notes, {tones = tones, length = tonumber(length)})
  88.             end
  89.         end
  90.     end
  91.     f.close()
  92.     return bpm, notes
  93. end
  94.  
  95. -- -----------------------------
  96. -- Filter nach bespielbaren Noten
  97. -- -----------------------------
  98. local function filterSong(song, config, bpm)
  99.     local playable = {}
  100.     local sideNotes = {}
  101.     for _, side in ipairs({"front", "right", "back", "left"}) do
  102.         if config[side] and config[side] ~= "none" then
  103.             sideNotes[config[side]] = side
  104.         end
  105.     end
  106.  
  107.     local function noteLengthToSeconds(noteValue, bpm)
  108.         return (4 / noteValue) * (60 / bpm)
  109.     end
  110.  
  111.     for _, entry in ipairs(song) do
  112.         local validTones = {}
  113.         for _, tone in ipairs(entry.tones) do
  114.             if sideNotes[tone] then
  115.                 table.insert(validTones, tone)
  116.             end
  117.         end
  118.  
  119.         if #validTones > 0 then
  120.             table.insert(playable, {
  121.                 tones = validTones,
  122.                 length = noteLengthToSeconds(entry.length, bpm)
  123.             })
  124.         else
  125.             table.insert(playable, {
  126.                 tones = {"REST"},
  127.                 length = noteLengthToSeconds(entry.length, bpm)
  128.             })
  129.         end
  130.     end
  131.  
  132.     return playable, sideNotes
  133. end
  134.  
  135. -- -----------------------------
  136. -- Steuerdatei lesen
  137. -- -----------------------------
  138. local function readControlFile()
  139.     if not fileExists(CONTROL_FILE) then return false, 0 end
  140.  
  141.     local f = fs.open(CONTROL_FILE, "r")
  142.     local play = false
  143.     local startTime = 0
  144.  
  145.     while true do
  146.         local line = f.readLine()
  147.         if not line then break end
  148.         local key, val = line:match("^(.-)=(.*)$")
  149.         if key == "play" then
  150.             play = (val == "true")
  151.         elseif key == "startTime" then
  152.             startTime = tonumber(val)
  153.         end
  154.     end
  155.     f.close()
  156.     return play, startTime
  157. end
  158.  
  159. -- -----------------------------
  160. -- Song abspielen
  161. -- -----------------------------
  162. local function playSong(filtered, sideNotes)
  163.     for _, entry in ipairs(filtered) do
  164.         if entry.tones[1] == "REST" then
  165.             sleep(entry.length)
  166.         else
  167.             -- Redstone aktivieren
  168.             for _, tone in ipairs(entry.tones) do
  169.                 local side = sideNotes[tone]
  170.                 if side then redstone.setOutput(side, true) end
  171.             end
  172.  
  173.             sleep(0.001)
  174.  
  175.             -- Redstone deaktivieren
  176.             for _, tone in ipairs(entry.tones) do
  177.                 local side = sideNotes[tone]
  178.                 if side then redstone.setOutput(side, false) end
  179.             end
  180.  
  181.             -- Rest der Notenlänge warten
  182.             local remaining = entry.length - 0.001
  183.             if remaining > 0 then sleep(remaining) end
  184.         end
  185.     end
  186. end
  187.  
  188. -- -----------------------------
  189. -- Hauptprogramm
  190. -- -----------------------------
  191. if fileExists(CONFIG_FILE) then
  192.     instrumentConfig = loadConfig()
  193.     print("Konfiguration geladen für Instrument: " .. instrumentConfig.name)
  194. else
  195.     instrumentConfig = initialize()
  196. end
  197.  
  198. print("Lade Song von Disk...")
  199. local bpm, song = loadSong(instrumentConfig.name)
  200. print("Song geladen (" .. #song .. " Schritte) mit BPM = " .. bpm)
  201.  
  202. print("Filtere Song für bespielbare Noten...")
  203. local filtered, sideNotes = filterSong(song, instrumentConfig, bpm)
  204. print("Gefilterter Song enthält " .. #filtered .. " Einträge.")
  205.  
  206. print("Warte auf Startsignal...")
  207.  
  208. while true do
  209.     local play, startTime = readControlFile()
  210.     if play then
  211.         local current = os.epoch("utc")
  212.         local diff = startTime - current
  213.         if diff > 0 then
  214.             print("Starte Song in " .. string.format("%.2f", diff / 1000) .. " Sekunden...")
  215.             sleep(diff / 1000)
  216.         end
  217.  
  218.         print("Starte Abspielen!")
  219.         playSong(filtered, sideNotes)
  220.         print("Song beendet.")
  221.         break
  222.     end
  223.  
  224.     sleep(0.2) -- Systemschonende Abfrage
  225. end
  226.  
Advertisement
Add Comment
Please, Sign In to add comment