From 817febe60500b3646bf156f4f90e4706e2736693 Mon Sep 17 00:00:00 2001 From: FlorianMichael <60033407+FlorianMichael@users.noreply.github.com> Date: Thu, 14 Mar 2024 12:00:31 +0100 Subject: [PATCH] Even more work! --- .../Protocol1_20_5To1_20_3.java | 5 +- .../data/MappingData.java | 52 +++++++++++++ .../BlockItemPacketRewriter1_20_5.java | 73 ++++++++++++++---- .../rewriter/StructuredDataConverter.java | 62 ++++++++++++--- .../assets/viaversion/data/itemIds-1.20.3.nbt | Bin 0 -> 22238 bytes 5 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MappingData.java create mode 100644 common/src/main/resources/assets/viaversion/data/itemIds-1.20.3.nbt 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 6023368d1..6d4d63f0e 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 @@ -18,8 +18,6 @@ package com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3; import com.viaversion.viaversion.api.connection.UserConnection; -import com.viaversion.viaversion.api.data.MappingData; -import com.viaversion.viaversion.api.data.MappingDataBase; import com.viaversion.viaversion.api.minecraft.RegistryType; import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey; import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5; @@ -40,6 +38,7 @@ import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.Clientb import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.ClientboundPackets1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.ServerboundPacket1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.packet.ServerboundPackets1_20_3; +import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.MappingData; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ClientboundConfigurationPackets1_20_5; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ClientboundPacket1_20_5; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ClientboundPackets1_20_5; @@ -56,7 +55,7 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap; public final class Protocol1_20_5To1_20_3 extends AbstractProtocol { - public static final MappingData MAPPINGS = new MappingDataBase("1.20.3", "1.20.5"); + public static final MappingData MAPPINGS = new MappingData(); private final EntityPacketRewriter1_20_5 entityRewriter = new EntityPacketRewriter1_20_5(this); private final BlockItemPacketRewriter1_20_5 itemRewriter = new BlockItemPacketRewriter1_20_5(this); private final TagRewriter tagRewriter = new TagRewriter<>(this); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MappingData.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MappingData.java new file mode 100644 index 000000000..313a684a8 --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/data/MappingData.java @@ -0,0 +1,52 @@ +/* + * 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.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.viaversion.viaversion.api.data.MappingDataBase; +import com.viaversion.viaversion.api.data.MappingDataLoader; +import java.util.ArrayList; +import java.util.List; + +public class MappingData extends MappingDataBase { + + private final List itemIds = new ArrayList<>(); + + public MappingData() { + super("1.20.3", "1.20.5"); + } + + @Override + protected void loadExtras(final CompoundTag data) { + super.loadExtras(data); + + final CompoundTag items = MappingDataLoader.loadNBT("itemIds-1.20.3.nbt"); + for (final StringTag tag : items.getListTag("items", StringTag.class)) { + itemIds.add(tag.getValue()); + } + } + + public int itemId(final String name) { + return itemIds.indexOf(name); + } + + public String itemName(final int id) { + return itemIds.get(id); + } +} 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 ea6c58eee..6ff00465a 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 @@ -40,6 +40,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrimPattern; import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifier; import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers; import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer; +import com.viaversion.viaversion.api.minecraft.item.data.Bee; import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties; import com.viaversion.viaversion.api.minecraft.item.data.DyedColor; import com.viaversion.viaversion.api.minecraft.item.data.Enchantments; @@ -91,7 +92,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter { - private static final String[] MOB_TAGS = {"NoAI", "Silent", "NoGravity", "Glowing", "Invulnerable", "Health", "Age", "Variant", "HuntingCooldown", "BucketVariantTag"}; + public static final String[] MOB_TAGS = {"NoAI", "Silent", "NoGravity", "Glowing", "Invulnerable", "Health", "Age", "Variant", "HuntingCooldown", "BucketVariantTag"}; private static final GameProfile.Property[] EMPTY_PROPERTIES = new GameProfile.Property[0]; public BlockItemPacketRewriter1_20_5(final Protocol1_20_5To1_20_3 protocol) { @@ -395,18 +396,15 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter beesTag) { + final Bee[] bees = beesTag.stream().map(bee -> { + final CompoundTag entityData = bee.getCompoundTag("EntityData"); + final int ticksInHive = bee.getInt("TicksInHive"); + final int minOccupationTicks = bee.getInt("MinOccupationTicks"); + + return new Bee(entityData, ticksInHive, minOccupationTicks); + }).toArray(Bee[]::new); + + data.set(StructuredDataKey.BEES, bees); + } + private void updateProperties(final CompoundTag propertiesTag, final List properties) { for (final Map.Entry entry : propertiesTag.entrySet()) { if (!(entry.getValue() instanceof ListTag)) { @@ -810,9 +825,41 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter beesTag = tag.getListTag("Bees", CompoundTag.class); + if (beesTag != null) { + updateBees(data, beesTag); + } + + final ListTag sherdsTag = tag.getListTag("sherds", StringTag.class); + if (sherdsTag != null) { + final String sherd1 = sherdsTag.get(0).getValue(); + final String sherd2 = sherdsTag.get(1).getValue(); + final String sherd3 = sherdsTag.get(2).getValue(); + final String sherd4 = sherdsTag.get(3).getValue(); + + data.set(StructuredDataKey.POT_DECORATIONS, new int[]{toItemId(sherd1), toItemId(sherd2), toItemId(sherd3), toItemId(sherd4)}); + } + + final StringTag noteBlockSoundTag = tag.getStringTag("note_block_sound"); + if (noteBlockSoundTag != null) { + data.set(StructuredDataKey.NOTE_BLOCK_SOUND, noteBlockSoundTag.getValue()); + } + + final StringTag lootTableTag = tag.getStringTag("LootTable"); + if (lootTableTag != null) { + final long lootTableSeed = tag.getLong("LootTableSeed"); + + final CompoundTag containerLoot = new CompoundTag(); + containerLoot.putString("loot_table", lootTableTag.getValue()); + containerLoot.putLong("loot_table_seed", lootTableSeed); + data.set(StructuredDataKey.CONTAINER_LOOT, containerLoot); + } } final Tag skullOwnerTag = tag.remove("SkullOwner"); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java index b5e903dfd..2a31be9cf 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java @@ -27,15 +27,18 @@ import com.viaversion.viaversion.api.minecraft.data.StructuredData; import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey; import com.viaversion.viaversion.api.minecraft.item.Item; import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifier; +import com.viaversion.viaversion.api.minecraft.item.data.Bee; 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.protocols.protocol1_20_5to1_20_3.Protocol1_20_5To1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.Attributes1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.Enchantments1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.Instruments1_20_3; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.data.MapDecorations1_20_3; import com.viaversion.viaversion.util.ComponentUtil; +import com.viaversion.viaversion.util.Key; import com.viaversion.viaversion.util.UUIDUtil; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; @@ -220,6 +223,42 @@ final class StructuredDataConverter { tag.putString("instrument", identifier); } }); + register(StructuredDataKey.BEES, (data, tag) -> { + final ListTag bees = new ListTag<>(CompoundTag.class); + for (final Bee bee : data) { + final CompoundTag beeTag = new CompoundTag(); + beeTag.put("EntityData", bee.entityData()); + beeTag.putInt("TicksInHive", bee.ticksInHive()); + beeTag.putInt("MinOccupationTicks", bee.minTicksInHive()); + bees.add(beeTag); + } + getBlockEntityTag(tag).put("Bees", bees); + }); + register(StructuredDataKey.LOCK, (data, tag) -> getBlockEntityTag(tag).put("Lock", data)); + register(StructuredDataKey.NOTE_BLOCK_SOUND, (data, tag) -> getBlockEntityTag(tag).putString("note_block_sound", data)); + register(StructuredDataKey.POT_DECORATIONS, (data, tag) -> { + final ListTag sherds = new ListTag<>(StringTag.class); + for (final int id : data) { + final int oldId = Protocol1_20_5To1_20_3.MAPPINGS.getOldItemId(id); + sherds.add(new StringTag(Protocol1_20_5To1_20_3.MAPPINGS.itemName(oldId))); + } + getBlockEntityTag(tag).put("sherds", sherds); + }); + register(StructuredDataKey.CREATIVE_SLOT_LOCK, (data, tag) -> tag.put("CustomCreativeLock", new CompoundTag())); + register(StructuredDataKey.DEBUG_STICK_STATE, (data, tag) -> tag.put("DebugProperty", data)); + register(StructuredDataKey.RECIPES, (data, tag) -> tag.put("Recipes", data)); + register(StructuredDataKey.ENTITY_DATA, (data, tag) -> tag.put("EntityTag", data)); + register(StructuredDataKey.BUCKET_ENTITY_DATA, (data, tag) -> { + for (final String mobTagName : BlockItemPacketRewriter1_20_5.MOB_TAGS) { + if (data.contains(mobTagName)) { + tag.put(mobTagName, data.get(mobTagName)); + } + } + }); + register(StructuredDataKey.BLOCK_ENTITY_DATA, (data, tag) -> { + // Handling of previously block entity tags is done using the getBlockEntityTag method + tag.put("BlockEntityTag", data); + }); //register(StructuredDataKey., (data, tag) -> ); //TODO @@ -228,25 +267,24 @@ final class StructuredDataConverter { // StructuredDataKey POTION_CONTENT // StructuredDataKey SUSPICIOUS_STEW_EFFECT // StructuredDataKey TRIM - // StructuredDataKey DEBUG_STICK_STATE - // StructuredDataKey ENTITY_DATA - // StructuredDataKey BUCKET_ENTITY_DATA - // StructuredDataKey BLOCK_ENTITY_DATA - // StructuredDataKey RECIPES // StructuredDataKey BANNER_PATTERNS // StructuredDataKey BLOCK_STATE - // StructuredDataKey POT_DECORATIONS - // StructuredDataKey NOTE_BLOCK_SOUND - // StructuredDataKey BEES - // StructuredDataKey LOCK // StructuredDataKey CONTAINER_LOOT // StructuredDataKey CONTAINER - // StructuredDataKey CREATIVE_SLOT_LOCK // StructuredDataKey ENCHANTMENT_GLINT_OVERRIDE // StructuredDataKey INTANGIBLE_PROJECTILE // StructuredDataKey MAP_POST_PROCESSING } + private static CompoundTag getBlockEntityTag(final CompoundTag tag) { + CompoundTag blockEntityTag = tag.getCompoundTag("BlockEntityTag"); + if (blockEntityTag == null) { + blockEntityTag = new CompoundTag(); + tag.put("BlockEntityTag", blockEntityTag); + } + return blockEntityTag; + } + private static CompoundTag convertExplosion(final FireworkExplosion explosion) { final CompoundTag explosionTag = new CompoundTag(); explosionTag.putInt("Type", explosion.shape()); @@ -260,8 +298,10 @@ final class StructuredDataConverter { private static void convertItemList(final Item[] items, final CompoundTag tag, final String key) { final ListTag itemsTag = new ListTag<>(CompoundTag.class); for (final Item item : items) { + final int oldId = Protocol1_20_5To1_20_3.MAPPINGS.getOldItemId(item.identifier()); + final CompoundTag savedItem = new CompoundTag(); - savedItem.putString("id", "stone"); // TODO + savedItem.putString("id", Protocol1_20_5To1_20_3.MAPPINGS.itemName(oldId)); savedItem.putByte("Count", (byte) item.amount()); final CompoundTag itemTag = new CompoundTag(); diff --git a/common/src/main/resources/assets/viaversion/data/itemIds-1.20.3.nbt b/common/src/main/resources/assets/viaversion/data/itemIds-1.20.3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..0f02d99b035c059cb1f7a3dcd9e0d95bb8c4d76b GIT binary patch literal 22238 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 LALt2*c&Ym@4QLCt literal 0 HcmV?d00001