diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/Holder.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/Holder.java index 14d08f0bf..59bc32109 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/Holder.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/Holder.java @@ -22,21 +22,29 @@ */ package com.viaversion.viaversion.api.minecraft; -import com.google.common.base.Preconditions; +public interface Holder { -public final class Holder { - - private final T value; - private final int id; - - public Holder(final int id) { - this.value = null; - this.id = id; + /** + * Returns an indirect id holder. + * + * @param id the id + * @param the type of the value + * @return a new holder with the given id + * @throws IllegalArgumentException if the id is negative + */ + static Holder of(final int id) { + return new HolderImpl<>(id); } - public Holder(final T value) { - this.value = value; - this.id = -1; + /** + * Returns a direct value holder. + * + * @param value the value + * @param the type of the value + * @return a new direct holder + */ + static Holder of(final T value) { + return new HolderImpl<>(value); } /** @@ -45,9 +53,7 @@ public final class Holder { * @return true if the holder is direct * @see #hasId() */ - public boolean isDirect() { - return id == -1; - } + boolean isDirect(); /** * Returns true if this holder has an id. @@ -55,16 +61,22 @@ public final class Holder { * @return true if this holder has an id * @see #isDirect() */ - public boolean hasId() { - return id != -1; - } + boolean hasId(); - public T value() { - Preconditions.checkArgument(isDirect(), "Holder is not direct"); - return value; - } + /** + * Returns the value of this holder. + * + * @return the value of this holder + * @throws IllegalArgumentException if this holder is not direct + * @see #isDirect() + */ + T value(); - public int id() { - return id; - } + /** + * Returns the id of this holder, or -1 if this holder is direct. + * + * @return the id of this holder, or -1 if this holder is direct + * @see #hasId() + */ + int id(); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/HolderImpl.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/HolderImpl.java new file mode 100644 index 000000000..58d66f6aa --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/HolderImpl.java @@ -0,0 +1,63 @@ +/* + * 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; + +import com.google.common.base.Preconditions; + +final class HolderImpl implements Holder { + + private final T value; + private final int id; + + HolderImpl(final int id) { + Preconditions.checkArgument(id >= 0, "id cannot be negative"); + this.value = null; + this.id = id; + } + + HolderImpl(final T value) { + this.value = value; + this.id = -1; + } + + @Override + public boolean isDirect() { + return id == -1; + } + + @Override + public boolean hasId() { + return id != -1; + } + + @Override + public T value() { + Preconditions.checkArgument(isDirect(), "Holder is not direct"); + return value; + } + + @Override + public int id() { + return id; + } +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/misc/HolderType.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/misc/HolderType.java index 42c35694a..286c5c69d 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/misc/HolderType.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/misc/HolderType.java @@ -36,9 +36,9 @@ public abstract class HolderType extends Type> { public Holder read(final ByteBuf buffer) throws Exception { final int id = Type.VAR_INT.readPrimitive(buffer) - 1; // Normalize id if (id == -1) { - return new Holder<>(readDirect(buffer)); + return Holder.of(readDirect(buffer)); } - return new Holder<>(id); + return Holder.of(id); } @Override diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java index c84c278e1..02326a964 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java @@ -245,7 +245,7 @@ public class InventoryPackets extends ItemRewriter lore = display.getListTag("Lore", StringTag.class); if (lore != null) { - display.put(nbtTagName("Lore"), new ListTag<>(lore.copy().getValue())); // Save old lore + display.put(nbtTagName("Lore"), lore.copy()); // Save old lore for (StringTag loreEntry : lore) { String jsonText = ComponentUtil.legacyToJsonString(loreEntry.getValue(), true); loreEntry.setValue(jsonText); @@ -269,7 +269,7 @@ public class InventoryPackets extends ItemRewriter(((ListTag) savedLore).getValue())); + display.put("Lore", savedLore.copy()); } else { for (StringTag loreEntry : lore) { loreEntry.setValue(ComponentUtil.jsonToLegacy(loreEntry.getValue())); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19_3to1_19_1/Protocol1_19_3To1_19_1.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19_3to1_19_1/Protocol1_19_3To1_19_1.java index 8ab81af12..a5a054187 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19_3to1_19_1/Protocol1_19_3To1_19_1.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19_3to1_19_1/Protocol1_19_3To1_19_1.java @@ -96,13 +96,13 @@ public final class Protocol1_19_3To1_19_1 extends AbstractProtocol(soundId)); + wrapper.write(Type.SOUND_EVENT, Holder.of(soundId)); }; registerClientbound(ClientboundPackets1_19_1.ENTITY_SOUND, soundHandler); registerClientbound(ClientboundPackets1_19_1.SOUND, soundHandler); registerClientbound(ClientboundPackets1_19_1.NAMED_SOUND, ClientboundPackets1_19_3.SOUND, wrapper -> { final String soundIdentifier = wrapper.read(Type.STRING); - wrapper.write(Type.SOUND_EVENT, new Holder<>(new SoundEvent(soundIdentifier, null))); + wrapper.write(Type.SOUND_EVENT, Holder.of(new SoundEvent(soundIdentifier, null))); }); new StatisticsRewriter<>(this).register(ClientboundPackets1_19_1.STATISTICS); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/AttributeMappings.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/AttributeMappings.java index 088a41017..5e1a8ae48 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/AttributeMappings.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/AttributeMappings.java @@ -17,8 +17,7 @@ */ package com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import com.viaversion.viaversion.util.KeyMappings; import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -26,35 +25,28 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ public final class AttributeMappings { - private static final String[] ATTRIBUTES = { - "generic.armor", - "generic.armor_toughness", - "generic.attack_damage", - "generic.attack_knockback", - "generic.attack_speed", - "generic.flying_speed", - "generic.follow_range", - "horse.jump_strength", - "generic.knockback_resistance", - "generic.luck", - "generic.max_absorption", - "generic.max_health", - "generic.movement_speed", - "zombie.spawn_reinforcements" - }; - private static final Object2IntMap STRING_TO_ID = new Object2IntOpenHashMap<>(); - - static { - for (int i = 0; i < ATTRIBUTES.length; i++) { - STRING_TO_ID.put(ATTRIBUTES[i], i); - } - } + private static final KeyMappings ATTRIBUTES = new KeyMappings( + "generic.armor", + "generic.armor_toughness", + "generic.attack_damage", + "generic.attack_knockback", + "generic.attack_speed", + "generic.flying_speed", + "generic.follow_range", + "horse.jump_strength", + "generic.knockback_resistance", + "generic.luck", + "generic.max_absorption", + "generic.max_health", + "generic.movement_speed", + "zombie.spawn_reinforcements" + ); public static @Nullable String attribute(final int id) { - return id >= 0 && id < ATTRIBUTES.length ? ATTRIBUTES[id] : null; + return ATTRIBUTES.idToKey(id); } public static int id(final String attribute) { - return STRING_TO_ID.getOrDefault(attribute, -1); + return ATTRIBUTES.keyToId(attribute); } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/EnchantmentMappings.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/EnchantmentMappings.java index b9430b48a..3fd7b5bfe 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/EnchantmentMappings.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/EnchantmentMappings.java @@ -17,14 +17,12 @@ */ package com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data; -import com.viaversion.viaversion.util.Key; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import com.viaversion.viaversion.util.KeyMappings; import org.checkerframework.checker.nullness.qual.Nullable; public final class EnchantmentMappings { - public static final String[] ENCHANTMENTS = { + public static final KeyMappings ENCHANTMENTS = new KeyMappings( "protection", "fire_protection", "feather_falling", @@ -64,20 +62,13 @@ public final class EnchantmentMappings { "piercing", "mending", "vanishing_curse" - }; - private static final Object2IntMap STRING_TO_ID = new Object2IntOpenHashMap<>(); - - static { - for (int i = 0; i < ENCHANTMENTS.length; i++) { - STRING_TO_ID.put(ENCHANTMENTS[i], i); - } - } + ); public static @Nullable String enchantment(final int id) { - return id >= 0 && id < ENCHANTMENTS.length ? ENCHANTMENTS[id] : null; + return ENCHANTMENTS.idToKey(id); } public static int id(final String attribute) { - return STRING_TO_ID.getOrDefault(Key.stripMinecraftNamespace(attribute), -1); + return ENCHANTMENTS.keyToId(attribute); } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/InstrumentMappings.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/InstrumentMappings.java new file mode 100644 index 000000000..33948b568 --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/InstrumentMappings.java @@ -0,0 +1,43 @@ +/* + * 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.data; + +import com.viaversion.viaversion.util.KeyMappings; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class InstrumentMappings { + + private static final KeyMappings MAPPINGS = new KeyMappings( + "ponder_goat_horn", + "sing_goat_horn", + "seek_goat_horn", + "feel_goat_horn", + "admire_goat_horn", + "call_goat_horn", + "yearn_goat_horn", + "dream_goat_horn" + ); + + public static @Nullable String idToKey(final int id) { + return MAPPINGS.idToKey(id); + } + + public static int keyToId(final String name) { + return MAPPINGS.keyToId(name); + } +} diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MapDecorationMappings.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MapDecorationMappings.java index 5af00a952..24c46bc31 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MapDecorationMappings.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MapDecorationMappings.java @@ -17,9 +17,11 @@ */ package com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data; +import com.viaversion.viaversion.util.KeyMappings; + public final class MapDecorationMappings { - private static final String[] MAP_DECORATIONS = { + private static final KeyMappings MAP_DECORATIONS = new KeyMappings( "player", "frame", "red_marker", @@ -54,9 +56,9 @@ public final class MapDecorationMappings { "village_taiga", "jungle_temple", "swamp_hut" - }; + ); public static String mapDecoration(final int index) { - return index < 0 || index >= MAP_DECORATIONS.length ? "player" : MAP_DECORATIONS[index]; + return index < 0 || index >= MAP_DECORATIONS.size() ? "player" : MAP_DECORATIONS.idToKey(index); } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/BlockItemPacketRewriter1_20_5.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/BlockItemPacketRewriter1_20_5.java index 8d294dc60..f2f11dad6 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/BlockItemPacketRewriter1_20_5.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/BlockItemPacketRewriter1_20_5.java @@ -26,6 +26,7 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import com.viaversion.viaversion.api.data.ParticleMappings; import com.viaversion.viaversion.api.minecraft.GameProfile; import com.viaversion.viaversion.api.minecraft.GlobalPosition; +import com.viaversion.viaversion.api.minecraft.Holder; import com.viaversion.viaversion.api.minecraft.Particle; import com.viaversion.viaversion.api.minecraft.data.StructuredData; import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer; @@ -39,17 +40,21 @@ import com.viaversion.viaversion.api.minecraft.item.data.Enchantments; import com.viaversion.viaversion.api.minecraft.item.data.FilterableComponent; import com.viaversion.viaversion.api.minecraft.item.data.FilterableString; import com.viaversion.viaversion.api.minecraft.item.data.FireworkExplosion; +import com.viaversion.viaversion.api.minecraft.item.data.Fireworks; import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker; +import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect; import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook; 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_3; import com.viaversion.viaversion.api.type.types.version.Types1_20_5; +import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.util.PotionEffects; import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.ClientboundPacket1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.ClientboundPackets1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.rewriter.RecipeRewriter1_20_3; 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.EnchantmentMappings; +import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.InstrumentMappings; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.MapDecorationMappings; 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; @@ -202,7 +207,6 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter if (tag == null) { return item; } @@ -255,14 +261,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter properties = new HashMap<>(); - for (final Map.Entry entry : blockState.entrySet()) { - if (entry.getValue() instanceof StringTag) { - properties.put(entry.getKey(), ((StringTag) entry.getValue()).getValue()); - } - } - // TODO block state changes - data.set(StructuredDataKey.BLOCK_STATE, new BlockStateProperties(properties)); + updateBlockState(blockState, data); } final CompoundTag entityTag = tag.getCompoundTag("EntityTag"); @@ -299,19 +298,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter recipesTag = tag.getListTag("Recipes", StringTag.class); @@ -322,17 +309,28 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter effectsTag = tag.getListTag("effects", CompoundTag.class); + if (effectsTag != null) { + updateEffects(effectsTag, data); + } + + final StringTag instrumentTag = tag.getStringTag("instrument"); + if (instrumentTag != null) { + final int id = InstrumentMappings.keyToId(instrumentTag.getValue()); + if (id != -1) { + data.set(StructuredDataKey.INSTRUMENT, Holder.of(id)); + } + } + + final CompoundTag fireworksTag = tag.getCompoundTag("Fireworks"); + if (fireworksTag != null) { + final ListTag explosionsTag = fireworksTag.getListTag("Explosions", CompoundTag.class); + if (explosionsTag != null) { + updateFireworks(fireworksTag, explosionsTag, data); + } } if (old.identifier() == 1085) { @@ -347,12 +345,15 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter decorationsTag = tag.getListTag("Decorations", CompoundTag.class); + if (decorationsTag != null) { + updateMapDecorations(data, decorationsTag); + } // MAP_POST_PROCESSING is only used internally @@ -365,12 +366,9 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter properties = new HashMap<>(); + for (final Map.Entry entry : blockState.entrySet()) { + // It's all strings now because ??? + final Tag value = entry.getValue(); + if (value instanceof StringTag) { + properties.put(entry.getKey(), ((StringTag) value).getValue()); + } else if (value instanceof NumberTag) { + // TODO Boolean values + properties.put(entry.getKey(), Integer.toString(((NumberTag) value).asInt())); + } + } + data.set(StructuredDataKey.BLOCK_STATE, new BlockStateProperties(properties)); + } + + private static void updateFireworks(final CompoundTag fireworksTag, final ListTag explosionsTag, final StructuredDataContainer data) { + final NumberTag flightDuration = fireworksTag.getNumberTag("Flight"); + final Fireworks fireworks = new Fireworks( + flightDuration != null ? flightDuration.asInt() : 0, + explosionsTag.stream().map(BlockItemPacketRewriter1_20_5::readExplosion).toArray(FireworkExplosion[]::new) + ); + data.set(StructuredDataKey.FIREWORKS, fireworks); + } + + private static void updateEffects(final ListTag effects, final StructuredDataContainer data) { + final SuspiciousStewEffect[] suspiciousStewEffects = new SuspiciousStewEffect[effects.size()]; + for (int i = 0; i < effects.size(); i++) { + final CompoundTag effect = effects.get(i); + final StringTag effectId = effect.getStringTag("id"); + final NumberTag duration = effect.getNumberTag("duration"); + final SuspiciousStewEffect stewEffect = new SuspiciousStewEffect( + PotionEffects.keyToId(effectId != null ? effectId.getValue() : "luck") - 1, + duration != null ? duration.asInt() : 0 + ); + suspiciousStewEffects[i] = stewEffect; + } + data.set(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, suspiciousStewEffects); + } + + private static void updateLodestoneTracker(final CompoundTag tag, final CompoundTag lodestonePosTag, final StringTag lodestoneDimensionTag, final StructuredDataContainer data) { + final NumberTag trackedTag = tag.getNumberTag("LodestoneTracked"); + final NumberTag xTag = lodestonePosTag.getNumberTag("X"); + final NumberTag yTag = lodestonePosTag.getNumberTag("Y"); + final NumberTag zTag = lodestonePosTag.getNumberTag("Z"); + final GlobalPosition position = new GlobalPosition( + lodestoneDimensionTag.getValue(), + xTag != null ? xTag.asInt() : 0, + yTag != null ? yTag.asInt() : 0, + zTag != null ? zTag.asInt() : 0 + ); + data.set(StructuredDataKey.LODESTONE_TRACKER, new LodestoneTracker(position, trackedTag != null && trackedTag.asBoolean())); + } + + private static FireworkExplosion readExplosion(final CompoundTag tag) { + final NumberTag shape = tag.getNumberTag("Type"); + final IntArrayTag colors = tag.getIntArrayTag("Colors"); + final IntArrayTag fadeColors = tag.getIntArrayTag("FadeColors"); + final NumberTag trail = tag.getNumberTag("Trail"); + final NumberTag flicker = tag.getNumberTag("Flicker"); + return new FireworkExplosion( + shape != null ? shape.asInt() : 0, + colors != null ? colors.getValue() : new int[0], + fadeColors != null ? fadeColors.getValue() : new int[0], + trail != null && trail.asBoolean(), + flicker != null && flicker.asBoolean() + ); + } + private void updateWritableBookPages(final StructuredDataContainer data, final CompoundTag tag) { final ListTag pagesTag = tag.getListTag("pages", StringTag.class); final CompoundTag filteredPagesTag = tag.getCompoundTag("filtered_pages"); @@ -454,11 +520,8 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter items = new ArrayList<>(); - for (final CompoundTag item : chargedProjectiles) { - items.add(itemFromTag(item)); - } - data.set(dataKey, items.toArray(new Item[0])); + final Item[] items = chargedProjectiles.stream().map(this::itemFromTag).toArray(Item[]::new); + data.set(dataKey, items); } private Item itemFromTag(final CompoundTag item) { @@ -502,7 +565,6 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter properties = new ArrayList<>(1); if (skullOwnerTag instanceof StringTag) { final String name = ((StringTag) skullOwnerTag).getValue(); data.set(StructuredDataKey.PROFILE, new GameProfile(name, null, EMPTY_PROPERTIES)); @@ -517,6 +579,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter properties = new ArrayList<>(1); final CompoundTag propertiesTag = skullOwner.getCompoundTag("Properties"); if (propertiesTag != null) { updateProperties(propertiesTag, properties); @@ -549,10 +612,6 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter decorationsTag) { - if (decorationsTag == null) { - return; - } - final CompoundTag updatedDecorationsTag = new CompoundTag(); for (final CompoundTag decorationTag : decorationsTag) { final StringTag idTag = decorationTag.getStringTag("id"); @@ -591,11 +650,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter loreTag = displayTag.getListTag("Lore", StringTag.class); if (loreTag != null) { - final List updatedLore = new ArrayList<>(); - for (final StringTag loreEntry : loreTag) { - updatedLore.add(ComponentUtil.jsonStringToTag((loreEntry.getValue()))); - } - data.set(StructuredDataKey.LORE, updatedLore.toArray(new Tag[0])); + data.set(StructuredDataKey.LORE, loreTag.stream().map(t -> ComponentUtil.jsonStringToTag(t.getValue())).toArray(Tag[]::new)); } final NumberTag colorTag = displayTag.getNumberTag("color"); diff --git a/common/src/main/java/com/viaversion/viaversion/rewriter/SoundRewriter.java b/common/src/main/java/com/viaversion/viaversion/rewriter/SoundRewriter.java index 52a25326f..ed94a710b 100644 --- a/common/src/main/java/com/viaversion/viaversion/rewriter/SoundRewriter.java +++ b/common/src/main/java/com/viaversion/viaversion/rewriter/SoundRewriter.java @@ -69,7 +69,7 @@ public class SoundRewriter { } if (mappedId != soundEventHolder.id()) { - soundEventHolder = new Holder<>(mappedId); + soundEventHolder = Holder.of(mappedId); } wrapper.write(Type.SOUND_EVENT, soundEventHolder); diff --git a/common/src/main/java/com/viaversion/viaversion/util/KeyMappings.java b/common/src/main/java/com/viaversion/viaversion/util/KeyMappings.java new file mode 100644 index 000000000..16b648321 --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/util/KeyMappings.java @@ -0,0 +1,51 @@ +/* + * 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.util; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class KeyMappings { + + private final Object2IntMap keyToId; + private final String[] keys; + + public KeyMappings(final String... keys) { + this.keys = keys; + keyToId = new Object2IntOpenHashMap<>(keys.length); + for (int i = 0; i < keys.length; i++) { + keyToId.put(keys[i], i); + } + } + + public @Nullable String idToKey(final int id) { + if (id < 0 || id >= keys.length) { + return null; + } + return keys[id]; + } + + public int keyToId(final String identifier) { + return keyToId.getInt(Key.stripMinecraftNamespace(identifier)); + } + + public int size() { + return keys.length; + } +}