feat: 添加智能系列对高级ae供应器的支持

This commit is contained in:
C-H716 2025-09-20 22:05:01 +08:00
parent 5a9e7bfc7c
commit e45bcf87b0
15 changed files with 675 additions and 36 deletions

View File

@ -162,6 +162,12 @@ dependencies {
// runtimeOnly "mekanism:Mekanism:1.21.1-10.7.0.55" // runtimeOnly "mekanism:Mekanism:1.21.1-10.7.0.55"
runtimeOnly "curse.maven:ex-pattern-provider-892005:6863556" runtimeOnly "curse.maven:ex-pattern-provider-892005:6863556"
//aea
implementation "curse.maven:advancedae-1084104:6921281"
//geckolib
runtimeOnly "curse.maven:geckolib-388172:7009924"
// setup Xei (EMI/REI/JEI) using project property 'use_Xei' // setup Xei (EMI/REI/JEI) using project property 'use_Xei'
switch (project.findProperty('use_Xei') ?: 'emi') { switch (project.findProperty('use_Xei') ?: 'emi') {
case 'emi': case 'emi':

View File

@ -0,0 +1,38 @@
package com.extendedae_plus.mixin.advancedae;
import appeng.api.crafting.IPatternDetails;
import com.extendedae_plus.content.ScaledProcessingPattern;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.List;
/**适配
* Redirect PatternProviderLogic.pushPattern 中对 List.contains 的调用
* 在遇到缩放样板时回退匹配到原始样板实例
*/
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public class AdvPatternProviderLogicContainsRedirectMixin {
@Redirect(method = "pushPattern",
at = @At(
value = "INVOKE",
target = "Ljava/util/List;contains(Ljava/lang/Object;)Z")
)
private boolean eap$patternsContains(List<?> list, Object o) {
try {
if (o instanceof ScaledProcessingPattern scaled) {
IPatternDetails base = scaled.getOriginal();
if (base != null && list.indexOf(base) != -1) {
return true;
}
}
// 使用 indexOf 避免再次触发对 List.contains redirect防止递归
return list.indexOf(o) != -1;
} catch (Throwable t) {
return list.indexOf(o) != -1;
}
}
}

View File

@ -0,0 +1,14 @@
package com.extendedae_plus.mixin.advancedae.accessor;
import appeng.api.crafting.IPatternDetails;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public interface AdvPatternProviderLogicPatternsAccessor {
@Accessor("patterns")
List<IPatternDetails> eap$patterns();
}

View File

@ -0,0 +1,12 @@
package com.extendedae_plus.mixin.advancedae.accessor;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(AdvPatternProviderMenu.class)
public interface AdvPatternProviderMenuAdvancedAccessor {
@Accessor(value = "logic", remap = false)
AdvPatternProviderLogic eap$logic();
}

View File

@ -0,0 +1,139 @@
package com.extendedae_plus.mixin.advancedae.client.gui;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.client.gui.widgets.SettingToggleButton;
import com.extendedae_plus.api.PatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.PatternProviderMenuDoublingSync;
import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket;
import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.pedroksl.advanced_ae.client.gui.AdvPatternProviderScreen;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
import org.checkerframework.checker.units.qual.C;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static com.extendedae_plus.util.ExtendedAELogger.LOGGER;
/**
* 为高级ae样板供应器界面添加高级阻挡模式按钮
* - 位于左侧工具栏
* - 点击仅发送 C2S 切换请求状态由 AE2 @GuiSync 回传决定
*/
@Mixin(AdvPatternProviderScreen.class)
public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen<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(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
super((AdvPatternProviderMenu) 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 PatternProviderMenuAdvancedSync 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 PatternProviderMenuDoublingSync sync2) {
this.eap$SmartDoublingEnabled = sync2.eap$getSmartDoublingSynced();
}
} catch (Throwable t) {
LOGGER.error("Error initializing smart doubling sync", t);
}
this.eap$SmartDoublingToggle = new SettingToggleButton<>(
Settings.BLOCKING_MODE,
this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO,
(btn, backwards) -> {
var conn = Minecraft.getInstance().getConnection();
if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE);
}
) {
@Override
public java.util.List<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 PatternProviderMenuAdvancedSync sync) {
desired = sync.eap$getAdvancedBlockingSynced();
}
this.eap$AdvancedBlockingEnabled = desired;
this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO);
}
if (this.eap$SmartDoublingToggle != null) {
boolean desired2 = this.eap$SmartDoublingEnabled;
if (this.menu instanceof PatternProviderMenuDoublingSync sync2) {
desired2 = sync2.eap$getSmartDoublingSynced();
}
this.eap$SmartDoublingEnabled = desired2;
this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO);
}
}
}

