package me.shedaniel.rei.client; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.RoughlyEnoughItemsPlugin; import me.shedaniel.rei.api.*; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.RecipeManager; import java.awt.*; import java.util.*; import java.util.List; import java.util.stream.Collectors; public class RecipeHelper { private final Map> recipeCategoryListMap = Maps.newHashMap(); private final List categories = Lists.newArrayList(); private final Map speedCraftAreaSupplierMap = Maps.newHashMap(); private final Map> speedCraftFunctionalMap = Maps.newHashMap(); private RecipeManager recipeManager; public static RecipeHelper getInstance() { return RoughlyEnoughItemsCore.getRecipeHelper(); } public List findCraftableByItems(List inventoryItems) { List craftables = new ArrayList<>(); for(List value : recipeCategoryListMap.values()) for(IRecipeDisplay recipeDisplay : value) { int slotsCraftable = 0; List> requiredInput = (List>) recipeDisplay.getRequiredItems(); for(List slot : requiredInput) { if (slot.isEmpty()) { slotsCraftable++; continue; } boolean slotDone = false; for(ItemStack possibleType : inventoryItems) { for(ItemStack slotPossible : slot) if (ItemStack.areItemsEqual(slotPossible, possibleType)) { slotsCraftable++; slotDone = true; break; } if (slotDone) break; } } if (slotsCraftable == recipeDisplay.getRequiredItems().size()) craftables.addAll((List) recipeDisplay.getOutput()); } return craftables.stream().distinct().collect(Collectors.toList()); } public void registerCategory(IRecipeCategory category) { categories.add(category); recipeCategoryListMap.put(category.getIdentifier(), Lists.newLinkedList()); } public void registerDisplay(Identifier categoryIdentifier, IRecipeDisplay display) { if (!recipeCategoryListMap.containsKey(categoryIdentifier)) return; recipeCategoryListMap.get(categoryIdentifier).add(display); } public Map> getRecipesFor(ItemStack stack) { Map> categoriesMap = new HashMap<>(); categories.forEach(f -> categoriesMap.put(f.getIdentifier(), Lists.newArrayList())); for(Map.Entry> entry : recipeCategoryListMap.entrySet()) { IRecipeCategory category = getCategory(entry.getKey()); for(IRecipeDisplay recipeDisplay : entry.getValue()) for(ItemStack outputStack : (List) recipeDisplay.getOutput()) if (category.checkTags() ? ItemStack.areItemStacksEqual(stack, outputStack) : ItemStack.areItemsEqual(stack, outputStack)) categoriesMap.get(recipeDisplay.getRecipeCategory()).add(recipeDisplay); } Map> recipeCategoryListMap = Maps.newLinkedHashMap(); categories.forEach(category -> { if (categoriesMap.containsKey(category.getIdentifier()) && !categoriesMap.get(category.getIdentifier()).isEmpty()) recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier())); }); return recipeCategoryListMap; } private IRecipeCategory getCategory(Identifier identifier) { return categories.stream().filter(category -> category.getIdentifier().equals(identifier)).findFirst().orElse(null); } public RecipeManager getRecipeManager() { return recipeManager; } public Map> getUsagesFor(ItemStack stack) { Map> categoriesMap = new HashMap<>(); categories.forEach(f -> categoriesMap.put(f.getIdentifier(), Lists.newArrayList())); for(Map.Entry> entry : recipeCategoryListMap.entrySet()) { IRecipeCategory category = getCategory(entry.getKey()); for(IRecipeDisplay recipeDisplay : entry.getValue()) { boolean found = false; for(List input : (List>) recipeDisplay.getInput()) { for(ItemStack itemStack : input) { if (category.checkTags() ? ItemStack.areItemStacksEqual(itemStack, stack) : ItemStack.areItemsEqual(itemStack, stack)) { categoriesMap.get(recipeDisplay.getRecipeCategory()).add(recipeDisplay); found = true; break; } } if (found) break; } } } Map> recipeCategoryListMap = Maps.newLinkedHashMap(); categories.forEach(category -> { if (categoriesMap.containsKey(category.getIdentifier()) && !categoriesMap.get(category.getIdentifier()).isEmpty()) recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier())); }); return recipeCategoryListMap; } public List getCategories() { return new LinkedList<>(categories); } public SpeedCraftAreaSupplier getSpeedCraftButtonArea(IRecipeCategory category) { if (!speedCraftAreaSupplierMap.containsKey(category.getIdentifier())) return bounds -> { return new Rectangle((int) bounds.getMaxX() - 16, (int) bounds.getMaxY() - 16, 10, 10); }; return speedCraftAreaSupplierMap.get(category.getIdentifier()); } public void registerSpeedCraftButtonArea(Identifier category, SpeedCraftAreaSupplier rectangle) { speedCraftAreaSupplierMap.put(category, rectangle); } public List getSpeedCraftFunctional(IRecipeCategory category) { if (speedCraftFunctionalMap.get(category.getIdentifier()) == null) return Lists.newArrayList(); return speedCraftFunctionalMap.get(category.getIdentifier()); } public void registerSpeedCraftFunctional(Identifier category, SpeedCraftFunctional functional) { List list = speedCraftFunctionalMap.containsKey(category) ? new LinkedList<>(speedCraftFunctionalMap.get(category)) : Lists.newLinkedList(); list.add(functional); speedCraftFunctionalMap.put(category, list); } @SuppressWarnings("deprecation") public void recipesLoaded(RecipeManager recipeManager) { this.recipeManager = recipeManager; this.recipeCategoryListMap.clear(); this.categories.clear(); this.speedCraftAreaSupplierMap.clear(); this.speedCraftFunctionalMap.clear(); List plugins = new LinkedList<>(RoughlyEnoughItemsPlugin.getPlugins()); plugins.sort((first, second) -> { return second.getPriority() - first.getPriority(); }); RoughlyEnoughItemsCore.LOGGER.info("Loading %d REI plugins: %s", plugins.size(), String.join(", ", plugins.stream().map(plugin -> { Identifier identifier = RoughlyEnoughItemsPlugin.getIdentifier(plugin); return identifier == null ? "NULL" : identifier.toString(); }).collect(Collectors.toList()))); Collections.reverse(plugins); RoughlyEnoughItemsCore.getItemRegisterer().getModifiableItemList().clear(); IPluginDisabler pluginDisabler = RoughlyEnoughItemsCore.getPluginDisabler(); plugins.forEach(plugin -> { Identifier location = RoughlyEnoughItemsPlugin.getIdentifier(plugin); Identifier identifier = location == null ? new Identifier("null") : location; if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_ITEMS)) plugin.registerItems(RoughlyEnoughItemsCore.getItemRegisterer()); if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_CATEGORIES)) plugin.registerPluginCategories(this); if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_RECIPE_DISPLAYS)) plugin.registerRecipeDisplays(this); if (pluginDisabler.isFunctionEnabled(identifier, PluginFunction.REGISTER_SPEED_CRAFT)) plugin.registerSpeedCraft(this); }); RoughlyEnoughItemsCore.LOGGER.info("Registered REI Categories: " + String.join(", ", categories.stream().map(category -> { return category.getCategoryName(); }).collect(Collectors.toList()))); } }