/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Lists */ package net.minecraft.recipebook; import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; import net.minecraft.core.Holder; import net.minecraft.recipebook.PlaceRecipeHelper; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.StackedItemContents; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeInput; public class ServerPlaceRecipe> { private static final int ITEM_NOT_FOUND = -1; private final Inventory inventory; private final CraftingMenuAccess menu; private final boolean useMaxItems; private final int gridWidth; private final int gridHeight; private final List inputGridSlots; private final List slotsToClear; public static > RecipeBookMenu.PostPlaceAction placeRecipe(CraftingMenuAccess menu, int gridWidth, int gridHeight, List inputGridSlots, List slotsToClear, Inventory inventory, RecipeHolder recipe, boolean useMaxItems, boolean allowDroppingItemsToClear) { ServerPlaceRecipe placer = new ServerPlaceRecipe(menu, inventory, useMaxItems, gridWidth, gridHeight, inputGridSlots, slotsToClear); if (!allowDroppingItemsToClear && !placer.testClearGrid()) { return RecipeBookMenu.PostPlaceAction.NOTHING; } StackedItemContents availableItems = new StackedItemContents(); inventory.fillStackedContents(availableItems); menu.fillCraftSlotsStackedContents(availableItems); return placer.tryPlaceRecipe(recipe, availableItems); } private ServerPlaceRecipe(CraftingMenuAccess menu, Inventory inventory, boolean useMaxItems, int gridWidth, int gridHeight, List inputGridSlots, List slotsToClear) { this.menu = menu; this.inventory = inventory; this.useMaxItems = useMaxItems; this.gridWidth = gridWidth; this.gridHeight = gridHeight; this.inputGridSlots = inputGridSlots; this.slotsToClear = slotsToClear; } private RecipeBookMenu.PostPlaceAction tryPlaceRecipe(RecipeHolder recipe, StackedItemContents availableItems) { if (availableItems.canCraft((Recipe)recipe.value(), null)) { this.placeRecipe(recipe, availableItems); this.inventory.setChanged(); return RecipeBookMenu.PostPlaceAction.NOTHING; } this.clearGrid(); this.inventory.setChanged(); return RecipeBookMenu.PostPlaceAction.PLACE_GHOST_RECIPE; } private void clearGrid() { for (Slot slot : this.slotsToClear) { ItemStack itemStackCopy = slot.getItem().copy(); this.inventory.placeItemBackInInventory(itemStackCopy, false); slot.set(itemStackCopy); } this.menu.clearCraftingContent(); } private void placeRecipe(RecipeHolder recipe, StackedItemContents availableItems) { boolean recipeMatchesPlaced = this.menu.recipeMatches(recipe); int biggestCraftableStack = availableItems.getBiggestCraftableStack((Recipe)recipe.value(), null); if (recipeMatchesPlaced) { for (Slot inputSlot : this.inputGridSlots) { ItemStack itemStack = inputSlot.getItem(); if (itemStack.isEmpty() || Math.min(biggestCraftableStack, itemStack.getMaxStackSize()) >= itemStack.getCount() + 1) continue; return; } } int amountToCraft = this.calculateAmountToCraft(biggestCraftableStack, recipeMatchesPlaced); ArrayList> itemsUsedPerIngredient = new ArrayList>(); if (!availableItems.canCraft((Recipe)recipe.value(), amountToCraft, itemsUsedPerIngredient::add)) { return; } int adjustedAmountToCraft = ServerPlaceRecipe.clampToMaxStackSize(amountToCraft, itemsUsedPerIngredient); if (adjustedAmountToCraft != amountToCraft) { itemsUsedPerIngredient.clear(); if (!availableItems.canCraft((Recipe)recipe.value(), adjustedAmountToCraft, itemsUsedPerIngredient::add)) { return; } } this.clearGrid(); PlaceRecipeHelper.placeRecipe(this.gridWidth, this.gridHeight, recipe.value(), recipe.value().placementInfo().slotsToIngredientIndex(), (ingredientIndex, gridIndex, gridXPos, gridYPos) -> { if (ingredientIndex == -1) { return; } Slot targetGridSlot = this.inputGridSlots.get(gridIndex); Holder itemUsed = (Holder)itemsUsedPerIngredient.get((int)ingredientIndex); int remainingCount = adjustedAmountToCraft; while (remainingCount > 0) { if ((remainingCount = this.moveItemToGrid(targetGridSlot, itemUsed, remainingCount)) != -1) continue; return; } }); } private static int clampToMaxStackSize(int value, List> items) { for (Holder item : items) { value = Math.min(value, item.value().getDefaultMaxStackSize()); } return value; } private int calculateAmountToCraft(int biggestCraftableStack, boolean recipeMatchesPlaced) { if (this.useMaxItems) { return biggestCraftableStack; } if (recipeMatchesPlaced) { int smallestStackSize = Integer.MAX_VALUE; for (Slot inputSlot : this.inputGridSlots) { ItemStack itemStack = inputSlot.getItem(); if (itemStack.isEmpty() || smallestStackSize <= itemStack.getCount()) continue; smallestStackSize = itemStack.getCount(); } if (smallestStackSize != Integer.MAX_VALUE) { ++smallestStackSize; } return smallestStackSize; } return 1; } private int moveItemToGrid(Slot targetSlot, Holder itemInInventory, int count) { ItemStack itemInTargetSlot = targetSlot.getItem(); int inventorySlotId = this.inventory.findSlotMatchingCraftingIngredient(itemInInventory, itemInTargetSlot); if (inventorySlotId == -1) { return -1; } ItemStack inventoryItem = this.inventory.getItem(inventorySlotId); ItemStack takenStack = count < inventoryItem.getCount() ? this.inventory.removeItem(inventorySlotId, count) : this.inventory.removeItemNoUpdate(inventorySlotId); int takenCount = takenStack.getCount(); if (itemInTargetSlot.isEmpty()) { targetSlot.set(takenStack); } else { itemInTargetSlot.grow(takenCount); } return count - takenCount; } private boolean testClearGrid() { ArrayList freeSlots = Lists.newArrayList(); int freeSlotsInInventory = this.getAmountOfFreeSlotsInInventory(); for (Slot inputSlot : this.inputGridSlots) { ItemStack itemStack = inputSlot.getItem().copy(); if (itemStack.isEmpty()) continue; int slotId = this.inventory.getSlotWithRemainingSpace(itemStack); if (slotId == -1 && freeSlots.size() <= freeSlotsInInventory) { for (ItemStack itemStackInList : freeSlots) { if (!ItemStack.isSameItem(itemStackInList, itemStack) || itemStackInList.getCount() == itemStackInList.getMaxStackSize() || itemStackInList.getCount() + itemStack.getCount() > itemStackInList.getMaxStackSize()) continue; itemStackInList.grow(itemStack.getCount()); itemStack.setCount(0); break; } if (itemStack.isEmpty()) continue; if (freeSlots.size() < freeSlotsInInventory) { freeSlots.add(itemStack); continue; } return false; } if (slotId != -1) continue; return false; } return true; } private int getAmountOfFreeSlotsInInventory() { int freeSlots = 0; for (ItemStack item : this.inventory.getNonEquipmentItems()) { if (!item.isEmpty()) continue; ++freeSlots; } return freeSlots; } public static interface CraftingMenuAccess> { public void fillCraftSlotsStackedContents(StackedItemContents var1); public void clearCraftingContent(); public boolean recipeMatches(RecipeHolder var1); } }