View File

@ -0,0 +1,139 @@
package com.extendedae_plus.mixin.advancedae.client.gui;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.client.gui.widgets.SettingToggleButton;
import com.extendedae_plus.api.PatternProviderMenuAdvancedSync;
import com.extendedae_plus.api.PatternProviderMenuDoublingSync;
import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket;
import com.extendedae_plus.network.ToggleSmartDoublingC2SPacket;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.pedroksl.advanced_ae.client.gui.SmallAdvPatternProviderScreen;
import net.pedroksl.advanced_ae.gui.advpatternprovider.SmallAdvPatternProviderMenu;
import org.checkerframework.checker.units.qual.C;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static com.extendedae_plus.util.ExtendedAELogger.LOGGER;
/**
* 为高级ae样板供应器界面添加高级阻挡模式按钮
* - 位于左侧工具栏
* - 点击仅发送 C2S 切换请求状态由 AE2 @GuiSync 回传决定
*/
@Mixin(SmallAdvPatternProviderScreen.class)
public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<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;
public SmallAdvPatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
super((SmallAdvPatternProviderMenu) menu, playerInventory, title, style);
}
@Inject(method = "<init>", at = @At("RETURN"))
private void eap$initAdvancedBlocking(SmallAdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
// 使用 @GuiSync 初始化
try {
if (menu instanceof PatternProviderMenuAdvancedSync sync) {
this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced();
}
} catch (Throwable t) {
LOGGER.error("Error initializing advanced sync", t);
}
// 使用 SettingToggleButton<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 PatternProviderMenuDoublingSync sync2) {
this.eap$SmartDoublingEnabled = sync2.eap$getSmartDoublingSynced();
}
} catch (Throwable t) {
LOGGER.error("Error initializing smart doubling sync", t);
}
this.eap$SmartDoublingToggle = new SettingToggleButton<>(
Settings.BLOCKING_MODE,
this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO,
(btn, backwards) -> {
var conn = Minecraft.getInstance().getConnection();
if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE);
}
) {
@Override
public java.util.List<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 PatternProviderMenuAdvancedSync sync) {
desired = sync.eap$getAdvancedBlockingSynced();
}
this.eap$AdvancedBlockingEnabled = desired;
this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO);
}
if (this.eap$SmartDoublingToggle != null) {
boolean desired2 = this.eap$SmartDoublingEnabled;
if (this.menu instanceof PatternProviderMenuDoublingSync sync2) {
desired2 = sync2.eap$getSmartDoublingSynced();
}
this.eap$SmartDoublingEnabled = desired2;
this.eap$SmartDoublingToggle.set(desired2 ? YesNo.YES : YesNo.NO);
}
}
}

View File

