From f68aed464db9c3d4803276ed50971b81fe7e00c8 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Thu, 29 Feb 2024 19:59:18 +0100 Subject: [PATCH] Once again refactor structured data storage Optionals are no more --- .../minecraft/data/EmptyStructuredData.java | 70 +++++++++++ .../minecraft/data/FilledStructuredData.java | 75 ++++++++++++ .../api/minecraft/data/StructuredData.java | 84 +++++++------ .../data/StructuredDataContainer.java | 102 ++++++++-------- .../api/type/types/item/ItemType1_20_5.java | 53 +++++---- .../type/types/item/StructuredDataType.java | 7 +- .../api/type/types/version/Types1_20_5.java | 4 +- .../kotlin/via.shadow-conventions.gradle.kts | 7 +- .../Protocol1_20_5To1_20_3.java | 10 +- .../BlockItemPacketRewriter1_20_5.java | 111 +++++++++--------- .../viaversion/rewriter/ItemRewriter.java | 2 - .../rewriter/StructuredItemRewriter.java | 81 +++++++++++++ .../rewriter/BlockItemPacketRewriter1_99.java | 5 +- 13 files changed, 429 insertions(+), 182 deletions(-) create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/data/EmptyStructuredData.java create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/data/FilledStructuredData.java create mode 100644 common/src/main/java/com/viaversion/viaversion/rewriter/StructuredItemRewriter.java diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/EmptyStructuredData.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/EmptyStructuredData.java new file mode 100644 index 000000000..0ca603c7d --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/EmptyStructuredData.java @@ -0,0 +1,70 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2024 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.minecraft.data; + +import io.netty.buffer.ByteBuf; + +final class EmptyStructuredData implements StructuredData { + + private final StructuredDataKey key; + private int id; + + EmptyStructuredData(final StructuredDataKey key, final int id) { + this.key = key; + this.id = id; + } + + @Override + public void setValue(final T value) { + throw new UnsupportedOperationException(); + } + + @Override + public void write(final ByteBuf buffer) { + } + + @Override + public void setId(final int id) { + this.id = id; + } + + @Override + public StructuredDataKey key() { + return this.key; + } + + @Override + public T value() { + return null; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public int id() { + return this.id; + } +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/FilledStructuredData.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/FilledStructuredData.java new file mode 100644 index 000000000..1d1fb4169 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/FilledStructuredData.java @@ -0,0 +1,75 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2024 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.minecraft.data; + +import com.google.common.base.Preconditions; +import io.netty.buffer.ByteBuf; + +final class FilledStructuredData implements StructuredData { + + private final StructuredDataKey key; + private T value; + private int id; + + FilledStructuredData(final StructuredDataKey key, final T value, final int id) { + Preconditions.checkNotNull(key); + this.key = key; + this.value = value; + this.id = id; + } + + @Override + public void setValue(final T value) { + this.value = value; + } + + @Override + public void write(final ByteBuf buffer) throws Exception { + key.type().write(buffer, value); + } + + @Override + public void setId(final int id) { + this.id = id; + } + + @Override + public StructuredDataKey key() { + return key; + } + + @Override + public T value() { + return value; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public int id() { + return id; + } +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredData.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredData.java index d1f5afea1..3d7cf69f4 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredData.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredData.java @@ -22,53 +22,59 @@ */ package com.viaversion.viaversion.api.minecraft.data; -import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.util.IdHolder; -import com.viaversion.viaversion.util.Unit; import io.netty.buffer.ByteBuf; +import org.checkerframework.checker.nullness.qual.Nullable; -public final class StructuredData implements IdHolder { +public interface StructuredData extends IdHolder { - private final StructuredDataKey key; - private T value; - private int id; - - public StructuredData(final StructuredDataKey key, final T value, final int id) { - this.key = key; - this.value = value; - this.id = id; + /** + * Returns filled structured data, equivalent to an Optional with a value in vanilla. + * + * @param key serializer key + * @param value value + * @param id serializer id + * @param serializer type + * @return filled structured data + */ + static StructuredData of(final StructuredDataKey key, final T value, final int id) { + return new FilledStructuredData<>(key, value, id); } - public boolean isEmpty() { - return key.type() == Type.UNIT; + /** + * Returns empty structured data, equivalent to an empty Optional in vanilla. + * + * @param key serializer key + * @param id serializer id + * @return empty structured data + */ + static StructuredData empty(final StructuredDataKey key, final int id) { + return new EmptyStructuredData<>(key, id); } - public void setValue(final T value) { - if (value != null && !key.type().getOutputClass().isAssignableFrom(value.getClass())) { - throw new IllegalArgumentException("Item data type and value are incompatible. Type=" + key - + ", value=" + value + " (" + value.getClass().getSimpleName() + ")"); - } - this.value = value; + void setValue(final T value); + + void write(final ByteBuf buffer) throws Exception; + + void setId(final int id); + + StructuredDataKey key(); + + @Nullable T value(); + + /** + * Returns whether the structured data is present. Even if true, the value may be null. + * + * @return true if the structured data is present + */ + default boolean isPresent() { + return !isEmpty(); } - public void write(final ByteBuf buffer) throws Exception { - key.type().write(buffer, value); - } - - public void setId(final int id) { - this.id = id; - } - - public StructuredDataKey key() { - return key; - } - - public T value() { - return value; - } - - @Override - public int id() { - return id; - } + /** + * Returns whether the structured data is empty. Not to be confused with a null value. + * + * @return true if the structured data is empty + */ + boolean isEmpty(); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataContainer.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataContainer.java index f6f7daff4..01b21d1a5 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataContainer.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataContainer.java @@ -23,96 +23,106 @@ package com.viaversion.viaversion.api.minecraft.data; import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.data.FullMappings; import com.viaversion.viaversion.api.protocol.Protocol; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.util.Optional; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.Nullable; public final class StructuredDataContainer { - private final Int2ObjectMap>> data; // Bless Optionals in a map + private final Map, StructuredData> data; + private FullMappings lookup; + private boolean mappedNames; - public StructuredDataContainer(final Int2ObjectMap>> data) { + public StructuredDataContainer(final Map, StructuredData> data) { this.data = data; } public StructuredDataContainer() { - this(new Int2ObjectOpenHashMap<>()); + this(new Reference2ObjectOpenHashMap<>()); } /** - * Returns structured data by id. You might want to call {@link #contains(int)} first. + * Returns structured data by id if present. * - * @param id serializer id + * @param key serializer id * @param data type * @return structured data */ - public Optional> get(final int id) { - return this.data.getOrDefault(id, Optional.empty()); + public @Nullable StructuredData get(final StructuredDataKey key) { + //noinspection unchecked + return (StructuredData) this.data.get(key); } /** - * Returns structured data by id. You might want to call {@link #contains(Protocol, StructuredDataKey)} first. + * Returns structured data by id if not empty. * - * @param protocol protocol to retreive the id of the serializer from - * @param key serializer id - * @param data type - * @return structured data + * @param key serializer id + * @param data type + * @return structured data if not empty */ - public Optional> get(final Protocol protocol, final StructuredDataKey key) { - final Optional> data = this.data.getOrDefault(serializerId(protocol, key), Optional.empty()); + public @Nullable StructuredData getNonEmpty(final StructuredDataKey key) { //noinspection unchecked - return data.map(value -> (StructuredData) value); + final StructuredData data = (StructuredData) this.data.get(key); + return data != null && data.isPresent() ? data : null; } - public void add(final StructuredData data) { - this.data.put(data.id(), Optional.of(data)); - } - - public void add(final Protocol protocol, final StructuredDataKey key, final T value) { - final int id = serializerId(protocol, key); + public void add(final StructuredDataKey key, final T value) { + final int id = serializerId(key); if (id != -1) { - add(new StructuredData<>(key, value, id)); + this.data.put(key, StructuredData.of(key, value, id)); } } - public void addEmpty(final Protocol protocol, final StructuredDataKey key) { - final int id = serializerId(protocol, key); - if (id != -1) { - this.data.put(id, Optional.empty()); - } - } - - public void remove(final int id) { - this.data.remove(id); - } - - public void removeDefault(final int id) { + public void addEmpty(final StructuredDataKey key) { // Empty optional to override the Minecraft default - this.data.put(id, Optional.empty()); + this.data.put(key, StructuredData.empty(key, serializerId(key))); } - public boolean contains(final int id) { - return this.data.containsKey(id); + /** + * Removes and returns structured data by the given key. + * + * @param key serializer key + * @param data type + * @return removed structured data + */ + public @Nullable StructuredData remove(final StructuredDataKey key) { + final StructuredData data = this.data.remove(key); + //noinspection unchecked + return data != null ? (StructuredData) data : null; } - public boolean contains(final Protocol protocol, final StructuredDataKey key) { - return this.data.containsKey(serializerId(protocol, key)); + public boolean contains(final StructuredDataKey key) { + return this.data.containsKey(key); + } + + /** + * Sets the lookup for serializer ids. Required to call most of the other methods. + * + * @param protocol protocol to retreive the id of the serializer from + * @param mappedNames if the names are mapped (true if structures from the mapped version are added, false for the unmapped version) + */ + public void setIdLookup(final Protocol protocol, final boolean mappedNames) { + this.lookup = protocol.getMappingData().getDataComponentSerializerMappings(); + this.mappedNames = mappedNames; } public StructuredDataContainer copy() { - return new StructuredDataContainer(new Int2ObjectOpenHashMap<>(data)); + final StructuredDataContainer copy = new StructuredDataContainer(new Reference2ObjectOpenHashMap<>(data)); + copy.lookup = this.lookup; + return copy; } - private int serializerId(final Protocol protocol, final StructuredDataKey key) { - final int id = protocol.getMappingData().getDataComponentSerializerMappings().mappedId(key.identifier()); + private int serializerId(final StructuredDataKey key) { + final int id = mappedNames ? lookup.mappedId(key.identifier()) : lookup.id(key.identifier()); if (id == -1) { Via.getPlatform().getLogger().severe("Could not find item data serializer for type " + key); } return id; } - public Int2ObjectMap>> data() { + public Map, StructuredData> data() { return data; } } diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/item/ItemType1_20_5.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/item/ItemType1_20_5.java index b1773d41a..8a149f053 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/item/ItemType1_20_5.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/item/ItemType1_20_5.java @@ -22,24 +22,25 @@ */ package com.viaversion.viaversion.api.type.types.item; -import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer; -import com.viaversion.viaversion.api.minecraft.item.Item; +import com.google.common.base.Preconditions; import com.viaversion.viaversion.api.minecraft.data.StructuredData; +import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer; +import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey; +import com.viaversion.viaversion.api.minecraft.item.Item; import com.viaversion.viaversion.api.minecraft.item.StructuredItem; import com.viaversion.viaversion.api.type.Type; import io.netty.buffer.ByteBuf; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.util.Optional; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import java.util.Map; import org.checkerframework.checker.nullness.qual.Nullable; public class ItemType1_20_5 extends Type { - private final Type> dataType; + private final StructuredDataType dataType; - public ItemType1_20_5(final Type> itemDataType) { + public ItemType1_20_5(final StructuredDataType dataType) { super(Item.class); - this.dataType = itemDataType; + this.dataType = dataType; } @Override @@ -50,26 +51,30 @@ public class ItemType1_20_5 extends Type { } final int id = Type.VAR_INT.readPrimitive(buffer); - final Int2ObjectMap>> data = readData(buffer); + final Map, StructuredData> data = readData(buffer); return new StructuredItem(id, amount, new StructuredDataContainer(data)); } - private Int2ObjectMap>> readData(final ByteBuf buffer) throws Exception { + private Map, StructuredData> readData(final ByteBuf buffer) throws Exception { final int valuesSize = Type.VAR_INT.readPrimitive(buffer); final int markersSize = Type.VAR_INT.readPrimitive(buffer); if (valuesSize == 0 && markersSize == 0) { - return new Int2ObjectOpenHashMap<>(); + return new Reference2ObjectOpenHashMap<>(); } - final Int2ObjectMap>> map = new Int2ObjectOpenHashMap<>(valuesSize + markersSize); + final Map, StructuredData> map = new Reference2ObjectOpenHashMap<>(valuesSize + markersSize); for (int i = 0; i < valuesSize; i++) { final StructuredData value = dataType.read(buffer); - map.put(value.id(), Optional.of(value)); + final StructuredDataKey key = dataType.key(value.id()); + Preconditions.checkNotNull(key, "No data component serializer found for $s", value); + map.put(key, value); } for (int i = 0; i < markersSize; i++) { - final int key = Type.VAR_INT.readPrimitive(buffer); - map.put(key, Optional.empty()); + final int id = Type.VAR_INT.readPrimitive(buffer); + final StructuredDataKey key = dataType.key(id); + Preconditions.checkNotNull(key, "No data component serializer found for empty id $s", id); + map.put(key, StructuredData.empty(key, id)); } return map; } @@ -84,11 +89,11 @@ public class ItemType1_20_5 extends Type { buffer.writeByte(object.amount()); Type.VAR_INT.writePrimitive(buffer, object.identifier()); - final Int2ObjectMap>> data = object.structuredData().data(); + final Map, StructuredData> data = object.structuredData().data(); int valuesSize = 0; int markersSize = 0; - for (final Int2ObjectMap.Entry>> entry : data.int2ObjectEntrySet()) { - if (entry.getValue().isPresent()) { + for (final StructuredData value : data.values()) { + if (value.isPresent()) { valuesSize++; } else { markersSize++; @@ -98,14 +103,14 @@ public class ItemType1_20_5 extends Type { Type.VAR_INT.writePrimitive(buffer, valuesSize); Type.VAR_INT.writePrimitive(buffer, markersSize); - for (final Int2ObjectMap.Entry>> entry : data.int2ObjectEntrySet()) { - if (entry.getValue().isPresent()) { - dataType.write(buffer, entry.getValue().get()); + for (final StructuredData value : data.values()) { + if (value.isPresent()) { + dataType.write(buffer, value); } } - for (final Int2ObjectMap.Entry>> entry : data.int2ObjectEntrySet()) { - if (!entry.getValue().isPresent()) { - Type.VAR_INT.writePrimitive(buffer, entry.getIntKey()); + for (final StructuredData value : data.values()) { + if (value.isEmpty()) { + Type.VAR_INT.writePrimitive(buffer, value.id()); } } } diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/item/StructuredDataType.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/item/StructuredDataType.java index 6ef84b73f..813b221d6 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/item/StructuredDataType.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/item/StructuredDataType.java @@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.type.Type; import io.netty.buffer.ByteBuf; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.checkerframework.checker.nullness.qual.Nullable; public class StructuredDataType extends Type> { @@ -55,8 +56,12 @@ public class StructuredDataType extends Type> { throw new IllegalArgumentException("No data component serializer found for id " + id); } + public @Nullable StructuredDataKey key(final int id) { + return types.get(id); + } + private StructuredData readData(final ByteBuf buffer, final StructuredDataKey key, final int id) throws Exception { - return new StructuredData<>(key, key.type().read(buffer), id); + return StructuredData.of(key, key.type().read(buffer), id); } public DataFiller filler(final Protocol protocol) { diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_5.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_5.java index 86f0a07f1..daba1e0a7 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_5.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_5.java @@ -38,8 +38,8 @@ public final class Types1_20_5 { // Most of these are only safe to use after protocol loading public static final ParticleType PARTICLE = new ParticleType(); - public static final StructuredDataType ITEM_DATA = new StructuredDataType(); - public static final Type ITEM = new ItemType1_20_5(ITEM_DATA); + public static final StructuredDataType STRUCTURED_DATA = new StructuredDataType(); + public static final Type ITEM = new ItemType1_20_5(STRUCTURED_DATA); public static final Type ITEM_ARRAY = new ArrayType<>(ITEM); public static final MetaTypes1_20_5 META_TYPES = new MetaTypes1_20_5(PARTICLE); public static final Type METADATA = new MetadataType(META_TYPES); diff --git a/build-logic/src/main/kotlin/via.shadow-conventions.gradle.kts b/build-logic/src/main/kotlin/via.shadow-conventions.gradle.kts index eb9926d0b..2b83f26ac 100644 --- a/build-logic/src/main/kotlin/via.shadow-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/via.shadow-conventions.gradle.kts @@ -29,9 +29,10 @@ fun ShadowJar.configureRelocations() { } fun ShadowJar.configureExcludes() { - // FastUtil - we only want object, int, and reference maps + // FastUtil - we only want object, int, and certain reference maps // Object types - exclude("it/unimi/dsi/fastutil/*/*Reference*") + exclude("it/unimi/dsi/fastutil/*/*2Reference*") + exclude("it/unimi/dsi/fastutil/*/*Reference2Int*") exclude("it/unimi/dsi/fastutil/*/*Boolean*") exclude("it/unimi/dsi/fastutil/*/*Byte*") exclude("it/unimi/dsi/fastutil/*/*Short*") @@ -48,4 +49,6 @@ fun ShadowJar.configureExcludes() { exclude("it/unimi/dsi/fastutil/*/*Big*") exclude("it/unimi/dsi/fastutil/*/*Synchronized*") exclude("it/unimi/dsi/fastutil/*/*Unmodifiable*") + // More + exclude("it/unimi/dsi/fastutil/io/TextIO") } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java index 74967e577..f4175ff63 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java @@ -23,19 +23,11 @@ import com.viaversion.viaversion.api.data.MappingDataBase; import com.viaversion.viaversion.api.minecraft.RegistryType; import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey; import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5; -import com.viaversion.viaversion.api.minecraft.item.data.BannerPattern; -import com.viaversion.viaversion.api.minecraft.item.data.Bee; -import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties; -import com.viaversion.viaversion.api.minecraft.item.data.DyedColor; -import com.viaversion.viaversion.api.minecraft.item.data.GameProfile; -import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTarget; -import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook; import com.viaversion.viaversion.api.protocol.AbstractProtocol; import com.viaversion.viaversion.api.protocol.packet.State; import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider; import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider; import com.viaversion.viaversion.api.type.Type; -import com.viaversion.viaversion.api.minecraft.item.data.Enchantments; import com.viaversion.viaversion.api.type.types.misc.ParticleType; import com.viaversion.viaversion.api.type.types.version.Types1_20_5; import com.viaversion.viaversion.data.entity.EntityTrackerBase; @@ -120,7 +112,7 @@ public final class Protocol1_20_5To1_20_3 extends AbstractProtocol { @@ -189,7 +188,10 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter customData = data.getNonEmpty(StructuredDataKey.CUSTOM_DATA); + final CompoundTag tag = customData != null ? customData.value() : new CompoundTag(); // TODO @@ -200,6 +202,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter newKey, final boolean hide) { + final StructuredDataKey newKey, final boolean show) { final ListTag enchantmentsTag = tag.getListTag(key); if (enchantmentsTag == null) { return; @@ -318,7 +321,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter. + */ +package com.viaversion.viaversion.rewriter; + +import com.viaversion.viaversion.api.data.MappingData; +import com.viaversion.viaversion.api.data.Mappings; +import com.viaversion.viaversion.api.data.ParticleMappings; +import com.viaversion.viaversion.api.minecraft.Particle; +import com.viaversion.viaversion.api.minecraft.item.Item; +import com.viaversion.viaversion.api.protocol.Protocol; +import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType; +import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; +import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType; +import com.viaversion.viaversion.api.protocol.remapper.PacketHandler; +import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers; +import com.viaversion.viaversion.api.rewriter.RewriterBase; +import com.viaversion.viaversion.api.type.Type; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class StructuredItemRewriter> extends ItemRewriter { + + public StructuredItemRewriter(T protocol, Type itemType, Type itemArrayType, Type mappedItemType, Type mappedItemArrayType) { + super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType); + } + + public StructuredItemRewriter(T protocol, Type itemType, Type itemArrayType) { + super(protocol, itemType, itemArrayType, itemType, itemArrayType); + } + + @Override + public @Nullable Item handleItemToClient(@Nullable Item item) { + if (item == null) { + return null; + } + + final MappingData mappingData = protocol.getMappingData(); + if (mappingData != null) { + if (mappingData.getItemMappings() != null) { + item.setIdentifier(mappingData.getNewItemId(item.identifier())); + } + if (mappingData.getDataComponentSerializerMappings() != null) { + item.structuredData().setIdLookup(protocol, false); + } + } + return item; + } + + @Override + public @Nullable Item handleItemToServer(@Nullable Item item) { + if (item == null) { + return null; + } + + final MappingData mappingData = protocol.getMappingData(); + if (mappingData != null) { + if (mappingData.getItemMappings() != null) { + item.setIdentifier(mappingData.getOldItemId(item.identifier())); + } + if (mappingData.getDataComponentSerializerMappings() != null) { + item.structuredData().setIdLookup(protocol, true); + } + } + return item; + } +} diff --git a/template/src/main/java/com/viaversion/viaversion/template/protocols/rewriter/BlockItemPacketRewriter1_99.java b/template/src/main/java/com/viaversion/viaversion/template/protocols/rewriter/BlockItemPacketRewriter1_99.java index ea0082dd3..d69775ea5 100644 --- a/template/src/main/java/com/viaversion/viaversion/template/protocols/rewriter/BlockItemPacketRewriter1_99.java +++ b/template/src/main/java/com/viaversion/viaversion/template/protocols/rewriter/BlockItemPacketRewriter1_99.java @@ -17,7 +17,6 @@ */ package com.viaversion.viaversion.template.protocols.rewriter; -import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2; import com.viaversion.viaversion.api.type.types.version.Types1_20_5; import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.rewriter.RecipeRewriter1_20_3; @@ -26,13 +25,13 @@ import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.Clientb import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPacket1_20_5; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPackets1_20_5; import com.viaversion.viaversion.rewriter.BlockRewriter; -import com.viaversion.viaversion.rewriter.ItemRewriter; +import com.viaversion.viaversion.rewriter.StructuredItemRewriter; import com.viaversion.viaversion.template.protocols.Protocol1_99To_98; // To replace if needed: // ChunkType1_20_2 // RecipeRewriter1_20_3 -public final class BlockItemPacketRewriter1_99 extends ItemRewriter { +public final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter { public BlockItemPacketRewriter1_99(final Protocol1_99To_98 protocol) { super(protocol, /*TypesOLD.ITEM, TypesOLD.ITEM_ARRAY, */Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY);