From 7dda653ebf53f8925ed3aa8393f1f4cb1ea2a69d Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Fri, 29 May 2026 01:49:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201=E3=80=81=E6=B7=BB=E5=8A=A0=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E5=90=88=E6=88=90=E5=8D=A1=E5=AF=B9Neo=20ECO=E7=9A=84?= =?UTF-8?q?=E9=80=82=E9=85=8D(issue=20#61)=202=E3=80=81=E6=95=B4=E7=90=86?= =?UTF-8?q?=E8=99=9A=E6=8B=9F=E5=90=88=E6=88=90=E5=8D=A1=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 +- gradle.properties | 2 +- .../mixin/ExtendedAEPlusMixinPlugin.java | 9 + ...rnProviderLogicVirtualCompletionMixin.java | 139 ++++--------- .../PatternProviderLogicCompatMixin.java | 122 ------------ ...rnProviderLogicVirtualCompletionMixin.java | 77 ++++++++ .../accessor/ECOCraftingCPULogicAccessor.java | 16 ++ .../ECOExecutingCraftingJobAccessor.java | 15 ++ .../accessor/ECOTaskProgressAccessor.java | 10 + ...rnProviderLogicVirtualCompletionMixin.java | 78 ++++++++ .../util/VirtualCraftingHelper.java | 187 ++++++++++++++++++ .../resources/extendedae_plus.mixins.json | 7 +- 12 files changed, 443 insertions(+), 225 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicVirtualCompletionMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOCraftingCPULogicAccessor.java create mode 100644 src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOExecutingCraftingJobAccessor.java create mode 100644 src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOTaskProgressAccessor.java create mode 100644 src/main/java/com/extendedae_plus/mixin/neoecoae/compat/PatternProviderLogicVirtualCompletionMixin.java create mode 100644 src/main/java/com/extendedae_plus/util/VirtualCraftingHelper.java diff --git a/build.gradle b/build.gradle index 142f695..1b8513b 100644 --- a/build.gradle +++ b/build.gradle @@ -132,7 +132,7 @@ configurations { dependencies { // --- Added dependencies for target mods --- implementation "curse.maven:glodium-957920:5821676" - implementation "org.appliedenergistics:appliedenergistics2:19.2.15" + implementation "org.appliedenergistics:appliedenergistics2:19.2.17" implementation "org.appliedenergistics:guideme:2.5.1" // jarJar configuration not set in this build; use implementation for API for now implementation "de.mari_023:ae2wtlib_api:19.2.0" @@ -172,6 +172,10 @@ dependencies { //geckolib runtimeOnly "curse.maven:geckolib-388172:7009924" + // eco +// runtimeOnly "curse.maven:ldlib-626676:8133369" + compileOnly "curse.maven:neo-eco-ae-extension-1460639:7884362" + //ftbteams runtimeOnly "curse.maven:ftb-teams-forge-404468:6930910" runtimeOnly "curse.maven:ftb-library-forge-404465:7029003" diff --git a/gradle.properties b/gradle.properties index 63b83ac..396bf7f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ minecraft_version=1.21.1 # as they do not follow standard versioning conventions. minecraft_version_range=[1.21.1] # The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=21.1.206 +neo_version=21.1.216 # The loader version range can only use the major version of FML as bounds loader_version_range=[1,) diff --git a/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java b/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java index 825a8bb..0bd19b5 100644 --- a/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java +++ b/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java @@ -42,6 +42,10 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { return isClassPresent("com.glodblock.github.appflux.AppFlux"); } + private static boolean isNeoECOAEPresent() { + return isClassPresent("cn.dancingsnow.neoecoae.NeoECOAE"); + } + @Override public void onLoad(String mixinPackage) { } @@ -63,6 +67,11 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { return false; } } + if (!isNeoECOAEPresent()) { + if (mixinClassName.startsWith("com.extendedae_plus.mixin.neoecoae.")) { + return false; + } + } if (mixinClassName.equals("com.extendedae_plus.mixin.ae2.CraftingCPUClusterMixin")) { if (isUfoPresent() || isBiggerAePresent()) { return false; diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/compat/PatternProviderLogicVirtualCompletionMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/compat/PatternProviderLogicVirtualCompletionMixin.java index a67c94d..b554d2e 100644 --- a/src/main/java/com/extendedae_plus/mixin/advancedae/compat/PatternProviderLogicVirtualCompletionMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/compat/PatternProviderLogicVirtualCompletionMixin.java @@ -2,7 +2,6 @@ package com.extendedae_plus.mixin.advancedae.compat; import appeng.api.crafting.IPatternDetails; import appeng.api.networking.crafting.ICraftingCPU; -import appeng.api.networking.crafting.ICraftingService; import appeng.api.stacks.KeyCounter; import appeng.helpers.patternprovider.PatternProviderLogic; import com.extendedae_plus.compat.PatternProviderLogicVirtualCompatBridge; @@ -10,9 +9,9 @@ import com.extendedae_plus.mixin.advancedae.accessor.AdvCraftingCPUAccessor; import com.extendedae_plus.mixin.advancedae.accessor.AdvCraftingCPULogicAccessor; import com.extendedae_plus.mixin.advancedae.accessor.AdvExecutingCraftingJobAccessor; import com.extendedae_plus.mixin.advancedae.accessor.AdvExecutingCraftingJobTaskProgressAccessor; +import com.extendedae_plus.util.VirtualCraftingHelper; import net.pedroksl.advanced_ae.common.cluster.AdvCraftingCPU; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -28,114 +27,54 @@ public abstract class PatternProviderLogicVirtualCompletionMixin { @Inject(method = "pushPattern", at = @At("RETURN")) private void eap$advancedaeVirtualCompletion(IPatternDetails patternDetails, KeyCounter[] inputHolder, CallbackInfoReturnable cir) { - if (!cir.getReturnValueZ()) { - return; - } - if (!(this instanceof PatternProviderLogicVirtualCompatBridge bridge)) { - return; - } - if (!bridge.eap$compatIsVirtualCraftingEnabled()) { + if (!cir.getReturnValueZ() + || !(this instanceof PatternProviderLogicVirtualCompatBridge bridge) + || !bridge.eap$compatIsVirtualCraftingEnabled()) { return; } - var mainNode = bridge.eap$compatGetMainNode(); - if (mainNode == null) { - return; - } + VirtualCraftingHelper.executeVirtualCompletion( + bridge.eap$compatGetMainNode(), + patternDetails, + new VirtualCraftingHelper.VirtualCompletionHandler() { + @Override + public boolean isValidCPU(ICraftingCPU cpu) { + return cpu instanceof AdvCraftingCPU; + } - var node = mainNode.getNode(); - if (node == null) { - return; - } - - var grid = node.getGrid(); - if (grid == null) { - return; - } - - ICraftingService craftingService = grid.getCraftingService(); - if (craftingService == null) { - return; - } - - for (ICraftingCPU cpu : craftingService.getCpus()) { - if (!cpu.isBusy()) { - continue; - } - - if (cpu instanceof AdvCraftingCPU advCpu) { - var logic = advCpu.craftingLogic; - if (logic instanceof AdvCraftingCPULogicAccessor advLogicAccessor) { - var job = advLogicAccessor.eap$getAdvJob(); - if (job != null && job instanceof AdvExecutingCraftingJobAccessor advJobAccessor) { - var tasks = advJobAccessor.eap$getAdvTasks(); - var progress = tasks.get(patternDetails); - if (progress == null && patternDetails != null) { - var patternDefinition = patternDetails.getDefinition(); - for (var entry : tasks.entrySet()) { - var taskPattern = entry.getKey(); - if (taskPattern == patternDetails) { - progress = entry.getValue(); - break; - } - if (taskPattern != null && patternDefinition != null) { - var taskDefinition = taskPattern.getDefinition(); - if (taskDefinition != null && taskDefinition.equals(patternDefinition)) { - progress = entry.getValue(); - break; - } - } + @Override + @SuppressWarnings("unchecked") + public Map getTasks( + AdvCraftingCPU cpu) { + var logic = cpu.craftingLogic; + if (logic instanceof AdvCraftingCPULogicAccessor la) { + var job = la.eap$getAdvJob(); + if (job instanceof AdvExecutingCraftingJobAccessor ja) { + return (Map) (Map) ja.eap$getAdvTasks(); } } + return null; + } - if (progress instanceof AdvExecutingCraftingJobTaskProgressAccessor advProgressAccessor) { - if (this.eap$advancedaeShouldCancelWholeJob(tasks, advProgressAccessor)) { - boolean finished = false; - try { - ((AdvCraftingCPUAccessor) (Object) advCpu).eap$invokeUpdateOutput(null); - } catch (Throwable ignored) { - } - try { - advLogicAccessor.eap$invokeAdvFinishJob(true); - finished = true; - } catch (Throwable ignored) { - } - if (!finished) { - advCpu.cancelJob(); - } - break; + @Override + public long getProgressValue(AdvExecutingCraftingJobTaskProgressAccessor progress) { + return progress.eap$getAdvValue(); + } + + @Override + public boolean finishJob(AdvCraftingCPU cpu) { + try { + ((AdvCraftingCPUAccessor) cpu).eap$invokeUpdateOutput(null); + if (cpu.craftingLogic instanceof AdvCraftingCPULogicAccessor la) { + la.eap$invokeAdvFinishJob(true); + return true; } + } catch (Throwable ignored) { } + cpu.cancelJob(); + return true; } } - } - } - } - - @Unique - private boolean eap$advancedaeShouldCancelWholeJob( - Map tasks, - AdvExecutingCraftingJobTaskProgressAccessor matchedProgress) { - if (matchedProgress.eap$getAdvValue() > 1) { - return false; - } - - for (var entry : tasks.entrySet()) { - var taskProgress = entry.getValue(); - if (!(taskProgress instanceof AdvExecutingCraftingJobTaskProgressAccessor advTaskProgress)) { - continue; - } - - long remaining = advTaskProgress.eap$getAdvValue(); - if (taskProgress == matchedProgress) { - remaining -= 1; - } - - if (remaining > 0) { - return false; - } - } - - return true; + ); } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java index c25c192..29c2b18 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java @@ -1,18 +1,14 @@ package com.extendedae_plus.mixin.ae2.compat; -import appeng.api.crafting.IPatternDetails; import appeng.api.networking.IGridConnection; import appeng.api.networking.IManagedGridNode; -import appeng.api.networking.crafting.ICraftingCPU; import appeng.api.networking.security.IActionSource; -import appeng.api.stacks.KeyCounter; import appeng.api.upgrades.IUpgradeInventory; import appeng.api.upgrades.IUpgradeableObject; import appeng.api.upgrades.UpgradeInventories; import appeng.blockentity.AEBaseBlockEntity; import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.helpers.patternprovider.PatternProviderLogicHost; -import appeng.me.cluster.implementations.CraftingCPUCluster; import com.extendedae_plus.ae.wireless.WirelessSlaveLink; import com.extendedae_plus.ae.wireless.endpoint.GenericNodeEndpointImpl; import com.extendedae_plus.api.bridge.CompatUpgradeProvider; @@ -21,9 +17,6 @@ import com.extendedae_plus.api.bridge.PatternProviderLogicUpgradeCompatBridge; import com.extendedae_plus.compat.PatternProviderLogicVirtualCompatBridge; import com.extendedae_plus.compat.UpgradeSlotCompat; import com.extendedae_plus.init.ModItems; -import com.extendedae_plus.mixin.ae2.accessor.CraftingCPUClusterAccessor; -import com.extendedae_plus.mixin.ae2.accessor.CraftingCpuLogicAccessor; -import com.extendedae_plus.mixin.ae2.accessor.ExecutingCraftingJobAccessor; import com.extendedae_plus.mixin.appflux.accessor.PatternProviderLogicAppfluxAccessor; import com.extendedae_plus.util.ExtendedAELogger; import com.extendedae_plus.util.wireless.ChannelCardLinkHelper; @@ -37,9 +30,6 @@ import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Map; import java.util.List; import java.util.UUID; @@ -189,9 +179,6 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr } } - - - @Override public void eap$updateWirelessLink() { if (this.eap$compatLink != null) { @@ -382,10 +369,6 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr private void eap$compatNotifyHostChanged() { try { this.host.saveChanges(); - } catch (Throwable ignored) { - } - - try { if (this.host.getBlockEntity() instanceof AEBaseBlockEntity blockEntity) { blockEntity.markForUpdate(); } @@ -430,84 +413,6 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr return this.eap$compatUpgrades != null ? this.eap$compatUpgrades : UpgradeInventories.empty(); } - @Inject(method = "pushPattern", at = @At("RETURN"), cancellable = true) - private void eap$compatAfterPushPattern(IPatternDetails patternDetails, KeyCounter[] inputHolder, CallbackInfoReturnable cir) { - if (cir.getReturnValueZ()) { - this.eap$compatTryVirtualCompletion(patternDetails); - } - } - - @Unique - private void eap$compatTryVirtualCompletion(IPatternDetails patternDetails) { - if (!this.eap$compatVirtualCraftingEnabled) { - return; - } - - var node = this.mainNode.getNode(); - if (node == null) { - return; - } - - var grid = node.getGrid(); - if (grid == null) { - return; - } - - var craftingService = grid.getCraftingService(); - if (craftingService == null) { - return; - } - - for (ICraftingCPU cpu : craftingService.getCpus()) { - if (!cpu.isBusy()) { - continue; - } - if (cpu instanceof CraftingCPUCluster cluster) { - if (cluster.craftingLogic instanceof CraftingCpuLogicAccessor logicAccessor) { - var job = logicAccessor.eap$getJob(); - if (job instanceof ExecutingCraftingJobAccessor accessor) { - var tasks = accessor.eap$getTasks(); - var progress = tasks.get(patternDetails); - if (progress == null && patternDetails != null) { - var patternDefinition = patternDetails.getDefinition(); - for (var entry : tasks.entrySet()) { - var taskPattern = entry.getKey(); - if (taskPattern == patternDetails) { - progress = entry.getValue(); - break; - } - if (taskPattern != null && patternDefinition != null) { - var taskDefinition = taskPattern.getDefinition(); - if (taskDefinition != null && taskDefinition.equals(patternDefinition)) { - progress = entry.getValue(); - break; - } - } - } - } - - if (this.eap$compatShouldCancelWholeJob(tasks, progress)) { - boolean finished = false; - try { - ((CraftingCPUClusterAccessor) (Object) cluster).eap$invokeUpdateOutput(null); - } catch (Throwable ignored) { - } - try { - logicAccessor.eap$invokeFinishJob(true); - finished = true; - } catch (Throwable ignored) { - } - if (!finished) { - cluster.cancelJob(); - } - break; - } - } - } - } - } - } - @Override public boolean eap$compatIsVirtualCraftingEnabled() { return this.eap$compatVirtualCraftingEnabled; @@ -518,33 +423,6 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr return this.mainNode; } - @Unique - private boolean eap$compatShouldCancelWholeJob( - Map tasks, - com.extendedae_plus.mixin.ae2.accessor.ExecutingCraftingJobTaskProgressAccessor matchedProgress) { - if (matchedProgress == null || matchedProgress.eap$getValue() > 1) { - return false; - } - - for (var entry : tasks.entrySet()) { - var taskProgress = entry.getValue(); - if (taskProgress == null) { - continue; - } - - long remaining = taskProgress.eap$getValue(); - if (taskProgress == matchedProgress) { - remaining -= 1; - } - - if (remaining > 0) { - return false; - } - } - - return true; - } - @Unique private void eap$compatSyncVirtualCraftingState() { try { diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicVirtualCompletionMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicVirtualCompletionMixin.java new file mode 100644 index 0000000..b3d3af2 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicVirtualCompletionMixin.java @@ -0,0 +1,77 @@ +package com.extendedae_plus.mixin.ae2.compat; + +import appeng.api.crafting.IPatternDetails; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.stacks.KeyCounter; +import appeng.helpers.patternprovider.PatternProviderLogic; +import appeng.me.cluster.implementations.CraftingCPUCluster; +import com.extendedae_plus.compat.PatternProviderLogicVirtualCompatBridge; +import com.extendedae_plus.mixin.ae2.accessor.CraftingCPUClusterAccessor; +import com.extendedae_plus.mixin.ae2.accessor.CraftingCpuLogicAccessor; +import com.extendedae_plus.mixin.ae2.accessor.ExecutingCraftingJobAccessor; +import com.extendedae_plus.mixin.ae2.accessor.ExecutingCraftingJobTaskProgressAccessor; +import com.extendedae_plus.util.VirtualCraftingHelper; +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.Map; + +/** + * AE2 版本的虚拟完成兼容逻辑。 + */ +@Mixin(value = PatternProviderLogic.class, priority = 900, remap = false) +public abstract class PatternProviderLogicVirtualCompletionMixin { + + @Inject(method = "pushPattern", at = @At("RETURN")) + private void eap$ae2VirtualCompletion(IPatternDetails patternDetails, KeyCounter[] inputHolder, + CallbackInfoReturnable cir) { + if (!cir.getReturnValueZ() || !(this instanceof PatternProviderLogicVirtualCompatBridge bridge) + || !bridge.eap$compatIsVirtualCraftingEnabled()) { + return; + } + + VirtualCraftingHelper.executeVirtualCompletion( + bridge.eap$compatGetMainNode(), + patternDetails, + new VirtualCraftingHelper.VirtualCompletionHandler() { + @Override + public boolean isValidCPU(ICraftingCPU cpu) { + return cpu instanceof CraftingCPUCluster; + } + + @Override + public Map getTasks(CraftingCPUCluster cpu) { + var logic = cpu.craftingLogic; + if (logic instanceof CraftingCpuLogicAccessor la) { + var job = la.eap$getJob(); + if (job instanceof ExecutingCraftingJobAccessor ja) { + return ja.eap$getTasks(); + } + } + return null; + } + + @Override + public long getProgressValue(ExecutingCraftingJobTaskProgressAccessor progress) { + return progress.eap$getValue(); + } + + @Override + public boolean finishJob(CraftingCPUCluster cpu) { + try { + ((CraftingCPUClusterAccessor) (Object) cpu).eap$invokeUpdateOutput(null); + if (cpu.craftingLogic instanceof CraftingCpuLogicAccessor la) { + la.eap$invokeFinishJob(true); + return true; + } + } catch (Throwable ignored) { + } + cpu.cancelJob(); + return true; + } + } + ); + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOCraftingCPULogicAccessor.java b/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOCraftingCPULogicAccessor.java new file mode 100644 index 0000000..a0fb6a7 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOCraftingCPULogicAccessor.java @@ -0,0 +1,16 @@ +package com.extendedae_plus.mixin.neoecoae.accessor; + +import cn.dancingsnow.neoecoae.api.me.ECOCraftingCPULogic; +import cn.dancingsnow.neoecoae.api.me.ExecutingCraftingJob; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = ECOCraftingCPULogic.class, remap = false) +public interface ECOCraftingCPULogicAccessor { + @Accessor("job") + ExecutingCraftingJob eap$getECOJob(); + + @Invoker("finishJob") + void eap$invokeECOFinishJob(boolean success); +} diff --git a/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOExecutingCraftingJobAccessor.java b/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOExecutingCraftingJobAccessor.java new file mode 100644 index 0000000..21bf094 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOExecutingCraftingJobAccessor.java @@ -0,0 +1,15 @@ +package com.extendedae_plus.mixin.neoecoae.accessor; + +import appeng.api.crafting.IPatternDetails; +import cn.dancingsnow.neoecoae.api.me.ExecutingCraftingJob; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(value = ExecutingCraftingJob.class, remap = false) +public interface ECOExecutingCraftingJobAccessor { + + @Accessor("tasks") + Map eap$getECOTasks(); +} diff --git a/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOTaskProgressAccessor.java b/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOTaskProgressAccessor.java new file mode 100644 index 0000000..57c0185 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/neoecoae/accessor/ECOTaskProgressAccessor.java @@ -0,0 +1,10 @@ +package com.extendedae_plus.mixin.neoecoae.accessor; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(targets = "cn.dancingsnow.neoecoae.api.me.ExecutingCraftingJob$TaskProgress", remap = false) +public interface ECOTaskProgressAccessor { + @Accessor("value") + long eap$getECOValue(); +} diff --git a/src/main/java/com/extendedae_plus/mixin/neoecoae/compat/PatternProviderLogicVirtualCompletionMixin.java b/src/main/java/com/extendedae_plus/mixin/neoecoae/compat/PatternProviderLogicVirtualCompletionMixin.java new file mode 100644 index 0000000..e198f37 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/neoecoae/compat/PatternProviderLogicVirtualCompletionMixin.java @@ -0,0 +1,78 @@ +package com.extendedae_plus.mixin.neoecoae.compat; + +import appeng.api.crafting.IPatternDetails; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.stacks.KeyCounter; +import appeng.helpers.patternprovider.PatternProviderLogic; +import cn.dancingsnow.neoecoae.api.me.ECOCraftingCPU; +import com.extendedae_plus.compat.PatternProviderLogicVirtualCompatBridge; +import com.extendedae_plus.mixin.neoecoae.accessor.ECOCraftingCPULogicAccessor; +import com.extendedae_plus.mixin.neoecoae.accessor.ECOExecutingCraftingJobAccessor; +import com.extendedae_plus.mixin.neoecoae.accessor.ECOTaskProgressAccessor; +import com.extendedae_plus.util.VirtualCraftingHelper; +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.Map; + +/** + * NeoECOAE 版本的虚拟完成兼容逻辑。 + */ +@Mixin(value = PatternProviderLogic.class, priority = 840, remap = false) +public abstract class PatternProviderLogicVirtualCompletionMixin { + + @Inject(method = "pushPattern", at = @At("RETURN")) + private void eap$neoecoaeVirtualCompletion(IPatternDetails patternDetails, KeyCounter[] inputHolder, + CallbackInfoReturnable cir) { + if (!cir.getReturnValueZ() + || !(this instanceof PatternProviderLogicVirtualCompatBridge bridge) + || !bridge.eap$compatIsVirtualCraftingEnabled()) { + return; + } + + VirtualCraftingHelper.executeVirtualCompletion( + bridge.eap$compatGetMainNode(), + patternDetails, + new VirtualCraftingHelper.VirtualCompletionHandler() { + @Override + public boolean isValidCPU(ICraftingCPU cpu) { + return cpu instanceof ECOCraftingCPU; + } + + @Override + @SuppressWarnings("unchecked") + public Map getTasks(ECOCraftingCPU cpu) { + var logic = cpu.getLogic(); + if (logic instanceof ECOCraftingCPULogicAccessor la) { + var job = la.eap$getECOJob(); + if (job instanceof ECOExecutingCraftingJobAccessor ja) { + return (Map) (Map) ja.eap$getECOTasks(); + } + } + return null; + } + + @Override + public long getProgressValue(ECOTaskProgressAccessor progress) { + return progress.eap$getECOValue(); + } + + @Override + public boolean finishJob(ECOCraftingCPU cpu) { + try { + var logic = cpu.getLogic(); + if (logic instanceof ECOCraftingCPULogicAccessor la) { + la.eap$invokeECOFinishJob(true); + return true; + } + } catch (Throwable ignored) { + } + cpu.cancelJob(); + return true; + } + } + ); + } +} diff --git a/src/main/java/com/extendedae_plus/util/VirtualCraftingHelper.java b/src/main/java/com/extendedae_plus/util/VirtualCraftingHelper.java new file mode 100644 index 0000000..8d1aa9c --- /dev/null +++ b/src/main/java/com/extendedae_plus/util/VirtualCraftingHelper.java @@ -0,0 +1,187 @@ +package com.extendedae_plus.util; + +import appeng.api.crafting.IPatternDetails; +import appeng.api.networking.IManagedGridNode; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.crafting.ICraftingService; + +import java.util.Map; +import java.util.function.Function; + +/** + * 虚拟合成卡辅助工具类 + * 用于处理不同MOD的CPU虚拟完成逻辑 + */ +public class VirtualCraftingHelper { + + /** + * 检查是否应该取消整个任务 + * + * @param tasks 任务映射 + * @param matchedProgress 匹配到的进度 + * @param valueExtractor 提取进度的函数 + * @return 是否应该取消整个任务 + */ + public static boolean shouldCancelWholeJob( + Map tasks, + T matchedProgress, + Function valueExtractor) { + if (matchedProgress == null) { + return false; + } + long matchedValue = valueExtractor.apply(matchedProgress); + if (matchedValue > 1) { + return false; + } + + for (var entry : tasks.entrySet()) { + var taskProgress = entry.getValue(); + if (taskProgress == null) { + continue; + } + + long remaining = valueExtractor.apply(taskProgress); + if (taskProgress == matchedProgress) { + remaining -= 1; + } + + if (remaining > 0) { + return false; + } + } + + return true; + } + + /** + * 查找匹配的进度 + * + * @param tasks 任务映射 + * @param patternDetails 样板详情 + * @return 匹配的进度,如果没有则返回null + */ + public static T findMatchingProgress( + Map tasks, + IPatternDetails patternDetails) { + if (patternDetails == null) { + return null; + } + + var progress = tasks.get(patternDetails); + if (progress != null) { + return progress; + } + + var patternDefinition = patternDetails.getDefinition(); + for (var entry : tasks.entrySet()) { + var taskPattern = entry.getKey(); + if (taskPattern == patternDetails) { + return entry.getValue(); + } + if (taskPattern != null && patternDefinition != null) { + var taskDefinition = taskPattern.getDefinition(); + if (taskDefinition != null && taskDefinition.equals(patternDefinition)) { + return entry.getValue(); + } + } + } + + return null; + } + + /** + * 获取网格的合成服务 + * + * @param mainNode 主节点 + * @return 合成服务,如果不可用则返回null + */ + public static ICraftingService getCraftingService(IManagedGridNode mainNode) { + if (mainNode == null) { + return null; + } + + var node = mainNode.getNode(); + if (node == null) { + return null; + } + + var grid = node.getGrid(); + if (grid == null) { + return null; + } + + return grid.getCraftingService(); + } + + /** + * 虚拟完成处理器接口 + */ + public interface VirtualCompletionHandler { + /** + * 检查CPU类型是否匹配 + */ + boolean isValidCPU(ICraftingCPU cpu); + + /** + * 获取任务映射 + */ + Map getTasks(T cpu); + + /** + * 获取进度值 + */ + long getProgressValue(P progress); + + /** + * 完成任务 + * @return 是否成功完成 + */ + boolean finishJob(T cpu); + } + + /** + * 执行虚拟完成逻辑 + * + * @param mainNode 主节点 + * @param patternDetails 样板详情 + * @param handler 处理器 + */ + @SuppressWarnings("unchecked") + public static void executeVirtualCompletion( + IManagedGridNode mainNode, + IPatternDetails patternDetails, + VirtualCompletionHandler handler) { + + ICraftingService craftingService = getCraftingService(mainNode); + if (craftingService == null) { + return; + } + + for (ICraftingCPU cpu : craftingService.getCpus()) { + if (!cpu.isBusy()) { + continue; + } + + if (!handler.isValidCPU(cpu)) { + continue; + } + + T typedCpu = (T) cpu; + Map tasks = handler.getTasks(typedCpu); + if (tasks == null) { + continue; + } + + P progress = findMatchingProgress(tasks, patternDetails); + if (progress == null) { + continue; + } + + if (shouldCancelWholeJob(tasks, progress, handler::getProgressValue)) { + if (handler.finishJob(typedCpu)) { + break; + } + } + } + } +} diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index d8e80a1..5e12244 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -39,6 +39,7 @@ "ae2.autopattern.CraftingSimulationStateMixin", "ae2.autopattern.PatternProviderLogicContainsRedirectMixin", "ae2.compat.PatternProviderLogicCompatMixin", + "ae2.compat.PatternProviderLogicVirtualCompletionMixin", "ae2.helpers.InterfaceLogicChannelCardMixin", "ae2.helpers.InterfaceLogicTickerMixin", "ae2.helpers.InterfaceLogicUpgradesMixin", @@ -71,7 +72,11 @@ "extendedae.container.ContainerExPatternProviderMixin", "extendedae.container.ContainerExPatternTerminalMixin", "extendedae.container.ContainerWirelessExPatternTerminalMixin", - "minecraft.accessor.BlockEntityAccessor" + "minecraft.accessor.BlockEntityAccessor", + "neoecoae.accessor.ECOCraftingCPULogicAccessor", + "neoecoae.accessor.ECOExecutingCraftingJobAccessor", + "neoecoae.accessor.ECOTaskProgressAccessor", + "neoecoae.compat.PatternProviderLogicVirtualCompletionMixin" ], "client": [ "accessor.AbstractContainerScreenAccessor",