Introduction
Hello I’m dand and I’ve been scripting for over a year now and I’ve come across newproxy, a Lua Global that may be confusing to some especially new programmers.
Short answer
Well its a lua global that can be called to create a blank userdata.
In short its explained in the dev hub as ‘Creates a blank userdata
, with the option for it to have a metatable.’
What is userdata?
Basically since lua is an extension language it offers a custom datatype (e.g strings, numbers, booleans) userdata for custom behaviour.
In roblox userdata is used in Instances to give custom behaviour. You can test this by running;
print(type(workspace)) -- userdata
To give userdata its functionality you can offer to attach an empty metatable by puting true
as the first parameter to it which you can later edit by using getmetatable
Example
Now lets utilize userdata with Newproxy
local userdata = newproxy(true) -- returns a blank userdata with a blank metatable.
local meta = getmetatable(userdata)
print(meta) -- {}
Giving functionality!
Now how will we give userdata functionality? Its basically just an empty peice of data.
Adding metatables!
Lets give this userdata a name.
local userdata = newproxy(true)
local meta = getmetatable(userdata)
print(userdata) -- userdata 0xsomething211f228
meta.__tostring = function()
return 'name'
end
print(userdata) -- name
Giving values
Now what if you wanted to change that name or maybe make a custom Instance?
Lets create a new dictionary with all internal data!
local userdata = newproxy(true)
local meta = getmetatable(userdata)
local internal = {}
internal.Name = 'something' -- Add a value to the internal dictionary
meta.__tostring = function(t)
return t.Name
end
meta.__index = internal
print(userdata) -- name
print(userdata.Name) -- name
userdata.Name = 'something else' -- errors
Changing values
But what if we want to change the name?
Well just add a __newindex
metamethod!
local userdata = newproxy(true)
local meta = getmetatable(userdata)
local internal = {}
internal.Name = 'something' -- Add a value to the internal dictionary
meta.__tostring = function(t)
return t.Name
end
meta.__index = internal
meta.__newindex = internal
print(userdata.Name) -- something
userdata.Name = 'something else'
print(userdata.Name) -- something else
Conclusion
Now why would you use userdata? It just seems like a complex and harder table with fancy words.
Well in the grand scheme of things, its pretty useless unless you’re trying to make something very complex which requires such things as change tracking etc. But to me its still fun to know.
This was a bit of a basic guide and only included what I fully understood, click this topic for more in depth explanation.
Fell free to comment if I got anything wrong or if I missed something.
Thanks for reading,
Dandcx
Simple Custom Instance with newproxy
I was bored so I decided to try and replicate a custom instance (since this is probably the closest you’ll get)
local function CreateProperty(container, name, valuetype, value, locked)
local property = {}
property.Name = name
property.ValueType = valuetype
property.Value = value
property.Locked = locked or false
container[name] = property
return property
end
local function CreateCustomInstance(name, classname, properties)
local userdata = newproxy(true)
local meta = getmetatable(userdata)
local internal = {}
CreateProperty(internal, 'Name', 'string', name, false)
CreateProperty(internal, 'ClassName', 'string', classname, true)
CreateProperty(internal, 'Parent', 'userdata', nil, false)
CreateProperty(internal, 'Archivable', 'boolean', true, false)
for i,v in pairs(properties) do
CreateProperty(internal, i, type(v), v, false)
end
meta.__tostring = function(self)
return self.Name
end
meta.__index = function(self, i)
local property = internal[i]
if property then
return property.Value
end
end
meta.__newindex = function(self, i, v)
local property = internal[i]
if property and not property.Locked and type(v) == property.ValueType then
property.Value = v
end
end
return userdata
end
local custom = CreateCustomInstance('a thing', 'CustomInstance', {
SomeProperty = true,
AnotherProperty = 'aaaaa'
})
print(custom.Name) -- a thing