450bdecc34
Раньше клиент умел только показывать меню. Теперь он заходит на сервер,
получает наш мир и рисует его.
Как это устроено:
- Наш сетевой слой (net/rustnotmc/client/net) читает наш протокол и
переводит его пакеты в пакеты игры. Игра остаётся игрой: у неё есть
мир, игрок, сущности и рендер, и все они работают. Не переписывать их
ради того, чтобы нарисовать тот же мир иначе, незачем.
- Пакеты игры, которые не имеют соответствия у нас, не отправляются, а
наоборот: перемещение игрока и ломание блока переводятся в наши.
- Экран входа игры (GuiConnecting) заменён наш: он спрашивает у лаунчера,
кем пришёл игрок, и подставляет это в рукопожатие.
- Соединение качается из тика игры, а не из экрана. Рукопожатие, которое
зависит от того, что экран ещё на экране, ломается alt-tab'ом.
Вход теперь через лаунчер, а не внутри игры:
- Лаунчер уже умеет логинить игрока и отдаёт игре имя, uuid и токен
(--username, --uuid, --accessToken). Это та же роль, что у Yggdrasil в
ванилле, только лаунчер наш.
- Сервер спрашивает лаунчер, один из ли наш этот игрок, и заодно получает
бан-лист. Токен используется один раз и не хранится.
- Свои аккаунты сервера, когда настроен лаунчер, закрыты: сервер с двумя
дверями не имеет дверей. Открыть их можно флагом, но намеренно.
- Если игру запустили без лаунчера, экран всё равно спрашивает имя и
пароль: это путь для своего сервера и для разработки.
Проверено живьём: клиент вошёл по токену лаунчера, сервер спросил
лаунчер, лаунчер сказал "свой", игрок получил мир, 210 чанков пришли и
лежат на диске, рельеф нарисован.
Что чинилось по дороге:
- Minecraft.setIngameFocus() возвращал на главное меню, когда окно
получало фокус. Игрок как раз кликает в окно, чтобы напечатать пароль, и
экран входа исчезал в этот самый момент.
- Ответ лаунчера разбирается, а не ищется подстрокой: {"valid": true} и
{"valid":true} это один и тот же ответ, и сервер, который понимает
только второй, ломает работающий лаунчер.
39 lines
1.2 KiB
Java
39 lines
1.2 KiB
Java
package net.rustnotmc.client.gui;
|
|
|
|
import net.minecraft.client.gui.FontRenderer;
|
|
import net.minecraft.client.gui.GuiTextField;
|
|
|
|
/**
|
|
* A text field that shows dots instead of what is in it.
|
|
*
|
|
* The game has no password field, and a password that appears on the screen
|
|
* while it is typed is a password that ends up in a screenshot.
|
|
*
|
|
* The game draws the text field from its own private text, so the only way to
|
|
* mask it without copying the whole field is to put the dots in for the moment
|
|
* it takes to draw and put the real text back afterwards. The cursor ends up
|
|
* at the end of the text, which for a password is where it is wanted anyway.
|
|
*/
|
|
public class RsxPasswordField extends GuiTextField {
|
|
|
|
public RsxPasswordField(int id, FontRenderer font, int x, int y, int width, int height) {
|
|
super(id, font, x, y, width, height);
|
|
}
|
|
|
|
@Override
|
|
public void drawTextBox() {
|
|
String real = getText();
|
|
if (real.isEmpty()) {
|
|
super.drawTextBox();
|
|
return;
|
|
}
|
|
StringBuilder dots = new StringBuilder(real.length());
|
|
for (int i = 0; i < real.length(); i++) {
|
|
dots.append('*');
|
|
}
|
|
setText(dots.toString());
|
|
super.drawTextBox();
|
|
setText(real);
|
|
}
|
|
}
|