扩展样板供应器完成
This commit is contained in:
parent
d056ee43a9
commit
5ae5e7a950
14
build.gradle
14
build.gradle
|
|
@ -127,8 +127,10 @@ sourceSets.main.resources { srcDir 'src/generated/resources' }
|
|||
|
||||
// 暂时排除缺少依赖的可选联动源码,待补齐依赖后再启用
|
||||
sourceSets.main.java {
|
||||
// 让编译期能解析 ExtendedAE 的类(如 GuiExPatternProvider、ActionEPPButton 等),仅作编译期源引用
|
||||
// 运行期仍由 CurseMaven 依赖提供真实模组 Jar
|
||||
srcDir 'othermods/ExtendedAE-1.21-2.2.21-neoforge/src/main/java'
|
||||
// 广泛屏蔽迁移中的旧源码,仅保留模板核心类(ExtendedAEPlus、ExtendedAEPlusClient、Config)
|
||||
exclude 'com/extendedae_plus/NewIcon.java'
|
||||
// 注意:不要屏蔽 api/**,我们有选择性 include 的接口文件需要参与编译
|
||||
include 'com/extendedae_plus/api/**'
|
||||
exclude 'com/extendedae_plus/client/**'
|
||||
|
|
@ -146,10 +148,16 @@ sourceSets.main.java {
|
|||
include 'com/extendedae_plus/mixin/ae2/accessor/**'
|
||||
// 启用对 PatternProviderLogic 的功能混入(高级阻挡/智能翻倍开关的持久化与逻辑)
|
||||
include 'com/extendedae_plus/mixin/ae2/helpers/**'
|
||||
// 启用 AEProcessingPattern 的 mixin(提供可缩放标记)
|
||||
include 'com/extendedae_plus/mixin/ae2/AEProcessingPatternMixin.java'
|
||||
// GUI 方案A:解禁最小 GUI 混入
|
||||
include 'com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenMixin.java'
|
||||
include 'com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuAdvancedMixin.java'
|
||||
include 'com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuDoublingMixin.java'
|
||||
// ExtendedAE GUI 混入(右侧外列按钮与翻页),以及其依赖的 NewIcon 类
|
||||
// 仅包含 Provider GUI 混入(不要使用广域 exclude,以免覆盖 include)
|
||||
include 'com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternProviderMixin.java'
|
||||
include 'com/extendedae_plus/NewIcon.java'
|
||||
// 注意:不要屏蔽 network/**,我们已选择性 include 需要的网络文件
|
||||
// 仅解禁样板倍增核心所需的两个 util 文件
|
||||
include 'com/extendedae_plus/util/PatternProviderDataUtil.java'
|
||||
|
|
@ -161,6 +169,7 @@ sourceSets.main.java {
|
|||
include 'com/extendedae_plus/network/ModNetwork.java'
|
||||
include 'com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java'
|
||||
include 'com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java'
|
||||
include 'com/extendedae_plus/network/ScalePatternsC2SPacket.java'
|
||||
// 仅 include 需要的 util 文件(不再对 util/** 做全局排除,以免误伤)
|
||||
include 'com/extendedae_plus/util/PatternProviderDataUtil.java'
|
||||
include 'com/extendedae_plus/util/PatternProviderUIHelper.java'
|
||||
|
|
@ -205,9 +214,9 @@ dependencies {
|
|||
implementation "org.appliedenergistics:guideme:2.5.1"
|
||||
// jarJar configuration not set in this build; use implementation for API for now
|
||||
implementation "de.mari_023:ae2wtlib_api:19.2.0"
|
||||
implementation "curse.maven:ex-pattern-provider-892005:6863556"
|
||||
implementation "curse.maven:curios-309927:6529130"
|
||||
|
||||
compileOnly "curse.maven:ex-pattern-provider-892005:6863556"
|
||||
compileOnly "curse.maven:applied-flux-965012:5614830"
|
||||
compileOnly "dev.emi:emi-neoforge:1.1.10+1.21"
|
||||
compileOnly "curse.maven:mega-cells-622112:6005043"
|
||||
|
|
@ -229,6 +238,7 @@ dependencies {
|
|||
runtimeOnly "curse.maven:jade-324717:5427817"
|
||||
runtimeOnly "curse.maven:mega-cells-622112:6005043"
|
||||
runtimeOnly "mekanism:Mekanism:1.21.1-10.7.0.55"
|
||||
runtimeOnly "curse.maven:ex-pattern-provider-892005:6863556"
|
||||
|
||||
// setup Xei (EMI/REI/JEI) using project property 'use_Xei'
|
||||
switch (project.findProperty('use_Xei') ?: 'emi') {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ import net.minecraft.resources.ResourceLocation;
|
|||
|
||||
public class NewIcon {
|
||||
@SuppressWarnings("all")
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(ExtendedAEPlus.MODID,"textures/gui/nicons.png");
|
||||
// 贴图当前存放于 assets/extendedae_plus/textures/gui/nicons.png
|
||||
// 与 MODID (extendedaeplus) 不同,因此这里直接指定贴图所在命名空间
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath("extendedae_plus", "textures/gui/nicons.png");
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ import com.extendedae_plus.config.ModConfigs;
|
|||
import com.glodblock.github.extendedae.client.button.ActionEPPButton;
|
||||
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
|
||||
import com.glodblock.github.extendedae.container.ContainerExPatternProvider;
|
||||
import com.glodblock.github.extendedae.network.EPPNetworkHandler;
|
||||
import com.glodblock.github.glodium.network.packet.CGenericPacket;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import com.extendedae_plus.network.ScalePatternsC2SPacket;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
|
@ -196,34 +196,40 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
|
|||
this.addToLeftToolbar(this.prevPage);
|
||||
}
|
||||
|
||||
// 倍增/除法按钮,通过 ExtendedAE 的通用包派发
|
||||
// 倍增/除法按钮:使用自有 C2S 包发送到服务端执行样板缩放
|
||||
this.x2Button = new ActionEPPButton((b) -> {
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply2"));
|
||||
var conn = Minecraft.getInstance().getConnection();
|
||||
if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.MUL2));
|
||||
}, NewIcon.MULTIPLY2);
|
||||
this.x2Button.setVisibility(true);
|
||||
|
||||
this.divideBy2Button = new ActionEPPButton((b) -> {
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide2"));
|
||||
var conn = Minecraft.getInstance().getConnection();
|
||||
if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.DIV2));
|
||||
}, NewIcon.DIVIDE2);
|
||||
this.divideBy2Button.setVisibility(true);
|
||||
|
||||
this.x10Button = new ActionEPPButton((b) -> {
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply10"));
|
||||
var conn = Minecraft.getInstance().getConnection();
|
||||
if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.MUL10));
|
||||
}, NewIcon.MULTIPLY10);
|
||||
this.x10Button.setVisibility(true);
|
||||
|
||||
this.divideBy10Button = new ActionEPPButton((b) -> {
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide10"));
|
||||
var conn = Minecraft.getInstance().getConnection();
|
||||
if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.DIV10));
|
||||
}, NewIcon.DIVIDE10);
|
||||
this.divideBy10Button.setVisibility(true);
|
||||
|
||||
this.divideBy5Button = new ActionEPPButton((b) -> {
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide5"));
|
||||
var conn = Minecraft.getInstance().getConnection();
|
||||
if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.DIV5));
|
||||
}, NewIcon.DIVIDE5);
|
||||
this.divideBy5Button.setVisibility(true);
|
||||
|
||||
this.x5Button = new ActionEPPButton((b) -> {
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply5"));
|
||||
var conn = Minecraft.getInstance().getConnection();
|
||||
if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.MUL5));
|
||||
}, NewIcon.MULTIPLY5);
|
||||
this.x5Button.setVisibility(true);
|
||||
|
||||
|
|
@ -357,119 +363,7 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在服务器端执行样板缩放操作(单机模式)
|
||||
*/
|
||||
@Unique
|
||||
private void executePatternScalingOnServer(net.minecraft.server.level.ServerPlayer serverPlayer, String scalingType, double scaleFactor) {
|
||||
try {
|
||||
// 将实际逻辑切换到服务端主线程执行,避免跨线程访问导致读取到空库存
|
||||
serverPlayer.getServer().execute(() -> {
|
||||
try {
|
||||
// 直接基于容器槽位操作,完全绕开 PatternProviderLogic 及其内部字段
|
||||
if (!(serverPlayer.containerMenu instanceof com.glodblock.github.extendedae.container.ContainerExPatternProvider exMenu)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int scaled = 0;
|
||||
int failed = 0;
|
||||
int total = 0;
|
||||
final int scale = (int) Math.round(scaleFactor);
|
||||
final boolean div = !"MULTIPLY".equals(scalingType);
|
||||
|
||||
java.util.List<net.minecraft.world.inventory.Slot> slots = exMenu.getSlots(appeng.menu.SlotSemantics.ENCODED_PATTERN);
|
||||
for (var slot : slots) {
|
||||
var stack = slot.getItem();
|
||||
if (stack.getItem() instanceof appeng.crafting.pattern.EncodedPatternItem patternItem) {
|
||||
total++;
|
||||
var detail = patternItem.decode(stack, serverPlayer.level(), false);
|
||||
if (detail instanceof appeng.crafting.pattern.AEProcessingPattern process) {
|
||||
var input = process.getSparseInputs();
|
||||
var output = process.getOutputs();
|
||||
|
||||
// 检查是否可修改(来源:ExtendedAE ContainerPatternModifier.checkModify)
|
||||
if (checkModifyLikeExtendedAE(input, scale, div) && checkModifyLikeExtendedAE(output, scale, div)) {
|
||||
var mulInput = new appeng.api.stacks.GenericStack[input.length];
|
||||
var mulOutput = new appeng.api.stacks.GenericStack[output.length];
|
||||
modifyStacksLikeExtendedAE(input, mulInput, scale, div);
|
||||
modifyStacksLikeExtendedAE(output, mulOutput, scale, div);
|
||||
var newPattern = appeng.api.crafting.PatternDetailsHelper.encodeProcessingPattern(mulInput, mulOutput);
|
||||
if (slot instanceof appeng.menu.slot.AppEngSlot as) {
|
||||
as.set(newPattern);
|
||||
} else {
|
||||
slot.set(newPattern);
|
||||
}
|
||||
scaled++;
|
||||
} else {
|
||||
failed++;
|
||||
}
|
||||
} else {
|
||||
// 非处理样板:跳过
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构造结果并回显
|
||||
String message;
|
||||
if (scaled == 0) {
|
||||
message = String.format(
|
||||
"ℹ️ ExtendedAE Plus: 样板%s完成,但未处理任何样板。共发现 %d 个样板,失败 %d 个(可能全为合成样板或数量不满足条件)",
|
||||
div ? "除法" : "倍增", total, failed);
|
||||
} else if (failed > 0) {
|
||||
message = String.format("✅ ExtendedAE Plus: 样板%s完成!处理了 %d 个,跳过 %d 个", div ? "除法" : "倍增", scaled, failed);
|
||||
} else {
|
||||
message = String.format("✅ ExtendedAE Plus: 样板%s成功!处理了 %d 个", div ? "除法" : "倍增", scaled);
|
||||
}
|
||||
|
||||
var minecraft = net.minecraft.client.Minecraft.getInstance();
|
||||
if (minecraft.player != null) {
|
||||
minecraft.player.displayClientMessage(net.minecraft.network.chat.Component.literal(message), true);
|
||||
}
|
||||
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private boolean checkModifyLikeExtendedAE(appeng.api.stacks.GenericStack[] stacks, int scale, boolean div) {
|
||||
if (div) {
|
||||
for (var stack : stacks) {
|
||||
if (stack != null) {
|
||||
if (stack.amount() % scale != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var stack : stacks) {
|
||||
if (stack != null) {
|
||||
long upper = 999999L * stack.what().getAmountPerUnit();
|
||||
if (stack.amount() * scale > upper) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void modifyStacksLikeExtendedAE(appeng.api.stacks.GenericStack[] stacks,
|
||||
appeng.api.stacks.GenericStack[] des,
|
||||
int scale,
|
||||
boolean div) {
|
||||
for (int i = 0; i < stacks.length; i++) {
|
||||
if (stacks[i] != null) {
|
||||
long amt = div ? stacks[i].amount() / scale : stacks[i].amount() * scale;
|
||||
des[i] = new appeng.api.stacks.GenericStack(stacks[i].what(), amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 本文件原包含本地样板缩放实现(单机模式)和 ExtendedAE 网络派发,已移除以兼容 1.21.1 与最小可构建集。
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -9,5 +9,6 @@ public class ModNetwork {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
package com.extendedae_plus.network;
|
||||
|
||||
import appeng.helpers.patternprovider.PatternProviderLogic;
|
||||
import appeng.menu.implementations.PatternProviderMenu;
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor;
|
||||
import com.extendedae_plus.util.ExtendedAELogger;
|
||||
import com.extendedae_plus.util.PatternProviderDataUtil;
|
||||
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;
|
||||
|
||||
/**
|
||||
* C2S:请求对当前打开的样板供应器执行样板数量缩放(倍增或除法)。
|
||||
*/
|
||||
public class ScalePatternsC2SPacket implements CustomPacketPayload {
|
||||
public enum Operation {
|
||||
MUL2, DIV2, MUL5, DIV5, MUL10, DIV10
|
||||
}
|
||||
|
||||
public static final Type<ScalePatternsC2SPacket> TYPE = new Type<>(
|
||||
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "scale_patterns"));
|
||||
|
||||
public static final StreamCodec<FriendlyByteBuf, ScalePatternsC2SPacket> STREAM_CODEC = StreamCodec.of(
|
||||
(buf, pkt) -> buf.writeEnum(pkt.op),
|
||||
buf -> new ScalePatternsC2SPacket(buf.readEnum(Operation.class))
|
||||
);
|
||||
|
||||
private final Operation op;
|
||||
|
||||
public ScalePatternsC2SPacket(Operation op) {
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
public Operation op() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public static void handle(final ScalePatternsC2SPacket msg, final IPayloadContext ctx) {
|
||||
ctx.enqueueWork(() -> {
|
||||
if (!(ctx.player() instanceof ServerPlayer player)) return;
|
||||
if (!(player.containerMenu instanceof PatternProviderMenu menu)) return;
|
||||
|
||||
try {
|
||||
var accessor = (PatternProviderMenuAdvancedAccessor) menu;
|
||||
PatternProviderLogic logic = accessor.eap$logic();
|
||||
if (logic == null) return;
|
||||
|
||||
double factor;
|
||||
boolean multiply;
|
||||
switch (msg.op) {
|
||||
case MUL2 -> { factor = 2.0; multiply = true; }
|
||||
case DIV2 -> { factor = 2.0; multiply = false; }
|
||||
case MUL5 -> { factor = 5.0; multiply = true; }
|
||||
case DIV5 -> { factor = 5.0; multiply = false; }
|
||||
case MUL10 -> { factor = 10.0; multiply = true; }
|
||||
case DIV10 -> { factor = 10.0; multiply = false; }
|
||||
default -> { return; }
|
||||
}
|
||||
|
||||
PatternProviderDataUtil.PatternScalingResult result;
|
||||
if (multiply) {
|
||||
result = PatternProviderDataUtil.multiplyPatternAmounts(logic, factor);
|
||||
} else {
|
||||
result = PatternProviderDataUtil.dividePatternAmounts(logic, factor);
|
||||
}
|
||||
|
||||
logic.saveChanges();
|
||||
|
||||
// 回显结果到玩家
|
||||
String summary = String.format("样板缩放(%s x%.0f): 共%d, 成功%d, 失败%d", multiply ? "倍增" : "除法",
|
||||
factor, result.getTotalPatterns(), result.getScaledPatterns(), result.getFailedPatterns());
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.literal("[EAP] " + summary), true);
|
||||
|
||||
for (String err : result.getErrors()) {
|
||||
ExtendedAELogger.LOGGER.debug("[EAP] scale error: {}", err);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
ExtendedAELogger.LOGGER.error("[EAP] Handle ScalePatternsC2SPacket failed", t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,15 @@
|
|||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"ae2.accessor.PatternProviderLogicAccessor",
|
||||
"ae2.accessor.PatternProviderLogicPatternsAccessor",
|
||||
"ae2.accessor.PatternProviderMenuAdvancedAccessor",
|
||||
"ae2.client.gui.PatternProviderScreenMixin",
|
||||
"ae2.menu.PatternProviderMenuAdvancedMixin",
|
||||
"ae2.menu.PatternProviderMenuDoublingMixin",
|
||||
"ae2.helpers.PatternProviderLogicAdvancedMixin",
|
||||
"ae2.helpers.PatternProviderLogicDoublingMixin"
|
||||
"ae2.helpers.PatternProviderLogicDoublingMixin",
|
||||
"ae2.AEProcessingPatternMixin",
|
||||
"extendedae.client.gui.GuiExPatternProviderMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user