Search code examples
luametatable

Lua __lt not working with table.sort even though it is defined


I've got a tile class that inherits from an entity class. The entity class defines __lt, and though I can access it from the tile class, I get a "comparing two tables" error when I try to put all tiles through table.sort.

Entity Class

local Entity = {}

function Entity:New(pos, obj)

    local ent = obj or {}

    ent.entity_type = "none / unnasigned"
    ent.pos = pos or vec3(0, 0, 0)
    ent.z_order = 0
    ent.offset = vec3(0, 0, 0)

    setmetatable(ent, self)
    self.__index = self

    ent:update_z_order()

    return ent

end

function Entity.__lt(a, b)
    if a.z_order == b.z_order then return math.abs(a.pos.z) < math.abs(b.pos.z) end
    return a.z_order < b.z_order
end

return Entity

Tile Class

local Entity = require "entity"

local Map_Tile = Entity:New()

function Map_Tile:New(pos, tile_type, gid)

    local map_tile = Entity:New(pos)

    map_tile.entity_type = "map_tile"

    setmetatable(map_tile, self)
    self.__index = self

    return map_tile

end

return Map_Tile

I can just give table.sort a compare function and that works fine, but I'd like to know why this doesn't work.


Solution

  • You can find the way for lua to get metamethods in the manual, it is:

    rawget(getmetatable(o) or {}, event)
    

    Therefore, the comparison handler must be defined as a direct member of the metatable. In your code, you replaced the metatable from Entity to Map_Tile, this caused lua not being able to find the __lt function, so the most simple solution is to copy the function to Map_Tile.

    Map_Tile.__lt = Entity.__lt