PageRenderTime 29ms CodeModel.GetById 11ms app.highlight 14ms RepoModel.GetById 2ms app.codeStats 0ms

/common/buildcraft/lib/list/ListHandler.java

https://github.com/2xsaiko/BuildCraft
Java | 290 lines | 245 code | 35 blank | 10 comment | 78 complexity | 2e3babd1ef527befd1cd4ce300cf122b MD5 | raw file
  1/*
  2 * Copyright (c) 2017 SpaceToad and the BuildCraft team
  3 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
  4 * distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/
  5 */
  6
  7package buildcraft.lib.list;
  8
  9import java.util.ArrayList;
 10import java.util.Collections;
 11import java.util.List;
 12import javax.annotation.Nonnull;
 13
 14import net.minecraft.creativetab.CreativeTabs;
 15import net.minecraft.item.Item;
 16import net.minecraft.item.ItemStack;
 17import net.minecraft.nbt.NBTTagCompound;
 18import net.minecraft.nbt.NBTTagList;
 19import net.minecraft.util.NonNullList;
 20
 21import net.minecraftforge.fml.common.registry.ForgeRegistries;
 22import net.minecraftforge.fml.relauncher.Side;
 23import net.minecraftforge.fml.relauncher.SideOnly;
 24
 25import buildcraft.api.lists.ListMatchHandler;
 26import buildcraft.api.lists.ListRegistry;
 27
 28import buildcraft.lib.misc.NBTUtilBC;
 29import buildcraft.lib.misc.StackUtil;
 30
 31public final class ListHandler {
 32    public static final int WIDTH = 9;
 33    public static final int HEIGHT = 2;
 34
 35    public static class Line {
 36        public final NonNullList<ItemStack> stacks;
 37        public boolean precise, byType, byMaterial;
 38
 39        public Line() {
 40            stacks = NonNullList.withSize(WIDTH, StackUtil.EMPTY);
 41        }
 42
 43        /** Checks to see if this line is completely blank, and no data would be lost if this line was not saved. */
 44        public boolean isDefault() {
 45            if (precise || byType || byMaterial) return false;
 46            return !hasItems();
 47        }
 48
 49        /** Checks to see if this line has any items */
 50        public boolean hasItems() {
 51            for (ItemStack stack : stacks) {
 52                if (!stack.isEmpty()) return true;
 53            }
 54            return false;
 55        }
 56
 57        public boolean isOneStackMode() {
 58            return byType || byMaterial;
 59        }
 60
 61        public boolean getOption(int id) {
 62            return id == 0 ? precise : (id == 1 ? byType : byMaterial);
 63        }
 64
 65        public void toggleOption(int id) {
 66            if (!byType && !byMaterial && (id == 1 || id == 2)) {
 67                for (int i = 1; i < stacks.size(); i++) {
 68                    stacks.set(i, StackUtil.EMPTY);
 69                }
 70            }
 71            switch (id) {
 72                case 0:
 73                    precise = !precise;
 74                    break;
 75                case 1:
 76                    byType = !byType;
 77                    break;
 78                case 2:
 79                    byMaterial = !byMaterial;
 80                    break;
 81            }
 82        }
 83
 84        public boolean matches(@Nonnull ItemStack target) {
 85            if (byType || byMaterial) {
 86                if (stacks.get(0).isEmpty()) {
 87                    return false;
 88                }
 89
 90                List<ListMatchHandler> handlers = ListRegistry.getHandlers();
 91                ListMatchHandler.Type type = getSortingType();
 92                for (ListMatchHandler h : handlers) {
 93                    if (h.matches(type, stacks.get(0), target, precise)) {
 94                        return true;
 95                    }
 96                }
 97            } else {
 98                for (ItemStack s : stacks) {
 99                    if (s != null && StackUtil.isMatchingItem(s, target, true, precise)) {
100                        // If precise, re-check damage
101                        if (!precise || s.getItemDamage() == target.getItemDamage()) {
102                            return true;
103                        }
104                    }
105                }
106            }
107            return false;
108        }
109
110        public ListMatchHandler.Type getSortingType() {
111            return byType ? (byMaterial ? ListMatchHandler.Type.CLASS : ListMatchHandler.Type.TYPE) : ListMatchHandler.Type.MATERIAL;
112        }
113
114        public static Line fromNBT(NBTTagCompound data) {
115            Line line = new Line();
116
117            if (data != null && data.hasKey("st")) {
118                NBTTagList l = data.getTagList("st", 10);
119                for (int i = 0; i < l.tagCount(); i++) {
120                    line.stacks.set(i, new ItemStack(l.getCompoundTagAt(i)));
121                }
122
123                line.precise = data.getBoolean("Fp");
124                line.byType = data.getBoolean("Ft");
125                line.byMaterial = data.getBoolean("Fm");
126            }
127
128            return line;
129        }
130
131        public NBTTagCompound toNBT() {
132            NBTTagCompound data = new NBTTagCompound();
133            NBTTagList stackList = new NBTTagList();
134            for (ItemStack stack1 : stacks) {
135                NBTTagCompound stack = new NBTTagCompound();
136                if (stack1 != null) {
137                    stack1.writeToNBT(stack);
138                }
139                stackList.appendTag(stack);
140            }
141            data.setTag("st", stackList);
142            data.setBoolean("Fp", precise);
143            data.setBoolean("Ft", byType);
144            data.setBoolean("Fm", byMaterial);
145            return data;
146        }
147
148        public void setStack(int slotIndex, @Nonnull ItemStack stack) {
149            if (slotIndex == 0 || (!byType && !byMaterial)) {
150                if (stack.isEmpty()) {
151                    stacks.set(slotIndex, StackUtil.EMPTY);
152                } else {
153                    stack = stack.copy();
154                    stack.setCount(1);
155                    stacks.set(slotIndex, stack);
156                }
157            }
158        }
159
160        @Nonnull
161        public ItemStack getStack(int i) {
162            if (i < 0 || i >= stacks.size()) {
163                return StackUtil.EMPTY;
164            } else {
165                return stacks.get(i);
166            }
167        }
168
169        @SideOnly(Side.CLIENT)
170        public NonNullList<ItemStack> getExamples() {
171            ItemStack firstStack = stacks.get(0);
172            if (firstStack.isEmpty()) {
173                return NonNullList.withSize(0, StackUtil.EMPTY);
174            }
175            NonNullList<ItemStack> stackList = NonNullList.create();
176            List<ListMatchHandler> handlers = ListRegistry.getHandlers();
177            List<ListMatchHandler> handlersCustom = new ArrayList<>();
178            ListMatchHandler.Type type = getSortingType();
179            for (ListMatchHandler h : handlers) {
180                if (h.isValidSource(type, firstStack)) {
181                    NonNullList<ItemStack> examples = h.getClientExamples(type, firstStack);
182                    if (examples != null) {
183                        stackList.addAll(examples);
184                    } else {
185                        handlersCustom.add(h);
186                    }
187                }
188            }
189            if (handlersCustom.size() > 0) {
190                for (Item i : ForgeRegistries.ITEMS) {
191                    NonNullList<ItemStack> examples = NonNullList.create();
192                    i.getSubItems(CreativeTabs.MISC, examples);
193                    for (ItemStack s : examples) {
194                        for (ListMatchHandler mh : handlersCustom) {
195                            if (mh.matches(type, firstStack, s, false)) {
196                                stackList.add(s);
197                                break;
198                            }
199                        }
200                    }
201                }
202            }
203            Collections.shuffle(stackList);
204            return stackList;
205        }
206    }
207
208    private ListHandler() {
209
210    }
211
212    public static boolean hasItems(@Nonnull ItemStack stack) {
213        if (!stack.hasTagCompound()) return false;
214        for (Line l : getLines(stack)) {
215            if (l.hasItems()) return true;
216        }
217        return false;
218    }
219
220    public static boolean isDefault(@Nonnull ItemStack stack) {
221        if (!stack.hasTagCompound()) return true;
222        for (Line l : getLines(stack)) {
223            if (!l.isDefault()) return false;
224        }
225        return true;
226    }
227
228    public static Line[] getLines(@Nonnull ItemStack item) {
229        NBTTagCompound data = NBTUtilBC.getItemData(item);
230        if (data.hasKey("written") && data.hasKey("lines")) {
231            NBTTagList list = data.getTagList("lines", 10);
232            Line[] lines = new Line[list.tagCount()];
233            for (int i = 0; i < lines.length; i++) {
234                lines[i] = Line.fromNBT(list.getCompoundTagAt(i));
235            }
236            return lines;
237        } else {
238            Line[] lines = new Line[HEIGHT];
239            for (int i = 0; i < lines.length; i++) {
240                lines[i] = new Line();
241            }
242            return lines;
243        }
244    }
245
246    public static void saveLines(@Nonnull ItemStack stackList, Line[] lines) {
247        boolean hasLine = false;
248
249        for (Line l : lines) {
250            if (!l.isDefault()) {
251                hasLine = true;
252                break;
253            }
254        }
255
256        if (hasLine) {
257            NBTTagCompound data = NBTUtilBC.getItemData(stackList);
258            data.setBoolean("written", true);
259            NBTTagList lineList = new NBTTagList();
260            for (Line saving : lines) {
261                lineList.appendTag(saving.toNBT());
262            }
263            data.setTag("lines", lineList);
264        } else if (stackList.hasTagCompound()) {
265            NBTTagCompound data = NBTUtilBC.getItemData(stackList);
266            // No non-default lines, we can remove the old NBT data
267            data.removeTag("written");
268            data.removeTag("lines");
269            if (data.hasNoTags()) {
270                // We can safely remove the
271                stackList.setTagCompound(null);
272            }
273        }
274    }
275
276    public static boolean matches(@Nonnull ItemStack stackList, @Nonnull ItemStack item) {
277        NBTTagCompound data = NBTUtilBC.getItemData(stackList);
278        if (data.hasKey("written") && data.hasKey("lines")) {
279            NBTTagList list = data.getTagList("lines", 10);
280            for (int i = 0; i < list.tagCount(); i++) {
281                Line line = Line.fromNBT(list.getCompoundTagAt(i));
282                if (line.matches(item)) {
283                    return true;
284                }
285            }
286        }
287
288        return false;
289    }
290}