diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/Protocol1_21To1_21_2.java b/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/Protocol1_21To1_21_2.java index 746b19fa0..cb97f6d4e 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/Protocol1_21To1_21_2.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/Protocol1_21To1_21_2.java @@ -18,6 +18,8 @@ package com.viaversion.viaversion.protocols.v1_21to1_21_2; 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.data.StructuredDataKey; import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_2; import com.viaversion.viaversion.api.protocol.AbstractProtocol; @@ -37,7 +39,6 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPac import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21; import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21; import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21; -import com.viaversion.viaversion.protocols.v1_21to1_21_2.data.MappingData1_21_2; import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2; import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2; import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPacket1_21_2; @@ -54,7 +55,7 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap; public final class Protocol1_21To1_21_2 extends AbstractProtocol { - public static final MappingData1_21_2 MAPPINGS = new MappingData1_21_2(); + public static final MappingData MAPPINGS = new MappingDataBase("1.21", "1.21.2"); private final EntityPacketRewriter1_21_2 entityRewriter = new EntityPacketRewriter1_21_2(this); private final BlockItemPacketRewriter1_21_2 itemRewriter = new BlockItemPacketRewriter1_21_2(this); private final TagRewriter tagRewriter = new TagRewriter<>(this); @@ -180,7 +181,7 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol. - */ -package com.viaversion.viaversion.protocols.v1_21to1_21_2.data; - -import com.viaversion.nbt.tag.CompoundTag; -import com.viaversion.viaversion.api.data.MappingDataBase; -import com.viaversion.viaversion.api.data.MappingDataLoader; -import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; -import com.viaversion.viaversion.api.type.Types; -import java.util.ArrayList; -import java.util.List; - -public final class MappingData1_21_2 extends MappingDataBase { - - private final List recipeInputs = new ArrayList<>(); - - public MappingData1_21_2() { - super("1.21", "1.21.2"); - } - - @Override - protected void loadExtras(final CompoundTag data) { - final CompoundTag extraMappings = MappingDataLoader.INSTANCE.loadNBT("recipe-inputs-1.21.2.nbt"); - addRecipeInputs(extraMappings, "smithing_addition"); - addRecipeInputs(extraMappings, "smithing_template"); - addRecipeInputs(extraMappings, "smithing_base"); - addRecipeInputs(extraMappings, "furnace_input"); - addRecipeInputs(extraMappings, "smoker_input"); - addRecipeInputs(extraMappings, "blast_furnace_input"); - addRecipeInputs(extraMappings, "campfire_input"); - } - - private void addRecipeInputs(final CompoundTag tag, final String key) { - final int[] ids = tag.getIntArrayTag(key).getValue(); - recipeInputs.add(new RecipeInputs(key, ids)); - } - - public void writeInputs(final PacketWrapper wrapper) { - wrapper.write(Types.VAR_INT, recipeInputs.size()); - for (final RecipeInputs inputs : recipeInputs) { - wrapper.write(Types.STRING, inputs.key); - wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, inputs.ids.clone()); - } - } - - public record RecipeInputs(String key, int[] ids) { - } -} diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/BlockItemPacketRewriter1_21_2.java b/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/BlockItemPacketRewriter1_21_2.java index d4a060809..746e64d40 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/BlockItemPacketRewriter1_21_2.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/BlockItemPacketRewriter1_21_2.java @@ -240,10 +240,9 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter< } rewriter.finalizeRecipes(); - // These are used for client predictions, such as what items can be used as fuel in a furnace - protocol.getMappingData().writeInputs(wrapper); - - rewriter.writeStoneCutterRecipes(wrapper); + // These are used for client predictions, such smithing or furnace inputs. + // Other recipes will be written in RECIPE/RECIPE_BOOK_ADD + rewriter.writeUpdateRecipeInputs(wrapper); }); protocol.registerClientbound(ClientboundPackets1_21.RECIPE, ClientboundPackets1_21_2.RECIPE_BOOK_ADD, wrapper -> { diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/RecipeRewriter1_21_2.java b/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/RecipeRewriter1_21_2.java index f2151af52..790d4863d 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/RecipeRewriter1_21_2.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/v1_21to1_21_2/rewriter/RecipeRewriter1_21_2.java @@ -27,8 +27,11 @@ import com.viaversion.viaversion.api.type.types.version.Types1_21_2; import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3; import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21; import com.viaversion.viaversion.util.Key; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -39,9 +42,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; // Use directly as a connection storage. Slightly weird, but easiest and closed off from other packages final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3 implements StorableObject { + private static final int[] EMPTY_ARRAY = new int[0]; private final List stoneCutterRecipes = new ArrayList<>(); private final Object2IntMap recipeGroups = new Object2IntOpenHashMap<>(); private final Map recipesByKey = new HashMap<>(); + private final Map recipeInputs = new Object2ObjectArrayMap<>(); private final List recipes = new ArrayList<>(); private String currentRecipeIdentifier; @@ -52,6 +57,11 @@ final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3 protocol) { super(protocol); recipeGroups.defaultReturnValue(-1); + + recipeHandlers.put("smelting", wrapper -> handleSmelting("furnace_input", wrapper)); + recipeHandlers.put("blasting", wrapper -> handleSmelting("blast_furnace_input", wrapper)); + recipeHandlers.put("smoking", wrapper -> handleSmelting("smoker_input", wrapper)); + recipeHandlers.put("campfire_cooking", wrapper -> handleSmelting("campfire_input", wrapper)); } @Override @@ -77,17 +87,17 @@ final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3= 0 && displayId < recipes.size() ? recipes.get(displayId) : null; } - public void writeStoneCutterRecipes(final PacketWrapper wrapper) { + public void finalizeRecipes() { + // Need to be sorted alphabetically + stoneCutterRecipes.sort(Comparator.comparing(recipe -> recipe.identifier)); + } + + public void writeUpdateRecipeInputs(final PacketWrapper wrapper) { + // Smithing and smelting inputs + wrapper.write(Types.VAR_INT, recipeInputs.size()); + for (final Map.Entry entry : recipeInputs.entrySet()) { + wrapper.write(Types.STRING, entry.getKey()); + wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, entry.getValue().toArray(EMPTY_ARRAY)); + } + + // Stonecutter recipes wrapper.write(Types.VAR_INT, stoneCutterRecipes.size()); for (final StoneCutterRecipe recipe : stoneCutterRecipes) { final HolderSet ingredient = toHolderSet(recipe.ingredient()); @@ -186,9 +208,14 @@ final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3 recipe.identifier)); + private Item[] readRecipeInputs(final String key, final PacketWrapper wrapper) { + // Collect inputs for new UPDATE_RECIPE + final Item[] ingredient = readIngredient(wrapper); + final IntSet ids = recipeInputs.computeIfAbsent(key, $ -> new IntOpenHashSet(ingredient.length)); + for (final Item item : ingredient) { + ids.add(item.identifier()); + } + return ingredient; } interface Recipe { diff --git a/common/src/main/resources/assets/viaversion/data/recipe-inputs-1.21.2.nbt b/common/src/main/resources/assets/viaversion/data/recipe-inputs-1.21.2.nbt deleted file mode 100644 index 90ae695c2..000000000 Binary files a/common/src/main/resources/assets/viaversion/data/recipe-inputs-1.21.2.nbt and /dev/null differ