diff options
| author | shedaniel <daniel@shedaniel.me> | 2021-10-22 01:40:06 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2021-10-22 01:55:30 +0800 |
| commit | c8f1c10e6c661ecf949ab29e0e8efeaa13324670 (patch) | |
| tree | 4628eb7559a385d00f62e2f6eee9b2a9d8c59f00 | |
| parent | 62045c9cc0416557e6b57b6f4101b98a0da02dde (diff) | |
| download | RoughlyEnoughItems-c8f1c10e6c661ecf949ab29e0e8efeaa13324670.tar.gz RoughlyEnoughItems-c8f1c10e6c661ecf949ab29e0e8efeaa13324670.tar.bz2 RoughlyEnoughItems-c8f1c10e6c661ecf949ab29e0e8efeaa13324670.zip | |
Add Performance Analysis
17 files changed, 801 insertions, 55 deletions
diff --git a/fabric/build.gradle b/fabric/build.gradle index 6d42ecee2..f91ffc538 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -34,7 +34,7 @@ dependencies { modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") { exclude(module: "fabric-api") } - modRuntime("com.terraformersmc:modmenu:${modmenu_version}") { transitive false } + //modRuntime("com.terraformersmc:modmenu:${modmenu_version}") { transitive false } modApi("dev.architectury:architectury-fabric:${architectury_version}") depProjects.forEach { diff --git a/fabric/src/main/java/me/shedaniel/rei/fabric/PluginDetectorImpl.java b/fabric/src/main/java/me/shedaniel/rei/fabric/PluginDetectorImpl.java index c44ae6a06..711437449 100644 --- a/fabric/src/main/java/me/shedaniel/rei/fabric/PluginDetectorImpl.java +++ b/fabric/src/main/java/me/shedaniel/rei/fabric/PluginDetectorImpl.java @@ -80,7 +80,8 @@ public class PluginDetectorImpl { } catch (Throwable t) { Throwable throwable = t; while (throwable != null) { - if (throwable.getMessage() != null && throwable.getMessage().contains("environment type SERVER") && !RoughlyEnoughItemsInitializer.isClient()) continue out; + if (throwable.getMessage() != null && throwable.getMessage().contains("environment type SERVER") && !RoughlyEnoughItemsInitializer.isClient()) + continue out; throwable = throwable.getCause(); } String error = "Could not create REI Plugin [" + getSimpleName(pluginClass) + "] due to errors, provided by '" + container.getProvider().getMetadata().getId() + "'!"; @@ -98,12 +99,10 @@ public class PluginDetectorImpl { public static void detectServerPlugins() { loadPlugin(REIServerPlugin.class, ((PluginView<REIServerPlugin>) PluginManager.getServerInstance())::registerPlugin); - if (FabricLoader.getInstance().isModLoaded("libblockattributes-fluids")) { - try { - PluginView.getServerInstance().registerPlugin((REIServerPlugin) Class.forName("me.shedaniel.rei.impl.common.compat.FabricFluidAPISupportPlugin").getConstructor().newInstance()); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } + try { + PluginView.getServerInstance().registerPlugin((REIServerPlugin) Class.forName("me.shedaniel.rei.impl.common.compat.FabricFluidAPISupportPlugin").getConstructor().newInstance()); + } catch (Throwable throwable) { + throwable.printStackTrace(); } } diff --git a/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java b/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java index cc7ea594d..aace5aa12 100644 --- a/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java +++ b/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java @@ -40,12 +40,12 @@ import me.shedaniel.rei.plugin.common.runtime.DefaultRuntimePlugin; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import org.apache.logging.log4j.util.TriConsumer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.function.BiConsumer; import java.util.function.Supplier; public class PluginDetectorImpl { @@ -74,14 +74,14 @@ public class PluginDetectorImpl { PluginView.getServerInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultPlugin())); PluginView.getServerInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultRuntimePlugin())); PluginView.getServerInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new JEIExtraPlugin())); - RoughlyEnoughItemsForge.<REIPlugin, REIServerPlugin>scanAnnotation(REIPlugin.class, REIServerPlugin.class::isAssignableFrom, (modId, plugin) -> { + RoughlyEnoughItemsForge.<REIPlugin, REIServerPlugin>scanAnnotation(REIPlugin.class, REIServerPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> { ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(modId, plugin.get())); }); } public static void detectCommonPlugins() { EventBuses.registerModEventBus("roughlyenoughitems", FMLJavaModLoadingContext.get().getModEventBus()); - RoughlyEnoughItemsForge.<REIPlugin, me.shedaniel.rei.api.common.plugins.REIPlugin<?>>scanAnnotation(REIPlugin.class, me.shedaniel.rei.api.common.plugins.REIPlugin.class::isAssignableFrom, (modId, plugin) -> { + RoughlyEnoughItemsForge.<REIPlugin, me.shedaniel.rei.api.common.plugins.REIPlugin<?>>scanAnnotation(REIPlugin.class, me.shedaniel.rei.api.common.plugins.REIPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> { ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(modId, plugin.get())); }); } @@ -91,7 +91,7 @@ public class PluginDetectorImpl { PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultClientPlugin())); PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultClientRuntimePlugin())); PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new JEIExtraClientPlugin())); - RoughlyEnoughItemsForge.<REIPlugin, REIClientPlugin>scanAnnotation(REIPlugin.class, REIClientPlugin.class::isAssignableFrom, (modId, plugin) -> { + RoughlyEnoughItemsForge.<REIPlugin, REIClientPlugin>scanAnnotation(REIPlugin.class, REIClientPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> { ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(modId, plugin.get())); }); ClientInternals.attachInstance((Supplier<List<String>>) () -> { @@ -103,7 +103,7 @@ public class PluginDetectorImpl { } return modIds; }, "jeiCompatMods"); - JEIPluginDetector.detect((aClass, consumer) -> RoughlyEnoughItemsForge.scanAnnotation((Class<Object>) aClass, clazz -> true, - (BiConsumer<List<String>, Supplier<Object>>) (BiConsumer) consumer), PluginView.getClientInstance()::registerPlugin); + JEIPluginDetector.detect((aClass, consumer) -> RoughlyEnoughItemsForge.scanAnnotation((Class<Object>) aClass, c -> true, + (TriConsumer<List<String>, Supplier<Object>, Class<Object>>) (TriConsumer) consumer), PluginView.getClientInstance()::registerPlugin); } } diff --git a/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java b/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java index dc9dc0175..dd5824c70 100644 --- a/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java +++ b/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java @@ -31,15 +31,15 @@ import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.ModFileScanData; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.ImmutableTriple; +import org.apache.commons.lang3.tuple.Triple; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.util.TriConsumer; import org.jetbrains.annotations.ApiStatus; import org.objectweb.asm.Type; import java.util.List; -import java.util.function.BiConsumer; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -54,12 +54,12 @@ public class RoughlyEnoughItemsForge { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RoughlyEnoughItemsInitializer::onInitializeClient); } - public static <A, T> void scanAnnotation(Class<A> clazz, Predicate<Class<T>> predicate, BiConsumer<List<String>, Supplier<T>> consumer) { + public static <A, T> void scanAnnotation(Class<A> clazz, Predicate<Class<T>> predicate, TriConsumer<List<String>, Supplier<T>, Class<T>> consumer) { scanAnnotation(Type.getType(clazz), predicate, consumer); } - public static <T> void scanAnnotation(Type annotationType, Predicate<Class<T>> predicate, BiConsumer<List<String>, Supplier<T>> consumer) { - List<Pair<List<String>, Supplier<T>>> instances = Lists.newArrayList(); + public static <T> void scanAnnotation(Type annotationType, Predicate<Class<T>> predicate, TriConsumer<List<String>, Supplier<T>, Class<T>> consumer) { + List<Triple<List<String>, Supplier<T>, Class<T>>> instances = Lists.newArrayList(); for (ModFileScanData data : ModList.get().getAllScanData()) { List<String> modIds = data.getIModInfoData().stream() .flatMap(info -> info.getMods().stream()) @@ -70,14 +70,14 @@ public class RoughlyEnoughItemsForge { try { Class<T> clazz = (Class<T>) Class.forName(annotation.memberName()); if (predicate.test(clazz)) { - instances.add(new ImmutablePair<>(modIds, () -> { + instances.add(new ImmutableTriple<>(modIds, () -> { try { return clazz.getDeclaredConstructor().newInstance(); } catch (Throwable throwable) { LOGGER.error("Failed to load plugin: " + annotation.memberName(), throwable); return null; } - })); + }, clazz)); } } catch (Throwable throwable) { LOGGER.error("Failed to load plugin: " + annotation.memberName(), throwable); @@ -86,8 +86,8 @@ public class RoughlyEnoughItemsForge { } } - for (Pair<List<String>, Supplier<T>> pair : instances) { - consumer.accept(pair.getLeft(), pair.getRight()); + for (Triple<List<String>, Supplier<T>, Class<T>> pair : instances) { + consumer.accept(pair.getLeft(), pair.getMiddle(), pair.getRight()); } } } diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java index 119841487..654552028 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java @@ -55,6 +55,8 @@ import me.shedaniel.rei.impl.common.logging.FileLogger; import me.shedaniel.rei.impl.common.logging.Log4JLogger; import me.shedaniel.rei.impl.common.logging.Logger; import me.shedaniel.rei.impl.common.logging.MultiLogger; +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.registry.RecipeManagerContextImpl; import me.shedaniel.rei.impl.common.transfer.MenuInfoRegistryImpl; @@ -75,6 +77,7 @@ public class RoughlyEnoughItemsCore { new FileLogger(Platform.getGameFolder().resolve("logs/rei.log")), new Log4JLogger(LogManager.getFormatterLogger("REI")) )); + public static final PerformanceLogger PERFORMANCE_LOGGER = new PerformanceLoggerImpl(); static { attachCommonInternals(); @@ -151,7 +154,10 @@ public class RoughlyEnoughItemsCore { if (Platform.getEnvironment() == Env.SERVER) { MutableLong lastReload = new MutableLong(-1); ReloadListenerRegistry.register(PackType.SERVER_DATA, (preparationBarrier, resourceManager, profilerFiller, profilerFiller2, executor, executor2) -> { - return preparationBarrier.wait(Unit.INSTANCE).thenRunAsync(() -> RoughlyEnoughItemsCore._reloadPlugins(null), executor2); + return preparationBarrier.wait(Unit.INSTANCE).thenRunAsync(() -> { + PERFORMANCE_LOGGER.clear(); + RoughlyEnoughItemsCore._reloadPlugins(null); + }, executor2); }); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java index 9f0b4552f..131592218 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -272,8 +272,14 @@ public class RoughlyEnoughItemsCoreClient { 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 -> reloadPlugins(startReload, ReloadStage.START)); - ClientRecipeUpdateEvent.EVENT.register(recipeManager -> reloadPlugins(endReload, Platform.isFabric() ? ReloadStage.END : null)); + PRE_UPDATE_RECIPES.register(recipeManager -> { + RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear(); + reloadPlugins(startReload, ReloadStage.START); + }); + ClientRecipeUpdateEvent.EVENT.register(recipeManager -> { + if (!Platform.isFabric()) RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear(); + reloadPlugins(endReload, Platform.isFabric() ? ReloadStage.END : null); + }); ClientGuiEvent.INIT_POST.register((screen, access) -> { REIRuntimeImpl.getInstance().setPreviousScreen(screen); if (ConfigObject.getInstance().doesDisableRecipeBook() && screen instanceof AbstractContainerScreen) { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java index f582734e2..e6eefa6b6 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java @@ -63,6 +63,7 @@ import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule; import me.shedaniel.rei.impl.client.entry.filtering.rules.ManualFilteringRule; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.credits.CreditsScreen; +import me.shedaniel.rei.impl.client.gui.performance.entry.PerformanceEntry; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.ChatFormatting; @@ -340,6 +341,7 @@ public class ConfigManagerImpl implements ConfigManager { builder.setGlobalizedExpanded(false); if (Minecraft.getInstance().getConnection() != null && Minecraft.getInstance().getConnection().getRecipeManager() != null) { builder.getOrCreateCategory(new TranslatableComponent("config.roughlyenoughitems.advanced")).getEntries().add(0, new ReloadPluginsEntry(220)); + builder.getOrCreateCategory(new TranslatableComponent("config.roughlyenoughitems.advanced")).getEntries().add(0, new PerformanceEntry(220)); } return builder.setAfterInitConsumer(screen -> { TextListEntry feedbackEntry = ConfigEntryBuilder.create().startTextDescription( diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java index a96680983..6452e883c 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java @@ -48,7 +48,10 @@ import java.util.Optional; @ApiStatus.Internal public class ReloadPluginsEntry extends AbstractConfigListEntry<Unit> { private int width; - private AbstractWidget buttonWidget = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> RoughlyEnoughItemsCoreClient.reloadPlugins(null, null)) { + private AbstractWidget buttonWidget = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> { + RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear(); + RoughlyEnoughItemsCoreClient.reloadPlugins(null, null); + }) { @Override public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { if (PluginManager.areAnyReloading()) { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java new file mode 100644 index 000000000..92bfb78be --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/PerformanceScreen.java @@ -0,0 +1,193 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.performance; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.datafixers.util.Pair; +import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget; +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.impl.client.gui.performance.entry.EntryListEntry; +import me.shedaniel.rei.impl.client.gui.performance.entry.SubCategoryListEntry; +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.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.util.FormattedCharSequence; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static java.util.concurrent.TimeUnit.*; + +@Environment(EnvType.CLIENT) +public class PerformanceScreen extends Screen { + private Screen parent; + + public PerformanceScreen(Screen parent) { + super(new TranslatableComponent("text.rei.performance")); + this.parent = parent; + } + + private PerformanceEntryListWidget list; + + /* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + public static FormattedCharSequence formatTime(long time, boolean total) { + TimeUnit unit = chooseUnit(time); + double value = (double) time / NANOSECONDS.convert(1, unit); + return new TextComponent(String.format(Locale.ROOT, "%.4g", value) + " " + abbreviate(unit)) + .withStyle(style -> style.withColor(TextColor.fromRgb(chooseColor(MILLISECONDS.convert(time, NANOSECONDS), total)))) + .getVisualOrderText(); + } + + private static int chooseColor(long time, boolean total) { + if (time > (total ? 2500 : 1000)) { + return 0xff5555; + } else if (time > (total ? 700 : 300)) { + return 0xffa600; + } else if (time > (total ? 200 : 100)) { + return 0xfff017; + } + return 0x12ff22; + } + + private static TimeUnit chooseUnit(long nanos) { + if (DAYS.convert(nanos, NANOSECONDS) > 0) { + return DAYS; + } + if (HOURS.convert(nanos, NANOSECONDS) > 0) { + return HOURS; + } + if (MINUTES.convert(nanos, NANOSECONDS) > 0) { + return MINUTES; + } + if (SECONDS.convert(nanos, NANOSECONDS) > 0) { + return SECONDS; + } + if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) { + return MILLISECONDS; + } + if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) { + return MICROSECONDS; + } + return NANOSECONDS; + } + + private static String abbreviate(TimeUnit unit) { + switch (unit) { + case NANOSECONDS: + return "ns"; + case MICROSECONDS: + return "\u03bcs"; // μs + case MILLISECONDS: + return "ms"; + case SECONDS: + return "s"; + case MINUTES: + return "min"; + case HOURS: + return "h"; + case DAYS: + return "d"; + default: + throw new AssertionError(); + } + } + + @Override + public void init() { + { + Component backText = new TextComponent("↩ ").append(new TranslatableComponent("gui.back")); + addRenderableWidget(new Button(4, 4, Minecraft.getInstance().font.width(backText) + 10, 20, backText, button -> { + minecraft.setScreen(parent); + this.parent = null; + })); + } + list = new PerformanceEntryListWidget(); + RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.getStages().forEach((stage, inner) -> { + List<EntryListEntry> entries = new ArrayList<>(); + inner.times().forEach((obj, time) -> { + entries.add(new EntryListEntry(new TextComponent(obj instanceof Pair ? ((Pair<REIPluginProvider<?>, REIPlugin<?>>) obj).getFirst().getPluginProviderName() : Objects.toString(obj)), time)); + }); + long separateTime = inner.times().values().stream().collect(Collectors.summarizingLong(value -> value)).getSum(); + if ((inner.totalNano() - separateTime) > 1000000) { + entries.add(new EntryListEntry(new TextComponent("Miscellaneous Operations"), inner.totalNano() - separateTime)); + } + entries.sort(Comparator.<EntryListEntry>comparingLong(value -> value.time).reversed()); + list.addItem(new SubCategoryListEntry(new TextComponent(stage), (List<PerformanceScreen.PerformanceEntry>) (List<? extends PerformanceScreen.PerformanceEntry>) entries, inner.totalNano(), false)); + }); + addWidget(list); + } + + @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 PerformanceEntry extends DynamicElementListWidget.ElementEntry<PerformanceEntry> { + + } + + private class PerformanceEntryListWidget extends DynamicElementListWidget<PerformanceEntry> { + public PerformanceEntryListWidget() {super(PerformanceScreen.this.minecraft, PerformanceScreen.this.width, PerformanceScreen.this.height, 30, PerformanceScreen.this.height, GuiComponent.BACKGROUND_LOCATION);} + + @Override + public int getItemWidth() { + return width; + } + + @Override + public int addItem(PerformanceEntry item) { + return super.addItem(item); + } + + @Override + protected int getScrollbarPosition() { + return width - 6; + } + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/EntryListEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/EntryListEntry.java new file mode 100644 index 000000000..5c2db0471 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/EntryListEntry.java @@ -0,0 +1,71 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.performance.entry; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.rei.impl.client.gui.performance.PerformanceScreen; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; +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.Collections; +import java.util.List; + +@Environment(EnvType.CLIENT) +public class EntryListEntry extends PerformanceScreen.PerformanceEntry { + private final Component name; + public final long time; + + public EntryListEntry(Component name, long time) { + this.name = name; + this.time = time; + } + + 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.name.getVisualOrderText(), (float) x, (float) (y + 6), -1); + FormattedCharSequence timeText = PerformanceScreen.formatTime(time, false); + Minecraft.getInstance().font.drawShadow(matrices, timeText, (float) x + entryWidth - 6 - 4 - Minecraft.getInstance().font.width(timeText), (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(); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/PerformanceEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/PerformanceEntry.java new file mode 100644 index 000000000..99b84ef5d --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/performance/entry/PerformanceEntry.java @@ -0,0 +1,93 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.performance.entry; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.clothconfig2.api.AbstractConfigListEntry; +import me.shedaniel.rei.impl.client.gui.performance.PerformanceScreen; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.chat.NarratorChatListener; +import net.minecraft.client.gui.components.AbstractWidget; +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.TranslatableComponent; +import net.minecraft.util.Unit; +import org.jetbrains.annotations.ApiStatus; + +import java.util.List; +import java.util.Optional; + +@ApiStatus.Internal +public class PerformanceEntry extends AbstractConfigListEntry<Unit> { + private int width; + private AbstractWidget buttonWidget = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> { + Minecraft.getInstance().setScreen(new PerformanceScreen(Minecraft.getInstance().screen)); + }); + private List<AbstractWidget> children = ImmutableList.of(buttonWidget); + + public PerformanceEntry(int width) { + |
