Skip to content

Instantly share code, notes, and snippets.

@eliasdaler
Last active June 5, 2021 03:40
Show Gist options
  • Save eliasdaler/f3516d3deabc32b465a7c244ff082cf0 to your computer and use it in GitHub Desktop.
Save eliasdaler/f3516d3deabc32b465a7c244ff082cf0 to your computer and use it in GitHub Desktop.
Safe reference implementation. Lua part. See https://eliasdaler.github.io/game-object-references for details
Handles = {}
local memoizedFuncs = {}
-- metatable which does magic
local mt = {}
mt.__index = function(handle, key)
if not handle.isValid then
print(debug.traceback())
error("Error: handle is not valid!", 2)
end
local f = memoizedFuncs[key]
if not f then
f = function(handle, ...) return Entity[key](handle.cppRef, ...) end
memoizedFuncs[key] = f
end
return f
end
function getWrappedSafeFunction(f)
return function(handle, ...)
if not handle.isValid then
print(debug.traceback())
error("Error: handle is not valid!", 2)
end
return f(handle.cppRef, ...)
end
end
function createHandle(cppRef)
local handle = {
cppRef = cppRef,
isValid = true
}
-- speedy access without __index call
handle.getName = getWrappedSafeFunction(Entity.getName)
setmetatable(handle, mt)
Handles[cppRef:getId()] = handle
return handle
end
function onEntityRemoved(cppRef)
local handle = Handles[cppRef:getId()];
handle.cppRef = nil
handle.isValid = false
Handles[cppRef:getId()] = nil
end
function test(cppRef)
local handle = createHandle(cppRef)
testHandle(handle)
end
function testHandle(handle)
print("Hello, my name is " .. handle:getName())
handle:setName("Mark")
print("My name is " .. handle:getName() .. " now!")
end
function testBadReference()
local handle = Handles[0] -- this handle exists and is okay
handle.isValid = false -- but suppose that entity was removed!
local _, err = pcall(testHandle, handle)
if err then
print(err)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment