I’m trying to create a Player Data Storage modulescript using object oriented programming. I realized that I need to detect when a player data object changes data. I found a way to detect changes in table, here:
The thing is, I am really, really confused as to how I can implement this. This is my first attempt at OOP, after all. But I semi-understand metatables.
My current code can find when a new index is created, but it can’t find when an index changes. Here’s my code right now, fyi:
local playerData = {}
local defaultData = {
Name = nil,
UserId = nil
}
local objects = {}
local bindableEvent = Instance.new("BindableEvent")
playerData.Changed = bindableEvent.Event
playerData.__index = playerData
-- The __newindex metamethod is called whenever a new index is assigned to the table
function playerData:__newindex(index, value)
print("NEW INDEX CREATED")
print(index, value, objects)
-- Get the raw value currently stored in the table
local oldValue = rawget(self, index)
-- Only fire the changed event if the value is actually different
if oldValue ~= value then
-- Store the new value using rawset to avoid recursive calls to __newindex
rawset(self, index, value)
-- Fire the changed event with information about what changed
bindableEvent:Fire(
self.UserId,
index,
oldValue,
value
)
end
end
function playerData.new (player: Player) -- Constructor
local specificDefaultData = table.clone(defaultData)
specificDefaultData.Name = player.Name
specificDefaultData.UserId = player.UserId
local self = setmetatable(specificDefaultData, playerData)
--[[
When a function is indexed, it won't be found in the new playerData instance.
Thus, it will look in playerData class to find all the functions!
]]--
objects[self.UserId] = self
return self
end
function playerData.findPlayerData (player: Player, createIfNotFound: boolean)
local userId = player.UserId
if objects[userId] then
return objects[userId]
else
if createIfNotFound then
local playerFromId = game.Players:GetPlayerByUserId(userId)
if playerFromId then
playerData.new()
end
end
end
return nil
end
function playerData:Destroy()
if self.UserId then
objects[self.UserId] = nil
end
-- Clear the object's data
for k, _ in pairs(self) do
self[k] = nil
end
setmetatable(self, nil)
self = nil
end
return playerData
Thanks for reading!