diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23449a2b..37f78a6a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index d66754a7..d9c3d95b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.19' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.21' } diff --git a/src/main/java/codechicken/nei/FavoriteRecipes.java b/src/main/java/codechicken/nei/FavoriteRecipes.java index 6dd517aa..f41d82ea 100644 --- a/src/main/java/codechicken/nei/FavoriteRecipes.java +++ b/src/main/java/codechicken/nei/FavoriteRecipes.java @@ -135,6 +135,7 @@ public class FavoriteRecipes { }; + public static final String FAVORITE_ITEM = "FavoriteItem"; private static final FavoriteStorage manualFavorites = new FavoriteStorage(); private static FavoriteStorage autoFavorites = new FavoriteStorage(); private static File favoriteFile; @@ -224,7 +225,7 @@ public class FavoriteRecipes { continue; } - if (RecipeHandlerRef.of(recipeId) != null) { + if (FAVORITE_ITEM.equals(recipeId.getHandleName()) || RecipeHandlerRef.of(recipeId) != null) { manualFavorites.add(stack, recipeId); } else { hasErrors = true; @@ -256,6 +257,20 @@ public class FavoriteRecipes { loadAutoGeneratedRecipes(); } + public static RecipeId getGeneratedFavorite(ItemStack stack) { + if (NEIClientConfig.favoritesEnabled() && stack != null) { + return autoFavorites.getRecipeId(stack); + } + return null; + } + + public static ItemStack getGeneratedFavorite(RecipeId recipeId) { + if (NEIClientConfig.favoritesEnabled() && recipeId != null) { + return autoFavorites.getItemStack(recipeId); + } + return null; + } + public static RecipeId getManualFavorite(ItemStack stack) { if (NEIClientConfig.favoritesEnabled() && stack != null) { return manualFavorites.getRecipeId(stack); diff --git a/src/main/java/codechicken/nei/ItemList.java b/src/main/java/codechicken/nei/ItemList.java index f2594d2f..dea01fe4 100644 --- a/src/main/java/codechicken/nei/ItemList.java +++ b/src/main/java/codechicken/nei/ItemList.java @@ -31,6 +31,7 @@ import codechicken.nei.api.ItemFilter; import codechicken.nei.api.ItemFilter.ItemFilterProvider; import codechicken.nei.api.ItemInfo; import codechicken.nei.recipe.InformationHandler; +import codechicken.nei.recipe.RecipeHandlerRef; import codechicken.nei.search.TooltipFilter; import codechicken.nei.util.ItemUntranslator; import cpw.mods.fml.common.FMLLog; @@ -432,7 +433,8 @@ public class ItemList { loadFinished = true; - FavoriteRecipes.loadAutoGeneratedRecipes(); + RecipeHandlerRef.clearCache(); + FavoriteRecipes.reload(); SubsetWidget.updateHiddenItems(); ItemPanels.bookmarkPanel.load(); updateFilter.restart(); diff --git a/src/main/java/codechicken/nei/NEIClientConfig.java b/src/main/java/codechicken/nei/NEIClientConfig.java index 39e8d6e8..655c99d5 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -827,6 +827,7 @@ public class NEIClientConfig { API.addHashBind("gui.search", Keyboard.KEY_F); API.addKeyBind("gui.bookmark", Keyboard.KEY_A); API.addHashBind("gui.favorite", Keyboard.KEY_F + NEIClientUtils.SHIFT_HASH); + API.addKeyBind("gui.favorite_item", Keyboard.KEY_F); API.addHashBind("gui.remove_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH); API.addKeyBind("gui.bookmark_pull_items", Keyboard.KEY_V); API.addKeyBind("gui.overlay", Keyboard.KEY_S); @@ -1009,7 +1010,6 @@ public class NEIClientConfig { SubsetWidget.loadHidden(); CollapsibleItems.load(); ItemSorter.loadConfig(); - FavoriteRecipes.load(); // Set pluginNEIConfigLoaded here before posting the NEIConfigsLoadedEvent. This used to be the // other way around, but apparently if your modpack includes 800 mods the event poster might not diff --git a/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java b/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java index e5c06038..742814a1 100644 --- a/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java +++ b/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java @@ -205,29 +205,47 @@ public class GuiFavoriteButton extends GuiRecipeButton { if (stack == null) { stack = ingr.getItemStack(); - RecipeId recipeId = FavoriteRecipes.getFavorite(stack); + RecipeId recipeId = FavoriteRecipes.getManualFavorite(stack); if (recipeId == null) { for (ItemStack permStack : permutations) { - if ((recipeId = FavoriteRecipes.getFavorite(permStack)) != null) { + if ((recipeId = FavoriteRecipes.getManualFavorite(permStack)) != null) { stack = permStack; break; } } } - Recipe recipe = Recipe.of(recipeId); + if (recipeId == null) { + recipeId = FavoriteRecipes.getGeneratedFavorite(stack); + } - if (recipe == null) { - stack = null; - } else { - items.add(stack); - - if (depth >= 0) { - result.add(recipe); - localLoop.add(recipe); + if (recipeId == null) { + for (ItemStack permStack : permutations) { + if ((recipeId = FavoriteRecipes.getGeneratedFavorite(permStack)) != null) { + stack = permStack; + break; + } } } + + if (recipeId != null && FavoriteRecipes.FAVORITE_ITEM.contains(recipeId.getHandleName())) { + items.add(stack); + } else { + Recipe recipe = Recipe.of(recipeId); + + if (recipe == null) { + stack = null; + } else { + items.add(stack); + + if (depth >= 0) { + result.add(recipe); + localLoop.add(recipe); + } + } + } + } if (stack != null) { diff --git a/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java b/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java index 86ad3ace..320c357a 100644 --- a/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java +++ b/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java @@ -13,6 +13,7 @@ import java.util.stream.Stream; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; @@ -31,12 +32,14 @@ import codechicken.nei.api.IGuiContainerOverlay; import codechicken.nei.api.ShortcutInputHandler; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.GuiRecipeButton.UpdateRecipeButtonsEvent; +import codechicken.nei.recipe.Recipe.RecipeId; import codechicken.nei.util.NEIMouseUtils; public class NEIRecipeWidget extends Widget { protected AcceptsFollowingTooltipLineHandler acceptsFollowingTooltipLineHandler; - protected final WeakHashMap> permutations = new WeakHashMap<>(); + protected final Map favoriteIndexes = new WeakHashMap<>(); + protected final Map> permutations = new WeakHashMap<>(); protected int favoriteRevision = -1; protected boolean update = true; protected int cycleticks = 0; @@ -188,6 +191,11 @@ public class NEIRecipeWidget extends Widget { GuiContainerManager.enableMatrixStackLogging(); for (PositionedStack pStack : getInputs()) { + + if (!this.permutations.containsKey(pStack)) { + updatePermutationsFor(pStack); + } + GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item); if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) { @@ -196,6 +204,11 @@ public class NEIRecipeWidget extends Widget { } for (PositionedStack pStack : getCatalysts()) { + + if (!this.permutations.containsKey(pStack)) { + updatePermutationsFor(pStack); + } + GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item); if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) { @@ -244,6 +257,38 @@ public class NEIRecipeWidget extends Widget { @Override public boolean handleKeyPress(int keyID, char keyChar) { + + if (NEIClientConfig.favoritesEnabled() && NEIClientUtils.shiftKey() + && NEIClientConfig.isKeyHashDown("gui.favorite_item")) { + final Point mouse = GuiDraw.getMousePosition(); + final int yShift = this.handlerInfo.getYShift(); + PositionedStack pStackOver = null; + + for (PositionedStack pStack : getInputs()) { + if (pStack.contains(mouse.x - this.x, mouse.y - this.y - yShift)) { + pStackOver = pStack; + break; + } + } + + if (pStackOver != null) { + + if (FavoriteRecipes.containsManual(pStackOver.item)) { + FavoriteRecipes.setFavorite(pStackOver.item, null); + } else { + FavoriteRecipes.setFavorite( + pStackOver.item, + RecipeId.of( + pStackOver.item, + FavoriteRecipes.FAVORITE_ITEM, + Arrays.asList(new ItemStack(Blocks.fire, 1), pStackOver.item))); + } + + return true; + } + + } + return false; } @@ -342,10 +387,11 @@ public class NEIRecipeWidget extends Widget { if (hovered == null || hovered.items.length <= 1) { this.acceptsFollowingTooltipLineHandler = null; - } else if (this.acceptsFollowingTooltipLineHandler == null - || this.acceptsFollowingTooltipLineHandler.tooltipGUID != hovered) { + } else if ((this.acceptsFollowingTooltipLineHandler == null + || this.acceptsFollowingTooltipLineHandler.tooltipGUID != hovered) + && this.permutations.getOrDefault(hovered, Collections.emptyList()).size() > 1) { this.acceptsFollowingTooltipLineHandler = AcceptsFollowingTooltipLineHandler - .of(hovered, hovered.getFilteredPermutations(), hovered.item); + .of(hovered, this.permutations.get(hovered), hovered.item); } } else if (this.acceptsFollowingTooltipLineHandler != null) { this.acceptsFollowingTooltipLineHandler = null; @@ -360,6 +406,7 @@ public class NEIRecipeWidget extends Widget { @Override public Map handleHotkeys(int mouseX, int mouseY, Map hotkeys) { + final int yShift = this.handlerInfo.getYShift(); final Map buttonHotkeys = forEachButtons( button -> button.contains(mouseX, mouseY) ? button.handleHotkeys(mouseX, mouseY, hotkeys) : null, hotkeys); @@ -372,6 +419,14 @@ public class NEIRecipeWidget extends Widget { NEIClientUtils.translate("recipe.accepts.scroll")); } + if (getInputs().stream().anyMatch( + pStack -> this.permutations.getOrDefault(pStack, Collections.emptyList()).size() > 1 + && pStack.contains(mouseX - this.x, mouseY - this.y - yShift))) { + hotkeys.put( + NEIClientConfig.getKeyName("gui.favorite_item", NEIClientUtils.SHIFT_HASH), + NEIClientUtils.translate("recipe.favorite.toggle")); + } + return buttonHotkeys; } @@ -396,8 +451,8 @@ public class NEIRecipeWidget extends Widget { if (!NEIClientUtils.shiftKey()) return false; final PositionedStack overStack = getPositionedStackMouseOver(mx, my); - if (overStack != null && overStack.items.length > 1) { - final List items = overStack.getFilteredPermutations(); + if (overStack != null && this.permutations.getOrDefault(overStack, Collections.emptyList()).size() > 1) { + final List items = this.permutations.get(overStack); final int stackIndex = indexOf(items, overStack.item); final ItemStack stack = items.get((items.size() - scroll + stackIndex) % items.size()); @@ -506,29 +561,21 @@ public class NEIRecipeWidget extends Widget { } protected void updatePermutations() { + final int rev = FavoriteRecipes.getRevision(); - if (this.favoriteRevision != FavoriteRecipes.getRevision()) { - this.favoriteRevision = FavoriteRecipes.getRevision(); + if (this.favoriteRevision != rev) { + this.favoriteRevision = rev; this.acceptsFollowingTooltipLineHandler = null; + this.favoriteIndexes.clear(); this.permutations.clear(); } for (PositionedStack pStack : getInputs()) { - if (pStack.items.length > 1) { - final List permutations = this.permutations.computeIfAbsent( - pStack, - stack -> stack.getFilteredPermutations(FavoriteRecipes::containsManual)); - pStack.setPermutationToRender(permutations.get(this.lastcycle % permutations.size())); - } + updatePermutationsFor(pStack); } for (PositionedStack pStack : getCatalysts()) { - if (pStack.items.length > 1) { - final List permutations = this.permutations.computeIfAbsent( - pStack, - stack -> stack.getFilteredPermutations(FavoriteRecipes::containsManual)); - pStack.setPermutationToRender(permutations.get(this.lastcycle % permutations.size())); - } + updatePermutationsFor(pStack); } if (this.acceptsFollowingTooltipLineHandler != null) { @@ -538,6 +585,34 @@ public class NEIRecipeWidget extends Widget { } + private void updatePermutationsFor(PositionedStack pStack) { + List perms = this.permutations.get(pStack); + int favoriteIndex = this.favoriteIndexes.getOrDefault(pStack, -1); + + if (perms == null) { + perms = pStack.getFilteredPermutations(); + favoriteIndex = -1; + + if (perms.size() > 1) { + for (ItemStack item : perms) { + if (!FavoriteRecipes.containsManual(item)) break; + favoriteIndex++; + } + } + + this.permutations.put(pStack, perms); + this.favoriteIndexes.put(pStack, favoriteIndex); + } + + if (perms.size() > 1) { + final int size = favoriteIndex != -1 ? favoriteIndex + 1 : perms.size(); + + if (size > 0) { + pStack.setPermutationToRender(perms.get(this.lastcycle % size)); + } + } + } + protected List getInputs() { return this.handlerRef.handler.getIngredientStacks(this.handlerRef.recipeIndex); } diff --git a/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java b/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java index adc826fe..456821d9 100644 --- a/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java +++ b/src/main/java/codechicken/nei/recipe/RecipeHandlerRef.java @@ -52,6 +52,11 @@ public class RecipeHandlerRef { return null; } + public static void clearCache() { + recipeRefCache.clear(); + transferAlghoritmCache.clear(); + } + private GuiContainer prepareGui(GuiContainer firstGui) { if (firstGui instanceof GuiRecipe gui) { diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index 48a87a57..286c784e 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -202,6 +202,7 @@ nei.options.keys.gui.itemzoom_hold=Hold to Display Item Zoom nei.options.keys.gui.itemzoom_zoom_in=Item Zoom In nei.options.keys.gui.itemzoom_zoom_out=Item Zoom Out nei.options.keys.gui.favorite=Add Favorite +nei.options.keys.gui.favorite_item=Toggle Favorite nei.options.keys.world=World nei.options.keys.world.chunkoverlay=Chunk Boundary Overlay nei.options.keys.world.moboverlay=Mob Spawn Overlay @@ -574,6 +575,7 @@ nei.recipe.overlay.bookmarkRecipeAndCount=Save with Recipe & Count nei.recipe.favorite=Favorite nei.recipe.favorite.bookmark_recipe=Save Recipe Tree nei.recipe.favorite.change_result_index=Change Output +nei.recipe.favorite.toggle=Toggle Favorite nei.recipe.information=Information