-- Compiled with roblox-ts v2.0.4 --[[ * * Attributes wrapper class. Enforces default attribute values * and attribute typings. * * ```ts * const attrs = new Attributes(myInstance, { * name: "default_name", * points: 0, * xp: 0, * cool: false, * }); * * print(attrs.attributes.points); * attrs.set("points", 10); * attrs.destroy(); * ``` ]] local Attributes do Attributes = setmetatable({}, { __tostring = function() return "Attributes" end, }) Attributes.__index = Attributes function Attributes.new(...) local self = setmetatable({}, Attributes) return self:constructor(...) or self end function Attributes:constructor(instance, defaultAttributes) self.instance = instance self.attr = {} self.connections = {} self.onChangedCallbacks = {} local attrBound = instance:GetAttributes() for k, v in pairs(defaultAttributes) do local key = k local val = v local bound = attrBound[key] if bound ~= nil then self.attr[key] = bound else self.attr[key] = val instance:SetAttribute(key, val) end local connection = instance:GetAttributeChangedSignal(key):Connect(function() self:handleOnChange(key, instance:GetAttribute(key)) end) table.insert(self.connections, connection) end self.attributes = self.attr end function Attributes:handleOnChange(key, newValue) local oldValue = self.attr[key] if newValue == oldValue then return false end self.attr[key] = newValue local _onChangedCallbacks = self.onChangedCallbacks local _key = key local callbacks = _onChangedCallbacks[_key] if callbacks then for _, callback in callbacks do task.spawn(callback, newValue, oldValue) end end return true end function Attributes:set(key, value) local changed = self:handleOnChange(key, value) if not changed then return nil end self.instance:SetAttribute(key, value) end function Attributes:onChanged(key, handler) local _onChangedCallbacks = self.onChangedCallbacks local _key = key local callbacks = _onChangedCallbacks[_key] if callbacks == nil then callbacks = {} local _onChangedCallbacks_1 = self.onChangedCallbacks local _key_1 = key local _callbacks = callbacks _onChangedCallbacks_1[_key_1] = _callbacks end local _callbacks = callbacks local _handler = handler table.insert(_callbacks, _handler) return function() local _callbacks_1 = callbacks local _handler_1 = handler local index = (table.find(_callbacks_1, _handler_1) or 0) - 1 if index == -1 then return nil end local _result = callbacks if _result ~= nil then -- ▼ Array.unorderedRemove ▼ local _index = index + 1 local _length = #_result local _value = _result[_index] if _value ~= nil then _result[_index] = _result[_length] _result[_length] = nil end -- ▲ Array.unorderedRemove ▲ end end end function Attributes:observe(key, observer) task.spawn(observer, self.attributes[key]) return self:onChanged(key, function(newValue) return observer(newValue) end) end function Attributes:destroy() for _, connection in self.connections do connection:Disconnect() end table.clear(self.connections) table.clear(self.onChangedCallbacks) end end return { Attributes = Attributes, }