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..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 @@ -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; @@ -382,31 +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) { + + 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(packet.getEntityId()); - if (npc != null) { - // call the event - switch (packet.getAction()) { - 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)); - 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); } } } 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(); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 25e3a9b..54ade43 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,8 +24,8 @@ fabricLoader = "0.18.4" fabricApi = "0.141.3+1.21.11" # platform extensions -packetEvents = "2.11.2" -protocolLib = "9417eee444" +packetEvents = "2.13.0" +protocolLib = "8eeb82f89d" [libraries]