Merge remote-tracking branch 'origin/1.21.1'

# Conflicts:
#	build/generated/sources/modMetadata/META-INF/neoforge.mods.toml
This commit is contained in:
GaLi 2025-12-03 18:24:26 +08:00
commit 162b15a748
31 changed files with 635 additions and 1027 deletions

View File

@ -166,6 +166,7 @@ dependencies {
runtimeOnly "curse.maven:ex-pattern-provider-892005:6863556"
//aea
// compileOnly "curse.maven:advancedae-1084104:6932981"
implementation "curse.maven:advancedae-1084104:6932981"
//geckolib

View File

@ -1,5 +1,7 @@
package com.extendedae_plus.api.advancedBlocking;
import appeng.api.config.YesNo;
public interface IPatternProviderMenuAdvancedSync {
boolean eap$getAdvancedBlockingSynced();
YesNo eap$getAdvancedBlockingSynced();
}

View File

@ -11,8 +11,9 @@ import java.util.Map;
public final class EAPSettings {
private static final Map<String, Setting<?>> SETTINGS = new HashMap<>();
public static final Setting<YesNo> ACCELERATE = register("accelerate", YesNo.NO, YesNo.YES);
public static final Setting<YesNo> REDSTONE_CONTROL = register("redstoneControl", YesNo.NO, YesNo.YES);
public static final Setting<YesNo> REDSTONE_CONTROL = register("redstone_control", YesNo.NO, YesNo.YES);
public static final Setting<YesNo> SMART_DOUBLING = register("smart_doubling", YesNo.NO, YesNo.YES);
public static final Setting<YesNo> ADVANCED_BLOCKING = register("advanced_blocking", YesNo.NO, YesNo.YES);
private EAPSettings() {
}

View File

@ -25,9 +25,6 @@ public final class ScaledProcessingPatternAdv extends ScaledProcessingPattern im
this.dirMap = ((AdvProcessingPattern) original).getDirectionMap();
}
@Override
public @NotNull AdvProcessingPattern getOriginal() {return (AdvProcessingPattern) this.original;}
@Override
public void pushInputsToExternalInventory(KeyCounter[] inputHolder, PatternInputSink sink) {
// 如果 sparseInputs inputs 一一对应则无需 reorder

View File

@ -1,5 +1,7 @@
package com.extendedae_plus.api.smartDoubling;
import appeng.api.config.YesNo;
public interface IPatternProviderMenuDoublingSync {
boolean eap$getSmartDoublingSynced();
YesNo eap$getSmartDoublingSynced();
}

View File

@ -28,13 +28,13 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
private final EnumSet<T> validValues;
private T currentValue;
public EAPSettingToggleButton(Setting<T> setting, T val,
IHandler<EAPSettingToggleButton<T>> onPress) {
EAPSettingToggleButton(Setting<T> setting, T val,
IHandler<EAPSettingToggleButton<T>> onPress) {
this(setting, val, t -> true, onPress);
}
public EAPSettingToggleButton(Setting<T> setting, T val, Predicate<T> isValidValue,
IHandler<EAPSettingToggleButton<T>> onPress) {
private EAPSettingToggleButton(Setting<T> setting, T val, Predicate<T> isValidValue,
IHandler<EAPSettingToggleButton<T>> onPress) {
super(EAPSettingToggleButton::onPress);
this.onPress = onPress;
@ -64,6 +64,21 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
registerApp(Icon.REDSTONE_IGNORE, EAPSettings.REDSTONE_CONTROL, YesNo.NO,
EAPText.RedstoneControl,
EAPText.RedstoneControlDisabled);
registerApp(Icon.BLOCKING_MODE_YES, EAPSettings.SMART_DOUBLING, YesNo.YES,
EAPText.SmartDoubling,
EAPText.SmartDoublingEnabled);
registerApp(Icon.BLOCKING_MODE_NO, EAPSettings.SMART_DOUBLING, YesNo.NO,
EAPText.SmartDoubling,
EAPText.SmartDoublingDisabled);
registerApp(Icon.BLOCKING_MODE_YES, EAPSettings.ADVANCED_BLOCKING, YesNo.YES,
EAPText.AdvancedBlocking,
EAPText.AdvancedBlockingEnabled);
registerApp(Icon.BLOCKING_MODE_NO, EAPSettings.ADVANCED_BLOCKING, YesNo.NO,
EAPText.AdvancedBlocking,
EAPText.AdvancedBlockingDisabled);
}
}
@ -106,7 +121,7 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
if (currentScreen instanceof AEBaseScreen) {
backwards = ((AEBaseScreen<?>) currentScreen).isHandlingRightClick();
}
onPress.handle(this, backwards);
this.onPress.handle(this, backwards);
}
@Nullable
@ -119,7 +134,7 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
@Override
protected Icon getIcon() {
var app = getApperance();
var app = this.getApperance();
if (app != null && app.icon != null) {
return app.icon;
}
@ -128,7 +143,7 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
@Override
protected Item getItemOverlay() {
var app = getApperance();
var app = this.getApperance();
if (app != null && app.item != null) {
return app.item;
}
@ -150,7 +165,7 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
return buttonAppearance.tooltipLines;
}
public Setting<T> getSetting() {
Setting<T> getSetting() {
return this.buttonSetting;
}
@ -165,7 +180,7 @@ public class EAPSettingToggleButton<T extends Enum<T>> extends IconButton {
}
public T getNextValue(boolean backwards) {
return EnumCycler.rotateEnum(currentValue, backwards, validValues);
return EnumCycler.rotateEnum(this.currentValue, backwards, this.validValues);
}
@FunctionalInterface

View File

@ -28,27 +28,27 @@ public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPa
int x = this.leftPos + (this.imageWidth - totalW3) / 2;
// 行1三个单项切换
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_blocking"), b ->
this.addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_blocking"), b ->
PacketDistributor.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Operation.TOGGLE,
GlobalToggleProviderModesC2SPacket.Operation.NOOP,
GlobalToggleProviderModesC2SPacket.Operation.NOOP,
this.menu.getBlockEntityPos()
))).bounds(x, y, w, h).build());
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_adv_blocking"), b ->
this.addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_adv_blocking"), b ->
PacketDistributor.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Operation.NOOP,
GlobalToggleProviderModesC2SPacket.Operation.TOGGLE,
GlobalToggleProviderModesC2SPacket.Operation.NOOP,
this.menu.getBlockEntityPos()
))).bounds(x + w + s, y, w, h).build());
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_smart_doubling"), b ->
this.addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_smart_doubling"), b ->
PacketDistributor.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
GlobalToggleProviderModesC2SPacket.Operation.NOOP,
GlobalToggleProviderModesC2SPacket.Operation.NOOP,
GlobalToggleProviderModesC2SPacket.Operation.TOGGLE,
this.menu.getBlockEntityPos()
))).bounds(x + (w + s) * 2, y, w, h).build());
@ -57,23 +57,36 @@ public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPa
// 第二行两列按钮总宽并居中
int totalW2 = w * 2 + s;
int x2 = this.leftPos + (this.imageWidth - totalW2) / 2;
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.all_on"), b ->
this.addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.all_on"), b ->
PacketDistributor.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Operation.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Operation.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Operation.SET_TRUE,
this.menu.getBlockEntityPos()
))).bounds(x2, y2, w, h).build());
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.all_off"), b ->
this.addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.all_off"), b ->
PacketDistributor.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Operation.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Operation.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Operation.SET_FALSE,
this.menu.getBlockEntityPos()
))).bounds(x2 + w + s, y2, w, h).build());
}
@Override
public void render(net.minecraft.client.gui.GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(gfx, mouseX, mouseY, partialTicks);
super.render(gfx, mouseX, mouseY, partialTicks);
gfx.drawString(this.font, CUSTOM_TITLE, this.leftPos + 10, this.topPos + 8, 0xFFFFFF, false);
}
@Override
protected void renderLabels(net.minecraft.client.gui.GuiGraphics gfx, int mouseX, int mouseY) {
// 不绘制默认的玩家物品栏标题例如物品栏避免与自定义面板重叠
// 标题已在 render() 中手动绘制
}
@Override
protected void renderBg(net.minecraft.client.gui.GuiGraphics gfx, float partialTicks, int mouseX, int mouseY) {
// 半透明全屏遮罩避免底层 HUD准星/物品栏文字透出
@ -92,17 +105,4 @@ public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPa
gfx.fill(panelLeft, panelTop, panelLeft + 1, panelBottom, 0x80FFFFFF);
gfx.fill(panelRight - 1, panelTop, panelRight, panelBottom, 0x80000000);
}
@Override
public void render(net.minecraft.client.gui.GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(gfx, mouseX, mouseY, partialTicks);
super.render(gfx, mouseX, mouseY, partialTicks);
gfx.drawString(this.font, CUSTOM_TITLE, this.leftPos + 10, this.topPos + 8, 0xFFFFFF, false);
}
@Override
protected void renderLabels(net.minecraft.client.gui.GuiGraphics gfx, int mouseX, int mouseY) {
// 不绘制默认的玩家物品栏标题例如物品栏避免与自定义面板重叠
// 标题已在 render() 中手动绘制
}
}

View File

