Track sent armor trim registries in 1.20.3->1.20.5

This commit is contained in:
Nassim Jahnke 2024-08-07 12:36:51 +02:00
parent 02442a9775
commit 802e868b2e
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
7 changed files with 103 additions and 91 deletions

View File

@ -50,6 +50,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.BlockItemPac
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.ComponentRewriter1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.EntityPacketRewriter1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.AcknowledgedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
@ -292,6 +293,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
connection.put(new AcknowledgedMessagesStorage());
connection.put(new ArmorTrimStorage());
}
@Override
@ -332,4 +334,4 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
}

View File

@ -1,45 +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 <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data;
import com.viaversion.viaversion.util.KeyMappings;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class TrimMaterials1_20_3 {
private static final KeyMappings MATERIALS = new KeyMappings(
"amethyst",
"copper",
"diamond",
"emerald",
"gold",
"iron",
"lapis",
"netherite",
"quartz",
"redstone"
);
public static @Nullable String idToKey(final int id) {
return MATERIALS.idToKey(id);
}
public static int keyToId(final String material) {
return MATERIALS.keyToId(material);
}
}

View File

@ -93,10 +93,9 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.MapDecorations1_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.MaxStackSize1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.PotionEffects1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Potions1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimMaterials1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimPatterns1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.ItemRewriter;
@ -499,7 +498,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final CompoundTag trimTag = tag.getCompoundTag("Trim");
if (trimTag != null) {
updateArmorTrim(data, trimTag, (hideFlagsValue & StructuredDataConverter.HIDE_ARMOR_TRIM) == 0);
updateArmorTrim(connection, data, trimTag, (hideFlagsValue & StructuredDataConverter.HIDE_ARMOR_TRIM) == 0);
}
final CompoundTag explosionTag = tag.getCompoundTag("Explosion");
@ -967,12 +966,12 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
}
private void updateArmorTrim(final StructuredDataContainer data, final CompoundTag trimTag, final boolean showInTooltip) {
private void updateArmorTrim(final UserConnection connection, final StructuredDataContainer data, final CompoundTag trimTag, final boolean showInTooltip) {
final Tag materialTag = trimTag.get("material");
final Holder<ArmorTrimMaterial> materialHolder;
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (materialTag instanceof StringTag materialStringTag) {
// Would technically have to be stored and retrieved from registry data, but that'd mean a lot of work
final int id = TrimMaterials1_20_3.keyToId(materialStringTag.getValue());
final int id = trimStorage.trimMaterials().keyToId(materialStringTag.getValue());
if (id == -1) {
return;
}
@ -1020,11 +1019,11 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final Tag patternTag = trimTag.get("pattern");
final Holder<ArmorTrimPattern> patternHolder;
if (patternTag instanceof StringTag patternStringTag) {
// Would technically have to be stored and retrieved from registry data, but that'd mean a lot of work
final int id = TrimPatterns1_20_3.keyToId(patternStringTag.getValue());
final int id = trimStorage.trimPatterns().keyToId(patternStringTag.getValue());
if (id == -1) {
return;
}
patternHolder = Holder.of(id);
} else if (patternTag instanceof CompoundTag patternCompoundTag) {
final String assetId = patternCompoundTag.getString("assetId");

View File

@ -17,6 +17,7 @@
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.FloatTag;
@ -25,7 +26,6 @@ import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.GameProfile;
@ -83,8 +83,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.EquipmentSlots1_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Instruments1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.PotionEffects1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Potions1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimMaterials1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimPatterns1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Either;
@ -132,7 +131,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.HIDE_TOOLTIP, this::convertHideTooltip);
register(StructuredDataKey.REPAIR_COST, this::convertRepairCost);
register(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, this::convertEnchantmentGlintOverride);
register(StructuredDataKey.CREATIVE_SLOT_LOCK, null);
registerEmpty(StructuredDataKey.CREATIVE_SLOT_LOCK);
register(StructuredDataKey.INTANGIBLE_PROJECTILE, this::convertIntangibleProjectile);
register(StructuredDataKey.FOOD1_20_5, this::convertFood);
register(StructuredDataKey.FIRE_RESISTANT, this::convertFireResistant);
@ -142,7 +141,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.MAP_COLOR, this::convertMapColor);
register(StructuredDataKey.MAP_ID, this::convertMapId);
register(StructuredDataKey.MAP_DECORATIONS, this::convertMapDecorations);
register(StructuredDataKey.MAP_POST_PROCESSING, null);
registerEmpty(StructuredDataKey.MAP_POST_PROCESSING);
register(StructuredDataKey.CHARGED_PROJECTILES1_20_5, this::convertChargedProjectiles);
register(StructuredDataKey.BUNDLE_CONTENTS1_20_5, this::convertBundleContents);
register(StructuredDataKey.POTION_CONTENTS, this::convertPotionContents);
@ -247,7 +246,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
if (!data.isEmpty()) {
final CompoundTag components;
try {
components = toTag(data, false);
components = toTag(connection, data, false);
} catch (final Exception e) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
protocol.getLogger().log(Level.WARNING, "Error writing components in show_item!", e);
@ -278,7 +277,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
}
public CompoundTag toTag(final Map<StructuredDataKey<?>, StructuredData<?>> data, final boolean empty) {
public CompoundTag toTag(final UserConnection connection, final Map<StructuredDataKey<?>, StructuredData<?>> data, final boolean empty) {
final CompoundTag tag = new CompoundTag();
for (final Map.Entry<StructuredDataKey<?>, StructuredData<?>> entry : data.entrySet()) {
final StructuredDataKey<?> key = entry.getKey();
@ -302,7 +301,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
//noinspection unchecked
final Tag valueTag = converter.dataConverter.convert(value.value());
final Tag valueTag = converter.dataConverter.convert(connection, value.value());
if (valueTag == null) {
continue;
}
@ -578,12 +577,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return value; // String<->id conversion is already done by the item rewriter
}
protected ListTag<CompoundTag> convertChargedProjectiles(final Item[] value) {
return convertItemArray(value);
protected ListTag<CompoundTag> convertChargedProjectiles(final UserConnection connection, final Item[] value) {
return convertItemArray(connection, value);
}
protected ListTag<CompoundTag> convertBundleContents(final Item[] value) {
return convertItemArray(value);
protected ListTag<CompoundTag> convertBundleContents(final UserConnection connection, final Item[] value) {
return convertItemArray(connection, value);
}
protected CompoundTag convertPotionContents(final PotionContents value) {
@ -668,11 +667,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return tag;
}
protected CompoundTag convertTrim(final ArmorTrim value) {
protected CompoundTag convertTrim(final UserConnection connection, final ArmorTrim value) {
final CompoundTag tag = new CompoundTag();
final Holder<ArmorTrimMaterial> material = value.material();
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (material.hasId()) {
final String trimMaterial = TrimMaterials1_20_3.idToKey(material.id());
final String trimMaterial = trimStorage.trimMaterials().idToKey(material.id());
tag.putString("material", trimMaterial);
} else {
final ArmorTrimMaterial armorTrimMaterial = material.value();
@ -700,7 +700,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
final Holder<ArmorTrimPattern> pattern = value.pattern();
if (pattern.hasId()) {
tag.putString("pattern", TrimPatterns1_20_3.idToKey(pattern.id()));
tag.putString("pattern", trimStorage.trimPatterns().idToKey(pattern.id()));
} else {
final ArmorTrimPattern armorTrimPattern = pattern.value();
final CompoundTag patternTag = new CompoundTag();
@ -862,9 +862,9 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return tag;
}
protected ListTag<CompoundTag> convertContainer(final Item[] value) {
protected ListTag<CompoundTag> convertContainer(final UserConnection connection, final Item[] value) {
final ListTag<CompoundTag> tag = new ListTag<>(CompoundTag.class);
final ListTag<CompoundTag> items = convertItemArray(value);
final ListTag<CompoundTag> items = convertItemArray(connection, value);
for (int i = 0; i < items.size(); i++) {
final CompoundTag itemTag = new CompoundTag();
itemTag.putInt("slot", i);
@ -950,17 +950,17 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
}
protected ListTag<CompoundTag> convertItemArray(final Item[] value) {
protected ListTag<CompoundTag> convertItemArray(final UserConnection connection, final Item[] value) {
final ListTag<CompoundTag> tag = new ListTag<>(CompoundTag.class);
for (final Item item : value) {
final CompoundTag itemTag = new CompoundTag();
convertItem(itemTag, item);
convertItem(connection, itemTag, item);
tag.add(itemTag);
}
return tag;
}
protected void convertItem(final CompoundTag tag, final Item item) {
protected void convertItem(final UserConnection connection, final CompoundTag tag, final Item item) {
final String identifier = mappedIdentifier(item.identifier());
if (identifier == null) {
throw new IllegalArgumentException("Unknown item: " + item.identifier());
@ -972,7 +972,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
tag.putInt("count", 1);
}
final Map<StructuredDataKey<?>, StructuredData<?>> components = item.dataContainer().data();
tag.put("components", toTag(components, true));
tag.put("components", toTag(connection, components, true));
}
protected void convertFilterableString(final CompoundTag tag, final FilterableString string, final int max) {
@ -1126,10 +1126,19 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
// ---------------------------------------------------------------------------------------
protected <T> void registerEmpty(final StructuredDataKey<T> key) {
converters.put(key, new ConverterPair<>(null, null));
}
protected <T> void register(final StructuredDataKey<T> key, final DataConverter<T> dataConverter) { // TODO Remove this method
converters.put(key, new ConverterPair<>(dataConverter, null));
}
protected <T> void register(final StructuredDataKey<T> key, final SimpleDataConverter<T> dataConverter) {
final DataConverter<T> converter = ($, value) -> dataConverter.convert(value);
converters.put(key, new ConverterPair<>(converter, null));
}
protected <T> void register(final StructuredDataKey<T> key, final DataConverter<T> dataConverter, final TagConverter<T> tagConverter) {
converters.put(key, new ConverterPair<>(dataConverter, tagConverter));
}
@ -1151,11 +1160,17 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
@FunctionalInterface
protected interface DataConverter<T> {
protected interface SimpleDataConverter<T> {
Tag convert(T value);
}
@FunctionalInterface
protected interface DataConverter<T> {
Tag convert(UserConnection connection, T value);
}
@FunctionalInterface
protected interface TagConverter<T> {
@ -1164,4 +1179,4 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
private record ConverterPair<T>(DataConverter<T> dataConverter, TagConverter<T> tagConverter) {
}
}
}

View File

@ -46,8 +46,10 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.BannerPatterns1_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.AcknowledgedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
import com.viaversion.viaversion.util.TagUtil;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
@ -156,7 +158,8 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
registryEntries[id] = new RegistryEntry(name, tag.get("element"));
}
if (Key.stripMinecraftNamespace(type).equals("damage_type")) {
final String strippedKey = Key.stripMinecraftNamespace(type);
if (strippedKey.equals("damage_type")) {
// Add spit damage type
highestId++;
registryEntries = Arrays.copyOf(registryEntries, highestId + 1);
@ -188,6 +191,13 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
replaceNullValues(registryEntries);
}
// Track custom armor trims
if (strippedKey.equals("trim_pattern")) {
wrapper.user().get(ArmorTrimStorage.class).setTrimPatterns(toMappings(registryEntries));
} else if (strippedKey.equals("trim_material")) {
wrapper.user().get(ArmorTrimStorage.class).setTrimMaterials(toMappings(registryEntries));
}
final PacketWrapper registryPacket = wrapper.create(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA);
registryPacket.write(Types.STRING, type);
registryPacket.write(Types.REGISTRY_ENTRY_ARRAY, registryEntries);
@ -328,6 +338,14 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
});
}
private KeyMappings toMappings(final RegistryEntry[] entries) {
final String[] keys = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
keys[i] = Key.stripMinecraftNamespace(entries[i].key());
}
return new KeyMappings(keys);
}
private void updateParticleFormat(final CompoundTag options, final String particleType) {
if ("block".equals(particleType) || "block_marker".equals(particleType) || "falling_dust".equals(particleType) || "dust_pillar".equals(particleType)) {
moveTag(options, "value", "block_state");

View File

@ -18,7 +18,6 @@
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.FloatTag;
import com.viaversion.nbt.tag.IntArrayTag;
@ -61,8 +60,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Instruments1_20_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.MapDecorations1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.PotionEffects1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Potions1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimMaterials1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimPatterns1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.UUIDUtil;
@ -516,8 +514,9 @@ public final class StructuredDataConverter {
tag.putInt("map_scale_direction", 1);
}
});
register(StructuredDataKey.TRIM, (data, tag) -> {
register(StructuredDataKey.TRIM, (connection, data, tag) -> {
final CompoundTag trimTag = new CompoundTag();
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (data.material().isDirect()) {
final CompoundTag materialTag = new CompoundTag();
final ArmorTrimMaterial material = data.material().value();
@ -540,7 +539,7 @@ public final class StructuredDataConverter {
materialTag.put("description", material.description());
trimTag.put("material", materialTag);
} else {
final String oldKey = TrimMaterials1_20_3.idToKey(data.material().id());
final String oldKey = trimStorage.trimMaterials().idToKey(data.material().id());
if (oldKey != null) {
trimTag.putString("material", oldKey);
}
@ -559,7 +558,7 @@ public final class StructuredDataConverter {
patternTag.putBoolean("decal", pattern.decal());
trimTag.put("pattern", patternTag);
} else {
final String oldKey = TrimPatterns1_20_3.idToKey(data.pattern().id());
final String oldKey = trimStorage.trimPatterns().idToKey(data.pattern().id());
if (oldKey != null) {
trimTag.putString("pattern", oldKey);
}

View File

@ -15,13 +15,26 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data;
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.util.KeyMappings;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class TrimPatterns1_20_3 {
public final class ArmorTrimStorage implements StorableObject {
// Default 1.20.3 registries
private static final KeyMappings MATERIALS = new KeyMappings(
"amethyst",
"copper",
"diamond",
"emerald",
"gold",
"iron",
"lapis",
"netherite",
"quartz",
"redstone"
);
private static final KeyMappings PATTERNS = new KeyMappings(
"coast",
"dune",
@ -41,11 +54,22 @@ public final class TrimPatterns1_20_3 {
"wild"
);
public static @Nullable String idToKey(final int id) {
return PATTERNS.idToKey(id);
private KeyMappings trimPatterns = PATTERNS;
private KeyMappings trimMaterials = MATERIALS;
public KeyMappings trimPatterns() {
return trimPatterns;
}
public static int keyToId(final String pattern) {
return PATTERNS.keyToId(pattern);
public KeyMappings trimMaterials() {
return trimMaterials;
}
public void setTrimPatterns(final KeyMappings trimPatterns) {
this.trimPatterns = trimPatterns;
}
public void setTrimMaterials(final KeyMappings trimMaterials) {
this.trimMaterials = trimMaterials;
}
}