Hey, I’m rivertropic and I’m looking for a way to add a custom song feature to my music system, but I’m struggling to find a way to add this.
A custom song feature would include a way for players to pay x robux and then their song would be played next.
Some issues I could see with this:
If two people request a song, wouldn’t this cancel out the other player’s song? - Fix: Create a queue specifically for custom songs.
Troll songs - Fix: Make a way for players to vote skip a song.
Music Script ( Server )
local function Shuffle()
local MusicArray = sounds:GetChildren()
for i = 1, #MusicArray do
local index = math.random(1, #MusicArray)
local Song = MusicArray[index]
local str = tostring(Song.SoundId)
local newID, replaced = string.gsub(str, "rbxassetid://", "")
local asset = game:GetService("MarketplaceService"):GetProductInfo(tonumber(newID))
local asset_name = asset.Name
mainSpeaker.SoundId = Song.SoundId
mainSpeaker:Play()
mainSpeaker.PlaybackSpeed = Song.PlaybackSpeed
mainSpeaker.TimePosition = 0
if asset_name == "(Removed for copyright)" then
mainSpeaker.TimePosition = mainSpeaker.TimeLength
table.remove(MusicArray, index)
end
if imageenabled == false then
tosendimageid = "Disabled"
else
tosendimageid = Song:WaitForChild("ImageID").Value
end
wait(0.1)
if mainSpeaker.TimePosition == 0 then
Skip()
end
Event:FireAllClients(Song:WaitForChild("Name").Value,Song:WaitForChild("Artist").Value,tosendimageid)
Text.Value = Song:WaitForChild("Name").Value.." by "..Song:WaitForChild("Artist").Value
mainSpeaker.Ended:Wait()
table.remove(MusicArray, index)
end
end
wait(5)
while wait() do
Shuffle()
end
If anyone has any ideas or soloutions let me know in the replies
I think the issue is with your music system. Your music system should probably check to see if there is something in the music queue.
We can implement a queue data-structure, with 3 methods. The first being push, which adds an element to the end of the queue. The second one being pop, which takes out the last element of the queue. The last one being peek, which returns the last element of the queue without removing it.
local Queue = {}
Queue.__index = Queue
function Queue:push(data)
self.size += 1
self.data[self.size] = data
end
function Queue:pop()
self.size -= 1
return self.data[1]
end
function Queue:peek()
return self.data[1]
end
function Queue.new(initialData)
local self = setmetatable({
data = initialData or {},
size = initialData and #initialData or 0
})
return self
end
return Queue
Once we have our queue data-structure, we can implement it in our music system. We want our music system to be able to check if there is music in the queue. If there is, then we will take that instead of the music we had planned to play.
local requestQueue = Queue.new()
local function Shuffle()
local MusicArray = sounds:GetChildren()
for i = 1, #MusicArray do
local Song
if requestQueue.size > 0 then
Song = requestQueue:pop()
else
local index = math.random(1, #MusicArray)
Song = MusicArray[index]
table.remove(MusicArray, index)
end
local str = tostring(Song.SoundId)
local newID, replaced = string.gsub(str, "rbxassetid://", "")
local asset = game:GetService("MarketplaceService"):GetProductInfo(tonumber(newID))
local asset_name = asset.Name
mainSpeaker.SoundId = Song.SoundId
mainSpeaker:Play()
mainSpeaker.PlaybackSpeed = Song.PlaybackSpeed
mainSpeaker.TimePosition = 0
if asset_name == "(Removed for copyright)" then
mainSpeaker.TimePosition = mainSpeaker.TimeLength
table.remove(MusicArray, index)
end
if imageenabled == false then
tosendimageid = "Disabled"
else
tosendimageid = Song:WaitForChild("ImageID").Value
end
wait(0.1)
if mainSpeaker.TimePosition == 0 then
Skip()
end
Event:FireAllClients(Song:WaitForChild("Name").Value,Song:WaitForChild("Artist").Value,tosendimageid)
Text.Value = Song:WaitForChild("Name").Value.." by "..Song:WaitForChild("Artist").Value
mainSpeaker.Ended:Wait()
end
end
wait(5)
while wait() do
Shuffle()
end
If you wanted to, you could also use a queue for the normal songs, by initializing it with your shuffled data.