Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-26 00:00:28 +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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
import com.viaversion.viaversion.util.EitherImpl;
|
||||
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) {
|
||||
super(tagKey, null);
|
||||
}
|
||||
record Tag(String tagKey) implements HolderSet {
|
||||
@Override
|
||||
public boolean hasTagKey() {
|
||||
return true;
|
||||
}
|
||||
|
||||
HolderSetImpl(final int[] ids) {
|
||||
super(null, ids);
|
||||
}
|
||||
@Override
|
||||
public int[] ids() {
|
||||
throw new IllegalArgumentException("This holder set has a tag key");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tagKey() {
|
||||
return left();
|
||||
}
|
||||
@Override
|
||||
public boolean hasIds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTagKey() {
|
||||
return isLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] ids() {
|
||||
return right();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIds() {
|
||||
return isRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||
if (hasTagKey()) {
|
||||
@Override
|
||||
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
final int[] ids = ids();
|
||||
final int[] mappedIds = new int[ids.length];
|
||||
for (int i = 0; i < mappedIds.length; i++) {
|
||||
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
|
||||
record Ids(int[] ids) implements HolderSet {
|
||||
@Override
|
||||
public boolean hasTagKey() {
|
||||
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_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.rewriter.RecipeRewriter1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
|
||||
@ -70,9 +70,11 @@ final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Clientbou
|
||||
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_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
|
||||
// Add new serializers to RecipeRewriter, or extend the last one for changes
|
||||
// new RecipeRewriter1_21_2<ClientboundPacket1_21>(this) {}.register1_20_5(ClientboundPackets1_21.DECLARE_RECIPES);
|
||||
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
});
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
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.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.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;
|
||||
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
|
||||
public class RecipeRewriter1_21_2<C extends ClientboundPacketType> extends RecipeRewriter1_20_3<C> {
|
||||
final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3<ClientboundPacket1_21> {
|
||||
|
||||
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);
|
||||
// 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
|
||||
public void handleCraftingShaped(final PacketWrapper wrapper) {
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
||||
wrapper.passthrough(Types.VAR_INT); // Width
|
||||
wrapper.passthrough(Types.VAR_INT); // Height
|
||||
|
||||
final int ingredients = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int i = 0; i < ingredients; i++) {
|
||||
handleIngredient(wrapper);
|
||||
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||
final int category = wrapper.read(Types.VAR_INT);
|
||||
final int width = wrapper.read(Types.VAR_INT);
|
||||
final int height = wrapper.read(Types.VAR_INT);
|
||||
final int ingredientsSize = width * height;
|
||||
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()));
|
||||
shapedRecipes.add(new ShapedRecipe(group, category, width, height, ingredients, result));
|
||||
|
||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show notification
|
||||
wrapper.read(Types.BOOLEAN); // Show notification
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCraftingShapeless(final PacketWrapper wrapper) {
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
|
||||
handleIngredients(wrapper);
|
||||
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||
final int category = wrapper.read(Types.VAR_INT);
|
||||
final int ingredientsSize = wrapper.read(Types.VAR_INT);
|
||||
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
|
||||
protected void handleIngredient(final PacketWrapper wrapper) {
|
||||
final HolderSet items = wrapper.passthrough(Types.HOLDER_SET);
|
||||
if (items.hasTagKey()) {
|
||||
return;
|
||||
}
|
||||
private void handleSmelting(final PacketWrapper wrapper, final IntCollection list) {
|
||||
final int group = recipeGroupId(wrapper.read(Types.STRING));
|
||||
final int category = wrapper.read(Types.VAR_INT);
|
||||
readIngredientToList(wrapper, list);
|
||||
wrapper.read(itemType()); // Result
|
||||
|
||||
final int[] ids = items.ids();
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
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;
|
||||
wrapper.read(Types.FLOAT); // EXP
|
||||
wrapper.read(Types.VAR_INT); // Cooking time
|
||||
}
|
||||
}
|
||||
|
@ -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 org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
// Base up to and including 1.21.1
|
||||
public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
|
||||
protected final Protocol<C, ?, ?, ?> protocol;
|
||||
@ -54,9 +55,6 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
recipeHandlers.put("smithing_transform", this::handleSmithingTransform);
|
||||
recipeHandlers.put("smithing_trim", this::handleSmithingTrim);
|
||||
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) {
|
||||
@ -163,15 +161,6 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
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) {
|
||||
if (protocol.getMappingData() != null && protocol.getItemRewriter() != null) {
|
||||
return protocol.getMappingData().getNewItemId(itemId);
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren