diff --git a/src/main/java/com/extendedae_plus/ae/api/crafting/ScaledProcessingPattern.java b/src/main/java/com/extendedae_plus/ae/api/crafting/ScaledProcessingPattern.java index e3952d6..c402127 100644 --- a/src/main/java/com/extendedae_plus/ae/api/crafting/ScaledProcessingPattern.java +++ b/src/main/java/com/extendedae_plus/ae/api/crafting/ScaledProcessingPattern.java @@ -27,8 +27,6 @@ public class ScaledProcessingPattern implements IPatternDetails { private transient volatile GenericStack[] outputsCache; private transient volatile GenericStack[] sparseInputsCache; private transient volatile GenericStack[] sparseOutputsCache; - // per-provider scaling limit (0 = no limit). Can be updated from UI via provider settings. - private int perProviderScalingLimit = 0; public ScaledProcessingPattern(AEProcessingPattern original, AEItemKey definition, long multiplier) { this.original = Objects.requireNonNull(original); @@ -36,14 +34,6 @@ public class ScaledProcessingPattern implements IPatternDetails { this.multiplier = multiplier <= 0 ? 1L : multiplier; } - public int getPerProviderScalingLimit() { - return this.perProviderScalingLimit; - } - - public void setPerProviderScalingLimit(int limit) { - this.perProviderScalingLimit = Math.max(0, limit); - } - /* -------------------- API 实现 -------------------- */ public AEProcessingPattern getOriginal() { diff --git a/src/main/java/com/extendedae_plus/api/smartDoubling/IPatternProviderMenuDoublingSync.java b/src/main/java/com/extendedae_plus/api/smartDoubling/IPatternProviderMenuDoublingSync.java index 8160d05..4fd840c 100644 --- a/src/main/java/com/extendedae_plus/api/smartDoubling/IPatternProviderMenuDoublingSync.java +++ b/src/main/java/com/extendedae_plus/api/smartDoubling/IPatternProviderMenuDoublingSync.java @@ -2,4 +2,6 @@ package com.extendedae_plus.api.smartDoubling; public interface IPatternProviderMenuDoublingSync { boolean eap$getSmartDoublingSynced(); + + int eap$getScalingLimit(); } diff --git a/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingAwarePattern.java b/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingAwarePattern.java index b33da38..4a3027a 100644 --- a/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingAwarePattern.java +++ b/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingAwarePattern.java @@ -3,7 +3,8 @@ package com.extendedae_plus.api.smartDoubling; public interface ISmartDoublingAwarePattern { boolean eap$allowScaling(); void eap$setAllowScaling(boolean allow); - /** per-provider scaling limit: 0 means no limit */ + + // 翻倍限制:0 表示无限制 int eap$getScalingLimit(); void eap$setScalingLimit(int limit); } diff --git a/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingHolder.java b/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingHolder.java index a1f3cb0..f956208 100644 --- a/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingHolder.java +++ b/src/main/java/com/extendedae_plus/api/smartDoubling/ISmartDoublingHolder.java @@ -2,5 +2,10 @@ package com.extendedae_plus.api.smartDoubling; public interface ISmartDoublingHolder { boolean eap$getSmartDoubling(); + void eap$setSmartDoubling(boolean value); + + int eap$getProviderSmartDoublingLimit(); + + void eap$setProviderSmartDoublingLimit(int limit); } diff --git a/src/main/java/com/extendedae_plus/init/ModNetwork.java b/src/main/java/com/extendedae_plus/init/ModNetwork.java index 85a039e..6a70eca 100644 --- a/src/main/java/com/extendedae_plus/init/ModNetwork.java +++ b/src/main/java/com/extendedae_plus/init/ModNetwork.java @@ -90,6 +90,12 @@ public class ModNetwork { .consumerNetworkThread(ToggleSmartDoublingC2SPacket::handle) .add(); + CHANNEL.messageBuilder(com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER) + .encoder(com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket::encode) + .decoder(com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket::decode) + .consumerNetworkThread(com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket::handle) + .add(); + CHANNEL.messageBuilder(GlobalToggleProviderModesC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER) .encoder(GlobalToggleProviderModesC2SPacket::encode) .decoder(GlobalToggleProviderModesC2SPacket::decode) diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenMixin.java index 3849dd9..f4423b7 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenMixin.java @@ -11,9 +11,12 @@ import com.extendedae_plus.api.IExPatternButtonsAccessor; import com.extendedae_plus.api.IPatternProviderMenuAdvancedSync; import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync; import com.extendedae_plus.init.ModNetwork; +import com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket; import com.extendedae_plus.network.provider.ToggleAdvancedBlockingC2SPacket; import com.extendedae_plus.network.provider.ToggleSmartDoublingC2SPacket; import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; @@ -33,20 +36,14 @@ import static com.extendedae_plus.util.Logger.EAP$LOGGER; @Mixin(PatternProviderScreen.class) public abstract class PatternProviderScreenMixin extends AEBaseScreen { - @Unique - private SettingToggleButton eap$AdvancedBlockingToggle; + @Unique private SettingToggleButton eap$AdvancedBlockingToggle; + @Unique private SettingToggleButton eap$SmartDoublingToggle; + @Unique private EditBox eap$PerProviderLimitInput; - @Unique - private boolean eap$AdvancedBlockingEnabled = false; - - @Unique - private SettingToggleButton eap$SmartDoublingToggle; - - @Unique - private boolean eap$SmartDoublingEnabled = false; - - @Unique - private net.minecraft.client.gui.components.EditBox eap$PerProviderLimitInput; + @Unique private boolean eap$AdvancedBlockingEnabled = false; + @Unique private boolean eap$SmartDoublingEnabled = false; + @Unique private int eap$PerProviderScalingLimit = 0; + @Unique private boolean eap$PerProviderLimitWasFocused = false; public PatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) { super(menu, playerInventory, title, style); @@ -73,24 +70,24 @@ public abstract class PatternProviderScreenMixin } ) { @Override - public java.util.List getTooltipMessage() { + public java.util.List getTooltipMessage() { boolean enabled = eap$AdvancedBlockingEnabled; - var title = net.minecraft.network.chat.Component.literal("智能阻挡"); + var title = Component.literal("智能阻挡"); var line = enabled - ? net.minecraft.network.chat.Component.literal("已启用:对于同一种配方将不再阻挡(需要开启原版的阻挡模式)") - : net.minecraft.network.chat.Component.literal("已禁用:这么好的功能为什么不打开呢"); + ? 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 IPatternProviderMenuDoublingSync sync2) { this.eap$SmartDoublingEnabled = sync2.eap$getSmartDoublingSynced(); + this.eap$PerProviderScalingLimit = sync2.eap$getScalingLimit(); } } catch (Throwable t) { EAP$LOGGER.error("Error initializing smart doubling sync", t); @@ -104,12 +101,12 @@ public abstract class PatternProviderScreenMixin } ) { @Override - public java.util.List getTooltipMessage() { + public java.util.List getTooltipMessage() { boolean enabled = eap$SmartDoublingEnabled; - var title = net.minecraft.network.chat.Component.literal("智能翻倍"); + var title = Component.literal("智能翻倍"); var line = enabled - ? net.minecraft.network.chat.Component.literal("已启用:根据请求量对处理样板进行智能缩放") - : net.minecraft.network.chat.Component.literal("已禁用:按原始样板数量进行发配"); + ? Component.literal("已启用:根据请求量对处理样板进行智能缩放") + : Component.literal("已禁用:按原始样板数量进行发配"); return java.util.List.of(title, line); } }; @@ -121,29 +118,33 @@ public abstract class PatternProviderScreenMixin try { // 使用与左侧工具栏一致的布局托管,避免绝对坐标问题 // 使用更短的输入框并去除前导 0(显示更紧凑) - this.eap$PerProviderLimitInput = new net.minecraft.client.gui.components.EditBox(this.font, 0, 0, 28, 12, net.minecraft.network.chat.Component.literal("Limit")); - this.eap$PerProviderLimitInput.setValue("0"); + this.eap$PerProviderLimitInput = new EditBox(this.font, 0, 0, 28, 12, Component.literal("Limit")); + this.eap$PerProviderLimitInput.setValue(String.valueOf(this.eap$PerProviderScalingLimit)); this.eap$PerProviderLimitInput.setMaxLength(6); - // 调试用:值变更时打印到控制台,同时去掉前导 0(如用户输入 012 -> 12),但保留单个 0 + // 值变更响应 this.eap$PerProviderLimitInput.setResponder((s) -> { try { - if (s != null && s.length() > 0) { - // 去掉前导0但保留单个0 + if (s != null && !s.isEmpty()) { String trimmed = s.replaceFirst("^0+(?=.)", ""); if (!trimmed.equals(s)) { this.eap$PerProviderLimitInput.setValue(trimmed); - System.out.println("[EAP] PerProviderLimit changed (trimmed): " + trimmed); - return; + s = trimmed; } } - System.out.println("[EAP] PerProviderLimit changed: " + s); - } catch (Throwable ignored) { - } + // 实时发送:尝试解析并发送到服务端(若值变化) + int val = Integer.parseInt(s == null || s.isBlank() ? "0" : s); + + if (val != this.eap$PerProviderScalingLimit) { + this.eap$PerProviderScalingLimit = val; + ModNetwork.CHANNEL.sendToServer(new SetPerProviderScalingLimitC2SPacket(val)); + } + } catch (Throwable ignored) {} }); // 初次加入渲染列表(后续在 updateBeforeRender 每帧更新 tooltip/位置) this.addRenderableWidget(this.eap$PerProviderLimitInput); - } catch (Throwable ignored) { - } + // 若菜单/逻辑已在之前同步了上限,则在控件创建后填充显示 + this.eap$PerProviderLimitInput.setValue(String.valueOf(this.eap$PerProviderScalingLimit)); + } catch (Throwable ignored) {} } // 每帧刷新:仅从菜单(@GuiSync)同步布尔值,保持按钮状态一致 @@ -167,6 +168,20 @@ public abstract class PatternProviderScreenMixin this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO); } + if (this.eap$PerProviderLimitInput != null) { + int remoteLimit = this.eap$PerProviderScalingLimit; + if (this.menu instanceof IPatternProviderMenuDoublingSync sync3) { + remoteLimit = sync3.eap$getScalingLimit(); + } + // 若输入框没有焦点且远端值变化则更新控件;否则保留用户编辑的值 + boolean focused = this.eap$PerProviderLimitInput.isFocused(); + if (!focused && remoteLimit != this.eap$PerProviderScalingLimit) { + this.eap$PerProviderScalingLimit = remoteLimit; + this.eap$PerProviderLimitInput.setValue(String.valueOf(remoteLimit)); + + } + } + if ((Object) this instanceof GuiExPatternProvider) { try { ((IExPatternButtonsAccessor) this).eap$updateButtonsLayout(); @@ -184,45 +199,44 @@ public abstract class PatternProviderScreenMixin } // 当输入框未获得焦点且内容为空时填充 0 - try { - if (!this.eap$PerProviderLimitInput.isFocused() && this.eap$PerProviderLimitInput.getValue().trim().isEmpty()) { - this.eap$PerProviderLimitInput.setValue("0"); - } - } catch (Throwable ignored) { + if (!this.eap$PerProviderLimitInput.isFocused() && this.eap$PerProviderLimitInput.getValue().trim().isEmpty()) { + this.eap$PerProviderLimitInput.setValue("0"); } // 优先参考已有的左侧按钮定位 - net.minecraft.client.gui.components.Button ref = eap$SmartDoublingToggle; - + Button ref = eap$SmartDoublingToggle; if (ref != null) { int ex = ref.getX() - this.eap$PerProviderLimitInput.getWidth() - 5; int ey = ref.getY() + 2; // 向下移动 2 像素 this.eap$PerProviderLimitInput.setX(ex); this.eap$PerProviderLimitInput.setY(ey); - } else { - // 回退到相对于 gui 的位置 - this.eap$PerProviderLimitInput.setX(this.leftPos - this.eap$PerProviderLimitInput.getWidth() - 4); - this.eap$PerProviderLimitInput.setY(this.topPos + 7); } // 动态更新 tooltip,简短且包含当前值 - try { - String cur = this.eap$PerProviderLimitInput.getValue(); - if (cur == null || cur.isBlank()) cur = "0"; - var tip = net.minecraft.network.chat.Component.literal("智能翻倍上限: " + cur); - this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(tip)); - } catch (Throwable ignored) {} + String cur = this.eap$PerProviderLimitInput.getValue(); + if (cur.isBlank()) cur = "0"; + var tip = Component.literal("智能翻倍上限: " + cur); + this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(tip)); + + // 当输入框失去焦点且之前处于聚焦时,提交当前值并更新本地同步字段 + boolean focusedNow = this.eap$PerProviderLimitInput.isFocused(); + if (this.eap$PerProviderLimitWasFocused && !focusedNow) { + int val = Integer.parseInt(cur); + // 更新本地展示值并发包到服务端 + this.eap$PerProviderScalingLimit = val; + EAP$LOGGER.info("更新"); + ModNetwork.CHANNEL.sendToServer(new SetPerProviderScalingLimitC2SPacket(val)); + } + this.eap$PerProviderLimitWasFocused = focusedNow; + } else { // 隐藏输入框 - try { - if (this.renderables.contains(this.eap$PerProviderLimitInput)) { - this.removeWidget(this.eap$PerProviderLimitInput); - } - } catch (Throwable ignored) {} + if (this.renderables.contains(this.eap$PerProviderLimitInput)) { + this.removeWidget(this.eap$PerProviderLimitInput); + } } } - - } catch (Throwable ignored) { - } + } catch (Throwable ignored) {} } } + 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 8d0887b..e8ed143 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 @@ -17,18 +17,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = PatternProviderLogic.class, remap = false) public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder { - @Unique - private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling"; + @Unique private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling"; + @Unique private static final String EAP_PROVIDER_SCALING_LIMIT = "eap_provider_scaling_limit"; - @Unique - private boolean eap$smartDoubling = false; - @Unique - private static final Object EAP_SCALING_LOCK = new Object(); - @Unique - private static final java.util.concurrent.ScheduledExecutorService EAP_EXECUTOR = - java.util.concurrent.Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "eap-scaling-save")); - @Unique - private java.util.concurrent.ScheduledFuture eap$pendingScalingSave = null; + @Unique private boolean eap$smartDoubling = false; + @Unique private int eap$providerScalingLimit = 0; // 供应器级别的上限,0 表示不限制 @Override public boolean eap$getSmartDoubling() { @@ -48,36 +41,37 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder { } // 触发一次刷新,让网络及时拿到最新状态(也会触发 ICraftingProvider.requestUpdate(mainNode)) ((PatternProviderLogic) (Object) this).updatePatterns(); - } catch (Throwable ignored) { + } catch (Throwable ignored) {} + } + + @Override + public int eap$getProviderSmartDoublingLimit() { + return this.eap$providerScalingLimit; + } + + @Override + public void eap$setProviderSmartDoublingLimit(int limit) { + // 更新供应器级别上限并去抖保存 + var list = ((PatternProviderLogicAccessor) this).eap$patterns(); + this.eap$providerScalingLimit = Math.max(0, limit); + // 现在把防抖移到客户端屏幕端来处理,服务器端直接立即应用并保存 + for (IPatternDetails d : list) { + if (d instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern a) { + try { a.eap$setScalingLimit(this.eap$providerScalingLimit); } catch (Throwable ignored) {} + } } + try { + ((PatternProviderLogic) (Object) this).updatePatterns(); + } catch (Throwable ignored) {} + } @Inject(method = "writeToNBT", at = @At("TAIL")) private void eap$writeSmartDoublingToNbt(CompoundTag tag, CallbackInfo ci) { tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling); - // persist any pattern-level scaling limits - try { - var list = ((PatternProviderLogicAccessor) this).eap$patterns(); - int[] limits = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - var details = list.get(i); - if (details instanceof com.extendedae_plus.ae.api.crafting.ScaledProcessingPattern sp) { - limits[i] = sp.getPerProviderScalingLimit(); - } else if (details instanceof appeng.crafting.pattern.AEProcessingPattern base && base instanceof ISmartDoublingAwarePattern aware) { - limits[i] = aware.eap$getScalingLimit(); - } else { - limits[i] = 0; - } - } - var listTag = new net.minecraft.nbt.ListTag(); - for (int v : limits) { - var c = new CompoundTag(); - c.putInt("limit", v); - listTag.add(c); - } - tag.put("eap_scaling_limits", listTag); - } catch (Throwable ignored) { - } + // 保存供应器级别上限 + tag.putInt(EAP_PROVIDER_SCALING_LIMIT, this.eap$providerScalingLimit); + } @Inject(method = "readFromNBT", at = @At("TAIL")) @@ -85,23 +79,9 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder { if (tag.contains(EAP_SMART_DOUBLING_KEY)) { this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY); } - try { - if (tag.contains("eap_scaling_limits")) { - var list = ((PatternProviderLogicAccessor) this).eap$patterns(); - var limitsTag = tag.getList("eap_scaling_limits", net.minecraft.nbt.Tag.TAG_COMPOUND); - int n = Math.min(list.size(), limitsTag.size()); - for (int i = 0; i < n; i++) { - var c = limitsTag.getCompound(i); - int lim = c.getInt("limit"); - var details = list.get(i); - if (details instanceof com.extendedae_plus.ae.api.crafting.ScaledProcessingPattern sp) { - sp.setPerProviderScalingLimit(lim); - } else if (details instanceof appeng.crafting.pattern.AEProcessingPattern base && base instanceof ISmartDoublingAwarePattern aware) { - aware.eap$setScalingLimit(lim); - } - } - } - } catch (Throwable ignored) {} + if (tag.contains(EAP_PROVIDER_SCALING_LIMIT)) { + this.eap$providerScalingLimit = tag.getInt(EAP_PROVIDER_SCALING_LIMIT); + } } @Inject(method = "updatePatterns", at = @At("TAIL")) @@ -109,47 +89,24 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder { try { var list = ((PatternProviderLogicAccessor) this).eap$patterns(); boolean allow = this.eap$smartDoubling; + int limit = this.eap$providerScalingLimit; for (IPatternDetails details : list) { if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) { aware.eap$setAllowScaling(allow); + aware.eap$setScalingLimit(limit); } } } catch (Throwable ignored) { } } - // called by UI when user changes per-provider limit; apply with debounce and save - @Unique - public void eap$onPerProviderLimitChanged(int patternIndex, int newLimit) { - try { - var list = ((PatternProviderLogicAccessor) this).eap$patterns(); - if (patternIndex < 0 || patternIndex >= list.size()) return; - var details = list.get(patternIndex); - if (details instanceof com.extendedae_plus.ae.api.crafting.ScaledProcessingPattern sp) { - sp.setPerProviderScalingLimit(newLimit); - } else if (details instanceof appeng.crafting.pattern.AEProcessingPattern base && base instanceof ISmartDoublingAwarePattern aware) { - aware.eap$setScalingLimit(newLimit); - } - - synchronized (EAP_SCALING_LOCK) { - if (eap$pendingScalingSave != null) { - eap$pendingScalingSave.cancel(false); - } - eap$pendingScalingSave = EAP_EXECUTOR.schedule(() -> { - try { - this.saveChanges(); - } catch (Throwable ignored) {} - }, 1000, java.util.concurrent.TimeUnit.MILLISECONDS); - } - } catch (Throwable ignored) {} - } - @Shadow public void saveChanges() {} @Inject(method = "exportSettings(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("TAIL")) private void onExportSettings(CompoundTag output, CallbackInfo ci) { output.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling); + output.putInt(EAP_PROVIDER_SCALING_LIMIT, this.eap$providerScalingLimit); } @Inject(method = "importSettings(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/entity/player/Player;)V", at = @At("TAIL")) @@ -159,5 +116,9 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder { // 持久化到 world this.saveChanges(); } + if (input.contains(EAP_PROVIDER_SCALING_LIMIT)) { + this.eap$providerScalingLimit = input.getInt(EAP_PROVIDER_SCALING_LIMIT); + this.saveChanges(); + } } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuDoublingMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuDoublingMixin.java index 08d6c69..caf1479 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuDoublingMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuDoublingMixin.java @@ -32,17 +32,13 @@ public abstract class PatternProviderMenuDoublingMixin implements IPatternProvid @GuiSync(22) public int eap$PerProviderScalingLimit = 0; // 0 = no limit - public void eap$setPerProviderScalingLimit(int v) { - this.eap$PerProviderScalingLimit = Math.max(0, v); - // send to server via an existing packet channel or custom packet (not implemented here) - } - @Inject(method = "broadcastChanges", at = @At("HEAD")) private void eap$syncSmartDoubling(CallbackInfo ci) { if (!((AEBaseMenu) (Object) this).isClientSide()) { var l = this.logic; if (l instanceof ISmartDoublingHolder holder) { this.eap$SmartDoubling = holder.eap$getSmartDoubling(); + this.eap$PerProviderScalingLimit = holder.eap$getProviderSmartDoublingLimit(); } } } @@ -53,6 +49,7 @@ public abstract class PatternProviderMenuDoublingMixin implements IPatternProvid var l = this.logic; if (l instanceof ISmartDoublingHolder holder) { this.eap$SmartDoubling = holder.eap$getSmartDoubling(); + this.eap$PerProviderScalingLimit = holder.eap$getProviderSmartDoublingLimit(); } } catch (Throwable t) { EAP$LOGGER.error("Error initializing smart doubling sync", t); @@ -65,14 +62,21 @@ public abstract class PatternProviderMenuDoublingMixin implements IPatternProvid var l = this.logic; if (l instanceof ISmartDoublingHolder holder) { this.eap$SmartDoubling = holder.eap$getSmartDoubling(); + this.eap$PerProviderScalingLimit = holder.eap$getProviderSmartDoublingLimit(); } } catch (Throwable t) { EAP$LOGGER.error("Error initializing smart doubling sync", t); } } + @Override public boolean eap$getSmartDoublingSynced() { return this.eap$SmartDoubling; } + + @Override + public int eap$getScalingLimit() { + return this.eap$PerProviderScalingLimit; + } } diff --git a/src/main/java/com/extendedae_plus/network/provider/SetPerProviderScalingLimitC2SPacket.java b/src/main/java/com/extendedae_plus/network/provider/SetPerProviderScalingLimitC2SPacket.java new file mode 100644 index 0000000..6e4762f --- /dev/null +++ b/src/main/java/com/extendedae_plus/network/provider/SetPerProviderScalingLimitC2SPacket.java @@ -0,0 +1,59 @@ +package com.extendedae_plus.network.provider; + +import appeng.menu.implementations.PatternProviderMenu; +import com.extendedae_plus.api.smartDoubling.ISmartDoublingHolder; +import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor; +import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAccessor; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; +import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu; + +import java.util.function.Supplier; + +/** + * C2S: set per-provider scaling limit for the currently opened provider and pattern index + */ +public class SetPerProviderScalingLimitC2SPacket { + private final int limit; + + public SetPerProviderScalingLimitC2SPacket(int limit) { + this.limit = limit; + } + + public static void encode(SetPerProviderScalingLimitC2SPacket msg, FriendlyByteBuf buf) { + buf.writeInt(msg.limit); + } + + public static SetPerProviderScalingLimitC2SPacket decode(FriendlyByteBuf buf) { + return new SetPerProviderScalingLimitC2SPacket(buf.readInt()); + } + + public static void handle(SetPerProviderScalingLimitC2SPacket msg, Supplier ctxSupplier) { + var ctx = ctxSupplier.get(); + ctx.enqueueWork(() -> { + try { + ServerPlayer player = ctx.getSender(); + if (player == null) return; + var containerMenu = player.containerMenu; + if (containerMenu instanceof PatternProviderMenu menu) { + var accessor = (PatternProviderMenuAccessor) menu; + var logic = accessor.eap$logic(); + if (logic instanceof ISmartDoublingHolder handler) { + handler.eap$setProviderSmartDoublingLimit(msg.limit); + } + } else if (containerMenu instanceof AdvPatternProviderMenu advMenu) { + var accessor = (AdvPatternProviderMenuAdvancedAccessor) advMenu; + var logic = accessor.eap$logic(); + if (logic instanceof ISmartDoublingHolder handler) { + handler.eap$setProviderSmartDoublingLimit(msg.limit); + } + } + } catch (Throwable ignored) { + } + }); + ctx.setPacketHandled(true); + } +} + + diff --git a/src/main/java/com/extendedae_plus/util/smartDoubling/PatternScaler.java b/src/main/java/com/extendedae_plus/util/smartDoubling/PatternScaler.java index b93413d..77d5565 100644 --- a/src/main/java/com/extendedae_plus/util/smartDoubling/PatternScaler.java +++ b/src/main/java/com/extendedae_plus/util/smartDoubling/PatternScaler.java @@ -66,6 +66,7 @@ public final class PatternScaler { if (patternLimit > 0 && multiplier > patternLimit) { multiplier = patternLimit; } else { + // 应用配置的最大倍数上限(0 表示不限制) int maxMul = ModConfig.INSTANCE.smartScalingMaxMultiplier; if (maxMul > 0 && multiplier > maxMul) { multiplier = maxMul; @@ -83,15 +84,7 @@ public final class PatternScaler { } catch (Throwable ignore) { // 配置读取异常时保持默认行为(不绕过) } - // 应用配置的最大倍数上限(0 表示不限制) - try { - int maxMul = ModConfig.INSTANCE.smartScalingMaxMultiplier; - if (maxMul > 0 && multiplier > maxMul) { - multiplier = maxMul; - } - } catch (Throwable ignore) { - // 配置读取异常时不施加上限 - } + if (ModList.get().isLoaded("advanced_ae")) { // 如果加载了 Advanced AE 且 base 实现了 AdvPatternDetails,返回兼容版 try {