From 8a51f1ff342bb5c6fd4bb13ccde941c0a0bc303b Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 16 Sep 2025 20:52:34 -0700 Subject: [PATCH 01/43] feat(custom-extensions): init --- .vitepress/config.mts | 40 +++++++++++++++++-- extensions/dev-intro.md | 3 ++ extensions/files.md | 3 ++ extensions/format.md | 68 +++++++++++++++++++++++++++++++++ extensions/input.md | 3 ++ extensions/intro.md | 4 ++ extensions/network.md | 3 ++ extensions/platform-specific.md | 3 ++ extensions/render.md | 3 ++ extensions/runtime.md | 3 ++ extensions/updates.md | 3 ++ 11 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 extensions/dev-intro.md create mode 100644 extensions/files.md create mode 100644 extensions/format.md create mode 100644 extensions/input.md create mode 100644 extensions/intro.md create mode 100644 extensions/network.md create mode 100644 extensions/platform-specific.md create mode 100644 extensions/render.md create mode 100644 extensions/runtime.md create mode 100644 extensions/updates.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index d6277e1..3500a7c 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -29,8 +29,8 @@ export default defineConfig({ logo: "https://github.com/ScratchEverywhere/ScratchEverywhere/blob/main/gfx/logo_se.png?raw=true", siteTitle: false, - sidebar: [ - { + sidebar: { + "/": [{ items: [ { text: "Introduction", link: "/intro" }, { text: "Installation", link: "/install" }, @@ -42,7 +42,41 @@ export default defineConfig({ { text: "Controls", link: "/controls" }, { text: "Settings", link: "/settings" }, ], - }, + }], + "/extensions/": [ + { + items: [ + { text: "Introduction", link: "/extensions/intro" }, + ], + }, + { + text: "Dev", + items: [ + { text: "Introduction", link: "/extensions/dev-intro" }, + { text: "File Format", link: "/extensions/format" }, + { + text: "API", + items: [ + { text: "File System", link: "/extensions/files" }, + { text: "Network", link: "/extensions/network" }, + { text: "Input", link: "/extensions/input" }, + { text: "Render", link: "/extensions/render" }, + { text: "Updates", link: "/extensions/updates" }, + { + text: "Platform Specific", + link: "/extensions/platform-specific", + }, + { text: "Runtime", link: "/extensions/runtime" }, + ], + }, + ], + }, + ], + }, + + nav: [ + { text: "Docs", link: "/intro" }, + { text: "Custom Extension Docs", link: "/extensions/intro" }, ], socialLinks: [ diff --git a/extensions/dev-intro.md b/extensions/dev-intro.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/dev-intro.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/files.md b/extensions/files.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/files.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/format.md b/extensions/format.md new file mode 100644 index 0000000..a61da42 --- /dev/null +++ b/extensions/format.md @@ -0,0 +1,68 @@ +> [!NOTE] +> Most people shouldn't need to worry about this. This is for people +> implementing SE! extensions, and people working on compilers like seec. + +# SEE (Scratch Everywhere! Extension) + +IDK how to properly format one of these and it's a pretty simple format so... + +The first part of a `.see` file is the magic string `SE! EXTENSION` (not +null-terminated.) It's followed by a null-terminated string representing the ID +of the extension. Then there's a null-terminated string representing the name of +the extension. There's a null-terminated string representing the description of +the extension after that. The next byte is used to figure out the permissions +needed by the extension. After the permissions is a byte representing supported +platforms. Following the supported platforms is any amount of bytes representing +types of blocks, this section is null-terminated. After the types is the +corresponding IDs in the same order, each one should be null-terminated and +there should be the same amount of IDs as types. Followed by the Lua bytecode of +the extension. + +# SECE (Scratch Everywhere! Core Extension) + +`.sece` files start with the magic string `SE! CORE.EXT` (not null-terminated.) +The magic string is followed by a null-terminated string representing the name +of the extension. The name is followed by a null-terminated representing the +description of the extension. The next byte is used to figure out the +permissions needed by the extension. After the permissions is a byte +representing supported platforms. Following the supported platforms is any +amount of bytes representing types of blocks, this section is null-terminated. +After the types is the corresponding IDs in the same order, each one should be +null-terminated and there should be the same amount of IDs as types. Followed by +the Lua bytecode of the extension. + +# Permissions + +- 1st bit represents if the extension needs local file system access. This is + what should be used the majority of the time. +- 2nd bit represents if the extension needs root file system access. This is not + recommended for most extensions. +- 3rd bit represents if the extension needs internet access. +- 4th bit represents if the extension needs access to inputs. +- 5th bit represents if the extension needs access to rendering. +- 6th bit represents if the extension has update functions that need to be + called each frame. +- 7th bit represents if the extension needs access to platform specific APIs + (e.g. Amiibo or account information.) +- 8th bit represents if the extension needs access to the runtime (e.g. sprite + position, costume, or variables.) + +# Block Types + +- `0x1`: Command +- `0x2`: Hat +- `0x3`: Event +- `0x4`: Reporter +- `0x5`: Boolean + +# Supported Platforms Map + +Just `&` these together. + +- `0b00000001`: 3DS +- `0b00000010`: Wii U +- `0b00000100`: Wii +- `0b00001000`: GameCube +- `0b00010000`: Switch +- `0b00100000`: PC +- `0b01000000`: Vita diff --git a/extensions/input.md b/extensions/input.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/input.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/intro.md b/extensions/intro.md new file mode 100644 index 0000000..21f1e7c --- /dev/null +++ b/extensions/intro.md @@ -0,0 +1,4 @@ +# [WIP] Custom Extensions + +> [!WARNING] +> Custom Extensions are very WIP and don't even have an implementation yet. diff --git a/extensions/network.md b/extensions/network.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/network.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/platform-specific.md b/extensions/platform-specific.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/platform-specific.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/render.md b/extensions/render.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/render.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/runtime.md b/extensions/runtime.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/runtime.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/updates.md b/extensions/updates.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/updates.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. From 1e3837b25f0f41269b94c60977e277a7232d2e64 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 16 Sep 2025 21:09:25 -0700 Subject: [PATCH 02/43] feat(custom-extensions): init json api --- .vitepress/config.mts | 1 + extensions/json.md | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 extensions/json.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 3500a7c..12e6b1b 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -57,6 +57,7 @@ export default defineConfig({ { text: "API", items: [ + { text: "JSON", link: "/extensions/json" }, { text: "File System", link: "/extensions/files" }, { text: "Network", link: "/extensions/network" }, { text: "Input", link: "/extensions/input" }, diff --git a/extensions/json.md b/extensions/json.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/json.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. From 7d7fb4cad8a9d5d21e47c763c085e81a143d58d2 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 16 Sep 2025 21:13:32 -0700 Subject: [PATCH 03/43] feat(custom-extensions): init json api content --- extensions/json.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/extensions/json.md b/extensions/json.md index d3d6af9..9fdf337 100644 --- a/extensions/json.md +++ b/extensions/json.md @@ -1,3 +1,16 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# JSON + +The JSON API is a subset of +[Playdate's JSON API](https://sdk.play.date/inside-playdate/#M-json). + +## `json.decode(string)` + +Decodes a JSON string into a Lua table. + +## `json.encode(table)` + +Encodes a Lua table into a JSON string. + +## `json.encodePretty(table)` + +Encodes a Lua table into a JSON string, with human-readble formatting. From 011f19d06a1c594701dc56babc2095092c23712e Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 16 Sep 2025 21:24:24 -0700 Subject: [PATCH 04/43] feat(custom-extensions): add info about arg names --- extensions/json.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/json.md b/extensions/json.md index 9fdf337..d191119 100644 --- a/extensions/json.md +++ b/extensions/json.md @@ -3,14 +3,14 @@ The JSON API is a subset of [Playdate's JSON API](https://sdk.play.date/inside-playdate/#M-json). -## `json.decode(string)` +## `json.decode(json: string)` Decodes a JSON string into a Lua table. -## `json.encode(table)` +## `json.encode(data: table)` Encodes a Lua table into a JSON string. -## `json.encodePretty(table)` +## `json.encodePretty(data: table)` Encodes a Lua table into a JSON string, with human-readble formatting. From 726b89a97517bcb338e00696e716fe5e84e66a21 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 17 Sep 2025 11:26:21 -0700 Subject: [PATCH 05/43] feat(custom-extensions): init file api content --- extensions/files.md | 55 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/extensions/files.md b/extensions/files.md index d3d6af9..8b8308c 100644 --- a/extensions/files.md +++ b/extensions/files.md @@ -1,3 +1,52 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# File System + +> [!NOTE] +> The file system API requires either the root or local file system permissions. + +## Root Location + +If the root file system permission is present the file system root will be +`sdmc:/` on console, `/` on Unix-like systems (Linux, macOS, BSD), and `C:\` on +Windows. + +For the local file system permission the root location will be the +`se:/extension-data/`. + +If both are present then the root file system permission takes priority. + +## Current Directory + +If the root file system permission is present then the current directory will be +the root of the Scratch Everywhere! directory. + +If the local file system permission is present then the current directory is +`se:/extension-data/`. + +If both are present then the local file system permission takes priority. + +## `files.read(path: string)` + +Reads the entire file at the inputed path into a string. + +## `files.write(path: string, content: string)` + +Overwrites the specified file's content with the provided content. + +## `files.append(path: string, content: string)` + +Appends the specified content the specified file. + +## `files.mkdir(path: string)` + +Creates a directory at the given path. + +## `files.ls(path: string)` + +Lists all files in a directory, including dot files. + +## `files.mainDirectory` + +> [!NOTE] +> This variable is only available with the root file system permission. + +The path of the Scratch Everywhere! directory. From 59addf97dbbe0741f685a4008dc7e75719bb9ebf Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 17 Sep 2025 15:33:41 -0700 Subject: [PATCH 06/43] feat(custom-extensions): seperate functions, types --- extensions/files.md | 12 +++++++----- extensions/json.md | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/extensions/files.md b/extensions/files.md index 8b8308c..a8b6127 100644 --- a/extensions/files.md +++ b/extensions/files.md @@ -24,27 +24,29 @@ If the local file system permission is present then the current directory is If both are present then the local file system permission takes priority. +## Functions + ## `files.read(path: string)` Reads the entire file at the inputed path into a string. -## `files.write(path: string, content: string)` +### `files.write(path: string, content: string)` Overwrites the specified file's content with the provided content. -## `files.append(path: string, content: string)` +### `files.append(path: string, content: string)` Appends the specified content the specified file. -## `files.mkdir(path: string)` +### `files.mkdir(path: string)` Creates a directory at the given path. -## `files.ls(path: string)` +### `files.ls(path: string)` Lists all files in a directory, including dot files. -## `files.mainDirectory` +### `files.mainDirectory` > [!NOTE] > This variable is only available with the root file system permission. diff --git a/extensions/json.md b/extensions/json.md index d191119..92e9bd9 100644 --- a/extensions/json.md +++ b/extensions/json.md @@ -3,14 +3,16 @@ The JSON API is a subset of [Playdate's JSON API](https://sdk.play.date/inside-playdate/#M-json). -## `json.decode(json: string)` +## Functions + +### `json.decode(json: string)` Decodes a JSON string into a Lua table. -## `json.encode(data: table)` +### `json.encode(data: table)` Encodes a Lua table into a JSON string. -## `json.encodePretty(data: table)` +### `json.encodePretty(data: table)` Encodes a Lua table into a JSON string, with human-readble formatting. From dba3dc86e43298f5e591fccb8ffed06bf8597cd1 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Fri, 19 Sep 2025 18:05:40 -0700 Subject: [PATCH 07/43] feat(custom-extensions): init runtime api content --- .vitepress/config.mts | 3 + extensions/runtime.md | 355 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 355 insertions(+), 3 deletions(-) diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 12e6b1b..6de7e81 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -95,6 +95,9 @@ export default defineConfig({ search: { provider: "local", }, + outline: { + level: [2, 3], + }, }, markdown: { theme: { diff --git a/extensions/runtime.md b/extensions/runtime.md index d3d6af9..7107143 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -1,3 +1,352 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Runtime API + +## Types + +### `runtime.variable: table` + +#### `id: string` + +The ID of the variable. + +#### `name: string` + +The name of the variable. + +#### `cloud: boolean` + +`false` for normal variables and `true` for cloud variables. + +#### `value: string | number | boolean` + +The value of the variable. + +### `runtime.list: table` + +#### `id: string` + +The ID of the list. + +#### `name: string` + +The name of the list. + +#### `items: (string | number | boolean)[]` + +The items of the list. + +### `runtime.comment: table` + +#### `id: string` + +The ID of the comment. + +#### `blockId: string?` + +The ID of the block it is linked to. + +#### `content: string` + +The content of the comment. + +#### `x: number` + +The comment's X position. + +#### `y: number` + +The comment's Y position. + +#### `width: number` + +The comment's width. + +#### `height: number` + +The comment's height. + +### `runtime.broadcast: table` + +#### `id: string` + +The ID of the broadcast. + +#### `name: string` + +The name of the broadcast. + +### `runtime.blockField` + +#### `id: string` + +The ID of the field. + +#### `value: string | number | boolean` + +The parsed value of the field. + +### `runtime.blockInput` + +#### `type: "block" | "literal" | "reporter" | "variable"` + +The type of input. + +#### `literalValue: (number | string | boolean)?` + +The value of the input if the input was a literal. + +#### `variableId: string?` + +The ID of the variable inputed, only present if the type is `"variable"`. + +#### `blockId: string?` + +The ID of the block inputed, only present if the type is `"block" | "boolean"`. + +### `runtime.block: table` + +#### `id: string` + +The ID of the block. + +#### `opcode: string` + +The opcode of the block. + +#### `next: string` + +The ID of the next block. + +#### `inputs: table` + +A table representing all of the block's inputs. + +#### `fields: table` + +A table representing all of the block's fields. + +#### `shadow: boolean` + +Whether or not the block is a shadow block. + +### `runtime.monitor: table` + +#### `id: string` + +The ID of the monitor. + +#### `mode: "default" | "large" | "slider" | "list"` + +What view mode the monitor is currently in. + +#### `opcode: string` + +The block opcode this monitor belongs to. + +#### `params: table` + +A table associating names of inputs of the block the monitor belongs to with +their values. + +#### `sprite: string` + +> [!NOTE] +> This field is only present if the target the monitor belongs to is a sprite. + +The name of the sprite the monitor belongs to. + +#### `value: string | boolean | number` + +The value of the monitor. + +#### `x: integer` + +The X position of the monitor. + +#### `y: integer` + +The Y position of the monitor. + +#### `visible: boolean` + +Whether or not the monitor is visible. + +#### `min: number` + +The minimum value of the slider. + +#### `max: number` + +The maximum value of the slider. + +#### `discrete: boolean` + +Whether or not the slider snaps to integers. + +### `runtime.costume: table` + +#### `id: string` + +The ID of the costume/backdrop. + +#### `name: string` + +The name of the costume/backdrop. + +#### `dataFormat: string` + +The format of the costume/backdrop. + +#### `vector: boolean` + +Whether or not the costume/backdrop is a vector image. + +### `runtime.sound: table` + +#### `id: string` + +The ID of the sound. + +#### `name: string` + +The name of the sound. + +#### `dataFormat: string` + +The format of the sound. + +#### `sampleRate: integer` + +The sample rate of the audio file. + +#### `sampleCount: integer` + +The sample count of the audio file. + +### `runtime.target: table` + +#### `name: string` + +Name of the target. + +#### `id: string` + +ID of the target. + +#### `isStage: boolean` + +`true` if the target is the stage, `false` if it's a sprite. + +#### `draggable: boolean?` + +> [!NOTE] +> This field is only present on sprites. + +`true` if the target is draggable, `false` if it is not. + +#### `visible: boolean?` + +> [!NOTE] +> This field is only present on sprites. + +`true` if the target is visible, `false` if it's hidden. + +#### `isClone: boolean?` + +> [!NOTE] +> This field is only present on sprites. + +`true` if the target is a clone, `false` if it's the original sprite. + +#### `currentCostume: integer` + +The target's current costume/backdrop number. + +#### `volume: number` + +The target's current volume. + +#### `x: number?` + +> [!NOTE] +> This field is only present on sprites. + +The target's current X position. + +#### `y: number?` + +> [!NOTE] +> This field is only present on sprites. + +The target's current Y position. + +#### `size: number?` + +> [!NOTE] +> This field is only present on sprites. + +The target's current Size. + +#### `direction: number` + +> [!NOTE] +> This field is only present on sprites. + +The target's current direction. + +#### `layer: number?` + +> [!NOTE] +> This field is only present on sprites. + +The target's current layer number. + +#### `ghostEffect: number` + +The target's current ghost effect. + +#### `brightnessEffect: number` + +The target's current brightness effect. + +#### `colorEffect: number` + +The target's current color effect. + +#### `rotationStyle: ("None" | "All Around" | "Left Right")?` + +> [!NOTE] +> This field is only present on sprites. + +The target's current rotation style. + +#### `variables: table` + +A table representing all of the target's variables. + +#### `lists: table` + +A table representing all of the target's lists. + +#### `comments: table` + +A table representing all of the target's comments, useful for loading configs. + +#### `blocks: table` + +A table representing all of the target's blocks. + +#### `costumes: runtime.costume[]` + +An array of all costumes/backdrops for the target. + +#### `sounds: table` + +A table of sound's IDs and other data about the sound. + +### `runtime.broadcasts: table` + +A table representing all broadcasts. + +### `runtime.monitors: runtime.monitor[]` + +An array of all monitors, in the order of how they are layered. From 0f0096adaf872bf8b422fc48cb36fb93758efdb8 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Fri, 19 Sep 2025 18:21:41 -0700 Subject: [PATCH 08/43] feat(custom-extensions): new permissions and apis --- .vitepress/config.mts | 2 ++ extensions/audio.md | 3 +++ extensions/extensions.md | 3 +++ extensions/format.md | 21 +++++++++++++-------- 4 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 extensions/audio.md create mode 100644 extensions/extensions.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 6de7e81..e7987c9 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -68,6 +68,8 @@ export default defineConfig({ link: "/extensions/platform-specific", }, { text: "Runtime", link: "/extensions/runtime" }, + { text: "Audio", link: "/extensions/audio" }, + { text: "Extensions", link: "/extensions/extensions" }, ], }, ], diff --git a/extensions/audio.md b/extensions/audio.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/audio.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/extensions.md b/extensions/extensions.md new file mode 100644 index 0000000..d3d6af9 --- /dev/null +++ b/extensions/extensions.md @@ -0,0 +1,3 @@ +> [!INFO] +> This page hasn't been written yet. Please remember extensions are WIP, so +> documentation for it is incomplete. diff --git a/extensions/format.md b/extensions/format.md index a61da42..d8a7678 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -10,20 +10,20 @@ The first part of a `.see` file is the magic string `SE! EXTENSION` (not null-terminated.) It's followed by a null-terminated string representing the ID of the extension. Then there's a null-terminated string representing the name of the extension. There's a null-terminated string representing the description of -the extension after that. The next byte is used to figure out the permissions -needed by the extension. After the permissions is a byte representing supported -platforms. Following the supported platforms is any amount of bytes representing -types of blocks, this section is null-terminated. After the types is the -corresponding IDs in the same order, each one should be null-terminated and -there should be the same amount of IDs as types. Followed by the Lua bytecode of -the extension. +the extension after that. The 2 next bytes are used to figure out the +permissions needed by the extension. After the permissions is a byte +representing supported platforms. Following the supported platforms is any +amount of bytes representing types of blocks, this section is null-terminated. +After the types is the corresponding IDs in the same order, each one should be +null-terminated and there should be the same amount of IDs as types. Followed by +the Lua bytecode of the extension. # SECE (Scratch Everywhere! Core Extension) `.sece` files start with the magic string `SE! CORE.EXT` (not null-terminated.) The magic string is followed by a null-terminated string representing the name of the extension. The name is followed by a null-terminated representing the -description of the extension. The next byte is used to figure out the +description of the extension. The next 2 bytes are used to figure out the permissions needed by the extension. After the permissions is a byte representing supported platforms. Following the supported platforms is any amount of bytes representing types of blocks, this section is null-terminated. @@ -33,6 +33,8 @@ the Lua bytecode of the extension. # Permissions +(2 bytes treated like a 16 bit number, wait isn't that just a word :shrug:) + - 1st bit represents if the extension needs local file system access. This is what should be used the majority of the time. - 2nd bit represents if the extension needs root file system access. This is not @@ -46,6 +48,9 @@ the Lua bytecode of the extension. (e.g. Amiibo or account information.) - 8th bit represents if the extension needs access to the runtime (e.g. sprite position, costume, or variables.) +- 9th bit represents if the extension needs access to audio APIs. +- 10th bit represents if the extension needs access to be able to communicate + with other extensions. # Block Types From aa47c953b7e4d125121487910c603a799dedb0ad Mon Sep 17 00:00:00 2001 From: Grady Link Date: Fri, 19 Sep 2025 19:21:12 -0700 Subject: [PATCH 09/43] feat(custom-extensions): runtime wip warning --- extensions/runtime.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extensions/runtime.md b/extensions/runtime.md index 7107143..0677842 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -350,3 +350,9 @@ A table representing all broadcasts. ### `runtime.monitors: runtime.monitor[]` An array of all monitors, in the order of how they are layered. + +## Functions + +> [!WARNING] +> This page is still a work in progress so runtime functions are yet to be +> documented. From 093c6635a6686487db6ece03522da40ae8cb81c2 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Fri, 19 Sep 2025 19:22:45 -0700 Subject: [PATCH 10/43] feat(custom-extensions): split types and variables --- extensions/runtime.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extensions/runtime.md b/extensions/runtime.md index 0677842..a983ca0 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -343,6 +343,8 @@ An array of all costumes/backdrops for the target. A table of sound's IDs and other data about the sound. +## Variables + ### `runtime.broadcasts: table` A table representing all broadcasts. @@ -351,6 +353,10 @@ A table representing all broadcasts. An array of all monitors, in the order of how they are layered. +### `runtime.targets: runtime.target[]` + +An array of all targets. + ## Functions > [!WARNING] From de8fffe31da1c667b94ca4542230e345b554741a Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 24 Sep 2025 20:43:06 -0700 Subject: [PATCH 11/43] feat(custom-extensions): init extensions content --- extensions/extensions.md | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/extensions/extensions.md b/extensions/extensions.md index d3d6af9..2391d7c 100644 --- a/extensions/extensions.md +++ b/extensions/extensions.md @@ -1,3 +1,37 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Extensions + +## Variables + +### `extensions.active: string[]` + +A list of all extensions the current project uses. + +### `extensions.installed: string[]` + +A list of all extensions that are installed on the device. This does not include +extensions embedded in the project. + +### `extensions.embedded: string[]` + +A list of all embedded extensions. This includes both extensions embedded in the +project and the Scratch Everywhere! executable. + +## Functions + +### `extensions.send(id: string, message: string)` + +Sends the specified message to a specific extension. + +### `extensions.sendAll(message: string)` + +Sends the specified message to all extensions. + +### `extensions.receive(id: string, callback: fun(message: string))` + +Takes in a callback that is called whenever a message is received from a +specific extension. + +### `extensions.receiveAll(callback: fun(message: string))` + +Takes in a callback that is called whenever a message is received from any +extension. From 1d1b0cca2393c021c5d344527d44bbf3a57e4b43 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 24 Sep 2025 20:54:37 -0700 Subject: [PATCH 12/43] refactor(custom-extensions): new core extensions --- extensions/format.md | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/extensions/format.md b/extensions/format.md index d8a7678..c3c8fb9 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -7,29 +7,17 @@ IDK how to properly format one of these and it's a pretty simple format so... The first part of a `.see` file is the magic string `SE! EXTENSION` (not -null-terminated.) It's followed by a null-terminated string representing the ID -of the extension. Then there's a null-terminated string representing the name of -the extension. There's a null-terminated string representing the description of -the extension after that. The 2 next bytes are used to figure out the -permissions needed by the extension. After the permissions is a byte -representing supported platforms. Following the supported platforms is any -amount of bytes representing types of blocks, this section is null-terminated. -After the types is the corresponding IDs in the same order, each one should be -null-terminated and there should be the same amount of IDs as types. Followed by -the Lua bytecode of the extension. - -# SECE (Scratch Everywhere! Core Extension) - -`.sece` files start with the magic string `SE! CORE.EXT` (not null-terminated.) -The magic string is followed by a null-terminated string representing the name -of the extension. The name is followed by a null-terminated representing the -description of the extension. The next 2 bytes are used to figure out the -permissions needed by the extension. After the permissions is a byte -representing supported platforms. Following the supported platforms is any -amount of bytes representing types of blocks, this section is null-terminated. -After the types is the corresponding IDs in the same order, each one should be -null-terminated and there should be the same amount of IDs as types. Followed by -the Lua bytecode of the extension. +null-terminated.) The magic string is followed by a byte which should be `1` if +the extension is a core extension and a `0` in all other cases. After that is a +null-terminated string representing the ID of the extension. Then there's a +null-terminated string representing the name of the extension. There's a +null-terminated string representing the description of the extension after that. +The 2 next bytes are used to figure out the permissions needed by the extension. +After the permissions is a byte representing supported platforms. Following the +supported platforms is any amount of bytes representing types of blocks, this +section is null-terminated. After the types is the corresponding IDs in the same +order, each one should be null-terminated and there should be the same amount of +IDs as types. Followed by the Lua bytecode of the extension. # Permissions From 6e8999c56c3eaed0a7b14d7f500df2c2237d023f Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 24 Sep 2025 21:02:14 -0700 Subject: [PATCH 13/43] feat(custom-extensions): init extension info api --- extensions/extensions.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/extensions/extensions.md b/extensions/extensions.md index 2391d7c..1e0d34e 100644 --- a/extensions/extensions.md +++ b/extensions/extensions.md @@ -1,5 +1,33 @@ # Extensions +## Types + +### `extensions.info: table` + +#### `core: boolean` + +Whether or not the extension is a core extension. + +#### `id: string` + +The ID of the extension. + +#### `name: string` + +The name of the extension. + +#### `description: string` + +The extension's description. + +#### `permissions: ("localfs" | "rootfs" | "network" | "input" | "render" | "update" | "platform-specific" | "runtime" | "audio" | "extensions")[]` + +A list of all the permissions the extension has. + +#### `platforms: ("3ds" | "wiiu" | "wii" | "gamecube" | "switch" | "vita" | "pc")[]` + +A list of all the platforms the extension supports. + ## Variables ### `extensions.active: string[]` @@ -35,3 +63,8 @@ specific extension. Takes in a callback that is called whenever a message is received from any extension. + +### `extensions.getInfo(id: string)` + +Gets info about a specific custom extension. Returns a [`extensions.info`]() +table. From b9458f0a098cde88800eaaa79f79dae9d38ca68b Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 24 Sep 2025 22:19:02 -0700 Subject: [PATCH 14/43] feat(custom-extensions): init input api content --- extensions/input.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/extensions/input.md b/extensions/input.md index d3d6af9..4cb03e5 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -1,3 +1,30 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Input + +## Variables + +### `input.mappings: table` + +A table representing mappings between controller buttons and keyboard keys. + +## Functions + +### `input.keyDown(key: string)` + +> [!NOTE] +> Keys try to be as similar as possible to JavaScript's events. + +Checks if a given key is currently pressed, returns a `boolean`, does **not** +include controller buttons mapped to keys. + +### `input.buttonDown(button: string)` + +Checks if a given controller button is currently pressed. + +### `input.mouseDown(button: ("left" | "middle" | "right")?)` + +Checks if a given mouse button is down. If no button is specified it defaults to +`left`. + +### `input.onEvent(event: "click" | "keydown" | "keyup" | "buttondown" | "buttonup", handler: fun(data: string))` + +Adds an event handler for a specific event. From 215a1df82c5b94f775a66d91df0b9e27b76de25f Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 25 Sep 2025 17:14:43 -0700 Subject: [PATCH 15/43] feat(custom-extensions): add clone api --- extensions/runtime.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/runtime.md b/extensions/runtime.md index a983ca0..0e28d17 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -359,6 +359,6 @@ An array of all targets. ## Functions -> [!WARNING] -> This page is still a work in progress so runtime functions are yet to be -> documented. +### `runtime.clone(id: string)` + +Creates a clone of a specific sprite. From ed9b556b21844b80d874b3dcf632a176a6892f45 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 25 Sep 2025 17:21:50 -0700 Subject: [PATCH 16/43] feat(custom-extensions): add update api content --- extensions/updates.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/extensions/updates.md b/extensions/updates.md index d3d6af9..e361fd3 100644 --- a/extensions/updates.md +++ b/extensions/updates.md @@ -1,3 +1,19 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Updates + +## Functions + +### `update.preUpdate(cb: fun())` + +A function that is called before Scratch Everywhere! updates. + +### `update.postUpdate(cb: fun())` + +A function that is called after Scratch Everywhere! updates. + +### `update.preRender(cb: fun())` + +A function that is called before Scratch Everywhere! renders. + +### `update.postRender(cb: fun())` + +A function that is called after Scratch Everywhere! renders. From 8dbedfc44347482eb959b31686631cc4dbf7acd8 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 25 Sep 2025 18:51:40 -0700 Subject: [PATCH 17/43] feat(custom-extensions): add runtime api warning --- extensions/runtime.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/runtime.md b/extensions/runtime.md index 0e28d17..1103738 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -362,3 +362,6 @@ An array of all targets. ### `runtime.clone(id: string)` Creates a clone of a specific sprite. + +> [!WARNING] +> The runtime API is currently missing some functions which will be added later. From 02f70be3167c2f104f780ccfac51fbfbc0640539 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 25 Sep 2025 18:55:08 -0700 Subject: [PATCH 18/43] feat(custom-extensions): runtime api username --- extensions/runtime.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/runtime.md b/extensions/runtime.md index 1103738..f044412 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -357,6 +357,10 @@ An array of all monitors, in the order of how they are layered. An array of all targets. +### `runtime.username: string` + +The current username. + ## Functions ### `runtime.clone(id: string)` From 92016558def0179f4f8d3fc6ee1901dcf7c1cb82 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 1 Oct 2025 20:11:49 -0700 Subject: [PATCH 19/43] refactor(custom-extensions): improve format layout --- extensions/format.md | 76 +++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/extensions/format.md b/extensions/format.md index c3c8fb9..2dfb791 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -4,24 +4,33 @@ # SEE (Scratch Everywhere! Extension) -IDK how to properly format one of these and it's a pretty simple format so... +All strings are UTF-8. -The first part of a `.see` file is the magic string `SE! EXTENSION` (not -null-terminated.) The magic string is followed by a byte which should be `1` if -the extension is a core extension and a `0` in all other cases. After that is a -null-terminated string representing the ID of the extension. Then there's a -null-terminated string representing the name of the extension. There's a -null-terminated string representing the description of the extension after that. -The 2 next bytes are used to figure out the permissions needed by the extension. -After the permissions is a byte representing supported platforms. Following the -supported platforms is any amount of bytes representing types of blocks, this -section is null-terminated. After the types is the corresponding IDs in the same -order, each one should be null-terminated and there should be the same amount of -IDs as types. Followed by the Lua bytecode of the extension. +## Magic Strings -# Permissions +All `.see` files start with the magic string `SE! EXTENSION` (not +null-terminated.) -(2 bytes treated like a 16 bit number, wait isn't that just a word :shrug:) +## Core Extensions + +The core extensions flag is made up of 1 byte that is either `0` if the +extension is not a core extension, or `1` of the extension is a core extension. +Core extensions allow creating blocks that are not tied to the specific +extension ID. + +## Extension Info + +The extension info section contains information about the extension. It is made +up of 3 null-terminated strings in this order: + +- Extension ID +- Extension Name +- Extension Description + +## Permissions + +The permissions section contains the necessary permissions the extension needs, +it is made up of a single unsigned 16-bit integer. - 1st bit represents if the extension needs local file system access. This is what should be used the majority of the time. @@ -40,7 +49,29 @@ IDs as types. Followed by the Lua bytecode of the extension. - 10th bit represents if the extension needs access to be able to communicate with other extensions. -# Block Types +## Supported Platforms + +The platforms section is just a single byte with its bits representing the +platforms that the extension works on. Most extensions should support all +platforms. + +- 1st bit: 3DS +- 2nd bit: Wii U +- 3rd bit: Wii +- 4th bit: GameCube +- 5th bit: Switch +- 6th bit: PC +- 7th bit: Vita + +## Blocks + +The blocks section is actually split into two sub-sections, the block types +section and the block IDs section. + +### Block Types + +The block types section itself is null-terminated and is simply represented by 1 +byte for each block which tells the runtime what type of block, each block is. - `0x1`: Command - `0x2`: Hat @@ -48,14 +79,7 @@ IDs as types. Followed by the Lua bytecode of the extension. - `0x4`: Reporter - `0x5`: Boolean -# Supported Platforms Map - -Just `&` these together. +### Block IDs -- `0b00000001`: 3DS -- `0b00000010`: Wii U -- `0b00000100`: Wii -- `0b00001000`: GameCube -- `0b00010000`: Switch -- `0b00100000`: PC -- `0b01000000`: Vita +After the block types is the block IDs. Each ID is a null-terminated string. +There should be the same amount of IDs as types. From d278a838592eacb6e9da2a5672fcfe8b05164763 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 1 Oct 2025 20:15:04 -0700 Subject: [PATCH 20/43] feat(custom-extensions): version info in format --- extensions/format.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/extensions/format.md b/extensions/format.md index 2dfb791..d385f34 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -11,6 +11,13 @@ All strings are UTF-8. All `.see` files start with the magic string `SE! EXTENSION` (not null-terminated.) +## Version Info + +This section contains all info about versioning. It is made up of 3 bytes. The +first byte is the version of this file format, the second byte is the major +version of the API the extension was designed for, and the third byte is the +minor version of the API the extension was designed for. + ## Core Extensions The core extensions flag is made up of 1 byte that is either `0` if the From a2c15ade4a927120c84769f5355b8c39f4a4000d Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 1 Oct 2025 20:20:16 -0700 Subject: [PATCH 21/43] feat(custom-extensions): add versions to format --- extensions/format.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extensions/format.md b/extensions/format.md index d385f34..06c4398 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -18,6 +18,14 @@ first byte is the version of this file format, the second byte is the major version of the API the extension was designed for, and the third byte is the minor version of the API the extension was designed for. +### File Format Versions + +- `0` + +### API Versions + +- `0.0` + ## Core Extensions The core extensions flag is made up of 1 byte that is either `0` if the From ecce2facb1919a577046d95bc8b3dc36792843a6 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 1 Oct 2025 20:28:53 -0700 Subject: [PATCH 22/43] feat(custom-extensions): add testing to versions --- extensions/format.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/format.md b/extensions/format.md index 06c4398..734f21c 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -20,11 +20,11 @@ minor version of the API the extension was designed for. ### File Format Versions -- `0` +- `0` (testing) ### API Versions -- `0.0` +- `0.0` (testing) ## Core Extensions From f6605225aa3ec7f02b0d4d46c6505a1261cf98d4 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 1 Oct 2025 20:29:47 -0700 Subject: [PATCH 23/43] fix(custom-extensions): add missing lua bytecode --- extensions/format.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/format.md b/extensions/format.md index 734f21c..2c6f764 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -98,3 +98,7 @@ byte for each block which tells the runtime what type of block, each block is. After the block types is the block IDs. Each ID is a null-terminated string. There should be the same amount of IDs as types. + +## Lua Bytecode + +Following everything else is simply just some compiled Lua bytecode (`.luac`). From 4edfdf886429e3f32d45f871848d934ad3672248 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 2 Oct 2025 19:41:10 -0700 Subject: [PATCH 24/43] feat(custom-extensions): add more input stuff --- extensions/input.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/extensions/input.md b/extensions/input.md index 4cb03e5..9409312 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -6,6 +6,14 @@ A table representing mappings between controller buttons and keyboard keys. +### `input.mouseX: number` + +The mouse's X position. + +### `input.mouseY: number` + +The mouse's Y position. + ## Functions ### `input.keyDown(key: string)` @@ -25,6 +33,21 @@ Checks if a given controller button is currently pressed. Checks if a given mouse button is down. If no button is specified it defaults to `left`. -### `input.onEvent(event: "click" | "keydown" | "keyup" | "buttondown" | "buttonup", handler: fun(data: string))` +### `input.getAxis(joystick: ("left" | "right"), axis: ("x" | "y"))` + +Gets the value of a specific joystick axis. + +### `input.onEvent(event: "click" | "keydown" | "keyup" | "buttondown" | "buttonup" | "mousedown" | "mouseup" | "joystickmove", handler: fun(data: string?))` + +Adds an event handler for a specific event. The following is the data given from +each event: -Adds an event handler for a specific event. +- `click`: The mouse button that was pressed, `"left" | "right" | "middle"` +- `keydown`: The key that was pressed. +- `keyup`: The key that was released. +- `buttondown`: The button that was pressed. +- `buttonup`: The button that was released. +- `mousemove`: `nil` +- `mousedown`: The mouse button that was pressed, `"left" | "right" | "middle"` +- `mouseup`: The mouse button that was released, `"left" | "right" | "middle"` +- `joystickmove`: The joystick that was moved, `"left" | "right"` From b6040837c94a205e3928588d89512155f2e2ff2d Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 2 Oct 2025 20:05:40 -0700 Subject: [PATCH 25/43] feat(custom-extensions): render api content --- extensions/render.md | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/extensions/render.md b/extensions/render.md index d3d6af9..b95b6ff 100644 --- a/extensions/render.md +++ b/extensions/render.md @@ -1,3 +1,40 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Render + +## Types + +### `render.renderTarget: "screen1" | "screen2"` + + + +Simply which screen to draw to, if a device only has one screen, you need to use +`"screen1"`. + +## Functions + +### `render.setColor(target: render.renderTarget, r: number, g: number, b: number)` + +Sets the color to be used in subsequent operations. + +### `render.drawRect(target: render.renderTarget, x: number, y: number, width: number, height: number)` + +Draws a rectangle outline at the given position with the given size. + +### `render.fillRect(target: render.renderTarget, x: number, y: number, width: number, height: number)` + +Draws a filled rectangle at the given position with the given size. + +### `render.drawCircle(target: render.renderTarget, x: number, y: number, radius: number)` + +Draws a circle outline at the given position with the given radius. + +### `render.fillCircle(target: render.renderTarget, x: number, y: number, radius: number)` + +Draws a filled circle at the given position with the given radius. + +### `render.drawLine(target: render.renderTarget, x1: number, y1: number, x2: number, y2: number)` + +Draws a line between two points. + +### `render.drawImage(target: render.renderTarget, x: number, y: number, dataUrl: string)` + +Draws an image in the form of a data url. From 5308790f34d006643a838d525d57ef27f84179d0 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 2 Oct 2025 20:07:15 -0700 Subject: [PATCH 26/43] chore(custom-extensions): remove runtime warning --- extensions/runtime.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/extensions/runtime.md b/extensions/runtime.md index f044412..a565849 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -366,6 +366,3 @@ The current username. ### `runtime.clone(id: string)` Creates a clone of a specific sprite. - -> [!WARNING] -> The runtime API is currently missing some functions which will be added later. From 7b431e5f7ddec6a42559cb3e3f39078edfdf4f06 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 2 Oct 2025 20:38:25 -0700 Subject: [PATCH 27/43] feat(custom-extensions): get costume as data url --- extensions/runtime.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/runtime.md b/extensions/runtime.md index a565849..6409762 100644 --- a/extensions/runtime.md +++ b/extensions/runtime.md @@ -366,3 +366,7 @@ The current username. ### `runtime.clone(id: string)` Creates a clone of a specific sprite. + +### `runtime.costumeAsDataUrl(costumeId: string)` + +Simply gets a costume as a data url. From b19de09f9020f03e42cef30988d2a53149c96ad5 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 7 Oct 2025 18:59:30 -0700 Subject: [PATCH 28/43] feat(custom-extensions): init network api content --- extensions/network.md | 63 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/extensions/network.md b/extensions/network.md index d3d6af9..f092198 100644 --- a/extensions/network.md +++ b/extensions/network.md @@ -1,3 +1,60 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Networking + +> [!IMPORTANT] +> The current version of the extension API does **not** support SSL. It is also +> currently missing a WebSockets API so you'll need to use raw TCP for now. + +## Types + +### `network.http.response: table` + +#### `statusCode: integer` + +The status code of the response. + +#### `statusMessage: string` + +The status message of the response. + +#### `body: string` + +The response's body. + +#### `headers: table` + +The response headers. + +## Variables + +### `network.connected: boolean` + +Whether or not we are currently connected to the internet. + +## Functions + +### `network.http.get(address: string, headers?: string | table | string[]): network.http.response` + +Makes a `GET` request to a specific URL. + +### `network.http.head(address: string, headers?: string | table | string[]): network.http.response` + +Makes a `HEAD` request to a specific URL. + +### `network.http.delete(address: string, headers?: string | table | string[]): network.http.response` + +Makes a `DELETE` request to a specific URL. + +### `network.http.post(address: string, headers?: string | table | string[], data: any): network.http.response` + +Makes a `POST` request to a specific URL. Any data passed in will automatically +be converted to a string with tables being converted to JSON. + +### `network.http.put(address: string, headers?: string | table | string[], data: any): network.http.response` + +Makes a `PUT` request to a specific URL. Any data passed in will automatically +be converted to a string with tables being converted to JSON. + +### `network.http.patch(address: string, headers?: string | table | string[], data: any): network.http.response` + +Makes a `PATCH` request to a specific URL. Any data passed in will automatically +be converted to a string with tables being converted to JSON. From f0eb7d9d59716fa1823d03f055ab634f801bd58a Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 7 Oct 2025 21:59:00 -0700 Subject: [PATCH 29/43] feat(custom-extensions): add big endian note --- extensions/format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/format.md b/extensions/format.md index 2c6f764..ab121d2 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -4,7 +4,7 @@ # SEE (Scratch Everywhere! Extension) -All strings are UTF-8. +All strings are UTF-8 and all numbers are big endian. ## Magic Strings From 3b0b2a8c17539e69159bedbbfc351d24b0acc8bc Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 8 Oct 2025 20:07:48 -0700 Subject: [PATCH 30/43] feat(custom-extensions): init settings --- .vitepress/config.mts | 1 + extensions/format.md | 32 ++++++++++++++++++++++++++++++++ extensions/general.md | 9 +++++++++ 3 files changed, 42 insertions(+) create mode 100644 extensions/general.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index e7987c9..fb6c26a 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -57,6 +57,7 @@ export default defineConfig({ { text: "API", items: [ + { text: "General", link: "/extensions/general" }, { text: "JSON", link: "/extensions/json" }, { text: "File System", link: "/extensions/files" }, { text: "Network", link: "/extensions/network" }, diff --git a/extensions/format.md b/extensions/format.md index ab121d2..a1f706d 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -78,6 +78,38 @@ platforms. - 6th bit: PC - 7th bit: Vita +## Settings + +The settings section allows custom extensions to provide modifiable settings +available in the runtime's UI. + +The section begins with a single byte for the number of settings available in +the extension. + +The rest of the section is made up of data for each setting. The size of these +settings is not always the same (not even the same number of data types.) All +settings start with a single byte repsenting the type of the extension, followed +by 2 null-terminated strings, one for the ID of the setting, and another for the +name of the setting. The name and ID is always followed by a default value, the +size of which varies between types. Some types also have additional data. + +### Toggles + +Toggles have the type of `0x12`. Toggles' default value is a single byte with a +`1` representing enabled and a `0` representing disabled. + +### Text + +Text settings have the type of `0x63`. Their default value is a null-terminated +string. They also have another null-terminated string called the prompt which is +what will be displayed in the on-screen keyboard when editing the text setting. + +### Sliders + +Sliders have the type of `0x6E`. Their default value is a 32-bit float. Sliders +also have an additional three 32-bit floats in this order, slider max, slider +minimum, and slider snap. + ## Blocks The blocks section is actually split into two sub-sections, the block types diff --git a/extensions/general.md b/extensions/general.md new file mode 100644 index 0000000..a07f54e --- /dev/null +++ b/extensions/general.md @@ -0,0 +1,9 @@ +# General API + +These are functions, variables, and types that don't really have dedicated APIs. + +## Variables + +### `settings: table` + +A table representing each settings' ID and its value. From ce5be462a982364032b64e18932bf2a6b1240b5b Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 14 Oct 2025 17:52:44 -0700 Subject: [PATCH 31/43] refactor(custom-extensions): simpler update api --- extensions/updates.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/updates.md b/extensions/updates.md index e361fd3..afb4209 100644 --- a/extensions/updates.md +++ b/extensions/updates.md @@ -1,19 +1,19 @@ # Updates -## Functions +## Extension Defined Functions -### `update.preUpdate(cb: fun())` +### `update.preUpdate()` A function that is called before Scratch Everywhere! updates. -### `update.postUpdate(cb: fun())` +### `update.postUpdate()` A function that is called after Scratch Everywhere! updates. -### `update.preRender(cb: fun())` +### `update.preRender()` A function that is called before Scratch Everywhere! renders. -### `update.postRender(cb: fun())` +### `update.postRender()` A function that is called after Scratch Everywhere! renders. From 67d2fdf664c2658d3b859755663b039045ae5c96 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Tue, 14 Oct 2025 18:32:28 -0700 Subject: [PATCH 32/43] fix(custom-extensions): files heading level --- extensions/files.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/files.md b/extensions/files.md index a8b6127..9db91a9 100644 --- a/extensions/files.md +++ b/extensions/files.md @@ -26,7 +26,7 @@ If both are present then the local file system permission takes priority. ## Functions -## `files.read(path: string)` +### `files.read(path: string)` Reads the entire file at the inputed path into a string. From db9119e7341a31380dba36768fdc39792931cef0 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 15 Oct 2025 18:24:19 -0700 Subject: [PATCH 33/43] feat(custom-extensions): add `"any"` as mouse btn --- extensions/input.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extensions/input.md b/extensions/input.md index 9409312..30ab530 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -28,7 +28,7 @@ include controller buttons mapped to keys. Checks if a given controller button is currently pressed. -### `input.mouseDown(button: ("left" | "middle" | "right")?)` +### `input.mouseDown(button: ("left" | "middle" | "right" | "any")?)` Checks if a given mouse button is down. If no button is specified it defaults to `left`. @@ -48,6 +48,8 @@ each event: - `buttondown`: The button that was pressed. - `buttonup`: The button that was released. - `mousemove`: `nil` -- `mousedown`: The mouse button that was pressed, `"left" | "right" | "middle"` -- `mouseup`: The mouse button that was released, `"left" | "right" | "middle"` +- `mousedown`: The mouse button that was pressed, + `"left" | "right" | "middle" | "any"` +- `mouseup`: The mouse button that was released, + `"left" | "right" | "middle" | "any"` - `joystickmove`: The joystick that was moved, `"left" | "right"` From 40d91658fa6f95b12b042cf4a4704f98a497ec26 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Wed, 15 Oct 2025 20:21:36 -0700 Subject: [PATCH 34/43] fix(custom-extensions): `"any"` in event handler --- extensions/input.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/extensions/input.md b/extensions/input.md index 30ab530..30764aa 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -48,8 +48,6 @@ each event: - `buttondown`: The button that was pressed. - `buttonup`: The button that was released. - `mousemove`: `nil` -- `mousedown`: The mouse button that was pressed, - `"left" | "right" | "middle" | "any"` -- `mouseup`: The mouse button that was released, - `"left" | "right" | "middle" | "any"` +- `mousedown`: The mouse button that was pressed, `"left" | "right" | "middle"` +- `mouseup`: The mouse button that was released, `"left" | "right" | "middle"` - `joystickmove`: The joystick that was moved, `"left" | "right"` From 5757b9160e4c548788d4a27b9248ac735a930fb1 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 16 Oct 2025 21:23:49 -0700 Subject: [PATCH 35/43] feat(custom-extensions): remove `input.onEvent` pretty useless imo and really hard to properly implement --- extensions/input.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/extensions/input.md b/extensions/input.md index 30764aa..ce8a3c1 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -36,18 +36,3 @@ Checks if a given mouse button is down. If no button is specified it defaults to ### `input.getAxis(joystick: ("left" | "right"), axis: ("x" | "y"))` Gets the value of a specific joystick axis. - -### `input.onEvent(event: "click" | "keydown" | "keyup" | "buttondown" | "buttonup" | "mousedown" | "mouseup" | "joystickmove", handler: fun(data: string?))` - -Adds an event handler for a specific event. The following is the data given from -each event: - -- `click`: The mouse button that was pressed, `"left" | "right" | "middle"` -- `keydown`: The key that was pressed. -- `keyup`: The key that was released. -- `buttondown`: The button that was pressed. -- `buttonup`: The button that was released. -- `mousemove`: `nil` -- `mousedown`: The mouse button that was pressed, `"left" | "right" | "middle"` -- `mouseup`: The mouse button that was released, `"left" | "right" | "middle"` -- `joystickmove`: The joystick that was moved, `"left" | "right"` From 85c538bf2cc845da38688de676c58b9225e8b1b3 Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 16 Oct 2025 21:26:30 -0700 Subject: [PATCH 36/43] feat(custom-extensions): init `input.devices` --- extensions/input.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/input.md b/extensions/input.md index ce8a3c1..4648e45 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -14,6 +14,10 @@ The mouse's X position. The mouse's Y position. +### `input.devices: ("keyboard" | "mouse" | "controller")[]` + +A list of input devices connected to the device running Scratch Everrywhere!. + ## Functions ### `input.keyDown(key: string)` From a364ac679d434e4c0e0604c5b632c21c80aacb5a Mon Sep 17 00:00:00 2001 From: Grady Link Date: Thu, 16 Oct 2025 21:30:13 -0700 Subject: [PATCH 37/43] feat(custom-extensions): add touch input device --- extensions/input.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/input.md b/extensions/input.md index 4648e45..d34dd1f 100644 --- a/extensions/input.md +++ b/extensions/input.md @@ -14,7 +14,7 @@ The mouse's X position. The mouse's Y position. -### `input.devices: ("keyboard" | "mouse" | "controller")[]` +### `input.devices: ("keyboard" | "mouse" | "controller" | "touchscreen")[]` A list of input devices connected to the device running Scratch Everrywhere!. From b1ed164c277b06dfcd3cea2cab844711fd1ae36c Mon Sep 17 00:00:00 2001 From: Grady Link Date: Sat, 28 Mar 2026 20:49:52 -0700 Subject: [PATCH 38/43] chore(custom-extensions): add new platforms --- extensions/format.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/extensions/format.md b/extensions/format.md index a1f706d..a4a8c96 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -66,9 +66,9 @@ it is made up of a single unsigned 16-bit integer. ## Supported Platforms -The platforms section is just a single byte with its bits representing the -platforms that the extension works on. Most extensions should support all -platforms. +The platforms section is a single unsigned 16-bit integer with its bits +representing the platforms that the extension works on. Most extensions should +support all platforms. - 1st bit: 3DS - 2nd bit: Wii U @@ -77,6 +77,11 @@ platforms. - 5th bit: Switch - 6th bit: PC - 7th bit: Vita +- 8th bit: NDS +- 9th bit: PS4 +- 10th bit: PSP +- 11th bit: webOS +- 12th bit: WASM ## Settings From 64c3626aa6dc6dbf71c35ec29e24bbccfa99b818 Mon Sep 17 00:00:00 2001 From: gradylink Date: Fri, 23 Oct 2026 18:58:41 -0700 Subject: [PATCH 39/43] chore(extensions/format): add og xbox --- extensions/format.md | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/format.md b/extensions/format.md index a4a8c96..c0c8390 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -82,6 +82,7 @@ support all platforms. - 10th bit: PSP - 11th bit: webOS - 12th bit: WASM +- 13th bit: OG Xbox ## Settings From 090bd8ec2493fc0e98c15495310367212c5fbc22 Mon Sep 17 00:00:00 2001 From: gradylink Date: Fri, 23 Oct 2026 19:02:55 -0700 Subject: [PATCH 40/43] chore(extensions/format): update version stuff --- extensions/format.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/format.md b/extensions/format.md index c0c8390..bc58987 100644 --- a/extensions/format.md +++ b/extensions/format.md @@ -20,11 +20,12 @@ minor version of the API the extension was designed for. ### File Format Versions -- `0` (testing) +- `0`: initial +- `1`: added Xbox to the platforms flag ### API Versions -- `0.0` (testing) +- `0.1`: initial ## Core Extensions @@ -82,7 +83,7 @@ support all platforms. - 10th bit: PSP - 11th bit: webOS - 12th bit: WASM -- 13th bit: OG Xbox +- 13th bit: Xbox ## Settings From 0c3e788cf171d0267b78d0bfab452d3dd591084e Mon Sep 17 00:00:00 2001 From: gradylink Date: Fri, 23 Oct 2026 19:11:25 -0700 Subject: [PATCH 41/43] fix(extensions/extensions): add missing platforms --- extensions/extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/extensions.md b/extensions/extensions.md index 1e0d34e..41e9635 100644 --- a/extensions/extensions.md +++ b/extensions/extensions.md @@ -24,7 +24,7 @@ The extension's description. A list of all the permissions the extension has. -#### `platforms: ("3ds" | "wiiu" | "wii" | "gamecube" | "switch" | "vita" | "pc")[]` +#### `platforms: ("3ds" | "wiiu" | "wii" | "gamecube" | "switch" | "vita" | "pc" | "xbox" | "wasm" | "psp" | "ps4" | "nds" | "webos")[]` A list of all the platforms the extension supports. From c35f56b68aa82e5b32026a71e442cdf7b5dac6ce Mon Sep 17 00:00:00 2001 From: Starlii10 Date: Fri, 23 Oct 2026 22:46:02 -0400 Subject: [PATCH 42/43] feat(intro): init --- extensions/intro.md | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/extensions/intro.md b/extensions/intro.md index 21f1e7c..096f21a 100644 --- a/extensions/intro.md +++ b/extensions/intro.md @@ -1,4 +1,41 @@ -# [WIP] Custom Extensions +# Introduction to Custom Extensions > [!WARNING] -> Custom Extensions are very WIP and don't even have an implementation yet. +> Custom extensions are a **work-in-progress**. + +**Custom extensions** are a way to add new blocks and functionality to the +Scratch Everywhere! runtime that can be used in your projects. + +Not all platforms support custom extensions. See the +[limitations page](/limitations.md#platform-specific) for a list of platforms +that do. + +Custom extensions come in two forms: **Lua extensions** and **native +extensions**. Native extensions are more powerful, while Lua extensions are +simpler to use. + +## Installation + +### Lua Extensions + +Lua extensions must be compiled before they are installed. Use +[seec](https://github.com/ScratchEverywhere/seec) to compile them: + +```sh +seec -i /path/to/extension/main.lua -m /path/to/extension/meta.json -o /path/to/output/extension.see +``` + +Alternatively, to compile all of the available Lua extensions, use +`bun build.ts` in the root directory of the Lua extension repository: + +```sh +git clone https://github.com/ScratchEverywhere/lua-extensions +cd lua-extensions/ +bun build.ts +``` + +The resulting `.see` files can be found in the `bin` folder. + +Place the `.see` files in your Scratch Everywhere! folder +(`scratch-everywhere/extensions`) and they will be automatically loaded when a +project uses them! From 3d506f2575d0451bf802b813d90307ce640974eb Mon Sep 17 00:00:00 2001 From: Starlii10 Date: Fri, 23 Oct 2026 22:46:15 -0400 Subject: [PATCH 43/43] feat(dev-intro): init --- extensions/dev-intro.md | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/extensions/dev-intro.md b/extensions/dev-intro.md index d3d6af9..9e7438a 100644 --- a/extensions/dev-intro.md +++ b/extensions/dev-intro.md @@ -1,3 +1,35 @@ -> [!INFO] -> This page hasn't been written yet. Please remember extensions are WIP, so -> documentation for it is incomplete. +# Developer Intro to Custom Extensions + +Custom extensions come in two forms: **Lua extensions** and **native +extensions**. Native extensions are more powerful as they have direct access to +the SE! source code, and are best used for complex blocks or those with strict +performance requirements. Lua extensions are better for simple blocks, as they +are easy to program. + +## Lua Extensions + +Lua extensions are broken into two parts: the Lua code itself and a metadata +JSON file. As an example, here's the `meta.json` for the JSON extension: + +```json +{ + "$schema": "https://raw.githubusercontent.com/ScratchEverywhere/seec/refs/heads/main/schema.json", + "core": false, + "id": "skyhigh173JSON", + "name": "JSON", + "description": "Handle JSON strings and arrarys.", + "permissions": [] +} +``` + +The format of this file can be found in the schema file. + +Compiling a Lua extension is done with +[seec](https://github.com/ScratchEverywhere/seec). + +## Native Extensions + +Native extensions require that you are able to compile SE! itself. In order for +a native extension to work on Scratch Everywhere!, it must be built on the +**same system**, using the **same compiler** and the **same arguments**, with +the **same version of Scratch Everywhere!**.