216 lines
6.7 KiB
Java
216 lines
6.7 KiB
Java
package net.minecraft.world.inventory;
|
|
|
|
import java.util.Optional;
|
|
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.Container;
|
|
import net.minecraft.world.entity.player.Inventory;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.entity.player.StackedContents;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.crafting.CraftingInput;
|
|
import net.minecraft.world.item.crafting.CraftingRecipe;
|
|
import net.minecraft.world.item.crafting.RecipeHolder;
|
|
import net.minecraft.world.item.crafting.RecipeType;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class CraftingMenu extends RecipeBookMenu<CraftingInput, CraftingRecipe> {
|
|
public static final int RESULT_SLOT = 0;
|
|
private static final int CRAFT_SLOT_START = 1;
|
|
private static final int CRAFT_SLOT_END = 10;
|
|
private static final int INV_SLOT_START = 10;
|
|
private static final int INV_SLOT_END = 37;
|
|
private static final int USE_ROW_SLOT_START = 37;
|
|
private static final int USE_ROW_SLOT_END = 46;
|
|
private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 3, 3);
|
|
private final ResultContainer resultSlots = new ResultContainer();
|
|
private final ContainerLevelAccess access;
|
|
private final Player player;
|
|
private boolean placingRecipe;
|
|
|
|
public CraftingMenu(int containerId, Inventory playerInventory) {
|
|
this(containerId, playerInventory, ContainerLevelAccess.NULL);
|
|
}
|
|
|
|
public CraftingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) {
|
|
super(MenuType.CRAFTING, containerId);
|
|
this.access = access;
|
|
this.player = playerInventory.player;
|
|
this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 124, 35));
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
this.addSlot(new Slot(this.craftSlots, j + i * 3, 30 + j * 18, 17 + i * 18));
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 9; j++) {
|
|
this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
|
|
}
|
|
}
|
|
|
|
protected static void slotChangedCraftingGrid(
|
|
AbstractContainerMenu menu,
|
|
Level level,
|
|
Player player,
|
|
CraftingContainer craftSlots,
|
|
ResultContainer resultSlots,
|
|
@Nullable RecipeHolder<CraftingRecipe> recipe
|
|
) {
|
|
if (!level.isClientSide) {
|
|
CraftingInput craftingInput = craftSlots.asCraftInput();
|
|
ServerPlayer serverPlayer = (ServerPlayer)player;
|
|
ItemStack itemStack = ItemStack.EMPTY;
|
|
Optional<RecipeHolder<CraftingRecipe>> optional = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInput, level, recipe);
|
|
if (optional.isPresent()) {
|
|
RecipeHolder<CraftingRecipe> recipeHolder = (RecipeHolder<CraftingRecipe>)optional.get();
|
|
CraftingRecipe craftingRecipe = recipeHolder.value();
|
|
if (resultSlots.setRecipeUsed(level, serverPlayer, recipeHolder)) {
|
|
ItemStack itemStack2 = craftingRecipe.assemble(craftingInput, level.registryAccess());
|
|
if (itemStack2.isItemEnabled(level.enabledFeatures())) {
|
|
itemStack = itemStack2;
|
|
}
|
|
}
|
|
}
|
|
|
|
resultSlots.setItem(0, itemStack);
|
|
menu.setRemoteSlot(0, itemStack);
|
|
serverPlayer.connection.send(new ClientboundContainerSetSlotPacket(menu.containerId, menu.incrementStateId(), 0, itemStack));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void slotsChanged(Container container) {
|
|
if (!this.placingRecipe) {
|
|
this.access.execute((level, blockPos) -> slotChangedCraftingGrid(this, level, this.player, this.craftSlots, this.resultSlots, null));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void beginPlacingRecipe() {
|
|
this.placingRecipe = true;
|
|
}
|
|
|
|
@Override
|
|
public void finishPlacingRecipe(RecipeHolder<CraftingRecipe> recipe) {
|
|
this.placingRecipe = false;
|
|
this.access.execute((level, blockPos) -> slotChangedCraftingGrid(this, level, this.player, this.craftSlots, this.resultSlots, recipe));
|
|
}
|
|
|
|
@Override
|
|
public void fillCraftSlotsStackedContents(StackedContents itemHelper) {
|
|
this.craftSlots.fillStackedContents(itemHelper);
|
|
}
|
|
|
|
@Override
|
|
public void clearCraftingContent() {
|
|
this.craftSlots.clearContent();
|
|
this.resultSlots.clearContent();
|
|
}
|
|
|
|
@Override
|
|
public boolean recipeMatches(RecipeHolder<CraftingRecipe> recipe) {
|
|
return recipe.value().matches(this.craftSlots.asCraftInput(), this.player.level());
|
|
}
|
|
|
|
@Override
|
|
public void removed(Player player) {
|
|
super.removed(player);
|
|
this.access.execute((level, blockPos) -> this.clearContainer(player, this.craftSlots));
|
|
}
|
|
|
|
@Override
|
|
public boolean stillValid(Player player) {
|
|
return stillValid(this.access, player, Blocks.CRAFTING_TABLE);
|
|
}
|
|
|
|
@Override
|
|
public ItemStack quickMoveStack(Player player, int index) {
|
|
ItemStack itemStack = ItemStack.EMPTY;
|
|
Slot slot = this.slots.get(index);
|
|
if (slot != null && slot.hasItem()) {
|
|
ItemStack itemStack2 = slot.getItem();
|
|
itemStack = itemStack2.copy();
|
|
if (index == 0) {
|
|
this.access.execute((level, blockPos) -> itemStack2.getItem().onCraftedBy(itemStack2, level, player));
|
|
if (!this.moveItemStackTo(itemStack2, 10, 46, true)) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
|
|
slot.onQuickCraft(itemStack2, itemStack);
|
|
} else if (index >= 10 && index < 46) {
|
|
if (!this.moveItemStackTo(itemStack2, 1, 10, false)) {
|
|
if (index < 37) {
|
|
if (!this.moveItemStackTo(itemStack2, 37, 46, false)) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
} else if (!this.moveItemStackTo(itemStack2, 10, 37, false)) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
}
|
|
} else if (!this.moveItemStackTo(itemStack2, 10, 46, false)) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
|
|
if (itemStack2.isEmpty()) {
|
|
slot.setByPlayer(ItemStack.EMPTY);
|
|
} else {
|
|
slot.setChanged();
|
|
}
|
|
|
|
if (itemStack2.getCount() == itemStack.getCount()) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
|
|
slot.onTake(player, itemStack2);
|
|
if (index == 0) {
|
|
player.drop(itemStack2, false);
|
|
}
|
|
}
|
|
|
|
return itemStack;
|
|
}
|
|
|
|
@Override
|
|
public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) {
|
|
return slot.container != this.resultSlots && super.canTakeItemForPickAll(stack, slot);
|
|
}
|
|
|
|
@Override
|
|
public int getResultSlotIndex() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public int getGridWidth() {
|
|
return this.craftSlots.getWidth();
|
|
}
|
|
|
|
@Override
|
|
public int getGridHeight() {
|
|
return this.craftSlots.getHeight();
|
|
}
|
|
|
|
@Override
|
|
public int getSize() {
|
|
return 10;
|
|
}
|
|
|
|
@Override
|
|
public RecipeBookType getRecipeBookType() {
|
|
return RecipeBookType.CRAFTING;
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldMoveToInventory(int slotIndex) {
|
|
return slotIndex != this.getResultSlotIndex();
|
|
}
|
|
}
|