Discuss Scratch
- nXIII
-
1000+ posts
Extension Discussion Thread
This thread provides a place for discussing extensions to Scratch 2.0. The topic post provides a description of the current state of extensions in Scratch.
Experimental Extensions
Experimental extensions can be imported into Scratch by shift-clicking the File menu and selecting Import Experimental Extension. The resulting file dialog allows you to select an extension manifest JSON file, which contains the extension name, the port on which the extension runs, and the blocks which the extension defines. It follows this format:
The extension name should be an alphanumeric string in CamelCase, e.g., SensorBoard. The extension port can be any valid port number.
Block specs include a block type (“ ” for command blocks, “f” for cap blocks, “r” for reporter blocks, or “b” for boolean reporter blocks), a block spec, and a selector (which should be a lowerCamelCase identifier). They can have additional array elements, which specify the block's default input values.
If the “useHTTP” flag is set to true in an extension manifest, Scratch will use HTTP requests rather than sockets to connect to the extension (see “Communication” below).
Below is a simple example of a socket-based extension manifest:
There is no established convention for the name of a manifest file; I name my extension manifests extension.json.
Experimental extension manifests are saved with projects under the “savedExtensions” key so that the blocks in the project can be deserialized without having to import the extension manifest again.
Communication
When an experimental extension is imported into Scratch, it attempts to connect to a server running at the extension's port on the local machine in one of two ways.
Sockets
Scratch connects to extensions which have “useHTTP”: false in their manifests using a TCP socket. Before any communication can occur between the client and server, Flash sends a request for a policy file, containing the string <policy-file-request/> terminated by a null character to the extension host on port 843. The server should respond to this request with a null-terminated cross-domain policy file allowing the connection; for example:
After this transaction is complete, Scratch sends newline-terminated JSON packets to the server of the form
Scratch periodically sends poll packets with no parameters. Additionally, it sends a packet with the same method name as the block selector whenever one of the extension's command blocks is executed; the parameters of these packets correspond to the evaluate arguments to the block.
The server can send packets of the same form back to Scratch. The only one it currently responds to is the update packet; its parameters should be a list of 2-tuples containing names and values corresponding to the selectors for the extension's reporter blocks.
HTTP
Scratch uses HTTP connections for extensions which declare “useHTTP”: true in their manifests. Before sending any other requests, Flash sends an HTTP request to http://127.0.0.1:extensionPort/crossdomain.xml and expects a Flash cross-domain policy file in response. For example, an extension could send back the following policy file:
For each reporter block declared in the manifest, Scratch regularly sends requests to http://127.0.0.1:extensionPort/selector and stores the result as the value of that reporter block.
When a command block is executed, Scratch sends a request to http://127.0.0.1:extensionPort/selector and ignores the result. Any block inputs are appended this URL, escape-encoded and preceded by a solidus. For example, running the block [log [Hello, world!]] from the example extension above would send a request to http://127.0.0.1:49001/log/Hello%2C%20world%21.
Making Experimental Extensions
I made a node.js framework for Scratch extensions. It currently only support socket-based extensions. You can check it out on Github.
Experimental Extensions
Experimental extensions can be imported into Scratch by shift-clicking the File menu and selecting Import Experimental Extension. The resulting file dialog allows you to select an extension manifest JSON file, which contains the extension name, the port on which the extension runs, and the blocks which the extension defines. It follows this format:
{ "extensionName": name, "extensionPort": port, "useHTTP": useHTTP, "blockSpecs": [ [type, spec, selector], ... ] }
Block specs include a block type (“ ” for command blocks, “f” for cap blocks, “r” for reporter blocks, or “b” for boolean reporter blocks), a block spec, and a selector (which should be a lowerCamelCase identifier). They can have additional array elements, which specify the block's default input values.
If the “useHTTP” flag is set to true in an extension manifest, Scratch will use HTTP requests rather than sockets to connect to the extension (see “Communication” below).
Below is a simple example of a socket-based extension manifest:
{ "extensionName": "ExampleExtension", "extensionPort": 49001, "blockSpecs": [ [" ", "log %s", "log", "hello, world!"], [" ", "press key %m.key", "pressKey", "space"], [" ", "increment counter", "increment"], [" ", "reset counter", "reset"], ["r", "counter", "counter"] ] }
There is no established convention for the name of a manifest file; I name my extension manifests extension.json.
Experimental extension manifests are saved with projects under the “savedExtensions” key so that the blocks in the project can be deserialized without having to import the extension manifest again.
Communication
When an experimental extension is imported into Scratch, it attempts to connect to a server running at the extension's port on the local machine in one of two ways.
Sockets
Scratch connects to extensions which have “useHTTP”: false in their manifests using a TCP socket. Before any communication can occur between the client and server, Flash sends a request for a policy file, containing the string <policy-file-request/> terminated by a null character to the extension host on port 843. The server should respond to this request with a null-terminated cross-domain policy file allowing the connection; for example:
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <allow-access-from domain="*.scratch.mit.edu" to-ports="*"/> <allow-access-from domain="*.media.mit.edu" to-ports="*"/> </cross-domain-policy>
{ "method": method, "params": [params] }
The server can send packets of the same form back to Scratch. The only one it currently responds to is the update packet; its parameters should be a list of 2-tuples containing names and values corresponding to the selectors for the extension's reporter blocks.
HTTP
Scratch uses HTTP connections for extensions which declare “useHTTP”: true in their manifests. Before sending any other requests, Flash sends an HTTP request to http://127.0.0.1:extensionPort/crossdomain.xml and expects a Flash cross-domain policy file in response. For example, an extension could send back the following policy file:
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <allow-access-from domain="*.scratch.mit.edu" to-ports="*"/> <allow-access-from domain="*.media.mit.edu" to-ports="*"/> </cross-domain-policy>
For each reporter block declared in the manifest, Scratch regularly sends requests to http://127.0.0.1:extensionPort/selector and stores the result as the value of that reporter block.
When a command block is executed, Scratch sends a request to http://127.0.0.1:extensionPort/selector and ignores the result. Any block inputs are appended this URL, escape-encoded and preceded by a solidus. For example, running the block [log [Hello, world!]] from the example extension above would send a request to http://127.0.0.1:49001/log/Hello%2C%20world%21.
Making Experimental Extensions
I made a node.js framework for Scratch extensions. It currently only support socket-based extensions. You can check it out on Github.
Last edited by nXIII (Aug. 7, 2013 19:22:58)
- easymath123
-
100+ posts
Extension Discussion Thread
[rest of quote removed]Tried The Tutorial On GitHub And Failed.
I made a node.js framework for Scratch extensions. You can check it out on Github.
a)You Haven't Written The Script Properly.
b)Node.js Has A Bug.
Last edited by nXIII (June 29, 2013 17:13:53)
- easymath123
-
100+ posts
Extension Discussion Thread
It Doesn't Say “Hello World!” In The Console, Yay! It Works!
It Just Says “Disconnected From Scratch.”.
Last edited by easymath123 (June 30, 2013 10:11:09)
- Hardmath123
-
1000+ posts
Extension Discussion Thread
Last edited by Hardmath123 (June 29, 2013 15:44:55)
- technoboy10
-
1000+ posts
Extension Discussion Thread
Awesome, now I can port my Snap! extensions to Scratch! 

