aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2024-09-17 21:34:04 +0800
committershedaniel <daniel@shedaniel.me>2024-09-17 21:34:04 +0800
commit3febdc4e1d6927f19d0de6fc8430765336d34d7e (patch)
treee8cc88c46ce9b2ebf0954f94dcb56189f2fa5a1b /runtime
parentbc039e2d0a45409396c9156307d70529ccb28a3e (diff)
parentccf3dcd60aa6c1d079dd57c59d9a89c2ca60b1e7 (diff)
downloadRoughlyEnoughItems-3febdc4e1d6927f19d0de6fc8430765336d34d7e.tar.gz
RoughlyEnoughItems-3febdc4e1d6927f19d0de6fc8430765336d34d7e.tar.bz2
RoughlyEnoughItems-3febdc4e1d6927f19d0de6fc8430765336d34d7e.zip
Merge remote-tracking branch 'origin/12.x-1.20' into 13.x-1.20.2
# Conflicts: # default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/DefaultSmithingDisplay.java # fabric/src/main/resources/roughlyenoughitems.accessWidener # runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java # runtime/src/main/java/me/shedaniel/rei/impl/common/registry/RecipeManagerContextImpl.java
Diffstat (limited to 'runtime')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java32
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java50
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java3
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java6
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/DisplayRegistryInfoScreen.java176
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java37
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/SubCategoryListEntry.java4
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/ScreenWithMenu.java89
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java7
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCache.java4
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCacheImpl.java16
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java78
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/util/OriginalRetainingCyclingList.java42
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java8
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/plugins/PluginManagerImpl.java187
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/plugins/ReloadManagerImpl.java211
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/registry/RecipeManagerContextImpl.java17
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/util/InstanceHelper.java125
-rwxr-xr-xruntime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json6
19 files changed, 891 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..3f99fa7cb 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,6 +50,8 @@ 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;
@@ -135,7 +134,7 @@ public class RoughlyEnoughItemsCore {
UnaryOperator.identity(),
new EntryTypeRegistryImpl(),
new EntrySettingsAdapterRegistryImpl(),
- new RecipeManagerContextImpl<>(RecipeManagerContextImpl.supplier()),
+ new RecipeManagerContextImpl<>(),
new ItemComparatorRegistryImpl(),
new FluidComparatorRegistryImpl(),
new DisplaySerializerRegistryImpl(),
@@ -147,28 +146,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 +156,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..c117f70e4
--- /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.
+ *
+ * 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.screen;
+
+import me.shedaniel.rei.impl.client.gui.modules.Menu;
+import ne