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 | }
|