From be4c8607d46d5ee2c47f4743415119a5eac6c756 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 11:53:28 -0400 Subject: [PATCH 01/13] Disable faster texture loader if Changed:MC is installed Related: #108 --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 2cbd9276..3b4522a3 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -190,7 +190,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.launch.class_search_cache", "optifine"); disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine"); disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide"); - disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine"); + disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine", "changed"); } private void disableIfModPresent(String configName, String... ids) { From baca029fd06b039036204ea836b79bf703fc6ce8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 14:59:46 -0400 Subject: [PATCH 02/13] Add support for Diagonal Fences --- common/build.gradle | 1 + .../MultipartAppenderMixin.java | 43 +++++++++++++++++++ .../main/resources/modernfix.accesswidener | 3 +- gradle.properties | 1 + 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java diff --git a/common/build.gradle b/common/build.gradle index bbf54231..bc9b8299 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -26,6 +26,7 @@ dependencies { modCompileOnly("appeng:appliedenergistics2-fabric:${appeng_version}") { transitive = false } + modCompileOnly("curse.maven:diagonal-fences-458048:${diagonal_fences_version}") // compile against the JEI API but do not include it at runtime modCompileOnly("mezz.jei:jei-${minecraft_version}-common:${jei_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-gui:${jei_version}") diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java new file mode 100644 index 00000000..7c702fba --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java @@ -0,0 +1,43 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.diagonalfences; + +import fuzs.diagonalfences.api.world.level.block.DiagonalBlock; +import fuzs.diagonalfences.client.model.MultipartAppender; +import net.minecraft.client.renderer.block.model.multipart.MultiPart; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.FenceBlock; +import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.annotation.RequiresMod; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MultipartAppender.class) +@RequiresMod("diagonalfences") +public abstract class MultipartAppenderMixin { + @Shadow(remap = false) + public static void appendDiagonalSelectors(ModelBakery modelBakery, MultiPart multiPart) { + throw new AssertionError(); + } + + @Inject(method = "onPrepareModelBaking", at = @At("RETURN")) + private static void setupHelper(CallbackInfo ci) { + ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { + @Override + public UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { + if(originalModel instanceof MultiPart multipart) { + Block block = multipart.definition.getOwner(); + if(block instanceof FenceBlock && block instanceof DiagonalBlock diagonalBlock && diagonalBlock.hasProperties()) { + appendDiagonalSelectors(bakery, multipart); + } + } + return originalModel; + } + }); + } +} diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 0873eccb..f43fe931 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -29,4 +29,5 @@ accessible class net/minecraft/world/level/chunk/PalettedContainer$Data accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources; accessible class net/minecraft/server/MinecraftServer$ReloadableResources accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; -accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; \ No newline at end of file +accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; +accessible field net/minecraft/client/renderer/block/model/multipart/MultiPart definition Lnet/minecraft/world/level/block/state/StateDefinition; \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index cfb24271..b59cb53a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,3 +18,4 @@ fabric_api_version=0.76.0+1.19.2 modmenu_version=4.1.2 appeng_version=12.9.3 +diagonal_fences_version=4545943 \ No newline at end of file From 2bd2fd7ef760bebbb598fbb6217684d72ad0e932 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 16:38:34 -0400 Subject: [PATCH 03/13] Only inject integration first time --- .../diagonalfences/MultipartAppenderMixin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java index 7c702fba..5be40715 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java @@ -25,8 +25,13 @@ public abstract class MultipartAppenderMixin { throw new AssertionError(); } + private static boolean handlerInjected = false; + @Inject(method = "onPrepareModelBaking", at = @At("RETURN")) private static void setupHelper(CallbackInfo ci) { + if(handlerInjected) + return; + handlerInjected = true; ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { @Override public UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { From 74eb8a06197373f69fe110d527f11a65e9f31774 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 18:50:49 -0400 Subject: [PATCH 04/13] Split unbaked model load event into load and pre-bake stages Allows mods like Continuity to wrap the model being baked separately from the model in the cache --- .../api/entrypoint/ModernFixClientIntegration.java | 13 +++++++++++++ .../perf/dynamic_resources/ModelBakeryMixin.java | 11 +++++++++++ .../perf/dynamic_resources/ModelBakeryMixin.java | 11 +++++++++++ 3 files changed, 35 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java b/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java index f5757766..aa3b78bc 100644 --- a/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java +++ b/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java @@ -34,6 +34,19 @@ public interface ModernFixClientIntegration { return originalModel; } + /** + * Called to allow mods to observe the use of an unbaked model at bake time and either make changes to it or wrap it with their + * own instance. + * @param location the ResourceLocation of the model (this may be a ModelResourceLocation) + * @param originalModel the original model + * @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect + * with dynamic resources on + * @return the model which should actually be loaded for this resource location + */ + default UnbakedModel onUnbakedModelPreBake(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { + return originalModel; + } + /** * Called to allow mods to observe the loading of a baked model and either make changes to it or wrap it with their * own instance. diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java index a8551700..311530f3 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -448,6 +448,17 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { if(iunbakedmodel == missingModel && debugDynamicModelLoading) LOGGER.warn("Model {} not present", arg); + + if(iunbakedmodel != missingModel) { + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + iunbakedmodel = integration.onUnbakedModelPreBake(arg, iunbakedmodel, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception firing model pre-bake event for {}", arg, e); + } + } + } + BakedModel ibakedmodel = null; if (iunbakedmodel instanceof BlockModel) { BlockModel blockmodel = (BlockModel)iunbakedmodel; diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java index 7b75a2d8..3fe1d7cf 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -322,6 +322,17 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { iunbakedmodel.getMaterials(this::getModel, new HashSet<>()); if(iunbakedmodel == missingModel && debugDynamicModelLoading) LOGGER.warn("Model {} not present", arg); + + if(iunbakedmodel != missingModel) { + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + iunbakedmodel = integration.onUnbakedModelPreBake(arg, iunbakedmodel, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception encountered firing bake event for {}", arg, e); + } + } + } + BakedModel ibakedmodel = null; if (iunbakedmodel instanceof BlockModel) { BlockModel blockmodel = (BlockModel)iunbakedmodel; From ddf2fc5a7413e3015a0c0dba3f81ac7778dc7eec Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 19:29:24 -0400 Subject: [PATCH 05/13] Provide more useful information if the image used in DynamicTexture is null --- .../mixin/safety/DynamicTextureMixin.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java new file mode 100644 index 00000000..388cc1eb --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java @@ -0,0 +1,24 @@ +package org.embeddedt.modernfix.common.mixin.safety; + +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.client.renderer.texture.DynamicTexture; +import org.embeddedt.modernfix.ModernFix; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(DynamicTexture.class) +public class DynamicTextureMixin { + @Shadow @Nullable private NativeImage pixels; + + @Redirect(method = "(Lcom/mojang/blaze3d/platform/NativeImage;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0)) + private void putNewPixel(DynamicTexture texture, NativeImage pixels) { + if(pixels == null) { + ModernFix.LOGGER.error("Null image provided to DynamicTexture", new Exception()); + pixels = new NativeImage(4, 4, false); + } + this.pixels = pixels; + } +} From a327b460bbe1ccd5977a8239e838077284057706 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 20:30:22 -0400 Subject: [PATCH 06/13] Tweak dynamic texture mixin --- .../mixin/safety/DynamicTextureMixin.java | 24 --------------- .../mixin/safety/DynamicTextureMixin.java | 30 +++++++++++++++++++ 2 files changed, 30 insertions(+), 24 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java create mode 100644 fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java deleted file mode 100644 index 388cc1eb..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.safety; - -import com.mojang.blaze3d.platform.NativeImage; -import net.minecraft.client.renderer.texture.DynamicTexture; -import org.embeddedt.modernfix.ModernFix; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(DynamicTexture.class) -public class DynamicTextureMixin { - @Shadow @Nullable private NativeImage pixels; - - @Redirect(method = "(Lcom/mojang/blaze3d/platform/NativeImage;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0)) - private void putNewPixel(DynamicTexture texture, NativeImage pixels) { - if(pixels == null) { - ModernFix.LOGGER.error("Null image provided to DynamicTexture", new Exception()); - pixels = new NativeImage(4, 4, false); - } - this.pixels = pixels; - } -} diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java new file mode 100644 index 00000000..5cc7f1ac --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java @@ -0,0 +1,30 @@ +package org.embeddedt.modernfix.fabric.mixin.safety; + +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.client.renderer.texture.DynamicTexture; +import org.embeddedt.modernfix.ModernFix; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(DynamicTexture.class) +public class DynamicTextureMixin { + @Shadow @Nullable private NativeImage pixels; + + private Exception closeTrace; + + @Inject(method = "method_22793", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0)) + private void checkNullPixels(CallbackInfo ci) { + if(pixels == null) { + ModernFix.LOGGER.error("Attempted to upload null texture! This is not allowed, closed here", closeTrace); + } + } + + @Inject(method = "close", at = @At("HEAD")) + private void storeCloseTrace(CallbackInfo ci) { + closeTrace = new Exception(); + } +} From 214b39ce8fdf1e80de12c97c9764f6855d877d0e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 21:02:27 -0400 Subject: [PATCH 07/13] Fixes for LBG+Diagonal Fences together --- .../mixin/perf/dynamic_resources/ModelBakeryMixin.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java index b97b8412..8094dfcc 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -44,10 +44,6 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -179,7 +175,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @Inject(method = "loadModel", at = @At(value = "HEAD"), cancellable = true) private void ignoreNonFabricModel(ResourceLocation modelLocation, CallbackInfo ci) throws Exception { - if(this.inTextureGatheringPass && !this.forceLoadModel && !this.injectedModels.contains(modelLocation)) { + if(this.inTextureGatheringPass && this.blockStateFiles != null && !this.forceLoadModel && !this.injectedModels.contains(modelLocation)) { // Custom model processor, try to avoid loading unwrapped models // First add this to the list of models to scan for textures ResourceLocation blockStateLocation = null; @@ -210,7 +206,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { this.cacheAndQueueDependencies(modelLocation, this.missingModel); this.forceLoadModel = false; if(this.smallLoadingCache.get(modelLocation) != this.missingModel) { - /* probably a wrapped model, allow it to load normally */ + // probably a wrapped model, allow it to load normally isWrappedModel = true; } this.smallLoadingCache.clear(); @@ -344,6 +340,8 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @ModifyVariable(method = "cacheAndQueueDependencies", at = @At("HEAD"), argsOnly = true) private UnbakedModel fireUnbakedEvent(UnbakedModel model, ResourceLocation location) { + if(this.inTextureGatheringPass) + return model; for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { try { model = integration.onUnbakedModelLoad(location, model, (ModelBakery)(Object)this); From b5d62b4bbb70ce28affbeadf2bb284b3fcaf749c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 26 May 2023 11:55:57 -0400 Subject: [PATCH 08/13] Add off-by-default feature to automatically thread dump every 60 seconds --- .../org/embeddedt/modernfix/ModernFix.java | 14 +++++++ .../core/config/ModernFixEarlyConfig.java | 1 + .../modernfix/world/IntegratedWatchdog.java | 40 ++++++++++--------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java index cbd44bf4..4e6e89d1 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -11,6 +11,7 @@ import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.resources.ReloadExecutor; import org.embeddedt.modernfix.util.ClassInfoManager; +import org.embeddedt.modernfix.world.IntegratedWatchdog; import java.lang.management.ManagementFactory; import java.util.concurrent.Executor; @@ -46,6 +47,19 @@ public class ModernFix { public ModernFix() { INSTANCE = this; ModernFixPlatformHooks.onServerCommandRegister(ModernFixCommands::register); + if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spam_thread_dump.ThreadDumper")) { + Thread t = new Thread() { + public void run() { + while(true) { + LOGGER.error("------ DEBUG THREAD DUMP (occurs every 60 seconds) ------"); + LOGGER.error(IntegratedWatchdog.obtainThreadDump()); + try { Thread.sleep(60000); } catch(InterruptedException e) {} + } + } + }; + t.setDaemon(true); + t.start(); + } } public void onServerStarted() { diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 3b4522a3..ca7e9333 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -147,6 +147,7 @@ public class ModernFixEarlyConfig { .put("mixin.perf.deduplicate_location", false) .put("mixin.feature.integrated_server_watchdog", true) .put("mixin.perf.faster_item_rendering", false) + .put("mixin.feature.spam_thread_dump", false) .put("mixin.perf.blast_search_trees", shouldReplaceSearchTrees) .put("mixin.devenv", isDevEnv) .put("mixin.perf.remove_spawn_chunks", isDevEnv) diff --git a/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java b/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java index 150269fe..1f8f0bc7 100644 --- a/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java +++ b/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java @@ -25,6 +25,27 @@ public class IntegratedWatchdog extends Thread { this.setName("ModernFix integrated server watchdog"); } + public static String obtainThreadDump() { + ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true); + StringBuilder sb = new StringBuilder(); + sb.append("Thread Dump:\n"); + for(ThreadInfo threadinfo : athreadinfo) { + sb.append(threadinfo); + StackTraceElement[] elements = threadinfo.getStackTrace(); + if(elements.length > 8) { + sb.append("extended trace:\n"); + for(int i = 8; i < elements.length; i++) { + sb.append("\tat "); + sb.append(elements[i]); + sb.append('\n'); + } + } + sb.append('\n'); + } + return sb.toString(); + } + public void run() { while(true) { MinecraftServer server = this.server.get(); @@ -35,24 +56,7 @@ public class IntegratedWatchdog extends Thread { long delta = curTime - nextTick; if(delta > MAX_TICK_DELTA) { LOGGER.error("A single server tick has taken {}, more than {} milliseconds", delta, MAX_TICK_DELTA); - ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean(); - ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true); - StringBuilder sb = new StringBuilder(); - sb.append("Thread Dump:\n"); - for(ThreadInfo threadinfo : athreadinfo) { - sb.append(threadinfo); - StackTraceElement[] elements = threadinfo.getStackTrace(); - if(elements.length > 8) { - sb.append("extended trace:\n"); - for(int i = 8; i < elements.length; i++) { - sb.append("\tat "); - sb.append(elements[i]); - sb.append('\n'); - } - } - sb.append('\n'); - } - LOGGER.error(sb); + LOGGER.error(obtainThreadDump()); nextTick = 0; curTime = 0; } From c4a50bb6e2a1fb9e31a4b46b9b9cfdd999c3cfa9 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 27 May 2023 10:12:05 -0400 Subject: [PATCH 09/13] Replace default backing map of NBT tags in more compatible way Related: #111 --- .../nbt_memory_usage/CompoundTagMixin.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java index 4a12e9b1..7b20e23d 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java @@ -6,27 +6,24 @@ import org.embeddedt.modernfix.util.CanonizingStringMap; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Map; @Mixin(CompoundTag.class) public class CompoundTagMixin { - @Shadow @Final @Mutable + @Shadow @Final private Map tags; /** - * Ensure that the backing map is always a CanonizingStringMap. + * Ensure that the default backing map is a CanonizingStringMap. */ - @Redirect(method = "(Ljava/util/Map;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/nbt/CompoundTag;tags:Ljava/util/Map;", ordinal = 0)) - private void replaceTagMap(CompoundTag tag, Map incomingMap) { - if(incomingMap instanceof CanonizingStringMap) - this.tags = incomingMap; - else { - this.tags = new CanonizingStringMap<>(); - this.tags.putAll(incomingMap); - } + @ModifyArg(method = "()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;(Ljava/util/Map;)V"), index = 0) + private static Map useCanonizingStringMap(Map incoming) { + CanonizingStringMap newMap = new CanonizingStringMap<>(); + newMap.putAll(incoming); + return newMap; } /** From b8850b2aae9ce722be61320d45057e82796f2349 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 28 May 2023 22:17:03 -0400 Subject: [PATCH 10/13] Only use JEI backed search tree if EMI is not installed --- .../org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java b/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java index 57a8ff25..6779e51c 100644 --- a/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java +++ b/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java @@ -99,7 +99,7 @@ public class JEIBackedSearchTree extends DummySearchTree { @Override public boolean canUse() { - return ModernFixPlatformHooks.modPresent("jei") && getIngredientListUncached != null && filterField != null; + return ModernFixPlatformHooks.modPresent("jei") && !ModernFixPlatformHooks.modPresent("emi") && getIngredientListUncached != null && filterField != null; } @Override From 04f34a00fa5876576aa0a103fcc6dcf98f8ad71c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 29 May 2023 10:15:18 -0400 Subject: [PATCH 11/13] Fix resource pack cache not working as well as it could --- .../mixin/perf/resourcepacks/ModFileResourcePackMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java index bfb3d510..ff0046d2 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java @@ -70,7 +70,7 @@ public abstract class ModFileResourcePackMixin implements ICachingResourcePack { @Inject(method = "getResources", at = @At("HEAD"), cancellable = true) private void fastGetResources(PackType type, String resourceNamespace, String pathIn, int maxDepth, Predicate filter, CallbackInfoReturnable> cir) { - if(!PackTypeHelper.isVanillaPackType(type) || this.cacheEngine == null) + if(!PackTypeHelper.isVanillaPackType(type)) return; cir.setReturnValue(this.generateResourceCache().getResources(type, resourceNamespace, pathIn, maxDepth, filter)); } From a7d894cbc2fde0ad591f9c99eed1730eb5b60201 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 29 May 2023 10:16:54 -0400 Subject: [PATCH 12/13] Disable cache invalidation outside dev Not needed as mod contents shouldn't change (right...) --- .../modernfix/resources/PackResourcesCacheEngine.java | 3 +++ .../modernfix/platform/forge/ModernFixPlatformHooksImpl.java | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java b/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java index 8c592cdf..ef5e2cbc 100644 --- a/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java +++ b/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.util.PackTypeHelper; import java.io.IOException; @@ -163,6 +164,8 @@ public class PackResourcesCacheEngine { } public static void invalidate() { + if(!ModernFixPlatformHooks.isDevEnv()) + return; synchronized (cachingPacks) { cachingPacks.keySet().forEach(pack -> { if(pack != null) diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index 525a7d47..8b31a33e 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -22,7 +22,6 @@ import net.minecraftforge.fml.ModLoader; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.LoadingModList; -import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.server.ServerLifecycleHooks; @@ -76,7 +75,7 @@ public class ModernFixPlatformHooksImpl { } public static boolean isDevEnv() { - return !FMLLoader.isProduction() && FMLLoader.getLoadingModList().getModFileById("modernfix").getFile().getLocator() instanceof ExplodedDirectoryLocator; + return !FMLLoader.isProduction(); } public static MinecraftServer getCurrentServer() { From 3dbff477e936d7ffd02067b5c5705527f5c36934 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 29 May 2023 18:25:03 -0400 Subject: [PATCH 13/13] Improve structure cache wording --- .../modernfix/structure/CachingStructureManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java b/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java index 365fb4d7..9f96c0ee 100644 --- a/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java +++ b/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java @@ -62,7 +62,8 @@ public class CachingStructureManager { currentTag.putInt("DataVersion", 500); } int currentDataVersion = currentTag.getInt("DataVersion"); - if(currentDataVersion < SharedConstants.getCurrentVersion().getWorldVersion()) { + int requiredMinimumDataVersion = SharedConstants.getCurrentVersion().getWorldVersion(); + if(currentDataVersion < requiredMinimumDataVersion) { /* Needs upgrade, try looking up from cache */ MessageDigest hasher = digestThreadLocal.get(); hasher.reset(); @@ -70,13 +71,13 @@ public class CachingStructureManager { CompoundTag cachedUpgraded = getCachedUpgraded(location, truncateHash(hash)); if(cachedUpgraded == null) cachedUpgraded = getCachedUpgraded(location, hash); /* pick up old cache */ - if(cachedUpgraded != null && cachedUpgraded.getInt("DataVersion") == SharedConstants.getCurrentVersion().getWorldVersion()) { + if(cachedUpgraded != null && cachedUpgraded.getInt("DataVersion") == requiredMinimumDataVersion) { ModernFix.LOGGER.debug("Using cached upgraded version of {}", location); currentTag = cachedUpgraded; } else { synchronized (laggyStructureMods) { if(laggyStructureMods.add(location.getNamespace())) { - ModernFix.LOGGER.warn("Mod {} is shipping outdated structure files, which can cause worldgen lag; please report this to them.", location.getNamespace()); + ModernFix.LOGGER.warn("The namespace {} contains an outdated structure file, which can cause worldgen lag. Please view debug.log for the full filename, determine which mod provides the structure, and report to the mod/datapack author, including the debug log.", location.getNamespace()); } } ModernFix.LOGGER.debug("Structure {} is being run through DFU (hash {}), this will cause launch time delays", location, hash);