Files
NotEnoughItems/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java
T
slprimeandgithub-actions[bot] a685efb3b7 Recipe Group Optimization (#1054)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-28 00:19:29 +03:00

209 lines
7.5 KiB
Java

package codechicken.nei.recipe;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.item.ItemStack;
import codechicken.lib.gui.GuiDraw;
import codechicken.nei.FavoriteRecipes;
import codechicken.nei.ItemPanels;
import codechicken.nei.ItemsGrid.ItemsGridSlot;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
import codechicken.nei.bookmark.BookmarksGridSlot;
import codechicken.nei.recipe.Recipe.RecipeId;
public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
public static ArrayList<ICraftingHandler> craftinghandlers = new ArrayList<>();
public static ArrayList<ICraftingHandler> serialCraftingHandlers = new ArrayList<>();
private static Set<String> existingHandlers = new HashSet<>();
public static boolean openRecipeGui(String outputId, Object... results) {
return createRecipeGui(outputId, true, results) != null;
}
public static GuiRecipe<?> createRecipeGui(String outputId, boolean open, Object... results) {
final Minecraft mc = NEIClientUtils.mc();
final RecipeId recipeId;
List<ItemStack> pinnedIngredients = null;
for (int i = 0; i < results.length; i++) {
if (results[i] instanceof ItemStack stack) {
results[i] = StackInfo.normalizeRecipeQueryStack(stack.copy());
}
}
if ("item".equals(outputId)) {
recipeId = getRecipeId(mc.currentScreen, (ItemStack) results[0]);
} else if ("recipeId".equals(outputId)) {
recipeId = (RecipeId) results[1];
// optional third argument: ingredients to pin the found recipe with
if (results.length > 2 && results[2] instanceof List<?>list) {
pinnedIngredients = extractIngredients(list);
}
} else {
recipeId = getCurrentRecipeId(mc.currentScreen);
}
final ArrayList<ICraftingHandler> handlers = getCraftingHandlers(outputId, results);
if (!handlers.isEmpty()) {
final GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers);
if (open) {
if (NEIClientConfig.showHistoryPanelWidget() && "item".equals(outputId)
&& results[0] instanceof ItemStack stack) {
ItemPanels.itemPanel.historyPanel.addItem(stack);
}
mc.displayGuiScreen(gui);
}
gui.openTargetRecipe(recipeId, pinnedIngredients);
return gui;
}
return null;
}
private static List<ItemStack> extractIngredients(List<?> list) {
final List<ItemStack> ingredients = new ArrayList<>(list.size());
for (Object item : list) {
if (item instanceof ItemStack stack) {
ingredients.add(stack);
}
}
return ingredients;
}
public static ArrayList<ICraftingHandler> getCraftingHandlers(String outputId, Object... results) {
ArrayList<ICraftingHandler> craftinghandlers = GuiCraftingRecipe.craftinghandlers;
ArrayList<ICraftingHandler> serialCraftingHandlers = GuiCraftingRecipe.serialCraftingHandlers;
UnaryOperator<ICraftingHandler> recipeHandlerFunction;
if ("all".equals(outputId)) {
recipeHandlerFunction = GuiCraftingRecipe::buildAllRecipesHandler;
} else if ("recipeId".equals(outputId)) {
ItemStack stack = (ItemStack) results[0];
RecipeId recipeId = (RecipeId) results[1];
craftinghandlers = filterByHandlerName(craftinghandlers, recipeId.getHandlerName());
serialCraftingHandlers = filterByHandlerName(serialCraftingHandlers, recipeId.getHandlerName());
recipeHandlerFunction = h -> h.getRecipeHandler("item", stack);
} else {
recipeHandlerFunction = h -> h.getRecipeHandler(outputId, results);
}
final RecipeHandlerQuery<ICraftingHandler> recipeQuery = new RecipeHandlerQuery<>(
recipeHandlerFunction,
craftinghandlers,
serialCraftingHandlers,
"Error while looking up crafting recipe",
"outputId: " + outputId,
"results: " + Arrays.toString(results));
return recipeQuery.runWithProfiling(NEIClientUtils.translate("recipe.concurrent.crafting"));
}
private static ICraftingHandler buildAllRecipesHandler(ICraftingHandler handler) {
if (handler instanceof TemplateRecipeHandler templateHandler) {
return templateHandler.getAllRecipeHandler();
}
return handler.getRecipeHandler("all");
}
private static ArrayList<ICraftingHandler> filterByHandlerName(ArrayList<ICraftingHandler> craftinghandlers,
String handlerName) {
return craftinghandlers.stream().filter(h -> getHandlerName(h).equals(handlerName))
.collect(Collectors.toCollection(ArrayList::new));
}
private static String getHandlerName(ICraftingHandler handler) {
return GuiRecipeTab.getHandlerInfo(handler).getHandlerName();
}
public static RecipeId getRecipeId(GuiScreen gui, ItemStack stackover) {
if (gui instanceof GuiRecipe<?>guiRecipe) {
final Recipe focusedRecipe = guiRecipe.getFocusedRecipe();
if (focusedRecipe != null) {
return focusedRecipe.getRecipeId();
}
}
final Point mouseover = GuiDraw.getMousePosition();
final BookmarksGridSlot panelSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseover.x, mouseover.y);
if (panelSlot != null) {
return panelSlot.getType() == BookmarkItemType.INGREDIENT || panelSlot.getRecipeId() == null
? FavoriteRecipes.getFavorite(stackover)
: panelSlot.getRecipeId();
}
ItemsGridSlot itemSlot = ItemPanels.itemPanel.getSlotMouseOver(mouseover.x, mouseover.y);
if (itemSlot == null) {
itemSlot = ItemPanels.itemPanel.historyPanel.getSlotMouseOver(mouseover.x, mouseover.y);
}
if (itemSlot == null) {
itemSlot = ItemPanels.itemPanel.craftablesPanel.getSlotMouseOver(mouseover.x, mouseover.y);
}
if (itemSlot != null) {
return itemSlot.getRecipeId();
}
return null;
}
private GuiCraftingRecipe(ArrayList<ICraftingHandler> handlers) {
super(NEIClientUtils.mc().currentScreen);
this.currenthandlers = handlers;
}
public static void registerRecipeHandler(ICraftingHandler handler) {
final String handlerId = handler.getHandlerId();
if (existingHandlers.contains(handlerId)) {
return;
}
synchronized (existingHandlers) {
existingHandlers.add(handlerId);
}
if (NEIClientConfig.serialHandlers.contains(handlerId)) {
synchronized (serialCraftingHandlers) {
serialCraftingHandlers.add(handler);
}
} else {
synchronized (craftinghandlers) {
craftinghandlers.add(handler);
}
}
}
@Override
public ArrayList<ICraftingHandler> getCurrentRecipeHandlers() {
return currenthandlers;
}
}