154 lines
4.5 KiB
Lua
154 lines
4.5 KiB
Lua
|
|
local Tables = Require('use/tables.lua')
|
|
local Ids = Require("use/ids.lua")
|
|
|
|
local AllInstances = {}
|
|
|
|
|
|
---@class Class
|
|
Class = {}
|
|
Class.ClassName = "Class"
|
|
Class.__call = function(this, ...)
|
|
return this:new(...)
|
|
end
|
|
Builders = {}
|
|
|
|
function Class.SetInstance(instance)
|
|
AllInstances[instance.id] = instance
|
|
end
|
|
|
|
function Class.GetInstance(id)
|
|
return AllInstances[id]
|
|
end
|
|
|
|
--- Default (empty) constructor
|
|
--- @param self Class
|
|
--- @vararg any
|
|
function Class:init(...) end
|
|
|
|
--- Creates a subclass of the current class.
|
|
--- This function copies the properties and methods of the current class to a new object.
|
|
--- It also sets up metatables to allow for object-oriented behavior, such as method calls and property access.
|
|
--- @param obj object | nil: The table to extend. If nil, a new table will be created.
|
|
--- @return obj object: The extended object with properties and methods from the given class obj.
|
|
function Class:extend(obj)
|
|
local className = obj.ClassName or "Class"
|
|
|
|
|
|
local old = Tables.DeepClone(self, {}, {components = true})
|
|
local new = Tables.DeepClone(obj, old, {ClassName = true})
|
|
|
|
new.components = self.components or {}
|
|
new.components[className] = obj
|
|
|
|
if not new.id then new.id = Ids.CreateUniqueId(new.components) end
|
|
|
|
-- create new objects directly, like o = Object()
|
|
self = setmetatable(new, Class)
|
|
|
|
if not Class.GetInstance(new.id) then Class.SetInstance(self) end
|
|
return self
|
|
end
|
|
|
|
--- Sets a property on the object. NOTE: This is mostly for internal purposes.
|
|
--- @param prop string|table: The property name or a table of properties to set.
|
|
--- @param value any: The value to set the property to.
|
|
function Class:set(prop, value)
|
|
if not value and type(prop) == "table" then
|
|
for k, v in pairs(prop) do
|
|
rawset(self._, k, v)
|
|
end
|
|
else
|
|
rawset(self._, prop, value)
|
|
end
|
|
end
|
|
|
|
--- This function is used to create a new instance of the class.
|
|
--- It calls the init function if it exists.
|
|
--- @vararg any: The arguments to pass to the init
|
|
--- @return object: The new instance of the class.
|
|
function Class:new(...)
|
|
local obj = self:extend({})
|
|
if obj.init then obj:init(...) end
|
|
return obj
|
|
end
|
|
|
|
--- This function is used to create a new instance of the class.
|
|
--- It calls the struct function if it exists.
|
|
--- @vararg object(s): List of objects to extend the class with.
|
|
--- @return object: The new instance of the class with the data and functions from the objects passed.
|
|
function class(className, ...)
|
|
local newObj = Class:extend({})
|
|
local components = table.pack(...)
|
|
newObj.ClassName = className
|
|
if components then
|
|
for k, v in pairs(components) do
|
|
local clName = v.ClassName
|
|
if not Builders[clName] then -- builders are used to reconstruct an object usually when pulled from server to client or vice versa
|
|
Builders[clName] = Tables.DeepClone(newObj)
|
|
end
|
|
end
|
|
end
|
|
if components.n > 0 then
|
|
for k, v in pairs(components) do
|
|
if k ~= "n" then
|
|
local newNewObject = nil
|
|
if v.Struct and type(v.Struct) == "function" then
|
|
newNewObject = v:Struct()
|
|
end
|
|
newObj = newObj:extend(newNewObject or v)
|
|
end
|
|
end
|
|
else
|
|
return newObj
|
|
end
|
|
|
|
return newObj
|
|
end
|
|
|
|
function reconstruct(obj)
|
|
local newTable = {}
|
|
local tbl = obj.components or {}
|
|
for k, v in pairs(tbl) do
|
|
local builder = Builders[k]
|
|
if builder then
|
|
newTable[k] = builder
|
|
end
|
|
end
|
|
return class(table.unpack(newTable))
|
|
end
|
|
|
|
--- Overwrites the type(self) value to return "Class".
|
|
--- @return string: The string "Class".
|
|
function Class:__type()
|
|
return self.ClassName or "Class"
|
|
end
|
|
|
|
--- Overwrites the call operator to call the new function. Ex: Class()
|
|
--- @vararg any: The arguments to pass to the new function.
|
|
--- @return object: The new instance of the class.
|
|
function Class:__call(...)
|
|
return self:new(...)
|
|
end
|
|
|
|
|
|
--- Checks to see if the class is an instance of the given class.
|
|
--- @param cls Class: The class to check against.
|
|
--- @return boolean: True if the class is an instance of the given class, false otherwise.
|
|
function Class:IsA(cls)
|
|
local p = promise.new()
|
|
CreateThread(function()
|
|
local m = getmetatable(self)
|
|
while m do
|
|
if m == cls then
|
|
return p:resolve(true)
|
|
end
|
|
m = getmetatable(m)
|
|
Wait(0)
|
|
end
|
|
return p:resolve(false)
|
|
end)
|
|
return Citizen.Await(p)
|
|
end
|
|
|
|
return {Class, class} |