tachyne Java gateway for Minecraft 1.21.5–1.21.8 (protocols 770–772) https://tachyne.com
  • Go 88.8%
  • Dockerfile 11.2%
Find a file
Wesley Channon 4bbf1f8928 Pin tachyne-common 855ad30 for bundles
Picks up the bundle_contents component translation, the click button the
frame was discarding, and the bundle_item_selected action. No code change
here — the Java gateways share gwsession, where the dispatch lives.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3k8GjiCuFcFEFmBiXorba
2026-08-15 11:15:42 +02:00
.github/workflows CI: build + publish the component image to ghcr on push to main 2026-07-10 15:15:41 +02:00
cmd/gw Wire TACHYNE_VIEW_CAP; pin common with paced chunk delivery 2026-07-10 19:24:13 +02:00
deploy deploy examples: full classic world by default; real registry refs 2026-07-10 15:31:47 +02:00
.dockerignore tachyne-gw-java-770: initial public release 2026-07-10 14:55:50 +02:00
.gitignore tachyne-gw-java-770: initial public release 2026-07-10 14:55:50 +02:00
CONTRIBUTING.md tachyne-gw-java-770: initial public release 2026-07-10 14:55:50 +02:00
Dockerfile tachyne-gw-java-770: initial public release 2026-07-10 14:55:50 +02:00
go.mod Pin tachyne-common 855ad30 for bundles 2026-08-15 11:15:42 +02:00
go.sum Pin tachyne-common 855ad30 for bundles 2026-08-15 11:15:42 +02:00
LICENSE tachyne-gw-java-770: initial public release 2026-07-10 14:55:50 +02:00
NOTICE tachyne-gw-java-770: initial public release 2026-07-10 14:55:50 +02:00
README.md README: the session pipeline lives in tachyne-common, and three debts are paid 2026-08-03 22:19:15 +02:00

tachyne-gw-java-770

tachyne is an unofficial fan project, not affiliated with Mojang, Microsoft, or Minecraft's developer/publisher in any way. See the Disclaimer at the bottom.

Project status

Work in progress. tachyne is young and moving fast: a full survival game runs today, but expect rough edges, missing vanilla features, and breaking changes between updates. Bug reports are genuinely useful — please open a GitHub Issue with your client version/edition and what you saw. Contributions are welcome too: see CONTRIBUTING.md.

Just want to run a server? The quickstart repo brings up the whole stack in one command — Docker Compose or Kubernetes, classic infinite survival by default, real-Cape-Town earth mode as a variant.

What's implemented? Gameplay features live in the world engine, not the gateways — see tachyne-world's feature matrix for what to expect (implemented / partial / missing) as a player.

Gateway for Java protocols 770772 (Minecraft 1.21.51.21.8): terminates real clients, authorizes every login via tachyne-access (fail closed, 30 s verdict cache), attaches the session to a tachyne-world pod over the domain attach protocol, and renders the typed event stream into 770 wire format via the shared tachyne-common/render770 package. 770→772 differ by little more than packet-ID remaps (plus a known-packs version rewrite in the config phase), so all three protocols are served from the one canonical composition, translated per connection by protocol.TranslatorFor.

Clients do not reach this pod directly: tachyne-ingress owns the public port (<server-ip>:25565), reads the handshake, and splices matching protocols here (cluster-internal service :25570), prefixing PROXY protocol v1 so access checks and logs see the real client IP.

Session pipeline

