在构造合成树前,对样板进行设置,使用ScaledProcessingPattern代替AEProcessingPattern,实现样板的自动倍增
This commit is contained in:
parent
83c52fc659
commit
6924ff968a
|
|
@ -0,0 +1,136 @@
|
|||
package com.extendedae_plus.content;
|
||||
|
||||
import appeng.api.crafting.IPatternDetails;
|
||||
import appeng.api.stacks.AEItemKey;
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.api.stacks.GenericStack;
|
||||
import appeng.api.stacks.KeyCounter;
|
||||
import appeng.crafting.pattern.AEProcessingPattern;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 缩放后的处理样板,结构完全模拟 AEProcessingPattern。
|
||||
* 保持 sparse/condensed/inputs 的一致性,同时保存原始样板。
|
||||
*/
|
||||
public final class ScaledProcessingPattern implements IPatternDetails {
|
||||
|
||||
private final AEProcessingPattern original; // 原始样板引用
|
||||
private final AEItemKey definition; // 样板物品
|
||||
private final GenericStack[] sparseInputs; // 缩放后的稀疏输入
|
||||
private final GenericStack[] sparseOutputs; // 缩放后的稀疏输出
|
||||
private final IInput[] inputs; // 缩放后的压缩输入
|
||||
private final GenericStack[] condensedOutputs; // 缩放后的压缩输出
|
||||
|
||||
public ScaledProcessingPattern(
|
||||
AEProcessingPattern original,
|
||||
AEItemKey definition,
|
||||
GenericStack[] sparseInputs,
|
||||
GenericStack[] sparseOutputs,
|
||||
IInput[] inputs,
|
||||
GenericStack[] condensedOutputs
|
||||
) {
|
||||
this.original = Objects.requireNonNull(original);
|
||||
this.definition = Objects.requireNonNull(definition);
|
||||
this.sparseInputs = Objects.requireNonNull(sparseInputs);
|
||||
this.sparseOutputs = Objects.requireNonNull(sparseOutputs);
|
||||
this.inputs = Objects.requireNonNull(inputs);
|
||||
this.condensedOutputs = Objects.requireNonNull(condensedOutputs);
|
||||
}
|
||||
|
||||
/* -------------------- API 实现 -------------------- */
|
||||
|
||||
public AEProcessingPattern getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEItemKey getDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IInput[] getInputs() {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericStack[] getOutputs() {
|
||||
return condensedOutputs;
|
||||
}
|
||||
|
||||
public GenericStack[] getSparseInputs() {
|
||||
return sparseInputs;
|
||||
}
|
||||
|
||||
public GenericStack[] getSparseOutputs() {
|
||||
return sparseOutputs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericStack getPrimaryOutput() {
|
||||
if (condensedOutputs.length > 0) return condensedOutputs[0];
|
||||
return original.getPrimaryOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsPushInputsToExternalInventory() {
|
||||
return original.supportsPushInputsToExternalInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushInputsToExternalInventory(KeyCounter[] inputHolder, PatternInputSink inputSink) {
|
||||
// 保持和 AEProcessingPattern 一致,用 sparseInputs 驱动
|
||||
if (sparseInputs.length == inputs.length) {
|
||||
IPatternDetails.super.pushInputsToExternalInventory(inputHolder, inputSink);
|
||||
} else {
|
||||
KeyCounter allInputs = new KeyCounter();
|
||||
for (KeyCounter counter : inputHolder) {
|
||||
allInputs.addAll(counter);
|
||||
}
|
||||
for (GenericStack sparseInput : sparseInputs) {
|
||||
if (sparseInput != null) {
|
||||
AEKey key = sparseInput.what();
|
||||
long amount = sparseInput.amount();
|
||||
long available = allInputs.get(key);
|
||||
if (available < amount) {
|
||||
throw new RuntimeException("Expected at least %d of %s when pushing scaled pattern, but only %d available"
|
||||
.formatted(amount, key, available));
|
||||
}
|
||||
inputSink.pushInput(key, amount);
|
||||
allInputs.remove(key, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------- 缩放输入代理 -------------------- */
|
||||
|
||||
public static final class Input implements IPatternDetails.IInput {
|
||||
private final GenericStack[] template;
|
||||
private final long multiplier;
|
||||
|
||||
public Input(GenericStack[] template, long multiplier) {
|
||||
this.template = template;
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
public GenericStack[] getPossibleInputs() {
|
||||
return this.template;
|
||||
}
|
||||
|
||||
public long getMultiplier() {
|
||||
return this.multiplier;
|
||||
}
|
||||
|
||||
public boolean isValid(AEKey input, Level level) {
|
||||
return input.matches(this.template[0]);
|
||||
}
|
||||
|
||||
public @Nullable AEKey getRemainingKey(AEKey template) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.extendedae_plus.mixin.ae2;
|
||||
|
||||
import appeng.api.crafting.IPatternDetails;
|
||||
import appeng.api.networking.crafting.ICraftingService;
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.crafting.CraftingCalculation;
|
||||
import appeng.crafting.CraftingTreeNode;
|
||||
import appeng.crafting.CraftingTreeProcess;
|
||||
import appeng.crafting.pattern.AEProcessingPattern;
|
||||
import com.extendedae_plus.mixin.ae2.accessor.CraftingCalculationAccessor;
|
||||
import com.extendedae_plus.mixin.ae2.accessor.CraftingTreeNodeAccessor;
|
||||
import com.extendedae_plus.util.PatternScaler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
/**
|
||||
* 注入 CraftingTreeProcess 构造器尾部:将 AEProcessingPattern 替换为 ScaledProcessingPattern
|
||||
* 以确保后续执行使用放大后的输入/输出视图。
|
||||
*/
|
||||
@Mixin(CraftingTreeProcess.class)
|
||||
public class CraftingTreeProcessMixin {
|
||||
|
||||
@ModifyVariable(method = "<init>(Lappeng/api/networking/crafting/ICraftingService;Lappeng/crafting/CraftingCalculation;Lappeng/api/crafting/IPatternDetails;Lappeng/crafting/CraftingTreeNode;)V",
|
||||
at = @At("HEAD"), argsOnly = true)
|
||||
private static IPatternDetails extendedae_plus$replaceDetailsAtHead(IPatternDetails original, ICraftingService cc, CraftingCalculation job, IPatternDetails details, CraftingTreeNode craftingTreeNode) {
|
||||
try {
|
||||
if (!(details instanceof AEProcessingPattern proc)) return original;
|
||||
|
||||
CraftingCalculationAccessor jobAcc = (CraftingCalculationAccessor) job;
|
||||
long requested = jobAcc.extendedae_plus$getRequestedAmount();
|
||||
|
||||
CraftingTreeNodeAccessor parentAcc = (CraftingTreeNodeAccessor) craftingTreeNode;
|
||||
AEKey parentTarget = parentAcc.extendedae_plus$getWhat();
|
||||
|
||||
System.out.println("[extendedae_plus] Replacing constructor details at HEAD for: " + parentTarget + " x " + requested);
|
||||
|
||||
return PatternScaler.scale(proc, parentTarget, requested);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[extendedae_plus] Error replacing pattern at HEAD: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return original;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.extendedae_plus.mixin.ae2.accessor;
|
||||
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.crafting.CraftingCalculation;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(CraftingCalculation.class)
|
||||
public interface CraftingCalculationAccessor {
|
||||
@Accessor("output")
|
||||
AEKey extendedae_plus$getOutput();
|
||||
|
||||
@Accessor("requestedAmount")
|
||||
long extendedae_plus$getRequestedAmount();
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.extendedae_plus.mixin.ae2.accessor;
|
||||
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.crafting.CraftingTreeNode;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(CraftingTreeNode.class)
|
||||
public interface CraftingTreeNodeAccessor {
|
||||
|
||||
@Accessor("what")
|
||||
AEKey extendedae_plus$getWhat();
|
||||
|
||||
@Accessor("amount")
|
||||
long extendedae_plus$getAmount();
|
||||
}
|
||||
88
src/main/java/com/extendedae_plus/util/PatternScaler.java
Normal file
88
src/main/java/com/extendedae_plus/util/PatternScaler.java
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package com.extendedae_plus.util;
|
||||
|
||||
import appeng.api.crafting.IPatternDetails.IInput;
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.api.stacks.GenericStack;
|
||||
import appeng.crafting.pattern.AEProcessingPattern;
|
||||
import com.extendedae_plus.content.ScaledProcessingPattern;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class PatternScaler {
|
||||
private PatternScaler() {
|
||||
}
|
||||
|
||||
public static ScaledProcessingPattern scale(AEProcessingPattern base, AEKey target, long requestedAmount) {
|
||||
if (base == null) throw new IllegalArgumentException("base");
|
||||
if (target == null) throw new IllegalArgumentException("target");
|
||||
|
||||
GenericStack[] baseSparseInputs = base.getSparseInputs();
|
||||
GenericStack[] baseSparseOutputs = base.getSparseOutputs();
|
||||
IInput[] baseInputs = base.getInputs();
|
||||
GenericStack[] baseOutputs = base.getOutputs();
|
||||
|
||||
/* 1. 构建缩放后的 sparseInputs */
|
||||
GenericStack[] scaledSparseInputs = new GenericStack[baseSparseInputs.length];
|
||||
for (int i = 0; i < baseSparseInputs.length; i++) {
|
||||
GenericStack in = baseSparseInputs[i];
|
||||
if (in != null) {
|
||||
scaledSparseInputs[i] = new GenericStack(in.what(), requestedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. 构建缩放后的 sparseOutputs */
|
||||
GenericStack[] scaledSparseOutputs = new GenericStack[baseSparseOutputs.length];
|
||||
for (int i = 0; i < baseSparseOutputs.length; i++) {
|
||||
GenericStack out = baseSparseOutputs[i];
|
||||
if (out != null) {
|
||||
scaledSparseOutputs[i] = new GenericStack(out.what(), requestedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. 构建压缩输入(ScaledInput) */
|
||||
IInput[] scaledInputs = new IInput[baseInputs.length];
|
||||
for (int i = 0; i < baseInputs.length; i++) {
|
||||
var in = baseInputs[i];
|
||||
var template = in.getPossibleInputs();
|
||||
|
||||
GenericStack[] scaledTemplates = new GenericStack[template.length];
|
||||
for (int j = 0; j < template.length; j++) {
|
||||
scaledTemplates[j] = new GenericStack(template[j].what(), 1);
|
||||
}
|
||||
scaledInputs[i] = new ScaledProcessingPattern.Input(scaledTemplates, requestedAmount);
|
||||
}
|
||||
|
||||
/* 4. 构建压缩输出 */
|
||||
GenericStack[] scaledCondensedOutputs = new GenericStack[baseOutputs.length];
|
||||
for (int i = 0; i < baseOutputs.length; i++) {
|
||||
GenericStack out = baseOutputs[i];
|
||||
if (out != null) {
|
||||
scaledCondensedOutputs[i] = new GenericStack(out.what(), requestedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/* Debug 输出 */
|
||||
System.out.println("[extendedae_plus] 正在缩放样板:");
|
||||
System.out.println(" 原始样板: " + base);
|
||||
System.out.println(" 目标物品: " + target);
|
||||
System.out.println(" 请求数量: " + requestedAmount);
|
||||
System.out.println(" 缩放后输入: " + Arrays.toString(scaledInputs));
|
||||
System.out.println(" 缩放后输出: " + Arrays.toString(scaledCondensedOutputs));
|
||||
System.out.println(" 缩放后稀疏输入: " + Arrays.toString(scaledSparseInputs));
|
||||
System.out.println(" 缩放后稀疏输出: " + Arrays.toString(scaledSparseOutputs));
|
||||
|
||||
|
||||
return new ScaledProcessingPattern(base,
|
||||
base.getDefinition(),
|
||||
scaledSparseInputs,
|
||||
scaledSparseOutputs,
|
||||
scaledInputs,
|
||||
scaledCondensedOutputs);
|
||||
}
|
||||
|
||||
private static long safeMul(long a, long b) {
|
||||
if (a == 0 || b == 0) return 0;
|
||||
if (a > Long.MAX_VALUE / b) return Long.MAX_VALUE;
|
||||
return a * b;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,15 +23,20 @@
|
|||
"extendedae.HighlightButtonMixin",
|
||||
"extendedae.accessor.GuiExPatternTerminalAccessor",
|
||||
"extendedae.accessor.GuiExPatternTerminalSlotsRowAccessor",
|
||||
"jei.EncodePatternTransferHandlerMixin",
|
||||
"hooks.ModelBakeryMixin"
|
||||
"hooks.ModelBakeryMixin",
|
||||
"jei.EncodePatternTransferHandlerMixin"
|
||||
],
|
||||
"mixins": [
|
||||
"ae2.AEProcessingPatternMixin",
|
||||
"ae2.ContainerPatternEncodingTermMenuMixin",
|
||||
"ae2.CraftingCPUClusterMixin",
|
||||
"ae2.CraftingTreeProcessMixin",
|
||||
"ae2.MEStorageMenuMixin",
|
||||
"ae2.PatternEncodingTermMenuMixin",
|
||||
"ae2.PatternProviderLogicAdvancedMixin",
|
||||
"ae2.PatternProviderMenuAdvancedMixin",
|
||||
"ae2.accessor.CraftingCalculationAccessor",
|
||||
"ae2.accessor.CraftingTreeNodeAccessor",
|
||||
"ae2.accessor.MEStorageMenuAccessor",
|
||||
"ae2.accessor.PatternEncodingTermMenuAccessor",
|
||||
"ae2.accessor.PatternProviderLogicAccessor",
|
||||
|
|
@ -41,7 +46,6 @@
|
|||
"extendedae.ContainerExPatternProviderMixin",
|
||||
"extendedae.ContainerExPatternTerminalMixin",
|
||||
"extendedae.ContainerWirelessExPatternTerminalMixin",
|
||||
"ae2.CraftingCPUClusterMixin",
|
||||
"extendedae.PartExPatternProviderMixin",
|
||||
"extendedae.TileExPatternProviderMixin"
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user