README: серверная часть, наш протокол и вход через лаунчер
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user