Skip to content

feat(server): enable Bedrock Edition support via Geyser plugin - #2

Merged
nicoechaniz merged 1 commit into
nicoechaniz:mainfrom
Fede654:feat/bedrock-geyser-support
May 3, 2026
Merged

feat(server): enable Bedrock Edition support via Geyser plugin#2
nicoechaniz merged 1 commit into
nicoechaniz:mainfrom
Fede654:feat/bedrock-geyser-support

Conversation

@Fede654

@Fede654 Fede654 commented May 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Wire up Bedrock Edition cross-play by having itzg/minecraft-server auto-install the Geyser-Spigot plugin from Modrinth on boot. Geyser binds UDP/19132 in-process and responds to RakNet unconnected pings, so Bedrock clients on the LAN auto-discover the server with no extra broadcaster.

The repo already contained server/geyser/config.yml (a leftover from a prior standalone-Geyser setup) but no service or plugin actually loaded it — start-dev.sh even advertised a geyser compose service that didn't exist. This PR closes that gap with the smallest viable change.

Design choice — plugin-mode (one container) vs sibling Geyser-standalone container

Picked plugin-mode to preserve the project's "one docker compose up" UX. Trade-offs:

Plugin-mode (chosen) Standalone container
Compose surface +2 env vars, 1 volume new service
Failure coupling Geyser failures fold into MC logs independent restart/logs
Config dir re-uses existing server/geyser/ re-uses existing server/geyser/
LAN discovery works (host network) works (host network)

Floodgate intentionally skipped

The Java side runs ONLINE_MODE=false and the existing server/geyser/config.yml already has auth-type: offline, so Floodgate's keypair-sharing complexity is not needed. Trade-off: Bedrock and Java users sharing a name share a UUID. Acceptable for a dev server; can be revisited (Floodgate is not on Modrinth for paper/spigot — would need direct-URL install via itzg PLUGINS:).

Notes

  • MODRINTH_ALLOWED_VERSION_TYPE: beta is required because Geyser only ships beta-tagged continuous builds on Modrinth (their normal release cadence — not a stability signal).
  • Geyser's broadcast-port: 0 (already set in the existing config) makes it respond to RakNet unconnected pings on its bound port, which is exactly the Bedrock LAN discovery mechanism. No companion to lan-broadcast is needed.
  • .gitignore additions cover Geyser runtime artifacts (key.pem, dumps/, packs/, saved-refresh-tokens.json) and the local .env file.

Verified locally

  • Geyser 2.9.5-b1130 auto-downloaded from Modrinth on container boot.
  • Geyser-Spigot v2.9.5-SNAPSHOT enabled inside Purpur 1.21.11.
  • Log: Started Geyser on UDP port 19132.
  • ss -uln confirms UDP/19132 bound by the JVM.

Test plan

  • docker compose up -d minecraft; wait for healthy.
  • docker compose logs minecraft | grep Geyser shows the plugin loaded and listening on UDP/19132.
  • Connect a Java client to <host>:25565 — works as before.
  • On a Bedrock client (phone/console/Win10) on the same LAN, open Friends → LAN tab — server appears automatically.
  • Manually add <host>:19132 from a remote Bedrock client — connects.

Wire up Bedrock cross-play by having itzg/minecraft-server auto-install
the Geyser-Spigot plugin from Modrinth on boot. Geyser binds UDP/19132
in-process and responds to RakNet unconnected pings, so Bedrock clients
on the LAN auto-discover the server with no extra broadcaster.

Chose plugin-mode (single container) over a sibling Geyser-standalone
service to preserve the project's "one docker compose up" UX. Floodgate
is intentionally skipped: the Java side runs ONLINE_MODE=false and
Geyser's auth-type=offline matches (server/geyser/config.yml). Trade-off:
Bedrock and Java users with the same name share a UUID — acceptable for
a dev server, can be revisited with Floodgate later.

Changes:
- docker-compose.yml: add MODRINTH_PROJECTS=geyser and
  MODRINTH_ALLOWED_VERSION_TYPE=beta (Geyser only ships beta-tagged
  continuous builds); mount server/geyser as the plugin's config dir
  so the pre-existing config.yml is picked up.
- start-dev.sh: remove the stale `docker compose logs -f geyser` line
  (Geyser runs in-process, no separate service); restore the Bedrock
  endpoint advertisement now that it's real.
- .gitignore: ignore Geyser runtime artifacts (key.pem, dumps/, packs/,
  saved-refresh-tokens.json) and the local .env file.

Verified locally: Geyser 2.9.5-b1130 downloaded, plugin enabled, UDP/19132
bound by the server JVM.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@nicoechaniz

Copy link
Copy Markdown
Owner

Review — Bedrock/Geyser support

Overall: clean, minimal change. One merge note.

Merge conflict heads-up

