Release Notes for 502

Notes for Release 502

55 Likes

Client Difference Log

API Changes

Added Class AnimationClipProvider : Instance [NotCreatable] [Service] [NotReplicated]
	Added Function AnimationClip AnimationClipProvider:GetAnimationClip(Content assetId) {PluginSecurity} [Preliminary]
	Added Function AnimationClip AnimationClipProvider:GetAnimationClipAsync(Content assetId) [Yields]
	Added Function AnimationClip AnimationClipProvider:GetAnimationClipById(int64 assetId, bool useCache) {PluginSecurity} [Preliminary]
	Added Function Instance AnimationClipProvider:GetAnimations(int64 userId) [Yields]
	Added Function Dictionary AnimationClipProvider:GetMemStats() {RobloxScriptSecurity}
	Added Function Content AnimationClipProvider:RegisterActiveAnimationClip(AnimationClip animationClip)
	Added Function Content AnimationClipProvider:RegisterAnimationClip(AnimationClip animationClip)

Added Class DataModelPatchService : Instance [NotCreatable] [Service] [NotReplicated]
	Added Function Instance DataModelPatchService:GetPatch(string patchName) {RobloxScriptSecurity}
	Added Function void DataModelPatchService:RegisterPatch(string patchName, string behaviorName, string localConfigPath, int64 userId) {RobloxScriptSecurity}
	Added Function void DataModelPatchService:UpdatePatch(int64 userId, string patchName, Function callbackFunction) {RobloxScriptSecurity}

Added Class LuauScriptAnalyzerService : Instance [NotCreatable] [Service] [NotReplicated]

Added Class PackageUIService : Instance [NotCreatable] [Service] [NotReplicated]
	Added Function void PackageUIService:ConvertToPackageUpload(string uploadUrl, Objects cloneInstances, Objects originalInstances) {RobloxScriptSecurity}
	Added Event PackageUIService.OnConvertToPackageResult(bool isSuccessful, string errorMessage) {RobloxScriptSecurity}
	Added Event PackageUIService.OnOpenConvertToPackagePlugin(Objects instances, string name, Objects cloneInstances) {RobloxScriptSecurity}

Added Class TemporaryScriptService : Instance [NotCreatable] [Service] [NotReplicated]

Added Property string MetaBreakpoint.LogMessage {RobloxScriptSecurity} [Hidden] [ReadOnly]
Added Property bool MetaBreakpoint.IsLogpoint {RobloxScriptSecurity} [Hidden] [ReadOnly]

Added Function void DebuggerUIService:EditBreakpoint(int metaBreakpointId) {RobloxScriptSecurity}

Added Event AssetImportService.SettingsChanged(string property)
Added Event ScriptChangeService.ScriptAdded(LuaSourceContainer script) {RobloxScriptSecurity}
Added Event ScriptChangeService.ScriptBeingRemoved(LuaSourceContainer script) {RobloxScriptSecurity}
Added Event ScriptChangeService.ScriptChanged(LuaSourceContainer script, string property) {RobloxScriptSecurity}
Added Event ScriptChangeService.ScriptFullNameChanged(LuaSourceContainer script) {RobloxScriptSecurity}
Added Event ScriptChangeService.ScriptSourceChanged(LuaSourceContainer script) {RobloxScriptSecurity}

Added Tag [NotCreatable] to Class VoiceChatService

Removed Function AssetImportService:UpdateSettings

(Click here for a syntax highlighted version!)

22 Likes

This is interesting, are these just constants inside their respective tables?
Could we also get Vector2.yAxis for consistency.

I also laugh at this again.

12 Likes

I’m liking this one a lot since I don’t enjoy doing math very much when transferring rotations to different translations.

26 Likes

Removed auto horizontal scrolling as it is hurting user’s experience.

By this does it mean it fixes this longstanding bug?

EDIT: Well never mind, it’s for another issue.

15 Likes

Here’s the complete list:

