I ran into an issue when trying to send metatables through TriggerEvent
and finally thought of a simple solution to it.
Class FIle
---@class Something
Something = setmetatable({}, Something)
Something.__call = function()
return "Something"
end
Something.__index = Something
function Something.new(name)
local _Something = {
Name = name
}
return setmetatable(_Something, Something)
end
function Something:Hello()
print("My name is " .. self.Name)
end
function Something:SetName(name)
print("Setting name to ", name)
self.Name = name
end
Another file which instantiates the Something class and adds it to an array for indexing later. i.e. An array of currently logged in users.This also contains the “magic” function
local something = Something.new("Bob")
---@param tb table
function toPack(tb)
local tmpObj = {}
local tmpMt = getmetatable(tb) or {}
for k,v in pairs(tb) do
tmpObj[k] = v
end
for k,v in pairs(tmpMt) do
if k ~= "__index" and k ~= "__call" and k ~= "new" then
tmpObj[k] = v
end
end
for k,v in pairs(tmpObj) do
if type(v) == "function" then
tmpObj[k] = function(...)
v(tmpObj, ...)
end
end
end
return tmpObj
end
local mySomething = toPack(something)
local Cache = {}
Cache[1] = mySomething
RegisterCommand('doit', function()
TriggerEvent('server:do', Cache[1])
end)
RegisterCommand('first', function()
Cache[1].Hello()
end)
Another file that receives the table and wishes to manipulate/run functions on it
RegisterServerEvent('server:do')
AddEventHandler('server:do', function(something)
something.Hello()
something.SetName("Something")
end)
The idea of the “magic” function is to reassign all of the functions that exist on the metatable to the table itself along with a wrapped function which passes itself as the self
parameter for ease of use.
This also allows for mutability of the orignal object through MessagePack, which means the call to SetName
in the 3rd file is able to mutate the Name
property of Cache[1]
Could probably design the class in a different way to not require this (such as a function that simply returns a table), but this was my solution if it was desired to use classes in this fashion