Meta table not updating

I’m trying to make a simple playlist music system and I keep running into an issue that in the function where outside the __newindex function Playlist[#Playlist+1] = [[SOUND ID]]
doesn’t seem to exist. It returns nil instead of a string.
Please help!
here’s the code:

local SS = game:GetService("SoundService")
local RS = game:GetService("ReplicatedStorage")
local Remotes = RS.Remotes
local Scripts = RS.Scripts
local Promise = require(Scripts.External.Promise)

local DefaultMusic = SS.DefaultMusic
local GlobalMusic = SS.GlobalMusic
GlobalMusic:Play()

local MetaMusic = {}
local Current = 1
local DefaultNumber = #DefaultMusic:GetChildren()
local Playlist = setmetatable({},MetaMusic)


local Playing 

for i,v in pairs (DefaultMusic:GetChildren()) do
	Playlist[i] = v.SoundId
end


function PlayMusic()
	print(Current)
	print(Playlist[Current])
	return Promise.new(function(resolve, reject, onCancel)
        GlobalMusic:Stop()
		GlobalMusic.SoundId = Playlist[Current]
		wait(.1)
		GlobalMusic:Play()
		Remotes.PlayMusic:FireAllClients(Playlist[Current])
		wait(GlobalMusic.TimeLength)
		
		if not Playlist[Current+1] then
			Current = 1
		else	
			Current = Current + 1
		end
		Playing = PlayMusic()
		resolve()
		return
	end)
end


MetaMusic.__newindex = function(tab, index, value)
	print(index)
	if Current <= DefaultNumber then
		Current = index
		Playing:cancel()
		Playing = PlayMusic()
	end
end


Playing = PlayMusic()
wait(5)
Playlist[#Playlist+1] = "rbxassetid://"..5783067628

the wait (5) seconds is obviously to debug
Thank you, have a good day/night :wink:

You’re concenating an string with a number
Playlist[#Playlist+1] = "rbxassetid://"..5783067628


Solution: "rbxassetid://"..tostring(5783067628)

Not the problem dude.

if you’re looking for a way to insert an element into an array (@Unbunnz), use table.insert instead.

...
table.insert(playlist, 'rbxassetid://' .. soundId)

You also will want to use onCancel as well, that’s a big thing.

I don’t advise using the newindex metamethod unless you want things to get messy with proxies and other horrors of that nature. I’d probably just stick with the typical loops.


When you concatenate a string with a non-string Lua automatically attempts to convert the non-string into a string before the concatenation occurs.

As of right now your “__newindex” metamethod isn’t setting any value when it is invoked (by attempting to assign a non-existent key/field of the “Playlist” table a value). Add a call to “rawset” inside the anonymous function assigned to the metakey “__newindex” such that the metamethod assigns the specified value to the specified key in the original table for which the metatable “MetaMusic” is set for.

MetaMusic.__newindex = function(tab, index, value)
	print(index)
	if Current <= DefaultNumber then
		Current = index
		Playing:cancel()
		Playing = PlayMusic()
	end
	rawset(tab, index, value)
end

Here’s a quick example of the above in action.

local tables = {}
local metatables = {}

metatables["__newindex"] = function(data, index, value)
	rawset(data, index, value)
end

setmetatable(tables, metatables)

tables["Key"] = true
print(tables.Key) --true
2 Likes

I’ve decided not to use newindex since it’s kind of pointless

local SS = game:GetService("SoundService")
local RS = game:GetService("ReplicatedStorage")
local Remotes = RS.Remotes
local Scripts = RS.Scripts
local Promise = require(Scripts.External.Promise)

local DefaultMusic = SS.DefaultMusic
local GlobalMusic = SS.GlobalMusic
GlobalMusic:Play()

local endpromise = false
local Current = 1
local DefaultNumber = #DefaultMusic:GetChildren()
local Playlist = {}


local Playing 

for i,v in pairs (DefaultMusic:GetChildren()) do
	table.insert(Playlist,v.SoundId)
end


function PlayMusic()
	print(Current)
	print(Playlist[Current])
	return Promise.new(function(resolve, reject, onCancel)
		onCancel(function()
			print("Cancelled")
			reject()
		end)
		GlobalMusic.SoundId = Playlist[Current]
		wait()
		GlobalMusic:Play()
		Remotes.PlayMusic:FireAllClients(Playlist[Current])
		wait(GlobalMusic.TimeLength)
		if not Playlist[Current+1] then
			Current = 1
		else	
			Current = Current + 1
		end
		Playing = PlayMusic()
	end)
end





Playing = PlayMusic()
wait(5)
table.insert(Playlist, 'rbxassetid://' ..5783067628)
if Current <= DefaultNumber then
	for i = 1, math.floor(#Playlist/2) do
		local j = #Playlist - i + 1
		Playlist[i], Playlist[j] = Playlist[j], Playlist[i]
	end
	Playing:cancel()
	Playing = nil
	Playing = PlayMusic()
end

However now when I do Playing = PlayMusic() on the very bottom
it does the promise function twice