Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Making sure duplicate objects do not muck up an Instance Wrapper? + Weird function bug? O.o

Asked by 7 years ago
Edited 7 years ago

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!!

1 answer

Log in to vote
0
Answered by 7 years ago

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.

Ad

Answer this question