From d0fd498682a60a4ee0c4bb6bc9b6b42059f15c0c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 1 Jan 2024 12:25:16 -0500 Subject: [PATCH 1/7] Suppress mixin forceload logging when clear_mixin_info is on --- .../modernfix/util/ClassInfoManager.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java b/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java index 8efaa4f1..1daa97a8 100644 --- a/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java +++ b/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java @@ -3,16 +3,22 @@ package org.embeddedt.modernfix.util; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.logging.ILogger; +import org.spongepowered.asm.logging.LoggerAdapterDefault; import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; import org.spongepowered.asm.mixin.transformer.ClassInfo; +import org.spongepowered.asm.service.MixinServiceAbstract; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; public class ClassInfoManager { private static boolean hasRun = false; + private static final List loggersToRestore = new ArrayList<>(); public static void clear() { if (!ModernFixMixinPlugin.instance.isOptionEnabled("perf.clear_mixin_classinfo.ClassInfoManager") || hasRun) return; @@ -25,11 +31,33 @@ public class ClassInfoManager { return f; } + private static void changeLoggerAndRestoreLater(Map map, ILogger newLogger) { + ILogger oldLogger = map.put("mixin.audit", newLogger); + loggersToRestore.add(() -> map.put("mixin.audit", oldLogger)); + } + + private static void disableLoggers() throws ReflectiveOperationException { + // Disable default audit logger + Field loggersField = accessible(MixinServiceAbstract.class.getDeclaredField("loggers")); + changeLoggerAndRestoreLater((Map)loggersField.get(null), new LoggerAdapterDefault("mixin.audit")); + Class fabricLogger = null; + try { + fabricLogger = Class.forName("net.fabricmc.loader.impl.knot.MixinLogger"); + } catch(Throwable e) { + // Probably not Fabric + return; + } + // Disable Fabric audit logger + loggersField = accessible(fabricLogger.getDeclaredField("LOGGER_MAP")); + changeLoggerAndRestoreLater((Map)loggersField.get(null), new LoggerAdapterDefault("mixin.audit")); + } + private static void doClear() { Map classInfoCache; Field mixinField, stateField, classNodeField, methodsField, fieldsField; Class stateClz; try { + disableLoggers(); Field field = accessible(ClassInfo.class.getDeclaredField("cache")); classInfoCache = (Map) field.get(null); mixinField = accessible(ClassInfo.class.getDeclaredField("mixin")); @@ -70,6 +98,9 @@ public class ClassInfoManager { } catch (RuntimeException e) { e.printStackTrace(); } + // Put back the old logger + loggersToRestore.forEach(Runnable::run); + loggersToRestore.clear(); ModernFix.LOGGER.warn("Cleared mixin data structures"); } } From 3214311bb6f1b51b3dd081a86689c5da428f00f2 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:03:52 -0500 Subject: [PATCH 2/7] Slightly optimize entity capability retrieval --- .../LivingEntityMixin.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java new file mode 100644 index 00000000..60935b4f --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java @@ -0,0 +1,24 @@ +package org.embeddedt.modernfix.forge.mixin.perf.forge_cap_retrieval; + +import net.minecraft.core.Direction; +import net.minecraft.world.entity.LivingEntity; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.items.CapabilityItemHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import javax.annotation.Nullable; + +@Mixin(LivingEntity.class) +public class LivingEntityMixin { + /** + * @author embeddedt (issue noted by XFactHD) + * @reason check capability equality before checking that entity is alive, the latter requires a lot more + * indirection + */ + @Redirect(method = "getCapability", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isAlive()Z")) + private boolean checkAliveAfterCap(LivingEntity entity, Capability capability, @Nullable Direction facing) { + return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && entity.isAlive(); + } +} From 17fdccddfed8773ac8d7827671a0bf8dd1f534de Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 2 Jan 2024 09:52:17 -0500 Subject: [PATCH 3/7] Allow missing models on item overrides Please ask your servers to stop shipping the client invalid model files. Related: #343 --- .../dynamic_resources/ItemOverridesMixin.java | 26 ++++++++++++++ .../modernfix/duck/IExtendedModelBaker.java | 3 +- .../ItemOverridesFabricMixin.java | 31 +++++++++++++++++ .../ModelBakerImplMixin.java | 6 ++-- .../dynamic_resources/ModelBakeryMixin.java | 2 +- .../ItemOverridesForgeMixin.java | 34 +++++++++++++++++++ .../ModelBakerImplMixin.java | 6 ++-- 7 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java create mode 100644 fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java new file mode 100644 index 00000000..5de98b42 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java @@ -0,0 +1,26 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IExtendedModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemOverrides.class) +@ClientOnlyMixin +public class ItemOverridesMixin { + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;getModel(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/resources/model/UnbakedModel;")) + private UnbakedModel preventThrowForMissing(ModelBaker instance, ResourceLocation resourceLocation, Operation original) { + boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); + try { + return original.call(instance, resourceLocation); + } finally { + ((IExtendedModelBaker)instance).throwOnMissingModel(prevState); + } + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java b/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java index 5a26ed55..b50f65d4 100644 --- a/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java +++ b/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java @@ -3,6 +3,7 @@ package org.embeddedt.modernfix.duck; public interface IExtendedModelBaker { /** * Causes the ModelBaker to throw when it finds a missing model instead of proceeding with the bake. + * @return the previous value of this flag */ - void throwOnMissingModel(); + boolean throwOnMissingModel(boolean flag); } diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java new file mode 100644 index 00000000..140f0737 --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java @@ -0,0 +1,31 @@ +package org.embeddedt.modernfix.fabric.mixin.perf.dynamic_resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IExtendedModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemOverrides.class) +@ClientOnlyMixin +public class ItemOverridesFabricMixin { + /** + * @author embeddedt + * @reason servers insist on generating invalid item overrides that have missing models + */ + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;)Lnet/minecraft/client/resources/model/BakedModel;")) + private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Operation original) { + boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); + try { + return original.call(instance, resourceLocation, modelState); + } finally { + ((IExtendedModelBaker)instance).throwOnMissingModel(prevState); + } + } +} diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index 5d88e0ec..2324eda4 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -59,8 +59,10 @@ public abstract class ModelBakerImplMixin implements IExtendedModelBaker { private boolean throwIfMissing; @Override - public void throwOnMissingModel() { - throwIfMissing = true; + public boolean throwOnMissingModel(boolean flag) { + boolean old = throwIfMissing; + throwIfMissing = flag; + return old; } @Inject(method = "getModel", at = @At("HEAD"), cancellable = true) 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 fd51fc97..39ac1fb3 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 @@ -310,7 +310,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return m; ModelBakery self = (ModelBakery) (Object) this; ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation); - ((IExtendedModelBaker)theBaker).throwOnMissingModel(); + ((IExtendedModelBaker)theBaker).throwOnMissingModel(true); synchronized(this) { m = theBaker.bake(modelLocation, state); } if(m != null) loadedBakedModels.put(key, m); diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java new file mode 100644 index 00000000..12c35328 --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java @@ -0,0 +1,34 @@ +package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IExtendedModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.function.Function; + +@Mixin(ItemOverrides.class) +@ClientOnlyMixin +public class ItemOverridesForgeMixin { + /** + * @author embeddedt + * @reason servers insist on generating invalid item overrides that have missing models + */ + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;")) + private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Function spriteGetter, Operation original) { + boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); + try { + return original.call(instance, resourceLocation, modelState, spriteGetter); + } finally { + ((IExtendedModelBaker)instance).throwOnMissingModel(prevState); + } + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index e55ffc39..11036e83 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -41,8 +41,10 @@ public abstract class ModelBakerImplMixin implements IModelBakerImpl, IExtendedM private boolean throwIfMissing; @Override - public void throwOnMissingModel() { - throwIfMissing = true; + public boolean throwOnMissingModel(boolean flag) { + boolean old = throwIfMissing; + throwIfMissing = flag; + return old; } @Inject(method = "getModel", at = @At("HEAD"), cancellable = true) From 9375a4233b1b04222509d5babf7afaf2b640dc60 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 2 Jan 2024 09:55:55 -0500 Subject: [PATCH 4/7] Fix Forge errors --- .../mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java | 2 +- .../forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java index 12c35328..3118b7b8 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java @@ -22,7 +22,7 @@ public class ItemOverridesForgeMixin { * @author embeddedt * @reason servers insist on generating invalid item overrides that have missing models */ - @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;")) + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;"), remap = false) private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Function spriteGetter, Operation original) { boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); try { 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 2f36b941..1a388a3c 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 @@ -316,7 +316,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return m; ModelBakery self = (ModelBakery) (Object) this; ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation); - ((IExtendedModelBaker)theBaker).throwOnMissingModel(); + ((IExtendedModelBaker)theBaker).throwOnMissingModel(true); synchronized(this) { m = theBaker.bake(modelLocation, state, theBaker.getModelTextureGetter()); } if(m != null) loadedBakedModels.put(key, m); From 7174ae1454c91ae0ab6917063becd6c23ed221be Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:17:53 -0500 Subject: [PATCH 5/7] Do not actually load all models in replaceAll, use clever trick instead Otherwise, it takes 20 seconds to run this with just Mekanism+Additions+Pneumaticcraft --- .../dynresources/ModelBakeEventHelper.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index 0aeb9fac..1aa4609f 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -153,13 +153,26 @@ public class ModelBakeEventHelper { @Override public void replaceAll(BiFunction function) { - ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. This requires temporarily loading every model for that mod, which is slow.", modId); + ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. Some hacks will be used to keep this fast, but they may not be 100% compatible.", modId); List locations = new ArrayList<>(keySet()); for(ResourceLocation location : locations) { - BakedModel existing = get(location); - BakedModel replacement = function.apply(location, existing); - if(replacement != existing) { - put(location, replacement); + /* + * Fetching every model is insanely slow. So we call the function with a null object first, since it + * probably isn't expecting that. If we get an exception thrown, or it returns nonnull, then we know + * it actually cares about the given model. + */ + boolean needsReplacement; + try { + needsReplacement = function.apply(location, null) != null; + } catch(Throwable e) { + needsReplacement = true; + } + if(needsReplacement) { + BakedModel existing = get(location); + BakedModel replacement = function.apply(location, existing); + if(replacement != existing) { + put(location, replacement); + } } } } From c678ebbb918e25a2c28e0e2a638b4e837491c0a7 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:30:13 -0500 Subject: [PATCH 6/7] Avoid refresh loop if no model data needs refreshing --- .../model_data_manager_cme/ModelDataManagerMixin.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java index 45836c89..ebca1644 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java @@ -6,6 +6,7 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraftforge.client.model.ModelDataManager; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -13,6 +14,7 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; import java.util.Collections; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -27,6 +29,8 @@ public abstract class ModelDataManagerMixin { throw new AssertionError(); } + @Shadow @Final private static Map> needModelDataRefresh; + /** * Make the set of positions to refresh a real concurrent hash set rather than relying on synchronizedSet, * because the returned iterator won't be thread-safe otherwise. See https://github.com/AppliedEnergistics/Applied-Energistics-2/issues/7511 @@ -40,7 +44,8 @@ public abstract class ModelDataManagerMixin { private static void onlyRefreshOnMainThread(Level toUpdate, ChunkPos pos) { // Only refresh model data on the main thread. This prevents calling getBlockEntity from worker threads // which could cause weird CMEs or other behavior. - if(Minecraft.getInstance().isSameThread()) { + // Avoid the loop if no model data needs to be refreshed, to prevent unnecessary allocation. + if(Minecraft.getInstance().isSameThread() && !needModelDataRefresh.isEmpty()) { // Refresh the given chunk, and all its neighbors. This is less efficient than the default code // but we have no choice since we need to not do refreshing on workers, and blocks might // try to access model data in neighboring chunks. From 2e88482344bb0d9d5602321ea2e259177fccd70c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:31:44 -0500 Subject: [PATCH 7/7] Update for 1.19 model data manager changes --- .../bugfix/model_data_manager_cme/ModelDataManagerMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java index e379b69a..5fba1b2e 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java @@ -26,7 +26,7 @@ import java.util.function.Function; public abstract class ModelDataManagerMixin { @Shadow protected abstract void refreshAt(ChunkPos chunk); - @Shadow @Final private static Map> needModelDataRefresh; + @Shadow @Final private Map> needModelDataRefresh; /** * Make the set of positions to refresh a real concurrent hash set rather than relying on synchronizedSet,