commit f52f82b867376f64a970987a8c2a221e7cbdda15
Author: Forest <77603428+ForestOfLight@users.noreply.github.com>
Date: Mon Mar 10 19:24:48 2025 -0700
Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..860f418
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+.vscode/
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1e7eecb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 ForestOfLight
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..36b2827
--- /dev/null
+++ b/README.md
@@ -0,0 +1,73 @@
+
+
+
+
+
Canopy Extension Example
+
+[](https://app.codacy.com/gh/ForestOfLight/Canopy-Extension-Example/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
+[-brightgreen)](https://feedback.minecraft.net/hc/en-us/sections/360001186971-Release-Changelogs)
+[](LICENSE)
+[](https://discord.gg/9KGche8fxm)
+
+
+---
+
+Extensions?! In a behavior pack?! Yep! This repo contains an example pack designed to teach you how to create your own extensions for **Canopy**. All extensions must be added to the same world as **Canopy** (the dependencies in the `manifest.json` should ensure that).
+
+## How this example pack functions ingame
+
+What **Canopy** handles:
+
+**`./canopy [true/false]`**
+**Canopy** will automatically include the names of your rules in the `./canopy` command.
+
+**`./help`**
+**Canopy** will automatically include a Rules and a Commands help page for your extension.
+
+
+
+What the extension handles:
+
+**`./example [message]`**
+This command sends a message to the chat. It also has a default message if no message is provided. (Alias: `./ex`)
+
+**`commandExample`**
+This rule will enable the `./example` command.
+
+**`exampleRule`**
+This rule will enable a message in chat when you push a button.
+
+## How to create an extension
+
+1. Clone this repo.
+ ```sh
+ git clone https://github.com/ForestOfLight/canopy-extension-example.git
+ ```
+2. Remove all files that are not the `pack_icon.png`, the `manifest.json` file, or in the `scripts/` folder.
+3. Rename the folder to your extension's name.
+ ```sh
+ mv canopy-extension-example your-extension-name
+ ```
+4. Open the folder in your favorite code editor.
+5. Edit the `manifest.json` file to match your extension's information.
+6. Replace the `pack_icon.png` with your extension's icon.
+7. Edit the `main.js` file to add your extension's functionality.
+
+> [!TIP]
+> Most information about how to code a **Canopy Extension** can be found in the `main.js` file.
+
+## How to use an extension
+
+1. Add the extension pack to the same world as the **Canopy** RP & BP.
+2. Profit.
+
+**Canopy** will automatically detect the extension and load it!
+
+## How does this work?
+
+**Canopy** and its extensions all communicate using scriptevents! The vanilla `/scriptevent` command allows for sending strings to Behavior Packs and the `ScriptEventCommandMessage` event allows for recieving them. **Canopy** uses [MCBE-IPC](https://https://github.com/OmniacDev/MCBE-IPC), a library that streamlines the process of sending and recieving scriptevents.
+**Canopy Extensions** use these to communicate with **Canopy** when new rules and commands are added. **Canopy** uses these as well to get rule data, set rule data, and call command callbacks from extensions.
+
+## Issues & Suggestions
+
+If you have any issues or suggestions, please open an issue on this repo. Additionally, if you're interested in contributing to the project, feel free to open a pull request!
diff --git a/example_help.png b/example_help.png
new file mode 100644
index 0000000..4889a69
Binary files /dev/null and b/example_help.png differ
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..c4b9575
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,40 @@
+{
+ "format_version": 2,
+ "header": {
+ "name": "Canopy Extension Example",
+ "description": "Example extension for §l§aCanopy§r by §aForestOfLight§r.",
+ "uuid": "e4e844d5-f45b-4623-82a7-534d44bb4c6f",
+ "min_engine_version": [1, 21, 60],
+ "version": [1, 0, 0]
+ },
+ "modules": [
+ {
+ "description": "Behavior Pack Module",
+ "type": "data",
+ "uuid": "1ce9eab8-0d4a-4e40-a899-575791a1b40d",
+ "version": [1, 0, 0]
+ },
+ {
+ "description": "Gametest Module",
+ "type": "script",
+ "language": "javascript",
+ "entry": "scripts/main.js",
+ "uuid": "839a937e-b4f9-4484-84a4-0db984822f25",
+ "version": [1, 0, 0]
+ }
+ ],
+ "dependencies": [
+ {
+ "module_name": "@minecraft/server",
+ "version": "1.18.0-beta"
+ },
+ {
+ "uuid": "bcf34368-ed0c-4cf7-938e-582cccf9950d", // Canopy RP
+ "version": [1, 0, 2]
+ },
+ {
+ "uuid": "7f6b23df-a583-476b-b0e4-87457e65f7c0", // Canopy BP
+ "version": [1, 3, 8]
+ }
+ ]
+}
diff --git a/pack_icon.png b/pack_icon.png
new file mode 100644
index 0000000..dfa91e7
Binary files /dev/null and b/pack_icon.png differ
diff --git a/scripts/lib/canopy/CanopyExtension.js b/scripts/lib/canopy/CanopyExtension.js
new file mode 100644
index 0000000..4e39608
--- /dev/null
+++ b/scripts/lib/canopy/CanopyExtension.js
@@ -0,0 +1,166 @@
+/**
+ * @license
+ * MIT License
+ *
+ * Copyright (c) 2024 ForestOfLight
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+import { world } from '@minecraft/server';
+import IPC from '../../lib/ipc/ipc';
+import Command from './Command';
+import Rule from './Rule';
+import { CommandCallbackRequest, CommandPrefixRequest, Ready, RegisterCommand, RegisterExtension, RegisterRule, RuleValueRequest, RuleValueSet, CommandPrefixResponse, RuleValueResponse } from './extension.ipc';
+
+class CanopyExtension {
+ name;
+ version;
+ author;
+ description;
+ #commands = {};
+ #rules = {};
+ #isRegistrationReady = false;
+
+ constructor({ name = 'Unnamed', version = '1.0.0', author = 'Unknown', description = { text: '' } }) {
+ this.id = this.#makeID(name);
+ this.name = name;
+ this.version = version;
+ this.author = author;
+ this.description = description;
+
+ this.#registerExtension();
+ this.#setupCommandPrefix();
+ this.#handleCommandCallbacks();
+ this.#handleRuleValueRequests();
+ this.#handleRuleValueSetters();
+ }
+
+ addCommand(command) {
+ if (!(command instanceof Command))
+ throw new Error('Command must be an instance of Command.');
+ this.#commands[command.getName()] = command;
+ if (this.#isRegistrationReady)
+ this.#registerCommand(command);
+ }
+
+ addRule(rule) {
+ if (!(rule instanceof Rule))
+ throw new Error('Rule must be an instance of Rule.');
+ this.#rules[rule.getID()] = rule;
+ if (this.#isRegistrationReady)
+ this.#registerRule(rule);
+ }
+
+ getRuleValue(ruleID) {
+ return this.#rules[ruleID].getValue();
+ }
+
+ #makeID(name) {
+ if (typeof name !== 'string')
+ throw new Error(`[${name}] Could not register extension. Extension name must be a string.`);
+ const id = name.toLowerCase().replace(/[^a-z0-9 ]/g, '').replace(/ /g, '_');
+ if (id.length === 0)
+ throw new Error(`[${name}] Could not register extension. Extension name must contain at least one alphanumeric character.`);
+ return id;
+ }
+
+ #registerExtension() {
+ IPC.once('canopyExtension:ready', Ready, () => {
+ IPC.send('canopyExtension:registerExtension', RegisterExtension, {
+ name: this.name,
+ version: this.version,
+ author: this.author,
+ description: this.description
+ });
+ });
+ IPC.once(`canopyExtension:${this.id}:ready`, Ready, () => {
+ this.#isRegistrationReady = true;
+ for (const rule of Object.values(this.#rules))
+ this.#registerRule(rule);
+ for (const command of Object.values(this.#commands))
+ this.#registerCommand(command);
+ });
+ }
+
+ #registerCommand(command) {
+ IPC.send(`canopyExtension:${this.id}:registerCommand`, RegisterCommand, {
+ name: command.getName(),
+ description: command.getDescription(),
+ usage: command.getUsage(),
+ callback: false,
+ args: command.getArgs(),
+ contingentRules: command.getContingentRules(),
+ adminOnly: command.isAdminOnly(),
+ helpEntries: command.getHelpEntries(),
+ helpHidden: command.isHelpHidden(),
+ extensionName: this.name
+ });
+ }
+
+ #handleCommandCallbacks() {
+ IPC.on(`canopyExtension:${this.id}:commandCallbackRequest`, CommandCallbackRequest, (cmdData) => {
+ if (cmdData.senderName === undefined)
+ return;
+ const sender = world.getPlayers({ name: cmdData.senderName })[0];
+ if (!sender)
+ throw new Error(`Sender ${cmdData.senderName} of ${cmdData.commandName} not found.`);
+ const parsedArgs = JSON.parse(cmdData.args);
+ this.#commands[cmdData.commandName].runCallback(sender, parsedArgs);
+ });
+ }
+
+ #registerRule(rule) {
+ IPC.send(`canopyExtension:${this.id}:registerRule`, RegisterRule, {
+ identifier: rule.getID(),
+ description: rule.getDescription(),
+ contingentRules: rule.getContigentRules(),
+ independentRules: rule.getIndependentRules(),
+ extensionName: this.name
+ });
+ if (rule.getValue() === true)
+ rule.onEnable();
+ }
+
+ #handleRuleValueRequests() {
+ IPC.handle(`canopyExtension:${this.id}:ruleValueRequest`, RuleValueRequest, RuleValueResponse, (data) => {
+ const rule = this.#rules[data.ruleID];
+ if (!rule)
+ throw new Error(`Rule ${data.ruleID} not found.`);
+ const value = rule.getValue();
+ return { value };
+ });
+ }
+
+ #handleRuleValueSetters() {
+ IPC.on(`canopyExtension:${this.id}:ruleValueSet`, RuleValueSet, (data) => {
+ const rule = this.#rules[data.ruleID];
+ if (!rule)
+ throw new Error(`Rule ${data.ruleID} not found.`);
+ rule.setValue(data.value);
+ });
+ }
+
+ #setupCommandPrefix() {
+ const prefix = IPC.invoke(`canopyExtension:commandPrefixRequest`, CommandPrefixRequest, void 0, CommandPrefixResponse).then(result => {
+ Command.setPrefix(result.prefix);
+ });
+ }
+}
+
+export { CanopyExtension, Command, Rule };
\ No newline at end of file
diff --git a/scripts/lib/canopy/Command.js b/scripts/lib/canopy/Command.js
new file mode 100644
index 0000000..9d0651d
--- /dev/null
+++ b/scripts/lib/canopy/Command.js
@@ -0,0 +1,103 @@
+/**
+ * @license
+ * MIT License
+ *
+ * Copyright (c) 2024 ForestOfLight
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+class Command {
+ #name;
+ #description;
+ #usage;
+ #callback;
+ #args;
+ #contingentRules;
+ #adminOnly;
+ #helpEntries;
+ #helpHidden;
+ static #prefix = '';
+
+ constructor({ name, description = '', usage, callback, args = [], contingentRules = [], adminOnly = false, helpEntries = [], helpHidden = false }) {
+ this.#name = name;
+ this.#description = description;
+ this.#usage = usage;
+ this.#callback = callback;
+ this.#args = args;
+ this.#contingentRules = contingentRules;
+ this.#adminOnly = adminOnly;
+ this.#helpEntries = helpEntries;
+ this.#helpHidden = helpHidden;
+ }
+
+ getName() {
+ return this.#name;
+ }
+
+ getDescription() {
+ return this.#description;
+ }
+
+ getUsage() {
+ return this.#usage;
+ }
+
+ getCallback() {
+ return this.#callback;
+ }
+
+ getArgs() {
+ return this.#args;
+ }
+
+ getContingentRules() {
+ return this.#contingentRules;
+ }
+
+ isAdminOnly() {
+ return this.#adminOnly;
+ }
+
+ getHelpEntries() {
+ return this.#helpEntries;
+ }
+
+ isHelpHidden() {
+ return this.#helpHidden;
+ }
+
+ runCallback(sender, args) {
+ this.#callback(sender, args);
+ }
+
+ sendUsage(sender) {
+ sender.sendMessage(`§cUsage: ${Command.#prefix}${this.#usage}`);
+ }
+
+ static setPrefix(prefix) {
+ Command.#prefix = prefix;
+ }
+
+ static getPrefix() {
+ return Command.#prefix;
+ }
+}
+
+export default Command;
\ No newline at end of file
diff --git a/scripts/lib/canopy/Rule.js b/scripts/lib/canopy/Rule.js
new file mode 100644
index 0000000..cafae2f
--- /dev/null
+++ b/scripts/lib/canopy/Rule.js
@@ -0,0 +1,76 @@
+/**
+ * @license
+ * MIT License
+ *
+ * Copyright (c) 2024 ForestOfLight
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+import { world } from '@minecraft/server';
+
+class Rule {
+ #identifier;
+ #description;
+ #contingentRules;
+ #independentRules;
+
+ constructor({ identifier, description, contingentRules = [], independentRules = [], onEnableCallback = () => {}, onDisableCallback = () => {} }) {
+ this.#identifier = identifier;
+ this.#description = description;
+ this.#contingentRules = contingentRules;
+ this.#independentRules = independentRules;
+ this.onEnable = onEnableCallback;
+ this.onDisable = onDisableCallback;
+ }
+
+ getID() {
+ return this.#identifier;
+ }
+
+ getDescription() {
+ return this.#description;
+ }
+
+ getContigentRules() {
+ return this.#contingentRules;
+ }
+
+ getIndependentRules() {
+ return this.#independentRules;
+ }
+
+ getValue() {
+ const value = world.getDynamicProperty(this.#identifier);
+ if (String(value) === 'true')
+ return true;
+ if (['false', 'undefined'].includes(String(value)))
+ return false;
+ throw new Error(`Rule ${this.#identifier} has an invalid value: ${value} (${typeof value})`);
+ }
+
+ setValue(value) {
+ if (value === true)
+ this.onEnable();
+ else
+ this.onDisable();
+ world.setDynamicProperty(this.#identifier, value);
+ }
+}
+
+export default Rule;
\ No newline at end of file
diff --git a/scripts/lib/canopy/extension.ipc.js b/scripts/lib/canopy/extension.ipc.js
new file mode 100644
index 0000000..5e00ab3
--- /dev/null
+++ b/scripts/lib/canopy/extension.ipc.js
@@ -0,0 +1,70 @@
+/* eslint-disable new-cap */
+import { PROTO } from '../ipc/ipc'
+
+const description = PROTO.Object({
+ text: PROTO.Optional(PROTO.String),
+ translate: PROTO.Optional(PROTO.String),
+ with: PROTO.Optional(PROTO.Array(PROTO.String))
+});
+
+export const Ready = PROTO.Void;
+
+export const RegisterExtension = PROTO.Object({
+ name: PROTO.String,
+ version: PROTO.String,
+ author: PROTO.String,
+ description: description,
+ isEndstone: PROTO.Boolean
+});
+
+export const RegisterCommand = PROTO.Object({
+ name: PROTO.String,
+ description: description,
+ usage: PROTO.String,
+ callback: PROTO.Optional(PROTO.Undefined),
+ args: PROTO.Optional(PROTO.Array(PROTO.Object({
+ type: PROTO.String,
+ name: PROTO.String
+ }))),
+ contingentRules: PROTO.Optional(PROTO.Array(PROTO.String)),
+ adminOnly: PROTO.Optional(PROTO.Boolean),
+ helpEntries: PROTO.Optional(PROTO.Array(PROTO.Object({
+ usage: PROTO.String,
+ description: description
+ }))),
+ helpHidden: PROTO.Optional(PROTO.Boolean),
+ extensionName: PROTO.Optional(PROTO.String)
+});
+
+export const RegisterRule = PROTO.Object({
+ identifier: PROTO.String,
+ description: description,
+ contingentRules: PROTO.Optional(PROTO.Array(PROTO.String)),
+ independentRules: PROTO.Optional(PROTO.Array(PROTO.String)),
+ extensionName: PROTO.Optional(PROTO.String)
+});
+
+export const RuleValueRequest = PROTO.Object({
+ ruleID: PROTO.String
+});
+
+export const RuleValueResponse = PROTO.Object({
+ value: PROTO.Boolean
+});
+
+export const RuleValueSet = PROTO.Object({
+ ruleID: PROTO.String,
+ value: PROTO.Boolean
+});
+
+export const CommandCallbackRequest = PROTO.Object({
+ commandName: PROTO.String,
+ senderName: PROTO.Optional(PROTO.String),
+ args: PROTO.String
+});
+
+export const CommandPrefixRequest = PROTO.Void;
+
+export const CommandPrefixResponse = PROTO.Object({
+ prefix: PROTO.String
+});
\ No newline at end of file
diff --git a/scripts/lib/ipc/ipc.d.ts b/scripts/lib/ipc/ipc.d.ts
new file mode 100644
index 0000000..dc6ef67
--- /dev/null
+++ b/scripts/lib/ipc/ipc.d.ts
@@ -0,0 +1,103 @@
+/**
+ * @license
+ * MIT License
+ *
+ * Copyright (c) 2025 OmniacDev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+export declare namespace PROTO {
+ interface Serializable {
+ serialize(value: T, stream: ByteQueue): Generator;
+ deserialize(stream: ByteQueue): Generator;
+ }
+ class ByteQueue {
+ private _buffer;
+ private _data_view;
+ private _length;
+ private _offset;
+ get end(): number;
+ get front(): number;
+ get data_view(): DataView;
+ constructor(size?: number);
+ write(...values: number[]): void;
+ read(amount?: number): number[];
+ ensure_capacity(size: number): void;
+ static from_uint8array(array: Uint8Array): ByteQueue;
+ to_uint8array(): Uint8Array;
+ }
+ namespace MIPS {
+ function serialize(byte_queue: PROTO.ByteQueue): Generator;
+ function deserialize(str: string): Generator;
+ }
+ const Void: PROTO.Serializable;
+ const Null: PROTO.Serializable;
+ const Undefined: PROTO.Serializable;
+ const Int8: PROTO.Serializable;
+ const Int16: PROTO.Serializable;
+ const Int32: PROTO.Serializable;
+ const UInt8: PROTO.Serializable;
+ const UInt16: PROTO.Serializable;
+ const UInt32: PROTO.Serializable;
+ const UVarInt32: PROTO.Serializable;
+ const Float32: PROTO.Serializable;
+ const Float64: PROTO.Serializable;
+ const String: PROTO.Serializable;
+ const Boolean: PROTO.Serializable;
+ const UInt8Array: PROTO.Serializable;
+ const Date: PROTO.Serializable;
+ function Object(obj: {
+ [K in keyof T]: PROTO.Serializable;
+ }): PROTO.Serializable;
+ function Array(value: PROTO.Serializable): PROTO.Serializable;
+ function Tuple(...values: {
+ [K in keyof T]: PROTO.Serializable;
+ }): PROTO.Serializable;
+ function Optional(value: PROTO.Serializable): PROTO.Serializable;
+ function Map(key: PROTO.Serializable, value: PROTO.Serializable): PROTO.Serializable