feat: 前置供应器级限制,避免构建合成树时计算倍率

This commit is contained in:
C-H716 2025-10-10 12:15:13 +08:00
parent 78033c5df0
commit 049a3fc182
8 changed files with 69 additions and 62 deletions

View File

@ -5,6 +5,6 @@ public interface ISmartDoublingAwarePattern {
void eap$setAllowScaling(boolean allow);
// 翻倍限制0 表示无限制
int eap$getScalingLimit();
void eap$setScalingLimit(int limit);
int eap$getMultiplierLimit();
void eap$setMultiplierLimit(int limit);
}

View File

@ -188,7 +188,7 @@ public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen<AdvPatt
// 设置 tooltip
String cur = this.eap$PerProviderLimitInput.getValue();
if (cur.isBlank()) cur = "0";
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.literal("板输入物品数量上限: " + cur)));
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.literal("样物品发配数量上限: " + cur)));
// 失焦时提交最新值
boolean focusedNow = this.eap$PerProviderLimitInput.isFocused();

View File

@ -189,7 +189,7 @@ public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<Sm
// 设置 tooltip
String cur = this.eap$PerProviderLimitInput.getValue();
if (cur.isBlank()) cur = "0";
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.literal("板输入物品数量上限: " + cur)));
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.literal("样物品发配数量上限: " + cur)));
// 失焦时提交最新值
boolean focusedNow = this.eap$PerProviderLimitInput.isFocused();

View File

@ -15,6 +15,8 @@ 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.smartDoubling.PatternScaler.getComputedMul;
@Mixin(value = AdvPatternProviderLogic.class, remap = false)
public class AdvPatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
@Unique private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling";
@ -51,18 +53,11 @@ public class AdvPatternProviderLogicDoublingMixin implements ISmartDoublingHolde
@Override
public void eap$setProviderSmartDoublingLimit(int limit) {
// 更新供应器级别上限并去抖保存
var list = ((AdvPatternProviderLogicPatternsAccessor) this).eap$patterns();
this.eap$providerScalingLimit = Math.max(0, limit);
// 现在把防抖移到客户端屏幕端来处理服务器端直接立即应用并保存
for (IPatternDetails d : list) {
if (d instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern a) {
try { a.eap$setScalingLimit(this.eap$providerScalingLimit); } catch (Throwable ignored) {}
}
}
try {
((AdvPatternProviderLogic) (Object) this).updatePatterns();
} catch (Throwable ignored) {}
// 更新供应器级别上限用于 UI 显示
this.eap$providerScalingLimit = Math.max(0, limit);
}
@Inject(method = "writeToNBT", at = @At("TAIL"))
@ -89,9 +84,9 @@ public class AdvPatternProviderLogicDoublingMixin implements ISmartDoublingHolde
boolean allow = this.eap$smartDoubling;
int limit = this.eap$providerScalingLimit;
for (IPatternDetails details : list) {
if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allow);
aware.eap$setScalingLimit(limit);
if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern pattern) {
pattern.eap$setAllowScaling(allow);
pattern.eap$setMultiplierLimit(getComputedMul(proc, limit));
}
}
} catch (Throwable ignored) {}

View File

@ -10,7 +10,7 @@ public class AEProcessingPatternMixin implements ISmartDoublingAwarePattern {
@Unique
private boolean eap$allowScaling = false; // 默认不允许缩放
@Unique
private int eap$scalingLimit = 0; // 0 表示不限制
private int eap$multiplierLimit = 0; // 模式级别的倍数上限0 表示不限制
@Override
public boolean eap$allowScaling() {
@ -23,12 +23,12 @@ public class AEProcessingPatternMixin implements ISmartDoublingAwarePattern {
}
@Override
public int eap$getScalingLimit() {
return this.eap$scalingLimit;
public int eap$getMultiplierLimit() {
return this.eap$multiplierLimit;
}
@Override
public void eap$setScalingLimit(int limit) {
this.eap$scalingLimit = Math.max(0, limit);
public void eap$setMultiplierLimit(int limit) {
this.eap$multiplierLimit = Math.max(0, limit);
}
}

View File

@ -192,7 +192,7 @@ public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu>
// 设置 tooltip
String cur = this.eap$PerProviderLimitInput.getValue();
if (cur.isBlank()) cur = "0";
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.literal("板输入物品数量上限: " + cur)));
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.literal("样物品发配数量上限: " + cur)));
// 失焦时提交最新值
boolean focusedNow = this.eap$PerProviderLimitInput.isFocused();

View File

