137 lines
5.3 KiB
Java
137 lines
5.3 KiB
Java
package net.minecraft.world.inventory;
|
|
|
|
import java.util.List;
|
|
import java.util.OptionalInt;
|
|
import net.minecraft.world.entity.player.Inventory;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.crafting.RecipeHolder;
|
|
import net.minecraft.world.item.crafting.RecipeType;
|
|
import net.minecraft.world.item.crafting.SmithingRecipe;
|
|
import net.minecraft.world.item.crafting.SmithingRecipeInput;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class SmithingMenu extends ItemCombinerMenu {
|
|
public static final int TEMPLATE_SLOT = 0;
|
|
public static final int BASE_SLOT = 1;
|
|
public static final int ADDITIONAL_SLOT = 2;
|
|
public static final int RESULT_SLOT = 3;
|
|
public static final int TEMPLATE_SLOT_X_PLACEMENT = 8;
|
|
public static final int BASE_SLOT_X_PLACEMENT = 26;
|
|
public static final int ADDITIONAL_SLOT_X_PLACEMENT = 44;
|
|
private static final int RESULT_SLOT_X_PLACEMENT = 98;
|
|
public static final int SLOT_Y_PLACEMENT = 48;
|
|
private final Level level;
|
|
@Nullable
|
|
private RecipeHolder<SmithingRecipe> selectedRecipe;
|
|
private final List<RecipeHolder<SmithingRecipe>> recipes;
|
|
|
|
public SmithingMenu(int containerId, Inventory playerInventory) {
|
|
this(containerId, playerInventory, ContainerLevelAccess.NULL);
|
|
}
|
|
|
|
public SmithingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) {
|
|
super(MenuType.SMITHING, containerId, playerInventory, access);
|
|
this.level = playerInventory.player.level();
|
|
this.recipes = this.level.getRecipeManager().getAllRecipesFor(RecipeType.SMITHING);
|
|
}
|
|
|
|
@Override
|
|
protected ItemCombinerMenuSlotDefinition createInputSlotDefinitions() {
|
|
return ItemCombinerMenuSlotDefinition.create()
|
|
.withSlot(0, 8, 48, itemStack -> this.recipes.stream().anyMatch(recipeHolder -> ((SmithingRecipe)recipeHolder.value()).isTemplateIngredient(itemStack)))
|
|
.withSlot(1, 26, 48, itemStack -> this.recipes.stream().anyMatch(recipeHolder -> ((SmithingRecipe)recipeHolder.value()).isBaseIngredient(itemStack)))
|
|
.withSlot(2, 44, 48, itemStack -> this.recipes.stream().anyMatch(recipeHolder -> ((SmithingRecipe)recipeHolder.value()).isAdditionIngredient(itemStack)))
|
|
.withResultSlot(3, 98, 48)
|
|
.build();
|
|
}
|
|
|
|
@Override
|
|
protected boolean isValidBlock(BlockState state) {
|
|
return state.is(Blocks.SMITHING_TABLE);
|
|
}
|
|
|
|
@Override
|
|
protected boolean mayPickup(Player player, boolean hasStack) {
|
|
return this.selectedRecipe != null && this.selectedRecipe.value().matches(this.createRecipeInput(), this.level);
|
|
}
|
|
|
|
@Override
|
|
protected void onTake(Player player, ItemStack stack) {
|
|
stack.onCraftedBy(player.level(), player, stack.getCount());
|
|
this.resultSlots.awardUsedRecipes(player, this.getRelevantItems());
|
|
this.shrinkStackInSlot(0);
|
|
this.shrinkStackInSlot(1);
|
|
this.shrinkStackInSlot(2);
|
|
this.access.execute((level, blockPos) -> level.levelEvent(1044, blockPos, 0));
|
|
}
|
|
|
|
private List<ItemStack> getRelevantItems() {
|
|
return List.of(this.inputSlots.getItem(0), this.inputSlots.getItem(1), this.inputSlots.getItem(2));
|
|
}
|
|
|
|
private SmithingRecipeInput createRecipeInput() {
|
|
return new SmithingRecipeInput(this.inputSlots.getItem(0), this.inputSlots.getItem(1), this.inputSlots.getItem(2));
|
|
}
|
|
|
|
private void shrinkStackInSlot(int index) {
|
|
ItemStack itemStack = this.inputSlots.getItem(index);
|
|
if (!itemStack.isEmpty()) {
|
|
itemStack.shrink(1);
|
|
this.inputSlots.setItem(index, itemStack);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void createResult() {
|
|
SmithingRecipeInput smithingRecipeInput = this.createRecipeInput();
|
|
List<RecipeHolder<SmithingRecipe>> list = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, smithingRecipeInput, this.level);
|
|
if (list.isEmpty()) {
|
|
this.resultSlots.setItem(0, ItemStack.EMPTY);
|
|
} else {
|
|
RecipeHolder<SmithingRecipe> recipeHolder = (RecipeHolder<SmithingRecipe>)list.get(0);
|
|
ItemStack itemStack = recipeHolder.value().assemble(smithingRecipeInput, this.level.registryAccess());
|
|
if (itemStack.isItemEnabled(this.level.enabledFeatures())) {
|
|
this.selectedRecipe = recipeHolder;
|
|
this.resultSlots.setRecipeUsed(recipeHolder);
|
|
this.resultSlots.setItem(0, itemStack);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getSlotToQuickMoveTo(ItemStack stack) {
|
|
return this.findSlotToQuickMoveTo(stack).orElse(0);
|
|
}
|
|
|
|
private static OptionalInt findSlotMatchingIngredient(SmithingRecipe recipe, ItemStack stack) {
|
|
if (recipe.isTemplateIngredient(stack)) {
|
|
return OptionalInt.of(0);
|
|
} else if (recipe.isBaseIngredient(stack)) {
|
|
return OptionalInt.of(1);
|
|
} else {
|
|
return recipe.isAdditionIngredient(stack) ? OptionalInt.of(2) : OptionalInt.empty();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) {
|
|
return slot.container != this.resultSlots && super.canTakeItemForPickAll(stack, slot);
|
|
}
|
|
|
|
@Override
|
|
public boolean canMoveIntoInputSlots(ItemStack stack) {
|
|
return this.findSlotToQuickMoveTo(stack).isPresent();
|
|
}
|
|
|
|
private OptionalInt findSlotToQuickMoveTo(ItemStack stack) {
|
|
return this.recipes
|
|
.stream()
|
|
.flatMapToInt(recipeHolder -> findSlotMatchingIngredient((SmithingRecipe)recipeHolder.value(), stack).stream())
|
|
.filter(i -> !this.getSlot(i).hasItem())
|
|
.findFirst();
|
|
}
|
|
}
|