{"id":51239878,"url":"https://github.com/runtoolkit/marker-command-engine","last_synced_at":"2026-06-28T23:31:54.154Z","repository":{"id":356102701,"uuid":"1229045877","full_name":"runtoolkit/marker-command-engine","owner":"runtoolkit","description":"Marker Command Engine (MCE)","archived":false,"fork":false,"pushed_at":"2026-06-24T16:25:28.000Z","size":244,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-24T16:26:34.594Z","etag":null,"topics":["api","datapack","dp","mc","mcfunction","minecraft","minecraft-commands","minecraft-java-edition","multiplayer-safe","vanilla"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/runtoolkit.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":"2026-05-04T16:37:51.000Z","updated_at":"2026-06-24T16:17:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/runtoolkit/marker-command-engine","commit_stats":null,"previous_names":["runtoolkit/marker-command-engine"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/runtoolkit/marker-command-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runtoolkit%2Fmarker-command-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runtoolkit%2Fmarker-command-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runtoolkit%2Fmarker-command-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runtoolkit%2Fmarker-command-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/runtoolkit","download_url":"https://codeload.github.com/runtoolkit/marker-command-engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runtoolkit%2Fmarker-command-engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34907985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["api","datapack","dp","mc","mcfunction","minecraft","minecraft-commands","minecraft-java-edition","multiplayer-safe","vanilla"],"created_at":"2026-06-28T23:31:52.772Z","updated_at":"2026-06-28T23:31:54.149Z","avatar_url":"https://github.com/runtoolkit.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Marker Command Engine (MCE)\n\nA Fabric mod for Minecraft 1.20.6 that executes server commands on behalf of datapacks — no command blocks, no marker entities, no forceloaded chunks.\n\n---\n\n## Installation\n\nDrop the `.jar` into your server's `mods/` directory.  \nRequires Fabric Loader and Fabric API.\n\n---\n\n## commands.json\n\nLocated at `data/mce/commands.json` (inside the mod JAR; override with a datapack).\n\n```json\n{\n  \"settings\": {\n    \"require_op_level\": 2,\n    \"log_executions\": true,\n    \"allowed_datapacks\": []\n  },\n  \"denylist\": {\n    \"prefixes\": [\"op\", \"deop\", \"ban\", \"stop\"],\n    \"patterns\": [\".*\\\\$\\\\{.*\\\\}.*\"]\n  },\n  \"commands\": [\n    {\n      \"id\": \"greet\",\n      \"aliases\": [\"g\", \"hello\"],\n      \"command\": \"say Hello %mce:vars=\\\"player_name\\\"%!\",\n      \"run_as\": \"console\",\n      \"enabled\": true\n    },\n    {\n      \"id\": \"start_event\",\n      \"aliases\": [\"event\"],\n      \"commands\": [\n        \"title @a title {\\\"text\\\":\\\"Event Start!\\\",\\\"bold\\\":true}\",\n        \"playsound minecraft:ui.toast.challenge_complete master @a\",\n        \"say The event has begun.\"\n      ],\n      \"run_as\": \"console\",\n      \"enabled\": true\n    }\n  ]\n}\n```\n\n### Entry fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `id` | string | ✓ | Unique primary identifier |\n| `command` | string | ✓ (or `commands`) | Single command string |\n| `commands` | string[] | ✓ (or `command`) | Ordered command sequence (v1.0.1) |\n| `aliases` | string[] | — | Alternative IDs for `/mce run-id` |\n| `run_as` | `\"console\"` \\| `\"player\"` | — | Execution context (default: `\"console\"`) |\n| `enabled` | boolean | — | Disabled entries are ignored on load (default: `true`) |\n\nIf both `command` and `commands` are present, `commands` takes priority.\n\n---\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `/mce run \u003ccommand\u003e` | Execute a command string through the denylist (placeholders resolved) |\n| `/mce run-id \u003cid\\|alias\u003e` | Run a named command from commands.json — **tab-completed**, aliases accepted |\n| `/mce reload` | Reload `commands.json` from disk without restarting |\n| `/mce list` | List all enabled commands with aliases and command count |\n| `/mce denylist` | Show active denylist prefixes and patterns |\n| `/mce stats` | Show execution statistics for the current session |\n| `/mce version` | Print mod version |\n\n---\n\n## Alias System\n\nEach command entry can declare one or more `aliases`. They are treated identically to the primary `id` in all contexts: `/mce run-id`, tab-completion, and the event bus.\n\n```json\n{\n  \"id\": \"test_command\",\n  \"aliases\": [\"test\", \"tc\"],\n  \"command\": \"say Hello!\"\n}\n```\n\n```\n/mce run-id test_command   ✓\n/mce run-id test           ✓\n/mce run-id tc             ✓\n```\n\nAll three names appear in tab-completion and are updated live after `/mce reload`.\n\n---\n\n## Multi-Command Sequences\n\nAn entry can run an ordered list of commands using the `commands` array (v1.0.1):\n\n```json\n{\n  \"id\": \"start_event\",\n  \"commands\": [\n    \"title @a title {\\\"text\\\":\\\"Event!\\\",\\\"bold\\\":true}\",\n    \"playsound minecraft:ui.toast.challenge_complete master @a\",\n    \"say The event has started.\"\n  ],\n  \"run_as\": \"console\"\n}\n```\n\nCommands execute in order. If any step is denied by the denylist or throws an exception, the sequence **aborts immediately** and the caller receives an `[MCE] Sequence aborted at step N of M` message. Each command in the sequence goes through the full denylist + placeholder pipeline independently.\n\n---\n\n## Storage Placeholders\n\nCommand strings can embed `%namespace:path=\"key\"%` tokens. At execution time MCE reads the value from the Minecraft command storage and substitutes it before dispatch.\n\n### Syntax\n\n```\n%\u003cstorage-id\u003e=\"\u003ckey\u003e\"%\n```\n\n- **`storage-id`** — Minecraft storage identifier (`namespace:path`), same as used in `/data ... storage \u003cid\u003e`  \n- **`key`** — Top-level key name inside that storage's NBT compound\n\n### Example\n\n**From a datapack function:**\n```mcfunction\ndata modify storage mce:vars player_name set value \"Legends11\"\nfunction #mce:run_id {id: \"greet_player\"}\n```\n\n**In commands.json:**\n```json\n{\n  \"id\": \"greet_player\",\n  \"command\": \"say Welcome %mce:vars=\\\"player_name\\\"%!\",\n  \"run_as\": \"console\"\n}\n```\n\n**Executed command:**\n```\nsay Welcome Legends11!\n```\n\n### Type conversion\n\n| NBT type | Substituted as |\n|---|---|\n| `NbtString` | Raw string value (no SNBT quotes) |\n| Numeric (`int`, `long`, `float`…) | Decimal string, SNBT type suffix stripped |\n| `NbtCompound`, `NbtList` | SNBT representation |\n| Missing key | Empty string `\"\"` (logged as warning) |\n\n### Security\n\nThe denylist runs **twice** per command:\n\n1. **Before** placeholder resolution — catches statically blocked templates  \n2. **After** placeholder resolution — catches values injected from storage that would form a denied command\n\nThis prevents a compromised datapack from writing `op GrieferName` into storage and having MCE execute it through an otherwise-allowed template.\n\n---\n\n## Event System\n\n```java\nMceEventBus bus = MarkerCommandEngine.getEventBus();\n\nbus.subscribe(MceEvent.COMMAND_ALLOWED, ctx -\u003e {\n    System.out.println(\"About to run: \" + ctx.command());\n});\n\nbus.subscribe(MceEvent.COMMAND_EXECUTED, ctx -\u003e {\n    boolean ok = Boolean.TRUE.equals(ctx.success());\n    System.out.println(\"Ran: \" + ctx.command() + \" success=\" + ok);\n});\n```\n\n| Event | When fired | Context fields |\n|---|---|---|\n| `COMMAND_ALLOWED` | After denylist checks pass, before dispatch | `source`, `command` |\n| `COMMAND_DENIED` | When denylist blocks a command | `source`, `command`, `reason` |\n| `COMMAND_EXECUTED` | After every dispatch attempt (pass or fail) | `source`, `command`, `success` |\n| `CONFIG_RELOADED` | After `/mce reload` | — |\n\n`COMMAND_EXECUTED` always fires if `COMMAND_ALLOWED` fired, even on dispatcher exception.  \n`ctx.success()` is `true` for a clean dispatch, `false` if the dispatcher threw.\n\n---\n\n## Stats\n\n`/mce stats` shows in-session execution counters:\n\n| Counter | Meaning |\n|---|---|\n| `allowed` | Commands that passed all denylist checks |\n| `denied` | Commands blocked by the denylist (pre- or post-expansion) |\n| `executed` | Dispatched commands that ran without exception |\n| `failed` | Dispatched commands that threw during execution |\n\nCounters reset automatically on `/mce reload`.\n\n---\n\n## Execution Flow\n\n```\n/mce run-id \u003cid|alias\u003e\n        │\n        ├─ Lookup by id OR any alias\n        │\n        └─ For each command in entry.commands():\n                │\n                ├─ 1. Strip leading '/'\n                ├─ 2. Denylist check (raw template)\n                ├─ 3. Resolve %ns:path=\"key\"% placeholders → expanded\n                ├─ 4. Denylist re-check (expanded)          ← injection guard\n                ├─ 5. fireAllowed event\n                ├─ 6. Dispatch via server command manager\n                └─ 7. fireExecuted event (success or fail)\n```\n\n---\n\n## Denylist\n\nThe denylist blocks commands by prefix or Java regex pattern. Both checks run on **every** execution, including post-placeholder expansion.\n\n```json\n\"denylist\": {\n  \"prefixes\": [\"op\", \"deop\", \"ban\", \"stop\"],\n  \"patterns\": [\".*\\\\$\\\\{.*\\\\}.*\"]\n}\n```\n\n- **Prefix** — the command must not *start with* the prefix (case-insensitive after stripping `/`)  \n- **Pattern** — the full expanded command is tested against each Java regex\n\n---\n\n## Changelog\n\n### v1.0.1\n- **Multi-command sequences** — `commands: [...]` array in entries; fail-fast with step reporting\n- **Alias system** — `aliases: [...]` per entry; tab-completed, accepted by `/mce run-id`\n- **Storage placeholders** — `%ns:path=\"key\"%` resolved from Minecraft command storage at runtime; double denylist pass for injection safety\n\n### v1.0.0\n- **`/mce run \u003ccommand\u003e`** — execute raw command strings through the denylist\n- **`/mce run-id \u003cid\u003e`** — execute named commands from `commands.json` with tab-completion\n- **`/mce reload`** — hot-reload `commands.json` without server restart\n- **Event bus** — `COMMAND_ALLOWED`, `COMMAND_DENIED`, `COMMAND_EXECUTED`, `CONFIG_RELOADED`\n- **`/mce stats`** — in-session execution counters\n- **Denylist** — prefix and regex pattern matching with post-expansion re-check\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruntoolkit%2Fmarker-command-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruntoolkit%2Fmarker-command-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruntoolkit%2Fmarker-command-engine/lists"}