@ -15,6 +15,8 @@ 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.smartDoubling.PatternScaler.getComputedMul;
@Mixin(value = PatternProviderLogic.class, remap = false)
public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
@Unique private static final String EAP_SMART_DOUBLING_KEY = "eap_smart_doubling";
@ -51,18 +53,11 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
@Override
public void eap$setProviderSmartDoublingLimit(int limit) {
// 更新供应器级别上限并去抖保存
var list = ((PatternProviderLogicAccessor) this).eap$patterns();
this.eap$providerScalingLimit = Math.max(0, limit);
// 现在把防抖移到客户端屏幕端来处理服务器端直接立即应用并保存
for (IPatternDetails d : list) {
if (d instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern a) {
try { a.eap$setScalingLimit(this.eap$providerScalingLimit); } catch (Throwable ignored) {}
}
}
try {
((PatternProviderLogic) (Object) this).updatePatterns();
} catch (Throwable ignored) {}
// 更新供应器级别上限用于 UI 显示
this.eap$providerScalingLimit = Math.max(0, limit);
}
@Inject(method = "writeToNBT", at = @At("TAIL"))
@ -90,13 +85,12 @@ public class PatternProviderLogicDoublingMixin implements ISmartDoublingHolder {
boolean allow = this.eap$smartDoubling;
int limit = this.eap$providerScalingLimit;
for (IPatternDetails details : list) {
if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) {
aware.eap$setAllowScaling(allow);
aware.eap$setScalingLimit(limit);
if (details instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern pattern) {
pattern.eap$setAllowScaling(allow);
pattern.eap$setMultiplierLimit(getComputedMul(proc, limit));
}
}
} catch (Throwable ignored) {
}
} catch (Throwable ignored) {}
}
@Shadow

View File

@ -50,40 +50,36 @@ public final class PatternScaler {
if (amt > 0) perOperationTarget = amt;
}
// 使用最小整数倍ceil策略直接选择满足请求的最小倍数
long multiplier = 1L;
if (requestedAmount > 0) {
long needed = requestedAmount / perOperationTarget + ((requestedAmount % perOperationTarget) == 0 ? 0 : 1);
multiplier = needed <= 1L ? 1L : needed;
long multiplier = 1L; // 默认倍数
// ---------------------- 优先模式限制 ----------------------
boolean patternHasLimit = false;
if (base instanceof ISmartDoublingAwarePattern aware) {
int patternMulLimit = aware.eap$getMultiplierLimit();
if (patternMulLimit > 0) {
multiplier = patternMulLimit; // 直接使用模式限制作为倍数
patternHasLimit = true;
}
}
// 优先应用模式级别的限制 base 支持然后是全局配置
try {
int patternLimit = 0;
if (base instanceof ISmartDoublingAwarePattern aware) {
patternLimit = aware.eap$getScalingLimit();
}
if (patternLimit > 0 && multiplier > patternLimit) {
multiplier = patternLimit;
} else {
// 应用配置的最大倍数上限0 表示不限制
int maxMul = ModConfig.INSTANCE.smartScalingMaxMultiplier;
if (maxMul > 0 && multiplier > maxMul) {
multiplier = maxMul;
}
}
} catch (Throwable ignore) {
// ignore config read errors
// ---------------------- 全局逻辑仅在没有模式限制时生效 ----------------------
if (!patternHasLimit && requestedAmount > 0) {
// 计算满足请求量的最小倍数
long needed = requestedAmount / perOperationTarget + ((requestedAmount % perOperationTarget) == 0 ? 0 : 1);
multiplier = Math.max(needed, 1L);
// 应用全局上限
int maxMul = ModConfig.INSTANCE.smartScalingMaxMultiplier;
if (maxMul > 0 && multiplier > maxMul) multiplier = maxMul;
}
// 小请求绕过若请求量小且不会带来收益则不启用缩放返回 null
// ---------------------- 小请求绕过 ----------------------
try {
int minBenefit = ModConfig.INSTANCE.smartScalingMinBenefitFactor;
if (minBenefit > 1 && requestedAmount > 0 && requestedAmount < perOperationTarget * (long) minBenefit) {
return null;
}
} catch (Throwable ignore) {
// 配置读取异常时保持默认行为不绕过
}
} catch (Throwable ignore) {}
if (ModList.get().isLoaded("advanced_ae")) {
// 如果加载了 Advanced AE base 实现了 AdvPatternDetails返回兼容版
@ -101,4 +97,26 @@ public final class PatternScaler {
// 仅使用 multiplier 构建轻量化 ScaledProcessingPattern具体视图按需计算
return new ScaledProcessingPattern(base, base.getDefinition(), multiplier);
}
public static int getComputedMul(AEProcessingPattern proc, int limit) {
int computedMul = 0; // 默认 0 表示不限制
if (limit > 0) {
long minMul = Long.MAX_VALUE;
for (var input : proc.getInputs()) {
long amt = input.getMultiplier();
if (amt > 0) {
// 保证翻倍限制至少为 1
long allowedMul = Math.max(1, limit / amt);
minMul = Math.min(minMul, allowedMul);
}
}
if (minMul != Long.MAX_VALUE) {
computedMul = (int) minMul;
}
}
return computedMul;
}
}