From 002139c20290f389b280a069083c908249787010 Mon Sep 17 00:00:00 2001 From: GaLi <133291877+GaLicn@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:14:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BE=9B=E5=BA=94=E5=99=A8?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=99=BA=E8=83=BD=E7=BF=BB=E5=80=8D=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/extendedae_plus/ExtendedAEPlus.java | 11 +-- .../api/PatternProviderMenuDoublingSync.java | 5 ++ .../api/SmartDoublingHolder.java | 6 ++ .../extendedae_plus/client/ClientProxy.java | 15 ++++ .../PatternProviderLogicDoublingMixin.java | 41 +++++++++++ .../ae2/PatternProviderMenuDoublingMixin.java | 69 +++++++++++++++++++ .../mixin/ae2/PatternProviderScreenMixin.java | 67 ++++++++++++++---- .../extendedae_plus/network/ModNetwork.java | 6 ++ .../network/ToggleSmartDoublingC2SPacket.java | 43 ++++++++++++ .../resources/extendedae_plus.mixins.json | 2 + 10 files changed, 244 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/api/PatternProviderMenuDoublingSync.java create mode 100644 src/main/java/com/extendedae_plus/api/SmartDoublingHolder.java create mode 100644 src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicDoublingMixin.java create mode 100644 src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuDoublingMixin.java create mode 100644 src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java diff --git a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java index 32d59db..93a51dc 100644 --- a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java +++ b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java @@ -19,7 +19,6 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraft.resources.ResourceLocation; import com.extendedae_plus.client.ClientProxy; -import com.extendedae_plus.client.ModConfigScreen; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; @@ -60,14 +59,8 @@ public class ExtendedAEPlus { // 构造期在客户端再确保一次注册(幂等) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientProxy::init); - // 在 Mods 菜单中注册配置界面入口(仅客户端) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> - ModLoadingContext.get().registerExtensionPoint( - ConfigScreenHandler.ConfigScreenFactory.class, - () -> new ConfigScreenHandler.ConfigScreenFactory( - (mc, parent) -> new ModConfigScreen(parent)) - ) - ); + // 在 Mods 菜单中注册配置界面入口(仅客户端,由 ClientProxy 执行以避免服务端类加载 Screen) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientProxy::registerConfigScreen); } /** diff --git a/src/main/java/com/extendedae_plus/api/PatternProviderMenuDoublingSync.java b/src/main/java/com/extendedae_plus/api/PatternProviderMenuDoublingSync.java new file mode 100644 index 0000000..a9d1492 --- /dev/null +++ b/src/main/java/com/extendedae_plus/api/PatternProviderMenuDoublingSync.java @@ -0,0 +1,5 @@ +package com.extendedae_plus.api; + +public interface PatternProviderMenuDoublingSync { + boolean eap$getSmartDoublingSynced(); +} diff --git a/src/main/java/com/extendedae_plus/api/SmartDoublingHolder.java b/src/main/java/com/extendedae_plus/api/SmartDoublingHolder.java new file mode 100644 index 0000000..b5af4ef --- /dev/null +++ b/src/main/java/com/extendedae_plus/api/SmartDoublingHolder.java @@ -0,0 +1,6 @@ +package com.extendedae_plus.api; + +public interface SmartDoublingHolder { + boolean eap$getSmartDoubling(); + void eap$setSmartDoubling(boolean value); +} diff --git a/src/main/java/com/extendedae_plus/client/ClientProxy.java b/src/main/java/com/extendedae_plus/client/ClientProxy.java index f6922e3..3a479e5 100644 --- a/src/main/java/com/extendedae_plus/client/ClientProxy.java +++ b/src/main/java/com/extendedae_plus/client/ClientProxy.java @@ -5,6 +5,8 @@ import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.client.render.crafting.EPlusCraftingCubeModelProvider; import com.extendedae_plus.content.crafting.EPlusCraftingUnitType; import com.extendedae_plus.hooks.BuiltInModelHooks; +import net.minecraftforge.client.ConfigScreenHandler; +import net.minecraftforge.fml.ModLoadingContext; /** * 客户端模型注册,将 formed 模型注册为内置模型。 @@ -38,4 +40,17 @@ public final class ClientProxy { ExtendedAEPlus.id("block/crafting/1024x_accelerator_formed_v2"), new CraftingCubeModel(new EPlusCraftingCubeModelProvider(EPlusCraftingUnitType.ACCELERATOR_1024x))); } + + /** + * 仅客户端:在 Mods 菜单注册配置界面入口。 + * 将对 Screen 的引用限制在客户端侧,避免服务端类加载。 + */ + public static void registerConfigScreen() { + // 将 ModConfigScreen 的引用放在此处,确保仅在 Dist.CLIENT 下解析该类 + ModLoadingContext.get().registerExtensionPoint( + ConfigScreenHandler.ConfigScreenFactory.class, + () -> new ConfigScreenHandler.ConfigScreenFactory( + (mc, parent) -> new com.extendedae_plus.client.ModConfigScreen(parent)) + ); + } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicDoublingMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicDoublingMixin.java new file mode 100644 index 0000000..47eaa1c --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicDoublingMixin.java @@ -0,0 +1,41 @@ +package com.extendedae_plus.mixin.ae2; + +import appeng.helpers.patternprovider.PatternProviderLogic; +import com.extendedae_plus.api.SmartDoublingHolder; +import net.minecraft.nbt.CompoundTag; +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; + +@Mixin(PatternProviderLogic.class) +public class PatternProviderLogicDoublingMixin implements SmartDoublingHolder { + @Unique + private static final String EPP_SMART_DOUBLING_KEY = "epp_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; + } + + @Inject(method = "writeToNBT", at = @At("TAIL"), remap = false) + private void eap$writeSmartDoublingToNbt(CompoundTag tag, CallbackInfo ci) { + tag.putBoolean(EPP_SMART_DOUBLING_KEY, this.eap$smartDoubling); + } + + @Inject(method = "readFromNBT", at = @At("TAIL"), remap = false) + private void eap$readSmartDoublingFromNbt(CompoundTag tag, CallbackInfo ci) { + if (tag.contains(EPP_SMART_DOUBLING_KEY)) { + this.eap$smartDoubling = tag.getBoolean(EPP_SMART_DOUBLING_KEY); + } + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuDoublingMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuDoublingMixin.java new file mode 100644 index 0000000..ee21660 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuDoublingMixin.java @@ -0,0 +1,69 @@ +package com.extendedae_plus.mixin.ae2; + +import appeng.helpers.patternprovider.PatternProviderLogic; +import appeng.helpers.patternprovider.PatternProviderLogicHost; +import appeng.menu.AEBaseMenu; +import appeng.menu.guisync.GuiSync; +import appeng.menu.implementations.PatternProviderMenu; +import com.extendedae_plus.api.PatternProviderMenuDoublingSync; +import com.extendedae_plus.api.SmartDoublingHolder; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +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; + +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; + +@Mixin(PatternProviderMenu.class) +public abstract class PatternProviderMenuDoublingMixin implements PatternProviderMenuDoublingSync { + @Shadow + protected PatternProviderLogic logic; + + @Unique + @GuiSync(21) + 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(); + LOGGER.debug("[EAP] Menu broadcastChanges HEAD: eap$SmartDoubling={}", this.eap$SmartDoubling); + } + } + } + + @Inject(method = "(ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/patternprovider/PatternProviderLogicHost;)V", at = @At("TAIL")) + private void eap$initSmartSync_Public(int id, Inventory playerInventory, PatternProviderLogicHost host, CallbackInfo ci) { + try { + var l = this.logic; + if (l instanceof SmartDoublingHolder holder) { + this.eap$SmartDoubling = holder.eap$getSmartDoubling(); + } + } catch (Throwable t) { + LOGGER.error("Error initializing smart doubling sync", t); + } + } + + @Inject(method = "(Lnet/minecraft/world/inventory/MenuType;ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/patternprovider/PatternProviderLogicHost;)V", at = @At("TAIL")) + private void eap$initSmartSync_Protected(MenuType menuType, int id, Inventory playerInventory, PatternProviderLogicHost host, CallbackInfo ci) { + try { + var l = this.logic; + if (l instanceof SmartDoublingHolder holder) { + this.eap$SmartDoubling = holder.eap$getSmartDoubling(); + } + } catch (Throwable t) { + LOGGER.error("Error initializing smart doubling sync", t); + } + } + + @Override + public boolean eap$getSmartDoublingSynced() { + return this.eap$SmartDoubling; + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java index fe2a81e..b0d383d 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java @@ -9,8 +9,10 @@ import appeng.client.gui.widgets.SettingToggleButton; import appeng.menu.implementations.PatternProviderMenu; import com.extendedae_plus.api.ExPatternButtonsAccessor; import com.extendedae_plus.api.PatternProviderMenuAdvancedSync; +import com.extendedae_plus.api.PatternProviderMenuDoublingSync; import com.extendedae_plus.network.ModNetwork; import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket; +import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket; import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; @@ -36,6 +38,12 @@ public abstract class PatternProviderScreenMixin @Unique private boolean eap$AdvancedBlockingEnabled = false; + @Unique + private SettingToggleButton eap$SmartDoublingToggle; + + @Unique + private boolean eap$SmartDoublingEnabled = false; + public PatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) { super(menu, playerInventory, title, style); } @@ -76,27 +84,62 @@ public abstract class PatternProviderScreenMixin 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) -> { + LOGGER.debug("[EAP] Click smart doubling toggle: send C2S"); + ModNetwork.CHANNEL.sendToServer(new ToggleSmartDoublingC2SPacket()); + } + ) { + @Override + public java.util.List getTooltipMessage() { + boolean enabled = eap$SmartDoublingEnabled; + var title = net.minecraft.network.chat.Component.literal("智能翻倍"); + var line = enabled + ? net.minecraft.network.chat.Component.literal("已启用:根据请求量对处理样板进行智能缩放") + : net.minecraft.network.chat.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) return; - - boolean desired = this.eap$AdvancedBlockingEnabled; - if (this.menu instanceof PatternProviderMenuAdvancedSync sync) { - desired = sync.eap$getAdvancedBlockingSynced(); + if (this.eap$AdvancedBlockingToggle != null) { + boolean desired = this.eap$AdvancedBlockingEnabled; + if (this.menu instanceof PatternProviderMenuAdvancedSync sync) { + desired = sync.eap$getAdvancedBlockingSynced(); + } + LOGGER.debug("[EAP] updateBeforeRender tick (adv): desired={}", desired); + this.eap$AdvancedBlockingEnabled = desired; + this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO); } - // 与AE2一致:每帧无条件对齐按钮状态至@GuiSync(使用YesNo以获得原版图标与提示) - LOGGER.debug("[EAP] updateBeforeRender tick: desired={}", desired); - if (this.eap$AdvancedBlockingEnabled != desired) { - LOGGER.debug("[EAP] updateBeforeRender: desired changed {} -> {}", this.eap$AdvancedBlockingEnabled, desired); + if (this.eap$SmartDoublingToggle != null) { + boolean desired2 = this.eap$SmartDoublingEnabled; + if (this.menu instanceof PatternProviderMenuDoublingSync sync2) { + desired2 = sync2.eap$getSmartDoublingSynced(); + } + LOGGER.debug("[EAP] updateBeforeRender tick (dbl): desired={}", desired2); + this.eap$SmartDoublingEnabled = desired2; + this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO); } - this.eap$AdvancedBlockingEnabled = desired; - this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO); - // 如果当前屏幕是 ExtendedAE 的 GuiExPatternProvider,则委托布局更新到 accessor if ((Object) this instanceof GuiExPatternProvider) { try { ((ExPatternButtonsAccessor) this).eap$updateButtonsLayout(); diff --git a/src/main/java/com/extendedae_plus/network/ModNetwork.java b/src/main/java/com/extendedae_plus/network/ModNetwork.java index 3cfe50a..2143246 100644 --- a/src/main/java/com/extendedae_plus/network/ModNetwork.java +++ b/src/main/java/com/extendedae_plus/network/ModNetwork.java @@ -66,6 +66,12 @@ public class ModNetwork { .consumerNetworkThread(ToggleAdvancedBlockingC2SPacket::handle) .add(); + CHANNEL.messageBuilder(ToggleSmartDoublingC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER) + .encoder(ToggleSmartDoublingC2SPacket::encode) + .decoder(ToggleSmartDoublingC2SPacket::decode) + .consumerNetworkThread(ToggleSmartDoublingC2SPacket::handle) + .add(); + CHANNEL.messageBuilder(AdvancedBlockingSyncS2CPacket.class, nextId(), NetworkDirection.PLAY_TO_CLIENT) .encoder(AdvancedBlockingSyncS2CPacket::encode) .decoder(AdvancedBlockingSyncS2CPacket::decode) diff --git a/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java b/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java new file mode 100644 index 0000000..3ad6405 --- /dev/null +++ b/src/main/java/com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java @@ -0,0 +1,43 @@ +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 net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +/** + * C2S:切换智能翻倍启用状态。 + * 不含额外负载,基于玩家当前打开的 PatternProviderMenu 进行切换。 + */ +public class ToggleSmartDoublingC2SPacket { + public ToggleSmartDoublingC2SPacket() {} + + public static void encode(ToggleSmartDoublingC2SPacket msg, FriendlyByteBuf buf) {} + + public static ToggleSmartDoublingC2SPacket decode(FriendlyByteBuf buf) { + return new ToggleSmartDoublingC2SPacket(); + } + + public static void handle(ToggleSmartDoublingC2SPacket msg, Supplier ctxSupplier) { + var ctx = ctxSupplier.get(); + ctx.enqueueWork(() -> { + ServerPlayer player = ctx.getSender(); + if (player == null) return; + if (!(player.containerMenu instanceof PatternProviderMenu menu)) return; + + 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(); + } + }); + ctx.setPacketHandled(true); + } +} diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index 7a916e8..776795c 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -32,6 +32,8 @@ "ae2.PatternEncodingTermMenuMixin", "ae2.PatternProviderLogicAdvancedMixin", "ae2.PatternProviderMenuAdvancedMixin", + "ae2.PatternProviderLogicDoublingMixin", + "ae2.PatternProviderMenuDoublingMixin", "ae2.accessor.MEStorageMenuAccessor", "ae2.accessor.PatternEncodingTermMenuAccessor", "ae2.accessor.PatternProviderLogicAccessor",