From 09ea5e1dc9fe965addf9fb8d3aca74ba1baadcb6 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:01:39 -0400 Subject: [PATCH] Runs, dynamic resources still broken --- .../chunk_deadlock/BlockStateBaseMixin.java | 22 --- .../cache_model_materials/MultipartMixin.java | 28 ---- .../CreateWorldScreenMixin.java | 2 +- .../MinecraftServerMixin.java | 2 +- .../StateHolderMixin.java | 16 ++- .../BlockBehaviourInvoker.java | 15 -- .../BlockStateBaseMixin.java | 130 ----------------- .../BlocksMixin.java | 28 ---- .../BiomeMixin.java | 6 +- .../modernfix/core/ModernFixMixinPlugin.java | 136 ------------------ 10 files changed, 14 insertions(+), 371 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/BlockStateBaseMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/MultipartMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/BlockStateBaseMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/BlockStateBaseMixin.java deleted file mode 100644 index 464130c8..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/BlockStateBaseMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock; - -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.state.BlockBehaviour; -import org.embeddedt.modernfix.chunk.SafeBlockGetter; -import org.embeddedt.modernfix.duck.ISafeBlockGetter; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; - -@Mixin(value = BlockBehaviour.BlockStateBase.class, priority = 100) -public class BlockStateBaseMixin { - @ModifyVariable(method = "getOffset", at = @At("HEAD"), argsOnly = true, index = 1) - private BlockGetter useSafeGetter(BlockGetter g) { - if(g instanceof ISafeBlockGetter) { - SafeBlockGetter replacement = ((ISafeBlockGetter) g).mfix$getSafeBlockGetter(); - if(replacement.shouldUse()) - return replacement; - } - return g; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/MultipartMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/MultipartMixin.java deleted file mode 100644 index 4d620db9..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/MultipartMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials; - -import net.minecraft.client.renderer.block.model.multipart.MultiPart; -import net.minecraft.resources.ResourceLocation; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Collection; - -@Mixin(MultiPart.class) -@ClientOnlyMixin -public class MultipartMixin { - private Collection dependencyCache = null; - @Inject(method = "getDependencies", at = @At("HEAD"), cancellable = true) - private void useDependencyCache(CallbackInfoReturnable> cir) { - if(dependencyCache != null) - cir.setReturnValue(dependencyCache); - } - - @Inject(method = "getDependencies", at = @At("RETURN")) - private void storeDependencyCache(CallbackInfoReturnable> cir) { - if(dependencyCache == null) - dependencyCache = cir.getReturnValue(); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java index 16a18dd8..acd42740 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java @@ -17,7 +17,7 @@ public class CreateWorldScreenMixin { return ModernFix.resourceReloadExecutor(); } - @ModifyArg(method = "openFresh", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 3) + @ModifyArg(method = "openCreateWorldScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 3) private static Executor getCreationExecutorService(Executor e) { return ModernFix.resourceReloadExecutor(); } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java index e0f53533..96e5075b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java @@ -10,7 +10,7 @@ import java.util.concurrent.Executor; @Mixin(MinecraftServer.class) public class MinecraftServerMixin { - @ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 5) + @ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Ljava/util/List;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 6) private Executor getReloadExecutor(Executor asyncExecutor) { return ModernFix.resourceReloadExecutor(); } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java index 9e67dd7b..537a68e8 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java @@ -1,9 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size; -import com.google.common.collect.ArrayTable; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.ImmutableTable; -import com.google.common.collect.Table; +import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import net.minecraft.world.level.block.state.StateHolder; import net.minecraft.world.level.block.state.properties.Property; import org.embeddedt.modernfix.annotation.RequiresMod; @@ -13,6 +10,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Map; + /** * Minor mixin to avoid duplicate empty neighbor tables, used when FerriteCore is not present. Won't be enabled in 99% of * modded environments but is useful for testing in dev without dragging in Fabric API. @@ -20,12 +19,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(StateHolder.class) @RequiresMod("!ferritecore") public class StateHolderMixin { - @Shadow private Table, Comparable, ?> neighbours; + private static final Reference2ObjectArrayMap, ?> EMPTY_NEIGHBOURS = new Reference2ObjectArrayMap<>(); + + @Shadow private Map, ?> neighbours; /* optimize the case where block has no properties */ @Inject(method = "populateNeighbours", at = @At("RETURN"), require = 0) private void replaceEmptyTable(CallbackInfo ci) { - if((this.neighbours instanceof ArrayTable || this.neighbours instanceof HashBasedTable) && this.neighbours.isEmpty()) - this.neighbours = ImmutableTable.of(); + if (this.neighbours.isEmpty()) { + this.neighbours = EMPTY_NEIGHBOURS; + } } } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java deleted file mode 100644 index 9c9eb142..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds; - -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(BlockBehaviour.class) -public interface BlockBehaviourInvoker { - @Invoker - FluidState invokeGetFluidState(BlockState blockState); - @Invoker - boolean invokeIsRandomlyTicking(BlockState blockState); -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java deleted file mode 100644 index 42ba3cee..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds; - -import com.mojang.serialization.MapCodec; -import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateHolder; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import org.embeddedt.modernfix.duck.IBlockState; -import org.objectweb.asm.Opcodes; -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(BlockBehaviour.BlockStateBase.class) -public abstract class BlockStateBaseMixin extends StateHolder implements IBlockState { - protected BlockStateBaseMixin(Block object, Reference2ObjectArrayMap, Comparable> immutableMap, MapCodec mapCodec) { - super(object, immutableMap, mapCodec); - } - - private static final FluidState MFIX$VANILLA_DEFAULT_FLUID = Fluids.EMPTY.defaultFluidState(); - - @Shadow public abstract void initCache(); - - @Shadow private BlockBehaviour.BlockStateBase.Cache cache; - @Shadow private FluidState fluidState; - @Shadow private boolean isRandomlyTicking; - @Shadow @Deprecated private boolean legacySolid; - - @Shadow protected abstract BlockState asState(); - - private volatile boolean cacheInvalid = false; - private static boolean buildingCache = false; - @Override - public void clearCache() { - cacheInvalid = true; - } - - @Override - public boolean isCacheInvalid() { - return cacheInvalid; - } - - private void mfix$generateCache() { - if(cacheInvalid) { - // Ensure that only one block's cache is built at a time - synchronized (BlockBehaviour.BlockStateBase.class) { - if(cacheInvalid) { - // Ensure that if we end up in here recursively, we just use the original cache - if(!buildingCache) { - buildingCache = true; - try { - this.initCache(); - cacheInvalid = false; - } finally { - buildingCache = false; - } - } - } - - } - } - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;", - ordinal = 0 - )) - private BlockBehaviour.BlockStateBase.Cache dynamicCacheGen(BlockBehaviour.BlockStateBase base) { - mfix$generateCache(); - return this.cache; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;fluidState:Lnet/minecraft/world/level/material/FluidState;", - ordinal = 0 - ), require = 0) - private FluidState genCacheBeforeGettingFluid(BlockBehaviour.BlockStateBase base) { - // don't generate the full cache here as mods will iterate for the fluid state a lot - // assume blockstates will not change their contained fluidstate at runtime more than once - // this is how Lithium's implementation used to work, so it should be fine - if(this.cacheInvalid && this.fluidState == MFIX$VANILLA_DEFAULT_FLUID) { - synchronized (BlockBehaviour.BlockStateBase.class) { - if(!buildingCache) { - buildingCache = true; - try { - this.fluidState = ((BlockBehaviourInvoker)this.owner).invokeGetFluidState(this.asState()); - } finally { - buildingCache = false; - } - } - } - - } - return this.fluidState; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;isRandomlyTicking:Z", - ordinal = 0 - )) - private boolean genCacheBeforeGettingTicking(BlockBehaviour.BlockStateBase base) { - if(this.cacheInvalid) - return ((BlockBehaviourInvoker)this.owner).invokeIsRandomlyTicking(this.asState()); - return this.isRandomlyTicking; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;legacySolid:Z", - ordinal = 0 - )) - private boolean genCacheBeforeCheckingSolid(BlockBehaviour.BlockStateBase base) { - mfix$generateCache(); - return this.legacySolid; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java deleted file mode 100644 index fe28dff6..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds; - -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import org.embeddedt.modernfix.blockstate.BlockStateCacheHandler; -import org.embeddedt.modernfix.duck.IBlockState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.util.function.Consumer; - -@Mixin(value = Blocks.class, priority = 1100) -public class BlocksMixin { - @ModifyArg(method = "rebuildCache", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/IdMapper;forEach(Ljava/util/function/Consumer;)V"), index = 0) - private static Consumer getEmptyConsumer(Consumer original) { - BlockStateCacheHandler.rebuildParallel(true); - return o -> {}; - } - - // require = 0 due to Forge removing the BLOCK_STATE_REGISTRY init here - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;initCache()V"), require = 0) - private static void skipCacheInit(BlockState state) { - // Mark the cache as invalid - ((IBlockState)state).clearCache(); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java index 0091ac98..bbc3dd03 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java @@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.Shadow; /* Idea from Lithium for 1.19.3 */ @Mixin(Biome.class) public abstract class BiomeMixin { - @Shadow protected abstract float getHeightAdjustedTemperature(BlockPos pos); + @Shadow protected abstract float getHeightAdjustedTemperature(BlockPos pos, int i); /** * @author 2No2Name @@ -18,7 +18,7 @@ public abstract class BiomeMixin { * @return */ @Overwrite - private float getTemperature(BlockPos pos) { - return this.getHeightAdjustedTemperature(pos); + private float getTemperature(BlockPos pos, int i) { + return this.getHeightAdjustedTemperature(pos, i); } } diff --git a/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java b/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java index 5fbe1c36..6c902036 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java @@ -1,18 +1,14 @@ package org.embeddedt.modernfix.core; -import com.google.common.collect.ImmutableSet; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.embeddedt.modernfix.core.config.ModernFixEarlyConfig; import org.embeddedt.modernfix.core.config.Option; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.world.ThreadDumper; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; import org.objectweb.asm.tree.*; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import org.spongepowered.asm.mixin.transformer.meta.MixinMerged; import java.io.File; import java.util.*; @@ -150,138 +146,6 @@ public class ModernFixMixinPlugin implements IMixinConfigPlugin { @Override public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - if(mixinClassName.equals("org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds.BlockStateBaseMixin")) { - try { - applyBlockStateCacheScan(targetClass); - } catch(RuntimeException e) { - ModernFixMixinPlugin.instance.logger.error("Applying blockstate cache ASM patch failed", e); - } - } ModernFixPlatformHooks.INSTANCE.applyASMTransformers(mixinClassName, targetClass); } - - private void applyBlockStateCacheScan(ClassNode targetClass) { - Set initCacheMethodNames = ImmutableSet.of("m_60611_", "func_215692_c", "method_26200", "initCache"); - Set whitelistedInjections = ImmutableSet.of( - "getFluidState", "method_26227", "m_60819_", "func_204520_s" - ); - Map injectorMethodNames = new HashMap<>(); - Map allMethods = new HashMap<>(); - Map injectorMixinSource = new HashMap<>(); - String descriptor = Type.getDescriptor(MixinMerged.class); - for(MethodNode m : targetClass.methods) { - if((m.access & Opcodes.ACC_STATIC) != 0) - continue; - allMethods.put(m.name, m); - Set seenNodes = new HashSet<>(); - if(m.invisibleAnnotations != null) { - for(AnnotationNode ann : m.invisibleAnnotations) { - if(ann.desc.equals(descriptor)) { - seenNodes.add(ann); - } - } - } - if(m.visibleAnnotations != null) { - for(AnnotationNode ann : m.visibleAnnotations) { - if(ann.desc.equals(descriptor)) { - seenNodes.add(ann); - } - } - } - if(seenNodes.size() > 0) { - injectorMethodNames.put(m.name, m); - for(AnnotationNode node : seenNodes) { - for(int i = 0; i < node.values.size(); i += 2) { - if(Objects.equals(node.values.get(i), "mixin")) { - injectorMixinSource.put(m.name, (String)node.values.get(i + 1)); - break; - } - } - } - } - } - Set cacheCalledInjectors = new HashSet<>(); - // Search for initCache in the class - for(MethodNode m : targetClass.methods) { - if((m.access & Opcodes.ACC_STATIC) != 0) - continue; - if(initCacheMethodNames.contains(m.name)) { - // This is it. Check for any injectors it calls - for(AbstractInsnNode n : m.instructions) { - if(n instanceof MethodInsnNode) { - MethodInsnNode invoke = (MethodInsnNode)n; - if(((MethodInsnNode)n).owner.equals(targetClass.name) && injectorMethodNames.containsKey(((MethodInsnNode)n).name)) { - cacheCalledInjectors.add(invoke.name); - } - } - } - break; - } - } - Set accessedFieldNames = new HashSet<>(); - - // Make a map of all injected methods called by initCache - Map writingMethods = new HashMap<>(injectorMethodNames); - writingMethods.keySet().retainAll(cacheCalledInjectors); - - // Recursively check the injected methods for any methods they may call - int previousSize = 0; - Set checkedCalls = new HashSet<>(); - while(writingMethods.size() > previousSize) { - previousSize = writingMethods.size(); - List keysToCheck = new ArrayList<>(writingMethods.keySet()); - for(String name : keysToCheck) { - if(!checkedCalls.add(name)) - continue; - for(AbstractInsnNode n : writingMethods.get(name).instructions) { - if(n instanceof MethodInsnNode) { - MethodInsnNode invokeNode = (MethodInsnNode)n; - if(invokeNode.owner.equals(targetClass.name)) { - MethodNode theMethod = allMethods.get(invokeNode.name); - if(theMethod != null) - writingMethods.put(invokeNode.name, theMethod); - } - } - } - } - } - - // We now know all methods that have been injected into initCache, and their callers. See what fields they write to - writingMethods.forEach((name, method) -> { - for(AbstractInsnNode n : method.instructions) { - if(n instanceof FieldInsnNode) { - FieldInsnNode fieldAcc = (FieldInsnNode)n; - if(fieldAcc.getOpcode() == Opcodes.PUTFIELD && fieldAcc.owner.equals(targetClass.name)) { - accessedFieldNames.add(fieldAcc.name); - } - } - } - }); - // Lastly, scan all injected methods and see if they retrieve from the field. If so, inject a generateCache - // call at the start. - injectorMethodNames.forEach((name, method) -> { - // skip whitelisted injectors, and injectors called by initCache itself (to prevent recursion) - if(whitelistedInjections.contains(name) || cacheCalledInjectors.contains(name)) - return; - boolean needInjection = false; - for(AbstractInsnNode n : method.instructions) { - if(n instanceof FieldInsnNode) { - FieldInsnNode fieldAcc = (FieldInsnNode)n; - if(fieldAcc.getOpcode() == Opcodes.GETFIELD && accessedFieldNames.contains(fieldAcc.name)) { - needInjection = true; - break; - } - } - } - if(needInjection) { - ModernFixMixinPlugin.instance.logger.info("Injecting BlockStateBase cache population hook into {} from {}", - name, injectorMixinSource.getOrDefault(name, "[unknown mixin]")); - // inject this.mfix$generateCache() at method head - InsnList injection = new InsnList(); - injection.add(new VarInsnNode(Opcodes.ALOAD, 0)); - injection.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, targetClass.name, "mfix$generateCache", "()V")); - method.instructions.insert(injection); - } - }); - } } \ No newline at end of file