From 113fe8f692f4f9bb113d28f6a1b3375bd8f0eec8 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 27 Aug 2021 05:26:06 +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 | 41 +++++++++++ .../gui/screen/UncertainDisplayViewingScreen.java | 2 +- .../gui/widget/search/OverlaySearchField.java | 66 ++++++++++++++++- .../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 | 21 ++++-- .../common/runtime/DefaultRuntimePlugin.java | 11 ++- .../runtime/PluginStageExecutionWatcher.java | 83 ++++++++++++++++++++++ .../common/runtime/SearchBarHighlightWatcher.java | 55 ++++++++++++++ 18 files changed, 352 insertions(+), 23 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/common/runtime/PluginStageExecutionWatcher.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/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 fe495d876..d6f6ac5a1 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 dev.architectury.platform.Platform; import dev.architectury.registry.ReloadListenerRegistry; import dev.architectury.utils.Env; import dev.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,10 +114,16 @@ 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.startReload(); + instance.startReload(stage); } } catch (Throwable throwable) { throwable.printStackTrace(); @@ -130,7 +138,7 @@ public class RoughlyEnoughItemsCore { if (Platform.getEnvironment() == Env.SERVER) { MutableLong lastReload = new MutableLong(-1); ReloadListenerRegistry.register(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 2f09e6a22..2b3a9aef4 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -25,11 +25,14 @@ package me.shedaniel.rei; import com.google.common.collect.Lists; import com.mojang.serialization.DataResult; +import dev.architectury.event.Event; +import dev.architectury.event.EventFactory; import dev.architectury.event.EventResult; import dev.architectury.event.events.client.ClientGuiEvent; import dev.architectury.event.events.client.ClientRecipeUpdateEvent; import dev.architectury.event.events.client.ClientScreenInputEvent; import dev.architectury.networking.NetworkManager; +import dev.architectury.platform.Platform; import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigObject; @@ -48,6 +51,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; @@ -108,6 +112,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 -> { @@ -262,8 +267,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); - ClientRecipeUpdateEvent.EVENT.register(recipeManager -> reloadPlugins(lastReload)); + MutableLong startReload = new MutableLong(-1); + MutableLong endReload = new MutableLong(-1); + PRE_UPDATE_RECIPES.register(recipeManager -> reloadPlugins(endReload, ReloadStage.START)); + ClientRecipeUpdateEvent.EVENT.register(recipeManager -> reloadPlugins(endReload, Platform.isFabric() ? ReloadStage.END : null)); ClientGuiEvent.INIT_POST.register((screen, access) -> { REIRuntimeImpl.getInstance().setPreviousScreen(screen); if (ConfigObject.getInstance().doesDisableRecipeBook() && screen instanceof AbstractContainerScreen) { @@ -359,7 +366,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!"); @@ -368,9 +375,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 956bfd62a..07a94a0b3 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 @@ -39,7 +39,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.resources.ResourceLocation; 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 81944d716..a96680983 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 @@ -48,7 +48,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..d66c63387 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/hints/HintProvider.java @@ -0,0 +1,41 @@ +/* + * 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.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +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 8a630cfd6..1ec5aa3f5 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..8c82258ec 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,8 +48,10 @@ 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; @@ -130,11 +139,66 @@ 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(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + bufferBuilder.begin(VertexFormat.Mode.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/screen/ScreenRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/screen/ScreenRegistryImpl.java index 0577de76e..6456c7aa9 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; @@ -68,6 +69,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 00ae2d0c4..47d1f277c 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 dev.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.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -45,6 +46,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 0c43edeee..48e818d32 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; @@ -149,7 +150,7 @@ public class PluginManagerImpl

> implements PluginManager< } @Override - public void startReload() { + public void startReload(ReloadStage stage) { try { reloading = true; long startTime = Util.getMillis(); @@ -158,7 +159,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(); } @@ -166,20 +167,26 @@ 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); - pluginSection(sectionData, "pre-register", plugins, REIPlugin::preRegister); + if (stage == ReloadStage.START) { + pluginSection(sectionData, "pre-register", plugins, REIPlugin::preRegister); + } + 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)); + } + + if (stage == ReloadStage.END) { + pluginSection(sectionData, "post-register", plugins, REIPlugin::postRegister); } - pluginSection(sectionData, "post-register", plugins, REIPlugin::postRegister); 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/common/runtime/DefaultRuntimePlugin.java b/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/DefaultRuntimePlugin.java index 8aeff8a20..08911b34b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/DefaultRuntimePlugin.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/DefaultRuntimePlugin.java @@ -29,11 +29,11 @@ import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.fluid.FluidSupportProvider; +import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.plugins.REIServerPlugin; +import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.plugin.client.entry.FluidEntryDefinition; import me.shedaniel.rei.plugin.client.entry.ItemEntryDefinition; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; @@ -44,6 +44,13 @@ import java.util.stream.Stream; public class DefaultRuntimePlugin implements REIServerPlugin { public static final ResourceLocation PLUGIN = new ResourceLocation("roughlyenoughitems", "default_runtime_plugin"); + public DefaultRuntimePlugin() { + PluginStageExecutionWatcher watcher = new PluginStageExecutionWatcher(); + PluginManager.getInstance().registerReloadable(watcher); + REIRuntimeImpl.getInstance().addHintProvider(watcher); + REIRuntimeImpl.getInstance().addHintProvider(new SearchBarHighlightWatcher()); + } + @Override public void registerEntryTypes(EntryTypeRegistry registry) { registry.register(VanillaEntryTypes.ITEM, new ItemEntryDefinition()); diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/PluginStageExecutionWatcher.java b/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/PluginStageExecutionWatcher.java new file mode 100644 index 000000000..c92020949 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/PluginStageExecutionWatcher.java @@ -0,0 +1,83 @@ +/* + * 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.common.runtime; + +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.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 Reloadable>, HintProvider { + private Set stages = new HashSet<>(); + + @Override + public void startReload() { + for (ReloadStage stage : ReloadStage.values()) { + startReload(stage); + } + } + + @Override + public void startReload(ReloadStage stage) { + if (stage.ordinal() == 0) stages.clear(); + stages.add(stage); + } + + public Set notVisited() { + Set notVisited = new HashSet<>(Arrays.asList(ReloadStage.values())); + notVisited.removeAll(stages); + 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/common/runtime/SearchBarHighlightWatcher.java b/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/SearchBarHighlightWatcher.java new file mode 100644 index 000000000..08dd06ea0 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/common/runtime/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.common.runtime; + +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