From 60130d8d1796edec49823bdce903fb35968f96ba Mon Sep 17 00:00:00 2001 From: sasheg dev <152582704+SashegDev@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:11:19 +0300 Subject: [PATCH] =?UTF-8?q?README:=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=87=D0=B0=D1=81=D1=82=D1=8C,=20=D0=BD?= =?UTF-8?q?=D0=B0=D1=88=20=D0=BF=D1=80=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=BB?= =?UTF-8?q?=20=D0=B8=20=D0=B2=D1=85=D0=BE=D0=B4=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=20=D0=BB=D0=B0=D1=83=D0=BD=D1=87=D0=B5=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 062c96a..0b7df9e 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ with its own server, its own protocol and its own accounts. | Repository | License | What lives there | |---|---|---| | `rsx-client` | MIT | Loader, mod API, client hooks, deobfuscation tools | -| `rsx-protocol` | MIT | Wire format, packet schemas, shared simulation library | +| `rsx-protocol` | MIT | Wire format, packet schemas, shared vocabulary | | `rsx-plugin-api` | MIT | Interfaces for server-side content | | `rsx-server-core` | proprietary | Tick loop, world, entities, scaling | -| `rsx-auth` | proprietary | Accounts, tokens, revocation | +| `rsx-auth` | proprietary | The server's own accounts, used when there is no launcher | ## Target @@ -56,6 +56,71 @@ both came out of this class of bug. The fork holds Mojang-derived code and is **not published**. What ships in the open repository is the loader, the mod API and the build tools. +## The server + +The server owns the world. The client draws it and believes nothing. + +### The wire + +The protocol is ours, not the vanilla one. A vanilla 1.12.2 client and our +server cannot talk to each other at all, and that is the point: the game is +ours, so the wire is ours, and every packet in it is one we wrote down. + +The client's own game code is not rewritten. The client reads our packets and +translates them into the game's, and the game does what it already knows how to +do: build a world, spawn entities, draw them. The transport is ours; the +renderer is the game's. The other direction is the same: the game says "the +player moved" and "the player broke a block", and those two become our packets. + +### The world + +A chunk is sixteen by sixteen columns, two hundred and fifty six high, one byte +per block. Generation is a pure function of the seed and the coordinates: no +shared state, no `java.util.Random` carried between calls, no dependence on the +order chunks are asked for. A chunk may be generated months after its +neighbour, on another machine, and has to agree with it exactly, because a save +file can only record what changed and not the terrain underneath it. + +Chunks are written one file per chunk, to a temporary name and moved into +place, with a version and a checksum. A chunk that is half written when the +power goes is a chunk the server refuses to load, rather than one that loads +with half a world in it. + +### Who gets in + +The launcher is where accounts live: it has the passwords, the roles, the bans +and the friends. The game server has none of that and does not want a second +copy, so it asks the launcher whether a player is one of ours, and gets the ban +list in the same answer. + +This is the part Yggdrasil does in vanilla, done with our own launcher. The +launcher already logs the player in and already hands the game a name, a uuid +and a token; the game hands that token to the server, and the server asks the +launcher about it. The token is used once and dropped. + +The server's own accounts exist for a server of our own and for development. +When a launcher is configured they are shut, because a server with two doors +has no doors. + +``` +client game server launcher + | Hello | | + |------------------------->| | + | HelloAck | | + |<-------------------------| | + | LauncherAuth | | + |------------------------->|--- POST /auth/validate ->| + | |<-- {valid, reason} -----| + | AuthAck | | + |<-------------------------| | + | Login / LoginAck | | + |==========================>| | + | JoinWorld / WorldJoin | | + |<==========================| | + | ChunkData ... | | + |<==========================| | +``` + ## Modding Mods are jars with a descriptor at `META-INF/rsxmod.properties`: @@ -114,10 +179,27 @@ rsx-client\scripts\test.ps1 # self test, 128 checks game-fork\scripts\prepare-game.ps1 # rebuild the fork from the vanilla jar game-fork\scripts\compile-game.ps1 # compile only, fast iteration rsx-client\scripts\run-game.ps1 # launch the client + +rsx-protocol\scripts\build.ps1 # dist\rsx-protocol.jar +rsx-protocol\scripts\test.ps1 # 22 checks +rsx-server-core\scripts\build.ps1 # dist\rsx-server-core.jar +rsx-server-core\scripts\test.ps1 # 49 checks +rsx-server-core\scripts\run-server.ps1 ``` Only a JDK is required. No Gradle, no network once the mappings are cached. +### Running the server + +``` +run-server.ps1 --port 25565 --world world --seed 0 +run-server.ps1 --launcher-api https://launcher.example/api +``` + +`--launcher-api` points the server at the launcher's API. With it, the +launcher decides who gets in and the server's own accounts are shut. +`--allow-local-accounts` opens them again on purpose. + ### Assets The client will not run without a real asset tree, and the launcher on this