Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-11-16 13:00:12 +01:00
Start working on recipe rewriting
Dieser Commit ist enthalten in:
Ursprung
354a5f1b75
Commit
aabe47f8bc
@ -36,7 +36,7 @@ public interface HolderSet {
|
|||||||
* @return a new holder set
|
* @return a new holder set
|
||||||
*/
|
*/
|
||||||
static HolderSet of(final String tagKey) {
|
static HolderSet of(final String tagKey) {
|
||||||
return new HolderSetImpl(tagKey);
|
return new HolderSetImpl.Tag(tagKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,7 +46,7 @@ public interface HolderSet {
|
|||||||
* @return a new holder set
|
* @return a new holder set
|
||||||
*/
|
*/
|
||||||
static HolderSet of(final int[] ids) {
|
static HolderSet of(final int[] ids) {
|
||||||
return new HolderSetImpl(ids);
|
return new HolderSetImpl.Ids(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,50 +22,63 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.api.minecraft;
|
package com.viaversion.viaversion.api.minecraft;
|
||||||
|
|
||||||
import com.viaversion.viaversion.util.EitherImpl;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
final class HolderSetImpl extends EitherImpl<String, int[]> implements HolderSet {
|
final class HolderSetImpl {
|
||||||
|
|
||||||
HolderSetImpl(final String tagKey) {
|
record Tag(String tagKey) implements HolderSet {
|
||||||
super(tagKey, null);
|
@Override
|
||||||
}
|
public boolean hasTagKey() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
HolderSetImpl(final int[] ids) {
|
@Override
|
||||||
super(null, ids);
|
public int[] ids() {
|
||||||
}
|
throw new IllegalArgumentException("This holder set has a tag key");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String tagKey() {
|
public boolean hasIds() {
|
||||||
return left();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTagKey() {
|
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||||
return isLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] ids() {
|
|
||||||
return right();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasIds() {
|
|
||||||
return isRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
|
||||||
if (hasTagKey()) {
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final int[] ids = ids();
|
record Ids(int[] ids) implements HolderSet {
|
||||||
final int[] mappedIds = new int[ids.length];
|
@Override
|
||||||
for (int i = 0; i < mappedIds.length; i++) {
|
public boolean hasTagKey() {
|
||||||
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String tagKey() {
|
||||||
|
throw new IllegalArgumentException("This holder set has direct ids");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasIds() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||||
|
final int[] mappedIds = new int[ids.length];
|
||||||
|
for (int i = 0; i < mappedIds.length; i++) {
|
||||||
|
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
|
||||||
|
}
|
||||||
|
return new Ids(mappedIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Ids{" +
|
||||||
|
"ids=" + Arrays.toString(ids) +
|
||||||
|
'}';
|
||||||
}
|
}
|
||||||
return new HolderSetImpl(mappedIds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPac
|
|||||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
|
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
|
||||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_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_20_5to1_21.packet.ClientboundPackets1_21;
|
||||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter.RecipeRewriter1_21_2;
|
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||||
|
|
||||||
@ -70,9 +70,11 @@ final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Clientbou
|
|||||||
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
|
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
|
||||||
registerExplosion1_21_2(ClientboundPackets1_21.EXPLODE); // Rewrites the included sound and particles
|
registerExplosion1_21_2(ClientboundPackets1_21.EXPLODE); // Rewrites the included sound and particles
|
||||||
|
|
||||||
new RecipeRewriter1_21_2<>(protocol).register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
|
final RecipeDisplayRewriter<ClientboundPacket1_21> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
|
||||||
|
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21.UPDATE_RECIPES);
|
||||||
|
//recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21.RECIPE_BOOK_ADD);
|
||||||
|
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21.PLACE_GHOST_RECIPE);
|
||||||
// OR do this if serialization of recipes changed and override the relevant method
|
// OR do this if serialization of recipes changed and override the relevant method
|
||||||
// Add new serializers to RecipeRewriter, or extend the last one for changes
|
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
|
||||||
// new RecipeRewriter1_21_2<ClientboundPacket1_21>(this) {}.register1_20_5(ClientboundPackets1_21.DECLARE_RECIPES);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
|||||||
});
|
});
|
||||||
|
|
||||||
protocol.registerClientbound(ClientboundPackets1_21.UPDATE_RECIPES, wrapper -> {
|
protocol.registerClientbound(ClientboundPackets1_21.UPDATE_RECIPES, wrapper -> {
|
||||||
final RecipeRewriter rewriter = new RecipeRewriter(protocol);
|
final RecipeRewriter1_21_2 rewriter = new RecipeRewriter1_21_2(protocol); // Holds state, create a new one for each packet
|
||||||
wrapper.cancel(); // TODO
|
wrapper.cancel(); // TODO
|
||||||
|
|
||||||
final int size = wrapper.passthrough(Types.VAR_INT);
|
final int size = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.v1_21to1_21_2.rewriter;
|
|
||||||
|
|
||||||
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
|
||||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
|
||||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
|
||||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
|
||||||
import com.viaversion.viaversion.api.type.Types;
|
|
||||||
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;
|
|
||||||
|
|
||||||
final class RecipeRewriter extends RecipeRewriter1_20_3<ClientboundPacket1_21> {
|
|
||||||
|
|
||||||
RecipeRewriter(final Protocol<ClientboundPacket1_21, ?, ?, ?> protocol) {
|
|
||||||
super(protocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleIngredient(final PacketWrapper wrapper) {
|
|
||||||
wrapper.write(Types.HOLDER_SET, ingredient(wrapper));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleCraftingShaped(final PacketWrapper wrapper) {
|
|
||||||
wrapper.passthrough(Types.STRING); // Group
|
|
||||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
|
||||||
final int width = wrapper.passthrough(Types.VAR_INT);
|
|
||||||
final int height = wrapper.passthrough(Types.VAR_INT);
|
|
||||||
final int ingredients = width * height;
|
|
||||||
|
|
||||||
wrapper.write(Types.VAR_INT, ingredients);
|
|
||||||
for (int i = 0; i < ingredients; i++) {
|
|
||||||
wrapper.write(Types.HOLDER_SET, ingredient(wrapper));
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
|
|
||||||
wrapper.passthrough(Types.BOOLEAN); // Show notification
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleCraftingShapeless(final PacketWrapper wrapper) {
|
|
||||||
wrapper.passthrough(Types.STRING); // Group
|
|
||||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
|
||||||
|
|
||||||
final int ingredients = wrapper.read(Types.VAR_INT);
|
|
||||||
final HolderSet[] ingredient = new HolderSet[ingredients];
|
|
||||||
for (int i = 0; i < ingredients; i++) {
|
|
||||||
ingredient[i] = ingredient(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType())));
|
|
||||||
|
|
||||||
// Also moved below here
|
|
||||||
wrapper.write(Types.VAR_INT, ingredients);
|
|
||||||
for (final HolderSet item : ingredient) {
|
|
||||||
wrapper.write(Types.HOLDER_SET, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private HolderSet ingredient(final PacketWrapper wrapper) {
|
|
||||||
final Item[] items = wrapper.read(itemArrayType());
|
|
||||||
final int[] ids = new int[items.length];
|
|
||||||
for (int i = 0; i < items.length; i++) {
|
|
||||||
final Item item = rewrite(wrapper.user(), items[i]);
|
|
||||||
ids[i] = item.identifier();
|
|
||||||
}
|
|
||||||
return HolderSet.of(ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleRecipeType(final PacketWrapper wrapper, final String type) {
|
|
||||||
if (type.equals("crafting_special_suspiciousstew") || type.equals("crafting_special_shulkerboxcoloring")) {
|
|
||||||
wrapper.read(Types.VAR_INT); // Crafting book category
|
|
||||||
} else {
|
|
||||||
super.handleRecipeType(wrapper, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,63 +17,161 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter;
|
package com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter;
|
||||||
|
|
||||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
import com.viaversion.viaversion.api.data.MappingData;
|
||||||
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
||||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
|
||||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
import com.viaversion.viaversion.api.type.Types;
|
import com.viaversion.viaversion.api.type.Types;
|
||||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
|
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 it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntCollection;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
// Dead as of 1.21.2, the server only sends simple recipe display data instead of full results
|
final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3<ClientboundPacket1_21> {
|
||||||
public class RecipeRewriter1_21_2<C extends ClientboundPacketType> extends RecipeRewriter1_20_3<C> {
|
|
||||||
|
|
||||||
public RecipeRewriter1_21_2(final Protocol<C, ?, ?, ?> protocol) {
|
private final List<ShapelessRecipe> shapelessRecipes = new ArrayList<>();
|
||||||
|
private final List<ShapedRecipe> shapedRecipes = new ArrayList<>();
|
||||||
|
private final List<SmithingRecipe> smithingRecipes = new ArrayList<>();
|
||||||
|
private final List<StoneCutterRecipe> stoneCutterRecipes = new ArrayList<>();
|
||||||
|
private final List<SimpleRecipe> simpleRecipes = new ArrayList<>();
|
||||||
|
private final Object2IntMap<String> recipeGroups = new Object2IntOpenHashMap<>();
|
||||||
|
// TODO
|
||||||
|
private final IntList smithingAddition = new IntArrayList();
|
||||||
|
private final IntList smithingTemplate = new IntArrayList();
|
||||||
|
private final IntList smithingBase = new IntArrayList();
|
||||||
|
private final IntList furnaceInput = new IntArrayList();
|
||||||
|
private final IntList smokerInput = new IntArrayList();
|
||||||
|
private final IntList blastFurnaceInput = new IntArrayList();
|
||||||
|
private final IntList campfireInput = new IntArrayList();
|
||||||
|
|
||||||
|
record SimpleRecipe(int category) {
|
||||||
|
}
|
||||||
|
|
||||||
|
record ShapelessRecipe(int group, int category, HolderSet[] ingredients, Item result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
record ShapedRecipe(int group, int category, int width, int height, HolderSet[] ingredients, Item result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
record StoneCutterRecipe(int group, HolderSet ingredient, Item result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
record SmithingRecipe(HolderSet ingredient, Item result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
RecipeRewriter1_21_2(final Protocol<ClientboundPacket1_21, ?, ?, ?> protocol) {
|
||||||
super(protocol);
|
super(protocol);
|
||||||
|
// TODO ?
|
||||||
|
recipeHandlers.put("smelting", wrapper -> handleSmelting(wrapper, furnaceInput));
|
||||||
|
recipeHandlers.put("blasting", wrapper -> handleSmelting(wrapper, blastFurnaceInput));
|
||||||
|
recipeHandlers.put("smoking", wrapper -> handleSmelting(wrapper, smokerInput));
|
||||||
|
recipeHandlers.put("campfire_cooking", wrapper -> handleSmelting(wrapper, campfireInput));
|
||||||
|
recipeGroups.defaultReturnValue(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HolderSet readIngredient(final PacketWrapper wrapper) {
|
||||||
|
// Ingredients are no longer full items, already store them as just holder sets
|
||||||
|
final Item[] items = wrapper.read(itemArrayType());
|
||||||
|
final int[] ids = new int[items.length];
|
||||||
|
final MappingData mappings = protocol.getMappingData();
|
||||||
|
for (int i = 0; i < items.length; i++) {
|
||||||
|
final Item item = items[i];
|
||||||
|
ids[i] = mappings.getNewItemId(item.identifier());
|
||||||
|
}
|
||||||
|
return HolderSet.of(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readIngredientToList(final PacketWrapper wrapper, final IntCollection list) {
|
||||||
|
final Item[] items = wrapper.read(itemArrayType());
|
||||||
|
final MappingData mappings = protocol.getMappingData();
|
||||||
|
for (final Item item : items) {
|
||||||
|
final int mappedId = mappings.getNewItemId(item.identifier());
|
||||||
|
list.add(mappedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSimpleRecipe(final PacketWrapper wrapper) {
|
||||||
|
final int category = wrapper.read(Types.VAR_INT);
|
||||||
|
simpleRecipes.add(new SimpleRecipe(category));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleStonecutting(final PacketWrapper wrapper) {
|
||||||
|
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||||
|
final HolderSet ingredient = readIngredient(wrapper);
|
||||||
|
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||||
|
stoneCutterRecipes.add(new StoneCutterRecipe(group, ingredient, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int recipeGroupId(final String recipeGroup) {
|
||||||
|
final int size = recipeGroups.size();
|
||||||
|
final int value = recipeGroups.putIfAbsent(recipeGroup, size);
|
||||||
|
return value != -1 ? value : size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSmithingTransform(final PacketWrapper wrapper) {
|
||||||
|
final IntList template = new IntArrayList();
|
||||||
|
readIngredientToList(wrapper, template);
|
||||||
|
smithingTemplate.addAll(template);
|
||||||
|
readIngredientToList(wrapper, smithingBase);
|
||||||
|
readIngredientToList(wrapper, smithingAddition);
|
||||||
|
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||||
|
smithingRecipes.add(new SmithingRecipe(HolderSet.of(template.toIntArray()), result)); // TODO ?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSmithingTrim(final PacketWrapper wrapper) {
|
||||||
|
readIngredientToList(wrapper, smithingTemplate);
|
||||||
|
readIngredientToList(wrapper, smithingBase);
|
||||||
|
readIngredientToList(wrapper, smithingAddition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleCraftingShaped(final PacketWrapper wrapper) {
|
public void handleCraftingShaped(final PacketWrapper wrapper) {
|
||||||
wrapper.passthrough(Types.STRING); // Group
|
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
final int category = wrapper.read(Types.VAR_INT);
|
||||||
wrapper.passthrough(Types.VAR_INT); // Width
|
final int width = wrapper.read(Types.VAR_INT);
|
||||||
wrapper.passthrough(Types.VAR_INT); // Height
|
final int height = wrapper.read(Types.VAR_INT);
|
||||||
|
final int ingredientsSize = width * height;
|
||||||
final int ingredients = wrapper.passthrough(Types.VAR_INT);
|
final HolderSet[] ingredients = new HolderSet[ingredientsSize];
|
||||||
for (int i = 0; i < ingredients; i++) {
|
for (int i = 0; i < ingredientsSize; i++) {
|
||||||
handleIngredient(wrapper);
|
ingredients[i] = readIngredient(wrapper);
|
||||||
}
|
}
|
||||||
|
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||||
|
shapedRecipes.add(new ShapedRecipe(group, category, width, height, ingredients, result));
|
||||||
|
|
||||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
|
wrapper.read(Types.BOOLEAN); // Show notification
|
||||||
wrapper.passthrough(Types.BOOLEAN); // Show notification
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleCraftingShapeless(final PacketWrapper wrapper) {
|
public void handleCraftingShapeless(final PacketWrapper wrapper) {
|
||||||
wrapper.passthrough(Types.STRING); // Group
|
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
final int category = wrapper.read(Types.VAR_INT);
|
||||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
|
final int ingredientsSize = wrapper.read(Types.VAR_INT);
|
||||||
handleIngredients(wrapper);
|
final HolderSet[] ingredients = new HolderSet[ingredientsSize];
|
||||||
|
for (int i = 0; i < ingredientsSize; i++) {
|
||||||
|
ingredients[i] = readIngredient(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||||
|
shapelessRecipes.add(new ShapelessRecipe(group, category, ingredients, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void handleSmelting(final PacketWrapper wrapper, final IntCollection list) {
|
||||||
protected void handleIngredient(final PacketWrapper wrapper) {
|
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||||
final HolderSet items = wrapper.passthrough(Types.HOLDER_SET);
|
final int category = wrapper.read(Types.VAR_INT);
|
||||||
if (items.hasTagKey()) {
|
readIngredientToList(wrapper, list);
|
||||||
return;
|
wrapper.read(itemType()); // Result
|
||||||
}
|
|
||||||
|
|
||||||
final int[] ids = items.ids();
|
wrapper.read(Types.FLOAT); // EXP
|
||||||
for (int i = 0; i < ids.length; i++) {
|
wrapper.read(Types.VAR_INT); // Cooking time
|
||||||
ids[i] = rewriteItemId(wrapper.user(), ids[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int rewriteItemId(final UserConnection connection, final int id) {
|
|
||||||
if (protocol.getMappingData() != null && protocol.getMappingData().getItemMappings() != null) {
|
|
||||||
return protocol.getMappingData().getItemMappings().getNewIdOrDefault(id, id);
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* 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.rewriter;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
||||||
|
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||||
|
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
|
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
|
||||||
|
import com.viaversion.viaversion.api.type.Types;
|
||||||
|
|
||||||
|
// Base for 1.21.2 and onwards
|
||||||
|
public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
|
||||||
|
protected final Protocol<C, ?, ?, ?> protocol;
|
||||||
|
|
||||||
|
public RecipeDisplayRewriter(final Protocol<C, ?, ?, ?> protocol) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerUpdateRecipes(final C packetType) {
|
||||||
|
protocol.registerClientbound(packetType, wrapper -> {
|
||||||
|
final int size = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
wrapper.passthrough(Types.STRING); // Recipe group
|
||||||
|
rewriteItemIds(wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
final int stonecutterRecipesSize = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
for (int i = 0; i < stonecutterRecipesSize; i++) {
|
||||||
|
handleIngredient(wrapper);
|
||||||
|
handleSlotDisplay(wrapper);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerRecipeBookAdd(final C packetType) {
|
||||||
|
protocol.registerClientbound(packetType, wrapper -> {
|
||||||
|
final int size = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
wrapper.passthrough(Types.VAR_INT); // Display ID
|
||||||
|
handleRecipeDisplay(wrapper);
|
||||||
|
wrapper.passthrough(Types.OPTIONAL_VAR_INT); // Group
|
||||||
|
wrapper.passthrough(Types.VAR_INT); // Category
|
||||||
|
if (wrapper.passthrough(Types.BOOLEAN)) {
|
||||||
|
final int ingredientsSize = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
for (int j = 0; j < ingredientsSize; j++) {
|
||||||
|
handleIngredient(wrapper); // Items
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper.passthrough(Types.BYTE); // Flags
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerPlaceGhostRecipe(final C packetType) {
|
||||||
|
protocol.registerClientbound(packetType, wrapper -> {
|
||||||
|
wrapper.passthrough(Types.VAR_INT); // Container ID
|
||||||
|
handleRecipeDisplay(wrapper);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleShapeless(final PacketWrapper wrapper) {
|
||||||
|
handleSlotDisplayList(wrapper); // Ingredients
|
||||||
|
handleSlotDisplay(wrapper); // Result
|
||||||
|
handleSlotDisplay(wrapper); // Crafting station
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleShaped(final PacketWrapper wrapper) {
|
||||||
|
wrapper.passthrough(Types.VAR_INT); // Width
|
||||||
|
wrapper.passthrough(Types.VAR_INT); // Height
|
||||||
|
handleSlotDisplayList(wrapper); // Ingredients
|
||||||
|
handleSlotDisplay(wrapper); // Result
|
||||||
|
handleSlotDisplay(wrapper); // Crafting station
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleFurnace(final PacketWrapper wrapper) {
|
||||||
|
handleSlotDisplay(wrapper); // Ingredient
|
||||||
|
handleSlotDisplay(wrapper); // Fuel
|
||||||
|
handleSlotDisplay(wrapper); // Result
|
||||||
|
handleSlotDisplay(wrapper); // Crafting station
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleStoneCutter(final PacketWrapper wrapper) {
|
||||||
|
handleSlotDisplay(wrapper); // Result
|
||||||
|
handleSlotDisplay(wrapper); // Crafting station
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleSmithing(final PacketWrapper wrapper) {
|
||||||
|
handleSlotDisplay(wrapper); // Result
|
||||||
|
handleSlotDisplay(wrapper); // Crafting station
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleSlotDisplayList(final PacketWrapper wrapper) {
|
||||||
|
final int size = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
handleSlotDisplay(wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleRecipeDisplay(final PacketWrapper wrapper) {
|
||||||
|
final int type = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
switch (type) {
|
||||||
|
case 0 -> handleShapeless(wrapper);
|
||||||
|
case 1 -> handleShaped(wrapper);
|
||||||
|
case 2 -> handleFurnace(wrapper);
|
||||||
|
case 3 -> handleStoneCutter(wrapper);
|
||||||
|
case 4 -> handleSmithing(wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleSlotDisplay(final PacketWrapper wrapper) {
|
||||||
|
// empty, any_fuel, smithing_trim are empty
|
||||||
|
final int type = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
switch (type) {
|
||||||
|
case 2 -> handleItemId(wrapper); // Item type
|
||||||
|
case 3 -> handleItem(wrapper); // Item
|
||||||
|
case 4 -> wrapper.passthrough(Types.STRING); // Tag key
|
||||||
|
case 6 -> handleSlotDisplayList(wrapper); // Composite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleIngredient(final PacketWrapper wrapper) {
|
||||||
|
final HolderSet items = wrapper.passthrough(Types.HOLDER_SET);
|
||||||
|
if (items.hasTagKey()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] ids = items.ids();
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
ids[i] = rewriteItemId(ids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleItemId(final PacketWrapper wrapper) {
|
||||||
|
final int id = wrapper.passthrough(Types.VAR_INT);
|
||||||
|
wrapper.write(Types.VAR_INT, rewriteItemId(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleItem(final PacketWrapper wrapper) {
|
||||||
|
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
|
||||||
|
final Item item = wrapper.read(itemRewriter.itemType());
|
||||||
|
itemRewriter.handleItemToClient(wrapper.user(), item);
|
||||||
|
wrapper.write(itemRewriter.mappedItemType(), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int rewriteItemId(final int id) {
|
||||||
|
if (protocol.getMappingData() != null && protocol.getMappingData().getItemMappings() != null) {
|
||||||
|
return protocol.getMappingData().getItemMappings().getNewIdOrDefault(id, id);
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void rewriteItemIds(final int[] ids) {
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
final int id = ids[i];
|
||||||
|
ids[i] = rewriteItemId(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
// Base up to and including 1.21.1
|
||||||
public class RecipeRewriter<C extends ClientboundPacketType> {
|
public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||||
|
|
||||||
protected final Protocol<C, ?, ?, ?> protocol;
|
protected final Protocol<C, ?, ?, ?> protocol;
|
||||||
@ -54,9 +55,6 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
|||||||
recipeHandlers.put("smithing_transform", this::handleSmithingTransform);
|
recipeHandlers.put("smithing_transform", this::handleSmithingTransform);
|
||||||
recipeHandlers.put("smithing_trim", this::handleSmithingTrim);
|
recipeHandlers.put("smithing_trim", this::handleSmithingTrim);
|
||||||
recipeHandlers.put("crafting_decorated_pot", this::handleSimpleRecipe);
|
recipeHandlers.put("crafting_decorated_pot", this::handleSimpleRecipe);
|
||||||
|
|
||||||
// Added in 1.21.2
|
|
||||||
recipeHandlers.put("crafting_transmute", this::handleTransmute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleRecipeType(PacketWrapper wrapper, String type) {
|
public void handleRecipeType(PacketWrapper wrapper, String type) {
|
||||||
@ -163,15 +161,6 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
|||||||
handleIngredient(wrapper); // Additions
|
handleIngredient(wrapper); // Additions
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTransmute(final PacketWrapper wrapper) {
|
|
||||||
wrapper.passthrough(Types.STRING); // Group
|
|
||||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
|
||||||
handleIngredient(wrapper); // Input
|
|
||||||
handleIngredient(wrapper); // Material
|
|
||||||
final int resultItemId = wrapper.read(Types.VAR_INT);
|
|
||||||
wrapper.write(Types.VAR_INT, rewrite(resultItemId));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int rewrite(final int itemId) {
|
protected int rewrite(final int itemId) {
|
||||||
if (protocol.getMappingData() != null && protocol.getItemRewriter() != null) {
|
if (protocol.getMappingData() != null && protocol.getItemRewriter() != null) {
|
||||||
return protocol.getMappingData().getNewItemId(itemId);
|
return protocol.getMappingData().getNewItemId(itemId);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren