feat: 添加对翻倍样板的单个限制属性

This commit is contained in:
C-H716 2025-10-07 20:25:19 +08:00
parent 4c407e412b
commit 637c3cdea7
6 changed files with 124 additions and 0 deletions

View File

@ -27,6 +27,8 @@ public class ScaledProcessingPattern implements IPatternDetails {
private transient volatile GenericStack[] outputsCache; private transient volatile GenericStack[] outputsCache;
private transient volatile GenericStack[] sparseInputsCache; private transient volatile GenericStack[] sparseInputsCache;
private transient volatile GenericStack[] sparseOutputsCache; private transient volatile GenericStack[] sparseOutputsCache;
// per-provider scaling limit (0 = no limit). Can be updated from UI via provider settings.
private int perProviderScalingLimit = 0;
public ScaledProcessingPattern(AEProcessingPattern original, AEItemKey definition, long multiplier) { public ScaledProcessingPattern(AEProcessingPattern original, AEItemKey definition, long multiplier) {
this.original = Objects.requireNonNull(original); this.original = Objects.requireNonNull(original);
@ -34,6 +36,14 @@ public class ScaledProcessingPattern implements IPatternDetails {
this.multiplier = multiplier <= 0 ? 1L : multiplier; this.multiplier = multiplier <= 0 ? 1L : multiplier;
} }
public int getPerProviderScalingLimit() {
return this.perProviderScalingLimit;
}
public void setPerProviderScalingLimit(int limit) {
this.perProviderScalingLimit = Math.max(0, limit);
}
/* -------------------- API 实现 -------------------- */ /* -------------------- API 实现 -------------------- */
public AEProcessingPattern getOriginal() { public AEProcessingPattern getOriginal() {

View File

@ -3,4 +3,7 @@ package com.extendedae_plus.api.smartDoubling;
public interface ISmartDoublingAwarePattern { public interface ISmartDoublingAwarePattern {
boolean eap$allowScaling(); boolean eap$allowScaling();
void eap$setAllowScaling(boolean allow); void eap$setAllowScaling(boolean allow);
/** per-provider scaling limit: 0 means no limit */
int eap$getScalingLimit();
void eap$setScalingLimit(int limit);
} }

View File

@ -9,6 +9,8 @@ import org.spongepowered.asm.mixin.Unique;
public class AEProcessingPatternMixin implements ISmartDoublingAwarePattern { public class AEProcessingPatternMixin implements ISmartDoublingAwarePattern {
@Unique @Unique
private boolean eap$allowScaling = false; // 默认不允许缩放 private boolean eap$allowScaling = false; // 默认不允许缩放
@Unique
private int eap$scalingLimit = 0; // 0 表示不限制
@Override @Override
public boolean eap$allowScaling() { public boolean eap$allowScaling() {
@ -19,4 +21,14 @@ public class AEProcessingPatternMixin implements ISmartDoublingAwarePattern {
public void eap$setAllowScaling(boolean allow) { public void eap$setAllowScaling(boolean allow) {
this.eap$allowScaling = allow; this.eap$allowScaling = allow;
} }
@Override
public int eap$getScalingLimit() {
return this.eap$scalingLimit;
}
@Override
public void eap$setScalingLimit(int limit) {
this.eap$scalingLimit = Math.max(0, limit);
}
} }

View File

@ -22,6 +22,13 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
@Unique @Unique
private boolean eap$smartDoubling = false; private boolean eap$smartDoubling = false;
@Unique
private static final Object EAP_SCALING_LOCK = new Object();
@Unique
private static final java.util.concurrent.ScheduledExecutorService EAP_EXECUTOR =
java.util.concurrent.Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "eap-scaling-save"));
@Unique
private java.util.concurrent.ScheduledFuture<?> eap$pendingScalingSave = null;
@Override @Override
public boolean eap$getSmartDoubling() { public boolean eap$getSmartDoubling() {
@ -48,6 +55,29 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
@Inject(method = "writeToNBT", at = @At("TAIL")) @Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$writeSmartDoublingToNbt(CompoundTag tag, CallbackInfo ci) { private void eap$writeSmartDoublingToNbt(CompoundTag tag, CallbackInfo ci) {
tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling); tag.putBoolean(EAP_SMART_DOUBLING_KEY, this.eap$smartDoubling);
// persist any pattern-level scaling limits
try {
var list = ((PatternProviderLogicAccessor) this).eap$patterns();
int[] limits = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
var details = list.get(i);
if (details instanceof com.extendedae_plus.ae.api.crafting.ScaledProcessingPattern sp) {
limits[i] = sp.getPerProviderScalingLimit();
} else if (details instanceof appeng.crafting.pattern.AEProcessingPattern base && base instanceof ISmartDoublingAwarePattern aware) {
limits[i] = aware.eap$getScalingLimit();
} else {
limits[i] = 0;
}
}
var listTag = new net.minecraft.nbt.ListTag();
for (int v : limits) {
var c = new CompoundTag();
c.putInt("limit", v);
listTag.add(c);
}
tag.put("eap_scaling_limits", listTag);
} catch (Throwable ignored) {
}
} }
@Inject(method = "readFromNBT", at = @At("TAIL")) @Inject(method = "readFromNBT", at = @At("TAIL"))
@ -55,6 +85,23 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
if (tag.contains(EAP_SMART_DOUBLING_KEY)) { if (tag.contains(EAP_SMART_DOUBLING_KEY)) {
this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY); this.eap$smartDoubling = tag.getBoolean(EAP_SMART_DOUBLING_KEY);
} }
try {
if (tag.contains("eap_scaling_limits")) {
var list = ((PatternProviderLogicAccessor) this).eap$patterns();
var limitsTag = tag.getList("eap_scaling_limits", net.minecraft.nbt.Tag.TAG_COMPOUND);
int n = Math.min(list.size(), limitsTag.size());
for (int i = 0; i < n; i++) {
var c = limitsTag.getCompound(i);
int lim = c.getInt("limit");
var details = list.get(i);
if (details instanceof com.extendedae_plus.ae.api.crafting.ScaledProcessingPattern sp) {
sp.setPerProviderScalingLimit(lim);
} else if (details instanceof appeng.crafting.pattern.AEProcessingPattern base && base instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setScalingLimit(lim);
}
}
}
} catch (Throwable ignored) {}
} }
@Inject(method = "updatePatterns", at = @At("TAIL")) @Inject(method = "updatePatterns", at = @At("TAIL"))
@ -71,6 +118,32 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
} }
} }
// called by UI when user changes per-provider limit; apply with debounce and save
@Unique
public void eap$onPerProviderLimitChanged(int patternIndex, int newLimit) {
try {
var list = ((PatternProviderLogicAccessor) this).eap$patterns();
if (patternIndex < 0 || patternIndex >= list.size()) return;
var details = list.get(patternIndex);
if (details instanceof com.extendedae_plus.ae.api.crafting.ScaledProcessingPattern sp) {
sp.setPerProviderScalingLimit(newLimit);
} else if (details instanceof appeng.crafting.pattern.AEProcessingPattern base && base instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setScalingLimit(newLimit);
}
synchronized (EAP_SCALING_LOCK) {
if (eap$pendingScalingSave != null) {
eap$pendingScalingSave.cancel(false);
}
eap$pendingScalingSave = EAP_EXECUTOR.schedule(() -> {
try {
this.saveChanges();
} catch (Throwable ignored) {}
}, 1000, java.util.concurrent.TimeUnit.MILLISECONDS);
}
} catch (Throwable ignored) {}
}
@Shadow @Shadow
public void saveChanges() {} public void saveChanges() {}

