Is it possible to listen to changes in a table using a Metamethod like __set?
local SoundSettings = {
["MusicVolume"] = 1,
["SoundVolume"] = 1,
["SoundOn"] = true,
["MusicOn"] = true,
}
local MetaTable_Events = {
__set = function(self,i,v)
print("Index attempted to be set",self,i,v)
rawset(self,i,v)
end
}
setmetatable(SoundSettings,MetaTable_Events)
print(SoundSettings[1])
SoundSettings[1] = 5
print(SoundSettings[1])
-- Prints:
-->> 1
-->> Index attempted to be set table: 0xb4054f3b704cf479 1 5
-->> 5
I’m trying to create intrinsic events for pre-defined index changes using Metamethods. Like if a player adjusts their volume it triggers the metamethod event and calls a function from elsewhere.
Would love some pointers as I am very new to Metatables / Metamethods!
You’ll want to create an empty proxy table which will have a metatable that points to the main table. You can simply set __index of the metatable to the main table. From there you can set the __newindex metamethod to whatever function you’d like. That way, you can just use the proxy table as if it were the main table, just with a mock “__set” metamethod
local mainTable = { -- Your main table
["MusicVolume"] = 1,
["SoundVolume"] = 1,
["SoundOn"] = true,
["MusicOn"] = true,
}
local soundSettings = {} -- This will be our proxy table
local metatable = {
__index = mainTable, -- Will point to the main table when indexed
__newindex = function(self, i, v) -- This is basically your idea of a "__set" metamethod. Just note that you will have to modify this function if you want it to fire ONLY if the index already exists in our main table.
print("Attempted to set value", self, i, v)
end
}
setmetatable(soundSettings, metatable) -- Now we set the metatable of the proxy table to our metatable.
After modifying a few things from what you provided I came up with this and it seems to work soo far!
local SoundSettings = { -- Actual table
["MusicVolume"] = 1,
["SoundVolume"] = 1,
["SoundOn"] = true,
["MusicOn"] = true,
}
local Proxy_SoundSettings = {} -- Proxy table
local metatable = {
__index = SoundSettings, -- Will point to the main table when indexed
__newindex = function(self, i, v) -- This is basically your idea of a "__set" metamethod
warn("Attempted to set value", self, i, v)
rawset(self,i,v)
end
}
setmetatable(Proxy_SoundSettings, metatable) -- Now we set the metatable of the proxy table to our metatable.
warn(Proxy_SoundSettings.MusicVolume)
Proxy_SoundSettings.MusicVolume = 5
warn(Proxy_SoundSettings.MusicVolume)
-- Prints:
-->> 1
-->> Attempted to set value table: 0xe2eb19ef461e7ba8 MusicVolume 5
-->> 5
Any thoughts / criticisms on the modified version? Perhaps improvements I could make with it?