From 386495e1681cff47e82712d300b1449f39248ffc Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Wed, 6 Mar 2024 13:20:29 +0100 Subject: [PATCH] Handle map related data and skull owners Co-authored-by: Drex --- .../api/minecraft/data/StructuredDataKey.java | 2 +- .../minecraft/item/data/MapDecoration.java | 77 +++++++++++ .../minecraft/item/data/MapDecorations.java | 65 +++++++++ .../data/MapDecorationMappings.java | 62 +++++++++ .../BlockItemPacketRewriter1_20_5.java | 126 ++++++++++++++++-- 5 files changed, 318 insertions(+), 14 deletions(-) create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecoration.java create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecorations.java create mode 100644 common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MapDecorationMappings.java diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataKey.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataKey.java index 37fe3bbc5..2116e27d6 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataKey.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/data/StructuredDataKey.java @@ -93,7 +93,7 @@ public final class StructuredDataKey { public static final StructuredDataKey CONTAINER = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY); public static final StructuredDataKey BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE); public static final StructuredDataKey BEES = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE); - public static final StructuredDataKey LOCK = new StructuredDataKey<>("lock", Type.COMPOUND_TAG); + public static final StructuredDataKey LOCK = new StructuredDataKey<>("lock", Type.TAG); public static final StructuredDataKey CONTAINER_LOOT = new StructuredDataKey<>("container_loot", Type.COMPOUND_TAG); private final String identifier; diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecoration.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecoration.java new file mode 100644 index 000000000..e2252a447 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecoration.java @@ -0,0 +1,77 @@ +/* + * 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.item.data; + +import com.viaversion.viaversion.api.type.Type; +import io.netty.buffer.ByteBuf; + +public final class MapDecoration { + + public static final Type TYPE = new Type(MapDecoration.class) { + @Override + public MapDecoration read(final ByteBuf buffer) throws Exception { + final String type = Type.STRING.read(buffer); + final double x = Type.DOUBLE.readPrimitive(buffer); + final double z = Type.DOUBLE.readPrimitive(buffer); + final float rotation = Type.FLOAT.readPrimitive(buffer); + return new MapDecoration(type, x, z, rotation); + } + + @Override + public void write(final ByteBuf buffer, final MapDecoration value) throws Exception { + Type.STRING.write(buffer, value.type); + buffer.writeDouble(value.x); + buffer.writeDouble(value.z); + buffer.writeFloat(value.rotation); + } + }; + + private final String type; + private final double x; + private final double z; + private final float rotation; + + public MapDecoration(final String type, final double x, final double z, final float rotation) { + this.type = type; + this.x = x; + this.z = z; + this.rotation = rotation; + } + + public String type() { + return type; + } + + public double x() { + return x; + } + + public double z() { + return z; + } + + public float rotation() { + return rotation; + } + +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecorations.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecorations.java new file mode 100644 index 000000000..6bb9f4c3c --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/item/data/MapDecorations.java @@ -0,0 +1,65 @@ +/* + * 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.item.data; + +import com.viaversion.viaversion.api.type.Type; +import io.netty.buffer.ByteBuf; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import java.util.Map; + +public final class MapDecorations { + + public static final Type TYPE = new Type(MapDecorations.class) { + @Override + public MapDecorations read(final ByteBuf buffer) throws Exception { + final Object2ObjectMap decorations = new Object2ObjectOpenHashMap<>(); + final int size = Type.VAR_INT.readPrimitive(buffer); + for (int i = 0; i < size; i++) { + final String id = Type.STRING.read(buffer); + final MapDecoration decoration = MapDecoration.TYPE.read(buffer); + decorations.put(id, decoration); + } + return new MapDecorations(decorations); + } + + @Override + public void write(final ByteBuf buffer, final MapDecorations value) throws Exception { + Type.VAR_INT.writePrimitive(buffer, value.decorations.size()); + for (final Map.Entry entry : value.decorations.entrySet()) { + Type.STRING.write(buffer, entry.getKey()); + MapDecoration.TYPE.write(buffer, entry.getValue()); + } + } + }; + + private final Map decorations; + + public MapDecorations(final Map decorations) { + this.decorations = decorations; + } + + public Map decorations() { + return decorations; + } +} 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 new file mode 100644 index 000000000..5af00a952 --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MapDecorationMappings.java @@ -0,0 +1,62 @@ +/* + * 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; + +public final class MapDecorationMappings { + + private static final String[] MAP_DECORATIONS = { + "player", + "frame", + "red_marker", + "blue_marker", + "target_x", + "target_point", + "player_off_map", + "player_off_limits", + "mansion", + "monument", + "banner_white", + "banner_orange", + "banner_magenta", + "banner_light_blue", + "banner_yellow", + "banner_lime", + "banner_pink", + "banner_gray", + "banner_light_gray", + "banner_cyan", + "banner_purple", + "banner_blue", + "banner_brown", + "banner_green", + "banner_red", + "banner_black", + "red_x", + "village_desert", + "village_plains", + "village_savanna", + "village_snowy", + "village_taiga", + "jungle_temple", + "swamp_hut" + }; + + public static String mapDecoration(final int index) { + return index < 0 || index >= MAP_DECORATIONS.length ? "player" : MAP_DECORATIONS[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 0bd8017ee..1b250a6d3 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 @@ -18,11 +18,13 @@ 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.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.NumberTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; 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.Particle; import com.viaversion.viaversion.api.minecraft.data.StructuredData; import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer; @@ -41,18 +43,25 @@ import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.Clientb 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.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; import com.viaversion.viaversion.rewriter.BlockRewriter; import com.viaversion.viaversion.rewriter.ItemRewriter; import com.viaversion.viaversion.util.Key; +import com.viaversion.viaversion.util.UUIDUtil; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter { + private final String tagMarker = "VV|" + protocol.getClass().getSimpleName(); + public BlockItemPacketRewriter1_20_5(final Protocol1_20_5To1_20_3 protocol) { super(protocol, Type.ITEM1_20_2, Type.ITEM1_20_2_ARRAY, Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY); } @@ -208,27 +217,25 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter properties = new HashMap<>(); for (final Map.Entry entry : blockState.entrySet()) { if (entry.getValue() instanceof StringTag) { @@ -240,7 +247,6 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter properties = new ArrayList<>(1); + UUID uuid = null; + if (skullOwnerTag instanceof StringTag) { + name = ((StringTag) skullOwnerTag).getValue(); + } else if (skullOwnerTag instanceof CompoundTag) { + final CompoundTag skullOwner = (CompoundTag) skullOwnerTag; + final StringTag nameTag = skullOwner.getStringTag("Name"); + name = nameTag != null ? nameTag.getValue() : ""; + + final IntArrayTag idTag = skullOwner.getIntArrayTag("Id"); + if (idTag != null) { + uuid = UUIDUtil.fromIntArray(idTag.getValue()); + } + + final CompoundTag propertiesTag = skullOwner.getCompoundTag("Properties"); + if (propertiesTag != null) { + for (final Map.Entry entry : propertiesTag.entrySet()) { + if (!(entry.getValue() instanceof ListTag)) { + continue; + } + + for (final Tag propertyTag : (ListTag) entry.getValue()) { + if (!(propertyTag instanceof CompoundTag)) { + continue; + } + + final StringTag valueTag = ((CompoundTag) propertyTag).getStringTag("Value"); + final StringTag signatureTag = ((CompoundTag) propertyTag).getStringTag("Signature"); + final GameProfile.Property property = new GameProfile.Property( + entry.getKey(), + valueTag != null ? valueTag.getValue() : "", + signatureTag != null ? signatureTag.getValue() : null + ); + properties.add(property); + } + } + } + } else { + return; + } + + data.add(StructuredDataKey.PROFILE, new GameProfile(name, uuid, properties.toArray(new GameProfile.Property[0]))); + } + + private void updateMapDecorations(final StructuredDataContainer data, final ListTag decorationsTag) { + if (decorationsTag == null) { + return; + } + + final CompoundTag updatedDecorationsTag = new CompoundTag(); + for (final Tag decorationTag : decorationsTag) { + if (!(decorationTag instanceof CompoundTag)) { + continue; + } + + final CompoundTag decoration = (CompoundTag) decorationTag; + final StringTag idTag = decoration.getStringTag("id"); + final String id = idTag != null ? idTag.asRawString() : ""; + final NumberTag typeTag = decoration.getNumberTag("type"); + final int type = typeTag != null ? typeTag.asInt() : 0; + final NumberTag xTag = decoration.getNumberTag("x"); + final NumberTag zTag = decoration.getNumberTag("z"); + final NumberTag rotationTag = decoration.getNumberTag("rot"); + + final CompoundTag updatedDecorationTag = new CompoundTag(); + updatedDecorationTag.putString("type", MapDecorationMappings.mapDecoration(type)); + updatedDecorationTag.putDouble("x", xTag != null ? xTag.asDouble() : 0); + updatedDecorationTag.putDouble("z", zTag != null ? zTag.asDouble() : 0); + updatedDecorationTag.putFloat("rotation", rotationTag != null ? rotationTag.asFloat() : 0); + updatedDecorationsTag.put(id, updatedDecorationTag); + } + + data.add(StructuredDataKey.MAP_DECORATIONS, updatedDecorationsTag); + } + + private void updateDisplay(final StructuredDataContainer data, final CompoundTag displayTag) { + if (displayTag == null) { + return; + } + + final NumberTag mapColorTag = displayTag.getNumberTag("MapColor"); + if (mapColorTag != null) { + data.add(StructuredDataKey.MAP_COLOR, mapColorTag.asInt()); + } + // TODO other display values + } } \ No newline at end of file