- nXIII
-
1000+ posts
Extension Discussion Thread
Yeah! It's fairly limited right now, though—reporters can't have arguments (the SensorBoard blocks are hardcoded) and you can't make command blocks wait until their task completes. Awesome, now I can port my Snap! extensions to Scratch!
- nXIII
-
1000+ posts
Extension Discussion Thread
Oh, yeah… how do you do that? You should publish this on npm!
- Magnie
-
100+ posts
Extension Discussion Thread
Would it be possible to specify a domain as well as a port? Or are there other issues involved in there?
- MathWizz
-
100+ posts
Extension Discussion Thread
I've never tried it but this should get you started: https://npmjs.org/doc/publish.htm
- nXIII
-
1000+ posts
Extension Discussion Thread
Currently, Scratch only deserializes the port, name, and block specs: Would it be possible to specify a domain as well as a port? Or are there other issues involved in there?(decompiled)
var manifest:Object; try { manifest = JSON.parse(FileReference(event.target).data.toString()); } catch(e) {} if (!manifest || !("extensionName" in manifest) || !("extensionPort" in manifest) || !("blockSpecs" in manifest) { return; } var ext:ScratchExtension = new ScratchExtension(manifest.extensionName, manifest.extensionPort); ext.blockSpecs = manifest.blockSpecs; ext.showBlocks = true; extensionDict[manifest.extensionName] = ext; Scratch.app.translationChanged(); Scratch.app.updatePalette();
public var host:String = "127.0.0.1";
socket.connect(ext.host, ext.port);
- nXIII
-
1000+ posts
Extension Discussion Thread
Flash is refusing the connection to extensions built with my framework (again). I'll look into it (it worked yesterday, and I didn't change anything…?)
- DigiTechs
-
500+ posts
Extension Discussion Thread
This look nice. Once it's officially implemented we can have a /somewhat/ working connection to servers!
This is also good for my Lua server, because it wants newline terminated messages
This is also good for my Lua server, because it wants newline terminated messages

- nathanprocks
-
1000+ posts
Extension Discussion Thread
When I try to use variables, the reporter block in Scratch always returns 0 instead of what I set the variable to. Command blocks work perfectly though. Do you know why it does this and how can make it work?
- FireNinjaGAME
-
100+ posts
Extension Discussion Thread
Hmmm… This sounds interesting! Does this relate to the Remote Sensors Protocol in 1.4?
- nXIII
-
1000+ posts
Extension Discussion Thread
Yeah, it's similar—it's the external communication protocol for 2.0. Hmmm… This sounds interesting! Does this relate to the Remote Sensors Protocol in 1.4?
- nathanprocks
-
1000+ posts
Extension Discussion Thread
… When I try to use variables, the reporter block in Scratch always returns 0 instead of what I set the variable to. Command blocks work perfectly though. Do you know why it does this and how can make it work?