From a370f6e7b736ccb0680cbb04aa9c02bbb69ec087 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 20:13:42 +0200 Subject: [PATCH 1/9] Setup 1.21.2 server version and client version constants --- .../retrooper/packetevents/manager/server/ServerVersion.java | 2 +- .../retrooper/packetevents/protocol/player/ClientVersion.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/github/retrooper/packetevents/manager/server/ServerVersion.java b/api/src/main/java/com/github/retrooper/packetevents/manager/server/ServerVersion.java index d1aab94ac..4e08cf068 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/manager/server/ServerVersion.java +++ b/api/src/main/java/com/github/retrooper/packetevents/manager/server/ServerVersion.java @@ -50,7 +50,7 @@ public enum ServerVersion { //1.20 and 1.20.1 have the same protocol version. 1.20.3 and 1.20.4 have the same protocol version. 1.20.5 and 1.20.6 have the same protocol version V_1_20(763), V_1_20_1(763), V_1_20_2(764), V_1_20_3(765), V_1_20_4(765), V_1_20_5(766), V_1_20_6(766), //1.21 and 1.21.1 have the same protocol version - V_1_21(767), V_1_21_1(767), + V_1_21(767), V_1_21_1(767), V_1_21_2(768), //TODO UPDATE Add server version constant ERROR(-1, true); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/player/ClientVersion.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/player/ClientVersion.java index 7367c0faf..eee5aa27f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/player/ClientVersion.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/player/ClientVersion.java @@ -100,13 +100,14 @@ public enum ClientVersion { * 1.21 and 1.21.1 have the same protocol version. */ V_1_21(767), + V_1_21_2(768), //TODO UPDATE Add new protocol version field @Deprecated LOWER_THAN_SUPPORTED_VERSIONS(V_1_7_10.protocolVersion - 1, true), //TODO UPDATE Update HIGHER_THAN_SUPPORTED_VERSIONS field @Deprecated - HIGHER_THAN_SUPPORTED_VERSIONS(V_1_21.protocolVersion + 1, true), + HIGHER_THAN_SUPPORTED_VERSIONS(V_1_21_2.protocolVersion + 1, true), UNKNOWN(-1, true); From ce1baaad7aa33ba18dfab5c43afcd5dc97ab8554 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 20:13:52 +0200 Subject: [PATCH 2/9] Setup new 1.21.2 packet types --- .../protocol/packettype/PacketType.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/packettype/PacketType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/packettype/PacketType.java index 5f8729d12..4ff0af03f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/packettype/PacketType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/packettype/PacketType.java @@ -664,7 +664,12 @@ public enum Client implements PacketTypeCommon, ServerBoundPacket { // Added in 1.20.5 CHAT_COMMAND_UNSIGNED, COOKIE_RESPONSE, - DEBUG_SAMPLE_SUBSCRIPTION; + DEBUG_SAMPLE_SUBSCRIPTION, + + // added in 1.21.2 + CLIENT_TICK_END, + SELECT_BUNDLE_ITEM, + ; private static int INDEX = 0; private static final Map> PACKET_TYPE_ID_MAP = new HashMap<>(); @@ -901,7 +906,13 @@ public enum Server implements PacketTypeCommon, ClientBoundPacket { // added in 1.21 CUSTOM_REPORT_DETAILS, - SERVER_LINKS; + SERVER_LINKS, + + // added in 1.21.2 + MOVE_MINECART, + SET_CURSOR_ITEM, + SET_PLAYER_INVENTORY, + ; private static int INDEX = 0; private static final Map> PACKET_TYPE_ID_MAP = new HashMap<>(); From 83d925ead0a7f836a99dbda9edffbf0548df9e92 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 20:14:00 +0200 Subject: [PATCH 3/9] Implement most 1.21.2 packet wrapper changes --- .../retrooper/packetevents/util/Vector3d.java | 14 ++ .../packetevents/wrapper/PacketWrapper.java | 24 ++ .../client/WrapperPlayClientClickWindow.java | 4 +- .../WrapperPlayClientClickWindowButton.java | 7 +- .../WrapperPlayClientClientTickEnd.java | 35 +++ .../client/WrapperPlayClientCloseWindow.java | 4 +- .../WrapperPlayClientCraftRecipeRequest.java | 4 +- .../client/WrapperPlayClientEditBook.java | 51 ++-- ...WrapperPlayClientPlayerBlockPlacement.java | 31 ++- .../client/WrapperPlayClientPlayerFlying.java | 21 +- .../WrapperPlayClientSelectBundleItem.java | 73 ++++++ .../WrapperPlayClientSlotStateChange.java | 10 +- .../server/WrapperPlayServerCloseWindow.java | 17 +- .../WrapperPlayServerCraftRecipeResponse.java | 4 +- .../server/WrapperPlayServerExplosion.java | 225 ++++++++++++------ .../server/WrapperPlayServerJoinGame.java | 57 ++++- .../WrapperPlayServerMerchantOffers.java | 8 +- .../server/WrapperPlayServerMoveMinecart.java | 168 +++++++++++++ .../WrapperPlayServerOpenHorseWindow.java | 4 +- .../server/WrapperPlayServerOpenWindow.java | 14 +- .../WrapperPlayServerPlayerInfoUpdate.java | 71 +++++- .../play/server/WrapperPlayServerRespawn.java | 34 ++- .../server/WrapperPlayServerSetCooldown.java | 58 ++++- .../WrapperPlayServerSetCursorItem.java | 61 +++++ .../WrapperPlayServerSetPlayerInventory.java | 74 ++++++ .../play/server/WrapperPlayServerSetSlot.java | 4 +- .../server/WrapperPlayServerWindowItems.java | 6 +- .../WrapperPlayServerWindowProperty.java | 29 ++- 28 files changed, 951 insertions(+), 161 deletions(-) create mode 100644 api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClientTickEnd.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientSelectBundleItem.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMoveMinecart.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetCursorItem.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetPlayerInventory.java diff --git a/api/src/main/java/com/github/retrooper/packetevents/util/Vector3d.java b/api/src/main/java/com/github/retrooper/packetevents/util/Vector3d.java index b7c7fe97d..14049d62f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/util/Vector3d.java +++ b/api/src/main/java/com/github/retrooper/packetevents/util/Vector3d.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.util; import com.github.retrooper.packetevents.protocol.world.BlockFace; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; import java.util.Objects; @@ -99,6 +100,19 @@ public Vector3d(double[] array) { } } + public static Vector3d read(PacketWrapper wrapper) { + double x = wrapper.readDouble(); + double y = wrapper.readDouble(); + double z = wrapper.readDouble(); + return new Vector3d(x, y, z); + } + + public static void write(PacketWrapper wrapper, Vector3d vector) { + wrapper.writeDouble(vector.x); + wrapper.writeDouble(vector.y); + wrapper.writeDouble(vector.z); + } + public double getX() { return x; } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java index 2a843f5f1..09d895f6b 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java @@ -89,6 +89,7 @@ import com.github.retrooper.packetevents.protocol.world.WorldBlockPosition; import com.github.retrooper.packetevents.resources.ResourceLocation; import com.github.retrooper.packetevents.util.KnownPack; +import com.github.retrooper.packetevents.util.MathUtil; import com.github.retrooper.packetevents.util.StringUtil; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; @@ -1536,6 +1537,29 @@ public void writeMappedEntityOrDirect(Z entity, Writer< this.writeVarInt(id + 1); } + public int readContainerId() { + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + return this.readVarInt(); + } + return this.readUnsignedByte(); + } + + public void writeContainerId(int containerId) { + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.writeVarInt(containerId); + } else { + this.writeByte(containerId); + } + } + + public void writeRotation(float rotation) { + this.writeByte((byte) MathUtil.floor(rotation * 256f / 360f)); + } + + public float readRotation() { + return (float) (this.readByte() * 360) / 256f; + } + @FunctionalInterface public interface Reader extends Function, T> { } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindow.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindow.java index be0a40995..2e2da54af 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindow.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindow.java @@ -58,7 +58,7 @@ public WrapperPlayClientClickWindow(int windowID, Optional stateID, int @Override public void read() { boolean v1_17 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17); - this.windowID = readUnsignedByte(); + this.windowID = this.readContainerId(); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17_1)) { this.stateID = Optional.of(readVarInt()); } else { @@ -99,7 +99,7 @@ public void copy(WrapperPlayClientClickWindow wrapper) { @Override public void write() { boolean v1_17 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17); - writeByte(windowID); + this.writeContainerId(this.windowID); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17_1)) { writeVarInt(this.stateID.orElse(-1)); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindowButton.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindowButton.java index 90c191006..fd77457b7 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindowButton.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClickWindowButton.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.wrapper.play.client; import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.wrapper.PacketWrapper; @@ -41,13 +42,15 @@ public WrapperPlayClientClickWindowButton(int windowID, int buttonID) { @Override public void read() { - this.windowID = readByte(); + // TODO this changed from a byte to a var int, which version? + this.windowID = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) + ? this.readContainerId() : this.readVarInt(); this.buttonID = readByte(); } @Override public void write() { - writeByte(this.windowID); + this.writeContainerId(this.windowID); writeByte(this.buttonID); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClientTickEnd.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClientTickEnd.java new file mode 100644 index 000000000..22583c15b --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientClientTickEnd.java @@ -0,0 +1,35 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.wrapper.play.client; + +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +// the modern version of the idle packet +public class WrapperPlayClientClientTickEnd extends PacketWrapper { + + public WrapperPlayClientClientTickEnd(PacketReceiveEvent event) { + super(event); + } + + public WrapperPlayClientClientTickEnd() { + super(PacketType.Play.Client.CLIENT_TICK_END); + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCloseWindow.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCloseWindow.java index 1438d066e..81447939c 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCloseWindow.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCloseWindow.java @@ -36,12 +36,12 @@ public WrapperPlayClientCloseWindow(int windowID) { @Override public void read() { - this.windowID = readUnsignedByte(); + this.windowID = this.readContainerId(); } @Override public void write() { - writeByte(this.windowID); + this.writeContainerId(this.windowID); } @Override diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCraftRecipeRequest.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCraftRecipeRequest.java index a3d67fc55..11f5d603d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCraftRecipeRequest.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientCraftRecipeRequest.java @@ -50,7 +50,7 @@ public WrapperPlayClientCraftRecipeRequest(int windowId, @Nullable String recipe @Override public void read() { - this.windowId = readByte(); + this.windowId = this.readContainerId(); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_13)) { this.recipeModern = readString(); } else { @@ -61,7 +61,7 @@ public void read() { @Override public void write() { - writeByte(this.windowId); + this.writeContainerId(this.windowId); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_13)) { writeString(this.recipeModern); } else { diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientEditBook.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientEditBook.java index 8c5523bd9..d46ecd69d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientEditBook.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientEditBook.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.wrapper.play.client; import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.wrapper.PacketWrapper; import org.jetbrains.annotations.Nullable; @@ -27,10 +28,16 @@ import java.util.List; public class WrapperPlayClientEditBook extends PacketWrapper { + + @Deprecated public static final int MAX_BYTES_PER_CHAR = 4; - private static final int TITLE_MAX_CHARS = 128; - private static final int PAGE_MAX_CHARS = 8192; - private static final int AVERAGE_PAGES = 8; + + private static final int TITLE_MAX_CHARS_LEGACY = 128; + private static final int TITLE_MAX_CHARS = 32; + private static final int PAGE_MAX_CHARS_LEGACY = 8192; + private static final int PAGE_MAX_CHARS = 1024; + private static final int MAX_PAGES_LEGACY = 200; + private static final int MAX_PAGES = 100; private int slot; private List pages; @@ -49,23 +56,39 @@ public WrapperPlayClientEditBook(int slot, List pages, @Nullable String @Override public void read() { - slot = readVarInt(); - pages = new ArrayList<>(AVERAGE_PAGES); - int pagesSize = readVarInt(); - for (int i = 0; i < pagesSize; i++) { - pages.add(readString(PAGE_MAX_CHARS)); + boolean modernLimits = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2); + int pageLimit = modernLimits ? MAX_PAGES : MAX_PAGES_LEGACY; + int pageCharLimit = modernLimits ? PAGE_MAX_CHARS : PAGE_MAX_CHARS_LEGACY; + + this.slot = this.readVarInt(); + int pageCount = this.readVarInt(); + if (pageCount > pageLimit) { + throw new IllegalStateException("Page count " + pageCount + " is larger than limit of " + pageLimit); } - title = readOptional(reader -> reader.readString(TITLE_MAX_CHARS)); + this.pages = new ArrayList<>(pageCount); + for (int i = 0; i < pageCount; i++) { + this.pages.add(this.readString(pageCharLimit)); + } + this.title = this.readOptional(reader -> { + int titleLimit = modernLimits ? TITLE_MAX_CHARS : TITLE_MAX_CHARS_LEGACY; + return reader.readString(titleLimit); + }); } @Override public void write() { - writeVarInt(slot); - writeVarInt(pages.size()); - for (String page : pages) { - writeString(page, PAGE_MAX_CHARS); + boolean modernLimits = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2); + int pageCharLimit = modernLimits ? PAGE_MAX_CHARS : PAGE_MAX_CHARS_LEGACY; + + this.writeVarInt(this.slot); + this.writeVarInt(this.pages.size()); + for (String page : this.pages) { + this.writeString(page, pageCharLimit); } - writeOptional(title, (writer, innerTitle) -> writer.writeString(innerTitle, TITLE_MAX_CHARS)); + this.writeOptional(this.title, (writer, innerTitle) -> { + int titleLimit = modernLimits ? TITLE_MAX_CHARS : TITLE_MAX_CHARS_LEGACY; + writer.writeString(innerTitle, titleLimit); + }); } @Override diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerBlockPlacement.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerBlockPlacement.java index 001bec3d3..344fb5fca 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerBlockPlacement.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerBlockPlacement.java @@ -38,13 +38,24 @@ public class WrapperPlayClientPlayerBlockPlacement extends PacketWrapper itemStack; private Optional insideBlock; + private Optional worldBorderHit; private int sequence; public WrapperPlayClientPlayerBlockPlacement(PacketReceiveEvent event) { super(event); } - public WrapperPlayClientPlayerBlockPlacement(InteractionHand interactionHand, Vector3i blockPosition, BlockFace face, Vector3f cursorPosition, ItemStack itemStack, Boolean insideBlock, int sequence) { + public WrapperPlayClientPlayerBlockPlacement( + InteractionHand interactionHand, Vector3i blockPosition, BlockFace face, Vector3f cursorPosition, + ItemStack itemStack, Boolean insideBlock, int sequence + ) { + this(interactionHand, blockPosition, face, cursorPosition, itemStack, insideBlock, null, sequence); + } + + public WrapperPlayClientPlayerBlockPlacement( + InteractionHand interactionHand, Vector3i blockPosition, BlockFace face, Vector3f cursorPosition, + ItemStack itemStack, Boolean insideBlock, Boolean worldBorderHit, int sequence + ) { super(PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT); this.interactionHand = interactionHand; this.blockPosition = blockPosition; @@ -53,6 +64,7 @@ public WrapperPlayClientPlayerBlockPlacement(InteractionHand interactionHand, Ve this.cursorPosition = cursorPosition; this.itemStack = Optional.ofNullable(itemStack); this.insideBlock = Optional.ofNullable(insideBlock); + this.worldBorderHit = Optional.ofNullable(worldBorderHit); this.sequence = sequence; } @@ -68,6 +80,9 @@ public void read() { cursorPosition = new Vector3f(readFloat(), readFloat(), readFloat()); insideBlock = Optional.of(readBoolean()); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19)) { + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.worldBorderHit = Optional.of(this.readBoolean()); + } sequence = readVarInt(); } } else { @@ -106,6 +121,9 @@ public void write() { writeFloat(cursorPosition.z); writeBoolean(insideBlock.orElse(false)); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19)) { + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.writeBoolean(this.worldBorderHit.orElse(false)); + } writeVarInt(sequence); } } else { @@ -145,6 +163,7 @@ public void copy(WrapperPlayClientPlayerBlockPlacement wrapper) { cursorPosition = wrapper.cursorPosition; itemStack = wrapper.itemStack; insideBlock = wrapper.insideBlock; + worldBorderHit = wrapper.worldBorderHit; sequence = wrapper.sequence; } @@ -201,13 +220,21 @@ public void setItemStack(Optional itemStack) { } public Optional getInsideBlock() { - return insideBlock; + return this.insideBlock != null ? this.insideBlock : Optional.empty(); } public void setInsideBlock(Optional insideBlock) { this.insideBlock = insideBlock; } + public Optional getWorldBorderHit() { + return this.worldBorderHit != null ? this.worldBorderHit : Optional.empty(); + } + + public void setWorldBorderHit(Optional worldBorderHit) { + this.worldBorderHit = worldBorderHit; + } + public int getSequence() { return sequence; } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerFlying.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerFlying.java index 6e2b61189..48e828073 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerFlying.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientPlayerFlying.java @@ -31,6 +31,7 @@ public class WrapperPlayClientPlayerFlying extends PacketWrapper. + */ + +package com.github.retrooper.packetevents.wrapper.play.client; + +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class WrapperPlayClientSelectBundleItem extends PacketWrapper { + + private int slotId; + private int selectedItemIndex; + + public WrapperPlayClientSelectBundleItem(PacketReceiveEvent event) { + super(event); + } + + public WrapperPlayClientSelectBundleItem(int slotId, int selectedItemIndex) { + super(PacketType.Play.Client.SELECT_BUNDLE_ITEM); + this.slotId = slotId; + this.selectedItemIndex = selectedItemIndex; + } + + @Override + public void read() { + this.slotId = this.readVarInt(); + this.selectedItemIndex = this.readVarInt(); + } + + @Override + public void write() { + this.writeVarInt(this.slotId); + this.writeVarInt(this.selectedItemIndex); + } + + @Override + public void copy(WrapperPlayClientSelectBundleItem wrapper) { + this.slotId = wrapper.slotId; + this.selectedItemIndex = wrapper.selectedItemIndex; + } + + public int getSlotId() { + return this.slotId; + } + + public void setSlotId(int slotId) { + this.slotId = slotId; + } + + public int getSelectedItemIndex() { + return this.selectedItemIndex; + } + + public void setSelectedItemIndex(int selectedItemIndex) { + this.selectedItemIndex = selectedItemIndex; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientSlotStateChange.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientSlotStateChange.java index 9f0cc8714..407e4a64b 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientSlotStateChange.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/client/WrapperPlayClientSlotStateChange.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.wrapper.play.client; import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.wrapper.PacketWrapper; @@ -42,14 +43,19 @@ public WrapperPlayClientSlotStateChange(int slot, int windowId, boolean state) { @Override public void read() { this.slot = this.readVarInt(); - this.windowId = this.readVarInt(); + this.windowId = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) + ? this.readContainerId() : this.readVarInt(); this.state = this.readBoolean(); } @Override public void write() { this.writeVarInt(this.slot); - this.writeVarInt(this.windowId); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.writeContainerId(this.windowId); + } else { + this.writeVarInt(this.windowId); + } this.writeBoolean(this.state); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCloseWindow.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCloseWindow.java index 84228c491..f7c3f9d85 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCloseWindow.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCloseWindow.java @@ -23,12 +23,17 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper; public class WrapperPlayServerCloseWindow extends PacketWrapper { + private int windowId; public WrapperPlayServerCloseWindow(PacketSendEvent event) { super(event); } + public WrapperPlayServerCloseWindow() { + this(0); + } + public WrapperPlayServerCloseWindow(int id) { super(PacketType.Play.Server.CLOSE_WINDOW); this.windowId = id; @@ -36,12 +41,12 @@ public WrapperPlayServerCloseWindow(int id) { @Override public void read() { - this.windowId = readUnsignedByte(); + this.windowId = this.readContainerId(); } @Override public void write() { - writeByte(windowId); + this.writeContainerId(this.windowId); } @Override @@ -50,17 +55,15 @@ public void copy(WrapperPlayServerCloseWindow wrapper) { } /** - * @deprecated Window ID is ignored by the client on all versions. + * Note: Window ID is ignored by the client on all versions. */ - @Deprecated public int getWindowId() { - return windowId; + return this.windowId; } /** - * @deprecated Window ID is ignored by the client on all versions. + * Note: Window ID is ignored by the client on all versions. */ - @Deprecated public void setWindowId(int windowId) { this.windowId = windowId; } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCraftRecipeResponse.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCraftRecipeResponse.java index 30387c839..5a436e166 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCraftRecipeResponse.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerCraftRecipeResponse.java @@ -47,7 +47,7 @@ public WrapperPlayServerCraftRecipeResponse(int windowId, @Nullable String recip @Override public void read() { - this.windowId = readByte(); + this.windowId = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) ? this.readContainerId() : this.readByte(); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_13)) { this.recipeModern = readString(); } else { @@ -57,7 +57,7 @@ public void read() { @Override public void write() { - writeByte(this.windowId); + this.writeContainerId(this.windowId); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_13)) { writeString(this.recipeModern); } else { diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerExplosion.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerExplosion.java index 66cd921f2..c5cde2b58 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerExplosion.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerExplosion.java @@ -24,27 +24,29 @@ import com.github.retrooper.packetevents.protocol.particle.Particle; import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.protocol.sound.Sound; +import com.github.retrooper.packetevents.protocol.sound.Sounds; import com.github.retrooper.packetevents.protocol.sound.StaticSound; import com.github.retrooper.packetevents.resources.ResourceLocation; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3f; import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.PacketWrapper; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; public class WrapperPlayServerExplosion extends PacketWrapper { + private Vector3d position; - private float strength; - //Chunk posiitons? - private List records; - private Vector3f playerMotion; - - private Particle smallExplosionParticles; - private Particle largeExplosionParticles; - private BlockInteraction blockInteraction; + private float strength; // removed in 1.21.2 + private List records; // removed in 1.21.2 + private @Nullable Vector3d knockback; // optional since 1.21.2 + + private Particle smallParticle; // removed in 1.21.2 + private Particle particle; + private BlockInteraction blockInteraction; // removed in 1.21.2 private Sound explosionSound; public WrapperPlayServerExplosion(PacketSendEvent event) { @@ -65,20 +67,48 @@ public WrapperPlayServerExplosion(Vector3d position, float strength, List records, Vector3f playerMotion, - Particle smallExplosionParticles, Particle largeExplosionParticles, + Particle smallParticle, Particle particle, + BlockInteraction blockInteraction, Sound explosionSound) { + this(position, strength, records, new Vector3d(playerMotion.x, playerMotion.y, playerMotion.z), + smallParticle, particle, blockInteraction, explosionSound); + } + + public WrapperPlayServerExplosion(Vector3d position, float strength, List records, Vector3d playerMotion, + Particle smallParticle, Particle particle, BlockInteraction blockInteraction, Sound explosionSound) { super(PacketType.Play.Server.EXPLOSION); this.position = position; this.strength = strength; this.records = records; - this.playerMotion = playerMotion; - this.smallExplosionParticles = smallExplosionParticles; - this.largeExplosionParticles = largeExplosionParticles; + this.knockback = playerMotion; + this.smallParticle = smallParticle; + this.particle = particle; this.blockInteraction = blockInteraction; this.explosionSound = explosionSound; } + public WrapperPlayServerExplosion( + Vector3d position, + @Nullable Vector3d playerMotion + ) { + this(position, playerMotion, + new Particle<>(ParticleTypes.EXPLOSION_EMITTER), + Sounds.ENTITY_GENERIC_EXPLODE); + } + + public WrapperPlayServerExplosion( + Vector3d position, @Nullable Vector3d playerMotion, + Particle particle, Sound explosionSound + ) { + super(PacketType.Play.Server.EXPLOSION); + this.position = position; + this.knockback = playerMotion; + this.particle = particle; + this.explosionSound = explosionSound; + } + @Override public void read() { if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19_3)) { @@ -86,35 +116,42 @@ public void read() { } else { position = new Vector3d(readFloat(), readFloat(), readFloat()); } - strength = readFloat(); - int recordsLength = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17) ? readVarInt() : readInt(); - records = new ArrayList<>(recordsLength); - - Vector3i floor = toFloor(position); - - for (int i = 0; i < recordsLength; i++) { - int chunkPosX = readByte() + floor.getX(); - int chunkPosY = readByte() + floor.getY(); - int chunkPosZ = readByte() + floor.getZ(); - records.add(new Vector3i(chunkPosX, chunkPosY, chunkPosZ)); - } + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + // this packet has been basically completely emptied with 1.21.2 + this.knockback = this.readOptional(Vector3d::read); + this.particle = Particle.read(this); + this.explosionSound = Sound.read(this); + } else { + strength = readFloat(); + int recordsLength = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17) ? readVarInt() : readInt(); + records = new ArrayList<>(recordsLength); - float motX = readFloat(); - float motY = readFloat(); - float motZ = readFloat(); - playerMotion = new Vector3f(motX, motY, motZ); + Vector3i floor = toFloor(position); - if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_3)) { - this.blockInteraction = BlockInteraction.values()[this.readVarInt()]; - this.smallExplosionParticles = Particle.read(this); - this.largeExplosionParticles = Particle.read(this); + for (int i = 0; i < recordsLength; i++) { + int chunkPosX = readByte() + floor.getX(); + int chunkPosY = readByte() + floor.getY(); + int chunkPosZ = readByte() + floor.getZ(); + records.add(new Vector3i(chunkPosX, chunkPosY, chunkPosZ)); + } - if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5)) { - this.explosionSound = Sound.read(this); - } else { - ResourceLocation explosionSoundKey = this.readIdentifier(); - Float explosionSoundRange = this.readOptional(PacketWrapper::readFloat); - this.explosionSound = new StaticSound(explosionSoundKey, explosionSoundRange); + float motX = readFloat(); + float motY = readFloat(); + float motZ = readFloat(); + knockback = new Vector3d(motX, motY, motZ); + + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_3)) { + this.blockInteraction = BlockInteraction.values()[this.readVarInt()]; + this.smallParticle = Particle.read(this); + this.particle = Particle.read(this); + + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5)) { + this.explosionSound = Sound.read(this); + } else { + ResourceLocation explosionSoundKey = this.readIdentifier(); + Float explosionSoundRange = this.readOptional(PacketWrapper::readFloat); + this.explosionSound = new StaticSound(explosionSoundKey, explosionSoundRange); + } } } } @@ -130,36 +167,43 @@ public void write() { writeFloat((float) position.getY()); writeFloat((float) position.getZ()); } - writeFloat(strength); - - if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17)) { - writeVarInt(records.size()); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + // this packet has been basically completely emptied with 1.21.2 + this.writeOptional(this.knockback, Vector3d::write); + Particle.write(this, this.particle); + Sound.write(this, this.explosionSound); } else { - writeInt(records.size()); - } + writeFloat(strength); - Vector3i floor = toFloor(position); - - for (Vector3i record : records) { - writeByte(record.x - floor.getX()); - writeByte(record.y - floor.getY()); - writeByte(record.z - floor.getZ()); - } + if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17)) { + writeVarInt(records.size()); + } else { + writeInt(records.size()); + } - writeFloat(playerMotion.x); - writeFloat(playerMotion.y); - writeFloat(playerMotion.z); + Vector3i floor = toFloor(position); - if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_3)) { - this.writeVarInt(this.blockInteraction.ordinal()); - Particle.write(this, this.smallExplosionParticles); - Particle.write(this, this.largeExplosionParticles); + for (Vector3i record : records) { + writeByte(record.x - floor.getX()); + writeByte(record.y - floor.getY()); + writeByte(record.z - floor.getZ()); + } - if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5)) { - Sound.write(this, this.explosionSound); - } else { - this.writeIdentifier(this.explosionSound.getSoundId()); - this.writeOptional(this.explosionSound.getRange(), PacketWrapper::writeFloat); + writeFloat((float) knockback.x); + writeFloat((float) knockback.y); + writeFloat((float) knockback.z); + + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_3)) { + this.writeVarInt(this.blockInteraction.ordinal()); + Particle.write(this, this.smallParticle); + Particle.write(this, this.particle); + + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5)) { + Sound.write(this, this.explosionSound); + } else { + this.writeIdentifier(this.explosionSound.getSoundId()); + this.writeOptional(this.explosionSound.getRange(), PacketWrapper::writeFloat); + } } } } @@ -169,9 +213,9 @@ public void copy(WrapperPlayServerExplosion wrapper) { position = wrapper.position; strength = wrapper.strength; records = wrapper.records; - playerMotion = wrapper.playerMotion; - smallExplosionParticles = wrapper.smallExplosionParticles; - largeExplosionParticles = wrapper.largeExplosionParticles; + knockback = wrapper.knockback; + smallParticle = wrapper.smallParticle; + particle = wrapper.particle; blockInteraction = wrapper.blockInteraction; explosionSound = wrapper.explosionSound; } @@ -200,50 +244,83 @@ public void setPosition(Vector3d position) { this.position = position; } + @ApiStatus.Obsolete // removed in 1.21.2 public float getStrength() { return strength; } + @ApiStatus.Obsolete // removed in 1.21.2 public void setStrength(float strength) { this.strength = strength; } + @ApiStatus.Obsolete // removed in 1.21.2 public List getRecords() { return records; } + @ApiStatus.Obsolete // removed in 1.21.2 public void setRecords(List records) { this.records = records; } - public Vector3f getPlayerMotion() { - return playerMotion; + public @Nullable Vector3d getKnockback() { + return this.knockback; } - public void setPlayerMotion(Vector3f playerMotion) { - this.playerMotion = playerMotion; + public void setKnockback(@Nullable Vector3d knockback) { + this.knockback = knockback; } + @Deprecated + public @Nullable Vector3f getPlayerMotion() { + return this.knockback == null ? null : new Vector3f( + (float) this.knockback.x, + (float) this.knockback.y, + (float) this.knockback.z + ); + } + + @Deprecated + public void setPlayerMotion(@Nullable Vector3f playerMotion) { + this.knockback = playerMotion == null ? null : new Vector3d( + playerMotion.x, playerMotion.y, playerMotion.z); + } + + @ApiStatus.Obsolete // removed in 1.21.2 public Particle getSmallExplosionParticles() { - return this.smallExplosionParticles; + return this.smallParticle; } + @ApiStatus.Obsolete // removed in 1.21.2 public void setSmallExplosionParticles(Particle smallExplosionParticles) { - this.smallExplosionParticles = smallExplosionParticles; + this.smallParticle = smallExplosionParticles; + } + + public Particle getParticle() { + return this.particle; + } + + public void setParticle(Particle particle) { + this.particle = particle; } + @ApiStatus.Obsolete // renamed in 1.21.2 public Particle getLargeExplosionParticles() { - return this.largeExplosionParticles; + return this.getParticle(); } + @ApiStatus.Obsolete // renamed in 1.21.2 public void setLargeExplosionParticles(Particle largeExplosionParticles) { - this.largeExplosionParticles = largeExplosionParticles; + this.setParticle(largeExplosionParticles); } + @ApiStatus.Obsolete // removed in 1.21.2 public BlockInteraction getBlockInteraction() { return this.blockInteraction; } + @ApiStatus.Obsolete // removed in 1.21.2 public void setBlockInteraction(BlockInteraction blockInteraction) { this.blockInteraction = blockInteraction; } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerJoinGame.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerJoinGame.java index 301b08719..accafafa5 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerJoinGame.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerJoinGame.java @@ -38,6 +38,8 @@ import java.util.List; import java.util.Optional; +import static com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRespawn.FALLBACK_SEA_LEVEL; + public class WrapperPlayServerJoinGame extends PacketWrapper { private int entityID; private boolean hardcore; @@ -62,6 +64,7 @@ public class WrapperPlayServerJoinGame extends PacketWrapper worldNames, + NBTCompound dimensionCodec, DimensionType dimensionType, + Difficulty difficulty, String worldName, long hashedSeed, + int maxPlayers, int viewDistance, int simulationDistance, + boolean reducedDebugInfo, boolean enableRespawnScreen, boolean limitedCrafting, + boolean isDebug, boolean isFlat, WorldBlockPosition lastDeathPosition, + @Nullable Integer portalCooldown, int seaLevel, boolean enforcesSecureChat ) { this(entityID, hardcore, gameMode, previousGameMode, worldNames, dimensionCodec, (DimensionTypeRef) null, difficulty, worldName, hashedSeed, maxPlayers, viewDistance, simulationDistance, reducedDebugInfo, - enableRespawnScreen, limitedCrafting, isDebug, isFlat, lastDeathPosition, portalCooldown, enforcesSecureChat); + enableRespawnScreen, limitedCrafting, isDebug, isFlat, lastDeathPosition, + portalCooldown, seaLevel, enforcesSecureChat); this.dimensionTypeRef = dimensionType.asRef(this.serverVersion.toClientVersion()); } @@ -207,6 +227,22 @@ public WrapperPlayServerJoinGame( boolean reducedDebugInfo, boolean enableRespawnScreen, boolean limitedCrafting, boolean isDebug, boolean isFlat, WorldBlockPosition lastDeathPosition, @Nullable Integer portalCooldown, boolean enforcesSecureChat + ) { + this(entityID, hardcore, gameMode, previousGameMode, worldNames, dimensionCodec, dimensionTypeRef, difficulty, + worldName, hashedSeed, maxPlayers, viewDistance, simulationDistance, reducedDebugInfo, + enableRespawnScreen, limitedCrafting, isDebug, isFlat, lastDeathPosition, + portalCooldown, FALLBACK_SEA_LEVEL, enforcesSecureChat); + } + + public WrapperPlayServerJoinGame( + int entityID, boolean hardcore, GameMode gameMode, + @Nullable GameMode previousGameMode, List worldNames, + NBTCompound dimensionCodec, DimensionTypeRef dimensionTypeRef, + Difficulty difficulty, String worldName, long hashedSeed, + int maxPlayers, int viewDistance, int simulationDistance, + boolean reducedDebugInfo, boolean enableRespawnScreen, boolean limitedCrafting, + boolean isDebug, boolean isFlat, WorldBlockPosition lastDeathPosition, + @Nullable Integer portalCooldown, int seaLevel, boolean enforcesSecureChat ) { super(PacketType.Play.Server.JOIN_GAME); this.entityID = entityID; @@ -229,6 +265,7 @@ public WrapperPlayServerJoinGame( this.isFlat = isFlat; this.lastDeathPosition = lastDeathPosition; this.portalCooldown = portalCooldown; + this.seaLevel = seaLevel; this.enforcesSecureChat = enforcesSecureChat; } @@ -313,9 +350,12 @@ public void read() { } if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20)) { portalCooldown = readVarInt(); - } - if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5)) { - enforcesSecureChat = readBoolean(); + if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5)) { + enforcesSecureChat = readBoolean(); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.seaLevel = this.readVarInt(); + } + } } } @@ -443,6 +483,7 @@ public void copy(WrapperPlayServerJoinGame wrapper) { isFlat = wrapper.isFlat; lastDeathPosition = wrapper.lastDeathPosition; portalCooldown = wrapper.portalCooldown; + seaLevel = wrapper.seaLevel; enforcesSecureChat = wrapper.enforcesSecureChat; } @@ -626,6 +667,14 @@ public void setPortalCooldown(int portalCooldown) { this.portalCooldown = portalCooldown; } + public int getSeaLevel() { + return this.seaLevel; + } + + public void setSeaLevel(int seaLevel) { + this.seaLevel = seaLevel; + } + public boolean isEnforcesSecureChat() { return this.enforcesSecureChat; } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMerchantOffers.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMerchantOffers.java index e394fee4e..257bbdcfb 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMerchantOffers.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMerchantOffers.java @@ -52,7 +52,7 @@ public WrapperPlayServerMerchantOffers(int containerId, List merc @Override public void read() { - containerId = readVarInt(); + containerId = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) ? this.readContainerId() : this.readVarInt(); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19)) { merchantOffers = readList(PacketWrapper::readMerchantOffer); } else { @@ -70,7 +70,11 @@ public void read() { @Override public void write() { - writeVarInt(containerId); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)){ + this.writeContainerId(this.containerId); + } else { + this.writeVarInt(this.containerId); + } if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_19)) { writeList(merchantOffers, PacketWrapper::writeMerchantOffer); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMoveMinecart.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMoveMinecart.java new file mode 100644 index 000000000..76d564459 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerMoveMinecart.java @@ -0,0 +1,168 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.wrapper.play.server; + +import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.util.List; +import java.util.Objects; + +public class WrapperPlayServerMoveMinecart extends PacketWrapper { + + private int entityId; + private List lerpSteps; + + public WrapperPlayServerMoveMinecart(PacketSendEvent event) { + super(event); + } + + public WrapperPlayServerMoveMinecart(int entityId, List lerpSteps) { + super(PacketType.Play.Server.MOVE_MINECART); + this.entityId = entityId; + this.lerpSteps = lerpSteps; + } + + @Override + public void read() { + this.entityId = this.readVarInt(); + this.lerpSteps = this.readList(MinecartStep::read); + } + + @Override + public void write() { + this.writeVarInt(this.entityId); + this.writeList(this.lerpSteps, MinecartStep::write); + } + + @Override + public void copy(WrapperPlayServerMoveMinecart wrapper) { + this.entityId = wrapper.entityId; + this.lerpSteps = wrapper.lerpSteps; + } + + public int getEntityId() { + return this.entityId; + } + + public void setEntityId(int entityId) { + this.entityId = entityId; + } + + public List getLerpSteps() { + return this.lerpSteps; + } + + public void setLerpSteps(List lerpSteps) { + this.lerpSteps = lerpSteps; + } + + public static final class MinecartStep { + + private Vector3d position; + private Vector3d movement; + private float yaw; + private float pitch; + private float weight; + + public MinecartStep(Vector3d position, Vector3d movement, float yaw, float pitch, float weight) { + this.position = position; + this.movement = movement; + this.yaw = yaw; + this.pitch = pitch; + this.weight = weight; + } + + public static MinecartStep read(PacketWrapper wrapper) { + Vector3d position = Vector3d.read(wrapper); + Vector3d movement = Vector3d.read(wrapper); + float yaw = wrapper.readRotation(); + float pitch = wrapper.readRotation(); + float weight = wrapper.readFloat(); + return new MinecartStep(position, movement, yaw, pitch, weight); + } + + public static void write(PacketWrapper wrapper, MinecartStep step) { + Vector3d.write(wrapper, step.position); + Vector3d.write(wrapper, step.movement); + wrapper.writeRotation(step.yaw); + wrapper.writeRotation(step.pitch); + wrapper.writeFloat(step.weight); + } + + public Vector3d getPosition() { + return this.position; + } + + public void setPosition(Vector3d position) { + this.position = position; + } + + public Vector3d getMovement() { + return this.movement; + } + + public void setMovement(Vector3d movement) { + this.movement = movement; + } + + public float getYaw() { + return this.yaw; + } + + public void setYaw(float yaw) { + this.yaw = yaw; + } + + public float getPitch() { + return this.pitch; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public float getWeight() { + return this.weight; + } + + public void setWeight(float weight) { + this.weight = weight; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof MinecartStep)) return false; + MinecartStep that = (MinecartStep) obj; + if (Float.compare(that.yaw, this.yaw) != 0) return false; + if (Float.compare(that.pitch, this.pitch) != 0) return false; + if (Float.compare(that.weight, this.weight) != 0) return false; + if (!this.position.equals(that.position)) return false; + return this.movement.equals(that.movement); + } + + @Override + public int hashCode() { + return Objects.hash(this.position, this.movement, this.yaw, this.pitch, this.weight); + } + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenHorseWindow.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenHorseWindow.java index f4bf1529b..79d0299e0 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenHorseWindow.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenHorseWindow.java @@ -40,14 +40,14 @@ public WrapperPlayServerOpenHorseWindow(int windowId, int slotCount, int entityI @Override public void read() { - this.windowId = readUnsignedByte(); + this.windowId = this.readContainerId(); this.slotCount = readVarInt(); this.entityId = readInt(); } @Override public void write() { - writeByte(windowId); + this.writeContainerId(windowId); writeVarInt(slotCount); writeInt(entityId); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenWindow.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenWindow.java index 59beebd4c..3d36ad197 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenWindow.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerOpenWindow.java @@ -74,10 +74,11 @@ public WrapperPlayServerOpenWindow(int containerId, int type, Component title, i @Override public void read() { - if (serverVersion.isOlderThanOrEquals(ServerVersion.V_1_13_2)) { - this.containerId = readUnsignedByte(); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) + || this.serverVersion.isOlderThan(ServerVersion.V_1_14)) { + this.containerId = this.readContainerId(); } else { - this.containerId = readVarInt(); + this.containerId = this.readVarInt(); } // 1.7 has a very different packet format @@ -110,10 +111,11 @@ public void read() { @Override public void write() { - if (serverVersion.isOlderThanOrEquals(ServerVersion.V_1_13_2)) { - writeByte(this.containerId); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) + || this.serverVersion.isOlderThan(ServerVersion.V_1_14)) { + this.writeContainerId(this.containerId); } else { - writeVarInt(this.containerId); + this.writeVarInt(this.containerId); } // 1.7 has a very different packet format diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerPlayerInfoUpdate.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerPlayerInfoUpdate.java index 0840025c2..b1545585d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerPlayerInfoUpdate.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerPlayerInfoUpdate.java @@ -28,7 +28,11 @@ import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.UUID; public class WrapperPlayServerPlayerInfoUpdate extends PacketWrapper { //Specify entries using EnumSet.of() @@ -41,39 +45,65 @@ public enum Action { UPDATE_GAME_MODE, UPDATE_LISTED, UPDATE_LATENCY, - UPDATE_DISPLAY_NAME; + UPDATE_DISPLAY_NAME, + /** + * Updates the order in which the player is listed in the tablist. + */ + UPDATE_LIST_ORDER; public static final WrapperPlayServerPlayerInfoUpdate.Action[] VALUES = values(); } public static class PlayerInfo { - private UserProfile gameProfile; - private boolean listed; + private UserProfile profile; + private boolean listed = true; private int latency; private GameMode gameMode; @Nullable private Component displayName; @Nullable private RemoteChatSession chatSession; + private int listOrder; // added in 1.21.2 - public PlayerInfo(UserProfile gameProfile, boolean listed, - int latency, GameMode gameMode, - @Nullable Component displayName, @Nullable RemoteChatSession chatSession) { - this.gameProfile = gameProfile; + public PlayerInfo(UUID profileId) { + this(new UserProfile(profileId, "")); + } + + public PlayerInfo(UserProfile profile) { + this.profile = profile; + } + + public PlayerInfo( + UserProfile profile, boolean listed, + int latency, GameMode gameMode, + @Nullable Component displayName, + @Nullable RemoteChatSession chatSession + ) { + this(profile, listed, latency, gameMode, displayName, chatSession, 0); + } + + public PlayerInfo( + UserProfile profile, boolean listed, + int latency, GameMode gameMode, + @Nullable Component displayName, + @Nullable RemoteChatSession chatSession, + int listOrder + ) { + this.profile = profile; this.listed = listed; this.latency = latency; this.gameMode = gameMode; this.displayName = displayName; this.chatSession = chatSession; + this.listOrder = listOrder; } - @Deprecated public UUID getProfileId() { - return gameProfile.getUUID(); + return profile.getUUID(); } public UserProfile getGameProfile() { - return gameProfile; + return profile; } public boolean isListed() { @@ -96,8 +126,12 @@ public GameMode getGameMode() { return chatSession; } + public int getListOrder() { + return this.listOrder; + } + public void setGameProfile(UserProfile gameProfile) { - this.gameProfile = gameProfile; + this.profile = gameProfile; } public void setListed(boolean listed) { @@ -119,6 +153,10 @@ public void setDisplayName(@Nullable Component displayName) { public void setChatSession(@Nullable RemoteChatSession chatSession) { this.chatSession = chatSession; } + + public void setListOrder(int listOrder) { + this.listOrder = listOrder; + } } public WrapperPlayServerPlayerInfoUpdate(PacketSendEvent event) { @@ -157,6 +195,7 @@ public void read() { int latency = 0; @Nullable RemoteChatSession chatSession = null; @Nullable Component displayName = null; + int listOrder = 0; for (Action action : actions) { switch (action) { case ADD_PLAYER: @@ -187,9 +226,12 @@ public void read() { case UPDATE_DISPLAY_NAME: displayName = wrapper.readOptional(PacketWrapper::readComponent); break; + case UPDATE_LIST_ORDER: + listOrder = wrapper.readVarInt(); + break; } } - return new PlayerInfo(gameProfile, listed, latency, gameMode, displayName, chatSession); + return new PlayerInfo(gameProfile, listed, latency, gameMode, displayName, chatSession, listOrder); }); } @@ -223,6 +265,9 @@ public void write() { case UPDATE_DISPLAY_NAME: wrapper.writeOptional(playerInfo.getDisplayName(), PacketWrapper::writeComponent); break; + case UPDATE_LIST_ORDER: + wrapper.writeVarInt(playerInfo.getListOrder()); + break; } } }); diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerRespawn.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerRespawn.java index ade9b4a8d..7248f9662 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerRespawn.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerRespawn.java @@ -43,6 +43,9 @@ public class WrapperPlayServerRespawn extends PacketWrapper worldName; private Difficulty difficulty; @@ -54,6 +57,7 @@ public class WrapperPlayServerRespawn extends PacketWrapper { - private ItemType item; + + // changed in 1.21.2 + private ResourceLocation cooldownGroup; private int cooldownTicks; public WrapperPlayServerSetCooldown(PacketSendEvent event) { super(event); } + @ApiStatus.Obsolete // since 1.21.2 public WrapperPlayServerSetCooldown(ItemType item, int cooldownTicks) { + this(item.getName(), cooldownTicks); + } + + /** + * Note: only supporter since Minecraft 1.21.2. + * This will error if used on versions below and the specified cooldown group + * is not an item cooldown group. + */ + public WrapperPlayServerSetCooldown(ResourceLocation cooldownGroup, int cooldownTicks) { super(PacketType.Play.Server.SET_COOLDOWN); - this.item = item; + this.cooldownGroup = cooldownGroup; this.cooldownTicks = cooldownTicks; } @Override public void read() { - item = ItemTypes.getById(serverVersion.toClientVersion(), readVarInt()); - cooldownTicks = readVarInt(); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.cooldownGroup = this.readIdentifier(); + } else { + ItemType item = this.readMappedEntity(ItemTypes.getRegistry()); + this.cooldownGroup = item.getName(); + } + this.cooldownTicks = this.readVarInt(); } @Override public void write() { - writeVarInt(item.getId(serverVersion.toClientVersion())); - writeVarInt(cooldownTicks); + if (this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + this.writeIdentifier(this.cooldownGroup); + } else { + this.writeMappedEntity(this.getItem()); + } + this.writeVarInt(this.cooldownTicks); } @Override public void copy(WrapperPlayServerSetCooldown wrapper) { - item = wrapper.item; - cooldownTicks = wrapper.cooldownTicks; + this.cooldownGroup = wrapper.cooldownGroup; + this.cooldownTicks = wrapper.cooldownTicks; + } + + public ResourceLocation getCooldownGroup() { + return this.cooldownGroup; + } + + public void setCooldownGroup(ResourceLocation cooldownGroup) { + this.cooldownGroup = cooldownGroup; } + @ApiStatus.Obsolete // since 1.21.2 public ItemType getItem() { + ItemType item = ItemTypes.getByName(this.cooldownGroup.toString()); + if (item == null) { + throw new IllegalStateException("Can't get legacy cooldown item for cooldown group " + this.cooldownGroup); + } return item; } + @ApiStatus.Obsolete // since 1.21.2 public void setItem(ItemType item) { - this.item = item; + this.cooldownGroup = item.getName(); } public int getCooldownTicks() { - return cooldownTicks; + return this.cooldownTicks; } public void setCooldownTicks(int cooldownTicks) { diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetCursorItem.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetCursorItem.java new file mode 100644 index 000000000..854956f36 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetCursorItem.java @@ -0,0 +1,61 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.wrapper.play.server; + +import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.item.ItemStack; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class WrapperPlayServerSetCursorItem extends PacketWrapper { + + private ItemStack stack; + + public WrapperPlayServerSetCursorItem(PacketSendEvent event) { + super(event); + } + + public WrapperPlayServerSetCursorItem(ItemStack stack) { + super(PacketType.Play.Server.SET_CURSOR_ITEM); + this.stack = stack; + } + + @Override + public void read() { + this.stack = this.readItemStack(); + } + + @Override + public void write() { + this.writeItemStack(this.stack); + } + + @Override + public void copy(WrapperPlayServerSetCursorItem wrapper) { + this.stack = wrapper.stack; + } + + public ItemStack getStack() { + return this.stack; + } + + public void setStack(ItemStack stack) { + this.stack = stack; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetPlayerInventory.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetPlayerInventory.java new file mode 100644 index 000000000..be61d3bb9 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetPlayerInventory.java @@ -0,0 +1,74 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.wrapper.play.server; + +import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.item.ItemStack; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class WrapperPlayServerSetPlayerInventory extends PacketWrapper { + + private int slot; + private ItemStack stack; + + public WrapperPlayServerSetPlayerInventory(PacketSendEvent event) { + super(event); + } + + public WrapperPlayServerSetPlayerInventory(int slot, ItemStack stack) { + super(PacketType.Play.Server.SET_PLAYER_INVENTORY); + this.slot = slot; + this.stack = stack; + } + + @Override + public void read() { + this.slot = this.readVarInt(); + this.stack = this.readItemStack(); + } + + @Override + public void write() { + this.writeVarInt(this.slot); + this.writeItemStack(this.stack); + } + + @Override + public void copy(WrapperPlayServerSetPlayerInventory wrapper) { + this.slot = wrapper.slot; + this.stack = wrapper.stack; + } + + public int getSlot() { + return this.slot; + } + + public void setSlot(int slot) { + this.slot = slot; + } + + public ItemStack getStack() { + return this.stack; + } + + public void setStack(ItemStack stack) { + this.stack = stack; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetSlot.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetSlot.java index 522267698..a5a33aa77 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetSlot.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerSetSlot.java @@ -44,7 +44,7 @@ public WrapperPlayServerSetSlot(int windowID, int stateID, int slot, ItemStack i @Override public void read() { - windowID = readByte(); + this.windowID = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_21_2) ? this.readContainerId() : this.readByte(); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17_1)) { stateID = readVarInt(); } @@ -54,7 +54,7 @@ public void read() { @Override public void write() { - writeByte(windowID); + this.writeContainerId(this.windowID); if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17_1)) { writeVarInt(stateID); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowItems.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowItems.java index 00594338b..9b2765997 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowItems.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowItems.java @@ -49,7 +49,7 @@ public WrapperPlayServerWindowItems(int windowID, int stateID, List i @Override public void read() { - windowID = readUnsignedByte(); + windowID = this.readContainerId(); boolean v1_17_1 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17_1); if (v1_17_1) { stateID = readVarInt(); @@ -70,7 +70,7 @@ public void read() { @Override public void write() { - writeByte(windowID); + this.writeContainerId(this.windowID); boolean v1_17_1 = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17_1); if (v1_17_1) { writeVarInt(stateID); @@ -127,4 +127,4 @@ public Optional getCarriedItem() { public void setCarriedItem(@Nullable ItemStack carriedItem) { this.carriedItem = Optional.ofNullable(carriedItem); } -} \ No newline at end of file +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowProperty.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowProperty.java index 1283d04a5..7f8a82e64 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowProperty.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerWindowProperty.java @@ -23,7 +23,8 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper; public class WrapperPlayServerWindowProperty extends PacketWrapper { - private byte windowId; + + private int windowId; private int id; private int value; @@ -32,6 +33,10 @@ public WrapperPlayServerWindowProperty(PacketSendEvent event) { } public WrapperPlayServerWindowProperty(byte windowId, int id, int value) { + this((int) windowId, id, value); + } + + public WrapperPlayServerWindowProperty(int windowId, int id, int value) { super(PacketType.Play.Server.WINDOW_PROPERTY); this.windowId = windowId; this.id = id; @@ -40,14 +45,14 @@ public WrapperPlayServerWindowProperty(byte windowId, int id, int value) { @Override public void read() { - this.windowId = (byte) readUnsignedByte(); + this.windowId = this.readContainerId(); this.id = readShort(); this.value = readShort(); } @Override public void write() { - writeByte(this.windowId); + this.writeContainerId(this.windowId); writeShort(this.id); writeShort(this.value); } @@ -59,14 +64,24 @@ public void copy(WrapperPlayServerWindowProperty wrapper) { this.value = wrapper.value; } - public byte getWindowId() { - return windowId; + public int getContainerId() { + return this.windowId; } - public void setWindowId(byte windowId) { + public void setContainerId(int windowId) { this.windowId = windowId; } + @Deprecated + public byte getWindowIdB() { + return (byte) this.getContainerId(); + } + + @Deprecated + public void setWindowId(byte windowId) { + this.setContainerId(windowId); + } + public int getId() { return id; } @@ -82,4 +97,4 @@ public int getValue() { public void setValue(int value) { this.value = value; } -} \ No newline at end of file +} From 57fb06ca5fcc198c1c0a08fef9d913300e7e8a96 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 20:28:59 +0200 Subject: [PATCH 4/9] Implement dynamic instrument registry --- .../protocol/item/instrument/Instrument.java | 61 ++++++++++++++-- .../protocol/item/instrument/Instruments.java | 72 +++++-------------- .../item/instrument/StaticInstrument.java | 59 ++++++++------- .../protocol/mapper/DeepComparableEntity.java | 26 +++++++ .../SynchronizedRegistriesHandler.java | 5 +- 5 files changed, 139 insertions(+), 84 deletions(-) create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/mapper/DeepComparableEntity.java diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instrument.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instrument.java index cf60c0c55..a40ebee07 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instrument.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instrument.java @@ -18,27 +18,51 @@ package com.github.retrooper.packetevents.protocol.item.instrument; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; +import com.github.retrooper.packetevents.protocol.nbt.NBT; +import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; +import com.github.retrooper.packetevents.protocol.nbt.NBTFloat; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.sound.Sound; +import com.github.retrooper.packetevents.util.MathUtil; +import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; +import com.github.retrooper.packetevents.util.mappings.TypesBuilderData; import com.github.retrooper.packetevents.wrapper.PacketWrapper; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; -public interface Instrument extends MappedEntity { +public interface Instrument extends MappedEntity, CopyableEntity, DeepComparableEntity { Sound getSound(); - int getUseDuration(); + float getUseSeconds(); + + /** + * Use duration measured in ticks + */ + default int getUseDuration() { + return MathUtil.floor(this.getUseSeconds() * 20); + } float getRange(); + Component getDescription(); + static Instrument read(PacketWrapper wrapper) { - return wrapper.readMappedEntityOrDirect(Instruments::getById, Instrument::readDirect); + return wrapper.readMappedEntityOrDirect(Instruments.getRegistry(), Instrument::readDirect); } static Instrument readDirect(PacketWrapper wrapper) { Sound sound = Sound.read(wrapper); - int useDuration = wrapper.readVarInt(); + float useSeconds = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2) + ? wrapper.readFloat() : wrapper.readVarInt() * 20f; float range = wrapper.readFloat(); - return new StaticInstrument(sound, useDuration, range); + Component description = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2) + ? wrapper.readComponent() : Component.empty(); + return new StaticInstrument(sound, useSeconds, range, description); } static void write(PacketWrapper wrapper, Instrument instrument) { @@ -47,7 +71,32 @@ static void write(PacketWrapper wrapper, Instrument instrument) { static void writeDirect(PacketWrapper wrapper, Instrument instrument) { Sound.write(wrapper, instrument.getSound()); - wrapper.writeVarInt(instrument.getUseDuration()); + if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + wrapper.writeFloat(instrument.getUseSeconds()); + } else { + wrapper.writeVarInt(instrument.getUseDuration()); + } wrapper.writeFloat(instrument.getRange()); + if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + wrapper.writeComponent(instrument.getDescription()); + } + } + + static Instrument decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) { + NBTCompound compound = (NBTCompound) nbt; + Sound sound = Sound.decode(compound.getTagOrThrow("sound_event"), version); + float useSeconds = compound.getNumberTagOrThrow("use_duration").getAsFloat(); + float range = compound.getNumberTagOrThrow("range").getAsFloat(); + Component description = AdventureSerializer.fromNbt(compound.getTagOrThrow("description")); + return new StaticInstrument(data, sound, useSeconds, range, description); + } + + static NBT encode(Instrument instrument, ClientVersion version) { + NBTCompound compound = new NBTCompound(); + compound.setTag("sound_event", Sound.encode(instrument.getSound(), version)); + compound.setTag("use_duration", new NBTFloat(instrument.getUseSeconds())); + compound.setTag("range", new NBTFloat(instrument.getRange())); + compound.setTag("description", AdventureSerializer.toNbt(instrument.getDescription())); + return compound; } } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instruments.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instruments.java index c443f64df..475da5fe3 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instruments.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/Instruments.java @@ -21,74 +21,40 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.sound.Sound; import com.github.retrooper.packetevents.protocol.sound.Sounds; -import com.github.retrooper.packetevents.resources.ResourceLocation; -import com.github.retrooper.packetevents.util.mappings.MappingHelper; -import com.github.retrooper.packetevents.util.mappings.TypesBuilder; -import com.github.retrooper.packetevents.util.mappings.TypesBuilderData; +import com.github.retrooper.packetevents.util.mappings.VersionedRegistry; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.ApiStatus; -import java.util.HashMap; -import java.util.Map; +public final class Instruments { -public class Instruments { + private static final VersionedRegistry REGISTRY = new VersionedRegistry<>( + "instrument", "item/item_instrument_mappings"); - private static final Map INSTRUMENT_MAP = new HashMap<>(); - private static final Map> INSTRUMENT_ID_MAP = new HashMap<>(); - private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_instrument_mappings"); + private Instruments() { + } public static Instrument define(String key, Sound sound) { // vanilla defaults for goat horns - return define(key, sound, 140, 256f); + return define(key, sound, 20 * 7, 256f); } + @ApiStatus.Internal public static Instrument define(String key, Sound sound, int useDuration, float range) { - TypesBuilderData data = TYPES_BUILDER.define(key); - Instrument instrument = new Instrument() { - @Override - public Sound getSound() { - return sound; - } - - @Override - public int getUseDuration() { - return useDuration; - } - - @Override - public float getRange() { - return range; - } - - @Override - public ResourceLocation getName() { - return data.getName(); - } - - @Override - public int getId(ClientVersion version) { - return MappingHelper.getId(version, TYPES_BUILDER, data); - } + return REGISTRY.define(key, data -> new StaticInstrument( + data, sound, useDuration, range, + Component.translatable("instrument.minecraft." + key))); + } - @Override - public boolean equals(Object obj) { - if (obj instanceof Instrument) { - return getName().equals(((Instrument) obj).getName()); - } - return false; - } - }; - MappingHelper.registerMapping(TYPES_BUILDER, INSTRUMENT_MAP, INSTRUMENT_ID_MAP, instrument); - return instrument; + public static VersionedRegistry getRegistry() { + return REGISTRY; } - // with key public static Instrument getByName(String name) { - return INSTRUMENT_MAP.get(name); + return REGISTRY.getByName(name); } public static Instrument getById(ClientVersion version, int id) { - int index = TYPES_BUILDER.getDataIndex(version); - Map idMap = INSTRUMENT_ID_MAP.get((byte) index); - return idMap.get(id); + return REGISTRY.getById(version, id); } public static final Instrument PONDER_GOAT_HORN = define("ponder_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_0); @@ -101,6 +67,6 @@ public static Instrument getById(ClientVersion version, int id) { public static final Instrument DREAM_GOAT_HORN = define("dream_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_7); static { - TYPES_BUILDER.unloadFileMappings(); + REGISTRY.unloadMappings(); } } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/StaticInstrument.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/StaticInstrument.java index ef2b68563..f3cd2256f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/StaticInstrument.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/instrument/StaticInstrument.java @@ -18,22 +18,41 @@ package com.github.retrooper.packetevents.protocol.item.instrument; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity; import com.github.retrooper.packetevents.protocol.sound.Sound; -import com.github.retrooper.packetevents.resources.ResourceLocation; +import com.github.retrooper.packetevents.util.mappings.TypesBuilderData; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; import java.util.Objects; -public class StaticInstrument implements Instrument { +public class StaticInstrument extends AbstractMappedEntity implements Instrument { private final Sound sound; - private final int useDuration; + private final float useSeconds; private final float range; + private final Component description; + @Deprecated // useDuration changed from ticks to seconds in 1.21.2 public StaticInstrument(Sound sound, int useDuration, float range) { + this(sound, useDuration * 20f, range, Component.empty()); + } + + public StaticInstrument(Sound sound, float useSeconds, float range, Component description) { + this(null, sound, useSeconds, range, description); + } + + public StaticInstrument(@Nullable TypesBuilderData data, Sound sound, float useSeconds, float range, Component description) { + super(data); this.sound = sound; - this.useDuration = useDuration; + this.useSeconds = useSeconds; this.range = range; + this.description = description; + } + + @Override + public Instrument copy(@Nullable TypesBuilderData newData) { + return new StaticInstrument(newData, this.sound, this.useSeconds, this.range, this.description); } @Override @@ -42,8 +61,8 @@ public Sound getSound() { } @Override - public int getUseDuration() { - return this.useDuration; + public float getUseSeconds() { + return this.useSeconds; } @Override @@ -52,32 +71,24 @@ public float getRange() { } @Override - public ResourceLocation getName() { - throw new UnsupportedOperationException(); - } - - @Override - public int getId(ClientVersion version) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isRegistered() { - return false; + public Component getDescription() { + return this.description; } @Override - public boolean equals(Object obj) { + public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticInstrument)) return false; + if (!super.equals(obj)) return false; StaticInstrument that = (StaticInstrument) obj; - if (this.useDuration != that.useDuration) return false; + if (this.useSeconds != that.useSeconds) return false; if (Float.compare(that.range, this.range) != 0) return false; - return this.sound.equals(that.sound); + if (!this.sound.equals(that.sound)) return false; + return this.description.equals(that.description); } @Override - public int hashCode() { - return Objects.hash(this.sound, this.useDuration, this.range); + public int deepHashCode() { + return Objects.hash(super.hashCode(), this.sound, this.useSeconds, this.range, this.description); } } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/mapper/DeepComparableEntity.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/mapper/DeepComparableEntity.java new file mode 100644 index 000000000..72eea5340 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/mapper/DeepComparableEntity.java @@ -0,0 +1,26 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.mapper; + +public interface DeepComparableEntity { + + boolean deepEquals(Object obj); + + int deepHashCode(); +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java b/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java index bbde2b7d6..d12ca7bca 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java +++ b/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java @@ -27,6 +27,8 @@ import com.github.retrooper.packetevents.protocol.item.banner.BannerPatterns; import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentType; import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes; +import com.github.retrooper.packetevents.protocol.item.instrument.Instrument; +import com.github.retrooper.packetevents.protocol.item.instrument.Instruments; import com.github.retrooper.packetevents.protocol.item.jukebox.IJukeboxSong; import com.github.retrooper.packetevents.protocol.item.jukebox.JukeboxSongs; import com.github.retrooper.packetevents.protocol.item.trimmaterial.TrimMaterial; @@ -76,7 +78,8 @@ public final class SynchronizedRegistriesHandler { new RegistryEntry<>(DamageTypes.getRegistry(), DamageType::decode), new RegistryEntry<>(BannerPatterns.getRegistry(), BannerPattern::decode), new RegistryEntry<>(EnchantmentTypes.getRegistry(), EnchantmentType::decode), - new RegistryEntry<>(JukeboxSongs.getRegistry(), IJukeboxSong::decode) + new RegistryEntry<>(JukeboxSongs.getRegistry(), IJukeboxSong::decode), + new RegistryEntry<>(Instruments.getRegistry(), Instrument::decode) ).collect(Collectors.toMap(RegistryEntry::getRegistryKey, Function.identity())); private SynchronizedRegistriesHandler() { From 1e738f038f3bf29f5c1fcba6c715b55c0d9b0350 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 20:31:32 +0200 Subject: [PATCH 5/9] Implement DeepComparableEntity for all dynamic registry entries --- .../github/retrooper/packetevents/protocol/chat/ChatType.java | 3 ++- .../retrooper/packetevents/protocol/chat/StaticChatType.java | 2 ++ .../protocol/entity/wolfvariant/StaticWolfVariant.java | 2 ++ .../packetevents/protocol/entity/wolfvariant/WolfVariant.java | 3 ++- .../packetevents/protocol/item/banner/BannerPattern.java | 3 ++- .../protocol/item/banner/StaticBannerPattern.java | 2 ++ .../protocol/item/enchantment/type/EnchantmentType.java | 3 ++- .../protocol/item/enchantment/type/StaticEnchantmentType.java | 2 ++ .../packetevents/protocol/item/jukebox/IJukeboxSong.java | 4 +++- .../packetevents/protocol/item/jukebox/JukeboxSong.java | 2 ++ .../protocol/item/trimmaterial/StaticTrimMaterial.java | 2 ++ .../packetevents/protocol/item/trimmaterial/TrimMaterial.java | 3 ++- .../protocol/item/trimpattern/StaticTrimPattern.java | 2 ++ .../packetevents/protocol/item/trimpattern/TrimPattern.java | 3 ++- .../retrooper/packetevents/protocol/world/biome/Biome.java | 3 ++- .../packetevents/protocol/world/biome/StaticBiome.java | 2 ++ .../packetevents/protocol/world/damagetype/DamageType.java | 3 ++- .../protocol/world/damagetype/StaticDamageType.java | 2 ++ .../packetevents/protocol/world/dimension/DimensionType.java | 3 ++- .../protocol/world/dimension/StaticDimensionType.java | 2 ++ .../packetevents/protocol/world/painting/PaintingVariant.java | 3 ++- .../protocol/world/painting/StaticPaintingVariant.java | 2 ++ 22 files changed, 45 insertions(+), 11 deletions(-) diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/ChatType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/ChatType.java index 421637d36..e849aa940 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/ChatType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/ChatType.java @@ -20,6 +20,7 @@ import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_1; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -37,7 +38,7 @@ import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow; -public interface ChatType extends MappedEntity, CopyableEntity { +public interface ChatType extends MappedEntity, CopyableEntity, DeepComparableEntity { @UnknownNullability("only nullable for 1.19") ChatTypeDecoration getChatDecoration(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/StaticChatType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/StaticChatType.java index f57e7038e..ed8914fb2 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/StaticChatType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/chat/StaticChatType.java @@ -96,6 +96,7 @@ public ChatType copy(@Nullable TypesBuilderData newData) { return this.narrationPriority; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticChatType)) return false; @@ -107,6 +108,7 @@ public boolean deepEquals(Object obj) { return this.narrationPriority == that.narrationPriority; } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.chatDecoration, this.overlayDecoration, this.narrationDecoration, this.narrationPriority); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/StaticWolfVariant.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/StaticWolfVariant.java index 7a8b4b4d7..5df581534 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/StaticWolfVariant.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/StaticWolfVariant.java @@ -82,6 +82,7 @@ public MappedEntitySet getBiomes() { return this.biomes; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticWolfVariant)) return false; @@ -93,6 +94,7 @@ public boolean deepEquals(Object obj) { return this.biomes.equals(that.biomes); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.wildTexture, this.tameTexture, this.angryTexture, this.biomes); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/WolfVariant.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/WolfVariant.java index 2d1690201..752a73d6c 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/WolfVariant.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/entity/wolfvariant/WolfVariant.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.protocol.entity.wolfvariant; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet; import com.github.retrooper.packetevents.protocol.nbt.NBT; @@ -31,7 +32,7 @@ import com.github.retrooper.packetevents.util.mappings.TypesBuilderData; import org.jetbrains.annotations.Nullable; -public interface WolfVariant extends MappedEntity, CopyableEntity { +public interface WolfVariant extends MappedEntity, CopyableEntity, DeepComparableEntity { ResourceLocation getWildTexture(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/BannerPattern.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/BannerPattern.java index fc228b8eb..dffdfa69f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/BannerPattern.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/BannerPattern.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.protocol.item.banner; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -29,7 +30,7 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper; import org.jetbrains.annotations.Nullable; -public interface BannerPattern extends MappedEntity, CopyableEntity { +public interface BannerPattern extends MappedEntity, CopyableEntity, DeepComparableEntity { ResourceLocation getAssetId(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/StaticBannerPattern.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/StaticBannerPattern.java index 5b40bf0d8..cb203787f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/StaticBannerPattern.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/banner/StaticBannerPattern.java @@ -55,6 +55,7 @@ public String getTranslationKey() { return this.translationKey; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticBannerPattern)) return false; @@ -64,6 +65,7 @@ public boolean deepEquals(Object obj) { return this.translationKey.equals(that.translationKey); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.assetId, this.translationKey); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/EnchantmentType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/EnchantmentType.java index edff9da01..ea407dd12 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/EnchantmentType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/EnchantmentType.java @@ -23,6 +23,7 @@ import com.github.retrooper.packetevents.protocol.component.StaticComponentMap; import com.github.retrooper.packetevents.protocol.item.enchantment.EnchantmentDefinition; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet; import com.github.retrooper.packetevents.protocol.nbt.NBT; @@ -35,7 +36,7 @@ import java.util.Optional; -public interface EnchantmentType extends MappedEntity, CopyableEntity { +public interface EnchantmentType extends MappedEntity, CopyableEntity, DeepComparableEntity { Component getDescription(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/StaticEnchantmentType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/StaticEnchantmentType.java index 6f01b368b..d90f4f055 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/StaticEnchantmentType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/enchantment/type/StaticEnchantmentType.java @@ -84,6 +84,7 @@ public StaticComponentMap getEffects() { return this.effects; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticEnchantmentType)) return false; @@ -95,6 +96,7 @@ public boolean deepEquals(Object obj) { return this.effects.equals(that.effects); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.description, this.definition, this.exclusiveSet, this.effects); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/IJukeboxSong.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/IJukeboxSong.java index da6b0cb06..3c43ab39c 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/IJukeboxSong.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/IJukeboxSong.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.protocol.item.jukebox; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -32,7 +33,8 @@ import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Nullable; -public interface IJukeboxSong extends MappedEntity, CopyableEntity { +public interface IJukeboxSong extends MappedEntity, CopyableEntity, DeepComparableEntity { + Sound getSound(); Component getDescription(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/JukeboxSong.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/JukeboxSong.java index aaf2dfd06..5934e1479 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/JukeboxSong.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/jukebox/JukeboxSong.java @@ -101,6 +101,7 @@ public void setComparatorOutput(int comparatorOutput) { this.comparatorOutput = comparatorOutput; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof JukeboxSong)) return false; @@ -112,6 +113,7 @@ public boolean deepEquals(Object obj) { return this.description.equals(that.description); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.sound, this.description, this.lengthInSeconds, this.comparatorOutput); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/StaticTrimMaterial.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/StaticTrimMaterial.java index ca5928677..09dd7649d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/StaticTrimMaterial.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/StaticTrimMaterial.java @@ -87,6 +87,7 @@ public Component getDescription() { return this.description; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticTrimMaterial)) return false; @@ -99,6 +100,7 @@ public boolean deepEquals(Object obj) { return this.description.equals(that.description); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.assetName, this.ingredient, this.itemModelIndex, this.overrideArmorMaterials, this.description); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/TrimMaterial.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/TrimMaterial.java index bc1038e4c..9460fda21 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/TrimMaterial.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimmaterial/TrimMaterial.java @@ -23,6 +23,7 @@ import com.github.retrooper.packetevents.protocol.item.type.ItemType; import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -39,7 +40,7 @@ import java.util.HashMap; import java.util.Map; -public interface TrimMaterial extends MappedEntity, CopyableEntity { +public interface TrimMaterial extends MappedEntity, CopyableEntity, DeepComparableEntity { String getAssetName(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/StaticTrimPattern.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/StaticTrimPattern.java index 1f6a7f586..1a1e55a1f 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/StaticTrimPattern.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/StaticTrimPattern.java @@ -79,6 +79,7 @@ public boolean isDecal() { return this.decal; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticTrimPattern)) return false; @@ -90,6 +91,7 @@ public boolean deepEquals(Object obj) { return this.description.equals(that.description); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.assetId, this.templateItem, this.description, this.decal); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/TrimPattern.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/TrimPattern.java index d20290b1b..8c38a8f6c 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/TrimPattern.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/trimpattern/TrimPattern.java @@ -21,6 +21,7 @@ import com.github.retrooper.packetevents.protocol.item.type.ItemType; import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTByte; @@ -34,7 +35,7 @@ import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Nullable; -public interface TrimPattern extends MappedEntity, CopyableEntity { +public interface TrimPattern extends MappedEntity, CopyableEntity, DeepComparableEntity { ResourceLocation getAssetId(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/Biome.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/Biome.java index 739c2d470..16701615e 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/Biome.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/Biome.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.protocol.world.biome; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTByte; @@ -35,7 +36,7 @@ import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow; -public interface Biome extends MappedEntity, CopyableEntity { +public interface Biome extends MappedEntity, CopyableEntity, DeepComparableEntity { boolean hasPrecipitation(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/StaticBiome.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/StaticBiome.java index 0e95c4d0f..a395045b8 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/StaticBiome.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/biome/StaticBiome.java @@ -153,6 +153,7 @@ public BiomeEffects getEffects() { return this.effects; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticBiome)) return false; @@ -168,6 +169,7 @@ public boolean deepEquals(Object obj) { return this.effects.equals(that.effects); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.precipitation, this.temperature, this.temperatureModifier, this.downfall, this.category, this.depth, this.scale, this.effects); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/DamageType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/DamageType.java index 84bd3a6bd..8f8826771 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/DamageType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/DamageType.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.protocol.world.damagetype; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -32,7 +33,7 @@ import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow; -public interface DamageType extends MappedEntity, CopyableEntity { +public interface DamageType extends MappedEntity, CopyableEntity, DeepComparableEntity { String getMessageId(); DamageScaling getScaling(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/StaticDamageType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/StaticDamageType.java index 5efe4a782..52a527f6d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/StaticDamageType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/damagetype/StaticDamageType.java @@ -73,6 +73,7 @@ public DeathMessageType getDeathMessageType() { return this.deathMessageType; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticDamageType)) return false; @@ -85,6 +86,7 @@ public boolean deepEquals(Object obj) { return this.deathMessageType == that.deathMessageType; } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.messageId, this.scaling, this.exhaustion, this.effects, this.deathMessageType); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/DimensionType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/DimensionType.java index a05bb33b3..857bef8e0 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/DimensionType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/DimensionType.java @@ -20,6 +20,7 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTByte; @@ -36,7 +37,7 @@ import java.util.OptionalLong; -public interface DimensionType extends MappedEntity, CopyableEntity { +public interface DimensionType extends MappedEntity, CopyableEntity, DeepComparableEntity { OptionalLong getFixedTime(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/StaticDimensionType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/StaticDimensionType.java index 362a11246..778b79ff0 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/StaticDimensionType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/dimension/StaticDimensionType.java @@ -187,6 +187,7 @@ public int getMonsterSpawnBlockLightLimit() { return this.monsterSpawnBlockLightLimit; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticDimensionType)) return false; @@ -212,6 +213,7 @@ public boolean deepEquals(Object obj) { return Objects.equals(this.monsterSpawnLightLevel, that.monsterSpawnLightLevel); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.fixedTime, this.hasSkyLight, this.hasCeiling, this.ultraWarm, this.natural, this.coordinateScale, this.bedWorking, this.respawnAnchorWorking, this.minY, this.height, this.logicalHeight, this.infiniburnTag, this.effectsLocation, this.ambientLight, this.piglinSafe, this.hasRaids, this.monsterSpawnLightLevel, this.monsterSpawnBlockLightLimit); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/PaintingVariant.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/PaintingVariant.java index afb3d9a79..3eec7376d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/PaintingVariant.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/PaintingVariant.java @@ -19,6 +19,7 @@ package com.github.retrooper.packetevents.protocol.world.painting; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -30,7 +31,7 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper; import org.jetbrains.annotations.Nullable; -public interface PaintingVariant extends MappedEntity, CopyableEntity { +public interface PaintingVariant extends MappedEntity, CopyableEntity, DeepComparableEntity { int getWidth(); diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/StaticPaintingVariant.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/StaticPaintingVariant.java index c7caacf01..9b6219f2d 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/StaticPaintingVariant.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/world/painting/StaticPaintingVariant.java @@ -62,6 +62,7 @@ public ResourceLocation getAssetId() { return this.assetId; } + @Override public boolean deepEquals(Object obj) { if (this == obj) return true; if (!(obj instanceof StaticPaintingVariant)) return false; @@ -72,6 +73,7 @@ public boolean deepEquals(Object obj) { return this.assetId.equals(that.assetId); } + @Override public int deepHashCode() { return Objects.hash(super.hashCode(), this.width, this.height, this.assetId); } From c9d42f8e8ee8e430d357cb8d8fe22f2db59999ae Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 20:34:37 +0200 Subject: [PATCH 6/9] Check for deep equals before using vanilla registry element Could potentially solve #962, although I can't reproduce that issue This may be caused by two different changes to packetevents: 1. We did a little memory optimization so only elements different to the vanilly registry get stored 2. We fixed an issue where some elements would not equal the "same" vanilla element This could cause every custom element to just never be registered, so we now do explicit deep-equals checks before saving the vanilla element instead --- .../util/mappings/SynchronizedRegistriesHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java b/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java index d12ca7bca..df0df4683 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java +++ b/api/src/main/java/com/github/retrooper/packetevents/util/mappings/SynchronizedRegistriesHandler.java @@ -36,6 +36,7 @@ import com.github.retrooper.packetevents.protocol.item.trimpattern.TrimPattern; import com.github.retrooper.packetevents.protocol.item.trimpattern.TrimPatterns; import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity; +import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity; import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; import com.github.retrooper.packetevents.protocol.nbt.NBT; import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; @@ -145,7 +146,7 @@ public interface NbtEntryDecoder { } @ApiStatus.Internal - public static final class RegistryEntry> { + public static final class RegistryEntry & DeepComparableEntity> { private final IRegistry baseRegistry; private final NbtEntryDecoder decoder; @@ -189,7 +190,7 @@ private void handleElement( if (element.getData() != null) { // data was provided, use registry element sent over network T value = this.decoder.decode(element.getData(), version, data); - if (!value.equals(copiedBaseEntry)) { + if (!value.deepEquals(copiedBaseEntry)) { // only define decoded value if it doesn't match the base // registry value this ensures we don't save everything twice, // if it has been already stored in memory From 7cdb95116ad42de72af5a4cc937538355adc5894 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 21:21:06 +0200 Subject: [PATCH 7/9] Implement all new components --- api/build.gradle.kts | 1 + .../protocol/component/ComponentTypes.java | 17 +++ .../builtin/item/ItemConsumable.java | 138 ++++++++++++++++++ .../builtin/item/ItemEnchantable.java | 67 +++++++++ .../builtin/item/ItemRepairable.java | 70 +++++++++ .../builtin/item/ItemUseCooldown.java | 101 +++++++++++++ .../builtin/item/ItemUseRemainder.java | 68 +++++++++ .../item/consumables/ConsumeEffect.java | 45 ++++++ .../item/consumables/ConsumeEffectType.java | 29 ++++ .../item/consumables/ConsumeEffectTypes.java | 64 ++++++++ .../consumables/StaticConsumeEffectType.java | 52 +++++++ .../builtin/ApplyEffectsConsumeEffect.java | 57 ++++++++ .../builtin/ClearAllEffectsConsumeEffect.java | 41 ++++++ .../builtin/PlaySoundConsumeEffect.java | 47 ++++++ .../builtin/RemoveEffectsConsumeEffect.java | 49 +++++++ .../TeleportRandomlyConsumeEffect.java | 46 ++++++ .../item/consume_effect_type_mappings.json | 9 ++ 17 files changed, 901 insertions(+) create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemConsumable.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemEnchantable.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemRepairable.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseCooldown.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseRemainder.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffect.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectType.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectTypes.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ApplyEffectsConsumeEffect.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ClearAllEffectsConsumeEffect.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/PlaySoundConsumeEffect.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/RemoveEffectsConsumeEffect.java create mode 100644 api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/TeleportRandomlyConsumeEffect.java create mode 100644 mappings/item/consume_effect_type_mappings.json diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 6a94d3951..05a891f17 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -73,6 +73,7 @@ mappingCompression { compress("entity/painting_mappings.json") compress("entity/wolf_variant_mappings.json") + compress("item/consume_effect_type_mappings.json") compress("item/item_armor_material_mappings.json") compress("item/item_banner_pattern_mappings.json") compress("item/item_component_mappings.json") diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/ComponentTypes.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/ComponentTypes.java index 9b2be9815..21304d315 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/ComponentTypes.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/ComponentTypes.java @@ -31,9 +31,11 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAttributeModifiers; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBees; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBlockStateProperties; +import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemConsumable; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerContents; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerLoot; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDyeColor; +import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantable; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemFireworks; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemJukeboxPlayable; @@ -45,7 +47,10 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemProfile; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRarity; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRecipes; +import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRepairable; import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTool; +import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUseCooldown; +import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUseRemainder; import com.github.retrooper.packetevents.protocol.component.builtin.item.LodestoneTracker; import com.github.retrooper.packetevents.protocol.component.builtin.item.PotDecorations; import com.github.retrooper.packetevents.protocol.component.builtin.item.SuspiciousStewEffects; @@ -220,6 +225,18 @@ public static ComponentType getById(ClientVersion version, int id) { public static final ComponentType JUKEBOX_PLAYABLE = define("jukebox_playable", ItemJukeboxPlayable::read, ItemJukeboxPlayable::write); + // added in 1.21.2 + public static final ComponentType CONSUMABLE = define("consumable", + ItemConsumable::read, ItemConsumable::write); + public static final ComponentType USE_REMAINDER = define("use_remainder", + ItemUseRemainder::read, ItemUseRemainder::write); + public static final ComponentType USE_COOLDOWN = define("use_cooldown", + ItemUseCooldown::read, ItemUseCooldown::write); + public static final ComponentType ENCHANTABLE = define("enchantable", + ItemEnchantable::read, ItemEnchantable::write); + public static final ComponentType REPAIRABLE = define("repairable", + ItemRepairable::read, ItemRepairable::write); + /** * Returns an immutable view of the component types. * diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemConsumable.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemConsumable.java new file mode 100644 index 000000000..33358c6f8 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemConsumable.java @@ -0,0 +1,138 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.component.builtin.item; + +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect; +import com.github.retrooper.packetevents.protocol.sound.Sound; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.util.List; +import java.util.Objects; + +public class ItemConsumable { + + private float consumeSeconds; + private Animation animation; + private Sound sound; + private boolean consumeParticles; + private List effects; + + public ItemConsumable( + float consumeSeconds, Animation animation, Sound sound, + boolean consumeParticles, List effects + ) { + this.consumeSeconds = consumeSeconds; + this.animation = animation; + this.sound = sound; + this.consumeParticles = consumeParticles; + this.effects = effects; + } + + public static ItemConsumable read(PacketWrapper wrapper) { + float consumeSeconds = wrapper.readFloat(); + Animation animation = wrapper.readEnum(Animation.values()); + Sound sound = Sound.read(wrapper); + boolean consumeParticles = wrapper.readBoolean(); + List effects = wrapper.readList(ConsumeEffect::readFull); + return new ItemConsumable(consumeSeconds, animation, sound, consumeParticles, effects); + } + + public static void write(PacketWrapper wrapper, ItemConsumable consumable) { + wrapper.writeFloat(consumable.consumeSeconds); + wrapper.writeEnum(consumable.animation); + Sound.write(wrapper, consumable.sound); + wrapper.writeBoolean(consumable.consumeParticles); + wrapper.writeList(consumable.effects, ConsumeEffect::writeFull); + } + + public float getConsumeSeconds() { + return this.consumeSeconds; + } + + public void setConsumeSeconds(float consumeSeconds) { + this.consumeSeconds = consumeSeconds; + } + + public Animation getAnimation() { + return this.animation; + } + + public void setAnimation(Animation animation) { + this.animation = animation; + } + + public Sound getSound() { + return this.sound; + } + + public void setSound(Sound sound) { + this.sound = sound; + } + + public boolean isConsumeParticles() { + return this.consumeParticles; + } + + public void setConsumeParticles(boolean consumeParticles) { + this.consumeParticles = consumeParticles; + } + + public List getEffects() { + return this.effects; + } + + public void setEffects(List effects) { + this.effects = effects; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ItemConsumable)) return false; + ItemConsumable that = (ItemConsumable) obj; + if (Float.compare(that.consumeSeconds, this.consumeSeconds) != 0) return false; + if (this.consumeParticles != that.consumeParticles) return false; + if (this.animation != that.animation) return false; + if (!this.sound.equals(that.sound)) return false; + return this.effects.equals(that.effects); + } + + @Override + public int hashCode() { + return Objects.hash(this.consumeSeconds, this.animation, this.sound, this.consumeParticles, this.effects); + } + + @Override + public String toString() { + return "ItemConsumable{consumeSeconds=" + this.consumeSeconds + ", animation=" + this.animation + ", sound=" + this.sound + ", consumeParticles=" + this.consumeParticles + ", effects=" + this.effects + '}'; + } + + public enum Animation { + NONE, + EAT, + DRINK, + BLOCK, + BOW, + SPEAR, + CROSSBOW, + SPYGLASS, + TOOT_HORN, + BRUSH, + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemEnchantable.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemEnchantable.java new file mode 100644 index 000000000..5836d33cc --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemEnchantable.java @@ -0,0 +1,67 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.component.builtin.item; + +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.util.Objects; + +public class ItemEnchantable { + + private int value; + + public ItemEnchantable(int value) { + this.value = value; + } + + public static ItemEnchantable read(PacketWrapper wrapper) { + int value = wrapper.readVarInt(); + return new ItemEnchantable(value); + } + + public static void write(PacketWrapper wrapper, ItemEnchantable enchantable) { + wrapper.writeVarInt(enchantable.value); + } + + public int getValue() { + return this.value; + } + + public void setValue(int value) { + this.value = value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ItemEnchantable)) return false; + ItemEnchantable that = (ItemEnchantable) obj; + return this.value == that.value; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.value); + } + + @Override + public String toString() { + return "ItemEnchantable{value=" + this.value + '}'; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemRepairable.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemRepairable.java new file mode 100644 index 000000000..e6fb5c7a5 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemRepairable.java @@ -0,0 +1,70 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.component.builtin.item; + +import com.github.retrooper.packetevents.protocol.item.type.ItemType; +import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; +import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.util.Objects; + +public class ItemRepairable { + + private MappedEntitySet items; + + public ItemRepairable(MappedEntitySet items) { + this.items = items; + } + + public static ItemRepairable read(PacketWrapper wrapper) { + MappedEntitySet items = MappedEntitySet.read(wrapper, ItemTypes.getRegistry()); + return new ItemRepairable(items); + } + + public static void write(PacketWrapper wrapper, ItemRepairable repairable) { + MappedEntitySet.write(wrapper, repairable.items); + } + + public MappedEntitySet getItems() { + return this.items; + } + + public void setItems(MappedEntitySet items) { + this.items = items; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ItemRepairable)) return false; + ItemRepairable that = (ItemRepairable) obj; + return this.items.equals(that.items); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.items); + } + + @Override + public String toString() { + return "ItemRepairable{items=" + this.items + '}'; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseCooldown.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseCooldown.java new file mode 100644 index 000000000..c1c7fe73d --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseCooldown.java @@ -0,0 +1,101 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.component.builtin.item; + +import com.github.retrooper.packetevents.protocol.item.ItemStack; +import com.github.retrooper.packetevents.protocol.item.type.ItemType; +import com.github.retrooper.packetevents.resources.ResourceLocation; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetCooldown; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.Optional; + +public class ItemUseCooldown { + + private float seconds; + private Optional cooldownGroup; + + public ItemUseCooldown(float seconds, @Nullable ResourceLocation cooldownGroup) { + this(seconds, Optional.ofNullable(cooldownGroup)); + } + + public ItemUseCooldown(float seconds, Optional cooldownGroup) { + this.seconds = seconds; + this.cooldownGroup = cooldownGroup; + } + + public static ItemUseCooldown read(PacketWrapper wrapper) { + float seconds = wrapper.readFloat(); + ResourceLocation cooldownGroup = wrapper.readOptional(PacketWrapper::readIdentifier); + return new ItemUseCooldown(seconds, cooldownGroup); + } + + public static void write(PacketWrapper wrapper, ItemUseCooldown cooldown) { + wrapper.writeFloat(cooldown.seconds); + wrapper.writeOptional(cooldown.cooldownGroup.orElse(null), PacketWrapper::writeIdentifier); + } + + public WrapperPlayServerSetCooldown buildWrapper(ItemStack fallbackStack) { + return this.buildWrapper(fallbackStack.getType()); + } + + public WrapperPlayServerSetCooldown buildWrapper(ItemType fallbackItem) { + int ticks = (int) (this.seconds * 20f); + return this.cooldownGroup + .map(resourceLocation -> new WrapperPlayServerSetCooldown(resourceLocation, ticks)) + .orElseGet(() -> new WrapperPlayServerSetCooldown(fallbackItem, ticks)); + } + + public float getSeconds() { + return this.seconds; + } + + public void setSeconds(float seconds) { + this.seconds = seconds; + } + + public Optional getCooldownGroup() { + return this.cooldownGroup; + } + + public void setCooldownGroup(Optional cooldownGroup) { + this.cooldownGroup = cooldownGroup; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ItemUseCooldown)) return false; + ItemUseCooldown that = (ItemUseCooldown) obj; + if (Float.compare(that.seconds, this.seconds) != 0) return false; + return this.cooldownGroup.equals(that.cooldownGroup); + } + + @Override + public int hashCode() { + return Objects.hash(this.seconds, this.cooldownGroup); + } + + @Override + public String toString() { + return "ItemUseCooldown{seconds=" + this.seconds + ", cooldownGroup=" + this.cooldownGroup + '}'; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseRemainder.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseRemainder.java new file mode 100644 index 000000000..8e4f6ea2d --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/component/builtin/item/ItemUseRemainder.java @@ -0,0 +1,68 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.component.builtin.item; + +import com.github.retrooper.packetevents.protocol.item.ItemStack; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.util.Objects; + +public class ItemUseRemainder { + + private ItemStack target; + + public ItemUseRemainder(ItemStack target) { + this.target = target; + } + + public static ItemUseRemainder read(PacketWrapper wrapper) { + ItemStack target = wrapper.readItemStack(); + return new ItemUseRemainder(target); + } + + public static void write(PacketWrapper wrapper, ItemUseRemainder remainder) { + wrapper.writeItemStack(remainder.target); + } + + public ItemStack getTarget() { + return this.target; + } + + public void setTarget(ItemStack target) { + this.target = target; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ItemUseRemainder)) return false; + ItemUseRemainder that = (ItemUseRemainder) obj; + return this.target.equals(that.target); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.target); + } + + @Override + public String toString() { + return "ItemUseRemainder{target=" + this.target + '}'; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffect.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffect.java new file mode 100644 index 000000000..b38a33940 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffect.java @@ -0,0 +1,45 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables; + +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public abstract class ConsumeEffect> { + + protected final ConsumeEffectType type; + + protected ConsumeEffect(ConsumeEffectType type) { + this.type = type; + } + + public static ConsumeEffect readFull(PacketWrapper wrapper) { + ConsumeEffectType type = wrapper.readMappedEntity(ConsumeEffectTypes.getRegistry()); + return type.read(wrapper); + } + + @SuppressWarnings("unchecked") // I hate generics + public static > void writeFull(PacketWrapper wrapper, ConsumeEffect effect) { + wrapper.writeMappedEntity(effect.getType()); + ((ConsumeEffectType>) effect.getType()).write(wrapper, effect); + } + + public ConsumeEffectType getType() { + return this.type; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectType.java new file mode 100644 index 000000000..71a05b1fa --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectType.java @@ -0,0 +1,29 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables; + +import com.github.retrooper.packetevents.protocol.mapper.MappedEntity; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public interface ConsumeEffectType> extends MappedEntity { + + T read(PacketWrapper wrapper); + + void write(PacketWrapper wrapper, T effect); +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectTypes.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectTypes.java new file mode 100644 index 000000000..9ca17f2fc --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/ConsumeEffectTypes.java @@ -0,0 +1,64 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables; + +import com.github.retrooper.packetevents.protocol.item.consumables.builtin.ApplyEffectsConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.builtin.ClearAllEffectsConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.builtin.PlaySoundConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.builtin.RemoveEffectsConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.builtin.TeleportRandomlyConsumeEffect; +import com.github.retrooper.packetevents.util.mappings.VersionedRegistry; +import com.github.retrooper.packetevents.wrapper.PacketWrapper.Reader; +import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer; +import org.jetbrains.annotations.ApiStatus; + +public final class ConsumeEffectTypes { + + private static final VersionedRegistry> REGISTRY = new VersionedRegistry<>( + "consume_effect_type", "item/consume_effect_type_mappings"); + + private ConsumeEffectTypes() { + } + + @ApiStatus.Internal + public static > ConsumeEffectType define( + String name, Reader reader, Writer writer) { + return REGISTRY.define(name, data -> + new StaticConsumeEffectType<>(data, reader, writer)); + } + + public static final ConsumeEffectType APPLY_EFFECTS = define( + "apply_effects", ApplyEffectsConsumeEffect::read, ApplyEffectsConsumeEffect::write); + public static final ConsumeEffectType REMOVE_EFFECTS = define( + "remove_effects", RemoveEffectsConsumeEffect::read, RemoveEffectsConsumeEffect::write); + public static final ConsumeEffectType CLEAR_ALL_EFFECTS = define( + "clear_all_effects", ClearAllEffectsConsumeEffect::read, ClearAllEffectsConsumeEffect::write); + public static final ConsumeEffectType TELEPORT_RANDOMLY = define( + "teleport_randomly", TeleportRandomlyConsumeEffect::read, TeleportRandomlyConsumeEffect::write); + public static final ConsumeEffectType PLAY_SOUND = define( + "play_sound", PlaySoundConsumeEffect::read, PlaySoundConsumeEffect::write); + + public static VersionedRegistry> getRegistry() { + return REGISTRY; + } + + static { + REGISTRY.unloadMappings(); + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java new file mode 100644 index 000000000..e1902b655 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java @@ -0,0 +1,52 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables; + +import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity; +import com.github.retrooper.packetevents.util.mappings.TypesBuilderData; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; +import com.github.retrooper.packetevents.wrapper.PacketWrapper.Reader; +import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer; +import org.jetbrains.annotations.Nullable; + +public class StaticConsumeEffectType extends AbstractMappedEntity implements ConsumeEffectType { + + private final Reader reader; + private final Writer writer; + + public StaticConsumeEffectType( + @Nullable TypesBuilderData data, + Reader reader, + Writer writer + ) { + super(data); + this.reader = reader; + this.writer = writer; + } + + @Override + public T read(PacketWrapper wrapper) { + return this.reader.apply(wrapper); + } + + @Override + public void write(PacketWrapper wrapper, T effect) { + this.writer.accept(wrapper, effect); + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ApplyEffectsConsumeEffect.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ApplyEffectsConsumeEffect.java new file mode 100644 index 000000000..aa0d7b79c --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ApplyEffectsConsumeEffect.java @@ -0,0 +1,57 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables.builtin; + +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes; +import com.github.retrooper.packetevents.protocol.potion.PotionEffect; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.util.List; + +public class ApplyEffectsConsumeEffect extends ConsumeEffect { + + private final List effects; + private final float probability; + + public ApplyEffectsConsumeEffect(List effects, float probability) { + super(ConsumeEffectTypes.APPLY_EFFECTS); + this.effects = effects; + this.probability = probability; + } + + public static ApplyEffectsConsumeEffect read(PacketWrapper wrapper) { + List effects = wrapper.readList(PotionEffect::read); + float probability = wrapper.readFloat(); + return new ApplyEffectsConsumeEffect(effects, probability); + } + + public static void write(PacketWrapper wrapper, ApplyEffectsConsumeEffect effect) { + wrapper.writeList(effect.effects, PotionEffect::write); + wrapper.writeFloat(effect.probability); + } + + public List getEffects() { + return this.effects; + } + + public float getProbability() { + return this.probability; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ClearAllEffectsConsumeEffect.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ClearAllEffectsConsumeEffect.java new file mode 100644 index 000000000..8af981bdc --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/ClearAllEffectsConsumeEffect.java @@ -0,0 +1,41 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables.builtin; + +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectType; +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class ClearAllEffectsConsumeEffect extends ConsumeEffect { + + public static final ClearAllEffectsConsumeEffect INSTANCE = new ClearAllEffectsConsumeEffect(); + + private ClearAllEffectsConsumeEffect() { + super(ConsumeEffectTypes.CLEAR_ALL_EFFECTS); + } + + public static ClearAllEffectsConsumeEffect read(PacketWrapper ignoredWrapper) { + return INSTANCE; + } + + public static void write(PacketWrapper ignoredWrapper, ClearAllEffectsConsumeEffect ignoredEffect) { + // NO-OP + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/PlaySoundConsumeEffect.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/PlaySoundConsumeEffect.java new file mode 100644 index 000000000..89f177bcc --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/PlaySoundConsumeEffect.java @@ -0,0 +1,47 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables.builtin; + +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes; +import com.github.retrooper.packetevents.protocol.sound.Sound; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class PlaySoundConsumeEffect extends ConsumeEffect { + + private final Sound sound; + + public PlaySoundConsumeEffect(Sound sound) { + super(ConsumeEffectTypes.PLAY_SOUND); + this.sound = sound; + } + + public static PlaySoundConsumeEffect read(PacketWrapper wrapper) { + Sound sound = Sound.read(wrapper); + return new PlaySoundConsumeEffect(sound); + } + + public static void write(PacketWrapper wrapper, PlaySoundConsumeEffect effect) { + Sound.write(wrapper, effect.sound); + } + + public Sound getSound() { + return this.sound; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/RemoveEffectsConsumeEffect.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/RemoveEffectsConsumeEffect.java new file mode 100644 index 000000000..caabcdc4a --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/RemoveEffectsConsumeEffect.java @@ -0,0 +1,49 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables.builtin; + +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes; +import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet; +import com.github.retrooper.packetevents.protocol.potion.PotionType; +import com.github.retrooper.packetevents.protocol.potion.PotionTypes; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class RemoveEffectsConsumeEffect extends ConsumeEffect { + + private final MappedEntitySet effects; + + public RemoveEffectsConsumeEffect(MappedEntitySet effects) { + super(ConsumeEffectTypes.REMOVE_EFFECTS); + this.effects = effects; + } + + public static RemoveEffectsConsumeEffect read(PacketWrapper wrapper) { + MappedEntitySet effects = MappedEntitySet.read(wrapper, PotionTypes::getById); + return new RemoveEffectsConsumeEffect(effects); + } + + public static void write(PacketWrapper wrapper, RemoveEffectsConsumeEffect effect) { + MappedEntitySet.write(wrapper, effect.effects); + } + + public MappedEntitySet getEffects() { + return this.effects; + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/TeleportRandomlyConsumeEffect.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/TeleportRandomlyConsumeEffect.java new file mode 100644 index 000000000..138a132f6 --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/builtin/TeleportRandomlyConsumeEffect.java @@ -0,0 +1,46 @@ +/* + * This file is part of packetevents - https://github.com/retrooper/packetevents + * Copyright (C) 2024 retrooper and 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 . + */ + +package com.github.retrooper.packetevents.protocol.item.consumables.builtin; + +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect; +import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +public class TeleportRandomlyConsumeEffect extends ConsumeEffect { + + private final float diameter; + + public TeleportRandomlyConsumeEffect(float diameter) { + super(ConsumeEffectTypes.TELEPORT_RANDOMLY); + this.diameter = diameter; + } + + public static TeleportRandomlyConsumeEffect read(PacketWrapper wrapper) { + float diameter = wrapper.readFloat(); + return new TeleportRandomlyConsumeEffect(diameter); + } + + public static void write(PacketWrapper wrapper, TeleportRandomlyConsumeEffect effect) { + wrapper.writeFloat(effect.diameter); + } + + public float getDiameter() { + return this.diameter; + } +} diff --git a/mappings/item/consume_effect_type_mappings.json b/mappings/item/consume_effect_type_mappings.json new file mode 100644 index 000000000..77e86a35f --- /dev/null +++ b/mappings/item/consume_effect_type_mappings.json @@ -0,0 +1,9 @@ +{ + "V_1_21_2": [ + "apply_effects", + "remove_effects", + "clear_all_effects", + "teleport_randomly", + "play_sound" + ] +} From bdccde4040290d51e0ccc2a1fda783b4c8e8bce0 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 21:44:45 +0200 Subject: [PATCH 8/9] Fix compile issue with StaticConsumeEffectType --- .../protocol/item/consumables/StaticConsumeEffectType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java index e1902b655..ff050341b 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java +++ b/api/src/main/java/com/github/retrooper/packetevents/protocol/item/consumables/StaticConsumeEffectType.java @@ -25,7 +25,7 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer; import org.jetbrains.annotations.Nullable; -public class StaticConsumeEffectType extends AbstractMappedEntity implements ConsumeEffectType { +public class StaticConsumeEffectType> extends AbstractMappedEntity implements ConsumeEffectType { private final Reader reader; private final Writer writer; From 1260aa1de5634cb73efa801f4a6dfc5f6d78d133 Mon Sep 17 00:00:00 2001 From: booky10 Date: Fri, 30 Aug 2024 22:53:19 +0200 Subject: [PATCH 9/9] Add some transformations for slot changes --- .../util/PacketTransformationUtil.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/com/github/retrooper/packetevents/util/PacketTransformationUtil.java b/api/src/main/java/com/github/retrooper/packetevents/util/PacketTransformationUtil.java index a2c9fa2a8..4e333f7fd 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/util/PacketTransformationUtil.java +++ b/api/src/main/java/com/github/retrooper/packetevents/util/PacketTransformationUtil.java @@ -19,13 +19,15 @@ package com.github.retrooper.packetevents.util; import com.github.retrooper.packetevents.manager.server.ServerVersion; -import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper; import com.github.retrooper.packetevents.protocol.player.Equipment; import com.github.retrooper.packetevents.protocol.world.chunk.LightData; import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChunkData; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetCursorItem; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPlayerInventory; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetSlot; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateLight; import java.util.Collections; @@ -73,6 +75,18 @@ public static PacketWrapper[] transform(PacketWrapper wrapper) { return output; } + } else if (wrapper instanceof WrapperPlayServerSetSlot) { + // some plugins will probably fail to update this correctly, so just transform it when sending + WrapperPlayServerSetSlot setSlot = (WrapperPlayServerSetSlot) wrapper; + if (setSlot.getSlot() == -1) { // transform to cursor item + if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + wrapper = new WrapperPlayServerSetCursorItem(setSlot.getItem()); + } + } else if (setSlot.getWindowId() == -2) { // transform to player inventory set + if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) { + wrapper = new WrapperPlayServerSetPlayerInventory(setSlot.getSlot(), setSlot.getItem()); + } + } } return new PacketWrapper[]{wrapper}; }