{"id":43785187,"url":"https://github.com/brickadia-community/omegga","last_synced_at":"2026-02-05T19:02:42.207Z","repository":{"id":40258438,"uuid":"289722349","full_name":"brickadia-community/omegga","owner":"brickadia-community","description":"Brickadia server wrapper, automator, and plugin runner","archived":false,"fork":false,"pushed_at":"2026-02-01T21:05:28.000Z","size":19542,"stargazers_count":39,"open_issues_count":19,"forks_count":13,"subscribers_count":7,"default_branch":"master","last_synced_at":"2026-02-02T04:39:59.609Z","etag":null,"topics":["application","omegga","server-wrapper","tool"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/omegga","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brickadia-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-08-23T16:17:21.000Z","updated_at":"2026-02-01T21:05:32.000Z","dependencies_parsed_at":"2023-12-03T03:19:08.861Z","dependency_job_id":"24ba4e22-4834-4bcf-80ac-d67f9c637dbd","html_url":"https://github.com/brickadia-community/omegga","commit_stats":{"total_commits":412,"total_committers":11,"mean_commits":37.45454545454545,"dds":0.4247572815533981,"last_synced_commit":"c61085e0f2ccf6c6fa2866242fdd25cfc177e6c2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/brickadia-community/omegga","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brickadia-community%2Fomegga","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brickadia-community%2Fomegga/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brickadia-community%2Fomegga/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brickadia-community%2Fomegga/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brickadia-community","download_url":"https://codeload.github.com/brickadia-community/omegga/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brickadia-community%2Fomegga/sbom","scorecard":{"id":253573,"data":{"date":"2025-08-11","repo":{"name":"github.com/brickadia-community/omegga","commit":"8610ddbbde4b952db4ba546096dd3e69ac6d13da"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/lint.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":1,"reason":"Found 3/20 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 16 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/brickadia-community/omegga/lint.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/brickadia-community/omegga/lint.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/lint.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/brickadia-community/omegga/lint.yml/master?enable=pin","Warn: npmCommand not pinned by hash: templates/safe-ts/setup.sh:4","Warn: npmCommand not pinned by hash: templates/safe/setup.sh:4","Warn: npmCommand not pinned by hash: templates/unsafe/setup.sh:4","Warn: npmCommand not pinned by hash: .github/workflows/lint.yml:24","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   1 out of   5 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: ISC License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-cchq-frgv-rjh5","Warn: Project is vulnerable to: GHSA-g644-9gfx-q4q4"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T09:03:07.039Z","repository_id":40258438,"created_at":"2025-08-17T09:03:07.039Z","updated_at":"2025-08-17T09:03:07.039Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29130113,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T18:55:47.139Z","status":"ssl_error","status_checked_at":"2026-02-05T18:55:04.010Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["application","omegga","server-wrapper","tool"],"created_at":"2026-02-05T19:02:40.018Z","updated_at":"2026-02-05T19:02:42.189Z","avatar_url":"https://github.com/brickadia-community.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Omegga\n\nRead the README first before asking questions! [Join the discord](https://discord.gg/UcdwTYhS75) to browse plugins and get support.\n\nOmegga wraps [Brickadia](https://brickadia.com/)'s server console to provide interactivity and utility via plugins along with a web interface for managing your server.\n\nOmegga can do things like:\n\n- Automatically update/restart your server\n- Manage your worlds from a web interface and load a world on startup/restart\n- Chat with players while not on the server\n- Read chat history with timestamps\n- See kick and ban history\n- Configure plugins from a web interface\n\nOmegga plugins can do things like:\n\n- Add custom chat !commands and /commands\n- Respond to and send chat messages\n- Load bricks to player's clipboards\n- Load/Clear regions of bricks\n- Damage/heal players\n- Give/remove weapons to players\n- Change the environment\n- Create/delete minigames, and join/leave players from minigames\n- Teleport players, detect player's positions\n- Grant players roles\n- Detect when a brick with an interact component is clicked\n\n## Screenshots\n\n[\u003cimg src=\"https://i.imgur.com/AqJF2T0.png\" width=\"256\"/\u003e](https://i.imgur.com/AqJF2T0.png)\n[\u003cimg src=\"https://i.imgur.com/vGjKoB6.png\" width=\"256\"/\u003e](https://i.imgur.com/vGjKoB6.png)\n[\u003cimg src=\"https://i.imgur.com/EhT1GBR.png\" width=\"256\"/\u003e](https://i.imgur.com/EhT1GBR.png)\n[\u003cimg src=\"https://i.imgur.com/PLwgVlx.png\" width=\"256\"/\u003e](https://i.imgur.com/PLwgVlx.png)\n[\u003cimg src=\"https://i.imgur.com/bCnQ5Pb.png\" width=\"256\"/\u003e](https://i.imgur.com/bCnQ5Pb.png)\n\n## Install\n\nYou can run omegga in the [Windows Subsystem for Linux](#wsl) (I recommend Ubuntu) or on an actual linux install.\n\n\u003cfont size=\"5\" color=\"red\"\u003eDo not install omegga or run brickadia/omegga as root/superuser\u003c/font\u003e:\n\n- running `whoami` should NOT print \"root\"\n- your terminal prompt should NOT end with #\n- you should NOT be typing `sudo npm i -g omegga`\n- running `echo $EUID` should NOT print \"0\"\n- if you type `pwd` it should NOT print \"/root\" (type `cd` to navigate to your user's home dir)\n\nIf any of the above are true, [create a new user](#creating-a-new-user) and continue from there.\n\nIf you need to run omegga as root, make sure your branch is `main-server` or `unstable-server`, as `main` will not work as root.\n\n### Quick Setup\n\n1. Install linux if you haven't already ([Windows Install](#wsl) is not that bad)\n\n2. If you type `whoami` and it says \"root\", [create a new user](#creating-a-new-user) and come back. This step is usually only necessary for people using a VPS.\n\n3. Run these commands (Installs a node installer, installs node, installs omegga):\n\n    ```sh\n    # download nvm\n    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash\n\n    # activate nvm\n    . ~/.nvm/nvm.sh\n\n    # install node version 24\n    nvm install 24\n\n    # install omegga\n    npm i -g omegga\n    ```\n\n4. Head over to [Running Omegga](#running) or troubleshoot below.\n\n### Install Troubleshooting\n\nIf you are having issues running omegga, see the [troubleshooting](#troubleshooting) section for a potential fix. This section is for issues with installing.\n\n  - If you are on Ubuntu and the output of `which npm` is `/bin/npm`\n    ```sh\n    sudo apt purge nodejs # uninstall old version of nodejs\n    # restart install instructions from this point\n    nvm install 24 # install node version 24 via nvm\n    ```\n\n  - If you get an error like \"`sh: 28: cd: can't cd to .`\", you need to be in `bash` (and probably type `cd` to navigate out of root directory):\n\n    ```sh\n    bash # use bash instead of sh\n    cd # navigate home\n    ```\n\n  - If you get an error like \"`gyp info find Python using Python version 3.8.10 found at /usr/bin/python3`\" you need to install python3:\n\n    ```sh\n    sudo apt install python3\n    npm i -g omegga\n    ```\n\n  - If you get an error like \"`gyp ERR! stack Error: not found: make`\" you need to install build-essential:\n    ```sh\n    sudo apt install build-essential # install make\n    npm i -g omegga # re-run omegga install\n    ```\n\n  - If you get an error like \"`Unable to fetch some archives, maybe run apt-get update`\" you need to run this before running your original command:\n    ```sh\n    sudo apt update \u0026\u0026 sudo apt upgrade\n    ```\n\n  - If you are having trouble installing with nvm and are running **Ubuntu/Debian**, run the following commands (installs node, installs omegga) instead or install node\u0026npm from [NodeSource Binary Distributions](https://github.com/nodesource/distributions/blob/master/README.md).\n\n    ```sh\n    curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -\n    sudo apt-get install -y nodejs\n    npm i -g omegga\n    ```\n\n### Manual Setup (you install stuff)\n\nOmegga depends on:\n\n- linux\n  - [Windows Install](https://docs.microsoft.com/en-us/windows/wsl/install-win10#manual-installation-steps) (WSL 1 or WSL 2)\n    - [Windows Ubuntu](https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6)\n- Node v23+ ([ubuntu/deb](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions), but `nvm` from Quick Setup is better)\n- One of:\n  - `tar` (most linuxes come with this, though you can `sudo apt install tar`)\n  - [Brickadia linux launcher](https://brickadia.com/download)\n\nOmegga is installed as a global npm package\n\n    npm i -g omegga\n\nAlternatively, you can use a development/local omegga.\n\n```sh\n# clone omegga\ngit clone https://github.com/brickadia-community/omegga.git \u0026\u0026 cd omegga\n\n# install dependencies\nnpm i\n\n# point development omegga to global npm bin\nnpm link\n\n# build the web ui, build omegga's typescript, and the plugin omegga.d.ts\nnpm run dist\n```\n\nIf you accidentally install both from Github and `npm i -g omegga`, you can run `npm unlink omegga` to stop npm from using the git one.\n\nAny errors, see the [troubleshooting](#troubleshooting) section for a potential fix.\n\n### WSL\n\nThese are simple instructions to get Windows System for Linux installed.\n\n**Note**: WSL 2 at the moment requires the [wsl2binds plugin](https://github.com/Meshiest/omegga-wsl2binds). You can install it with `omegga install gh:meshiest/wsl2binds`\n\nTo enable WSL, run this in powershell as an administrator:\n\n```powershell\ndism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart\n```\n\nThen in the Microsoft Store, download a linux:\n\n- [Ubuntu](https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6)\n\n[More Advanced Instructions here](https://docs.microsoft.com/en-us/windows/wsl/install-win10#manual-installation-steps) if the above is not sufficient.\n\nTo set WSL version from 2 to 1:\n\n1. Check WSL version with `wsl -l -v` in cmd\n2. In Administrator cmd, run `wsl --set-version \u003cdistribution name\u003e 1` where `\u003cdistribution name\u003e` is `Ubuntu`, `Debian`, etc. (From the NAME section of the previous command)\n\n### Creating a New User\n\nIf you are running as root (terminal prompt ends with '#' instead of '$' or running `whoami` says \"root\"), create a new user.\n\nThe following commands will create a user named `brickadia`. Feel free to replace it to `user` or your own name.\n\n```sh\n# create the user\nuseradd -m brickadia\n# set the new user's password\npasswd brickadia\n# allow \"sudo apt install ....\" to work in this user\nusermod -aG sudo brickadia\n\n# become this user, navigate to user's home, and run bash\nsu brickadia -c \"cd \u0026\u0026 bash\"\n\n# if you were root, you would be in /root (root's home) instead of /home/brickadia\n# this fixes some issues when installing omegga on a VPS\n```\n\n## Running\n\nIt's recommend to create a folder first _before_ starting your server:\n\n```sh\n# change \"myServer\" to \"brickadia\" or \"server\" or whatever you want\nmkdir myServer \u0026\u0026 cd myServer\n\n# this will place a folder called \"myServer\" in your home (cd ~)\n```\n\nTo start a server, simply type the following in a linux shell after install:\n\n    omegga\n\nOmegga will prompt for credentials as necessary and only stores the auth tokens brickadia generates on login. **Omegga does not store your password**.\n\n## Updating\n\nOmegga will tell you when it's out of date. You can update with this command:\n\n    npm i -g omegga\n\nIf don't have automatic update enabled, you can start update the Brickadia server by starting omegga with the `--update` flag:\n\n    omegga --update\n\nOr you can run the `/update` command in the Omegga console, or even update from the Server menu in the web UI.\n\n## Configuration\n\n- CLI config via `omegga config`\n- Omegga config is located in a generated `omegga-config.yml`\n- Plugin config is managed inside the web-ui's plugins tab.\n- Plugin config can also be set with `omegga set-config pluginName configName configValue`\n- Plugin config can be fetched with `omegga get-config pluginName`\n\nExample available `omegga-config.yml` fields\n\n```yaml\nomegga:\n  port: 8080\n  webui: true\n  https: true\n  debug: false\ncredentials:\n  token: # hosting token can go here instead of global config\n  # if you are hosting servers for multiple people\nserver:\n  port: 7777\n  map: Plate\n  # Specifying a branch will use the old launcher instead of SteamCMD\n  # This does not have full auto-updater support yet, though the game will update every time it is restarted\n  # branch: release:release-server\n```\n\nNote: `BRANCH-server` branches download only server data\n\n## Troubleshooting\n\nNarrow down where the issue might be with the following options:\n\n- If you forgot your server's password:\n  - terminal: `cat data/Saved/Config/LinuxServer/ServerSettings.ini | grep Password`\n- If your brickadia is crashing and omegga works:\n  - omegga console: `/debug`\n  - terminal: `omegga --debug`\n- If your omegga isn't starting\n  - terminal: `omegga --verbose`\n- If a plugin is crashing, message the plugin developer\n  - discord: #plugin-bugs\n- If you are on Ubuntu and the output of `which npm` is `/bin/npm`\n  - terminal: `sudo apt purge nodejs` and restart install instructions from `nvm install 24`.\n- If you're getting an `EACCES` error when running `npm i -g omegga`:\n  1. First, try [this](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally).\n  2. If that doesn't work, try this horrible bodge method for WSL:\n     1. Set your WSL to WSL 2\n     2. `npm i -g omegga`\n     3. Set your WSL back to WSL 1 (assuming you want wsl1)\n- If you're getting a \"`gyp ERR! stack Error: not found: make`\"\n  - Install [build-essential](https://wiki.gnucash.org/wiki/Install_Build_Tools)\n\n\n## Uninstalling\n\n```sh\n# uninstall omegga\nnpm uninstall -g omegga\n\n# remove omegga config\nrm -rf ~/.config/omegga\n\n# remove brickadia installs\nrm -rf ~/.local/share/brickadia-launcher\n\n# potentially remove extra brickadia config\nrm ~/.config/Epic\n```\n\nYou will have to delete your omegga data folders manually\n\n# Plugins\n\nPlugins are located in the `plugins` directory in an omegga config folder\n\nPlugins are most easily developed in Javascript at the moment using the Node VM Plugins and Node Plugins. You can use JSON RPC Plugins to write plugins in other languages.\n\n## Installing Plugins\n\n### CLI Installation\n\nYou can install plugins with the `omegga install https://github.com/user/repo` command.\n\nYou can install plugins using a shorthand `omegga install gh:user/repo` which will install the plugin located at `https://github.com/user/omegga-repo`\n\nThis is the recommended way of installing plugins as it automatically runs a setup script when present.\n\n### Manual Installation\n\nYou can clone a plugin's github repo inside the `plugins` folder (created when you run `omegga` for the first time):\n\n- `cd plugins` to navigate to plugins folder\n- `git clone https://github.com/user/repo` to download the plugin\n- Make sure to read the plugin's README file for after-install instructions\n\n## Updating Plugins\n\nPlugins can be updated with `omegga update`:\n\n```sh\n# update all plugins\nomegga update\n\n# update plugins named \"pluginName\" and \"anotherPluginName\"\nomegga update pluginName anotherPluginName\n```\n\nPlugins may also need to be updated based on the project's README file.\n\n## Uninstalling Plugins\n\nPlugins can be installed by deleting the plugin's respective folder:\n\n```sh\nrm -rf plugins/PLUGIN_NAME\n```\n\n## Creating Plugins\n\nPlugins can be created manually using the file structure described below, or they can be initialized automatically using `omegga init-plugin`.\nFollow the prompts and your plugin will be generated for you.\n\nThe plugin types are as follows:\n\n- `safe` (default), the standard Node VM plugin type\n- `unsafe`, an unsafe plugin with raw access to internal Omegga APIs\n- `rust`, an RPC plugin that makes use of the [omegga-rs](https://github.com/voximity/omegga-rs) Rust interface\n- `rpc`, a plugin that will interface another executable using RPC over STDIN/STDOUT\n\n## Plugin Structure\n\nAll plugins are located in a `plugins` directory where you are running Omegga:\n\n- `plugins/myPlugin` - plugin folder (required)\n- `plugins/myPlugin/doc.json` - plugin information (required)\n- `plugins/myPlugin/plugin.json` - plugin version information, validated with `omegga check` (optional, for now)\n- `plugins/myPlugin/setup.sh` - plugin setup script, run after installed by `omegga install` (optional)\n- `plugins/myPlugin/disable.omegga` - empty file only present if the plugin should be disabled (optional)\n\nEvery plugin requires a `doc.json` file to document which briefly describes the plugin and its commands.\n\n### `doc.json` (example)\n\n```json\n{\n  \"name\": \"My Plugin\",\n  \"description\": \"Example Plugin\",\n  \"author\": \"cake\",\n  \"config\": {\n    \"example-text\": {\n      \"description\": \"This is an example text input\",\n      \"default\": \"default value\",\n      \"type\": \"string\"\n    },\n    \"example-password\": {\n      \"description\": \"This is example text input hidden as a password\",\n      \"default\": \"hidden password value\",\n      \"type\": \"password\"\n    },\n    \"example-number\": {\n      \"description\": \"This is an example numerical input\",\n      \"default\": 5,\n      \"type\": \"number\"\n    },\n    \"example-bool\": {\n      \"description\": \"This is an example boolean input\",\n      \"default\": false,\n      \"type\": \"boolean\"\n    }\n  },\n  \"commands\": [\n    {\n      \"name\": \"!ping\",\n      \"description\": \"sends a pong to the sender\",\n      \"example\": \"!ping foo bar\",\n      \"args\": [\n        {\n          \"name\": \"args\",\n          \"description\": \"random filler arguments\",\n          \"required\": false\n        }\n      ]\n    },\n    {\n      \"name\": \"!pos\",\n      \"description\": \"announces player position\",\n      \"example\": \"!pos\",\n      \"args\": []\n    }\n  ]\n}\n```\n\n## Plugin Config\n\nThis is an example config section of a `doc.json`. The web ui provides an interface for editing these configs.\n\n```json\n{\n  \"config\": {\n    \"example-text\": {\n      \"description\": \"This is an example text input\",\n      \"default\": \"default value\",\n      \"type\": \"string\"\n    },\n    \"example-password\": {\n      \"description\": \"This is example text input hidden as a password\",\n      \"default\": \"hidden password value\",\n      \"type\": \"password\"\n    },\n    \"example-number\": {\n      \"description\": \"This is an example numerical input\",\n      \"default\": 5,\n      \"type\": \"number\"\n    },\n    \"example-bool\": {\n      \"description\": \"This is an example boolean input\",\n      \"default\": false,\n      \"type\": \"boolean\"\n    },\n    \"example-list\": {\n      \"description\": \"This is an example list input. List type can be string, password, number, or enum\",\n      \"type\": \"list\",\n      \"itemType\": \"string\",\n      \"default\": [\"hello\"]\n    },\n    \"example-enum\": {\n      \"description\": \"This is an example enum/dropdown input\",\n      \"type\": \"enum\",\n      \"options\": [\"foo\", \"bar\", \"baz\", 1, 2, 3],\n      \"default\": \"foo\"\n    },\n    \"example-enum-list\": {\n      \"description\": \"This is an example list of enums.\",\n      \"type\": \"list\",\n      \"itemType\": \"enum\",\n      \"options\": [\"foo\", \"bar\", \"baz\"],\n      \"default\": [\"foo\"]\n    },\n    \"example-players-list\": {\n      \"description\": \"This is an example list of players.\",\n      \"type\": \"players\",\n      \"default\": [\n        {\n          \"id\": \"fa577b9e-f2be-493f-a30a-3789b02ba70b\",\n          \"name\": \"Aware\"\n        }\n      ]\n    },\n    \"example-role\": {\n      \"description\": \"This is an example role dropdown\",\n      \"type\": \"role\",\n      \"default\": \"Admin\"\n    }\n  }\n}\n```\n\nThat config section would generate the following default config:\n\n```json\n{\n  \"example-text\": \"default value\",\n  \"example-password\": \"hidden password value\",\n  \"example-number\": 5,\n  \"example-bool\": false,\n  \"example-list\": [\"hello\"],\n  \"example-enum\": \"foo\",\n  \"example-enum-list\": [\"foo\"],\n  \"example-players-list\": [\n    { \"id\": \"fa577b9e-f2be-493f-a30a-3789b02ba70b\", \"name\": \"Aware\" }\n  ]\n}\n```\n\nThis is provided to plugins in the constructor or the RPC init function.\n\n## Plugin File\n\nThis is an example `plugin.json`, located inside a plugin folder. The plugin file helps omegga know if the plugin is compatible with the current installation. Plugin files can be validated with the `omegga check` command.\n\n```json\n{\n  \"formatVersion\": 1,\n  \"omeggaVersion\": \"\u003e=0.1.32\",\n  \"emitConfig\": \"config.json\",\n  \"dependencies\": {\n    \"otherPlugin\": \"https://github.com/owner/repo\",\n    \"requiredPlugin\": { \"optional\": false },\n    \"optionalPlugin\": { \"optional\": true, \"repo\": \"https://github.com/owner/repo\" }\n  },\n  \"loadPriority\": 0,\n  \"loadBefore\": [\"pluginToLoadAfterThis\"],\n  \"loadAfter\": [\"pluginToLoadBeforeThis\"]\n}\n```\n\n- `formatVersion` - indicates the plugin file format version\n- `omeggaVersion` - indicates compatible omegga versions ([semver cheatsheet](https://www.npmjs.com/package/semver#user-content-ranges))\n- `emitConfig` - optional, a path to a json file where plugin config will be saved to before the plugin starts.\n- `dependencies` - optional, declares dependencies on other plugins\n  - Can be a string specifying the GitHub repository URL (e.g., `\"otherPlugin\": \"https://github.com/owner/repo\"`)\n  - Can be an object with optional properties:\n    - `optional` - if `true`, the plugin will load even if this dependency is missing\n    - `repo` - GitHub repository URL where the dependency can be found (e.g., `\"https://github.com/owner/repo\"`)\n  - Dependencies are automatically loaded before the dependent plugin\n- `loadPriority` - optional, numeric priority for load order (lower/negative numbers load earlier, higher/positive numbers load later, undefined loads in the middle)\n- `loadBefore` - optional, array of plugin names that should load after this plugin\n- `loadAfter` - optional, array of plugin names that should load before this plugin\n\n**Note:** Omegga will automatically resolve the correct load order based on dependencies, `loadPriority`, `loadBefore`, and `loadAfter` constraints. If there's a cyclic dependency or conflicting constraints, plugins may fail to load.\n\n## Plugin Store\n\nAll plugins have the capability to get/set values in a very lightweight \"database\"\n\nThe following **asynchronous** methods are provided:\n\n| Method         | Arguments                 | Description                              |\n| -------------- | ------------------------- | ---------------------------------------- |\n| `store.get`    | key (string)              | Get an object from plugin store          |\n| `store.set`    | key (string), value (any) | Store an object in plugin store          |\n| `store.delete` | key (string)              | Remove an object from plugin store       |\n| `store.wipe`   | _none_                    | Remove all objects from plugin store     |\n| `store.count`  | _none_                    | Count number of objects in plugin store  |\n| `store.keys`   | _none_                    | Get keys for all objects in plugin store |\n\n### Example usage:\n\n```javascript\n// simple add function\nasync function add() {\n  const a = await store.get('foo');\n  const b = await store.get('bar');\n  await store.set('baz', a + b);\n  await store.delete('foo');\n  await store.delete('bar');\n}\n\n(async () =\u003e {\n  // store foo and bar in the plugin store\n  await Promise.all([store.set('foo', 5), store.set('bar', 2)]);\n\n  // add foo and bar\n  await add();\n\n  // baz should be equal to 7\n  console.log('assert', (await store.get('baz')) === 7);\n\n  // demo of storing an object\n  await store.set('example object', {\n    foo: 'you can store objects in the store too',\n    bar: \"just don't expect it to work with anything recursive (cannot serialize)\",\n  });\n})();\n```\n\nFor Node Plugins, the `store` is the third argument passed into the constructor. For JSONRPC Plugins, the `\"store.get\"`/etc. methods can be used.\n\n**JSONRPC Note:** `store.set` has an array of arguments (`[key, value]`)\n\n## Node VM Plugins\n\nNode VM Plugins are what you should be using. They are run inside a VM inside a Worker. This means when they crash, they do not crash the whole server, and they can in the future have locked down permissions (disable filesystem access, etc.).\n\nThese plugins receive a \"proxy\" reference to `omegga` and have limited reach for what they can touch.\n\nRegister custom `/commands` by returning `{registeredCommands: ['foo', 'bar']}` (registers command `/foo` and `/bar`) in the `async init()` method.\n\nBy defining an `async pluginEvent(event, from, ...args)` method in your plugin class, you can respond to events from other plugins, where `from` is the name of the other plugin, `event` is the name of the custom event, and `args` is an array of any passed arguments.\n\n### Globals\n\n- `OMEGGA_UTIL` - access to the `src/util/index.js` module\n- `Omegga` - access to the \"proxy\" omegga\n- `console.log` - and other variants (`console.error`, `console.info`) print specialized output to console\n\n### Folder Structure\n\nIn a `plugins` directory create the following folder structure:\n\n- `plugins/myPlugin` - plugin folder (required)\n- `plugins/myPlugin/omegga.plugin.js` - js plugin main file (required)\n- `plugins/myPlugin/doc.json`\n- `plugins/myPlugin/access.json` - plugin access information (required, but doesn't have to have anything right now). this will contain what things the vm will need to access\n\n### `access.json` (examples)\n\nAccess to any builtin modules (`fs`, `path`, etc.)\n\n```json\n[\"*\"]\n```\n\nAccess to nothing - only the code in the `omegga.plugin.js`\n\n```json\n[]\n```\n\nAccess to only `fs`, (`const fs = require('fs');`)\n\n```json\n[\"fs\"]\n```\n\n### `omegga.plugin.js` (example)\n\n```javascript\nclass PluginName {\n  // the constructor also contains an omegga if you don't want to use the global one\n  // config and store variables are optional but provide access to the plugin data store\n  constructor(omegga, config, store) {\n    this.omegga = omegga;\n    this.config = config;\n    this.store = store;\n    console.info('constructed my plugin!');\n  }\n\n  async init() {\n    Omegga.on('chatcmd:ping', (name, ...args) =\u003e {\n      Omegga.broadcast(`pong @ ${name} + ${args.length} args`);\n    }).on('chatcmd:pos', async name =\u003e {\n      const [x, y, z] = await Omegga.getPlayer(name).getPosition();\n      Omegga.broadcast(`\u003cb\u003e${name}\u003c/\u003e is at ${x} ${y} ${z}`);\n    });\n  }\n\n  async stop() {\n    // any remove events are not necessary because the VM removes the code\n  }\n}\n\nmodule.exports = PluginName;\n```\n\n### `omegga.plugin.ts` (example)\n\nBe sure to put `.build/` and `node_modules/` in your `.gitignore`\n\n**Requires a `tsconfig.json`**:\n\n```json\n{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"target\": \"es2020\",\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"omegga/*\": [\"node_modules/omegga/dist/*\"]\n    }\n  }\n}\n```\n\n`omegga.plugin.ts`:\n\n```ts\nimport type { OmeggaPlugin, OL, PS, PC } from 'omegga/plugin';\n\ntype Config = { foo: string };\ntype Storage = { bar: string };\n\nexport default class Plugin implements OmeggaPlugin\u003cConfig, Storage\u003e {\n  omegga: OL;\n  config: PC\u003cConfig\u003e;\n  store: PS\u003cStorage\u003e;\n\n  constructor(omegga: OL, config: PC\u003cConfig\u003e, store: PS\u003cStorage\u003e) {\n    this.omegga = omegga;\n    this.config = config;\n    this.store = store;\n  }\n\n  async init() {\n    // Write your plugin!\n    this.omegga.on('cmd:test', (speaker: string) =\u003e {\n      this.omegga.broadcast(`Hello, ${speaker}!`);\n    });\n\n    return { registeredCommands: ['test'] };\n  }\n\n  async stop() {\n    // Anything that needs to be cleaned up...\n  }\n}\n```\n\n## Node Plugins\n\nNode plugins are effectively `require`'d into omegga. They have the potential to crash the entire service through uncaught exceptions and also can be insecure. Develop and run these at your own risk - your server stability may suffer.\n\nThese plugins receive a direct reference to the `omegga` that wraps the brickadia server. As a result, they can directly modify how omegga runs.\n\nCleanup is important as code can still be running after the plugin is unloaded resulting in strange and undefined behavior. Make sure to run `clearInterval` and `clearTimeout`\n\nRegister custom `/commands` by returning `{registeredCommands: ['foo', 'bar']}` (registers command `/foo` and `/bar`) in the `async init()` method.\n\n### Globals\n\n- `OMEGGA_UTIL` - access to the `src/util/index.js` module\n\n### Folder Structure\n\nIn a `plugins` directory create the following folder structure:\n\n- `plugins/myPlugin` - plugin folder (required)\n- `plugins/myPlugin/doc.json`\n- `plugins/myPlugin/omegga.main.js` - js plugin main file (required)\n\n### `omegga.main.js` (example)\n\n```javascript\nclass PluginName {\n  // config and store variables are optional but provide access to the plugin data store\n  constructor(omegga, config, store) {\n    this.omegga = omegga;\n    this.config = config;\n    this.store = store;\n  }\n\n  async init() {\n    this.omegga\n      .on('chatcmd:ping', (name, ...args) =\u003e {\n        this.omegga.broadcast(`pong @ ${name} + ${args.length} args`);\n      })\n      .on('chatcmd:pos', async name =\u003e {\n        const [x, y, z] = await this.omegga.getPlayer(name).getPosition();\n        this.omegga.broadcast(`\u003cb\u003e${name}\u003c/\u003e is at ${x} ${y} ${z}`);\n      });\n  }\n\n  async stop() {\n    this.omegga\n      .removeAllListeners('chatcmd:ping')\n      .removeAllListeners('chatcmd:pos');\n  }\n}\n\nmodule.exports = PluginName;\n```\n\n## JSON RPC Plugins\n\nJSON RPC Plugins let you use any language you desire, as long as you can run it from a single executable file. They follow the [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification)\n\nThe server communicates with the plugin by sending messages to `stdin` and expects responses in `stdout`. All `stderr` is printed to the console.\n\nRegister custom `/commands` by returning `{registeredCommands: ['foo', 'bar']}` (registers command `/foo` and `/bar`) in the `init` method.\n\n### Omegga Methods (You can access these)\n\n| Method                         | Arguments                                            | Description                                                         | Returns                                                         |\n| ------------------------------ | ---------------------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------- |\n| `log`                          | line (string)                                        | Prints message to omegga console                                    |                                                                 |\n| `error`                        | line (string)                                        | Same as `log` but with different colors                             |                                                                 |\n| `info`                         | line (string)                                        | Same as `log` but with different colors                             |                                                                 |\n| `debug`                        | line (string)                                        | Same as `log` but with different colors                             |                                                                 |\n| `warn`                         | line (string)                                        | Same as `log` but with different colors                             |                                                                 |\n| `trace`                        | line (string)                                        | Same as `log` but with different colors                             |                                                                 |\n| `store.get`                    | key (string)                                         | Get an object from plugin store                                     | Object                                                          |\n| `store.set`                    | [key (string), value (any)]                          | Store an object in plugin store                                     |                                                                 |\n| `store.delete`                 | key (string)                                         | Remove an object from plugin store                                  |                                                                 |\n| `store.wipe`                   | _none_                                               | Remove all objects from plugin store                                |                                                                 |\n| `store.count`                  | _none_                                               | Count number of objects in plugin store                             | Integer                                                         |\n| `store.keys`                   | _none_                                               | Get keys for all objects in plugin store                            | List of Strings                                                 |\n| `exec`                         | cmd (string)                                         | Writes a console command to Brickadia                               |                                                                 |\n| `writeln`                      | cmd (string)                                         | Same as `exec`                                                      |                                                                 |\n| `broadcast`                    | line (string)                                        | Broadcasts a message to the server                                  |                                                                 |\n| `whisper`                      | {target: string, line: string}                       | Sends a message to a specific client                                |                                                                 |\n| `middlePrint`                  | {target: string, line: string}                       | Sends a middle print message to a specific client                   |                                                                 |\n| `getPlayers`                   | _none_                                               | Online players                                                      | List of Players                                                 |\n| `getAllPlayerPositions`        | _none_                                               | An array of objects with fields `pos` and `player`.                 | List of { _Player Object_(...), _Position_(...), isDead(bool) } |\n| `getRoleSetup`                 | _none_                                               | Server roles                                                        | _JSON Data_                                                     |\n| `getBanList`                   | _none_                                               | List of bans                                                        | _JSON Data_                                                     |\n| `getSaves`                     | _none_                                               | Saves in the saves directory                                        | List Strings                                                    |\n| `getSavePath`                  | name (string)                                        | The path to a specific save                                         | String                                                          |\n| `getSaveData`                  | _none_                                               | Current save as brs-js data                                         | _BRS Object_                                                    |\n| `clearBricks`                  | {target: string, quiet: bool}                        | Clears a specific player's bricks                                   |                                                                 |\n| `clearAllBricks`               | quiet                                                | Clears all bricks on the server                                     |                                                                 |\n| `saveBricks`                   | name (string)                                        | Save bricks to a save named `name`                                  |                                                                 |\n| `loadBricks`                   | {name: string, offX, offY, offY, quiet: bool}        | Load bricks of save named `name`                                    |                                                                 |\n| `loadBricksOnPlayer`           | {name: string, player: string, offX, offY, offY}     | Load bricks of save named `name` on player clipboard                |                                                                 |\n| `readSaveData`                 | name (string)                                        | Parses save into a brs-js save object, returns the object           | _BRS Object_                                                    |\n| `loadSaveData`                 | {data: object, offX, offY, offY, quiet: bool}        | Builds brs file from data, loads the file                           |                                                                 |\n| `loadSaveDataOnPlayer`         | {data: object, player: string, offX, offY, offY}     | Builds brs file from data, loads the file onto a player's clipboard |                                                                 |\n| `changeMap`                    | map (string)                                         | Change map to specified map name, returns success                   | Boolean                                                         |\n| `player.get`                   | target (string)                                      | Gets the player by their name or UUID.                              | `{name, id, controller, state, host: bool}`                     |\n| `player.getRoles`              | target (string)                                      | Target's roles                                                      | List of Strings                                                 |\n| `player.getPermissions`        | target (string)                                      | Target's permissions                                                | Record\u003cstring, boolean\u003e                                         |\n| `player.getNameColor`          | target (string)                                      | Target's name color                                                 | _RGB Hex String_                                                |\n| `player.getPosition`           | target (string)                                      | Target's position                                                   | [number, number, number] or null                                |\n| `player.getPawn`               | target (string)                                      | Target's pawn name                                                  | string or null                                                  |\n| `player.getGhostBrick`         | target (string)                                      | Target's ghost brick                                                | {targetGrid, location, orientation}                             |\n| `player.getPaint`              | target (string)                                      | Target's current paint selection                                    | {materialIndex, materialAlpha, material, color}                 |\n| `player.isCrouched`            | target (string)                                      | Check if target is crouched                                         | boolean                                                         |\n| `player.isDead`                | target (string)                                      | Check if target is dead                                             | boolean                                                         |\n| `player.getTemplateBounds`     | target (string)                                      | Target's template/selection bounds                                  | {minBound, maxBound, center}                                    |\n| `player.getTemplateBoundsData` | target (string)                                      | Target's template/selection as brs-js save data                     | _BRS Object_                                                    |\n| `player.clearBricks`           | {target, quiet}                                      | Clears target's bricks                                              |                                                                 |\n| `player.loadBricks`            | {target, saveName}                                   | Loads save file to target's clipboard                               |                                                                 |\n| `player.loadSaveData`          | {target, data, offX, offY, offZ}                     | Loads brs-js save data to target's clipboard                        |                                                                 |\n| `player.loadDataAtGhostBrick`  | {target, data, rotate=true, offX, offY, offZ, quiet} | Loads brs-js save data at target's selection bounds                 |                                                                 |\n| `player.kill`                  | target (string)                                      | Kills the target player                                             |                                                                 |\n| `player.damage`                | {target, amount}                                     | Damages target by amount                                            |                                                                 |\n| `player.heal`                  | {target, amount}                                     | Heals target by amount                                              |                                                                 |\n| `player.giveItem`              | {target, item}                                       | Gives target an item                                                |                                                                 |\n| `player.takeItem`              | {target, item}                                       | Removes item from target                                            |                                                                 |\n| `player.setTeam`               | {target, teamIndex}                                  | Sets target's team                                                  |                                                                 |\n| `player.setMinigame`           | {target, index}                                      | Adds target to minigame at index                                    |                                                                 |\n| `player.setScore`              | {target, minigameIndex, score}                       | Sets target's score in minigame                                     |                                                                 |\n| `player.getScore`              | target (string)                                      | Gets target's score in minigame                                     | number                                                          |\n| `player.setLeaderboard`        | {target, key, value}                                 | Sets leaderboard value for target                                   |                                                                 |\n| `player.getLeaderboard`        | target (string)                                      | Gets leaderboard value for target                                   | number or null                                                  |\n| `plugin.get`                   | target (string)                                      | Gets info on the target plugin                                      | Object                                                          |\n| `plugin.emit`                  | [target (string), event (string), ...args (any)]     | Emit a custom event to the target plugin                            |                                                                 |\n\n### Plugin Methods (You implement these)\n\n| Method               | Arguments                                                                                                                        | Description                                                                                                                                                                          | Required |\n| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- |\n| `init`               | config object                                                                                                                    | Returns a start result, called on plugin start                                                                                                                                       | \u0026#9745;  |\n| `stop`               | _none_                                                                                                                           | Returns _something_, called on plugin stop                                                                                                                                           | \u0026#9745;  |\n| `bootstrap`          | [{ omegga info (`host`, `version`, etc) }]                                                                                       | Run when plugin is started for base data                                                                                                                                             |          |\n| `plugin:players:raw` | [[... [player `username`, `displayName`, `id`, `controller`, `state`]]]                                                                             | Lists players on the server                                                                                                                                                          |          |\n| `plugin:emit`        | [event, from, ...args]                                                                                                           | Fired when another plugin sends an event                                                                                                                                             |          |\n| `line`               | [brickadiaLog string]                                                                                                            | A brickadia console log                                                                                                                                                              |          |\n| `start`              | [{map}]                                                                                                                          | On brickadia server start                                                                                                                                                            |          |\n| `host`               | [{name, id}]                                                                                                                     | When the host is detected                                                                                                                                                            |          |\n| `version`            | [-1 or the CL number]                                                                                                            | When the version is detected                                                                                                                                                         |          |\n| `unauthorized`       | _none_                                                                                                                           | On brickadia server fails an auth check                                                                                                                                              |          |\n| `join`               | [{name, id, state, controller}]                                                                                                  | Run when a player joins                                                                                                                                                              |          |\n| `leave`              | [{name, id, state, controller}]                                                                                                  | Run when a player leaves                                                                                                                                                             |          |\n| `cmd:command`        | [playerName, ...args]                                                                                                            | Runs when a player runs a `/command args`                                                                                                                                            |          |\n| `chatcmd:command`    | [playerName, ...args]                                                                                                            | Runs when a player runs a `!command args`                                                                                                                                            |          |\n| `chat`               | [playerName, message]                                                                                                            | Runs when a player sends a chat message                                                                                                                                              |          |\n| `interact`           | {brick_asset: string;player: { id: string; name: string; controller: string; pawn: string };position: [number, number, number];} | Runs when a player clicks a brick with an interact component. `data` is parsed JSON if `line` (from interact component) starts with \"json:{\"your\": \"json\"}`. Uses interact log field |          |\n| `event:NAME`         | [\u0026gt;player from click\u0026lt;, ...args]                                                                                             | Runs when an interact component has `event:NAME: arg1,arg2,arg\\,3,                                                                                                                   |          |\n| `mapchange`          | \\[{map}\\]                                                                                                                        | Runs when the map changes                                                                                                                                                            |          |\n| `autorestart`        | [autorestart config]                                                                                                             | Runs server has an autorestart scheduled                                                                                                                                             |          |\n| `minigamejoin`       | {player: {name, id}; minigameName: string}                                                                                       | Runs when a player joins a minigame. Note that minigameName is not unique between minigames. minigameName will be null if player leaves all minigames. This will run before `join`   |          |\n\n### Folder Structure\n\nIn a `plugins` directory create the following folder structure:\n\n- `plugins/myPlugin` - plugin folder (required)\n- `plugins/myPlugin/doc.json`\n- `plugins/myPlugin/omegga_plugin` - executable plugin file (required)\n\n### `omegga_plugin` (example, node javascript)\n\n```javascript\n#!/usr/bin/env node\n\nconst readline = require('readline');\nconst { EventEmitter } = require('events');\nconst {\n  JSONRPCServer,\n  JSONRPCServerAndClient,\n  JSONRPCClient,\n} = require('json-rpc-2.0');\n\n// events\nconst ev = new EventEmitter();\n\n// stdio handling\nconst rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout,\n  terminal: false,\n});\n\n// rpc \"server and client\" for responding/receiving messages\nconst rpc = new JSONRPCServerAndClient(\n  new JSONRPCServer(),\n  // the client outputs JSON to console\n  new JSONRPCClient(async blob =\u003e console.log(JSON.stringify(blob)))\n);\n\n// on stdin, pass into rpc\nrl.on('line', line =\u003e {\n  try {\n    rpc.receiveAndSend(JSON.parse(line));\n  } catch (e) {\n    console.error(e);\n  }\n});\n\n// regexes for matching brickadia console logs\nconst GENERIC_LINE_REGEX =\n  /^(\\[(?\u003cdate\u003e\\d{4}\\.\\d\\d.\\d\\d-\\d\\d.\\d\\d.\\d\\d:\\d{3})\\]\\[\\s*(?\u003ccounter\u003e\\d+)\\])?(?\u003cgenerator\u003e\\w+): (?\u003cdata\u003e.+)$/;\nconst LOG_LINE_REGEX =\n  /\\[(?\u003cdate\u003e\\d{4}\\.\\d\\d.\\d\\d-\\d\\d.\\d\\d.\\d\\d:\\d{3})\\]\\[\\s*(?\u003ccounter\u003e\\d+)\\](?\u003crest\u003e.*)$/;\n\nev.on('line', line =\u003e {\n  const logMatch = line.match(LOG_LINE_REGEX);\n  if (!logMatch) return;\n  const {\n    groups: { rest },\n  } = logMatch;\n  const dataMatch = rest.match(GENERIC_LINE_REGEX);\n  if (dataMatch) ev.emit('logData', dataMatch.groups);\n  else ev.emit('logLine', rest);\n});\n\n// list of players\nlet players;\n\n// get a player by name\nconst getPlayer = name =\u003e players.find(p =\u003e p.name === name);\n\n// watch console logs for a pattern, then remove the listener\nfunction watch(exec, pattern) {\n  return new Promise(resolve =\u003e {\n    function listener(line) {\n      const match = line.match(pattern);\n      // listener removes itself on a match\n      if (match) {\n        ev.off('logLine', listener);\n        resolve(match.groups);\n      }\n    }\n    // add the listener\n    ev.on('logLine', listener);\n\n    // run the console command\n    rpc.notify('writeln', exec);\n  });\n}\n\n// get a player's position\nasync function getPlayerPos(name) {\n  const player = getPlayer(name);\n  if (!player) return;\n\n  // get player position from player controller\n  const pawnRegExp = new RegExp(\n    `BP_PlayerController_C .+?PersistentLevel\\\\.${player.controller}\\.Pawn = BP_FigureV2_C'.+?:PersistentLevel.(?\u003cpawn\u003eBP_FigureV2_C_\\\\d+)'`\n  );\n  const { pawn } = await watch(\n    `GetAll BP_PlayerController_C Pawn Name=${player.controller}`,\n    pawnRegExp\n  );\n\n  // get player position from pawn\n  const posRegExp = new RegExp(\n    `CapsuleComponent .+?PersistentLevel\\\\.${pawn}\\\\.CollisionCylinder\\\\.RelativeLocation = \\\\(X=(?\u003cx\u003e[\\\\d\\\\.-]+),Y=(?\u003cy\u003e[\\\\d\\\\.-]+),Z=(?\u003cz\u003e[\\\\d\\\\.-]+)\\\\)`\n  );\n  const { x, y, z } = await watch(\n    `GetAll SceneComponent RelativeLocation Name=CollisionCylinder Outer=${pawn}`,\n    posRegExp\n  );\n\n  return [x, y, z].map(Number);\n}\n\n// emit a console log\nconst log = (...args) =\u003e rpc.notify('log', args.join(' '));\n\n// when available players updates - plugin:players:raw is emitted\nrpc.addMethod('plugin:players:raw', ([playerArr]) =\u003e {\n  // update the players list\n  players = playerArr.map(p =\u003e ({\n    name: p[0],\n    id: p[1],\n    controller: p[2],\n    state: p[3],\n  }));\n});\n\n// ping command\nrpc.addMethod('chatcmd:ping', ([name, ...args]) =\u003e {\n  rpc.notify('broadcast', `pong @ ${name} + ${args.length} args`);\n});\n\n// player position command\nrpc.addMethod('chatcmd:pos', async ([name]) =\u003e {\n  log('player', name, 'requests position');\n  const [x, y, z] = await getPlayerPos(name);\n  rpc.notify('broadcast', `\u003cb\u003e${name}\u003c/\u003e is at ${x} ${y} ${z}`);\n});\n\n// pass lines into the event emitter\nrpc.addMethod('line', ([line]) =\u003e {\n  ev.emit('line', line);\n});\n\n// receive config object in init\nrpc.addMethod('init', async ([config]) =\u003e ({ registeredCommands: [] }));\nrpc.addMethod('stop', async () =\u003e 'ok');\n```\n\n# Extra Features\n\n## Environment Variables\n\nThese can be set in your shell or in a `.env` file the same directory as a `omegga-config.yml` file.\n\n`omegga` accepts the following environment variables:\n\n- `BRICKADIA_TOKEN` - Specify hosting token instead of using config\n- `BRICKADIA_USER` - Brickadia auth username (on first start)\n- `BRICKADIA_PASS` - Brickadia auth password (on first start)\n- `BRICKADIA_PORT` - Brickadia server port (default `7777`, on config creation)\n- `OMEGGA_PORT` - omegga webserver port (default `8080`, on config creation)\n- `BRICKADIA_DIR` - Override the need to use steamcmd and point to a Brickadia install directory (eg. `/home/\u003cUSER\u003e/.config/omegga/steam_installs/main/Brickadia`)\n- `STEAM_INSTALLS_DIR` - Set where omegga installs brickadia via steamcmd (default `~/.config/omegga/steam_installs`)\n- `STEAM_APP_ID` - Set the Steam App ID for Brickadia (default `3017590`)\n- `STEAM_USERNAME` - Set the Steam username for downloading Brickadia via steamcmd\n- `STEAM_PASSWORD` - Set the Steam password for downloading Brickadia via steamcmd\n- `VERBOSE` - Set to `true` to enable verbose logging (default `false`)\n- `PACKAGE_NOTIFIER` - When set to `false`, disables the npm update notifier\n- `STEAM_NOTIFIER` - When set to `false`, disables the SteamCMD update notifier\n- `SKIP_STEAMCMD_PROMPT` - When set to `true`, agrees to installing SteamCMD without prompting\n\n## Config\n\nDefault config values (including hidden ones)\n\n```yaml\nomegga:\n  port: 8080 # web-ui port\n  webui: true # enable web-ui\n  plugins: true # enable plugins\n  singleUser: false # disable web-ui auth users\n  https: true # enable https for web-ui\n  debug: false # debug logging\nserver:\n  port: 7777 # game server port\n  map: Plate # map name\n  # When branch is present, steamcmd is not used\n  #branch: release:release-server # branch alias:branch name\n  steambeta: public # try `unstable`\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrickadia-community%2Fomegga","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrickadia-community%2Fomegga","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrickadia-community%2Fomegga/lists"}