mirror of
https://github.com/jonesdevelopment/sonar.git
synced 2026-11-05 09:20:15 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1438856531 | ||
|
|
694725b798 |
No files matched your search
+1
-1
@@ -1,3 +1,3 @@
|
||||
group=xyz.jonesdev.sonar
|
||||
version=2.1.5
|
||||
version=2.1.6
|
||||
description=A lightweight, effective, and easy-to-use anti-bot plugin for Velocity, BungeeCord, and Bukkit.
|
||||
+50
@@ -213,6 +213,20 @@ public enum FallbackPacketRegistry {
|
||||
map(0x5B, MINECRAFT_1_20_2, true),
|
||||
map(0x5D, MINECRAFT_1_20_3, true),
|
||||
map(0x5F, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(VehicleMovePacket.class, VehicleMovePacket::new,
|
||||
map(0x29, MINECRAFT_1_9, false),
|
||||
map(0x2B, MINECRAFT_1_13, false),
|
||||
map(0x2C, MINECRAFT_1_14, false),
|
||||
map(0x2D, MINECRAFT_1_15, false),
|
||||
map(0x2C, MINECRAFT_1_16, false),
|
||||
map(0x2B, MINECRAFT_1_16_2, false),
|
||||
map(0x2C, MINECRAFT_1_17, false),
|
||||
map(0x29, MINECRAFT_1_19, false),
|
||||
map(0x2B, MINECRAFT_1_19_1, false),
|
||||
map(0x2A, MINECRAFT_1_19_3, false),
|
||||
map(0x2E, MINECRAFT_1_19_4, false),
|
||||
map(0x2F, MINECRAFT_1_20_2, false),
|
||||
map(0x31, MINECRAFT_1_20_5, false));
|
||||
clientbound.register(SpawnEntityPacket.class, SpawnEntityPacket::new,
|
||||
map(0x0E, MINECRAFT_1_7_2, true),
|
||||
map(0x00, MINECRAFT_1_9, true),
|
||||
@@ -341,6 +355,14 @@ public enum FallbackPacketRegistry {
|
||||
map(0x4F, MINECRAFT_1_20_2, true),
|
||||
map(0x51, MINECRAFT_1_20_3, true),
|
||||
map(0x53, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(EntityAnimationPacket.class, EntityAnimationPacket::new,
|
||||
map(0x0B, MINECRAFT_1_7_2, true),
|
||||
map(0x06, MINECRAFT_1_9, true),
|
||||
map(0x05, MINECRAFT_1_16, true),
|
||||
map(0x06, MINECRAFT_1_17, true),
|
||||
map(0x03, MINECRAFT_1_19, true),
|
||||
map(0x04, MINECRAFT_1_19_4, true),
|
||||
map(0x03, MINECRAFT_1_20_2, true));
|
||||
|
||||
serverbound.register(SetHeldItemPacket.class, SetHeldItemPacket::new,
|
||||
map(0x09, MINECRAFT_1_7_2, false),
|
||||
@@ -385,6 +407,21 @@ public enum FallbackPacketRegistry {
|
||||
map(0x22, MINECRAFT_1_20_2, false),
|
||||
map(0x23, MINECRAFT_1_20_3, false),
|
||||
map(0x26, MINECRAFT_1_20_5, false));
|
||||
serverbound.register(VehicleMovePacket.class, VehicleMovePacket::new,
|
||||
map(0x10, MINECRAFT_1_9, false),
|
||||
map(0x11, MINECRAFT_1_12, false),
|
||||
map(0x10, MINECRAFT_1_12_1, false),
|
||||
map(0x13, MINECRAFT_1_13, false),
|
||||
map(0x15, MINECRAFT_1_14, false),
|
||||
map(0x16, MINECRAFT_1_16, false),
|
||||
map(0x15, MINECRAFT_1_17, false),
|
||||
map(0x17, MINECRAFT_1_19, false),
|
||||
map(0x18, MINECRAFT_1_19_1, false),
|
||||
map(0x17, MINECRAFT_1_19_3, false),
|
||||
map(0x18, MINECRAFT_1_19_4, false),
|
||||
map(0x1A, MINECRAFT_1_20_2, false),
|
||||
map(0x1B, MINECRAFT_1_20_3, false),
|
||||
map(0x1E, MINECRAFT_1_20_5, false));
|
||||
serverbound.register(SystemChatPacket.class, SystemChatPacket::new,
|
||||
map(0x01, MINECRAFT_1_7_2, false),
|
||||
map(0x02, MINECRAFT_1_9, false),
|
||||
@@ -518,6 +555,19 @@ public enum FallbackPacketRegistry {
|
||||
map(0x23, MINECRAFT_1_20_2, false),
|
||||
map(0x24, MINECRAFT_1_20_3, false),
|
||||
map(0x27, MINECRAFT_1_20_5, false));
|
||||
serverbound.register(AnimationPacket.class, AnimationPacket::new,
|
||||
map(0x0A, MINECRAFT_1_7_2, false),
|
||||
map(0x1A, MINECRAFT_1_9, false),
|
||||
map(0x1D, MINECRAFT_1_12, false),
|
||||
map(0x27, MINECRAFT_1_13, false),
|
||||
map(0x2A, MINECRAFT_1_14, false),
|
||||
map(0x2B, MINECRAFT_1_16, false),
|
||||
map(0x2C, MINECRAFT_1_16_2, false),
|
||||
map(0x2E, MINECRAFT_1_19, false),
|
||||
map(0x2F, MINECRAFT_1_19_1, false),
|
||||
map(0x32, MINECRAFT_1_20_2, false),
|
||||
map(0x33, MINECRAFT_1_20_3, false),
|
||||
map(0x36, MINECRAFT_1_20_5, false));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+17
-9
@@ -62,7 +62,7 @@ public class FallbackPreparer {
|
||||
public FallbackPacket enterCodeMessage;
|
||||
public FallbackPacket incorrectCaptcha;
|
||||
// JoinGame
|
||||
public final int PLAYER_ENTITY_ID = RANDOM.nextInt(10);
|
||||
public static final int PLAYER_ENTITY_ID = RANDOM.nextInt(50);
|
||||
public FallbackPacket joinGame;
|
||||
// Update Section Blocks
|
||||
public FallbackPacket updateSectionBlocks;
|
||||
@@ -84,10 +84,14 @@ public class FallbackPreparer {
|
||||
public FallbackPacket tooManyOnlinePerIP;
|
||||
|
||||
// Vehicle
|
||||
public FallbackPacket removeEntities;
|
||||
public FallbackPacket spawnEntity;
|
||||
public static FallbackPacket setPassengers;
|
||||
public static final int VEHICLE_ENTITY_ID = PLAYER_ENTITY_ID + 1 + RANDOM.nextInt(10);
|
||||
public FallbackPacket removeBoatEntities;
|
||||
public FallbackPacket removeMinecartEntities;
|
||||
public FallbackPacket spawnBoatEntity;
|
||||
public FallbackPacket spawnMinecartEntity;
|
||||
public FallbackPacket setBoatPassengers;
|
||||
public FallbackPacket setMinecartPassengers;
|
||||
public final int VEHICLE_BOAT_ENTITY_ID = PLAYER_ENTITY_ID + 1 + RANDOM.nextInt(10);
|
||||
public final int VEHICLE_MINECART_ENTITY_ID = VEHICLE_BOAT_ENTITY_ID + 1 + RANDOM.nextInt(10);
|
||||
|
||||
// Collisions
|
||||
public final int BLOCKS_PER_ROW = 8; // 8 * 8 = 64 (protocol maximum)
|
||||
@@ -181,10 +185,14 @@ public class FallbackPreparer {
|
||||
}
|
||||
|
||||
// Prepare packets for the vehicle check
|
||||
removeEntities = new FallbackPacketSnapshot(new RemoveEntitiesPacket(VEHICLE_ENTITY_ID));
|
||||
spawnEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(
|
||||
VEHICLE_ENTITY_ID, EntityType.BOAT, SPAWN_X_POSITION, IN_AIR_Y_POSITION, SPAWN_Z_POSITION));
|
||||
setPassengers = new FallbackPacketSnapshot(new SetPassengersPacket(VEHICLE_ENTITY_ID, PLAYER_ENTITY_ID));
|
||||
removeBoatEntities = new FallbackPacketSnapshot(new RemoveEntitiesPacket(VEHICLE_BOAT_ENTITY_ID));
|
||||
removeMinecartEntities = new FallbackPacketSnapshot(new RemoveEntitiesPacket(VEHICLE_MINECART_ENTITY_ID));
|
||||
spawnBoatEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(
|
||||
VEHICLE_BOAT_ENTITY_ID, EntityType.BOAT, SPAWN_X_POSITION, IN_AIR_Y_POSITION, SPAWN_Z_POSITION));
|
||||
spawnMinecartEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(
|
||||
VEHICLE_MINECART_ENTITY_ID, EntityType.MINECART, SPAWN_X_POSITION, IN_AIR_Y_POSITION, SPAWN_Z_POSITION));
|
||||
setBoatPassengers = new FallbackPacketSnapshot(new SetPassengersPacket(VEHICLE_BOAT_ENTITY_ID, PLAYER_ENTITY_ID));
|
||||
setMinecartPassengers = new FallbackPacketSnapshot(new SetPassengersPacket(VEHICLE_MINECART_ENTITY_ID, PLAYER_ENTITY_ID));
|
||||
|
||||
if (Sonar.get().getConfig().getVerification().getMap().getTiming() != SonarConfiguration.Verification.Timing.NEVER
|
||||
|| Sonar.get().getConfig().getVerification().getGravity().isCaptchaOnFail()) {
|
||||
|
||||
+43
-13
@@ -27,108 +27,128 @@ import java.util.function.Function;
|
||||
@SuppressWarnings("unused")
|
||||
@RequiredArgsConstructor
|
||||
public enum BlockType {
|
||||
STONE(protocolVersion -> 1, 1),
|
||||
// Useful resources:
|
||||
// - https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/
|
||||
// - https://pokechu22.github.io/Burger/
|
||||
// - https://github.com/ViaVersion/Mappings/tree/main/mappings
|
||||
STONE(protocolVersion -> 1, 1),
|
||||
ENCHANTMENT_TABLE(protocolVersion -> {
|
||||
switch (protocolVersion) {
|
||||
case MINECRAFT_1_7_2:
|
||||
case MINECRAFT_1_7_6:
|
||||
default:
|
||||
// 1.7.2-1.12.2
|
||||
return 116;
|
||||
// 1.13-1.13.1
|
||||
case MINECRAFT_1_13:
|
||||
case MINECRAFT_1_13_1:
|
||||
return 4612;
|
||||
// 1.13.2-1.14.3
|
||||
case MINECRAFT_1_13_2:
|
||||
case MINECRAFT_1_14:
|
||||
case MINECRAFT_1_14_1:
|
||||
case MINECRAFT_1_14_2:
|
||||
case MINECRAFT_1_14_3:
|
||||
return 4613;
|
||||
// 1.14.4-1.15.2
|
||||
case MINECRAFT_1_14_4:
|
||||
case MINECRAFT_1_15:
|
||||
case MINECRAFT_1_15_1:
|
||||
case MINECRAFT_1_15_2:
|
||||
return 5116;
|
||||
// 1.16-1.16.1
|
||||
case MINECRAFT_1_16:
|
||||
case MINECRAFT_1_16_1:
|
||||
return 5132;
|
||||
// 1.16.2-1.16.4
|
||||
case MINECRAFT_1_16_2:
|
||||
case MINECRAFT_1_16_3:
|
||||
case MINECRAFT_1_16_4:
|
||||
return 5136;
|
||||
// 1.17-1.18.2
|
||||
case MINECRAFT_1_17:
|
||||
case MINECRAFT_1_17_1:
|
||||
case MINECRAFT_1_18:
|
||||
case MINECRAFT_1_18_2:
|
||||
return 5333;
|
||||
// 1.19-1.19.1
|
||||
case MINECRAFT_1_19:
|
||||
case MINECRAFT_1_19_1:
|
||||
return 5719;
|
||||
// 1.19.3
|
||||
case MINECRAFT_1_19_3:
|
||||
return 7159;
|
||||
// 1.19.4
|
||||
case MINECRAFT_1_19_4:
|
||||
return 7385;
|
||||
// 1.20-1.21
|
||||
case MINECRAFT_1_20:
|
||||
case MINECRAFT_1_20_2:
|
||||
case MINECRAFT_1_20_3:
|
||||
case MINECRAFT_1_20_5:
|
||||
case MINECRAFT_1_21:
|
||||
return 7389;
|
||||
// 1.7.2-1.12.2
|
||||
default:
|
||||
return 116;
|
||||
}
|
||||
}, 0.75f),
|
||||
TRAPDOOR(protocolVersion -> {
|
||||
switch (protocolVersion) {
|
||||
// 1.7.2-1.7.6
|
||||
case MINECRAFT_1_7_2:
|
||||
case MINECRAFT_1_7_6:
|
||||
// We have to use wooden trapdoors for 1.7 since 1.7 doesn't have iron trapdoors
|
||||
return 96;
|
||||
default:
|
||||
// 1.8-1.12.2
|
||||
return 167;
|
||||
// 1.13-1.13.1
|
||||
case MINECRAFT_1_13:
|
||||
case MINECRAFT_1_13_1:
|
||||
return 6509;
|
||||
// 1.13.2-1.14.3
|
||||
case MINECRAFT_1_13_2:
|
||||
case MINECRAFT_1_14:
|
||||
case MINECRAFT_1_14_1:
|
||||
case MINECRAFT_1_14_2:
|
||||
case MINECRAFT_1_14_3:
|
||||
return 6510;
|
||||
// 1.14.4-1.15.2
|
||||
case MINECRAFT_1_14_4:
|
||||
case MINECRAFT_1_15:
|
||||
case MINECRAFT_1_15_1:
|
||||
case MINECRAFT_1_15_2:
|
||||
return 7016;
|
||||
// 1.16-1.16.1
|
||||
case MINECRAFT_1_16:
|
||||
case MINECRAFT_1_16_1:
|
||||
return 7552;
|
||||
// 1.16.2-1.16.4
|
||||
case MINECRAFT_1_16_2:
|
||||
case MINECRAFT_1_16_3:
|
||||
case MINECRAFT_1_16_4:
|
||||
return 7556;
|
||||
// 1.17-1.18.2
|
||||
case MINECRAFT_1_17:
|
||||
case MINECRAFT_1_17_1:
|
||||
case MINECRAFT_1_18:
|
||||
case MINECRAFT_1_18_2:
|
||||
return 7802;
|
||||
// 1.19-1.19.1
|
||||
case MINECRAFT_1_19:
|
||||
case MINECRAFT_1_19_1:
|
||||
return 8293;
|
||||
// 1.19.3
|
||||
case MINECRAFT_1_19_3:
|
||||
return 9937;
|
||||
// 1.19.4
|
||||
case MINECRAFT_1_19_4:
|
||||
return 10269;
|
||||
// 1.20
|
||||
case MINECRAFT_1_20:
|
||||
return 10273;
|
||||
// 1.20.2-1.21
|
||||
case MINECRAFT_1_20_2:
|
||||
case MINECRAFT_1_20_3:
|
||||
case MINECRAFT_1_20_5:
|
||||
case MINECRAFT_1_21:
|
||||
return 10414;
|
||||
// 1.8-1.12.2
|
||||
default:
|
||||
return 167;
|
||||
}
|
||||
}, 0.1875),
|
||||
BARRIER(protocolVersion -> {
|
||||
@@ -137,14 +157,14 @@ public enum BlockType {
|
||||
case MINECRAFT_1_7_6:
|
||||
// We have to use glass for 1.7 since 1.7 doesn't have barrier blocks
|
||||
return 20;
|
||||
default:
|
||||
// 1.8-1.12.2
|
||||
return 166;
|
||||
// 1.13-1.13.1
|
||||
case MINECRAFT_1_13:
|
||||
case MINECRAFT_1_13_1:
|
||||
return 6493;
|
||||
// 1.13.2
|
||||
case MINECRAFT_1_13_2:
|
||||
return 6494;
|
||||
// 1.14-1.15.2
|
||||
case MINECRAFT_1_14:
|
||||
case MINECRAFT_1_14_1:
|
||||
case MINECRAFT_1_14_2:
|
||||
@@ -154,37 +174,47 @@ public enum BlockType {
|
||||
case MINECRAFT_1_15_1:
|
||||
case MINECRAFT_1_15_2:
|
||||
return 7000;
|
||||
// 1.16-1.16.1
|
||||
case MINECRAFT_1_16:
|
||||
case MINECRAFT_1_16_1:
|
||||
return 7536;
|
||||
// 1.16.2-1.16.4
|
||||
case MINECRAFT_1_16_2:
|
||||
case MINECRAFT_1_16_3:
|
||||
case MINECRAFT_1_16_4:
|
||||
return 7540;
|
||||
// 1.17-1.18.2
|
||||
case MINECRAFT_1_17:
|
||||
case MINECRAFT_1_17_1:
|
||||
case MINECRAFT_1_18:
|
||||
case MINECRAFT_1_18_2:
|
||||
return 7754;
|
||||
// 1.19-1.19.1
|
||||
case MINECRAFT_1_19:
|
||||
case MINECRAFT_1_19_1:
|
||||
return 8245;
|
||||
// 1.19.3
|
||||
case MINECRAFT_1_19_3:
|
||||
return 9889;
|
||||
// 1.19.4
|
||||
case MINECRAFT_1_19_4:
|
||||
return 10221;
|
||||
// 1.20
|
||||
case MINECRAFT_1_20:
|
||||
return 10225;
|
||||
// 1.20.2-1.21
|
||||
case MINECRAFT_1_20_2:
|
||||
case MINECRAFT_1_20_3:
|
||||
case MINECRAFT_1_20_5:
|
||||
case MINECRAFT_1_21:
|
||||
return 10366;
|
||||
// 1.8-1.12.2
|
||||
default:
|
||||
return 166;
|
||||
}
|
||||
}, 1);
|
||||
|
||||
private final Function<ProtocolVersion, Integer> idFunction;
|
||||
// TODO: Implement per-version block heights?
|
||||
@Getter
|
||||
private final double blockHeight;
|
||||
|
||||
|
||||
+20
-9
@@ -26,20 +26,20 @@ import java.util.function.Function;
|
||||
@SuppressWarnings("unused")
|
||||
@RequiredArgsConstructor
|
||||
public enum ItemType {
|
||||
// Useful resources:
|
||||
// - https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/
|
||||
// - https://pokechu22.github.io/Burger/1.20.4.html
|
||||
// - https://github.com/ViaVersion/Mappings/tree/main/mappings
|
||||
FILLED_MAP(protocolVersion -> {
|
||||
// Useful resources:
|
||||
// - https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/
|
||||
// - https://pokechu22.github.io/Burger/1.20.4.html
|
||||
// - https://github.com/ViaVersion/Mappings/tree/main/mappings
|
||||
switch (protocolVersion) {
|
||||
default:
|
||||
// 1.7-1.12.2
|
||||
return 358;
|
||||
// 1.13-1.13.1
|
||||
case MINECRAFT_1_13:
|
||||
case MINECRAFT_1_13_1:
|
||||
return 608;
|
||||
// 1.13.2
|
||||
case MINECRAFT_1_13_2:
|
||||
return 613;
|
||||
// 1.14-1.15.2
|
||||
case MINECRAFT_1_14:
|
||||
case MINECRAFT_1_14_1:
|
||||
case MINECRAFT_1_14_2:
|
||||
@@ -49,38 +49,49 @@ public enum ItemType {
|
||||
case MINECRAFT_1_15_1:
|
||||
case MINECRAFT_1_15_2:
|
||||
return 671;
|
||||
// 1.16-1.16.4
|
||||
case MINECRAFT_1_16:
|
||||
case MINECRAFT_1_16_1:
|
||||
case MINECRAFT_1_16_2:
|
||||
case MINECRAFT_1_16_3:
|
||||
case MINECRAFT_1_16_4:
|
||||
return 733;
|
||||
// 1.17-1.18.2
|
||||
case MINECRAFT_1_17:
|
||||
case MINECRAFT_1_17_1:
|
||||
case MINECRAFT_1_18:
|
||||
case MINECRAFT_1_18_2:
|
||||
return 847;
|
||||
// 1.19-1.19.1
|
||||
case MINECRAFT_1_19:
|
||||
case MINECRAFT_1_19_1:
|
||||
return 886;
|
||||
// 1.19.3
|
||||
case MINECRAFT_1_19_3:
|
||||
return 914;
|
||||
// 1.19.4
|
||||
case MINECRAFT_1_19_4:
|
||||
return 937;
|
||||
// 1.20-1.20.2
|
||||
case MINECRAFT_1_20:
|
||||
case MINECRAFT_1_20_2:
|
||||
return 941;
|
||||
// 1.20.3
|
||||
case MINECRAFT_1_20_3:
|
||||
return 979;
|
||||
// 1.20.5-1.21
|
||||
case MINECRAFT_1_20_5:
|
||||
case MINECRAFT_1_21:
|
||||
return 982;
|
||||
default:
|
||||
// 1.7-1.12.2
|
||||
return 358;
|
||||
}
|
||||
});
|
||||
|
||||
private final Function<ProtocolVersion, Integer> function;
|
||||
private final Function<ProtocolVersion, Integer> idFunction;
|
||||
|
||||
public int getId(final @NotNull ProtocolVersion protocolVersion) {
|
||||
return function.apply(protocolVersion);
|
||||
return idFunction.apply(protocolVersion);
|
||||
}
|
||||
}
|
||||
+63
-21
@@ -25,35 +25,19 @@ import java.util.function.Function;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum EntityType {
|
||||
// Useful resources:
|
||||
// - https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/
|
||||
// - https://pokechu22.github.io/Burger/1.20.4.html
|
||||
BOAT(protocolVersion -> {
|
||||
// Useful resources:
|
||||
// - https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/
|
||||
// - https://pokechu22.github.io/Burger/1.20.4.html
|
||||
switch (protocolVersion) {
|
||||
default:
|
||||
case MINECRAFT_1_7_2:
|
||||
case MINECRAFT_1_7_6:
|
||||
case MINECRAFT_1_8:
|
||||
case MINECRAFT_1_9:
|
||||
case MINECRAFT_1_9_1:
|
||||
case MINECRAFT_1_9_2:
|
||||
case MINECRAFT_1_9_4:
|
||||
case MINECRAFT_1_10:
|
||||
case MINECRAFT_1_11:
|
||||
case MINECRAFT_1_11_1:
|
||||
case MINECRAFT_1_12:
|
||||
case MINECRAFT_1_12_1:
|
||||
case MINECRAFT_1_12_2:
|
||||
case MINECRAFT_1_13:
|
||||
case MINECRAFT_1_13_1:
|
||||
case MINECRAFT_1_13_2:
|
||||
return 1;
|
||||
// 1.14-1.14.4
|
||||
case MINECRAFT_1_14:
|
||||
case MINECRAFT_1_14_1:
|
||||
case MINECRAFT_1_14_2:
|
||||
case MINECRAFT_1_14_3:
|
||||
case MINECRAFT_1_14_4:
|
||||
return 5;
|
||||
// 1.15-1.16.4
|
||||
case MINECRAFT_1_15:
|
||||
case MINECRAFT_1_15_1:
|
||||
case MINECRAFT_1_15_2:
|
||||
@@ -63,23 +47,81 @@ public enum EntityType {
|
||||
case MINECRAFT_1_16_3:
|
||||
case MINECRAFT_1_16_4:
|
||||
return 6;
|
||||
// 1.17-1.18.2
|
||||
case MINECRAFT_1_17:
|
||||
case MINECRAFT_1_17_1:
|
||||
case MINECRAFT_1_18:
|
||||
case MINECRAFT_1_18_2:
|
||||
return 7;
|
||||
// 1.19-1.19.3
|
||||
case MINECRAFT_1_19:
|
||||
case MINECRAFT_1_19_1:
|
||||
case MINECRAFT_1_19_3:
|
||||
return 8;
|
||||
// 1.19.4-1.20.3
|
||||
case MINECRAFT_1_19_4:
|
||||
case MINECRAFT_1_20:
|
||||
case MINECRAFT_1_20_2:
|
||||
case MINECRAFT_1_20_3:
|
||||
return 9;
|
||||
// 1.20.5-1.21
|
||||
case MINECRAFT_1_20_5:
|
||||
case MINECRAFT_1_21:
|
||||
return 10;
|
||||
// 1.7-1.13.2
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}),
|
||||
MINECART(protocolVersion -> {
|
||||
switch (protocolVersion) {
|
||||
// 1.14-1.14.4
|
||||
case MINECRAFT_1_14:
|
||||
case MINECRAFT_1_14_1:
|
||||
case MINECRAFT_1_14_2:
|
||||
case MINECRAFT_1_14_3:
|
||||
case MINECRAFT_1_14_4:
|
||||
return 41;
|
||||
// 1.15-1.15.2
|
||||
case MINECRAFT_1_15:
|
||||
case MINECRAFT_1_15_1:
|
||||
case MINECRAFT_1_15_2:
|
||||
return 42;
|
||||
// 1.16-1.16.4
|
||||
case MINECRAFT_1_16:
|
||||
case MINECRAFT_1_16_1:
|
||||
case MINECRAFT_1_16_2:
|
||||
case MINECRAFT_1_16_3:
|
||||
case MINECRAFT_1_16_4:
|
||||
return 45;
|
||||
// 1.17-1.18.2
|
||||
case MINECRAFT_1_17:
|
||||
case MINECRAFT_1_17_1:
|
||||
case MINECRAFT_1_18:
|
||||
case MINECRAFT_1_18_2:
|
||||
return 50;
|
||||
// 1.19-1.19.1
|
||||
case MINECRAFT_1_19:
|
||||
case MINECRAFT_1_19_1:
|
||||
return 53;
|
||||
// 1.19.3
|
||||
case MINECRAFT_1_19_3:
|
||||
return 54;
|
||||
// 1.19.4-1.20.2
|
||||
case MINECRAFT_1_19_4:
|
||||
case MINECRAFT_1_20:
|
||||
case MINECRAFT_1_20_2:
|
||||
return 64;
|
||||
// 1.20.3
|
||||
case MINECRAFT_1_20_3:
|
||||
return 65;
|
||||
// 1.20.5-1.21
|
||||
case MINECRAFT_1_20_5:
|
||||
case MINECRAFT_1_21:
|
||||
return 69;
|
||||
// 1.7-1.13.2
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Sonar Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.fallback.protocol.packets.play;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_8;
|
||||
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.readVarInt;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class AnimationPacket implements FallbackPacket {
|
||||
private int entityId = -1;
|
||||
private int hand = MAIN_HAND;
|
||||
private LegacyAnimationType type = LegacyAnimationType.SWING_ARM;
|
||||
|
||||
public static final int MAIN_HAND = 0;
|
||||
|
||||
@Override
|
||||
public void encode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
|
||||
if (protocolVersion.compareTo(MINECRAFT_1_8) < 0) {
|
||||
entityId = byteBuf.readInt();
|
||||
type = LegacyAnimationType.getById(byteBuf.readByte());
|
||||
} else if (protocolVersion.compareTo(MINECRAFT_1_8) > 0) {
|
||||
// Only 1.9+ clients have an offhand
|
||||
hand = readVarInt(byteBuf);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum LegacyAnimationType {
|
||||
NO_ANIMATION,
|
||||
SWING_ARM,
|
||||
DAMAGE_ANIMATION,
|
||||
LEAVE_BED,
|
||||
EAT_FOOD,
|
||||
CRITICAL_EFFECT,
|
||||
MAGIC_CRITICAL_EFFECT,
|
||||
UNKNOWN(102),
|
||||
CROUCH(104),
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
UNCROUCH(105);
|
||||
|
||||
private final int id;
|
||||
|
||||
LegacyAnimationType(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
LegacyAnimationType() {
|
||||
this.id = ordinal();
|
||||
}
|
||||
|
||||
public static LegacyAnimationType getById(int id) {
|
||||
if (id >= 0 && id <= 7) {
|
||||
return LegacyAnimationType.values()[id];
|
||||
}
|
||||
switch (id) {
|
||||
case 102:
|
||||
return UNKNOWN;
|
||||
case 104:
|
||||
return CROUCH;
|
||||
case 105:
|
||||
return UNCROUCH;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown type with id: " + id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Sonar Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.fallback.protocol.packets.play;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
|
||||
|
||||
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.writeVarInt;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class EntityAnimationPacket implements FallbackPacket {
|
||||
private int entityId;
|
||||
private Type type;
|
||||
|
||||
@Override
|
||||
public void encode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
|
||||
writeVarInt(byteBuf, entityId);
|
||||
byteBuf.writeByte(type.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
SWING_MAIN_ARM,
|
||||
HURT,
|
||||
WAKE_UP,
|
||||
// 1.9+?
|
||||
SWING_OFF_HAND, // Eat food on 1.7
|
||||
CRITICAL_HIT,
|
||||
MAGIC_CRITICAL_HIT
|
||||
// unknown (102), crouch (104), uncrouch(105) only exist on 1.7 and unused here
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Sonar Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.fallback.protocol.packets.play;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
|
||||
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class VehicleMovePacket implements FallbackPacket {
|
||||
private double x, y, z;
|
||||
private float yaw, pitch;
|
||||
|
||||
@Override
|
||||
public void encode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
|
||||
byteBuf.writeDouble(x);
|
||||
byteBuf.writeDouble(y);
|
||||
byteBuf.writeDouble(z);
|
||||
byteBuf.writeFloat(yaw);
|
||||
byteBuf.writeFloat(pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
|
||||
x = byteBuf.readDouble();
|
||||
y = byteBuf.readDouble();
|
||||
z = byteBuf.readDouble();
|
||||
yaw = byteBuf.readFloat();
|
||||
pitch = byteBuf.readFloat();
|
||||
}
|
||||
}
|
||||
+53
-3
@@ -22,9 +22,14 @@ import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.fallback.FallbackUser;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacketDecoder;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.play.AnimationPacket;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.play.EntityAnimationPacket;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.play.SetHeldItemPacket;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.play.TransactionPacket;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_8;
|
||||
import static xyz.jonesdev.sonar.common.fallback.protocol.FallbackPreparer.PLAYER_ENTITY_ID;
|
||||
|
||||
public final class FallbackProtocolSessionHandler extends FallbackSessionHandler {
|
||||
|
||||
public FallbackProtocolSessionHandler(final @NotNull FallbackUser user,
|
||||
@@ -39,6 +44,7 @@ public final class FallbackProtocolSessionHandler extends FallbackSessionHandler
|
||||
}
|
||||
|
||||
private final boolean forceCAPTCHA;
|
||||
private boolean waitingSwingArm, waitingSlotConfirm;
|
||||
private short expectedTransactionId;
|
||||
private int currentClientSlotId, expectedSlotId = -1;
|
||||
|
||||
@@ -50,7 +56,7 @@ public final class FallbackProtocolSessionHandler extends FallbackSessionHandler
|
||||
*/
|
||||
private void sendTransaction() {
|
||||
// Send a Transaction (Ping) packet with a random ID
|
||||
expectedTransactionId = (short) -(RANDOM.nextInt(Short.MAX_VALUE));
|
||||
expectedTransactionId = (short) -RANDOM.nextInt(Short.MAX_VALUE);
|
||||
user.write(new TransactionPacket(0, expectedTransactionId, false));
|
||||
}
|
||||
|
||||
@@ -72,6 +78,17 @@ public final class FallbackProtocolSessionHandler extends FallbackSessionHandler
|
||||
user.getChannel().flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses EntityAnimation packets to check for the excepted Animation (SwingArm) from the client.
|
||||
* <br>
|
||||
* <a href="https://wiki.vg/Protocol#Entity_Animation">Wiki.vg - EntityAnimation</a>
|
||||
* <a href="https://wiki.vg/Protocol#Swing_Arm">Wiki.vg - SwingArm</a>
|
||||
*/
|
||||
private void sendArmAnimation() {
|
||||
waitingSwingArm = true;
|
||||
user.write(new EntityAnimationPacket(PLAYER_ENTITY_ID, EntityAnimationPacket.Type.SWING_MAIN_ARM));
|
||||
}
|
||||
|
||||
private void markSuccess() {
|
||||
// Either send the player to the vehicle check,
|
||||
// send the player to the CAPTCHA, or finish the verification.
|
||||
@@ -108,9 +125,20 @@ public final class FallbackProtocolSessionHandler extends FallbackSessionHandler
|
||||
// https://wiki.vg/Bedrock_Protocol#Player_Hotbar
|
||||
if (user.isGeyser()) {
|
||||
markSuccess();
|
||||
} else if (waitingSlotConfirm) {
|
||||
waitingSlotConfirm = false;
|
||||
expectedSlotId = -1;
|
||||
// The player did not send duplicate packets, so they pass this check
|
||||
if (user.isGeyser()) {
|
||||
markSuccess();
|
||||
} else {
|
||||
sendArmAnimation();
|
||||
}
|
||||
} else {
|
||||
sendSetHeldItem();
|
||||
}
|
||||
|
||||
expectedTransactionId = 0;
|
||||
} else if (packet instanceof SetHeldItemPacket) {
|
||||
final SetHeldItemPacket heldItemPacket = (SetHeldItemPacket) packet;
|
||||
|
||||
@@ -125,11 +153,33 @@ public final class FallbackProtocolSessionHandler extends FallbackSessionHandler
|
||||
if (expectedSlotId != -1
|
||||
// Check if the slot ID matches the expected slot ID
|
||||
// This can false flag if a player spams these packets, which is why we don't fail for this
|
||||
&& slotId == expectedSlotId) {
|
||||
markSuccess();
|
||||
&& slotId == expectedSlotId
|
||||
// Make sure we actually want to send a transaction at this point in time
|
||||
&& !waitingSlotConfirm) {
|
||||
sendTransaction();
|
||||
waitingSlotConfirm = true;
|
||||
}
|
||||
|
||||
currentClientSlotId = slotId;
|
||||
} else if (packet instanceof AnimationPacket) {
|
||||
// Make sure we are awaiting an AnimationPacket packet
|
||||
if (waitingSwingArm) {
|
||||
final AnimationPacket animationPacket = (AnimationPacket) packet;
|
||||
checkState(animationPacket.getHand() == AnimationPacket.MAIN_HAND,
|
||||
"invalid hand " + animationPacket.getHand());
|
||||
// Check that the 1.7 client is responding to the correct entity id and animation type.
|
||||
if (user.getProtocolVersion().compareTo(MINECRAFT_1_8) < 0) {
|
||||
// Check entity id is player itself and if the player is sending the correct animation type
|
||||
if (animationPacket.getEntityId() == PLAYER_ENTITY_ID
|
||||
&& animationPacket.getType() == AnimationPacket.LegacyAnimationType.SWING_ARM) {
|
||||
markSuccess();
|
||||
waitingSwingArm = false;
|
||||
}
|
||||
} else {
|
||||
markSuccess();
|
||||
waitingSwingArm = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
-12
@@ -59,15 +59,17 @@ public final class FallbackVehicleSessionHandler extends FallbackSessionHandler
|
||||
|
||||
this.forceCAPTCHA = forceCAPTCHA;
|
||||
|
||||
// Send the necessary packets to mount the player on the vehicle
|
||||
user.delayedWrite(spawnEntity);
|
||||
user.delayedWrite(setPassengers);
|
||||
// Send the necessary packets to mount the player on the boat vehicle
|
||||
user.delayedWrite(spawnBoatEntity);
|
||||
user.delayedWrite(setBoatPassengers);
|
||||
user.getChannel().flush();
|
||||
}
|
||||
|
||||
private final boolean forceCAPTCHA;
|
||||
private int paddlePackets, inputPackets, positionPackets, rotationPackets;
|
||||
private boolean expectMovement;
|
||||
private int expectedTransactionId;
|
||||
private int paddlePackets, inputPackets, positionPackets, rotationPackets, vehicleMovePackets;
|
||||
private boolean expectMovement, inMinecart, waitingSpawnMinecartTransaction;
|
||||
private @NotNull FallbackPacket removeEntitiesPacket = removeBoatEntities;
|
||||
|
||||
private void markSuccess() {
|
||||
// Pass the player to the next best verification handler
|
||||
@@ -91,7 +93,11 @@ public final class FallbackVehicleSessionHandler extends FallbackSessionHandler
|
||||
checkState(y <= IN_AIR_Y_POSITION, "invalid y position");
|
||||
// Mark this check as successful if the player sent a few position packets
|
||||
if (positionPackets++ > Sonar.get().getConfig().getVerification().getVehicle().getMinimumPackets()) {
|
||||
markSuccess();
|
||||
if (user.isGeyser() || inMinecart) {
|
||||
markSuccess();
|
||||
} else {
|
||||
spawnMinecart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,20 +106,51 @@ public final class FallbackVehicleSessionHandler extends FallbackSessionHandler
|
||||
final int minimumPackets = Sonar.get().getConfig().getVerification().getVehicle().getMinimumPackets();
|
||||
if (paddlePackets > minimumPackets
|
||||
&& inputPackets > minimumPackets
|
||||
&& rotationPackets > minimumPackets) {
|
||||
&& rotationPackets > minimumPackets
|
||||
&& vehicleMovePackets > minimumPackets) {
|
||||
// Remove the entity
|
||||
// The next y coordinate the player will send is going
|
||||
// to be the vehicle spawn position (y 64 in this case).
|
||||
user.write(removeEntities);
|
||||
user.write(removeEntitiesPacket);
|
||||
// Listen for next movement packet(s)
|
||||
expectMovement = true;
|
||||
}
|
||||
rotationPackets++;
|
||||
}
|
||||
|
||||
private void spawnMinecart() {
|
||||
expectMovement = false;
|
||||
paddlePackets = inputPackets = positionPackets = rotationPackets = 0;
|
||||
waitingSpawnMinecartTransaction = true;
|
||||
expectedTransactionId = (short) -RANDOM.nextInt(Short.MAX_VALUE);
|
||||
// Use transaction packets to confirm that the entity has spawned
|
||||
user.delayedWrite(new TransactionPacket(0, expectedTransactionId, false));
|
||||
user.delayedWrite(spawnMinecartEntity);
|
||||
user.delayedWrite(setMinecartPassengers);
|
||||
user.getChannel().flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(final @NotNull FallbackPacket packet) {
|
||||
if (packet instanceof SetPlayerPositionRotationPacket) {
|
||||
if (packet instanceof TransactionPacket) {
|
||||
// Waiting for transaction to make sure the player is riding on the minecart and not on the boat
|
||||
if (waitingSpawnMinecartTransaction) {
|
||||
final TransactionPacket transaction = (TransactionPacket) packet;
|
||||
// Make sure random transactions aren't counted
|
||||
checkState(expectedTransactionId <= 0, "unexpected transaction");
|
||||
// Make sure the transaction was accepted
|
||||
// This must - by vanilla protocol - always be accepted
|
||||
checkState(transaction.isAccepted(), "didn't accept transaction");
|
||||
// Also check if the transaction ID matches the expected ID
|
||||
checkState(expectedTransactionId == transaction.getTransactionId(),
|
||||
"expected T ID " + expectedTransactionId + ", but got " + transaction.getTransactionId());
|
||||
|
||||
waitingSpawnMinecartTransaction = false;
|
||||
expectedTransactionId = 0;
|
||||
removeEntitiesPacket = removeMinecartEntities;
|
||||
inMinecart = true;
|
||||
}
|
||||
} else if (packet instanceof SetPlayerPositionRotationPacket) {
|
||||
if (expectMovement) {
|
||||
final SetPlayerPositionRotationPacket posRot = (SetPlayerPositionRotationPacket) packet;
|
||||
handleMovement(posRot.getY());
|
||||
@@ -128,7 +165,11 @@ public final class FallbackVehicleSessionHandler extends FallbackSessionHandler
|
||||
handleRotation();
|
||||
}
|
||||
} else if (packet instanceof PaddleBoatPacket) {
|
||||
checkState(!inMinecart, "invalid packet order (unexpected PaddleBoatPacket)");
|
||||
paddlePackets++;
|
||||
} else if (packet instanceof VehicleMovePacket) {
|
||||
checkState(!inMinecart, "invalid packet order (unexpected VehicleMovePacket)");
|
||||
vehicleMovePackets++;
|
||||
} else if (packet instanceof PlayerInputPacket && !expectMovement) {
|
||||
final PlayerInputPacket playerInput = (PlayerInputPacket) packet;
|
||||
|
||||
@@ -153,13 +194,16 @@ public final class FallbackVehicleSessionHandler extends FallbackSessionHandler
|
||||
"illegal packet order; r/i " + rotationPackets + "/" + inputPackets);
|
||||
}
|
||||
|
||||
// 1.8 and below do not have PaddleBoat packets,
|
||||
// so we simply exempt them from the PaddleBoat check.
|
||||
if (user.getProtocolVersion().compareTo(MINECRAFT_1_9) < 0) {
|
||||
// 1.8 and below do not have PaddleBoat packets, so we simply exempt them from the PaddleBoat check.
|
||||
// Clients don't send PaddleBoat & VehicleMovePacket packets while riding minecarts.
|
||||
if (user.getProtocolVersion().compareTo(MINECRAFT_1_9) < 0 || inMinecart) {
|
||||
paddlePackets++;
|
||||
vehicleMovePackets++;
|
||||
} else {
|
||||
checkState(paddlePackets >= inputPackets,
|
||||
"illegal packet order; i/p " + inputPackets + "/" + paddlePackets);
|
||||
checkState(vehicleMovePackets == inputPackets,
|
||||
"illegal packet order; i/v " + inputPackets + "/" + vehicleMovePackets);
|
||||
}
|
||||
inputPackets++;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user