Files
MRCC/launcher/PCL-CE/Plain Craft Launcher 2/Modules/Minecraft/CrashAnalysis/Detection/CrashDetector.cs
T
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

121 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using PCL.Core.Logging;
namespace PCL;
internal sealed class CrashDetector
{
private readonly CrashEvidenceExtractor _extractor = new();
private readonly CrashStackAnalyzer _stackAnalyzer = new();
public CrashAnalysisResult Analyze(CrashLogSet logs, McInstance? instance)
{
LogWrapper.Info("Crash", "步骤 3:分析崩溃原因");
var result = new CrashAnalysisResult();
if (!logs.HasAnalyzableLog)
{
result.Add(new CrashFinding(CrashCause.NoAnalyzableFile, CrashConfidence.High) { ShouldStop = true });
_LogSummary(result);
return result;
}
var normalizedLogs = _Normalize(logs);
var modIndex = CrashModIndex.Create(normalizedLogs, instance);
_RunPhase(DetectionPhase.Fatal, normalizedLogs, modIndex, result);
if (_ShouldStop(result))
{
_LogSummary(result);
return result;
}
_RunPhase(DetectionPhase.Primary, normalizedLogs, modIndex, result);
if (_ShouldStop(result))
{
_LogSummary(result);
return result;
}
var stackFinding = _stackAnalyzer.Analyze(normalizedLogs, modIndex);
if (stackFinding is not null)
result.Add(stackFinding);
if (_ShouldStop(result))
{
_LogSummary(result);
return result;
}
_RunPhase(DetectionPhase.Secondary, normalizedLogs, modIndex, result);
_LogSummary(result);
return result;
}
private static CrashLogSet _Normalize(CrashLogSet logs)
{
var all = logs.All;
if (all.Contains("quilt", StringComparison.OrdinalIgnoreCase) &&
all.Contains("Mod Table Version", StringComparison.Ordinal))
{
LogWrapper.Info("Crash", "处理 Quilt Mod Table 后再继续分析");
all = CrashText.BeforeFirst(all, "| Index") + CrashText.AfterFirst(all, "Mod Table Version:");
}
return new CrashLogSet
{
Game = logs.Game,
Debug = logs.Debug,
CrashReport = logs.CrashReport,
HsErr = logs.HsErr,
All = all
};
}
private void _RunPhase(
DetectionPhase phase,
CrashLogSet logs,
CrashModIndex modIndex,
CrashAnalysisResult result)
{
var input = new CrashRuleInput { Logs = logs, ModIndex = modIndex };
foreach (var rule in CrashRuleCatalog.Rules.Where(rule => rule.Phase == phase))
{
var finding = rule.Evaluate(input);
if (finding is not null)
_AddAndLog(result, finding);
}
foreach (var finding in _extractor.Extract(phase, logs, modIndex))
_AddAndLog(result, finding);
}
private static void _AddAndLog(CrashAnalysisResult result, CrashFinding finding)
{
result.Add(finding);
_LogFinding(finding);
}
private static bool _ShouldStop(CrashAnalysisResult result)
{
return result.Findings.Any(finding => finding.ShouldStop);
}
private static void _LogFinding(CrashFinding finding)
{
var evidence = string.Join("", finding.Details);
LogWrapper.Info(
"Crash",
$"可能的崩溃原因:{finding.Cause}{(string.IsNullOrEmpty(evidence) ? "" : "" + evidence + "")}");
}
private static void _LogSummary(CrashAnalysisResult result)
{
if (!result.Any)
{
LogWrapper.Info("Crash", "步骤 3:分析崩溃原因完成,未找到可能的原因");
return;
}
LogWrapper.Info("Crash", $"步骤 3:分析崩溃原因完成,找到 {result.Findings.Count} 条可能的原因");
foreach (var finding in result.Findings)
_LogFinding(finding);
}
}