@ -0,0 +1,94 @@
package com.extendedae_plus.mixin.advancedae.helpers;
import appeng.api.crafting.IPatternDetails;
import appeng.api.crafting.IPatternDetails.IInput;
import appeng.api.stacks.AEKey;
import appeng.api.stacks.GenericStack;
import appeng.helpers.patternprovider.PatternProviderTarget;
import com.extendedae_plus.api.AdvancedBlockingHolder;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public class AdvPatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder {
@Unique
private static final String EAP_ADV_BLOCKING_KEY = "eap_advanced_blocking";
@Unique
private boolean eap$advancedBlocking = false;
@Override
public boolean eap$getAdvancedBlocking() {
return eap$advancedBlocking;
}
@Override
public void eap$setAdvancedBlocking(boolean value) {
this.eap$advancedBlocking = value;
}
@Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$writeAdvancedToNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
tag.putBoolean(EAP_ADV_BLOCKING_KEY, this.eap$advancedBlocking);
}
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$readAdvancedFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
if (tag.contains(EAP_ADV_BLOCKING_KEY)) {
this.eap$advancedBlocking = tag.getBoolean(EAP_ADV_BLOCKING_KEY);
}
}
// pushPattern 重定向对 adapter.containsPatternInput(...) 的调用
@Redirect(method = "pushPattern", at = @At(value = "INVOKE", target = "Lappeng/helpers/patternprovider/PatternProviderTarget;containsPatternInput(Ljava/util/Set;)Z"))
private boolean eap$redirectBlockingContains(PatternProviderTarget adapter,
java.util.Set<AEKey> patternInputs,
IPatternDetails patternDetails,
appeng.api.stacks.KeyCounter[] inputHolder) {
// 原版是否打开阻挡
boolean vanillaBlocking = ((AdvPatternProviderLogic)(Object)this).isBlocking();
if (!vanillaBlocking) {
return adapter.containsPatternInput(patternInputs);
}
// 仅当高级阻挡启用时启用匹配则不阻挡
if (this.eap$advancedBlocking) {
if (eap$targetFullyMatchesPatternInputs(adapter, patternDetails)) {
// 返回 false 表示不包含阻挡关键物从而不触发 continue允许发配
return false;
}
}
// 否则使用原判定
return adapter.containsPatternInput(patternInputs);
}
@Unique
private boolean eap$targetFullyMatchesPatternInputs(PatternProviderTarget adapter, IPatternDetails patternDetails) {
for (IInput in : patternDetails.getInputs()) {
boolean slotMatched = false;
for (GenericStack candidate : in.getPossibleInputs()) {
AEKey key = candidate.what().dropSecondary();
if (adapter.containsPatternInput(Collections.singleton(key))) {
slotMatched = true;
break;
}
}
if (!slotMatched) {
return false; // 任一输入槽未匹配则失败
}
}
return true; // 每个输入槽都至少匹配了一个候选输入
}
@Shadow public void saveChanges() {}
}

View File

@ -0,0 +1,76 @@
package com.extendedae_plus.mixin.advancedae.helpers;
import appeng.api.crafting.IPatternDetails;
import appeng.crafting.pattern.AEProcessingPattern;
import com.extendedae_plus.api.SmartDoublingAwarePattern;
import com.extendedae_plus.api.SmartDoublingHolder;
import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderLogicPatternsAccessor;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public class AdvPatternProviderLogicDoublingMixin implements SmartDoublingHolder {
@Unique
private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling";
@Unique
private boolean eap$smartDoubling = false;
@Override
public boolean eap$getSmartDoubling() {
return eap$smartDoubling;
}
@Override
public void eap$setSmartDoubling(boolean value) {
this.eap$smartDoubling = value;
// 立即将开关状态应用到当前 Provider 的样板上避免等待下一次 updatePatterns
try {
var list = ((AdvPatternProviderLogicPatternsAccessor) this).eap$patterns();
for (IPatternDetails details : list) {
if (details instanceof AEProcessingPattern proc && proc instanceof SmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(value);
}
}
// 触发一次刷新让网络及时拿到最新状态也会触发 ICraftingProvider.requestUpdate(mainNode)
((AdvPatternProviderLogic) (Object) this).updatePatterns();
} catch (Throwable ignored) {
}
}
@Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$writeSmartDoublingToNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling);
}
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$readSmartDoublingFromNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) {
if (tag.contains(EAP_SMART_DOUBLING_KEY)) {
this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY);
}
}
@Inject(method = "updatePatterns", at = @At("TAIL"))
private void eap$applySmartDoublingToPatterns(CallbackInfo ci) {
try {
var list = ((AdvPatternProviderLogicPatternsAccessor) this).eap$patterns();
boolean allow = this.eap$smartDoubling;
for (IPatternDetails details : list) {
if (details instanceof AEProcessingPattern proc && proc instanceof SmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allow);
}
}
} catch (Throwable ignored) {
}
}
@Shadow
public void saveChanges() {}
}

View File

