Discuss Scratch

NamelessCat
Scratcher
100+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

* This is the second guide to creating Unsandboxed Extensions on this forum. The first one can be found here. This topic does not qualify as a dupe as 1. This extension covers the full process, not just converting your sandboxed extension to unsandboxed. 2. This topic is specifically designed for TurboWarp extensions, because TurboWarp has a slightly different syntax than most other ways to load unsandboxed extensions.
** Most of this forum is an elaboration of the topics covered in the official sandbox documentation. Some things may be left out for the sake of being more user-friendly. If you have any question, please consult the original documentation before commenting.


Section 0 - What Is an Unsandboxed Extension?

This guide was created on the basis that the reader has no former knowledge of sandboxed or unsandboxed extensions. If you already do, feel free to skip to section one.
With that being said, there are two types of Scratch extensions; the sandboxed and unsandboxed varieties. There's several difference between the two of them, such as the former not being allowed to access all APIs and taking a frame to run each time it's called on, but the general consensus is that unsandboxed extensions are far more powerful. Along with that, unsandboxed extensions are simply easier to share, due to the Official TurboWarp Unsandboxed Extension Gallery (which is an amazing site if you haven't checked it out beforehand). Other than that, you can also find all examples of TurboWarp Unsandboxed Extensions here.
That being said, great power comes with great responsibility. There's certain formatting and syntax that TurboWarp Extensions require in order to run, just to keep the site safe and secure. Although it may seem daunting at first, it's pretty simple as long as you program carefully and follow a guide.

Section 1.1 - Loading Extensions via File

Originally, this step would consist of creating a local server and hosting our scripts via the command prompt. Luckily, we don't have to deal with that anymore. We can now load extensions via a file, or even through copied text.
Navigate to the TurboWarp Editor. At the bottom of the toolbox, click on the “Add Extension” button. This should look familiar– it's the same button for adding extensions such as Pen to Scratch projects.
There's a lot of options here, however we specifically need to select “Custom Extension,” which should be the last option before the first line.
This opens a menu with 3 tabs. For extension development, the last 2 tabs will prove useful to you. “File” can be used to open JS extension files, and “Text” can load any extension copied to your clipboard. As practice, navigate to “Text” and paste in this extension:

class HelloWorld {
getInfo() {
return {
id: 'helloworld',
name: 'It works!',
blocks: [
{
opcode: 'hello',
blockType: Scratch.BlockType.REPORTER,
text: 'Hello!'
}
]
};
}

hello() {
return 'World!';
}
}

Scratch.extensions.register(new HelloWorld());
If you've done everything correctly, the extension should be loaded.

Section 1.2 - Setting Up Our Script.

You'll likely want to create a new JS (JavaScript) file. If your operating system doesn't have a simple way to do this, create a text file and replace the letters “txt” with “js” and press ok through any pop-ups that may occur. Then open the file. If you have Visual Studio Code or other code editing software installed, use that. Otherwise, you'll have to use a notepad, which is okay, however it won't autofill scripts or catch errors for you.
The other option would be to repeatedly copy-paste our code into the “Text” tab, however this can be quite tedious and doesn't allow use of code editing softwares. Plus, to share the extension, you'll want it in a JS file anyways.
When we get into our script, we have to paste our template:
(function(Scratch) {
'use strict';

if (!Scratch.extensions.unsandboxed) {
throw new Error('[NAME HERE] must run unsandboxed');
}

class [ID HERE] {
getInfo() {
return {
id: '[ID HERE]',
name: '[NAME HERE]',
blocks: [
// Palette Here
]
};
}
// Block Code Here
}
Scratch.extensions.register(new [ID HERE]());
})(Scratch);
Now we need to decide on the name and id of our extension. There's not many limitations on name, however for id, I'd stick to one word, and only English characters. Then, everywhere it says “ID HERE”, replace it with your id, and everywhere it says “NAME HERE”, replace it with the name you chose. Congrats! You already have the basics of your extension down.

Section 2.1 - Adding Blocks To Our Palette.

Now that we have our template down, we can start adding our blocks. I've put a comment (the double /) called “Palette Here” where you can define each of your blocks. Here's the syntax for each block of code:
        {
opcode: 'hello',
blockType: Scratch.BlockType.REPORTER,
text: 'Hello!'
},
This is the same example given in the official documentation, so we'll have to do a bit of editing. First, let's focus on the variable “opcode”. Rename this to any all lowercase string of characters that describes the block you're trying to make. Remember this, we'll need it later.
As for the blocktype, there's 3 different values we can set this to. These correspond to the 3 types of Scratch blocks.

Block (Scratch.BlockType.COMMAND)
The basic Scratch block, doesn't return an output.
say []

Boolean (Scratch.BlockType.BOOLEAN)
The hexagonal block. Reports true/false values.
<[] = []>

Reporter (Scratch.BlockType.REPORTER)
Any block that returns a number/string output.
((0) + (0))

Unlike the other two, the blocktype does not need to be surrounded in quotes, as it is not a string (don't forget the comma after it, however).
The last variable we need to set it the blockname. Set it to something that represents what the block does. Any inputs, whether it be a dropdown, boolean input, or a menu, must be surrounded by .
There's more that can be added to the block syntax to add extra functions, however none are particularly helpful for beginners and will be skipped over in this tutorial.

Section 2.2 - Defining Any Arguments We Made.

If your blocks don't have any arguments (which is rather unlikely), you may skip this section. Otherwise, we have to do a little bit more work so our arguments work. First, we have to add a comma after our “text” variable:
          text: 'Hello!',
Then, we have to add another syntax. The length will vary based on how many arguments your block has, however for simplicity sake I'll offer the syntax for the one argument and two argument versions, and you can fill in the blanks.
          arguments: {
WHAT YOU PUT IN BRACKET ONE: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Default'
}
          arguments: {
WHAT YOU PUT IN BRACKET ONE: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Default'
},
WHAT YOU PUT IN BRACKET TWO: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Default'
}
Now we have to fill in our blanks again. Of course (if you haven't already), replace ‘WHAT YOU PUT IN BRACKET _“ whatever text you put in the brackets in section 2.1 in the corresponding order. Inside each section, you can change the ”defaultValue“ to reflect what you want the block to show in the pallet, and you can change the ”type" to the type of input you want the block to have. There’s quite a few of these, but here's the basic 3:

String (Scratch.ArgumentType.STRING)
Leaves a spot for string to be typed.
say []

Boolean (Scratch.ArgumentType.BOOLEAN)
Leaves a spot for a boolean input.
wait until <>

String (Scratch.ArgumentType.NUMBER)
Leaves a spot for a number to be typed.
move () steps

Great! We have arguments! Some people may be wondering how you can program in dropdown menus, such as those used in the “move to the front/back layer” block. Although it may seem like it's own ArgumentType, it's actually quite a bit more complicated than that. To keep this guide as short as possible, I will not be including dropdown menus in this tutorial, however, further guidance can be found here.

Section 2.3 - Troubleshooting.

It's always a good idea to test your extension as you go to make sure no issues occur. Although code editors can point out JavaScript and JSON errors, TurboWarp is ultimately the program that's best for checking your code. Follow the same instructions as in Section 1.1. If your custom extension is not appearing in the toolbox, or looks incorrect, check your code for the following errors:
  • Forgetting a comma or semicolon. Seriously, those things can mess up your entire script if you're not careful.
  • Forgetting to define an argument.
  • Accidentally using the same opcode for several different blocks.
Another useful trick is pressing Ctrl+Shift+I and looking at the console tab. Most of the time, any errors that occur in your code will show up here. If you're not sure what an error means, you can sometimes Google it for a more descriptive explanation.

Section 3.1 - Programming Our Blocks.

So, you've got your blocks in the pallet now, however they don't do anything. Luckily, Scratch makes it relatively simple to program these blocks using JavaScript. Let's have a look back at our code, specifically where a comment says “Block Code Here”. If it wasn't self-explanatory, that's where we're going to start coding. Let's erase that comment, and replace it with the following script:
  REPLACE(args) {
return 'Placeholder';
}
The only thing we have to do to prep this script for free editing is to replace the word “REPLACE” with the opcode for the block you're programming (See? I told you they'd come back eventually). From here, you're free to start programming your block inside the curly brackets. To call upon any argument you may have defined earlier, you just have to add “args.” to the beginning of whatever you named your variable.
With booleans and reporters, of course you'll need to return a value when the block is processed. Luckily, Scratch is programmed so that returning any string, number, or bool will automatically relay that information to the user. If you're making a standard command block, there's no need for a reporter and you can delete the “return” line of code in the script.
Of course, most extensions will have more than one block. In that case, you can simply repeat the example script below the one you already wrote, remembering to replace the opcode. Refreshing the tab you have open with your extension at any point will reload whatever code you wrote and saved, so make sure to save and refresh often.

Section 3.2 - API Requests And Asynchronous Blocks.

Lots of extensions require access to different APIs across the web. Requesting information from a website using TurboWarp is actually very easy, however somewhat limited. The biggest 2 limiting factors are that:
  1. TurboWarp will ask from permission from the user you try to access any domain.
  2. Certain domains, such as the Scratch API, are off-limits to the likes of TurboWarp.
With that being said, API requests are still a vital tool in the Scratch Extension making toolbox. To request information from a website, use the script:
const response = await Scratch.fetch('url');
and then can read it as text with the script:
const textData = await response.text();
or split it up into a JSON with the script:
const jsonData = await response.json();
It's also important that sending out an API request will make your block asynchronous. This means that your block cannot complete its action in under a frame. To mark a block as asynchronous, ad the string “async” before your opcode, like so:
  async REPLACE(args) {
return 'Placeholder';
}
Finally, as you'll read later, TurboWarp syntax really doesn't like empty returns on reporters or booleans. As such, it's always a good idea to add a script such as this around an API request:
try {
// CODE HERE
} catch (error){
return '';
}

Section 3.3 - Keeping to TurboWarp Formatting.

If you're programming your extension all for yourself, TurboWarp formatting won't have too much of an affect on your code. However, if you want to submit your extension to the Official TurboWarp Unsandboxed Extension Gallery, there's a few rules you have to follow. For one, most if not all copyrighted material is usually difficult to add to an extension, there's some stuff you can fill out to gain access to it, however that's legal stuff and legal stuff is boring. Basically, stay away from copyrighted material or code snippets if at all possible.
As for the code itself, GarboMuffin prefers if you use semicolons and double spaces (which is absolutely preposterous but it what it is I guess).
GarboMuffin will also usually turn down extensions that can be deemed dangerous, such as two extensions that are currently in limbo, Local Storage and JavaScript Execution. As long as your extension isn't dangerous to the user, you shouldn't have to worry about that.
Any libraries that the extension uses must be embedded into the code of the extension, and the extension should be able to work on all browsers.
Extensions must not return empty in a boolean or reporter. An empty string (such as ‘ ’) is acceptable, but it needs to return something.

Section 4.1 - Customizing Your Extension.

You may have noticed that up until now your extension has been looking rather bland. Not to worry, this can be fixed using some built-in APIs! For one, we can change the color of our extension. Using a color to hex code converter online, you can get the hex codes for the outlines and the block colors of your extensions. We can insert some variables inside the getInfo part of our original template:
... getInfo() {
return {
id: 'yourextension',
name: 'Your Extension',
color1: '#000000', // Block Color
color2: '#000000', // Outline Color
color3: '#000000', // Dropdown color
blocks: ...
Simply insert the hex codes next to the comments to color your blocks. You may notice that the category icon on the toolbar changes to whatever you set your block color to; this is completely intentional. However, there is a process to add an icon to your extension. First, make a square icon (it doesn't need to literally be a square, however the width must be the same as the height). Then, use a program such as ezgif to convert the png of this icon into base64. After you do that, you simply plug in 2 lines of code:
... const icon = "insert very long base64 string here";

class YourExtension {
getInfo() {
return {
id: 'yourextension',
name: 'Your Extension',
color1: '#000000',
color2: '#000000',
color3: '#000000',
menuIconURI: icon, // Don't forget this!
blocks: ...
While we're at it, you may want to include a link to the documentation of your extension. This is by no means required nor outright encouraged, but can be a neat professional touch to your extension. Or, you could just make it a link to a rickroll. Your choice:
... getInfo() {
return {
id: 'yourextension',
name: 'Your Extension',
color1: '#000000',
color2: '#000000',
color3: '#000000',
menuIconURI: icon,
docsURI: 'url', // Replace the text with the link to your documentation, perhaps.
blocks: ...

Section 5 - Finishing Statements.

Congratulations on making an unsandboxed extension! What's outlined in this tutorial is by no means the full power of the unsandboxed extension maker, however, as you experiment more, you'll find more interesting features and tricks to level up your extensions. While I'd love to share how to share your extension, it's unfortunately against Scratch TOS to share links with outside sources. With that being said, you can freely post the JS of your extension in the forums, or other places.

Topics to be added to this guide:
  • Hat blocks
  • Scratch.Cast
  • Menus and dropdowns

    If any other topics are misrepresented, missed, or need to be elaborated on, please feel free to let me know as a reply to this post.

Last edited by NamelessCat (March 31, 2024 03:57:13)


The forums scare me, but I still come on here from time to time.

I'm fine.
swiftgtsn
Scratcher
47 posts

Guide to Creating Unsandboxed TurboWarp Extensions

complicated words
--FlamingGames--
Scratcher
22 posts

Guide to Creating Unsandboxed TurboWarp Extensions

We need to make a new file on our computer, this is where we will be hosting our server. You can name it whatever you want, however, it'll help in the long run if you name it whatever username you go by.

What type of file do we use for our server? Also great guide: I will for sure use this if I feel like creating any unsandboxed extensions.
NamelessCat
Scratcher
100+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

--FlamingGames-- wrote:

We need to make a new file on our computer, this is where we will be hosting our server. You can name it whatever you want, however, it'll help in the long run if you name it whatever username you go by.

What type of file do we use for our server? Also great guide: I will for sure use this if I feel like creating any unsandboxed extensions.
Oopsie, I meant to write “folder.” I'll go ahead and fix that!

The forums scare me, but I still come on here from time to time.

I'm fine.
Boomanwilliam
Scratcher
11 posts

Guide to Creating Unsandboxed TurboWarp Extensions

thats great but it doesn't talk about some useful tools available in unsandboxed extensions like the util argument you can have or Scratch.vm

best quote from the year 1 to the year 10,000:

joemama wrote:

want to play among us?
CyberVen
Scratcher
8 posts

Guide to Creating Unsandboxed TurboWarp Extensions

I specify that I don't have much experience in the Scratch development environment.
I would like to clarify that I'm trying to make an extension for using a robot that has a Raspberry Pi 3 Model B+.
where I installed scratch version 3.12.0
It previously worked with a scratchx application, which is now obsolete.
I don't think it's possible to install scratch3.0 gui for software development directly on the raspberry, but I can interface with a PC using vnc viewer, to develop an application.
Thanks in advance for your help.
NamelessCat
Scratcher
100+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

CyberVen wrote:

I specify that I don't have much experience in the Scratch development environment.
I would like to clarify that I'm trying to make an extension for using a robot that has a Raspberry Pi 3 Model B+.
where I installed scratch version 3.12.0
It previously worked with a scratchx application, which is now obsolete.
I don't think it's possible to install scratch3.0 gui for software development directly on the raspberry, but I can interface with a PC using vnc viewer, to develop an application.
Thanks in advance for your help.
I've tried to install Scratch to my Pi 3 in the past… did not go well lol
I'd suggest finding an alternative way to run Scratch, or getting a Pi 4

The forums scare me, but I still come on here from time to time.

I'm fine.
franciscomagic
Scratcher
32 posts

Guide to Creating Unsandboxed TurboWarp Extensions

NamelessCat wrote:

* This is the second guide to creating Unsandboxed Extensions on this forum. The first one can be found here.
  • Hat blocks
  • Scratch.Cast
  • Menus and dropdowns

    If any other topics are misrepresented, missed, or need to be elaborated on, please feel free to let me know as a reply to this post.
What about Cap and C blocks?

Last edited by franciscomagic (Oct. 12, 2023 17:30:38)


If you see that I use Scratch during night it's because the forum hours are from the U.S.A. and here in France it is still day!
usefun
Scratcher
1000+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

SUPER COMPLICATED
I don't think I'll ever do that

Alt: @usefun2
My profile
Sinistar (My best game)
See your exact post count here.
unfortunately this signature has been corrupted by an evil cat blockCAT BLOCKS WILL RULE
Picosuke
Scratcher
3 posts

Guide to Creating Unsandboxed TurboWarp Extensions

Is it okay if I write the code for the extension I created? (I'm Japanese)
Sam0IR
Scratcher
100+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

NamelessCat wrote:

* This is the second guide to creating Unsandboxed Extensions on this forum. The first one can be found here. This topic does not qualify as a dupe as 1. This extension covers the full process, not just converting your sandboxed extension to unsandboxed. 2. This topic is specifically designed for TurboWarp extensions, because TurboWarp has a slightly different syntax than most other ways to load unsandboxed extensions.
** Most of this forum is an elaboration of the topics covered in the official sandbox documentation. Some things may be left out for the sake of being more user-friendly. If you have any question, please consult the original documentation before commenting.


Section 0 - What Is an Unsandboxed Extension?

This guide was created on the basis that the reader has no former knowledge of sandboxed or unsandboxed extensions. If you already do, feel free to skip to section one.
With that being said, there are two types of Scratch extensions; the sandboxed and unsandboxed varieties. There's several difference between the two of them, such as the former not being allowed to access all APIs and taking a frame to run each time it's called on, but the general consensus is that unsandboxed extensions are far more powerful. Along with that, unsandboxed extensions are simply easier to share, due to the Official TurboWarp Unsandboxed Extension Gallery (which is an amazing site if you haven't checked it out beforehand). Other than that, you can also find all examples of TurboWarp Unsandboxed Extensions here.
That being said, great power comes with great responsibility. There's certain formatting and syntax that TurboWarp Extensions require in order to run, just to keep the site safe and secure. Although it may seem daunting at first, it's pretty simple as long as you program carefully and follow a guide.

Section 1.1 - Setting Up a Local Server.

One of the defining factors of an unsandboxed extension is that they run outside of Scratch, but that presents an obvious problem; where is there for the extension to run? Not to worry, we can make our own server at home with minimal effort. Open up a file explorer, as well as a command prompt line (there should be one pre-installed on every computer, make sure to use that one and not another command line). We need to make a new folder on our computer, this is where we will be hosting our server. You can name it whatever you want, however, it'll help in the long run if you name it whatever username you go by. Then we need the path of this file, you can find that easily by right clicking the file and selecting “Copy File Path.”
Then we can switch over to our command line, where we have to run two commands.
cd [file path]
python3 -m http.server 8000
This should start up a local server we can host our extension from. If an error pops up, it's likely you haven't installed python on your computer yet. If so, you can go here for help.

Section 1.2 - Setting Up Our Script.

Let's make our way back to the folder we copied the directory to. Here, we want to create a new JS (JavaScript) file. If your operating system doesn't have this on automatically, create a text file and replace the letters “txt” with “js” and press ok through any pop-ups that may occur. Then open the file. If you have Visual Studio Code or other code editing software installed, use that. Otherwise, you'll have to use a notepad, which is okay, however it won't autofill scripts or catch errors for you.
When we get into our script, we have to paste our template:
(function(Scratch) {
'use strict';

if (!Scratch.extensions.unsandboxed) {
throw new Error('[NAME HERE] must run unsandboxed');
}

class [ID HERE] {
getInfo() {
return {
id: '[ID HERE]',
name: '[NAME HERE]',
blocks: [
// Pallet Here
]
};
}
// Block Code Here
}
Scratch.extensions.register(new [ID HERE]());
})(Scratch);
Now we need to decide on the name and id of our extension. There's not many limitations on name, however for id, I'd stick to one word, and only English characters. Then, everywhere it says "“, replace it with your id, and everywhere it says ”", replace it with the name you chose. Congrats! You already have the basics of your extension down.

Section 2.1 - Adding Blocks To Our Pallet.

Now that we have our template down, we can start adding our blocks. I've put a comment (the double /) called “Pallet Here” where you can define each of your blocks. Here's the syntax for each block of code:
        {
opcode: 'hello',
blockType: Scratch.BlockType.REPORTER,
text: 'Hello!'
},
This is the same example given in the official documentation, so we'll have to do a bit of editing. First, let's focus on the variable “opcode”. Rename this to any all lowercase string of characters that describes the block you're trying to make. Remember this, we'll need it later.
As for the blocktype, there's 3 different values we can set this to. These correspond to the 3 types of Scratch blocks.

Block (Scratch.BlockType.COMMAND)
The basic Scratch block, doesn't return an output.
say []

Boolean (Scratch.BlockType.BOOLEAN)
The hexagonal block. Reports true/false values.
<[] = []>

Reporter (Scratch.BlockType.REPORTER)
Any block that returns a number/string output.
((0) + (0))

Unlike the other two, the blocktype does not need to be surrounded in quotes, as it is not a string (don't forget the comma after it, however).
The last variable we need to set it the blockname. Set it to something that represents what the block does. Any inputs, whether it be a dropdown, boolean input, or a menu, must be surrounded by .
There's more that can be added to the block syntax to add extra functions, however none are particularly helpful and will be skipped over in this tutorial.

Section 2.2 - Defining Any Arguments We Made.

If your blocks don't have any arguments (which is rather unlikely), you may skip this section. Otherwise, we have to do a little bit more work so our arguments work. First, we have to add a comma after our “text” variable:
          text: 'Hello!',
Then, we have to add another syntax. The length will vary based on how many arguments your block has, however for simplicity sake I'll offer the syntax for the one argument and two argument versions, and you can fill in the blanks.
          arguments: {
WHAT YOU PUT IN BRACKET ONE: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Default'
}
          arguments: {
WHAT YOU PUT IN BRACKET ONE: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Default'
},
WHAT YOU PUT IN BRACKET TWO: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Default'
}
Now we have to fill in our blanks again. Of course (if you haven't already), replace ‘WHAT YOU PUT IN BRACKET _“ whatever text you put in the brackets in section 2.1 in the corresponding order. Inside each section, you can change the ”defaultValue“ to reflect what you want the block to show in the pallet, and you can change the ”type" to the type of input you want the block to have. There’s quite a few of these, but here's the basic 3:

String (Scratch.ArgumentType.STRING)
Leaves a spot for string to be typed.
say []

Boolean (Scratch.ArgumentType.BOOLEAN)
Leaves a spot for a boolean input.
wait until <>

String (Scratch.ArgumentType.NUMBER)
Leaves a spot for a number to be typed.
move () steps

Great! We have arguments! Some people may be wondering how you can program in dropdown menus, such as those used in the “move to the front/back layer” block. Although it may seem like it's own ArgumentType, it's actually quite a bit more complicated than that. To keep this guide as short as possible, I will not be including dropdown menus in this tutorial, however, further guidance can be found here.

Section 2.3 - Let's Load Our Current Extension.

Before we continue, we should load our extension to make sure the block pallet looks okay. This may sound complicated, however it's quite easy! We can go to http://localhost:8000/whatever-we-named-our-file.js to view what we have so far. If everything you've done so far has been correct, the extension will load and you can see all the blocks you added. If the extension doesn't load, or things are messed up, it could be a plethora of issues, such as:
  • Forgetting a comma or semicolon. Seriously, those things can mess up your entire script if you're not careful.
  • Forgetting to define an argument.
  • Messing up the URL (this got me my first time around, make sure the last part of your url matches exactly what you named your file).

Section 3.1 - Programming Our Blocks.

So, you've got your blocks in the pallet now, however they don't do anything. Luckily, Scratch makes it relatively simple to program these blocks using JavaScript. Let's have a look back at our code, specifically where a comment says “Block Code Here”. If it wasn't self-explanatory, that's where we're going to start coding. Let's erase that comment, and replace it with the following script:
  REPLACE(args) {
return 'Placeholder';
}
The only thing we have to do to prep this script for free editing is to replace the word “REPLACE” with the opcode for the block you're programming (See? I told you they'd come back eventually). From here, you're free to start programming your block inside the curly brackets. To call upon any argument you may have defined earlier, you just have to add “args.” to the beginning of whatever you named your variable.
With booleans and reporters, of course you'll need to return a value when the block is processed. Luckily, Scratch is programmed so that returning any string, number, or bool will automatically relay that information to the user. If you're making a standard command block, there's no need for a reporter and you can delete the “return” line of code in the script.
Of course, most extensions will have more than one block. In that case, you can simply repeat the example script below the one you already wrote, remembering to replace the opcode. Refreshing the tab you have open with your extension at any point will reload whatever code you wrote and saved, so make sure to save and refresh often.

Section 3.2 - API Requests And Asynchronous Blocks.

Lots of extensions require access to different APIs across the web. Requesting information from a website using TurboWarp is actually very easy, however somewhat limited. The biggest 2 limiting factors are that:
  1. TurboWarp will ask from permission from the user you try to access any domain.
  2. Certain domains, such as the Scratch API, are off-limits to the likes of TurboWarp.
With that being said, API requests are still a vital tool in the Scratch Extension making toolbox. To request information from a website, use the script:
const response = await Scratch.fetch('url');
and then can read it as text with the script:
const textData = await response.text();
or split it up into a JSON with the script:
const jsonData = await response.json();
It's also important that sending out an API request will make your block asynchronous. This means that your block cannot complete its action in under a frame. To mark a block as asynchronous, ad the string “async” before your opcode, like so:
  async REPLACE(args) {
return 'Placeholder';
}
Finally, as you'll read later, TurboWarp syntax really doesn't like empty returns on reporters or booleans. As such, it's always a good idea to add a script such as this around an API request:
try {
// CODE HERE
} catch (error){
return '';
}

Section 3.3 - Keeping to TurboWarp Formatting.

If you're programming your extension all for yourself, TurboWarp formatting won't have too much of an affect on your code. However, if you want to submit your extension to the Official TurboWarp Unsandboxed Extension Gallery, there's a few rules you have to follow. For one, most if not all copyrighted material is usually difficult to add to an extension, there's some stuff you can fill out to gain access to it, however that's legal stuff and legal stuff is boring. Basically, stay away from copyrighted material or code snippets if at all possible.
As for the code itself, GarboMuffin prefers if you use semicolons and double spaces (which is absolutely preposterous but it what it is I guess).
GarboMuffin will also usually turn down extensions that can be deemed dangerous, such as two extensions that are currently in limbo, Local Storage and JavaScript Execution. As long as your extension isn't dangerous to the user, you shouldn't have to worry about that.
Any libraries that the extension uses must be embedded into the code of the extension, and the extension should be able to work on all browsers.
Extensions must not return empty in a boolean or reporter. An empty string (such as ‘ ’) is acceptable, but it needs to return something.

Section 4.1 - Customizing Your Extension.

You may have noticed that up until now your extension has been looking rather bland. Not to worry, this can be fixed using some built-in APIs! For one, we can change the color of our extension. Using a color to hex code converter online, you can get the hex codes for the outlines and the block colors of your extensions. We can insert some variables inside the getInfo part of our original template:
... getInfo() {
return {
id: 'yourextension',
name: 'Your Extension',
color1: '#000000', // Block Color
color2: '#000000', // Outline Color
color3: '#000000', // Dropdown color
blocks: ...
Simply insert the hex codes next to the comments to color your blocks. You may notice that the category icon on the toolbar changes to whatever you set your block color to; this is completely intentional. However, there is a process to add an icon to your extension. First, make a square icon (it doesn't need to literally be a square, however the width must be the same as the height). Then, use a program such as ezgif to convert the png of this icon into base64. After you do that, you simply plug in 2 lines of code:
... const icon = "insert very long base64 string here";

class YourExtension {
getInfo() {
return {
id: 'yourextension',
name: 'Your Extension',
color1: '#000000',
color2: '#000000',
color3: '#000000',
menuIconURI: icon, // Don't forget this!
blocks: ...
While we're at it, you may want to include a link to the documentation of your extension. This is by no means required nor outright encouraged, but can be a neat professional touch to your extension. Or, you could just make it a link to a rickroll. Your choice:
... getInfo() {
return {
id: 'yourextension',
name: 'Your Extension',
color1: '#000000',
color2: '#000000',
color3: '#000000',
menuIconURI: icon,
docsURI: 'url', // Replace the text with the link to your documentation, perhaps.
blocks: ...

Section 5 - Finishing Statements.

Congratulations on making an unsandboxed extension! What's outlined in this tutorial is by no means the full power of the unsandboxed extension maker, however, as you experiment more, you'll find more interesting features and tricks to level up your extensions. While I'd love to share how to share your extension, it's unfortunately against Scratch TOS to share links with outside sources. With that being said, you can freely post the JS of your extension in the forums, or other places.

Topics to be added to this guide:
  • Hat blocks
  • Scratch.Cast
  • Menus and dropdowns

    If any other topics are misrepresented, missed, or need to be elaborated on, please feel free to let me know as a reply to this post.
time to make dualtouch buttons on turbowarp




Forum Tic Tac Toe
Reply to my post with a spot to set it to an X


___
_O_
___

TP2222
Scratcher
100+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

Hi!

CODE,CATS,NO SCHOOL!!!
when I receive [Cat! v]
play drum (D) for (join [0.] (L) )beats
wait until <(who) = [Me!]>
add [Me!] to [Fun! v]
Generation VII (7): the first time you see this copy and paste it on top of your sig in the scratch forums and increase generation by 1. Social experiment.

mik_and_djdarkfox
Scratcher
8 posts

Guide to Creating Unsandboxed TurboWarp Extensions

u
run (34) block ((3+4)/(7/3))
shertiff1234
Scratcher
4 posts

Guide to Creating Unsandboxed TurboWarp Extensions

mik_and_djdarkfox wrote:

u
run (34) block ((3+4)/(7/3))
*insert nerd emoji here*
co0lcr34t10ns
Scratcher
1000+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

How did a TurboWarp topic get stickied? I LOVE IT! And thank you for this cool guide!

I'm a professional forum lurker who likes Vocaloid, retro games, and story writing.

Social Experiment Generation 0: Add this to your signature increase generation by 1 and add the username of the person whose signature you saw this in to this studio




I am the 454th most active TIRAP forumer. Wow! Not surprised in any way though.

I love the OG mods. They are just done with forum trolls.

Gamer_Logan819
Scratcher
1000+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

Is there a way to create turbowarp extensions by using custom blocks? Like I make custom blocks in a turbowarp editor, and then I want to turn those into an extension. Is it possible to do this?

The forum boogeymen are out to get you

Picosuke
Scratcher
3 posts

Guide to Creating Unsandboxed TurboWarp Extensions

ピコ助 wrote:

Is it okay if I write the code for the extension I created? (I'm Japanese)
OK?
Cookiebuns
Scratcher
99 posts

Guide to Creating Unsandboxed TurboWarp Extensions

i'm working on a personal project for turbowarp. a kind of kinito pet, bonzi buddy, and clippy type of program. it will be simple, just a simple sprite walking along the screen which you can talk to when you click it but i wanna know how i would make an extension that makes the background fully transparent.

thanks!

(EDIT: i just wanna tell you that my only known languages are scratch and turbowarp)

Last edited by Cookiebuns (March 30, 2024 13:17:38)


ㅤ/l、ㅤmeow
(゚、 。7
ㅤl、゙~ヽ
ㅤじしf_, )ノ
ArshanAijazKhan
Scratcher
3 posts

Guide to Creating Unsandboxed TurboWarp Extensions

Umm…. can anyone of you make a project on turbowarp by the new things or whatever
julmik6478
Scratcher
100+ posts

Guide to Creating Unsandboxed TurboWarp Extensions

franciscomagic wrote:

NamelessCat wrote:

* This is the second guide to creating Unsandboxed Extensions on this forum. The first one can be found here.
  • Hat blocks
  • Scratch.Cast
  • Menus and dropdowns

    If any other topics are misrepresented, missed, or need to be elaborated on, please feel free to let me know as a reply to this post.
What about Cap and C blocks?
CAPS not need to explain so much, beacuse caps are just stack blocks, but you can't put any blocks under it. C blocks needs more to explain.


Support the suggestion HERE by adding this button to your signature

My social media:
youtube
snail ide
planet minecraft
mcreator
electramod

Powered by DjangoBB