@ -10,7 +10,15 @@ public enum EAPText implements LocalizationEnum {
RedstoneControl("Redstone control", Type.TOOLTIP),
RedstoneControlEnabled("Control acceleration with redstone signal", Type.TOOLTIP),
RedstoneControlDisabled("Ignore redstone signals", Type.TOOLTIP);
RedstoneControlDisabled("Ignore redstone signals", Type.TOOLTIP),
AdvancedBlocking("Smart Blocking", Type.TOOLTIP),
AdvancedBlockingEnabled("Will not block the same recipe type (requires vanilla blocking mode enabled)", Type.TOOLTIP),
AdvancedBlockingDisabled("Use vanilla blocking logic", Type.TOOLTIP),
SmartDoubling("Smart Doubling", Type.TOOLTIP),
SmartDoublingEnabled("Intelligently double processing patterns based on request quantity", Type.TOOLTIP),
SmartDoublingDisabled("Distribute according to original pattern quantity", Type.TOOLTIP);
private final String englishText;
private final Type type;

View File

@ -10,12 +10,9 @@ public class ModNetwork {
// Mod 构造中通过 modEventBus.addListener(ModNetwork::registerPayloadHandlers) 注册
public static void registerPayloadHandlers(final RegisterPayloadHandlersEvent event) {
var registrar = event.registrar(ExtendedAEPlus.MODID);
registrar.playToServer(ToggleAdvancedBlockingC2SPacket.TYPE, ToggleAdvancedBlockingC2SPacket.STREAM_CODEC, ToggleAdvancedBlockingC2SPacket::handle);
registrar.playToServer(ToggleSmartDoublingC2SPacket.TYPE, ToggleSmartDoublingC2SPacket.STREAM_CODEC, ToggleSmartDoublingC2SPacket::handle);
registrar.playToServer(ScalePatternsC2SPacket.TYPE, ScalePatternsC2SPacket.STREAM_CODEC, ScalePatternsC2SPacket::handle);
registrar.playToServer(InterfaceAdjustConfigAmountC2SPacket.TYPE, InterfaceAdjustConfigAmountC2SPacket.STREAM_CODEC, InterfaceAdjustConfigAmountC2SPacket::handle);
registrar.playToClient(SetPatternHighlightS2CPacket.TYPE, SetPatternHighlightS2CPacket.STREAM_CODEC, SetPatternHighlightS2CPacket::handle);
registrar.playToClient(AdvancedBlockingSyncS2CPacket.TYPE, AdvancedBlockingSyncS2CPacket.STREAM_CODEC, AdvancedBlockingSyncS2CPacket::handle);
registrar.playToClient(ProvidersListS2CPacket.TYPE, ProvidersListS2CPacket.STREAM_CODEC, ProvidersListS2CPacket::handle);
registrar.playToServer(RequestProvidersListC2SPacket.TYPE, RequestProvidersListC2SPacket.STREAM_CODEC, RequestProvidersListC2SPacket::handle);
registrar.playToClient(SetProviderPageS2CPacket.TYPE, SetProviderPageS2CPacket.STREAM_CODEC, SetProviderPageS2CPacket::handle);

View File

@ -25,14 +25,14 @@ public class AdvPatternProviderLogicContainsRedirectMixin {
try {
if (o instanceof ScaledProcessingPattern scaled) {
IPatternDetails base = scaled.getOriginal();
if (list.indexOf(base) != -1) {
if (list.contains(base)) {
return true;
}
}
// 使用 indexOf 避免再次触发对 List.contains redirect防止递归
return list.indexOf(o) != -1;
return list.contains(o);
} catch (Throwable t) {
return list.indexOf(o) != -1;
return list.contains(o);
}
}
}

View File

@ -1,138 +0,0 @@
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.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
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.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<AdvPatternProviderMenu> {
@Unique
private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@Unique
private boolean eap$AdvancedBlockingEnabled = false;
@Unique
private SettingToggleButton<YesNo> eap$SmartDoublingToggle;
@Unique
private boolean eap$SmartDoublingEnabled = false;
public AdvPatternProviderScreenMixin(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
}
@Inject(method = "<init>", at = @At("RETURN"))
private void eap$initAdvancedBlocking(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
// 使用 @GuiSync 初始化
try {
if (menu instanceof IPatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced();
}
} catch (Throwable t) {
LOGGER.error("Error initializing advanced sync", t);
}
// 使用 SettingToggleButton<YesNo> 的外观原版图标但自定义悬停描述为智能阻挡
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<Component> 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 IPatternProviderMenuDoublingSync 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<Component> 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 IPatternProviderMenuAdvancedSync 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 IPatternProviderMenuDoublingSync sync2) {
desired2 = sync2.eap$getSmartDoublingSynced();
}
this.eap$SmartDoublingEnabled = desired2;
this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO);
}
}
}

View File

@ -0,0 +1,52 @@
package com.extendedae_plus.mixin.advancedae.client.gui;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.style.ScreenStyle;
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.client.gui.widgets.EAPServerSettingToggleButton;
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.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;
/**
* 为高级ae样板供应器界面添加高级阻挡模式按钮
* - 位于左侧工具栏
* - 点击仅发送 C2S 切换请求状态由 AE2 @GuiSync 回传决定
*/
@Mixin(AdvPatternProviderScreen.class)
public abstract class AdvPatternProviderSmartFeaturesMixin extends AEBaseScreen<AdvPatternProviderMenu> {
@Unique private EAPServerSettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@Unique private EAPServerSettingToggleButton<YesNo> eap$SmartDoublingToggle;
public AdvPatternProviderSmartFeaturesMixin(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
}
@Inject(method = "<init>", at = @At("RETURN"), remap = false)
private void eap$initAdvancedBlocking(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
this.eap$AdvancedBlockingToggle = new EAPServerSettingToggleButton<>(EAPSettings.ADVANCED_BLOCKING, YesNo.YES);
this.addToLeftToolbar(this.eap$AdvancedBlockingToggle);
this.eap$SmartDoublingToggle = new EAPServerSettingToggleButton<>(EAPSettings.SMART_DOUBLING, YesNo.YES);
this.addToLeftToolbar(this.eap$SmartDoublingToggle);
}
// 每帧刷新仅从菜单(@GuiSync)同步布尔值保持按钮状态一致
@Inject(method = "updateBeforeRender", at = @At("HEAD"), remap = false)
private void eap$updateAdvancedBlocking(CallbackInfo ci) {
if (this.menu instanceof IPatternProviderMenuDoublingSync sync) {
this.eap$SmartDoublingToggle.set(sync.eap$getSmartDoublingSynced());
}
if (this.menu instanceof IPatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingToggle.set(sync.eap$getAdvancedBlockingSynced());
}
}
}

View File

