Research on random technical old Roblox stuff
This primarily aims to document the unknown regarding:
- Lua APIs whose purpose aren't immediately obvious (especially those removed prior to 2016)
- Web endpoints that are defunct and/or largely unknown (due to a lack of context and archives)
- General lesser-known game client functionality and features and stuff
Thanks to Matt for helping out with documenting ScriptInformationProvider.
(07/03/2025) Just remembered I had this lying around, I'm sure this'll be an interesting read for someone. There's so much more info and interesting stuff that I never got around to adding here but ¯\_(ツ)_/¯
"Build mode" is what Play Solo launched from the Roblox web site was periodically referred to as since 2009, as Play Solo also gave you access to Studio tools.
In September 2009, Roblox introduced a new feature called Building with Friends (also known as Group Build), which allowed for players to build together in a multiplayer game (almost) as if they were in standard solo Build mode, even allowing for the client toolbox to be used in-game (see screenshot).
This was significant, because as noted in the blog post, the following features and functionality were additionally introduced to power it:
- The standard set of build tool gears as the Studio UI couldn't be used (which were also added to standard Build mode anyway)
- A mechanism for players to insert content remotely on the server (see
DataModel:SetRemoteBuildMode) - The ScriptInformationProvider service for inserting content safely
- A system for game server saving (see
DataModel:ServerSave)
Building with Friends laid the groundwork for future Roblox features, most notably InsertService in 2010 and Personal Build Servers in 2011.
Parameters:
assetId: Specifies the current place ID. This would only be set for web-launched play solo, and otherwise be 0 for Studio-launched play solo.userId: Specifies the subject user IDisSolo: Eithertrueorfalse
This specifies what build permissions the player has, responding plainly with a hexadecimal number. The number is a bitfield, where each bit's role is defined by Enum.BuildPermission. For example, if a player only has permissions to move and color parts, then it'd respond with 0x28, which is 101000 in binary.
From here, the Insert permission determines whether the player is able to open the client toolbox in a multiplayer game, given that Remote Build mode is enabled (see DataModel:SetRemoteBuildMode).
Additionally, Player:HasBuildPermission can be used to check for a permission the player has. It's unknown where this is used, though.
Paramaters are the same as /Game/BuildActionPermissionCheck.ashx.
This specifies what tools the player should be given when their character loads in, and will respond plainly with a list of semicolon-delimited asset URLs. A response for a user who only has permission to move and clone parts may look like this:
http://www.roblox.com/asset/?id=16201421;http://www.roblox.com/asset/?id=16200204;http://www.roblox.com/asset/?id=402;
This actually just serves as an extension of the player's character appearance, following the same response format as /Asset/CharacterFetch.ashx. Therefore, the build tools will be grouped in with the player's own gears.
The permission information retrieved from BuildActionPermissionCheck.ashx does not determine which tools are given to the player and which are not, it's entirely up to this endpoint to do that.
This was only used up until December 2010, where the job of giving build tools was moved to the CoreScript system.
The endpoint URLs have to be declared in Lua, like this snippet from Visit.ashx for play solo:
pcall(function() game:GetService("Players"):SetBuildToolsUrl("http://www.roblox.com//Game/GetUserBuildToolSet.ashx?assetId=0&userId=%d&isSolo=true") end)
pcall(function() game:GetService("Players"):SetBuildUserPermissionsUrl("http://www.roblox.com//Game/BuildActionPermissionCheck.ashx?assetId=0&userId=%d&isSolo=true") end)For Group Build servers, these would be declared in the gameserver script. These endpoints are queried when the player initially loads into the world.
This is set on the client upon joining a multiplayer game, and determines if inserting content should be enabled.
If Remote Build mode is enabled, then the client will invoke the Player.RemoteInsert event for a server-side content insert when attempting to insert content locally. It will also allow the client toolbox to be used if the player has sufficient permissions (see /Game/BuildActionPermissionCheck.ashx).
Having this enabled was necessary for Group Build to work properly, and later InsertService. Essentially, it should pretty much always be set to true when joining a server.
ScriptInformationProvider was introduced in September 2009 alongside Building with Friends in an effort to effectively combat the problem of malicious scripts floating around the catalog, and make it safer for players to insert free models into their place. Back then, web services would have been running to periodically extract and record every script within every single uploaded asset, allowing Roblox staff to remotely blacklist scripts.
It was later extended in December 2010 to also provide information on Roblox-authored scripts.
Parameters:
ScriptHash: The MD5 hash of the script's sourceAccurateResults: Eithertrueorfalse, where for InsertService queries it can be controlled withInsertService:SetAdvancedResults
This endpoint will be queried whenever a Script instance with an unknown source is either executed or inserted from a free model.
It responds plainly with an array of space-delimited numbers, where for example:
- A script that the Roblox website has never seen before would respond with
0 0 0 0 - A trusted model script (i.e. scripts from gears) may respond with
0 0 1 0or0 0 0.5 0 - A blacklisted script may respond with
1 0 0 0 - A Roblox-authored script may respond with
0 0 1 1(December 2010 and newer only) - The client will assume a script state of
0 1 0 0if a request fails
The first number is a Boolean and specifies whether the script is unsafe or not. If it is unsafe, then the script's source will be wiped when it is ran.
The second number is a Boolean. Its purpose is unknown and it appears to be unused.
The third number is a float and specifies the trust level of the script. This is only used when an asset from the catalog is inserted in-game. If the script's trust level is below the accepted trust level, then the asset will be inserted without the script (see screenshot). The accepted trust level is 0.5 by default, and can be manually set with InsertService:SetTrustLevel if available.
The fourth number is a Boolean and specifies whether it is a Roblox-authored script. If it is, the script will run with an elevated identity of 4 (same as CoreScripts) instead of 2. This number is only present since December 2010.
All the keys specified below have boolean values.
Does exactly what it says (uploading scripts as script assets instead of models), but more specifically, when attempting to upload a Script instance:
- The save dialog navigates to http://www.roblox.com/UI/Save.aspx?type=Lua (normally it's "type=Model")
CContent::Upload(BSTR url)will only write the script's source instead of the Script instance XML
Overrides the LockPlayMode verb (see RobloxApp commands/verbs) to allow the Studio UI to be used in a multiplayer game.
Additionally, it allows for the 2010 RobloxApp player interface (launched with the "-player" arg) to fully function. Prior to late 2010 it won't even open if this AppSettings flag is not set. (interestingly, InsertService is not present in this)
Can be seen in use in these screenshots by Shedletsky from 2008 (note the Tools button is enabled and active).
Parameters:
UserID: The ID of the user who chatted the message
The endpoint used for chat filtering prior to 2013.
The chat message is sent in a POST request plainly as the request body. The endpoint would respond with "False" to indicate that the message is filtered, otherwise it would respond with "True".
Nothing special here, chat filtering is done the same way that local Diogenes filtering is.
The client will constantly ping this endpoint to ensure that the player's website authentication doesn't expire. Responds plainly with the number of minutes to wait before the next ping (typically 8).
Prior to July 2008, it has the function signature of CApp::CreateGame(WINDOW_TYPE WindowType) where:
typedef enum {
NoWindowType = 0,
PlayWindowType = 2
} WINDOW_TYPE;The WindowType parameter was removed in July 2008 (around the time the bootstrapper was introduced).
Prior to December 2008, it is called directly by JavaScript. Since then, the function signature is changed to CApp::CreateGame(BSTR p) where it must be given a security token of "44340105256" to do anything (see why), and JavaScript instead calls the launcher which internally calls this.
C pseudocode that generates the token:
int a = 1;
int b = 450;
char token[12];
for (int i = 0; i < b; i++) {
a = b - (a + 1) * (a + 1);
b = 3 * (b / 3) - 1;
}
itoa(a, token, 7); // token = "44340105256"| Verb | Class name | wParam | Actor |
|---|---|---|---|
| Exit | ExitCommand |
0xE102 |
The top "Exit" button |
| ToggleFullscreen | ToggleFullscreenVerb |
0x80F4 |
The top "Fullscreen" button |
| TogglePlayMode | ToggleIDEModeVerb |
0x80F5 |
The top "Tools" button |
| Help | HelpCommand |
0x80FD |
The top "Help..." button |
| ToggleToolbox | InsertModelFromRobloxVerb |
0x80FE |
The top "Insert" button |
| LockPlayMode | LockPlayModeVerb |
0x80FF |
NetworkClient being created |
| ReportAbuse | ReportAbuseVerb |
0x8100 |
The bottom-right "Report" button |
Also, almost every single Studio button/function is handled through Win32 window messages, which can still be activated even when play mode is locked.
These are the tools that would've been given for build mode during this time (September 2009 - December 2010). Some of these tools continued to be used past 2010 for the build tools CoreScript.
These likely ended up so widespread throughout the catalog and in brickbuilding games due to people copying and saving the tools from their player backpack when in Play Solo.
| Asset ID | Build Tool |
|---|---|
| 16200204 | Part Dragger |
| 16200373 | Color Paintbrush |
| 16200402 | Clone Part |
| 16200420 | Material Tool |
| 16200508 | Surface Tool |
| 16201421 | Reset Tool |
| 16201628 | Delete Tool |
| 16969792 | Resize Tool |
| 16975388 | Configuration Tool |
| 21001552 | Insert Tool |
Sourced from http://wiki.roblox.com/index.php/HasBuildPermission_(Function)
| Enum | Name | Description |
|---|---|---|
| 0 | Insert | Allows a player to insert objects from his personal collection of Models. |
| 1 | Delete | Allows a player to remove objects. |
| 2 | Resize | Allows a player to resize objects. |
| 3 | Move | Allows a player to move objects. |
| 4 | Clone | Allows a player to copy objects. |
| 5 | Color | Allows a player to change the color of objects. |
| 6 | Material | Allows a player to change the material of an object. |
| 7 | Surface | Allows a player to change the surface type of an object. |
| 8 | Configuration | Allows a player to change configurations of objects. |
| 9 | Moderate |
seriously cool stuff. i knew about GetScriptState's default value but dang it is really powerful
and i suppose W34Tk is undocumented because it would allow for, well, exploiting