Multi-version servers (the compat layer)
Status: Implemented for the compat layer itself: client mods always see 26.3 packets and data, also on older servers. APIs that tell a mod about the connection (translated or not, the server’s protocol and brand), legacy plugin channel names and raw packet listeners are Planned.
The Celestial client speaks the 26.3 protocol natively, and it can also join servers running older versions through its compat layer. The compat layer translates every packet between the server’s protocol and 26.3, in both directions, so the rest of the client (and every client mod) only ever sees 26.3.
The compat layer is a protocol translator for joining servers. It does not load, convert or run Java mods or plugins of any version.
How a connection is set up
- Version detection. Before joining, the client pings the server and reads its protocol number. The player can also pin a version per server, which overrides detection (useful behind proxies that report a misleading version).
- Choosing a translator. A 26.3 server talks straight to the client. Otherwise the client uses the translator for that version family, with its id mappings for blocks, items, entities, particles, sounds and registries.
- Play. Inbound packets are decoded in the server’s format, translated, and handed to the client as 26.3 packets. Outbound 26.3 packets are translated back. Packets with no counterpart are emulated where the old client had an equivalent, or dropped.
server (older) ──bytes──► [decode] ─► [translate] ─► 26.3 packet ─► client + mods
client + mods ─► 26.3 packet ─► [translate back] ─► [encode] ──bytes──► server
What client mods see
| Mods see | Notes |
|---|---|
| Only 26.3 packets, registries and ids | A client mod written for 26.3 works on every supported server version without version checks |
| Missing features of the old version | The data simply never arrives (no trial chambers on old servers; item data is rebuilt as 26.3 components from legacy NBT) |
| Emulated things as their 26.3 equivalent | Old potions become potion_contents, legacy § text becomes text components |
Rules for mods on old servers
- Use
"sync": "client_only"for mods meant to work everywhere. Old servers are vanilla, Spigot, Paper or proxies, never CLight servers, so a mod that needs its server half does nothing useful there. - Don’t rely on payloads. No CLight server half answers on an old server. Keep client features working without one.
- Don’t fight server-side anti-cheat. Old servers often run anti-cheat plugins tuned to their version. The compat layer reproduces each version’s packets faithfully; a client mod that sends extra packets or acts for the player may get them kicked. Follow each server’s rules.
- Look content up by identifier, never by numeric id, and tolerate entries that don’t exist on that server.
- Proxies (Velocity, BungeeCord) can switch the player between back-end servers of different versions.
client.disconnect/client.connectand level changes happen as usual; don’t cache server facts across them.
Testing across versions
Run a local vanilla or Paper server of the target version on a spare port, start your mod with clight run, and join it from the Multiplayer screen (pin the version in Edit Server to test the override). Join public servers only with a normal account and normal play; automated testing against servers you don’t run is usually against their rules.
Planned
Connection facts for mods (whether the connection is translated, the server’s real protocol number and brand), legacy plugin channel names for payloads on pre-1.13 servers (BungeeCord-style), checking whether the server registered a channel, and raw packet listeners (packets.raw) with the rule that they never block inside the translator.