View File

@ -28,6 +28,14 @@ public abstract class PatternProviderMenuDoublingMixin implements IPatternProvid
@Unique @Unique
@GuiSync(21) @GuiSync(21)
public boolean eap$SmartDoubling = false; public boolean eap$SmartDoubling = false;
@Unique
@GuiSync(22)
public int eap$PerProviderScalingLimit = 0; // 0 = no limit
public void eap$setPerProviderScalingLimit(int v) {
this.eap$PerProviderScalingLimit = Math.max(0, v);
// send to server via an existing packet channel or custom packet (not implemented here)
}
@Inject(method = "broadcastChanges", at = @At("HEAD")) @Inject(method = "broadcastChanges", at = @At("HEAD"))
private void eap$syncSmartDoubling(CallbackInfo ci) { private void eap$syncSmartDoubling(CallbackInfo ci) {

View File

@ -56,6 +56,24 @@ public final class PatternScaler {
long needed = requestedAmount / perOperationTarget + ((requestedAmount % perOperationTarget) == 0 ? 0 : 1); long needed = requestedAmount / perOperationTarget + ((requestedAmount % perOperationTarget) == 0 ? 0 : 1);
multiplier = needed <= 1L ? 1L : needed; multiplier = needed <= 1L ? 1L : needed;
} }
// 优先应用模式级别的限制 base 支持然后是全局配置
try {
int patternLimit = 0;
if (base instanceof ISmartDoublingAwarePattern aware) {
patternLimit = aware.eap$getScalingLimit();
}
if (patternLimit > 0 && multiplier > patternLimit) {
multiplier = patternLimit;
} else {
int maxMul = ModConfig.INSTANCE.smartScalingMaxMultiplier;
if (maxMul > 0 && multiplier > maxMul) {
multiplier = maxMul;
}
}
} catch (Throwable ignore) {
// ignore config read errors
}
// 小请求绕过若请求量小且不会带来收益则不启用缩放返回 null // 小请求绕过若请求量小且不会带来收益则不启用缩放返回 null
try { try {
int minBenefit = ModConfig.INSTANCE.smartScalingMinBenefitFactor; int minBenefit = ModConfig.INSTANCE.smartScalingMinBenefitFactor;