API Method to easily get the properties of an object

Edit: This thread is still being brought up so and at the time, clarification on the true desired goal was hazy so I thought i’d update the thread. The true goal here is to have access to a list of an Instance’s properties. Right now, people use API dumps to accomplish this, but having to use external sources is not really ideal especially in terms of maintainability.

Some use cases as specified in earlier discussions:

Currently, getting and setting properties can be a time consuming task. 2 additions and 1 change in the API would allow use to easily get and set a mass of properties with ease.

API Addition #1:
A :GetProperties() method. This method will put all of the property details in a single table and return it. You can then set this to a variable and use it, similar to :GetChildren()

Edit: The :GetProperty() method should also take optional parameters. This optional parameter will either get a specific property (or group of properties), a property categorization (Appearance, Data, Behavior etc) or it gets all of the properties if left blank.
Example:
local PropTable = Workspace.Part:GetProperties()

Returns Table with all properties

local PropTable = Workspace.Part:GetProperties(“Appearance”)

Returns table with properties under the appearance categorization as shown in the properties panel.

local PropTable = Workspace.Part:GetProperties(“BrickColor”,“Material”,“Name”)

Returns a table with the BrickColor, Material, and Name properties.

API Addition #2:
A :SetProperties(Table) method. This works together with the :GetProperties method. If the code behind the method can detect any correct values in the table and match it with the object’s properties then apply the changes to the part.
Example:
local PropTable = Workspace.Part:GetProperties()
Workspace.Part2:SetProperties(PropTable)

API Change #1:
This change adds a new parameter to Instance.new(), it will take a table as a 3rd parameter and basically do the same thing as the :SetProperties method. It will read the properties of the table and apply it to the newly instanced part. This is a good way for coders to setup their own default properties for their instanced part.

local NewPart = Instance.new(“Part”,Workspace,PropTable)

I think these additions will help improve the workflow for coders and overall make certain task that have to do with properties easier.

There may be a big question that comes up with “You can already do this yourself.”
While yes, you can, It’s just a very annoying thing to do. Nobody wants to set all of the parts individually or set all the parts themselves in a table. These API changes just saves time and makes it easier rather than it being a nuisance. Practically the same reason API things like :GetChildren() and the parent parameter for Instance.new() is here.

EDIT:

Changes to the :GetProperty have been changed. I have added added optional parameters in which you can see by referencing back to the property explanation.

Editing this thread to address on “Why do I want this?”
One obvious thing is that it helps make code cleaner. You can get the properties in a single method instead of spending several lines getting them.

Also, these methods overall provides a nice property handling solution again because you don’t have to do it all one by one.

Any feedback is appreciated!

61 Likes

Also “why would you need this”.

9 Likes

YES, :D!

EDIT: But one problem, how would you know which property goes first? Like, does name go first, size, anchored, etc.

Also “why would you need this”.[/quote]

I personally haven’t come across a situation in which I need these changes. Then again I haven’t been coding an actual project for a while. Waiting until I improve my Lua skills atm.

The main reason I wanted to suggest these changes is because of in a thread someone mentioned about setting the default properties of an instanced object. This approach simply lets you do that while leaving open these API methods for anyone who might need to get and set a mass of properties at once with ease. Ontop of these methods making things easier for cleaner code, it actually provides a decent solution to getting a ton of properties at once and being able to apply them rather than getting each one 1 by 1. Perhaps Osyris recommendation may be more useful. Nevertheless, I don’t think this implementation would cause any harm and would probably help a few people.

[quote] YES, :D!

EDIT: But one problem, how would you know which property goes first? Like, does name go first, size, anchored, etc. [/quote]

