Reputation: 621
I am writing a new constructor and I have something like this:
function Map:new(path, world, debug)
local map = sti(path, { "box2d" })
return map
end
function Map:update(dt)
print('call this')
end
sti is some thirdparty library that constructs a class object. What I am trying to do is make it so when I call:
map:update(dt)
it calls the functions I have declared. If not found, it calls the actual function that sti sets up on the object.
I've tried stuffing around with metatables but can't seem to get my functions to take priority over the third party library supplied functions....
Upvotes: 1
Views: 171
Reputation: 621
unfortunately sti declares 'local dir' at the top of the function so copying the code did not work. I found a solution how ever I have made myself some way to easily set a class as a proxy in lua:
-- forward a function call from oldSelf:fn(...) to newSelf:fn(...)
function utils.forwardFunc(fn, newSelf)
return function(oldSelf, ...)
local function __NULL__() end
return (fn or __NULL__)(newSelf, ...)
end
end
-- make a function fn(...) call newSelf:fn(...)
function utils.func(fn, newSelf)
return function(...)
local function __NULL__() end
return (fn or __NULL__)(newSelf, ...)
end
end
-- forward any undefined functions called on 'from' to 'to'
-- if 'to' is a function, it acts as a dynamic proxy, incase you are changing what class you are proxying to
-- on the fly. For example, a state machine proxies to the current state
function utils.proxyClass(from, to)
local mt = getmetatable(from)
setmetatable(from, {__index = function(_, func)
if mt and mt[func] then
return mt[func]
end
local forwardTo = to
if type(to) == 'function' then
forwardTo = to(from)
end
if type(forwardTo[func]) == 'function' then
return utils.forwardFunc(forwardTo[func], forwardTo)
else
return forwardTo[func]
end
end})
end
Upvotes: 0
Reputation: 344
Reading the source code for what I believe is the library you're using (Simple-Tiled-Implementation), I figured out it actually overrides your metatable with another one:
local function new(map, plugins, ox, oy)
local dir = ""
if type(map) == "table" then
map = setmetatable(map, Map) -- Here
else
-- Check for valid map type
local ext = map:sub(-4, -1)
assert(ext == ".lua", string.format(
"Invalid file type: %s. File must be of type: lua.",
ext
))
-- Get directory of map
dir = map:reverse():find("[/\\]") or ""
if dir ~= "" then
dir = map:sub(1, 1 + (#map - dir))
end
-- Load map
map = setmetatable(assert(love.filesystem.load(map))(), Map) -- Or here
end
map:init(dir, plugins, ox, oy)
return map
end
The function above is defined here
You'll need to pass a table argument as map instead of the path, there you can define update()
, which will take precedence over the metatable provided by STI.
I believe you can copy the procedure STI does to load your map and provide it with a table containing the function you wish to define inside:
-- Check for valid map type
local ext = map:sub(-4, -1)
assert(ext == ".lua", string.format(
"Invalid file type: %s. File must be of type: lua.",
ext
))
-- Get directory of map
dir = map:reverse():find("[/\\]") or ""
if dir ~= "" then
dir = map:sub(1, 1 + (#map - dir))
end
-- Load map
local map = assert(love.filesystem.load(map))()
function map:update()
-- Do things
end
sti(map, { "box2d" })
Upvotes: 1