• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

help metatable in lua

Sunwave

New Member
Joined
Dec 30, 2021
Messages
3
Reaction score
0
I'm working with metatables and I need help, I have a table inside this metatable and I wanted to insert values into them and return this table, but when I create the metatable these values are 0


Lua:
function Teste(cid)
  local player = Player(cid)
  if not player then
     return
  end
  local t = {}
  local init = {
    insert = function(self, target)
      table.insert(t, target)
    end,
    getTable = function(self)
        return t
    end
  }
  local meta = {
    __index = init
  }
  return setmetatable({}, meta)
end

-- call metatable
if player then
  local teste = Teste(player)
  print(#teste:getTable()) -- value is 0
end
 
I'm working with metatables and I need help, I have a table inside this metatable and I wanted to insert values into them and return this table, but when I create the metatable these values are 0


Lua:
function Teste(cid)
  local player = Player(cid)
  if not player then
     return
  end
  local t = {}
  local init = {
    insert = function(self, target)
      table.insert(t, target)
    end,
    getTable = function(self)
        return t
    end
  }
  local meta = {
    __index = init
  }
  return setmetatable({}, meta)
end

-- call metatable
if player then
  local teste = Teste(player)
  print(#teste:getTable()) -- value is 0
end

Lua:
function table.copy(t) -- In case you don't have it within your libs
  local ret = { }
  for k,v in pairs(t) do
    if type(v) ~= 'table' then
      ret[k] = v
    else
      ret[k] = table.copy(v)
    end
  end
  local metaTable = getmetatable(t)
  if metaTable then
    setmetatable(ret, metaTable)
  end
  return ret
end

MyClass = {
  t = {},

  new = function()
    local obj = setmetatable({}, { __index = MyClass })

    -- If you don't do that, the table 't' will be the same table for all objects
    -- This happens because tables are copied by reference, so it will not clone it's value; instead, it will get same reference to this table (same table to all)
    -- You need to worry about it just for table values by "fixing" it like that:
    obj.t = table.copy(obj.t) -- Clone table 't' of class to the object

    return obj
  end,

  insert = function(self, value)
    table.insert(self.t, value)
  end,
}

local player1Cid = 268435457
local player2Cid = 268435458
local player3Cid = 268435459

local obj1 = MyClass.new()
obj1:insert(player1Cid)
obj1:insert(player2Cid)

local obj2 = MyClass.new()
obj2:insert(player1Cid)
obj2:insert(player2Cid)
obj2:insert(player3Cid)

print(#obj1.t) -- value is 2 (without table.copy in "new" function, it would be 5 since is the same table for all objects)
print(#obj2.t) -- value is 3 (without table.copy in "new" function, it would be 5 since is the same table for all objects)
 
The code works as it was written, you are printing the size of an empty table.
I don't see any place where I am adding something to the table...
example:
1640870881061.png


I'm not sure what you really need to do with this code, I don't know what the reason for using this simple metatable is, when you can just use a normal table.
Here is a cleaner example where the values are stored in the table itself and not in a local table in a separate environment:
Lua:
local function new()
    local t = {
        values = {},
        insert = function (self, v)
            return table.insert(self.values, v)
        end,
        getTable = function (self) return self.values end
    }
    return setmetatable(t, {
        __index = function (self, k)
            local v = rawget(self, k)
            if not v then return self.values[k] end
            return v
        end,

        __len = function (self) return #self.values end
    })
end

local n = new()
n:insert(100)
n:insert(200)

print(#n) -- Result: 2

for k, v in pairs(n:getTable()) do
    print("index:", k, "value:", v)
end

--[[ Results:
index:  1   value:  100
index:  2   value:  200
]]--
in this way you can count the values in the table, applying the length operator # to the main table, and also you can access the values through the operator []

I hope this example will make you understand a little more about metatables, if you need more help do not hesitate to post your questions here.
 
Last edited:
I tried that way but I couldn't
@River KA

Lua:
function table.copy(t)
  local ret = {}
  for k,v in pairs(t) do
    if type(v) ~= 'table' then
      ret[k] = v
    else
      ret[k] = table.copy(v)
    end
  end
  local metaTable = getmetatable(t)
  if metaTable then
    setmetatable(ret, metaTable)
  end
  return ret
end


function Team(cid)
    local player = Player(cid)
    if not player then
        return
    end
    
    local init = {
        player_send_invitations = {},
        invitations_team = {},
        your_team = {},
    
        insert_invite = function(self, target)
            table.insert(self.player_send_invitations, target)
        end,
        
        insert_player = function(self, target)
            table.insert(self.your_team, target)
        end,
        
        doAccept = function(self, name_player) -- accept invite
            local target = Player(name_player)
            if target then
                local team = Team(target)
                if team then
                    team:insert_player(player)
                end
            end
        end,

        ----------
        doSendInvite = function(self, target) -- send invite
            if target then
                local team = Team(target)
                if team then
                    team:insert_invite(player)
                    table.insert(self.invitations_team, target)
                end
            end
        end,
        
        getYourInvitations = function(self) -- table your invitation
            return self.invitations_team
        end,
        
    }
  local obj = setmetatable({}, { __index = init })
        obj.player_send_invitations = table.copy(obj.player_send_invitations)
        obj.invitations_team = table.copy(obj.player_send_invitations)
        obj.your_team = table.copy(obj.your_team)
    return obj
end
 
A simpler way could be

Lua:
function Teste()
    local obj = {}

    function obj:insert(target)
        return table.insert(self, target)
    end

    function obj:getTable()
        return self
    end
 
    return obj
end

EDIT:
Lua:
local data1 = Teste()
local data2 = Teste()

data1:insert("-")
print(#data1:getTable()) -- 1
print(#data2:getTable()) -- 0
 
Last edited:
Back
Top