26.1 Support (#568)

* Add 26.1 protocol versions

* Add 26.1 block state IDs

* Add 26.1 codec

* Add missing tags for 26.1

* Fix chunk data on 26.1

* Fix SetContainerSlotPacket on 26.1

* Fix map item type and components on 26.1

* Fix UpdateTimePacket

* Fix ChunkDataPacket for <26.1
This commit is contained in:
Jones authored and GitHub committed 2026-03-30 19:03:04 +02:00
1 parent 6ea9c1dcba
commit 37d294afe3
13 files changed
+241 -44

No files matched your search

@@ -75,7 +75,8 @@ public enum ProtocolVersion {
MINECRAFT_1_21_6(771, "1.21.6"),
MINECRAFT_1_21_7(772, "1.21.7"),
MINECRAFT_1_21_9(773, "1.21.9"),
MINECRAFT_1_21_11(774, "1.21.11");
MINECRAFT_1_21_11(774, "1.21.11"),
MINECRAFT_26_1(775, "26.1");
private final int protocol;
private final String name;
@@ -81,7 +81,8 @@ public enum BukkitServerVersion {
MINECRAFT_1_21_8,
MINECRAFT_1_21_9,
MINECRAFT_1_21_10,
MINECRAFT_1_21_11;
MINECRAFT_1_21_11,
MINECRAFT_26_1;
static final BukkitServerVersion[] REVERSED_VALUES;
@@ -23,6 +23,7 @@ import net.kyori.adventure.nbt.IntBinaryTag;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.jonesdev.sonar.api.Sonar;
import xyz.jonesdev.sonar.api.antibot.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.api.config.SonarConfiguration;
@@ -37,6 +38,7 @@ import xyz.jonesdev.sonar.common.protocol.dimension.DimensionType;
import xyz.jonesdev.sonar.common.protocol.entity.EntityType;
import xyz.jonesdev.sonar.common.protocol.item.ItemType;
import xyz.jonesdev.sonar.common.protocol.packets.configuration.RegistryDataPacket;
import xyz.jonesdev.sonar.common.protocol.packets.configuration.UpdateTagsPacket;
import xyz.jonesdev.sonar.common.protocol.packets.login.LoginSuccessPacket;
import xyz.jonesdev.sonar.common.protocol.packets.play.*;
import xyz.jonesdev.sonar.common.util.ComponentHolder;
@@ -98,6 +100,8 @@ public class SonarPacketPreparer {
public final SonarPacket[] REGISTRY_SYNC_1_21_4 = RegistryDataPacket.of(DimensionRegistry.CODEC_1_21_4);
public final SonarPacket[] REGISTRY_SYNC_1_21_5 = RegistryDataPacket.of(DimensionRegistry.CODEC_1_21_5);
public final SonarPacket[] REGISTRY_SYNC_1_21_11 = RegistryDataPacket.of(DimensionRegistry.CODEC_1_21_11);
public final SonarPacket[] REGISTRY_SYNC_26_1 = RegistryDataPacket.of(DimensionRegistry.CODEC_26_1);
public final SonarPacket TAGS_UPDATE_26_1 = UpdateTagsPacket.of(DimensionRegistry.TAGS_26_1);
public final SonarPacket START_WRITING_CHUNKS = new GameEventPacket(13, 0);
public final static SonarPacket INVALID_HELD_ITEM_SLOT = new SetHeldItemPacket(-1);
public final SonarPacket RANDOM_KEEP_ALIVE = new SonarPacketSnapshot(new KeepAlivePacket(RANDOM.nextInt()));
@@ -295,8 +299,17 @@ public class SonarPacketPreparer {
+ Sonar.get0().getConfig().getVerification().getMaxPacketCount();
}
public static @Nullable SonarPacket getTagsPacket(final @NotNull ProtocolVersion protocolVersion) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_1)) {
return TAGS_UPDATE_26_1;
}
return null; // apparently doesn't crash the client; we're safe... for now.
}
public static SonarPacket[] getRegistryPackets(final @NotNull ProtocolVersion protocolVersion) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_21_11)) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_1)) {
return REGISTRY_SYNC_26_1;
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_21_11)) {
return REGISTRY_SYNC_1_21_11;
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_21_5)) {
return REGISTRY_SYNC_1_21_5;
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.antibot.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.protocol.packets.configuration.FinishConfigurationPacket;
import xyz.jonesdev.sonar.common.protocol.packets.configuration.RegistryDataPacket;
import xyz.jonesdev.sonar.common.protocol.packets.configuration.UpdateTagsPacket;
import xyz.jonesdev.sonar.common.protocol.packets.handshake.HandshakePacket;
import xyz.jonesdev.sonar.common.protocol.packets.login.LoginAcknowledgedPacket;
import xyz.jonesdev.sonar.common.protocol.packets.login.LoginStartPacket;
@@ -75,6 +76,8 @@ public enum SonarPacketRegistry {
clientbound.register(RegistryDataPacket.class, RegistryDataPacket::new,
map(0x05, MINECRAFT_1_20_2, true),
map(0x07, MINECRAFT_1_20_5, true));
clientbound.register(UpdateTagsPacket.class, UpdateTagsPacket::new,
map(0x0D, MINECRAFT_1_20_5, true));
serverbound.register(ClientInformationPacket.class, ClientInformationPacket::new,
map(0x00, MINECRAFT_1_20_2, false));
@@ -109,7 +112,8 @@ public enum SonarPacketRegistry {
map(0x2B, MINECRAFT_1_20_5, true),
map(0x2C, MINECRAFT_1_21_2, true),
map(0x2B, MINECRAFT_1_21_5, true),
map(0x30, MINECRAFT_1_21_9, true));
map(0x30, MINECRAFT_1_21_9, true),
map(0x31, MINECRAFT_26_1, true));
// minecraft:keep_alive
clientbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x00, MINECRAFT_1_7_2, true),
@@ -128,7 +132,8 @@ public enum SonarPacketRegistry {
map(0x26, MINECRAFT_1_20_5, true),
map(0x27, MINECRAFT_1_21_2, true),
map(0x26, MINECRAFT_1_21_5, true),
map(0x2B, MINECRAFT_1_21_9, true));
map(0x2B, MINECRAFT_1_21_9, true),
map(0x2C, MINECRAFT_26_1, true));
// minecraft:disconnect
clientbound.register(DisconnectPacket.class, DisconnectPacket::new,
map(0x40, MINECRAFT_1_7_2, true),
@@ -166,7 +171,8 @@ public enum SonarPacketRegistry {
map(0x40, MINECRAFT_1_20_5, true),
map(0x42, MINECRAFT_1_21_2, true),
map(0x41, MINECRAFT_1_21_5, true),
map(0x46, MINECRAFT_1_21_9, true));
map(0x46, MINECRAFT_1_21_9, true),
map(0x48, MINECRAFT_26_1, true));
// minecraft:player_abilities
clientbound.register(PlayerAbilitiesPacket.class, PlayerAbilitiesPacket::new,
map(0x39, MINECRAFT_1_7_2, true),
@@ -186,7 +192,8 @@ public enum SonarPacketRegistry {
map(0x38, MINECRAFT_1_20_5, true),
map(0x3A, MINECRAFT_1_21_2, true),
map(0x39, MINECRAFT_1_21_5, true),
map(0x3E, MINECRAFT_1_21_9, true));
map(0x3E, MINECRAFT_1_21_9, true),
map(0x40, MINECRAFT_26_1, true));
// minecraft:level_chunk_with_light
clientbound.register(ChunkDataPacket.class, ChunkDataPacket::new,
map(0x21, MINECRAFT_1_7_2, true),
@@ -205,7 +212,8 @@ public enum SonarPacketRegistry {
map(0x27, MINECRAFT_1_20_5, true),
map(0x28, MINECRAFT_1_21_2, true),
map(0x27, MINECRAFT_1_21_5, true),
map(0x2C, MINECRAFT_1_21_9, true));
map(0x2C, MINECRAFT_1_21_9, true),
map(0x2D, MINECRAFT_26_1, true));
// minecraft:remove_entities
clientbound.register(RemoveEntitiesPacket.class, RemoveEntitiesPacket::new,
map(0x13, MINECRAFT_1_7_2, true),
@@ -227,7 +235,8 @@ public enum SonarPacketRegistry {
map(0x42, MINECRAFT_1_20_5, true),
map(0x47, MINECRAFT_1_21_2, true),
map(0x46, MINECRAFT_1_21_5, true),
map(0x4B, MINECRAFT_1_21_9, true));
map(0x4B, MINECRAFT_1_21_9, true),
map(0x4D, MINECRAFT_26_1, true));
// minecraft:set_passengers
clientbound.register(SetPassengersPacket.class, SetPassengersPacket::new,
map(0x1B, MINECRAFT_1_7_2, true),
@@ -246,7 +255,8 @@ public enum SonarPacketRegistry {
map(0x5F, MINECRAFT_1_20_5, true),
map(0x65, MINECRAFT_1_21_2, true),
map(0x64, MINECRAFT_1_21_5, true),
map(0x69, MINECRAFT_1_21_9, true));
map(0x69, MINECRAFT_1_21_9, true),
map(0x6B, MINECRAFT_26_1, true));
// minecraft:add_entity
clientbound.register(SpawnEntityPacket.class, SpawnEntityPacket::new,
map(0x0E, MINECRAFT_1_7_2, true),
@@ -270,7 +280,8 @@ public enum SonarPacketRegistry {
map(0x49, MINECRAFT_1_20_5, true),
map(0x4E, MINECRAFT_1_21_2, true),
map(0x4D, MINECRAFT_1_21_5, true),
map(0x52, MINECRAFT_1_21_9, true));
map(0x52, MINECRAFT_1_21_9, true),
map(0x54, MINECRAFT_26_1, true));
// minecraft:ping
clientbound.register(TransactionPacket.class, TransactionPacket::new,
map(0x32, MINECRAFT_1_7_2, true),
@@ -288,7 +299,8 @@ public enum SonarPacketRegistry {
map(0x35, MINECRAFT_1_20_5, true),
map(0x37, MINECRAFT_1_21_2, true),
map(0x36, MINECRAFT_1_21_5, true),
map(0x3B, MINECRAFT_1_21_9, true));
map(0x3B, MINECRAFT_1_21_9, true),
map(0x3D, MINECRAFT_26_1, true));
// minecraft:set_default_spawn_position
clientbound.register(SetDefaultSpawnPositionPacket.class, SetDefaultSpawnPositionPacket::new,
map(0x05, MINECRAFT_1_7_2, true),
@@ -309,7 +321,8 @@ public enum SonarPacketRegistry {
map(0x56, MINECRAFT_1_20_5, true),
map(0x5B, MINECRAFT_1_21_2, true),
map(0x5A, MINECRAFT_1_21_5, true),
map(0x5F, MINECRAFT_1_21_9, true));
map(0x5F, MINECRAFT_1_21_9, true),
map(0x61, MINECRAFT_26_1, true));
// minecraft:map_item_data
clientbound.register(MapDataPacket.class, MapDataPacket::new,
map(0x34, MINECRAFT_1_7_2, true),
@@ -327,7 +340,8 @@ public enum SonarPacketRegistry {
map(0x2C, MINECRAFT_1_20_5, true),
map(0x2D, MINECRAFT_1_21_2, true),
map(0x2C, MINECRAFT_1_21_5, true),
map(0x31, MINECRAFT_1_21_9, true));
map(0x31, MINECRAFT_1_21_9, true),
map(0x33, MINECRAFT_26_1, true));
// minecraft:container_set_slot
clientbound.register(SetContainerSlotPacket.class, SetContainerSlotPacket::new,
map(0x2F, MINECRAFT_1_7_2, true),
@@ -361,7 +375,8 @@ public enum SonarPacketRegistry {
map(0x5C, MINECRAFT_1_20_5, true),
map(0x61, MINECRAFT_1_21_2, true),
map(0x60, MINECRAFT_1_21_5, true),
map(0x65, MINECRAFT_1_21_9, true));
map(0x65, MINECRAFT_1_21_9, true),
map(0x67, MINECRAFT_26_1, true));
// minecraft:system_chat
clientbound.register(SystemChatPacket.class, SystemChatPacket::new,
map(0x02, MINECRAFT_1_7_2, true),
@@ -379,7 +394,8 @@ public enum SonarPacketRegistry {
map(0x6C, MINECRAFT_1_20_5, true),
map(0x73, MINECRAFT_1_21_2, true),
map(0x72, MINECRAFT_1_21_5, true),
map(0x77, MINECRAFT_1_21_9, true));
map(0x77, MINECRAFT_1_21_9, true),
map(0x79, MINECRAFT_26_1, true));
// minecraft:game_event
clientbound.register(GameEventPacket.class, GameEventPacket::new,
map(0x20, MINECRAFT_1_20_3, true),
@@ -391,7 +407,8 @@ public enum SonarPacketRegistry {
clientbound.register(TransferPacket.class, TransferPacket::new,
map(0x73, MINECRAFT_1_20_5, true),
map(0x7A, MINECRAFT_1_21_2, true),
map(0x7F, MINECRAFT_1_21_9, true));
map(0x7F, MINECRAFT_1_21_9, true),
map(0x81, MINECRAFT_26_1, true));
// minecraft:set_held_slot
clientbound.register(SetHeldItemPacket.class, SetHeldItemPacket::new,
map(0x09, MINECRAFT_1_7_2, true),
@@ -412,7 +429,8 @@ public enum SonarPacketRegistry {
map(0x53, MINECRAFT_1_20_5, true),
map(0x63, MINECRAFT_1_21_2, true),
map(0x62, MINECRAFT_1_21_5, true),
map(0x67, MINECRAFT_1_21_9, true));
map(0x67, MINECRAFT_1_21_9, true),
map(0x69, MINECRAFT_26_1, true));
// minecraft:animate
clientbound.register(EntityAnimationPacket.class, EntityAnimationPacket::new,
map(0x0B, MINECRAFT_1_7_2, true),
@@ -443,12 +461,14 @@ public enum SonarPacketRegistry {
map(0x64, MINECRAFT_1_20_5, true),
map(0x6B, MINECRAFT_1_21_2, true),
map(0x6A, MINECRAFT_1_21_5, true),
map(0x6F, MINECRAFT_1_21_9, true));
map(0x6F, MINECRAFT_1_21_9, true),
map(0x71, MINECRAFT_26_1, true));
// minecraft:client_tick_end
serverbound.register(ClientTickEndPacket.class, ClientTickEndPacket::new,
map(0x0B, MINECRAFT_1_21_2, false),
map(0x0C, MINECRAFT_1_21_6, false));
map(0x0C, MINECRAFT_1_21_6, false),
map(0x0D, MINECRAFT_26_1, false));
// minecraft:set_carried_item
serverbound.register(SetHeldItemPacket.class, SetHeldItemPacket::new,
map(0x09, MINECRAFT_1_7_2, false),
@@ -465,7 +485,8 @@ public enum SonarPacketRegistry {
map(0x2F, MINECRAFT_1_20_5, false),
map(0x31, MINECRAFT_1_21_2, false),
map(0x33, MINECRAFT_1_21_4, false),
map(0x34, MINECRAFT_1_21_6, false));
map(0x34, MINECRAFT_1_21_6, false),
map(0x35, MINECRAFT_26_1, false));
// minecraft:paddle_boat
serverbound.register(PaddleBoatPacket.class, PaddleBoatPacket::new,
map(0x11, MINECRAFT_1_9, false),
@@ -483,7 +504,8 @@ public enum SonarPacketRegistry {
map(0x1C, MINECRAFT_1_20_3, false),
map(0x1F, MINECRAFT_1_20_5, false),
map(0x21, MINECRAFT_1_21_2, false),
map(0x22, MINECRAFT_1_21_6, false));
map(0x22, MINECRAFT_1_21_6, false),
map(0x23, MINECRAFT_26_1, false));
// minecraft:player_input
serverbound.register(PlayerInputPacket.class, PlayerInputPacket::new,
map(0x0C, MINECRAFT_1_7_2, false),
@@ -502,7 +524,8 @@ public enum SonarPacketRegistry {
map(0x26, MINECRAFT_1_20_5, false),
map(0x28, MINECRAFT_1_21_2, false),
map(0x29, MINECRAFT_1_21_4, false),
map(0x2A, MINECRAFT_1_21_6, false));
map(0x2A, MINECRAFT_1_21_6, false),
map(0x26, MINECRAFT_26_1, false));
// minecraft:move_vehicle
serverbound.register(VehicleMovePacket.class, VehicleMovePacket::new,
map(0x10, MINECRAFT_1_9, false),
@@ -520,7 +543,8 @@ public enum SonarPacketRegistry {
map(0x1B, MINECRAFT_1_20_3, false),
map(0x1E, MINECRAFT_1_20_5, false),
map(0x20, MINECRAFT_1_21_2, false),
map(0x21, MINECRAFT_1_21_6, false));
map(0x21, MINECRAFT_1_21_6, false),
map(0x22, MINECRAFT_26_1, false));
// minecraft:chat
serverbound.register(SystemChatPacket.class, SystemChatPacket::new,
map(0x01, MINECRAFT_1_7_2, false),
@@ -533,7 +557,8 @@ public enum SonarPacketRegistry {
map(0x05, MINECRAFT_1_19_3, false),
map(0x06, MINECRAFT_1_20_5, false),
map(0x07, MINECRAFT_1_21_2, false),
map(0x08, MINECRAFT_1_21_6, false));
map(0x08, MINECRAFT_1_21_6, false),
map(0x09, MINECRAFT_26_1, false));
// minecraft:keep_alive
serverbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x00, MINECRAFT_1_7_2, false),
@@ -552,7 +577,8 @@ public enum SonarPacketRegistry {
map(0x15, MINECRAFT_1_20_3, false),
map(0x18, MINECRAFT_1_20_5, false),
map(0x1A, MINECRAFT_1_21_2, false),
map(0x1B, MINECRAFT_1_21_6, false));
map(0x1B, MINECRAFT_1_21_6, false),
map(0x1C, MINECRAFT_26_1, false));
// minecraft:client_information
serverbound.register(ClientInformationPacket.class, ClientInformationPacket::new,
map(0x15, MINECRAFT_1_7_2, false),
@@ -567,7 +593,8 @@ public enum SonarPacketRegistry {
map(0x09, MINECRAFT_1_20_2, false),
map(0x0A, MINECRAFT_1_20_5, false),
map(0x0C, MINECRAFT_1_21_2, false),
map(0x0D, MINECRAFT_1_21_6, false));
map(0x0D, MINECRAFT_1_21_6, false),
map(0x0E, MINECRAFT_26_1, false));
// minecraft:custom_payload
serverbound.register(PluginMessagePacket.class, PluginMessagePacket::new,
map(0x17, MINECRAFT_1_7_2, false),
@@ -584,7 +611,8 @@ public enum SonarPacketRegistry {
map(0x0F, MINECRAFT_1_20_2, false),
map(0x12, MINECRAFT_1_21, false),
map(0x14, MINECRAFT_1_21_2, false),
map(0x15, MINECRAFT_1_21_6, false));
map(0x15, MINECRAFT_1_21_6, false),
map(0x16, MINECRAFT_26_1, false));
// minecraft:move_player_status_only
serverbound.register(SetPlayerOnGround.class, SetPlayerOnGround::new,
map(0x03, MINECRAFT_1_7_2, false),
@@ -603,7 +631,8 @@ public enum SonarPacketRegistry {
map(0x1A, MINECRAFT_1_20_3, false),
map(0x1D, MINECRAFT_1_20_5, false),
map(0x1F, MINECRAFT_1_21_2, false),
map(0x20, MINECRAFT_1_21_6, false));
map(0x20, MINECRAFT_1_21_6, false),
map(0x21, MINECRAFT_26_1, false));
// minecraft:move_player_pos
serverbound.register(SetPlayerPositionPacket.class, SetPlayerPositionPacket::new,
map(0x04, MINECRAFT_1_7_2, false),
@@ -622,7 +651,8 @@ public enum SonarPacketRegistry {
map(0x17, MINECRAFT_1_20_3, false),
map(0x1A, MINECRAFT_1_20_5, false),
map(0x1C, MINECRAFT_1_21_2, false),
map(0x1D, MINECRAFT_1_21_6, false));
map(0x1D, MINECRAFT_1_21_6, false),
map(0x1E, MINECRAFT_26_1, false));
// minecraft:move_player_rot
serverbound.register(SetPlayerRotationPacket.class, SetPlayerRotationPacket::new,
map(0x05, MINECRAFT_1_7_2, false),
@@ -641,7 +671,8 @@ public enum SonarPacketRegistry {
map(0x19, MINECRAFT_1_20_3, false),
map(0x1C, MINECRAFT_1_20_5, false),
map(0x1E, MINECRAFT_1_21_2, false),
map(0x1F, MINECRAFT_1_21_6, false));
map(0x1F, MINECRAFT_1_21_6, false),
map(0x20, MINECRAFT_26_1, false));
// minecraft:move_player_pos_rot
serverbound.register(SetPlayerPositionRotationPacket.class, SetPlayerPositionRotationPacket::new,
map(0x06, MINECRAFT_1_7_2, false),
@@ -660,7 +691,8 @@ public enum SonarPacketRegistry {
map(0x18, MINECRAFT_1_20_3, false),
map(0x1B, MINECRAFT_1_20_5, false),
map(0x1D, MINECRAFT_1_21_2, false),
map(0x1E, MINECRAFT_1_21_6, false));
map(0x1E, MINECRAFT_1_21_6, false),
map(0x1F, MINECRAFT_26_1, false));
// minecraft:accept_teleportation
serverbound.register(ConfirmTeleportationPacket.class, ConfirmTeleportationPacket::new,
map(0x00, MINECRAFT_1_9, false));
@@ -682,7 +714,8 @@ public enum SonarPacketRegistry {
map(0x27, MINECRAFT_1_20_5, false),
map(0x29, MINECRAFT_1_21_2, false),
map(0x2B, MINECRAFT_1_21_4, false),
map(0x2C, MINECRAFT_1_21_6, false));
map(0x2C, MINECRAFT_1_21_6, false),
map(0x2D, MINECRAFT_26_1, false));
// minecraft:swing
serverbound.register(AnimationPacket.class, AnimationPacket::new,
map(0x0A, MINECRAFT_1_7_2, false),
@@ -700,7 +733,8 @@ public enum SonarPacketRegistry {
map(0x38, MINECRAFT_1_21_2, false),
map(0x3A, MINECRAFT_1_21_4, false),
map(0x3B, MINECRAFT_1_21_5, false),
map(0x3C, MINECRAFT_1_21_6, false));
map(0x3C, MINECRAFT_1_21_6, false),
map(0x3F, MINECRAFT_26_1, false));
}
};
@@ -77,7 +77,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 8173;
}
return 9250;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 9250;
}
return 9451;
}, protocolVersion -> (double) 0.75f),
TRAPDOOR(protocolVersion -> {
// We have to use wooden trapdoors for 1.7 since 1.7 doesn't have iron trapdoors
@@ -129,7 +132,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 11303;
}
return 12380;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 12380;
}
return 12582;
}, protocolVersion -> 0.1875),
END_PORTAL_FRAME(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -174,7 +180,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 8195;
}
return 9272;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 9272;
}
return 9473;
}, protocolVersion -> 0.8125),
DAYLIGHT_SENSOR(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -222,7 +231,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 10016;
}
return 11093;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 11093;
}
return 11295;
}, protocolVersion -> 0.375),
COBBLESTONE_WALL(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -267,7 +279,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 8706;
}
return 9783;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 9783;
}
return 9984;
}, protocolVersion -> 1.5),
STONE_SLABS(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -315,7 +330,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 12120;
}
return 13197;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 13197;
}
return 13399;
}, protocolVersion -> 0.5),
WHITE_CARPET(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -363,7 +381,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 11617;
}
return 12694;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 12694;
}
return 12896;
}, protocolVersion -> protocolVersion.compareTo(MINECRAFT_1_8) < 0 ? 0 : 0.0625);
private final Function<ProtocolVersion, Integer> id;
@@ -41,6 +41,8 @@ public final class DimensionRegistry {
public final CompoundBinaryTag CODEC_1_21_4;
public final CompoundBinaryTag CODEC_1_21_5;
public final CompoundBinaryTag CODEC_1_21_11;
public final CompoundBinaryTag CODEC_26_1;
public final CompoundBinaryTag TAGS_26_1;
static {
CODEC_1_16 = getCodec("codec_1_16.nbt");
@@ -56,6 +58,8 @@ public final class DimensionRegistry {
CODEC_1_21_4 = getCodec("codec_1_21_4.nbt");
CODEC_1_21_5 = getCodec("codec_1_21_5.nbt");
CODEC_1_21_11 = getCodec("codec_1_21_11.nbt");
CODEC_26_1 = getCodec("codec_26_1.nbt");
TAGS_26_1 = getCodec("tags_26_1.nbt");
}
private @NotNull CompoundBinaryTag getCodec(final @NotNull String fileName) {
@@ -82,7 +82,10 @@ public enum ItemType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_7)) {
return 1059;
}
return 1104;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 1104;
}
return 1105;
}, protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21)) {
return 26;
@@ -93,7 +96,10 @@ public enum ItemType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_9)) {
return 37;
}
return 44;
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 44;
}
return 46;
});
private final Function<ProtocolVersion, Integer> id;
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2026 Jones Development
*
* All rights reserved.
* This software is proprietary and cannot be copied, modified, or distributed without explicit permission.
*/
package xyz.jonesdev.sonar.common.protocol.packets.configuration;
import io.netty.buffer.ByteBuf;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;
import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.IntBinaryTag;
import net.kyori.adventure.nbt.ListBinaryTag;
import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.antibot.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.protocol.SonarPacket;
import xyz.jonesdev.sonar.common.protocol.SonarPacketSnapshot;
import xyz.jonesdev.sonar.common.util.ProtocolUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// If you want a decent solution, use Sonar 3.0 - I don't have the time to implement tags.
//
// Taken from
// https://github.com/BoomEaro/NanoLimbo/blob/feature/1.21.2/src/main/java/ua/nanit/limbo/protocol/packets/configuration/PacketUpdateTags.java
@ToString
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public final class UpdateTagsPacket implements SonarPacket {
private Map<String, Map<String, List<Integer>>> tags;
@Override
public void encode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
ProtocolUtil.writeVarInt(byteBuf, this.tags.size());
for (Map.Entry<String, Map<String, List<Integer>>> entry : this.tags.entrySet()) {
ProtocolUtil.writeString(byteBuf, entry.getKey());
Map<String, List<Integer>> subTags = entry.getValue();
ProtocolUtil.writeVarInt(byteBuf, subTags.size());
for (Map.Entry<String, List<Integer>> subEntry : subTags.entrySet()) {
ProtocolUtil.writeString(byteBuf, subEntry.getKey());
List<Integer> ids = subEntry.getValue();
ProtocolUtil.writeVarInt(byteBuf, ids.size());
for (int id : ids) {
ProtocolUtil.writeVarInt(byteBuf, id);
}
}
}
}
public static @NotNull SonarPacket of(@NotNull CompoundBinaryTag tags) {
Map<String, Map<String, List<Integer>>> tagsMap = new HashMap<>();
for (Map.Entry<String, ? extends BinaryTag> namedTag : tags) {
Map<String, List<Integer>> subTagsMap = new HashMap<>();
CompoundBinaryTag subTag = (CompoundBinaryTag) namedTag.getValue();
for (Map.Entry<String, ? extends BinaryTag> subNamedTag : subTag) {
List<Integer> idsList = new ArrayList<>();
ListBinaryTag ids = (ListBinaryTag) subNamedTag.getValue();
for (BinaryTag id : ids) {
idsList.add(((IntBinaryTag) id).value());
}
subTagsMap.put(subNamedTag.getKey(), idsList);
}
tagsMap.put(namedTag.getKey(), subTagsMap);
}
return new SonarPacketSnapshot(new UpdateTagsPacket(tagsMap));
}
@Override
public void decode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
throw new UnsupportedOperationException();
}
}
@@ -25,6 +25,7 @@ import lombok.ToString;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.LongArrayBinaryTag;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
import xyz.jonesdev.sonar.api.antibot.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.protocol.SonarPacket;
import xyz.jonesdev.sonar.common.util.ProtocolUtil;
@@ -111,7 +112,7 @@ public final class ChunkDataPacket implements SonarPacket {
// Since 1.21.5. The length of the long array of PaletteStorage no longer depends on the VarInt in the packet
// SingularPalette doesn't need to read any additional long array.
// So we'll remove suffix 0 as array length here. The cost of writing a palette has been reduced from 3 to 2 bytes.
final byte[] sectionData = protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_21_5) ? new byte[]{0, 0, 0, 0, 0, 0, 1, 0} : new byte[]{0, 0, 0, 0, 0, 1};
final byte[] sectionData = getSectionDataBytes(protocolVersion);
int count = 24;
ProtocolUtil.writeVarInt(byteBuf, sectionData.length * count);
@@ -141,6 +142,20 @@ public final class ChunkDataPacket implements SonarPacket {
}
}
private static byte @NonNull [] getSectionDataBytes(@NonNull ProtocolVersion protocolVersion) {
final byte[] sectionData;
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_1)) {
sectionData = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_21_5)) {
sectionData = new byte[]{0, 0, 0, 0, 0, 1};
} else {
sectionData = new byte[]{0, 0, 0, 0, 0, 0, 1, 0};
}
return sectionData;
}
@Override
public void decode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
throw new UnsupportedOperationException();
@@ -24,6 +24,7 @@ import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.antibot.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.protocol.SonarPacket;
import xyz.jonesdev.sonar.common.util.ProtocolUtil;
@Getter
@NoArgsConstructor
@@ -34,6 +35,17 @@ public final class UpdateTimePacket implements SonarPacket {
@Override
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_1)) {
// muck fojang
byteBuf.writeLong(timeOfDay);
ProtocolUtil.writeVarInt(byteBuf, 1);
ProtocolUtil.writeVarInt(byteBuf, 0); // dimension
ProtocolUtil.writeVarLong(byteBuf, timeOfDay);
byteBuf.writeFloat(0f); // partialTicks
byteBuf.writeFloat(tickDayTime ? 1f : 0f); // rate
return;
}
byteBuf.writeLong(worldAge);
byteBuf.writeLong(timeOfDay);
@@ -138,6 +138,11 @@ public final class LoginHandler extends VerificationHandler {
for (final SonarPacket packet : getRegistryPackets(user.getProtocolVersion())) {
user.delayedWrite(packet);
}
// Write the tags because Mojang decided to screw everyone over in 26.1.
final SonarPacket tags = getTagsPacket(user.getProtocolVersion());
if (tags != null) {
user.delayedWrite(tags);
}
// Write the FinishConfiguration packet to the buffer
user.delayedWrite(FinishConfigurationPacket.INSTANCE);
// Send all packets in one flush