diff options
| author | shedaniel <daniel@shedaniel.me> | 2024-09-17 21:46:23 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2024-09-17 21:46:23 +0800 |
| commit | ed0f9e051623b0a37b438a3df11c3e50a7d85ab5 (patch) | |
| tree | 8984cc5c538beca93ae296903e431d54dba8706e /runtime/src | |
| parent | 8442364d7da83cda185dee99f0c980a46df55448 (diff) | |
| parent | 93c67936af006bbaad287a9e902a8b67a0d7fc7d (diff) | |
| download | RoughlyEnoughItems-ed0f9e051623b0a37b438a3df11c3e50a7d85ab5.tar.gz RoughlyEnoughItems-ed0f9e051623b0a37b438a3df11c3e50a7d85ab5.tar.bz2 RoughlyEnoughItems-ed0f9e051623b0a37b438a3df11c3e50a7d85ab5.zip | |
Merge remote-tracking branch 'origin/13.x-1.20.2' into 14.x-1.20.4
Diffstat (limited to 'runtime/src')
19 files changed, 895 insertions, 207 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java index 732ca00cd..8f4738fe9 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java @@ -29,13 +29,10 @@ 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.type.EntryType; -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.impl.Internals; import me.shedaniel.rei.impl.common.InternalLogger; import me.shedaniel.rei.impl.common.category.CategoryIdentifierImpl; @@ -53,11 +50,15 @@ import me.shedaniel.rei.impl.common.logging.*; import me.shedaniel.rei.impl.common.logging.performance.PerformanceLogger; import me.shedaniel.rei.impl.common.logging.performance.PerformanceLoggerImpl; import me.shedaniel.rei.impl.common.plugins.PluginManagerImpl; +import me.shedaniel.rei.impl.common.plugins.ReloadInterruptionContext; +import me.shedaniel.rei.impl.common.plugins.ReloadManagerImpl; import me.shedaniel.rei.impl.common.registry.RecipeManagerContextImpl; import me.shedaniel.rei.impl.common.transfer.MenuInfoRegistryImpl; import me.shedaniel.rei.impl.common.transfer.SlotAccessorRegistryImpl; +import me.shedaniel.rei.impl.common.util.InstanceHelper; import me.shedaniel.rei.impl.init.PluginDetector; import me.shedaniel.rei.impl.init.PrimitivePlatformAdapter; +import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import net.minecraft.util.Unit; @@ -70,6 +71,7 @@ import java.util.Comparator; import java.util.ServiceLoader; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; import java.util.function.UnaryOperator; @ApiStatus.Internal @@ -127,6 +129,7 @@ public class RoughlyEnoughItemsCore { Internals.attachInstanceSupplier(LOGGER, "logger"); CategoryIdentifierImpl.attach(); Internals.attachInstance((Function<ResourceLocation, EntryType<?>>) DeferringEntryTypeProviderImpl.INSTANCE, "entryTypeDeferred"); + Internals.attachInstance((Supplier<RegistryAccess>) () -> InstanceHelper.getInstance().registryAccess(), "registryAccess"); Internals.attachInstance(EntryStackProviderImpl.INSTANCE, Internals.EntryStackProvider.class); Internals.attachInstance(NbtHasherProviderImpl.INSTANCE, Internals.NbtHasherProvider.class); Internals.attachInstance(EntryIngredientImpl.INSTANCE, Internals.EntryIngredientProvider.class); @@ -135,7 +138,7 @@ public class RoughlyEnoughItemsCore { UnaryOperator.identity(), new EntryTypeRegistryImpl(), new EntrySettingsAdapterRegistryImpl(), - new RecipeManagerContextImpl<>(RecipeManagerContextImpl.supplier()), + new RecipeManagerContextImpl<>(), new ItemComparatorRegistryImpl(), new FluidComparatorRegistryImpl(), new DisplaySerializerRegistryImpl(), @@ -147,28 +150,6 @@ public class RoughlyEnoughItemsCore { new SlotAccessorRegistryImpl()), "serverPluginManager"); } - public static void _reloadPlugins(@Nullable ReloadStage stage) { - if (stage == null) { - for (ReloadStage reloadStage : ReloadStage.values()) { - _reloadPlugins(reloadStage); - } - return; - } - try { - for (PluginManager<? extends REIPlugin<?>> instance : PluginManager.getActiveInstances()) { - instance.view().pre(stage); - } - for (PluginManager<? extends REIPlugin<?>> instance : PluginManager.getActiveInstances()) { - instance.startReload(stage); - } - for (PluginManager<? extends REIPlugin<?>> instance : PluginManager.getActiveInstances()) { - instance.view().post(stage); - } - } catch (Throwable throwable) { - throwable.printStackTrace(); - } - } - public void onInitialize() { PluginDetector detector = getPluginDetector(); detector.detectCommonPlugins(); @@ -179,8 +160,7 @@ public class RoughlyEnoughItemsCore { MutableLong lastReload = new MutableLong(-1); ReloadListenerRegistry.register(PackType.SERVER_DATA, (preparationBarrier, resourceManager, profilerFiller, profilerFiller2, executor, executor2) -> { return preparationBarrier.wait(Unit.INSTANCE).thenRunAsync(() -> { - PERFORMANCE_LOGGER.clear(); - RoughlyEnoughItemsCore._reloadPlugins(null); + ReloadManagerImpl.reloadPlugins(null, ReloadInterruptionContext.ofNever()); }, executor2); }); } diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java index 408227e16..a04b44849 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -24,13 +24,12 @@ package me.shedaniel.rei; import com.google.common.collect.Lists; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; 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.ClientPlayerEvent; import dev.architectury.event.events.client.ClientRecipeUpdateEvent; import dev.architectury.event.events.client.ClientScreenInputEvent; import dev.architectury.networking.NetworkManager; @@ -67,7 +66,6 @@ import me.shedaniel.rei.impl.client.entry.filtering.rules.FilteringRuleTypeRegis import me.shedaniel.rei.impl.client.entry.renderer.EntryRendererRegistryImpl; import me.shedaniel.rei.impl.client.favorites.DelegatingFavoriteEntryProviderImpl; import me.shedaniel.rei.impl.client.favorites.FavoriteEntryTypeRegistryImpl; -import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.modules.entries.SubMenuEntry; import me.shedaniel.rei.impl.client.gui.modules.entries.ToggleMenuEntry; import me.shedaniel.rei.impl.client.gui.widget.InternalWidgets; @@ -89,6 +87,8 @@ import me.shedaniel.rei.impl.common.entry.type.EntryRegistryImpl; import me.shedaniel.rei.impl.common.entry.type.collapsed.CollapsibleEntryRegistryImpl; import me.shedaniel.rei.impl.common.entry.type.types.EmptyEntryDefinition; import me.shedaniel.rei.impl.common.plugins.PluginManagerImpl; +import me.shedaniel.rei.impl.common.plugins.ReloadManagerImpl; +import me.shedaniel.rei.impl.common.util.InstanceHelper; import me.shedaniel.rei.impl.common.util.IssuesDetector; import me.shedaniel.rei.plugin.test.REITestPlugin; import net.fabricmc.api.EnvType; @@ -121,7 +121,6 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.List; -import java.util.concurrent.*; import java.util.function.BiFunction; import java.util.function.BooleanSupplier; import java.util.function.Function; @@ -133,15 +132,6 @@ public class RoughlyEnoughItemsCoreClient { public static final Event<ClientRecipeUpdateEvent> PRE_UPDATE_RECIPES = EventFactory.createLoop(); public static final Event<Runnable> POST_UPDATE_TAGS = EventFactory.createLoop(); public static boolean isLeftMousePressed = false; - private static final ExecutorService RELOAD_PLUGINS = Executors.newSingleThreadScheduledExecutor(task -> { - Thread thread = new Thread(task, "REI-ReloadPlugins"); - thread.setDaemon(true); - thread.setUncaughtExceptionHandler(($, exception) -> { - InternalLogger.getInstance().throwException(exception); - }); - return thread; - }); - private static final List<Future<?>> RELOAD_TASKS = new CopyOnWriteArrayList<>(); public static void attachClientInternals() { InternalWidgets.attach(); @@ -317,24 +307,25 @@ public class RoughlyEnoughItemsCoreClient { private void registerEvents() { Minecraft client = Minecraft.getInstance(); final ResourceLocation recipeButtonTex = new ResourceLocation("textures/gui/recipe_button.png"); - MutableLong startReload = new MutableLong(-1); MutableLong endReload = new MutableLong(-1); PRE_UPDATE_RECIPES.register(recipeManager -> { - RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear(); - reloadPlugins(startReload, ReloadStage.START); + reloadPlugins(null, ReloadStage.START); }); ClientRecipeUpdateEvent.EVENT.register(recipeManager -> { reloadPlugins(endReload, ReloadStage.END); }); + ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> { + InternalLogger.getInstance().debug("Player quit, clearing reload tasks!"); + endReload.setValue(-1); + ReloadManagerImpl.terminateReloadTasks(); + }); ClientGuiEvent.INIT_PRE.register((screen, access) -> { List<ReloadStage> stages = ((PluginManagerImpl<REIPlugin<?>>) PluginManager.getInstance()).getObservedStages(); if (Minecraft.getInstance().level != null && Minecraft.getInstance().player != null && stages.contains(ReloadStage.START) && !stages.contains(ReloadStage.END) && !PluginManager.areAnyReloading() && screen instanceof AbstractContainerScreen) { - for (Future<?> task : RELOAD_TASKS) { - if (!task.isDone()) { - return EventResult.pass(); - } + if (ReloadManagerImpl.countRunningReloadTasks() > 0) { + return EventResult.pass(); } InternalLogger.getInstance().error("Detected missing stage: END! This is possibly due to issues during client recipe reload! REI will force a reload of the recipes now!"); @@ -473,27 +464,12 @@ public class RoughlyEnoughItemsCoreClient { public static void reloadPlugins(MutableLong lastReload, @Nullable ReloadStage start) { if (Minecraft.getInstance().level == null) return; if (lastReload != null) { - if (lastReload.getValue() > 0 && System.currentTimeMillis() - lastReload.getValue() <= 5000) { + if (lastReload.getValue() > 0 && System.currentTimeMillis() - lastReload.getValue() <= 1000) { InternalLogger.getInstance().warn("Suppressing Reload Plugins of stage " + start); return; } lastReload.setValue(System.currentTimeMillis()); } - InternalLogger.getInstance().debug("Starting Reload Plugins of stage " + start, new Throwable()); - if (ConfigObject.getInstance().doesRegisterRecipesInAnotherThread()) { - Future<?>[] futures = new Future<?>[1]; - CompletableFuture<Void> future = CompletableFuture.runAsync(() -> RoughlyEnoughItemsCore._reloadPlugins(start), RELOAD_PLUGINS) - .whenComplete((unused, throwable) -> { - // Remove the future from the list of futures - if (futures[0] != null) { - RELOAD_TASKS.remove(futures[0]); - futures[0] = null; - } - }); - futures[0] = future; - RELOAD_TASKS.add(future); - } else { - RoughlyEnoughItemsCore._reloadPlugins(start); - } + ReloadManagerImpl.reloadPlugins(start, () -> InstanceHelper.connectionFromClient() == null); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java index 28b83e639..b206fd6e5 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java @@ -116,7 +116,8 @@ public interface AllREIConfigGroups { OptionGroup DEBUG_PERFORMANCE = make("debug.performance") .add(PLUGINS_PERFORMANCE) .add(SEARCH_PERFORMANCE) - .add(ENTRY_LIST_PERFORMANCE); + .add(ENTRY_LIST_PERFORMANCE) + .add(DISPLAY_REGISTRY_ANALYSIS); OptionGroup RESET_RELOAD = make("reset.reload") .add(RELOAD_PLUGINS) .add(RELOAD_SEARCH); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java index 30340bfba..97119df2e 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java @@ -24,7 +24,6 @@ package me.shedaniel.rei.impl.client.gui.config.options; import me.shedaniel.clothconfig2.api.ModifierKeyCode; -import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.RoughlyEnoughItemsCoreClient; import me.shedaniel.rei.api.client.config.entry.EntryStackProvider; import me.shedaniel.rei.api.client.gui.config.*; @@ -37,6 +36,7 @@ import me.shedaniel.rei.impl.client.config.entries.ConfigureCategoriesScreen; import me.shedaniel.rei.impl.client.config.entries.FilteringEntry; import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen; import me.shedaniel.rei.impl.client.gui.config.options.configure.PanelBoundariesConfiguration; +import me.shedaniel.rei.impl.client.gui.performance.DisplayRegistryInfoScreen; import me.shedaniel.rei.impl.client.gui.performance.PerformanceScreen; import me.shedaniel.rei.impl.client.gui.screen.ConfigReloadingScreen; import me.shedaniel.rei.impl.client.gui.screen.collapsible.CollapsibleEntriesScreen; @@ -246,9 +246,11 @@ public interface AllREIConfigOptions { .enabledDisabled(); CompositeOption<Boolean> ENTRY_LIST_PERFORMANCE = make("debug.entry_list_performance", i -> i.advanced.layout.debugRenderTimeRequired, (i, v) -> i.advanced.layout.debugRenderTimeRequired = v) .enabledDisabled(); + CompositeOption<Object> DISPLAY_REGISTRY_ANALYSIS = make("debug.display_registry_analysis", i -> null, (i, v) -> new Object()) + .details((access, option, onClose) -> Minecraft.getInstance().setScreen(new DisplayRegistryInfoScreen(onClose))) + .requiresLevel(); CompositeOption<Object> RELOAD_PLUGINS = make("reset.reload_plugins", i -> null, (i, v) -> new Object()) .reload((access, option, onClose) -> { - RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear(); RoughlyEnoughItemsCoreClient.reloadPlugins(null, null); while (!PluginManager.areAnyReloading()) { try { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/DisplayRegistryInfoScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/DisplayRegistryInfoScreen.java new file mode 100644 index 000000000..f0cb9de14 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/DisplayRegistryInfoScreen.java @@ -0,0 +1,176 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.performance; + +import com.mojang.blaze3d.systems.RenderSystem; +import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.gui.modules.Menu; +import me.shedaniel.rei.impl.client.gui.modules.entries.ToggleMenuEntry; +import me.shedaniel.rei.impl.client.gui.screen.ScreenWithMenu; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.util.FormattedCharSequence; + +import java.util.*; +import java.util.function.Supplier; +import java.util.stream.Stream; + +@Environment(EnvType.CLIENT) +public class DisplayRegistryInfoScreen extends ScreenWithMenu { + private Runnable onClose; + + public DisplayRegistryInfoScreen(Runnable onClose) { + super(Component.translatable("text.rei.display_registry_analysis")); + this.onClose = onClose; + } + + private ListWidget list; + private SortType sortType = SortType.ID; + + @Override + public void init() { + { + Component backText = Component.literal("↩ ").append(Component.translatable("gui.back")); + addRenderableWidget(new Button(4, 4, Minecraft.getInstance().font.width(backText) + 10, 20, backText, button -> { + this.onClose.run(); + this.onClose = null; + }, Supplier::get) { + }); + } + { + Component text = Component.translatable("text.rei.sort"); + Rectangle bounds = new Rectangle(this.width - 4 - Minecraft.getInstance().font.width(text) - 10, 4, Minecraft.getInstance().font.width(text) + 10, 20); + addRenderableWidget(new Button(bounds.x, bounds.y, bounds.width, bounds.height, text, button -> { + this.setMenu(new Menu(bounds, CollectionUtils.map(SortType.values(), type -> { + return ToggleMenuEntry.of(Component.translatable("text.rei.sort.by", type.name().toLowerCase(Locale.ROOT)), () -> false, o -> { + this.closeMenu(); + this.sortType = type; + this.init(this.minecraft, this.width, this.height); + }); + }), false)); + }, Supplier::get) { + }); + } + list = new ListWidget(); + list.addItem(new EntryImpl(Component.literal("Total Displays"), DisplayRegistry.getInstance().displaySize())); + sort(DisplayRegistry.getInstance().getAll().entrySet().stream()) + .forEach(entry -> { + list.addItem(new EntryImpl(entry.getKey(), entry.getValue().size())); + }); + addWidget(list); + } + + private Stream<Map.Entry<CategoryIdentifier<?>, List<Display>>> sort(Stream<Map.Entry<CategoryIdentifier<?>, List<Display>>> stream) { + return switch (sortType) { + case COUNT -> stream.sorted(Comparator.<Map.Entry<CategoryIdentifier<?>, List<Display>>>comparingInt(value -> value.getValue().size()).reversed()); + case ID -> stream.sorted(Comparator.comparing(value -> value.getKey().toString())); + }; + } + + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + renderDirtBackground(graphics); + list.render(graphics, mouseX, mouseY, delta); + graphics.drawString(this.font, this.title.getVisualOrderText(), (int) (this.width / 2.0F - this.font.width(this.title) / 2.0F), 12, -1); + super.render(graphics, mouseX, mouseY, delta); + } + + public static abstract class ListEntry extends DynamicElementListWidget.ElementEntry<ListEntry> { + } + + private class ListWidget extends DynamicElementListWidget<ListEntry> { + public ListWidget() { + super(DisplayRegistryInfoScreen.this.minecraft, DisplayRegistryInfoScreen.this.width, DisplayRegistryInfoScreen.this.height, 30, DisplayRegistryInfoScreen.this.height, Screen.BACKGROUND_LOCATION); + } + + @Override + public int getItemWidth() { + return width; + } + + @Override + public int addItem(ListEntry item) { + return super.addItem(item); + } + + @Override + protected int getScrollbarPosition() { + return width - 6; + } + } + + public static class EntryImpl extends ListEntry { + private final Component component; + public final int count; + + public EntryImpl(CategoryIdentifier<?> identifier, int count) { + this(Component.literal(identifier.getIdentifier().toString()), count); + } + + public EntryImpl(Component component, int count) { + this.component = component; + this.count = count; + } + + @Override + public void render(GuiGraphics graphics, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + graphics.drawString(Minecraft.getInstance().font, this.component.getVisualOrderText(), x + 4, y + 6, -1); + FormattedCharSequence rightText = Component.translatable("text.rei.display_registry_analysis.displays", count).getVisualOrderText(); + graphics.drawString(Minecraft.getInstance().font, rightText, x + entryWidth - 6 - 8 - Minecraft.getInstance().font.width(rightText), y + 6, -1); + } + + @Override + public int getItemHeight() { + return 24; + } + + @Override + public List<? extends GuiEventListener> children() { + return Collections.emptyList(); + } + + @Override + public List<? extends NarratableEntry> narratables() { + return Collections.emptyList(); + } + } + + private enum SortType { + COUNT, + ID + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java index 21c8c20c9..f96f7bc5f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java @@ -25,11 +25,16 @@ package me.shedaniel.rei.impl.client.gui.performance; import com.mojang.datafixers.util.Pair; import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget; +import me.shedaniel.math.Rectangle; import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.api.common.plugins.REIPlugin; import me.shedaniel.rei.api.common.plugins.REIPluginProvider; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.gui.modules.Menu; +import me.shedaniel.rei.impl.client.gui.modules.entries.ToggleMenuEntry; import me.shedaniel.rei.impl.client.gui.performance.entry.PerformanceEntryImpl; import me.shedaniel.rei.impl.client.gui.performance.entry.SubCategoryListEntry; +import me.shedaniel.rei.impl.client.gui.screen.ScreenWithMenu; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; @@ -48,7 +53,7 @@ import java.util.stream.Collectors; import static java.util.concurrent.TimeUnit.*; @Environment(EnvType.CLIENT) -public class PerformanceScreen extends Screen { +public class PerformanceScreen extends ScreenWithMenu { private Runnable onClose; public PerformanceScreen(Runnable onClose) { @@ -57,6 +62,7 @@ public class PerformanceScreen extends Screen { } private PerformanceEntryListWidget list; + private SortType sortType = SortType.ORDER; /* * Copyright (C) 2008 The Guava Authors @@ -142,8 +148,22 @@ public class PerformanceScreen extends Screen { this.onClose = null; }, Supplier::get) {}); } + { + Component text = Component.translatable("text.rei.sort"); + Rectangle bounds = new Rectangle(this.width - 4 - Minecraft.getInstance().font.width(text) - 10, 4, Minecraft.getInstance().font.width(text) + 10, 20); + addRenderableWidget(new Button(bounds.x, bounds.y, bounds.width, bounds.height, text, button -> { + this.setMenu(new Menu(bounds, CollectionUtils.map(SortType.values(), type -> { + return ToggleMenuEntry.of(Component.translatable("text.rei.sort.by", type.name().toLowerCase(Locale.ROOT)), () -> false, o -> { + this.closeMenu(); + this.sortType = type; + this.init(this.minecraft, this.width, this.height); + }); + }), false)); + }, Supplier::get) {}); + } list = new PerformanceEntryListWidget(); long[] totalTime = {0}; + List<SubCategoryListEntry> subCategories = new ArrayList<>(); RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.getStages().forEach((stage, inner) -> { List<PerformanceEntryImpl> entries = new ArrayList<>(); inner.times().forEach((obj, time) -> { @@ -158,9 +178,15 @@ public class PerformanceScreen extends Screen { entries.add(new PerformanceEntryImpl(Component.literal("Miscellaneous Operations"), inner.totalNano() - separateTime)); } totalTime[0] += Math.max(inner.totalNano(), separateTime); - entries.sort(Comparator.<PerformanceEntryImpl>comparingLong(value -> value.time).reversed()); - list.addItem(new SubCategoryListEntry(Component.literal(stage), (List<PerformanceScreen.PerformanceEntry>) (List<? extends PerformanceScreen.PerformanceEntry>) entries, Math.max(inner.totalNano(), separateTime), false)); + if (this.sortType == SortType.DURATION) { + entries.sort(Comparator.<PerformanceEntryImpl>comparingLong(value -> value.time).reversed()); + } + subCategories.add(new SubCategoryListEntry(Component.literal(stage), (List<PerformanceScreen.PerformanceEntry>) (List<? extends PerformanceScreen.PerformanceEntry>) entries, Math.max(inner.totalNano(), separateTime), false)); }); + if (this.sortType == SortType.DURATION) { + subCategories.sort(Comparator.comparingLong(SubCategoryListEntry::getTotalTime).reversed()); + } + subCategories.forEach(list::addItem); list.children().add(0, new PerformanceEntryImpl(Component.literal("Total Load Time"), totalTime[0])); addWidget(list); } @@ -212,4 +238,9 @@ public class PerformanceScreen extends Screen { return width - 6; } } + + private enum SortType { + ORDER, + DURATION + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/SubCategoryListEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/SubCategoryListEntry.java index 322c6cf5a..191192692 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/SubCategoryListEntry.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/SubCategoryListEntry.java @@ -156,6 +156,10 @@ public class SubCategoryListEntry extends PerformanceScreen.PerformanceEntry imp return Collections.emptyList(); } + public long getTotalTime() { + return totalTime; + } + public class CategoryLabelWidget implements GuiEventListener { private final Rectangle rectangle = new Rectangle(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/ScreenWithMenu.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/ScreenWithMenu.java new file mode 100644 index 000000000..bfd3379e9 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/ScreenWithMenu.java @@ -0,0 +1,89 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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. |
