Release Notes for 418

Notes for Release 418


Client Difference Log

API Changes

Added Property QDir Studio.LocalAssetsFolder {✏️RobloxScriptSecurity}

Added Function void StudioService:ShowBulkImportView() {RobloxScriptSecurity}
Added Function void WorldRoot:IkMoveTo(Instance part, CFrame target, float translateStiffness = 1, float rotateStiffness = 1, Enum<CollisionsMode> collisionsMode = "OtherMechanismsAnchored") {RobloxScriptSecurity}

Added Enum CollisionsMode
	Added EnumItem CollisionsMode.NoCollisions : 0
	Added EnumItem CollisionsMode.OtherMechanismsAnchored : 1
	Added EnumItem CollisionsMode.IncludeContactedMechanisms : 2

Added Tag [Deprecated] to Function Plugin:GetStudioUserId

Added Tags [Hidden] [Deprecated] to Property Studio.UI Theme

Changed the security of Function StudioService:GetUserId 
	from: {RobloxScriptSecurity}
	  to: {PluginSecurity}

(Click here for a syntax highlighted version!)


Added Min / Max methods to Vector2 and Vector3 classes.

I’m interested. Got info?

now fires after the Player has been removed from Players when a player leaves the game.

:flushed: :flushed: :flushed:


I can rely on this method much more now! Thank you so much for addressing this. Just to be certain though: this fixes the issue where a player would remain on the team for a frame, correct? Referencing this:


Added a details page to edit allowed/denied plugin HTTP permissions into Manage Plugins.


Can anyone clarify what this means? Like… denying a plugin’s HTTP access?


It means that plugins no longer require global HTTP requests to be enabled and instead the game developer can enable/disable it for specific plugins.


After all these years… Goodbye, if-then spaghetti…


Here’s the API diff for Vector2/3::Min/Max:

+Method Vector2 Vector2::Min(Vector2... others)
+Method Vector2 Vector2::Max(Vector2... others)
+Method Vector3 Vector3::Min(Vector3... others)
+Method Vector3 Vector3::Max(Vector3... others)

Once enabled gets the element-wise min/max of a set of Vectors, so:, 2, 3):Min(, 3, 2)) --> 1, 2, 2

Is there a reason for this? I would think that the Game Thumbnail would be better suited, the current loading screen.

1 Like

continue is weird, it’s like a keyword, but not.

for i=1,1 do

continue is a keyword like break here

But it’s also valid as an identifier?

local continue = 10

I assume this is for backwards compatibility.

Does this mean we will be able to preview local assets from our pc in studio?

I think this is a good idea. It will help with player retention as players see game icons while searching for games. If they see a game icon they recognize they will be more likely to click. So, by having the icon as the last web-image they see rather than the thumbnail, they will more likely remember it easier :slight_smile: (i have no clue if this is the reasoning, just my thoughts on the subject)


Correct, it’s a context-sensitive keyword.
A lot of scripts on the platform use continue as an identifier - we had to keep them working.


It’s actually amazing that this was even done to begin with for this exact reason. I remember a conversation between @zeuxcg and another person (really wish I remember their name because I believe they are pretty much the reason this happened).

In summary they had basically pointed out that continue can be treated like return or break but only where they wouldn’t be treated like variables. Keywords like this cannot be assigned to variables however they pointed out that this exact behaviour allows them to behave as variables at the same time. (For there to be an error describing the issue, the issue must be known, therefore if you replace the error with “this is a variable”) You get backwards compatibility and still get a handy new keyword at the same time!

Pretty clever imo. I think this can be applied to a lot of things in the future. This has already opened up the doors for Roblox to add new keywords. This also defines a pretty useful thought process for people: Does it produce a syntax error? If the answer is yes it means that error can behave as something completely different if you want it to.

The only edge cases of this thought process include scripts which use loadstring to check for syntax errors. This is not really useful in any context besides checking for new syntax. Games such as script builder would not produce a syntax error, however that’s pretty much the goal!

Tl;dr with a few very minor (and probably obvious) exceptions, syntax errors are pretty much free to change. They act almost as “forwards comparability” in the sense that they are useless to developers and won’t break scripts.


I’m confused how does it work?

1 Like

continue works by jumping to the end of the loop

for i=1,1 do
    do continue end -- jumps to the end of the loop
    print"this is skipped"

This is useful for something like

while something do
    -- ...
    if x then continue end
    -- ...
    if y then continue end
    -- ...
    if z then continue end
    -- ...

Instead of doing

while something do
    -- ...
    if not x then
        -- ...
        if not y then
            -- ...
            if not z then
                -- ...

Yeah, this is exactly right. The story of continue is actually pretty interesting.

When we first looked at adding continue, which was at the end of last year, we were thinking about ways to add this - since continue is de-facto standard in basically every language on Earth, we really wanted this name instead of something different.

The obvious question was “can we just make continue a keyword”. We actually shipped code that tracked the usage of continue as an identifier and collected place ids with scripts with them. The hope was that there would be only a few places that do this; the actual reality was that a fair amount of games in the top 1000 used code like this:

script.Frame.continue.TextLabel.Text = "..."

So continue was used as a name of an object in the hierarchy. Ok - we can’t go this route.

Then we tried the next obvious route - what if we treated any statement that started from continue as a loop continuation statement? Again, we actually shipped code that tracked the usage of continue and collected place ids. The hope was that there would be only a few places that do this; the actual reality, again, disappointed, since many people had code like this:

continue = true

or like this:

function continue(...) ... end

It became obvious that we would need to disambiguate this somehow. We needed a solution that didn’t change the meaning of any existing source code, no matter how obscure.

At this point we have launched the Luau type checking beta, and started actually looking really closely at the syntactic extensions that it introduces and the interactions with the existing code. For example, as was not safe for us to add - we had to remove this from the language extensions for now. But type was safe - it’s because type has to be followed by an identifier to produce a type alias, and type Foo is invalid Lua - as you note, syntax errors are fair game.

And basically simultaneously the conversation you’re thinking of happened: Luau Type Checking Beta! (+ follow the parent chain). During this as I was explaining why continue can’t be added as a keyword, I realized that the disambiguation here is actually simple, and @1waffle1 correctly pointed out that statements like

(1, 2, 3)

Can, uh, continue to be treated as function calls because from the programmer’s point of view, they don’t seem ambiguous - continue is only expected to work as the last statement anyway.

From there on it was a simple matter of refactoring the parser around the disambiguation point a bit, extending it with continue support, adding continue to the compiler and shipping this. Yay!

edit Oh also Lua grammar doesn’t say this explicitly, but both vanilla Lua parser and our Luau parser actually treat this:

(1, 2, 3)

as a syntax error anyhow - the opening parenthesis must be on the same line as the identifier.


I don’t really get it but from how it’s described I think it skips the current iteration but still runs the loop instead of ending it like break

Is that correct?

1 Like


while something do
    -- ...
    if x then continue end
    -- ...
    -- continue jumps down here

With regards to as, it can be context specific as well because like you said, x as type and statements of that sort are generally syntax errors in Lua. It’s probably a slippery slope to start adding a bunch of these sorts of keywords, but I think keeping as is worth it in the same way continue was.