Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Simple (well, simplish) sandbox that allows wrapping of instances:
- local wrapped,properties = Instance.wrap(someInstance)
- properties.PROP = true
- print(wrapped.PROP) --> nil (works)
- wrapped.PROP = 123 (works)
- print(wrapped.PROP) --> 123 (works)
- print(wrapped.DERP) (error)
- wrapped.DERP = 123 (error)
- print(wrapped.Name) (works)
- wrapped.Name = "Idk" (works)
- wrapped.Parent = realInstance (works)
- anotherRealInstance.Parent = wrapped (works)
- wrapped:Destroy() (works)
- Instance.new("Folder",wrapped) (works)
- --]]
- local RealToFake = setmetatable({},{__mode="v"})
- local FakeToReal = setmetatable({},{__mode="k"})
- local function isInstance(obj)
- return pcall(game.GetService,game,obj)
- end
- local instaMeta,sandbox = {}
- function instaMeta:__tostring()
- return self.Name
- end instaMeta.__metatable = "Locked"
- function instaMeta:__index(key)
- local real = FakeToReal[self]
- return sandbox(real[key])
- end
- function instaMeta:__newindex(key,val)
- local real = FakeToReal[self]
- real[key] = FakeToReal[val] or val
- end
- local function wrapInstance(obj)
- return setmetatable({},instaMeta)
- end
- local function register(fake,real)
- RealToFake[real] = fake
- FakeToReal[fake] = real
- end
- local sandboxTuple,unsandboxTuple
- function sandbox(obj)
- if RealToFake[obj] then
- return RealToFake[obj]
- elseif type(obj) == "userdata" and isInstance(obj) then
- local wrapped = wrapInstance(obj)
- register(wrapped,obj) return wrapped
- elseif type(obj) == "function" then
- local wrapped = function(...)
- return sandboxTuple(obj(unsandboxTuple(...)))
- end register(wrapped,obj) return wrapped
- end return obj
- end
- function sandboxTuple(...)
- local num = select("#",...)
- local res = {...}
- for k,v in pairs(res) do
- if type(v) == "table" then
- local res = {}
- for a,b in pairs(v) do
- res[sandbox(a)] = sandbox(b)
- end v = res
- end res[k] = sandbox(v)
- end return unpack(res,1,num)
- end
- function unsandboxTuple(...)
- local num = select("#",...)
- local res = {...}
- for k,v in pairs(res) do
- if type(v) == "table" and not FakeToReal[v] then
- local res = {}
- for a,b in pairs(v) do
- local c = FakeToReal[a]
- local d = FakeToReal[b]
- res[c or a] = d or b
- end v = res
- end res[k] = FakeToReal[v] or v
- end return unpack(res,1,num)
- end
- local real,envMeta = getfenv(),{}
- function envMeta:__index(key)
- return key ~= "script" and sandbox(real[key]) or nil
- end
- local lockedMeta = {}
- function lockedMeta:__newindex()
- error("Attempt to modify a readonly table",2)
- end
- local instance = {}
- register(instance,Instance)
- function instance.new(...)
- return sandbox(Instance.new(unsandboxTuple(...)))
- end local function set(a,b,c) a[b] = c end
- function instance.wrap(obj)
- local met,props,d = {},{},{}
- function met:__newindex(key,val)
- if props[key] then
- d[key] = val return
- end obj[key] = val
- end met.__metatable = "Locked"
- function met:__index(key)
- if props[key] then
- return d[key]
- end return obj[key]
- end
- local res = setmetatable({},met)
- FakeToReal[res] = FakeToReal[obj]
- return res, props
- end setmetatable(instance,lockedMeta)
- function _rawget(tab,key)
- return rawget(FakeToReal[tab],key)
- end register(_rawget,rawget)
- function _rawset(tab,key,val)
- return rawset(FakeToReal[tab],key,val)
- end register(_rawset,rawset)
- local function Sandbox(script)
- local env = {}
- env.script = sandbox(script)
- setmetatable(env,envMeta)
- return env
- end
- --[[ START EXAMPLE CODE ]]--
- local function test()
- print("script =",script)
- print(game,game.Name)
- local p,props = Instance.new("Part",workspace)
- print("----------------")
- -- Wrap instance in something we can play with
- p,props = Instance.wrap(p)
- -- And make sure we can edit the Banana property
- props.Banana = true
- -- Using it with real instances should still work:
- p.Parent = nil p.Parent = workspace
- local val = Instance.new("ObjectValue")
- val.Value = p print("val.Value =",val.Value)
- -- Now let's play with the Banana property
- p.Banana = 123
- print(p.Name,p.Banana)
- print("Parent:",p.Parent)
- p:Destroy()
- print("Parent:",p.Parent)
- print("----------------")
- -- We can also override properties, too lazy to fix this "issue"
- props.Name = true
- p.Name = "NotTheRealName"
- print("Name stuff:",p,p.Name,p:GetFullName())
- print("----------------")
- warn("This should print false and an error:")
- print(pcall(function() return p.NonExistingStuff end))
- warn("Next line should error too:")
- print(pcall(function() p.NonExistingProperty = 123 end))
- end
- setfenv(test,Sandbox(script))()
- --[[ END EXAMPLE CODE ]]--
- return Sandbox
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement