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 217f5f059..56eab13a2 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 @@ -79,10 +79,10 @@ public class StructuredDataType extends Type> { types = new StructuredDataKey[mappings.mappedSize()]; } - public DataFiller add(final StructuredDataKey reader) { - final int id = mappings.mappedId(reader.identifier()); - Preconditions.checkArgument(id != -1, "No mapped id found for %s", reader.identifier()); - types[id] = reader; + public DataFiller add(final StructuredDataKey key) { + final int id = mappings.mappedId(key.identifier()); + Preconditions.checkArgument(id != -1, "No mapped id found for %s", key.identifier()); + types[id] = key; return this; } } 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 4e8c522bc..41165c2ae 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 @@ -68,7 +68,7 @@ public final class Protocol1_20_5To1_20_3 extends AbstractProtocol tagRewriter = new TagRewriter<>(this); - private final ComponentRewriter componentRewriter = new ComponentRewriter1_20_5(this); + private final ComponentRewriter1_20_5 componentRewriter = new ComponentRewriter1_20_5<>(this, Types1_20_5.STRUCTURED_DATA); public Protocol1_20_5To1_20_3() { super(ClientboundPacket1_20_3.class, ClientboundPacket1_20_5.class, ServerboundPacket1_20_3.class, ServerboundPacket1_20_5.class); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/ComponentRewriter1_20_5.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/ComponentRewriter1_20_5.java index 6d6520612..fb693f9e4 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/ComponentRewriter1_20_5.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/ComponentRewriter1_20_5.java @@ -71,7 +71,8 @@ import com.viaversion.viaversion.api.minecraft.item.data.ToolRule; import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable; import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook; import com.viaversion.viaversion.api.protocol.Protocol; -import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.ClientboundPacket1_20_3; +import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType; +import com.viaversion.viaversion.api.type.types.item.StructuredDataType; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.Protocol1_20_5To1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.ArmorMaterials1_20_5; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.Attributes1_20_5; @@ -93,18 +94,25 @@ import com.viaversion.viaversion.util.UUIDUtil; import com.viaversion.viaversion.util.Unit; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import java.util.HashMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.logging.Level; +import org.checkerframework.checker.nullness.qual.Nullable; -// 1.20.5 data component -> 1.20.5 nbt conversion -public class ComponentRewriter1_20_5 extends ComponentRewriter { +public class ComponentRewriter1_20_5 extends ComponentRewriter { - @SuppressWarnings("rawtypes") - protected final Map rewriters = new HashMap<>(); + private final Map, ConverterPair> converters = new Reference2ObjectOpenHashMap<>(); + private final StructuredDataType structuredDataType; - public ComponentRewriter1_20_5(final Protocol protocol) { + /** + * @param protocol protocol + * @param structuredDataType unmapped structured data type + */ + public ComponentRewriter1_20_5(final Protocol protocol, final StructuredDataType structuredDataType) { super(protocol, ReadType.NBT); + this.structuredDataType = structuredDataType; register(StructuredDataKey.CUSTOM_DATA, this::convertCustomData); register(StructuredDataKey.MAX_STACK_SIZE, this::convertMaxStackSize); @@ -166,6 +174,8 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter, StructuredData> data, final boolean empty) { + public CompoundTag toTag(final Map, StructuredData> data, final boolean empty) { final CompoundTag tag = new CompoundTag(); for (final Map.Entry, StructuredData> entry : data.entrySet()) { final StructuredDataKey key = entry.getKey(); - if (!rewriters.containsKey(key)) { // Should NOT happen - Via.getPlatform().getLogger().severe("No converter for " + key.identifier() + " found!"); + final String identifier = key.identifier(); + + //noinspection rawtypes + final ConverterPair converter = converters.get(key); + if (converter == null) { // Should NOT happen + Via.getPlatform().getLogger().severe("No converter found for data component: " + identifier); continue; } + final StructuredData value = entry.getValue(); if (value.isEmpty()) { if (empty) { // Theoretically not needed here, but we'll keep it for consistency - tag.put("!" + key.identifier(), new CompoundTag()); + tag.put("!" + identifier, new CompoundTag()); continue; } - throw new IllegalArgumentException("Empty structured data: " + key.identifier()); + throw new IllegalArgumentException("Empty structured data: " + identifier); } //noinspection unchecked - final Tag valueTag = rewriters.get(key).convert(value.value()); + final Tag valueTag = converter.dataConverter.convert(value.value()); if (valueTag == null) { continue; } - tag.put(key.identifier(), valueTag); + + tag.put(identifier, valueTag); } return tag; } + public List> toData(final CompoundTag tag) { + final List> list = new ArrayList<>(); + for (final Map.Entry entry : tag.entrySet()) { + final StructuredData data = readFromTag(entry.getKey(), entry.getValue()); + list.add(data); + } + return list; + } + + public StructuredData readFromTag(final String identifier, final Tag tag) { + final int id = protocol.getMappingData().getDataComponentSerializerMappings().mappedId(identifier); + Preconditions.checkArgument(id != -1, "Unknown data component: %s", identifier); + final StructuredDataKey key = structuredDataType.key(id); + return readFromTag(key, id, tag); + } + + private StructuredData readFromTag(final StructuredDataKey key, final int id, final Tag tag) { + final TagConverter converter = tagConverter(key); + Preconditions.checkNotNull(converter, "No converter found for: %s", key); + return StructuredData.of(key, converter.convert(tag), id); + } + // --------------------------------------------------------------------------------------- // Conversion methods, can be overridden in future protocols to handle new changes @@ -363,27 +401,11 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter match = matcher.matcher(); - if (match.isLeft()) { - state.putString(matcher.name(), match.left()); - } else { - final StatePropertyMatcher.RangedMatcher range = match.right(); - final CompoundTag rangeTag = new CompoundTag(); - if (range.minValue() != null) { - rangeTag.putString("min", range.minValue()); - } - if (range.maxValue() != null) { - rangeTag.putString("max", range.maxValue()); - } - state.put(matcher.name(), rangeTag); - } - } + final CompoundTag state = convertPredicate(predicate); predicateTag.put("state", state); } if (predicate.tag() != null) { - predicateTag.putString("nbt", serializerVersion().toSNBT(predicate.tag())); + predicateTag.put("nbt", predicate.tag()); } predicates.add(predicateTag); @@ -395,6 +417,27 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter match = matcher.matcher(); + if (match.isLeft()) { + state.putString(matcher.name(), match.left()); + } else { + final StatePropertyMatcher.RangedMatcher range = match.right(); + final CompoundTag rangeTag = new CompoundTag(); + if (range.minValue() != null) { + rangeTag.putString("min", range.minValue()); + } + if (range.maxValue() != null) { + rangeTag.putString("max", range.maxValue()); + } + state.put(matcher.name(), rangeTag); + } + } + return state; + } + protected CompoundTag convertCanBreak(final AdventureModePredicate value) { return convertCanPlaceOn(value); } @@ -585,7 +628,7 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter pagesTag = new ListTag<>(CompoundTag.class); for (final FilterableString page : value) { final CompoundTag pageTag = new CompoundTag(); - convertFilterableString(pageTag, page, 0, 1024); + convertFilterableString(pageTag, page, 1024); pagesTag.add(pageTag); } tag.put("pages", pagesTag); @@ -594,14 +637,14 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter pagesTag = new ListTag<>(CompoundTag.class); @@ -728,7 +771,7 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter 0) { - convertProperties(tag, "properties", value.properties()); + convertProperties(tag, value.properties()); } return tag; } @@ -792,7 +835,7 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter tag = new ListTag<>(CompoundTag.class); for (final BannerPatternLayer layer : value) { final CompoundTag layerTag = new CompoundTag(); - convertBannerPattern(layerTag, "pattern", layer.pattern()); + convertBannerPattern(layerTag, layer.pattern()); layerTag.put("color", convertDyeColor(layer.dyeColor())); tag.add(layerTag); } @@ -895,7 +938,7 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter propertiesTag = new ListTag<>(CompoundTag.class); for (final GameProfile.Property property : properties) { final CompoundTag propertyTag = new CompoundTag(); @@ -960,12 +1003,12 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter pattern) { + protected void convertBannerPattern(final CompoundTag tag, final Holder pattern) { if (pattern.hasId()) { - tag.putString(name, BannerPatterns1_20_5.idToKey(pattern.id())); + tag.putString("pattern", BannerPatterns1_20_5.idToKey(pattern.id())); return; } @@ -973,7 +1016,7 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter convertComponents(final Tag[] value, final int maxLength) { @@ -1079,8 +1122,24 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter void register(final StructuredDataKey key, final DataConverter converter) { - rewriters.put(key, converter); + protected void register(final StructuredDataKey key, final DataConverter dataConverter) { // TODO Remove this method + converters.put(key, new ConverterPair<>(dataConverter, null)); + } + + protected void register(final StructuredDataKey key, final DataConverter dataConverter, final TagConverter tagConverter) { + converters.put(key, new ConverterPair<>(dataConverter, tagConverter)); + } + + protected @Nullable DataConverter dataConverter(final StructuredDataKey key) { + //noinspection unchecked + final ConverterPair converters = (ConverterPair) this.converters.get(key); + return converters != null ? converters.dataConverter : null; + } + + protected @Nullable TagConverter tagConverter(final StructuredDataKey key) { + //noinspection unchecked + final ConverterPair converters = (ConverterPair) this.converters.get(key); + return converters != null ? converters.tagConverter : null; } public SerializerVersion serializerVersion() { @@ -1092,4 +1151,20 @@ public class ComponentRewriter1_20_5 extends ComponentRewriter { + + T convert(final Tag tag); + } + + private static final class ConverterPair { + private final DataConverter dataConverter; + private final TagConverter tagConverter; + + ConverterPair(final DataConverter dataConverter, final TagConverter tagConverter) { + this.dataConverter = dataConverter; + this.tagConverter = tagConverter; + } + } } \ No newline at end of file diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredNBTConverter.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredNBTConverter.java deleted file mode 100644 index c92c58ba8..000000000 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredNBTConverter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion - * Copyright (C) 2016-2024 ViaVersion 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.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.rewriter; - -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; -import com.google.common.base.Preconditions; -import com.viaversion.viaversion.api.minecraft.data.StructuredData; -import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -// 1.20.5 nbt -> 1.20.5 data component conversion, technically only needed in VB but kept here to make maintenance easier -public final class StructuredNBTConverter { - - private static final Map> rewriters = new HashMap<>(); - - static { - register(StructuredDataKey.CUSTOM_DATA, tag -> (CompoundTag) tag); - // TODO Add missing handlers for other data types, this will probably be done after the component rework - } - - public static List> toData(final CompoundTag tag) { - final List> data = new ArrayList<>(); - for (final Map.Entry entry : tag.entrySet()) { - final StructuredData structuredData = readFromTag(entry.getKey(), entry.getValue()); - data.add(structuredData); - } - return data; - } - - @SuppressWarnings("unchecked") - public static StructuredData readFromTag(final String identifier, final Tag tag) { - final DataConverter converter = (DataConverter) rewriters.get(identifier); - Preconditions.checkNotNull(converter, "No converter for %s found", identifier); - return (StructuredData) converter.convert(tag); - } - - private static void register(final StructuredDataKey key, final DataConverter converter) { - rewriters.put(key.identifier(), converter); - } - - @FunctionalInterface - interface DataConverter { - - T convert(final Tag tag); - } -} \ No newline at end of file diff --git a/common/src/main/java/com/viaversion/viaversion/rewriter/StructuredItemRewriter.java b/common/src/main/java/com/viaversion/viaversion/rewriter/StructuredItemRewriter.java index b980befdd..68502fae0 100644 --- a/common/src/main/java/com/viaversion/viaversion/rewriter/StructuredItemRewriter.java +++ b/common/src/main/java/com/viaversion/viaversion/rewriter/StructuredItemRewriter.java @@ -19,17 +19,10 @@ package com.viaversion.viaversion.rewriter; import com.viaversion.viaversion.api.connection.UserConnection; 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;