@ -1,15 +1,12 @@
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.advancedBlocking.IPatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket;
import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket;
import net.minecraft.client.Minecraft;
import com.extendedae_plus.client.gui.widgets.EAPServerSettingToggleButton;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.pedroksl.advanced_ae.client.gui.SmallAdvPatternProviderScreen;
@ -20,8 +17,6 @@ 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样板供应器界面添加高级阻挡模式按钮
* - 位于左侧工具栏
@ -29,110 +24,29 @@ import static com.extendedae_plus.util.ExtendedAELogger.LOGGER;
*/
@Mixin(SmallAdvPatternProviderScreen.class)
public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<SmallAdvPatternProviderMenu> {
@Unique
private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@Unique
private boolean eap$AdvancedBlockingEnabled = false;
@Unique
private SettingToggleButton<YesNo> eap$SmartDoublingToggle;
@Unique
private boolean eap$SmartDoublingEnabled = false;
@Unique private EAPServerSettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@Unique private EAPServerSettingToggleButton<YesNo> eap$SmartDoublingToggle;
public SmallAdvPatternProviderScreenMixin(SmallAdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
}
@Inject(method = "<init>", at = @At("RETURN"))
@Inject(method = "<init>", at = @At("RETURN"), remap = false)
private void eap$initAdvancedBlocking(SmallAdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
// 使用 @GuiSync 初始化
try {
if (menu instanceof IPatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced();
}
} catch (Throwable t) {
LOGGER.error("Error initializing advanced sync", t);
}
// 使用 SettingToggleButton<YesNo> 的外观原版图标但自定义悬停描述为智能阻挡
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<Component> getTooltipMessage() {
boolean enabled = SmallAdvPatternProviderScreenMixin.this.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.eap$AdvancedBlockingToggle = new EAPServerSettingToggleButton<>(EAPSettings.ADVANCED_BLOCKING, YesNo.YES);
this.addToLeftToolbar(this.eap$AdvancedBlockingToggle);
// 智能翻倍按钮与高级阻挡同款样式点击仅发送C2S状态由@GuiSync驱动
try {
if (menu instanceof IPatternProviderMenuDoublingSync 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<Component> getTooltipMessage() {
boolean enabled = SmallAdvPatternProviderScreenMixin.this.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.eap$SmartDoublingToggle = new EAPServerSettingToggleButton<>(EAPSettings.SMART_DOUBLING, YesNo.YES);
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 IPatternProviderMenuAdvancedSync sync) {
desired = sync.eap$getAdvancedBlockingSynced();
}
this.eap$AdvancedBlockingEnabled = desired;
this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO);
if (this.menu instanceof IPatternProviderMenuDoublingSync sync) {
this.eap$SmartDoublingToggle.set(sync.eap$getSmartDoublingSynced());
}
if (this.eap$SmartDoublingToggle != null) {
boolean desired2 = this.eap$SmartDoublingEnabled;
if (this.menu instanceof IPatternProviderMenuDoublingSync sync2) {
desired2 = sync2.eap$getSmartDoublingSynced();
}
this.eap$SmartDoublingEnabled = desired2;
this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO);
if (this.menu instanceof IPatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingToggle.set(sync.eap$getAdvancedBlockingSynced());
}
}
}

View File

@ -1,14 +1,23 @@
package com.extendedae_plus.mixin.advancedae.helpers;
import appeng.api.config.Setting;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.api.crafting.IPatternDetails;
import appeng.api.crafting.IPatternDetails.IInput;
import appeng.api.networking.IManagedGridNode;
import appeng.api.stacks.AEKey;
import appeng.api.stacks.GenericStack;
import appeng.api.stacks.KeyCounter;
import appeng.api.util.IConfigManager;
import appeng.helpers.patternprovider.PatternProviderTarget;
import com.extendedae_plus.api.advancedBlocking.IAdvancedBlocking;
import appeng.util.ConfigManager;
import com.extendedae_plus.api.config.EAPSettings;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogicHost;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@ -18,51 +27,45 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
import java.util.Set;
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public class AdvPatternProviderLogicAdvancedMixin implements IAdvancedBlocking {
@Unique
private static final String EAP_ADV_BLOCKING_KEY = "eap_advanced_blocking";
public class AdvPatternProviderLogicAdvancedMixin {
@Shadow @Final private IConfigManager configManager;
@Unique
private boolean eap$advancedBlocking = false;
@Shadow public IConfigManager getConfigManager() {throw new AssertionError();}
@Override
public boolean eap$getAdvancedBlocking() {
return this.eap$advancedBlocking;
}
@Shadow public boolean isBlocking() {throw new AssertionError();}
@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);
}
@Inject(
method = "<init>(Lappeng/api/networking/IManagedGridNode;Lnet/pedroksl/advanced_ae/common/logic/AdvPatternProviderLogicHost;I)V",
at = @At("TAIL")
)
private void onInitTail(IManagedGridNode mainNode, AdvPatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
// 直接往构建后的 configManager 里加 setting
ConfigManager configManager = (ConfigManager) this.getConfigManager();
configManager.registerSetting(EAPSettings.ADVANCED_BLOCKING, YesNo.NO);
}
// pushPattern 重定向对 adapter.containsPatternInput(...) 的调用
@Redirect(method = "pushPattern", at = @At(value = "INVOKE", target = "Lappeng/helpers/patternprovider/PatternProviderTarget;containsPatternInput(Ljava/util/Set;)Z"))
@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<AEKey> patternInputs,
Set<AEKey> patternInputs,
IPatternDetails patternDetails,
appeng.api.stacks.KeyCounter[] inputHolder) {
KeyCounter[] inputHolder) {
// 原版是否打开阻挡
boolean vanillaBlocking = ((AdvPatternProviderLogic)(Object)this).isBlocking();
if (!vanillaBlocking) {
if (!this.isBlocking()) {
return adapter.containsPatternInput(patternInputs);
}
// 仅当高级阻挡启用时启用匹配则不阻挡
if (this.eap$advancedBlocking) {
if (this.configManager.getSetting(EAPSettings.ADVANCED_BLOCKING) == YesNo.YES) {
if (this.eap$targetFullyMatchesPatternInputs(adapter, patternDetails)) {
// 返回 false 表示不包含阻挡关键物从而不触发 continue允许发配
return false;
@ -90,5 +93,26 @@ public class AdvPatternProviderLogicAdvancedMixin implements IAdvancedBlocking {
return true; // 每个输入槽都至少匹配了一个候选输入
}
@Shadow public void saveChanges() {}
@Inject(method = "configChanged", at = @At("HEAD"))
private void eap$onConfigChanged(IConfigManager manager, Setting<?> setting, CallbackInfo ci) {
// 开启智能阻挡联动开启原版阻挡
if (setting == EAPSettings.ADVANCED_BLOCKING && manager.getSetting(EAPSettings.ADVANCED_BLOCKING) == YesNo.YES) {
manager.putSetting(Settings.BLOCKING_MODE, YesNo.YES);
}
// 关闭原版阻挡联动关闭智能阻挡
if (setting == Settings.BLOCKING_MODE && manager.getSetting(Settings.BLOCKING_MODE) == YesNo.NO) {
manager.putSetting(EAPSettings.ADVANCED_BLOCKING, YesNo.NO);
}
}
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$readSmartDoublingFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
// TODO
// 适配旧版本中的数据后续版本删除
if (tag.contains("eap_advanced_blocking")) {
this.configManager.putSetting(EAPSettings.ADVANCED_BLOCKING,
tag.getBoolean("eap_advanced_blocking") ? YesNo.YES : YesNo.NO);
tag.remove("eap_advanced_blocking");
}
}
}

View File

@ -1,75 +1,73 @@
package com.extendedae_plus.mixin.advancedae.helpers;
import appeng.api.config.Setting;
import appeng.api.config.YesNo;
import appeng.api.crafting.IPatternDetails;
import com.extendedae_plus.api.smartDoubling.ISmartDoubling;
import appeng.api.networking.IManagedGridNode;
import appeng.api.util.IConfigManager;
import appeng.util.ConfigManager;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.ISmartDoublingAwarePattern;
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 net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogicHost;
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;
import java.util.List;
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public class AdvPatternProviderLogicDoublingMixin implements ISmartDoubling {
@Unique
private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling";
public class AdvPatternProviderLogicDoublingMixin {
@Shadow @Final private List<IPatternDetails> patterns;
@Shadow @Final private IConfigManager configManager;
@Unique
private boolean eap$smartDoubling = false;
@Shadow
public IConfigManager getConfigManager() {return null;}
@Override
public boolean eap$getSmartDoubling() {
return this.eap$smartDoubling;
@Shadow
public void updatePatterns() {}
@Inject(
method = "<init>(Lappeng/api/networking/IManagedGridNode;Lnet/pedroksl/advanced_ae/common/logic/AdvPatternProviderLogicHost;I)V",
at = @At("TAIL")
)
private void onInitTail(IManagedGridNode mainNode, AdvPatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
// 直接往构建后的 configManager 里加 setting
ConfigManager configManager = (ConfigManager) this.getConfigManager();
configManager.registerSetting(EAPSettings.SMART_DOUBLING, YesNo.NO);
}
@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 ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(value);
}
}
// 触发一次刷新让网络及时拿到最新状态也会触发 ICraftingProvider.requestUpdate(mainNode)
((AdvPatternProviderLogic) (Object) this).updatePatterns();
} catch (Throwable ignored) {
@Inject(method = "configChanged", at = @At("HEAD"))
private void eap$onConfigChanged(IConfigManager manager, Setting<?> setting, CallbackInfo ci) {
if (setting == EAPSettings.SMART_DOUBLING) {
this.updatePatterns();
}
}
@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);
// TODO
// 适配旧版本中的数据后续版本删除
if (tag.contains("eap_smart_doubling")) {
this.configManager.putSetting(EAPSettings.SMART_DOUBLING,
tag.getBoolean("eap_smart_doubling") ? YesNo.YES : YesNo.NO);
tag.remove("eap_smart_doubling");
}
}
@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 ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allow);
}
IConfigManager configManager = this.getConfigManager();
boolean allowScaling = configManager.getSetting(EAPSettings.SMART_DOUBLING) == YesNo.YES;
for (IPatternDetails details : this.patterns) {
if (details instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allowScaling);
}
} catch (Throwable ignored) {
}
}
@Shadow
public void saveChanges() {}
}

View File

