Updated clientside crafting fix

This commit is contained in:
RaphiMC 2024-10-26 22:41:07 +02:00
parent 959cacdc6c
commit 983f550769
No known key found for this signature in database
GPG Key ID: 0F6BB0657A03AC94
7 changed files with 229 additions and 47 deletions

View File

@ -24,6 +24,7 @@ import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.event.PostGameLoadCallback;
import de.florianmichael.viafabricplus.fixes.data.EntityDimensionDiff;
import de.florianmichael.viafabricplus.fixes.data.ResourcePackHeaderDiff;
import de.florianmichael.viafabricplus.fixes.data.recipe.Recipes1_11_2;
import de.florianmichael.viafabricplus.fixes.versioned.EnchantmentAttributesEmulation1_20_6;
import de.florianmichael.viafabricplus.fixes.versioned.classic.CPEAdditions;
import de.florianmichael.viafabricplus.fixes.versioned.classic.GridItemSelectionScreen;
@ -123,6 +124,11 @@ public class ClientsideFixes {
GridItemSelectionScreen.INSTANCE.itemGrid = null;
}
// Reloads the clientside recipes
if (newVersion.olderThanOrEqualTo(ProtocolVersion.v1_11_1)) {
Recipes1_11_2.reset();
}
// Reload sound system when switching between 3D Shareware and normal versions
if (oldVersion.equals(AprilFoolsProtocolVersion.s3d_shareware) || newVersion.equals(AprilFoolsProtocolVersion.s3d_shareware)) {
MinecraftClient.getInstance().getSoundManager().reloadSounds();

View File

@ -45,10 +45,10 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
}
@Override
public boolean matches(CraftingRecipeInput inv, World world) {
public boolean matches(CraftingRecipeInput input, World world) {
boolean foundBanner = false;
for (int i = 0; i < inv.size(); i++) {
ItemStack stack = inv.getStackInSlot(i);
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
if (stack.getItem() instanceof BannerItem) {
if (foundBanner)
return false;
@ -57,15 +57,15 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
foundBanner = true;
}
}
return foundBanner && getBannerPattern(inv) != null;
return foundBanner && getBannerPattern(input) != null;
}
@Override
public ItemStack craft(CraftingRecipeInput inv, RegistryWrapper.WrapperLookup lookup) {
public ItemStack craft(CraftingRecipeInput input, RegistryWrapper.WrapperLookup lookup) {
ItemStack result = ItemStack.EMPTY;
for (int i = 0; i < inv.size(); i++) {
ItemStack stack = inv.getStackInSlot(i);
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() instanceof BannerItem) {
result = stack.copy();
result.setCount(1);
@ -73,12 +73,12 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
}
}
final BannerPattern_1_13_2 pattern = getBannerPattern(inv);
final BannerPattern_1_13_2 pattern = getBannerPattern(input);
if (pattern != null) {
final var patternKey = lookup.getOrThrow(RegistryKeys.BANNER_PATTERN).getOrThrow(pattern.getKey());
DyeColor color = ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) ? DyeColor.BLACK : DyeColor.WHITE;
for (int i = 0; i < inv.size(); i++) {
Item item = inv.getStackInSlot(i).getItem();
for (int i = 0; i < input.size(); i++) {
Item item = input.getStackInSlot(i).getItem();
if (item instanceof DyeItem dyeItem) {
color = dyeItem.getColor();
}
@ -100,7 +100,7 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
return SERIALIZER;
}
private static BannerPattern_1_13_2 getBannerPattern(CraftingRecipeInput inv) {
private static BannerPattern_1_13_2 getBannerPattern(CraftingRecipeInput input) {
for (BannerPattern_1_13_2 pattern : BannerPattern_1_13_2.values()) {
if (!pattern.isCraftable())
continue;
@ -109,8 +109,8 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
if (pattern.hasBaseStack()) {
boolean foundBaseItem = false;
boolean foundDye = false;
for (int i = 0; i < inv.size(); i++) {
ItemStack stack = inv.getStackInSlot(i);
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
if (!stack.isEmpty() && !(stack.getItem() instanceof BannerItem)) {
if (stack.getItem() instanceof DyeItem) {
if (foundDye) {
@ -128,12 +128,12 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
}
}
if (!foundBaseItem || (!foundDye && ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_10))) matches = false;
} else if (inv.size() == pattern.getRecipePattern().length * pattern.getRecipePattern()[0].length()) {
} else if (input.size() == pattern.getRecipePattern().length * pattern.getRecipePattern()[0].length()) {
DyeColor patternColor = null;
for (int i = 0; i < inv.size(); i++) {
for (int i = 0; i < input.size(); i++) {
int row = i / 3;
int col = i % 3;
ItemStack stack = inv.getStackInSlot(i);
ItemStack stack = input.getStackInSlot(i);
Item item = stack.getItem();
if (!stack.isEmpty() && !(item instanceof BannerItem)) {
if (!(item instanceof DyeItem)) {

View File

@ -24,7 +24,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.recipe.*;
import net.minecraft.recipe.book.CookingRecipeCategory;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.util.Identifier;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.collection.DefaultedList;
import java.util.*;
@ -316,9 +316,8 @@ public final class RecipeInfo {
* @param id The id
* @return The recipe info
*/
public RecipeEntry<?> create(Identifier id) {
// return new RecipeEntry<Recipe<?>>(id, this.creator.get()); TODO UPDATE-1.21.3
return null;
public RecipeEntry<?> create(RegistryKey<Recipe<?>> id) {
return new RecipeEntry<>(id, this.creator.get());
}
}

View File

@ -0,0 +1,76 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 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 de.florianmichael.viafabricplus.fixes.data.recipe;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeType;
import net.minecraft.recipe.input.RecipeInput;
import net.minecraft.registry.RegistryKey;
import net.minecraft.world.World;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
public class RecipeManager1_11_2 {
private final Multimap<RecipeType<?>, RecipeEntry<?>> recipesByType;
private final Map<RegistryKey<Recipe<?>>, RecipeEntry<?>> recipesById;
public RecipeManager1_11_2(final Iterable<RecipeEntry<?>> recipes) {
final ImmutableMultimap.Builder<RecipeType<?>, RecipeEntry<?>> recipesByTypeBuilder = ImmutableMultimap.builder();
final ImmutableMap.Builder<RegistryKey<Recipe<?>>, RecipeEntry<?>> recipesByIdBuilder = ImmutableMap.builder();
for (RecipeEntry<?> recipeEntry : recipes) {
final RecipeType<?> recipeType = recipeEntry.value().getType();
recipesByTypeBuilder.put(recipeType, recipeEntry);
recipesByIdBuilder.put(recipeEntry.id(), recipeEntry);
}
this.recipesByType = recipesByTypeBuilder.build();
this.recipesById = recipesByIdBuilder.build();
}
public <I extends RecipeInput, T extends Recipe<I>> Optional<RecipeEntry<T>> getFirstMatch(final RecipeType<T> type, final I input, final World world) {
if (input.isEmpty()) {
return Optional.empty();
} else {
return this.recipesByType.get(type).stream().map(e -> (RecipeEntry<T>) e).filter(recipe -> recipe.value().matches(input, world)).findFirst();
}
}
public Optional<RecipeEntry<?>> get(final RegistryKey<Recipe<?>> id) {
return Optional.ofNullable(this.recipesById.get(id));
}
public Collection<RecipeEntry<?>> values() {
return this.recipesById.values();
}
public Stream<RegistryKey<Recipe<?>>> keys() {
return this.recipesById.keySet().stream();
}
}

View File

@ -20,6 +20,7 @@
package de.florianmichael.viafabricplus.fixes.data.recipe;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.inventory.RecipeInputInventory;
@ -29,8 +30,10 @@ import net.minecraft.item.Items;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
import net.minecraft.recipe.*;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.Identifier;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import org.jetbrains.annotations.ApiStatus;
@ -42,6 +45,26 @@ import java.util.List;
*/
public class Recipes1_11_2 {
private static RecipeManager1_11_2 RECIPE_MANAGER;
public static RecipeManager1_11_2 getRecipeManager() {
if (RECIPE_MANAGER == null) {
final List<RecipeInfo> recipeInfos = Recipes1_11_2.getRecipes(ProtocolTranslator.getTargetVersion());
final List<RecipeEntry<?>> recipes = new ArrayList<>(recipeInfos.size());
for (int i = 0; i < recipeInfos.size(); i++) {
final RegistryKey<Recipe<?>> key = RegistryKey.of(RegistryKeys.RECIPE, Identifier.of("viafabricplus", "recipe/" + i));
recipes.add(recipeInfos.get(i).create(key));
}
RECIPE_MANAGER = new RecipeManager1_11_2(recipes);
}
return RECIPE_MANAGER;
}
public static void reset() {
RECIPE_MANAGER = null;
}
/**
* @return A list of all recipes for the given version.
*/
@ -57,7 +80,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.of(() -> new FireworkRocketRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_11)) {
// recipes.add(RecipeInfo.of(() -> new ShulkerBoxColoringRecipe(CraftingRecipeCategory.MISC))); TODO UPDATE-1.21.3
recipes.add(RecipeInfo.of(() -> new ShulkerBoxColoringRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_9)) {
recipes.add(RecipeInfo.of(() -> new TippedArrowRecipe(CraftingRecipeCategory.MISC)));
@ -625,7 +648,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.smelting(Items.IRON_INGOT, Items.IRON_ORE, 0.7F));
recipes.add(RecipeInfo.smelting(Items.GOLD_INGOT, Items.GOLD_ORE, 1.0F));
recipes.add(RecipeInfo.smelting(Items.DIAMOND, Items.DIAMOND_ORE, 1.0F));
// recipes.add(RecipeInfo.smelting(Items.GLASS, Ingredient.fromTag(ItemTags.SAND), 0.1F)); TODO UPDATE-1.21.3
recipes.add(RecipeInfo.smelting(Items.GLASS, Ingredient.ofItems(Items.SAND, Items.RED_SAND), 0.1F));
recipes.add(RecipeInfo.smelting(Items.COOKED_PORKCHOP, Items.PORKCHOP, 0.35F));
recipes.add(RecipeInfo.smelting(Items.STONE, Items.COBBLESTONE, 0.1F));
recipes.add(RecipeInfo.smelting(Items.BRICK, Items.CLAY_BALL, 0.3F));
@ -685,7 +708,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.smelting(Items.COOKED_BEEF, Items.BEEF, 0.35F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_2_0tob1_2_2)) {
// recipes.add(RecipeInfo.smelting(Items.CHARCOAL, Ingredient.fromTag(ItemTags.LOGS), 0.15F)); TODO UPDATE-1.21.3
recipes.add(RecipeInfo.smelting(Items.CHARCOAL, Ingredient.ofItems(Items.OAK_LOG, Items.SPRUCE_LOG, Items.BIRCH_LOG, Items.JUNGLE_LOG, Items.ACACIA_LOG, Items.DARK_OAK_LOG), 0.15F));
recipes.add(RecipeInfo.smelting(Items.GREEN_DYE, Items.CACTUS, 0.2F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.a1_2_0toa1_2_1_1)) {
@ -710,13 +733,13 @@ public class Recipes1_11_2 {
final var world = MinecraftClient.getInstance().world;
final var craftingRecipeInput = inventory.createRecipeInput();
// final var result = network.getRecipeManager() TODO UPDATE-1.21.3
// .getFirstMatch(RecipeType.CRAFTING, craftingRecipeInput, world) // Get the first matching recipe
// .map(recipe -> recipe.value().craft(craftingRecipeInput, network.getRegistryManager())) // Craft the recipe to get the result
// .orElse(ItemStack.EMPTY); // If there is no recipe, set the result to air
final var result = getRecipeManager()
.getFirstMatch(RecipeType.CRAFTING, craftingRecipeInput, world) // Get the first matching recipe
.map(recipe -> recipe.value().craft(craftingRecipeInput, network.getRegistryManager())) // Craft the recipe to get the result
.orElse(ItemStack.EMPTY); // If there is no recipe, set the result to air
// Update the result slot
//network.onScreenHandlerSlotUpdate(new ScreenHandlerSlotUpdateS2CPacket(syncId, screenHandler.getRevision(), 0, result));
network.onScreenHandlerSlotUpdate(new ScreenHandlerSlotUpdateS2CPacket(syncId, screenHandler.getRevision(), 0, result));
}
}

View File

@ -0,0 +1,93 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 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 de.florianmichael.viafabricplus.fixes.data.recipe;
import net.minecraft.block.Block;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.item.DyeItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.recipe.input.CraftingRecipeInput;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.world.World;
public class ShulkerBoxColoringRecipe extends SpecialCraftingRecipe {
public static final RecipeSerializer<ShulkerBoxColoringRecipe> SERIALIZER = new SpecialRecipeSerializer<>(ShulkerBoxColoringRecipe::new);
public ShulkerBoxColoringRecipe(CraftingRecipeCategory craftingRecipeCategory) {
super(craftingRecipeCategory);
}
public boolean matches(CraftingRecipeInput input, World world) {
int i = 0;
int j = 0;
for (int k = 0; k < input.size(); k++) {
ItemStack stack = input.getStackInSlot(k);
if (!stack.isEmpty()) {
if (Block.getBlockFromItem(stack.getItem()) instanceof ShulkerBoxBlock) {
i++;
} else {
if (!(stack.getItem() instanceof DyeItem)) {
return false;
}
j++;
}
if (j > 1 || i > 1) {
return false;
}
}
}
return i == 1 && j == 1;
}
public ItemStack craft(CraftingRecipeInput input, RegistryWrapper.WrapperLookup wrapperLookup) {
ItemStack result = ItemStack.EMPTY;
DyeItem dyeItem = (DyeItem) Items.WHITE_DYE;
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
if (!stack.isEmpty()) {
Item item = stack.getItem();
if (Block.getBlockFromItem(item) instanceof ShulkerBoxBlock) {
result = stack;
} else if (item instanceof DyeItem) {
dyeItem = (DyeItem) item;
}
}
}
return result.copyComponentsToNewStack(ShulkerBoxBlock.get(dyeItem.getColor()), 1);
}
@Override
public RecipeSerializer<ShulkerBoxColoringRecipe> getSerializer() {
return SERIALIZER;
}
}

View File

@ -23,8 +23,6 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.fixes.ClientsideFixes;
import de.florianmichael.viafabricplus.fixes.data.recipe.RecipeInfo;
import de.florianmichael.viafabricplus.fixes.data.recipe.Recipes1_11_2;
import de.florianmichael.viafabricplus.injection.access.IDownloadingTerrainScreen;
import de.florianmichael.viafabricplus.injection.access.IPlayerListHud;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
@ -48,9 +46,7 @@ import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.ChatCommandSignedC2SPacket;
import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket;
import net.minecraft.network.packet.s2c.play.*;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.Identifier;
import net.minecraft.world.GameMode;
import net.minecraft.world.World;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
@ -63,7 +59,6 @@ import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@ -82,13 +77,11 @@ public abstract class MixinClientPlayNetworkHandler extends ClientCommonNetworkH
@Shadow
public abstract ClientConnection getConnection();
@Shadow
public abstract void onSynchronizeRecipes(SynchronizeRecipesS2CPacket packet);
@Shadow
protected abstract boolean isSecureChatEnforced();
@Shadow private LastSeenMessagesCollector lastSeenMessagesCollector;
@Shadow
private LastSeenMessagesCollector lastSeenMessagesCollector;
protected MixinClientPlayNetworkHandler(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) {
super(client, connection, connectionState);
@ -249,15 +242,7 @@ public abstract class MixinClientPlayNetworkHandler extends ClientCommonNetworkH
// }
@Inject(method = "onGameJoin", at = @At("RETURN"))
private void sendRecipes(GameJoinS2CPacket packet, CallbackInfo ci) {
// if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_11_1)) { TODO UPDATE-1.21.3
// final List<RecipeEntry<?>> recipes = new ArrayList<>();
// final List<RecipeInfo> recipeInfos = Recipes1_11_2.getRecipes(ProtocolTranslator.getTargetVersion());
// for (int i = 0; i < recipeInfos.size(); i++) {
// recipes.add(recipeInfos.get(i).create(Identifier.of("viafabricplus", "recipe/" + i)));
// }
// this.onSynchronizeRecipes(new SynchronizeRecipesS2CPacket(recipes));
// }
private void initPlayerListFix(GameJoinS2CPacket packet, CallbackInfo ci) {
ClientsideFixes.globalTablistIndex = 0;
((IPlayerListHud) MinecraftClient.getInstance().inGameHud.getPlayerListHud()).viaFabricPlus$setMaxPlayers(packet.maxPlayers());
}