package codechicken.nei.recipe; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.function.Function; import java.util.stream.Collectors; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import codechicken.nei.ItemList; import codechicken.nei.NEIClientConfig; public class RecipeHandlerQuery { private final Function recipeHandlerFunction; private final List recipeHandlers; private final List serialRecipeHandlers; private final String[] errorMessage; private boolean error = false; public RecipeHandlerQuery(Function recipeHandlerFunction, List recipeHandlers, List serialRecipeHandlers, String... errorMessage) { this.recipeHandlerFunction = recipeHandlerFunction; this.recipeHandlers = recipeHandlers; this.serialRecipeHandlers = serialRecipeHandlers; this.errorMessage = errorMessage; } public ArrayList runWithProfiling(String profilerSection) { return ProfilerRecipeHandler.recipeProfiler.start(profilerSection, () -> { try { ArrayList handlers = getRecipeHandlersParallel(); if (error) { displayRecipeLookupError(); } return handlers; } catch (InterruptedException | ExecutionException e) { printLog(e); displayRecipeLookupError(); return new ArrayList<>(0); } }); } private ArrayList getRecipeHandlersParallel() throws InterruptedException, ExecutionException { // Pre-find the fuels so we're not fighting over it if (NEIClientConfig.getBooleanSetting("findFuelsParallel")) { FuelRecipeHandler.findFuelsOnceParallel(); } else { FuelRecipeHandler.findFuelsOnce(); } ArrayList handlers = getSerialHandlersWithRecipes(); handlers.addAll(getHandlersWithRecipes()); handlers.sort(NEIClientConfig.HANDLER_COMPARATOR); return handlers; } private ArrayList getSerialHandlersWithRecipes() { return serialRecipeHandlers.stream() .map(handler -> ProfilerRecipeHandler.recipeProfiler.profile(handler, () -> { try { return isHidden(handler) ? null : recipeHandlerFunction.apply(handler); } catch (Throwable t) { printLog(t); error = true; return null; } })) .filter( h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1) .collect(Collectors.toCollection(ArrayList::new)); } private ArrayList getHandlersWithRecipes() throws InterruptedException, ExecutionException { return ItemList.forkJoinPool.submit( () -> recipeHandlers.parallelStream() .map(handler -> ProfilerRecipeHandler.recipeProfiler.profile(handler, () -> { try { return isHidden(handler) ? null : recipeHandlerFunction.apply(handler); } catch (Throwable t) { printLog(t); error = true; return null; } })) .filter( h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1) .collect(Collectors.toCollection(ArrayList::new))) .get(); } private boolean isHidden(T handler) { final String handlerName = handler.getHandlerId(); final String handlerId = handler.getOverlayIdentifier(); return NEIClientConfig.hiddenHandlers.stream().anyMatch(h -> h.equals(handlerId) || h.equals(handlerName)); } private void printLog(Throwable t) { for (String message : errorMessage) { NEIClientConfig.logger.error(message); } t.printStackTrace(); } private void displayRecipeLookupError() { EntityPlayer player = Minecraft.getMinecraft().thePlayer; if (player != null) { IChatComponent chat = new ChatComponentTranslation("nei.chat.recipe.error"); chat.getChatStyle().setColor(EnumChatFormatting.RED); player.addChatComponentMessage(chat); } } }