diff options
| author | shedaniel <daniel@shedaniel.me> | 2024-09-06 20:49:27 +0900 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2024-09-06 20:59:03 +0900 |
| commit | 428d5359f0aff3b9922c7a80058f5214cf7f8340 (patch) | |
| tree | 9a8cefc83f037b25ca463e756031afbe43592dbf | |
| parent | a31f7254d76add6c34f134713c131463602f8cef (diff) | |
| download | RoughlyEnoughItems-428d5359f0aff3b9922c7a80058f5214cf7f8340.tar.gz RoughlyEnoughItems-428d5359f0aff3b9922c7a80058f5214cf7f8340.tar.bz2 RoughlyEnoughItems-428d5359f0aff3b9922c7a80058f5214cf7f8340.zip | |
New Display Registry Analysis in REI config, with options to sort the entries
7 files changed, 312 insertions, 5 deletions
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 b9596c200..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 @@ -36,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; @@ -245,6 +246,9 @@ 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) -> { RoughlyEnoughItemsCoreClient.reloadPlugins(null, null); 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..289a1c4fd --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/DisplayRegistryInfoScreen.java @@ -0,0 +1,173 @@ +/* + * 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 com.mojang.blaze3d.vertex.PoseStack; +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.GuiComponent; +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.network.chat.Component; +import net.minecraft.util.FormattedCharSequence; + +import java.util.*; +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; + })); + } + { + 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)); + })); + } + 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(PoseStack poses, int mouseX, int mouseY, float delta) { + renderDirtBackground(0); + list.render(poses, mouseX, mouseY, delta); + this.font.drawShadow(poses, this.title.getVisualOrderText(), this.width / 2.0F - this.font.width(this.title) / 2.0F, 12.0F, -1); + super.render(poses, 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, GuiComponent.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(PoseStack matrices, 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); + Minecraft.getInstance().font.drawShadow(matrices, this.component.getVisualOrderText(), (float) x + 4, (float) (y + 6), -1); + FormattedCharSequence rightText = Component.translatable("text.rei.display_registry_analysis.displays", count).getVisualOrderText(); + Minecraft.getInstance().font.drawShadow(matrices, rightText, (float) x + entryWidth - 6 - 8 - Minecraft.getInstance().font.width(rightText), (float) (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 239489a71..29d170779 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 @@ -26,17 +26,21 @@ package me.shedaniel.rei.impl.client.gui.performance; import com.mojang.blaze3d.vertex.PoseStack; 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; import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextColor; import net.minecraft.util.FormattedCharSequence; @@ -48,7 +52,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 +61,7 @@ public class PerformanceScreen extends Screen { } private PerformanceEntryListWidget list; + private SortType sortType = SortType.ORDER; /* * Copyright (C) 2008 The Guava Authors @@ -142,8 +147,22 @@ public class PerformanceScreen extends Screen { this.onClose = null; })); } + { + 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)); + })); + } 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 +177,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 +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 368bd5a3a..9596fc51d 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 @@ -157,6 +157,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..ab8df5df8 --- /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 com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.rei.impl.client.gui.modules.Menu; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +public class ScreenWithMenu extends Screen { + @Nullable + private Menu menu; + + protected ScreenWithMenu(Component component) { + super(component); + } + + @Override + public void render(PoseStack poses, int mouseX, int mouseY, float delta) { + super.render(poses, mouseX, mouseY, delta); + if (this.menu != null) { + poses.pushPose(); + poses.translate(0, 0, 400); + this.menu.render(poses, mouseX, mouseY, delta); + poses.popPose(); + } + } + + protected void setMenu(@Nullable Menu menu) { + this.menu = menu; + } + + protected void closeMenu() { + this.menu = null; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.menu != null) { + if (!this.menu.mouseClicked(mouseX, mouseY, button)) + this.menu = null; + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + if (this.menu != null && this.menu.mouseReleased(mouseX, mouseY, button)) + return true; + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { + if (this.menu != null && this.menu.mouseScrolled(mouseX, mouseY, amount)) + return true; + return super.mouseScrolled(mouseX, mouseY, amount); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (this.menu != null && this.menu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) + return true; + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } +} diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json index 0146868cf..5568968b6 100755 --- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json +++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json @@ -79,6 +79,10 @@ "text.rei.tag_accept": "Tag: #%s", "text.rei.missing": "Missing following:", "text.rei.performance": "Performance Analysis", + "text.rei.display_registry_analysis": "Display Registry Analysis", + "text.rei.display_registry_analysis.displays": "%d display(s)", + "text.rei.sort": "Sort", + "text.rei.sort.by": "Sort by %s", "text.rei.addons": "REI Addons", "text.rei.shapeless": "Shapeless", "text.rei.crafting.firework.gunpowder.amount": "The amount of gunpowder affects the flight duration of the firework.", @@ -451,6 +455,8 @@ "config.rei.options.debug.search_performance.desc": "Verbose console print out for analysing search performance.", "config.rei.options.debug.entry_list_performance": "Entry List Performance", "config.rei.options.debug.entry_list_performance.desc": "Display the time used to render entries on the entry list.", + "config.rei.options.debug.display_registry_analysis": "Display Registry Analysis", + "config.rei.options.debug.display_registry_analysis.desc": "Break-down in registration of displays in each category.", "config.rei.options.groups.reset.reload": "Reload", "config.rei.options.reset.reload_plugins": "Reload Plugins", "config.rei.options.reset.reload_plugins.desc": "Resets the current loaded data and reload all data and plugins.", |
