From 956b2efe975f20d0fd68270d9855bf8d2bc47865 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 27 Aug 2021 22:36:16 +0800 Subject: Add hints for if REI does not initialize properly --- .../me/shedaniel/rei/RoughlyEnoughItemsCore.java | 14 +++- .../rei/RoughlyEnoughItemsCoreClient.java | 17 +++-- .../shedaniel/rei/impl/client/REIRuntimeImpl.java | 21 ++++- .../client/config/entries/ReloadPluginsEntry.java | 2 +- .../favorites/FavoriteEntryTypeRegistryImpl.java | 6 ++ .../rei/impl/client/gui/hints/HintProvider.java | 44 +++++++++++ .../gui/screen/UncertainDisplayViewingScreen.java | 2 +- .../gui/widget/search/OverlaySearchField.java | 66 +++++++++++++++- .../registry/category/CategoryRegistryImpl.java | 5 ++ .../client/registry/screen/ScreenRegistryImpl.java | 6 ++ .../impl/client/subsets/SubsetsRegistryImpl.java | 6 ++ .../comparison/EntryComparatorRegistryImpl.java | 6 ++ .../impl/common/entry/type/EntryRegistryImpl.java | 6 ++ .../common/entry/type/EntryTypeRegistryImpl.java | 6 ++ .../common/fluid/FluidSupportProviderImpl.java | 6 ++ .../rei/impl/common/plugins/PluginManagerImpl.java | 11 +-- .../plugin/client/DefaultClientRuntimePlugin.java | 14 ++++ .../plugin/client/PluginStageExecutionWatcher.java | 89 ++++++++++++++++++++++ .../plugin/client/SearchBarHighlightWatcher.java | 55 +++++++++++++ 19 files changed, 363 insertions(+), 19 deletions(-) create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/hints/HintProvider.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/plugin/client/PluginStageExecutionWatcher.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/plugin/client/SearchBarHighlightWatcher.java (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java index 840c3b34a..50349d2ce 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java @@ -27,6 +27,7 @@ import me.shedaniel.architectury.platform.Platform; import me.shedaniel.architectury.registry.ReloadListeners; import me.shedaniel.architectury.utils.Env; import me.shedaniel.architectury.utils.EnvExecutor; +import me.shedaniel.cloth.clothconfig.shadowed.blue.endless.jankson.annotation.Nullable; import me.shedaniel.rei.api.common.entry.comparison.FluidComparatorRegistry; import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry; import me.shedaniel.rei.api.common.entry.type.EntryType; @@ -36,6 +37,7 @@ import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.plugins.PluginView; import me.shedaniel.rei.api.common.plugins.REIPlugin; import me.shedaniel.rei.api.common.plugins.REIServerPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.transfer.info.MenuInfoRegistry; import me.shedaniel.rei.impl.Internals; import me.shedaniel.rei.impl.common.category.CategoryIdentifierImpl; @@ -112,13 +114,19 @@ public class RoughlyEnoughItemsCore { new MenuInfoRegistryImpl()), "serverPluginManager"); } - public static void _reloadPlugins() { + public static void _reloadPlugins(@Nullable ReloadStage stage) { + if (stage == null) { + for (ReloadStage reloadStage : ReloadStage.values()) { + _reloadPlugins(reloadStage); + } + return; + } try { for (PluginManager> instance : PluginManager.getActiveInstances()) { instance.view().pre(); } for (PluginManager> instance : PluginManager.getActiveInstances()) { - instance.startReload(); + instance.startReload(stage); } for (PluginManager> instance : PluginManager.getActiveInstances()) { instance.view().post(); @@ -136,7 +144,7 @@ public class RoughlyEnoughItemsCore { if (Platform.getEnvironment() == Env.SERVER) { MutableLong lastReload = new MutableLong(-1); ReloadListeners.registerReloadListener(PackType.SERVER_DATA, (preparationBarrier, resourceManager, profilerFiller, profilerFiller2, executor, executor2) -> { - return preparationBarrier.wait(Unit.INSTANCE).thenRunAsync(RoughlyEnoughItemsCore::_reloadPlugins, executor2); + return preparationBarrier.wait(Unit.INSTANCE).thenRunAsync(() -> RoughlyEnoughItemsCore._reloadPlugins(null), executor2); }); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java index a2f572a6e..8bf56ba8e 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -25,10 +25,13 @@ package me.shedaniel.rei; import com.google.common.collect.Lists; import com.mojang.serialization.DataResult; +import me.shedaniel.architectury.event.Event; +import me.shedaniel.architectury.event.EventFactory; import me.shedaniel.architectury.event.events.GuiEvent; import me.shedaniel.architectury.event.events.RecipeUpdateEvent; import me.shedaniel.architectury.event.events.client.ClientScreenInputEvent; import me.shedaniel.architectury.networking.NetworkManager; +import me.shedaniel.architectury.platform.Platform; import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigObject; @@ -47,6 +50,7 @@ import me.shedaniel.rei.api.client.registry.screen.OverlayDecider; import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.plugins.PluginView; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.ClientInternals; import me.shedaniel.rei.impl.client.REIRuntimeImpl; @@ -107,6 +111,7 @@ import java.util.stream.Stream; @Environment(EnvType.CLIENT) public class RoughlyEnoughItemsCoreClient { + public static final Event PRE_UPDATE_RECIPES = EventFactory.createLoop(); @ApiStatus.Experimental public static boolean isLeftMousePressed = false; private static final ExecutorService RELOAD_PLUGINS = Executors.newSingleThreadScheduledExecutor(task -> { @@ -261,8 +266,10 @@ public class RoughlyEnoughItemsCoreClient { private void registerEvents() { Minecraft client = Minecraft.getInstance(); final ResourceLocation recipeButtonTex = new ResourceLocation("textures/gui/recipe_button.png"); - MutableLong lastReload = new MutableLong(-1); - RecipeUpdateEvent.EVENT.register(recipeManager -> reloadPlugins(lastReload)); + MutableLong startReload = new MutableLong(-1); + MutableLong endReload = new MutableLong(-1); + PRE_UPDATE_RECIPES.register(recipeManager -> reloadPlugins(startReload, ReloadStage.START)); + RecipeUpdateEvent.EVENT.register(recipeManager -> reloadPlugins(endReload, Platform.isFabric() ? ReloadStage.END : null)); GuiEvent.INIT_POST.register((screen, widgets, children) -> { REIRuntimeImpl.getInstance().setPreviousScreen(screen); if (ConfigObject.getInstance().doesDisableRecipeBook() && screen instanceof AbstractContainerScreen) { @@ -357,7 +364,7 @@ public class RoughlyEnoughItemsCoreClient { } @ApiStatus.Internal - public static void reloadPlugins(MutableLong lastReload) { + public static void reloadPlugins(MutableLong lastReload, @Nullable ReloadStage start) { if (lastReload != null) { if (lastReload.getValue() > 0 && System.currentTimeMillis() - lastReload.getValue() <= 5000) { RoughlyEnoughItemsCore.LOGGER.warn("Suppressing Reload Plugins!"); @@ -366,9 +373,9 @@ public class RoughlyEnoughItemsCoreClient { lastReload.setValue(System.currentTimeMillis()); } if (ConfigObject.getInstance().doesRegisterRecipesInAnotherThread()) { - CompletableFuture.runAsync(RoughlyEnoughItemsCore::_reloadPlugins, RELOAD_PLUGINS); + CompletableFuture.runAsync(() -> RoughlyEnoughItemsCore._reloadPlugins(start), RELOAD_PLUGINS); } else { - RoughlyEnoughItemsCore._reloadPlugins(); + RoughlyEnoughItemsCore._reloadPlugins(start); } } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java index 7f1328db5..3e5582bdd 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java @@ -38,7 +38,9 @@ import me.shedaniel.rei.api.client.gui.widgets.TextField; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.overlay.ScreenOverlay; import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; +import me.shedaniel.rei.impl.client.gui.hints.HintProvider; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -50,8 +52,7 @@ import net.minecraft.world.InteractionResult; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.util.LinkedHashSet; -import java.util.Optional; +import java.util.*; @ApiStatus.Internal @Environment(EnvType.CLIENT) @@ -65,6 +66,7 @@ public class REIRuntimeImpl implements REIRuntime { private AbstractContainerScreen previousContainerScreen = null; private Screen previousScreen = null; private LinkedHashSet lastDisplayScreen = Sets.newLinkedHashSetWithExpectedSize(10); + private List hintProviders = new ArrayList<>(); /** * @return the instance of screen helper @@ -75,6 +77,14 @@ public class REIRuntimeImpl implements REIRuntime { return (REIRuntimeImpl) REIRuntime.getInstance(); } + public void addHintProvider(HintProvider provider) { + this.hintProviders.add(provider); + } + + public List getHintProviders() { + return Collections.unmodifiableList(hintProviders); + } + @Override public void queueTooltip(@Nullable Tooltip tooltip) { if (overlay != null && tooltip != null) { @@ -211,7 +221,12 @@ public class REIRuntimeImpl implements REIRuntime { } @Override - public void endReload() { + public void startReload(ReloadStage stage) { + startReload(); + } + + @Override + public void endReload(ReloadStage stage) { getOverlay().ifPresent(ScreenOverlay::queueReloadOverlay); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java index 839fae68d..e72f8318c 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java @@ -47,7 +47,7 @@ import java.util.Optional; @ApiStatus.Internal public class ReloadPluginsEntry extends AbstractConfigListEntry { private int width; - private AbstractWidget buttonWidget = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> RoughlyEnoughItemsCoreClient.reloadPlugins(null)) { + private AbstractWidget buttonWidget = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> RoughlyEnoughItemsCoreClient.reloadPlugins(null, null)) { @Override public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { if (PluginManager.areAnyReloading()) { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java index f5b2aedfe..fb5787276 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java @@ -31,6 +31,7 @@ import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; @@ -46,6 +47,11 @@ public class FavoriteEntryTypeRegistryImpl implements FavoriteEntryType.Registry private final BiMap> registry = HashBiMap.create(); private final Map sections = Maps.newLinkedHashMap(); + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void acceptPlugin(REIClientPlugin plugin) { plugin.registerFavorites(this); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/hints/HintProvider.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/hints/HintProvider.java new file mode 100644 index 000000000..e34544294 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/hints/HintProvider.java @@ -0,0 +1,44 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.hints; + +import me.shedaniel.math.Color; +import me.shedaniel.math.Point; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@Environment(EnvType.CLIENT) +public interface HintProvider { + List provide(); + + @Nullable + Tooltip provideTooltip(Point mouse); + + Color getColor(); +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/UncertainDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/UncertainDisplayViewingScreen.java index 6cba06206..7922e4187 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/UncertainDisplayViewingScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/UncertainDisplayViewingScreen.java @@ -146,7 +146,7 @@ public class UncertainDisplayViewingScreen extends Screen { } else if (allModsUsingJEI != null && jeiEnabled) { ConfigManagerImpl.getInstance().getConfig().setJEICompatibilityLayerEnabled(jeiEnabled); ConfigManager.getInstance().saveConfig(); - RoughlyEnoughItemsCoreClient.reloadPlugins(null); + RoughlyEnoughItemsCoreClient.reloadPlugins(null, null); Minecraft.getInstance().setScreen(new ConfigReloadingScreen(() -> callback.accept(original))); } else { callback.accept(original); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java index 08433acae..50693844c 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java @@ -26,14 +26,21 @@ package me.shedaniel.rei.impl.client.gui.widget.search; import com.google.common.collect.Lists; import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.*; +import com.mojang.datafixers.util.Pair; +import com.mojang.math.Matrix4f; import me.shedaniel.math.Color; import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.gui.config.SyntaxHighlightingMode; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; +import me.shedaniel.rei.impl.client.gui.hints.HintProvider; import me.shedaniel.rei.impl.client.gui.text.TextTransformations; import me.shedaniel.rei.impl.client.gui.widget.basewidgets.TextFieldWidget; import me.shedaniel.rei.impl.client.search.argument.type.ArgumentType; @@ -41,14 +48,17 @@ import me.shedaniel.rei.impl.client.search.argument.type.ArgumentTypesRegistry; import me.shedaniel.rei.impl.client.search.argument.type.TextArgumentType; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.Tuple; import org.jetbrains.annotations.ApiStatus; +import org.lwjgl.opengl.GL11; import java.util.List; import java.util.function.Consumer; @@ -130,11 +140,65 @@ public class OverlaySearchField extends TextFieldWidget implements TextFieldWidg public void laterRender(PoseStack matrices, int int_1, int int_2, float float_1) { RenderSystem.disableDepthTest(); + if (isMain) drawHint(matrices, int_1, int_2); setSuggestion(!isFocused() && getText().isEmpty() ? I18n.get("text.rei.search.field.suggestion") : null); super.render(matrices, int_1, int_2, float_1); RenderSystem.enableDepthTest(); } + private void drawHint(PoseStack poses, int int_1, int int_2) { + List> hints = CollectionUtils.flatMap(REIRuntimeImpl.getInstance().getHintProviders(), provider -> + CollectionUtils.map(provider.provide(), component -> new Pair<>(provider, component))); + if (hints.isEmpty()) return; + int width = getBounds().getWidth() - 4; + List> sequences = CollectionUtils.flatMap(hints, pair -> + CollectionUtils.map(font.split(pair.getSecond(), width - 6), sequence -> new Pair<>(pair.getFirst(), sequence))); + Color color = hints.stream() + .map(Pair::getFirst) + .distinct() + .map(HintProvider::getColor) + .reduce((color1, color2) -> { + int r = color1.getRed() - (color1.getRed() - color2.getRed()) / 2; + int g = color1.getGreen() - (color1.getGreen() - color2.getGreen()) / 2; + int b = color1.getBlue() - (color1.getBlue() - color2.getBlue()) / 2; + return Color.ofRGBA(r, g, b, (color1.getAlpha() + color2.getAlpha()) / 2); + }).orElse(Color.ofTransparent(0x50000000)); + int height = 6 + font.lineHeight * sequences.size(); + int x = getBounds().getX() + 2; + int y = getBounds().getY() - height; + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder bufferBuilder = tesselator.getBuilder(); + bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormat.POSITION_COLOR); + Matrix4f pose = poses.last().pose(); + int background = 0xf0100010; + int color1 = color.getColor(); + int color2 = color.darker(2).getColor(); + fillGradient(pose, bufferBuilder, x, y - 1, x + width, y, 400, background, background); + fillGradient(pose, bufferBuilder, x, y + height, x + width, y + height + 1, 400, background, background); + fillGradient(pose, bufferBuilder, x, y, x + width, y + height, 400, background, background); + fillGradient(pose, bufferBuilder, x - 1, y, x, y + height, 400, background, background); + fillGradient(pose, bufferBuilder, x + width, y, x + width + 1, y + height, 400, background, background); + fillGradient(pose, bufferBuilder, x, y + 1, x + 1, y + height - 1, 400, color1, color2); + fillGradient(pose, bufferBuilder, x + width - 1, y + 1, x + width, y + height - 1, 400, color1, color2); + fillGradient(pose, bufferBuilder, x, y, x + width, y + 1, 400, color1, color1); + fillGradient(pose, bufferBuilder, x, y + height - 1, x + width, y + height, 400, color2, color2); + bufferBuilder.end(); + BufferUploader.end(bufferBuilder); + poses.pushPose(); + poses.translate(0.0D, 0.0D, 400.0D); + for (int i = 0; i < sequences.size(); i++) { + Pair pair = sequences.get(i); + int lineWidth = font.drawShadow(poses, pair.getSecond(), x + 3, y + 3 + font.lineHeight * i, -1); + if (new Rectangle(x + 3, y + 3 + font.lineHeight * i, lineWidth, font.lineHeight).contains(int_1, int_2)) { + Tooltip tooltip = pair.getFirst().provideTooltip(new Point(int_1, int_2)); + if (tooltip != null) { + tooltip.queue(); + } + } + } + poses.popPose(); + } + @Override protected void renderSuggestion(PoseStack matrices, int x, int y) { matrices.pushPose(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java index 0ab51036f..c9941c2db 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/category/CategoryRegistryImpl.java @@ -75,6 +75,11 @@ public class CategoryRegistryImpl implements CategoryRegistry { return (CategoryConfiguration) Objects.requireNonNull(this.categories.get(category), category.toString()); } + @Override + public Optional> tryGet(CategoryIdentifier category) { + return Optional.ofNullable((CategoryConfiguration) this.categories.get(category)); + } + @Override public void configure(CategoryIdentifier category, Consumer> action) { if (this.categories.containsKey(category)) { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/screen/ScreenRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/screen/ScreenRegistryImpl.java index 60d943268..89df30b89 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/screen/ScreenRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/screen/ScreenRegistryImpl.java @@ -39,6 +39,7 @@ import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.screen.*; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.EntryStacks; import net.fabricmc.api.EnvType; @@ -69,6 +70,11 @@ public class ScreenRegistryImpl implements ScreenRegistry { private ExclusionZones exclusionZones; private Class tmpScreen; + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void acceptPlugin(REIClientPlugin plugin) { plugin.registerScreens(this); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/subsets/SubsetsRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/subsets/SubsetsRegistryImpl.java index 9cbdfd76c..7e2913f55 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/subsets/SubsetsRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/subsets/SubsetsRegistryImpl.java @@ -28,6 +28,7 @@ import com.google.common.collect.Sets; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.subsets.SubsetsRegistry; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.util.CollectionUtils; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -42,6 +43,11 @@ import java.util.*; public class SubsetsRegistryImpl implements SubsetsRegistry { private final Map>> paths = Maps.newHashMap(); + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void acceptPlugin(REIClientPlugin plugin) { plugin.registerSubsets(this); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/comparison/EntryComparatorRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/comparison/EntryComparatorRegistryImpl.java index 51d91cb14..38fe8e118 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/comparison/EntryComparatorRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/comparison/EntryComparatorRegistryImpl.java @@ -26,6 +26,7 @@ package me.shedaniel.rei.impl.common.entry.comparison; import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext; import me.shedaniel.rei.api.common.entry.comparison.EntryComparator; import me.shedaniel.rei.api.common.entry.comparison.EntryComparatorRegistry; +import me.shedaniel.rei.api.common.registry.ReloadStage; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.ApiStatus; @@ -46,6 +47,11 @@ public abstract class EntryComparatorRegistryImpl implements EntryComparat } } + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void startReload() { comparators.clear(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java index 07c0e618c..a52ee508a 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java @@ -31,6 +31,7 @@ import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; @@ -68,6 +69,11 @@ public class EntryRegistryImpl implements EntryRegistry { plugin.registerEntries(this); } + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void startReload() { entries.clear(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryTypeRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryTypeRegistryImpl.java index 43e3531ce..f25f2d13f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryTypeRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryTypeRegistryImpl.java @@ -32,6 +32,7 @@ import me.shedaniel.rei.api.common.entry.type.EntryType; import me.shedaniel.rei.api.common.entry.type.EntryTypeBridge; import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry; import me.shedaniel.rei.api.common.plugins.REIPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; @@ -45,6 +46,11 @@ public class EntryTypeRegistryImpl implements EntryTypeRegistry { private final BiMap> entryTypes = HashBiMap.create(); private final Table>> typeBridges = HashBasedTable.create(); + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void acceptPlugin(REIPlugin plugin) { plugin.registerEntryTypes(this); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/fluid/FluidSupportProviderImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/fluid/FluidSupportProviderImpl.java index 16e2e0973..386438bc0 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/fluid/FluidSupportProviderImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/fluid/FluidSupportProviderImpl.java @@ -30,6 +30,7 @@ import me.shedaniel.architectury.fluid.FluidStack; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.fluid.FluidSupportProvider; import me.shedaniel.rei.api.common.plugins.REIPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; import net.minecraft.world.item.ItemStack; import org.apache.commons.lang3.BooleanUtils; import org.jetbrains.annotations.ApiStatus; @@ -46,6 +47,11 @@ public class FluidSupportProviderImpl extends ForwardingList providers = Lists.newCopyOnWriteArrayList(); private final List immutable = Collections.unmodifiableList(providers); + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + @Override public void acceptPlugin(REIPlugin plugin) { plugin.registerFluidSupport(this); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/plugins/PluginManagerImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/plugins/PluginManagerImpl.java index 5225c1afb..82bc8f518 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/plugins/PluginManagerImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/plugins/PluginManagerImpl.java @@ -32,6 +32,7 @@ import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.plugins.PluginView; import me.shedaniel.rei.api.common.plugins.REIPlugin; import me.shedaniel.rei.api.common.plugins.REIPluginProvider; +import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.registry.Reloadable; import me.shedaniel.rei.api.common.util.CollectionUtils; import net.minecraft.Util; @@ -167,7 +168,7 @@ public class PluginManagerImpl

> implements PluginManager< } @Override - public void startReload() { + public void startReload(ReloadStage stage) { try { reloading = true; long startTime = Util.getMillis(); @@ -176,7 +177,7 @@ public class PluginManagerImpl

> implements PluginManager< for (Reloadable

reloadable : reloadables) { Class reloadableClass = reloadable.getClass(); try (SectionClosable startReload = section(sectionData, "start-reload-" + MoreObjects.firstNonNull(reloadableClass.getSimpleName(), reloadableClass.getName()))) { - reloadable.startReload(); + reloadable.startReload(stage); } catch (Throwable throwable) { throwable.printStackTrace(); } @@ -184,18 +185,18 @@ public class PluginManagerImpl

> implements PluginManager< List

plugins = new ArrayList<>(getPlugins().toList()); plugins.sort(Comparator.comparingDouble(P::getPriority).reversed()); - RoughlyEnoughItemsCore.LOGGER.info("Reloading Plugin Manager [%s], registered %d plugins: %s", pluginClass.getSimpleName(), plugins.size(), CollectionUtils.mapAndJoinToString(plugins, REIPlugin::getPluginProviderName, ", ")); + RoughlyEnoughItemsCore.LOGGER.info("Reloading Plugin Manager [%s] stage [%s], registered %d plugins: %s", pluginClass.getSimpleName(), stage.toString(), plugins.size(), CollectionUtils.mapAndJoinToString(plugins, REIPlugin::getPluginProviderName, ", ")); Collections.reverse(plugins); for (Reloadable

reloadable : getReloadables()) { Class reloadableClass = reloadable.getClass(); - pluginSection(sectionData, "reloadable-plugin-" + MoreObjects.firstNonNull(reloadableClass.getSimpleName(), reloadableClass.getName()), plugins, reloadable::acceptPlugin); + pluginSection(sectionData, "reloadable-plugin-" + MoreObjects.firstNonNull(reloadableClass.getSimpleName(), reloadableClass.getName()), plugins, plugin -> reloadable.acceptPlugin(plugin, stage)); } for (Reloadable

reloadable : reloadables) { Class reloadableClass = reloadable.getClass(); try (SectionClosable endReload = section(sectionData, "end-reload-" + MoreObjects.firstNonNull(reloadableClass.getSimpleName(), reloadableClass.getName()))) { - reloadable.endReload(); + reloadable.endReload(stage); } catch (Throwable throwable) { throwable.printStackTrace(); } diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientRuntimePlugin.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientRuntimePlugin.java index ae8ea8f6d..153fe4e80 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientRuntimePlugin.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientRuntimePlugin.java @@ -50,8 +50,12 @@ import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; import me.shedaniel.rei.api.client.util.ClientEntryStacks; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.plugins.PluginManager; +import me.shedaniel.rei.api.common.plugins.REIPlugin; +import me.shedaniel.rei.api.common.registry.Reloadable; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.client.ClientHelperImpl; +import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.screen.AbstractDisplayViewingScreen; import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen; @@ -76,6 +80,16 @@ import java.util.function.Function; @Environment(EnvType.CLIENT) @ApiStatus.Internal public class DefaultClientRuntimePlugin implements REIClientPlugin { + @SuppressWarnings("rawtypes") + public DefaultClientRuntimePlugin() { + PluginStageExecutionWatcher watcher = new PluginStageExecutionWatcher(); + for (PluginManager> instance : PluginManager.getActiveInstances()) { + instance.registerReloadable((Reloadable) watcher.reloadable(instance)); + } + REIRuntimeImpl.getInstance().addHintProvider(watcher); + REIRuntimeImpl.getInstance().addHintProvider(new SearchBarHighlightWatcher()); + } + @Override public void registerEntries(EntryRegistry registry) { if (ClientHelperImpl.getInstance().isAprilFools.get()) { diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/PluginStageExecutionWatcher.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/PluginStageExecutionWatcher.java new file mode 100644 index 000000000..b520f3858 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/PluginStageExecutionWatcher.java @@ -0,0 +1,89 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client; + +import com.google.common.collect.ImmutableList; +import me.shedaniel.math.Color; +import me.shedaniel.math.Point; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.common.plugins.PluginManager; +import me.shedaniel.rei.api.common.plugins.REIPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; +import me.shedaniel.rei.api.common.registry.Reloadable; +import me.shedaniel.rei.impl.client.gui.hints.HintProvider; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.stream.Collectors; + +public class PluginStageExecutionWatcher implements HintProvider { + private Map, Set> allStages = new HashMap<>(); + + public > Reloadable reloadable(PluginManager manager) { + return new Reloadable() { + @Override + public void startReload() { + for (ReloadStage stage : ReloadStage.values()) { + startReload(stage); + } + } + + @Override + public void startReload(ReloadStage stage) { + Set stages = allStages.computeIfAbsent(manager, $ -> new HashSet<>()); + if (stage.ordinal() == 0) stages.clear(); + stages.add(stage); + } + }; + } + + public Set notVisited() { + Set notVisited = new HashSet<>(Arrays.asList(ReloadStage.values())); + notVisited.removeIf(stage -> allStages.values().stream().allMatch(stages -> stages.contains(stage))); + return notVisited; + } + + @Override + public List provide() { + Set notVisited = notVisited(); + if (notVisited.isEmpty()) { + return Collections.emptyList(); + } else { + return ImmutableList.of(new TranslatableComponent("text.rei.not.fully.initialized")); + } + } + + @Override + @Nullable + public Tooltip provideTooltip(Point mouse) { + return Tooltip.create(mouse, new TranslatableComponent("text.rei.not.fully.initialized.tooltip", notVisited().stream().map(Enum::name).collect(Collectors.joining(", ")))); + } + + @Override + public Color getColor() { + return Color.ofTransparent(0x50ff1500); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/SearchBarHighlightWatcher.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/SearchBarHighlightWatcher.java new file mode 100644 index 000000000..c1be2b7ca --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/SearchBarHighlightWatcher.java @@ -0,0 +1,55 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client; + +import me.shedaniel.math.Color; +import me.shedaniel.math.Point; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.impl.client.gui.hints.HintProvider; +import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class SearchBarHighlightWatcher implements HintProvider { + @Override + public List provide() { + return OverlaySearchField.isHighlighting ? Collections.singletonList(new TranslatableComponent("text.rei.inventory.highlighting.enabled")) : + Collections.emptyList(); + } + + @Override + @Nullable + public Tooltip provideTooltip(Point mouse) { + return Tooltip.create(mouse, new TranslatableComponent("text.rei.inventory.highlighting.enabled.tooltip")); + } + + @Override + public Color getColor() { + return Color.ofTransparent(0x50f7ed23); + } +} -- cgit