Режим игры решает сервер: клиент больше не ломает блоки сам

This commit is contained in:
sasheg dev
2026-10-20 23:03:54 +03:00
parent 1c93d9ae9a
commit aee8b61128
14 changed files with 367 additions and 33 deletions
@@ -102,6 +102,22 @@ public final class Packets {
*/
public static final int LAUNCHER_AUTH = 0x1A;
/**
* The player's game mode, changed while the player is in the world.
*
* The mode arrives with the world join and can be changed afterwards, the
* way a server changes it. What a player may do about blocks follows from
* it: in survival the player breaks nothing, in creative the player
* breaks what they look at.
*/
public static final int SET_GAME_MODE = 0x1B;
/** Survival: the player cannot break blocks at all. */
public static final int GAMEMODE_SURVIVAL = 0;
/** Creative: the player breaks the block they are looking at. */
public static final int GAMEMODE_CREATIVE = 1;
public static final int DISCONNECT = 0x7F;
/** The client introducing itself, and naming the account it wants. */
@@ -465,8 +481,11 @@ public final class Packets {
public final int viewDistance;
public final int worldHeight;
/** The game mode the player starts in. */
public final int gameMode;
public WorldJoin(int entityId, long seed, double spawnX, double spawnY,
double spawnZ, int viewDistance, int worldHeight) {
double spawnZ, int viewDistance, int worldHeight, int gameMode) {
this.entityId = entityId;
this.seed = seed;
this.spawnX = spawnX;
@@ -474,6 +493,7 @@ public final class Packets {
this.spawnZ = spawnZ;
this.viewDistance = viewDistance;
this.worldHeight = worldHeight;
this.gameMode = gameMode;
}
public Buf write() {
@@ -483,6 +503,7 @@ public final class Packets {
buf.writePosition(this.spawnX, this.spawnY, this.spawnZ);
buf.writeVarInt(this.viewDistance);
buf.writeVarInt(this.worldHeight);
buf.writeVarInt(this.gameMode);
return buf;
}
@@ -491,7 +512,7 @@ public final class Packets {
long seed = in.readVarLong();
double[] spawn = in.readPosition();
return new WorldJoin(entityId, seed, spawn[0], spawn[1], spawn[2],
in.readVarInt(), in.readVarInt());
in.readVarInt(), in.readVarInt(), in.readVarInt());
}
}
@@ -750,6 +771,31 @@ public final class Packets {
}
}
/** The game mode of one player. */
public static final class GameMode implements Packet {
public final int mode;
public GameMode(int mode) {
this.mode = mode;
}
/** True when the player may break blocks. */
public boolean creative() {
return this.mode == GAMEMODE_CREATIVE;
}
public Buf write() {
Buf buf = new Buf(8);
buf.writeVarInt(this.mode);
return buf;
}
public static GameMode read(Buf in) {
return new GameMode(in.readVarInt());
}
}
/**
* The launcher's session, as the game server sees it.
*
@@ -807,6 +853,7 @@ public final class Packets {
map.put(Integer.valueOf(ENTITY_SPAWN), "EntitySpawn");
map.put(Integer.valueOf(ENTITY_REMOVE), "EntityRemove");
map.put(Integer.valueOf(LAUNCHER_AUTH), "LauncherAuth");
map.put(Integer.valueOf(SET_GAME_MODE), "GameMode");
map.put(Integer.valueOf(DISCONNECT), "Disconnect");
return map;
}
@@ -417,7 +417,8 @@ public final class ProtocolTest {
yes("a fresh join carries no position", !freshBack.hasPosition);
Packets.WorldJoin world =
new Packets.WorldJoin(7, 1234567890123L, 0.5D, 64.0D, 0.5D, 8, 256);
new Packets.WorldJoin(7, 1234567890123L, 0.5D, 64.0D, 0.5D, 8, 256,
Packets.GAMEMODE_CREATIVE);
Packets.WorldJoin worldBack =
Packets.WorldJoin.read(new Buf(world.write().toByteArray()));
eq("entity id", Integer.valueOf(7), Integer.valueOf(worldBack.entityId));
@@ -425,6 +426,16 @@ public final class ProtocolTest {
eq("view distance", Integer.valueOf(8), Integer.valueOf(worldBack.viewDistance));
eq("world height", Integer.valueOf(256), Integer.valueOf(worldBack.worldHeight));
eq("spawn x", Double.valueOf(0.5D), Double.valueOf(worldBack.spawnX));
eq("game mode", Integer.valueOf(Packets.GAMEMODE_CREATIVE),
Integer.valueOf(worldBack.gameMode));
Packets.GameMode mode = new Packets.GameMode(Packets.GAMEMODE_SURVIVAL);
Packets.GameMode modeBack = Packets.GameMode.read(new Buf(mode.write().toByteArray()));
eq("survival comes back", Integer.valueOf(Packets.GAMEMODE_SURVIVAL),
Integer.valueOf(modeBack.mode));
yes("survival cannot break blocks", !modeBack.creative());
yes("creative can break blocks",
new Packets.GameMode(Packets.GAMEMODE_CREATIVE).creative());
Packets.BlockChange change = new Packets.BlockChange(-100, 70, 250, Blocks.STONE);
Packets.BlockChange changeBack =
@@ -528,6 +539,7 @@ public final class ProtocolTest {
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.LAUNCHER_AUTH,
Packets.SET_GAME_MODE,
Packets.DISCONNECT,
};
for (int i = 0; i < ids.length; i++) {