I’ve made a module which allows you to track when a property in a table is changed using Shadow tables
What is a Shadow table ?
A shadow table, also known as a proxy table simply put is a table that “acts” as it holds Data when in reality its “empty”. It basically uses metamethods to get the data that it doesn’t hold.
– Note this is a really plain and simple explanation, I recommend searching them up to get more in-depth explanation.
Additional info :
Whenever a new value is assigned a new thread is created.
How to use :
local ShadowTable = require(script:WaitForChild("ShadowTable"))
local Data = ShadowTable.New({Gold = 0})
Data.Changed:Connect(function(Index, Value)
print(Index, Value)
end)
Data.Gold = 1235
In this case we change the value to 1235 and it will print out Gold, 1235.
Download the module down below, Thanks for reading
Sure, Currently only Table.Changed is possible, will add Table.Property.Changed sooner or later, Pastebin link: https://pastebin.com/gnUZhMhB, Feel free to share ; )
Why do you go for a non-Bindable event approach rather than with Bindable events? They’ll be easier to use and cover their entire set of functions and events.
By going with that approach, you will have no access to :Wait() or :Disconnect()
I think according to your code as well that it will set only one function when connecting due to overriding .Connection
What do you mean by serializing all data types? Though, you should add those extra functions that a Bindable event normally if you can easily mimic it.
local be = script.Parent
-- Define a simple function to connect
-- to the custom event
local function onEvent(...)
print(...)
end
be.Event:Connect(onEvent)
-- These values CAN be sent when firing BindableEvents
be:Fire() -- nil
be:Fire(25) -- numbers
be:Fire("hello") -- strings
be:Fire(true) -- booleans
be:Fire("buy", 25) -- multiple values are OK
be:Fire{1, 2, 3} -- tables as arrays with no gaps
-- note the curly braces
be:Fire{ -- tables with string keys only
hello = "world";
goodbye = "world";
}
be:Fire{ -- tables with string keys
point = {1, 2}; -- whose values are also valid
point2 = {3, 4};
}
be:Fire{ -- tables as arrays
{1, 2, 3}; -- whose values also are valid
{hello = "world";};
}
-- These are some values you CANNOT send to/from BindableFunctions
be:Fire{1, nil, 3} -- tables as arrays cannot have nil gaps
be:Fire{
[{}] = "hello"; -- table keys can only be numbers OR strings
}
be:Fire{ -- tables keys cannot be BOTH numbers AND strings
[1] = "apple";
hello = "world";
}
Never knew about this guess I need to keep in touch with API stuff, thank you for the clarification. For my use, I never have to use mixed tables anyways so Bindable events would always work for my use but now I know to keep this in mind.
I did minimal testing on this, but I created a version of this module with a :GetPropertyChangedSignal implementation with a bit of a different coding style too:
local ProxyTable = require(path.to.ProxyTable)
local tabl = ProxyTable.new({ Gold = 0 })
tabl.Changed:Connect(print)
tabl:GetPropertyChangedSignal("Gold"):Connect(print)
tabl.Gold = 1235
--> Gold 1235 -- from `Changed`
--> 1235 -- from `GetPropertyChangedSignal`
I had an Event module sitting around, so I just parented it under the main module and implemented it for .Changed and cached :GetPropertyChangedSignal events. As for the Event module, it has a near-identical interface as a bindable event except for some necessary meta-data and :Fire being in the same scope. Otherwise, it has :Connect and :Wait methods.
Did not know about them, could you please post the link that lead to their posts? Also I thought this was a fun little creation and wanted to share it, as well as seeing quite many people asking how to make something as Table.Changed so this is basically to give them the idea about it, you could also consider it a more efficient method than using binds as it doesn’t use networking to pass around changed Data.