# Creating modular scripts and converting them to plugins

A ScriptPack is a modular collection of JavaScript files that can be loaded and unloaded as a single unit. It allows you to organize complex scripts into subfolders with a `main.js` entry point. ScriptPacks can be distributed as zip archives and can even be converted into a plugin.

#### Creating a ScriptPack

A ScriptPack is simply a folder inside the `scripts/` directory. The folder must contain a `main.js` file, this is the entry point that will be executed when the pack is loaded.

Optionally, you can include an `info.json` file for metadata and plugin conversion.

**Folder structure example:**

```
scripts/
└── mypack/
    ├── main.js          # entry point
    ├── helper.js        # additional script (can be required)
    ├── subfolder/
    │   └── utils.js
    └── info.json        # required
```

### **`main.js`** <sup><sub>(not optional)<sub></sup>

The `main.js` file is executed when the pack is loaded. It can use [`requireScript()`](https://openjs.wiki.gd/apis-and-tools/globals/requirescript) to load other scripts within the pack.

Example `main.js`:

```javascript
const helper = requireScript("helper.js")
const utils = requireScript("subfolder/utils.js")

addCommand("mypack", {
    onCommand: (sender) => {
        sender.sendMessage("Hello from mypack!")
    }
})

// Optional unload cleanup
task.bindToUnload(() => {
    removeCommand("mypack")
})
```

### **`info.json`** <sup><sub>(not optional)<sub></sup>

Used when converting the pack to a plugin (see below). It can contain:

```
{
    "name": "MyPack",
    "version": "1.0.0",
    "description": "An example script pack",
    "api-version": "1.21",
    "authors": ["Author Name"],
    "folia-supported": true
}
```

### Installing ScriptPacks

**Via zip file**

Simply drop a `.zip` file containing the pack folder (with `info.json` and `main.js`) into the `scripts/` folder. The plugin will automatically extract the zip and load the pack if `AutoReloadScriptsOnChange` is enabled.

**Via folder**

Manually create a folder inside `scripts/` and place your files there. The pack will be detected and loaded on the next reload.

#### Managing ScriptPacks

**Enabling / Disabling**

* **Enable**: `/oj enable <packName>/main.js` – loads the pack.
* **Disable**: `/oj disable <packName>/main.js` – unloads the pack and disables it.

You can also list packs with `/oj list enabled` or `/oj list disabled`.

**Reloading**

* **Reload all scripts**: `/oj reload`
* **Reload a specific pack**: `/oj reload <packName>/main.js` (only if enabled)

#### Converting to a Plugin

You can convert a ScriptPack into a standalone plugin jar using the command:

```
/oj generatePlugin <packName>
```

This will create a `.jar` file in the `convertedPlugins/` folder inside the OpenJS data folder. The generated plugin will:

* Use the metadata from `info.json` (name, version, etc.)
* Bundle the entire pack as a resource (`<packName>.zip`) inside the jar
* Extract and load the pack when the plugin is enabled
* Extracted script is linked to the plugin (if plugin is removed, the script gets removed too)

The generated plugin is a complete, installable Bukkit plugin that does require OpenJS to be installed.&#x20;

#### Example

```
// scripts/myAwesomePack/main.js
const fileManager = Services.get("FileManager")

addCommand("awesome", {
    onCommand: (sender, args) => {
        if (args[0] === "reload") {
            // Reload pack
            LoadScript("myAwesomePack/main.js")
            sender.sendMessage("§aPack reloaded!")
        } else {
            sender.sendMessage("§eWelcome to my awesome pack!")
        }
    }
})
```

**`info.json` (for plugin conversion)**

```
{
    "name": "AwesomePack",
    "version": "1.0.0",
    "description": "An awesome pack",
    "api-version": "1.20",
    "authors": ["coolcostupit"]
}
```

After converting to a plugin (`/oj generatePlugin myAwesomePack`), you get `AwesomePack.jar` (located at: `plugins/OpenJS/convertedPlugins`) that can be placed in the server’s `plugins/` folder.
