2.10.1
This commit is contained in:
@@ -491,6 +491,9 @@
|
||||
Case "path-tracing" : Tags.Add("路径追踪")
|
||||
Case "pbr" : Tags.Add("PBR")
|
||||
Case "reflections" : Tags.Add("反射")
|
||||
|
||||
Case "iris" : Tags.Add("Iris")
|
||||
Case "optifine" : Tags.Add("OptiFine")
|
||||
Case "vanilla" : Tags.Add("原版可用")
|
||||
End Select
|
||||
Next
|
||||
@@ -947,38 +950,39 @@ NoSubtitle:
|
||||
''' 根据搜索请求获取一系列的工程列表。需要基于加载器运行。
|
||||
''' </summary>
|
||||
Public Sub CompProjectsGet(Task As LoaderTask(Of CompProjectRequest, Integer))
|
||||
Dim Storage = Task.Input.Storage '避免多线程问题
|
||||
Dim Request As CompProjectRequest = Task.Input
|
||||
Dim Storage = Request.Storage '避免多线程问题
|
||||
|
||||
If Task.Input.Storage.Results.Count >= Task.Input.TargetResultCount Then
|
||||
Log($"[Comp] 已有 {Task.Input.Storage.Results.Count} 个结果,多于所需的 {Task.Input.TargetResultCount} 个结果,结束处理")
|
||||
Exit Sub
|
||||
ElseIf Not Task.Input.CanContinue Then
|
||||
If Not Task.Input.Storage.Results.Any() Then
|
||||
If Request.Storage.Results.Count >= Request.TargetResultCount Then
|
||||
Log($"[Comp] 已有 {Request.Storage.Results.Count} 个结果,多于所需的 {Request.TargetResultCount} 个结果,结束处理")
|
||||
Return
|
||||
ElseIf Not Request.CanContinue Then
|
||||
If Not Request.Storage.Results.Any() Then
|
||||
Throw New Exception("没有符合条件的结果")
|
||||
Else
|
||||
Log($"[Comp] 已有 {Task.Input.Storage.Results.Count} 个结果,少于所需的 {Task.Input.TargetResultCount} 个结果,但无法继续获取,结束处理")
|
||||
Exit Sub
|
||||
Log($"[Comp] 已有 {Request.Storage.Results.Count} 个结果,少于所需的 {Request.TargetResultCount} 个结果,但无法继续获取,结束处理")
|
||||
Return
|
||||
End If
|
||||
End If
|
||||
|
||||
#Region "拒绝 1.13- Quilt(这个版本根本没有 Quilt)"
|
||||
|
||||
If Task.Input.ModLoader = CompModLoaderType.Quilt AndAlso VersionSortInteger(If(Task.Input.GameVersion, "1.15"), "1.14") = -1 Then
|
||||
Throw New Exception("Quilt 不支持 Minecraft " & Task.Input.GameVersion)
|
||||
If Request.ModLoader = CompModLoaderType.Quilt AndAlso VersionSortInteger(If(Request.GameVersion, "1.15"), "1.14") = -1 Then
|
||||
Throw New Exception("Quilt 不支持 Minecraft " & Request.GameVersion)
|
||||
End If
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "处理搜索文本,赋值回 Task.Input.SearchText"
|
||||
|
||||
Dim RawFilter As String = If(Task.Input.SearchText, "").Trim
|
||||
Task.Input.SearchText = RawFilter
|
||||
Dim RawFilter As String = If(Request.SearchText, "").Trim
|
||||
Request.SearchText = RawFilter
|
||||
RawFilter = RawFilter.ToLower
|
||||
Log("[Comp] 工程列表搜索原始文本:" & RawFilter)
|
||||
|
||||
'中文请求关键字处理
|
||||
Dim IsChineseSearch As Boolean = RegexCheck(RawFilter, "[\u4e00-\u9fbb]") AndAlso Not String.IsNullOrEmpty(RawFilter)
|
||||
If IsChineseSearch AndAlso (Task.Input.Type = CompType.Mod OrElse Task.Input.Type = CompType.DataPack) Then
|
||||
If IsChineseSearch AndAlso (Request.Type = CompType.Mod OrElse Request.Type = CompType.DataPack) Then
|
||||
'构造搜索请求
|
||||
Dim SearchEntries As New List(Of SearchEntry(Of CompDatabaseEntry))
|
||||
For Each Entry In CompDatabase
|
||||
@@ -991,7 +995,7 @@ NoSubtitle:
|
||||
})
|
||||
Next
|
||||
'获取搜索结果
|
||||
Dim SearchResults = Search(SearchEntries, Task.Input.SearchText, 3)
|
||||
Dim SearchResults = Search(SearchEntries, Request.SearchText, 3)
|
||||
If Not SearchResults.Any() Then Throw New Exception("无搜索结果,请尝试搜索英文名称")
|
||||
Dim SearchResult As String = ""
|
||||
For i = 0 To Math.Min(4, SearchResults.Count - 1) '就算全是准确的,也最多只要 5 个
|
||||
@@ -1009,14 +1013,14 @@ NoSubtitle:
|
||||
If SearchResult.Split(" ").Count > 3 AndAlso {"ftb"}.Contains(Word.ToLower) Then Continue For
|
||||
RealFilter += Word.TrimStart("{[(").TrimEnd("}])") & " "
|
||||
Next
|
||||
Task.Input.SearchText = RealFilter
|
||||
Request.SearchText = RealFilter
|
||||
Log("[Comp] 中文搜索最终关键词:" & RealFilter, LogLevel.Developer)
|
||||
End If
|
||||
|
||||
'驼峰英文请求关键字处理
|
||||
Dim SpacedKeywords = Task.Input.SearchText.RegexReplace("([A-Z]+|[a-z]+?)(?=[A-Z]+[a-z]+[a-z ]*)", "$& ")
|
||||
Dim ConnectedKeywords = Task.Input.SearchText.Replace(" ", "")
|
||||
Dim AllPossibleKeywords = (SpacedKeywords & " " & If(IsChineseSearch, Task.Input.SearchText, ConnectedKeywords & " " & RawFilter)).ToLower
|
||||
Dim SpacedKeywords = Request.SearchText.RegexReplace("([A-Z]+|[a-z]+?)(?=[A-Z]+[a-z]+[a-z ]*)", "$& ")
|
||||
Dim ConnectedKeywords = Request.SearchText.Replace(" ", "")
|
||||
Dim AllPossibleKeywords = (SpacedKeywords & " " & If(IsChineseSearch, Request.SearchText, ConnectedKeywords & " " & RawFilter)).ToLower
|
||||
|
||||
'最终处理关键字:分割、去重
|
||||
Dim RightKeywords As New List(Of String)
|
||||
@@ -1030,15 +1034,15 @@ NoSubtitle:
|
||||
RightKeywords.Add(Keyword)
|
||||
Next
|
||||
If RawFilter.Length > 0 AndAlso Not RightKeywords.Any() Then
|
||||
Task.Input.SearchText = RawFilter '全都被过滤掉了
|
||||
Request.SearchText = RawFilter '全都被过滤掉了
|
||||
Else
|
||||
Task.Input.SearchText = Join(RightKeywords.Distinct.ToList, " ").ToLower
|
||||
Request.SearchText = Join(RightKeywords.Distinct.ToList, " ").ToLower
|
||||
End If
|
||||
|
||||
'例外项:OptiForge、OptiFabric(拆词后因为包含 Forge/Fabric 导致无法搜到实际的 Mod)
|
||||
If RawFilter.Replace(" ", "").ContainsF("optiforge", True) Then Task.Input.SearchText = "optiforge"
|
||||
If RawFilter.Replace(" ", "").ContainsF("optifabric", True) Then Task.Input.SearchText = "optifabric"
|
||||
Log("[Comp] 工程列表搜索最终文本:" & Task.Input.SearchText, LogLevel.Debug)
|
||||
If RawFilter.Replace(" ", "").ContainsF("optiforge", True) Then Request.SearchText = "optiforge"
|
||||
If RawFilter.Replace(" ", "").ContainsF("optifabric", True) Then Request.SearchText = "optifabric"
|
||||
Log("[Comp] 工程列表搜索最终文本:" & Request.SearchText, LogLevel.Debug)
|
||||
Task.Progress = 0.1
|
||||
|
||||
#End Region
|
||||
@@ -1054,10 +1058,17 @@ Retry:
|
||||
Dim ModrinthThread As Thread = Nothing
|
||||
Dim ResultsLock As New Object
|
||||
|
||||
'在 1.14-,部分老 Mod 没有设置支持的加载器,因此添加 Forge 筛选就会出现遗漏
|
||||
'所以,在发起请求时不筛选加载器,然后在返回的结果中自行筛除不是 Forge 的 Mod
|
||||
Dim IsOldForgeRequest = Request.ModLoader = CompModLoaderType.Forge AndAlso Request.GameVersion?.Contains(".") AndAlso Val(Request.GameVersion.Split(".")(1)) < 14
|
||||
If IsOldForgeRequest Then Request.ModLoader = CompModLoaderType.Any
|
||||
Dim CurseForgeUrl As String = Request.GetCurseForgeAddress()
|
||||
Dim ModrinthUrl As String = Request.GetModrinthAddress()
|
||||
If IsOldForgeRequest Then Request.ModLoader = CompModLoaderType.Forge '设置回去
|
||||
|
||||
Try
|
||||
|
||||
'启动 CurseForge 线程
|
||||
Dim CurseForgeUrl As String = Task.Input.GetCurseForgeAddress()
|
||||
Dim CurseForgeFailed As Boolean = False
|
||||
If CurseForgeUrl IsNot Nothing Then
|
||||
CurseForgeThread = RunInNewThread(
|
||||
@@ -1070,7 +1081,7 @@ Retry:
|
||||
Dim ProjectList As New List(Of CompProject)
|
||||
For Each JsonEntry As JObject In RequestResult("data")
|
||||
Dim Project As New CompProject(JsonEntry)
|
||||
If Task.Input.Type = CompType.ResourcePack AndAlso Project.Tags.Contains("数据包") Then Continue For 'CurseForge 将一些数据包分类成了资源包
|
||||
If Request.Type = CompType.ResourcePack AndAlso Project.Tags.Contains("数据包") Then Continue For 'CurseForge 将一些数据包分类成了资源包
|
||||
ProjectList.Add(Project)
|
||||
Next
|
||||
'更新结果
|
||||
@@ -1090,7 +1101,6 @@ Retry:
|
||||
End If
|
||||
|
||||
'启动 Modrinth 线程
|
||||
Dim ModrinthUrl As String = Task.Input.GetModrinthAddress()
|
||||
Dim ModrinthFailed As Boolean = False
|
||||
If ModrinthUrl IsNot Nothing Then
|
||||
ModrinthThread = RunInNewThread(
|
||||
@@ -1123,9 +1133,9 @@ Retry:
|
||||
|
||||
'等待线程结束
|
||||
If CurseForgeThread IsNot Nothing Then CurseForgeThread.Join()
|
||||
If Task.IsAborted Then Exit Sub '会自动触发 Finally
|
||||
If Task.IsAborted Then Return '会自动触发 Finally
|
||||
If ModrinthThread IsNot Nothing Then ModrinthThread.Join()
|
||||
If Task.IsAborted Then Exit Sub
|
||||
If Task.IsAborted Then Return
|
||||
|
||||
'确保存在结果
|
||||
Storage.ErrorMessage = Nothing
|
||||
@@ -1133,11 +1143,11 @@ Retry:
|
||||
If [Error] IsNot Nothing Then
|
||||
Throw [Error]
|
||||
Else
|
||||
If IsChineseSearch AndAlso Not (Task.Input.Type = CompType.Mod OrElse Task.Input.Type = CompType.DataPack) Then
|
||||
If IsChineseSearch AndAlso Not (Request.Type = CompType.Mod OrElse Request.Type = CompType.DataPack) Then
|
||||
Throw New Exception("没有搜索结果,请尝试使用英文搜索")
|
||||
ElseIf Task.Input.Source = CompSourceType.CurseForge AndAlso Task.Input.Tag.StartsWithF("/") Then
|
||||
ElseIf Request.Source = CompSourceType.CurseForge AndAlso Request.Tag.StartsWithF("/") Then
|
||||
Throw New Exception("CurseForge 不兼容所选的类型")
|
||||
ElseIf Task.Input.Source = CompSourceType.Modrinth AndAlso Task.Input.Tag.EndsWithF("/") Then
|
||||
ElseIf Request.Source = CompSourceType.Modrinth AndAlso Request.Tag.EndsWithF("/") Then
|
||||
Throw New Exception("Modrinth 不兼容所选的类型")
|
||||
Else
|
||||
Throw New Exception("没有搜索结果")
|
||||
@@ -1146,17 +1156,22 @@ Retry:
|
||||
ElseIf [Error] IsNot Nothing Then
|
||||
'有结果但是有错误
|
||||
If CurseForgeFailed Then
|
||||
Storage.ErrorMessage = $"无法连接到 CurseForge,所以目前仅显示了来自 Modrinth 的内容,结果可能不全。{vbCrLf}请尝试使用 VPN 或加速器以改善网络。"
|
||||
Storage.ErrorMessage = $"无法连接到 CurseForge,所以目前仅显示了来自 Modrinth 的内容,搜索结果可能不全。{vbCrLf}请稍后重试,或使用 VPN 以改善网络环境。"
|
||||
Else
|
||||
Storage.ErrorMessage = $"无法连接到 Modrinth,所以目前仅显示了来自 CurseForge 的内容,结果可能不全。{vbCrLf}请尝试使用 VPN 或加速器以改善网络。"
|
||||
Storage.ErrorMessage = $"无法连接到 Modrinth,所以目前仅显示了来自 CurseForge 的内容,搜索结果可能不全。{vbCrLf}请稍后重试,或使用 VPN 以改善网络环境。"
|
||||
End If
|
||||
End If
|
||||
|
||||
Finally
|
||||
If CurseForgeThread IsNot Nothing Then CurseForgeThread.Interrupt()
|
||||
If ModrinthThread IsNot Nothing Then ModrinthThread.Interrupt()
|
||||
CurseForgeThread?.Interrupt()
|
||||
ModrinthThread?.Interrupt()
|
||||
End Try
|
||||
|
||||
'筛除不是 Forge 的 Mod
|
||||
If IsOldForgeRequest Then
|
||||
RawResults = RawResults.Where(Function(p) Not p.ModLoaders.Any() OrElse p.ModLoaders.Contains(CompModLoaderType.Forge)).ToList
|
||||
End If
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "提取非重复项,存储于 RealResults"
|
||||
@@ -1177,9 +1192,9 @@ Retry:
|
||||
|
||||
#Region "检查结果数量,如果不足且可继续,会继续加载下一页"
|
||||
|
||||
If RealResults.Count + Storage.Results.Count < Task.Input.TargetResultCount Then
|
||||
Log($"[Comp] 总结果数需求最少 {Task.Input.TargetResultCount} 个,仅获得了 {RealResults.Count + Storage.Results.Count} 个")
|
||||
If Task.Input.CanContinue AndAlso [Error] Is Nothing Then '如果有下载源失败则不再重试,这时候重试可能导致无限循环
|
||||
If RealResults.Count + Storage.Results.Count < Request.TargetResultCount Then
|
||||
Log($"[Comp] 总结果数需求最少 {Request.TargetResultCount} 个,仅获得了 {RealResults.Count + Storage.Results.Count} 个")
|
||||
If Request.CanContinue AndAlso [Error] Is Nothing Then '如果有下载源失败则不再重试,这时候重试可能导致无限循环
|
||||
Log("[Comp] 将继续尝试加载下一页")
|
||||
GoTo Retry
|
||||
Else
|
||||
@@ -1194,7 +1209,7 @@ Retry:
|
||||
Dim Scores As New Dictionary(Of CompProject, Double) '排序分
|
||||
Dim GetDownloadCountMult =
|
||||
Function(Project As CompProject) As Double
|
||||
Select Case Task.Input.Type
|
||||
Select Case Request.Type
|
||||
Case CompType.Mod, CompType.ModPack
|
||||
Return If(Project.FromCurseForge, 1, 7)
|
||||
Case CompType.DataPack
|
||||
@@ -1205,7 +1220,7 @@ Retry:
|
||||
Return 1
|
||||
End Select
|
||||
End Function
|
||||
If String.IsNullOrEmpty(Task.Input.SearchText) Then
|
||||
If String.IsNullOrEmpty(Request.SearchText) Then
|
||||
'如果没有搜索文本,按下载量将结果排序
|
||||
For Each Result As CompProject In RealResults
|
||||
Scores.Add(Result, Result.DownloadCount * GetDownloadCountMult(Result))
|
||||
@@ -1638,7 +1653,7 @@ Retry:
|
||||
'如果为整合包就不会有 Dependencies 信息,所以不用管
|
||||
Dim Deps As List(Of String) = Files.SelectMany(Function(f) f.Dependencies).Distinct.ToList()
|
||||
Deps.Sort()
|
||||
If Not Deps.Any() Then Exit Sub
|
||||
If Not Deps.Any() Then Return
|
||||
Deps = Deps.Where(
|
||||
Function(dep)
|
||||
If Not CompProjectCache.ContainsKey(dep) Then Log($"[Comp] 未找到 ID {dep} 的前置信息", LogLevel.Debug)
|
||||
|
||||
@@ -71,11 +71,7 @@
|
||||
'将可能可用的日志文件导出
|
||||
For Each FilePath In RightLogs
|
||||
Try
|
||||
If FilePath.Contains("crash-") Then
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath).Split(vbCrLf.ToCharArray)))
|
||||
Else
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath, Encoding.UTF8).Split(vbCrLf.ToCharArray)))
|
||||
End If
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath).Split(vbCrLf.ToCharArray)))
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取可能的崩溃日志文件失败(" & FilePath & ")")
|
||||
End Try
|
||||
@@ -117,11 +113,7 @@ Extracted:
|
||||
If Not TargetFile.Exists OrElse TargetFile.Length = 0 Then Continue For
|
||||
Dim Ext As String = TargetFile.Extension.ToLower
|
||||
If Ext = ".log" OrElse Ext = ".txt" Then
|
||||
If TargetFile.Name.StartsWithF("crash-") Then
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName).Split(vbCrLf.ToCharArray)))
|
||||
Else
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName, Encoding.UTF8).Split(vbCrLf.ToCharArray)))
|
||||
End If
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName).Split(vbCrLf.ToCharArray)))
|
||||
Else
|
||||
File.Delete(TargetFile.FullName)
|
||||
End If
|
||||
@@ -137,20 +129,21 @@ Extracted:
|
||||
Private Enum AnalyzeFileType
|
||||
HsErr
|
||||
MinecraftLog
|
||||
ExtraLog
|
||||
ExtraLogFile
|
||||
ExtraReportFile
|
||||
CrashReport
|
||||
End Enum
|
||||
Private DirectFile As KeyValuePair(Of String, String())? = Nothing '在弹窗中选择直接打开的文件
|
||||
''' <summary>
|
||||
''' 从 AnalyzeRawFiles 中提取实际有用的文本片段存储到 AnalyzeFiles,并整理可用于生成报告的文件。
|
||||
''' 返回找到的用于分析的项目数。
|
||||
''' 返回是否有足够信息可用于分析。
|
||||
''' </summary>
|
||||
Public Function Prepare() As Integer
|
||||
Public Function Prepare() As Boolean
|
||||
Log("[Crash] 步骤 2:准备日志文本")
|
||||
|
||||
'对日志文件进行分类
|
||||
DirectFile = Nothing
|
||||
Dim TotalFiles As New List(Of KeyValuePair(Of AnalyzeFileType, KeyValuePair(Of String, String())))
|
||||
Dim AllFiles As New List(Of KeyValuePair(Of AnalyzeFileType, KeyValuePair(Of String, String())))
|
||||
For Each LogFile In AnalyzeRawFiles
|
||||
Dim MatchName As String = GetFileNameFromPath(LogFile.Key).ToLower
|
||||
Dim TargetType As AnalyzeFileType
|
||||
@@ -170,27 +163,35 @@ Extracted:
|
||||
TargetType = AnalyzeFileType.MinecraftLog
|
||||
If DirectFile Is Nothing Then DirectFile = LogFile
|
||||
Else
|
||||
TargetType = AnalyzeFileType.ExtraLog
|
||||
TargetType = AnalyzeFileType.ExtraLogFile
|
||||
End If
|
||||
ElseIf MatchName.EndsWithF(".log", True) OrElse MatchName.EndsWithF(".txt", True) Then
|
||||
TargetType = AnalyzeFileType.ExtraLog
|
||||
ElseIf MatchName.EndsWithF(".log", True) Then
|
||||
TargetType = AnalyzeFileType.ExtraLogFile
|
||||
ElseIf MatchName.EndsWithF(".txt", True) Then
|
||||
TargetType = AnalyzeFileType.ExtraReportFile
|
||||
Else
|
||||
Log("[Crash] " & MatchName & " 分类为 Ignore")
|
||||
Continue For
|
||||
End If
|
||||
If Not LogFile.Value.Any() Then
|
||||
Log("[Crash] " & MatchName & " 由于内容为空跳过")
|
||||
Else
|
||||
TotalFiles.Add(New KeyValuePair(Of AnalyzeFileType, KeyValuePair(Of String, String()))(TargetType, LogFile))
|
||||
If LogFile.Value.Any Then
|
||||
AllFiles.Add(New KeyValuePair(Of AnalyzeFileType, KeyValuePair(Of String, String()))(TargetType, LogFile))
|
||||
Log("[Crash] " & MatchName & " 分类为 " & GetStringFromEnum(TargetType))
|
||||
Else
|
||||
Log("[Crash] " & MatchName & " 由于内容为空跳过")
|
||||
End If
|
||||
Next
|
||||
|
||||
'若只有额外日志,则将它们视作 Minecraft 日志
|
||||
If AllFiles.Any() AndAlso AllFiles.All(Function(p) p.Key = AnalyzeFileType.ExtraLogFile) Then
|
||||
Log("[Crash] 由于仅发现了额外日志,将它们视作 Minecraft 日志进行分析")
|
||||
AllFiles = AllFiles.Select(Function(p) New KeyValuePair(Of AnalyzeFileType, KeyValuePair(Of String, String()))(AnalyzeFileType.MinecraftLog, p.Value)).ToList
|
||||
End If
|
||||
|
||||
'将分类后的文件分别写入
|
||||
For Each SelectType In {AnalyzeFileType.MinecraftLog, AnalyzeFileType.HsErr, AnalyzeFileType.ExtraLog, AnalyzeFileType.CrashReport}
|
||||
For Each SelectType In {AnalyzeFileType.MinecraftLog, AnalyzeFileType.HsErr, AnalyzeFileType.ExtraLogFile, AnalyzeFileType.CrashReport}
|
||||
'获取该种类的所有文件 {文件路径 -> 文件内容行}
|
||||
Dim SelectedFiles As New List(Of KeyValuePair(Of String, String()))
|
||||
For Each File In TotalFiles
|
||||
For Each File In AllFiles
|
||||
If SelectType = File.Key Then SelectedFiles.Add(File.Value)
|
||||
Next
|
||||
If Not SelectedFiles.Any() Then Continue For
|
||||
@@ -232,54 +233,59 @@ Extracted:
|
||||
Next
|
||||
'选择一份最佳的来自启动器的游戏日志
|
||||
For Each FileName As String In {"rawoutput.log", "启动器日志.txt", "log1.txt", "游戏崩溃前的输出.txt", "PCL2 启动器日志.txt", "PCL 启动器日志.txt"}
|
||||
If FileNameDict.ContainsKey(FileName) Then
|
||||
Dim CurrentLog = FileNameDict(FileName)
|
||||
'截取 “以下为游戏输出的最后一段内容” 后的内容
|
||||
Dim HasLauncherMark As Boolean = False
|
||||
For Each Line In CurrentLog.Value
|
||||
If HasLauncherMark Then
|
||||
LogMc += Line & vbLf
|
||||
ElseIf Line.Contains("以下为游戏输出的最后一段内容") Then
|
||||
HasLauncherMark = True
|
||||
Log("[Crash] 找到 PCL 输出的游戏实时日志头")
|
||||
End If
|
||||
Next
|
||||
'导入后 500 行
|
||||
If Not HasLauncherMark Then LogMc += GetHeadTailLines(CurrentLog.Value, 0, 500)
|
||||
LogMc = LogMc.TrimEnd(vbCrLf.ToCharArray)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为启动器日志")
|
||||
Exit For
|
||||
End If
|
||||
If Not FileNameDict.ContainsKey(FileName) Then Continue For
|
||||
Dim CurrentLog = FileNameDict(FileName)
|
||||
'截取 “以下为游戏输出的最后一段内容” 后的内容
|
||||
Dim HasLauncherMark As Boolean = False
|
||||
For Each Line In CurrentLog.Value
|
||||
If HasLauncherMark Then
|
||||
LogMc += Line & vbLf
|
||||
ElseIf Line.Contains("以下为游戏输出的最后一段内容") Then
|
||||
HasLauncherMark = True
|
||||
Log("[Crash] 找到 PCL 输出的游戏实时日志头")
|
||||
End If
|
||||
Next
|
||||
'导入后 500 行
|
||||
If Not HasLauncherMark Then LogMc += GetHeadTailLines(CurrentLog.Value, 0, 500)
|
||||
LogMc = LogMc.TrimEnd(vbCrLf.ToCharArray)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为启动器日志")
|
||||
Exit For
|
||||
Next
|
||||
'选择一份最佳的 Minecraft Log
|
||||
For Each FileName As String In {"latest.log", "latest log.txt", "debug.log", "debug log.txt"}
|
||||
If FileNameDict.ContainsKey(FileName) Then
|
||||
Dim CurrentLog = FileNameDict(FileName)
|
||||
LogMc += GetHeadTailLines(CurrentLog.Value, 250, 500)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为 Minecraft 日志")
|
||||
Exit For
|
||||
End If
|
||||
If Not FileNameDict.ContainsKey(FileName) Then Continue For
|
||||
Dim CurrentLog = FileNameDict(FileName)
|
||||
LogMc += GetHeadTailLines(CurrentLog.Value, 1500, 500)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为 Minecraft 日志")
|
||||
Exit For
|
||||
Next
|
||||
'查找 Debug Log
|
||||
For Each FileName As String In {"debug.log", "debug log.txt"}
|
||||
If FileNameDict.ContainsKey(FileName) Then
|
||||
Dim CurrentLog = FileNameDict(FileName)
|
||||
LogMcDebug += GetHeadTailLines(CurrentLog.Value, 1000, 0)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为 Minecraft Debug 日志")
|
||||
Exit For
|
||||
End If
|
||||
If Not FileNameDict.ContainsKey(FileName) Then Continue For
|
||||
Dim CurrentLog = FileNameDict(FileName)
|
||||
LogMcDebug += GetHeadTailLines(CurrentLog.Value, 1000, 0)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为 Minecraft Debug 日志")
|
||||
Exit For
|
||||
Next
|
||||
'检查错误
|
||||
'兜底
|
||||
If LogMc = "" Then
|
||||
LogMc = Nothing
|
||||
Throw New Exception("无法找到匹配的 Minecraft Log")
|
||||
If LogMcDebug <> "" Then '如果没有找到 Minecraft 日志,则使用 Debug 日志作为兜底
|
||||
LogMc = LogMcDebug
|
||||
ElseIf FileNameDict.Any() Then '如果都没有找到,则使用第一个文件
|
||||
Dim CurrentLog = FileNameDict.First.Value
|
||||
LogMc += GetHeadTailLines(CurrentLog.Value, 1500, 500)
|
||||
Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为兜底日志")
|
||||
Else
|
||||
LogMc = Nothing
|
||||
Throw New Exception("无法找到匹配的 Minecraft Log")
|
||||
End If
|
||||
End If
|
||||
If LogMcDebug = "" Then LogMcDebug = Nothing
|
||||
Case AnalyzeFileType.ExtraLog
|
||||
Case AnalyzeFileType.ExtraLogFile, AnalyzeFileType.ExtraReportFile
|
||||
'全部丢过去
|
||||
For Each SelectedFile In SelectedFiles
|
||||
OutputFiles.Add(SelectedFile.Key)
|
||||
Log("[Crash] 输出报告:" & SelectedFile.Key & ",作为额外日志")
|
||||
Log("[Crash] 输出报告:" & SelectedFile.Key & ",不用作分析")
|
||||
Next
|
||||
End Select
|
||||
Catch ex As Exception
|
||||
@@ -287,15 +293,13 @@ Extracted:
|
||||
End Try
|
||||
Next
|
||||
|
||||
'获取种类数
|
||||
Dim ResultCount As Integer = If(LogMc Is Nothing, 0, 1) + If(LogHs Is Nothing, 0, 1) + If(LogCrash Is Nothing, 0, 1)
|
||||
If ResultCount = 0 Then
|
||||
Log("[Crash] 步骤 2:准备日志文本完成,没有任何可供分析的日志")
|
||||
Else
|
||||
'结束
|
||||
Prepare = LogMc IsNot Nothing OrElse LogHs IsNot Nothing OrElse LogCrash IsNot Nothing
|
||||
If Prepare Then
|
||||
Log(("[Crash] 步骤 2:准备日志文本完成,找到" & If(LogMc Is Nothing, "", "游戏日志、") & If(LogMcDebug Is Nothing, "", "游戏 Debug 日志、") & If(LogHs Is Nothing, "", "虚拟机日志、") & If(LogCrash Is Nothing, "", "崩溃日志、")).TrimEnd("、") & "用作分析")
|
||||
Else
|
||||
Log("[Crash] 步骤 2:准备日志文本完成,没有任何可供分析的日志")
|
||||
End If
|
||||
Return ResultCount
|
||||
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 输出字符串的前后某些行,并统一行尾为 vbLf (正则 \n)、删除空行和重复行。
|
||||
@@ -386,7 +390,7 @@ Extracted:
|
||||
''' </summary>
|
||||
Public Sub Analyze(Optional Version As McVersion = Nothing)
|
||||
Log("[Crash] 步骤 3:分析崩溃原因")
|
||||
LogAll = (If(LogMc, "") & If(LogMcDebug, "") & If(LogHs, "") & If(LogCrash, ""))
|
||||
LogAll = If(LogMc, If(LogMcDebug, "")) & If(LogHs, "") & If(LogCrash, "")
|
||||
|
||||
'1. 精准日志匹配,中/高优先级
|
||||
AnalyzeCrit1()
|
||||
@@ -472,7 +476,7 @@ Done:
|
||||
'空白分析
|
||||
If LogMc Is Nothing AndAlso LogHs Is Nothing AndAlso LogCrash Is Nothing Then
|
||||
AppendReason(CrashReason.没有可用的分析文件)
|
||||
Exit Sub
|
||||
Return
|
||||
End If
|
||||
|
||||
'崩溃报告分析,高优先级
|
||||
@@ -614,9 +618,9 @@ Done:
|
||||
Dim IsMixin As Boolean = MixinAnalyze(LogMc)
|
||||
'常规信息
|
||||
If LogMc.Contains("An exception was thrown, the game will display an error screen and halt.") Then AppendReason(CrashReason.Forge报错, RegexSeek(LogMc, "(?<=the game will display an error screen and halt.[\n\r]+[^\n]+?Exception: )[\s\S]+?(?=\n\tat)")?.Trim(vbCrLf))
|
||||
If LogMc.Contains("A potential solution has been determined:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("A potential solution has been determined, this may resolve your problem:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined, this may resolve your problem:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("确定了一种可能的解决方法,这样做可能会解决你的问题:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=确定了一种可能的解决方法,这样做可能会解决你的问题:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("A potential solution has been determined:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined:\n)(\s+ - [^\n]+\n)+"), ""), "(?<=\s+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("A potential solution has been determined, this may resolve your problem:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined, this may resolve your problem:\n)(\s+ - [^\n]+\n)+"), ""), "(?<=\s+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("确定了一种可能的解决方法,这样做可能会解决你的问题:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=确定了一种可能的解决方法,这样做可能会解决你的问题:\n)(\s+ - [^\n]+\n)+"), ""), "(?<=\s+)[^\n]+"), vbLf))
|
||||
If Not IsMixin AndAlso LogMc.Contains("due to errors, provided by ") Then '在 #3104 的情况下,这一句导致 OptiFabric 的 Mixin 失败错判为 Fabric Loader 加载失败
|
||||
AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogMc, "(?<=due to errors, provided by ')[^']+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||
End If
|
||||
@@ -873,7 +877,7 @@ NextStack:
|
||||
Try
|
||||
'获取文件路径
|
||||
RunInUiWait(Sub() FileAddress = SelectSaveFile("选择保存位置", "错误报告-" & Date.Now.ToString("G").Replace("/", "-").Replace(":", ".").Replace(" ", "_") & ".zip", "Minecraft 错误报告(*.zip)|*.zip"))
|
||||
If String.IsNullOrEmpty(FileAddress) Then Exit Sub
|
||||
If String.IsNullOrEmpty(FileAddress) Then Return
|
||||
Directory.CreateDirectory(GetPathFromFullPath(FileAddress))
|
||||
If File.Exists(FileAddress) Then File.Delete(FileAddress)
|
||||
'输出诊断信息
|
||||
@@ -896,9 +900,10 @@ NextStack:
|
||||
End Select
|
||||
If File.Exists(OutputFile) Then
|
||||
If FileEncoding Is Nothing Then FileEncoding = GetEncoding(ReadFileBytes(OutputFile))
|
||||
WriteFile(TempFolder & "Report\" & FileName,
|
||||
SecretFilter(ReadFile(OutputFile, FileEncoding), If(FileName = "启动脚本.bat", "F", "*")),
|
||||
Encoding:=FileEncoding)
|
||||
Dim FileContent As String = ReadFile(OutputFile, FileEncoding)
|
||||
FileContent = FilterAccessToken(FileContent, If(FileName = "启动脚本.bat", "F", "*"))
|
||||
FileContent = FilterUserName(FileContent, "*")
|
||||
WriteFile(TempFolder & "Report\" & FileName, FileContent, Encoding:=FileEncoding)
|
||||
Log($"[Crash] 导出文件:{FileName},编码:{FileEncoding.HeaderName}")
|
||||
End If
|
||||
Next
|
||||
@@ -908,7 +913,7 @@ NextStack:
|
||||
Hint("错误报告已导出!", HintType.Finish)
|
||||
Catch ex As Exception
|
||||
Log(ex, "导出错误报告失败", LogLevel.Feedback)
|
||||
Exit Sub
|
||||
Return
|
||||
End Try
|
||||
OpenExplorer(FileAddress)
|
||||
End Select
|
||||
@@ -937,7 +942,7 @@ NextStack:
|
||||
Case CrashReason.内存不足
|
||||
Results.Add("Minecraft 内存不足,导致其无法继续运行。\n这很可能是因为电脑内存不足、游戏分配的内存不足,或是配置要求过高。\n\n你可以尝试在 更多 → 百宝箱 中选择 内存优化,然后再启动游戏。\n如果还是不行,请在启动设置中增加为游戏分配的内存,并删除配置要求较高的材质、Mod、光影。\n如果依然不奏效,请在开始游戏前尽量关闭其他软件,或者……换台电脑?\h")
|
||||
Case CrashReason.使用OpenJ9
|
||||
Results.Add("游戏因为使用 Open J9 而崩溃了。\n请在启动设置的 Java 选择一项中改用非 OpenJ9 的 Java,然后再启动游戏。")
|
||||
Results.Add("游戏因为使用 OpenJ9 而崩溃了。\n请在启动设置的 Java 选择一项中改用非 OpenJ9 的 Java,然后再启动游戏。")
|
||||
Case CrashReason.使用JDK
|
||||
Results.Add("游戏似乎因为使用 JDK,或 Java 版本过高而崩溃了。\n请在启动设置的 Java 选择一项中改用 JRE 8(Java 8),然后再启动游戏。\n如果你没有安装 JRE 8,你可以从网络中下载、安装一个。")
|
||||
Case CrashReason.Java版本过高
|
||||
@@ -1019,7 +1024,7 @@ NextStack:
|
||||
Case CrashReason.OptiFine与Forge不兼容
|
||||
Results.Add("由于 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n\n请前往 OptiFine 官网(https://optifine.net/downloads)查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏。")
|
||||
Case CrashReason.ShadersMod与OptiFine同时安装
|
||||
Results.Add("无需同时安装 Optifine 和 Shaders Mod,OptiFine 已经集成了 Shaders Mod 的功能。\n在删除 Shaders Mod 后,游戏即可正常运行。")
|
||||
Results.Add("无需同时安装 OptiFine 和 Shaders Mod,OptiFine 已经集成了 Shaders Mod 的功能。\n在删除 Shaders Mod 后,游戏即可正常运行。")
|
||||
Case CrashReason.低版本Forge与高版本Java不兼容
|
||||
Results.Add("由于低版本 Forge 与当前 Java 不兼容,导致了游戏崩溃。\n\n请尝试以下解决方案:\n - 更新 Forge 到 36.2.26 或更高版本\n - 换用版本低于 1.8.0.320 的 Java")
|
||||
Case CrashReason.版本Json中存在多个Forge
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
'检查是否有要求的版本(#5195)
|
||||
If Not String.IsNullOrEmpty(Loader.Input) Then
|
||||
Dim Id = Loader.Input
|
||||
If Not DlClientListLoader.Output.Value("versions").Any(Function(v) v("id") = Id) Then
|
||||
If DlClientListLoader.Output.Value IsNot Nothing AndAlso Not DlClientListLoader.Output.Value("versions").Any(Function(v) v("id") = Id) Then
|
||||
Throw New Exception("BMCLAPI 源未包含目标版本 " & Id)
|
||||
End If
|
||||
End If
|
||||
@@ -1291,7 +1291,7 @@
|
||||
'检查加载器成功
|
||||
MainLoader.Output = SubLoader.Key.Output
|
||||
DlSourceLoaderAbort(LoaderList)
|
||||
Exit Sub
|
||||
Return
|
||||
ElseIf BeforeLoadersAllFailed Then
|
||||
'此前的加载器全部失败,直接启动后续加载器
|
||||
If WaitCycle < SubLoader.Value * 100 Then WaitCycle = SubLoader.Value * 100
|
||||
@@ -1333,7 +1333,7 @@
|
||||
'检查父加载器中断
|
||||
If MainLoader.IsAborted Then
|
||||
DlSourceLoaderAbort(LoaderList)
|
||||
Exit Sub
|
||||
Return
|
||||
End If
|
||||
Loop
|
||||
End Sub
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
''' 检查并获取 Java 详细信息。在 Java 存在异常时抛出错误。
|
||||
''' </summary>
|
||||
Public Sub Check()
|
||||
If IsChecked Then Exit Sub
|
||||
If IsChecked Then Return
|
||||
Dim Output As String = Nothing
|
||||
Try
|
||||
'确定文件存在
|
||||
@@ -108,6 +108,9 @@
|
||||
If Not File.Exists(PathFolder & "java.exe") Then
|
||||
Throw New FileNotFoundException("未找到 java.exe 文件", PathFolder & "java.exe")
|
||||
End If
|
||||
If File.Exists(PathFolder & "pdf-bookmark") Then
|
||||
Throw New Exception("不兼容 PDF Bookmark 的 Java") '#5326
|
||||
End If
|
||||
IsJre = Not File.Exists(PathFolder & "javac.exe")
|
||||
'运行 -version
|
||||
Output = ShellAndGetOutput(PathFolder & "java.exe", "-version", 15000).ToLower
|
||||
@@ -668,7 +671,7 @@ Wait:
|
||||
Private Sub JavaSearchFolder(OriginalPath As DirectoryInfo, ByRef Results As Dictionary(Of String, Boolean), Source As Boolean, Optional IsFullSearch As Boolean = False)
|
||||
Try
|
||||
'确认目录存在
|
||||
If Not OriginalPath.Exists Then Exit Sub
|
||||
If Not OriginalPath.Exists Then Return
|
||||
Dim Path As String = OriginalPath.FullName.Replace("\\", "\")
|
||||
If Not Path.EndsWithF("\") Then Path += "\"
|
||||
'若该目录有 Java,则加入结果
|
||||
|
||||
@@ -65,7 +65,7 @@ Public Module ModLaunch
|
||||
''' 记录启动日志。
|
||||
''' </summary>
|
||||
Public Sub McLaunchLog(Text As String)
|
||||
Text = SecretFilter(Text, "*")
|
||||
Text = FilterUserName(FilterAccessToken(Text, "*"), "*")
|
||||
RunInUi(Sub() FrmLaunchRight.LabLog.Text += vbCrLf & "[" & GetTimeNow() & "] " & Text)
|
||||
Log("[Launch] " & Text)
|
||||
End Sub
|
||||
@@ -578,11 +578,7 @@ SkipLogin:
|
||||
Private Sub McLoginServerStart(Data As LoaderTask(Of McLoginServer, McLoginResult))
|
||||
Dim Input As McLoginServer = Data.Input
|
||||
Dim NeedRefresh As Boolean = False, WasRefreshed As Boolean = False
|
||||
Dim LogUsername As String = Input.UserName
|
||||
If LogUsername.Contains("@") AndAlso Setup.Get("UiLauncherEmail") Then
|
||||
LogUsername = AccountFilter(LogUsername)
|
||||
End If
|
||||
McLaunchLog("登录方式:" & Input.Description & "(" & LogUsername & ")")
|
||||
McLaunchLog("登录方式:" & Input.Description)
|
||||
Data.Progress = 0.05
|
||||
'尝试登录
|
||||
If (Not Data.Input.ForceReselectProfile) AndAlso
|
||||
@@ -602,7 +598,7 @@ SkipLogin:
|
||||
McLaunchLog("验证登录失败:" & AllMessage)
|
||||
If (AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout")) AndAlso Not AllMessage.Contains("403") Then
|
||||
McLaunchLog("已触发超时登录失败")
|
||||
Throw New Exception("$登录失败:连接登录服务器超时。" & vbCrLf & "请检查你的网络状况是否良好,或尝试使用 VPN!")
|
||||
Throw New Exception("$登录失败:你的网络环境不佳,导致难以连接到海外服务器。" & vbCrLf & "请稍后重试,或使用加速器或 VPN 以改善网络环境。")
|
||||
End If
|
||||
End Try
|
||||
Data.Progress = 0.25
|
||||
@@ -845,7 +841,7 @@ LoginFinish:
|
||||
" - 只注册了账号,但没有加入对应服务器。")
|
||||
End Select
|
||||
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") OrElse AllMessage.Contains("网络请求失败") Then
|
||||
Throw New Exception("$登录失败:连接登录服务器超时。" & vbCrLf & "请检查你的网络状况是否良好,或尝试使用 VPN!")
|
||||
Throw New Exception("$登录失败:你的网络环境不佳,导致难以连接到海外服务器。" & vbCrLf & "请稍后重试,或使用加速器或 VPN 以改善网络环境。")
|
||||
ElseIf ex.Message.StartsWithF("$") Then
|
||||
Throw
|
||||
Else
|
||||
@@ -956,7 +952,7 @@ Retry:
|
||||
End If
|
||||
Throw New Exception("$$")
|
||||
ElseIf ex.Message.Contains("2148916235") Then
|
||||
MyMsgBox($"你的网络所在的国家或地区无法登录微软账号。{vbCrLf}请尝试使用加速器或 VPN。", "登录失败", "我知道了")
|
||||
MyMsgBox($"你的网络所在的国家或地区无法登录微软账号。{vbCrLf}请使用加速器或 VPN。", "登录失败", "我知道了")
|
||||
Throw New Exception("$$")
|
||||
ElseIf ex.Message.Contains("2148916238") Then
|
||||
If MyMsgBox("该账号年龄不足,你需要先修改出生日期,然后才能登录。" & vbCrLf &
|
||||
@@ -1084,8 +1080,7 @@ Retry:
|
||||
Uuid = McLoginMojangUuid(SkinName, False)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "离线启动时使用的正版皮肤获取失败")
|
||||
MyMsgBox("由于设置的离线启动时使用的正版皮肤获取失败,游戏将以无皮肤的方式启动。" & vbCrLf & "请检查你的网络是否通畅,或尝试使用 VPN!" & vbCrLf & vbCrLf & "详细的错误信息:" & ex.Message, "皮肤获取失败")
|
||||
Log(ex, "皮肤信息获取失败,游戏将以无皮肤的方式启动", LogLevel.Hint)
|
||||
End Try
|
||||
Case 4
|
||||
'自定义
|
||||
@@ -1221,14 +1216,14 @@ Retry:
|
||||
'选择 Java
|
||||
McLaunchLog("Java 版本需求:最低 " & MinVer.ToString & ",最高 " & MaxVer.ToString)
|
||||
McLaunchJavaSelected = JavaSelect("$$", MinVer, MaxVer, McVersionCurrent)
|
||||
If Task.IsAborted Then Exit Sub
|
||||
If Task.IsAborted Then Return
|
||||
If McLaunchJavaSelected IsNot Nothing Then
|
||||
McLaunchLog("选择的 Java:" & McLaunchJavaSelected.ToString)
|
||||
Exit Sub
|
||||
Return
|
||||
End If
|
||||
|
||||
'无合适的 Java
|
||||
If Task.IsAborted Then Exit Sub '中断加载会导致 JavaSelect 异常地返回空值,误判找不到 Java
|
||||
If Task.IsAborted Then Return '中断加载会导致 JavaSelect 异常地返回空值,误判找不到 Java
|
||||
McLaunchLog("无合适的 Java,需要确认是否自动下载")
|
||||
Dim JavaCode As String
|
||||
If MinVer >= New Version(1, 22) Then '潜在的向后兼容
|
||||
@@ -1276,7 +1271,7 @@ Retry:
|
||||
'检查下载结果
|
||||
If JavaSearchLoader.State <> LoadState.Loading Then JavaSearchLoader.State = LoadState.Waiting '2872#
|
||||
McLaunchJavaSelected = JavaSelect("$$", MinVer, MaxVer, McVersionCurrent)
|
||||
If Task.IsAborted Then Exit Sub
|
||||
If Task.IsAborted Then Return
|
||||
If McLaunchJavaSelected IsNot Nothing Then
|
||||
McLaunchLog("选择的 Java:" & McLaunchJavaSelected.ToString)
|
||||
Else
|
||||
@@ -1355,11 +1350,11 @@ Retry:
|
||||
End If
|
||||
'编码参数(#4700、#5892、#5909)
|
||||
If McLaunchJavaSelected.VersionCode > 8 Then
|
||||
If Not Arguments.Contains("-Dstdout.encoding=") Then Arguments += " -Dstdout.encoding=UTF-8"
|
||||
If Not Arguments.Contains("-Dstderr.encoding=") Then Arguments += " -Dstderr.encoding=UTF-8"
|
||||
If Not Arguments.Contains("-Dstdout.encoding=") Then Arguments = "-Dstdout.encoding=UTF-8 " & Arguments
|
||||
If Not Arguments.Contains("-Dstderr.encoding=") Then Arguments = "-Dstderr.encoding=UTF-8 " & Arguments
|
||||
End If
|
||||
If McLaunchJavaSelected.VersionCode >= 18 Then
|
||||
If Not Arguments.Contains("-Dfile.encoding=") Then Arguments += " -Dfile.encoding=COMPAT"
|
||||
If Not Arguments.Contains("-Dfile.encoding=") Then Arguments = "-Dfile.encoding=COMPAT " & Arguments
|
||||
End If
|
||||
'替换参数
|
||||
Dim ReplaceArguments = McLaunchArgumentsReplace(McVersionCurrent, Loader)
|
||||
@@ -1785,7 +1780,7 @@ NextVersion:
|
||||
Catch ex As UnauthorizedAccessException
|
||||
McLaunchLog("删除多余文件访问被拒绝,跳过删除步骤")
|
||||
McLaunchLog("实际的错误信息:" & GetExceptionSummary(ex))
|
||||
Exit Sub
|
||||
Return
|
||||
End Try
|
||||
Next
|
||||
|
||||
@@ -2100,25 +2095,24 @@ IgnoreCustomSkin:
|
||||
'输出 bat
|
||||
Try
|
||||
Dim CmdString As String =
|
||||
$"{If(McLaunchJavaSelected.VersionCode > 8 AndAlso McLaunchJavaSelected.VersionCode < 18, "chcp 65001>nul" & vbCrLf, "")}" &
|
||||
$"{If(McLaunchJavaSelected.VersionCode > 8, "chcp 65001>nul" & vbCrLf, "")}" &
|
||||
"@echo off" & vbCrLf &
|
||||
$"title 启动 - {McVersionCurrent.Name}" & vbCrLf &
|
||||
"echo 游戏正在启动,请稍候。" & vbCrLf &
|
||||
$"set APPDATA=""{ShortenPath(McVersionCurrent.PathIndie)}""" & vbCrLf &
|
||||
$"cd /D ""{ShortenPath(McVersionCurrent.PathIndie)}""" & vbCrLf &
|
||||
CustomCommandGlobal & vbCrLf &
|
||||
CustomCommandVersion & vbCrLf &
|
||||
$"""{McLaunchJavaSelected.PathJava}"" {McLaunchArgument}" & vbCrLf &
|
||||
"echo 游戏已退出。" & vbCrLf &
|
||||
"pause"
|
||||
WriteFile(If(CurrentLaunchOptions.SaveBatch, Path & "PCL\LatestLaunch.bat"), SecretFilter(CmdString, "F"),
|
||||
WriteFile(If(CurrentLaunchOptions.SaveBatch, Path & "PCL\LatestLaunch.bat"), FilterAccessToken(CmdString, "F"),
|
||||
Encoding:=If(McLaunchJavaSelected.VersionCode > 8, Encoding.UTF8, Encoding.Default))
|
||||
If CurrentLaunchOptions.SaveBatch IsNot Nothing Then
|
||||
McLaunchLog("导出启动脚本完成,强制结束启动过程")
|
||||
AbortHint = "导出启动脚本成功!"
|
||||
OpenExplorer(CurrentLaunchOptions.SaveBatch)
|
||||
Loader.Parent.Abort()
|
||||
Exit Sub '导出脚本完成
|
||||
Return '导出脚本完成
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "输出启动脚本失败")
|
||||
@@ -2189,8 +2183,6 @@ IgnoreCustomSkin:
|
||||
StartInfo.EnvironmentVariables("appdata") = ShortenPath(PathMcFolder)
|
||||
|
||||
'设置其他参数
|
||||
StartInfo.StandardErrorEncoding = If(McLaunchJavaSelected.VersionCode > 8, Encoding.UTF8, Nothing)
|
||||
StartInfo.StandardOutputEncoding = If(McLaunchJavaSelected.VersionCode > 8, Encoding.UTF8, Nothing)
|
||||
StartInfo.WorkingDirectory = ShortenPath(McVersionCurrent.PathIndie)
|
||||
StartInfo.UseShellExecute = False
|
||||
StartInfo.RedirectStandardOutput = True
|
||||
@@ -2205,7 +2197,7 @@ IgnoreCustomSkin:
|
||||
If Loader.IsAborted Then
|
||||
McLaunchLog("由于取消启动,已强制结束游戏进程") '#1631
|
||||
GameProcess.Kill()
|
||||
Exit Sub
|
||||
Return
|
||||
End If
|
||||
Loader.Output = GameProcess
|
||||
McLaunchProcess = GameProcess
|
||||
|
||||
@@ -127,7 +127,7 @@ Public Module ModMinecraft
|
||||
''' </summary>
|
||||
Public Sub McFolderLauncherProfilesJsonCreate(Folder As String)
|
||||
Try
|
||||
If File.Exists(Folder & "launcher_profiles.json") Then Exit Sub
|
||||
If File.Exists(Folder & "launcher_profiles.json") Then Return
|
||||
Dim ResultJson As String =
|
||||
"{
|
||||
""profiles"": {
|
||||
@@ -165,10 +165,10 @@ Public Module ModMinecraft
|
||||
Return _McVersionCurrent
|
||||
End Get
|
||||
Set(value As McVersion)
|
||||
If ReferenceEquals(_McVersionLast, value) Then Exit Property
|
||||
If ReferenceEquals(_McVersionLast, value) Then Return
|
||||
_McVersionCurrent = value '由于有可能是 Nothing,导致无法初始化,才得这样弄一圈
|
||||
_McVersionLast = value
|
||||
If value Is Nothing Then Exit Property
|
||||
If value Is Nothing Then Return
|
||||
'重置缓存的 Mod 文件夹
|
||||
PageDownloadCompDetail.CachedFolder = Nothing
|
||||
'统一通行证重判
|
||||
@@ -208,6 +208,7 @@ Public Module ModMinecraft
|
||||
Public ReadOnly Property PathIndie As String
|
||||
Get
|
||||
If Setup.IsUnset("VersionArgumentIndieV2", Version:=Me) Then
|
||||
If Not IsLoaded Then Load()
|
||||
'决定该版本是否应该被隔离
|
||||
Dim ShouldBeIndie =
|
||||
Function() As Boolean
|
||||
@@ -224,17 +225,17 @@ Public Module ModMinecraft
|
||||
Return True
|
||||
End If
|
||||
'根据全局的默认设置决定是否隔离
|
||||
Log($"[Minecraft] 版本隔离初始化({Name}):从全局默认设置中({Setup.Get("LaunchArgumentIndieV2")})判断")
|
||||
Dim IsRelease As Boolean = State = McVersionState.Fool OrElse State = McVersionState.Old OrElse State = McVersionState.Snapshot
|
||||
Dim IsRelease As Boolean = State <> McVersionState.Fool AndAlso State <> McVersionState.Old AndAlso State <> McVersionState.Snapshot
|
||||
Log($"[Minecraft] 版本隔离初始化({Name}):从全局默认设置中({Setup.Get("LaunchArgumentIndieV2")})判断,State {GetStringFromEnum(State)},IsRelease {IsRelease},Modable {Modable}")
|
||||
Select Case Setup.Get("LaunchArgumentIndieV2")
|
||||
Case 0 '关闭
|
||||
Return False
|
||||
Case 1 '仅隔离可安装 Mod 的版本
|
||||
Return Modable
|
||||
Case 2 '仅隔离非正式版
|
||||
Return IsRelease
|
||||
Return Not IsRelease
|
||||
Case 3 '隔离非正式版与可安装 Mod 的版本
|
||||
Return Modable OrElse IsRelease
|
||||
Return Not IsRelease OrElse Modable
|
||||
Case Else '隔离所有版本
|
||||
Return True
|
||||
End Select
|
||||
@@ -1133,7 +1134,7 @@ Reload:
|
||||
|
||||
'改变当前选择的版本
|
||||
OnLoaded:
|
||||
If Loader.IsAborted Then Exit Sub
|
||||
If Loader.IsAborted Then Return
|
||||
If McVersionList.Any(Function(v) v.Key <> McVersionCardType.Error) Then
|
||||
'尝试读取已储存的选择
|
||||
Dim SavedSelection As String = ReadIni(Path & "PCL.ini", "Version")
|
||||
@@ -1145,7 +1146,7 @@ OnLoaded:
|
||||
McVersionCurrent = Version
|
||||
Setup.Set("LaunchVersionSelect", McVersionCurrent.Name)
|
||||
Log("[Minecraft] 选择该文件夹储存的 Minecraft 版本:" & McVersionCurrent.Path)
|
||||
Exit Sub
|
||||
Return
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
@@ -1595,7 +1596,7 @@ OnLoaded:
|
||||
Try
|
||||
For Each SkinProperty In GetJson(SkinString)("properties")
|
||||
If SkinProperty("name") = "textures" Then
|
||||
SkinValue = SkinProperty("value").Replace("http:","https:")
|
||||
SkinValue = SkinProperty("value").Replace("http:", "https:")
|
||||
Exit Try
|
||||
End If
|
||||
Next
|
||||
@@ -2263,7 +2264,7 @@ OnLoaded:
|
||||
End If
|
||||
Next
|
||||
'进行提示
|
||||
If Version Is Nothing Then Exit Sub
|
||||
If Version Is Nothing Then Return
|
||||
Dim Time As Date = Version("releaseTime")
|
||||
Dim MsgBoxText As String = $"新版本:{VersionName}{vbCrLf}" &
|
||||
If((Date.Now - Time).TotalDays > 1, "更新时间:" & Time.ToString, "更新于:" & GetTimeSpanString(Time - Date.Now, False))
|
||||
@@ -2368,26 +2369,33 @@ NextEntry:
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 为邮箱地址或手机号账号进行部分打码。
|
||||
''' 打码字符串中的 AccessToken。
|
||||
''' </summary>
|
||||
Public Function AccountFilter(Account As String) As String
|
||||
If Account.Contains("@") Then
|
||||
'是邮箱
|
||||
Dim Splits = Account.Split("@")
|
||||
'If Splits(0).Count >= 6 Then
|
||||
' '前半部分至少 6 位,屏蔽后 4 位
|
||||
' Return Mid(Splits(0), 1, Splits(0).Count - 4) & "****" & "@" & Splits(1)
|
||||
'Else
|
||||
'前半部分不到 6 位,返回全 *
|
||||
Return "".PadLeft(Splits(0).Count, "*") & "@" & Splits(1)
|
||||
'End If
|
||||
ElseIf Account.Count >= 6 Then
|
||||
'至少 6 位,屏蔽后 4 位
|
||||
Return Mid(Account, 1, Account.Count - 4) & "****"
|
||||
Else
|
||||
'不到 6 位,返回全 *
|
||||
Return "".PadLeft(Account.Count, "*")
|
||||
Public Function FilterAccessToken(Raw As String, FilterChar As Char) As String
|
||||
'打码 "accessToken " 后的内容
|
||||
If Raw.Contains("accessToken ") Then
|
||||
For Each Token In RegexSearch(Raw, "(?<=accessToken ([^ ]{5}))[^ ]+(?=[^ ]{5})")
|
||||
Raw = Raw.Replace(Token, New String(FilterChar, Token.Count))
|
||||
Next
|
||||
End If
|
||||
'打码当前登录的结果
|
||||
Dim AccessToken As String = McLoginLoader.Output.AccessToken
|
||||
If AccessToken IsNot Nothing AndAlso AccessToken.Length >= 10 AndAlso Raw.ContainsF(AccessToken, True) AndAlso
|
||||
McLoginLoader.Output.Uuid <> McLoginLoader.Output.AccessToken Then 'UUID 和 AccessToken 一样则不打码
|
||||
Raw = Raw.Replace(AccessToken, Left(AccessToken, 5) & New String(FilterChar, AccessToken.Length - 10) & Right(AccessToken, 5))
|
||||
End If
|
||||
Return Raw
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 打码字符串中的 Windows 用户名。
|
||||
''' </summary>
|
||||
Public Function FilterUserName(Raw As String, FilterChar As Char) As String
|
||||
If Raw.Contains(":\Users\") Then
|
||||
For Each Token In RegexSearch(Raw, "(?<=:\\Users\\)[^\\]+")
|
||||
Raw = Raw.Replace(Token, New String(FilterChar, Token.Count))
|
||||
Next
|
||||
End If
|
||||
Return Raw
|
||||
End Function
|
||||
|
||||
End Module
|
||||
|
||||
@@ -188,9 +188,9 @@ Public Module ModMod
|
||||
Private _Dependencies As New Dictionary(Of String, String)
|
||||
Private Sub AddDependency(ModID As String, Optional VersionRequirement As String = Nothing)
|
||||
'确保信息正确
|
||||
If ModID Is Nothing OrElse ModID.Count < 2 Then Exit Sub
|
||||
If ModID Is Nothing OrElse ModID.Count < 2 Then Return
|
||||
ModID = ModID.ToLower
|
||||
If ModID = "name" OrElse Val(ModID).ToString = ModID Then Exit Sub '跳过 name 与纯数字 id
|
||||
If ModID = "name" OrElse Val(ModID).ToString = ModID Then Return '跳过 name 与纯数字 id
|
||||
If VersionRequirement Is Nothing OrElse ((Not VersionRequirement.Contains(".")) AndAlso (Not VersionRequirement.Contains("-"))) OrElse VersionRequirement.Contains("$") Then
|
||||
VersionRequirement = Nothing
|
||||
Else
|
||||
@@ -279,7 +279,7 @@ Public Module ModMod
|
||||
''' 进行文件可用性检查与 .class 以外的信息获取。
|
||||
''' </summary>
|
||||
Public Sub Load(Optional ForceReload As Boolean = False)
|
||||
If IsLoaded AndAlso Not ForceReload Then Exit Sub
|
||||
If IsLoaded AndAlso Not ForceReload Then Return
|
||||
'初始化
|
||||
Init()
|
||||
Dim Jar As ZipArchive = Nothing
|
||||
@@ -819,7 +819,7 @@ Finished:
|
||||
Try
|
||||
RunInUiWait(Sub() If FrmVersionMod IsNot Nothing Then FrmVersionMod.Load.Text = "正在更新 Mod")
|
||||
Do Until Not PageVersionMod.UpdatingVersions.Contains(Loader.Input)
|
||||
If Loader.IsAborted Then Exit Sub
|
||||
If Loader.IsAborted Then Return
|
||||
Thread.Sleep(100)
|
||||
Loop
|
||||
Finally
|
||||
@@ -872,7 +872,7 @@ Finished:
|
||||
Dim ModUpdateList As New List(Of McMod)
|
||||
For Each ModFile As FileInfo In ModFileList
|
||||
Loader.Progress += 0.94 / ModFileList.Count
|
||||
If Loader.IsAborted Then Exit Sub
|
||||
If Loader.IsAborted Then Return
|
||||
'加载 McMod 对象
|
||||
Dim ModEntry As New McMod(ModFile.FullName)
|
||||
ModEntry.Load()
|
||||
@@ -912,7 +912,7 @@ Finished:
|
||||
End Function)
|
||||
|
||||
'回设
|
||||
If Loader.IsAborted Then Exit Sub
|
||||
If Loader.IsAborted Then Return
|
||||
Loader.Output = ModList
|
||||
|
||||
'开始联网加载
|
||||
@@ -950,7 +950,7 @@ Finished:
|
||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")), JObject)
|
||||
Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息")
|
||||
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
||||
If ModrinthVersion.Count = 0 Then Exit Sub
|
||||
If ModrinthVersion.Count = 0 Then Return
|
||||
Dim ModrinthMapping As New Dictionary(Of String, List(Of McMod))
|
||||
For Each Entry In Mods
|
||||
If Not ModrinthVersion.ContainsKey(Entry.ModrinthHash) Then Continue For
|
||||
@@ -963,10 +963,10 @@ Finished:
|
||||
Dim File As New CompFile(ModrinthVersion(Entry.ModrinthHash), CompType.Mod)
|
||||
If Entry.CompFile Is Nothing OrElse Entry.CompFile.ReleaseDate < File.ReleaseDate Then Entry.CompFile = File
|
||||
Next
|
||||
If Loader.IsAbortedWithThread(MainThread) Then Exit Sub
|
||||
If Loader.IsAbortedWithThread(MainThread) Then Return
|
||||
Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息")
|
||||
'步骤 3:获取工程信息
|
||||
If Not ModrinthMapping.Any() Then Exit Sub
|
||||
If Not ModrinthMapping.Any() Then Return
|
||||
Dim ModrinthProject = CType(GetJson(DlModRequest(
|
||||
$"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]",
|
||||
"GET", "", "application/json")), JArray)
|
||||
@@ -1013,13 +1013,13 @@ Finished:
|
||||
Dim CurseForgeHashes As New List(Of UInteger)
|
||||
For Each Entry In Mods
|
||||
CurseForgeHashes.Add(Entry.CurseForgeHash)
|
||||
If Loader.IsAbortedWithThread(MainThread) Then Exit Sub
|
||||
If Loader.IsAbortedWithThread(MainThread) Then Return
|
||||
Next
|
||||
Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432", "POST",
|
||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer)
|
||||
Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息")
|
||||
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
||||
If Not CurseForgeRaw.Any() Then Exit Sub
|
||||
If Not CurseForgeRaw.Any() Then Return
|
||||
Dim CurseForgeMapping As New Dictionary(Of Integer, List(Of McMod))
|
||||
For Each Project In CurseForgeRaw
|
||||
Dim ProjectId = Project("id").ToString
|
||||
@@ -1034,10 +1034,10 @@ Finished:
|
||||
If Entry.CompFile Is Nothing OrElse Entry.CompFile.ReleaseDate < File.ReleaseDate Then Entry.CompFile = File
|
||||
Next
|
||||
Next
|
||||
If Loader.IsAbortedWithThread(MainThread) Then Exit Sub
|
||||
If Loader.IsAbortedWithThread(MainThread) Then Return
|
||||
Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息")
|
||||
'步骤 3:获取工程信息
|
||||
If Not CurseForgeMapping.Any() Then Exit Sub
|
||||
If Not CurseForgeMapping.Any() Then Return
|
||||
Dim CurseForgeProject = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods", "POST",
|
||||
$"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")), JObject)("data")
|
||||
Dim UpdateFileIds As New Dictionary(Of Integer, List(Of McMod)) 'FileId -> 本地 Mod 文件列表
|
||||
@@ -1078,7 +1078,7 @@ Finished:
|
||||
Next
|
||||
Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息")
|
||||
'步骤 4:获取更新文件信息
|
||||
If Not UpdateFileIds.Any() Then Exit Sub
|
||||
If Not UpdateFileIds.Any() Then Return
|
||||
Dim CurseForgeFiles = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST",
|
||||
$"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")), JObject)("data")
|
||||
Dim UpdateFiles As New Dictionary(Of McMod, CompFile)
|
||||
@@ -1114,13 +1114,13 @@ Finished:
|
||||
End Sub, "Mod List Detail Loader CurseForge")
|
||||
'等待线程结束
|
||||
Do Until EndedThreadCount = 2
|
||||
If Loader.IsAborted Then Exit Sub
|
||||
If Loader.IsAborted Then Return
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
'保存缓存
|
||||
Mods = Mods.Where(Function(m) m.Comp IsNot Nothing).ToList()
|
||||
Log($"[Mod] 联网获取本地 Mod 信息完成,为 {Mods.Count} 个 Mod 更新缓存")
|
||||
If Not Mods.Any() Then Exit Sub
|
||||
If Not Mods.Any() Then Return
|
||||
For Each Entry In Mods
|
||||
Entry.CompLoaded = Not IsFailed
|
||||
Cache(Entry.ModrinthHash & McVersion & ModLoaders.Join("")) = Entry.ToJson()
|
||||
|
||||
@@ -8,7 +8,7 @@ Public Module ModModpack
|
||||
''' </summary>
|
||||
Public Sub ModpackInstall()
|
||||
Dim File As String = SelectFile("整合包文件(*.rar;*.zip;*.mrpack)|*.rar;*.zip;*.mrpack", "选择整合包压缩文件") '选择整合包文件
|
||||
If String.IsNullOrEmpty(File) Then Exit Sub
|
||||
If String.IsNullOrEmpty(File) Then Return
|
||||
RunInThread(
|
||||
Sub()
|
||||
Try
|
||||
@@ -128,7 +128,7 @@ Retry:
|
||||
'完全不知道为啥会出现文件正在被另一进程使用的问题,总之加个重试
|
||||
If RetryCount < 5 Then
|
||||
Thread.Sleep(RetryCount * 2000)
|
||||
If Loader IsNot Nothing AndAlso Loader.LoadingState <> MyLoading.MyLoadingState.Run Then Exit Sub
|
||||
If Loader IsNot Nothing AndAlso Loader.LoadingState <> MyLoading.MyLoadingState.Run Then Return
|
||||
RetryCount += 1
|
||||
GoTo Retry
|
||||
Else
|
||||
@@ -693,6 +693,7 @@ Retry:
|
||||
End If
|
||||
'解压
|
||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||
Dim SetupFile As String = $"{PathMcFolder}versions\{VersionName}\PCL\Setup.ini"
|
||||
Dim InstallLoaders As New List(Of LoaderBase)
|
||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
@@ -701,15 +702,13 @@ Retry:
|
||||
InstallTemp & ArchiveBaseFolder & "overrides",
|
||||
PathMcFolder & "versions\" & VersionName,
|
||||
Task, 0.4)
|
||||
'JVM 参数
|
||||
If Json("launchInfo") IsNot Nothing Then
|
||||
Dim LaunchInfo As JObject = Json("launchInfo")
|
||||
If LaunchInfo.ContainsKey("javaArgument") Then WriteIni(SetupFile, "VersionAdvanceJvm", String.Join(" ", LaunchInfo("javaArgument")))
|
||||
If LaunchInfo.ContainsKey("launchArgument") Then WriteIni(SetupFile, "VersionAdvanceGame", String.Join(" ", LaunchInfo("launchArgument")))
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||
If Json("launchInfo") Is Nothing Then
|
||||
Log("[ModPack] 整合包中未找到启动信息,已跳过")
|
||||
Else
|
||||
Dim launchArgument As String = String.Join(" ", Json("launchInfo")("launchArgument"))
|
||||
Dim javaArgument As String = String.Join(" ", Json("launchInfo")("javaArgument"))
|
||||
WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionAdvanceJvm", javaArgument)
|
||||
WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionAdvanceGame", launchArgument)
|
||||
End If
|
||||
'构造加载器
|
||||
If Json("addons") Is Nothing Then Throw New Exception("该 MCBBS 整合包未提供游戏版本附加信息,无法安装!")
|
||||
Dim Addons As New Dictionary(Of String, String)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
TriggerLauncherShutdown = False
|
||||
End If
|
||||
Next
|
||||
If IsWatcherRunning = IsRunning Then Exit Sub
|
||||
If IsWatcherRunning = IsRunning Then Return
|
||||
IsWatcherRunning = IsRunning
|
||||
If IsWatcherRunning Then
|
||||
MinecraftStart()
|
||||
@@ -81,7 +81,7 @@
|
||||
WatcherStateChanged()
|
||||
|
||||
'初始化进程与日志读取
|
||||
Me.GameProcess = Loader.Input
|
||||
GameProcess = Loader.Input
|
||||
GameProcess.BeginOutputReadLine()
|
||||
GameProcess.BeginErrorReadLine()
|
||||
AddHandler GameProcess.OutputDataReceived, AddressOf LogReceived
|
||||
@@ -118,7 +118,7 @@
|
||||
Return _State
|
||||
End Get
|
||||
Set(value As MinecraftState)
|
||||
If _State = value Then Exit Property
|
||||
If _State = value Then Return
|
||||
_State = value
|
||||
WatcherStateChanged()
|
||||
End Set
|
||||
@@ -144,7 +144,7 @@
|
||||
'输出文本
|
||||
Dim Copyed As New List(Of String)
|
||||
SyncLock WaitingLogLock
|
||||
If Not WaitingLog.Any() Then Exit Sub
|
||||
If Not WaitingLog.Any() Then Return
|
||||
Copyed = WaitingLog
|
||||
WaitingLog = New List(Of String)(1000)
|
||||
End SyncLock
|
||||
@@ -180,8 +180,9 @@
|
||||
Public LatestLog As New Queue(Of String)
|
||||
Private Sub GameLog(Text As String)
|
||||
'预处理
|
||||
If Text Is Nothing Then Exit Sub
|
||||
If Text Is Nothing Then Return
|
||||
Text = Text.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr, vbCrLf)
|
||||
'If Text.Contains("�����") Then Hint("检测到错误的日志编码:" & Text)
|
||||
'加入预存储
|
||||
LatestLog.Enqueue(Text)
|
||||
If LatestLog.Count >= 501 Then LatestLog.Dequeue()
|
||||
@@ -256,8 +257,8 @@
|
||||
Private WindowHandle As IntPtr
|
||||
Private Sub TimerWindow()
|
||||
Try
|
||||
If GameProcess.HasExited Then Exit Sub
|
||||
If IsWindowFinished Then Exit Sub
|
||||
If GameProcess.HasExited Then Return
|
||||
If IsWindowFinished Then Return
|
||||
'获取全部窗口,检查是否有新增的
|
||||
Dim MinecraftWindow As KeyValuePair(Of IntPtr, String)? = Nothing
|
||||
Try
|
||||
@@ -267,7 +268,7 @@
|
||||
Log(ex, "由于反作弊或安全软件拦截,PCL 无法操作游戏窗口", LogLevel.Hint)
|
||||
IsWindowFinished = True
|
||||
End Try
|
||||
If MinecraftWindow Is Nothing Then Exit Sub
|
||||
If MinecraftWindow Is Nothing Then Return
|
||||
Dim MinecraftWindowName = MinecraftWindow.Value.Value, MinecraftWindowHandle = MinecraftWindow.Value.Key
|
||||
'已找到窗口
|
||||
If Not MinecraftWindowName.StartsWithF("FML") Then
|
||||
@@ -307,27 +308,27 @@
|
||||
TryGetMinecraftWindow = Nothing
|
||||
EnumWindows(
|
||||
Sub(hwnd As IntPtr, lParam As Integer)
|
||||
If TryGetMinecraftWindow IsNot Nothing Then Exit Sub
|
||||
If TryGetMinecraftWindow IsNot Nothing Then Return
|
||||
'检查类名
|
||||
Dim str As New StringBuilder(512)
|
||||
GetClassName(hwnd, str, str.Capacity)
|
||||
Dim ClassName As String = str.ToString
|
||||
If Not (ClassName = "GLFW30" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Exit Sub
|
||||
If Not (ClassName = "GLFW30" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Return
|
||||
'获取窗口标题名
|
||||
str = New StringBuilder(512)
|
||||
GetWindowText(hwnd, str, str.Capacity)
|
||||
Dim WindowText As String = str.ToString
|
||||
'有的 Mod 可以修改窗口标题,所以不能检测是否为 Minecraft 打头,这并不准确
|
||||
'部分版本会搞个 GLFW message window 出来所以得反选
|
||||
If Not (WindowText.StartsWithF("FML") OrElse (WindowText <> "PopupMessageWindow") AndAlso Not WindowText.StartsWithF("GLFW")) Then Exit Sub
|
||||
If Not (WindowText.StartsWithF("FML") OrElse (WindowText <> "PopupMessageWindow") AndAlso Not WindowText.StartsWithF("GLFW")) Then Return
|
||||
'获取窗口关联的进程
|
||||
Dim ProcessId As Integer
|
||||
GetWindowThreadProcessId(hwnd, ProcessId)
|
||||
Try
|
||||
If Process.GetProcessById(ProcessId).StartTime < GameProcess.StartTime Then Exit Sub '需要是此后启动的进程
|
||||
If Process.GetProcessById(ProcessId).StartTime < GameProcess.StartTime Then Return '需要是此后启动的进程
|
||||
Catch ex As Exception
|
||||
Log(ex, "枚举 Minecraft 窗口进程失败")
|
||||
Exit Sub
|
||||
Return
|
||||
End Try
|
||||
'返回
|
||||
TryGetMinecraftWindow = New KeyValuePair(Of IntPtr, String)(hwnd, WindowText)
|
||||
@@ -344,7 +345,7 @@
|
||||
|
||||
'崩溃处理
|
||||
Private Sub Crashed()
|
||||
If State = MinecraftState.Crashed OrElse State = MinecraftState.Ended Then Exit Sub
|
||||
If State = MinecraftState.Crashed OrElse State = MinecraftState.Ended Then Return
|
||||
State = MinecraftState.Crashed
|
||||
'崩溃分析
|
||||
WatcherLog("Minecraft 已崩溃,将在 2 秒后开始崩溃分析")
|
||||
|
||||
Reference in New Issue
Block a user