From ed0f738f450dc554877512dfa875c0889843e8a3 Mon Sep 17 00:00:00 2001 From: ItsNature Date: Tue, 23 Dec 2025 18:31:30 +0100 Subject: [PATCH 1/5] Add `ApolloPlayerUseItemBucketEvent` API --- .github/workflows/deploy.yml | 2 +- .../world/ApolloPlayerUseItemBucketEvent.java | 73 ++++++++++++++++++ .../world/ApolloPlayerUseItemEvent.java | 2 +- .../raytrace/BlockHitResult.java | 64 ++++++++++++++++ .../packetenrichment/raytrace/Direction.java | 38 ++++++++++ .../raytrace/EntityHitResult.java | 56 ++++++++++++++ .../packetenrichment/raytrace/MissResult.java | 33 +++++++++ .../raytrace/RayTraceResult.java | 33 +++++++++ .../PacketEnrichmentImpl.java | 17 +++++ .../apollo/network/NetworkTypes.java | 74 +++++++++++++++++++ gradle/libs.versions.toml | 2 +- 11 files changed, 391 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java create mode 100644 api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/BlockHitResult.java create mode 100644 api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/Direction.java create mode 100644 api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/EntityHitResult.java create mode 100644 api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/MissResult.java create mode 100644 api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/RayTraceResult.java diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 344b9d67c..31dc44065 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,7 +41,7 @@ jobs: fi - name: Gradle Publish - if: "${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/') }}" + if: "${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/') || github.ref == 'refs/heads/feature/bucket-desync' }}" run: ./gradlew publish - name: Gradle Release diff --git a/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java b/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java new file mode 100644 index 000000000..8715cbbae --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java @@ -0,0 +1,73 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.event.packetenrichment.world; + +import com.lunarclient.apollo.event.Event; +import com.lunarclient.apollo.module.packetenrichment.PlayerInfo; +import com.lunarclient.apollo.module.packetenrichment.raytrace.RayTraceResult; +import com.lunarclient.apollo.player.ApolloPlayer; +import lombok.Value; + +/** + * Represents an event that is fired when a player uses a bucket (1.7 and 1.8). + * + * @since 1.2.2 + */ +@Value +public class ApolloPlayerUseItemBucketEvent implements Event { + + /** + * The player that sent the packet. + * + * @return the player + * @since 1.2.2 + */ + ApolloPlayer player; + + /** + * The {@code long} representing the unix timestamp + * when the packet was created. + * + * @return the unix timestamp + * @since 1.2.2 + */ + long instantiationTimeMs; + + /** + * The player's {@link PlayerInfo} information. + * + * @return the player info + * @since 1.2.2 + */ + PlayerInfo playerInfo; + + /** + * The player's {@link RayTraceResult}. + * + * @return the ray trace result + * @since 1.2.2 + */ + RayTraceResult rayTraceResult; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemEvent.java b/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemEvent.java index d878e2235..beb9e6ede 100644 --- a/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemEvent.java +++ b/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemEvent.java @@ -29,7 +29,7 @@ import lombok.Value; /** - * Represents an event that is when a player uses an item (1.16.1+). + * Represents an event that is fired when a player uses an item (1.16.1+). * * @since 1.0.7 */ diff --git a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/BlockHitResult.java b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/BlockHitResult.java new file mode 100644 index 000000000..6bd312c8b --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/BlockHitResult.java @@ -0,0 +1,64 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.packetenrichment.raytrace; + +import com.lunarclient.apollo.common.location.ApolloBlockLocation; +import com.lunarclient.apollo.common.location.ApolloLocation; +import lombok.Builder; +import lombok.Getter; + +/** + * Represents the block hit ray trace result. + * + * @since 1.2.2 + */ +@Getter +@Builder +public class BlockHitResult extends RayTraceResult { + + /** + * The exact hit {@link ApolloLocation} of the ray on the block. + * + * @return the hit location + * @since 1.2.2 + */ + ApolloLocation hitLocation; + + /** + * The {@link ApolloBlockLocation} of the block that was hit. + * + * @return the block location + * @since 1.2.2 + */ + ApolloBlockLocation blockLocation; + + /** + * The {@link Direction} from which the block was hit. + * + * @return the direction + * @since 1.2.2 + */ + Direction direction; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/Direction.java b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/Direction.java new file mode 100644 index 000000000..9b729b15c --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/Direction.java @@ -0,0 +1,38 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.packetenrichment.raytrace; + +/** + * Represents a direction in which a block was hit. + * + * @since 1.2.2 + */ +public enum Direction { + DOWN, + UP, + NORTH, + SOUTH, + WEST, + EAST +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/EntityHitResult.java b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/EntityHitResult.java new file mode 100644 index 000000000..030436b82 --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/EntityHitResult.java @@ -0,0 +1,56 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.packetenrichment.raytrace; + +import com.lunarclient.apollo.common.ApolloEntity; +import com.lunarclient.apollo.common.location.ApolloLocation; +import lombok.Builder; +import lombok.Getter; + +/** + * Represents the entity hit ray trace result. + * + * @since 1.2.2 + */ +@Getter +@Builder +public class EntityHitResult extends RayTraceResult { + + /** + * The exact hit {@link ApolloLocation} of the ray on the entity. + * + * @return the hit location + * @since 1.2.2 + */ + ApolloLocation hitLocation; + + /** + * The {@link ApolloEntity} that was hit. + * + * @return the entity ID + * @since 1.2.2 + */ + ApolloEntity entityId; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/MissResult.java b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/MissResult.java new file mode 100644 index 000000000..5c7f91bc3 --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/MissResult.java @@ -0,0 +1,33 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.packetenrichment.raytrace; + +/** + * Represents the missed ray trace result. + * + * @since 1.2.2 + */ +public class MissResult extends RayTraceResult { + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/RayTraceResult.java b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/RayTraceResult.java new file mode 100644 index 000000000..46eb2667d --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/raytrace/RayTraceResult.java @@ -0,0 +1,33 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2023 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.packetenrichment.raytrace; + +/** + * The abstract base class for ray trace results. + * + * @since 1.2.2 + */ +public abstract class RayTraceResult { + +} diff --git a/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java b/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java index de9d02472..25c679e9c 100644 --- a/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java +++ b/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java @@ -28,11 +28,13 @@ import com.lunarclient.apollo.event.packetenrichment.chat.ApolloPlayerChatCloseEvent; import com.lunarclient.apollo.event.packetenrichment.chat.ApolloPlayerChatOpenEvent; import com.lunarclient.apollo.event.packetenrichment.melee.ApolloPlayerAttackEvent; +import com.lunarclient.apollo.event.packetenrichment.world.ApolloPlayerUseItemBucketEvent; import com.lunarclient.apollo.event.packetenrichment.world.ApolloPlayerUseItemEvent; import com.lunarclient.apollo.network.NetworkTypes; import com.lunarclient.apollo.packetenrichment.v1.PlayerAttackMessage; import com.lunarclient.apollo.packetenrichment.v1.PlayerChatCloseMessage; import com.lunarclient.apollo.packetenrichment.v1.PlayerChatOpenMessage; +import com.lunarclient.apollo.packetenrichment.v1.PlayerUseItemBucketMessage; import com.lunarclient.apollo.packetenrichment.v1.PlayerUseItemMessage; /** @@ -109,6 +111,21 @@ private void onReceivePacket(ApolloReceivePacketEvent event) { throwable.printStackTrace(); } }); + + event.unpack(PlayerUseItemBucketMessage.class).ifPresent(packet -> { + ApolloPlayerUseItemBucketEvent playerUseItemBucketEvent = new ApolloPlayerUseItemBucketEvent( + event.getPlayer(), + NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), + NetworkTypes.fromProtobuf(packet.getPlayerInfo()), + NetworkTypes.fromProtobuf(packet.getRayTraceResult()) + ); + + EventBus.EventResult result = EventBus.getBus().post(playerUseItemBucketEvent); + + for (Throwable throwable : result.getThrowing()) { + throwable.printStackTrace(); + } + }); } } diff --git a/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java b/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java index 4987d74e7..304c0e043 100644 --- a/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java +++ b/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java @@ -37,6 +37,14 @@ import com.lunarclient.apollo.common.v1.EntityId; import com.lunarclient.apollo.common.v1.Uuid; import com.lunarclient.apollo.module.packetenrichment.PlayerInfo; +import com.lunarclient.apollo.module.packetenrichment.raytrace.BlockHitResult; +import com.lunarclient.apollo.module.packetenrichment.raytrace.Direction; +import com.lunarclient.apollo.module.packetenrichment.raytrace.EntityHitResult; +import com.lunarclient.apollo.module.packetenrichment.raytrace.MissResult; +import com.lunarclient.apollo.module.packetenrichment.raytrace.RayTraceResult; +import com.lunarclient.apollo.packetenrichment.v1.BlockHit; +import com.lunarclient.apollo.packetenrichment.v1.EntityHit; +import com.lunarclient.apollo.packetenrichment.v1.Miss; import java.awt.Color; import java.time.Duration; import java.util.UUID; @@ -226,6 +234,72 @@ public static PlayerInfo fromProtobuf(com.lunarclient.apollo.packetenrichment.v1 .build(); } + /** + * Converts a {@link RayTraceResult} object to a + * {@link com.lunarclient.apollo.packetenrichment.v1.RayTraceResult} proto message. + * + * @param object the ray trace result + * @return the proto ray trace result message + * @since 1.2.2 + */ + public static com.lunarclient.apollo.packetenrichment.v1.RayTraceResult toProtobuf(RayTraceResult object) { + com.lunarclient.apollo.packetenrichment.v1.RayTraceResult.Builder builder = com.lunarclient.apollo.packetenrichment.v1.RayTraceResult.newBuilder(); + + if (object instanceof BlockHitResult) { + BlockHitResult result = (BlockHitResult) object; + + BlockHit blockHit = BlockHit.newBuilder() + .setHitLocation(NetworkTypes.toProtobuf(result.getHitLocation())) + .setBlockLocation(NetworkTypes.toProtobuf(result.getBlockLocation())) + .setDirection(com.lunarclient.apollo.packetenrichment.v1.Direction.forNumber(result.getDirection().ordinal() + 1)) + .build(); + + builder.setBlock(blockHit); + } else if (object instanceof EntityHitResult) { + EntityHitResult result = (EntityHitResult) object; + + EntityHit entityHit = EntityHit.newBuilder() + .setHitLocation(NetworkTypes.toProtobuf(result.getHitLocation())) + .setEntityId(NetworkTypes.toProtobuf(result.getEntityId())) + .build(); + + builder.setEntity(entityHit); + } else { + builder.setMiss(Miss.getDefaultInstance()); + } + + return builder.build(); + } + + /** + * Converts a {@link com.lunarclient.apollo.packetenrichment.v1.RayTraceResult} + * proto message to a {@link RayTraceResult} object. + * + * @param message the ray trace result message + * @return the apollo ray trace result object + * @since 1.2.2 + */ + public static RayTraceResult fromProtobuf(com.lunarclient.apollo.packetenrichment.v1.RayTraceResult message) { + if (message.hasBlock()) { + BlockHit blockHitMessage = message.getBlock(); + + return BlockHitResult.builder() + .hitLocation(NetworkTypes.fromProtobuf(blockHitMessage.getHitLocation())) + .blockLocation(NetworkTypes.fromProtobuf(blockHitMessage.getBlockLocation())) + .direction(Direction.values()[blockHitMessage.getDirectionValue() - 1]) + .build(); + } else if (message.hasEntity()) { + EntityHit entityHitMessage = message.getEntity(); + + return EntityHitResult.builder() + .hitLocation(NetworkTypes.fromProtobuf(entityHitMessage.getHitLocation())) + .entityId(NetworkTypes.fromProtobuf(entityHitMessage.getEntityId())) + .build(); + } + + return new MissResult(); + } + /** * Converts an {@link ApolloLocation} object to an * {@link com.lunarclient.apollo.common.v1.Location} proto message. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4cf9b10b8..1a56e5582 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ geantyref = "1.3.11" idea = "1.1.7" jetbrains = "24.0.1" lombok = "1.18.38" -protobuf = "0.0.5" +protobuf = "0.0.6" gson = "2.10.1" shadow = "8.1.1" spotless = "6.13.0" From fa0baaab742986659a5cbd07c2d9e88c79abc5b7 Mon Sep 17 00:00:00 2001 From: ItsNature Date: Thu, 5 Feb 2026 03:17:50 +0100 Subject: [PATCH 2/5] Add additional Packet Enrichment config options for each packet --- .../PacketEnrichmentModule.java | 122 +++++++++++++- .../PacketEnrichmentImpl.java | 155 ++++++++++-------- 2 files changed, 205 insertions(+), 72 deletions(-) diff --git a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentModule.java b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentModule.java index de359ec6b..bf519e076 100644 --- a/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentModule.java +++ b/api/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentModule.java @@ -25,6 +25,9 @@ import com.lunarclient.apollo.module.ApolloModule; import com.lunarclient.apollo.module.ModuleDefinition; +import com.lunarclient.apollo.option.Option; +import com.lunarclient.apollo.option.SimpleOption; +import io.leangen.geantyref.TypeToken; import org.jetbrains.annotations.ApiStatus; /** @@ -36,8 +39,125 @@ @ModuleDefinition(id = "packet_enrichment", name = "PacketEnrichment") public abstract class PacketEnrichmentModule extends ApolloModule { + /** + * Controls whether the client sends an additional player attack packet to the server. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_ATTACK_PACKET = Option.builder() + .comment("Set to 'true' to have the client send an additional player attack packet to the server, otherwise 'false'.") + .node("player-attack", "send-packet").type(TypeToken.get(Boolean.class)) + .defaultValue(false).notifyClient().build(); + + /** + * Controls whether Apollo fires {@link com.lunarclient.apollo.event.packetenrichment.melee.ApolloPlayerAttackEvent} + * when the packet is received. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_ATTACK_EVENT = Option.builder() + .comment("If 'true', Apollo fires the player attack event on the main thread. Disable this and handle the packet yourself if you require asynchronous or off-thread processing.") + .node("player-attack", "fire-apollo-event").type(TypeToken.get(Boolean.class)) + .defaultValue(false).build(); + + /** + * Controls whether the client sends an additional player chat open packet to the server. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_CHAT_OPEN_PACKET = Option.builder() + .comment("Set to 'true' to have the client send an additional player chat open packet to the server, otherwise 'false'.") + .node("player-chat-open", "send-packet").type(TypeToken.get(Boolean.class)) + .defaultValue(false).notifyClient().build(); + + /** + * Controls whether Apollo fires {@link com.lunarclient.apollo.event.packetenrichment.chat.ApolloPlayerChatOpenEvent} + * when the packet is received. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_CHAT_OPEN_EVENT = Option.builder() + .comment("If 'true', Apollo fires the player chat open event on the main thread. Disable this and handle the packet yourself if you require asynchronous or off-thread processing.") + .node("player-chat-open", "fire-apollo-event").type(TypeToken.get(Boolean.class)) + .defaultValue(false).build(); + + /** + * Controls whether the client sends an additional player chat close packet to the server. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_CHAT_CLOSE_PACKET = Option.builder() + .comment("Set to 'true' to have the client send an additional player chat close packet to the server, otherwise 'false'.") + .node("player-chat-close", "send-packet").type(TypeToken.get(Boolean.class)) + .defaultValue(false).notifyClient().build(); + + /** + * Controls whether Apollo fires {@link com.lunarclient.apollo.event.packetenrichment.chat.ApolloPlayerChatCloseEvent} + * when the packet is received. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_CHAT_CLOSE_EVENT = Option.builder() + .comment("If 'true', Apollo fires the player chat close event on the main thread. Disable this and handle the packet yourself if you require asynchronous or off-thread processing.") + .node("player-chat-close", "fire-apollo-event").type(TypeToken.get(Boolean.class)) + .defaultValue(false).build(); + + /** + * Controls whether the client sends an additional player use item packet to the server. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_USE_ITEM_PACKET = Option.builder() + .comment("Set to 'true' to have the client send an additional player use item packet to the server, otherwise 'false'.") + .node("player-use-item", "send-packet").type(TypeToken.get(Boolean.class)) + .defaultValue(false).notifyClient().build(); + + /** + * Controls whether Apollo fires {@link com.lunarclient.apollo.event.packetenrichment.world.ApolloPlayerUseItemEvent} + * when the packet is received. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_USE_ITEM_EVENT = Option.builder() + .comment("If 'true', Apollo fires the player use item event on the main thread. Disable this and handle the packet yourself if you require asynchronous or off-thread processing.") + .node("player-use-item", "fire-apollo-event").type(TypeToken.get(Boolean.class)) + .defaultValue(false).build(); + + /** + * Controls whether the client sends an additional player use item bucket packet to the server. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_USE_ITEM_BUCKET_PACKET = Option.builder() + .comment("Set to 'true' to have the client send an additional player use item bucket packet to the server, otherwise 'false'.") + .node("player-use-item-bucket", "send-packet").type(TypeToken.get(Boolean.class)) + .defaultValue(false).notifyClient().build(); + + /** + * Controls whether Apollo fires {@link com.lunarclient.apollo.event.packetenrichment.world.ApolloPlayerUseItemBucketEvent} + * when the packet is received. + * + * @since 1.2.2 + */ + public static final SimpleOption PLAYER_USE_ITEM_BUCKET_EVENT = Option.builder() + .comment("If 'true', Apollo fires the player use item bucket event on the main thread. Disable this and handle the packet yourself if you require asynchronous or off-thread processing.") + .node("player-use-item-bucket", "fire-apollo-event").type(TypeToken.get(Boolean.class)) + .defaultValue(false).build(); + protected PacketEnrichmentModule() { - this.registerOptions(ApolloModule.ENABLE_OPTION_OFF); + this.registerOptions( + ApolloModule.ENABLE_OPTION_OFF, + PacketEnrichmentModule.PLAYER_ATTACK_PACKET, + PacketEnrichmentModule.PLAYER_ATTACK_EVENT, + PacketEnrichmentModule.PLAYER_CHAT_OPEN_PACKET, + PacketEnrichmentModule.PLAYER_CHAT_OPEN_EVENT, + PacketEnrichmentModule.PLAYER_CHAT_CLOSE_PACKET, + PacketEnrichmentModule.PLAYER_CHAT_CLOSE_EVENT, + PacketEnrichmentModule.PLAYER_USE_ITEM_PACKET, + PacketEnrichmentModule.PLAYER_USE_ITEM_EVENT, + PacketEnrichmentModule.PLAYER_USE_ITEM_BUCKET_PACKET, + PacketEnrichmentModule.PLAYER_USE_ITEM_BUCKET_EVENT + ); } } diff --git a/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java b/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java index 25c679e9c..1bfa2f92a 100644 --- a/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java +++ b/common/src/main/java/com/lunarclient/apollo/module/packetenrichment/PacketEnrichmentImpl.java @@ -31,6 +31,7 @@ import com.lunarclient.apollo.event.packetenrichment.world.ApolloPlayerUseItemBucketEvent; import com.lunarclient.apollo.event.packetenrichment.world.ApolloPlayerUseItemEvent; import com.lunarclient.apollo.network.NetworkTypes; +import com.lunarclient.apollo.option.Options; import com.lunarclient.apollo.packetenrichment.v1.PlayerAttackMessage; import com.lunarclient.apollo.packetenrichment.v1.PlayerChatCloseMessage; import com.lunarclient.apollo.packetenrichment.v1.PlayerChatOpenMessage; @@ -55,77 +56,89 @@ public PacketEnrichmentImpl() { } private void onReceivePacket(ApolloReceivePacketEvent event) { - event.unpack(PlayerAttackMessage.class).ifPresent(packet -> { - ApolloPlayerAttackEvent playerAttackEvent = new ApolloPlayerAttackEvent( - event.getPlayer(), - NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), - NetworkTypes.fromProtobuf(packet.getTargetInfo()), - NetworkTypes.fromProtobuf(packet.getAttackerInfo()), - packet.getDistance() - ); - - EventBus.EventResult result = EventBus.getBus().post(playerAttackEvent); - - for (Throwable throwable : result.getThrowing()) { - throwable.printStackTrace(); - } - }); - - event.unpack(PlayerChatOpenMessage.class).ifPresent(packet -> { - ApolloPlayerChatOpenEvent playerChatOpenEvent = new ApolloPlayerChatOpenEvent( - event.getPlayer(), - NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), - NetworkTypes.fromProtobuf(packet.getPlayerInfo())); - - EventBus.EventResult result = EventBus.getBus().post(playerChatOpenEvent); - - for (Throwable throwable : result.getThrowing()) { - throwable.printStackTrace(); - } - }); - - event.unpack(PlayerChatCloseMessage.class).ifPresent(packet -> { - ApolloPlayerChatCloseEvent playerChatCloseEvent = new ApolloPlayerChatCloseEvent( - event.getPlayer(), - NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), - NetworkTypes.fromProtobuf(packet.getPlayerInfo())); - - EventBus.EventResult result = EventBus.getBus().post(playerChatCloseEvent); - - for (Throwable throwable : result.getThrowing()) { - throwable.printStackTrace(); - } - }); - - event.unpack(PlayerUseItemMessage.class).ifPresent(packet -> { - ApolloPlayerUseItemEvent playerUseItemEvent = new ApolloPlayerUseItemEvent( - event.getPlayer(), - NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), - NetworkTypes.fromProtobuf(packet.getPlayerInfo()), - packet.getMainHand() - ); - - EventBus.EventResult result = EventBus.getBus().post(playerUseItemEvent); - - for (Throwable throwable : result.getThrowing()) { - throwable.printStackTrace(); - } - }); - - event.unpack(PlayerUseItemBucketMessage.class).ifPresent(packet -> { - ApolloPlayerUseItemBucketEvent playerUseItemBucketEvent = new ApolloPlayerUseItemBucketEvent( - event.getPlayer(), - NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), - NetworkTypes.fromProtobuf(packet.getPlayerInfo()), - NetworkTypes.fromProtobuf(packet.getRayTraceResult()) - ); - - EventBus.EventResult result = EventBus.getBus().post(playerUseItemBucketEvent); - - for (Throwable throwable : result.getThrowing()) { - throwable.printStackTrace(); - } - }); + Options options = this.getOptions(); + + if (options.get(PacketEnrichmentModule.PLAYER_CHAT_OPEN_EVENT)) { + event.unpack(PlayerAttackMessage.class).ifPresent(packet -> { + ApolloPlayerAttackEvent playerAttackEvent = new ApolloPlayerAttackEvent( + event.getPlayer(), + NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), + NetworkTypes.fromProtobuf(packet.getTargetInfo()), + NetworkTypes.fromProtobuf(packet.getAttackerInfo()), + packet.getDistance() + ); + + EventBus.EventResult result = EventBus.getBus().post(playerAttackEvent); + + for (Throwable throwable : result.getThrowing()) { + throwable.printStackTrace(); + } + }); + } + + if (options.get(PacketEnrichmentModule.PLAYER_CHAT_OPEN_EVENT)) { + event.unpack(PlayerChatOpenMessage.class).ifPresent(packet -> { + ApolloPlayerChatOpenEvent playerChatOpenEvent = new ApolloPlayerChatOpenEvent( + event.getPlayer(), + NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), + NetworkTypes.fromProtobuf(packet.getPlayerInfo())); + + EventBus.EventResult result = EventBus.getBus().post(playerChatOpenEvent); + + for (Throwable throwable : result.getThrowing()) { + throwable.printStackTrace(); + } + }); + } + + if (options.get(PacketEnrichmentModule.PLAYER_CHAT_CLOSE_EVENT)) { + event.unpack(PlayerChatCloseMessage.class).ifPresent(packet -> { + ApolloPlayerChatCloseEvent playerChatCloseEvent = new ApolloPlayerChatCloseEvent( + event.getPlayer(), + NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), + NetworkTypes.fromProtobuf(packet.getPlayerInfo())); + + EventBus.EventResult result = EventBus.getBus().post(playerChatCloseEvent); + + for (Throwable throwable : result.getThrowing()) { + throwable.printStackTrace(); + } + }); + } + + if (options.get(PacketEnrichmentModule.PLAYER_USE_ITEM_EVENT)) { + event.unpack(PlayerUseItemMessage.class).ifPresent(packet -> { + ApolloPlayerUseItemEvent playerUseItemEvent = new ApolloPlayerUseItemEvent( + event.getPlayer(), + NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), + NetworkTypes.fromProtobuf(packet.getPlayerInfo()), + packet.getMainHand() + ); + + EventBus.EventResult result = EventBus.getBus().post(playerUseItemEvent); + + for (Throwable throwable : result.getThrowing()) { + throwable.printStackTrace(); + } + }); + } + + if (options.get(PacketEnrichmentModule.PLAYER_USE_ITEM_BUCKET_EVENT)) { + event.unpack(PlayerUseItemBucketMessage.class).ifPresent(packet -> { + ApolloPlayerUseItemBucketEvent playerUseItemBucketEvent = new ApolloPlayerUseItemBucketEvent( + event.getPlayer(), + NetworkTypes.fromProtobuf(packet.getPacketInfo().getInstantiationTime()), + NetworkTypes.fromProtobuf(packet.getPlayerInfo()), + NetworkTypes.fromProtobuf(packet.getRayTraceResult()) + ); + + EventBus.EventResult result = EventBus.getBus().post(playerUseItemBucketEvent); + + for (Throwable throwable : result.getThrowing()) { + throwable.printStackTrace(); + } + }); + } } } From cb58fdfc8f7e67237746e8547e389ebf9f26318c Mon Sep 17 00:00:00 2001 From: ItsNature Date: Tue, 10 Feb 2026 19:30:57 +0100 Subject: [PATCH 3/5] Add docs for new packet enrichment options --- .../world/ApolloPlayerUseItemBucketEvent.java | 2 +- docs/developers/events.mdx | 16 +++++ docs/developers/modules/packetenrichment.mdx | 69 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java b/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java index 8715cbbae..a27c1395a 100644 --- a/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java +++ b/api/src/main/java/com/lunarclient/apollo/event/packetenrichment/world/ApolloPlayerUseItemBucketEvent.java @@ -63,7 +63,7 @@ public class ApolloPlayerUseItemBucketEvent implements Event { PlayerInfo playerInfo; /** - * The player's {@link RayTraceResult}. + * The result of the client's {@link RayTraceResult} for this bucket interaction. * * @return the ray trace result * @since 1.2.2 diff --git a/docs/developers/events.mdx b/docs/developers/events.mdx index f6af36f80..abeb8307e 100644 --- a/docs/developers/events.mdx +++ b/docs/developers/events.mdx @@ -252,6 +252,22 @@ _Called when the player uses an item (1.16.1+)._ +
+ApolloPlayerUseItemBucketEvent + +### ApolloPlayerUseItemBucketEvent + +_Called when the player uses a bucket (1.7 and 1.8)._ + +| Field | Description | +| ------------------------------- | --------------------------------------------------- | +| `ApolloPlayer player` | The Apollo player that sent the packet. | +| `long instantiationTimeMs` | The unix timestamp when the packet was created. | +| `PlayerInfo playerInfo` | The player's general information. | +| `RayTraceResult rayTraceResult` | The client ray trace result for the interaction. | + +
+ ## Integration ### Sample Code (Method 1) diff --git a/docs/developers/modules/packetenrichment.mdx b/docs/developers/modules/packetenrichment.mdx index ffa50b7c5..5edf9a5a5 100644 --- a/docs/developers/modules/packetenrichment.mdx +++ b/docs/developers/modules/packetenrichment.mdx @@ -7,6 +7,8 @@ import { Tab, Tabs } from 'nextra-theme-docs' The packet enrichment module provides servers with additional information about already existing packets and/or adds additional packets to provide servers with extra information about a player. +We have an open-source reference [plugin](https://github.com/LunarClient/apollo-bucket-desync-fix) that leverages the `PLAYER_USE_ITEM_BUCKET_PACKET` to eliminate water and lava bucket desync on 1.7 and 1.8. + This module is disabled by default, if you wish to use this module you will need to enable it in `config.yml`. @@ -27,6 +29,7 @@ The following events are related to the packet enrichment module, you can find m * `ApolloPlayerChatOpenEvent` * `ApolloPlayerAttackEvent` * `ApolloPlayerUseItemEvent` +* `ApolloPlayerUseItemBucketEvent` @@ -38,3 +41,69 @@ Visit [Apollo Serverbound packets](/apollo/developers/lightweight/protobuf/serve +## Available options + +- __`PLAYER_ATTACK_PACKET`__ + - Controls whether the client sends an additional player attack packet to the server. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_ATTACK_EVENT`__ + - Controls whether Apollo fires `ApolloPlayerAttackEvent` when the packet is received. + - Disable this and handle the packet yourself if you require asynchronous or off-thread processing. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_CHAT_OPEN_PACKET`__ + - Controls whether the client sends an additional player chat open packet to the server. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_CHAT_OPEN_EVENT`__ + - Controls whether Apollo fires `ApolloPlayerChatOpenEvent` when the packet is received. + - Disable this and handle the packet yourself if you require asynchronous or off-thread processing. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_CHAT_CLOSE_PACKET`__ + - Controls whether the client sends an additional player chat close packet to the server. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_CHAT_CLOSE_EVENT`__ + - Controls whether Apollo fires `ApolloPlayerChatCloseEvent` when the packet is received. + - Disable this and handle the packet yourself if you require asynchronous or off-thread processing. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_USE_ITEM_PACKET`__ + - Controls whether the client sends an additional player use item packet to the server. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_USE_ITEM_EVENT`__ + - Controls whether Apollo fires `ApolloPlayerUseItemEvent` when the packet is received. + - Disable this and handle the packet yourself if you require asynchronous or off-thread processing. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_USE_ITEM_BUCKET_PACKET`__ + - Controls whether the client sends an additional player use item bucket packet to the server. + - Values + - Type: `Boolean` + - Default: `false` + +- __`PLAYER_USE_ITEM_BUCKET_EVENT`__ + - Controls whether Apollo fires `ApolloPlayerUseItemBucketEvent` when the packet is received. + - Disable this and handle the packet yourself if you require asynchronous or off-thread processing. + - Values + - Type: `Boolean` + - Default: `false` From 15dde95250c07715e79941bc596f9243b145e912 Mon Sep 17 00:00:00 2001 From: ItsNature Date: Tue, 10 Feb 2026 19:36:56 +0100 Subject: [PATCH 4/5] Update apollo-protos version --- docs/developers/lightweight/protobuf/getting-started.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/developers/lightweight/protobuf/getting-started.mdx b/docs/developers/lightweight/protobuf/getting-started.mdx index 2304efe1c..467c0db9e 100644 --- a/docs/developers/lightweight/protobuf/getting-started.mdx +++ b/docs/developers/lightweight/protobuf/getting-started.mdx @@ -26,7 +26,7 @@ Available fields for each message, including their types, are available on the B com.lunarclient apollo-protos - 0.0.5 + 0.0.6 ``` @@ -41,7 +41,7 @@ Available fields for each message, including their types, are available on the B } dependencies { - api 'com.lunarclient:apollo-protos:0.0.5' + api 'com.lunarclient:apollo-protos:0.0.6' } ``` @@ -55,7 +55,7 @@ Available fields for each message, including their types, are available on the B } dependencies { - api("com.lunarclient:apollo-protos:0.0.5") + api("com.lunarclient:apollo-protos:0.0.6") } ``` From 61c685f5c6e9bc4409898fb9a04b22cfa785e13c Mon Sep 17 00:00:00 2001 From: ItsNature Date: Thu, 19 Feb 2026 19:20:03 +0100 Subject: [PATCH 5/5] Don't publish this branch anymore --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 31dc44065..344b9d67c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,7 +41,7 @@ jobs: fi - name: Gradle Publish - if: "${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/') || github.ref == 'refs/heads/feature/bucket-desync' }}" + if: "${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/') }}" run: ./gradlew publish - name: Gradle Release