BEFORE GETTING THE MODULE
Ensure you have stravant’s GoodSignal Module in your game set up to add it into the Module!
And add it at the start of the ProxyTable Module like this:
local GoodSignal = require(game.ReplicatedStorage.GoodSignal)
Because this module uses GoodSignal, that means you can safely yield inside connection.
USAGE EXAMPLE
local ProxyTable = require(game.ReplicatedStorage.Libraries.ProxyTable)
-- create the proxyTable
local Values = {
Money = 0,
Health = 100,
}
local PlayerData = ProxyTable.new(Values)
PlayerData:Changed('Money'):Connect(function()
print(PlayerData.Money)
end)
PlayerData:Changed('Health'):Connect(function()
if PlayerData.Health < 1 then
print('Player has died!')
end
end)
PlayerData.Money = 50 -- will print 50
PlayerData.Money = 10 -- will print 10
PlayerData.Health -= 100 -- will print Player has died!
MISC
You don’t have to put already created table to create ProxyTable, you can leave arguments blank.
In times where you don’t want to fire an connection when variable changes, use ProxyTable:GetRaw() method and use the table you get.
It supports metatables! So now you can create objects that you can listen for changes!
You just need to wrap self like this before returning it:
local ProxyTable = require(game.ReplicatedStorage.Libraries.ProxyTable)
local Object = {}
Object.__index = Object
function Object.new()
local self = setmetatable({}, Object)
self.Variable = 5
return ProxyTable.new(self)
end
function Object:Add(amount)
self.Variable += amount
end
local CreatedObject = Object.new()
CreatedObject:Changed('Variable'):Connect(function()
print('Variable has changed to', tostring(CreatedObject.Variable))
end)
CreatedObject:Add(10) -- will print Variable has changed to 15
You can also make ProxyTable give you old variable automatically by giving a second argument when creating it:
local ProxyTable = require(game.ReplicatedStorage.Libraries.ProxyTable)
local Table = ProxyTable.new(nil, true)
Table.Stuff = 10
Table:Changed('Stuff'):Connect(function(oldVariable)
print('Stuff changed from', tostring(oldVariable), 'to', tostring(Table.Stuff))
end)
Table.Stuff += 5 -- will print Stuff changed from 10 to 15
Table.Stuff += 5 -- will print Stuff changed from 15 to 20
Table.Stuff += 5 -- will print Stuff changed from 20 to 25
Table.Stuff += 5 -- will print Stuff changed from 25 to 30
THE MODULE
-- Created by ArtemVoronin0 05/09/2024
-- ProxyTable, an easy module that let you watch over changed values in table.
local GoodSignal -- require good signal implementation there!
export type ProxyTable = {
Changed : (self : ProxyTable, index : any) -> nil, -- GoodSignal.Signal (change to it if you have own Signal type)
GetRaw : (self : ProxyTable) -> {[any] : any},
}
local ProxyTable = {}
ProxyTable.__index = ProxyTable
local signalMeta = {
__index = function(T, K)
T[K] = GoodSignal.new()
return T[K]
end,
}
local proxyMeta = {
__index = function(T, K : any)
if not T.__proxy[K] then return ProxyTable[K] end
return T.__proxy[K]
end,
__newindex = function(T, K : any, V : any)
if V == T.__proxy[K] then return end
T.__proxy[K] = V
if rawget(T.__signals, K) then
T.__signals[K]:Fire()
end
end,
__iter = function(T)
return next, T.__proxy
end,
__len = function(T)
return #T.__proxy
end,
}
local proxyMetaWithSave = table.clone(proxyMeta)
proxyMetaWithSave.__newindex = function(T, K : any, V : any)
if V == T.__proxy[K] then return end
local oldValue : any = T[K]
T.__proxy[K] = V
if rawget(T.__signals, K) then
T.__signals[K]:Fire(oldValue)
end
end
function ProxyTable.new(t : {[any] : any}?, passOldValue : boolean?) : ProxyTable
if not t then t = {} end
local __signals = setmetatable({}, signalMeta)
local __proxy = t
local self = setmetatable({__signals = __signals, __proxy = __proxy}, if passOldValue then proxyMetaWithSave else proxyMeta)
return self
end
function ProxyTable:Changed(index : any)
return self.__signals[index]
end
function ProxyTable:GetRaw()
return self.__proxy
end
return ProxyTable