aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2024-09-17 21:52:18 +0800
committershedaniel <daniel@shedaniel.me>2024-09-17 21:52:18 +0800
commit581543cb56b8a85d32d7237e0d37fb5ad24da9b5 (patch)
treef3b8a2c81bef17fe6cb4672bbb1b77607e657b50 /runtime/src/main
parent048eccb27ce9907b1028b7acc4f0f98321864750 (diff)
parented0f9e051623b0a37b438a3df11c3e50a7d85ab5 (diff)
downloadRoughlyEnoughItems-581543cb56b8a85d32d7237e0d37fb5ad24da9b5.tar.gz
RoughlyEnoughItems-581543cb56b8a85d32d7237e0d37fb5ad24da9b5.tar.bz2
RoughlyEnoughItems-581543cb56b8a85d32d7237e0d37fb5ad24da9b5.zip
Merge remote-tracking branch 'origin/14.x-1.20.4' into 15.x-1.20.5
# Conflicts: # api/src/main/java/me/shedaniel/rei/api/common/display/basic/BasicDisplay.java # api/src/main/java/me/shedaniel/rei/impl/Internals.java # 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/RoughlyEnoughItemsCoreClient.java # runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java
Diffstat (limited to 'runtime/src/main')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java36
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java47
-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, 895 insertions, 204 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 7756fb24c..b807eecf0 100644
--- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java
+++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java
@@ -29,6 +29,7 @@ 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;
@@ -86,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 +124,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.*;
import java.util.stream.Stream;
@@ -130,15 +132,6 @@ public class RoughlyEnoughItemsCoreClient {
public static final Event<BiConsumer<RecipeManager, RegistryAccess>> 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();
@@ -314,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, registryAccess) -> {
- RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear();
- reloadPlugins(startReload, ReloadStage.START, registryAccess);
+ reloadPlugins(null, ReloadStage.START, registryAccess);
});
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!");
@@ -475,27 +469,12 @@ public class RoughlyEnoughItemsCoreClient {
public static void reloadPlugins(MutableLong lastReload, @Nullable ReloadStage start, @Nullable RegistryAccess registryAccess) {
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 625a56238..13e3a1c19 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
@@ -24,11 +24,16 @@
package me.shedaniel.rei.impl.client.gui.performance;
import com.mojang.datafixers.util.Pair;
+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 me.shedaniel.rei.impl.client.gui.widget.UpdatedListWidget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@@ -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);
}
@@ -211,4 +237,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.
+ *
+ * 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