@ -0,0 +1,43 @@
package com.extendedae_plus.mixin.advancedae.menu;
import appeng.menu.AEBaseMenu;
import appeng.menu.guisync.GuiSync;
import com.extendedae_plus.api.AdvancedBlockingHolder;
import com.extendedae_plus.api.PatternProviderMenuAdvancedSync;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(AdvPatternProviderMenu.class)
public abstract class AdvPatternProviderMenuAdvancedMixin implements PatternProviderMenuAdvancedSync {
@Final
@Shadow(remap = false)
protected AdvPatternProviderLogic logic;
// 选择一个未占用的 GUI 同步 idAE2 已用到 7这里使用 21 以避冲突
@Unique
@GuiSync(22)
public boolean eap$AdvancedBlocking = false;
@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 AdvancedBlockingHolder holder) {
this.eap$AdvancedBlocking = holder.eap$getAdvancedBlocking();
}
}
}
@Override
public boolean eap$getAdvancedBlockingSynced() {
return this.eap$AdvancedBlocking;
}
}

View File

@ -0,0 +1,41 @@
package com.extendedae_plus.mixin.advancedae.menu;
import appeng.menu.AEBaseMenu;
import appeng.menu.guisync.GuiSync;
import com.extendedae_plus.api.PatternProviderMenuDoublingSync;
import com.extendedae_plus.api.SmartDoublingHolder;
import net.pedroksl.advanced_ae.common.logic.AdvPatternProviderLogic;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(AdvPatternProviderMenu.class)
public abstract class AdvPatternProviderMenuDoublingMixin implements PatternProviderMenuDoublingSync {
@Final
@Shadow(remap = false)
protected AdvPatternProviderLogic logic;
@Unique
@GuiSync(23)
public boolean eap$SmartDoubling = false;
@Inject(method = "broadcastChanges", at = @At("HEAD"))
private void eap$syncSmartDoubling(CallbackInfo ci) {
if (!((AEBaseMenu) (Object) this).isClientSide()) {
var l = this.logic;
if (l instanceof SmartDoublingHolder holder) {
this.eap$SmartDoubling = holder.eap$getSmartDoubling();
}
}
}
@Override
public boolean eap$getSmartDoublingSynced() {
return this.eap$SmartDoubling;
}
}

View File

@ -8,7 +8,6 @@ import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderTarget; import appeng.helpers.patternprovider.PatternProviderTarget;
import com.extendedae_plus.api.AdvancedBlockingHolder; import com.extendedae_plus.api.AdvancedBlockingHolder;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@ -22,7 +21,7 @@ import java.util.Collections;
@Mixin(value = PatternProviderLogic.class, remap = false) @Mixin(value = PatternProviderLogic.class, remap = false)
public class PatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder { public class PatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder {
@Unique @Unique
private static final String EPP_ADV_BLOCKING_KEY = "epp_advanced_blocking"; private static final String EAP_ADV_BLOCKING_KEY = "epp_advanced_blocking";
@Unique @Unique
private boolean eap$advancedBlocking = false; private boolean eap$advancedBlocking = false;
@ -39,13 +38,13 @@ public class PatternProviderLogicAdvancedMixin implements AdvancedBlockingHolder
@Inject(method = "writeToNBT", at = @At("TAIL")) @Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$writeAdvancedToNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { private void eap$writeAdvancedToNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
tag.putBoolean(EPP_ADV_BLOCKING_KEY, this.eap$advancedBlocking); tag.putBoolean(EAP_ADV_BLOCKING_KEY, this.eap$advancedBlocking);
} }
@Inject(method = "readFromNBT", at = @At("TAIL")) @Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$readAdvancedFromNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { private void eap$readAdvancedFromNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
if (tag.contains(EPP_ADV_BLOCKING_KEY)) { if (tag.contains(EAP_ADV_BLOCKING_KEY)) {
this.eap$advancedBlocking = tag.getBoolean(EPP_ADV_BLOCKING_KEY); this.eap$advancedBlocking = tag.getBoolean(EAP_ADV_BLOCKING_KEY);
} }
} }

View File

