Клиент говорит с сервером по нашему протоколу

Раньше клиент умел только показывать меню. Теперь он заходит на сервер,
получает наш мир и рисует его.

Как это устроено:

- Наш сетевой слой (net/rustnotmc/client/net) читает наш протокол и
  переводит его пакеты в пакеты игры. Игра остаётся игрой: у неё есть
  мир, игрок, сущности и рендер, и все они работают. Не переписывать их
  ради того, чтобы нарисовать тот же мир иначе, незачем.
- Пакеты игры, которые не имеют соответствия у нас, не отправляются, а
  наоборот: перемещение игрока и ломание блока переводятся в наши.
- Экран входа игры (GuiConnecting) заменён наш: он спрашивает у лаунчера,
  кем пришёл игрок, и подставляет это в рукопожатие.
- Соединение качается из тика игры, а не из экрана. Рукопожатие, которое
  зависит от того, что экран ещё на экране, ломается alt-tab'ом.

Вход теперь через лаунчер, а не внутри игры:

- Лаунчер уже умеет логинить игрока и отдаёт игре имя, uuid и токен
  (--username, --uuid, --accessToken). Это та же роль, что у Yggdrasil в
  ванилле, только лаунчер наш.
- Сервер спрашивает лаунчер, один из ли наш этот игрок, и заодно получает
  бан-лист. Токен используется один раз и не хранится.
- Свои аккаунты сервера, когда настроен лаунчер, закрыты: сервер с двумя
  дверями не имеет дверей. Открыть их можно флагом, но намеренно.
- Если игру запустили без лаунчера, экран всё равно спрашивает имя и
  пароль: это путь для своего сервера и для разработки.

Проверено живьём: клиент вошёл по токену лаунчера, сервер спросил
лаунчер, лаунчер сказал "свой", игрок получил мир, 210 чанков пришли и
лежат на диске, рельеф нарисован.

Что чинилось по дороге:

- Minecraft.setIngameFocus() возвращал на главное меню, когда окно
  получало фокус. Игрок как раз кликает в окно, чтобы напечатать пароль, и
  экран входа исчезал в этот самый момент.
- Ответ лаунчера разбирается, а не ищется подстрокой: {"valid": true} и
  {"valid":true} это один и тот же ответ, и сервер, который понимает
  только второй, ломает работающий лаунчер.
This commit is contained in:
sasheg dev
2026-10-19 20:10:19 +03:00
parent 68dfea27b5
commit 46784aa88f
8 changed files with 541 additions and 5 deletions
@@ -470,6 +470,14 @@ public final class ProtocolTest {
Packets.EntityRemove remove = new Packets.EntityRemove(11);
eq("remove", Integer.valueOf(11), Integer.valueOf(
Packets.EntityRemove.read(new Buf(remove.write().toByteArray())).entityId));
Packets.LauncherAuth launcher = new Packets.LauncherAuth("Player",
"00000000-0000-0000-0000-000000000000", "a.b.c");
Packets.LauncherAuth launcherBack =
Packets.LauncherAuth.read(new Buf(launcher.write().toByteArray()));
eq("launcher account", "Player", launcherBack.account);
eq("launcher uuid", "00000000-0000-0000-0000-000000000000", launcherBack.uuid);
eq("launcher token", "a.b.c", launcherBack.token);
}
private static void testChunkCompression() {
@@ -519,7 +527,7 @@ public final class ProtocolTest {
Packets.LOGIN, Packets.LOGIN_ACK, Packets.JOIN_WORLD,
Packets.WORLD_JOIN, Packets.CHUNK_DATA, Packets.BLOCK_CHANGE,
Packets.PLAYER_MOVE, Packets.ENTITY_MOVE, Packets.PING, Packets.PONG,
Packets.ENTITY_SPAWN, Packets.ENTITY_REMOVE,
Packets.ENTITY_SPAWN, Packets.ENTITY_REMOVE, Packets.LAUNCHER_AUTH,
Packets.DISCONNECT,
};
for (int i = 0; i < ids.length; i++) {