babalae/better-genshin-impact · error · FormatException

原粹树脂上限解析失败:{countText}

Error message

原粹树脂上限解析失败:{countText}

What it means

在取到至少 3 位数字后,代码取最后三位作为 limitText 并 int.TryParse。由于 digits 已剔除非数字,解析仅在三种情况失败:数值溢出(>int.MaxValue)、或解析出 0(resinLimit <= 0 分支,如 limitText='000')。FormatException 表示上限被读成 0 或异常大值。

Source

Thrown at BetterGenshinImpact/GameTask/AutoBoss/AutoBossTask.cs:354

    /// <summary>
    /// 按原右上角 OCR 区域读取当前/上限文本,并取数字串最后三位作为树脂上限。
    /// </summary>
    private int RecognizeOriginalResinLimit(ImageRegion capture, int resinIconRight)
    {
        var countRect = new Rect(resinIconRight + ScaleX(25), ScaleY(37), ScaleX(120), ScaleY(24));
        using var countRegion = capture.DeriveCrop(countRect);
        var countText = OcrFactory.Paddle.OcrWithoutDetector(countRegion.SrcMat);
        var digits = Regex.Replace(StringUtils.ConvertFullWidthNumToHalfWidth(countText), @"\D", "");
        if (digits.Length < 3)
        {
            throw new FormatException($"原粹树脂上限 OCR 失败:{countText}");
        }

        var limitText = digits[^3..];
        if (!int.TryParse(limitText, NumberStyles.None, CultureInfo.InvariantCulture, out var resinLimit) || resinLimit <= 0)
        {
            throw new FormatException($"原粹树脂上限解析失败:{countText}");
        }

        _logger.LogDebug("{Name}:原粹树脂上限 OCR:{Text} -> {Limit}", Name, countText, resinLimit);
        return resinLimit;
    }

    /// <summary>
    /// 读取树脂详情弹窗中的全部恢复时间;已完全恢复时返回零时长。
    /// </summary>
    private TimeSpan RecognizeFullRecoveryTime(ImageRegion capture, int resinIconLeft, int resinIconBottom)
    {
        // 该偏移来自截图实际像素,不随 AssetScale 缩放。
        var detailRect = new Rect(
            resinIconLeft - 13,
            resinIconBottom + 29,
            220,
            150);
        using var detailRegion = capture.DeriveCrop(detailRect);

View on GitHub (pinned to a7cb36712d)

Solutions

  1. 记录 countText 原文(debug 日志)确认是否为 '000' 类误读。
  2. 当 limit==0 时按树脂上限常识(如 160)做一次容错重试,而非直接抛出。
  3. 校准 countRect 区域,避免覆盖到非数字图形。
  4. 在外层兜底 catch 中降级为预检跳过。

Example fix

// before
var limitText = digits[^3..];
if (!int.TryParse(limitText, NumberStyles.None, CultureInfo.InvariantCulture, out var resinLimit) || resinLimit <= 0)
{
    throw new FormatException($"原粹树脂上限解析失败:{countText}");
}

// after
var limitText = digits[^3..];
if (!int.TryParse(limitText, NumberStyles.None, CultureInfo.InvariantCulture, out var resinLimit) || resinLimit <= 0)
{
    throw new FormatException($"原粹树脂上限解析失败(原文={countText}, 末三位={limitText})");
}
Defensive patterns

Strategy: validation

Validate before calling

// 取末三位前先校验是否为合理上限范围
var limitText = digits[^3..];
if (int.TryParse(limitText, NumberStyles.None, CultureInfo.InvariantCulture, out var candidate)
    && candidate is >= 60 and <= 200)
{
    return candidate;
}
// 否则按异常处理

Prevention

When it happens

Trigger: '当前/上限' 被读成 '000/000' 或 limit 段为 '000'(例如把图标/分隔线误读为 0);或 digits 含超长数字串使最后三位虽能解析但整体上限异常(此处不会溢出,三位最大 999)。

Common situations: OCR 把无数字区域读成多个 0;区域漂移到非数字元素;游戏 UI 临时显示占位符。

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/55073dc0c06f3f6f. Report an issue: GitHub.