minecraft-src/net/minecraft/world/inventory/ItemCombinerMenu.java
2025-07-04 02:49:36 +03:00

185 lines
5.6 KiB
Java

package net.minecraft.world.inventory;
import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ItemCombinerMenuSlotDefinition.SlotDefinition;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public abstract class ItemCombinerMenu extends AbstractContainerMenu {
private static final int INVENTORY_SLOTS_PER_ROW = 9;
private static final int INVENTORY_ROWS = 3;
private static final int INPUT_SLOT_START = 0;
protected final ContainerLevelAccess access;
protected final Player player;
protected final Container inputSlots;
protected final ResultContainer resultSlots = new ResultContainer() {
@Override
public void setChanged() {
ItemCombinerMenu.this.slotsChanged(this);
}
};
private final int resultSlotIndex;
protected boolean mayPickup(Player player, boolean hasStack) {
return true;
}
protected abstract void onTake(Player player, ItemStack stack);
protected abstract boolean isValidBlock(BlockState state);
public ItemCombinerMenu(
@Nullable MenuType<?> menuType, int containerId, Inventory inventory, ContainerLevelAccess access, ItemCombinerMenuSlotDefinition slotDefinition
) {
super(menuType, containerId);
this.access = access;
this.player = inventory.player;
this.inputSlots = this.createContainer(slotDefinition.getNumOfInputSlots());
this.resultSlotIndex = slotDefinition.getResultSlotIndex();
this.createInputSlots(slotDefinition);
this.createResultSlot(slotDefinition);
this.addStandardInventorySlots(inventory, 8, 84);
}
private void createInputSlots(ItemCombinerMenuSlotDefinition slotDefinition) {
for (final SlotDefinition slotDefinition2 : slotDefinition.getSlots()) {
this.addSlot(new Slot(this.inputSlots, slotDefinition2.slotIndex(), slotDefinition2.x(), slotDefinition2.y()) {
@Override
public boolean mayPlace(ItemStack stack) {
return slotDefinition2.mayPlace().test(stack);
}
});
}
}
private void createResultSlot(ItemCombinerMenuSlotDefinition slotDefinition) {
this.addSlot(new Slot(this.resultSlots, slotDefinition.getResultSlot().slotIndex(), slotDefinition.getResultSlot().x(), slotDefinition.getResultSlot().y()) {
@Override
public boolean mayPlace(ItemStack stack) {
return false;
}
@Override
public boolean mayPickup(Player player) {
return ItemCombinerMenu.this.mayPickup(player, this.hasItem());
}
@Override
public void onTake(Player player, ItemStack stack) {
ItemCombinerMenu.this.onTake(player, stack);
}
});
}
/**
* Called when the Anvil Input Slot changes, calculates the new result and puts it in the output slot.
*/
public abstract void createResult();
private SimpleContainer createContainer(int size) {
return new SimpleContainer(size) {
@Override
public void setChanged() {
super.setChanged();
ItemCombinerMenu.this.slotsChanged(this);
}
};
}
@Override
public void slotsChanged(Container container) {
super.slotsChanged(container);
if (container == this.inputSlots) {
this.createResult();
}
}
@Override
public void removed(Player player) {
super.removed(player);
this.access.execute((level, blockPos) -> this.clearContainer(player, this.inputSlots));
}
@Override
public boolean stillValid(Player player) {
return this.access
.evaluate((level, blockPos) -> !this.isValidBlock(level.getBlockState(blockPos)) ? false : player.canInteractWithBlock(blockPos, 4.0), true);
}
@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();
int i = this.getInventorySlotStart();
int j = this.getUseRowEnd();
if (index == this.getResultSlot()) {
if (!this.moveItemStackTo(itemStack2, i, j, true)) {
return ItemStack.EMPTY;
}
slot.onQuickCraft(itemStack2, itemStack);
} else if (index >= 0 && index < this.getResultSlot()) {
if (!this.moveItemStackTo(itemStack2, i, j, false)) {
return ItemStack.EMPTY;
}
} else if (this.canMoveIntoInputSlots(itemStack2) && index >= this.getInventorySlotStart() && index < this.getUseRowEnd()) {
if (!this.moveItemStackTo(itemStack2, 0, this.getResultSlot(), false)) {
return ItemStack.EMPTY;
}
} else if (index >= this.getInventorySlotStart() && index < this.getInventorySlotEnd()) {
if (!this.moveItemStackTo(itemStack2, this.getUseRowStart(), this.getUseRowEnd(), false)) {
return ItemStack.EMPTY;
}
} else if (index >= this.getUseRowStart()
&& index < this.getUseRowEnd()
&& !this.moveItemStackTo(itemStack2, this.getInventorySlotStart(), this.getInventorySlotEnd(), 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);
}
return itemStack;
}
protected boolean canMoveIntoInputSlots(ItemStack stack) {
return true;
}
public int getResultSlot() {
return this.resultSlotIndex;
}
private int getInventorySlotStart() {
return this.getResultSlot() + 1;
}
private int getInventorySlotEnd() {
return this.getInventorySlotStart() + 27;
}
private int getUseRowStart() {
return this.getInventorySlotEnd();
}
private int getUseRowEnd() {
return this.getUseRowStart() + 9;
}
}