can someone help me figure out how i would get the properties of an instance, incase the properties are different than default?
No, there are many normal properties with a Write value of 0, same with Read. I do wish this would be expanded on. The documentation currently isn’t that great either, as they mention SecurityCapabilities and give examples, but there isn’t a proper section or page regarding it.
In any case, I’ve been working on an API Service Lite module, which would simplify this and filter out the extra stuff, but I can’t finish it without Roblox adding the extra needed tags like the “Hidden” tag. I’m thinking of publishing an early version of the module that uses a pre-defined dictionary of properties that are meant to be Hidden, just to filter them out that way for now. Hopefully that table won’t be too big or it’ll get flagged by automatic moderation for being suspicious. I’ve also been planning an API Service Lite Extended module, which would be the same as the base Lite version, but also including Events and Methods (until the ReflectionService supports it natively, then it’ll all be combined together).
This might be a bit complicated as Roblox has recently made it possible to change the default properties in Studio. So, it depends if plugins respect that or not, not to mention the potential conflictions in Team Create.
In any case, you could probably discover the default properties by inserting a new instance of that class and reading through its properties. Save that into a cache so that you don’t have to do that every time the same class is called. Obviously, clean up the inserted instance. Then you can use that to compare against the other instances of the same class, to see if they differ.
Found a bug that crashes studio
game:GetService("ReflectionService"):GetClass("<<<ROOT>>>")
Doubt people would actually use it like this but this service opens so much more plugin functionality and just scripting in general.
Will definitely use it
This is what I did, it’s not the best code and I’m just experimenting.
local function GetChangedPropertiesOfInstance(instance: Instance)
local Properties = ReflectionService:GetPropertiesOfClass(instance.ClassName)
local Defaults: Instance = Instance.new(instance.ClassName)
local Changed = {}
for _, Property in ipairs(Properties) do
if not Property.Serialized then continue end
pcall(function()
if instance:IsPropertyModified(Property.Name) then
if Types[Property.Type.ScriptType] then
local Typ = Types[Property.Type.ScriptType]
Changed[Property.Name] = Typ(instance[Property.Name])
else
Changed[Property.Name] = instance[Property.Name]
end
end
end)
end
Defaults:Destroy()
return Changed
end
This feels like searching for google on google.
local game = game ahh script
Wait WHAT
Does this mean my network engine can finally get automatic Instance buffer encoding Implemented without having to use download an api dump every time the game runs ![]()
Yes, but do note that it currently doesn’t provide tags for properties. You can check for read/write permissions and deprecation, but you can’t currently check if a property is Hidden. Hopefully they add Tags in very soon.
I’ve generated an array of properties that have the Hidden property, which I would recommend converting into a dictionary, but it’s still a huge amount of text unfortunately:
Hidden Properties Array
(json)
return '["A","AbsolutePositionWrite","AbsolutePositionWrite","AbsoluteSizeWrite","AbsoluteSizeWrite","AccessList","AccountAgeReplicate","AcquisitionMethod","Active","Active","Active","ActiveInstance","ActiveQueryNames","AdditionalLuaState","Adornee","AdorneeOffset","AeroMeshData","AlignDraggedObjects","AllThreadsPaused","AllowCustomAnimations","AllowSleep","AlternateMeshHash","AnchorPoint","Animation","AnnotationsLoadingStatus","AnnotationsVisible","AppearanceDidLoad","AssetId","AssetId","AttachmentForward","AttachmentPos","AttachmentRight","AttachmentUp","Attributes","AttributesReplicate","AttributesSerialize","AudioAnimationEnabled","AudioApiByDefault","AuroraScriptBindingsSerialize","AuthorColor3","AuthorId","AuthoredHipHeight","AvatarJointUpgrade_SerializedRollout","AvgMetalness","AvgRoughness","B","BackParamA","BackParamB","BackSurfaceInput","BackendAccoutrementState","BackgroundColor","Bevel","Bevel Roundness","BiometricDataConsent","BorderColor","BottomBarSize","BottomParamA","BottomParamB","BottomSurfaceInput","Breakpoint","BufferFullInputCount","Bulge","C","C0","C1","CFrame","CFrame0","CFrame1","CachedData","CachedRemoteSource","CachedRemoteSourceLoadState","CameraCFrame","CameraFieldOfView","CameraID","CameraMaxDistance","CameraMinDistance","CameraMode","CameraYInverted","CanAutoUpdate","ChannelId","ChararacterRegionId","ChatAvailabilityStatus","ChatMode","ChatPrivacyMode","ChatTranslationEnabled","ChatTranslationFTUXShown","ChatTranslationFTUXShown","ChatTranslationLocale","ChatTranslationToggleEnabled","ChatTranslationToggleEnabled","Checked","ChildData","ChildData","ChildData2","ChildOrder","ClientFeatures","ClientFeaturesInitialized","ClippedRect","CloudEditCameraCoordinateFrame","CloudEditPlayerActive","ClusterGrid","ClusterGridV2","ClusterGridV3","CollaboratorColor","CollaboratorColor3","CollisionGroupData","CollisionGroupReplicate","CollisionGroups","Color","Color","Color3uint8","ColorMapContent","Command","CompletedTutorials","ComponentIndex","ComputerCameraMovementChanged","ComputerMovementChanged","Condition","Condition","ConditionsSerialize","Confidential","Confidential","Confidential","Confidential","ConstrainedValue","ConstrainedValue","ContentImageSize","ContentImageSize","Contents","Contents","ContextDataInternal","ContinueExecution","ContinueExecution","ConvexDecompCompressed","ConvexDecompHolder","CoordinateFrame","CoreEffectFolder","CoreGuiFolder","CoreGuiNavigationEnabled","CoreScriptIdentifier","CountryRegionCodeReplicate","CreationTimeUnix","CurDocGUID","CurScriptLineNumber","CurrentDataModelType","CustomPoliciesEnabled","DCDPropertyData","DataComplexity","DataComplexityLimit","DataCost","DataModelPlaceVersion","DataReady","DefaultCameraID","DefaultShortcut","DefinesCapabilities","DevelopmentLanguage","DidPointerHit","DisplayName","Doc View Code Background Color","DragBeginConnectionCount","DragStoppedConnectionCount","DraggingScrollBar","DraggingV1","EditableStatus","Elasticity","EmotesDataInternal","EmulatedCountryCode","EmulatedGameLocale","EmulatedTotalMemoryInMB","EnableFRM","EnableFallbackAudioInput","EnableOnTypeAutocomplete","EnableScriptCollabByDefaultOnLoad","Enabled","Enabled","Enabled","EntityData","EntityLodEnabled","EntityPosition","EntityScale","EntitySource","EquippedEmotesDataInternal","ErrorMessage","ExceptionText","ExperienceNameOverlayEnabled","ExplicitAutoJoints","ExtentsMax","ExtentsMin","FACSDataLod","FaceTrackingStatusEnum","FacsReplicationData","FilteringEnabled","FlipHeadOrientation","FluidFidelityInternal","FocusedDataModelSession","FollowUserIdReplicated","Font","Font","Font","Font","ForceCSGv2","ForcePlayModeGameLocaleId","ForcePlayModeRobloxLocaleId","ForceR15","FormFactor","FrameCount","FrameId","FrameName","FrameType","FramerateCap","FreeMemoryMBytes","Friction","FrontParamA","FrontParamB","FrontSurfaceInput","GameAvatarType","GameSettingsAssetIDFace","GameSettingsAssetIDHead","GameSettingsAssetIDLeftArm","GameSettingsAssetIDLeftLeg","GameSettingsAssetIDPants","GameSettingsAssetIDRightArm","GameSettingsAssetIDRightLeg","GameSettingsAssetIDShirt","GameSettingsAssetIDTeeShirt","GameSettingsAssetIDTorso","GameSettingsAvatar","GameSettingsR15Collision","GameSettingsScaleRangeBodyType","GameSettingsScaleRangeHead","GameSettingsScaleRangeHeight","GameSettingsScaleRangeProportion","GameSettingsScaleRangeWidth","GameSourceLanguageId","GameplayPaused","GizmoReference","Globals","GridV3","GripForward","GripPos","GripRight","GripUp","Guest","Guid","GuidBinaryString","HSRData","HSRData","HSRMeshIdData","HSRMeshIdData","HapticStrength","HasAssociatedDrafts","HasError","HasJointOffset","HasMigratedSettingsToTestService","HasMultiTouchStarted","HasNewVersion","HasSeenDeprecationDialog","HasSkinnedMesh","Health_XML","HiddenSelectionEnabled","HistoryId","HorizontalBarRect","HorizontalCurvature","HorizontalPadding","HostDataModelType","HostDataModelTypeIsCurrent","HoverInstance","HoverLineThickness","Hovered","Id","Id","Id","ImageData","ImportInProcess","Index","Index","InertiaMigrated","InitialCameraCFrame","InitialSize","InitialSize","InputBindingMappingsRaw","InputDropRate","InputPinData","InstalledPluginData","InternalBodyScale","InternalCharacterAppearanceLoaded","InternalDisplayName","InternalHeadScale","InternalOriginalHipHeight","InterpolationThrottling","Is30FpsThrottleEnabled","IsArrowVisible","IsAutoMigrated","IsConnected","IsDifferentFromFileSystem","IsError","IsExemptFromUGCAnalytics","IsFocusedWrite","IsIdle","IsInBackground","IsInCaptureMode","IsLegacyChatDisabled","IsLogpoint","IsLuaChatEnabled","IsLuobuServer","IsMirrored","IsMultiTouchEmulationOn","IsMultiTouchEnabled","IsNewExpForAudioApiByDefault","IsNextVisible","IsNotOccluded","IsPaused","IsPaused","IsPlaying","IsPlaying","IsReplicatedCopy","IsReplicatedCopy","IsSFFlagsLoaded","IsSlimEnabled","IsSpatial","IsSuccess","IsTextScraperRunning","IsUsingCameraYInverted","IsUsingGamepadCameraSensitivity","JointOffset","JumpReplicate","LaserDistance","LastModifiedTimeUnix","LastUsedModificationMethod","LeftLeg","LeftParamA","LeftParamB","LeftSurfaceInput","LegacyInputEventsEnabled","LegacyNamingScheme","LimitEnabled","Line","Line","Line","LineThickness","LinearImpulse","LoadCharacterLayeredClothing","LoadingReplies","LocalSimulationValidation","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocalTransparencyModifier","LocaleId","LocaleManifest","LocalizationMatchIdentifier","LocalizationMatchIdentifier","LocalizationMatchIdentifier","LocalizationMatchedSourceText","LocalizationMatchedSourceText","LocalizationMatchedSourceText","Localize","LocalizedPlaceholderText","LocalizedText","LocalizedText","Locals","LodEntity","LogMessage","LogMessage","LuaDebuggerEnabledAtStartup","LuobuWhitelisted","ManifoldMesh_DEPRECATED","ManualFocusRelease","MaterialVariantSerialized","MaxCanvasPosition","MaxFrequency","MaxFrictionTorqueXml","MaxPlayersInternal","MaxSimulationRadius","MaxSize","MaximumSimulationRadius","MembershipTypeReplicate","MeshData","MeshData","MeshData","MeshData2","MeshID","Message","MessageId","MetaBreakpointId","MetalnessMap","MetalnessMapContent","MicroProfilerWebServerEnabled","MicroProfilerWebServerIP","MicroProfilerWebServerPort","Mode","ModelMeshCFrame","ModelMeshData","ModelMeshSize","ModifiedState","MouseButton1ClickConnectionCount","MouseButton1DownConnectionCount","MouseButton1DownConnectionCount","MouseButton1DownConnectionCount","MouseButton1UpConnectionCount","MouseButton1UpConnectionCount","MouseButton1UpConnectionCount","MouseButton2ClickConnectionCount","MouseButton2DownConnectionCount","MouseButton2UpConnectionCount","MouseDragConnectionCount","MouseDragConnectionCount","MouseEnterConnectionCount","MouseEnterConnectionCount","MouseEnterConnectionCount","MouseLeaveConnectionCount","MouseLeaveConnectionCount","MouseLeaveConnectionCount","MouseMovedConnectionCount","MouseSensitivityFirstPerson","MouseSensitivityThirdPerson","MouseWheelBackwardConnectionCount","MouseWheelForwardConnectionCount","MoveDirectionInternal","MoveState","MultipleDocumentInterfaceInstance","Name","NavBarSize","NeedsPivotMigration","NetworkHumanoidState","NetworkIsSleeping","NetworkOwnerV3","NetworkOwnershipRule","NormalMap","NormalMapContent","NumberEmotesLoaded","OffCentered","Offset","OnScreenKeyboardAnimationDuration","OnScreenProfilerEnabled","OnTopOfCoreBlur","OpenCertManagerDialog","Orientation","Orientation","Orientation","OsPlatform","OutOfOrderInputCount","Outfit1","Outfit2","OverlayFont","OverlayNativeInput","OverrideDefaultCollisions","OverrideMouseIconBehavior","PackageGuid","PackageIdSerialize","Part0","Part0Internal","Part1","Part1Internal","PartyId","PerformanceStatsVisible","PersistedCurrentValue","PhysicalConfigData","PhysicalDragClickedPart","PhysicalDragHitPoint","PhysicalDragIsInVR","PhysicalDragTargetFrame","PhysicsData","PhysicsData","PhysicsEnvironmentalThrottle","PhysicsGrid","PhysicsRepRootPart","PhysicsStepTime","PivotPosition","PivotSnapToGeometry","PlatformName","PlayerEmulationEnabled","PlayerHeight","PlayingReplicating","PlayingReplicating","PlayingReplicator","Plugin","PointerHitCFrame","Populated","Populated","Populated","PortalVersion","Position","Position","Position","PreferredPlayersInternal","PreferredTextSize","PreferredTransparency","PreferredTransparency","PreviousOperation","Priority","ProcessUserInput","PropertiesSerialize","PropertiesSerialize","PropertyStatusStudio","PseudolocalizationEnabled","QualityResetLevel","QuestASWState","QuestDisplayRefreshRate","R15CollisionType","RCCHeartbeatFPS","Range","RawJoinData","RawRect2D","ReadAloud","Reason","ReceiveAge","ReducedMotion","ReducedMotionEnabled","RemoveOnHit","RemoveOnHit","RenderFidelityReplicate","RenderMode","ReplicateCurrentAngle","ReplicateCurrentAngle6D","ReplicateCurrentOffset6D","ReplicatedGuiInsertionOrder","ReplicatedInsertionOrder","ReplicationPV","ReplyCount","RequestId","ReservedId","ResetIncludesBodyParts","ResolutionScale","Resolved","ResolvedLoadingStatus","ReturnKeyType","RightBarSize","RightLeg","RightParamA","RightParamB","RightSurfaceInput","RobloxForcePlayModeGameLocaleId","RobloxForcePlayModeRobloxLocaleId","RobloxLocked","RollOffGain","Root","RotVelocity","Rotation","RotationType","RoughnessMap","RoughnessMapContent","RowName","SandboxedSource","ScaleFactor","Script","Script","Script","ScriptCollabEnabled","ScriptCollabVersionHistoryEnabled","ScriptEditorMenuBorderColor","ScriptEditorShouldShowPluginMethods","ScriptGuid","ScriptGuid","ScriptsDisabled","ScrollRate","ScrollVelocity","Selected","SelectedCoreObject","SelectionBoxThickness","SelectionLineThickness","SelectionMode","SelectionRect2D","SerializedEmulatedPolicyInfo","SerializedOperationGraph","ServerFeatures","ServerGitHash","ServerLiveEditingMode","ServerLogPrefix","ServiceState","ServiceVisibility","SessionId","SessionName","Shape","ShouldEmitReturnEvents","ShouldEmitTabEvents","ShouldEmitUpAndDownArrowEvents","ShouldUseCloudTable","ShowActiveInstanceHighlight","SignalBehavior2","SimulationRadius","Size","SlimHash","SmoothGrid","SmoothGrid","SmoothScroll","SmoothVoxelsUpgraded","SolidMeshHolder","SolidMeshHolder","SourceAssetId","State","Status","Status","StatusBarSize","Strafe","StreamingPauseMode","StudioDefaultStyleSheet","StudioInsertWidgetLayerCollectorAutoLinkStyleSheet","StudioSelectionBox","SuperSafeChatReplicate","SurfaceColor","SurfaceColor","TaggedUsers","Tags","Teleported","TeleportedIn","TemporaryCageMeshId","TemporaryReferenceId","TerrainWeldsFixed","Text","TextColor","TextColor","TextColor","TextElongationFactor","TextInputType","TextureName","TexturePack","TexturePack","TexturePackMetadata","Thickness","ThreadId","ThreadId","ThreadName","TimePositionReplicating","TimePositionReplicator","Timeout","Timeout","Title","TooOldInputCount","TopParamA","TopParamB","TopSurfaceInput","Torso","TotalGroupScale","TouchCameraMovementChanged","TouchMovementChanged","TrackerMode","TrackerType","Transform","TransformedCFrame","Transparency","Type","TypeColor","UI Theme","UiNavigationKeyBindEnabled","UnfilteredChat","UnscaledCofm","UnscaledVolInertiaDiags","UnscaledVolInertiaOffDiags","UnscaledVolume","Upvalues","UsageContextPermission","Use2022MaterialsXml","UseNewAudioApi","UseNewControlPaths","UseNewJoinFlow","UseStreamSwitching","UserId","UserIdReplicated","Username","UsernameOverlayEnabled","UsesAssetInsertionDrag","VIPServerId","VIPServerOwnerId","VRComfortSetting","VRDevice","VRDeviceAvailable","VRDeviceName","VREnabled","VRSafetyBubbleMode","VRSessionState","VRSmoothRotationEnabledCustomOption","VRThirdPersonFollowCamEnabled","VRThirdPersonFollowCamEnabledCustomOption","Valid","Valid","Value","Value","ValuesAndTimes","ValuesAndTimes","ValuesAndTimes","ValuesAndTimes","VariableId","VariablesCount","Velocity","Verified","Verified","VersionIdSerialize","VertexCount","VerticalBarRect","VerticalPadding","VideoAnimationEnabled","VignetteEnabledCustomOption","VoiceChatEnabledForPlaceOnRcc","VoiceChatEnabledForUniverseOnRcc","VoiceChatState","WalkAngleError","WalkDirection","WaveformData","WeightCurrent","WeightTarget","WorldOrientation","WorldPivotData","WorldPosition","WorldRotation","archivable","formFactor","formFactorRaw","gaID","heat_xml","hit","isPlayerScript","label","line","localPlayer","name","numExpectedDirectChildren","numPlayers","opacity_xml","parent","part1","postTransform","preTransform","riseVelocity_xml","shap","shape","siz","size","size_xml","size_xml","style","transform","value","value","xmlRead_MaxDistance_3","xmlRead_MinDistance_3"]'
Some of these hidden properties shouldn’t actually be hidden, so consider manually filtering through this.
This is great! As soon as we get access to all members I will be able to use this to drastically optimize my custom intellisense provider, and make things so much easier. In fact I couldnt upload the plugin to the plugin store because (probably) keeping a json string copy of the api dump inside of the plugin marked it as obfuscated or too long to moderate and got it taken down. With the only other option being HttpService which is slow and requires a lot of extra processing, as well as prompting the end user.
Will ReflectionService also allow us to access datatype information associated with the engine? Because currently the only way to dynamically get datatype info is to scrape it from the docs, which is unfavorable and not sustainable for public facing plugins.
Probably not, because the core point of DataTypes is that we only introduce them when we need some bespoke mechanics that don’t follow the usual patterns, making it hard to accurately describe them with metadata.
APIs we add these days that take or return random one-off blobs of data do it the form of a table with a specific table shape rather than a bespoke DataType. For those table shapes we will be able to provide metadata about the structure.
So while you still may need to hardcode the things you care about for DataTypes, seeing a new one added should be pretty rare and not present an unworkable maintenance burden.
Could we still get Member Tags like Hidden? That’s the only thing stopping me from using this right now.
I already have a temporary solution, but as @intykat has said, the automatic moderation doesn’t typically like large scripts, regardless of their actual content:
I figure that would be a direct port from the API dump, considering that it’s just a basic array.
We’re trying to avoid exposing “Hidden” here because “Hidden” is not a well defined concept. The only purpose of the hidden tag is to hide things in the Properties pane, but as part of the properties pane rewrite there won’t be one single source of truth on what’s hidden anymore, different properties will be hidden or visible depending on the context. Even in the current properties pane many properties are conditionally visible depending on the value of another property.
Deprecated is really the only “hidden” metadata that is well defined. Anything else is fair game for a script with the relevant security permissions to go fetch.
What would be the solution then? I don’t want to show properties that would normally be hidden in the property pane, given the context. But currently, that doesn’t seem to be possible? Will there be another way to do this?
This may be a more useful topic to circle back to next year once you see exactly what we’ve done with the Properties pane rewrite.
For now I would say that showing almost every non-deprecated member that a script would have access to read/write is not a bad solution. Especially if augmented with a small list of special case things that you subjectively think make sense to hide. I don’t think you’d need a very long list of special cases to get something you’re satisfied with.
Specifically there’s a fair bit of redundancy between these pieces of metadata: There’s not actually that many hidden-but-still-accessible-and-not-deprecated members. Some of the few there are arguably shouldn’t be hidden to boot.
Been waiting for this forever, god bless ya’ll for finally releasing it! ![]()
So far i’ve only encountered one minor issue, which is that ‘Lighting’ returns an ‘Outlines’ property even though said property seems to no longer exist (I figure there’s more cases like that, but that’s the only one i’ve encountered so far), so I figured I may as well report it.
Here’s what i’m using to get the properties:
local function GetProperties(ClassName: string): {string}
local Properties = {}
for _, Property in ReflectionService:GetPropertiesOfClass(ClassName, {ExcludeInherited = true, ExcludeDisplay = true}) do
if Property.Permits.Write and Property.Permits.Read then
table.insert(Properties, Property.Name)
end
end
return Properties
end
And here’s an ‘ObjValue’ tree generated with it:
Aside from that this works like a charm, only thing i’m personally missing is a way to get instance properties in type form with something other than:
type LightingProperties = {[keyof<Lighting>]: index<Lighting, keyof<Lighting>>}
Which doesn’t give me the filtered properties ‘ReflectionService’ would, but I figure that’s outside the scope of the feature (or i’m simply missing something on my end).
Nonetheless thanks a bunch, this on it’s own is going to save me a lot of time manually writting down each instance property.
While it no longer does anything, the Lighting.Outlines property very much still exists:
print(game.Lighting.Outlines) - Studio
11:40:44.385 false - Edit
Most likely what you want to do here is exclude Deprecated properties with an added check of Property.Display.DeprecationMessage == nil which will exclude Lighting.Outlines.
Oh, I figured since it no longer did anything it wouldn’t exist, my bad for not checking, will use that additional check going forward.
The reason these deprecated properties often still exist is to try to avoid breaking scripts which accessed them for some reason. Those scripts would definitely break if the property were actually removed but may mostly still work if the property is just changed to not do anything instead.
Is there a way to quickly figure out if an instance has a certain property?
Currently, the properties are provided in an array where the keys are indexes rather than property names, which makes it really expensive to search for certain properties within the list.
Also why are we not able to filter properties by their properties? For example if I only want writable properties, I am unable to do so right now.
