Create Your Plugin
Before getting started, make sure you have the following tools installed:
1. Create Plugin Project
Create from Template Repository
We provide a plugin template repository based on TypeScript. You can either clone this repository directly to create your plugin project, or click the Use this template button to create a new repository.
git clone https://github.com/IceBlcokMC/js_engine_plugin_template.git
cd js_engine_plugin_templateCreate from Scratch
You can also manually create a plugin project from scratch. You can refer to our template repository to learn how to create a plugin project. We won't go into details here.
2. Install Dependencies
npm installThis command will install necessary dependencies, including typescript, @types/node, etc.
After the install is complete, the postinstall script will run, which pulls the latest types files from the Js_Engine repository and installs them in your project.
3. Configure Plugin
Open your project with VSCode, then open the package.json file. You'll see the following configuration items:
{
"main": "index.js",
"type": "module",
"scripts": {
"build": "tsc",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"postinstall": "node ./scripts/pull_types.cjs",
"postbuild": "node scripts/pack.cjs"
},
"devDependencies": {
"@types/node": "^22.10.3",
"@typescript-eslint/eslint-plugin": "^8.19.0",
"@typescript-eslint/parser": "^8.19.0",
"eslint": "^9.17.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-n": "^17.15.1",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^7.2.1",
"fs-extra": "^11.2.0",
"prettier": "^3.4.2"
}
}As you can see, the plugin project doesn't use all fields in package.json, only a portion. The main field specifies the entry file, which Js_Engine will use to load your plugin. The type field specifies whether your plugin uses CommonJS or ES Module. Here we use ES Module, so the type field is set to module.
WARNING
Note that if your plugin uses ES Module, your JSE.registerPlugin needs to be placed as early as possible to ensure it executes first. Due to the asynchronous loading nature of the ESM module system, Js_Engine will pre-post up to 15 event loops when loading plugins with type: module. Therefore, you need to ensure that JSE.registerPlugin completes within this time, otherwise the engine cannot obtain the plugin's information.
4. Register Commands
After configuring the plugin project, open the src/index.ts file and register a simple command:
JSE.registerPlugin({
name: "my_plugin",
version: "1.0.0",
onLoad: () => {
console.log("Plugin loaded!");
},
onEnable: () => {
console.log("Plugin enabled!");
},
onDisable: () => {
console.log("Plugin disabled!");
},
});The plugin template has already registered a my_plugin plugin for us. We just need to make some simple modifications.
JSE.registerPlugin({
name: "helloworld",
version: "1.0.0",
permissions: {
hello: {
default: Enums.PermissionDefault.True,
description: "Allows the user to say hello",
},
},
commands: {
hello: {
description: "Says hello to the user",
permissions: ["hello"],
usages: ["/hello"],
},
},
onLoad: () => {
console.log("Plugin loaded!");
},
onEnable: () => {
console.log("Plugin enabled!");
},
onDisable: () => {
console.log("Plugin disabled!");
},
});As you can see, we registered a helloworld plugin and registered a hello command with the hello permission.
TIP
If you need to add parameters to commands, you can check the endstone documentation
INFO
JSE.registerPlugin accepts an object as a parameter that describes the plugin's metadata, including plugin name, version, permissions, commands, etc. For a complete list of parameters, see the API documentation
WARNING
The object passed to JSE.registerPlugin is only parsed when the plugin loads, and this object is readonly, so you cannot modify this object during plugin runtime.
5. Listen for Commands
After registering the command, we need to listen for this command so we can handle it when users execute it.
JSE.registerPlugin({
name: "helloworld",
version: "1.0.0",
permissions: {
hello: {
default: Enums.PermissionDefault.True,
description: "Allows the user to say hello",
},
},
commands: {
hello: {
description: "Says hello to the user",
permissions: ["hello"],
usages: ["/hello"],
},
},
onLoad: () => {
console.log("Plugin loaded!");
},
onEnable: () => {
console.log("Plugin enabled!");
},
onDisable: () => {
console.log("Plugin disabled!");
},
onCommand(sender, command, args) {
if (command.getName() === "hello") {
sender.sendMessage("Hello world!");
}
return true;
},
});Now, when users execute the /hello command, the plugin will output Hello world!.
WARNING
Due to issues with the loading mechanism, the engine needs to wait for ES (Endstone) to allocate some resources. Therefore, you cannot access any Endstone resources (such as Logger, etc.) before the onLoad method is called. You cannot access any Minecraft resources (such as getServer, etc.) before the onEnable method is called. JSE, FileAPI classes, and other Node APIs are not affected.
6. Compile and Run Plugin
After completing the plugin development, we need to compile it to JavaScript and then run it.
npm run buildAfter compilation, we can find the compiled plugin files in the dist directory. We put the dist folder in the plugins folder and then run the server.
TIP
Of course, you can also rename dist to your plugin name for better management.
endstoneAfter the server is running, we can enter the /hello command in the console and see the output Hello world!.
PS D:\Codes> endstone
[2025-01-23 16:26:48.593 INFO] [EndstoneRuntime] Initialising...
// ...
[2025-01-23 16:26:50.408 INFO] [Server] This server is running Endstone version: 0.5.7.1 (Minecraft: 1.21.50)
[2025-01-23 16:26:51.402 INFO] [JsEngine] Loading js_engine v0.1.0
[2025-01-23 16:26:51.512 INFO] [JsEngine] Load javascript plugin...
[2025-01-23 16:26:51.871 INFO] [Helloworld] Loading helloworld v1.0.0
Plugin loaded!
// ...
[2025-01-23 16:26:54.527 INFO] [JsEngine] Enabling js_engine v0.1.0
[2025-01-23 16:26:54.529 INFO] [Helloworld] Enabling helloworld v1.0.0
Plugin enabled!
? hello
[2025-01-23 16:27:03.221 INFO] [Server] hello:
[2025-01-23 16:27:03.222 INFO] [Server] Says hello to the user
[2025-01-23 16:27:03.223 INFO] [Server] Usage:
[2025-01-23 16:27:03.224 INFO] [Server] - /hello
hello
[2025-01-23 16:27:07.011 INFO] [Server] Hello world!
[2025-01-23 16:27:16.139 INFO] [Server] Server stop requested.
[2025-01-23 16:27:16.158 INFO] [Server] Stopping server...
[2025-01-23 16:27:16.280 INFO] [JsEngine] Disabling js_engine v0.1.0
[2025-01-23 16:27:16.281 INFO] [Helloworld] Disabling helloworld v1.0.0
Plugin disabled!
Quit correctly7. Publish Your Plugin
After completing plugin development and testing, you can publish your plugin to the plugin marketplace for other users to use.