GRxRedZero

Untitled

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