Discuss Scratch
- nXIII
- Scratcher
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
- Scratcher
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)
- Hardmath123
- Scratcher
1000+ posts
Extension Discussion Thread
Last edited by Hardmath123 (June 29, 2013 15:44:55)
- technoboy10
- Scratcher
1000+ posts
Extension Discussion Thread
Awesome, now I can port my Snap! extensions to Scratch!
trans rights are human rights
- MathWizz
- Scratcher
100+ posts
Extension Discussion Thread
You should publish this on npm!
running Chromium 42.0.2311.90 with Flash Player 15.0.0.189 on Arch Linux 3.19.5-1-ck
MathWizz — JsScratch && sb.js & Amber (coming soon! maybe)
- Magnie
- Scratcher
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?
▴ ▾ ▴ Macbook Pro 13" 2015 i5-5257U 8GB RAM - MacOS Sierra - Vivaldi v1.7 ▴ ▾ ▴
There are 10 types of people in this world, those who understand binary, those who don't, and those who know ternary.
- MathWizz
- Scratcher
100+ posts
Extension Discussion Thread
I've never tried it but this should get you started: https://npmjs.org/doc/publish.htm
running Chromium 42.0.2311.90 with Flash Player 15.0.0.189 on Arch Linux 3.19.5-1-ck
MathWizz — JsScratch && sb.js & Amber (coming soon! maybe)
- nXIII
- Scratcher
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);
- DigiTechs
- Scratcher
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
I do, in fact, have my own site; it's here.
I'm also working on a thing called Fetch. Look at it here!
@thisandagain pls explain. @thisandagain pls explain. @thisandagain pls explain. @thisandagain pls explain. @thisandagain pls explain.
- nathanprocks
- Scratcher
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
- Scratcher
100+ posts
Extension Discussion Thread
Hmmm… This sounds interesting! Does this relate to the Remote Sensors Protocol in 1.4?
Moving on from Scratch, to much bigger things. It's gonna be one fun adventure.
- nathanprocks
- Scratcher
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?