226 lines
8.7 KiB
Java
226 lines
8.7 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*/
|
|
package net.minecraft.world.inventory;
|
|
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.HolderLookup;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
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.AbstractContainerMenu;
|
|
import net.minecraft.world.inventory.ContainerLevelAccess;
|
|
import net.minecraft.world.inventory.DataSlot;
|
|
import net.minecraft.world.inventory.MenuType;
|
|
import net.minecraft.world.inventory.ResultContainer;
|
|
import net.minecraft.world.inventory.Slot;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.crafting.RecipeHolder;
|
|
import net.minecraft.world.item.crafting.SelectableRecipe;
|
|
import net.minecraft.world.item.crafting.SingleRecipeInput;
|
|
import net.minecraft.world.item.crafting.StonecutterRecipe;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
|
|
public class StonecutterMenu
|
|
extends AbstractContainerMenu {
|
|
public static final int INPUT_SLOT = 0;
|
|
public static final int RESULT_SLOT = 1;
|
|
private static final int INV_SLOT_START = 2;
|
|
private static final int INV_SLOT_END = 29;
|
|
private static final int USE_ROW_SLOT_START = 29;
|
|
private static final int USE_ROW_SLOT_END = 38;
|
|
private final ContainerLevelAccess access;
|
|
private final DataSlot selectedRecipeIndex = DataSlot.standalone();
|
|
private final Level level;
|
|
private SelectableRecipe.SingleInputSet<StonecutterRecipe> recipesForInput = SelectableRecipe.SingleInputSet.empty();
|
|
private ItemStack input = ItemStack.EMPTY;
|
|
private long lastSoundTime;
|
|
final Slot inputSlot;
|
|
final Slot resultSlot;
|
|
private Runnable slotUpdateListener = () -> {};
|
|
public final Container container = new SimpleContainer(1){
|
|
|
|
@Override
|
|
public void setChanged() {
|
|
super.setChanged();
|
|
StonecutterMenu.this.slotsChanged(this);
|
|
StonecutterMenu.this.slotUpdateListener.run();
|
|
}
|
|
};
|
|
private final ResultContainer resultContainer = new ResultContainer();
|
|
|
|
public StonecutterMenu(int containerId, Inventory inventory) {
|
|
this(containerId, inventory, ContainerLevelAccess.NULL);
|
|
}
|
|
|
|
public StonecutterMenu(int containerId, Inventory inventory, final ContainerLevelAccess access) {
|
|
super(MenuType.STONECUTTER, containerId);
|
|
this.access = access;
|
|
this.level = inventory.player.level();
|
|
this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33));
|
|
this.resultSlot = this.addSlot(new Slot(this.resultContainer, 1, 143, 33){
|
|
|
|
@Override
|
|
public boolean mayPlace(ItemStack itemStack) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onTake(Player player, ItemStack carried) {
|
|
carried.onCraftedBy(player, carried.getCount());
|
|
StonecutterMenu.this.resultContainer.awardUsedRecipes(player, this.getRelevantItems());
|
|
ItemStack remaining = StonecutterMenu.this.inputSlot.remove(1);
|
|
if (!remaining.isEmpty()) {
|
|
StonecutterMenu.this.setupResultSlot(StonecutterMenu.this.selectedRecipeIndex.get());
|
|
}
|
|
access.execute((level, pos) -> {
|
|
long gameTime = level.getGameTime();
|
|
if (StonecutterMenu.this.lastSoundTime != gameTime) {
|
|
level.playSound(null, (BlockPos)pos, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0f, 1.0f);
|
|
StonecutterMenu.this.lastSoundTime = gameTime;
|
|
}
|
|
});
|
|
super.onTake(player, carried);
|
|
}
|
|
|
|
private List<ItemStack> getRelevantItems() {
|
|
return List.of(StonecutterMenu.this.inputSlot.getItem());
|
|
}
|
|
});
|
|
this.addStandardInventorySlots(inventory, 8, 84);
|
|
this.addDataSlot(this.selectedRecipeIndex);
|
|
}
|
|
|
|
public int getSelectedRecipeIndex() {
|
|
return this.selectedRecipeIndex.get();
|
|
}
|
|
|
|
public SelectableRecipe.SingleInputSet<StonecutterRecipe> getVisibleRecipes() {
|
|
return this.recipesForInput;
|
|
}
|
|
|
|
public int getNumberOfVisibleRecipes() {
|
|
return this.recipesForInput.size();
|
|
}
|
|
|
|
public boolean hasInputItem() {
|
|
return this.inputSlot.hasItem() && !this.recipesForInput.isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public boolean stillValid(Player player) {
|
|
return StonecutterMenu.stillValid(this.access, player, Blocks.STONECUTTER);
|
|
}
|
|
|
|
@Override
|
|
public boolean clickMenuButton(Player player, int buttonId) {
|
|
if (this.selectedRecipeIndex.get() == buttonId) {
|
|
return false;
|
|
}
|
|
if (this.isValidRecipeIndex(buttonId)) {
|
|
this.selectedRecipeIndex.set(buttonId);
|
|
this.setupResultSlot(buttonId);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean isValidRecipeIndex(int buttonId) {
|
|
return buttonId >= 0 && buttonId < this.recipesForInput.size();
|
|
}
|
|
|
|
@Override
|
|
public void slotsChanged(Container container) {
|
|
ItemStack input = this.inputSlot.getItem();
|
|
if (!input.is(this.input.getItem())) {
|
|
this.input = input.copy();
|
|
this.setupRecipeList(input);
|
|
}
|
|
}
|
|
|
|
private void setupRecipeList(ItemStack item) {
|
|
this.selectedRecipeIndex.set(-1);
|
|
this.resultSlot.set(ItemStack.EMPTY);
|
|
this.recipesForInput = !item.isEmpty() ? this.level.recipeAccess().stonecutterRecipes().selectByInput(item) : SelectableRecipe.SingleInputSet.empty();
|
|
}
|
|
|
|
private void setupResultSlot(int index) {
|
|
Optional<RecipeHolder<Object>> usedRecipe;
|
|
if (!this.recipesForInput.isEmpty() && this.isValidRecipeIndex(index)) {
|
|
SelectableRecipe.SingleInputEntry<StonecutterRecipe> entry = this.recipesForInput.entries().get(index);
|
|
usedRecipe = entry.recipe().recipe();
|
|
} else {
|
|
usedRecipe = Optional.empty();
|
|
}
|
|
usedRecipe.ifPresentOrElse(recipe -> {
|
|
this.resultContainer.setRecipeUsed((RecipeHolder<?>)recipe);
|
|
this.resultSlot.set(((StonecutterRecipe)recipe.value()).assemble(new SingleRecipeInput(this.container.getItem(0)), (HolderLookup.Provider)this.level.registryAccess()));
|
|
}, () -> {
|
|
this.resultSlot.set(ItemStack.EMPTY);
|
|
this.resultContainer.setRecipeUsed(null);
|
|
});
|
|
this.broadcastChanges();
|
|
}
|
|
|
|
@Override
|
|
public MenuType<?> getType() {
|
|
return MenuType.STONECUTTER;
|
|
}
|
|
|
|
public void registerUpdateListener(Runnable slotUpdateListener) {
|
|
this.slotUpdateListener = slotUpdateListener;
|
|
}
|
|
|
|
@Override
|
|
public boolean canTakeItemForPickAll(ItemStack carried, Slot target) {
|
|
return target.container != this.resultContainer && super.canTakeItemForPickAll(carried, target);
|
|
}
|
|
|
|
@Override
|
|
public ItemStack quickMoveStack(Player player, int slotIndex) {
|
|
ItemStack clicked = ItemStack.EMPTY;
|
|
Slot slot = (Slot)this.slots.get(slotIndex);
|
|
if (slot != null && slot.hasItem()) {
|
|
ItemStack stack = slot.getItem();
|
|
Item item = stack.getItem();
|
|
clicked = stack.copy();
|
|
if (slotIndex == 1) {
|
|
item.onCraftedBy(stack, player);
|
|
if (!this.moveItemStackTo(stack, 2, 38, true)) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
slot.onQuickCraft(stack, clicked);
|
|
} else if (slotIndex == 0 ? !this.moveItemStackTo(stack, 2, 38, false) : (this.level.recipeAccess().stonecutterRecipes().acceptsInput(stack) ? !this.moveItemStackTo(stack, 0, 1, false) : (slotIndex >= 2 && slotIndex < 29 ? !this.moveItemStackTo(stack, 29, 38, false) : slotIndex >= 29 && slotIndex < 38 && !this.moveItemStackTo(stack, 2, 29, false)))) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
if (stack.isEmpty()) {
|
|
slot.setByPlayer(ItemStack.EMPTY);
|
|
}
|
|
slot.setChanged();
|
|
if (stack.getCount() == clicked.getCount()) {
|
|
return ItemStack.EMPTY;
|
|
}
|
|
slot.onTake(player, stack);
|
|
if (slotIndex == 1) {
|
|
player.drop(stack, false);
|
|
}
|
|
this.broadcastChanges();
|
|
}
|
|
return clicked;
|
|
}
|
|
|
|
@Override
|
|
public void removed(Player player) {
|
|
super.removed(player);
|
|
this.resultContainer.removeItemNoUpdate(1);
|
|
this.access.execute((level, pos) -> this.clearContainer(player, this.container));
|
|
}
|
|
}
|
|
|