MysticT

NBS API

Jul 3rd, 2012
1,272
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.25 KB | None | 0 0
  1. -- NoteBlock Song API
  2. -- by MysticT
  3.  
  4. -- yield to avoid error
  5. local function yield()
  6.     os.queueEvent("fake")
  7.     os.pullEvent("fake")
  8. end
  9.  
  10. -- read short integer (16-bit) from file
  11. local function readShort(file)
  12.     return file.read() + file.read() * 256
  13. end
  14.  
  15. -- read integer (32-bit) from file
  16. local function readInt(file)
  17.     return file.read() + file.read() * 256 + file.read() * 65536 + file.read() * 16777216
  18. end
  19.  
  20. -- read string from file
  21. local function readString(file)
  22.     local s = ""
  23.     local len = readInt(file)
  24.     for i = 1, len do
  25.         local c = file.read()
  26.         if not c then
  27.             break
  28.         end
  29.         s = s..string.char(c)
  30.     end
  31.     return s
  32. end
  33.  
  34. -- read nbs file header
  35. local function readNBSHeader(file)
  36.     local header = {}
  37.     header.lenght = readShort(file)
  38.     header.height = readShort(file)
  39.     header.name = readString(file)
  40.     if header.name == "" then
  41.         header.name = "Untitled"
  42.     end
  43.     header.author = readString(file)
  44.     if header.author == "" then
  45.         header.author = "Unknown"
  46.     end
  47.     header.original_author = readString(file)
  48.     if header.original_author == "" then
  49.         header.original_author = "Unknown"
  50.     end
  51.     header.description = readString(file)
  52.     header.tempo = readShort(file) / 100
  53.     header.autosave = file.read()
  54.     header.autosave_duration = file.read()
  55.     header.time_signature = file.read()
  56.     header.minutes_spent = readInt(file)
  57.     header.left_clicks = readInt(file)
  58.     header.right_clicks = readInt(file)
  59.     header.blocks_added = readInt(file)
  60.     header.blocks_removed = readInt(file)
  61.     header.filename = readString(file)
  62.     return header
  63. end
  64.  
  65. -- jump to the next tick in the file
  66. local function nextTick(file, tSong)
  67.     local jump = readShort(file)
  68.     for i = 1, jump - 1 do
  69.         table.insert(tSong, {})
  70.     end
  71.     return jump > 0
  72. end
  73.  
  74. -- read the notes in a tick
  75. local function readTick(file)
  76.     local t = {}
  77.     local jump = readShort(file)
  78.     while jump > 0 do
  79.         local instrument = file.read() + 1
  80.         if instrument > 5 then
  81.             return nil, "Can't convert custom instruments"
  82.         end
  83.         local note = file.read() - 33
  84.         if note < 0 or note > 24 then
  85.             return nil, "Notes must be in Minecraft's 2 octaves"
  86.         end
  87.         if not t[instrument] then
  88.             t[instrument] = {}
  89.         end
  90.         table.insert(t[instrument], note)
  91.         jump = readShort(file)
  92.     end
  93.     return t
  94. end
  95.  
  96. -- API functions
  97.  
  98. -- save a converted song to a file
  99. function saveSong(tSong, sPath)
  100.     local file = fs.open(sPath, "w")
  101.     if file then
  102.         file.write(textutils.serialize(tSong))
  103.         file.close()
  104.         return true
  105.     end
  106.     return false, "Error opening file "..sPath
  107. end
  108.  
  109. -- load and convert an .nbs file and save it
  110. function load(sPath, bVerbose)
  111.     local file = fs.open(sPath, "rb")
  112.     if file then
  113.         if bVerbose then
  114.             print("Reading header...")
  115.         end
  116.         local tSong = {}
  117.         local header = readNBSHeader(file)
  118.         tSong.name = header.name
  119.         tSong.author = header.author
  120.         tSong.original_author = header.original_author
  121.         tSong.lenght = header.lenght / header.tempo
  122.         tSong.delay = 1 / header.tempo
  123.         if bVerbose then
  124.             print("Reading ticks...")
  125.         end
  126.         while nextTick(file, tSong) do
  127.             local tick, err = readTick(file, tSong)
  128.             if tick then
  129.                 table.insert(tSong, tick)
  130.             else
  131.                 file.close()
  132.                 return nil, err
  133.             end
  134.             yield()
  135.         end
  136.         file.close()
  137.         return tSong
  138.     end
  139.     return nil, "Error opening file "..sPath
  140. end
Advertisement
Add Comment
Please, Sign In to add comment