From 376198ac017c4f915faa431ca691acaaaf299e0d Mon Sep 17 00:00:00 2001 From: vfyjxf_ <2331007009@qq.com> Date: Sun, 26 Oct 2025 03:31:18 +0800 Subject: [PATCH 1/3] backport history --- .../mezz/jei/common/config/ClientConfig.java | 69 +++++++ .../jei/common/config/HistoryDisplaySide.java | 5 + .../mezz/jei/common/config/IClientConfig.java | 16 ++ .../jei/common/config/file/ConfigSchema.java | 4 +- .../jei/common/config/file/ConfigValue.java | 14 +- .../common/config/file/IConfigListener.java | 5 + .../jei/common/gui/textures/Textures.java | 12 ++ .../jei/common/util/DeduplicatingRunner.java | 10 +- .../main/resources/assets/jei/lang/en_us.json | 3 + .../gui/icons/history_button_disabled.png | Bin 0 -> 166 bytes .../gui/icons/history_button_enabled.png | Bin 0 -> 178 bytes .../jei/test/DeduplicatingRunnerTest.java | 8 +- .../java/mezz/jei/core/util/WeakList.java | 16 +- .../mezz/jei/test/lib/TestClientConfig.java | 37 ++++ .../mezz/jei/gui/bookmarks/BookmarkList.java | 20 +- .../mezz/jei/gui/config/BookmarkConfig.java | 56 +++--- .../jei/gui/config/ILookupHistoryConfig.java | 14 ++ .../gui/config/LookupHistoryJsonConfig.java | 163 ++++++++++++++++ .../input/handlers/BookmarkInputHandler.java | 7 +- .../gui/overlay/IngredientListOverlay.java | 42 +++- .../overlay/bookmarks/BookmarkOverlay.java | 78 +++++++- .../bookmarks/history/LookupHistory.java | 70 +++++++ .../history/LookupHistoryButton.java | 56 ++++++ .../history/LookupHistoryOverlay.java | 180 ++++++++++++++++++ .../bookmarks/history/package-info.java | 7 + .../mezz/jei/gui/recipes/RecipeGuiLogic.java | 63 +++++- .../java/mezz/jei/gui/recipes/RecipesGui.java | 4 + .../mezz/jei/gui/startup/GuiConfigData.java | 8 +- .../mezz/jei/gui/startup/JeiGuiStarter.java | 16 +- .../mezz/jei/gui/startup/OverlayHelper.java | 36 +++- 30 files changed, 943 insertions(+), 76 deletions(-) create mode 100644 Common/src/main/java/mezz/jei/common/config/HistoryDisplaySide.java create mode 100644 Common/src/main/java/mezz/jei/common/config/file/IConfigListener.java create mode 100644 Common/src/main/resources/assets/jei/textures/jei/atlas/gui/icons/history_button_disabled.png create mode 100644 Common/src/main/resources/assets/jei/textures/jei/atlas/gui/icons/history_button_enabled.png create mode 100644 Gui/src/main/java/mezz/jei/gui/config/ILookupHistoryConfig.java create mode 100644 Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java create mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java create mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java create mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java create mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/package-info.java diff --git a/Common/src/main/java/mezz/jei/common/config/ClientConfig.java b/Common/src/main/java/mezz/jei/common/config/ClientConfig.java index 518d894f2..209ab2388 100644 --- a/Common/src/main/java/mezz/jei/common/config/ClientConfig.java +++ b/Common/src/main/java/mezz/jei/common/config/ClientConfig.java @@ -3,6 +3,7 @@ import com.google.common.base.Preconditions; import mezz.jei.common.config.file.ConfigValue; import mezz.jei.common.config.file.IConfigCategoryBuilder; +import mezz.jei.common.config.file.IConfigListener; import mezz.jei.common.config.file.IConfigSchemaBuilder; import mezz.jei.common.config.file.serializers.EnumSerializer; import mezz.jei.common.config.file.serializers.ListSerializer; @@ -33,6 +34,12 @@ public final class ClientConfig implements IClientConfig { private final Supplier holdShiftToShowBookmarkTooltipFeaturesEnabled; private final Supplier dragToRearrangeBookmarksEnabled; + // lookup history + private final ConfigValue lookupHistoryEnabled; + private final ConfigValue maxLookupHistoryRows; + private final ConfigValue maxLookupHistoryIngredients; + private final ConfigValue lookupHistoryDisplaySide; + // advanced private final Supplier lowMemorySlowSearchEnabled; private final Supplier catchRenderErrorsEnabled; @@ -112,6 +119,33 @@ public ClientConfig(IConfigSchemaBuilder schema) { "Drag bookmarks to rearrange them in the list." ); + IConfigCategoryBuilder lookupHistory = schema.addCategory("lookupHistory"); + + lookupHistoryEnabled = lookupHistory.addBoolean( + "Enabled", + false, + "Display or hide the lookup history overlay." + ); + maxLookupHistoryRows = lookupHistory.addInteger( + "MaxRows", + 2, + 1, + 7, + "Max number of rows to display in the lookup history overlay." + ); + maxLookupHistoryIngredients = lookupHistory.addInteger( + "MaxIngredients", + 100, + 10, + 1_000, + "Max number of lookup history ingredients to save." + ); + lookupHistoryDisplaySide = lookupHistory.addEnum( + "DisplaySide", + HistoryDisplaySide.LEFT, + "Side of the screen to display the lookup history overlay." + ); + IConfigCategoryBuilder advanced = schema.addCategory("advanced"); lowMemorySlowSearchEnabled = advanced.addBoolean( "LowMemorySlowSearchEnabled", @@ -256,6 +290,41 @@ public boolean isDragToRearrangeBookmarksEnabled() { return dragToRearrangeBookmarksEnabled.get(); } + @Override + public boolean isLookupHistoryEnabled() { + return lookupHistoryEnabled.get(); + } + + @Override + public void setLookupHistoryEnabled(boolean enabled) { + lookupHistoryEnabled.set(enabled); + } + + @Override + public void addLookupHistoryEnabledListener(IConfigListener listener) { + lookupHistoryEnabled.addListener(listener); + } + + @Override + public int getMaxLookupHistoryRows() { + return maxLookupHistoryRows.get(); + } + + @Override + public int getMaxLookupHistoryIngredients() { + return maxLookupHistoryIngredients.get(); + } + + @Override + public HistoryDisplaySide getLookupHistoryDisplaySide() { + return lookupHistoryDisplaySide.get(); + } + + @Override + public void addLookupHistoryDisplaySideListener(IConfigListener listener) { + lookupHistoryDisplaySide.addListener(listener); + } + @Override public int getDragDelayMs() { return dragDelayMs.get(); diff --git a/Common/src/main/java/mezz/jei/common/config/HistoryDisplaySide.java b/Common/src/main/java/mezz/jei/common/config/HistoryDisplaySide.java new file mode 100644 index 000000000..885ec967e --- /dev/null +++ b/Common/src/main/java/mezz/jei/common/config/HistoryDisplaySide.java @@ -0,0 +1,5 @@ +package mezz.jei.common.config; + +public enum HistoryDisplaySide { + LEFT, RIGHT +} diff --git a/Common/src/main/java/mezz/jei/common/config/IClientConfig.java b/Common/src/main/java/mezz/jei/common/config/IClientConfig.java index 3124a1b1d..849b0887e 100644 --- a/Common/src/main/java/mezz/jei/common/config/IClientConfig.java +++ b/Common/src/main/java/mezz/jei/common/config/IClientConfig.java @@ -1,5 +1,7 @@ package mezz.jei.common.config; +import mezz.jei.common.config.file.IConfigListener; + import java.util.List; import java.util.Set; @@ -32,6 +34,20 @@ public interface IClientConfig { boolean isDragToRearrangeBookmarksEnabled(); + boolean isLookupHistoryEnabled(); + + void setLookupHistoryEnabled(boolean enabled); + + void addLookupHistoryEnabledListener(IConfigListener listener); + + int getMaxLookupHistoryRows(); + + int getMaxLookupHistoryIngredients(); + + HistoryDisplaySide getLookupHistoryDisplaySide(); + + void addLookupHistoryDisplaySideListener(IConfigListener listener); + int getDragDelayMs(); int getSmoothScrollRate(); diff --git a/Common/src/main/java/mezz/jei/common/config/file/ConfigSchema.java b/Common/src/main/java/mezz/jei/common/config/file/ConfigSchema.java index a7a3a5e86..3d6ebcdf6 100644 --- a/Common/src/main/java/mezz/jei/common/config/file/ConfigSchema.java +++ b/Common/src/main/java/mezz/jei/common/config/file/ConfigSchema.java @@ -21,7 +21,7 @@ public class ConfigSchema implements IConfigSchema { @Unmodifiable private final List categories; private final AtomicBoolean needsLoad = new AtomicBoolean(true); - private final DeduplicatingRunner delayedSave = new DeduplicatingRunner(this::save, SAVE_DELAY_TIME, "JEI Config Save Delay"); + private final DeduplicatingRunner delayedSave = new DeduplicatingRunner(SAVE_DELAY_TIME, "JEI Config Save Delay"); public ConfigSchema(Path path, List categoryBuilders) { this.path = path; @@ -70,7 +70,7 @@ private void save() { @Override public void markDirty() { - delayedSave.run(); + delayedSave.run(this::save); } @Override diff --git a/Common/src/main/java/mezz/jei/common/config/file/ConfigValue.java b/Common/src/main/java/mezz/jei/common/config/file/ConfigValue.java index 5cee3ef01..d7771e188 100644 --- a/Common/src/main/java/mezz/jei/common/config/file/ConfigValue.java +++ b/Common/src/main/java/mezz/jei/common/config/file/ConfigValue.java @@ -2,6 +2,7 @@ import mezz.jei.api.runtime.config.IJeiConfigValue; import mezz.jei.api.runtime.config.IJeiConfigValueSerializer; +import mezz.jei.core.util.WeakList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -16,6 +17,7 @@ public class ConfigValue implements IJeiConfigValue, Supplier { private final String description; private final T defaultValue; private final IJeiConfigValueSerializer serializer; + private final WeakList> listeners = new WeakList<>(); private volatile T currentValue; @Nullable private IConfigSchema schema; @@ -68,7 +70,12 @@ public IJeiConfigValueSerializer getSerializer() { public List setFromSerializedValue(String value) { IJeiConfigValueSerializer.IDeserializeResult deserializeResult = serializer.deserialize(value); deserializeResult.getResult() - .ifPresent(t -> currentValue = t); + .ifPresent(t -> { + if (currentValue != t){ + currentValue = t; + listeners.forEach(c -> c.onConfigValueChanged(currentValue)); + } + }); return deserializeResult.getErrors(); } @@ -80,6 +87,7 @@ public boolean set(T value) { } if (!currentValue.equals(value)) { currentValue = value; + listeners.forEach(c -> c.onConfigValueChanged(currentValue)); if (schema != null) { schema.markDirty(); } @@ -87,4 +95,8 @@ public boolean set(T value) { } return false; } + + public void addListener(IConfigListener listener) { + this.listeners.add(listener); + } } diff --git a/Common/src/main/java/mezz/jei/common/config/file/IConfigListener.java b/Common/src/main/java/mezz/jei/common/config/file/IConfigListener.java new file mode 100644 index 000000000..40c947065 --- /dev/null +++ b/Common/src/main/java/mezz/jei/common/config/file/IConfigListener.java @@ -0,0 +1,5 @@ +package mezz.jei.common.config.file; + +public interface IConfigListener { + void onConfigValueChanged(T configValue); +} diff --git a/Common/src/main/java/mezz/jei/common/gui/textures/Textures.java b/Common/src/main/java/mezz/jei/common/gui/textures/Textures.java index 175fbd6b0..fd44e152a 100644 --- a/Common/src/main/java/mezz/jei/common/gui/textures/Textures.java +++ b/Common/src/main/java/mezz/jei/common/gui/textures/Textures.java @@ -41,6 +41,8 @@ public class Textures { private final IDrawableStatic configButtonCheatIcon; private final IDrawableStatic bookmarkButtonDisabledIcon; private final IDrawableStatic bookmarkButtonEnabledIcon; + private final IDrawableStatic historyButtonDisabledIcon; + private final IDrawableStatic historyButtonEnabledICon; private final IDrawableStatic infoIcon; private final DrawableNineSliceTexture catalystTab; private final DrawableNineSliceTexture recipeOptionsTab; @@ -105,6 +107,8 @@ public Textures(JeiSpriteUploader spriteUploader) { this.configButtonCheatIcon = createGuiSprite("icons/config_button_cheat", 16, 16); this.bookmarkButtonDisabledIcon = createGuiSprite("icons/bookmark_button_disabled", 16, 16); this.bookmarkButtonEnabledIcon = createGuiSprite("icons/bookmark_button_enabled", 16, 16); + this.historyButtonDisabledIcon = createGuiSprite("icons/history_button_disabled", 16, 16); + this.historyButtonEnabledICon = createGuiSprite("icons/history_button_enabled", 16, 16); this.infoIcon = createGuiSprite("icons/info", 16, 16); this.flameIcon = createGuiSprite("icons/flame", 14, 14); this.flameEmptyIcon = createGuiSprite("icons/flame_empty", 14, 14); @@ -182,6 +186,14 @@ public IDrawableStatic getBookmarkButtonEnabledIcon() { return bookmarkButtonEnabledIcon; } + public IDrawableStatic getHistoryButtonDisabledIcon() { + return historyButtonDisabledIcon; + } + + public IDrawableStatic getHistoryButtonEnabledICon() { + return historyButtonEnabledICon; + } + public DrawableNineSliceTexture getButtonForState(boolean pressed, boolean enabled, boolean hovered) { if (!enabled) { return buttonDisabled; diff --git a/Common/src/main/java/mezz/jei/common/util/DeduplicatingRunner.java b/Common/src/main/java/mezz/jei/common/util/DeduplicatingRunner.java index 262d72c52..58f4d8916 100644 --- a/Common/src/main/java/mezz/jei/common/util/DeduplicatingRunner.java +++ b/Common/src/main/java/mezz/jei/common/util/DeduplicatingRunner.java @@ -10,26 +10,24 @@ * This will only run once `delay` has elapsed, without additional runs being called. */ public class DeduplicatingRunner { - private final Runnable runnable; private final Duration delay; private final String name; private @Nullable Timer timer; private @Nullable TimerTask task; - public DeduplicatingRunner(Runnable runnable, Duration delay, String name) { - this.runnable = runnable; + public DeduplicatingRunner(Duration delay, String name) { this.delay = delay; this.name = name; } - public synchronized void run() { + public synchronized void run(Runnable runnable) { if (task != null) { task.cancel(); } task = new TimerTask() { @Override public void run() { - doRun(this); + doRun(this, runnable); } }; if (timer == null) { @@ -38,7 +36,7 @@ public void run() { timer.schedule(task, delay.toMillis()); } - private synchronized void doRun(TimerTask fromTask) { + private synchronized void doRun(TimerTask fromTask, Runnable runnable) { if (task == fromTask) { runnable.run(); task = null; diff --git a/Common/src/main/resources/assets/jei/lang/en_us.json b/Common/src/main/resources/assets/jei/lang/en_us.json index cf8a4f328..025d24bec 100644 --- a/Common/src/main/resources/assets/jei/lang/en_us.json +++ b/Common/src/main/resources/assets/jei/lang/en_us.json @@ -30,6 +30,9 @@ "jei.tooltip.bookmarks.tooltips.usage": "[Press \"%s\" to show details]", "jei.tooltip.bookmarks.tooltips.transfer.usage": "[Press \"%s\" to craft one]", "jei.tooltip.bookmarks.tooltips.transfer.max.usage": "[Press \"%s\" to craft many]", + "jei.tooltip.lookupHistory.enable": "Show JEI Lookup History", + "jei.tooltip.lookupHistory.disable": "Hide JEI Lookup History", + "jei.tooltip.lookupHistory.usage": "Shows a list of the ingredients recently used for looking up recipes.", "jei.tooltip.recipe.sort.bookmarks.first.enabled": "Show bookmarked recipes first (enabled).", "jei.tooltip.recipe.sort.bookmarks.first.disabled": "Show bookmarked recipes first (disabled).", "jei.tooltip.recipe.sort.craftable.first.enabled": "Show craftable recipes first (enabled).", diff --git a/Common/src/main/resources/assets/jei/textures/jei/atlas/gui/icons/history_button_disabled.png b/Common/src/main/resources/assets/jei/textures/jei/atlas/gui/icons/history_button_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..33090b8b64f40f7e1a2f36657870b01561c64a9e GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHV5AX?b1=59ug+OxZ)TxGshP&+l zuL5!yOM?7@862M7NCR?QJzX3_IIbrPz{9LOL*XrxN-BewnZwO`wVajxzfWpT z)17_Tv3ZNNv3=K7j=cginK~jKIKQkAxf85hl^T1{SyJ`p(nkq;>g@MtT24I5&wH9{ UlgdgqVW8m*p00i_>zopr0BcM*`~Uy| literal 0 HcmV?d00001 diff --git a/Common/src/test/java/mezz/jei/test/DeduplicatingRunnerTest.java b/Common/src/test/java/mezz/jei/test/DeduplicatingRunnerTest.java index 1cb73ba19..a1b1b83b9 100644 --- a/Common/src/test/java/mezz/jei/test/DeduplicatingRunnerTest.java +++ b/Common/src/test/java/mezz/jei/test/DeduplicatingRunnerTest.java @@ -17,9 +17,9 @@ public void testDeduplicatedRuns() throws InterruptedException { AtomicInteger runs = new AtomicInteger(); Runnable testRunnable = runs::getAndIncrement; Duration delay = Duration.ofMillis(10); - DeduplicatingRunner deduplicatingRunner = new DeduplicatingRunner(testRunnable, delay, "test"); + DeduplicatingRunner deduplicatingRunner = new DeduplicatingRunner(delay, "test"); for (int i = 0; i < 10; i++) { - deduplicatingRunner.run(); + deduplicatingRunner.run(testRunnable); } Assertions.assertEquals(0, runs.get()); Thread.sleep(2 * delay.toMillis()); @@ -35,9 +35,9 @@ public void testSpacedOutRuns() throws InterruptedException { AtomicInteger runs = new AtomicInteger(); Runnable testRunnable = runs::getAndIncrement; Duration delay = Duration.ofMillis(10); - DeduplicatingRunner deduplicatingRunner = new DeduplicatingRunner(testRunnable, delay, "test"); + DeduplicatingRunner deduplicatingRunner = new DeduplicatingRunner(delay, "test"); for (int i = 0; i < 5; i++) { - deduplicatingRunner.run(); + deduplicatingRunner.run(testRunnable); Thread.sleep(2 * delay.toMillis()); Assertions.assertEquals(i + 1, runs.get()); } diff --git a/Core/src/main/java/mezz/jei/core/util/WeakList.java b/Core/src/main/java/mezz/jei/core/util/WeakList.java index 1db215ec2..4b67ff919 100644 --- a/Core/src/main/java/mezz/jei/core/util/WeakList.java +++ b/Core/src/main/java/mezz/jei/core/util/WeakList.java @@ -1,5 +1,6 @@ package mezz.jei.core.util; +import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Iterator; @@ -7,13 +8,20 @@ import java.util.function.Consumer; public class WeakList { - private final List> list = new ArrayList<>(); + @Nullable + private List> list; public void add(T item) { + if (list == null) { + list = new ArrayList<>(); + } list.add(new WeakReference<>(item)); } public void forEach(Consumer consumer) { + if (list == null) { + return; + } Iterator> iterator = list.iterator(); while (iterator.hasNext()) { WeakReference reference = iterator.next(); @@ -24,9 +32,15 @@ public void forEach(Consumer consumer) { consumer.accept(item); } } + if (list.isEmpty()) { + list = null; + } } public boolean isEmpty() { + if (list == null) { + return true; + } Iterator> iterator = list.iterator(); while (iterator.hasNext()) { WeakReference reference = iterator.next(); diff --git a/Forge/src/test/java/mezz/jei/test/lib/TestClientConfig.java b/Forge/src/test/java/mezz/jei/test/lib/TestClientConfig.java index 6955457ed..278e16f8d 100644 --- a/Forge/src/test/java/mezz/jei/test/lib/TestClientConfig.java +++ b/Forge/src/test/java/mezz/jei/test/lib/TestClientConfig.java @@ -2,9 +2,11 @@ import mezz.jei.common.config.BookmarkTooltipFeature; import mezz.jei.common.config.GiveMode; +import mezz.jei.common.config.HistoryDisplaySide; import mezz.jei.common.config.IngredientSortStage; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.RecipeSorterStage; +import mezz.jei.common.config.file.IConfigListener; import java.util.List; import java.util.Set; @@ -76,6 +78,41 @@ public boolean isDragToRearrangeBookmarksEnabled() { return false; } + @Override + public boolean isLookupHistoryEnabled() { + return false; + } + + @Override + public void setLookupHistoryEnabled(boolean enabled) { + + } + + @Override + public void addLookupHistoryEnabledListener(IConfigListener listener) { + + } + + @Override + public int getMaxLookupHistoryRows() { + return 0; + } + + @Override + public int getMaxLookupHistoryIngredients() { + return 0; + } + + @Override + public HistoryDisplaySide getLookupHistoryDisplaySide() { + return HistoryDisplaySide.LEFT; + } + + @Override + public void addLookupHistoryDisplaySideListener(IConfigListener listener) { + + } + @Override public int getDragDelayMs() { return 0; diff --git a/Gui/src/main/java/mezz/jei/gui/bookmarks/BookmarkList.java b/Gui/src/main/java/mezz/jei/gui/bookmarks/BookmarkList.java index bf6cef1f4..fa56431e9 100644 --- a/Gui/src/main/java/mezz/jei/gui/bookmarks/BookmarkList.java +++ b/Gui/src/main/java/mezz/jei/gui/bookmarks/BookmarkList.java @@ -7,7 +7,9 @@ import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.common.config.IClientConfig; import mezz.jei.gui.config.IBookmarkConfig; +import mezz.jei.gui.input.UserInput; import mezz.jei.gui.overlay.IIngredientGridSource; +import mezz.jei.gui.overlay.bookmarks.BookmarkOverlay; import mezz.jei.gui.overlay.elements.IElement; import net.minecraft.core.RegistryAccess; @@ -84,14 +86,16 @@ public boolean contains(IBookmark value) { return this.bookmarksSet.contains(value); } - public boolean onElementBookmarked(IElement element) { - return element.getBookmark() - .map(this::remove) - .orElseGet(() -> { - ITypedIngredient ingredient = element.getTypedIngredient(); - IBookmark bookmark = IngredientBookmark.create(ingredient, ingredientManager); - return add(bookmark); - }); + public boolean onElementBookmarked(IElement element, UserInput input, BookmarkOverlay bookmarkOverlay) { + if (bookmarkOverlay.isMouseOver(input.getMouseX(), input.getMouseY())) { + return element.getBookmark() + .map(this::remove) + .orElse(false); + } + + ITypedIngredient ingredient = element.getTypedIngredient(); + IBookmark bookmark = IngredientBookmark.create(ingredient, ingredientManager); + return add(bookmark); } public void toggleBookmark(IBookmark bookmark) { diff --git a/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java b/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java index dc69dfa57..6f32fcd77 100644 --- a/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java +++ b/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java @@ -23,6 +23,7 @@ import net.minecraft.world.item.ItemStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.nio.file.Files; @@ -35,11 +36,11 @@ public class BookmarkConfig implements IBookmarkConfig { private static final Logger LOGGER = LogManager.getLogger(); - private static final String MARKER_STACK = "T:"; - private static final String MARKER_INGREDIENT = "I:"; - private static final String LEGACY_MARKER_OTHER = "O:"; + static final String MARKER_STACK = "T:"; + static final String MARKER_INGREDIENT = "I:"; + static final String LEGACY_MARKER_OTHER = "O:"; - private static final String MARKER_RECIPE = "R:"; + static final String MARKER_RECIPE = "R:"; private final Path jeiConfigurationDir; @@ -133,31 +134,34 @@ public void loadBookmarks( IIngredientHelper itemStackHelper = ingredientManager.getIngredientHelper(VanillaTypes.ITEM_STACK); for (String line : lines) { + IBookmark bookmark = null; if (line.startsWith(MARKER_STACK)) { String itemStackAsJson = line.substring(MARKER_STACK.length()); - loadItemStackBookmark(itemStackHelper, ingredientManager, itemStackAsJson, bookmarkList); + bookmark = loadItemStackBookmark(itemStackHelper, ingredientManager, itemStackAsJson); } else if (line.startsWith(MARKER_INGREDIENT)) { String serializedIngredient = line.substring(MARKER_INGREDIENT.length()); - loadIngredientBookmark(ingredientSerializer, ingredientManager, serializedIngredient, bookmarkList); + bookmark = loadIngredientBookmark(ingredientSerializer, ingredientManager, serializedIngredient); } else if (line.startsWith(LEGACY_MARKER_OTHER)) { String uid = line.substring(LEGACY_MARKER_OTHER.length()); - loadLegacyIngredientBookmark(otherIngredientTypes, ingredientManager, uid, bookmarkList); + bookmark = loadLegacyIngredientBookmark(otherIngredientTypes, ingredientManager, uid); } else if (line.startsWith(MARKER_RECIPE)) { String serializedRecipe = line.substring(MARKER_RECIPE.length()); - loadRecipeBookmark(recipeBookmarkSerializer, serializedRecipe, bookmarkList); + bookmark = loadRecipeBookmark(recipeBookmarkSerializer, serializedRecipe); } else { LOGGER.error("Failed to load unknown bookmark type:\n{}", line); } + if (bookmark != null){ + bookmarkList.addToListWithoutNotifying(bookmark, false); + } } bookmarkList.notifyListenersOfChange(); }); } - private static void loadItemStackBookmark( + static @Nullable IBookmark loadItemStackBookmark( IIngredientHelper itemStackHelper, IIngredientManager ingredientManager, - String itemStackAsJson, - BookmarkList bookmarkList + String itemStackAsJson ) { try { CompoundTag itemStackAsNbt = TagParser.parseTag(itemStackAsJson); @@ -168,8 +172,7 @@ private static void loadItemStackBookmark( if (typedIngredient.isEmpty()) { LOGGER.warn("Failed to load bookmarked ItemStack from json string, the item no longer exists:\n{}", itemStackAsJson); } else { - IngredientBookmark bookmark = IngredientBookmark.create(typedIngredient.get(), ingredientManager); - bookmarkList.addToListWithoutNotifying(bookmark, false); + return IngredientBookmark.create(typedIngredient.get(), ingredientManager); } } else { LOGGER.warn("Failed to load bookmarked ItemStack from json string, the item is empty:\n{}", itemStackAsJson); @@ -177,13 +180,13 @@ private static void loadItemStackBookmark( } catch (CommandSyntaxException e) { LOGGER.error("Failed to load bookmarked ItemStack from json string:\n{}", itemStackAsJson, e); } + return null; } - private static void loadIngredientBookmark( + static @Nullable IBookmark loadIngredientBookmark( TypedIngredientSerializer ingredientSerializer, IIngredientManager ingredientManager, - String serializedIngredient, - BookmarkList bookmarkList + String serializedIngredient ) { IDeserializeResult> deserialized = ingredientSerializer.deserialize(serializedIngredient); Optional> result = deserialized.getResult(); @@ -191,30 +194,28 @@ private static void loadIngredientBookmark( List errors = deserialized.getErrors(); LOGGER.warn("Failed to load bookmarked ingredients from string: \n{}\n{}", serializedIngredient, String.join(", ", errors)); } else { - IngredientBookmark bookmark = IngredientBookmark.create(result.get(), ingredientManager); - bookmarkList.addToListWithoutNotifying(bookmark, false); + return IngredientBookmark.create(result.get(), ingredientManager); } + return null; } - private static void loadLegacyIngredientBookmark( + private static @Nullable IBookmark loadLegacyIngredientBookmark( Collection> otherIngredientTypes, IIngredientManager ingredientManager, - String uid, - BookmarkList bookmarkList + String uid ) { Optional> typedIngredient = getLegacyNormalizedIngredientByUid(ingredientManager, otherIngredientTypes, uid); if (typedIngredient.isEmpty()) { LOGGER.error("Failed to load unknown bookmarked ingredient with uid:\n{}", uid); } else { - IngredientBookmark bookmark = IngredientBookmark.create(typedIngredient.get(), ingredientManager); - bookmarkList.addToListWithoutNotifying(bookmark, false); + return IngredientBookmark.create(typedIngredient.get(), ingredientManager); } + return null; } - private static void loadRecipeBookmark( + static @Nullable IBookmark loadRecipeBookmark( RecipeBookmarkSerializer recipeBookmarkSerializer, - String serializedRecipe, - BookmarkList bookmarkList + String serializedRecipe ) { IDeserializeResult> deserialized = recipeBookmarkSerializer.deserialize(serializedRecipe); Optional> result = deserialized.getResult(); @@ -222,8 +223,9 @@ private static void loadRecipeBookmark( List errors = deserialized.getErrors(); LOGGER.warn("Failed to load bookmarked recipe from string: \n{}\n{}", serializedRecipe, String.join(", ", errors)); } else { - bookmarkList.addToListWithoutNotifying(result.get(), false); + return result.get(); } + return null; } private static Optional> getLegacyNormalizedIngredientByUid(IIngredientManager ingredientManager, Collection> ingredientTypes, String uid) { diff --git a/Gui/src/main/java/mezz/jei/gui/config/ILookupHistoryConfig.java b/Gui/src/main/java/mezz/jei/gui/config/ILookupHistoryConfig.java new file mode 100644 index 000000000..39fc4ed82 --- /dev/null +++ b/Gui/src/main/java/mezz/jei/gui/config/ILookupHistoryConfig.java @@ -0,0 +1,14 @@ +package mezz.jei.gui.config; + +import mezz.jei.api.recipe.IFocusFactory; +import mezz.jei.api.recipe.IRecipeManager; +import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.gui.bookmarks.IBookmark; + +import java.util.List; + +public interface ILookupHistoryConfig { + void save(IRecipeManager recipeManager, IIngredientManager ingredientManager, IFocusFactory focusFactory, List bookmarks); + + List load(IRecipeManager recipeManager, IIngredientManager ingredientManager,IFocusFactory focusFactory); +} diff --git a/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java b/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java new file mode 100644 index 000000000..b39a83bac --- /dev/null +++ b/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java @@ -0,0 +1,163 @@ +package mezz.jei.gui.config; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.ingredients.IIngredientHelper; +import mezz.jei.api.ingredients.ITypedIngredient; +import mezz.jei.api.recipe.IFocusFactory; +import mezz.jei.api.recipe.IRecipeManager; +import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.common.config.file.serializers.TypedIngredientSerializer; +import mezz.jei.common.util.DeduplicatingRunner; +import mezz.jei.common.util.ServerConfigPathUtil; +import mezz.jei.gui.bookmarks.IBookmark; +import mezz.jei.gui.bookmarks.IngredientBookmark; +import mezz.jei.gui.bookmarks.RecipeBookmark; +import mezz.jei.gui.config.file.serializers.RecipeBookmarkSerializer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Unmodifiable; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static mezz.jei.gui.config.BookmarkConfig.*; + +public class LookupHistoryJsonConfig implements ILookupHistoryConfig { + private static final Logger LOGGER = LogManager.getLogger(); + private static final Duration SAVE_DELAY_TIME = Duration.ofSeconds(5); + + private final Path jeiConfigurationDir; + private final DeduplicatingRunner delayedSave = new DeduplicatingRunner(SAVE_DELAY_TIME, "JEI Lookup History Save Delay"); + + private static Optional getPath(Path jeiConfigurationDir) { + return ServerConfigPathUtil.getWorldPath(jeiConfigurationDir) + .flatMap(configPath -> { + try { + Files.createDirectories(configPath); + } catch (IOException e) { + LOGGER.error("Unable to create lookup history config folder: {}", configPath); + return Optional.empty(); + } + Path path = configPath.resolve("lookupHistory.ini"); + return Optional.of(path); + }); + } + + public LookupHistoryJsonConfig(Path jeiConfigurationDir) { + this.jeiConfigurationDir = jeiConfigurationDir; + } + + @Override + public void save( + IRecipeManager recipeManager, + IIngredientManager ingredientManager, + IFocusFactory focusFactory, + List bookmarks + ) { + getPath(jeiConfigurationDir) + .ifPresent(path -> { + delayedSave.run(() -> { + save(path, recipeManager, ingredientManager, focusFactory, bookmarks); + }); + }); + } + + private void save( + Path path, + IRecipeManager recipeManager, + IIngredientManager ingredientManager, + IFocusFactory focusFactory, + List bookmarks) { + List strings = new ArrayList<>(); + TypedIngredientSerializer ingredientSerializer = new TypedIngredientSerializer(ingredientManager); + RecipeBookmarkSerializer recipeBookmarkSerializer = new RecipeBookmarkSerializer(recipeManager, focusFactory, ingredientSerializer); + for (IBookmark bookmark : bookmarks) { + if (bookmark instanceof IngredientBookmark ingredientBookmark) { + ITypedIngredient typedIngredient = ingredientBookmark.getIngredient(); + if (typedIngredient.getIngredient() instanceof ItemStack stack) { + strings.add(MARKER_STACK + stack.save(new CompoundTag())); + } else { + strings.add(MARKER_INGREDIENT + ingredientSerializer.serialize(typedIngredient)); + } + } else if (bookmark instanceof RecipeBookmark recipeBookmark) { + strings.add(MARKER_RECIPE + recipeBookmarkSerializer.serialize(recipeBookmark)); + } else { + LOGGER.error("Unknown IBookmark type, unable to save it: {}", bookmark.getClass()); + } + } + + try { + Files.write(path, strings); + LOGGER.debug("Saved lookup history config to file {}", path); + } catch (IOException e) { + LOGGER.error("Failed to save lookup history config to file {}", path, e); + } + } + + @Override + public List load( + IRecipeManager recipeManager, + IIngredientManager ingredientManager, + IFocusFactory focusFactory + ) { + return loadBookmarks(ingredientManager, recipeManager, focusFactory); + } + + @Unmodifiable + private List loadBookmarks( + IIngredientManager ingredientManager, + IRecipeManager recipeManager, + IFocusFactory focusFactory + ) { + return getPath(jeiConfigurationDir) + .>map(path -> { + if (!Files.exists(path)) { + return List.of(); + } + + List lines; + try { + lines = Files.readAllLines(path); + } catch (IOException e) { + LOGGER.error("Encountered an exception when loading the lookup history config from file {}\n{}", path, e); + return List.of(); + } + + TypedIngredientSerializer ingredientSerializer = new TypedIngredientSerializer(ingredientManager); + RecipeBookmarkSerializer recipeBookmarkSerializer = new RecipeBookmarkSerializer(recipeManager, focusFactory, ingredientSerializer); + + IIngredientHelper itemStackHelper = ingredientManager.getIngredientHelper(VanillaTypes.ITEM_STACK); + List bookmarks = new ArrayList<>(); + for (String line : lines) { + IBookmark bookmark = null; + if (line.startsWith(MARKER_STACK)) { + String itemStackAsJson = line.substring(MARKER_STACK.length()); + bookmark = loadItemStackBookmark(itemStackHelper, ingredientManager, itemStackAsJson); + } else if (line.startsWith(MARKER_INGREDIENT)) { + String serializedIngredient = line.substring(MARKER_INGREDIENT.length()); + bookmark = loadIngredientBookmark(ingredientSerializer, ingredientManager, serializedIngredient); + } else if (line.startsWith(MARKER_RECIPE)) { + String serializedRecipe = line.substring(MARKER_RECIPE.length()); + bookmark = loadRecipeBookmark(recipeBookmarkSerializer, serializedRecipe); + } else { + LOGGER.error("Failed to load unknown bookmark type:\n{}", line); + } + if (bookmark != null) { + bookmarks.add(bookmark); + } + } + + return bookmarks; + }) + .orElseGet(List::of); + } + + +} \ No newline at end of file diff --git a/Gui/src/main/java/mezz/jei/gui/input/handlers/BookmarkInputHandler.java b/Gui/src/main/java/mezz/jei/gui/input/handlers/BookmarkInputHandler.java index 4ece53bdb..cd5a75501 100644 --- a/Gui/src/main/java/mezz/jei/gui/input/handlers/BookmarkInputHandler.java +++ b/Gui/src/main/java/mezz/jei/gui/input/handlers/BookmarkInputHandler.java @@ -5,6 +5,7 @@ import mezz.jei.gui.input.CombinedRecipeFocusSource; import mezz.jei.gui.input.IUserInputHandler; import mezz.jei.gui.input.UserInput; +import mezz.jei.gui.overlay.bookmarks.BookmarkOverlay; import net.minecraft.client.gui.screens.Screen; import java.util.Optional; @@ -12,10 +13,12 @@ public class BookmarkInputHandler implements IUserInputHandler { private final CombinedRecipeFocusSource focusSource; private final BookmarkList bookmarkList; + private final BookmarkOverlay bookmarkOverlay; - public BookmarkInputHandler(CombinedRecipeFocusSource focusSource, BookmarkList bookmarkList) { + public BookmarkInputHandler(CombinedRecipeFocusSource focusSource, BookmarkList bookmarkList, BookmarkOverlay bookmarkOverlay) { this.focusSource = focusSource; this.bookmarkList = bookmarkList; + this.bookmarkOverlay = bookmarkOverlay; } @Override @@ -31,7 +34,7 @@ private Optional handleBookmark(UserInput input, IInternalKey .findFirst() .flatMap(clicked -> { if (input.isSimulate() || - bookmarkList.onElementBookmarked(clicked.getElement()) + bookmarkList.onElementBookmarked(clicked.getElement(), input, bookmarkOverlay) ) { IUserInputHandler handler = new SameElementInputHandler(this, clicked::isMouseOver); return Optional.of(handler); diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java index 1639101dc..060b86028 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java @@ -5,8 +5,10 @@ import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.runtime.IIngredientListOverlay; import mezz.jei.api.runtime.IScreenHelper; +import mezz.jei.common.config.HistoryDisplaySide; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IClientToggleState; +import mezz.jei.common.config.file.IConfigListener; import mezz.jei.common.input.IInternalKeyMappings; import mezz.jei.common.util.ImmutableRect2i; import mezz.jei.gui.GuiProperties; @@ -25,6 +27,7 @@ import mezz.jei.gui.input.handlers.NullInputHandler; import mezz.jei.gui.input.handlers.ProxyDragHandler; import mezz.jei.gui.input.handlers.ProxyInputHandler; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistoryOverlay; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import org.jetbrains.annotations.Nullable; @@ -43,6 +46,7 @@ public class IngredientListOverlay implements IIngredientListOverlay, IRecipeFoc private final GuiIconToggleButton configButton; private final IngredientGridWithNavigation contents; + private final LookupHistoryOverlay lookupHistoryOverlay; private final IClientConfig clientConfig; private final IClientToggleState toggleState; private final GuiTextFieldFilter searchField; @@ -50,17 +54,26 @@ public class IngredientListOverlay implements IIngredientListOverlay, IRecipeFoc private final ScreenPropertiesCache screenPropertiesCache; private final IFilterTextSource filterTextSource; + + // these need to be stored as strong references here because listeners are weakly stored elsewhere + @SuppressWarnings("FieldCanBeLocal") + private final IConfigListener lookupHistoryEnabledListener; + @SuppressWarnings("FieldCanBeLocal") + private final IConfigListener lookupHistoryViewSideListener; + public IngredientListOverlay( IIngredientGridSource ingredientGridSource, IFilterTextSource filterTextSource, IScreenHelper screenHelper, IngredientGridWithNavigation contents, + LookupHistoryOverlay lookupHistoryOverlay, IClientConfig clientConfig, IClientToggleState toggleState, IInternalKeyMappings keyBindings ) { this.screenPropertiesCache = new ScreenPropertiesCache(screenHelper); this.contents = contents; + this.lookupHistoryOverlay = lookupHistoryOverlay; this.clientConfig = clientConfig; this.toggleState = toggleState; @@ -80,6 +93,12 @@ public IngredientListOverlay( }); this.configButton = ConfigButton.create(this::isListDisplayed, toggleState, keyBindings); + + this.lookupHistoryEnabledListener = v -> onScreenPropertiesChanged(); + this.lookupHistoryViewSideListener = v -> onScreenPropertiesChanged(); + + clientConfig.addLookupHistoryEnabledListener(lookupHistoryEnabledListener); + clientConfig.addLookupHistoryDisplaySideListener(lookupHistoryViewSideListener); } @Override @@ -115,7 +134,17 @@ private void onScreenPropertiesChanged() { private void updateBounds(IGuiProperties guiProperties, ImmutableRect2i displayArea, Set guiExclusionAreas) { final boolean searchBarCentered = isSearchBarCentered(this.clientConfig, guiProperties); - final ImmutableRect2i availableContentsArea = getAvailableContentsArea(displayArea, searchBarCentered); + ImmutableRect2i availableContentsArea = getAvailableContentsArea(displayArea, searchBarCentered); + if (clientConfig.isLookupHistoryEnabled() && lookupHistoryOverlay.isOnSide()) { + int historyRows = clientConfig.getMaxLookupHistoryRows(); + availableContentsArea = availableContentsArea.cropBottom(historyRows * LookupHistoryOverlay.SLOT_HEIGHT); + ImmutableRect2i historyArea = displayArea + .insetBy(BORDER_MARGIN) + .moveUp(BUTTON_SIZE + INNER_PADDING) + .keepBottom(historyRows * LookupHistoryOverlay.SLOT_HEIGHT); + this.lookupHistoryOverlay.updateBounds(historyArea, guiExclusionAreas, null); + this.lookupHistoryOverlay.updateLayout(); + } this.contents.updateBounds(availableContentsArea, guiExclusionAreas, null); this.contents.updateLayout(false); @@ -165,6 +194,10 @@ public void drawScreen(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, } if (this.screenPropertiesCache.hasValidScreen()) { this.configButton.draw(guiGraphics, mouseX, mouseY, partialTicks); + + } + if (this.screenPropertiesCache.hasValidScreen() && toggleState.isOverlayEnabled()) { + this.lookupHistoryOverlay.draw(minecraft, guiGraphics, mouseX, mouseY, partialTicks); } } @@ -175,6 +208,9 @@ public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouse if (this.screenPropertiesCache.hasValidScreen()) { this.configButton.drawTooltips(guiGraphics, mouseX, mouseY); } + if (this.screenPropertiesCache.hasValidScreen() && toggleState.isOverlayEnabled()) { + this.lookupHistoryOverlay.drawTooltips(minecraft, guiGraphics, mouseX, mouseY); + } } public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { @@ -192,7 +228,7 @@ public void handleTick() { @Override public Stream> getIngredientUnderMouse(double mouseX, double mouseY) { if (isListDisplayed()) { - return this.contents.getIngredientUnderMouse(mouseX, mouseY); + return Stream.concat(this.contents.getIngredientUnderMouse(mouseX, mouseY), this.lookupHistoryOverlay.getIngredientUnderMouse(mouseX, mouseY)); } return Stream.empty(); } @@ -200,7 +236,7 @@ public Stream> getIngredientUnderMouse(double mo @Override public Stream> getDraggableIngredientUnderMouse(double mouseX, double mouseY) { if (isListDisplayed()) { - return this.contents.getDraggableIngredientUnderMouse(mouseX, mouseY); + return Stream.concat(this.contents.getDraggableIngredientUnderMouse(mouseX, mouseY), this.lookupHistoryOverlay.getDraggableIngredientUnderMouse(mouseX, mouseY)); } return Stream.empty(); } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java index 320263859..eb5ec76d5 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java @@ -5,7 +5,10 @@ import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.runtime.IBookmarkOverlay; import mezz.jei.api.runtime.IScreenHelper; +import mezz.jei.common.config.HistoryDisplaySide; +import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IClientToggleState; +import mezz.jei.common.config.file.IConfigListener; import mezz.jei.common.input.IInternalKeyMappings; import mezz.jei.common.util.ImmutablePoint2i; import mezz.jei.common.util.ImmutableRect2i; @@ -27,6 +30,8 @@ import mezz.jei.gui.overlay.IngredientGridWithNavigation; import mezz.jei.gui.overlay.IngredientListSlot; import mezz.jei.gui.overlay.ScreenPropertiesCache; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistoryButton; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistoryOverlay; import mezz.jei.gui.overlay.elements.IElement; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -51,23 +56,37 @@ public class BookmarkOverlay implements IRecipeFocusSource, IBookmarkOverlay { // display elements private final IngredientGridWithNavigation contents; + private final LookupHistoryOverlay lookupHistoryOverlay; private final GuiIconToggleButton bookmarkButton; + private final GuiIconToggleButton historyButton; // data private final BookmarkList bookmarkList; private final IClientToggleState toggleState; + private final IClientConfig clientConfig; + + // these need to be stored as strong references here because listeners are weakly stored elsewhere + @SuppressWarnings("FieldCanBeLocal") + private final IConfigListener lookupHistoryEnabledListener; + @SuppressWarnings("FieldCanBeLocal") + private final IConfigListener lookupHistoryViewSideListener; public BookmarkOverlay( BookmarkList bookmarkList, IngredientGridWithNavigation contents, + LookupHistoryOverlay lookupHistoryOverlay, IClientToggleState toggleState, + IClientConfig clientConfig, IScreenHelper screenHelper, IInternalKeyMappings keyBindings ) { this.bookmarkList = bookmarkList; this.toggleState = toggleState; + this.clientConfig = clientConfig; this.bookmarkButton = BookmarkButton.create(this, bookmarkList, toggleState, keyBindings); + this.historyButton = LookupHistoryButton.create(clientConfig); this.contents = contents; + this.lookupHistoryOverlay = lookupHistoryOverlay; this.screenPropertiesCache = new ScreenPropertiesCache(screenHelper); this.bookmarkDragManager = new BookmarkDragManager(this); bookmarkList.addSourceListChangedListener(() -> { @@ -77,6 +96,19 @@ public BookmarkOverlay( .updateScreen(minecraft.screen) .update(); }); + + lookupHistoryOverlay.getLookupHistory().addSourceListChangedListener(() -> { + Minecraft minecraft = Minecraft.getInstance(); + this.getScreenPropertiesUpdater() + .updateScreen(minecraft.screen) + .update(); + }); + + this.lookupHistoryEnabledListener = v -> onScreenPropertiesChanged(); + this.lookupHistoryViewSideListener = v -> onScreenPropertiesChanged(); + + clientConfig.addLookupHistoryEnabledListener(lookupHistoryEnabledListener); + clientConfig.addLookupHistoryDisplaySideListener(lookupHistoryViewSideListener); } public boolean isListDisplayed() { @@ -105,6 +137,16 @@ private void updateBounds(IGuiProperties guiProperties) { ImmutablePoint2i mouseExclusionArea = this.screenPropertiesCache.getMouseExclusionArea(); ImmutableRect2i availableContentsArea = displayArea.cropBottom(BUTTON_SIZE + INNER_PADDING); + if (clientConfig.isLookupHistoryEnabled() && lookupHistoryOverlay.isOnSide()) { + int historyRows = clientConfig.getMaxLookupHistoryRows(); + availableContentsArea = availableContentsArea.cropBottom(historyRows * LookupHistoryOverlay.SLOT_HEIGHT); + ImmutableRect2i historyArea = displayArea + .insetBy(BORDER_MARGIN) + .moveUp(BUTTON_SIZE + INNER_PADDING) + .keepBottom(historyRows * LookupHistoryOverlay.SLOT_HEIGHT); + this.lookupHistoryOverlay.updateBounds(historyArea, guiExclusionAreas, mouseExclusionArea); + this.lookupHistoryOverlay.updateLayout(); + } this.contents.updateBounds(availableContentsArea, guiExclusionAreas, mouseExclusionArea); this.contents.updateLayout(false); @@ -116,12 +158,16 @@ private void updateBounds(IGuiProperties guiProperties) { .keepBottom(BUTTON_SIZE) .keepLeft(BUTTON_SIZE); this.bookmarkButton.updateBounds(bookmarkButtonArea); + ImmutableRect2i historyButtonArea = bookmarkButtonArea.moveRight(2 + BUTTON_SIZE); + this.historyButton.updateBounds(historyButtonArea); } else { ImmutableRect2i bookmarkButtonArea = displayArea .insetBy(BORDER_MARGIN) .keepBottom(BUTTON_SIZE) .keepLeft(BUTTON_SIZE); this.bookmarkButton.updateBounds(bookmarkButtonArea); + ImmutableRect2i historyButtonArea = bookmarkButtonArea.moveRight(2 + BUTTON_SIZE); + this.historyButton.updateBounds(historyButtonArea); } } @@ -139,26 +185,34 @@ public void drawScreen(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, this.bookmarkDragManager.updateDrag(mouseX, mouseY); this.contents.draw(minecraft, guiGraphics, mouseX, mouseY, partialTicks); } + if (screenPropertiesCache.hasValidScreen() && toggleState.isOverlayEnabled()) { + this.lookupHistoryOverlay.draw(minecraft, guiGraphics, mouseX, mouseY, partialTicks); + } if (this.screenPropertiesCache.hasValidScreen()) { this.bookmarkButton.draw(guiGraphics, mouseX, mouseY, partialTicks); + this.historyButton.draw(guiGraphics, mouseX, mouseY, partialTicks); } } public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, int mouseY) { - if (isListDisplayed()) { - if (!this.bookmarkDragManager.drawDraggedItem(guiGraphics, mouseX, mouseY)) { + if (!this.bookmarkDragManager.drawDraggedItem(guiGraphics, mouseX, mouseY)) { + if (isListDisplayed()) { this.contents.drawTooltips(minecraft, guiGraphics, mouseX, mouseY); } + if (screenPropertiesCache.hasValidScreen() && toggleState.isOverlayEnabled()) { + this.lookupHistoryOverlay.drawTooltips(minecraft, guiGraphics, mouseX, mouseY); + } } if (this.screenPropertiesCache.hasValidScreen()) { bookmarkButton.drawTooltips(guiGraphics, mouseX, mouseY); + historyButton.drawTooltips(guiGraphics, mouseX, mouseY); } } @Override public Stream> getIngredientUnderMouse(double mouseX, double mouseY) { if (isListDisplayed()) { - return this.contents.getIngredientUnderMouse(mouseX, mouseY); + return Stream.concat(this.contents.getIngredientUnderMouse(mouseX, mouseY), this.lookupHistoryOverlay.getIngredientUnderMouse(mouseX, mouseY)); } return Stream.empty(); } @@ -166,7 +220,7 @@ public Stream> getIngredientUnderMouse(double mo @Override public Stream> getDraggableIngredientUnderMouse(double mouseX, double mouseY) { if (isListDisplayed()) { - return this.contents.getDraggableIngredientUnderMouse(mouseX, mouseY); + return Stream.concat(this.contents.getDraggableIngredientUnderMouse(mouseX, mouseY), this.lookupHistoryOverlay.getDraggableIngredientUnderMouse(mouseX, mouseY)); } return Stream.empty(); } @@ -195,18 +249,26 @@ public T getIngredientUnderMouse(IIngredientType ingredientType) { public IUserInputHandler createInputHandler() { final IUserInputHandler bookmarkButtonInputHandler = this.bookmarkButton.createInputHandler(); + final IUserInputHandler historyButtonInputHandler = this.historyButton.createInputHandler(); + + final IUserInputHandler buttonInputHandler = new CombinedInputHandler( + "BookmarkOverlayButton", + bookmarkButtonInputHandler, + historyButtonInputHandler + ); + final IUserInputHandler displayedInputHandler = new CombinedInputHandler( "BookmarkOverlay", this.contents.createInputHandler(), - bookmarkButtonInputHandler + buttonInputHandler ); return new ProxyInputHandler(() -> { if (isListDisplayed()) { return displayedInputHandler; } - return bookmarkButtonInputHandler; + return buttonInputHandler; }); } @@ -263,6 +325,10 @@ private Optional createDragTarget(IngredientListSlot ingredientListS .map(bookmark -> new DragTarget(ingredientListSlot.getArea(), bookmark, bookmarkList, 0)); } + public boolean isMouseOver(double mouseX, double mouseY) { + return this.contents.isMouseOver(mouseX, mouseY); + } + public static class ActionDragTarget extends DragTarget { private final Runnable action; diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java new file mode 100644 index 000000000..40142de9b --- /dev/null +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java @@ -0,0 +1,70 @@ +package mezz.jei.gui.overlay.bookmarks.history; + +import mezz.jei.api.recipe.IFocusFactory; +import mezz.jei.api.recipe.IRecipeManager; +import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.gui.bookmarks.IBookmark; +import mezz.jei.gui.config.ILookupHistoryConfig; +import mezz.jei.gui.overlay.IIngredientGridSource; +import mezz.jei.gui.overlay.elements.IElement; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Supplier; + +public class LookupHistory implements IIngredientGridSource { + private final List elements = new LinkedList<>(); + private final List listeners = new ArrayList<>(); + private final IRecipeManager recipeManager; + private final IIngredientManager ingredientManager; + private final IFocusFactory focusFactory; + private final Supplier maxElements; + private final ILookupHistoryConfig lookupHistoryConfig; + + public LookupHistory( + IRecipeManager recipeManager, + IIngredientManager ingredientManager, + IFocusFactory focusFactory, + Supplier maxElements, + ILookupHistoryConfig lookupHistoryConfig + ) { + this.recipeManager = recipeManager; + this.ingredientManager = ingredientManager; + this.focusFactory = focusFactory; + this.maxElements = maxElements; + this.lookupHistoryConfig = lookupHistoryConfig; + + List loaded = lookupHistoryConfig.load(recipeManager, ingredientManager, focusFactory); + this.elements.addAll(loaded); + } + + public void add(IBookmark element) { + elements.remove(element); + elements.add(0, element); + if (elements.size() > maxElements.get()) { + elements.remove(elements.size() - 1); + } + notifyListeners(); + lookupHistoryConfig.save(recipeManager, ingredientManager, focusFactory, elements); + } + + @Override + public @Unmodifiable List> getElements() { + return elements.stream() + .>map(IBookmark::getElement) + .toList(); + } + + @Override + public void addSourceListChangedListener(SourceListChangedListener listener) { + listeners.add(listener); + } + + private void notifyListeners() { + for (SourceListChangedListener listener : listeners) { + listener.onSourceListChanged(); + } + } +} \ No newline at end of file diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java new file mode 100644 index 000000000..d7873e2da --- /dev/null +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java @@ -0,0 +1,56 @@ +package mezz.jei.gui.overlay.bookmarks.history; + +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.common.Internal; +import mezz.jei.common.config.IClientConfig; +import mezz.jei.common.gui.JeiTooltip; +import mezz.jei.common.gui.textures.Textures; +import mezz.jei.gui.elements.GuiIconToggleButton; +import mezz.jei.gui.input.UserInput; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; + +public class LookupHistoryButton extends GuiIconToggleButton { + + public static LookupHistoryButton create(IClientConfig clientConfig) { + Textures textures = Internal.getTextures(); + IDrawableStatic offIcon = textures.getHistoryButtonDisabledIcon(); + IDrawableStatic onIcon = textures.getHistoryButtonEnabledICon(); + return new LookupHistoryButton(offIcon, onIcon, clientConfig); + } + + private final IClientConfig clientConfig; + + private LookupHistoryButton(IDrawable offIcon, IDrawable onIcon, IClientConfig clientConfig) { + super(offIcon, onIcon); + this.clientConfig = clientConfig; + } + + @Override + protected void getTooltips(JeiTooltip tooltip) { + if (clientConfig.isLookupHistoryEnabled()) { + tooltip.add(Component.translatable("jei.tooltip.lookupHistory.disable")); + } else { + tooltip.add(Component.translatable("jei.tooltip.lookupHistory.enable")); + } + tooltip.add( + Component.translatable("jei.tooltip.lookupHistory.usage") + .withStyle(ChatFormatting.ITALIC) + .withStyle(ChatFormatting.GRAY) + ); + } + + @Override + protected boolean isIconToggledOn() { + return clientConfig.isLookupHistoryEnabled(); + } + + @Override + protected boolean onMouseClicked(UserInput input) { + if (!input.isSimulate()) { + clientConfig.setLookupHistoryEnabled(!clientConfig.isLookupHistoryEnabled()); + } + return true; + } +} \ No newline at end of file diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java new file mode 100644 index 000000000..e194f4046 --- /dev/null +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java @@ -0,0 +1,180 @@ +package mezz.jei.gui.overlay.bookmarks.history; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import mezz.jei.api.helpers.IColorHelper; +import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.common.config.HistoryDisplaySide; +import mezz.jei.common.config.IClientConfig; +import mezz.jei.common.config.IClientToggleState; +import mezz.jei.common.config.IIngredientFilterConfig; +import mezz.jei.common.config.IIngredientGridConfig; +import mezz.jei.common.input.IInternalKeyMappings; +import mezz.jei.common.network.IConnectionToServer; +import mezz.jei.common.util.ImmutablePoint2i; +import mezz.jei.common.util.ImmutableRect2i; +import mezz.jei.gui.ingredients.GuiIngredientProperties; +import mezz.jei.gui.input.IClickableIngredientInternal; +import mezz.jei.gui.input.IDraggableIngredientInternal; +import mezz.jei.gui.input.IRecipeFocusSource; +import mezz.jei.gui.overlay.IIngredientGridSource; +import mezz.jei.gui.overlay.IngredientGrid; +import mezz.jei.gui.overlay.elements.IElement; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.util.Mth; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +public class LookupHistoryOverlay implements IRecipeFocusSource { + + private static final int INGREDIENT_PADDING = 1; + public static final int SLOT_HEIGHT = GuiIngredientProperties.getHeight(INGREDIENT_PADDING); + + // display elements + private final IngredientGrid contents; + + // data + private final IIngredientGridSource lookupHistory; + private final IClientConfig clientConfig; + private final HistoryDisplaySide ownerDisplaySide; + private int rows; + + public LookupHistoryOverlay( + IIngredientManager ingredientManager, + IIngredientGridSource lookupHistory, + IInternalKeyMappings keyMappings, + IIngredientGridConfig historyListConfig, + IIngredientFilterConfig ingredientFilterConfig, + IClientConfig clientConfig, + HistoryDisplaySide ownerDisplaySide, + IClientToggleState toggleState, + IConnectionToServer serverConnection, + IColorHelper colorHelper + ) { + this.clientConfig = clientConfig; + this.lookupHistory = lookupHistory; + this.contents = new IngredientGrid( + ingredientManager, + historyListConfig, + ingredientFilterConfig, + clientConfig, + toggleState, + serverConnection, + keyMappings, + colorHelper, + false + ); + this.ownerDisplaySide = ownerDisplaySide; + lookupHistory.addSourceListChangedListener(this::updateLayout); + } + + public boolean isListDisplayed() { + return clientConfig.isLookupHistoryEnabled() && + isOnSide() && + contents.hasRoom(); + } + + public boolean isOnSide() { + return ownerDisplaySide.equals(clientConfig.getLookupHistoryDisplaySide()); + } + + public IIngredientGridSource getLookupHistory() { + return lookupHistory; + } + + public void updateBounds(final ImmutableRect2i availableArea, Set guiExclusionAreas, @Nullable ImmutablePoint2i mouseExclusionPoint) { + this.contents.updateBounds(availableArea, guiExclusionAreas, mouseExclusionPoint); + int rows = this.contents.getArea().getHeight() / SLOT_HEIGHT; + this.rows = Math.min(rows, clientConfig.getMaxLookupHistoryRows()); + } + + public void updateLayout() { + List> ingredientList = lookupHistory.getElements(); + this.contents.set(0, ingredientList); + } + + private void drawLine(PoseStack poseStack, int x1, int x2, int y, int argbColor) { + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder builder = tesselator.getBuilder(); + builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + + float a = (float) (argbColor >> 24 & 255) / 255.0F; + float r = (float) (argbColor >> 16 & 255) / 255.0F; + float g = (float) (argbColor >> 8 & 255) / 255.0F; + float b = (float) (argbColor & 255) / 255.0F; + Matrix4f pose = poseStack.last().pose(); + + final int availableWidth = x2 - x1; + if (availableWidth <= 0) { + return; + } + final int dashWidth = 8; + final int dashHeight = 1; + final int spacing = 6; + + // space out the dashes so that we always start and end with whole dashes + final int interval = dashWidth + spacing; + final int dashCount = availableWidth / interval; + final float floatInterval = (availableWidth - dashWidth) / (float) dashCount; + + for (float x = x1; x < x2; x += floatInterval) { + builder.vertex(pose, Mth.clamp(x + dashWidth, x1, x2), y, 0).color(r, g, b, a).endVertex(); + builder.vertex(pose, Mth.clamp(x, x1, x2), y, 0).color(r, g, b, a).endVertex(); + builder.vertex(pose, Mth.clamp(x, x1, x2), y + dashHeight, 0).color(r, g, b, a).endVertex(); + builder.vertex(pose, Mth.clamp(x + dashWidth, x1, x2), y + dashHeight, 0).color(r, g, b, a).endVertex(); + } + + tesselator.end(); + RenderSystem.disableBlend(); + } + + public void draw(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { + if (isListDisplayed()) { + this.contents.draw(minecraft, guiGraphics, mouseX, mouseY); + ImmutableRect2i area = this.contents.getArea(); + int endX = area.getX() + area.getWidth(); + int startY = area.getY() + area.getHeight() - rows * SLOT_HEIGHT - 3; + int color = 0xFF959595; + drawLine(guiGraphics.pose(), area.getX(), endX, startY, color); + } + } + + public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, int mouseY) { + if (isListDisplayed()) { + this.contents.drawTooltips(minecraft, guiGraphics, mouseX, mouseY); + } + } + + public ImmutableRect2i getArea() { + return this.contents.getArea(); + } + + @Override + public Stream> getIngredientUnderMouse(double mouseX, double mouseY) { + if (isListDisplayed()) { + return contents.getIngredientUnderMouse(mouseX, mouseY); + } + return Stream.empty(); + } + + @Override + public Stream> getDraggableIngredientUnderMouse(double mouseX, double mouseY) { + if (isListDisplayed()) { + return contents.getDraggableIngredientUnderMouse(mouseX, mouseY); + } + return Stream.empty(); + } +} \ No newline at end of file diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/package-info.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/package-info.java new file mode 100644 index 000000000..94688d1f4 --- /dev/null +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package mezz.jei.gui.overlay.bookmarks.history; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/Gui/src/main/java/mezz/jei/gui/recipes/RecipeGuiLogic.java b/Gui/src/main/java/mezz/jei/gui/recipes/RecipeGuiLogic.java index 683df3b81..14374315b 100644 --- a/Gui/src/main/java/mezz/jei/gui/recipes/RecipeGuiLogic.java +++ b/Gui/src/main/java/mezz/jei/gui/recipes/RecipeGuiLogic.java @@ -2,18 +2,23 @@ import mezz.jei.api.gui.IRecipeLayoutDrawable; import mezz.jei.api.ingredients.ITypedIngredient; +import mezz.jei.api.recipe.IFocus; import mezz.jei.api.recipe.IFocusFactory; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.IRecipeManager; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.recipe.transfer.IRecipeTransferManager; +import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.common.Internal; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IJeiClientConfigs; import mezz.jei.common.config.RecipeSorterStage; import mezz.jei.common.gui.elements.DrawableNineSliceTexture; import mezz.jei.common.util.MathUtil; +import mezz.jei.gui.bookmarks.IngredientBookmark; +import mezz.jei.gui.bookmarks.RecipeBookmark; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistory; import mezz.jei.gui.recipes.layouts.IRecipeLayoutList; import mezz.jei.gui.recipes.layouts.RecipeLayoutDrawableErrored; import mezz.jei.gui.recipes.lookups.IFocusedRecipes; @@ -36,11 +41,13 @@ public class RecipeGuiLogic implements IRecipeGuiLogic { private final IRecipeManager recipeManager; private final IRecipeTransferManager recipeTransferManager; + private final IIngredientManager ingredientManager; private final IRecipeLogicStateListener stateListener; private boolean initialState = true; private ILookupState state; - private final Stack history = new Stack<>(); + private final Stack stateHistory = new Stack<>(); + private final LookupHistory lookupHistory; private final IFocusFactory focusFactory; private final IRecipeLayoutWithButtonsFactory recipeLayoutFactory; private @Nullable IRecipeCategory cachedRecipeCategory; @@ -49,12 +56,16 @@ public class RecipeGuiLogic implements IRecipeGuiLogic { public RecipeGuiLogic( IRecipeManager recipeManager, + IIngredientManager ingredientManager, + LookupHistory lookupHistory, IRecipeTransferManager recipeTransferManager, IRecipeLogicStateListener stateListener, IFocusFactory focusFactory, IRecipeLayoutWithButtonsFactory recipeLayoutFactory ) { this.recipeManager = recipeManager; + this.ingredientManager = ingredientManager; + this.lookupHistory = lookupHistory; this.recipeTransferManager = recipeTransferManager; this.stateListener = stateListener; this.recipeLayoutFactory = recipeLayoutFactory; @@ -79,8 +90,9 @@ public void tick() { @Override public boolean showFocus(IFocusGroup focuses) { + List> allFocuses = focuses.getAllFocuses(); List> recipeCategories = recipeManager.createRecipeCategoryLookup() - .limitFocus(focuses.getAllFocuses()) + .limitFocus(allFocuses) .get() .toList(); ILookupState state = IngredientLookupState.create( @@ -89,29 +101,60 @@ public boolean showFocus(IFocusGroup focuses) { recipeCategories, recipeTransferManager ); + + for (IFocus focus : allFocuses) { + IngredientBookmark ingredientBookmark = IngredientBookmark.create(focus.getTypedValue(), ingredientManager); + this.lookupHistory.add(ingredientBookmark); + } + return setState(state, true); } - @Override - public boolean showRecipes(IFocusedRecipes recipes, IFocusGroup focuses) { - ILookupState state = new SingleCategoryLookupState(recipes, focuses); + public boolean showRecipes(IFocusedRecipes focusedRecipes, IFocusGroup focuses) { + var recipeBookmark = createRecipeBookmark(recipeManager, ingredientManager, focusedRecipes, focuses); + if (recipeBookmark != null) { + this.lookupHistory.add(recipeBookmark); + } else { + for (IFocus focus : focuses.getAllFocuses()) { + IngredientBookmark ingredientBookmark = IngredientBookmark.create(focus.getTypedValue(), ingredientManager); + this.lookupHistory.add(ingredientBookmark); + } + } + ILookupState state = new SingleCategoryLookupState(focusedRecipes, focuses); return setState(state, true); } + private static @Nullable RecipeBookmark createRecipeBookmark( + IRecipeManager recipeManager, + IIngredientManager ingredientManager, + IFocusedRecipes focusedRecipes, + IFocusGroup focusGroup + ) { + IRecipeCategory recipeCategory = focusedRecipes.getRecipeCategory(); + List recipes = focusedRecipes.getRecipes(); + if (recipes.size() != 1) { + return null; + } + T recipe = recipes.get(0); + return recipeManager.createRecipeLayoutDrawable(recipeCategory, recipe, focusGroup) + .map(drawable -> RecipeBookmark.create(drawable, ingredientManager)) + .orElse(null); + } + @Override public boolean back() { - if (history.empty()) { + if (stateHistory.empty()) { return false; } - final ILookupState state = history.pop(); + final ILookupState state = stateHistory.pop(); setState(state, false); return true; } @Override public void clearHistory() { - while (!history.empty()) { - history.pop(); + while (!stateHistory.empty()) { + stateHistory.pop(); } } @@ -122,7 +165,7 @@ private boolean setState(ILookupState state, boolean saveHistory) { } if (saveHistory && !initialState) { - history.push(this.state); + stateHistory.push(this.state); } this.state = state; this.initialState = false; diff --git a/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java b/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java index f25bab211..e31491606 100644 --- a/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java +++ b/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java @@ -40,6 +40,7 @@ import mezz.jei.gui.input.MouseUtil; import mezz.jei.gui.input.UserInput; import mezz.jei.gui.input.handlers.UserInputRouter; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistory; import mezz.jei.gui.recipes.lookups.IFocusedRecipes; import mezz.jei.gui.recipes.lookups.StaticFocusedRecipes; import net.minecraft.client.Minecraft; @@ -115,6 +116,7 @@ public RecipesGui( IInternalKeyMappings keyBindings, IFocusFactory focusFactory, BookmarkList bookmarks, + LookupHistory lookupHistory, IGuiHelper guiHelper ) { super(Component.literal("Recipes")); @@ -123,6 +125,8 @@ public RecipesGui( this.keyBindings = keyBindings; this.logic = new RecipeGuiLogic( recipeManager, + ingredientManager, + lookupHistory, recipeTransferManager, this::updateLayout, focusFactory, diff --git a/Gui/src/main/java/mezz/jei/gui/startup/GuiConfigData.java b/Gui/src/main/java/mezz/jei/gui/startup/GuiConfigData.java index 68920ee90..bf1131699 100644 --- a/Gui/src/main/java/mezz/jei/gui/startup/GuiConfigData.java +++ b/Gui/src/main/java/mezz/jei/gui/startup/GuiConfigData.java @@ -1,15 +1,13 @@ package mezz.jei.gui.startup; import mezz.jei.common.platform.Services; -import mezz.jei.gui.config.BookmarkConfig; -import mezz.jei.gui.config.IBookmarkConfig; -import mezz.jei.gui.config.IngredientTypeSortingConfig; -import mezz.jei.gui.config.ModNameSortingConfig; +import mezz.jei.gui.config.*; import java.nio.file.Path; public record GuiConfigData( IBookmarkConfig bookmarkConfig, + ILookupHistoryConfig lookupHistoryConfig, ModNameSortingConfig modNameSortingConfig, IngredientTypeSortingConfig ingredientTypeSortingConfig ) { @@ -17,11 +15,13 @@ public static GuiConfigData create() { Path configDir = Services.PLATFORM.getConfigHelper().createJeiConfigDir(); IBookmarkConfig bookmarkConfig = new BookmarkConfig(configDir); + ILookupHistoryConfig lookupHistoryConfig = new LookupHistoryJsonConfig(configDir); ModNameSortingConfig ingredientModNameSortingConfig = new ModNameSortingConfig(configDir.resolve("ingredient-list-mod-sort-order.ini")); IngredientTypeSortingConfig ingredientTypeSortingConfig = new IngredientTypeSortingConfig(configDir.resolve("ingredient-list-type-sort-order.ini")); return new GuiConfigData( bookmarkConfig, + lookupHistoryConfig, ingredientModNameSortingConfig, ingredientTypeSortingConfig ); diff --git a/Gui/src/main/java/mezz/jei/gui/startup/JeiGuiStarter.java b/Gui/src/main/java/mezz/jei/gui/startup/JeiGuiStarter.java index 344986e6f..595f66953 100644 --- a/Gui/src/main/java/mezz/jei/gui/startup/JeiGuiStarter.java +++ b/Gui/src/main/java/mezz/jei/gui/startup/JeiGuiStarter.java @@ -26,6 +26,7 @@ import mezz.jei.core.util.LoggedTimer; import mezz.jei.gui.bookmarks.BookmarkList; import mezz.jei.gui.config.IBookmarkConfig; +import mezz.jei.gui.config.ILookupHistoryConfig; import mezz.jei.gui.config.IngredientTypeSortingConfig; import mezz.jei.gui.config.ModNameSortingConfig; import mezz.jei.gui.events.GuiEventHandler; @@ -50,6 +51,7 @@ import mezz.jei.gui.input.handlers.UserInputRouter; import mezz.jei.gui.overlay.IngredientListOverlay; import mezz.jei.gui.overlay.bookmarks.BookmarkOverlay; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistory; import mezz.jei.gui.recipes.RecipesGui; import mezz.jei.gui.util.FocusUtil; import net.minecraft.client.Minecraft; @@ -103,6 +105,7 @@ public static JeiEventHandlers start(IRuntimeRegistration registration) { IngredientTypeSortingConfig ingredientTypeSortingConfig = configData.ingredientTypeSortingConfig(); IClientToggleState toggleState = Internal.getClientToggleState(); IBookmarkConfig bookmarkConfig = configData.bookmarkConfig(); + ILookupHistoryConfig lookupHistoryConfig = configData.lookupHistoryConfig(); IJeiClientConfigs jeiClientConfigs = Internal.getJeiClientConfigs(); IClientConfig clientConfig = jeiClientConfigs.getClientConfig(); @@ -137,10 +140,19 @@ public static JeiEventHandlers start(IRuntimeRegistration registration) { IIngredientFilter ingredientFilterApi = new IngredientFilterApi(ingredientFilter, filterTextSource); registration.setIngredientFilter(ingredientFilterApi); + LookupHistory lookupHistory = new LookupHistory( + recipeManager, + ingredientManager, + focusFactory, + clientConfig::getMaxLookupHistoryIngredients, + lookupHistoryConfig + ); + IngredientListOverlay ingredientListOverlay = OverlayHelper.createIngredientListOverlay( ingredientManager, screenHelper, ingredientFilter, + lookupHistory, filterTextSource, keyMappings, ingredientListConfig, @@ -160,6 +172,7 @@ public static JeiEventHandlers start(IRuntimeRegistration registration) { ingredientManager, screenHelper, bookmarkList, + lookupHistory, keyMappings, bookmarkListConfig, ingredientFilterConfig, @@ -184,6 +197,7 @@ public static JeiEventHandlers start(IRuntimeRegistration registration) { keyMappings, focusFactory, bookmarkList, + lookupHistory, guiHelper ); registration.setRecipesGui(recipesGui); @@ -207,7 +221,7 @@ public static JeiEventHandlers start(IRuntimeRegistration registration) { ingredientListOverlay.createInputHandler(), bookmarkOverlay.createInputHandler(), new FocusInputHandler(recipeFocusSource, recipesGui, focusUtil, clientConfig, ingredientManager, toggleState, serverConnection), - new BookmarkInputHandler(recipeFocusSource, bookmarkList), + new BookmarkInputHandler(recipeFocusSource, bookmarkList, bookmarkOverlay), new GlobalInputHandler(toggleState), new GuiAreaInputHandler(screenHelper, recipesGui, focusFactory) ); diff --git a/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java b/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java index ab268c2a1..ecf8c238e 100644 --- a/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java +++ b/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java @@ -3,6 +3,7 @@ import mezz.jei.api.helpers.IColorHelper; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.api.runtime.IScreenHelper; +import mezz.jei.common.config.HistoryDisplaySide; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IClientToggleState; import mezz.jei.common.config.IIngredientFilterConfig; @@ -18,9 +19,11 @@ import mezz.jei.gui.overlay.IngredientGridWithNavigation; import mezz.jei.gui.overlay.IngredientListOverlay; import mezz.jei.gui.overlay.bookmarks.BookmarkOverlay; +import mezz.jei.gui.overlay.bookmarks.history.LookupHistoryOverlay; public final class OverlayHelper { - private OverlayHelper() {} + private OverlayHelper() { + } public static IngredientGridWithNavigation createIngredientGridWithNavigation( String debugName, @@ -69,6 +72,7 @@ public static IngredientListOverlay createIngredientListOverlay( IIngredientManager ingredientManager, IScreenHelper screenHelper, IIngredientGridSource ingredientFilter, + IIngredientGridSource historyList, IFilterTextSource filterTextSource, IInternalKeyMappings keyMappings, IIngredientGridConfig ingredientGridConfig, @@ -96,11 +100,25 @@ public static IngredientListOverlay createIngredientListOverlay( true ); + LookupHistoryOverlay lookupHistoryOverlay = new LookupHistoryOverlay( + ingredientManager, + historyList, + keyMappings, + ingredientGridConfig, + ingredientFilterConfig, + clientConfig, + HistoryDisplaySide.RIGHT, + toggleState, + serverConnection, + colorHelper + ); + return new IngredientListOverlay( ingredientFilter, filterTextSource, screenHelper, ingredientListGridNavigation, + lookupHistoryOverlay, clientConfig, toggleState, keyMappings @@ -111,6 +129,7 @@ public static BookmarkOverlay createBookmarkOverlay( IIngredientManager ingredientManager, IScreenHelper screenHelper, BookmarkList bookmarkList, + IIngredientGridSource lookupHistory, IInternalKeyMappings keyMappings, IIngredientGridConfig bookmarkListConfig, IIngredientFilterConfig ingredientFilterConfig, @@ -137,10 +156,25 @@ public static BookmarkOverlay createBookmarkOverlay( false ); + LookupHistoryOverlay lookupHistoryOverlay = new LookupHistoryOverlay( + ingredientManager, + lookupHistory, + keyMappings, + bookmarkListConfig, + ingredientFilterConfig, + clientConfig, + HistoryDisplaySide.LEFT, + toggleState, + serverConnection, + colorHelper + ); + return new BookmarkOverlay( bookmarkList, bookmarkListGridNavigation, + lookupHistoryOverlay, toggleState, + clientConfig, screenHelper, keyMappings ); From 3ae8de1af3d53f55a98fe4fcb4291ef530785a16 Mon Sep 17 00:00:00 2001 From: vfyjxf_ <2331007009@qq.com> Date: Sun, 26 Oct 2025 20:38:30 +0800 Subject: [PATCH 2/3] draggable lookup history --- .../gui/config/LookupHistoryJsonConfig.java | 2 +- .../gui/overlay/IngredientListOverlay.java | 11 +++++++++- .../overlay/bookmarks/BookmarkOverlay.java | 7 +++++- .../bookmarks/history/LookupHistory.java | 2 +- .../history/LookupHistoryButton.java | 2 +- .../history/LookupHistoryOverlay.java | 22 ++++++++++++++++++- .../mezz/jei/gui/startup/OverlayHelper.java | 2 ++ 7 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java b/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java index b39a83bac..08b023882 100644 --- a/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java +++ b/Gui/src/main/java/mezz/jei/gui/config/LookupHistoryJsonConfig.java @@ -160,4 +160,4 @@ private List loadBookmarks( } -} \ No newline at end of file +} diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java index 060b86028..5f4f370eb 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java @@ -22,6 +22,7 @@ import mezz.jei.gui.input.IRecipeFocusSource; import mezz.jei.gui.input.IUserInputHandler; import mezz.jei.gui.input.MouseUtil; +import mezz.jei.gui.input.handlers.CombinedDragHandler; import mezz.jei.gui.input.handlers.CombinedInputHandler; import mezz.jei.gui.input.handlers.NullDragHandler; import mezz.jei.gui.input.handlers.NullInputHandler; @@ -127,6 +128,7 @@ private void onScreenPropertiesChanged() { updateBounds(guiProperties, displayArea, guiExclusionAreas); }, () -> { this.contents.close(); + this.lookupHistoryOverlay.close(); this.searchField.setFocused(false); }); } @@ -216,6 +218,7 @@ public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouse public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { if (isListDisplayed()) { this.contents.drawOnForeground(guiGraphics, mouseX, mouseY); + this.lookupHistoryOverlay.drawOnForeground(guiGraphics, mouseX, mouseY); } } @@ -264,10 +267,16 @@ public IUserInputHandler createInputHandler() { public IDragHandler createDragHandler() { final IDragHandler displayedDragHandler = this.contents.createDragHandler(); + final IDragHandler historyDragHandler = this.lookupHistoryOverlay.createDragHandler(); + + CombinedDragHandler combinedDragHandler = new CombinedDragHandler( + displayedDragHandler, + historyDragHandler + ); return new ProxyDragHandler(() -> { if (isListDisplayed()) { - return displayedDragHandler; + return combinedDragHandler; } return NullDragHandler.INSTANCE; }); diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java index eb5ec76d5..0d116f7f1 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java @@ -128,7 +128,10 @@ public ScreenPropertiesCache.Updater getScreenPropertiesUpdater() { private void onScreenPropertiesChanged() { this.screenPropertiesCache.getGuiProperties() - .ifPresentOrElse(this::updateBounds, this.contents::close); + .ifPresentOrElse(this::updateBounds, () -> { + this.contents.close(); + this.lookupHistoryOverlay.close(); + }); } private void updateBounds(IGuiProperties guiProperties) { @@ -275,6 +278,7 @@ public IUserInputHandler createInputHandler() { public IDragHandler createDragHandler() { final IDragHandler combinedDragHandlers = new CombinedDragHandler( this.contents.createDragHandler(), + this.lookupHistoryOverlay.createDragHandler(), this.bookmarkDragManager.createDragHandler() ); @@ -289,6 +293,7 @@ public IDragHandler createDragHandler() { public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { if (isListDisplayed()) { this.contents.drawOnForeground(guiGraphics, mouseX, mouseY); + this.lookupHistoryOverlay.drawOnForeground(guiGraphics, mouseX, mouseY); } } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java index 40142de9b..d1d1ff86b 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistory.java @@ -67,4 +67,4 @@ private void notifyListeners() { listener.onSourceListChanged(); } } -} \ No newline at end of file +} diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java index d7873e2da..f40008692 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryButton.java @@ -53,4 +53,4 @@ protected boolean onMouseClicked(UserInput input) { } return true; } -} \ No newline at end of file +} diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java index e194f4046..7120faacc 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java @@ -8,6 +8,7 @@ import com.mojang.blaze3d.vertex.VertexFormat; import mezz.jei.api.helpers.IColorHelper; import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.api.runtime.IScreenHelper; import mezz.jei.common.config.HistoryDisplaySide; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IClientToggleState; @@ -17,8 +18,10 @@ import mezz.jei.common.network.IConnectionToServer; import mezz.jei.common.util.ImmutablePoint2i; import mezz.jei.common.util.ImmutableRect2i; +import mezz.jei.gui.ghost.GhostIngredientDragManager; import mezz.jei.gui.ingredients.GuiIngredientProperties; import mezz.jei.gui.input.IClickableIngredientInternal; +import mezz.jei.gui.input.IDragHandler; import mezz.jei.gui.input.IDraggableIngredientInternal; import mezz.jei.gui.input.IRecipeFocusSource; import mezz.jei.gui.overlay.IIngredientGridSource; @@ -47,6 +50,7 @@ public class LookupHistoryOverlay implements IRecipeFocusSource { private final IIngredientGridSource lookupHistory; private final IClientConfig clientConfig; private final HistoryDisplaySide ownerDisplaySide; + private final GhostIngredientDragManager ghostIngredientDragManager; private int rows; public LookupHistoryOverlay( @@ -58,6 +62,7 @@ public LookupHistoryOverlay( IClientConfig clientConfig, HistoryDisplaySide ownerDisplaySide, IClientToggleState toggleState, + IScreenHelper screenHelper, IConnectionToServer serverConnection, IColorHelper colorHelper ) { @@ -75,6 +80,7 @@ public LookupHistoryOverlay( false ); this.ownerDisplaySide = ownerDisplaySide; + this.ghostIngredientDragManager = new GhostIngredientDragManager(this.contents, screenHelper, ingredientManager, toggleState); lookupHistory.addSourceListChangedListener(this::updateLayout); } @@ -154,6 +160,7 @@ public void draw(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, int m public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, int mouseY) { if (isListDisplayed()) { + this.ghostIngredientDragManager.drawTooltips(minecraft, guiGraphics, mouseX, mouseY); this.contents.drawTooltips(minecraft, guiGraphics, mouseX, mouseY); } } @@ -162,6 +169,14 @@ public ImmutableRect2i getArea() { return this.contents.getArea(); } + public void close() { + this.ghostIngredientDragManager.stopDrag(); + } + + public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { + this.ghostIngredientDragManager.drawOnForeground(guiGraphics, mouseX, mouseY); + } + @Override public Stream> getIngredientUnderMouse(double mouseX, double mouseY) { if (isListDisplayed()) { @@ -177,4 +192,9 @@ public Stream> getDraggableIngredientUnderMouse( } return Stream.empty(); } -} \ No newline at end of file + + public IDragHandler createDragHandler() { + return this.ghostIngredientDragManager.createDragHandler(); + } + +} diff --git a/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java b/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java index ecf8c238e..0fc5b87c5 100644 --- a/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java +++ b/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java @@ -109,6 +109,7 @@ public static IngredientListOverlay createIngredientListOverlay( clientConfig, HistoryDisplaySide.RIGHT, toggleState, + screenHelper, serverConnection, colorHelper ); @@ -165,6 +166,7 @@ public static BookmarkOverlay createBookmarkOverlay( clientConfig, HistoryDisplaySide.LEFT, toggleState, + screenHelper, serverConnection, colorHelper ); From 8767118ee687fd3d772ea3cbf68cfcb42079e17c Mon Sep 17 00:00:00 2001 From: vfyjxf_ <2331007009@qq.com> Date: Sun, 26 Oct 2025 21:28:19 +0800 Subject: [PATCH 3/3] allow drag history when bookmark list is empty --- .../mezz/jei/gui/overlay/IngredientListOverlay.java | 10 ++++------ .../jei/gui/overlay/bookmarks/BookmarkOverlay.java | 8 ++++++-- .../bookmarks/history/LookupHistoryOverlay.java | 4 +++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java index 5f4f370eb..27f21f1ee 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListOverlay.java @@ -218,8 +218,8 @@ public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouse public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { if (isListDisplayed()) { this.contents.drawOnForeground(guiGraphics, mouseX, mouseY); - this.lookupHistoryOverlay.drawOnForeground(guiGraphics, mouseX, mouseY); } + this.lookupHistoryOverlay.drawOnForeground(guiGraphics, mouseX, mouseY); } public void handleTick() { @@ -266,12 +266,10 @@ public IUserInputHandler createInputHandler() { } public IDragHandler createDragHandler() { - final IDragHandler displayedDragHandler = this.contents.createDragHandler(); - final IDragHandler historyDragHandler = this.lookupHistoryOverlay.createDragHandler(); - CombinedDragHandler combinedDragHandler = new CombinedDragHandler( - displayedDragHandler, - historyDragHandler + final IDragHandler combinedDragHandler = new CombinedDragHandler( + this.contents.createDragHandler(), + this.lookupHistoryOverlay.createDragHandler() ); return new ProxyDragHandler(() -> { diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java index 0d116f7f1..17352ae37 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java @@ -276,9 +276,10 @@ public IUserInputHandler createInputHandler() { } public IDragHandler createDragHandler() { + final IDragHandler historyDragHandler = this.lookupHistoryOverlay.createDragHandler(); final IDragHandler combinedDragHandlers = new CombinedDragHandler( this.contents.createDragHandler(), - this.lookupHistoryOverlay.createDragHandler(), + historyDragHandler, this.bookmarkDragManager.createDragHandler() ); @@ -286,6 +287,9 @@ public IDragHandler createDragHandler() { if (isListDisplayed()) { return combinedDragHandlers; } + if (lookupHistoryOverlay.isListDisplayed()){ + return historyDragHandler; + } return NullDragHandler.INSTANCE; }); } @@ -293,8 +297,8 @@ public IDragHandler createDragHandler() { public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { if (isListDisplayed()) { this.contents.drawOnForeground(guiGraphics, mouseX, mouseY); - this.lookupHistoryOverlay.drawOnForeground(guiGraphics, mouseX, mouseY); } + this.lookupHistoryOverlay.drawOnForeground(guiGraphics, mouseX, mouseY); } public List createBookmarkDragTargets() { diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java index 7120faacc..d5909acbf 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/history/LookupHistoryOverlay.java @@ -174,7 +174,9 @@ public void close() { } public void drawOnForeground(GuiGraphics guiGraphics, int mouseX, int mouseY) { - this.ghostIngredientDragManager.drawOnForeground(guiGraphics, mouseX, mouseY); + if (isListDisplayed()) { + this.ghostIngredientDragManager.drawOnForeground(guiGraphics, mouseX, mouseY); + } } @Override