Skip to content

Commit

Permalink
Use barriers instead of stone blocks for verification (#54)
Browse files Browse the repository at this point in the history
* feat: replace abstract method with a java.util.function.Function

* fix: make spawn x and z position adapt to platform size

* feat: optimize/improve Fallback packet preparing

* fix: block id shifting being broken on 1.7-1.13

* fix: optimize 1.7 support in UpdateSectionBlocks packet

* style: improve codestyle of the UpdateSectionBlocks packet

* fix: use normal binary io reader for mappings instead of unlimited reader

* feat: implement universal Chat packet and add LOGIN / GAME states for better packet registry control

* feat: [wip] barrier block integration (block ids for 1.13+ are still missing)

* feat: use buffered writing more often to potentially reduce performance impact

* feat: optimize chunk sending by only flushing the packets if necessary

* refactor: setAbilitiesAndTeleport -> sendAbilitiesAndTeleport

* style: fix fields being named incorrectly

* feat: cache 1.7 empty chunk filler bytes

* feat: use barrier blocks instead of stone blocks for verification
  • Loading branch information
jonesdevelopment authored Oct 6, 2023
1 parent a75c409 commit 702ea1b
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ public FallbackVerificationHandler(final @NotNull FallbackUser<?, ?> user,
this.playerUuid = playerUuid;
this.state = State.KEEP_ALIVE;

// Send LoginSuccess packet to make the client think they are joining the server
user.write(new ServerLoginSuccess(username, playerUuid));

if (user.getProtocolVersion().compareTo(MINECRAFT_1_8) < 0) {
// 1.7 players don't have KeepAlive packets in the login process
sendJoinGamePacket();
Expand Down Expand Up @@ -110,6 +107,21 @@ private void sendJoinGamePacket() {
user.write(getJoinPacketForVersion(user.getProtocolVersion()));
}

private void sendAbilitiesAndTeleport() {
// Set the state to TELEPORT to avoid false positives
// and go on with the flow of the verification.
state = State.TELEPORT;
// Make sure the player is unable to fly (the player is in spectator mode)
user.delayedWrite(DEFAULT_ABILITIES);
// Generate the current teleport ID
expectedTeleportId = RANDOM.nextInt(Short.MAX_VALUE);
// Teleport the player to the spawn position
user.delayedWrite(new PositionLook(
SPAWN_X_POSITION, dynamicSpawnYPosition, SPAWN_Z_POSITION,
0f, 0f, expectedTeleportId, false
));
}

private void sendChunkData() {
// Set the state to POSITION to avoid false positives
// and go on with the flow of the verification.
Expand All @@ -123,18 +135,6 @@ private void sendChunkData() {
user.getChannel().flush();
}

private void setAbilitiesAndTeleport() {
// Make sure the player is unable to fly (the player is in spectator mode)
user.write(DEFAULT_ABILITIES);
// Generate the current teleport ID
expectedTeleportId = RANDOM.nextInt(Short.MAX_VALUE);
// Teleport the player to the spawn position
user.write(new PositionLook(
SPAWN_X_POSITION, DYNAMIC_SPAWN_Y_POSITION, SPAWN_Z_POSITION,
0f, 0f, expectedTeleportId, false
));
}

private static boolean validateClientLocale(final @SuppressWarnings("unused") @NotNull FallbackUser<?, ?> user,
final String locale) {
// Check the client locale by performing a simple regex check on it
Expand Down Expand Up @@ -254,16 +254,16 @@ public void handle(final @NotNull FallbackPacket packet) {
// First, send an abilities packet to the client to make
// sure the player falls even in spectator mode.
// Then, teleport the player to the spawn position.
setAbilitiesAndTeleport();
sendAbilitiesAndTeleport();

// 1.7-1.8 clients do not have a TeleportConfirm packet
if (user.getProtocolVersion().compareTo(MINECRAFT_1_8) <= 0) {
// Immediately send the chunk data as 1.7-1.8 can't confirm teleports
sendChunkData();
} else {
// Set the state to TELEPORT to avoid false positives
// and go on with the flow of the verification.
state = State.TELEPORT;
// Send all previously sent packets in one flush since we didn't flush
// the channel earlier when we teleported the player.
user.getChannel().flush();
}
}

Expand Down Expand Up @@ -305,7 +305,7 @@ private void handlePositionUpdate(final double x, final double y, final double z
if (user.getProtocolVersion().compareTo(MINECRAFT_1_8) <= 0
&& expectedTeleportId != -1 // Check if the teleport ID is currently unset
// Then, check if the position is equal to the spawn position
&& x == SPAWN_X_POSITION && y == DYNAMIC_SPAWN_Y_POSITION && z == SPAWN_Z_POSITION) {
&& x == SPAWN_X_POSITION && y == dynamicSpawnYPosition && z == SPAWN_Z_POSITION) {
// Reset all values to ensure safety on teleport
tick = 1;
posY = -1;
Expand All @@ -332,7 +332,7 @@ private void handlePositionUpdate(final double x, final double y, final double z
listenForMovements = true;
}

lastY = DYNAMIC_SPAWN_Y_POSITION;
lastY = dynamicSpawnYPosition;
return;
}

Expand All @@ -346,7 +346,7 @@ private void handlePositionUpdate(final double x, final double y, final double z
return;
}

if (tick > MAX_MOVEMENT_TICK) {
if (tick > maxMovementTick) {
if (!Sonar.get().getConfig().isCheckCollisions()) {
// Checking collisions is disabled, just finish verification
finish();
Expand Down Expand Up @@ -378,8 +378,8 @@ private void handlePositionUpdate(final double x, final double y, final double z
}
}

if (!ground && tick < MAX_PREDICTION_TICK) {
final double predictedY = PREPARED_MOVEMENTS[tick];
if (!ground && tick < maxPredictionTick) {
final double predictedY = preparedCachedYMotions[tick];
final double offsetY = Math.abs(deltaY - predictedY);

// Log/debug position if enabled in the configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public final class FallbackPacketDecoder extends ChannelInboundHandlerAdapter {
public FallbackPacketDecoder(final @NotNull FallbackUser<?, ?> user,
final @NotNull FallbackPacketListener listener) {
this.user = user;
this.registry = FallbackPacketRegistry.SONAR.getProtocolRegistry(
this.registry = FallbackPacketRegistry.GAME.getProtocolRegistry(
FallbackPacketRegistry.Direction.SERVERBOUND, user.getProtocolVersion()
);
this.listener = listener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@

public final class FallbackPacketEncoder extends MessageToByteEncoder<FallbackPacket> {
private final ProtocolVersion protocolVersion;
private final FallbackPacketRegistry.ProtocolRegistry registry;
private FallbackPacketRegistry.ProtocolRegistry registry;

public FallbackPacketEncoder(final ProtocolVersion protocolVersion) {
this.protocolVersion = protocolVersion;
this.registry = FallbackPacketRegistry.SONAR.getProtocolRegistry(
FallbackPacketRegistry.Direction.CLIENTBOUND, protocolVersion
);
this.registry = FallbackPacketRegistry.LOGIN
.getProtocolRegistry(FallbackPacketRegistry.Direction.CLIENTBOUND, protocolVersion);
}

public void loginSuccess() {
this.registry = FallbackPacketRegistry.GAME
.getProtocolRegistry(FallbackPacketRegistry.Direction.CLIENTBOUND, protocolVersion);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@
// Most of this is taken from
// https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java
public enum FallbackPacketRegistry {
SONAR {
LOGIN {
{
clientbound.fallback = false;
serverbound.fallback = false;

// LOGIN
clientbound.register(ServerLoginSuccess.class, ServerLoginSuccess::new,
map(0x02, MINECRAFT_1_7_2, false));

// GAME
}
},
GAME {
{
clientbound.register(JoinGame.class, JoinGame::new,
map(0x01, MINECRAFT_1_7_2, true),
map(0x23, MINECRAFT_1_9, true),
Expand Down Expand Up @@ -160,6 +161,17 @@ public enum FallbackPacketRegistry {
map(0x2F, MINECRAFT_1_19_1, true),
map(0x2E, MINECRAFT_1_19_3, true),
map(0x32, MINECRAFT_1_19_4, true));
clientbound.register(Chat.class, Chat::new,
map(0x02, MINECRAFT_1_7_2, true),
map(0x0F, MINECRAFT_1_9, true),
map(0x0E, MINECRAFT_1_13, true),
map(0x0F, MINECRAFT_1_15, true),
map(0x0E, MINECRAFT_1_16, true),
map(0x0F, MINECRAFT_1_18_2, true),
map(0x5F, MINECRAFT_1_19, true),
map(0x62, MINECRAFT_1_19_1, true),
map(0x60, MINECRAFT_1_19_3, true),
map(0x64, MINECRAFT_1_19_4, true));

serverbound.register(KeepAlive.class, KeepAlive::new,
map(0x00, MINECRAFT_1_7_2, false),
Expand Down
Loading

0 comments on commit 702ea1b

Please sign in to comment.