From 60850610f9510003e9eb9d9af19e5122fb8bd0ad Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 27 Feb 2026 19:11:24 -0500 Subject: [PATCH] Group capability providers of known types together when possible --- .../AttachCapabilitiesEventMixin.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_capabilities/bytecode_analysis/AttachCapabilitiesEventMixin.java diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_capabilities/bytecode_analysis/AttachCapabilitiesEventMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_capabilities/bytecode_analysis/AttachCapabilitiesEventMixin.java new file mode 100644 index 00000000..a5c168c4 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_capabilities/bytecode_analysis/AttachCapabilitiesEventMixin.java @@ -0,0 +1,70 @@ +package org.embeddedt.modernfix.common.mixin.perf.faster_capabilities.bytecode_analysis; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.EventPriority; +import org.apache.commons.lang3.tuple.Pair; +import org.embeddedt.modernfix.forge.capability.analysis.CapabilityAnalysisResult; +import org.embeddedt.modernfix.forge.capability.analysis.CapabilityAnalyzer; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +@Mixin(AttachCapabilitiesEvent.class) +public abstract class AttachCapabilitiesEventMixin extends Event { + @Shadow + public abstract void addCapability(ResourceLocation key, ICapabilityProvider cap); + + @Unique + private static final EventPriority MFIX_LAST_PRIO = EventPriority.values()[EventPriority.values().length - 1]; + + @Unique + private final List> mfix$batchedCaps = new ArrayList<>(); + + private static final Comparator> MFIX_COMPARATOR = Comparator.comparingInt(pair -> { + var result = CapabilityAnalyzer.analyze(pair.getRight().getClass()); + return result instanceof CapabilityAnalysisResult.Indeterminate ? 1 : 0; + }); + + @Unique + private boolean insertingBatch; + + /** + * @author embeddedt + * @reason batch additions of capability providers within the same phase so that we can hoist all + * the ones with statically known capability types to the beginning of the provider list + */ + @WrapMethod(method = "addCapability", remap = false) + private void mfix$batchCaps(ResourceLocation key, ICapabilityProvider cap, Operation original) { + // For simplicity, we don't try to batch on the last phase + if (this.insertingBatch || this.getPhase() == MFIX_LAST_PRIO) { + original.call(key, cap); + } else { + mfix$batchedCaps.add(Pair.of(key, cap)); + } + } + + @Override + public void setPhase(@NotNull EventPriority value) { + if (!this.mfix$batchedCaps.isEmpty()) { + this.mfix$batchedCaps.sort(MFIX_COMPARATOR); + this.insertingBatch = true; + try { + this.mfix$batchedCaps.forEach(p -> this.addCapability(p.getKey(), p.getValue())); + } finally { + this.insertingBatch = false; + this.mfix$batchedCaps.clear(); + } + } + super.setPhase(value); + } +}