So recently I learned about the function
and I was trying to figure out what I could do with it. WELL I was looking through Lua documentation about how to work with userdata and I learned quite a bit! Without further adieu, here’s a short script that showcases some cool stuff I figured out how to make with some of the recources available on the internet!
–purpose: ceate an object which holds data that cannot be accessed by another unless the know the password.
–aka: a hidden table with one or more values which are not accessable without explicitly knowing the index.
local function account( password, money, frozen )
local money = tonumber( money ) local password = tostring( password ) if not money or not password then return end frozen = tobool( frozen ) local obj = newproxy( true ) --create a userdata object with a blank metatable local mt = getmetatable( obj ) mt.__metatable = 42 --hide the metatable so that it can't be accessed outside of this scope function mt:__newindex( key, value )--we'll store data in the metatable and let the userdata object act as a buffer mt[key] = value end obj[password] = money --now that the metatable allows the userdata to know what to do when it gets a newindex event, we won't error! obj.frozen = frozen function mt:__index( key ) --the __index event happens whenever you try to access the key of a table, eg. obj[password] if key == "frozen" then --always tell the user if this object is frozen return mt.frozen elseif mt.frozen then --if they're asking for any key other than the frozen key while the account is actually frozen, return nil return nil else return mt[key] --if everything's good, just give them the value end end function mt:__unm() --this function is called when the - operator is run on it, eg. -obj return account( password, mt[password], not mt.frozen )--return an object that is the same, except invert our frozen value end --this isn't really a "newindex" function, more of a "changeindex" function mt:__newindex( key, value ) if mt[key] and key ~= "frozen" then-- only accept changes to existing keys, and don't let them change the frozen key this way mt[key] = value end end mt.__call = mt.__index -- so obj( password ) works just like obj.password or obj[password] return obj
local obj = new( “mypassword”, 100000000 ) --holy moly im rich!
print( obj.frozen ) --defaults to not frozen
obj.frozen = true --try to change it manually
print( obj.frozen ) --can’t
obj = -obj --cinvert it through our unary minus operator
print( obj.frozen ) --worked!
print( obj( “im guessing at passwords here” ) ) --nil
print( obj[“look at all these ways I can guess passwords!”] ) --nil
print( obj.wow_metatables_are_cool ) --nil
print( obj( “mypassword” ) ) --ok I guess I’ll prove that it does actually work.
–oops it’s frozen!
obj = -obj --gotta unfreeze it through our unfreeze operator
print( obj( “mypassword” ) ) --now it works!
for k,v in pairs( obj ) do --screw guessing, I’ll just print every key and value to see the password!
print( k, v )
end --hint: it doesn’t work!
–FINE. I’ll just get the metatable and loop through that!
for k,v in pairs( getmetatable(obj ) ) do
print( k, v )
end --hint:still doesn’t work
Obviously this has a couple cool applications. Basically this allows you to make private variables that truly cannot be access except through a get/set function, which has obvious upsides. I’m sure that programmers more skilled than me can/will/have found better applications for this kind of implementation in Lua. I just wanted to share a cool little bit of GLua that I haven’t really known about before, thanks for reading!