GameMode hardcoded abilities (#2366)

This commit is contained in:
TheMode 2024-09-04 01:49:35 +02:00 committed by Matt Worzala
parent 5ccd0f0789
commit a1048133d1
3 changed files with 41 additions and 63 deletions

View File

@ -11,49 +11,50 @@ import static net.minestom.server.network.NetworkBuffer.BYTE;
* Can be set with {@link Player#setGameMode(GameMode)}. * Can be set with {@link Player#setGameMode(GameMode)}.
*/ */
public enum GameMode { public enum GameMode {
SURVIVAL((byte) 0, true), SURVIVAL(false, false, false),
CREATIVE((byte) 1, false), CREATIVE(true, true, true),
ADVENTURE((byte) 2, true), ADVENTURE(false, false, false),
SPECTATOR((byte) 3, false); SPECTATOR(true, true, false);
private final byte id; private final boolean allowFlying;
private final boolean canTakeDamage; private final boolean invulnerable;
private final boolean instantBreak;
GameMode(byte id, boolean canTakeDamage) { GameMode(boolean allowFlying, boolean invulnerable, boolean instantBreak) {
this.id = id; this.allowFlying = allowFlying;
this.canTakeDamage = canTakeDamage; this.invulnerable = invulnerable;
this.instantBreak = instantBreak;
} }
public byte id() { public boolean allowFlying() {
return id; return allowFlying;
} }
public boolean canTakeDamage() { public boolean canTakeDamage() {
return canTakeDamage; return invulnerable;
} }
public static final NetworkBuffer.Type<GameMode> NETWORK_TYPE = BYTE.transform(GameMode::fromId, gameMode -> gameMode.id); public boolean instantBreak() {
return instantBreak;
}
private static final GameMode[] VALUES = values();
public static final NetworkBuffer.Type<GameMode> NETWORK_TYPE = BYTE.transform(
id -> VALUES[id],
gameMode -> (byte) gameMode.ordinal()
);
public static final NetworkBuffer.Type<GameMode> OPT_NETWORK_TYPE = new NetworkBuffer.Type<>() { public static final NetworkBuffer.Type<GameMode> OPT_NETWORK_TYPE = new NetworkBuffer.Type<>() {
@Override @Override
public void write(@NotNull NetworkBuffer buffer, GameMode value) { public void write(@NotNull NetworkBuffer buffer, GameMode value) {
buffer.write(BYTE, value != null ? value.id() : -1); buffer.write(BYTE, value != null ? (byte) value.ordinal() : -1);
} }
@Override @Override
public GameMode read(@NotNull NetworkBuffer buffer) { public GameMode read(@NotNull NetworkBuffer buffer) {
final byte id = buffer.read(BYTE); final byte id = buffer.read(BYTE);
return id != -1 ? GameMode.fromId(id) : null; return id != -1 ? VALUES[id] : null;
} }
}; };
public static @NotNull GameMode fromId(int id) {
return switch (id) {
case 0 -> SURVIVAL;
case 1 -> CREATIVE;
case 2 -> ADVENTURE;
case 3 -> SPECTATOR;
default -> throw new IllegalArgumentException("Unknown game mode id: " + id);
};
}
} }

View File

@ -1614,36 +1614,21 @@ public class Player extends LivingEntity implements CommandSender, HoverEventSou
this.gameMode = gameMode; this.gameMode = gameMode;
// Condition to prevent sending the packets before spawning the player // Condition to prevent sending the packets before spawning the player
if (isActive()) { if (isActive()) {
sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.CHANGE_GAMEMODE, gameMode.id())); sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.CHANGE_GAMEMODE, gameMode.ordinal()));
PacketSendingUtils.broadcastPlayPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, infoEntry())); PacketSendingUtils.broadcastPlayPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, infoEntry()));
} }
// The client updates their abilities based on the GameMode as follows // The client updates their abilities based on the GameMode as follows
switch (gameMode) { this.allowFlying = gameMode.allowFlying();
case CREATIVE -> { this.instantBreak = gameMode.instantBreak();
this.allowFlying = true; this.invulnerable = gameMode.canTakeDamage();
this.instantBreak = true; // Spectator automatically enables flying
this.invulnerable = true; // If new game mode cannot fly, disable it
} if (gameMode == GameMode.SPECTATOR || !gameMode.allowFlying()) {
case SPECTATOR -> { if (isActive()) {
this.allowFlying = true; refreshFlying(gameMode.allowFlying());
this.instantBreak = false; } else {
this.invulnerable = true; this.flying = gameMode.allowFlying();
if (isActive()) {
refreshFlying(true);
} else {
this.flying = true;
}
}
default -> {
this.allowFlying = false;
this.instantBreak = false;
this.invulnerable = false;
if (isActive()) {
refreshFlying(false);
} else {
this.flying = false;
}
} }
} }
// Make sure that the player is in the PLAY state and synchronize their flight speed. // Make sure that the player is in the PLAY state and synchronize their flight speed.

View File

@ -8,17 +8,9 @@ public class GameModeTest {
@Test @Test
public void toId() { public void toId() {
assertEquals(GameMode.SURVIVAL.id(), 0); assertEquals(GameMode.SURVIVAL.ordinal(), 0);
assertEquals(GameMode.CREATIVE.id(), 1); assertEquals(GameMode.CREATIVE.ordinal(), 1);
assertEquals(GameMode.ADVENTURE.id(), 2); assertEquals(GameMode.ADVENTURE.ordinal(), 2);
assertEquals(GameMode.SPECTATOR.id(), 3); assertEquals(GameMode.SPECTATOR.ordinal(), 3);
}
@Test
public void fromId() {
assertEquals(GameMode.SURVIVAL, GameMode.fromId(0));
assertEquals(GameMode.CREATIVE, GameMode.fromId(1));
assertEquals(GameMode.ADVENTURE, GameMode.fromId(2));
assertEquals(GameMode.SPECTATOR, GameMode.fromId(3));
} }
} }