More handled structures

This commit is contained in:
Nassim Jahnke 2024-03-08 13:43:13 +01:00
parent 329abcac7d
commit 7a66bb8e1c
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
12 changed files with 340 additions and 131 deletions

View File

@ -22,21 +22,29 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
public interface Holder<T> {
public final class Holder<T> {
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 <T> the type of the value
* @return a new holder with the given id
* @throws IllegalArgumentException if the id is negative
*/
static <T> Holder<T> 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 <T> the type of the value
* @return a new direct holder
*/
static <T> Holder<T> of(final T value) {
return new HolderImpl<>(value);
}
/**
@ -45,9 +53,7 @@ public final class Holder<T> {
* @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<T> {
* @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();
}

View File

@ -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<T> implements Holder<T> {
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;
}
}

View File

@ -36,9 +36,9 @@ public abstract class HolderType<T> extends Type<Holder<T>> {
public Holder<T> 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

View File

@ -245,7 +245,7 @@ public class InventoryPackets extends ItemRewriter<ClientboundPackets1_13, Serve
if (display != null) {
ListTag<StringTag> 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<ClientboundPackets1_13, Serve
if (lore != null) {
Tag savedLore = display.remove(nbtTagName("Lore"));
if (savedLore instanceof ListTag) {
display.put("Lore", new ListTag<>(((ListTag<?>) savedLore).getValue()));
display.put("Lore", savedLore.copy());
} else {
for (StringTag loreEntry : lore) {
loreEntry.setValue(ComponentUtil.jsonToLegacy(loreEntry.getValue()));

View File

@ -96,13 +96,13 @@ public final class Protocol1_19_3To1_19_1 extends AbstractProtocol<ClientboundPa
return;
}
wrapper.write(Type.SOUND_EVENT, new Holder<>(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);

View File

@ -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> 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);
}
}

View File

@ -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> 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);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -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);
}
}

View File

@ -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<Clientboun
return toOldItem(item);
}
// TODO Block entity changes
public Item toOldItem(final Item item) {
// Start out with custom data and add the rest on top, or short-curcuit with the original item
final StructuredDataContainer data = item.structuredData();
@ -220,11 +224,13 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
return dataItem;
}
// TODO Block entity changes
public Item toStructuredItem(final Item old, final boolean addMarker) {
final CompoundTag tag = old.tag();
final StructuredItem item = new StructuredItem(old.identifier(), (byte) old.amount(), new StructuredDataContainer());
final StructuredDataContainer data = item.structuredData();
data.setIdLookup(protocol, true);
// TODO add default data :>
if (tag == null) {
return item;
}
@ -255,14 +261,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final CompoundTag blockState = tag.getCompoundTag("BlockStateTag");
if (blockState != null) {
final Map<String, String> properties = new HashMap<>();
for (final Map.Entry<String, Tag> 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<Clientboun
final CompoundTag explosionTag = tag.getCompoundTag("Explosion");
if (explosionTag != null) {
final NumberTag shape = explosionTag.getNumberTag("Type");
final IntArrayTag colors = explosionTag.getIntArrayTag("Colors");
final IntArrayTag fadeColors = explosionTag.getIntArrayTag("FadeColors");
final NumberTag trail = explosionTag.getNumberTag("Trail");
final NumberTag flicker = explosionTag.getNumberTag("Flicker");
final FireworkExplosion explosion = 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()
);
data.set(StructuredDataKey.FIREWORK_EXPLOSION, explosion);
data.set(StructuredDataKey.FIREWORK_EXPLOSION, readExplosion(explosionTag));
}
final ListTag<StringTag> recipesTag = tag.getListTag("Recipes", StringTag.class);
@ -322,17 +309,28 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final CompoundTag lodestonePosTag = tag.getCompoundTag("LodestonePos");
final StringTag lodestoneDimensionTag = tag.getStringTag("LodestoneDimension");
if (lodestonePosTag != null && lodestoneDimensionTag != null) {
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()));
updateLodestoneTracker(tag, lodestonePosTag, lodestoneDimensionTag, data);
}
final ListTag<CompoundTag> 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<CompoundTag> 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<Clientboun
updateEnchantments(data, tag, "Enchantments", StructuredDataKey.ENCHANTMENTS, (hideFlagsValue & 0x01) == 0);
updateEnchantments(data, tag, "StoredEnchantments", StructuredDataKey.STORED_ENCHANTMENTS, (hideFlagsValue & 0x20) == 0);
final NumberTag map = tag.getNumberTag("map");
if (map != null) {
data.set(StructuredDataKey.MAP_ID, map.asInt());
final NumberTag mapId = tag.getNumberTag("map");
if (mapId != null) {
data.set(StructuredDataKey.MAP_ID, mapId.asInt());
}
updateMapDecorations(data, tag.getListTag("Decorations", CompoundTag.class));
final ListTag<CompoundTag> 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<Clientboun
// StructuredDataKey.CREATIVE_SLOT_LOCK
// StructuredDataKey.INTANGIBLE_PROJECTILE
// StructuredDataKey.POTION_CONTENTS
// StructuredDataKey.SUSPICIOUS_STEW_EFFECTS
// StructuredDataKey.TRIM
// StructuredDataKey.BUCKET_ENTITY_DATA
// StructuredDataKey.BLOCK_ENTITY_DATA
// StructuredDataKey.INSTRUMENT
// StructuredDataKey.FIREWORKS
// StructuredDataKey.NOTE_BLOCK_SOUND
// StructuredDataKey.BANNER_PATTERNS
// StructuredDataKey.BASE_COLOR
@ -388,6 +386,74 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
return item;
}
private static void updateBlockState(final CompoundTag blockState, final StructuredDataContainer data) {
final Map<String, String> properties = new HashMap<>();
for (final Map.Entry<String, Tag> 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<CompoundTag> 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<CompoundTag> 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<StringTag> 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<Clientboun
return;
}
final List<Item> 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<Clientboun
}
private void updateProfile(final StructuredDataContainer data, final Tag skullOwnerTag) {
final List<GameProfile.Property> 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<Clientboun
uuid = UUIDUtil.fromIntArray(idTag.getValue());
}
final List<GameProfile.Property> 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<Clientboun
}
private void updateMapDecorations(final StructuredDataContainer data, final ListTag<CompoundTag> 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<Clientboun
final ListTag<StringTag> loreTag = displayTag.getListTag("Lore", StringTag.class);
if (loreTag != null) {
final List<Tag> 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");

View File

@ -69,7 +69,7 @@ public class SoundRewriter<C extends ClientboundPacketType> {
}
if (mappedId != soundEventHolder.id()) {
soundEventHolder = new Holder<>(mappedId);
soundEventHolder = Holder.of(mappedId);
}
wrapper.write(Type.SOUND_EVENT, soundEventHolder);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<String> 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;
}
}