feat: add optional Fabric 1.21 mod pack support#719
feat: add optional Fabric 1.21 mod pack support#719Z0mb13V1 wants to merge 10 commits intomindcraft-bots:developfrom
Conversation
…DB memory
Adds the 3-phase ensemble pipeline used by CloudGrok:
- panel.js: queries 4 Grok models in parallel (60s timeout)
- arbiter.js: heuristic scoring (length, completeness, action quality, latency);
escalates to judge when top-2 within 0.08 margin
- judge.js: LLM-as-judge (grok-4) picks best response; 30s timeout with fallback
- feedback.js: ChromaDB vector memory (3072-dim Gemini embeddings); retrieves
similar past decisions (similarity > 0.6) and injects as [PAST EXPERIENCE]
- logger.js: writes every decision to bots/{BotName}/ensemble_log.json
- controller.js: EnsembleModel class — drop-in replacement for any single model
Integration: profile.model = 'ensemble' routes through EnsembleModel, which
implements the same sendRequest() interface as all other model providers.
…tone pathfinding Ender Dragon automation (dragon_runner.js + dragon_progress.js): - 6 gameplay chunks: getDiamondPickaxe, buildNetherPortal, collectBlazeRods, collectEnderPearls, locateStronghold, defeatEnderDragon - Persistent state (dragon_progress.json) with atomic writes and corruption recovery - 5 retries per chunk with exponential backoff; death recovery returns to drop coords - !beatMinecraft / !dragonProgression commands (120-180 min timeout) Baritone A* pathfinding (RC25+): - Custom A* pathfinder replacing mineflayer-pathfinder; distance-adaptive timeouts - Ghost block handling for Paper servers (re-fetch block after nav) - isClearPath() with Baritone integration; null-guard on isWalkable for respawn Skills RC13-RC29 (skills.js + world.js): - RC13: safeToBreak filter fix for tree logs - RC14-17: multi-hop smart explore (200-block relocation), water avoidance, wider collect range - RC18-20: resilient collectBlock — retry on combat, exclude failed positions - RC22: Aikar GC flags; RC23: bypass bot.collectBlock.collect() for Paper - RC24: timeout-protected dig (goToPosition 15s, dig 10s, pickup 8s) - RC26: prefer doors over block-breaking; stale dig fix (re-fetch after nav) - RC27: 9 runtime bug fixes from log review
Vision system (src/agent/vision/): - Dynamic import() for camera module with graceful fallback if WebGL unavailable - Xvfb + Mesa software rendering in Docker (LIBGL_ALWAYS_SOFTWARE=1) - 2-second delay after Xvfb start for WebGL context initialization - Patched prismarine-viewer: entity bone parent null check, unknown entity suppression - Per-bot vision model support (grok-2-vision-1212 for CloudGrok) HUD overlay (mindserver.js + public/index.html): - Gaming-style web dashboard at :8080 - Per-bot panels: runtime tracker, current goal, action display, scrollable command log - Live bot camera feeds via protocol-aware viewer iframes - Toolbar with bot controls; responsive CSS Discord bot (discord-bot.js): - Direct bot chat via Discord channels - Admin commands: !start, !stop, !restart with group-based control - Auto-fix monitor: watches bot-output events for errors, suggests fixes - Role-based access (DISCORD_ADMIN_IDS), usage tracking (!usage [agent|all]) - Path traversal guard + command injection detection on all user input - MindServer integration: live agent status display Windows launcher (start.ps1): one-command start/stop/detach for all bot profiles
…ctions, key loading New security modules: - message_validator.js: injection detection (shell commands, backticks, pipe-to-shell), character sanitization, and length limits for Discord/Minecraft chat - rate_limiter.js: sliding-window per-user limiter with automatic stale entry cleanup - usage_tracker.js: token usage tracking with cost estimation for active providers Existing file hardening: - keys.js: environment variables always override keys.json; added .env support - speak.js: TTS sanitization to prevent command injection in text-to-speech - commands/index.js: isCommandBlocked() check against per-profile blocked_actions array; settings.js deepSanitize() strips __proto__, constructor, prototype from SETTINGS_JSON
…Grafana monitoring Docker / Compose: - docker-compose.aws.yml: production config with LiteLLM proxy (:4000), ChromaDB, Tailscale sidecar, ENFORCE_SECURE_PROFILE=FALSE for mineflayer chat - docker-compose.yml: dev compose with Ollama host routing, port 19565 (was 25565) - Dockerfile: non-root user, Xvfb/Mesa for vision, memory 1536M→2560M - Tasks.Dockerfile: separate image for task evaluation runner - .dockerignore: exclude bot logs, node_modules, world saves from build context AWS scripts (aws/): - ec2-go.sh: one-command deploy (pull/rebuild/restart); IMDSv2 support, auto-detects local vs remote execution - setup.sh: full EC2 provisioning — Docker, Tailscale, ChromaDB, environment setup - deploy.sh: rsync-based deployment with SSM secret pulling - ec2-deploy.sh: self-contained bootstrap for EC2 browser SSH - env-toggle.sh: switch between cloud/local/hybrid environment configs - backup.sh / restore.sh: S3 world backup and restore - setup-ollama-proxy.sh: socat systemd service for Tailscale→Ollama routing Observability: - prometheus-aws.yml: Prometheus scrape config for EC2 deployment - grafana-provisioning/: dashboards, datasources, and alerting rules Security: - whitelist.json: pre-built offline UUIDs (avoids Playerdb crash for ONLINE_MODE=FALSE) - .env.example / keys.example.json: API key templates - .husky/pre-commit: ESLint zero-warning gate on every commit Patches: - prismarine-viewer: entity bone parent null check, unknown entity suppression
…ation, ESLint, and CI/CD
…ession orchestrator
- DragonSlayer-Launcher.ps1 (1122 lines, 19 functions): full automated launcher
- Pre-flight checks: Node, npm, Ollama, GPU, CUDA, profile, .env
- Ollama daemon management + model auto-pull (3 models)
- Optional local Paper MC server with EULA prompt
- Bot launch with 7-tier colorized timestamped log output
- MindServer HUD auto-open in browser
- !beatMinecraft via Socket.IO (prompt or auto mode)
- Crash detection event loop with graceful shutdown
- GitHub PR workflow: dynamic fork owner, feature branches,
staging confirmation, safe merge (no --delete-branch on protected)
- PS2EXE compatible for .exe conversion
- DragonSlayer.bat: double-click wrapper
- LAUNCHER_README.md: full config docs, PS2EXE instructions, troubleshooting
- README.md: added launcher section + docs table entry
- .gitignore: removed launcher exclusions to track files in repo
Add optional Fabric modded server support, gated behind settings.modded_mode (default: false). Zero impact on vanilla Paper server path. New modules: - src/registry/modded_registry.js: Scans mods/ directory for Fabric JARs, builds mod capability registry with category classification (performance, tech, magic, pathfinding, etc.), and generates LLM prompt summaries - src/agent/library/modded_skills.js: Mod-aware skill functions including mineModdedOre, useModdedMachine, processModdedItem, scanModdedBlocks, checkModAvailable, and listInstalledMods New commands (modded_mode only): - !mineModdedOre: Mine modded ores (Create zinc, AE2 certus quartz, etc.) - !useModdedMachine: Navigate to and interact with modded machine blocks - !processModdedItem: Process items via modded machines (fallback to furnace) - !scanModdedBlocks: Scan area for modded blocks - !listMods: List all detected Fabric mods Infrastructure: - docker-compose.fabric.yml: Docker Compose override switching Paper to Fabric with mod volume mounting (usage: -f docker-compose.yml -f docker-compose.fabric.yml) - mods/README.md: Instructions for adding Fabric mod JARs Modified: - settings.js: Add modded_mode, server_type, fabric_mods_dir config flags - DragonSlayer-Launcher.ps1: Add MODDED_MODE config with pre-flight checks and SETTINGS_JSON injection for modded mode - src/agent/commands/actions.js: Register modded commands conditionally - src/agent/library/index.js: Include modded skill docs when enabled - .gitignore: Ignore mod JARs but keep mods/ directory Recommended mod stack: Sodium + Lithium + Starlight + Baritone (Fabric port) Full documentation: docs/FABRIC_MODPACK.md
There was a problem hiding this comment.
Pull request overview
This PR is titled "feat: add optional Fabric 1.21 mod pack support" but is actually a very large omnibus fork that bundles numerous unrelated features and fork-specific customizations together. The Fabric mod support is only a small part.
Changes:
- Add optional Fabric 1.21 modded server support (new registry, skills, Docker override, commands)
- Add ensemble/multi-model decision system with chromaDB feedback memory, panel/arbiter/judge architecture
- Add extensive infrastructure: AWS deployment scripts, CI/CD workflows, Grafana/Prometheus monitoring, rate limiter, usage tracker, message validator, Baritone pathfinding, Discord bot dependency
Reviewed changes
Copilot reviewed 156 out of 158 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
settings.js |
Fork-specific defaults override project defaults; adds modded mode config; deepSanitize for prototype pollution protection |
src/agent/commands/index.js |
Fixes real bug in blacklistCommands where delete commandList.find(...) did nothing |
src/agent/coder.js |
Fixes logic inversion bug in missingSkills, adds code execution timeout, freezes exposed compartment objects |
src/process/init_agent.js |
Overly broad uncaughtException swallowing that suppresses legitimate bugs |
src/mindcraft/mindcraft.js |
Adds createRemoteAgent with hardcoded /tmp path (breaks Windows) |
src/ensemble/* |
New ensemble model system: panel, arbiter, judge, logger, feedback |
src/utils/usage_tracker.js |
New LLM usage tracking with cost estimation |
src/utils/rate_limiter.js |
New per-user rate limiting |
src/utils/message_validator.js |
New input validation and sanitization |
src/utils/mcdata.js |
Adds Baritone pathfinding, fixes auto-eat import |
src/models/* |
Usage tracking hooks (_lastUsage), embed param renaming, various fixes |
src/agent/vision/* |
Lazy camera loading, error handling improvements |
whitelist.json |
Fork-specific server whitelist with deployment-specific UUIDs |
profiles/*.json |
Fork-specific profile changes; renames bots; adds _TODO to all profiles |
data/minecraft_wiki.json |
New wiki reference data with questionable future-dated version info |
CLAUDE.md |
AI assistant guidance file with private deployment details |
package.json |
Adds Baritone, chromadb, discord.js, husky/lint-staged |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const NON_FATAL_PATTERNS = [ | ||
| 'Cannot read properties of undefined', | ||
| 'Cannot read properties of null', | ||
| 'aborted', | ||
| 'Timeout', | ||
| 'timed out', | ||
| 'goal is not a', | ||
| 'path was', | ||
| 'No path', | ||
| 'is not reachable', | ||
| 'position is not loaded', | ||
| 'stuck', | ||
| 'Digging', | ||
| 'event loop', | ||
| 'ECONNRESET', | ||
| 'ECONNREFUSED', | ||
| 'socket hang up', | ||
| ]; | ||
| function isNonFatal(msg) { | ||
| return NON_FATAL_PATTERNS.some(p => msg.includes(p)); | ||
| } | ||
| process.on('uncaughtException', (err) => { | ||
| const msg = err?.message || String(err); | ||
| if (isNonFatal(msg)) { | ||
| console.error(`[RC30] Caught non-fatal uncaught error: ${msg}`); | ||
| return; // swallow — goToGoal's timeout will handle recovery | ||
| } | ||
| console.error('[RC27] Uncaught exception (fatal):', err); | ||
| process.exit(1); | ||
| }); | ||
| process.on('unhandledRejection', (reason) => { | ||
| const msg = reason?.message || String(reason); | ||
| if (isNonFatal(msg)) { | ||
| console.error(`[RC30] Caught non-fatal unhandled rejection: ${msg}`); | ||
| return; | ||
| } | ||
| console.error('[RC27] Unhandled rejection:', reason); |
There was a problem hiding this comment.
The NON_FATAL_PATTERNS list in init_agent.js includes extremely broad strings like 'Cannot read properties of undefined', 'Cannot read properties of null', 'aborted', 'stuck', and 'event loop'. Swallowing uncaught exceptions matching these patterns is dangerous: legitimate null-pointer dereferences in application code (e.g., a bug in prompt building, task management, or conversation handling) will be silently suppressed instead of crashing the process. A process that has corrupted internal state will continue running in a degraded/undefined state. The unhandledRejection handler for the same patterns also does not exit the process, which is especially risky. Consider restricting these patterns strictly to known Baritone/pathfinder error messages only, and/or adding proper null checks at the call sites instead.
| const isLocal = provider === 'ollama' || provider === 'vllm'; | ||
| const costInfo = isLocal ? COST_TABLE._vllm_default : getCostPerMillion(modelName); |
There was a problem hiding this comment.
In src/utils/usage_tracker.js, for ollama providers the code uses COST_TABLE._vllm_default instead of COST_TABLE._ollama_default (line 117). While both entries happen to have the same { input: 0.00, output: 0.00 } values, this is semantically incorrect — Ollama and vLLM are different providers and should use their respective entries. If the cost table is ever updated, this bug would silently apply the wrong rate to Ollama.
| data = await new Promise((resolve, reject) => { | ||
| const req = client.request({ | ||
| hostname: url.hostname, | ||
| port: url.port || (url.protocol === 'https:' ? 443 : 11434), | ||
| path: url.pathname, | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| 'Content-Length': Buffer.byteLength(bodyStr), | ||
| }, | ||
| timeout: 90000, // 90s timeout for local model responses | ||
| }, (res) => { | ||
| if (res.statusCode < 200 || res.statusCode >= 300) { | ||
| res.resume(); | ||
| return reject(new Error(`Ollama Status: ${res.statusCode}`)); | ||
| } | ||
| let raw = ''; | ||
| res.on('data', chunk => raw += chunk); | ||
| res.on('end', () => { | ||
| try { resolve(JSON.parse(raw)); } | ||
| catch { reject(new Error(`Ollama parse error: ${raw.slice(0, 200)}`)); } | ||
| }); | ||
| }); | ||
| req.on('error', reject); | ||
| req.on('timeout', () => { req.destroy(new Error('Ollama request timed out')); }); | ||
| req.write(bodyStr); | ||
| req.end(); | ||
| }); |
There was a problem hiding this comment.
In src/models/ollama.js, the send() method is refactored from using fetch() to using raw Node.js http/https modules. The new implementation uses a hardcoded default port of 11434 for HTTP (line 95). However, the Ollama HTTP API default port is 11434, which is correct. But using raw http/https instead of fetch bypasses the existing AbortController integration and removes the ability to use standard HTTP client features. More critically, the Content-Length header (line 100) is computed from Buffer.byteLength(bodyStr) which is correct for UTF-8, but the old implementation using fetch was simpler and more portable. The main concern is that this change replaces a working implementation and could break in edge cases where the URL has a path component other than the endpoint (since url.pathname alone is used without any query string from the original URL).
| # | ||
| # Place Fabric 1.21-compatible mod JARs here when running in modded mode. | ||
| # | ||
| # This directory is mounted into the Docker container at /data/mods/ | ||
| # when using docker-compose.fabric.yml. | ||
| # | ||
| # Recommended mods: | ||
| # - sodium-fabric-*.jar (rendering optimization) | ||
| # - lithium-fabric-*.jar (game logic optimization) | ||
| # - starlight-fabric-*.jar (lighting engine rewrite) | ||
| # - ferritecore-fabric-*.jar (memory optimization) | ||
| # - baritone-fabric-*.jar (advanced pathfinding) | ||
| # | ||
| # Download mods from: | ||
| # - https://modrinth.com/ | ||
| # - https://www.curseforge.com/minecraft/mc-mods | ||
| # | ||
| # Ensure ALL mods target Minecraft 1.21 + Fabric Loader. |
There was a problem hiding this comment.
The mods/README.md file begins every line with # which makes them all comments in Markdown — the file renders as a blank page. Only the first line (# Fabric Mods Directory) is a proper Markdown heading; the rest of the lines starting with # are HTML comments/code in Markdown rendering. These should be regular text paragraphs or use proper Markdown list syntax.
| // RC30: Guard — ashfinder may not be initialized yet (respawn, early tick) | ||
| if (!bot.ashfinder?.config) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
In src/agent/library/world.js, isClearPath now returns false if bot.ashfinder?.config is not available (e.g., during respawn or early tick). This silent false return changes the semantics of the function — callers that previously relied on mineflayer-pathfinder returning whether a clear path exists will now silently get false even when the pathfinder could theoretically answer. This could cause the bot to unnecessarily break blocks or fail navigation when ashfinder hasn't initialized yet, rather than waiting for initialization.
| [ | ||
| { "uuid": "dcdb547c-1adf-31b3-a081-1d4f3f3ba007", "name": "LocalAndy" }, | ||
| { "uuid": "6110ac08-2bc8-3d04-a114-130376c985b5", "name": "CloudGrok" }, | ||
| { "uuid": "4a2d5a7c-8cbe-30e6-9b8c-23a9b6c100e2", "name": "DragonSlayer" }, | ||
| { "uuid": "37dbcbf4-632e-36cc-962b-dd0adb6c55ff", "name": "Ensemble_1" }, | ||
| { "uuid": "91c76ec0-2db6-3402-ac3d-874854749903", "name": "Gemini_1" }, | ||
| { "uuid": "f93b8dea-a9ee-35c1-b940-0e4b727f08e4", "name": "Grok_En" }, | ||
| { "uuid": "2ec2960b-8a4d-308c-83e8-44b228a16b16", "name": "claude" }, | ||
| { "uuid": "24b21ad7-f58b-3344-840f-6768388ff79e", "name": "claude_thinker" }, | ||
| { "uuid": "eba477de-beb2-3661-ac55-99822ff19c48", "name": "gpt" }, | ||
| { "uuid": "d06bd813-b99a-3f32-b35f-d31969bbf786", "name": "Freeguy" }, | ||
| { "uuid": "cb0ac5ea-5927-3c65-9a87-08b5dfa3e5f4", "name": "Mercury" }, | ||
| { "uuid": "5f12c2f2-2af8-39c0-b48f-d526a2fe8243", "name": "Mistral" }, | ||
| { "uuid": "84d7b3c7-8eac-3626-a11d-ac5d43472221", "name": "LLama" }, | ||
| { "uuid": "2890254a-5a40-31e4-aeae-bad2d96e7713", "name": "qwen" }, | ||
| { "uuid": "d44c22a0-5412-38a0-9d92-59e6f0fc81b9", "name": "deepseek" }, | ||
| { "uuid": "4102ff3f-3bad-3f3b-95fe-e949a7255468", "name": "vllm" }, | ||
| { "uuid": "e7d6a327-069b-3a6d-9079-6a34b25e4bb3", "name": "azure" }, | ||
| { "uuid": "b1ff8336-696d-3ca7-96fc-997325312040", "name": "andy-4" }, | ||
| { "uuid": "adb5bb64-bc18-3d3c-baf2-c328fca49ed6", "name": "andy-4-thinking" } | ||
| ] |
There was a problem hiding this comment.
The whitelist.json file added in this PR contains UUIDs associated with player/bot names including specific AI model names like claude, gpt, deepseek, azure, and vllm. This appears to be an operator-specific configuration file with real (offline-mode) UUIDs that is specific to this fork's deployment. This file should not be part of an upstream PR — it likely belongs in .gitignore or a deployment-specific override rather than in the shared codebase, as it exposes the specific whitelist configuration of this fork's private server.
There was a problem hiding this comment.
Copilot is the only chronically online sane one left in this codebase.
| let _messages = strictFormat(turns); | ||
| _messages = _messages.map(message => { | ||
| message.content += stop_seq; | ||
| return message; |
There was a problem hiding this comment.
In src/models/gpt.js, the variables _messages are declared with a leading underscore prefix (indicating unused), but they are actually used — _messages is assigned and then mapped over. This is confusing naming: the underscore convention (as configured in the ESLint config) signals "intentionally unused." If these are used, they should not have the leading underscore.
| - **CloudGrok** — cloud ensemble bot: 4 panel models (Gemini + Grok) voted by a heuristic arbiter + optional LLM judge; always-on on EC2 | ||
| - **DragonSlayer** — local GPU bot (currently active): `sweaterdog/andy-4:q8_0` via Ollama on RTX 3090; autonomous Ender Dragon speedrun with RC29 persistent state | ||
| - **LocalAndy** — local GPU bot (dormant): `sweaterdog/andy-4` via Ollama; research/exploration profile | ||
| - All bots connect to one persistent Minecraft server on AWS EC2 (Paper 1.21.11) with ChromaDB-backed memory |
There was a problem hiding this comment.
The CLAUDE.md file documents this as a research fork, mentions specific EC2 deployments, private bot names like DragonSlayer and CloudGrok, and includes deployment-specific operational notes (e.g., "connects to one persistent Minecraft server on AWS EC2"). This file is intended as guidance for AI coding assistants working within this private fork and should not be included in an upstream PR to the public mindcraft repository, as it exposes private infrastructure details and is specific to this fork's deployment.
| - **CloudGrok** — cloud ensemble bot: 4 panel models (Gemini + Grok) voted by a heuristic arbiter + optional LLM judge; always-on on EC2 | |
| - **DragonSlayer** — local GPU bot (currently active): `sweaterdog/andy-4:q8_0` via Ollama on RTX 3090; autonomous Ender Dragon speedrun with RC29 persistent state | |
| - **LocalAndy** — local GPU bot (dormant): `sweaterdog/andy-4` via Ollama; research/exploration profile | |
| - All bots connect to one persistent Minecraft server on AWS EC2 (Paper 1.21.11) with ChromaDB-backed memory | |
| - **CloudGrok** — cloud ensemble bot: 4 panel models (Gemini + Grok) voted by a heuristic arbiter + optional LLM judge; always-on in a managed cloud environment | |
| - **DragonSlayer** — local GPU bot (currently active): `sweaterdog/andy-4:q8_0` via Ollama on RTX 3090; autonomous Ender Dragon speedrun with RC29 persistent state | |
| - **LocalAndy** — local GPU bot (dormant): `sweaterdog/andy-4` via Ollama; research/exploration profile | |
| - All bots connect to a shared persistent Minecraft server with ChromaDB-backed memory (deployment managed outside this repository) |
| "name": "Grok_En", | ||
| "conversing": "You are Grok_En, a Minecraft bot running on grok-code-fast-1 via xAI Cloud API. You work with Gemini_1 to survive together. Always respond in plain text — never output code blocks for conversational replies. Only use code blocks when explicitly writing Minecraft bot action code.\n\nYour identity facts:\n- Name: Grok_En\n- Model: grok-code-fast-1\n- Provider: xAI Cloud API\n- Compute: Cloud-based\n\nRules:\n- Greetings/Chat/Status: 'hi', 'who are you', 'what is', questions → Plain text response\n- Intro/spawn: include your name, model, and compute type → e.g. \"Hello world! I'm Grok_En, running on grok-code-fast-1 via xAI Cloud (cloud-based).\"\n- Tasks: 'collect', 'mine', 'build', 'craft', 'go to', 'sleep', 'use door', action verbs → !newAction(\"detailed step-by-step plan\")\n- From other bots: Only respond if they need you to change what you're doing. Ignore casual chat and status updates.\n- If a task fails: try an alternative silently. Only report if you need help.\n- CONCISENESS: 1 sentence max. Prefer commands over words. No preamble, no narration.", |
There was a problem hiding this comment.
The grok.json profile changes the bot name from "Grok" to "Grok_En" and includes a lengthy hardcoded conversing prompt with private deployment context (mentions working with Gemini_1, specific model names, etc.). This is a fork-specific profile change that personalizes the bot for the author's deployment and should not be merged upstream as it would break existing users who have the grok.json profile configured to use the bot named "Grok".
| { | ||
| files: ["**/action-code/7.js"], | ||
| rules: { | ||
| "no-restricted-syntax": ["error", { | ||
| "selector": "ImportDeclaration, ExportDeclaration", | ||
| "message": "Imports and exports must be at the top level" | ||
| }], | ||
| }, |
There was a problem hiding this comment.
The eslint.config.js includes an override specifically for **/action-code/7.js (line 95) that enforces import/export restrictions for that specific file. Hardcoding a specific generated file name in the ESLint config is fragile — action-code files are dynamically generated with incrementing numbers (file_counter), so 7.js will eventually be overwritten. This rule serves no practical purpose and should be removed.
|
@copilot open a new pull request to apply changes based on the comments in this thread |
My thoughts exactly |
Summary
Add optional Fabric 1.21 modded server support, fully gated behind
modded_mode: false(default). Zero impact on vanilla Paper server path.What's New
Modded Registry (
src/registry/modded_registry.js)mods/directory for Fabric mod JARsMod-Aware Skills (
src/agent/library/modded_skills.js)mineModdedOre(bot, oreType, count)— Mine modded ores with fallback to vanillauseModdedMachine(bot, machineId)— Navigate to and interact with modded machinesprocessModdedItem(bot, inputItem, count)— Process via modded machines or vanilla furnacescanModdedBlocks(bot, range)— Scan area for modded blockslistInstalledMods(bot)— List all detected modsNew Commands (only when
modded_mode: true)!mineModdedOre!useModdedMachine!processModdedItem!scanModdedBlocks!listModsDocker Support
docker-compose.fabric.yml— Compose override: switches Paper to Fabric with mod volume mountingdocker compose -f docker-compose.yml -f docker-compose.fabric.yml up -dLauncher Update
DragonSlayer-Launcher.ps1gains$MODDED_MODEconfig flagSETTINGS_JSONfor modded modeConfiguration
Files Changed (10 files, +828 lines)
src/registry/modded_registry.jssrc/agent/library/modded_skills.jsdocker-compose.fabric.ymldocs/FABRIC_MODPACK.mdmods/README.mdsettings.jssrc/agent/commands/actions.jssrc/agent/library/index.jsDragonSlayer-Launcher.ps1.gitignoreBackward Compatibility
modded_mode: falseby default — no code paths activatedfalsegracefully on vanilla serversdocker compose upunchanged (still Paper)Recommended Fabric Mod Stack