2.13.0.0
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
Public Class CrashAnalyzer
|
||||
Public Class CrashAnalyzer
|
||||
|
||||
'构造函数
|
||||
Private TempFolder As String
|
||||
@@ -24,7 +24,7 @@
|
||||
'简单收集可能的日志文件路径
|
||||
Dim PossibleLogs As New List(Of String)
|
||||
Try
|
||||
PossibleLogs.AddRange(DirectoryUtils.GetFiles(VersionPathIndie & "crash-reports\"))
|
||||
PossibleLogs.AddRange(DirectoryUtils.EnumerateFiles(VersionPathIndie & "crash-reports\", True))
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, "收集 Minecraft 崩溃日志文件夹下的日志失败")
|
||||
End Try
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Public Module ModDownload
|
||||
Public Module ModDownload
|
||||
|
||||
#Region "DlClient* | Minecraft 客户端"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
Throw New Exception("底层版本 " & Instance.Name & " 中无 jar 文件下载信息")
|
||||
End If
|
||||
'检查文件
|
||||
Dim Checker As New FileChecker(MinSize:=1024, ActualSize:=If(Instance.JsonObject("downloads")("client")("size"), -1), Hash:=Instance.JsonObject("downloads")("client")("sha1"))
|
||||
Dim Checker As New FileChecker With {.MinSize = 1024, .ActualSize = If(Instance.JsonObject("downloads")("client")("size"), -1), .Hash = Instance.JsonObject("downloads")("client")("sha1")}
|
||||
If ReturnNothingOnFileUseable AndAlso Checker.Check(Instance.PathVersion & Instance.Name & ".jar") Is Nothing Then Return Nothing '通过校验
|
||||
'返回下载信息
|
||||
Dim JarUrl As String = Instance.JsonObject("downloads")("client")("url")
|
||||
@@ -44,14 +44,14 @@
|
||||
If IndexUrl = "" Then
|
||||
Return Nothing
|
||||
Else
|
||||
Return New NetFile(DlSourceLauncherOrMetaGet(IndexUrl), IndexAddress, New FileChecker(CanUseExistsFile:=False, IsJson:=True))
|
||||
Return New NetFile(DlSourceLauncherOrMetaGet(IndexUrl), IndexAddress, New FileChecker With {.IsJson = True})
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 构造补全某 Minecraft 版本的所有文件的加载器列表。失败会抛出异常。
|
||||
''' </summary>
|
||||
Public Function DlClientFix(Instance As McInstance, CheckAssetsHash As Boolean, AssetsIndexBehaviour As AssetsIndexExistsBehaviour) As List(Of LoaderBase)
|
||||
Public Function DlClientFix(Instance As McInstance, CheckAssetsHash As Boolean, DownloadAssetIndexInBackground As Boolean) As List(Of LoaderBase)
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
|
||||
#Region "下载支持库文件"
|
||||
@@ -69,6 +69,8 @@
|
||||
Else
|
||||
Dim LoadersAssets As New List(Of LoaderBase)
|
||||
'获取资源文件索引地址
|
||||
Dim TempAddressMain As String = Nothing
|
||||
Dim RealAddressMain As String = Nothing
|
||||
LoadersAssets.Add(New LoaderTask(Of String, List(Of NetFile))("分析资源文件索引地址",
|
||||
Sub(Task As LoaderTask(Of String, List(Of NetFile)))
|
||||
Try
|
||||
@@ -76,9 +78,16 @@
|
||||
If IndexFile Is Nothing Then
|
||||
Task.Output = New List(Of NetFile)
|
||||
Logger.Warn($"未找到版本 {Instance.Name} 的合适的资源索引下载地址,游戏 assets 可能缺失")
|
||||
ElseIf AssetsIndexBehaviour <> AssetsIndexExistsBehaviour.AlwaysDownload AndAlso IndexFile.Check.Check(IndexFile.LocalPath) Is Nothing Then
|
||||
Task.Output = New List(Of NetFile)
|
||||
Else
|
||||
ElseIf DownloadAssetIndexInBackground Then
|
||||
If IndexFile.Check.Check(IndexFile.LocalPath) Is Nothing Then
|
||||
Task.Output = New List(Of NetFile)
|
||||
Else
|
||||
Task.Output = New List(Of NetFile) From {IndexFile}
|
||||
End If
|
||||
Else '强制要求重新下载
|
||||
RealAddressMain = IndexFile.LocalPath
|
||||
TempAddressMain = PathTemp & "Cache\" & IndexFile.LocalName
|
||||
IndexFile.LocalPath = TempAddressMain
|
||||
Task.Output = New List(Of NetFile) From {IndexFile}
|
||||
End If
|
||||
Catch ex As Exception
|
||||
@@ -87,65 +96,55 @@
|
||||
End Sub) With {.ProgressWeight = 0.5, .Show = False})
|
||||
'下载资源文件索引
|
||||
LoadersAssets.Add(New LoaderDownload("下载资源文件索引", New List(Of NetFile)) With {.ProgressWeight = 2})
|
||||
'要求独立更新索引
|
||||
If AssetsIndexBehaviour = AssetsIndexExistsBehaviour.DownloadInBackground Then
|
||||
'获取资源文件地址
|
||||
LoadersAssets.Add(New LoaderTask(Of String, List(Of NetFile))("获取资源文件列表",
|
||||
Sub(Task)
|
||||
If TempAddressMain IsNot Nothing Then FileUtils.Move(TempAddressMain, RealAddressMain)
|
||||
Task.Output = McAssetsFixList(Instance, CheckAssetsHash, Task)
|
||||
End Sub) With {.ProgressWeight = 0.01})
|
||||
'下载资源文件
|
||||
LoadersAssets.Add(New LoaderDownload("下载资源文件", New List(Of NetFile)) With {.ProgressWeight = 25})
|
||||
'构造加载器
|
||||
Loaders.Add(New LoaderCombo(Of String)("下载资源文件(主加载器)", LoadersAssets) With {.Block = False, .Show = False, .ProgressWeight = 27})
|
||||
|
||||
'后台独立更新索引
|
||||
If DownloadAssetIndexInBackground Then
|
||||
Dim RealAddressBg As String = Nothing
|
||||
Dim TempAddressBg As String = Nothing
|
||||
Dim LoadersAssetsUpdate As New List(Of LoaderBase)
|
||||
Dim TempAddress As String = Nothing
|
||||
Dim RealAddress As String = Nothing
|
||||
LoadersAssetsUpdate.Add(New LoaderTask(Of String, List(Of NetFile))("后台分析资源文件索引地址",
|
||||
Sub(Task As LoaderTask(Of String, List(Of NetFile)))
|
||||
Dim BackAssetsFile As NetFile = DlClientAssetIndexGet(Instance)
|
||||
If BackAssetsFile Is Nothing Then
|
||||
Logger.Warn($"未找到版本 {Instance.Name} 的合适的资源索引下载地址,游戏 assets 可能缺失")
|
||||
Task.Interrupt()
|
||||
Throw New ThreadInterruptedException
|
||||
Task.Cancel()
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
RealAddress = BackAssetsFile.LocalPath
|
||||
TempAddress = PathTemp & "Cache\" & BackAssetsFile.LocalName
|
||||
BackAssetsFile.LocalPath = TempAddress
|
||||
RealAddressBg = BackAssetsFile.LocalPath
|
||||
TempAddressBg = PathTemp & "Cache\" & BackAssetsFile.LocalName & "_background"
|
||||
BackAssetsFile.LocalPath = TempAddressBg
|
||||
Task.Output = New List(Of NetFile) From {BackAssetsFile}
|
||||
'检查是否需要更新:每天只更新一次
|
||||
If FileUtils.Exists(RealAddress) AndAlso Math.Abs((FileUtils.GetInfo(RealAddress).LastWriteTime.Date - Now.Date).TotalDays) < 1 Then
|
||||
If FileUtils.Exists(RealAddressBg) AndAlso Math.Abs((FileUtils.GetInfo(RealAddressBg).LastWriteTime.Date - Now.Date).TotalDays) < 1 Then
|
||||
Logger.Info("无需更新资源文件索引,取消")
|
||||
Task.Interrupt()
|
||||
Task.Cancel()
|
||||
End If
|
||||
End Sub))
|
||||
LoadersAssetsUpdate.Add(New LoaderDownload("后台下载资源文件索引", New List(Of NetFile)))
|
||||
LoadersAssetsUpdate.Add(New LoaderTask(Of List(Of NetFile), String)("后台复制资源文件索引",
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), String))
|
||||
FileUtils.Copy(TempAddress, RealAddress)
|
||||
McLaunchLog("后台更新资源文件索引成功:" & TempAddress)
|
||||
FileUtils.Move(TempAddressBg, RealAddressBg)
|
||||
McLaunchLog("后台更新资源文件索引成功:" & TempAddressBg)
|
||||
End Sub))
|
||||
Dim Updater As New LoaderCombo(Of String)("后台更新资源文件索引", LoadersAssetsUpdate)
|
||||
Logger.Info("开始后台检查资源文件索引")
|
||||
Updater.Start()
|
||||
End If
|
||||
'获取资源文件地址
|
||||
LoadersAssets.Add(New LoaderTask(Of String, List(Of NetFile))("获取资源文件列表",
|
||||
Sub(Task) Task.Output = McAssetsFixList(Instance, CheckAssetsHash, Task)) With {.ProgressWeight = 0.01})
|
||||
'下载资源文件
|
||||
LoadersAssets.Add(New LoaderDownload("下载资源文件", New List(Of NetFile)) With {.ProgressWeight = 25})
|
||||
'构造加载器
|
||||
Loaders.Add(New LoaderCombo(Of String)("下载资源文件(主加载器)", LoadersAssets) With {.Block = False, .Show = False, .ProgressWeight = 27})
|
||||
End If
|
||||
#End Region
|
||||
|
||||
Return Loaders
|
||||
End Function
|
||||
Public Enum AssetsIndexExistsBehaviour
|
||||
''' <summary>
|
||||
''' 如果文件存在,则不进行下载。
|
||||
''' </summary>
|
||||
DontDownload
|
||||
''' <summary>
|
||||
''' 如果文件存在,则启动新的下载加载器进行独立的更新。
|
||||
''' </summary>
|
||||
DownloadInBackground
|
||||
''' <summary>
|
||||
''' 如果文件存在,也同样进行下载。
|
||||
''' </summary>
|
||||
AlwaysDownload
|
||||
End Enum
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -227,7 +226,7 @@
|
||||
Public DlClientListMojangLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Mojang", AddressOf DlClientListMojangMain)
|
||||
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
Dim StartTime As Long = GetTimeMs()
|
||||
Dim Json As JObject = GetJson(NetRequestByClientRetry("https://launchermeta.mojang.com/mc/game/version_manifest.json", RequireJson:=True))
|
||||
Dim Json As JObject = NetRequestByClientRetry("https://launchermeta.mojang.com/mc/game/version_manifest.json", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Versions As JArray = Json("versions")
|
||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||
@@ -238,7 +237,7 @@
|
||||
Logger.Info($"Mojang 官方源加载耗时:{DeltaTime}ms,{If(DlPreferMojang, "可优先使用官方源", "不优先使用官方源")}")
|
||||
End If
|
||||
'添加 PCL 特供项
|
||||
If FileUtils.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(GetJson(FileUtils.ReadAsString(PathTemp & "Cache\download.json")))
|
||||
If FileUtils.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(FileUtils.ReadAsJson(PathTemp & "Cache\download.json"))
|
||||
'返回
|
||||
Loader.Output = New DlClientListResult With {.IsOfficial = True, .SourceName = "Mojang 官方源", .Value = Json}
|
||||
'MC 更新提示
|
||||
@@ -269,12 +268,12 @@
|
||||
''' </summary>
|
||||
Public DlClientListBmclapiLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
||||
Private Sub DlClientListBmclapiMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
Dim Json As JObject = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json", RequireJson:=True))
|
||||
Dim Json As JObject = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Versions As JArray = Json("versions")
|
||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||
'添加 PCL 特供项
|
||||
If FileUtils.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(GetJson(FileUtils.ReadAsString(PathTemp & "Cache\download.json")))
|
||||
If FileUtils.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(FileUtils.ReadAsJson(PathTemp & "Cache\download.json"))
|
||||
'检查是否有要求的版本(#5195)
|
||||
If Not String.IsNullOrEmpty(Loader.Input) Then
|
||||
Dim Id = Loader.Input
|
||||
@@ -308,7 +307,7 @@
|
||||
DlClientListLoader.WaitForExit(Id, IsForceRestart:=True)
|
||||
Case LoadState.Loading
|
||||
DlClientListLoader.WaitForExit(Id)
|
||||
Case LoadState.Failed, LoadState.Interrupted, LoadState.Waiting
|
||||
Case LoadState.Failed, LoadState.Canceled, LoadState.Waiting
|
||||
DlClientListLoader.WaitForExit(Id, IsForceRestart:=True)
|
||||
End Select
|
||||
'重新查找版本
|
||||
@@ -447,7 +446,7 @@
|
||||
''' </summary>
|
||||
Public DlOptiFineListBmclapiLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Bmclapi", AddressOf DlOptiFineListBmclapiMain)
|
||||
Private Sub DlOptiFineListBmclapiMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
||||
Dim Json As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/optifine/versionList", RequireJson:=True))
|
||||
Dim Json As JArray = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/optifine/versionList", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Versions As New List(Of DlOptiFineListEntry)
|
||||
For Each Token As JObject In Json
|
||||
@@ -531,8 +530,8 @@
|
||||
''' </summary>
|
||||
Public DlForgeListBmclapiLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Bmclapi", AddressOf DlForgeListBmclapiMain)
|
||||
Private Sub DlForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
||||
Dim Result As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft",
|
||||
Encoding:=Encoding.Default, RequireJson:=True))
|
||||
Dim Result As JArray = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft",
|
||||
Encoding:=Encoding.Default, RequireJson:=True).DeserializeJson()
|
||||
Dim Names As List(Of String) = Result.Select(Function(v) v.ToString).ToList
|
||||
If Names.Count < 10 Then Throw New Exception("获取到的版本数量不足")
|
||||
Loader.Output = New DlForgeListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Names}
|
||||
@@ -738,8 +737,8 @@
|
||||
''' Forge 版本列表,BMCLAPI。
|
||||
''' </summary>
|
||||
Public Sub DlForgeVersionBmclapiMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
||||
Dim Json As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
|
||||
Loader.Input.Replace("-", "_"), RequireJson:=True)) '兼容 Forge 1.7.10-pre4,#4057
|
||||
Dim Json As JArray = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
|
||||
Loader.Input.Replace("-", "_"), RequireJson:=True).DeserializeJson() '兼容 Forge 1.7.10-pre4,#4057
|
||||
Dim Versions As New List(Of DlForgeVersionEntry)
|
||||
Try
|
||||
Dim Recommended As String = McDownloadForgeRecommendedGet(Loader.Input)
|
||||
@@ -1026,7 +1025,7 @@
|
||||
''' </summary>
|
||||
Public DlLiteLoaderListOfficialLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Official", AddressOf DlLiteLoaderListOfficialMain)
|
||||
Private Sub DlLiteLoaderListOfficialMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://dl.liteloader.com/versions/versions.json", RequireJson:=True))
|
||||
Dim Result As JObject = NetRequestByClientRetry("https://dl.liteloader.com/versions/versions.json", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Json As JObject = Result("versions")
|
||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||
@@ -1054,7 +1053,7 @@
|
||||
''' </summary>
|
||||
Public DlLiteLoaderListBmclapiLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Bmclapi", AddressOf DlLiteLoaderListBmclapiMain)
|
||||
Private Sub DlLiteLoaderListBmclapiMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json", RequireJson:=True))
|
||||
Dim Result As JObject = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Json As JObject = Result("versions")
|
||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||
@@ -1125,7 +1124,7 @@
|
||||
''' </summary>
|
||||
Public DlFabricListOfficialLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Official", AddressOf DlFabricListOfficialMain)
|
||||
Private Sub DlFabricListOfficialMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://meta.fabricmc.net/v2/versions", RequireJson:=True))
|
||||
Dim Result As JObject = NetRequestByClientRetry("https://meta.fabricmc.net/v2/versions", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Output = New DlFabricListResult With {.IsOfficial = True, .SourceName = "Fabric 官方源", .Value = Result}
|
||||
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
||||
@@ -1140,7 +1139,7 @@
|
||||
''' </summary>
|
||||
Public DlFabricListBmclapiLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Bmclapi", AddressOf DlFabricListBmclapiMain)
|
||||
Private Sub DlFabricListBmclapiMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/fabric-meta/v2/versions", RequireJson:=True))
|
||||
Dim Result As JObject = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/fabric-meta/v2/versions", RequireJson:=True).DeserializeJson()
|
||||
Try
|
||||
Dim Output = New DlFabricListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Result}
|
||||
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
||||
@@ -1197,7 +1196,7 @@
|
||||
Dim Exs As String = ""
|
||||
For Each Source In Urls
|
||||
Try
|
||||
Return GetJson(NetRequestByClient(Source.Url, Method, Content, ContentType, Timeout:=Source.Timeout * 1000, Encoding:=Encoding.UTF8, RequireJson:=True))
|
||||
Return NetRequestByClient(Source.Url, Method, Content, ContentType, Timeout:=Source.Timeout * 1000, Encoding:=Encoding.UTF8, RequireJson:=True).DeserializeJson()
|
||||
Catch ex As Exception
|
||||
Exs += ex.Message + vbCrLf
|
||||
End Try
|
||||
@@ -1328,7 +1327,7 @@
|
||||
If SubLoader.Key.State = LoadState.Finished Then
|
||||
'检查加载器成功
|
||||
MainLoader.Output = SubLoader.Key.Output
|
||||
DlSourceLoaderInterrupt(LoaderList)
|
||||
DlSourceLoaderCancel(LoaderList)
|
||||
Return
|
||||
ElseIf BeforeLoadersAllFailed Then
|
||||
'此前的加载器全部失败,直接启动后续加载器
|
||||
@@ -1360,7 +1359,7 @@
|
||||
End If
|
||||
Next
|
||||
If ErrorInfo Is Nothing Then ErrorInfo = New TimeoutException("下载源连接超时")
|
||||
DlSourceLoaderInterrupt(LoaderList)
|
||||
DlSourceLoaderCancel(LoaderList)
|
||||
Throw ErrorInfo
|
||||
End If
|
||||
Exit For
|
||||
@@ -1369,15 +1368,15 @@
|
||||
Thread.Sleep(10)
|
||||
WaitCycle += 1
|
||||
'检查父加载器中断
|
||||
If MainLoader.IsInterrupted Then
|
||||
DlSourceLoaderInterrupt(LoaderList)
|
||||
If MainLoader.IsCanceled Then
|
||||
DlSourceLoaderCancel(LoaderList)
|
||||
Return
|
||||
End If
|
||||
Loop
|
||||
End Sub
|
||||
Private Sub DlSourceLoaderInterrupt(Of InputType, OutputType)(LoaderList As List(Of KeyValuePair(Of LoaderTask(Of InputType, OutputType), Integer)))
|
||||
Private Sub DlSourceLoaderCancel(Of InputType, OutputType)(LoaderList As List(Of KeyValuePair(Of LoaderTask(Of InputType, OutputType), Integer)))
|
||||
For Each Loader In LoaderList
|
||||
If Loader.Key.State = LoadState.Loading Then Loader.Key.Interrupt()
|
||||
If Loader.Key.State = LoadState.Loading Then Loader.Key.Cancel()
|
||||
Next
|
||||
End Sub
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
Public Module ModLaunch
|
||||
Public Module ModLaunch
|
||||
|
||||
#Region "开始"
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
Public McLaunchWatcher As Watcher
|
||||
Private Sub McLaunchState(Loader As LoaderTask(Of McLaunchOptions, Object))
|
||||
Select Case McLaunchLoader.State
|
||||
Case LoadState.Finished, LoadState.Failed, LoadState.Waiting, LoadState.Interrupted
|
||||
Case LoadState.Finished, LoadState.Failed, LoadState.Waiting, LoadState.Canceled
|
||||
FrmLaunchLeft.PageChangeToLogin()
|
||||
Case LoadState.Loading
|
||||
'在预检测结束后再触发动画
|
||||
@@ -91,7 +91,7 @@
|
||||
''' <summary>
|
||||
''' 指定启动中断时的提示文本。若不为 Nothing 则会显示为绿色。
|
||||
''' </summary>
|
||||
Private InterruptHint As String = Nothing
|
||||
Private CanceledHint As String = Nothing
|
||||
|
||||
'实际的启动方法
|
||||
Private Sub McLaunchStart(Loader As LoaderTask(Of McLaunchOptions, Object))
|
||||
@@ -102,7 +102,7 @@
|
||||
McLaunchPrecheck()
|
||||
McLaunchLog("预检测已通过")
|
||||
Catch ex As Exception
|
||||
If Not ex.Message.StartsWithF("$$") Then Hint(ex.Message, HintType.Red)
|
||||
If Not ex.IsCanceled Then Hint(ex.Message, HintType.Red)
|
||||
Throw
|
||||
End Try
|
||||
Dim IsSavingBatch As Boolean = CurrentLaunchOptions?.SaveBatch IsNot Nothing
|
||||
@@ -113,7 +113,7 @@
|
||||
Dim Loaders As New List(Of LoaderBase) From {
|
||||
New LoaderTask(Of Integer, Integer)("获取 Java", AddressOf McLaunchJava) With {.ProgressWeight = 4, .Block = False},
|
||||
McLoginLoader, '.ProgressWeight = 15, .Block = False
|
||||
New LoaderCombo(Of String)("补全文件", DlClientFix(McInstanceSelected, False, AssetsIndexExistsBehaviour.DownloadInBackground)) With {.ProgressWeight = 15, .Show = False},
|
||||
New LoaderCombo(Of String)("补全文件", DlClientFix(McInstanceSelected, False, True)) With {.ProgressWeight = 15, .Show = False},
|
||||
New LoaderTask(Of String, Integer)("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
|
||||
New LoaderTask(Of Integer, Integer)("解压文件", AddressOf McLaunchNatives) With {.ProgressWeight = 2},
|
||||
New LoaderTask(Of Integer, Integer)("预启动处理", AddressOf McLaunchPrerun) With {.ProgressWeight = 1},
|
||||
@@ -138,7 +138,7 @@
|
||||
If McLoginLoader.State = LoadState.Finished Then McLoginLoader.State = LoadState.Waiting '要求重启登录主加载器,它会自行决定是否启动副加载器
|
||||
'等待加载器执行并更新 UI
|
||||
McLaunchLoaderReal = LaunchLoader
|
||||
InterruptHint = Nothing
|
||||
CanceledHint = Nothing
|
||||
LaunchLoader.Start()
|
||||
'任务栏进度条
|
||||
LoaderTaskbarAdd(LaunchLoader)
|
||||
@@ -157,11 +157,11 @@
|
||||
"Version", McInstanceSelected.VersionDisplayName,
|
||||
"LoginType", Settings.Get(Of McLoginType)("LoginType").ToString)
|
||||
End If
|
||||
Case LoadState.Interrupted
|
||||
If InterruptHint Is Nothing Then
|
||||
Case LoadState.Canceled
|
||||
If CanceledHint Is Nothing Then
|
||||
Hint(If(IsSavingBatch, "已取消导出启动脚本!", "已取消启动!"), HintType.Blue)
|
||||
Else
|
||||
Hint(InterruptHint, HintType.Green)
|
||||
Hint(CanceledHint, HintType.Green)
|
||||
End If
|
||||
Case LoadState.Failed
|
||||
Throw LaunchLoader.Error
|
||||
@@ -169,12 +169,12 @@
|
||||
Throw New Exception("错误的状态改变:" & LaunchLoader.State.ToString())
|
||||
End Select
|
||||
Catch ex As Exception
|
||||
ex.ThrowIfCanceled()
|
||||
Dim CurrentEx = ex
|
||||
NextInner:
|
||||
If CurrentEx.Message.StartsWithF("$") Then
|
||||
'若有以 $ 开头的错误信息,则以此为准显示提示
|
||||
'若错误信息为 $$,则不提示
|
||||
If Not CurrentEx.Message = "$$" Then MyMsgBox(CurrentEx.Message.TrimStart("$"), If(IsSavingBatch, "导出启动脚本失败", "启动失败"))
|
||||
MyMsgBox(CurrentEx.Message.TrimStart("$"), If(IsSavingBatch, "导出启动脚本失败", "启动失败"))
|
||||
Throw
|
||||
ElseIf CurrentEx.InnerException IsNot Nothing Then
|
||||
'检查下一级错误
|
||||
@@ -208,7 +208,7 @@ NextInner:
|
||||
PageOtherTest.MemoryOptimize(False)
|
||||
Finished = True
|
||||
End Sub, "Launch Memory Optimize")
|
||||
Do While Not Finished AndAlso Not Loader.IsInterrupted
|
||||
Do While Not Finished AndAlso Not Loader.IsCanceled
|
||||
If Loader.Progress < 0.7 Then
|
||||
Loader.Progress += 0.007 '10s
|
||||
Else
|
||||
@@ -273,7 +273,7 @@ NextInner:
|
||||
Hint("游戏将以试玩模式启动!", HintType.Red)
|
||||
CurrentLaunchOptions.ExtraGameArgs.Add("--demo")
|
||||
Case 3
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
End Select
|
||||
End If
|
||||
End If
|
||||
@@ -353,7 +353,8 @@ NextInner:
|
||||
Type = McLoginType.Ms
|
||||
End Sub
|
||||
Public Overrides Function GetHashCode() As Integer
|
||||
Return (OAuthRefreshToken & AccessToken & Uuid & UserName & ProfileJson).GetStableHashCode() Mod Integer.MaxValue
|
||||
'不能使用全部信息,这俩就足以在登录输入时确保是同一个用户了
|
||||
Return (OAuthRefreshToken & UserName).GetStableHashCode() Mod Integer.MaxValue
|
||||
End Function
|
||||
End Class
|
||||
Public Class McLoginLegacy
|
||||
@@ -465,7 +466,7 @@ NextInner:
|
||||
Public McLoginLoader As New LoaderTask(Of McLoginData, McLoginResult)("登录", AddressOf McLoginStart, AddressOf McLoginInput, ThreadPriority.BelowNormal) With {.ReloadTimeout = 1, .ProgressWeight = 15, .Block = False}
|
||||
Public Function McLoginInput() As McLoginData
|
||||
Dim LoginData As McLoginData = Nothing
|
||||
Dim LoginType As McLoginType = Settings.Get(Of McLoginType)("LoginType")
|
||||
Dim LoginType = Settings.Get(Of McLoginType)("LoginType")
|
||||
Try
|
||||
Select Case LoginType
|
||||
Case McLoginType.Legacy
|
||||
@@ -489,10 +490,10 @@ NextInner:
|
||||
LoginData = PageLoginAuthSkin.GetLoginData()
|
||||
End If
|
||||
End Select
|
||||
Return LoginData
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, $"获取登录输入信息失败({LoginType})")
|
||||
Throw New Exception($"获取登录输入信息失败({LoginType})", ex)
|
||||
End Try
|
||||
Return LoginData
|
||||
End Function
|
||||
Private Sub McLoginStart(Data As LoaderTask(Of McLoginData, McLoginResult))
|
||||
McLaunchLog("登录加载已开始")
|
||||
@@ -559,24 +560,24 @@ Relogin:
|
||||
OAuthTokens = MsLoginStep1Refresh(Input.OAuthRefreshToken)
|
||||
If OAuthTokens.OAuthAccessToken = "Relogin" Then GoTo Relogin '要求重新打开登录网页认证
|
||||
End If
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
Data.Progress = 0.25
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
Dim OAuthAccessToken As String = OAuthTokens.OAuthAccessToken
|
||||
Dim OAuthRefreshToken As String = OAuthTokens.OAuthRefreshToken
|
||||
Dim XBLToken As String = MsLoginStep2(OAuthAccessToken)
|
||||
Data.Progress = 0.4
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
Dim Tokens = MsLoginStep3(XBLToken)
|
||||
Data.Progress = 0.55
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
Dim LoginResult = MsLoginStep4(Tokens)
|
||||
ExpiresAt = LoginResult.ExpiresAt
|
||||
Data.Progress = 0.7
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
MsLoginStep5(LoginResult.AccessToken)
|
||||
Data.Progress = 0.85
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
Dim Result = MsLoginStep6(LoginResult.AccessToken)
|
||||
Data.Progress = 0.98
|
||||
'输出登录结果
|
||||
@@ -586,14 +587,14 @@ Relogin:
|
||||
Settings.Set("CacheMsV2Name", Result.UserName)
|
||||
Settings.Set("CacheMsV2ProfileJson", Result.ProfileJson)
|
||||
Settings.Set("CacheMsV2Expires", LoginResult.ExpiresAt)
|
||||
Dim MsJson As JObject = GetJson(Settings.Get(Of String)("LoginMsJson"))
|
||||
Dim MsJson As JObject = Settings.Get(Of String)("LoginMsJson").DeserializeJson()
|
||||
MsJson.Remove(Input.UserName) '如果更改了玩家名……
|
||||
MsJson(Result.UserName) = OAuthRefreshToken
|
||||
Settings.Set("LoginMsJson", MsJson.ToString(Newtonsoft.Json.Formatting.None))
|
||||
Data.Output = New McLoginResult With {.AccessToken = LoginResult.AccessToken, .Name = Result.UserName, .Uuid = Result.UUID, .Type = "Microsoft", .ClientToken = Result.UUID, .ProfileJson = Result.ProfileJson}
|
||||
'结束
|
||||
SkipLogin:
|
||||
McLaunchLog($"微软登录结束,AccessToken 将在 {DateTimeOffset.FromUnixTimeSeconds(ExpiresAt).Date.ToLocalTime} 过期")
|
||||
McLaunchLog($"微软登录结束,AccessToken 将在 {DateTimeOffset.FromUnixTimeSeconds(ExpiresAt).LocalDateTime} 过期")
|
||||
Settings.Set("HintBuy", True) '关闭正版购买提示
|
||||
If ThemeUnlock(10, False) Then MyMsgBox("感谢你对正版游戏的支持!" & vbCrLf & "隐藏主题 跳票红 已解锁!", "提示")
|
||||
End Sub
|
||||
@@ -612,7 +613,7 @@ SkipLogin:
|
||||
Settings.Get(Of String)("Cache" & Input.Token & "Name") <> "" Then
|
||||
'尝试验证登录
|
||||
Try
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
McLoginRequestValidate(Data)
|
||||
GoTo LoginFinish
|
||||
Catch ex As Exception
|
||||
@@ -623,7 +624,7 @@ SkipLogin:
|
||||
'尝试刷新登录
|
||||
Refresh:
|
||||
Try
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
McLoginRequestRefresh(Data, NeedRefresh)
|
||||
GoTo LoginFinish
|
||||
Catch ex As Exception
|
||||
@@ -634,7 +635,7 @@ Refresh:
|
||||
End If
|
||||
'尝试普通登录
|
||||
Try
|
||||
If Data.IsInterrupted Then Throw New ThreadInterruptedException
|
||||
If Data.IsCanceled Then Throw New OperationCanceledException
|
||||
NeedRefresh = McLoginRequestLogin(Data)
|
||||
Catch ex As Exception
|
||||
McLaunchLog("登录失败:" & ex.GetDisplay(True))
|
||||
@@ -718,7 +719,7 @@ LoginFinish:
|
||||
End Sub
|
||||
Private Sub McLoginRequestRefresh(ByRef Data As LoaderTask(Of McLoginServer, McLoginResult), RequestUser As Boolean)
|
||||
McLaunchLog("刷新登录开始(Refresh, " & Data.Input.Token & ")")
|
||||
Dim LoginJson As JObject = GetJson(NetRequestByClientRetry(
|
||||
Dim LoginJson As JObject = NetRequestByClientRetry(
|
||||
Data.Input.BaseUrl & "/refresh", HttpMethod.Post,
|
||||
Content:=New JObject(
|
||||
New JProperty("selectedProfile", New JObject(
|
||||
@@ -729,7 +730,7 @@ LoginFinish:
|
||||
New JProperty("requestUser", True)
|
||||
).ToString(Newtonsoft.Json.Formatting.None),
|
||||
Headers:={{"Accept-Language", "zh-CN"}},
|
||||
ContentType:="application/json; charset=utf-8", RequireJson:=True))
|
||||
ContentType:="application/json; charset=utf-8", RequireJson:=True).DeserializeJson()
|
||||
'将登录结果输出
|
||||
If LoginJson("selectedProfile") Is Nothing Then Throw New Exception("选择的角色 " & Settings.Get(Of String)("Cache" & Data.Input.Token & "Name") & " 无效!")
|
||||
Data.Output.AccessToken = LoginJson("accessToken").ToString
|
||||
@@ -755,11 +756,11 @@ LoginFinish:
|
||||
New JProperty("username", Data.Input.UserName),
|
||||
New JProperty("password", Data.Input.Password),
|
||||
New JProperty("requestUser", True))
|
||||
Dim LoginJson As JObject = GetJson(NetRequestByClientRetry(
|
||||
Dim LoginJson As JObject = NetRequestByClientRetry(
|
||||
Data.Input.BaseUrl & "/authenticate", HttpMethod.Post,
|
||||
Content:=RequestData.ToString(Newtonsoft.Json.Formatting.None),
|
||||
Headers:={{"Accept-Language", "zh-CN"}},
|
||||
ContentType:="application/json; charset=utf-8", RequireJson:=True))
|
||||
ContentType:="application/json; charset=utf-8", RequireJson:=True).DeserializeJson()
|
||||
'检查登录结果
|
||||
If LoginJson("availableProfiles").Count = 0 Then
|
||||
If Data.Input.ForceReselectProfile Then Hint("你还没有创建角色,无法更换!", HintType.Red)
|
||||
@@ -824,7 +825,7 @@ LoginFinish:
|
||||
Dim ErrorMessage As String = Nothing
|
||||
Try
|
||||
Dim Response = DirectCast(ex, HttpRequestCodeException).Response
|
||||
If Response.ContainsIgnoreCase("errorMessage") Then ErrorMessage = GetJson(Response)("errorMessage").ToString()
|
||||
If Response.ContainsIgnoreCase("errorMessage") Then ErrorMessage = Response.DeserializeJson()("errorMessage").ToString()
|
||||
Catch
|
||||
End Try
|
||||
If Not String.IsNullOrWhiteSpace(ErrorMessage) Then
|
||||
@@ -874,14 +875,14 @@ LoginFinish:
|
||||
'初始请求
|
||||
Retry:
|
||||
McLaunchLog("开始微软登录步骤 1/6(原始登录)")
|
||||
Dim PrepareJson As JObject = GetJson(NetRequestByClientRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", HttpMethod.Post,
|
||||
Dim PrepareJson As JObject = NetRequestByClientRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", HttpMethod.Post,
|
||||
Content:=$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access",
|
||||
ContentType:="application/x-www-form-urlencoded", RequireJson:=True))
|
||||
ContentType:="application/x-www-form-urlencoded", RequireJson:=True).DeserializeJson()
|
||||
McLaunchLog("网页登录地址:" & PrepareJson("verification_uri").ToString)
|
||||
|
||||
'弹窗
|
||||
Dim Converter As New MyMsgBoxConverter With {.Content = PrepareJson, .ForceWait = True, .Type = MyMsgBoxType.Login}
|
||||
WaitingMyMsgBox.Add(Converter)
|
||||
WaitingMyMsgBox.Enqueue(Converter)
|
||||
While Converter.Result Is Nothing
|
||||
Thread.Sleep(100)
|
||||
End While
|
||||
@@ -891,7 +892,7 @@ Retry:
|
||||
Button2Action:=Sub() OpenWebsite("https://account.live.com/password/Change")) = 1 Then
|
||||
GoTo Retry
|
||||
Else
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
ElseIf TypeOf Converter.Result Is Exception Then
|
||||
Throw CType(Converter.Result, Exception)
|
||||
@@ -906,7 +907,7 @@ Retry:
|
||||
Dim Result As String
|
||||
Try
|
||||
Result = NetRequestByClientMultiple("https://login.live.com/oauth20_token.srf", HttpMethod.Post,
|
||||
Content:=$"client_id={OAuthClientId}&refresh_token={EscapeUtils.FormUrlEscape(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
||||
Content:=$"client_id={OAuthClientId}&refresh_token={StringUtils.FormUrlEscape(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
||||
ContentType:="application/x-www-form-urlencoded",
|
||||
Headers:={{"Accept-Language", "en-US,en;q=0.5"}, {"X-Requested-With", "XMLHttpRequest"}},
|
||||
ThreadCount:=2)
|
||||
@@ -919,16 +920,16 @@ Retry:
|
||||
Return ("Relogin", "")
|
||||
ElseIf Response.Contains("Account security interrupt") Then
|
||||
MyMsgBox("该账号由于安全问题无法登陆,请前往微软账户页获取更多信息。", "登录失败", "我知道了", IsWarn:=True)
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
ElseIf Response.Contains("service abuse") Then
|
||||
MyMsgBox("非常抱歉,该账号已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
Else
|
||||
Throw
|
||||
End If
|
||||
End Try
|
||||
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim ResultJson As JObject = Result.DeserializeJson()
|
||||
Dim AccessToken As String = ResultJson("access_token").ToString
|
||||
Dim RefreshToken As String = ResultJson("refresh_token").ToString
|
||||
Return (AccessToken, RefreshToken)
|
||||
@@ -946,9 +947,8 @@ Retry:
|
||||
""RelyingParty"": ""http://auth.xboxlive.com"",
|
||||
""TokenType"": ""JWT""
|
||||
}"
|
||||
Dim Result As String = NetRequestByClientMultiple("https://user.auth.xboxlive.com/user/authenticate", HttpMethod.Post,
|
||||
Content:=Request, ContentType:="application/json", RequireJson:=True)
|
||||
Return GetJson(Result)("Token").ToString
|
||||
Return NetRequestByClientMultiple("https://user.auth.xboxlive.com/user/authenticate", HttpMethod.Post,
|
||||
Content:=Request, ContentType:="application/json", RequireJson:=True).DeserializeJson()("Token").ToString
|
||||
End Function
|
||||
'微软登录步骤 3:从 XBLToken 获取 {XSTSToken, UHS}
|
||||
Private Function MsLoginStep3(XBLToken As String) As (XSTSToken As String, UHS As String)
|
||||
@@ -970,15 +970,15 @@ Retry:
|
||||
'参考 https://github.com/PrismarineJS/prismarine-auth/blob/master/src/common/Constants.js
|
||||
If ex.Response.Contains("2148916227") Then
|
||||
MyMsgBox("该账号似乎已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
ElseIf ex.Response.Contains("2148916233") Then
|
||||
If MyMsgBox("你尚未注册 Xbox 账户,请在注册后再登录。", "登录提示", "注册", "取消") = 1 Then
|
||||
OpenWebsite("https://signup.live.com/signup")
|
||||
End If
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
ElseIf ex.Response.Contains("2148916235") Then
|
||||
MyMsgBox($"你的网络所在的国家或地区无法登录微软账号。{vbCrLf}请使用加速器或 VPN,然后再试。", "登录失败", "我知道了")
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
ElseIf ex.Response.Contains("2148916238") Then
|
||||
If MyMsgBox("该账号年龄不足,你需要先修改出生日期,然后才能登录。" & vbCrLf &
|
||||
"该账号目前填写的年龄是否在 13 岁以上?", "登录提示", "13 岁以上", "12 岁以下", "我不知道") = 1 Then
|
||||
@@ -990,13 +990,13 @@ Retry:
|
||||
MyMsgBox("请根据打开的网页的说明,修改账号的出生日期(至少改为 18 岁以上)。" & vbCrLf &
|
||||
"在修改成功后等待一分钟,然后再回到 PCL,就可以正常登录了!", "登录提示")
|
||||
End If
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
Else
|
||||
Throw
|
||||
End If
|
||||
End Try
|
||||
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim ResultJson As JObject = Result.DeserializeJson()
|
||||
Return (
|
||||
ResultJson("Token").ToString(), 'XSTSToken
|
||||
ResultJson("DisplayClaims")("xui")(0)("uhs").ToString() 'UHS
|
||||
@@ -1018,15 +1018,18 @@ Retry:
|
||||
ElseIf ex.StatusCode = HttpStatusCode.Forbidden Then
|
||||
Logger.Warn(ex, "微软登录第 4 步汇报 403")
|
||||
Throw New Exception("$当前 IP 的登录尝试异常。" & vbCrLf & "如果你使用了 VPN 或加速器,请把它们关掉或更换节点后再试!")
|
||||
ElseIf ex.StatusCode = HttpStatusCode.ServiceUnavailable Then
|
||||
Logger.Warn(ex, "微软登录第 4 步汇报 503")
|
||||
Throw New Exception("$Mojang 服务器出现问题,请稍后再试。" & vbCrLf & "你的网络是正常的,PCL 也是正常的,是 Mojang 出问题了……")
|
||||
ElseIf ex.Response?.Contains("ACCOUNT_SUSPENDED") Then '#8655
|
||||
MyMsgBox("该账号似乎已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
Else
|
||||
Throw
|
||||
End If
|
||||
End Try
|
||||
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim ResultJson As JObject = Result.DeserializeJson()
|
||||
Return (
|
||||
ResultJson("access_token").ToString,
|
||||
ResultJson("expires_in").ToObject(Of Integer) + GetUnixTimestampUtc() - 1200) '提前 20 分钟视作过期
|
||||
@@ -1038,13 +1041,13 @@ Retry:
|
||||
Dim Result As String = NetRequestByClientMultiple("https://api.minecraftservices.com/entitlements/mcstore",
|
||||
ContentType:="application/json", ThreadCount:=2, Headers:={{"Authorization", "Bearer " & AccessToken}}, RequireJson:=True)
|
||||
Try
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim ResultJson As JObject = Result.DeserializeJson()
|
||||
If Not (ResultJson.ContainsKey("items") AndAlso ResultJson("items").Any) Then
|
||||
Select Case MyMsgBox("你尚未购买正版 Minecraft,或者 Xbox Game Pass 已到期。", "登录失败", "购买 Minecraft", "取消")
|
||||
Case 1
|
||||
OpenWebsite("https://www.xbox.com/zh-cn/games/store/minecraft-java-bedrock-edition-for-pc/9nxp44l49shj")
|
||||
End Select
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, $"微软登录第 5 步异常:{Result}")
|
||||
@@ -1073,12 +1076,12 @@ Retry:
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/msaprofile/mygames/editprofile")
|
||||
End Select
|
||||
End Sub, "Login Failed: Create Profile")
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
Case Else
|
||||
Throw
|
||||
End Select
|
||||
End Try
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim ResultJson As JObject = Result.DeserializeJson()
|
||||
Dim UUID As String = ResultJson("id").ToString
|
||||
Dim UserName As String = ResultJson("name").ToString
|
||||
Return (UUID, UserName, Result)
|
||||
@@ -1131,7 +1134,7 @@ Retry:
|
||||
If Len(Uuid) = 32 Then Return Uuid
|
||||
'从官网获取
|
||||
Try
|
||||
Dim GotJson As JObject = GetJson(NetRequestByClientRetry("https://api.mojang.com/users/profiles/minecraft/" & Name, RequireJson:=True))
|
||||
Dim GotJson As JObject = NetRequestByClientRetry("https://api.mojang.com/users/profiles/minecraft/" & Name, RequireJson:=True).DeserializeJson()
|
||||
If GotJson Is Nothing Then Throw New FileNotFoundException("正版玩家档案不存在(" & Name & ")")
|
||||
Uuid = If(GotJson("id"), "")
|
||||
Catch ex As Exception
|
||||
@@ -1156,183 +1159,16 @@ Retry:
|
||||
|
||||
#Region "Java 处理"
|
||||
|
||||
Public McLaunchJavaSelected As JavaEntry = Nothing
|
||||
Public McLaunchJavaSelected As Java = Nothing
|
||||
Private Sub McLaunchJava(Task As LoaderTask(Of Integer, Integer))
|
||||
Dim MinVer As New Version(0, 0, 0, 0), MaxVer As New Version(999, 999, 999, 999)
|
||||
|
||||
'原版 26-:通过版本号判断
|
||||
If (Not McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.ReleaseTime >= New Date(2024, 4, 2)) OrElse
|
||||
(McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.Version.Vanilla >= New Version(20, 0, 5)) Then
|
||||
'1.20.5+(24w14a+):至少 Java 21
|
||||
MinVer = New Version(1, 21, 0, 0)
|
||||
ElseIf (Not McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.ReleaseTime >= New Date(2021, 11, 16)) OrElse
|
||||
(McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.Version.Vanilla.Major >= 18) Then
|
||||
'1.18 pre2+:至少 Java 17
|
||||
MinVer = New Version(1, 17, 0, 0)
|
||||
ElseIf (Not McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.ReleaseTime >= New Date(2021, 5, 11)) OrElse
|
||||
(McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.Version.Vanilla.Major >= 17) Then
|
||||
'1.17+ (21w19a+):至少 Java 16
|
||||
MinVer = New Version(1, 16, 0, 0)
|
||||
ElseIf McInstanceSelected.ReleaseTime.Year >= 2017 Then 'Minecraft 1.12 与 1.11 的分界线正好是 2017 年,太棒了
|
||||
'1.12+:至少 Java 8
|
||||
MinVer = New Version(1, 8, 0, 0)
|
||||
ElseIf McInstanceSelected.ReleaseTime <= New Date(2013, 5, 1) AndAlso McInstanceSelected.ReleaseTime.Year >= 2001 Then '避免某些版本写个 1960 年
|
||||
'1.5.2-:最高 Java 8
|
||||
MaxVer = New Version(1, 8, 999, 999)
|
||||
McLaunchJavaSelected = SelectOrDownloadJava(McInstanceSelected, True, Task.CreateCancellationToken, Task.CreateSyncProgressProvider)
|
||||
If Task.IsCanceled Then Return
|
||||
If McLaunchJavaSelected Is Nothing Then Throw New OperationCanceledException 'SelectOrDownloadJava 已经会给予适当的提示
|
||||
If ModeDebug Then
|
||||
McLaunchLog($"预期 Java 版本范围:{GetJavaRequirement(McInstanceSelected).Range}")
|
||||
McLaunchLog($"Java 版本设置类别:{Settings.Get(Of Integer)("VersionArgumentJavaV2", McInstanceSelected)}")
|
||||
End If
|
||||
|
||||
'原版 26+:获取 Mojang 要求的 Java 版本
|
||||
Dim RecommendedComponent As String = Nothing
|
||||
Dim RecommendedCode As Integer =
|
||||
If(McInstanceSelected.JsonObject?("javaVersion")?("majorVersion")?.ToObject(Of Integer),
|
||||
If(McInstanceSelected.JsonVersion?("java_version")?.ToObject(Of Integer), 0))
|
||||
If RecommendedCode >= 22 Then
|
||||
McLaunchLog("Mojang 要求至少使用 Java " & RecommendedCode)
|
||||
MinVer = New Version(1, RecommendedCode, 0, 0)
|
||||
RecommendedComponent =
|
||||
If(McInstanceSelected.JsonObject?("javaVersion")?("component")?.ToString,
|
||||
McInstanceSelected.JsonVersion?("java_component")?.ToString)
|
||||
If RecommendedComponent = "" Then RecommendedComponent = Nothing
|
||||
End If
|
||||
|
||||
'OptiFine 检测
|
||||
If McInstanceSelected.Version.HasOptiFine AndAlso McInstanceSelected.Version.Vaild Then '不管非标准版本
|
||||
If McInstanceSelected.Version.Vanilla.Major < 7 Then
|
||||
'<1.7:至多 Java 8
|
||||
MaxVer = New Version(1, 8, 999, 999)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major >= 8 AndAlso McInstanceSelected.Version.Vanilla.Major < 12 Then
|
||||
'1.8 - 1.11:必须恰好 Java 8
|
||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 8, 999, 999)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major = 12 Then
|
||||
'1.12:最高 Java 8
|
||||
MaxVer = New Version(1, 8, 999, 999)
|
||||
End If
|
||||
End If
|
||||
|
||||
'Forge 检测(部分测试结果见 #8432)
|
||||
If McInstanceSelected.Version.HasForge Then
|
||||
If McInstanceSelected.Version.Vanilla >= New Version(6, 0, 1) AndAlso McInstanceSelected.Version.Vanilla <= New Version(7, 0, 2) Then
|
||||
'1.6.1 - 1.7.2:必须 Java 7
|
||||
MinVer = If(New Version(1, 7, 0, 0) > MinVer, New Version(1, 7, 0, 0), MinVer)
|
||||
MaxVer = If(New Version(1, 7, 999, 999) < MaxVer, New Version(1, 7, 999, 999), MaxVer)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major <= 12 OrElse Not McInstanceSelected.Version.Vaild Then '非标准版本
|
||||
'<=1.12:Java 8
|
||||
MaxVer = New Version(1, 8, 999, 999)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major <= 14 Then
|
||||
'1.13 - 1.14:Java 8 - 10
|
||||
MinVer = If(New Version(1, 8, 0, 0) > MinVer, New Version(1, 8, 0, 0), MinVer)
|
||||
MaxVer = If(New Version(1, 10, 999, 999) < MaxVer, New Version(1, 10, 999, 999), MaxVer)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major = 15 Then
|
||||
'1.15:Java 8 - 15
|
||||
MinVer = If(New Version(1, 8, 0, 0) > MinVer, New Version(1, 8, 0, 0), MinVer)
|
||||
MaxVer = If(New Version(1, 15, 999, 999) < MaxVer, New Version(1, 15, 999, 999), MaxVer)
|
||||
ElseIf CompareVersionGE(McInstanceSelected.Version.Forge, "34.0.0") AndAlso CompareVersionGE("36.2.25", McInstanceSelected.Version.Forge) Then
|
||||
'1.16.3~5,Forge 34.0.0 ~ 36.2.25:最高 Java 8u320
|
||||
MaxVer = If(New Version(1, 8, 0, 320) < MaxVer, New Version(1, 8, 0, 320), MaxVer)
|
||||
ElseIf CompareVersionGE(McInstanceSelected.Version.Forge, "36.2.26") AndAlso CompareVersionGE("36.999.999", McInstanceSelected.Version.Forge) Then
|
||||
'1.16.5,Forge 36.2.26+,<37.0.0:最高 Java 23
|
||||
MaxVer = If(New Version(1, 23, 999, 999) < MaxVer, New Version(1, 23, 999, 999), MaxVer)
|
||||
ElseIf CompareVersionGE(McInstanceSelected.Version.Forge, "37.0.0") AndAlso CompareVersionGE("37.0.79", McInstanceSelected.Version.Forge) Then
|
||||
'1.17.1,Forge 37.0.0 ~ 37.0.79:最高 Java 16
|
||||
MaxVer = If(New Version(1, 16, 999, 999) < MaxVer, New Version(1, 16, 999, 999), MaxVer)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major = 18 AndAlso McInstanceSelected.Version.HasOptiFine Then '#305
|
||||
'1.18:若安装了 OptiFine,最高 Java 18
|
||||
MaxVer = If(New Version(1, 18, 999, 999) < MaxVer, New Version(1, 18, 999, 999), MaxVer)
|
||||
ElseIf CompareVersionGE(McInstanceSelected.Version.Forge, "45.0.21") AndAlso CompareVersionGE("45.0.65", McInstanceSelected.Version.Forge) Then
|
||||
'1.19.4,Forge 45.0.21 ~ 45.0.65:最高 Java 19
|
||||
MaxVer = If(New Version(1, 19, 999, 999) < MaxVer, New Version(1, 19, 999, 999), MaxVer)
|
||||
ElseIf CompareVersionGE(McInstanceSelected.Version.Forge, "45.0.66") AndAlso CompareVersionGE("47.4.8", McInstanceSelected.Version.Forge) Then
|
||||
'1.19.4~1.20.1,Forge 45.0.66 ~ 47.4.8:最高 Java 21
|
||||
MaxVer = If(New Version(1, 21, 999, 999) < MaxVer, New Version(1, 21, 999, 999), MaxVer)
|
||||
End If
|
||||
End If
|
||||
|
||||
'NeoForge 检测
|
||||
If McInstanceSelected.Version.HasNeoForge Then
|
||||
If McInstanceSelected.Version.Vanilla = New Version(20, 0, 1) OrElse
|
||||
(CompareVersionGE("20.2.62-beta", McInstanceSelected.Version.NeoForge) AndAlso Not McInstanceSelected.Version.NeoForge.Contains("25w14craftmine")) Then
|
||||
'1.20.1,以及 1.20.2 的 20.2.62-beta 之前:最高 Java 21
|
||||
MaxVer = If(New Version(1, 21, 999, 999) < MaxVer, New Version(1, 21, 999, 999), MaxVer)
|
||||
End If
|
||||
End If
|
||||
|
||||
'Fabric 检测
|
||||
If McInstanceSelected.Version.HasFabric AndAlso McInstanceSelected.Version.Vaild Then '不管非标准版本
|
||||
If McInstanceSelected.Version.Vanilla.Major >= 15 AndAlso McInstanceSelected.Version.Vanilla.Major <= 16 Then
|
||||
'1.15 - 1.16:Java 8+
|
||||
MinVer = If(New Version(1, 8, 0, 0) > MinVer, New Version(1, 8, 0, 0), MinVer)
|
||||
ElseIf McInstanceSelected.Version.Vanilla.Major >= 18 Then
|
||||
'1.18+:Java 17+
|
||||
MinVer = If(New Version(1, 17, 0, 0) > MinVer, New Version(1, 17, 0, 0), MinVer)
|
||||
End If
|
||||
End If
|
||||
|
||||
'LiteLoader 检测
|
||||
If McInstanceSelected.Version.HasLiteLoader AndAlso McInstanceSelected.Version.Vaild Then '不管非标准版本
|
||||
'最高 Java 8
|
||||
MaxVer = If(New Version(1, 8, 999, 999) < MaxVer, New Version(1, 8, 999, 999), MaxVer)
|
||||
End If
|
||||
|
||||
'统一通行证检测
|
||||
If Settings.Get(Of McLoginType)("LoginType") = McLoginType.Nide Then
|
||||
'至少 Java 8u101
|
||||
MinVer = If(New Version(1, 8, 0, 141) > MinVer, New Version(1, 8, 0, 141), MinVer)
|
||||
End If
|
||||
|
||||
SyncLock JavaLock
|
||||
|
||||
'选择 Java
|
||||
McLaunchLog("Java 版本需求:最低 " & MinVer.ToString & ",最高 " & MaxVer.ToString)
|
||||
McLaunchJavaSelected = JavaSelect("$$", MinVer, MaxVer, McInstanceSelected)
|
||||
If Task.IsInterrupted Then Return
|
||||
If McLaunchJavaSelected IsNot Nothing Then
|
||||
McLaunchLog("选择的 Java:" & McLaunchJavaSelected.ToString)
|
||||
Return
|
||||
End If
|
||||
|
||||
'无合适的 Java
|
||||
If Task.IsInterrupted Then Return '中断加载会导致 JavaSelect 异常地返回空值,误判找不到 Java
|
||||
McLaunchLog("无合适的 Java,准备自动下载")
|
||||
Dim JavaCode As String
|
||||
If MinVer >= New Version(1, 9) Then
|
||||
JavaCode = MinVer.Minor
|
||||
ElseIf MaxVer < New Version(1, 8) Then
|
||||
MyMsgBox($"你需要安装 Java 7 才能启动该版本。{vbCrLf}请自行搜索并安装 Java 7,安装后在 设置 → 启动选项 → 游戏 Java 中重新搜索或导入。", "未找到 Java")
|
||||
Throw New Exception("$$")
|
||||
ElseIf MinVer > New Version(1, 8, 0, 140) AndAlso MaxVer < New Version(1, 8, 0, 321) Then
|
||||
MyMsgBox($"你需要安装 Java 8u141 ~ 8u320 才能启动该版本。{vbCrLf}请自行搜索并安装,安装后在 设置 → 启动选项 → 游戏 Java 中重新搜索或导入。", "未找到 Java")
|
||||
Throw New Exception("$$")
|
||||
ElseIf MinVer > New Version(1, 8, 0, 140) Then
|
||||
MyMsgBox($"你需要安装 Java 8u141 或更高版本的 Java 8 才能启动该版本。{vbCrLf}请自行搜索并安装,安装后在 设置 → 启动选项 → 游戏 Java 中重新搜索或导入。", "未找到 Java")
|
||||
Throw New Exception("$$")
|
||||
Else
|
||||
JavaCode = 8
|
||||
End If
|
||||
|
||||
'开始自动下载
|
||||
Dim JavaLoader = GetJavaDownloadLoader()
|
||||
Try
|
||||
JavaLoader.Start(If(RecommendedComponent, JavaCode), IsForceRestart:=True) '在 Java 22+ 时优先使用 Mojang 提供的 Component 字段
|
||||
Do While JavaLoader.State = LoadState.Loading AndAlso Not Task.IsInterrupted
|
||||
Task.Progress = JavaLoader.Progress
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
Finally
|
||||
JavaLoader.Interrupt() '确保取消时中止 Java 下载
|
||||
End Try
|
||||
|
||||
'检查下载结果
|
||||
If JavaSearchLoader.State <> LoadState.Loading Then JavaSearchLoader.State = LoadState.Waiting '2872#
|
||||
McLaunchJavaSelected = JavaSelect("$$", MinVer, MaxVer, McInstanceSelected)
|
||||
If Task.IsInterrupted Then Return
|
||||
If McLaunchJavaSelected IsNot Nothing Then
|
||||
McLaunchLog("选择的 Java:" & McLaunchJavaSelected.ToString)
|
||||
Else
|
||||
Hint("没有可用的 Java,已取消启动!", HintType.Red)
|
||||
Throw New Exception("$$")
|
||||
End If
|
||||
|
||||
End SyncLock
|
||||
McLaunchLog("选择的 Java:" & McLaunchJavaSelected.ToString)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -1427,7 +1263,7 @@ NextInstance:
|
||||
End If
|
||||
'Authlib-Injector
|
||||
If McLoginLoader.Output.Type = "Auth" Then
|
||||
If McLaunchJavaSelected.MajorVersion >= 6 Then Args.Add("-Djavax.net.ssl.trustStoreType=WINDOWS-ROOT") '信任系统根证书(5252#)
|
||||
If McLaunchJavaSelected.Version.Major >= 6 Then Args.Add("-Djavax.net.ssl.trustStoreType=WINDOWS-ROOT") '信任系统根证书(5252#)
|
||||
Dim Server As String = Settings.Get(Of String)("VersionServerAuthServer", Instance:=McInstanceSelected)
|
||||
Try
|
||||
McLaunchLog($"开始 Authlib Injector Prefetch")
|
||||
@@ -1444,13 +1280,13 @@ NextInstance:
|
||||
'非 GBK 编码下命令行参数乱码的问题(JDK-8272352)
|
||||
Dim UseJLW As Boolean =
|
||||
Not Settings.Get(Of Boolean)("LaunchAdvanceDisableJLW") AndAlso Not Settings.Get(Of Boolean)("VersionAdvanceDisableJLW", McInstanceSelected) AndAlso
|
||||
Not IsGBKEncoding AndAlso Not McFolderSelected.IsAsciiOnly() '仅在该环境下才会触发该 Bug
|
||||
Not IsGBKEncoding '即使游戏文件夹名称不含非 ASCII 字符,但玩家名等也可能出现中文,因此依然需要 JLW(#8739)
|
||||
If UseJLW AndAlso CustomArg.Contains("-javaagent") Then
|
||||
UseJLW = False
|
||||
McLaunchLog("由于使用了自定义 javaagent,已禁用 JLW,这可能导致游戏崩溃!", LogLevel.Warn)
|
||||
End If
|
||||
If UseJLW Then
|
||||
If McLaunchJavaSelected.MajorVersion >= 9 Then
|
||||
If McLaunchJavaSelected.Version.Major >= 9 Then
|
||||
Args.Add("--add-exports") : Args.Add("cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
End If
|
||||
Args.Add("-Doolloo.jlw.tmpdir=${pure_directory}") '这里需要不以 \ 结尾
|
||||
@@ -1467,7 +1303,7 @@ NextInstance:
|
||||
#Region "内存管理"
|
||||
|
||||
McLaunchLog("当前剩余内存:" & Math.Round(My.Computer.Info.AvailablePhysicalMemory / 1024 / 1024 / 1024 * 10) / 10 & "G")
|
||||
Dim TargetRam As Integer = Math.Floor(PageInstanceSetup.GetRam(McInstanceSelected, Not McLaunchJavaSelected.Is64Bit) * 1024)
|
||||
Dim TargetRam As Integer = Math.Floor(PageInstanceSetup.GetRam(McInstanceSelected) * 1024)
|
||||
Args.Add("-Xmx" & TargetRam & "m")
|
||||
|
||||
'获取设置的管理方式
|
||||
@@ -1480,17 +1316,17 @@ NextInstance:
|
||||
If SetupType <> 3 Then
|
||||
'确定是使用 G1GC 还是 ZGC
|
||||
Dim UseG1GC As Boolean = False
|
||||
If (SetupType = 0 AndAlso McLaunchJavaSelected.MajorVersion < 15) OrElse
|
||||
(SetupType = 1 AndAlso McLaunchJavaSelected.MajorVersion < 21) OrElse
|
||||
If (SetupType = 0 AndAlso McLaunchJavaSelected.Version.Major < 15) OrElse
|
||||
(SetupType = 1 AndAlso McLaunchJavaSelected.Version.Major < 21) OrElse
|
||||
(SetupType = 2 OrElse SetupType = 4) Then UseG1GC = True '检查 Java 版本,ZGC 在 Java 15+ 可用,分代 ZGC 在 Java 21+ 可用
|
||||
If Is32BitSystem OrElse Environment.OSVersion.Version.Major < 10 OrElse Environment.OSVersion.Version.Build < 17763 Then UseG1GC = True '检查系统兼容性,ZGC 需要 Windows 10 1809+
|
||||
McLaunchLog($"GC 设置:{SetupType},选取 {If(UseG1GC, "G1GC", "ZGC")},Java 版本:{McLaunchJavaSelected.MajorVersion}")
|
||||
If Environment.OSVersion.Version.Major < 10 OrElse Environment.OSVersion.Version.Build < 17763 Then UseG1GC = True '检查系统兼容性,ZGC 需要 Windows 10 1809+
|
||||
McLaunchLog($"GC 设置:{SetupType},选取 {If(UseG1GC, "G1GC", "ZGC")},Java 版本:{McLaunchJavaSelected.Version.Major}")
|
||||
'移除已有的 GC 参数
|
||||
Args = Args.Where(Function(a) Not a.RegexCheck(
|
||||
"( )*-XX:[+-]?(Use\w+GC|ZGenerational|UseCompactObjectHeaders|G1\w+Percent|G1\w+Size|(Max|Min)(GCPauseMillis|HeapFreeRatio))")).ToList
|
||||
'添加 GC 参数
|
||||
Args.Add("-XX:+UnlockExperimentalVMOptions")
|
||||
If McLaunchJavaSelected.MajorVersion >= 24 AndAlso McLaunchJavaSelected.Is64Bit Then Args.Add("-XX:+UseCompactObjectHeaders")
|
||||
If McLaunchJavaSelected.Version.Major >= 24 Then Args.Add("-XX:+UseCompactObjectHeaders")
|
||||
If UseG1GC AndAlso SetupType = 4 Then
|
||||
'优化的 G1GC
|
||||
Args.Add("-XX:+UseG1GC")
|
||||
@@ -1499,10 +1335,10 @@ NextInstance:
|
||||
Args.Add("-XX:G1HeapRegionSize=32M")
|
||||
Args.Add("-XX:MaxGCPauseMillis=50")
|
||||
If Not ModeDebug Then Args.Add("-XX:+PerfDisableSharedMem")
|
||||
If McLaunchJavaSelected.MajorVersion <= 7 Then Args.Add("-XX:MaxPermSize=512m") '#8286
|
||||
If McLaunchJavaSelected.MajorVersion = 8 Then Args.Add("-XX:+ParallelRefProcEnabled")
|
||||
If McLaunchJavaSelected.MajorVersion >= 12 Then Args.Add("-XX:MinHeapFreeRatio=25") '需要比 G1NewSizePercent 大一点
|
||||
If McLaunchJavaSelected.MajorVersion >= 12 Then Args.Add("-XX:MaxHeapFreeRatio=40") '需要比 MinHeapFreeRatio 大一些
|
||||
If McLaunchJavaSelected.Version.Major <= 7 Then Args.Add("-XX:MaxPermSize=512m") '#8286
|
||||
If McLaunchJavaSelected.Version.Major = 8 Then Args.Add("-XX:+ParallelRefProcEnabled")
|
||||
If McLaunchJavaSelected.Version.Major >= 12 Then Args.Add("-XX:MinHeapFreeRatio=25") '需要比 G1NewSizePercent 大一点
|
||||
If McLaunchJavaSelected.Version.Major >= 12 Then Args.Add("-XX:MaxHeapFreeRatio=40") '需要比 MinHeapFreeRatio 大一些
|
||||
ElseIf UseG1GC Then
|
||||
'Mojang G1GC
|
||||
Args.Add("-XX:+UseG1GC")
|
||||
@@ -1510,11 +1346,11 @@ NextInstance:
|
||||
Args.Add("-XX:G1ReservePercent=20")
|
||||
Args.Add("-XX:G1HeapRegionSize=32M")
|
||||
Args.Add("-XX:MaxGCPauseMillis=50")
|
||||
If McLaunchJavaSelected.MajorVersion <= 7 Then Args.Add("-XX:MaxPermSize=512m") '#8286
|
||||
If McLaunchJavaSelected.Version.Major <= 7 Then Args.Add("-XX:MaxPermSize=512m") '#8286
|
||||
Else
|
||||
'ZGC
|
||||
Args.Add("-XX:+UseZGC")
|
||||
If McLaunchJavaSelected.MajorVersion = 21 OrElse McLaunchJavaSelected.MajorVersion = 22 Then Args.Add("-XX:+ZGenerational") 'Java 23 起默认启用分代 ZGC,不需要再添加参数
|
||||
If McLaunchJavaSelected.Version.Major = 21 OrElse McLaunchJavaSelected.Version.Major = 22 Then Args.Add("-XX:+ZGenerational") 'Java 23 起默认启用分代 ZGC,不需要再添加参数
|
||||
End If
|
||||
End If
|
||||
|
||||
@@ -1526,9 +1362,9 @@ NextInstance:
|
||||
Args.Add("-Dlog4j2.formatMsgNoLookups=true")
|
||||
|
||||
'编码(#4700、#5892、#5909)
|
||||
If McLaunchJavaSelected.MajorVersion > 8 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dstdout.encoding=")) Then Args.Add("-Dstdout.encoding=UTF-8")
|
||||
If McLaunchJavaSelected.MajorVersion > 8 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dstderr.encoding=")) Then Args.Add("-Dstderr.encoding=UTF-8")
|
||||
If McLaunchJavaSelected.MajorVersion >= 18 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dfile.encoding=")) Then Args.Add("-Dfile.encoding=COMPAT") 'Dfile.encoding 需要放在 Dstdout.encoding 后面(#6934)
|
||||
If McLaunchJavaSelected.Version.Major > 8 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dstdout.encoding=")) Then Args.Add("-Dstdout.encoding=UTF-8")
|
||||
If McLaunchJavaSelected.Version.Major > 8 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dstderr.encoding=")) Then Args.Add("-Dstderr.encoding=UTF-8")
|
||||
If McLaunchJavaSelected.Version.Major >= 18 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dfile.encoding=")) Then Args.Add("-Dfile.encoding=COMPAT") 'Dfile.encoding 需要放在 Dstdout.encoding 后面(#6934)
|
||||
|
||||
'为 JLW 添加 -jar,它必须放在最后
|
||||
If UseJLW Then
|
||||
@@ -1597,7 +1433,9 @@ NextInstance:
|
||||
McLaunchLog("发现错误的 OptiFineForge TweakClass,目前的游戏参数:" & Arg)
|
||||
Arg = Arg.Replace(" --tweakClass optifine.OptiFineTweaker", "") & " --tweakClass optifine.OptiFineForgeTweaker"
|
||||
Try
|
||||
FileUtils.Write(McInstanceSelected.GetJsonPath(), FileUtils.ReadAsString(McInstanceSelected.GetJsonPath()).Replace("optifine.OptiFineTweaker", "optifine.OptiFineForgeTweaker"))
|
||||
FileUtils.Write(
|
||||
McInstanceSelected.GetJsonPath(),
|
||||
FileUtils.ReadAsString(McInstanceSelected.GetJsonPath()).Replace("optifine.OptiFineTweaker", "optifine.OptiFineForgeTweaker"))
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, "替换 OptiFineForge TweakClass 失败")
|
||||
End Try
|
||||
@@ -1690,9 +1528,9 @@ NextInstance:
|
||||
TargetSize = New Size(854, 480)
|
||||
End Select
|
||||
If McInstanceSelected.Version.Vanilla.Major <= 12 AndAlso
|
||||
McLaunchJavaSelected.MajorVersion <= 8 AndAlso McLaunchJavaSelected.Version.Revision >= 200 AndAlso McLaunchJavaSelected.Version.Revision <= 321 AndAlso
|
||||
McLaunchJavaSelected.Version >= New Version(8, 0, 200) AndAlso McLaunchJavaSelected.Version <= New Version(8, 0, 321) AndAlso
|
||||
Not McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.HasForge Then '修复 1.12.2- 下 JRE 8u200~321 下窗口大小为设置大小的 DPI% 倍(#3463)
|
||||
McLaunchLog($"已应用窗口大小过大修复({McLaunchJavaSelected.Version.Revision})")
|
||||
McLaunchLog($"已应用窗口大小过大修复(Java 版本:{McLaunchJavaSelected.Version})")
|
||||
TargetSize.Width /= DPI / 96
|
||||
TargetSize.Height /= DPI / 96
|
||||
End If
|
||||
@@ -1843,7 +1681,7 @@ NextInstance:
|
||||
Next
|
||||
|
||||
'删除多余文件
|
||||
For Each FileName As String In DirectoryUtils.GetFiles(Target, True)
|
||||
For Each FileName As String In DirectoryUtils.EnumerateFiles(Target)
|
||||
If ExistFiles.Contains(FileName) Then Continue For
|
||||
Try
|
||||
McLaunchLog("删除:" & FileName)
|
||||
@@ -1862,7 +1700,7 @@ NextInstance:
|
||||
Private Function GetNativesFolder() As String
|
||||
Dim Result As String = PathUtils.AddSlashSuffix(PathUtils.ToShortPath(McInstanceSelected.PathVersion)) & McInstanceSelected.Name & "-natives\"
|
||||
If Not (IsGBKEncoding OrElse Result.IsAsciiOnly()) Then
|
||||
Result = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\bin\natives\"
|
||||
Result = Paths.AppData & ".minecraft\bin\natives\"
|
||||
If Not Result.IsAsciiOnly() Then
|
||||
Result = OsDrive & "ProgramData\PCL\natives\"
|
||||
End If
|
||||
@@ -1880,15 +1718,15 @@ NextInstance:
|
||||
'使用高性能显卡
|
||||
If Settings.Get(Of Boolean)("LaunchAdvanceGraphicCard") Then
|
||||
Try
|
||||
SetGPUPreference(McLaunchJavaSelected.PathJava)
|
||||
SetGPUPreference(McLaunchJavaSelected.JavaExePath)
|
||||
SetGPUPreference(PathExe)
|
||||
Catch ex As Exception
|
||||
If SystemUtils.HasAdminRole() Then
|
||||
If WindowsUtils.HasAdminRole() Then
|
||||
Logger.Warn(ex, "直接调整显卡设置失败")
|
||||
Else
|
||||
Logger.Warn(ex, "直接调整显卡设置失败,将以管理员权限重启 PCL 再次尝试")
|
||||
Try
|
||||
If RunAsAdmin($"--gpu ""{McLaunchJavaSelected.PathJava}""") = ProcessReturnValues.TaskDone Then
|
||||
If RunAsAdmin($"--gpu ""{McLaunchJavaSelected.JavaExePath}""") = ProcessReturnValues.TaskDone Then
|
||||
McLaunchLog("以管理员权限重启 PCL 并调整显卡设置成功")
|
||||
Else
|
||||
Throw New Exception("调整过程中出现异常")
|
||||
@@ -1924,9 +1762,9 @@ NextInstance:
|
||||
""profile"": ""66666555554444433333222221111100""
|
||||
}
|
||||
}"
|
||||
Dim ReplaceJson As JObject = GetJson(ReplaceJsonString)
|
||||
Dim ReplaceJson As JObject = (ReplaceJsonString).DeserializeJson()
|
||||
'更新文件
|
||||
Dim Profiles As JObject = GetJson(FileUtils.ReadAsString(McFolderSelected & "launcher_profiles.json"))
|
||||
Dim Profiles As JObject = FileUtils.ReadAsJson(McFolderSelected & "launcher_profiles.json")
|
||||
Profiles.Merge(ReplaceJson)
|
||||
FileUtils.Write(McFolderSelected & "launcher_profiles.json", Profiles.ToString, encoding:=Encoding.GetEncoding("GB18030"))
|
||||
McLaunchLog("已更新 launcher_profiles.json")
|
||||
@@ -1954,9 +1792,9 @@ NextInstance:
|
||||
""profile"": ""66666555554444433333222221111100""
|
||||
}
|
||||
}"
|
||||
Dim ReplaceJson As JObject = GetJson(ReplaceJsonString)
|
||||
Dim ReplaceJson As JObject = ReplaceJsonString.DeserializeJson()
|
||||
'更新文件
|
||||
Dim Profiles As JObject = GetJson(FileUtils.ReadAsString(McFolderSelected & "launcher_profiles.json"))
|
||||
Dim Profiles As JObject = FileUtils.ReadAsJson(McFolderSelected & "launcher_profiles.json")
|
||||
Profiles.Merge(ReplaceJson)
|
||||
FileUtils.Write(McFolderSelected & "launcher_profiles.json", Profiles.ToString, encoding:=Encoding.GetEncoding("GB18030"))
|
||||
McLaunchLog("已在删除后更新 launcher_profiles.json")
|
||||
@@ -2026,7 +1864,7 @@ NextInstance:
|
||||
Try
|
||||
Dim ZipFileAddress As String = McInstanceSelected.PathIndie & "resourcepacks\PCL2 Skin.zip"
|
||||
Dim NewTypeSetup As Boolean = McInstanceSelected.Version.Vanilla.Major >= 13 OrElse McInstanceSelected.Version.Vanilla.Major < 6
|
||||
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Settings.Get(Of Integer)("LaunchSkinType") = 4 AndAlso FileUtils.Exists(PathAppdata & "CustomSkin.png") Then
|
||||
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Settings.Get(Of Integer)("LaunchSkinType") = 4 AndAlso FileUtils.Exists(Paths.AppDataThenName & "CustomSkin.png") Then
|
||||
Dim MetaFileAddress As String = PathTemp & "pack.mcmeta"
|
||||
Dim PackPicAddress As String = PathTemp & "pack.png"
|
||||
Dim PackFormat As Integer
|
||||
@@ -2076,12 +1914,12 @@ NextInstance:
|
||||
Dim Bit As New MyBitmap(PathImage & "Heads/Logo.png")
|
||||
Bit.Save(PackPicAddress)
|
||||
FileUtils.Write(MetaFileAddress, "{""pack"":{""pack_format"":" & PackFormat & ",""description"":""PCL 自定义离线皮肤资源包""}}")
|
||||
Dim Skin As New MyBitmap(PathAppdata & "CustomSkin.png")
|
||||
Dim Skin As New MyBitmap(Paths.AppDataThenName & "CustomSkin.png")
|
||||
If (McInstanceSelected.Version.Vanilla.Major = 6 OrElse McInstanceSelected.Version.Vanilla.Major = 7) AndAlso Skin.Pic.Height = 64 Then
|
||||
McLaunchLog("该 Minecraft 版本不支持双层皮肤,已进行裁剪")
|
||||
Skin = Skin.Clip(0, 0, 64, 32)
|
||||
End If
|
||||
Skin.Save(PathExeFolder & "PCL\CustomSkin_Cliped.png")
|
||||
Skin.Save(Paths.Base & "PCL\CustomSkin_Cliped.png")
|
||||
'构建压缩文件
|
||||
Dim FilesToCompress As New Dictionary(Of String, String) From {
|
||||
{"pack.mcmeta", MetaFileAddress}, {"pack.png", PackPicAddress}}
|
||||
@@ -2090,15 +1928,15 @@ NextInstance:
|
||||
For Each SkinName In {"alex", "ari", "efe", "kai", "makena", "noor", "steve", "sunny", "zuri"}
|
||||
FilesToCompress.Add(
|
||||
$"assets/minecraft/textures/entity/player/{If(Settings.Get(Of Boolean)("LaunchSkinSlim"), "slim", "wide")}/{SkinName}.png",
|
||||
PathExeFolder & "PCL\CustomSkin_Cliped.png")
|
||||
Paths.Base & "PCL\CustomSkin_Cliped.png")
|
||||
Next
|
||||
Else
|
||||
FilesToCompress.Add(
|
||||
$"assets/minecraft/textures/entity/{If(Settings.Get(Of Boolean)("LaunchSkinSlim"), "alex.png", "steve.png")}",
|
||||
PathExeFolder & "PCL\CustomSkin_Cliped.png")
|
||||
Paths.Base & "PCL\CustomSkin_Cliped.png")
|
||||
End If
|
||||
FileUtils.CreateZipFromFiles(ZipFileAddress, FilesToCompress)
|
||||
FileUtils.Delete(PathExeFolder & "PCL\CustomSkin_Cliped.png")
|
||||
FileUtils.Delete(Paths.Base & "PCL\CustomSkin_Cliped.png")
|
||||
'更改设置文件
|
||||
IniClearCache(SetupFileAddress)
|
||||
Dim EnabledResourcePack As String = ReadIni(SetupFileAddress, "resourcePacks", "[]").TrimStart("[").TrimEnd("]")
|
||||
@@ -2159,25 +1997,25 @@ IgnoreCustomSkin:
|
||||
'输出 bat
|
||||
Try
|
||||
Dim CmdString As String =
|
||||
$"{If(McLaunchJavaSelected.MajorVersion > 8, "chcp 65001>nul" & vbCrLf, "")}" &
|
||||
$"{If(McLaunchJavaSelected.Version.Major > 8, "chcp 65001>nul" & vbCrLf, "")}" &
|
||||
"@echo off" & vbCrLf &
|
||||
$"title 启动 - {McInstanceSelected.Name}" & vbCrLf &
|
||||
"echo 游戏正在启动,请稍候。" & vbCrLf &
|
||||
$"cd /D ""{PathUtils.ToShortPath(McInstanceSelected.PathIndie)}""" & vbCrLf &
|
||||
CustomCommandGlobal & vbCrLf &
|
||||
CustomCommandVersion & vbCrLf &
|
||||
$"""{McLaunchJavaSelected.PathJava}"" {McLaunchArgument}" & vbCrLf &
|
||||
$"""{McLaunchJavaSelected.JavaExePath}"" {McLaunchArgument}" & vbCrLf &
|
||||
"echo 游戏已退出。" & vbCrLf &
|
||||
"pause"
|
||||
FileUtils.Write(
|
||||
filePath:=If(CurrentLaunchOptions.SaveBatch, PathExeFolder & "PCL\LatestLaunch.bat"),
|
||||
filePath:=If(CurrentLaunchOptions.SaveBatch, Paths.Base & "PCL\LatestLaunch.bat"),
|
||||
text:=FilterAccessToken(CmdString, "F").Replace("%", "%%"),
|
||||
encoding:=If(McLaunchJavaSelected.MajorVersion > 8, Encoding.UTF8, Encoding.Default))
|
||||
encoding:=If(McLaunchJavaSelected.Version.Major > 8, Encoding.UTF8, Encoding.Default))
|
||||
If CurrentLaunchOptions.SaveBatch IsNot Nothing Then
|
||||
McLaunchLog("导出启动脚本完成,强制结束启动过程")
|
||||
InterruptHint = "导出启动脚本成功!"
|
||||
CanceledHint = "导出启动脚本成功!"
|
||||
OpenExplorer(CurrentLaunchOptions.SaveBatch)
|
||||
Loader.Parent.Interrupt()
|
||||
Loader.Parent.Cancel()
|
||||
Return '导出脚本完成
|
||||
End If
|
||||
Catch ex As Exception
|
||||
@@ -2198,14 +2036,14 @@ IgnoreCustomSkin:
|
||||
.CreateNoWindow = True
|
||||
})
|
||||
If Settings.Get(Of Boolean)("LaunchAdvanceRunWait") Then
|
||||
Do Until CustomProcess.HasExited OrElse Loader.IsInterrupted
|
||||
Do Until CustomProcess.HasExited OrElse Loader.IsCanceled
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "执行全局自定义命令失败", LogBehavior.Toast)
|
||||
Finally
|
||||
If CustomProcess IsNot Nothing AndAlso Not CustomProcess.HasExited AndAlso Loader.IsInterrupted Then
|
||||
If CustomProcess IsNot Nothing AndAlso Not CustomProcess.HasExited AndAlso Loader.IsCanceled Then
|
||||
McLaunchLog("由于取消启动,已强制结束自定义命令 CMD 进程") '#1183
|
||||
CustomProcess.Kill()
|
||||
End If
|
||||
@@ -2223,14 +2061,14 @@ IgnoreCustomSkin:
|
||||
.CreateNoWindow = True
|
||||
})
|
||||
If Settings.Get(Of Boolean)("VersionAdvanceRunWait", Instance:=McInstanceSelected) Then
|
||||
Do Until CustomProcess.HasExited OrElse Loader.IsInterrupted
|
||||
Do Until CustomProcess.HasExited OrElse Loader.IsCanceled
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "执行版本自定义命令失败", LogBehavior.Toast)
|
||||
Finally
|
||||
If CustomProcess IsNot Nothing AndAlso Not CustomProcess.HasExited AndAlso Loader.IsInterrupted Then
|
||||
If CustomProcess IsNot Nothing AndAlso Not CustomProcess.HasExited AndAlso Loader.IsCanceled Then
|
||||
McLaunchLog("由于取消启动,已强制结束自定义命令 CMD 进程") '#1183
|
||||
CustomProcess.Kill()
|
||||
End If
|
||||
@@ -2241,13 +2079,13 @@ IgnoreCustomSkin:
|
||||
Private Sub McLaunchRun(Loader As LoaderTask(Of Integer, Process))
|
||||
|
||||
'启动信息
|
||||
Dim StartInfo As New ProcessStartInfo(McLaunchJavaSelected.PathJava) '使用 javaw.exe 会导致 #6263
|
||||
Dim StartInfo As New ProcessStartInfo(McLaunchJavaSelected.JavaExePath) '使用 javaw.exe 会导致 #6263
|
||||
|
||||
'设置环境变量
|
||||
Dim PathEnv As String = StartInfo.EnvironmentVariables("Path")
|
||||
Dim Paths As New List(Of String)
|
||||
If Not String.IsNullOrEmpty(PathEnv) Then Paths.AddRange(PathEnv.Split(";"))
|
||||
Paths.Add(PathUtils.ToShortPath(McLaunchJavaSelected.PathFolder))
|
||||
Paths.Add(PathUtils.ToShortPath(McLaunchJavaSelected.Folder))
|
||||
StartInfo.EnvironmentVariables("Path") = Paths.Distinct.Join(";"c)
|
||||
StartInfo.EnvironmentVariables("appdata") = PathUtils.ToShortPath(McFolderSelected)
|
||||
|
||||
@@ -2261,8 +2099,8 @@ IgnoreCustomSkin:
|
||||
|
||||
'开始进程
|
||||
Dim GameProcess = StartProcess(StartInfo)
|
||||
McLaunchLog("已启动游戏进程:" & McLaunchJavaSelected.PathJava)
|
||||
If Loader.IsInterrupted Then
|
||||
McLaunchLog("已启动游戏进程:" & McLaunchJavaSelected.JavaExePath)
|
||||
If Loader.IsCanceled Then
|
||||
McLaunchLog("由于取消启动,已强制结束游戏进程") '#1631
|
||||
GameProcess.Kill()
|
||||
Return
|
||||
@@ -2294,13 +2132,12 @@ IgnoreCustomSkin:
|
||||
McLaunchLog($"游戏版本:{McInstanceSelected.VersionDisplayName}({McInstanceSelected.Version.Vanilla},Drop {McInstanceSelected.Version.Drop}{If(McInstanceSelected.Version.Reliable, "", ",无法完全确定")})")
|
||||
McLaunchLog("资源版本:" & McAssetsGetIndexName(McInstanceSelected))
|
||||
McLaunchLog("版本继承:" & If(McInstanceSelected.InheritName = "", "无", McInstanceSelected.InheritName))
|
||||
McLaunchLog("分配的内存:" & PageInstanceSetup.GetRam(McInstanceSelected, Not McLaunchJavaSelected.Is64Bit) & " GB(" & Math.Round(PageInstanceSetup.GetRam(McInstanceSelected, Not McLaunchJavaSelected.Is64Bit) * 1024) & " MB)")
|
||||
McLaunchLog("分配的内存:" & PageInstanceSetup.GetRam(McInstanceSelected) & " GB(" & Math.Round(PageInstanceSetup.GetRam(McInstanceSelected) * 1024) & " MB)")
|
||||
McLaunchLog("MC 文件夹:" & McFolderSelected)
|
||||
McLaunchLog("版本文件夹:" & McInstanceSelected.PathVersion)
|
||||
McLaunchLog("版本隔离:" & (McInstanceSelected.PathIndie = McInstanceSelected.PathVersion))
|
||||
McLaunchLog("HMCL 格式:" & McInstanceSelected.IsHmclFormatJson)
|
||||
McLaunchLog("Java 信息:" & If(McLaunchJavaSelected IsNot Nothing, McLaunchJavaSelected.ToString, "无可用 Java"))
|
||||
McLaunchLog("环境变量:" & If(McLaunchJavaSelected IsNot Nothing, If(McLaunchJavaSelected.HasEnvironment, "已设置", "未设置"), "未设置"))
|
||||
McLaunchLog("Natives 文件夹:" & GetNativesFolder())
|
||||
McLaunchLog("")
|
||||
McLaunchLog("~ 登录参数 ~")
|
||||
@@ -2325,7 +2162,7 @@ IgnoreCustomSkin:
|
||||
Thread.Sleep(100)
|
||||
Loop
|
||||
If Watcher.State = Watcher.MinecraftState.Crashed Then
|
||||
Throw New Exception("$$")
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
|
||||
End Sub
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Public Module ModMinecraft
|
||||
Public Module ModMinecraft
|
||||
|
||||
#Region "文件夹"
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
End Property
|
||||
Private Sub SetMcFolder(Value As String) '等同 McFolderSelected.Set
|
||||
If _McFolderSelected = Value Then Return
|
||||
_McFolderSelected = Value.Replace("$", PathExeFolder)
|
||||
_McFolderSelected = Value.Replace("$", Paths.Base)
|
||||
_McFolderSelected = PathUtils.AddSlashSuffix(PathUtils.ForCompare(_McFolderSelected))
|
||||
Settings.Set("LaunchFolderSelect", Value.Replace(PathExeFolder, "$"))
|
||||
Settings.Set("LaunchFolderSelect", Value.Replace(Paths.Base, "$"))
|
||||
Logger.Info($"当前选择的 Minecraft 文件夹:{_McFolderSelected}")
|
||||
End Sub
|
||||
Private _McFolderSelected As String
|
||||
@@ -64,8 +64,8 @@
|
||||
|
||||
'扫描当前文件夹
|
||||
Try
|
||||
If DirectoryUtils.Exists(PathExeFolder & "versions\") Then CacheMcFolderList.Add(New McFolder With {.Name = "当前文件夹", .Location = PathExeFolder, .Type = McFolder.Types.Vanilla})
|
||||
For Each Folder As DirectoryInfo In DirectoryUtils.GetInfo(PathExeFolder).GetDirectories
|
||||
If DirectoryUtils.Exists(Paths.Base & "versions\") Then CacheMcFolderList.Add(New McFolder With {.Name = "当前文件夹", .Location = Paths.Base, .Type = McFolder.Types.Vanilla})
|
||||
For Each Folder As DirectoryInfo In DirectoryUtils.GetInfo(Paths.Base).GetDirectories
|
||||
If DirectoryUtils.Exists(Folder.FullName & "versions\") OrElse Folder.Name = ".minecraft" Then
|
||||
CacheMcFolderList.Add(New McFolder With {.Name = "当前文件夹", .Location = PathUtils.AddSlashSuffix(PathUtils.ForCompare(Folder.FullName)), .Type = McFolder.Types.Vanilla})
|
||||
End If
|
||||
@@ -75,7 +75,7 @@
|
||||
End Try
|
||||
|
||||
'扫描官启文件夹
|
||||
Dim MojangPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\"
|
||||
Dim MojangPath As String = Paths.AppData & ".minecraft\"
|
||||
If (Not CacheMcFolderList.Any OrElse MojangPath <> CacheMcFolderList(0).Location) AndAlso '当前文件夹不是官启文件夹
|
||||
DirectoryUtils.Exists(MojangPath & "versions\") Then '具有权限且存在 versions 文件夹
|
||||
CacheMcFolderList.Add(New McFolder With {.Name = "官方启动器文件夹", .Location = MojangPath, .Type = McFolder.Types.Vanilla})
|
||||
@@ -123,8 +123,8 @@
|
||||
|
||||
'若没有可用文件夹,则创建 .minecraft
|
||||
If Not CacheMcFolderList.Any() Then
|
||||
DirectoryUtils.Create(PathExeFolder & ".minecraft\versions\")
|
||||
CacheMcFolderList.Add(New McFolder With {.Name = "当前文件夹", .Location = PathExeFolder & ".minecraft\", .Type = McFolder.Types.Vanilla})
|
||||
DirectoryUtils.Create(Paths.Base & ".minecraft\versions\")
|
||||
CacheMcFolderList.Add(New McFolder With {.Name = "当前文件夹", .Location = Paths.Base & ".minecraft\", .Type = McFolder.Types.Vanilla})
|
||||
End If
|
||||
|
||||
For Each Folder As McFolder In CacheMcFolderList
|
||||
@@ -463,9 +463,9 @@ VersionSearchFinish:
|
||||
If Not FileUtils.Exists(JsonPath) Then
|
||||
'尝试寻找 JSON 文件
|
||||
JsonPath = Nothing
|
||||
For Each JsonCandidatePath In DirectoryUtils.GetFiles(PathVersion, True, "*.json")
|
||||
For Each JsonCandidatePath In DirectoryUtils.EnumerateFiles(PathVersion, searchPattern:="*.json")
|
||||
Try
|
||||
Dim JsonCandidate As JObject = GetJson(FileUtils.ReadAsString(JsonCandidatePath))
|
||||
Dim JsonCandidate As JObject = FileUtils.ReadAsJson(JsonCandidatePath)
|
||||
If Not JsonCandidate.ContainsKey("mainClass") Then Continue For
|
||||
If Not JsonCandidate.ContainsKey("type") Then Continue For
|
||||
If Not JsonCandidate.ContainsKey("id") Then Continue For
|
||||
@@ -501,12 +501,12 @@ VersionSearchFinish:
|
||||
If Not FastJsonCheck(_JsonText) Then
|
||||
If RunInUi() Then
|
||||
Logger.Warn("版本 JSON 文件为空或有误,由于代码在主线程运行,将不再进行重试")
|
||||
GetJson(_JsonText) '触发异常
|
||||
_JsonText.DeserializeJson() '触发异常
|
||||
Else
|
||||
Logger.Warn($"版本 JSON 文件为空或有误,将在 2s 后重试读取({JsonPath})")
|
||||
Thread.Sleep(2000)
|
||||
_JsonText = FileUtils.ReadAsString(JsonPath)
|
||||
If Not FastJsonCheck(_JsonText) Then GetJson(_JsonText) '触发异常
|
||||
If Not FastJsonCheck(_JsonText) Then _JsonText.DeserializeJson() '触发异常
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
@@ -526,7 +526,7 @@ VersionSearchFinish:
|
||||
If _JsonObject Is Nothing Then
|
||||
Dim Text As String = JsonText '触发 JsonText 的 Get 事件
|
||||
Try
|
||||
_JsonObject = GetJson(Text)
|
||||
_JsonObject = Text.DeserializeJson()
|
||||
'转换 HMCL 关键项
|
||||
If _JsonObject.ContainsKey("patches") AndAlso Not _JsonObject.ContainsKey("time") Then
|
||||
IsHmclFormatJson = True
|
||||
@@ -626,7 +626,7 @@ Recheck:
|
||||
Dim VersionJson As ZipArchiveEntry = JarArchive.GetEntry("version.json")
|
||||
If VersionJson Is Nothing Then Exit Try
|
||||
Using VersionJsonStream As New StreamReader(VersionJson.Open)
|
||||
_JsonVersion = GetJson(VersionJsonStream.ReadToEnd)
|
||||
_JsonVersion = VersionJsonStream.ReadToEnd().DeserializeJson()
|
||||
End Using
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
@@ -659,22 +659,23 @@ Recheck:
|
||||
End Property
|
||||
Private _InheritName As String = Nothing
|
||||
|
||||
Public Sub ResetIniCache()
|
||||
Public Config As JsonConfigProvider
|
||||
Public Sub ResetSettingsCache()
|
||||
IniClearCache(PathIndie & "options.txt")
|
||||
IniClearCache(PathVersion & "PCL\Setup.ini")
|
||||
Config.DiscardCache()
|
||||
For Each Entry In Settings.Entries.Values
|
||||
If Entry.Source = Settings.Sources.Instance Then Entry.ValueCache.Remove(PathVersion)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 从版本名,或版本文件夹的完整路径初始化(不规定是否以 \ 结尾)。
|
||||
''' 从版本名,或版本文件夹的完整路径初始化。
|
||||
''' </summary>
|
||||
Public Sub New(Name As String)
|
||||
Name = PathUtils.RemoveExtendedPrefix(Name)
|
||||
PathVersion = If(Name.Contains(":"), "", McFolderSelected & "versions\") & '补全完整路径
|
||||
Name &
|
||||
If(Name.EndsWithF("\"), "", "\") '补全右划线
|
||||
Public Sub New(NameOrFullPath As String)
|
||||
NameOrFullPath = PathUtils.RemoveExtendedPrefix(NameOrFullPath)
|
||||
PathVersion = PathUtils.AddSlashSuffix(If(NameOrFullPath.Contains(":"), "", McFolderSelected & "versions\") & NameOrFullPath)
|
||||
Config = New JsonConfigProvider(Path.Combine(PathVersion, "PCL\config.json"))
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -1286,7 +1287,7 @@ ExitDataLoad:
|
||||
GoTo OnLoaded
|
||||
End If
|
||||
'有可用版本
|
||||
Dim FolderListCheck As Integer = (Versions.MCINSTANCE_CACHE_VERSION & "#" & FolderList.Join("#"c)).GetStableHashCode() Mod (Integer.MaxValue - 1) '根据文件夹名列表生成辨识码
|
||||
Dim FolderListCheck As Integer = (Versions.McInstanceCacheVersion & "#" & FolderList.Join("#"c)).GetStableHashCode() Mod (Integer.MaxValue - 1) '根据文件夹名列表生成辨识码
|
||||
If Not McInstanceListForceRefresh AndAlso Val(ReadIni(PathMc & "PCL.ini", "InstanceCache")) = FolderListCheck Then
|
||||
'可以使用缓存
|
||||
Dim Result = InitMcInstanceListWithCache(PathMc)
|
||||
@@ -1307,7 +1308,7 @@ Reload:
|
||||
|
||||
'改变当前选择的版本
|
||||
OnLoaded:
|
||||
If Loader.IsInterrupted Then Return
|
||||
If Loader.IsCanceled Then Return
|
||||
If McInstanceList.Any(Function(v) v.Key <> McInstanceCardType.Error) Then
|
||||
'尝试读取已储存的选择
|
||||
Dim SavedSelection As String = ReadIni(PathMc & "PCL.ini", "Version")
|
||||
@@ -1333,9 +1334,8 @@ OnLoaded:
|
||||
Logger.Info("未找到可用 Minecraft 版本")
|
||||
End If
|
||||
If Settings.Get(Of Boolean)("SystemDebugDelay") Then Thread.Sleep(RandomInteger(200, 3000))
|
||||
Catch ex As ThreadInterruptedException
|
||||
Catch ex As Exception
|
||||
If Loader.IsInterrupted Then Return '#5617
|
||||
If Loader.IsCanceled OrElse ex.IsCanceled Then Return '#5617
|
||||
WriteIni(PathMc & "PCL.ini", "InstanceCache", "") '要求下次重新加载
|
||||
Logger.Error(ex, "加载 .minecraft 版本列表失败")
|
||||
End Try
|
||||
@@ -1716,7 +1716,7 @@ OnLoaded:
|
||||
'处理皮肤地址
|
||||
Dim SkinValue As String
|
||||
Try
|
||||
For Each SkinProperty In GetJson(SkinString)("properties")
|
||||
For Each SkinProperty In SkinString.DeserializeJson()("properties")
|
||||
If SkinProperty("name") = "textures" Then
|
||||
SkinValue = SkinProperty("value")
|
||||
Exit Try
|
||||
@@ -1728,7 +1728,7 @@ OnLoaded:
|
||||
Throw New Exception("皮肤返回值中不包含皮肤数据项,可能是未设置自定义皮肤的用户", ex)
|
||||
End Try
|
||||
SkinString = Encoding.UTF8.GetString(Convert.FromBase64String(SkinValue))
|
||||
Dim SkinJson As JObject = GetJson(SkinString.Lower)
|
||||
Dim SkinJson As JObject = SkinString.Lower.DeserializeJson()
|
||||
If SkinJson("textures") Is Nothing OrElse SkinJson("textures")("skin") Is Nothing OrElse SkinJson("textures")("skin")("url") Is Nothing Then
|
||||
Throw New Exception("用户未设置自定义皮肤")
|
||||
Else
|
||||
@@ -1751,7 +1751,6 @@ OnLoaded:
|
||||
SyncLock McSkinDownloadLock
|
||||
If Not FileUtils.Exists(FileAddress) Then
|
||||
NetDownloadByClient(Address, FileAddress & ".PCLDownloading")
|
||||
FileUtils.Delete(FileAddress)
|
||||
FileUtils.Move(FileAddress & ".PCLDownloading", FileAddress)
|
||||
Logger.Info($"皮肤下载成功:{FileAddress}")
|
||||
End If
|
||||
@@ -1835,7 +1834,7 @@ OnLoaded:
|
||||
Public OriginalName As String
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
Return If(IsNatives, "[Native] ", "") & FormatFileSize(Size) & " | " & LocalPath
|
||||
Return If(IsNatives, "[Native] ", "") & StringUtils.FormatByteSize(Size) & " | " & LocalPath
|
||||
End Function
|
||||
End Class
|
||||
|
||||
@@ -1865,7 +1864,7 @@ OnLoaded:
|
||||
End If
|
||||
End If
|
||||
If Rule("os")("arch") IsNot Nothing Then '操作系统架构
|
||||
IsRightRule = IsRightRule AndAlso ((Rule("os")("arch").ToString = "x86") = Is32BitSystem)
|
||||
IsRightRule = IsRightRule AndAlso Rule("os")("arch").ToString <> "x86" AndAlso Not Rule("os")("arch").Contains("arm")
|
||||
End If
|
||||
End If
|
||||
If Not IsNothing(Rule("features")) Then '标签
|
||||
@@ -2078,11 +2077,11 @@ OnLoaded:
|
||||
Try
|
||||
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
|
||||
Logger.Info("开始获取统一通行证下载信息")
|
||||
Dim DownloadInfo = GetJson(NetRequestByClientRetry("https://auth.mc-user.com:233/" & Settings.Get(Of String)("VersionServerNide", Instance:=Instance), RequireJson:=True))
|
||||
Dim DownloadInfo As JObject = NetRequestByClientRetry("https://auth.mc-user.com:233/" & Settings.Get(Of String)("VersionServerNide", Instance:=Instance), RequireJson:=True).DeserializeJson()
|
||||
Result.Add(New NetFile(
|
||||
Urls:={"https://login.mc-user.com:233/index/jar"},
|
||||
LocalPath:=TargetFile,
|
||||
Checker:=New FileChecker(Hash:=DownloadInfo("jarHash").ToString)))
|
||||
Checker:=New FileChecker With {.Hash = DownloadInfo("jarHash").ToString}))
|
||||
Catch ex As Exception
|
||||
If FileUtils.Exists(TargetFile) Then
|
||||
Logger.Warn(ex, "获取统一通行证下载信息失败")
|
||||
@@ -2097,15 +2096,15 @@ OnLoaded:
|
||||
Dim TargetFile = PathPure & "authlib-injector.jar"
|
||||
Try
|
||||
Logger.Info("开始获取 Authlib-Injector 下载信息")
|
||||
Dim DownloadInfo = GetJson(NetRequestByClientRetry(
|
||||
Dim DownloadInfo As JObject = NetRequestByClientRetry(
|
||||
"https://authlib-injector.yushi.moe/artifact/latest.json",
|
||||
BackupUrl:="https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json", RequireJson:=True))
|
||||
BackupUrl:="https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json", RequireJson:=True).DeserializeJson()
|
||||
Dim DownloadAddress As String = DownloadInfo("download_url").ToString.
|
||||
Replace("bmclapi2.bangbang93.com/mirrors/authlib-injector", "authlib-injector.yushi.moe")
|
||||
Result.Add(New NetFile({
|
||||
DownloadAddress,
|
||||
DownloadAddress.Replace("authlib-injector.yushi.moe", "bmclapi2.bangbang93.com/mirrors/authlib-injector")
|
||||
}, TargetFile, New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)))
|
||||
}, TargetFile, New FileChecker With {.Hash = DownloadInfo("checksums")("sha256").ToString}))
|
||||
Catch ex As Exception
|
||||
If FileUtils.Exists(TargetFile) Then
|
||||
Logger.Warn(ex, "获取 Authlib-Injector 下载信息失败")
|
||||
@@ -2144,7 +2143,7 @@ OnLoaded:
|
||||
If Token.Name.ContainsIgnoreCase("labymod") Then
|
||||
Checker = New FileChecker '不检查 LabyMod 的文件,它们提供的文件校验信息是错的(#3225)
|
||||
Else
|
||||
Checker = New FileChecker(ActualSize:=If(Token.Size = 0, -1, Token.Size), Hash:=Token.SHA1)
|
||||
Checker = New FileChecker With {.ActualSize = If(Token.Size = 0, -1, Token.Size), .Hash = Token.SHA1}
|
||||
End If
|
||||
'URL
|
||||
Dim Urls As New List(Of String)
|
||||
@@ -2238,16 +2237,16 @@ OnLoaded:
|
||||
'返回 assets 文件名会由于没有下载地址导致全局失败
|
||||
'If AssetsName IsNot Nothing AndAlso AssetsName <> "legacy" Then
|
||||
' Log("[Minecraft] 无法获取资源文件索引下载地址,使用 assets 项提供的资源文件名:" & AssetsName)
|
||||
' Return GetJson("{""id"": """ & AssetsName & """}")
|
||||
' Return ("{""id"": """ & AssetsName & """}").DeserializeJson()
|
||||
'Else
|
||||
Logger.Info("无法获取资源文件索引下载地址,使用默认的 legacy 下载地址")
|
||||
Return GetJson("{
|
||||
Return "{
|
||||
""id"": ""legacy"",
|
||||
""sha1"": ""c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729"",
|
||||
""size"": 134284,
|
||||
""url"": ""https://launchermeta.mojang.com/mc-staging/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json"",
|
||||
""totalSize"": 111220701
|
||||
}")
|
||||
}".DeserializeJson()
|
||||
'End If
|
||||
Else
|
||||
Throw New Exception("该版本不存在资源文件索引信息")
|
||||
@@ -2294,7 +2293,7 @@ OnLoaded:
|
||||
Public Hash As String
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
Return FormatFileSize(Size) & " | " & LocalPath
|
||||
Return StringUtils.FormatByteSize(Size) & " | " & LocalPath
|
||||
End Function
|
||||
End Structure
|
||||
''' <summary>
|
||||
@@ -2307,7 +2306,7 @@ OnLoaded:
|
||||
'初始化
|
||||
If Not FileUtils.Exists($"{McFolderSelected}assets\indexes\{IndexName}.json") Then Throw New FileNotFoundException("未找到 Asset Index", McFolderSelected & "assets\indexes\" & IndexName & ".json")
|
||||
Dim Result As New List(Of McAssetsToken)
|
||||
Dim Json As JObject = GetJson(FileUtils.ReadAsString($"{McFolderSelected}assets\indexes\{IndexName}.json"))
|
||||
Dim Json As JObject = FileUtils.ReadAsJson($"{McFolderSelected}assets\indexes\{IndexName}.json")
|
||||
|
||||
'读取列表
|
||||
For Each File As JProperty In Json("objects").Children
|
||||
@@ -2347,8 +2346,7 @@ OnLoaded:
|
||||
Select(Function(Token As McAssetsToken) New NetFile(
|
||||
DlSourceAssetsGet($"https://resources.download.minecraft.net/{Left(Token.Hash, 2)}/{Token.Hash}"),
|
||||
LocalPath:=Token.LocalPath,
|
||||
Checker:=New FileChecker(ActualSize:=If(Token.Size = 0, -1, Token.Size),
|
||||
Hash:=Token.Hash))).ToList
|
||||
Checker:=New FileChecker With {.ActualSize = If(Token.Size = 0, -1, Token.Size), .Hash = Token.Hash})).ToList
|
||||
End If
|
||||
'如果不检查 Hash,则立即处理
|
||||
Dim Result As New List(Of NetFile)
|
||||
@@ -2365,7 +2363,7 @@ OnLoaded:
|
||||
Dim File = FileUtils.GetInfo(Token.LocalPath)
|
||||
If File.Exists AndAlso (Token.Size = 0 OrElse Token.Size = File.Length) Then Continue For
|
||||
'文件不存在,添加下载
|
||||
Result.Add(New NetFile(DlSourceAssetsGet($"https://resources.download.minecraft.net/{Left(Token.Hash, 2)}/{Token.Hash}"), Token.LocalPath, New FileChecker(ActualSize:=If(Token.Size = 0, -1, Token.Size), Hash:=Token.Hash)))
|
||||
Result.Add(New NetFile(DlSourceAssetsGet($"https://resources.download.minecraft.net/{Left(Token.Hash, 2)}/{Token.Hash}"), Token.LocalPath, New FileChecker With {.ActualSize = If(Token.Size = 0, -1, Token.Size), .Hash = Token.Hash}))
|
||||
Next
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, "获取版本缺失的资源文件下载列表失败")
|
||||
@@ -2394,7 +2392,7 @@ OnLoaded:
|
||||
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))
|
||||
If((Date.Now - Time).TotalDays > 1, "更新时间:" & Time.ToString, "更新于:" & StringUtils.FormatTimeSpan(Time - Date.Now, False))
|
||||
Dim MsgResult = MyMsgBox(MsgBoxText, "Minecraft 更新提示", "确定", "下载", If((Date.Now - Time).TotalHours > 3, "更新日志", ""),
|
||||
Button3Action:=Sub() McUpdateLogShow(Version))
|
||||
'弹窗结果
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
Public Module ModModpack
|
||||
Imports System.Collections.ObjectModel
|
||||
Imports System.Text.RegularExpressions
|
||||
|
||||
Public Module ModModpack
|
||||
|
||||
'触发整合包安装的外部接口
|
||||
''' <summary>
|
||||
@@ -11,8 +14,8 @@
|
||||
Sub()
|
||||
Try
|
||||
ModpackInstall(File)
|
||||
Catch ex As CancelledException
|
||||
Catch ex As Exception
|
||||
ex.ThrowIfCanceled()
|
||||
Logger.Error(ex, "手动安装整合包失败", LogBehavior.Alert)
|
||||
End Try
|
||||
End Sub)
|
||||
@@ -21,7 +24,6 @@
|
||||
''' 构建并启动安装给定的整合包文件的加载器,并返回该加载器。若失败则抛出异常。
|
||||
''' 必须在工作线程执行。
|
||||
''' </summary>
|
||||
''' <exception cref="CancelledException" />
|
||||
Public Function ModpackInstall(File As String, Optional InstanceName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
Logger.Info($"整合包安装请求:{If(File, "null")}")
|
||||
Dim Archive As ZipArchive = Nothing
|
||||
@@ -29,7 +31,7 @@
|
||||
Try
|
||||
'字符校验
|
||||
Dim TargetFolder As String = $"{McFolderSelected}versions\{InstanceName}\"
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("游戏路径中不能含有感叹号或分号:" & TargetFolder, HintType.Red) : Throw New CancelledException
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("游戏路径中不能含有感叹号或分号:" & TargetFolder, HintType.Red) : Throw New OperationCanceledException
|
||||
'获取整合包种类与关键 Json
|
||||
Dim PackType As Integer = -1
|
||||
Try
|
||||
@@ -39,7 +41,7 @@
|
||||
If Archive.GetEntry("mmc-pack.json") IsNot Nothing Then PackType = 2 : Exit Try 'MMC 整合包(优先于 manifest.json 判断,#4194)
|
||||
If Archive.GetEntry("modrinth.index.json") IsNot Nothing Then PackType = 4 : Exit Try 'Modrinth 整合包
|
||||
If Archive.GetEntry("manifest.json") IsNot Nothing Then
|
||||
Dim Json As JObject = GetJson(Archive.GetEntry("manifest.json").Open().ReadString(Encoding.UTF8))
|
||||
Dim Json As JObject = Archive.GetEntry("manifest.json").Open().ReadString(Encoding.UTF8).DeserializeJson()
|
||||
If Json("addons") Is Nothing Then
|
||||
PackType = 0 : Exit Try 'CurseForge 整合包
|
||||
Else
|
||||
@@ -59,7 +61,7 @@
|
||||
If PathSplits(1) = "mmc-pack.json" Then PackType = 2 : Exit Try 'MMC 整合包(优先于 manifest.json 判断,#4194)
|
||||
If PathSplits(1) = "modrinth.index.json" Then PackType = 4 : Exit Try 'Modrinth 整合包
|
||||
If PathSplits(1) = "manifest.json" Then
|
||||
Dim Json As JObject = GetJson(Entry.Open().ReadString(Encoding.UTF8))
|
||||
Dim Json As JObject = Entry.Open().ReadString(Encoding.UTF8).DeserializeJson()
|
||||
If Json("addons") Is Nothing Then
|
||||
PackType = 0 : Exit Try 'CurseForge 整合包
|
||||
Else
|
||||
@@ -163,22 +165,21 @@ Retry:
|
||||
''' 弹窗提示整合包中存在不兼容的加载器。
|
||||
''' 如果取消,则抛出 CancelledException。
|
||||
''' </summary>
|
||||
''' <exception cref="CancelledException" />
|
||||
Private Sub NotifyIncompatibleLoader(LoaderName As String)
|
||||
If MyMsgBox($"整合包中存在不兼容的加载器:{LoaderName}{vbCrLf}如果你知道如何手动安装它,可以先选择跳过,然后在整合包下载结束后手动安装。",
|
||||
"不兼容的加载器", "取消", $"不安装 {LoaderName} 并继续") = 1 Then Throw New CancelledException
|
||||
"不兼容的加载器", "取消", $"不安装 {LoaderName} 并继续") = 1 Then Throw New OperationCanceledException
|
||||
End Sub
|
||||
|
||||
#Region "不同类型整合包的安装方法"
|
||||
|
||||
'CurseForge
|
||||
Private Function InstallPackCurseForge(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String,
|
||||
Private Function InstallPackCurseForge(FileAddress As String, Archive As ZipArchive, ArchiveBaseFolder As String,
|
||||
Optional InstanceName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
|
||||
'读取 Json 文件
|
||||
Dim Json As JObject
|
||||
Try
|
||||
Json = GetJson(Archive.GetEntry(ArchiveBaseFolder & "manifest.json").Open().ReadString)
|
||||
Json = Archive.GetEntry(ArchiveBaseFolder & "manifest.json").Open().ReadString().DeserializeJson()
|
||||
Catch ex As Exception
|
||||
Throw New Exception("CurseForge 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
@@ -189,8 +190,8 @@ Retry:
|
||||
InstanceName = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(McFolderSelected & "versions")
|
||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New CancelledException
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||
End If
|
||||
|
||||
'获取 Mod API 版本信息
|
||||
@@ -272,9 +273,9 @@ Retry:
|
||||
MissingDesc.Add($"{Project.TranslatedName} (文件 ID {Missing.FileId})")
|
||||
End If
|
||||
Next
|
||||
If MyMsgBox($"未找到该整合包所需的以下内容,它们可能已被原作者删除:{vbCrLf}- {MissingDesc.Join(vbCrLf & "- ")}{vbCrLf}{vbCrLf}是否继续安装?缺失这些内容可能导致整合包出现异常!",
|
||||
If MyMsgBox($"未找到该整合包所需的以下内容,它们可能已被原作者删除:{vbCrLf}- {MissingDesc.Join(vbCrLf + "- ")}{vbCrLf}{vbCrLf}是否继续安装?缺失这些内容可能导致整合包出现异常!",
|
||||
"整合包内容缺失", "继续", "取消", IsWarn:=True) = 2 Then
|
||||
Task.Interrupt()
|
||||
Task.Cancel()
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
||||
'构造 NetFile
|
||||
@@ -364,7 +365,7 @@ Retry:
|
||||
Dim LoaderName As String = "CurseForge 整合包安装:" & InstanceName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Red)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -377,12 +378,12 @@ Retry:
|
||||
End Function
|
||||
|
||||
'Modrinth
|
||||
Private Function InstallPackModrinth(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional InstanceName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
Private Function InstallPackModrinth(FileAddress As String, Archive As ZipArchive, ArchiveBaseFolder As String, Optional InstanceName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
|
||||
'读取 Json 文件
|
||||
Dim Json As JObject
|
||||
Try
|
||||
Json = GetJson(Archive.GetEntry(ArchiveBaseFolder & "modrinth.index.json").Open().ReadString)
|
||||
Json = Archive.GetEntry(ArchiveBaseFolder & "modrinth.index.json").Open().ReadString().DeserializeJson()
|
||||
Catch ex As Exception
|
||||
Throw New Exception("Modrinth 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
@@ -412,8 +413,8 @@ Retry:
|
||||
InstanceName = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(McFolderSelected & "versions")
|
||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New CancelledException
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||
End If
|
||||
'解压
|
||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||
@@ -452,10 +453,10 @@ Retry:
|
||||
Dim TargetPath As String = $"{McFolderSelected}versions\{InstanceName}\{File("path")}"
|
||||
If Not Path.GetFullPath(TargetPath).StartsWithF(Path.GetFullPath($"{McFolderSelected}versions\{InstanceName}\")) Then
|
||||
MyMsgBox($"整合包的文件路径超出了版本文件夹,请向整合包作者反馈此问题!{vbCrLf}目标:{Path.GetFullPath(TargetPath)}{vbCrLf}错误的文件:{TargetPath}", "文件路径校验失败", IsWarn:=True)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
FileList.Add(New NetFile(Urls, TargetPath,
|
||||
New FileChecker(ActualSize:=File("fileSize").ToObject(Of Long), Hash:=File("hashes")("sha1").ToString), True))
|
||||
New FileChecker With {.ActualSize = File("fileSize").ToObject(Of Long), .Hash = File("hashes")("sha1").ToString}, True))
|
||||
Next
|
||||
If FileList.Any Then
|
||||
InstallLoaders.Add(New LoaderDownload("下载额外文件", FileList) With {.ProgressWeight = FileList.Count * 1.5}) '每个 Mod 需要 1.5s
|
||||
@@ -502,7 +503,7 @@ Retry:
|
||||
Dim LoaderName As String = $"Modrinth 整合包安装:{InstanceName} "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Red)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -515,11 +516,11 @@ Retry:
|
||||
End Function
|
||||
|
||||
'HMCL
|
||||
Private Function InstallPackHMCL(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
Private Function InstallPackHMCL(FileAddress As String, Archive As ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
'读取 Json 文件
|
||||
Dim Json As JObject
|
||||
Try
|
||||
Json = GetJson(Archive.GetEntry(ArchiveBaseFolder & "modpack.json").Open().ReadString(Encoding.UTF8))
|
||||
Json = Archive.GetEntry(ArchiveBaseFolder & "modpack.json").Open().ReadString(Encoding.UTF8).DeserializeJson()
|
||||
Catch ex As Exception
|
||||
Throw New Exception("HMCL 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
@@ -527,8 +528,8 @@ Retry:
|
||||
Dim InstanceName As String = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(McFolderSelected & "versions")
|
||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New CancelledException
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||
'解压
|
||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||
Dim InstallLoaders As New List(Of LoaderBase)
|
||||
@@ -556,7 +557,7 @@ Retry:
|
||||
Dim LoaderName As String = "HMCL 整合包安装:" & InstanceName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Red)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||
@@ -568,11 +569,11 @@ Retry:
|
||||
End Function
|
||||
|
||||
'MMC
|
||||
Private Function InstallPackMMC(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
Private Function InstallPackMMC(FileAddress As String, Archive As ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
'读取 Json 文件
|
||||
Dim PackJson As JObject, PackInstance As String
|
||||
Try
|
||||
PackJson = GetJson(Archive.GetEntry(ArchiveBaseFolder & "mmc-pack.json").Open().ReadString(Encoding.UTF8))
|
||||
PackJson = Archive.GetEntry(ArchiveBaseFolder & "mmc-pack.json").Open().ReadString(Encoding.UTF8).DeserializeJson()
|
||||
PackInstance = Archive.GetEntry(ArchiveBaseFolder & "instance.cfg").Open().ReadString(Encoding.UTF8)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("MMC 整合包安装信息存在问题", ex)
|
||||
@@ -581,8 +582,8 @@ Retry:
|
||||
Dim InstanceName As String = If(PackInstance.RegexSeek("(?<=\nname\=)[^\n]+"), "")
|
||||
Dim Validate As New ValidateFolderName(McFolderSelected & "versions")
|
||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New CancelledException
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||
'解压
|
||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||
Dim SetupFile As String = $"{McFolderSelected}versions\{InstanceName}\PCL\Setup.ini"
|
||||
@@ -609,7 +610,7 @@ Retry:
|
||||
Dim PreLaunchCommand As String = ReadIni(MmcSetupFile, "PreLaunchCommand")
|
||||
If PreLaunchCommand <> "" Then
|
||||
PreLaunchCommand = PreLaunchCommand.Replace("\""", """").
|
||||
Replace("$INST_JAVA", "{java}javaw.exe").
|
||||
Replace("$INST_JAVA", "{java}java.exe").
|
||||
Replace("$INST_MC_DIR\", "{minecraft}").Replace("$INST_MC_DIR", "{minecraft}").
|
||||
Replace("$INST_DIR\", "{verpath}").Replace("$INST_DIR", "{verpath}").
|
||||
Replace("$INST_ID", "{name}").Replace("$INST_NAME", "{name}")
|
||||
@@ -622,10 +623,6 @@ Retry:
|
||||
WriteIni(SetupFile, "VersionServerEnter", ServerAddress)
|
||||
Logger.Info($"迁移 MultiMC 版本独立设置:自动进入服务器:{ServerAddress}")
|
||||
End If
|
||||
If ReadIni(MmcSetupFile, "IgnoreJavaCompatibility", False) Then
|
||||
WriteIni(SetupFile, "VersionAdvanceJava", True)
|
||||
Logger.Info("迁移 MultiMC 版本独立设置:忽略 Java 兼容性警告")
|
||||
End If
|
||||
Dim Logo As String = ReadIni(MmcSetupFile, "iconKey", "")
|
||||
If Logo <> "" AndAlso FileUtils.Exists($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png") Then
|
||||
WriteIni(SetupFile, "LogoCustom", True)
|
||||
@@ -685,7 +682,7 @@ Retry:
|
||||
Dim LoaderName As String = "MMC 整合包安装:" & InstanceName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Red)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -698,13 +695,13 @@ Retry:
|
||||
End Function
|
||||
|
||||
'MCBBS
|
||||
Private Function InstallPackMCBBS(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String,
|
||||
Private Function InstallPackMCBBS(FileAddress As String, Archive As ZipArchive, ArchiveBaseFolder As String,
|
||||
Optional InstanceName As String = Nothing) As LoaderCombo(Of String)
|
||||
'读取 Json 文件
|
||||
Dim Json As JObject
|
||||
Try
|
||||
Dim Entry = If(Archive.GetEntry(ArchiveBaseFolder & "mcbbs.packmeta"), Archive.GetEntry(ArchiveBaseFolder & "manifest.json"))
|
||||
Json = GetJson(Entry.Open().ReadString(Encoding.UTF8))
|
||||
Json = Entry.Open().ReadString(Encoding.UTF8).DeserializeJson()
|
||||
Catch ex As Exception
|
||||
Throw New Exception("MCBBS 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
@@ -713,8 +710,8 @@ Retry:
|
||||
InstanceName = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(McFolderSelected & "versions")
|
||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New CancelledException
|
||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||
End If
|
||||
'解压
|
||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||
@@ -742,7 +739,7 @@ Retry:
|
||||
If Not Addons.ContainsKey("game") Then Throw New Exception("该 MCBBS 整合包未提供游戏版本信息,无法安装!")
|
||||
If Addons.ContainsKey("quilt") Then
|
||||
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Red)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
Dim Request As New McInstallRequest With {
|
||||
.NewInstanceName = InstanceName,
|
||||
@@ -763,7 +760,7 @@ Retry:
|
||||
Dim LoaderName As String = "MCBBS 整合包安装:" & InstanceName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Red)
|
||||
Throw New CancelledException
|
||||
Throw New OperationCanceledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -777,12 +774,12 @@ Retry:
|
||||
End Function
|
||||
|
||||
'带启动器的压缩包
|
||||
Private Function InstallPackLauncherPack(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
Private Function InstallPackLauncherPack(FileAddress As String, Archive As ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
'获取解压路径
|
||||
MyMsgBox("接下来请选择一个空文件夹,它会被安装到这个文件夹里。", "安装", "继续", ForceWait:=True)
|
||||
Dim TargetFolder As String = Dialogs.SelectFolder("选择安装目标(必须是一个空文件夹)", False).FirstOrDefault
|
||||
If TargetFolder Is Nothing Then Throw New CancelledException
|
||||
If Not DirectoryUtils.IsEmpty(TargetFolder) Then Hint("请选择一个空文件夹作为安装目标!", HintType.Red) : Throw New CancelledException
|
||||
If TargetFolder Is Nothing Then Throw New OperationCanceledException
|
||||
If Not DirectoryUtils.IsEmpty(TargetFolder) Then Hint("请选择一个空文件夹作为安装目标!", HintType.Red) : Throw New OperationCanceledException
|
||||
'解压
|
||||
Dim Loader As New LoaderCombo(Of String)("解压压缩包", {
|
||||
New LoaderTask(Of String, Integer)("解压压缩包",
|
||||
@@ -792,7 +789,7 @@ Retry:
|
||||
Thread.Sleep(400) '避免文件争用
|
||||
'查找解压后的 exe 文件
|
||||
Dim Launcher As String = Nothing
|
||||
For Each ExeFile In DirectoryUtils.GetFiles(TargetFolder, True, "*.exe")
|
||||
For Each ExeFile In DirectoryUtils.EnumerateFiles(TargetFolder, searchPattern:="*.exe")
|
||||
Dim Info = FileVersionInfo.GetVersionInfo(ExeFile)
|
||||
Logger.Info($"文件 {ExeFile} 的产品名标识为 {Info.ProductName}")
|
||||
If Info.ProductName = "Plain Craft Launcher" Then
|
||||
@@ -826,7 +823,7 @@ Retry:
|
||||
TargetFolder & ".minecraft\" & ArchiveBaseFolder.Replace("/", "\").TrimStart("\"), '格式例如:包裹文件夹\.minecraft\(最短为空字符串)
|
||||
InstanceName, False)
|
||||
'调用 modpack 文件进行安装
|
||||
Dim ModpackFile = DirectoryUtils.GetFiles(TargetFolder, "modpack.*").First
|
||||
Dim ModpackFile = DirectoryUtils.EnumerateFiles(TargetFolder, True, "modpack.*").First
|
||||
Logger.Info($"调用 modpack 文件继续安装:{ModpackFile}")
|
||||
ModpackInstall(ModpackFile)
|
||||
End Sub)
|
||||
@@ -839,10 +836,10 @@ Retry:
|
||||
End Function
|
||||
|
||||
'普通压缩包
|
||||
Private Function InstallPackCompress(FileAddress As String, Archive As Compression.ZipArchive) As LoaderCombo(Of String)
|
||||
Private Function InstallPackCompress(FileAddress As String, Archive As ZipArchive) As LoaderCombo(Of String)
|
||||
'尝试定位 .minecraft 文件夹:寻找形如 “/versions/XXX/XXX.json” 的路径
|
||||
Dim Match As RegularExpressions.Match = Nothing
|
||||
Dim Regex As New RegularExpressions.Regex("^.*\/(?=versions\/(?<ver>[^\/]+)\/(\k<ver>)\.json$)", RegularExpressions.RegexOptions.IgnoreCase)
|
||||
Dim Match As Match = Nothing
|
||||
Dim Regex As New Regex("^.*\/(?=versions\/(?<ver>[^\/]+)\/(\k<ver>)\.json$)", RegexOptions.IgnoreCase)
|
||||
For Each Entry In Archive.Entries
|
||||
Dim EntryMatch = Regex.Match("/" & Entry.FullName)
|
||||
If EntryMatch.Success Then
|
||||
@@ -856,9 +853,9 @@ Retry:
|
||||
'获取解压路径
|
||||
MyMsgBox("接下来请选择一个空文件夹,它会被安装到这个文件夹里。", "安装", "继续", ForceWait:=True)
|
||||
Dim TargetFolder As String = Dialogs.SelectFolder("选择安装目标(必须是一个空文件夹)", False).FirstOrDefault
|
||||
If TargetFolder Is Nothing Then Throw New CancelledException
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Red) : Throw New CancelledException
|
||||
If Not DirectoryUtils.IsEmpty(TargetFolder) Then Hint("请选择一个空文件夹作为安装目标!", HintType.Red) : Throw New CancelledException
|
||||
If TargetFolder Is Nothing Then Throw New OperationCanceledException
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Red) : Throw New OperationCanceledException
|
||||
If Not DirectoryUtils.IsEmpty(TargetFolder) Then Hint("请选择一个空文件夹作为安装目标!", HintType.Red) : Throw New OperationCanceledException
|
||||
'解压
|
||||
Dim Loader As New LoaderCombo(Of String)("解压压缩包", {
|
||||
New LoaderTask(Of String, Integer)("解压压缩包",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Public Module ModWatcher
|
||||
Public Module ModWatcher
|
||||
|
||||
'对全体的监视
|
||||
Public McWatcherList As New List(Of Watcher)
|
||||
@@ -91,7 +91,7 @@
|
||||
RunInNewThread(
|
||||
Sub()
|
||||
Try
|
||||
Do Until State = MinecraftState.Ended OrElse State = MinecraftState.Crashed OrElse State = MinecraftState.Canceled OrElse Loader.State = LoadState.Interrupted
|
||||
Do Until State = MinecraftState.Ended OrElse State = MinecraftState.Crashed OrElse State = MinecraftState.Canceled OrElse Loader.State = LoadState.Canceled
|
||||
TimerWindow()
|
||||
TimerLog()
|
||||
'设置窗口标题
|
||||
@@ -177,7 +177,7 @@
|
||||
Logger.Error(ex, "输出 Minecraft 日志失败")
|
||||
End Try
|
||||
End Sub
|
||||
Public LatestLog As New Queue(Of String)
|
||||
Public LatestLog As New ConcurrentQueue(Of String)
|
||||
Private Sub GameLog(Text As String)
|
||||
'预处理
|
||||
If Text Is Nothing Then Return
|
||||
@@ -185,7 +185,7 @@
|
||||
'If Text.Contains("�����") Then Hint("检测到错误的日志编码:" & Text)
|
||||
'加入预存储
|
||||
LatestLog.Enqueue(Text)
|
||||
If LatestLog.Count >= 501 Then LatestLog.Dequeue()
|
||||
If LatestLog.Count >= 501 Then LatestLog.TryDequeue(Nothing)
|
||||
Logger.Trace(Text)
|
||||
'进度处理
|
||||
If LogProgress < 1 Then
|
||||
@@ -362,7 +362,7 @@
|
||||
Analyzer.Prepare()
|
||||
Analyzer.Analyze()
|
||||
Analyzer.Output(False, New List(Of String) From
|
||||
{Instance.PathVersion & Instance.Name & ".json", PathExeFolder & "PCL\Log1.txt", PathExeFolder & "PCL\LatestLaunch.bat"})
|
||||
{Instance.PathVersion & Instance.Name & ".json", Paths.Base & "PCL\Log1.txt", Paths.Base & "PCL\LatestLaunch.bat"})
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "崩溃分析失败")
|
||||
End Try
|
||||
|
||||
Reference in New Issue
Block a user