How would I intergrate a custom song into this robust music script?

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

2 Likes

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.

1 Like

Thank you! Sorry for the late response. This works perfectly!