PR #3 (Server Setup Overhaul) also touches MODRINTH_PROJECTS and MODRINTH_ALLOWED_VERSION_TYPE in docker-compose.yml. The two PRs will conflict. The recommended order is:

  1. Merge this PR (feat(server): enable Bedrock Edition support via Geyser plugin #2) first.
  2. Rebase Server Setup Overhaul (DC-124 epic): pin/harden/visualize #3 on top and combine the MODRINTH_PROJECTS lines.

Minor note

start-dev.sh update correctly removes the standalone geyser service reference, but double-check that no other scripts or docs still mention docker compose logs -f geyser (I did not spot any, but worth a grep).

No blockers from my side once the merge order is coordinated.

@nicoechaniz
nicoechaniz merged commit d0fbc7a into nicoechaniz:main May 3, 2026
nicoechaniz pushed a commit that referenced this pull request May 3, 2026
…lty=easy

Phase 0 stabilization for the Server Setup Overhaul (epic DC-124).
Locks the moving pieces so subsequent phases land on a deterministic
base. PR-A of the 5-PR overhaul series.

Changes:
- docker-compose.yml: pin itzg/minecraft-server to digest
  sha256:629762aaf864e109a35e00b11d701cfc6b2bddca4331944aefde0a352ebb9fd4
  (captured 2026-05-03 from a known-good running container).
  No more silent forward-rolls; bumps are deliberate after smoke test.
- docker-compose.yml: DIFFICULTY peaceful -> easy. Permits hostile mob
  spawns for rolemaster narrative tension while keeping kid-friendly
  damage scaling. Pamplinas can override per-scene via /difficulty
  through mc_command.
- agents/casts/rolemaster.yaml: model field corrected from
  kimi-k2.6 / kimi-coding to MiniMax-M2.7 / minimax to match the
  runtime (other casts already use this).
- docs/server-overhaul.md (new): operator runbook with the pinned
  versions table and the upgrade procedure. Companion to plans/DC-124.md
  and the verbatim plan in vault.

Geyser version pin deferred to a follow-up. The MODRINTH_PROJECTS
line lives on feat/bedrock-geyser-support (upstream PR #2 to
nicoechaniz). After that PR merges, a small follow-up replaces
"geyser" with "geyser:R7DKgZlt" (Geyser-Spigot 2.9.5-b1130).

Verified locally: container restarts cleanly with the pinned digest;
rcon-cli confirms difficulty=Easy applied to the live world (existing
worlds need a one-shot /difficulty to overwrite level.dat — documented
in the runbook).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nicoechaniz added a commit that referenced this pull request May 3, 2026
- PRs #2-#6 merged, 15 plugins active
- WorldEdit wand fix (wooden_axe -> blaze_rod)
- kanban.db corruption resolved
- DC-124/DC-126 epic status corrected in Lattice
- Current state and plugin list updated
Fede654 added a commit to Fede654/DaemonCraft that referenced this pull request May 7, 2026
Fede654 added a commit to Fede654/DaemonCraft that referenced this pull request May 7, 2026
…lty=easy

Phase 0 stabilization for the Server Setup Overhaul (epic DC-124).
Locks the moving pieces so subsequent phases land on a deterministic
base. PR-A of the 5-PR overhaul series.

Changes:
- docker-compose.yml: pin itzg/minecraft-server to digest
  sha256:629762aaf864e109a35e00b11d701cfc6b2bddca4331944aefde0a352ebb9fd4
  (captured 2026-05-03 from a known-good running container).
  No more silent forward-rolls; bumps are deliberate after smoke test.
- docker-compose.yml: DIFFICULTY peaceful -> easy. Permits hostile mob
  spawns for rolemaster narrative tension while keeping kid-friendly
  damage scaling. Pamplinas can override per-scene via /difficulty
  through mc_command.
- agents/casts/rolemaster.yaml: model field corrected from
  kimi-k2.6 / kimi-coding to MiniMax-M2.7 / minimax to match the
  runtime (other casts already use this).
- docs/server-overhaul.md (new): operator runbook with the pinned
  versions table and the upgrade procedure. Companion to plans/DC-124.md
  and the verbatim plan in vault.

Geyser version pin deferred to a follow-up. The MODRINTH_PROJECTS
line lives on feat/bedrock-geyser-support (upstream PR nicoechaniz#2 to
nicoechaniz). After that PR merges, a small follow-up replaces
"geyser" with "geyser:R7DKgZlt" (Geyser-Spigot 2.9.5-b1130).

Verified locally: container restarts cleanly with the pinned digest;
rcon-cli confirms difficulty=Easy applied to the live world (existing
worlds need a one-shot /difficulty to overwrite level.dat — documented
in the runbook).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nicoechaniz added a commit that referenced this pull request May 31, 2026
…te, interoception

Implements all 4 priority fixes from the Claude+Grok forum review (2026-05-31):

1. GAP #5 — L4 judge verdict feedback into next heartbeat
   - agent_loop.py: extract l4_verdict from /judge/pending, compact format
   - daemoncraft.py: inject [L4 last] line into heartbeat prompt
   - server.js: judgeAction sets initiator='l4_agent' + ts for seconds_ago

2. GAP #1+#2 — Registry normalization + real cancellation
   - action-registry.js: REG_KEY alias helper + direct aliases for dig/place/collect/place_fill
   - mutex.js: stopDigging() + ON_ABORT dispatch with 750ms timeout + performance.now()
   - server.js: REG_KEY in /action wrapper, ON_ABORT in /action/stop finally block

3. GAP #3+#4 — Auto-eat gated behind ENABLE_AUTO_EAT_PLUGIN env var
   - server.js: plugin load + config wrapped in feature flag (default: disabled)
   - runner/thread.py: ensure eat path works with plugin disabled

4. Interoception enrichment — body_activity block in heartbeat
   - agent_loop.py: compact body_activity string from runner + action data
   - daemoncraft.py: [Body] line in prompt

Tests: registry-normalization.test.js (10 tests), test_l4_verdict_injection.py

Co-authored-by: Grok Build <grok@x.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants