package net.gamelog.suntrot.screen; import com.google.common.collect.Lists; import net.gamelog.suntrot.block.SuntrotBlocks; import net.gamelog.suntrot.recipe.SewingRecipe; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.CraftingResultInventory; import net.minecraft.inventory.Inventory; import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.*; import net.minecraft.screen.*; import net.minecraft.screen.slot.Slot; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; import net.minecraft.world.World; import java.util.List; public class SewingScreenHandler extends ScreenHandler { public static final int INPUT_ID = 0; public static final int DYE_ID = 1; public static final int OUTPUT_ID = 2; private static final int INVENTORY_START = 3; private static final int INVENTORY_END = 30; private static final int OUTPUT_START = 30; private static final int OUTPUT_END = 39; private final ScreenHandlerContext context; private final Property selectedRecipe = Property.create(); private final World world; private List availableRecipes = Lists.newArrayList(); private ItemStack inputStack = ItemStack.EMPTY; long lastTakeTime; final Slot inputSlot; final Slot dyeSlot; final Slot outputSlot; Runnable contentsChangedListener = () -> { }; public final Inventory input = new SimpleInventory(2) { @Override public void markDirty() { super.markDirty(); SewingScreenHandler.this.onContentChanged(this); SewingScreenHandler.this.contentsChangedListener.run(); } }; final CraftingResultInventory output = new CraftingResultInventory(); public SewingScreenHandler(int syncId, PlayerInventory playerInventory) { this(syncId, playerInventory, ScreenHandlerContext.EMPTY); } public SewingScreenHandler(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { super(SuntrotScreenHandlers.SEWING, syncId); this.context = context; this.world = playerInventory.player.getWorld(); this.inputSlot = this.addSlot(new Slot(this.input, 0, 10, 33)); this.dyeSlot = this.addSlot(new Slot(this.input, 1, 30, 33){ @Override public boolean canInsert(ItemStack stack) { return stack.getItem() instanceof DyeItem; } }); this.outputSlot = this.addSlot(new Slot(this.output, 1, 143, 33) { @Override public boolean canInsert(ItemStack stack) { return false; } @Override public void onTakeItem(PlayerEntity player, ItemStack stack) { stack.onCraft(player.getWorld(), player, stack.getCount()); SewingScreenHandler.this.output.unlockLastRecipe(player, this.getInputStacks()); ItemStack itemStack = SewingScreenHandler.this.inputSlot.takeStack(1); if (!itemStack.isEmpty()) { SewingScreenHandler.this.populateResult(); } context.run((world, pos) -> { long l = world.getTime(); if (SewingScreenHandler.this.lastTakeTime != l) { world.playSound(null, pos, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundCategory.BLOCKS, 1.0F, 1.0F); SewingScreenHandler.this.lastTakeTime = l; } }); super.onTakeItem(player, stack); } private List getInputStacks() { return List.of(SewingScreenHandler.this.inputSlot.getStack()); } }); 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)); } this.addProperty(this.selectedRecipe); } public int getSelectedRecipe() { return this.selectedRecipe.get(); } public List getAvailableRecipes() { return this.availableRecipes; } public int getAvailableRecipeCount() { return this.availableRecipes.size(); } public boolean canCraft() { return this.inputSlot.hasStack() && !this.availableRecipes.isEmpty(); } @Override public boolean canUse(PlayerEntity player) { return canUse(this.context, player, SuntrotBlocks.SEWING_STATION); } @Override public boolean onButtonClick(PlayerEntity player, int id) { if (this.isInBounds(id)) { this.selectedRecipe.set(id); this.populateResult(); } return true; } private boolean isInBounds(int id) { return id >= 0 && id < this.availableRecipes.size(); } @Override public void onContentChanged(Inventory inventory) { ItemStack itemStack = this.inputSlot.getStack(); if (!itemStack.isOf(this.inputStack.getItem())) { this.inputStack = itemStack.copy(); this.updateInput(inventory, itemStack); } } private void updateInput(Inventory input, ItemStack stack) { this.availableRecipes.clear(); this.selectedRecipe.set(-1); this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY); if (!stack.isEmpty()) { this.availableRecipes = this.world.getRecipeManager().getAllMatches(SewingRecipe.Type.INSTANCE, input, this.world); } } void populateResult() { if (!this.availableRecipes.isEmpty() && this.isInBounds(this.selectedRecipe.get())) { SewingRecipe sewingRecipe = (SewingRecipe)this.availableRecipes.get(this.selectedRecipe.get()); ItemStack itemStack = sewingRecipe.craft(this.input, this.world.getRegistryManager()); if (itemStack.isItemEnabled(this.world.getEnabledFeatures())) { this.output.setLastRecipe(sewingRecipe); this.outputSlot.setStackNoCallbacks(itemStack); } else { this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY); } } else { this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY); } this.sendContentUpdates(); } @Override public ScreenHandlerType getType() { return SuntrotScreenHandlers.SEWING; } public void setContentsChangedListener(Runnable contentsChangedListener) { this.contentsChangedListener = contentsChangedListener; } @Override public boolean canInsertIntoSlot(ItemStack stack, Slot slot) { return slot.inventory != this.output && super.canInsertIntoSlot(stack, slot); } @Override public ItemStack quickMove(PlayerEntity player, int slot) { ItemStack itemStack = ItemStack.EMPTY; Slot slot2 = this.slots.get(slot); if (slot2 != null && slot2.hasStack()) { ItemStack itemStack2 = slot2.getStack(); itemStack = itemStack2.copy(); if (slot == this.outputSlot.id) { if (!this.insertItem(itemStack2, 4, 40, true)) { return ItemStack.EMPTY; } slot2.onQuickTransfer(itemStack2, itemStack); } else if (slot == this.inputSlot.id) { if (!this.insertItem(itemStack2, 3, 39, false)) { return ItemStack.EMPTY; } } else if (this.world.getRecipeManager().getFirstMatch(SewingRecipe.Type.INSTANCE, new SimpleInventory(itemStack2), this.world).isPresent()) { if (!this.insertItem(itemStack2, this.inputSlot.id, this.outputSlot.id, false)) { return ItemStack.EMPTY; } } else if (slot >= 3 && slot < 30) { if (!this.insertItem(itemStack2, 30, 39, false)) { return ItemStack.EMPTY; } } else if (slot >= 30 && slot < 39 && !this.insertItem(itemStack2, 3, 30, false)) { return ItemStack.EMPTY; } if (itemStack2.isEmpty()) { slot2.setStack(ItemStack.EMPTY); } slot2.markDirty(); if (itemStack2.getCount() == itemStack.getCount()) { return ItemStack.EMPTY; } slot2.onTakeItem(player, itemStack2); this.sendContentUpdates(); } return itemStack; } @Override public void onClosed(PlayerEntity player) { super.onClosed(player); this.output.removeStack(1); this.context.run((world, pos) -> this.dropInventory(player, this.input)); } public Slot getDyeSlot() { return this.dyeSlot; }