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;
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<SewingRecipe> availableRecipes = Lists.<SewingRecipe>newArrayList();
private ItemStack inputStack = ItemStack.EMPTY;
Runnable contentsChangedListener = () -> {
public final Inventory input = new SimpleInventory(2) {
public void 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.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){
public boolean canInsert(ItemStack stack) {
return stack.getItem() instanceof DyeItem;
this.outputSlot = this.addSlot(new Slot(this.output, 1, 143, 33) {
public boolean canInsert(ItemStack stack) {
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<ItemStack> 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<SewingRecipe> getAvailableRecipes() {
return this.availableRecipes;
public int getAvailableRecipeCount() {
return this.availableRecipes.size();
public boolean canCraft() {
return this.inputSlot.hasStack() && !this.availableRecipes.isEmpty();
public boolean canUse(PlayerEntity player) {
return canUse(this.context, player, SuntrotBlocks.SEWING_STATION);
public boolean onButtonClick(PlayerEntity player, int id) {
if (this.isInBounds(id)) {
this.selectedRecipe.set(id);
private boolean isInBounds(int id) {
return id >= 0 && id < this.availableRecipes.size();
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);
this.availableRecipes = this.world.getRecipeManager().getAllMatches(SewingRecipe.Type.INSTANCE, input, this.world);
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);
this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY);
this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY);
this.sendContentUpdates();
public ScreenHandlerType<?> getType() {
return SuntrotScreenHandlers.SEWING;
public void setContentsChangedListener(Runnable contentsChangedListener) {
this.contentsChangedListener = contentsChangedListener;
public boolean canInsertIntoSlot(ItemStack stack, Slot slot) {
return slot.inventory != this.output && super.canInsertIntoSlot(stack, slot);
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)) {
slot2.onQuickTransfer(itemStack2, itemStack);
} else if (slot == this.inputSlot.id) {
if (!this.insertItem(itemStack2, 3, 39, false)) {
} 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)) {
} else if (slot >= 3 && slot < 30) {
if (!this.insertItem(itemStack2, 30, 39, false)) {
} else if (slot >= 30 && slot < 39 && !this.insertItem(itemStack2, 3, 30, false)) {
if (itemStack2.isEmpty()) {
slot2.setStack(ItemStack.EMPTY);
if (itemStack2.getCount() == itemStack.getCount()) {
slot2.onTakeItem(player, itemStack2);
this.sendContentUpdates();
public void onClosed(PlayerEntity player) {
this.output.removeStack(1);
this.context.run((world, pos) -> this.dropInventory(player, this.input));
public Slot getDyeSlot() {