@ -7,7 +7,6 @@ import com.extendedae_plus.api.SmartDoublingAwarePattern;
import com.extendedae_plus.api.SmartDoublingHolder; import com.extendedae_plus.api.SmartDoublingHolder;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicPatternsAccessor; import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicPatternsAccessor;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@ -18,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = PatternProviderLogic.class, remap = false) @Mixin(value = PatternProviderLogic.class, remap = false)
public class PatternProviderLogicDoublingMixin implements SmartDoublingHolder { public class PatternProviderLogicDoublingMixin implements SmartDoublingHolder {
@Unique @Unique
private static final String EPP_SMART_DOUBLING_KEY = "epp_smart_doubling"; private static final String EAP_SMART_DOUBLING_KEY = "epp_smart_doubling";
@Unique @Unique
private boolean eap$smartDoubling = false; private boolean eap$smartDoubling = false;
@ -47,13 +46,13 @@ public class PatternProviderLogicDoublingMixin implements SmartDoublingHolder {
@Inject(method = "writeToNBT", at = @At("TAIL")) @Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$writeSmartDoublingToNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { private void eap$writeSmartDoublingToNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
tag.putBoolean(EPP_SMART_DOUBLING_KEY, this.eap$smartDoubling); tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling);
} }
@Inject(method = "readFromNBT", at = @At("TAIL")) @Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$readSmartDoublingFromNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { private void eap$readSmartDoublingFromNbt(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
if (tag.contains(EPP_SMART_DOUBLING_KEY)) { if (tag.contains(EAP_SMART_DOUBLING_KEY)) {
this.eap$smartDoubling = tag.getBoolean(EPP_SMART_DOUBLING_KEY); this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY);
} }
} }

View File