If this feature were to be implemented, there could be many formats. I would assume the layout would be the exact layout of how it is displayed in the properties section. However, there could be multiple approaches such as:
local Tab = {BrickColor = BrickColor.new(),Material = “Plastic”}
Basically just putting them all in a table or you can categorize them by their categorys in the property window (Appearance, data etc)
local Tab = {Appearance = {BrickColor = BrickColor.new()},Data = {Name = "Part}}

1 Like

This could come in handy.

5 Likes

For the third parameter of Instance.new, you can easily replace that with some RbxUtility functions:

local Create = assert(LoadLibrary('RbxUtility"), "Couldn't load RbxUtility!").Create
local Part = Create "Part" {
     Parent     = Workspace;
     Name       = "Something";
     Anchored   = true;
     [Create.E "Touched"] = function()
          print("Touched")
     end
}
1 Like

You may find this interesting: http://blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx

You may find this interesting: http://blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx[/quote]

Interesting read. I can understand the point of view of the poster.
It makes me retract that statement because you could say “eh wouldn’t hurt” for just about any implementation and when implementing things it needs to be considered carefully when deciding if it has enough use within the language and/or if a simplistic design for the feature that users can understand can be worked out.

I already supplied a good API usage examples that I personally think works well and is simplistic enough to understand.

Lets compare this to :GetChildren() Not only is it simple, it reduces complexity by providing an easy way to get descendants of an object instead of having to come up with a complex solution to that.

The methods I provided are indeed simple to use and easy to understand.
My main concern here with not having these methods is that it makes property manipulation difficult. There is no simple way to get a specific group of properties, or all of the properties you want to store for later with ease or without knowing the object’s properties beforehand. I wouldn’t be recommending this if you could just loop through the properties. I would even be fine with just the :GetProperty() method. I could probably handle it from there. It reduces complexity from having to retreive properties, API is simple and easy to use, and could prove to be quite useful.

Well, there does not seem to be any way of traversing the tree without GetChildren, since that content is completely dynamic.
By contrast, if you know the type of the instance, you know all properties that it has statically.

I think the only compelling usage example is custom serialization.

For the GetProperties() and SetProperties()

How would you represent nil?

I like GetProperties(), or any other method to get data from the API Dump.
That would be amazing, a new service “WikiService” or “ClassService” or “API Dump Thingy Service”.
That would just have methods as GetAllClasses(), GetClassHierarchie(), GetProperties(class), …
(A bit as I did in: http://wiki.roblox.com/index.php/Module:API/data Other wiki people already altered it a lot)

2 Likes

The other big use case is plugins. In fact, I just wrote an API Dump -> Giant Lua table parser just today to use in a plugin that I’m making, which will take a selected object in the game hierarchy, and generate a ModuleScript which when called creates the object in question. The idea being that the generated module is actually in a human-readable format, so that you can make further modifications to it in code.

Another example where we’ve needed a way to get metadata on the games team several times: In a “CreateShadowText” function. We need to know what properties to copy over to the shadow text objects when the original text object changes and what properties to not copy over because they are actually changes to locked / readonly properties, but we have no way of doing that without using a hard-coded lookup table of special cases, or by using pcall on every single property change.

Well, there does not seem to be any way of traversing the tree without GetChildren, since that content is completely dynamic.
By contrast, if you know the type of the instance, you know all properties that it has statically.

I think the only compelling usage example is custom serialization.[/quote]

That’s true. At the time I had some kind of complex idea that you could use the descendant API to loop through things and organize it based on that. That would be very unpractical though compared to :GetChildren()

[quote] For the GetProperties() and SetProperties()

How would you represent nil?

I like GetProperties(), or any other method to get data from the API Dump.
That would be amazing, a new service “WikiService” or “ClassService” or “API Dump Thingy Service”.
That would just have methods as GetAllClasses(), GetClassHierarchie(), GetProperties(class), …
(A bit as I did in: http://wiki.roblox.com/index.php/Module:API/data Other wiki people already altered it a lot) [/quote]

:GetProperties() would probably just return nil if you give it an invalid parameter.
If :SetProperties() doesn’t find any matches within the properties table then it would do nothing and issue out an error.

[quote] The other big use case is plugins. In fact, I just wrote an API Dump -> Giant Lua table parser just today to use in a plugin that I’m making, which will take a selected object in the game hierarchy, and generate a ModuleScript which when called creates the object in question. The idea being that the generated module is actually in a human-readable format, so that you can make further modifications to it in code.

Another example where we’ve needed a way to get metadata on the games team several times: In a “CreateShadowText” function. We need to know what properties to copy over to the shadow text objects when the original text object changes and what properties to not copy over because they are actually changes to locked / readonly properties, but we have no way of doing that without using a hard-coded lookup table of special cases, or by using pcall on every single property change. [/quote]

Thanks for providing some examples Stravant! I didn’t actually think of that.

These API additions wouldn’t be used all the time, but in special cases like what Stravant explained and for serialization purposes I could see these being useful. It’s true that you know what properties it has, but at first, but you may not know the values or need to keep track of the initial properties of multiple different objects as they dynamically change. And as I said, there is no simple way to get all of the properties at once, or a specific group easily without spending a bunch of time writing special property checking code.

I’ve seen recent issues where these API additions would prove useful. I would like to spark conversation on my age-old addition.

If you’re willing to enable HttpEnabled, you can just retrieve the contents of this page:
http://anaminus.github.io/rbx/raw/api/latest.txt

It’s not part of the ROBLOX domain so you wouldn’t need to use a proxy to access it. Plugins no longer require you to create a NetworkServer to use HttpService if that was an issue for you in the past.

[quote] If you’re willing to enable HttpEnabled, you can just retrieve the contents of this page:
http://anaminus.github.io/rbx/raw/api/latest.txt

It’s not part of the ROBLOX domain so you wouldn’t need to use a proxy to access it. Plugins no longer require you to create a NetworkServer to use HttpService if that was an issue for you in the past. [/quote]

While this is a neat solution, should we really need httpservice in order to have a maintenance free way of getting details about a object?

1 Like

No – the API dump and ReflectionMetadata should be included in a studio/client-readable location and we should be able to read the contents of those files. Regardless of what’s best though, if you don’t want to put your projects on hold for a year or three, HttpService is really your only option at this point.

That’s true. Based on the previous discussion, zeuxcg mostly didn’t see practical uses for this kind of thing. This is why I think this is a under-thought-about issue.

2 Likes

This kind of thing is too meta for use in actual games. The only real application here is for the development of games, so I think it’s better off staying outside the API. What I would prefer is improvements to the the API dump. Some things I’d like:

  • An API dump in a standard format (like JSON). The current API dump format has ambiguities that make it potentially difficult to parse (if the Studio settings class were ever added, all hell would break loose). This is also a good chance to include more detailed information, such as by incorporating ReflectionMetadata.
  • A reliable way to detect new versions of Roblox. What would great is a web API that receives a timestamp and returns a list of versions that were deployed after the given time.
  • A platform-independent way of getting API dumps (such as a web API). Right now, getting it depends on being able to run an executable and having all the required dependencies, which usually means running on Windows or some other non-Linux platform.

Another use would just be serialization methods for datastores.
Ex: Stravant’s Instance Encoder module and Merely’s Online Studio uses a parsed ReflectionMetadata that needs to be updated for new features.

1 Like

I’d like to be able to get the properties of an object, because of it’s use in making a script builder with a good properties, and workspace view to use as well, without being able to get the properties, you have to use a messy table of all known property names of Instances, and risk some instances erroring if it doesn’t allow you to index ClassName