PageRenderTime 29ms CodeModel.GetById 10ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/common/buildcraft/lib/client/guide/parts/recipe/GuideCraftingFactory.java

https://github.com/2xsaiko/BuildCraft
Java | 178 lines | 155 code | 17 blank | 6 comment | 48 complexity | 18da221aeaad382237db7981b110238f MD5 | raw file
  1/* Copyright (c) 2017 SpaceToad and the BuildCraft team
  2 * 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
  3 * distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/ */
  4
  5package buildcraft.lib.client.guide.parts.recipe;
  6
  7import java.util.List;
  8
  9import javax.annotation.Nonnull;
 10
 11import net.minecraft.item.Item;
 12import net.minecraft.item.ItemStack;
 13import net.minecraft.item.crafting.IRecipe;
 14import net.minecraft.item.crafting.Ingredient;
 15import net.minecraft.nbt.NBTTagList;
 16import net.minecraft.util.NonNullList;
 17
 18import net.minecraftforge.common.crafting.IShapedRecipe;
 19import net.minecraftforge.fml.common.registry.ForgeRegistries;
 20import net.minecraftforge.fml.relauncher.Side;
 21import net.minecraftforge.fml.relauncher.SideOnly;
 22import net.minecraftforge.oredict.OreDictionary;
 23
 24import buildcraft.api.core.BCLog;
 25
 26import buildcraft.lib.client.guide.GuiGuide;
 27import buildcraft.lib.client.guide.parts.GuidePartFactory;
 28import buildcraft.lib.misc.StackUtil;
 29import buildcraft.lib.misc.data.NonNullMatrix;
 30
 31public class GuideCraftingFactory implements GuidePartFactory {
 32
 33    private final NonNullMatrix<Ingredient> input;
 34    private final @Nonnull ItemStack output;
 35    private final int hash;
 36
 37    public GuideCraftingFactory(Ingredient[][] input, ItemStack output) {
 38        this.input = new NonNullMatrix<>(input, Ingredient.EMPTY);
 39        this.output = StackUtil.asNonNull(output);
 40        NBTTagList hashNbt = new NBTTagList();
 41        for (Ingredient ingredient : this.input) {
 42            NBTTagList list = new NBTTagList();
 43            for (ItemStack stack : ingredient.getMatchingStacks()) {
 44                list.appendTag(stack.serializeNBT());
 45            }
 46            hashNbt.appendTag(list);
 47        }
 48        this.hash = hashNbt.hashCode();
 49    }
 50
 51    public static GuidePartFactory create(@Nonnull ItemStack stack) {
 52        for (IRecipe recipe : ForgeRegistries.RECIPES) {
 53            if (OreDictionary.itemMatches(stack, StackUtil.asNonNull(recipe.getRecipeOutput()), false)) {
 54                GuidePartFactory val = getFactory(recipe);
 55                if (val != null) {
 56                    return val;
 57                } else {
 58                    BCLog.logger.warn("[lib.guide.crafting] Found a matching recipe, but of an unknown "
 59                        + recipe.getClass() + " for " + stack.getDisplayName());
 60                }
 61            }
 62        }
 63        return null;
 64    }
 65
 66    public static GuidePartFactory getFactory(IRecipe recipe) {
 67        ItemStack output = recipe.getRecipeOutput();
 68        NonNullList<Ingredient> input = recipe.getIngredients();
 69        if (input == null || input.isEmpty() || output.isEmpty()) {
 70            return null;
 71        }
 72        Ingredient[][] matrix = new Ingredient[3][3];
 73        int maxX = recipe instanceof IShapedRecipe ? ((IShapedRecipe) recipe).getRecipeWidth() : 3;
 74        int maxY = recipe instanceof IShapedRecipe ? ((IShapedRecipe) recipe).getRecipeHeight() : 3;
 75        int offsetX = maxX == 1 ? 1 : 0;
 76        int offsetY = maxY == 1 ? 1 : 0;
 77        for (int y = 0; y < 3; y++) {
 78            for (int x = 0; x < 3; x++) {
 79                if (x < offsetX || y < offsetY) {
 80                    matrix[x][y] = Ingredient.EMPTY;
 81                    continue;
 82                }
 83                int i = x - offsetX + (y - offsetY) * maxX;
 84                if (i >= input.size() || x - offsetX >= maxX) {
 85                    matrix[x][y] = Ingredient.EMPTY;
 86                } else {
 87                    matrix[x][y] = input.get(i);
 88                }
 89            }
 90        }
 91        return new GuideCraftingFactory(matrix, output);
 92    }
 93
 94    @Nonnull
 95    private static ItemStack oreConvert(Object object) {
 96        if (object == null) {
 97            return StackUtil.EMPTY;
 98        }
 99        if (object instanceof ItemStack) {
100            return ((ItemStack) object).copy();
101        }
102        if (object instanceof String) {
103            NonNullList<ItemStack> stacks = OreDictionary.getOres((String) object);
104            // It will be sorted out below
105            object = stacks;
106        }
107        if (object instanceof List<?>) {
108            List<?> list = (List<?>) object;
109            if (list.isEmpty()) {
110                return StackUtil.EMPTY;
111            }
112            Object first = list.get(0);
113            if (first == null) {
114                return StackUtil.EMPTY;
115            }
116            if (first instanceof ItemStack) {
117                ItemStack best = (ItemStack) first;
118                for (Object obj : list) {
119                    if (!(obj instanceof ItemStack)) {
120                        continue;
121                    }
122                    ItemStack stack = (ItemStack) obj;
123                    // The lower the ID of an item, the closer it is to minecraft. Hmmm.
124                    if (Item.getIdFromItem(stack.getItem()) < Item.getIdFromItem(best.getItem())) {
125                        best = stack;
126                    }
127                }
128                return best.copy();
129            }
130            BCLog.logger.warn("Found a list with unknown contents! " + first.getClass());
131        }
132        BCLog.logger.warn("Found an ore with an unknown " + object.getClass());
133        return StackUtil.EMPTY;
134    }
135
136    public static GuidePartFactory create(Item output) {
137        return create(new ItemStack(output));
138    }
139
140    @SideOnly(Side.CLIENT)
141    @Override
142    public GuideCrafting createNew(GuiGuide gui) {
143        return new GuideCrafting(gui, input, output);
144    }
145
146    @Override
147    public int hashCode() {
148        return hash;
149    }
150
151    @Override
152    public boolean equals(Object obj) {
153        if (obj == this) return true;
154        if (obj == null) return false;
155        if (obj.getClass() != getClass()) return false;
156        GuideCraftingFactory other = (GuideCraftingFactory) obj;
157        // Shortcut out of this full itemstack comparison as its really expensive
158        if (hash != other.hash) return false;
159        if (input.getWidth() != other.input.getWidth() || input.getHeight() != other.input.getHeight()) return false;
160        NBTTagList nbtThis = new NBTTagList();
161        for (Ingredient ingredient : this.input) {
162            NBTTagList list = new NBTTagList();
163            for (ItemStack stack : ingredient.getMatchingStacks()) {
164                list.appendTag(stack.serializeNBT());
165            }
166            nbtThis.appendTag(list);
167        }
168        NBTTagList nbtThat = new NBTTagList();
169        for (Ingredient ingredient : other.input) {
170            NBTTagList list = new NBTTagList();
171            for (ItemStack stack : ingredient.getMatchingStacks()) {
172                list.appendTag(stack.serializeNBT());
173            }
174            nbtThat.appendTag(list);
175        }
176        return nbtThis.equals(nbtThat);
177    }
178}