| 1 | package net.gamelog.suntrot.screen;
|
| 2 |
|
| 3 | import com.google.common.collect.Lists;
|
| 4 | import net.gamelog.suntrot.block.SuntrotBlocks;
|
| 5 | import net.gamelog.suntrot.recipe.SewingRecipe;
|
| 6 | import net.minecraft.entity.player.PlayerEntity;
|
| 7 | import net.minecraft.entity.player.PlayerInventory;
|
| 8 | import net.minecraft.inventory.CraftingResultInventory;
|
| 9 | import net.minecraft.inventory.Inventory;
|
| 10 | import net.minecraft.inventory.SimpleInventory;
|
| 11 | import net.minecraft.item.*;
|
| 12 | import net.minecraft.screen.*;
|
| 13 | import net.minecraft.screen.slot.Slot;
|
| 14 | import net.minecraft.sound.SoundCategory;
|
| 15 | import net.minecraft.sound.SoundEvents;
|
| 16 | import net.minecraft.world.World;
|
| 17 |
|
| 18 | import java.util.List;
|
| 19 |
|
| 20 | public class SewingScreenHandler extends ScreenHandler {
|
| 21 |
|
| 22 | public static final int INPUT_ID = 0;
|
| 23 | public static final int DYE_ID = 1;
|
| 24 | public static final int OUTPUT_ID = 2;
|
| 25 | private static final int INVENTORY_START = 3;
|
| 26 | private static final int INVENTORY_END = 30;
|
| 27 | private static final int OUTPUT_START = 30;
|
| 28 | private static final int OUTPUT_END = 39;
|
| 29 | private final ScreenHandlerContext context;
|
| 30 | private final Property selectedRecipe = Property.create();
|
| 31 | private final World world;
|
| 32 | private List<SewingRecipe> availableRecipes = Lists.<SewingRecipe>newArrayList();
|
| 33 | private ItemStack inputStack = ItemStack.EMPTY;
|
| 34 | long lastTakeTime;
|
| 35 | final Slot inputSlot;
|
| 36 | final Slot dyeSlot;
|
| 37 | final Slot outputSlot;
|
| 38 | Runnable contentsChangedListener = () -> {
|
| 39 | };
|
| 40 | public final Inventory input = new SimpleInventory(2) {
|
| 41 | @Override
|
| 42 | public void markDirty() {
|
| 43 | super.markDirty();
|
| 44 | SewingScreenHandler.this.onContentChanged(this);
|
| 45 | SewingScreenHandler.this.contentsChangedListener.run();
|
| 46 | }
|
| 47 | };
|
| 48 | final CraftingResultInventory output = new CraftingResultInventory();
|
| 49 |
|
| 50 | public SewingScreenHandler(int syncId, PlayerInventory playerInventory) {
|
| 51 | this(syncId, playerInventory, ScreenHandlerContext.EMPTY);
|
| 52 | }
|
| 53 |
|
| 54 | public SewingScreenHandler(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) {
|
| 55 | super(SuntrotScreenHandlers.SEWING, syncId);
|
| 56 | this.context = context;
|
| 57 | this.world = playerInventory.player.getWorld();
|
| 58 | this.inputSlot = this.addSlot(new Slot(this.input, 0, 10, 33));
|
| 59 | this.dyeSlot = this.addSlot(new Slot(this.input, 1, 30, 33){
|
| 60 | @Override
|
| 61 | public boolean canInsert(ItemStack stack) {
|
| 62 | return stack.getItem() instanceof DyeItem;
|
| 63 | }
|
| 64 | });
|
| 65 | this.outputSlot = this.addSlot(new Slot(this.output, 1, 143, 33) {
|
| 66 | @Override
|
| 67 | public boolean canInsert(ItemStack stack) {
|
| 68 | return false;
|
| 69 | }
|
| 70 |
|
| 71 | @Override
|
| 72 | public void onTakeItem(PlayerEntity player, ItemStack stack) {
|
| 73 | stack.onCraft(player.getWorld(), player, stack.getCount());
|
| 74 | SewingScreenHandler.this.output.unlockLastRecipe(player, this.getInputStacks());
|
| 75 | ItemStack itemStack = SewingScreenHandler.this.inputSlot.takeStack(1);
|
| 76 | if (!itemStack.isEmpty()) {
|
| 77 | SewingScreenHandler.this.populateResult();
|
| 78 | }
|
| 79 |
|
| 80 | context.run((world, pos) -> {
|
| 81 | long l = world.getTime();
|
| 82 | if (SewingScreenHandler.this.lastTakeTime != l) {
|
| 83 | world.playSound(null, pos, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
| 84 | SewingScreenHandler.this.lastTakeTime = l;
|
| 85 | }
|
| 86 | });
|
| 87 | super.onTakeItem(player, stack);
|
| 88 | }
|
| 89 |
|
| 90 | private List<ItemStack> getInputStacks() {
|
| 91 | return List.of(SewingScreenHandler.this.inputSlot.getStack());
|
| 92 | }
|
| 93 | });
|
| 94 |
|
| 95 | for (int i = 0; i < 3; i++) {
|
| 96 | for (int j = 0; j < 9; j++) {
|
| 97 | this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
|
| 98 | }
|
| 99 | }
|
| 100 |
|
| 101 | for (int i = 0; i < 9; i++) {
|
| 102 | this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
|
| 103 | }
|
| 104 |
|
| 105 | this.addProperty(this.selectedRecipe);
|
| 106 | }
|
| 107 |
|
| 108 | public int getSelectedRecipe() {
|
| 109 | return this.selectedRecipe.get();
|
| 110 | }
|
| 111 |
|
| 112 | public List<SewingRecipe> getAvailableRecipes() {
|
| 113 | return this.availableRecipes;
|
| 114 | }
|
| 115 |
|
| 116 | public int getAvailableRecipeCount() {
|
| 117 | return this.availableRecipes.size();
|
| 118 | }
|
| 119 |
|
| 120 | public boolean canCraft() {
|
| 121 | return this.inputSlot.hasStack() && !this.availableRecipes.isEmpty();
|
| 122 | }
|
| 123 |
|
| 124 | @Override
|
| 125 | public boolean canUse(PlayerEntity player) {
|
| 126 | return canUse(this.context, player, SuntrotBlocks.SEWING_STATION);
|
| 127 | }
|
| 128 |
|
| 129 | @Override
|
| 130 | public boolean onButtonClick(PlayerEntity player, int id) {
|
| 131 | if (this.isInBounds(id)) {
|
| 132 | this.selectedRecipe.set(id);
|
| 133 | this.populateResult();
|
| 134 | }
|
| 135 |
|
| 136 | return true;
|
| 137 | }
|
| 138 |
|
| 139 | private boolean isInBounds(int id) {
|
| 140 | return id >= 0 && id < this.availableRecipes.size();
|
| 141 | }
|
| 142 |
|
| 143 | @Override
|
| 144 | public void onContentChanged(Inventory inventory) {
|
| 145 | ItemStack itemStack = this.inputSlot.getStack();
|
| 146 | if (!itemStack.isOf(this.inputStack.getItem())) {
|
| 147 | this.inputStack = itemStack.copy();
|
| 148 | this.updateInput(inventory, itemStack);
|
| 149 | }
|
| 150 | }
|
| 151 |
|
| 152 | private void updateInput(Inventory input, ItemStack stack) {
|
| 153 | this.availableRecipes.clear();
|
| 154 | this.selectedRecipe.set(-1);
|
| 155 | this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY);
|
| 156 | if (!stack.isEmpty()) {
|
| 157 | this.availableRecipes = this.world.getRecipeManager().getAllMatches(SewingRecipe.Type.INSTANCE, input, this.world);
|
| 158 | }
|
| 159 | }
|
| 160 |
|
| 161 | void populateResult() {
|
| 162 | if (!this.availableRecipes.isEmpty() && this.isInBounds(this.selectedRecipe.get())) {
|
| 163 | SewingRecipe sewingRecipe = (SewingRecipe)this.availableRecipes.get(this.selectedRecipe.get());
|
| 164 | ItemStack itemStack = sewingRecipe.craft(this.input, this.world.getRegistryManager());
|
| 165 | if (itemStack.isItemEnabled(this.world.getEnabledFeatures())) {
|
| 166 | this.output.setLastRecipe(sewingRecipe);
|
| 167 | this.outputSlot.setStackNoCallbacks(itemStack);
|
| 168 | } else {
|
| 169 | this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY);
|
| 170 | }
|
| 171 | } else {
|
| 172 | this.outputSlot.setStackNoCallbacks(ItemStack.EMPTY);
|
| 173 | }
|
| 174 |
|
| 175 | this.sendContentUpdates();
|
| 176 | }
|
| 177 |
|
| 178 | @Override
|
| 179 | public ScreenHandlerType<?> getType() {
|
| 180 | return SuntrotScreenHandlers.SEWING;
|
| 181 | }
|
| 182 |
|
| 183 | public void setContentsChangedListener(Runnable contentsChangedListener) {
|
| 184 | this.contentsChangedListener = contentsChangedListener;
|
| 185 | }
|
| 186 |
|
| 187 | @Override
|
| 188 | public boolean canInsertIntoSlot(ItemStack stack, Slot slot) {
|
| 189 | return slot.inventory != this.output && super.canInsertIntoSlot(stack, slot);
|
| 190 | }
|
| 191 |
|
| 192 | @Override
|
| 193 | public ItemStack quickMove(PlayerEntity player, int slot) {
|
| 194 | ItemStack itemStack = ItemStack.EMPTY;
|
| 195 | Slot slot2 = this.slots.get(slot);
|
| 196 | if (slot2 != null && slot2.hasStack()) {
|
| 197 | ItemStack itemStack2 = slot2.getStack();
|
| 198 | itemStack = itemStack2.copy();
|
| 199 | if (slot == this.outputSlot.id) {
|
| 200 | if (!this.insertItem(itemStack2, 4, 40, true)) {
|
| 201 | return ItemStack.EMPTY;
|
| 202 | }
|
| 203 |
|
| 204 | slot2.onQuickTransfer(itemStack2, itemStack);
|
| 205 | } else if (slot == this.inputSlot.id) {
|
| 206 | if (!this.insertItem(itemStack2, 3, 39, false)) {
|
| 207 | return ItemStack.EMPTY;
|
| 208 | }
|
| 209 | } else if (this.world.getRecipeManager().getFirstMatch(SewingRecipe.Type.INSTANCE, new SimpleInventory(itemStack2), this.world).isPresent()) {
|
| 210 | if (!this.insertItem(itemStack2, this.inputSlot.id, this.outputSlot.id, false)) {
|
| 211 | return ItemStack.EMPTY;
|
| 212 | }
|
| 213 | } else if (slot >= 3 && slot < 30) {
|
| 214 | if (!this.insertItem(itemStack2, 30, 39, false)) {
|
| 215 | return ItemStack.EMPTY;
|
| 216 | }
|
| 217 | } else if (slot >= 30 && slot < 39 && !this.insertItem(itemStack2, 3, 30, false)) {
|
| 218 | return ItemStack.EMPTY;
|
| 219 | }
|
| 220 |
|
| 221 | if (itemStack2.isEmpty()) {
|
| 222 | slot2.setStack(ItemStack.EMPTY);
|
| 223 | }
|
| 224 |
|
| 225 | slot2.markDirty();
|
| 226 | if (itemStack2.getCount() == itemStack.getCount()) {
|
| 227 | return ItemStack.EMPTY;
|
| 228 | }
|
| 229 |
|
| 230 | slot2.onTakeItem(player, itemStack2);
|
| 231 | this.sendContentUpdates();
|
| 232 | }
|
| 233 |
|
| 234 | return itemStack;
|
| 235 | }
|
| 236 |
|
| 237 | @Override
|
| 238 | public void onClosed(PlayerEntity player) {
|
| 239 | super.onClosed(player);
|
| 240 | this.output.removeStack(1);
|
| 241 | this.context.run((world, pos) -> this.dropInventory(player, this.input));
|
| 242 | }
|
| 243 |
|
| 244 | public Slot getDyeSlot() {
|
| 245 | return this.dyeSlot;
|
| 246 | }
|