@ -1,9 +1,9 @@
package com.extendedae_plus.mixin.advancedae.menu;
import appeng.menu.AEBaseMenu;
import appeng.api.config.YesNo;
import appeng.menu.guisync.GuiSync;
import com.extendedae_plus.api.advancedBlocking.IAdvancedBlocking;
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.config.EAPSettings;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
import org.spongepowered.asm.mixin.Final;
@ -14,29 +14,20 @@ 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)
@Mixin(value = AdvPatternProviderMenu.class, remap = false)
public abstract class AdvPatternProviderMenuAdvancedMixin implements IPatternProviderMenuAdvancedSync {
@Final
@Shadow(remap = false)
protected AdvPatternProviderLogic logic;
// 选择一个未占用的 GUI 同步 idAE2 已用到 7这里使用 21 以避冲突
@Unique
@GuiSync(22) private boolean eap$AdvancedBlocking = false;
@Shadow @Final protected AdvPatternProviderLogic logic;
@Unique @GuiSync(20) private YesNo eap$AdvancedBlocking;
@Inject(method = "broadcastChanges", at = @At("HEAD"))
private void eap$syncAdvancedBlocking(CallbackInfo ci) {
// 避免@Shadow父类方法改用公共APIAEBaseMenu#isClientSide()
if (!((AEBaseMenu) (Object) this).isClientSide()) {
var l = this.logic;
if (l instanceof IAdvancedBlocking holder) {
this.eap$AdvancedBlocking = holder.eap$getAdvancedBlocking();
}
private void eap$syncSmartDoubling(CallbackInfo ci) {
if (!((AdvPatternProviderMenu) (Object) this).isClientSide()) {
this.eap$AdvancedBlocking = this.logic.getConfigManager().getSetting(EAPSettings.ADVANCED_BLOCKING);
}
}
@Override
public boolean eap$getAdvancedBlockingSynced() {
public YesNo eap$getAdvancedBlockingSynced() {
return this.eap$AdvancedBlocking;
}
}

View File

@ -1,9 +1,9 @@
package com.extendedae_plus.mixin.advancedae.menu;
import appeng.menu.AEBaseMenu;
import appeng.api.config.YesNo;
import appeng.menu.guisync.GuiSync;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.api.smartDoubling.ISmartDoubling;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
import org.spongepowered.asm.mixin.Final;
@ -14,27 +14,20 @@ 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)
@Mixin(value = AdvPatternProviderMenu.class, remap = false)
public abstract class AdvPatternProviderMenuDoublingMixin implements IPatternProviderMenuDoublingSync {
@Final
@Shadow(remap = false)
protected AdvPatternProviderLogic logic;
@Unique
@GuiSync(23) private boolean eap$SmartDoubling = false;
@Shadow @Final protected AdvPatternProviderLogic logic;
@Unique @GuiSync(21) private YesNo eap$SmartDoubling;
@Inject(method = "broadcastChanges", at = @At("HEAD"))
private void eap$syncSmartDoubling(CallbackInfo ci) {
if (!((AEBaseMenu) (Object) this).isClientSide()) {
var l = this.logic;
if (l instanceof ISmartDoubling holder) {
this.eap$SmartDoubling = holder.eap$getSmartDoubling();
}
if (!((AdvPatternProviderMenu) (Object) this).isClientSide()) {
this.eap$SmartDoubling = this.logic.getConfigManager().getSetting(EAPSettings.SMART_DOUBLING);
}
}
@Override
public boolean eap$getSmartDoublingSynced() {
public YesNo eap$getSmartDoublingSynced() {
return this.eap$SmartDoubling;
}
}

View File

@ -25,14 +25,14 @@ public class PatternProviderLogicContainsRedirectMixin {
try {
if (o instanceof ScaledProcessingPattern scaled) {
IPatternDetails base = scaled.getOriginal();
if (list.indexOf(base) != -1) {
if (list.contains(base)) {
return true;
}
}
// 使用 indexOf 避免再次触发对 List.contains redirect防止递归
return list.indexOf(o) != -1;
return list.contains(o);
} catch (Throwable t) {
return list.indexOf(o) != -1;
return list.contains(o);
}
}
}

View File

@ -1,154 +0,0 @@
package com.extendedae_plus.mixin.ae2.client.gui;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.implementations.PatternProviderScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.client.gui.widgets.SettingToggleButton;
import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.api.IExPatternButton;
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket;
import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket;
import com.extendedae_plus.util.ExtendedAELogger;
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
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;
/**
* AE2 原版样板供应器界面添加高级阻挡模式按钮
* - 位于左侧工具栏
* - 点击仅发送 C2S 切换请求状态由 AE2 @GuiSync 回传决定
*/
@Mixin(value = PatternProviderScreen.class, remap = false)
public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> {
@Unique
private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@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);
}
@Inject(method = "<init>", at = @At("RETURN"), remap = false)
private void eap$initAdvancedBlocking(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
// 使用 @GuiSync 初始化
try {
if (menu instanceof IPatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced();
}
} catch (Throwable t) {
ExtendedAELogger.LOGGER.error("Error initializing advanced sync", t);
}
// 使用 SettingToggleButton<YesNo> 的外观原版图标但自定义悬停描述为智能阻挡
this.eap$AdvancedBlockingToggle = new SettingToggleButton<>(
Settings.BLOCKING_MODE,
this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO,
(btn, backwards) -> {
// 不做本地切换点击仅发送自定义C2S显示由@GuiSync回传
// debug removed
var conn = Minecraft.getInstance().getConnection();
if (conn != null) conn.send(ToggleAdvancedBlockingC2SPacket.INSTANCE);
}
) {
@Override
public java.util.List<net.minecraft.network.chat.Component> getTooltipMessage() {
boolean enabled = PatternProviderScreenMixin.this.eap$AdvancedBlockingEnabled;
var title = net.minecraft.network.chat.Component.translatable("gui.tooltips.extendedae_plus.advanced_blocking.title");
var line = net.minecraft.network.chat.Component.translatable(
enabled ? "gui.tooltips.extendedae_plus.advanced_blocking.enabled"
: "gui.tooltips.extendedae_plus.advanced_blocking.disabled"
);
return java.util.List.of(title, line);
}
};
// 初始化后立刻对齐当前@GuiSync状态避免首帧显示不一致
// debug removed
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();
}
} catch (Throwable t) {
ExtendedAELogger.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) -> {
// debug removed
var conn = Minecraft.getInstance().getConnection();
if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE);
}
) {
@Override
public java.util.List<net.minecraft.network.chat.Component> getTooltipMessage() {
boolean enabled = PatternProviderScreenMixin.this.eap$SmartDoublingEnabled;
var title = net.minecraft.network.chat.Component.translatable("gui.tooltips.extendedae_plus.smart_doubling.title");
var line = net.minecraft.network.chat.Component.translatable(
enabled ? "gui.tooltips.extendedae_plus.smart_doubling.enabled"
: "gui.tooltips.extendedae_plus.smart_doubling.disabled"
);
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 IPatternProviderMenuAdvancedSync sync) {
desired = sync.eap$getAdvancedBlockingSynced();
}
// debug removed
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 IPatternProviderMenuDoublingSync sync2) {
desired2 = sync2.eap$getSmartDoublingSynced();
}
// debug removed
this.eap$SmartDoublingEnabled = desired2;
this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO);
}
if ((Object) this instanceof GuiExPatternProvider) {
try {
((IExPatternButton) this).eap$updateButtonsLayout();
} catch (Throwable t) {
// debug removed
}
}
}
}

View File

@ -0,0 +1,62 @@
package com.extendedae_plus.mixin.ae2.client.gui;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.implementations.PatternProviderScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.api.IExPatternButton;
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.client.gui.widgets.EAPServerSettingToggleButton;
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
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;
/**
* AE2 原版样板供应器界面添加高级阻挡模式按钮
* - 位于左侧工具栏
* - 点击仅发送 C2S 切换请求状态由 AE2 @GuiSync 回传决定
*/
@Mixin(value = PatternProviderScreen.class, remap = false)
public abstract class PatternProviderSmartFeaturesMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> {
@Unique private EAPServerSettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@Unique private EAPServerSettingToggleButton<YesNo> eap$SmartDoublingToggle;
public PatternProviderSmartFeaturesMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
}
@Inject(method = "<init>", at = @At("RETURN"), remap = false)
private void eap$initAdvancedBlocking(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
this.eap$AdvancedBlockingToggle = new EAPServerSettingToggleButton<>(EAPSettings.ADVANCED_BLOCKING, YesNo.YES);
this.addToLeftToolbar(this.eap$AdvancedBlockingToggle);
this.eap$SmartDoublingToggle = new EAPServerSettingToggleButton<>(EAPSettings.SMART_DOUBLING, YesNo.YES);
this.addToLeftToolbar(this.eap$SmartDoublingToggle);
}
// 每帧刷新仅从菜单(@GuiSync)同步布尔值保持按钮状态一致
@Inject(method = "updateBeforeRender", at = @At("HEAD"), remap = false)
private void eap$updateAdvancedBlocking(CallbackInfo ci) {
if (this.menu instanceof IPatternProviderMenuDoublingSync sync) {
this.eap$SmartDoublingToggle.set(sync.eap$getSmartDoublingSynced());
}
if (this.menu instanceof IPatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingToggle.set(sync.eap$getAdvancedBlockingSynced());
}
if ((Object) this instanceof GuiExPatternProvider) {
try {
((IExPatternButton) this).eap$updateButtonsLayout();
} catch (Throwable t) {
// debug removed
}
}
}
}

View File

