So basically, I have created a RBX.Lua Instance Wrapper. It is a module. It works perfectly- however, it depends off of object names, because I made it automatically wrap the Parent property and the FindFirstChild, WaitForChild, Children, and GetChildren methods. Why? Because I wanted to cover all possibilities, with the least amount of code. However, to do this, my WrappedObjects table depends on names. How can I make it depend on something that will never be identical to another object?
Also, even if it doesn't pertain to my question, I would love suggestions/criticism for the wrapper as a whole (or other bits)!
Table definition:
local WrappedObjects = {}
Some relevant snippets using it:
--\\Snippet 1 WrappedObjects[Thing.Name] = NewInstance --\\Snippet 2 elseif (Key == "Parent") then local RealParent = Thing.Parent local WrappedObject = WrappedObjects[RealParent.Name] if WrappedObject then return WrappedObject else return RealParent end
And so on for the other methods I auto-wrapped as well.
Full code:
local WrappedObjects = {} return(function(Thing, Fakes) local Type = type(Thing) if (Type == "userdata") then local IsWrappedObject = pcall(function() return Thing.WrappedCheck end) if IsWrappedObject then return Thing else local NewInstance = newproxy(true) WrappedObjects[Thing.Name] = NewInstance local MetaTable = getmetatable(NewInstance) MetaTable.__index = function(Self, Key) local KeyLower = Key:lower() local Fake = Fakes[Key] if (Key == "WrappedCheck") then return ("This object has been wrapped!") elseif (Key == "Parent") then local RealParent = Thing.Parent local WrappedObject = WrappedObjects[RealParent.Name] if WrappedObject then return WrappedObject else return RealParent end elseif ((Key == "children") or ("GetChildren")) then return(function() local Children = {} for Index, Child in next, Thing:GetChildren() do local WrappedObject = WrappedObjects[Child.Name] if WrappedObject then Children[#Children + 1] = WrappedObject else Children[#Children + 1] = Child end end return Children end) elseif (KeyLower == "findfirstchild") then return(function(ChildName) local Child = Thing:FindFirstChild(ChildName) if Child then local WrappedObject = WrappedObjects[Child.Name] if WrappedObject then return WrappedObject else return Child end end end) elseif (KeyLower == "waitforchild") then return(function(ChildName) repeat local Child = Thing:FindFirstChild(ChildName) if Child then local WrappedObject = WrappedObjects[Child.Name] if WrappedObject then return WrappedObject else return Child end end wait(0.1) until nil end) elseif Fake then return Fake else local Success, Variant = pcall(function() return Thing[Key] end) if Success then return Variant end end end MetaTable.__newindex = function(Self, Key, Value) pcall(function() Thing[Key] = Value end) end MetaTable.__metatable = "The meta-table has been locked!" return NewInstance end end end)
ALSO: Bug #2 is that with the following code:
local WrapInstance = require(game.ReplicatedStorage:WaitForChild("InstanceWrapper")) workspace = WrapInstance(workspace, {}) game = WrapInstance(game, {gameIsWrapped = true}) print(game.gameIsWrapped) print(workspace.Parent.gameIsWrapped)
It prints: function (0xSTUFF)
for some reason, a memory address. It should be printing true. WTH!!
Help very much so appreciated!!
Depend on objects
It's like DNA for code
Objects all have an identity, and are completely unique - One object may not have the same identity as another object, and this makes them suitable for holding information about themselves.
As you are writing a wrapper, I would like to take this moment to mention that your method of wrapping seems very primitive and flawed. You wrap statically and certainly not functionally, and the wrapper looks like it's going to have issues dealing with wrapped/unwrapped values in the wrong places.
You might want to consider taking a look at Freya's BaseLib and LiteLib, as they are both wrappers.