From 310d45255e91f0c478cdde15643843cfb0ba2e43 Mon Sep 17 00:00:00 2001 From: 0utplay Date: Wed, 8 Apr 2026 18:46:58 +0200 Subject: [PATCH 1/5] feat: start mc 26.1.1 work --- .../protocol/PacketEventsPacketAdapter.java | 20 +++++++++++++++++-- gradle/libs.versions.toml | 4 ++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java index 518a79d..96f6e3a 100644 --- a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java +++ b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java @@ -384,14 +384,15 @@ public NpcUsePacketAdapter(@NotNull Platform p public void onPacketPlayReceive(@NotNull PacketPlayReceiveEvent event) { // check for an entity use packet Object player = event.getPlayer(); - if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) { + if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY + || event.getPacketType() == PacketType.Play.Client.ATTACK) { WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); // get the associated npc from the tracked entities Npc npc = this.platform.npcTracker().npcById(packet.getEntityId()); if (npc != null) { // call the event - switch (packet.getAction()) { + switch (findAction(event.getPacketType(), packet)) { case ATTACK: this.platform.eventManager().post(DefaultAttackNpcEvent.attackNpc(npc, player)); break; @@ -409,6 +410,21 @@ public void onPacketPlayReceive(@NotNull PacketPlayReceiveEvent event) { } } } + + private static @NotNull WrapperPlayClientInteractEntity.InteractAction findAction( + @NotNull PacketType.Play.Client packetType, + @NotNull WrapperPlayClientInteractEntity packet + ) { + if (packet.getServerVersion().isOlderThan(ServerVersion.V_26_1)) { + return packet.getAction(); + } + + if (packetType == PacketType.Play.Client.ATTACK) { + return WrapperPlayClientInteractEntity.InteractAction.ATTACK; + } + + return WrapperPlayClientInteractEntity.InteractAction.INTERACT; + } } private static final class Lazy { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 25e3a9b..84b86a1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ netty = "4.1.117.Final" # platform api versions sponge = "10.0.0" -paper = "1.21.11-R0.1-SNAPSHOT" +paper = "26.1.1.build.29-alpha" minestom = "2026.03.03-1.21.11" # fabric @@ -24,7 +24,7 @@ fabricLoader = "0.18.4" fabricApi = "0.141.3+1.21.11" # platform extensions -packetEvents = "2.11.2" +packetEvents = "2.12.0" protocolLib = "9417eee444" From e59ce4ad9a2c089ddf85cc555189a3775da900bf Mon Sep 17 00:00:00 2001 From: 0utplay Date: Thu, 9 Apr 2026 14:17:19 +0200 Subject: [PATCH 2/5] fix: protocollib interact & attack handling --- .../protocol/ProtocolLibPacketAdapter.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/ProtocolLibPacketAdapter.java b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/ProtocolLibPacketAdapter.java index e87bb48..101df1a 100644 --- a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/ProtocolLibPacketAdapter.java +++ b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/ProtocolLibPacketAdapter.java @@ -572,7 +572,10 @@ private static final class NpcUsePacketAdapter extends PacketAdapter { private final Platform platform; public NpcUsePacketAdapter(@NotNull Platform platform) { - super(PacketAdapter.params(platform.extension(), PacketType.Play.Client.USE_ENTITY).optionAsync()); + super(PacketAdapter.params( + platform.extension(), + PacketType.Play.Client.USE_ENTITY, + PacketType.Play.Client.ATTACK).optionAsync()); this.platform = platform; } @@ -590,7 +593,16 @@ public void onPacketReceiving(@NotNull PacketEvent event) { EnumWrappers.EntityUseAction action; EnumWrappers.Hand hand = EnumWrappers.Hand.MAIN_HAND; - if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove()) { + if (MinecraftVersion.v26_1.atOrAbove()) { + // mc 26.1: action does not exist anymore as there are two separate packets + if (packet.getType() == PacketType.Play.Client.ATTACK) { + // attack packets always result in an attack action with the main hand + action = EnumWrappers.EntityUseAction.ATTACK; + } else { + action = EnumWrappers.EntityUseAction.INTERACT; + hand = packet.getHands().read(0); + } + } else if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove()) { // mc 1.17: hand & action are now in an internal wrapper class WrappedEnumEntityUseAction useAction = packet.getEnumEntityUseActions().read(0); action = useAction.getAction(); From 1fda089ef02c32988d2ec66ccf57683574a059be Mon Sep 17 00:00:00 2001 From: 0utplay Date: Sat, 20 Jun 2026 17:51:39 +0200 Subject: [PATCH 3/5] fix: protocollib interact & attack handling --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 84b86a1..dc7c30e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ fabricApi = "0.141.3+1.21.11" # platform extensions packetEvents = "2.12.0" -protocolLib = "9417eee444" +protocolLib = "8eeb82f89d" [libraries] From 923231ff8cb1b5ac6574bdd1f1c83e722c3a58c8 Mon Sep 17 00:00:00 2001 From: 0utplay Date: Mon, 22 Jun 2026 18:19:10 +0200 Subject: [PATCH 4/5] fix: dings --- .../protocol/PacketEventsPacketAdapter.java | 41 ++++++++++--------- gradle/libs.versions.toml | 2 +- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java index 96f6e3a..09d9d67 100644 --- a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java +++ b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java @@ -64,6 +64,7 @@ import com.github.retrooper.packetevents.util.TimeStampMode; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; import com.github.retrooper.packetevents.wrapper.PacketWrapper; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientAttack; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation; @@ -386,19 +387,34 @@ public void onPacketPlayReceive(@NotNull PacketPlayReceiveEvent event) { Object player = event.getPlayer(); if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY || event.getPacketType() == PacketType.Play.Client.ATTACK) { - WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); + + WrapperPlayClientInteractEntity.InteractAction action; + int entityId; + + if (event.getPacketType() == PacketType.Play.Client.ATTACK) { + WrapperPlayClientAttack packet = new WrapperPlayClientAttack(event); + action = WrapperPlayClientInteractEntity.InteractAction.ATTACK; + entityId = packet.getEntityId(); + } else { + WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); + action = packet.getAction(); + entityId = packet.getEntityId(); + } // get the associated npc from the tracked entities - Npc npc = this.platform.npcTracker().npcById(packet.getEntityId()); + Npc npc = this.platform.npcTracker().npcById(entityId); if (npc != null) { // call the event - switch (findAction(event.getPacketType(), packet)) { + switch (action) { case ATTACK: this.platform.eventManager().post(DefaultAttackNpcEvent.attackNpc(npc, player)); break; case INTERACT: - InteractNpcEvent.Hand hand = Lazy.HAND_CONVERTER.get(packet.getHand()); - this.platform.eventManager().post(DefaultInteractNpcEvent.interactNpc(npc, player, hand)); + if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) { + WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); + InteractNpcEvent.Hand hand = Lazy.HAND_CONVERTER.get(packet.getHand()); + this.platform.eventManager().post(DefaultInteractNpcEvent.interactNpc(npc, player, hand)); + } break; default: // we don't handle INTERACT_AT as the client sends it alongside the interact packet (duplicate event call) @@ -410,21 +426,6 @@ public void onPacketPlayReceive(@NotNull PacketPlayReceiveEvent event) { } } } - - private static @NotNull WrapperPlayClientInteractEntity.InteractAction findAction( - @NotNull PacketType.Play.Client packetType, - @NotNull WrapperPlayClientInteractEntity packet - ) { - if (packet.getServerVersion().isOlderThan(ServerVersion.V_26_1)) { - return packet.getAction(); - } - - if (packetType == PacketType.Play.Client.ATTACK) { - return WrapperPlayClientInteractEntity.InteractAction.ATTACK; - } - - return WrapperPlayClientInteractEntity.InteractAction.INTERACT; - } } private static final class Lazy { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dc7c30e..54ade43 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ fabricLoader = "0.18.4" fabricApi = "0.141.3+1.21.11" # platform extensions -packetEvents = "2.12.0" +packetEvents = "2.13.0" protocolLib = "8eeb82f89d" From abf92ba180021546e600e45cd268fab6be53dc73 Mon Sep 17 00:00:00 2001 From: 0utplay Date: Mon, 22 Jun 2026 18:58:45 +0200 Subject: [PATCH 5/5] fix: dings --- .../protocol/PacketEventsPacketAdapter.java | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java index 09d9d67..ca8d223 100644 --- a/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java +++ b/bukkit/src/main/java/com/github/juliarn/npclib/bukkit/protocol/PacketEventsPacketAdapter.java @@ -383,47 +383,47 @@ public NpcUsePacketAdapter(@NotNull Platform p @Override public void onPacketPlayReceive(@NotNull PacketPlayReceiveEvent event) { - // check for an entity use packet Object player = event.getPlayer(); - if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY - || event.getPacketType() == PacketType.Play.Client.ATTACK) { - - WrapperPlayClientInteractEntity.InteractAction action; - int entityId; - - if (event.getPacketType() == PacketType.Play.Client.ATTACK) { - WrapperPlayClientAttack packet = new WrapperPlayClientAttack(event); - action = WrapperPlayClientInteractEntity.InteractAction.ATTACK; - entityId = packet.getEntityId(); - } else { - WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); - action = packet.getAction(); - entityId = packet.getEntityId(); + + int entityId; + InteractNpcEvent.Hand hand = null; + WrapperPlayClientInteractEntity.InteractAction action; + + if (event.getPacketType() == PacketType.Play.Client.ATTACK) { + WrapperPlayClientAttack packet = new WrapperPlayClientAttack(event); + action = WrapperPlayClientInteractEntity.InteractAction.ATTACK; + entityId = packet.getEntityId(); + } else if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) { + WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); + entityId = packet.getEntityId(); + hand = Lazy.HAND_CONVERTER.get(packet.getHand()); + + action = packet.getAction(); + if (packet.getServerVersion().isNewerThanOrEquals(ServerVersion.V_26_1)) { + action = WrapperPlayClientInteractEntity.InteractAction.INTERACT; } + } else { + return; + } - // get the associated npc from the tracked entities - Npc npc = this.platform.npcTracker().npcById(entityId); - if (npc != null) { - // call the event - switch (action) { - case ATTACK: - this.platform.eventManager().post(DefaultAttackNpcEvent.attackNpc(npc, player)); - break; - case INTERACT: - if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) { - WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); - InteractNpcEvent.Hand hand = Lazy.HAND_CONVERTER.get(packet.getHand()); - this.platform.eventManager().post(DefaultInteractNpcEvent.interactNpc(npc, player, hand)); - } - break; - default: - // we don't handle INTERACT_AT as the client sends it alongside the interact packet (duplicate event call) - break; - } - - // don't pass the packet to the server - event.setCancelled(true); + // get the associated npc from the tracked entities + Npc npc = this.platform.npcTracker().npcById(entityId); + if (npc != null) { + // call the event + switch (action) { + case ATTACK: + this.platform.eventManager().post(DefaultAttackNpcEvent.attackNpc(npc, player)); + break; + case INTERACT: + this.platform.eventManager().post(DefaultInteractNpcEvent.interactNpc(npc, player, hand)); + break; + default: + // we don't handle INTERACT_AT as the client sends it alongside the interact packet + break; } + + // don't pass the packet to the server + event.setCancelled(true); } } }