@ -1,17 +1,22 @@
package com.extendedae_plus.mixin.ae2.helpers;
import appeng.api.config.Setting;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.api.crafting.IPatternDetails;
import appeng.api.crafting.IPatternDetails.IInput;
import appeng.api.networking.IManagedGridNode;
import appeng.api.stacks.AEKey;
import appeng.api.stacks.GenericStack;
import appeng.api.stacks.KeyCounter;
import appeng.api.util.IConfigManager;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import appeng.helpers.patternprovider.PatternProviderTarget;
import com.extendedae_plus.api.advancedBlocking.IAdvancedBlocking;
import com.extendedae_plus.api.ids.EAPComponents;
import appeng.util.ConfigManager;
import com.extendedae_plus.api.config.EAPSettings;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@ -21,51 +26,45 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
import java.util.Set;
@Mixin(value = PatternProviderLogic.class, remap = false)
public class PatternProviderLogicAdvancedMixin implements IAdvancedBlocking {
@Unique
private static final String EAP_ADV_BLOCKING_KEY = "epp_advanced_blocking";
public class PatternProviderLogicAdvancedMixin {
@Shadow @Final private IConfigManager configManager;
@Unique
private boolean eap$advancedBlocking = false;
@Shadow public IConfigManager getConfigManager() {throw new AssertionError();}
@Override
public boolean eap$getAdvancedBlocking() {
return this.eap$advancedBlocking;
}
@Shadow public boolean isBlocking() {throw new AssertionError();}
@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);
}
@Inject(
method = "<init>(Lappeng/api/networking/IManagedGridNode;Lappeng/helpers/patternprovider/PatternProviderLogicHost;I)V",
at = @At("TAIL")
)
private void onInitTail(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
// 直接往构建后的 configManager 里加 setting
ConfigManager configManager = (ConfigManager) this.getConfigManager();
configManager.registerSetting(EAPSettings.ADVANCED_BLOCKING, YesNo.NO);
}
// pushPattern 重定向对 adapter.containsPatternInput(...) 的调用
@Redirect(method = "pushPattern", at = @At(value = "INVOKE", target = "Lappeng/helpers/patternprovider/PatternProviderTarget;containsPatternInput(Ljava/util/Set;)Z"))
@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<AEKey> patternInputs,
Set<AEKey> patternInputs,
IPatternDetails patternDetails,
appeng.api.stacks.KeyCounter[] inputHolder) {
KeyCounter[] inputHolder) {
// 原版是否打开阻挡
boolean vanillaBlocking = ((PatternProviderLogic) (Object) this).isBlocking();
if (!vanillaBlocking) {
if (!this.isBlocking()) {
return adapter.containsPatternInput(patternInputs);
}
// 仅当高级阻挡启用时启用匹配则不阻挡
if (this.eap$advancedBlocking) {
if (this.configManager.getSetting(EAPSettings.ADVANCED_BLOCKING) == YesNo.YES) {
if (this.eap$targetFullyMatchesPatternInputs(adapter, patternDetails)) {
// 返回 false 表示不包含阻挡关键物从而不触发 continue允许发配
return false;
@ -77,7 +76,7 @@ public class PatternProviderLogicAdvancedMixin implements IAdvancedBlocking {
@Unique
private boolean eap$targetFullyMatchesPatternInputs(PatternProviderTarget adapter, IPatternDetails patternDetails) {
for (IInput in : patternDetails.getInputs()) {
for (IPatternDetails.IInput in : patternDetails.getInputs()) {
boolean slotMatched = false;
for (GenericStack candidate : in.getPossibleInputs()) {
AEKey key = candidate.what().dropSecondary();
@ -93,18 +92,26 @@ public class PatternProviderLogicAdvancedMixin implements IAdvancedBlocking {
return true; // 每个输入槽都至少匹配了一个候选输入
}
@Shadow
public void saveChanges() {}
@Inject(method = "exportSettings", at = @At("TAIL"))
private void onExportSettings(DataComponentMap.Builder builder, CallbackInfo ci) {
builder.set(EAPComponents.ADVANCED_BLOCKING, this.eap$advancedBlocking);
@Inject(method = "configChanged", at = @At("HEAD"))
private void eap$onConfigChanged(IConfigManager manager, Setting<?> setting, CallbackInfo ci) {
// 开启智能阻挡联动开启原版阻挡
if (setting == EAPSettings.ADVANCED_BLOCKING && manager.getSetting(EAPSettings.ADVANCED_BLOCKING) == YesNo.YES) {
manager.putSetting(Settings.BLOCKING_MODE, YesNo.YES);
}
// 关闭原版阻挡联动关闭智能阻挡
if (setting == Settings.BLOCKING_MODE && manager.getSetting(Settings.BLOCKING_MODE) == YesNo.NO) {
manager.putSetting(EAPSettings.ADVANCED_BLOCKING, YesNo.NO);
}
}
@Inject(method = "importSettings", at = @At("TAIL"))
private void onImportSettings(DataComponentMap input, Player player, CallbackInfo ci) {
this.eap$advancedBlocking = Boolean.TRUE.equals(input.get(EAPComponents.ADVANCED_BLOCKING.get()));
// 持久化到 world
this.saveChanges();
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$readSmartDoublingFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
// TODO
// 适配旧版本中的数据后续版本删除
if (tag.contains("epp_advanced_blocking")) {
this.configManager.putSetting(EAPSettings.ADVANCED_BLOCKING,
tag.getBoolean("epp_advanced_blocking") ? YesNo.YES : YesNo.NO);
tag.remove("epp_advanced_blocking");
}
}
}

View File

@ -1,90 +1,73 @@
package com.extendedae_plus.mixin.ae2.helpers;
import appeng.api.config.Setting;
import appeng.api.config.YesNo;
import appeng.api.crafting.IPatternDetails;
import appeng.crafting.pattern.AEProcessingPattern;
import appeng.api.networking.IManagedGridNode;
import appeng.api.util.IConfigManager;
import appeng.helpers.patternprovider.PatternProviderLogic;
import com.extendedae_plus.api.ids.EAPComponents;
import com.extendedae_plus.api.smartDoubling.ISmartDoubling;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import appeng.util.ConfigManager;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.ISmartDoublingAwarePattern;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicPatternsAccessor;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
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;
import java.util.List;
@Mixin(value = PatternProviderLogic.class, remap = false)
public class PatternProviderLogicDoublingMixin implements ISmartDoubling {
@Unique
private static final String EAP_SMART_DOUBLING_KEY = "epp_smart_doubling";
public class PatternProviderLogicDoublingMixin {
@Shadow @Final private List<IPatternDetails> patterns;
@Shadow @Final private IConfigManager configManager;
@Unique
private boolean eap$smartDoubling = false;
@Shadow
public IConfigManager getConfigManager() {return null;}
@Override
public boolean eap$getSmartDoubling() {
return this.eap$smartDoubling;
@Shadow
public void updatePatterns() {}
@Inject(
method = "<init>(Lappeng/api/networking/IManagedGridNode;Lappeng/helpers/patternprovider/PatternProviderLogicHost;I)V",
at = @At("TAIL")
)
private void onInitTail(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
// 直接往构建后的 configManager 里加 setting
ConfigManager configManager = (ConfigManager) this.getConfigManager();
configManager.registerSetting(EAPSettings.SMART_DOUBLING, YesNo.NO);
}
@Override
public void eap$setSmartDoubling(boolean value) {
this.eap$smartDoubling = value;
// 立即将开关状态应用到当前 Provider 的样板上避免等待下一次 updatePatterns
try {
var list = ((PatternProviderLogicPatternsAccessor) this).eap$patterns();
for (IPatternDetails details : list) {
if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(value);
}
}
// 触发一次刷新让网络及时拿到最新状态也会触发 ICraftingProvider.requestUpdate(mainNode)
((PatternProviderLogic) (Object) this).updatePatterns();
} catch (Throwable ignored) {
@Inject(method = "configChanged", at = @At("HEAD"))
private void eap$onConfigChanged(IConfigManager manager, Setting<?> setting, CallbackInfo ci) {
if (setting == EAPSettings.SMART_DOUBLING) {
this.updatePatterns();
}
}
@Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$writeSmartDoublingToNbt(CompoundTag tag, net.minecraft.core.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, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
if (tag.contains(EAP_SMART_DOUBLING_KEY)) {
this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY);
private void eap$readSmartDoublingFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
// TODO
// 适配旧版本中的数据后续版本删除
if (tag.contains("epp_smart_doubling")) {
this.configManager.putSetting(EAPSettings.SMART_DOUBLING,
tag.getBoolean("epp_smart_doubling") ? YesNo.YES : YesNo.NO);
tag.remove("epp_smart_doubling");
}
}
@Inject(method = "updatePatterns", at = @At("TAIL"))
private void eap$applySmartDoublingToPatterns(CallbackInfo ci) {
try {
var list = ((PatternProviderLogicPatternsAccessor) this).eap$patterns();
boolean allow = this.eap$smartDoubling;
for (IPatternDetails details : list) {
if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allow);
}
IConfigManager configManager = this.getConfigManager();
boolean allowScaling = configManager.getSetting(EAPSettings.SMART_DOUBLING) == YesNo.YES;
for (IPatternDetails details : this.patterns) {
if (details instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allowScaling);
}
} catch (Throwable ignored) {
}
}
@Shadow
public void saveChanges() {}
@Inject(method = "exportSettings", at = @At("TAIL"))
private void onExportSettings(DataComponentMap.Builder builder, CallbackInfo ci) {
builder.set(EAPComponents.SMART_DOUBLING, this.eap$smartDoubling);
}
@Inject(method = "importSettings", at = @At("TAIL"))
private void onImportSettings(DataComponentMap input, Player player, CallbackInfo ci) {
this.eap$smartDoubling = Boolean.TRUE.equals(input.get(EAPComponents.SMART_DOUBLING.get()));
// 持久化到 world
this.saveChanges();
}
}

View File

@ -1,51 +1,33 @@
package com.extendedae_plus.mixin.ae2.menu;
import appeng.api.config.YesNo;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.menu.AEBaseMenu;
import appeng.menu.guisync.GuiSync;
import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.api.advancedBlocking.IAdvancedBlocking;
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.config.EAPSettings;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PatternProviderMenu.class)
public abstract class PatternProviderMenuAdvancedMixin implements IPatternProviderMenuAdvancedSync {
@Shadow
protected PatternProviderLogic logic;
// 选择一个未占用的 GUI 同步 idAE2 已用到 7这里使用 20 以避冲突
@Unique
@GuiSync(20) private boolean eap$AdvancedBlocking = false;
@Shadow @Final protected PatternProviderLogic logic;
@Unique @GuiSync(20) private YesNo eap$AdvancedBlocking;
@Inject(method = "broadcastChanges", at = @At("HEAD"))
private void eap$syncAdvancedBlocking(CallbackInfo ci) {
// 避免@Shadow父类方法改用公共APIAEBaseMenu#isClientSide()
if (!((AEBaseMenu) (Object) this).isClientSide()) {
var l = this.logic;
if (l instanceof IAdvancedBlocking holder) {
this.eap$AdvancedBlocking = holder.eap$getAdvancedBlocking();
// debug removed
}
private void eap$syncSmartDoubling(CallbackInfo ci) {
if (!((PatternProviderMenu) (Object) this).isClientSide()) {
this.eap$AdvancedBlocking = this.logic.getConfigManager().getSetting(EAPSettings.ADVANCED_BLOCKING);
}
}
@Override
public boolean eap$getAdvancedBlockingSynced() {
public YesNo eap$getAdvancedBlockingSynced() {
return this.eap$AdvancedBlocking;
}
// 调试 Screen 每帧读取这些 getter 时打印验证 Mixin 是否生效
@Inject(method = "getBlockingMode", at = @At("HEAD"), remap = false)
private void eap$debug_getBlockingMode(CallbackInfoReturnable<?> cir) {
}
@Inject(method = "getShowInAccessTerminal", at = @At("HEAD"), remap = false)
private void eap$debug_getShowInAccessTerminal(CallbackInfoReturnable<?> cir) {
}
}

View File

@ -1,11 +1,12 @@
package com.extendedae_plus.mixin.ae2.menu;
import appeng.api.config.YesNo;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.menu.AEBaseMenu;
import appeng.menu.guisync.GuiSync;
import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.api.config.EAPSettings;
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
import com.extendedae_plus.api.smartDoubling.ISmartDoubling;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@ -15,25 +16,18 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PatternProviderMenu.class)
public abstract class PatternProviderMenuDoublingMixin implements IPatternProviderMenuDoublingSync {
@Shadow
protected PatternProviderLogic logic;
@Unique
@GuiSync(21) private boolean eap$SmartDoubling = false;
@Shadow @Final protected PatternProviderLogic logic;
@Unique @GuiSync(21) private YesNo eap$SmartDoubling;
@Inject(method = "broadcastChanges", at = @At("HEAD"))
private void eap$syncSmartDoubling(CallbackInfo ci) {
if (!((AEBaseMenu) (Object) this).isClientSide()) {
var l = this.logic;
if (l instanceof ISmartDoubling holder) {
this.eap$SmartDoubling = holder.eap$getSmartDoubling();
// debug removed
}
if (!((PatternProviderMenu) (Object) this).isClientSide()) {
this.eap$SmartDoubling = this.logic.getConfigManager().getSetting(EAPSettings.SMART_DOUBLING);
}
}
@Override
public boolean eap$getSmartDoublingSynced() {
public YesNo eap$getSmartDoublingSynced() {
return this.eap$SmartDoubling;
}
}
}

View File

@ -1,48 +0,0 @@
package com.extendedae_plus.network;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.client.ClientAdvancedBlockingState;
import net.minecraft.network.RegistryFriendlyByteBuf;
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;
/**
* S2C同步某个 Provider 的高级阻挡状态到客户端本地存储
*/
public class AdvancedBlockingSyncS2CPacket implements CustomPacketPayload {
public static final Type<AdvancedBlockingSyncS2CPacket> TYPE = new Type<>(
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "adv_blocking_sync"));
public static final StreamCodec<RegistryFriendlyByteBuf, AdvancedBlockingSyncS2CPacket> STREAM_CODEC = StreamCodec.of(
(buf, pkt) -> {
buf.writeUtf(pkt.dimensionId);
buf.writeLong(pkt.blockPosLong);
buf.writeBoolean(pkt.enabled);
},
buf -> new AdvancedBlockingSyncS2CPacket(buf.readUtf(), buf.readLong(), buf.readBoolean())
);
private final String dimensionId;
private final long blockPosLong;
private final boolean enabled;
public AdvancedBlockingSyncS2CPacket(String dimensionId, long blockPosLong, boolean enabled) {
this.dimensionId = dimensionId;
this.blockPosLong = blockPosLong;
this.enabled = enabled;
}
@Override
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
public static void handle(final AdvancedBlockingSyncS2CPacket msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> {
String key = ClientAdvancedBlockingState.key(msg.dimensionId, msg.blockPosLong);
ClientAdvancedBlockingState.set(key, msg.enabled);
});
}
}

View File

@ -9,8 +9,7 @@ import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import appeng.parts.crafting.PatternProviderPart;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.api.advancedBlocking.IAdvancedBlocking;
import com.extendedae_plus.api.smartDoubling.ISmartDoubling;
import com.extendedae_plus.api.config.EAPSettings;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
@ -19,188 +18,244 @@ import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* C2S全网批量切换样板供应器的三种模式
* - 阻挡模式AE2 内置 BLOCKING_MODE 设置
* - 高级阻挡模式IAdvancedBlocking mixin
* - 智能翻倍模式ISmartDoubling mixin
*
* 负载为三个操作码各1字节分别对应blockingadvancedBlockingsmartDoubling
* C2S 全局批量切换样板供应器的三种模式
* - 普通阻挡模式AE2 原生 BLOCKING_MODE
* - 高级阻挡模式
* - 智能翻倍模式
* <p>
* 包体包含三个操作码每个 1 byte以及控制器方块位置用于定位所属 ME 网络
*/
public class GlobalToggleProviderModesC2SPacket implements CustomPacketPayload {
public static final Type<GlobalToggleProviderModesC2SPacket> TYPE = new Type<>(
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "global_toggle_provider_modes"));
public static final StreamCodec<FriendlyByteBuf, GlobalToggleProviderModesC2SPacket> STREAM_CODEC = StreamCodec.of(
(buf, pkt) -> {
buf.writeByte(pkt.opBlocking.id);
buf.writeByte(pkt.opAdvancedBlocking.id);
buf.writeByte(pkt.opSmartDoubling.id);
buf.writeBlockPos(pkt.controllerPos);
(buf, packet) -> {
buf.writeByte(packet.blockingModeOperation.id);
buf.writeByte(packet.advancedBlockingOperation.id);
buf.writeByte(packet.smartDoublingOperation.id);
buf.writeBlockPos(packet.controllerBlockPos);
},
buf -> new GlobalToggleProviderModesC2SPacket(Op.byId(buf.readByte()), Op.byId(buf.readByte()), Op.byId(buf.readByte()), buf.readBlockPos())
buf -> new GlobalToggleProviderModesC2SPacket(
Operation.byId(buf.readByte()),
Operation.byId(buf.readByte()),
Operation.byId(buf.readByte()),
buf.readBlockPos())
);
private final Op opBlocking;
private final Op opAdvancedBlocking;
private final Op opSmartDoubling;
private final BlockPos controllerPos;
public GlobalToggleProviderModesC2SPacket(Op opBlocking, Op opAdvancedBlocking, Op opSmartDoubling, BlockPos controllerPos) {
this.opBlocking = opBlocking;
this.opAdvancedBlocking = opAdvancedBlocking;
this.opSmartDoubling = opSmartDoubling;
this.controllerPos = controllerPos;
private final Operation blockingModeOperation;
private final Operation advancedBlockingOperation;
private final Operation smartDoublingOperation;
/**
* 发起请求的玩家的控制器位置用于获取对应的 IGrid
*/
private final BlockPos controllerBlockPos;
public GlobalToggleProviderModesC2SPacket(Operation blockingModeOperation,
Operation advancedBlockingOperation,
Operation smartDoublingOperation,
BlockPos controllerBlockPos) {
this.blockingModeOperation = blockingModeOperation;
this.advancedBlockingOperation = advancedBlockingOperation;
this.smartDoublingOperation = smartDoublingOperation;
this.controllerBlockPos = controllerBlockPos;
}
public static void handle(final GlobalToggleProviderModesC2SPacket msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> {
if (!(ctx.player() instanceof ServerPlayer player)) return;
if (player == null) return;
public static void handle(final GlobalToggleProviderModesC2SPacket message, final IPayloadContext context) {
context.enqueueWork(() -> {
if (!(context.player() instanceof ServerPlayer player)) return;
// 从控制方块实体的 AE2 节点确定 AE 网络上下文
var level = player.serverLevel();
var be = level.getBlockEntity(msg.controllerPos);
if (!(be instanceof IInWorldGridNodeHost host)) return;
var node = host.getGridNode(null);
if (node == null) return;
IGrid grid = node.getGrid();
var blockEntity = level.getBlockEntity(message.controllerBlockPos);
if (!(blockEntity instanceof IInWorldGridNodeHost gridNodeHost)) return;
var gridNode = gridNodeHost.getGridNode(null);
if (gridNode == null) return;
IGrid grid = gridNode.getGrid();
if (grid == null) return;
int affected = applyToAllProviders(grid, msg);
// 向发起玩家反馈影响数量便于判断按钮是否生效
player.displayClientMessage(Component.literal("E+ 全局切换已应用到 " + affected + " 个样板供应器"), true);
int affectedCount = applyToAllPatternProviders(grid, message);
// 给发起者一个短暂的行动条提示方便知道本次操作实际影响了多少个供应器
player.displayClientMessage(
Component.literal("E+ 全局切换已应用到 " + affectedCount + " 个样板供应器"),
true);
});
}
private static int applyToAllProviders(IGrid grid, GlobalToggleProviderModesC2SPacket msg) {
int affected = 0;
// 去重集合避免同一逻辑重复计数
Set<PatternProviderLogic> all = new HashSet<>();
/**
* 遍历当前 ME 网络中所有样板供应器方块零件第三方实现并应用切换操作
*/
private static int applyToAllPatternProviders(IGrid grid, GlobalToggleProviderModesC2SPacket message) {
int affectedCount = 0;
// Set 去重因为同一个 Logic 实例可能被多种方式收集到
Set<PatternProviderLogic> uniqueLogics = new HashSet<>();
// 方块形式的样板供应器全部/在线
try {
Set<PatternProviderBlockEntity> blocksAll = grid.getMachines(PatternProviderBlockEntity.class);
Set<PatternProviderBlockEntity> blocksActive = grid.getActiveMachines(PatternProviderBlockEntity.class);
for (PatternProviderBlockEntity be : blocksAll) if (be != null && be.getLogic() != null) all.add(be.getLogic());
for (PatternProviderBlockEntity be : blocksActive) if (be != null && be.getLogic() != null) all.add(be.getLogic());
} catch (Throwable ignored) {}
// 1. AE2 原生的方块实体形式Pattern Provider BlockEntity
collectLogicsFromMachineSet(grid.getMachines(PatternProviderBlockEntity.class), uniqueLogics);
collectLogicsFromMachineSet(grid.getActiveMachines(PatternProviderBlockEntity.class), uniqueLogics);
// Part 形式的样板供应器全部/在线
try {
Set<PatternProviderPart> partsAll = grid.getMachines(PatternProviderPart.class);
Set<PatternProviderPart> partsActive = grid.getActiveMachines(PatternProviderPart.class);
for (PatternProviderPart part : partsAll) if (part != null && part.getLogic() != null) all.add(part.getLogic());
for (PatternProviderPart part : partsActive) if (part != null && part.getLogic() != null) all.add(part.getLogic());
} catch (Throwable ignored) {}
// 2. AE2 原生的电缆零件形式Pattern Provider Part
collectLogicsFromMachineSet(grid.getMachines(PatternProviderPart.class), uniqueLogics);
collectLogicsFromMachineSet(grid.getActiveMachines(PatternProviderPart.class), uniqueLogics);
// 兼容任意实现了 PatternProviderLogicHost 的机器例如 ExtendedAE PartExPatternProvider
try {
Set<PatternProviderLogicHost> hostsAll = grid.getMachines(PatternProviderLogicHost.class);
Set<PatternProviderLogicHost> hostsActive = grid.getActiveMachines(PatternProviderLogicHost.class);
for (PatternProviderLogicHost host : hostsAll) if (host != null && host.getLogic() != null) all.add(host.getLogic());
for (PatternProviderLogicHost host : hostsActive) if (host != null && host.getLogic() != null) all.add(host.getLogic());
} catch (Throwable ignored) {}
// 3. 任何实现了 PatternProviderLogicHost 接口的机器包括 ExtendedAE 自己的扩展
collectLogicsFromMachineSet(grid.getMachines(PatternProviderLogicHost.class), uniqueLogics);
collectLogicsFromMachineSet(grid.getActiveMachines(PatternProviderLogicHost.class), uniqueLogics);
// 兼容显式匹配第三方具体类通过反射避免 AE2 仅按精确类型匹配导致 interface 不返回的问题
collectByClassName(grid, all, "com.glodblock.github.extendedae.common.parts.PartExPatternProvider");
collectByClassName(grid, all, "com.glodblock.github.extendedae.common.tileentities.TileExPatternProvider");
// 4. 兼容 ExtendedAEglodblock自己的 ExPatternProvider因为 AE2 getMachines 只按精确类匹配接口会漏
collectByReflection(grid, uniqueLogics, "com.glodblock.github.extendedae.common.parts.PartExPatternProvider");
collectByReflection(grid, uniqueLogics, "com.glodblock.github.extendedae.common.tileentities.TileExPatternProvider");
for (PatternProviderLogic logic : all) {
if (applyToLogic(logic, msg)) affected++;
// 真正执行切换
for (PatternProviderLogic logic : uniqueLogics) {
if (applyOperationToLogic(logic, message)) {
affectedCount++;
}
}
return affected;
return affectedCount;
}
private static void collectByClassName(IGrid grid, Set<PatternProviderLogic> out, String className) {
try {
Class<?> cls = Class.forName(className);
// 收集全部与在线两类机器
Set<?> all = grid.getMachines((Class) cls);
Set<?> active = grid.getActiveMachines((Class) cls);
for (Object o : all) addLogicIfPresent(out, o);
for (Object o : active) addLogicIfPresent(out, o);
} catch (Throwable ignored) {}
/**
* 工具方法把一个 Set<? extends SomeMachine> 中的 Logic 加入去重集合
*/
private static void collectLogicsFromMachineSet(Set<?> machineSet, Set<PatternProviderLogic> target) {
if (machineSet == null) return;
for (Object obj : machineSet) {
addLogicIfPresent(target, obj);
}
}
private static void addLogicIfPresent(Set<PatternProviderLogic> out, Object o) {
/**
* 通过反射兼容第三方精确类防止接口匹配漏掉
*/
private static void collectByReflection(IGrid grid, Set<PatternProviderLogic> target, String className) {
try {
if (o instanceof PatternProviderLogicHost host) {
var logic = host.getLogic();
if (logic != null) out.add(logic);
Class<?> clazz = Class.forName(className);
collectLogicsFromMachineSet(grid.getMachines(clazz), target);
collectLogicsFromMachineSet(grid.getActiveMachines(clazz), target);
} catch (Throwable ignored) {
// 如果类不存在比如玩家没装 ExtendedAE直接忽略
}
}
/**
* 从任意对象里尝试取出 PatternProviderLogic兼容多种实现
*/
private static void addLogicIfPresent(Set<PatternProviderLogic> target, Object obj) {
if (obj == null) return;
try {
if (obj instanceof PatternProviderLogicHost host && host.getLogic() != null) {
target.add(host.getLogic());
return;
}
// 兜底若对象有 getLogic 方法且返回 PatternProviderLogic
var m = o.getClass().getMethod("getLogic");
Object ret = m.invoke(o);
if (ret instanceof PatternProviderLogic logic) out.add(logic);
} catch (Throwable ignored) {}
// 兜底反射调用 getLogic()
var method = obj.getClass().getMethod("getLogic");
Object result = method.invoke(obj);
if (result instanceof PatternProviderLogic logic) {
target.add(logic);
}
} catch (Throwable ignored) {
}
}
private static boolean applyToLogic(PatternProviderLogic logic, GlobalToggleProviderModesC2SPacket msg) {
/**
* 对单个 PatternProviderLogic 应用本次包里携带的三种操作
*/
private static boolean applyOperationToLogic(PatternProviderLogic logic, GlobalToggleProviderModesC2SPacket message) {
if (logic == null) return false;
boolean changed = false;
// 1) 阻挡模式AE2 内置设置
if (msg.opBlocking != Op.NOOP) {
boolean current = safeIsBlocking(logic);
boolean target = computeTarget(current, msg.opBlocking);
var cm = logic.getConfigManager();
if (cm != null) {
cm.putSetting(Settings.BLOCKING_MODE, target ? YesNo.YES : YesNo.NO);
changed = changed || (current != target);
var configManager = logic.getConfigManager();
if (configManager == null) return false;
boolean anyChanged = false;
// 1. AE2 原生阻挡模式
if (message.blockingModeOperation != Operation.NOOP) {
boolean current = isBlockingModeEnabled(logic);
boolean target = calculateTargetState(current, message.blockingModeOperation);
configManager.putSetting(Settings.BLOCKING_MODE, target ? YesNo.YES : YesNo.NO);
anyChanged |= (current != target);
}
// 2. 高级阻挡模式
if (message.advancedBlockingOperation != Operation.NOOP) {
boolean current = configManager.getSetting(EAPSettings.ADVANCED_BLOCKING) == YesNo.YES;
boolean target = calculateTargetState(current, message.advancedBlockingOperation);
configManager.putSetting(EAPSettings.ADVANCED_BLOCKING, target ? YesNo.YES : YesNo.NO);
anyChanged |= (current != target);
}
// 3. 智能翻倍模式
if (message.smartDoublingOperation != Operation.NOOP) {
boolean current = configManager.getSetting(EAPSettings.SMART_DOUBLING) == YesNo.YES;
boolean target = calculateTargetState(current, message.smartDoublingOperation);
configManager.putSetting(EAPSettings.SMART_DOUBLING, target ? YesNo.YES : YesNo.NO);
anyChanged |= (current != target);
}
// 有改动时保存并让 AE2 同步到客户端
if (anyChanged) {
try {
logic.saveChanges();
} catch (Throwable ignored) {
}
}
// 2) 高级阻挡mixin 接口
if (msg.opAdvancedBlocking != Op.NOOP && logic instanceof IAdvancedBlocking adv) {
boolean current = adv.eap$getAdvancedBlocking();
boolean target = computeTarget(current, msg.opAdvancedBlocking);
adv.eap$setAdvancedBlocking(target);
changed = changed || (current != target);
}
// 3) 智能翻倍mixin 接口
if (msg.opSmartDoubling != Op.NOOP && logic instanceof ISmartDoubling sd) {
boolean current = sd.eap$getSmartDoubling();
boolean target = computeTarget(current, msg.opSmartDoubling);
sd.eap$setSmartDoubling(target);
changed = changed || (current != target);
}
// 保存更改并让 AE2 同步
if (changed) {
try { logic.saveChanges(); } catch (Throwable ignored) {}
}
return changed;
return anyChanged;
}
private static boolean computeTarget(boolean current, Op op) {
return switch (op) {
/**
* 根据当前状态和操作码计算目标状态
*/
private static boolean calculateTargetState(boolean currentValue, Operation operation) {
return switch (operation) {
case SET_TRUE -> true;
case SET_FALSE -> false;
case TOGGLE -> !current;
default -> current;
case TOGGLE -> !currentValue;
case NOOP -> currentValue;
};
}
private static boolean safeIsBlocking(PatternProviderLogic logic) {
try { return logic.isBlocking(); } catch (Throwable t) { return false; }
/**
* 安全获取 AE2 原生阻挡模式状态防止旧版本抛异常
*/
private static boolean isBlockingModeEnabled(PatternProviderLogic logic) {
try {
return logic.isBlocking();
} catch (Throwable t) {
return false;
}
}
@Override
public Type<? extends CustomPacketPayload> type() {
public @NotNull Type<? extends CustomPacketPayload> type() {
return TYPE;
}
public enum Op {
NOOP((byte) 0),
SET_TRUE((byte) 1),
SET_FALSE((byte) 2),
TOGGLE((byte) 3);
/**
* 操作类型枚举对应客户端发来的 1 byte
*/
public enum Operation {
NOOP((byte) 0), // 不执行任何操作
SET_TRUE((byte) 1), // 强制开启
SET_FALSE((byte) 2), // 强制关闭
TOGGLE((byte) 3); // 切换当前状态
public final byte id;
Op(byte id) {this.id = id;}
Operation(byte id) {
this.id = id;
}
static Op byId(byte id) {
static Operation byId(byte id) {
return switch (id) {
case 1 -> SET_TRUE;
case 2 -> SET_FALSE;
@ -209,4 +264,4 @@ public class GlobalToggleProviderModesC2SPacket implements CustomPacketPayload {
};
}
}
}
}

View File

@ -1,69 +0,0 @@
package com.extendedae_plus.network;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.api.advancedBlocking.IAdvancedBlocking;
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.minecraft.server.level.ServerPlayer;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
/**
* C2S切换高级阻挡模式
* 不含额外负载直接基于玩家当前打开的 PatternProviderMenu 进行切换
*/
public class ToggleAdvancedBlockingC2SPacket implements CustomPacketPayload {
public static final Type<ToggleAdvancedBlockingC2SPacket> TYPE = new Type<>(
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "toggle_adv_blocking"));
public static final ToggleAdvancedBlockingC2SPacket INSTANCE = new ToggleAdvancedBlockingC2SPacket();
public static final StreamCodec<FriendlyByteBuf, ToggleAdvancedBlockingC2SPacket> STREAM_CODEC =
StreamCodec.unit(INSTANCE);
private ToggleAdvancedBlockingC2SPacket() {}
public static void handle(final ToggleAdvancedBlockingC2SPacket msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> {
if (!(ctx.player() instanceof ServerPlayer player)) return;
var containerMenu = player.containerMenu;
if (containerMenu instanceof PatternProviderMenu menu) {
var accessor = (PatternProviderMenuAdvancedAccessor) menu;
var logic = accessor.eap$logic();
if (logic instanceof IAdvancedBlocking 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 IAdvancedBlocking 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();
}
}
});
}
@Override
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
}

View File

@ -1,61 +0,0 @@
package com.extendedae_plus.network;
import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.api.smartDoubling.ISmartDoubling;
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.minecraft.server.level.ServerPlayer;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
/**
* C2S切换智能翻倍启用状态
* 不含额外负载基于玩家当前打开的 PatternProviderMenu 进行切换
*/
public class ToggleSmartDoublingC2SPacket implements CustomPacketPayload {
public static final Type<ToggleSmartDoublingC2SPacket> TYPE = new Type<>(
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "toggle_smart_doubling"));
public static final ToggleSmartDoublingC2SPacket INSTANCE = new ToggleSmartDoublingC2SPacket();
public static final StreamCodec<FriendlyByteBuf, ToggleSmartDoublingC2SPacket> STREAM_CODEC =
StreamCodec.unit(INSTANCE);
private ToggleSmartDoublingC2SPacket() {}
public static void handle(final ToggleSmartDoublingC2SPacket msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> {
if (!(ctx.player() instanceof ServerPlayer player)) return;
var containerMenu = player.containerMenu;
if (containerMenu instanceof PatternProviderMenu menu) {
var accessor = (PatternProviderMenuAdvancedAccessor) menu;
var logic = accessor.eap$logic();
if (logic instanceof ISmartDoubling 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 ISmartDoubling holder) {
boolean current = holder.eap$getSmartDoubling();
boolean next = !current;
holder.eap$setSmartDoubling(next);
logic.saveChanges();
}
}
});
}
@Override
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
}

View File

@ -142,10 +142,10 @@
"gui.tooltips.extendedae_plus.RedstoneControl": "Redstone Control",
"gui.tooltips.extendedae_plus.RedstoneControlEnabled": "Control acceleration with redstone signal",
"gui.tooltips.extendedae_plus.RedstoneControlDisabled": "Ignore redstone signals",
"gui.tooltips.extendedae_plus.advanced_blocking.title": "Smart Blocking",
"gui.tooltips.extendedae_plus.advanced_blocking.enabled": "Enabled: Will not block the same recipe type (requires vanilla blocking mode to be on)",
"gui.tooltips.extendedae_plus.advanced_blocking.disabled": "Disabled: Why not turn on this great feature?",
"gui.tooltips.extendedae_plus.smart_doubling.title": "Smart Doubling",
"gui.tooltips.extendedae_plus.smart_doubling.enabled": "Enabled: Intelligently scales processing patterns based on request amount",
"gui.tooltips.extendedae_plus.smart_doubling.disabled": "Disabled: Distributes according to original pattern count"
"gui.tooltips.extendedae_plus.AdvancedBlocking": "Smart Blocking",
"gui.tooltips.extendedae_plus.AdvancedBlockingEnabled": "Will not block the same recipe type (requires vanilla blocking mode enabled)",
"gui.tooltips.extendedae_plus.AdvancedBlockingDisabled": "Use vanilla blocking logic",
"gui.tooltips.extendedae_plus.SmartDoubling": "Smart Doubling",
"gui.tooltips.extendedae_plus.SmartDoublingEnabled": "Intelligently double processing patterns based on request quantity",
"gui.tooltips.extendedae_plus.SmartDoublingDisabled": "Distribute according to original pattern quantity"
}

View File

@ -141,11 +141,10 @@
"gui.tooltips.extendedae_plus.RedstoneControl": "红石控制",
"gui.tooltips.extendedae_plus.RedstoneControlEnabled": "使用红石信号控制加速",
"gui.tooltips.extendedae_plus.RedstoneControlDisabled": "忽略红石信号",
"gui.tooltips.extendedae_plus.advanced_blocking.title": "智能阻挡",
"gui.tooltips.extendedae_plus.advanced_blocking.enabled": "已启用:对于同一种配方将不再阻挡(需要开启原版的阻挡模式)",
"gui.tooltips.extendedae_plus.advanced_blocking.disabled": "已禁用:这么好的功能为什么不打开呢",
"gui.tooltips.extendedae_plus.smart_doubling.title": "智能翻倍",
"gui.tooltips.extendedae_plus.smart_doubling.enabled": "已启用:根据请求量对处理样板进行智能缩放",
"gui.tooltips.extendedae_plus.smart_doubling.disabled": "已禁用:按原始样板数量进行发配"
"gui.tooltips.extendedae_plus.AdvancedBlocking": "智能阻挡",
"gui.tooltips.extendedae_plus.AdvancedBlockingEnabled": "对于同一种配方将不再阻挡 (需要启用原版阻挡模式)",
"gui.tooltips.extendedae_plus.AdvancedBlockingDisabled": "使用原版阻挡逻辑",
"gui.tooltips.extendedae_plus.SmartDoubling": "智能翻倍",
"gui.tooltips.extendedae_plus.SmartDoublingEnabled": "根据请求量对处理样板进行智能翻倍",
"gui.tooltips.extendedae_plus.SmartDoublingDisabled": "按原始样板数量进行发配"
}

View File

@ -15,6 +15,7 @@
"advancedae.helpers.AdvPatternProviderLogicAdvancedMixin",
"advancedae.helpers.AdvPatternProviderLogicDoublingMixin",
"advancedae.menu.AdvPatternProviderMenuAdvancedMixin",
"advancedae.menu.AdvPatternProviderMenuDoublingMixin",
"ae2.AEProcessingPatternMixin",
"ae2.CraftingCalculationMixin",
"ae2.CraftingCPUClusterMixin",
@ -62,7 +63,7 @@
"PickFromWirelessMixin",
"accessor.AbstractContainerScreenAccessor",
"accessor.ScreenAccessor",
"advancedae.client.gui.AdvPatternProviderScreenMixin",
"advancedae.client.gui.AdvPatternProviderSmartFeaturesMixin",
"advancedae.client.gui.SmallAdvPatternProviderScreenMixin",
"ae2.QuartzCuttingKnifeItemMixin",
"ae2.accessor.AEBaseScreenAccessor",
@ -75,8 +76,8 @@
"ae2.client.gui.PatternEncodingTermScreenMixin",
"ae2.client.gui.PatternEncodingTermUploadMixin",
"ae2.client.gui.PatternProviderCloseMixin",
"ae2.client.gui.PatternProviderScreenMixin",
"ae2.client.gui.PatternProviderScreenUpgradesMixin",
"ae2.client.gui.PatternProviderSmartFeaturesMixin",
"ae2.client.gui.ScreenStyleMixin",
"ae2.client.gui.SlotGridLayoutMixin",
"ae2.menu.CraftConfirmMenuGoBackMixin",