Files
RustNotMC/rsx-protocol/src/main/java/net/rustnotmc/protocol/Blocks.java
T
sasheg dev 7cd074e13c Словарь протокола: блоки, формат чанка и игровые пакеты
Протокол до сих пор умел только рукопожатие: поздороваться, доказать
пароль, получить токен и войти. Дальше играть было нечем.

Добавлено:

- Packet, интерфейс, который умеет написать себя сам. Раньше отправитель
  разбирал тип пакета в ветке instanceof, и с каждым новым видом пакета эта
  ветка росла. Теперь отправитель знает только, что у пакета есть write().
- Блоки и ChunkFormat переехали в протокол. Идентификаторы блоков и
  геометрия чанка — это словарь провода, а не внутреннее дело сервера:
  клиент получает чанк байт на блок и обязан знать, что означает каждый
  байт. Один источник правды вместо двух, которые могут разойтись.
- Игровые пакеты: JoinWorld, WorldJoin, ChunkData, BlockChange,
  PlayerMove, EntityMove, Ping/Pong, EntitySpawn, EntityRemove.
- Чанк уходит по проводу сжатым. Чанк это 65536 байт, и почти все они это
  воздух, поэтому дефлейт тут не украшение, а разница между «сервер
  принял» и «клиент вошёл».
- Имена всем пакетам в таблице names(), чтобы забытый пакет был виден
  сразу, а не всплывал через месяц.

Проверено: 22 теста протокола, включая круг чанка через сжатие, отказ
битому сжатому блоку и отказ обрезанному.
2026-10-19 18:58:07 +03:00

65 lines
2.1 KiB
Java

package net.rustnotmc.protocol;
/**
* The block ids a world is made of.
*
* These live in the protocol rather than in the server because they are the
* vocabulary of the wire: a chunk that arrives at the client is a byte per
* block, and both ends have to agree on what each byte means. A server that
* invented its own ids would leave the client guessing.
*
* Kept as plain constants rather than an enum so that a chunk can store them in
* a byte array. A world holding an enum per block costs sixteen bytes a block
* and a garbage collector problem for every chunk that moves.
*
* The ids do not have to match anything right now. What matters is that they are
* stable, because they go into save files and onto the wire, and that air is
* zero, because every "is this chunk generated" shortcut in the code assumes it.
*/
public final class Blocks {
public static final byte AIR = 0;
public static final byte STONE = 1;
public static final byte DIRT = 2;
public static final byte GRASS = 3;
public static final byte SAND = 4;
public static final byte WATER = 5;
public static final byte WOOD = 6;
public static final byte LEAVES = 7;
/** Lowest and highest legal block id. */
public static final byte MIN = AIR;
public static final byte MAX = LEAVES;
private Blocks() {
}
public static String name(byte id) {
switch (id) {
case AIR: return "air";
case STONE: return "stone";
case DIRT: return "dirt";
case GRASS: return "grass";
case SAND: return "sand";
case WATER: return "water";
case WOOD: return "wood";
case LEAVES: return "leaves";
default: return "unknown(" + id + ")";
}
}
/** True when a player can walk through it. */
public static boolean isPassable(byte id) {
return id == AIR || id == WATER;
}
/** True when light passes through it. */
public static boolean isTransparent(byte id) {
return id == AIR || id == WATER;
}
public static boolean isValid(byte id) {
return id >= MIN && id <= MAX;
}
}