client ⇄ [status | login(access check) → configuration → play]   tachyne-common/gwsession
              play ⇄ attach session ⇄ tachyne-world :25500 (ATTACH_TOKEN)
  • Login/config: offline-mode Login Success, Set Compression (zlib, threshold 256), then the shared config-phase composition from tachyne-common/protocol — full registries (enchantments included), UpdateTagsPacket, brand, feature flags. Identical bytes to what the old monolith sent a 770 client, guarded by a strict re-parser test in common.
  • Play, world→client (tachyne-common/gwsession): every attach frame has a typed case rendering through render770 — entities via the per-viewer EntityView (relative i16 deltas vs absolute resyncs, NoSync), chat/boss bars/time, survival state, items/windows, sounds/particles/world FX, game events/abilities/vehicles, Dimension→Respawn + Teleport→re-center/re-Want. Chunks decode from the attach binary body into 770 chunk-data packets (block entities included via ChunkHeader.BEs).
  • Play, client→world: movement → Move frames + Want on center-chunk change (the client's own view distance, capped at 12 by TACHYNE_VIEW_CAP); dig/place parsed and forwarded as typed frames with the prediction sequence acked locally; chat/commands forwarded; every other gameplay packet lifted via render770.SID*/Parse* into the typed serverbound actions 0x340x3f (use-item/entity, window clicks, crafting, anvil/enchant, sneak/sprint, respawn, creative slots). Unknown serverbound packets are dropped — if a client feature doesn't work, add its parser to render770 and its frame to attach; there is no raw fallback.

Build / run

go build ./... && go test ./...
go run ./cmd/gw    # env-first config

Key env: TACHYNE_LISTEN, TACHYNE_BACKEND (world attach addr — tachyne-world-0.…:25500 in-cluster, localhost:25500 for local dev against a local engine), TACHYNE_ATTACH_TOKEN (secret tachyne-attach-token), TACHYNE_ACCESS_URL + TACHYNE_ACCESS_TOKEN (unset = access checks off, dev only), POD_NAME (ordinal → SID). See cmd/gw/main.go for the authoritative list.

Deploy

GitHub Actions runs gofmt/vet/test on every push and PR, then builds and pushes ghcr.io/tachyne/tachyne-gw-java-770:{latest,<short-sha>}; then kubectl rollout restart on the StatefulSet. Deploy the world pod first when a tachyne-common protocol change is involved.

Known debt

Protocols 773775 are unrouted, so 1.21.9, 1.21.10 and 1.21.11 clients are turned away at the ingress — including the engine's own canonical content version. Serving them needs translation steps in tachyne-common plus an ingress route.

(Three long-standing debts here are now paid: the recipe book IS sent, the join packet carries the real gamemode from Welcome, and the session pipeline was extracted into tachyne-common/gwsession — gw-776 shares it rather than copying it.)

Deployment

Dockerfile builds a static Go binary into a minimal image. deploy/ holds sanitized Kubernetes manifests shaped like the ones this project runs — treat them as examples: substitute your own image registry, hostnames, namespaces and secrets before applying them to your cluster.

Credits

All protocol rendering comes from the shared tachyne-common library — see its credits (PrismarineJS/minecraft-data, misode/mcmeta, the Minecraft Wiki, ViaVersion as factual references). This repo itself has no third-party dependencies beyond that library.

Development transparency

tachyne is built by its maintainer working with an AI coding agent (Anthropic's Claude): substantial portions of the implementation were written by the model under human direction, and every change is reviewed, tested and deployed by the maintainer. The project's engineering discipline is designed for exactly this workflow — byte-oracle tests pin the wire format, full test suites gate every image build, and real-client verification signs off gameplay. Disclosed here for transparency; judge the code on its behavior.

License

Licensed under the Apache License, Version 2.0 — see LICENSE and NOTICE. Note §6: the license grants no rights to the tachyne name or any trademarks.

Disclaimer

tachyne is an unofficial, independent project. It is not affiliated with, endorsed, sponsored, or approved by Mojang Studios, Mojang Synergies AB, Microsoft Corporation, or any of their subsidiaries — the developer and publisher of Minecraft have no involvement with this project. "Minecraft" is a trademark of Mojang Synergies AB. This project contains no Minecraft game code; all game behavior is independently reimplemented, and data tables are built from openly licensed community datasets (see Credits).