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