@ -1,17 +1,19 @@
package com.extendedae_plus.network; package com.extendedae_plus.network;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.menu.implementations.PatternProviderMenu; import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.api.AdvancedBlockingHolder;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor;
import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.api.AdvancedBlockingHolder;
import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import appeng.api.config.Settings; import net.neoforged.neoforge.network.handling.IPayloadContext;
import appeng.api.config.YesNo; import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
/** /**
* C2S切换高级阻挡模式 * C2S切换高级阻挡模式
@ -36,16 +38,31 @@ public class ToggleAdvancedBlockingC2SPacket implements CustomPacketPayload {
public static void handle(final ToggleAdvancedBlockingC2SPacket msg, final IPayloadContext ctx) { public static void handle(final ToggleAdvancedBlockingC2SPacket msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> { ctx.enqueueWork(() -> {
if (!(ctx.player() instanceof ServerPlayer player)) return; if (!(ctx.player() instanceof ServerPlayer player)) return;
if (!(player.containerMenu instanceof PatternProviderMenu menu)) return; var containerMenu = player.containerMenu;
if (containerMenu instanceof PatternProviderMenu menu) {
var accessor = (PatternProviderMenuAdvancedAccessor) menu; var accessor = (PatternProviderMenuAdvancedAccessor) menu;
var logic = accessor.eap$logic(); var logic = accessor.eap$logic();
if (logic instanceof AdvancedBlockingHolder holder) { if (logic instanceof AdvancedBlockingHolder holder) {
boolean next = !holder.eap$getAdvancedBlocking(); boolean current = holder.eap$getAdvancedBlocking();
holder.eap$setAdvancedBlocking(next); boolean next = !current;
// 自动开启原版阻挡 holder.eap$setAdvancedBlocking(next);
logic.getConfigManager().putSetting(Settings.BLOCKING_MODE, YesNo.YES); // 自动开启原版阻挡
logic.saveChanges(); logic.getConfigManager().putSetting(Settings.BLOCKING_MODE, YesNo.YES);
// 保存并触发 AE2 的菜单 @GuiSync 广播到所有观看该菜单的玩家
logic.saveChanges();
}
}else if (containerMenu instanceof AdvPatternProviderMenu menu){
var accessor = (AdvPatternProviderMenuAdvancedAccessor) menu;
var logic = accessor.eap$logic();
if (logic instanceof AdvancedBlockingHolder holder) {
boolean current = holder.eap$getAdvancedBlocking();
boolean next = !current;
holder.eap$setAdvancedBlocking(next);
// 自动开启原版阻挡
logic.getConfigManager().putSetting(Settings.BLOCKING_MODE, YesNo.YES);
// 保存并触发 AE2 的菜单 @GuiSync 广播到所有观看该菜单的玩家
logic.saveChanges();
}
} }
}); });
} }

View File

@ -1,15 +1,17 @@
package com.extendedae_plus.network; package com.extendedae_plus.network;
import appeng.menu.implementations.PatternProviderMenu; import appeng.menu.implementations.PatternProviderMenu;
import com.extendedae_plus.api.SmartDoublingHolder;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor;
import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.api.SmartDoublingHolder;
import com.extendedae_plus.mixin.advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.pedroksl.advanced_ae.gui.advpatternprovider.AdvPatternProviderMenu;
/** /**
* C2S切换智能翻倍启用状态 * C2S切换智能翻倍启用状态
@ -34,14 +36,25 @@ public class ToggleSmartDoublingC2SPacket implements CustomPacketPayload {
public static void handle(final ToggleSmartDoublingC2SPacket msg, final IPayloadContext ctx) { public static void handle(final ToggleSmartDoublingC2SPacket msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> { ctx.enqueueWork(() -> {
if (!(ctx.player() instanceof ServerPlayer player)) return; if (!(ctx.player() instanceof ServerPlayer player)) return;
if (!(player.containerMenu instanceof PatternProviderMenu menu)) return; var containerMenu = player.containerMenu;
if (containerMenu instanceof PatternProviderMenu menu) {
var accessor = (PatternProviderMenuAdvancedAccessor) menu; var accessor = (PatternProviderMenuAdvancedAccessor) menu;
var logic = accessor.eap$logic(); var logic = accessor.eap$logic();
if (logic instanceof SmartDoublingHolder holder) { if (logic instanceof SmartDoublingHolder holder) {
boolean next = !holder.eap$getSmartDoubling(); boolean current = holder.eap$getSmartDoubling();
holder.eap$setSmartDoubling(next); boolean next = !current;
logic.saveChanges(); holder.eap$setSmartDoubling(next);
logic.saveChanges();
}
}else if (containerMenu instanceof AdvPatternProviderMenu menu){
var accessor = (AdvPatternProviderMenuAdvancedAccessor) menu;
var logic = accessor.eap$logic();
if (logic instanceof SmartDoublingHolder holder) {
boolean current = holder.eap$getSmartDoubling();
boolean next = !current;
holder.eap$setSmartDoubling(next);
logic.saveChanges();
}
} }
}); });
} }

View File

@ -3,6 +3,13 @@
"package": "com.extendedae_plus.mixin", "package": "com.extendedae_plus.mixin",
"compatibilityLevel": "JAVA_21", "compatibilityLevel": "JAVA_21",
"mixins": [ "mixins": [
"advancedae.AdvPatternProviderLogicContainsRedirectMixin",
"advancedae.accessor.AdvPatternProviderLogicPatternsAccessor",
"advancedae.accessor.AdvPatternProviderMenuAdvancedAccessor",
"advancedae.helpers.AdvPatternProviderLogicAdvancedMixin",
"advancedae.helpers.AdvPatternProviderLogicDoublingMixin",
"advancedae.menu.AdvPatternProviderMenuAdvancedMixin",
"advancedae.menu.AdvPatternProviderMenuDoublingMixin",
"ae2.AEProcessingPatternMixin", "ae2.AEProcessingPatternMixin",
"ae2.CraftingCalculationMixin", "ae2.CraftingCalculationMixin",
"ae2.CraftingCPUClusterMixin", "ae2.CraftingCPUClusterMixin",
@ -37,6 +44,8 @@
"PickFromWirelessMixin", "PickFromWirelessMixin",
"accessor.AbstractContainerScreenAccessor", "accessor.AbstractContainerScreenAccessor",
"accessor.ScreenAccessor", "accessor.ScreenAccessor",
"advancedae.client.gui.AdvPatternProviderScreenMixin",
"advancedae.client.gui.SmallAdvPatternProviderScreenMixin",
"ae2.accessor.AEBaseScreenAccessor", "ae2.accessor.AEBaseScreenAccessor",
"ae2.accessor.AEBaseScreenInvoker", "ae2.accessor.AEBaseScreenInvoker",
"ae2.accessor.MEStorageScreenAccessor", "ae2.accessor.MEStorageScreenAccessor",