CFrame CFrame.identity = CFrame.new()
Vector3 Vector3.zero = Vector3.new()
Vector3 Vector3.one = Vector3.new(1, 1, 1)
Vector3 Vector3.xAxis = Vector3.new(1, 0, 0)
Vector3 Vector3.yAxis = Vector3.new(0, 1, 0)
Vector3 Vector3.zAxis = Vector3.new(0, 0, 1)
Vector2 Vector2.zero = Vector2.new()
Vector2 Vector2.one = Vector2.new(1, 1)
Vector2 Vector2.xAxis = Vector2.new(1, 0)
Vector2 Vector2.yAxis = Vector2.new(0, 1)
26 Likes

I feel like these should be UPPER_SNAKE_CASE since they’re constants.

10 Likes

I agree with @pobammer… I love it but am not a fan of the naming. Nothing else aside from data type constructors begin with lowercase letters. I would personally prefer CamelCase or UPPER_SNAKE_CASE for these, however the latter breaks conventions too.

Has CamelCase been considered?

12 Likes

All variants have been considered.

At excruciating length in fact: I actually implemented these 2 months ago, but left them sitting uncommitted until recently because I kept going back and forth internally and with some coworkers over whether the current casing was really the best one to use.

32 Likes

I would disagree considering it follows suit with API such as math.pi and math.huge.

6 Likes

Unfortunately not :slightly_frowning_face:

Tested it on a fresh baseplate to make sure that any PlayerModule customization didn’t get in the way of this, still no good results.

13 Likes

Judging by the FFlag’s name, I believe it’s related to this:

image

5 Likes

It’s really confusing when you type camelCase in the form of PascalCase. Which one is it you’re referring to?

1 Like

PascalCase, I got a little mixed up. :flushed:

3 Likes

Ever since this update, the following require that I use in most of my scripts has become an unsupported path; no longer autofills and throws a warning:

local MyModule = require(game:GetService("ReplicatedStorage"):WaitForChild("ModuleName"))
4 Likes

Why are you using WaitForChild there, is ModuleName a dynamically created object? If not you don’t need to wait for it.

Static objects that exist in the place file at load time are guaranteed to be present before scripts start running, so they don’t need to be waited on (with the obvious exception that scripts in ReplicatedFirst don’t have any guarantees at all).

5 Likes

I was referring to scripts as a generalised term for LuaSourceContainers. This is also used in (locally required) Modules and LocalScripts, where replication is not a guarantee.

It’s actually the same either way, even LocalScripts (as long as they aren’t in ReplicatedFirst) can rely on the content that was statically loaded from the place file on the server being fully replicated before they run. The best succinct description I know of of the behavior: Can I use game.Loaded to avoid using WaitForChild? - #18 by Anaminus

5 Likes

I’m getting this issue with absolute paths. I mostly notice it on ReplicatedStorage stuff, but that’s primarily since most of my modules don’t live outside of that service.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TypeDefs = require(ReplicatedStorage.CoreData.TypeDefs) 
-- Gives me an "unsupported path" warning even though this exists in studio and is
-- not created during runtime.
-- This also occurs if ReplicatedStorage isn't a variable e.g.
-- require(game:GetService("ReplicatedStorage").CoreData.TypeDefs)
-- It does NOT occur if I use game.ReplicatedStorage
-- It only occurs with game:GetService("ReplicatedStorage")
type SomeType = TypeDefs.SomeType -- And this warns for unknown type due to ^
4 Likes

I’ve since renounced that post:

Even disregarding the problems with direct indexing, the complexity behind deciding whether or not a module path is actually safe, combined with the lack of official documentation to guide the decision, is too much. I made that first post trying to frame the problem with locating objects in the game tree, but I believe it falls short. Now, I would only use it to demonstrate the complexity of the problem, and the need for a proper solution.

For modules at least, I feel like the long-term solution will be some sort of feature that handles everything for you (e.g. an analyzer that finds and replicates modules early, or an explicit module registry). Until then, FindFirstChild/WaitForChild/GetService definitely need to be supported by analysis in some capacity. Analysis already assumes that a directly indexed path is correct statically, even if it wont be correct at runtime. I see no reason why the other methods couldn’t be treated the same way.

4 Likes