NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
|
| 02 Jul 2015 07:22 PM |
| If I have a fake newproxy object where the metatable's index returns realObject[key], how can I make it so "fakeObj.Parent = realInstance" doesn't throw an error? |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:24 PM |
Here is something you might find helpful, idk if you are doing it this way, maybe not.
Object={ new=function() local obj=newproxy(true) getmetatable(obj).__index={Color=nil,Name='',Random=0} getmetatable(obj).__newindex=function(S,K,V) return rawset(getmetatable(S).__index,K,V) end return obj end }
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:25 PM |
Actually, can you post the code and the error it throws?
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
|
| 02 Jul 2015 07:27 PM |
| @TickerOfTime Thanks. Does that fix this issue? I'm not familiar with __newindex |
|
|
| Report Abuse |
|
|
NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
|
| 02 Jul 2015 07:28 PM |
Oh, sure. Here:
attempt to index local 'fakeObject' (a userdata value)
I can access properties n' stuff, and I can even print the parent, but trying to set the parent throws this. |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:29 PM |
Post your wrapper code please. I need to know how you are setting it up.
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
|
| 02 Jul 2015 07:33 PM |
local addMethods = function(obj, methods) local isInstance = function(obj) -- thanks to eLunate for this if type(obj) == "userdata" then local s, e = pcall(game.GetService, game, obj); return s and not e; end return false end if isInstance(obj) then local wrappedObj = newproxy(true) local metatable = getmetatable(wrappedObj) metatable.__index = function(_, key) if methods[key] ~= nil then return function(...) return methods[key](obj, ...) end elseif type(obj[key]) == "function" then return function(...) return obj[key](obj, ...) end else return obj[key] end end metatable.__tostring = function() return obj.Name or obj; end; return wrappedObj else return obj end end
local methods = { lol = function(self, ...) print(tostring(self).." is bae!") end }
local test = addMethods(workspace.BasePlate, methods)
wait(.1)
test:lol() -- works
print(test.Parent) -- works
test.Parent = game.ServerStorage -- errors
|
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:34 PM |
"rawset(getmetatable(S).__index,K,V)"
That would error. The __metatable field of all objects' metatables in Roblox are set to "The metatable is locked" so you can't do that. You're better off just firing the __newindex metamethod by using S[K] = V instead. |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:37 PM |
@Agent It doesn't error, I've used this before. Granted, it was with Parent being a string, but whatevs.
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:38 PM |
Now, it doesn't work with __metatable being set, but that is an easy fix.
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 07:42 PM |
K, lemme test this and I'll post it in a second.
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 08:01 PM |
Done! Works with Parent and Name in the same script with a Part
local addMethods = function(obj, methods) local isInstance = function(obj) -- thanks to eLunate for this if type(obj) == "userdata" then local s, e = pcall(game.GetService, game, obj); return s and not e; end return false end if isInstance(obj) then local wrappedObj = newproxy(true) local metatable = getmetatable(wrappedObj) metatable.__index = function(_, key) if methods[key] ~= nil then return function(...) return methods[key](obj, ...) end elseif type(obj[key]) == "function" then return function(...) return obj[key](obj, ...) end else return obj[key] end end metatable.__tostring = function() return obj.Name or obj; end; metatable.__newindex = function(ReindexObject,Key,Value) --print(ReindexObject,Key,Value) --print(obj[Key]) if obj[Key] or Key=='Parent' then local DidSet,YNot=ypcall(function() obj[Key]=Value end) if DidSet then obj[Key]=Value else error(YNot) end else error('Attempt to index \''..tostring(ReindexObject)..'\' (a userdata value)') end end return wrappedObj else return obj end end
local methods = { lol = function(self, ...) print(tostring(self).." is bae!") end } local p=Instance.new'Part' p.Name='THISISAPART' local thing = addMethods(p,methods) thing:lol()
print(thing.Parent) thing.Parent=workspace print(thing.Parent)
print(thing.Name) thing.Name='I spawned this part via a wrapper' print(thing.Name)
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
| |
|
|
| 02 Jul 2015 08:06 PM |
No problem! Send me the wrapper when it's done? I wanna see it.
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
|
| 02 Jul 2015 08:08 PM |
| It's done, you finished it. Not making a wrapper, just easy custom methods. |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 08:10 PM |
Oh, cool! Glad I could be of service!
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 09:20 PM |
"It's done, you finished it. Not making a wrapper, just easy custom methods."
That's still technically a wrapper. For a learning experience take a look at this, as far as I know it SHOULD work, it allows for custom properties and of course you can include functions in these properties to make methods (it won't use the real object though, it would use the wrapped object when calling it):
function Wrap(obj, newprops) local new = newproxy(true) local newprops = newprops or {} getmetatable(new).__index = function(t, k) if obj[k] then if type(obj[k]) == "function" then return function(dummy, ...) return obj[k](obj, ...) end else return obj[k] end else return newprops[k] end end getmetatable(new).__newindex = function(t, k, v) if obj[k] then local success = pcall(function() obj[k] = v end) if not success then newprops[k] = v end else newprops[k] = v end end getmetatable(new).__metatable = "Attempt to modify protected metatable" getmetatable(new).__tostring = function(t) return obj.Name end return new, newprops end |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 09:32 PM |
Actually could you test this for me? Try changing the value .ClassName and then print it:
function Wrap(obj, newprops) local new = newproxy(true) local newprops = newprops or {} getmetatable(new).__index = function(t, k) if obj[k] then if type(obj[k]) == "function" then return function(dummy, ...) return obj[k](obj, ...) end else if pcall(function obj[k] = obj[k] end) then return obj[k] end end else return newprops[k] end end getmetatable(new).__newindex = function(t, k, v) if obj[k] then local success = pcall(function() obj[k] = v end) if not success then newprops[k] = v end else newprops[k] = v end end getmetatable(new).__metatable = "Attempt to modify protected metatable" getmetatable(new).__tostring = function(t) return obj.Name end return new, newprops end
So something like
local workspace = Wrap(workspace) workspace.ClassName = "NotWorkspace" print(workspace.ClassName)
Just see what happens. |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 09:36 PM |
Here is an abstract version.
local setmembers = function(tab1,tab2) for i, v in pairs(tab2)do tab1[i] = tab2[i] end end
local obj = {}
obj.new = function() local this = {} local proxy = newproxy(true) local metatable = { __index = this; __newindex = function(self, i, v) self[i] = v end; }
setmembers(getmetatable(proxy), metatable) return proxy end
return obj |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 10:09 PM |
HA! TAKE THAT!
Yeah I found a few wicked errors in the wrapper. Errors found in wrappers can be difficult to fix because they're underlying and under the surface. But anyhow I fixed it, you can now overwrite read-only properties, set your own properties, write to writable properties, and write to your own properties. Indexing children should also still work fine :) (Don't bother testing, tested myself :D )
function Wrap(obj, newprops) local new = newproxy(true) local newprops = newprops or {} getmetatable(new).__index = function(t, k) if pcall(function() return obj[k] end) then if type(obj[k]) == "function" then return function(dummy, ...) return obj[k](obj, ...) end else if pcall(function() obj[k] = obj[k] end) then return obj[k] else return newprops[k] end end else return newprops[k] end end getmetatable(new).__newindex = function(t, k, v) if pcall(function() return obj[k] end) then if not pcall(function() obj[k] = v end) then newprops[k] = v end else newprops[k] = v end end getmetatable(new).__tostring = function(t) return obj.Name end getmetatable(new).__metatable = "Attempt to modify protected metatable" return new, newprops end |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 10:15 PM |
"you can now overwrite read-only properties" What exactly is the point of writing a wrapper then? Also, if anyone has any experience writing Script Builder type sandboxes, please let me know.
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
NotAshley
|
  |
| Joined: 16 Jan 2014 |
| Total Posts: 14257 |
|
|
| 02 Jul 2015 10:16 PM |
> Also, if anyone has any experience writing Script Builder type sandboxes, please let me know.
I'm writing a script builder and trying for the same thing. We could work together. |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 10:19 PM |
Sounds cool. How would we do that?
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 10:21 PM |
""you can now overwrite read-only properties" What exactly is the point of writing a wrapper then?"
Well it's to provide extra functionality on top of what's already given and to hide the underlying mechanisms so that the user does not need to worry about them.
My "wrapper" allows you to create, change, and index custom/new properties. It allows you to overwrite read-only properties (like ClassName). But any writable properties (such as Name, and Parent) would be changed before a new property is created (so no your cannot replace them). |
|
|
| Report Abuse |
|
|
|
| 02 Jul 2015 10:23 PM |
@Not Maybe party me if you're serious?
-Ticker of da Tocks | Scripter's Forum Breakfast Club |
|
|
| Report Abuse |
|
|