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.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 ServerPlaceRecipe.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( ServerPlaceRecipe.CraftingMenuAccess p_361168_, int p_364309_, int p_363223_, List p_362609_, List p_366501_, Inventory p_367037_, RecipeHolder p_365886_, boolean p_366586_, boolean p_362700_ ) { ServerPlaceRecipe serverplacerecipe = new ServerPlaceRecipe<>(p_361168_, p_367037_, p_366586_, p_364309_, p_363223_, p_362609_, p_366501_); if (!p_362700_ && !serverplacerecipe.testClearGrid()) { return RecipeBookMenu.PostPlaceAction.NOTHING; } else { StackedItemContents stackeditemcontents = new StackedItemContents(); p_367037_.fillStackedContents(stackeditemcontents); p_361168_.fillCraftSlotsStackedContents(stackeditemcontents); return serverplacerecipe.tryPlaceRecipe(p_365886_, stackeditemcontents); } } private ServerPlaceRecipe( ServerPlaceRecipe.CraftingMenuAccess p_364245_, Inventory p_366205_, boolean p_362556_, int p_368821_, int p_369958_, List p_364688_, List p_367687_ ) { this.menu = p_364245_; this.inventory = p_366205_; this.useMaxItems = p_362556_; this.gridWidth = p_368821_; this.gridHeight = p_369958_; this.inputGridSlots = p_364688_; this.slotsToClear = p_367687_; } private RecipeBookMenu.PostPlaceAction tryPlaceRecipe(RecipeHolder p_365851_, StackedItemContents p_368441_) { if (p_368441_.canCraft(p_365851_.value(), null)) { this.placeRecipe(p_365851_, p_368441_); this.inventory.setChanged(); return RecipeBookMenu.PostPlaceAction.NOTHING; } else { this.clearGrid(); this.inventory.setChanged(); return RecipeBookMenu.PostPlaceAction.PLACE_GHOST_RECIPE; } } private void clearGrid() { for (Slot slot : this.slotsToClear) { ItemStack itemstack = slot.getItem().copy(); this.inventory.placeItemBackInInventory(itemstack, false); slot.set(itemstack); } this.menu.clearCraftingContent(); } private void placeRecipe(RecipeHolder p_369245_, StackedItemContents p_365814_) { boolean flag = this.menu.recipeMatches(p_369245_); int i = p_365814_.getBiggestCraftableStack(p_369245_.value(), null); if (flag) { for (Slot slot : this.inputGridSlots) { ItemStack itemstack = slot.getItem(); if (!itemstack.isEmpty() && Math.min(i, itemstack.getMaxStackSize()) < itemstack.getCount() + 1) { return; } } } int j = this.calculateAmountToCraft(i, flag); List> list = new ArrayList<>(); if (p_365814_.canCraft(p_369245_.value(), j, list::add)) { int k = clampToMaxStackSize(j, list); if (k != j) { list.clear(); if (!p_365814_.canCraft(p_369245_.value(), k, list::add)) { return; } } this.clearGrid(); PlaceRecipeHelper.placeRecipe( this.gridWidth, this.gridHeight, p_369245_.value(), p_369245_.value().placementInfo().slotsToIngredientIndex(), (p_374854_, p_374855_, p_374856_, p_374857_) -> { if (p_374854_ != -1) { Slot slot1 = this.inputGridSlots.get(p_374855_); Holder holder = list.get(p_374854_); int l = k; while (l > 0) { l = this.moveItemToGrid(slot1, holder, l); if (l == -1) { return; } } } } ); } } private static int clampToMaxStackSize(int p_376825_, List> p_377337_) { for (Holder holder : p_377337_) { p_376825_ = Math.min(p_376825_, holder.value().getDefaultMaxStackSize()); } return p_376825_; } private int calculateAmountToCraft(int p_362229_, boolean p_364254_) { if (this.useMaxItems) { return p_362229_; } else if (p_364254_) { int i = Integer.MAX_VALUE; for (Slot slot : this.inputGridSlots) { ItemStack itemstack = slot.getItem(); if (!itemstack.isEmpty() && i > itemstack.getCount()) { i = itemstack.getCount(); } } if (i != Integer.MAX_VALUE) { i++; } return i; } else { return 1; } } private int moveItemToGrid(Slot p_135439_, Holder p_363932_, int p_342870_) { ItemStack itemstack = p_135439_.getItem(); int i = this.inventory.findSlotMatchingCraftingIngredient(p_363932_, itemstack); if (i == -1) { return -1; } else { ItemStack itemstack1 = this.inventory.getItem(i); ItemStack itemstack2; if (p_342870_ < itemstack1.getCount()) { itemstack2 = this.inventory.removeItem(i, p_342870_); } else { itemstack2 = this.inventory.removeItemNoUpdate(i); } int j = itemstack2.getCount(); if (itemstack.isEmpty()) { p_135439_.set(itemstack2); } else { itemstack.grow(j); } return p_342870_ - j; } } private boolean testClearGrid() { List list = Lists.newArrayList(); int i = this.getAmountOfFreeSlotsInInventory(); for (Slot slot : this.inputGridSlots) { ItemStack itemstack = slot.getItem().copy(); if (!itemstack.isEmpty()) { int j = this.inventory.getSlotWithRemainingSpace(itemstack); if (j == -1 && list.size() <= i) { for (ItemStack itemstack1 : list) { if (ItemStack.isSameItem(itemstack1, itemstack) && itemstack1.getCount() != itemstack1.getMaxStackSize() && itemstack1.getCount() + itemstack.getCount() <= itemstack1.getMaxStackSize()) { itemstack1.grow(itemstack.getCount()); itemstack.setCount(0); break; } } if (!itemstack.isEmpty()) { if (list.size() >= i) { return false; } list.add(itemstack); } } else if (j == -1) { return false; } } } return true; } private int getAmountOfFreeSlotsInInventory() { int i = 0; for (ItemStack itemstack : this.inventory.items) { if (itemstack.isEmpty()) { i++; } } return i; } public interface CraftingMenuAccess> { void fillCraftSlotsStackedContents(StackedItemContents p_362886_); void clearCraftingContent(); boolean recipeMatches(RecipeHolder p_361326_); } }