添加供应器启动智能翻倍状态按钮

This commit is contained in:
GaLi 2025-08-29 16:14:09 +08:00
parent 8597d1ad30
commit 002139c202
10 changed files with 244 additions and 21 deletions

View File

@ -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);
}
/**

View File

@ -0,0 +1,5 @@
package com.extendedae_plus.api;
public interface PatternProviderMenuDoublingSync {
boolean eap$getSmartDoublingSynced();
}

View File

@ -0,0 +1,6 @@
package com.extendedae_plus.api;
public interface SmartDoublingHolder {
boolean eap$getSmartDoubling();
void eap$setSmartDoubling(boolean value);
}

View File

@ -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))
);
}
}

View File

@ -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);
}
}
}

View File

@ -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 = "<init>(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 = "<init>(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<? extends PatternProviderMenu> 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;
}
}

View File

@ -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<C extends PatternProviderMenu>
@Unique
private boolean eap$AdvancedBlockingEnabled = false;
@Unique
private SettingToggleButton<YesNo> 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<C extends PatternProviderMenu>
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<net.minecraft.network.chat.Component> 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();

View File

@ -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)

View File

@ -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<NetworkEvent.Context> 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);
}
}

View File

@ -32,6 +32,8 @@
"ae2.PatternEncodingTermMenuMixin",
"ae2.PatternProviderLogicAdvancedMixin",
"ae2.PatternProviderMenuAdvancedMixin",
"ae2.PatternProviderLogicDoublingMixin",
"ae2.PatternProviderMenuDoublingMixin",
"ae2.accessor.MEStorageMenuAccessor",
"ae2.accessor.PatternEncodingTermMenuAccessor",
"ae2.accessor.PatternProviderLogicAccessor",