Hold on, before you read the 17 paragraph miniature community tutorial I’ve prepared for you, I’ll dumb down the question for you: how could I check to see if an instance has a property without using an Instance.new() statement? If your wondering why I would use an Instance.new() statement in the first place, or by what I even mean, or are just *slightly unsure, then just go ahead and read the 17 paragraphs. Should only take a few minutes (depending on how fast you read) and should thoroughly explain some of my thought process.
Oh yeah, one last thing, the script functions as intended, it’s not a problem with the results. It’s just that crashing everything after a fraction of a second after hitting run isn’t ideal.
-
I’m trying to achieve a table containing all the referenceable properties of every instance via an API-Dump. Don’t ask why, won’t help.
-
A singular Instance.new() statement used to briefly create an object and check if a property is referenceable is enough to crash studio and the server.
-
I have experimented with replacing the Instance.new() statement with an empty table (which does not error in this use case, just makes the section of the script ineffective and useless, while still allowing me to debug) resulting in the server and studio not crashing.
The reason why I’m using Instance.new() in the first place is because it creates an object, this and that the script will error when I try to reference a property that isn’t accessible/referenceable via script or outright does not have.
Since I have to include inheritance in my property fetching script (unless the only property a part has is “Shape”), I also have to include the properties of the classes it inherits from, and the classes those inherit from, and so on.
This leads to a simple part, amassing a total of 85 properties, from each of the classes it inherited from.
Now, most of these properties actually can be accessed via directly referencing them to the part. The problem is that, some properties for example “Pivot Offset Orientation” and “Pivot Offset Position”, are actually components of other properties. In this case, they are components of the “Pivot Offset”. If you were to edit “Pivot Offset”, both “Pivot Offset Orientation” and “Pivot Offset Position” would change respectively.
This means that if a script were to try and access one of the components of a property, it might error. You may be thinking “why don’t you just write that script specifically not to do that?” A part is one class. What I’m trying to do is get the properties of *every class.
Ok, now that you hopefully understand, let’s (finally) discuss how we would even check all this mumbo jumbo for if you can directly reference a property.
Well, remember earlier how we discussed how a script would error when referencing properties that don’t exist or can’t be directly referenced? We can actually use that to our advantage. I’m gonna assume you know how pcalls work, if you don’t; their actually quite simple.
They basically tell you if a chunk of code runs without erroring, or errors and then provides you with the error message (in oversimplified terms).
If you didn’t know, calling part["Size"]
is the same as calling part.Size
. We can use this to plug in variables (provided that they are strings) into the property parameter.
Combining this with a pcall gets us something looking like this:
local partHasProperty, errorMessage = pcall(function()
local t = part[property] --[[ let's say for example, property = "Size" ]]
end)
And since the first return value from a pcall is actually a boolean, we can just go
if partHasProperty then
--do something
end
Now that we’ve established how to check if something has a certain property, it’s time to throw you in the deep end.
local ClassData = {}
local proxyAddress = "roproxy.com"
local API = game:GetService("HttpService"):JSONDecode(game:GetService("HttpService"):GetAsync("http://setup."..proxyAddress.."/"..game:GetService("HttpService"):GetAsync("http://setup."..proxyAddress.."/versionQTStudio").."-API-Dump.json"))
for _, class in pairs(API.Classes) do
local propertyTable = {Name = class.Name, Superclass = class.Superclass, Properties = {}}
for _, property in pairs(class.Members) do
if property.MemberType == "Property" then
table.insert(propertyTable.Properties, property.Name)
end
end
ClassData[class.Name] = propertyTable
end
for _, class in pairs(ClassData) do --[[ inherit properties from all superclass ancestors ]]
local unreferencableProperties = {}
if class.Tags and class.Tags.NotCreatable then else
local object = false
pcall(function()
object = Instance.new(class.Name)
end)
if object then
local current = class
while current.Superclass and (current.Superclass ~= "<<<ROOT>>>") do --[[ <<<ROOT>>> is the highest class in the class hiechary ]]
current = ClassData[current.Superclass]
for i, propertyName in pairs(current.Properties) do
if not(table.find(class.Properties, propertyName)) then
local hasProperty,_ = pcall(function() --[[ check if property is referenceable ]]
local t = object[propertyName]
end)
if hasProperty then --[[ prevent unreferenceable properties from being added ]]
table.insert(class.Properties, current.Properties[i])
else
table.insert(unreferencableProperties, current.Properties[i]) --[[ for debugging ]]
end
end
end
end
pcall(function()
object:Destroy()
end)
end
end
if #unreferencableProperties > 0 then
print(unreferencableProperties, class.Name) --[[ for debugging ]]
end
end
print(ClassData)
print(ClassData.Part)
Now if you go to the part that says --[[ inherit properties from all superclass ancestors ]]
, you’ll find an Instance.new() statement. This is the very Instance.new() statement I was talking about 200 paragraphs earlier that is able to single-handedly crash my studio and the server. It’s probably because there’s an obscene amount of classes in roblox (you got the ones you use every day, and the ones you didn’t even know existed). And for each one of those classes that are creatable via an Instance.new() statement, I created it to do the property reference check thing. You can also see a object:Destroy() at the bottom after it’s done with it, everything still crashes, unnoticeable difference.
So to dumb this entire post down, how could I check to see if an instance has a property without using an Instance.new() statement? Also if there are any tips how to achieve the same functionality without having so many… nested for loops all over the place that would also be greatly appreciated.
If you still don’t understand go check out these posts: