211 lines
6.1 KiB
Java
211 lines
6.1 KiB
Java
package net.minecraft.recipebook;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
|
import it.unimi.dsi.fastutil.ints.IntList;
|
|
import java.util.List;
|
|
import net.minecraft.network.protocol.game.ClientboundPlaceGhostRecipePacket;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.entity.player.Inventory;
|
|
import net.minecraft.world.entity.player.StackedContents;
|
|
import net.minecraft.world.inventory.RecipeBookMenu;
|
|
import net.minecraft.world.inventory.Slot;
|
|
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;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class ServerPlaceRecipe<I extends RecipeInput, R extends Recipe<I>> implements PlaceRecipe<Integer> {
|
|
private static final int ITEM_NOT_FOUND = -1;
|
|
protected final StackedContents stackedContents = new StackedContents();
|
|
protected Inventory inventory;
|
|
protected RecipeBookMenu<I, R> menu;
|
|
|
|
public ServerPlaceRecipe(RecipeBookMenu<I, R> menu) {
|
|
this.menu = menu;
|
|
}
|
|
|
|
public void recipeClicked(ServerPlayer player, @Nullable RecipeHolder<R> recipe, boolean placeAll) {
|
|
if (recipe != null && player.getRecipeBook().contains(recipe)) {
|
|
this.inventory = player.getInventory();
|
|
if (this.testClearGrid() || player.isCreative()) {
|
|
this.stackedContents.clear();
|
|
player.getInventory().fillStackedContents(this.stackedContents);
|
|
this.menu.fillCraftSlotsStackedContents(this.stackedContents);
|
|
if (this.stackedContents.canCraft(recipe.value(), null)) {
|
|
this.handleRecipeClicked(recipe, placeAll);
|
|
} else {
|
|
this.clearGrid();
|
|
player.connection.send(new ClientboundPlaceGhostRecipePacket(player.containerMenu.containerId, recipe));
|
|
}
|
|
|
|
player.getInventory().setChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void clearGrid() {
|
|
for (int i = 0; i < this.menu.getSize(); i++) {
|
|
if (this.menu.shouldMoveToInventory(i)) {
|
|
ItemStack itemStack = this.menu.getSlot(i).getItem().copy();
|
|
this.inventory.placeItemBackInInventory(itemStack, false);
|
|
this.menu.getSlot(i).set(itemStack);
|
|
}
|
|
}
|
|
|
|
this.menu.clearCraftingContent();
|
|
}
|
|
|
|
protected void handleRecipeClicked(RecipeHolder<R> recipe, boolean placeAll) {
|
|
boolean bl = this.menu.recipeMatches(recipe);
|
|
int i = this.stackedContents.getBiggestCraftableStack(recipe, null);
|
|
if (bl) {
|
|
for (int j = 0; j < this.menu.getGridHeight() * this.menu.getGridWidth() + 1; j++) {
|
|
if (j != this.menu.getResultSlotIndex()) {
|
|
ItemStack itemStack = this.menu.getSlot(j).getItem();
|
|
if (!itemStack.isEmpty() && Math.min(i, itemStack.getMaxStackSize()) < itemStack.getCount() + 1) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int jx = this.getStackSize(placeAll, i, bl);
|
|
IntList intList = new IntArrayList();
|
|
if (this.stackedContents.canCraft(recipe.value(), intList, jx)) {
|
|
int k = jx;
|
|
|
|
for (int l : intList) {
|
|
ItemStack itemStack2 = StackedContents.fromStackingIndex(l);
|
|
if (!itemStack2.isEmpty()) {
|
|
int m = itemStack2.getMaxStackSize();
|
|
if (m < k) {
|
|
k = m;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.stackedContents.canCraft(recipe.value(), intList, k)) {
|
|
this.clearGrid();
|
|
this.placeRecipe(this.menu.getGridWidth(), this.menu.getGridHeight(), this.menu.getResultSlotIndex(), recipe, intList.iterator(), k);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void addItemToSlot(Integer item, int slot, int maxAmount, int x, int y) {
|
|
Slot slot2 = this.menu.getSlot(slot);
|
|
ItemStack itemStack = StackedContents.fromStackingIndex(item);
|
|
if (!itemStack.isEmpty()) {
|
|
int i = maxAmount;
|
|
|
|
while (i > 0) {
|
|
i = this.moveItemToGrid(slot2, itemStack, i);
|
|
if (i == -1) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected int getStackSize(boolean placeAll, int maxPossible, boolean recipeMatches) {
|
|
int i = 1;
|
|
if (placeAll) {
|
|
i = maxPossible;
|
|
} else if (recipeMatches) {
|
|
i = Integer.MAX_VALUE;
|
|
|
|
for (int j = 0; j < this.menu.getGridWidth() * this.menu.getGridHeight() + 1; j++) {
|
|
if (j != this.menu.getResultSlotIndex()) {
|
|
ItemStack itemStack = this.menu.getSlot(j).getItem();
|
|
if (!itemStack.isEmpty() && i > itemStack.getCount()) {
|
|
i = itemStack.getCount();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i != Integer.MAX_VALUE) {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
protected int moveItemToGrid(Slot slot, ItemStack stack, int maxAmount) {
|
|
int i = this.inventory.findSlotMatchingUnusedItem(stack);
|
|
if (i == -1) {
|
|
return -1;
|
|
} else {
|
|
ItemStack itemStack = this.inventory.getItem(i);
|
|
int j;
|
|
if (maxAmount < itemStack.getCount()) {
|
|
this.inventory.removeItem(i, maxAmount);
|
|
j = maxAmount;
|
|
} else {
|
|
this.inventory.removeItemNoUpdate(i);
|
|
j = itemStack.getCount();
|
|
}
|
|
|
|
if (slot.getItem().isEmpty()) {
|
|
slot.set(itemStack.copyWithCount(j));
|
|
} else {
|
|
slot.getItem().grow(j);
|
|
}
|
|
|
|
return maxAmount - j;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Places the output of the recipe into the player's inventory.
|
|
*/
|
|
private boolean testClearGrid() {
|
|
List<ItemStack> list = Lists.<ItemStack>newArrayList();
|
|
int i = this.getAmountOfFreeSlotsInInventory();
|
|
|
|
for (int j = 0; j < this.menu.getGridWidth() * this.menu.getGridHeight() + 1; j++) {
|
|
if (j != this.menu.getResultSlotIndex()) {
|
|
ItemStack itemStack = this.menu.getSlot(j).getItem().copy();
|
|
if (!itemStack.isEmpty()) {
|
|
int k = this.inventory.getSlotWithRemainingSpace(itemStack);
|
|
if (k == -1 && list.size() <= i) {
|
|
for (ItemStack itemStack2 : list) {
|
|
if (ItemStack.isSameItem(itemStack2, itemStack)
|
|
&& itemStack2.getCount() != itemStack2.getMaxStackSize()
|
|
&& itemStack2.getCount() + itemStack.getCount() <= itemStack2.getMaxStackSize()) {
|
|
itemStack2.grow(itemStack.getCount());
|
|
itemStack.setCount(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!itemStack.isEmpty()) {
|
|
if (list.size() >= i) {
|
|
return false;
|
|
}
|
|
|
|
list.add(itemStack);
|
|
}
|
|
} else if (k == -1) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private int getAmountOfFreeSlotsInInventory() {
|
|
int i = 0;
|
|
|
|
for (ItemStack itemStack : this.inventory.items) {
|
|
if (itemStack.isEmpty()) {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
}
|