From e45bcf87b04468716dba35259e348e32f80c6b20 Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Sat, 20 Sep 2025 22:05:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=99=BA=E8=83=BD?= =?UTF-8?q?=E7=B3=BB=E5=88=97=E5=AF=B9=E9=AB=98=E7=BA=A7ae=E4=BE=9B?= =?UTF-8?q?=E5=BA=94=E5=99=A8=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 + ...ernProviderLogicContainsRedirectMixin.java | 38 +++++ ...vPatternProviderLogicPatternsAccessor.java | 14 ++ ...dvPatternProviderMenuAdvancedAccessor.java | 12 ++ .../gui/AdvPatternProviderScreenMixin.java | 139 ++++++++++++++++++ .../SmallAdvPatternProviderScreenMixin.java | 139 ++++++++++++++++++ .../AdvPatternProviderLogicAdvancedMixin.java | 94 ++++++++++++ .../AdvPatternProviderLogicDoublingMixin.java | 76 ++++++++++ .../AdvPatternProviderMenuAdvancedMixin.java | 43 ++++++ .../AdvPatternProviderMenuDoublingMixin.java | 41 ++++++ .../PatternProviderLogicAdvancedMixin.java | 9 +- .../PatternProviderLogicDoublingMixin.java | 9 +- .../ToggleAdvancedBlockingC2SPacket.java | 47 ++++-- .../network/ToggleSmartDoublingC2SPacket.java | 35 +++-- .../resources/extendedae_plus.mixins.json | 9 ++ 15 files changed, 675 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/AdvPatternProviderLogicContainsRedirectMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderLogicPatternsAccessor.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderMenuAdvancedAccessor.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/AdvPatternProviderScreenMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/SmallAdvPatternProviderScreenMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicAdvancedMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicDoublingMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuAdvancedMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuDoublingMixin.java diff --git a/build.gradle b/build.gradle index 9687e17..8bbce35 100644 --- a/build.gradle +++ b/build.gradle @@ -162,6 +162,12 @@ dependencies { // runtimeOnly "mekanism:Mekanism:1.21.1-10.7.0.55" runtimeOnly "curse.maven:ex-pattern-provider-892005:6863556" + //aea + implementation "curse.maven:advancedae-1084104:6921281" + + //geckolib + runtimeOnly "curse.maven:geckolib-388172:7009924" + // setup Xei (EMI/REI/JEI) using project property 'use_Xei' switch (project.findProperty('use_Xei') ?: 'emi') { case 'emi': diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/AdvPatternProviderLogicContainsRedirectMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/AdvPatternProviderLogicContainsRedirectMixin.java new file mode 100644 index 0000000..0773388 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/AdvPatternProviderLogicContainsRedirectMixin.java @@ -0,0 +1,38 @@ +package com.extendedae_plus.mixin.advancedae; + +import appeng.api.crafting.IPatternDetails; +import com.extendedae_plus.content.ScaledProcessingPattern; +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.List; + +/**适配 + * Redirect PatternProviderLogic.pushPattern 中对 List.contains 的调用, + * 在遇到缩放样板时回退匹配到原始样板实例。 + */ +@Mixin(value = AdvPatternProviderLogic.class, remap = false) +public class AdvPatternProviderLogicContainsRedirectMixin { + + @Redirect(method = "pushPattern", + at = @At( + value = "INVOKE", + target = "Ljava/util/List;contains(Ljava/lang/Object;)Z") + ) + private boolean eap$patternsContains(List list, Object o) { + try { + if (o instanceof ScaledProcessingPattern scaled) { + IPatternDetails base = scaled.getOriginal(); + if (base != null && list.indexOf(base) != -1) { + return true; + } + } + // 使用 indexOf 避免再次触发对 List.contains 的 redirect(防止递归) + return list.indexOf(o) != -1; + } catch (Throwable t) { + return list.indexOf(o) != -1; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderLogicPatternsAccessor.java b/src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderLogicPatternsAccessor.java new file mode 100644 index 0000000..a75643c --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderLogicPatternsAccessor.java @@ -0,0 +1,14 @@ +package com.extendedae_plus.mixin.advancedae.accessor; + +import appeng.api.crafting.IPatternDetails; +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(value = AdvPatternProviderLogic.class, remap = false) +public interface AdvPatternProviderLogicPatternsAccessor { + @Accessor("patterns") + List eap$patterns(); +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderMenuAdvancedAccessor.java b/src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderMenuAdvancedAccessor.java new file mode 100644 index 0000000..bd75482 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/accessor/AdvPatternProviderMenuAdvancedAccessor.java @@ -0,0 +1,12 @@ +package com.extendedae_plus.mixin.advancedae.accessor; + +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AdvPatternProviderMenu.class) +public interface AdvPatternProviderMenuAdvancedAccessor { + @Accessor(value = "logic", remap = false) + AdvPatternProviderLogic eap$logic(); +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/AdvPatternProviderScreenMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/AdvPatternProviderScreenMixin.java new file mode 100644 index 0000000..2136f1a --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/AdvPatternProviderScreenMixin.java @@ -0,0 +1,139 @@ +package com.extendedae_plus.mixin.advancedae.client.gui; + +import appeng.api.config.Settings; +import appeng.api.config.YesNo; +import appeng.client.gui.AEBaseScreen; +import appeng.client.gui.style.ScreenStyle; +import appeng.client.gui.widgets.SettingToggleButton; +import com.extendedae_plus.api.PatternProviderMenuAdvancedSync; +import com.extendedae_plus.api.PatternProviderMenuDoublingSync; +import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket; +import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.pedroksl.advanced_ae.client.gui.AdvPatternProviderScreen; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; +import org.checkerframework.checker.units.qual.C; +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.CallbackInfo; + +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; + +/** + * 为高级ae样板供应器界面添加“高级阻挡模式”按钮。 + * - 位于左侧工具栏 + * - 点击仅发送 C2S 切换请求;状态由 AE2 @GuiSync 回传决定 + */ +@Mixin(AdvPatternProviderScreen.class) +public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen { + + @Unique + private SettingToggleButton eap$AdvancedBlockingToggle; + + @Unique + private boolean eap$AdvancedBlockingEnabled = false; + + @Unique + private SettingToggleButton eap$SmartDoublingToggle; + + @Unique + private boolean eap$SmartDoublingEnabled = false; + + public AdvPatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) { + super((AdvPatternProviderMenu) menu, playerInventory, title, style); + } + + @Inject(method = "", at = @At("RETURN")) + private void eap$initAdvancedBlocking(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) { + // 使用 @GuiSync 初始化 + try { + if (menu instanceof PatternProviderMenuAdvancedSync sync) { + this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced(); + } + } catch (Throwable t) { + LOGGER.error("Error initializing advanced sync", t); + } + + // 使用 SettingToggleButton 的外观(原版图标),但自定义悬停描述为“智能阻挡” + this.eap$AdvancedBlockingToggle = new SettingToggleButton<>( + Settings.BLOCKING_MODE, + this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO, + (btn, backwards) -> { + // 不做本地切换,点击仅发送自定义C2S,显示由@GuiSync回传 + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(ToggleAdvancedBlockingC2SPacket.INSTANCE); + } + ) { + @Override + public java.util.List getTooltipMessage() { + boolean enabled = eap$AdvancedBlockingEnabled; + var title = Component.literal("智能阻挡"); + var line = enabled + ? Component.literal("已启用:对于同一种配方将不再阻挡(需要开启原版的阻挡模式)") + : Component.literal("已禁用:这么好的功能为什么不打开呢"); + return java.util.List.of(title, line); + } + }; + // 初始化后立刻对齐当前@GuiSync状态,避免首帧显示不一致 + this.eap$AdvancedBlockingToggle.set(this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO); + + this.addToLeftToolbar(this.eap$AdvancedBlockingToggle); + + // 智能翻倍按钮:与高级阻挡同款样式,点击仅发送C2S,状态由@GuiSync驱动 + try { + if (menu instanceof PatternProviderMenuDoublingSync sync2) { + this.eap$SmartDoublingEnabled = sync2.eap$getSmartDoublingSynced(); + } + } catch (Throwable t) { + LOGGER.error("Error initializing smart doubling sync", t); + } + + this.eap$SmartDoublingToggle = new SettingToggleButton<>( + Settings.BLOCKING_MODE, + this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO, + (btn, backwards) -> { + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE); + } + ) { + @Override + public java.util.List getTooltipMessage() { + boolean enabled = eap$SmartDoublingEnabled; + var title = Component.literal("智能翻倍"); + var line = enabled + ? Component.literal("已启用:根据请求量对处理样板进行智能缩放") + : Component.literal("已禁用:按原始样板数量进行发配"); + return java.util.List.of(title, line); + } + }; + + this.eap$SmartDoublingToggle.set(this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO); + this.addToLeftToolbar(this.eap$SmartDoublingToggle); + } + + // 每帧刷新:仅从菜单(@GuiSync)同步布尔值,保持按钮状态一致 + @Inject(method = "updateBeforeRender", at = @At("HEAD"), remap = false) + private void eap$updateAdvancedBlocking(CallbackInfo ci) { + if (this.eap$AdvancedBlockingToggle != null) { + boolean desired = this.eap$AdvancedBlockingEnabled; + if (this.menu instanceof PatternProviderMenuAdvancedSync sync) { + desired = sync.eap$getAdvancedBlockingSynced(); + } + this.eap$AdvancedBlockingEnabled = desired; + this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO); + } + + if (this.eap$SmartDoublingToggle != null) { + boolean desired2 = this.eap$SmartDoublingEnabled; + if (this.menu instanceof PatternProviderMenuDoublingSync sync2) { + desired2 = sync2.eap$getSmartDoublingSynced(); + } + this.eap$SmartDoublingEnabled = desired2; + this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO); + } + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/SmallAdvPatternProviderScreenMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/SmallAdvPatternProviderScreenMixin.java new file mode 100644 index 0000000..d7be718 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/client/gui/SmallAdvPatternProviderScreenMixin.java @@ -0,0 +1,139 @@ +package com.extendedae_plus.mixin.advancedae.client.gui; + +import appeng.api.config.Settings; +import appeng.api.config.YesNo; +import appeng.client.gui.AEBaseScreen; +import appeng.client.gui.style.ScreenStyle; +import appeng.client.gui.widgets.SettingToggleButton; +import com.extendedae_plus.api.PatternProviderMenuAdvancedSync; +import com.extendedae_plus.api.PatternProviderMenuDoublingSync; +import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket; +import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.pedroksl.advanced_ae.client.gui.SmallAdvPatternProviderScreen; +import net.pedroksl.advanced_ae.gui.advpatternprovider.SmallAdvPatternProviderMenu; +import org.checkerframework.checker.units.qual.C; +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.CallbackInfo; + +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; + +/** + * 为高级ae样板供应器界面添加“高级阻挡模式”按钮。 + * - 位于左侧工具栏 + * - 点击仅发送 C2S 切换请求;状态由 AE2 @GuiSync 回传决定 + */ +@Mixin(SmallAdvPatternProviderScreen.class) +public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen { + + @Unique + private SettingToggleButton eap$AdvancedBlockingToggle; + + @Unique + private boolean eap$AdvancedBlockingEnabled = false; + + @Unique + private SettingToggleButton eap$SmartDoublingToggle; + + @Unique + private boolean eap$SmartDoublingEnabled = false; + + public SmallAdvPatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) { + super((SmallAdvPatternProviderMenu) menu, playerInventory, title, style); + } + + @Inject(method = "", at = @At("RETURN")) + private void eap$initAdvancedBlocking(SmallAdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) { + // 使用 @GuiSync 初始化 + try { + if (menu instanceof PatternProviderMenuAdvancedSync sync) { + this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced(); + } + } catch (Throwable t) { + LOGGER.error("Error initializing advanced sync", t); + } + + // 使用 SettingToggleButton 的外观(原版图标),但自定义悬停描述为“智能阻挡” + this.eap$AdvancedBlockingToggle = new SettingToggleButton<>( + Settings.BLOCKING_MODE, + this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO, + (btn, backwards) -> { + // 不做本地切换,点击仅发送自定义C2S,显示由@GuiSync回传 + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(ToggleAdvancedBlockingC2SPacket.INSTANCE); + } + ) { + @Override + public java.util.List getTooltipMessage() { + boolean enabled = eap$AdvancedBlockingEnabled; + var title = Component.literal("智能阻挡"); + var line = enabled + ? Component.literal("已启用:对于同一种配方将不再阻挡(需要开启原版的阻挡模式)") + : Component.literal("已禁用:这么好的功能为什么不打开呢"); + return java.util.List.of(title, line); + } + }; + // 初始化后立刻对齐当前@GuiSync状态,避免首帧显示不一致 + this.eap$AdvancedBlockingToggle.set(this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO); + + this.addToLeftToolbar(this.eap$AdvancedBlockingToggle); + + // 智能翻倍按钮:与高级阻挡同款样式,点击仅发送C2S,状态由@GuiSync驱动 + try { + if (menu instanceof PatternProviderMenuDoublingSync sync2) { + this.eap$SmartDoublingEnabled = sync2.eap$getSmartDoublingSynced(); + } + } catch (Throwable t) { + LOGGER.error("Error initializing smart doubling sync", t); + } + + this.eap$SmartDoublingToggle = new SettingToggleButton<>( + Settings.BLOCKING_MODE, + this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO, + (btn, backwards) -> { + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE); + } + ) { + @Override + public java.util.List getTooltipMessage() { + boolean enabled = eap$SmartDoublingEnabled; + var title = Component.literal("智能翻倍"); + var line = enabled + ? Component.literal("已启用:根据请求量对处理样板进行智能缩放") + : Component.literal("已禁用:按原始样板数量进行发配"); + return java.util.List.of(title, line); + } + }; + + this.eap$SmartDoublingToggle.set(this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO); + this.addToLeftToolbar(this.eap$SmartDoublingToggle); + } + + // 每帧刷新:仅从菜单(@GuiSync)同步布尔值,保持按钮状态一致 + @Inject(method = "updateBeforeRender", at = @At("HEAD"), remap = false) + private void eap$updateAdvancedBlocking(CallbackInfo ci) { + if (this.eap$AdvancedBlockingToggle != null) { + boolean desired = this.eap$AdvancedBlockingEnabled; + if (this.menu instanceof PatternProviderMenuAdvancedSync sync) { + desired = sync.eap$getAdvancedBlockingSynced(); + } + this.eap$AdvancedBlockingEnabled = desired; + this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO); + } + + if (this.eap$SmartDoublingToggle != null) { + boolean desired2 = this.eap$SmartDoublingEnabled; + if (this.menu instanceof PatternProviderMenuDoublingSync sync2) { + desired2 = sync2.eap$getSmartDoublingSynced(); + } + this.eap$SmartDoublingEnabled = desired2; + this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO); + } + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicAdvancedMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicAdvancedMixin.java new file mode 100644 index 0000000..0cce26d --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicAdvancedMixin.java @@ -0,0 +1,94 @@ +package com.extendedae_plus.mixin.advancedae.helpers; + +import appeng.api.crafting.IPatternDetails; +import appeng.api.crafting.IPatternDetails.IInput; +import appeng.api.stacks.AEKey; +import appeng.api.stacks.GenericStack; +import appeng.helpers.patternprovider.PatternProviderTarget; +import com.extendedae_plus.api.AdvancedBlockingHolder; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Collections; + +@Mixin(value = AdvPatternProviderLogic.class, remap = false) +public class AdvPatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder { + @Unique + private static final String EAP_ADV_BLOCKING_KEY = "eap_advanced_blocking"; + + @Unique + private boolean eap$advancedBlocking = false; + + @Override + public boolean eap$getAdvancedBlocking() { + return eap$advancedBlocking; + } + + @Override + public void eap$setAdvancedBlocking(boolean value) { + this.eap$advancedBlocking = value; + } + + @Inject(method = "writeToNBT", at = @At("TAIL")) + private void eap$writeAdvancedToNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { + tag.putBoolean(EAP_ADV_BLOCKING_KEY, this.eap$advancedBlocking); + } + + @Inject(method = "readFromNBT", at = @At("TAIL")) + private void eap$readAdvancedFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { + if (tag.contains(EAP_ADV_BLOCKING_KEY)) { + this.eap$advancedBlocking = tag.getBoolean(EAP_ADV_BLOCKING_KEY); + } + } + + // 在 pushPattern 中,重定向对 adapter.containsPatternInput(...) 的调用 + @Redirect(method = "pushPattern", at = @At(value = "INVOKE", target = "Lappeng/helpers/patternprovider/PatternProviderTarget;containsPatternInput(Ljava/util/Set;)Z")) + private boolean eap$redirectBlockingContains(PatternProviderTarget adapter, + java.util.Set patternInputs, + IPatternDetails patternDetails, + appeng.api.stacks.KeyCounter[] inputHolder) { + // 原版是否打开阻挡 + boolean vanillaBlocking = ((AdvPatternProviderLogic)(Object)this).isBlocking(); + if (!vanillaBlocking) { + return adapter.containsPatternInput(patternInputs); + } + + // 仅当高级阻挡启用时启用“匹配则不阻挡” + if (this.eap$advancedBlocking) { + if (eap$targetFullyMatchesPatternInputs(adapter, patternDetails)) { + // 返回 false 表示“不包含阻挡关键物”,从而不触发 continue,允许发配 + return false; + } + } + // 否则使用原判定 + return adapter.containsPatternInput(patternInputs); + } + + @Unique + private boolean eap$targetFullyMatchesPatternInputs(PatternProviderTarget adapter, IPatternDetails patternDetails) { + for (IInput in : patternDetails.getInputs()) { + boolean slotMatched = false; + for (GenericStack candidate : in.getPossibleInputs()) { + AEKey key = candidate.what().dropSecondary(); + if (adapter.containsPatternInput(Collections.singleton(key))) { + slotMatched = true; + break; + } + } + if (!slotMatched) { + return false; // 任一输入槽未匹配则失败 + } + } + return true; // 每个输入槽都至少匹配了一个候选输入 + } + + @Shadow public void saveChanges() {} +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicDoublingMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicDoublingMixin.java new file mode 100644 index 0000000..e3f3b3e --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/helpers/AdvPatternProviderLogicDoublingMixin.java @@ -0,0 +1,76 @@ +package com.extendedae_plus.mixin.advancedae.helpers; + +import appeng.api.crafting.IPatternDetails; +import appeng.crafting.pattern.AEProcessingPattern; +import com.extendedae_plus.api.SmartDoublingAwarePattern; +import com.extendedae_plus.api.SmartDoublingHolder; +import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderLogicPatternsAccessor; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; + +@Mixin(value = AdvPatternProviderLogic.class, remap = false) +public class AdvPatternProviderLogicDoublingMixin implements SmartDoublingHolder { + @Unique + private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling"; + + @Unique + private boolean eap$smartDoubling = false; + + @Override + public boolean eap$getSmartDoubling() { + return eap$smartDoubling; + } + + @Override + public void eap$setSmartDoubling(boolean value) { + this.eap$smartDoubling = value; + // 立即将开关状态应用到当前 Provider 的样板上,避免等待下一次 updatePatterns + try { + var list = ((AdvPatternProviderLogicPatternsAccessor) this).eap$patterns(); + for (IPatternDetails details : list) { + if (details instanceof AEProcessingPattern proc && proc instanceof SmartDoublingAwarePattern aware) { + aware.eap$setAllowScaling(value); + } + } + // 触发一次刷新,让网络及时拿到最新状态(也会触发 ICraftingProvider.requestUpdate(mainNode)) + ((AdvPatternProviderLogic) (Object) this).updatePatterns(); + } catch (Throwable ignored) { + } + } + + @Inject(method = "writeToNBT", at = @At("TAIL")) + private void eap$writeSmartDoublingToNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { + tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling); + } + + @Inject(method = "readFromNBT", at = @At("TAIL")) + private void eap$readSmartDoublingFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { + if (tag.contains(EAP_SMART_DOUBLING_KEY)) { + this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY); + } + } + + @Inject(method = "updatePatterns", at = @At("TAIL")) + private void eap$applySmartDoublingToPatterns(CallbackInfo ci) { + try { + var list = ((AdvPatternProviderLogicPatternsAccessor) this).eap$patterns(); + boolean allow = this.eap$smartDoubling; + for (IPatternDetails details : list) { + if (details instanceof AEProcessingPattern proc && proc instanceof SmartDoublingAwarePattern aware) { + aware.eap$setAllowScaling(allow); + } + } + } catch (Throwable ignored) { + } + } + + @Shadow + public void saveChanges() {} +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuAdvancedMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuAdvancedMixin.java new file mode 100644 index 0000000..65e8b9d --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuAdvancedMixin.java @@ -0,0 +1,43 @@ +package com.extendedae_plus.mixin.advancedae.menu; + +import appeng.menu.AEBaseMenu; +import appeng.menu.guisync.GuiSync; +import com.extendedae_plus.api.AdvancedBlockingHolder; +import com.extendedae_plus.api.PatternProviderMenuAdvancedSync; +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; + +@Mixin(AdvPatternProviderMenu.class) +public abstract class AdvPatternProviderMenuAdvancedMixin implements PatternProviderMenuAdvancedSync { + @Final + @Shadow(remap = false) + protected AdvPatternProviderLogic logic; + + // 选择一个未占用的 GUI 同步 id(AE2 已用到 7),这里使用 21 以避冲突 + @Unique + @GuiSync(22) + public boolean eap$AdvancedBlocking = false; + + @Inject(method = "broadcastChanges", at = @At("HEAD")) + private void eap$syncAdvancedBlocking(CallbackInfo ci) { + // 避免@Shadow父类方法,改用公共API:AEBaseMenu#isClientSide() + if (!((AEBaseMenu) (Object) this).isClientSide()) { + var l = this.logic; + if (l instanceof AdvancedBlockingHolder holder) { + this.eap$AdvancedBlocking = holder.eap$getAdvancedBlocking(); + } + } + } + + @Override + public boolean eap$getAdvancedBlockingSynced() { + return this.eap$AdvancedBlocking; + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuDoublingMixin.java b/src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuDoublingMixin.java new file mode 100644 index 0000000..b5f0493 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/advancedae/menu/AdvPatternProviderMenuDoublingMixin.java @@ -0,0 +1,41 @@ +package com.extendedae_plus.mixin.advancedae.menu; + +import appeng.menu.AEBaseMenu; +import appeng.menu.guisync.GuiSync; +import com.extendedae_plus.api.PatternProviderMenuDoublingSync; +import com.extendedae_plus.api.SmartDoublingHolder; +import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; + +@Mixin(AdvPatternProviderMenu.class) +public abstract class AdvPatternProviderMenuDoublingMixin implements PatternProviderMenuDoublingSync { + @Final + @Shadow(remap = false) + protected AdvPatternProviderLogic logic; + + @Unique + @GuiSync(23) + public boolean eap$SmartDoubling = false; + + @Inject(method = "broadcastChanges", at = @At("HEAD")) + private void eap$syncSmartDoubling(CallbackInfo ci) { + if (!((AEBaseMenu) (Object) this).isClientSide()) { + var l = this.logic; + if (l instanceof SmartDoublingHolder holder) { + this.eap$SmartDoubling = holder.eap$getSmartDoubling(); + } + } + } + + @Override + public boolean eap$getSmartDoublingSynced() { + return this.eap$SmartDoubling; + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicAdvancedMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicAdvancedMixin.java index 3990ae3..cb00349 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicAdvancedMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicAdvancedMixin.java @@ -8,7 +8,6 @@ import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.helpers.patternprovider.PatternProviderTarget; import com.extendedae_plus.api.AdvancedBlockingHolder; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -22,7 +21,7 @@ import java.util.Collections; @Mixin(value = PatternProviderLogic.class, remap = false) public class PatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder { @Unique - private static final String EPP_ADV_BLOCKING_KEY = "epp_advanced_blocking"; + private static final String EAP_ADV_BLOCKING_KEY = "epp_advanced_blocking"; @Unique private boolean eap$advancedBlocking = false; @@ -39,13 +38,13 @@ public class PatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder @Inject(method = "writeToNBT", at = @At("TAIL")) private void eap$writeAdvancedToNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { - tag.putBoolean(EPP_ADV_BLOCKING_KEY, this.eap$advancedBlocking); + tag.putBoolean(EAP_ADV_BLOCKING_KEY, this.eap$advancedBlocking); } @Inject(method = "readFromNBT", at = @At("TAIL")) private void eap$readAdvancedFromNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { - if (tag.contains(EPP_ADV_BLOCKING_KEY)) { - this.eap$advancedBlocking = tag.getBoolean(EPP_ADV_BLOCKING_KEY); + if (tag.contains(EAP_ADV_BLOCKING_KEY)) { + this.eap$advancedBlocking = tag.getBoolean(EAP_ADV_BLOCKING_KEY); } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicDoublingMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicDoublingMixin.java index ad455d6..60b65ec 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicDoublingMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicDoublingMixin.java @@ -7,7 +7,6 @@ import com.extendedae_plus.api.SmartDoublingAwarePattern; import com.extendedae_plus.api.SmartDoublingHolder; import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicPatternsAccessor; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -18,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = PatternProviderLogic.class, remap = false) public class PatternProviderLogicDoublingMixin implements SmartDoublingHolder { @Unique - private static final String EPP_SMART_DOUBLING_KEY = "epp_smart_doubling"; + private static final String EAP_SMART_DOUBLING_KEY = "epp_smart_doubling"; @Unique private boolean eap$smartDoubling = false; @@ -47,13 +46,13 @@ public class PatternProviderLogicDoublingMixin implements SmartDoublingHolder { @Inject(method = "writeToNBT", at = @At("TAIL")) private void eap$writeSmartDoublingToNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { - tag.putBoolean(EPP_SMART_DOUBLING_KEY, this.eap$smartDoubling); + tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling); } @Inject(method = "readFromNBT", at = @At("TAIL")) private void eap$readSmartDoublingFromNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { - if (tag.contains(EPP_SMART_DOUBLING_KEY)) { - this.eap$smartDoubling = tag.getBoolean(EPP_SMART_DOUBLING_KEY); + if (tag.contains(EAP_SMART_DOUBLING_KEY)) { + this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY); } } diff --git a/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java b/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java index c64655f..1c057e3 100644 --- a/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java +++ b/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java @@ -1,17 +1,19 @@ package com.extendedae_plus.network; +import appeng.api.config.Settings; +import appeng.api.config.YesNo; import appeng.menu.implementations.PatternProviderMenu; -import com.extendedae_plus.api.AdvancedBlockingHolder; -import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; import com.extendedae_plus.ExtendedAEPlus; +import com.extendedae_plus.api.AdvancedBlockingHolder; +import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor; +import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.network.handling.IPayloadContext; import net.minecraft.server.level.ServerPlayer; -import appeng.api.config.Settings; -import appeng.api.config.YesNo; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; /** * C2S:切换高级阻挡模式。 @@ -36,16 +38,31 @@ public class ToggleAdvancedBlockingC2SPacket implements CustomPacketPayload { public static void handle(final ToggleAdvancedBlockingC2SPacket msg, final IPayloadContext ctx) { ctx.enqueueWork(() -> { if (!(ctx.player() instanceof ServerPlayer player)) return; - if (!(player.containerMenu instanceof PatternProviderMenu menu)) return; - - var accessor = (PatternProviderMenuAdvancedAccessor) menu; - var logic = accessor.eap$logic(); - if (logic instanceof AdvancedBlockingHolder holder) { - boolean next = !holder.eap$getAdvancedBlocking(); - holder.eap$setAdvancedBlocking(next); - // 自动开启原版阻挡 - logic.getConfigManager().putSetting(Settings.BLOCKING_MODE, YesNo.YES); - logic.saveChanges(); + var containerMenu = player.containerMenu; + if (containerMenu instanceof PatternProviderMenu menu) { + var accessor = (PatternProviderMenuAdvancedAccessor) menu; + var logic = accessor.eap$logic(); + if (logic instanceof AdvancedBlockingHolder holder) { + boolean current = holder.eap$getAdvancedBlocking(); + boolean next = !current; + holder.eap$setAdvancedBlocking(next); + // 自动开启原版阻挡 + logic.getConfigManager().putSetting(Settings.BLOCKING_MODE, YesNo.YES); + // 保存并触发 AE2 的菜单 @GuiSync 广播到所有观看该菜单的玩家 + logic.saveChanges(); + } + }else if (containerMenu instanceof AdvPatternProviderMenu menu){ + var accessor = (AdvPatternProviderMenuAdvancedAccessor) menu; + var logic = accessor.eap$logic(); + if (logic instanceof AdvancedBlockingHolder holder) { + boolean current = holder.eap$getAdvancedBlocking(); + boolean next = !current; + holder.eap$setAdvancedBlocking(next); + // 自动开启原版阻挡 + logic.getConfigManager().putSetting(Settings.BLOCKING_MODE, YesNo.YES); + // 保存并触发 AE2 的菜单 @GuiSync 广播到所有观看该菜单的玩家 + logic.saveChanges(); + } } }); } diff --git a/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java b/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java index 2e2bd82..79f6664 100644 --- a/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java +++ b/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java @@ -1,15 +1,17 @@ package com.extendedae_plus.network; import appeng.menu.implementations.PatternProviderMenu; -import com.extendedae_plus.api.SmartDoublingHolder; -import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; import com.extendedae_plus.ExtendedAEPlus; +import com.extendedae_plus.api.SmartDoublingHolder; +import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor; +import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.network.handling.IPayloadContext; import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; /** * C2S:切换智能翻倍启用状态。 @@ -34,14 +36,25 @@ public class ToggleSmartDoublingC2SPacket implements CustomPacketPayload { public static void handle(final ToggleSmartDoublingC2SPacket msg, final IPayloadContext ctx) { ctx.enqueueWork(() -> { if (!(ctx.player() instanceof ServerPlayer player)) return; - if (!(player.containerMenu instanceof PatternProviderMenu menu)) return; - - var accessor = (PatternProviderMenuAdvancedAccessor) menu; - var logic = accessor.eap$logic(); - if (logic instanceof SmartDoublingHolder holder) { - boolean next = !holder.eap$getSmartDoubling(); - holder.eap$setSmartDoubling(next); - logic.saveChanges(); + var containerMenu = player.containerMenu; + if (containerMenu instanceof PatternProviderMenu menu) { + var accessor = (PatternProviderMenuAdvancedAccessor) menu; + var logic = accessor.eap$logic(); + if (logic instanceof SmartDoublingHolder holder) { + boolean current = holder.eap$getSmartDoubling(); + boolean next = !current; + holder.eap$setSmartDoubling(next); + logic.saveChanges(); + } + }else if (containerMenu instanceof AdvPatternProviderMenu menu){ + var accessor = (AdvPatternProviderMenuAdvancedAccessor) menu; + var logic = accessor.eap$logic(); + if (logic instanceof SmartDoublingHolder holder) { + boolean current = holder.eap$getSmartDoubling(); + boolean next = !current; + holder.eap$setSmartDoubling(next); + logic.saveChanges(); + } } }); } diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index 314e662..f7a85bd 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -3,6 +3,13 @@ "package": "com.extendedae_plus.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ + "advancedae.AdvPatternProviderLogicContainsRedirectMixin", + "advancedae.accessor.AdvPatternProviderLogicPatternsAccessor", + "advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor", + "advancedae.helpers.AdvPatternProviderLogicAdvancedMixin", + "advancedae.helpers.AdvPatternProviderLogicDoublingMixin", + "advancedae.menu.AdvPatternProviderMenuAdvancedMixin", + "advancedae.menu.AdvPatternProviderMenuDoublingMixin", "ae2.AEProcessingPatternMixin", "ae2.CraftingCalculationMixin", "ae2.CraftingCPUClusterMixin", @@ -37,6 +44,8 @@ "PickFromWirelessMixin", "accessor.AbstractContainerScreenAccessor", "accessor.ScreenAccessor", + "advancedae.client.gui.AdvPatternProviderScreenMixin", + "advancedae.client.gui.SmallAdvPatternProviderScreenMixin", "ae2.accessor.AEBaseScreenAccessor", "ae2.accessor.AEBaseScreenInvoker", "ae2.accessor.MEStorageScreenAccessor",