Object Wrapper
Get the module, ID: 5295404854
, Source Code
If you don’t know much about wrapping objects, here you go:
Wrapping objects is essentially, in a non-formal definition and in Roblox’s context, adding more features to Roblox instances, like properties, methods and even events.
First of all, you need to create a wrapped version of your instance, using :Wrap(instance)
, that returns a wrapped instance, which has a type
of userdata
.
local wrapper = require(game.ServerScriptService.Wrapper)
local wrappedPart = wrapper:Wrap(Instance.new("Part"))
wrappedPart.Name = "hi" --you can still change properties
wrappedPart.Name = workspace --it would get parented to workspace
print(wrappedPart) --Part
print(type(wrappedPart)) --userdata
This module creates custom :Destroy()
and :Clone()
methods for you, and a custom .Changed
event as well, to make them work with the custom properties and features you made, else things would break.
To add a custom property you use :AddProperty(wrappedInstance, propertyName, defaultValue)
, which creates a new property called propertyName
inside of the given wrappedInstance
, with a default value of defaultValue
.
local wrapper = require(game.ServerScriptService.Wrapper)
local wrappedPart = wrapper:Wrap(Instance.new("Part"))
wrappedPart.Name = "hi"
wrappedPart.Name = workspace
wrapper:AddProperty(wrappedPart, "MiddleName", "George")
print(wrappedPart.MiddleName) --"Geroge"
wrappedPart.MiddleName = "Mike"
print(wrappedPart.MiddleName) --"Mike"
local clone = wrappedPart:Clone()
wrappedPart.Parent = workspace
print(clone.Name) --"hi"
print(clone.MiddleName) --"Mike"
To add a custom method you use :AddMethod(wrappedInstance, methodName, methodBody)
, to create a method with the name methodName
inside of wrappedInstance
, that does what the function methodBody
does. Note that, due to how anonymous functions behvave, self
inside of methodBody
(which would refer to wrappedInstance
of course) has to be passed as a first parameter always, and other passed parameters after it.
local wrapper = require(5295404854)
local wrappedPart = wrapper:Wrap(Instance.new("Part"))
wrappedPart.Name = "hi"
wrappedPart.Name = workspace
wrapper:AddProperty(wrappedPart, "MiddleName", "George")
wrappedPart:AddMethod(wrappedPart, "IsMiddleNameLongerThan", function(self, n)
return #self.MiddleName > n
end)
print(wrappedPart:IsMiddleNameLongerThan(5)) --true
wrappedPart.MiddleName = "Mike"
print(wrappedPart:IsMiddleNameLongerThan(5)) --false
To add a custom event you use :AddEvent(wrappedInstance, eventName)
, to create an event inside of wrappedInstance
with the name of eventName
. This is only responsible for setting up the event, you’re responsible for firing the event (and passing parameters if you want) by doing wrappedInstance[eventName]:Fire(parameters)
, and making connections to it when needed, just like you would do with normal Roblox events. Let’s say you wanted to make this event, where whenever the MiddleName
property changed, it will fire if the new property satisfies wrappedInstance:IsMiddleNameLongerThan(5) == true
, basically if the MiddleName is longer than 5 characters. (Note that adding new custom properties will not fire .Changed
if a .Changed
connection was created before adding the new property, mutating the custom properties will of course). We would need to check inside of the .Changed
if the the property was MiddleName
, and check if it was longer than 5, and fire the event.
local wrapper = require(game.ServerScriptService.Wrapper)
local wrappedPart = wrapper:Wrap(Instance.new("Part"))
wrappedPart.Name = "hi"
wrappedPart.Parent = workspace
wrapper:AddProperty(wrappedPart, "MiddleName", nil) --default can be nil
wrapper:AddMethod(wrappedPart, "IsMiddleNameLongerThan", function(self, n)
return #self.MiddleName > n
end)
wrapper:AddEvent(wrappedPart, "NameSurpassedLength")
wrappedPart.NameSurpassedLength:Connect(function(n) --n is length of the MiddleName that fired the event
print(n)
end)
wrappedPart.Changed:Connect(function(prop)
if prop == "MiddleName" then
if wrappedPart:IsMiddleNameLongerThan(5) then
wrappedPart.NameSurpassedLength:Fire(#wrappedPart.MiddleName) --this is how to fire event, and pass parameters
end
end
end)
wrappedPart.MiddleName = "Geroge" --fires NameSurpassedLength, and prints length
wrappedPart.MiddleName = "Mike" --doesn't
Anywho, that’s it. If you have feedback, or found a problem with the module, I’m happy to hear about it.
Code sample
local wrapper = require(game.ServerScriptService.Wrapper)
local wrappedPart = wrapper:Wrap(Instance.new("Part"))
print(wrappedPart) --Part
print(type(wrappedPart)) --userdata
wrapper:AddProperty(wrappedPart, "MiddleName", "George")
wrappedPart.BrickColor = BrickColor.new("Really red")
wrappedPart.Parent = workspace
wrapper:AddMethod(wrappedPart, "IsMiddleNameLongerThan", function(self, n)
return #wrappedPart.MiddleName > n
end)
print(wrappedPart:IsMiddleNameLongerThan(5)) --prints true
wrappedPart.MiddleName = "Mike"
local clone = wrappedPart:Clone()
print(clone.MiddleName) --Mike
clone.Changed:Connect(function(prop)
print(prop, "=", clone[prop])
end)
clone.MiddleName = "starmaq"
clone.Transparency = 0.5
clone.Parent = workspace --fires and prints for all these
local c = wrappedPart.Changed:Connect(function()
print("hi")
end)
c:Disconnect()
wrappedPart.Name = "hi" --doesn't fire .Changed
(Note that this module has error debugging problems, errors are most of the time weird and unrelated to the actual problem which might making fixing issues slightly harder, might fix at some point)