2.7.2
This commit is contained in:
@@ -19,7 +19,6 @@ Public Class Application
|
|||||||
|
|
||||||
'开始
|
'开始
|
||||||
Private Sub Application_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
|
Private Sub Application_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
|
||||||
ApplicationStartTick = GetTimeTick()
|
|
||||||
SecretOnApplicationStart()
|
SecretOnApplicationStart()
|
||||||
Try
|
Try
|
||||||
'检查参数调用
|
'检查参数调用
|
||||||
@@ -104,9 +103,10 @@ Public Class Application
|
|||||||
'日志初始化
|
'日志初始化
|
||||||
LogStart()
|
LogStart()
|
||||||
'添加日志
|
'添加日志
|
||||||
Log("[Start] 程序版本:" & VersionDisplayName & "(" & VersionCode & ")")
|
Log($"[Start] 程序版本:{VersionDisplayName} ({VersionCode})")
|
||||||
Log("[Start] 识别码:" & UniqueAddress & If(ThemeCheckOne(9), ",已解锁反馈主题", ""))
|
Log($"[Start] 识别码:{UniqueAddress}{If(ThemeCheckOne(9), ",已解锁反馈主题", "")}")
|
||||||
Log("[Start] 程序路径:" & PathWithName)
|
Log($"[Start] 程序路径:{PathWithName}")
|
||||||
|
Log($"[Start] 系统编码:{Encoding.Default} ({Encoding.Default.CodePage}, GBK={IsGBKEncoding})")
|
||||||
'检测压缩包运行
|
'检测压缩包运行
|
||||||
If Path.Contains(IO.Path.GetTempPath()) OrElse Path.Contains("AppData\Local\Temp\") Then
|
If Path.Contains(IO.Path.GetTempPath()) OrElse Path.Contains("AppData\Local\Temp\") Then
|
||||||
MyMsgBox("PCL 正在临时文件夹运行,设置、游戏存档等很可能无法保存,且部分功能会无法使用或出错。" & vbCrLf & "请将 PCL 从压缩文件中解压,或是更换文件夹后再继续使用!", "环境警告", "我知道了", IsWarn:=True)
|
MyMsgBox("PCL 正在临时文件夹运行,设置、游戏存档等很可能无法保存,且部分功能会无法使用或出错。" & vbCrLf & "请将 PCL 从压缩文件中解压,或是更换文件夹后再继续使用!", "环境警告", "我知道了", IsWarn:=True)
|
||||||
@@ -220,7 +220,7 @@ Public Class Application
|
|||||||
Names.Remove(sender.Tag)
|
Names.Remove(sender.Tag)
|
||||||
Setup.Set("LoginLegacyName", Join(Names, "¨"))
|
Setup.Set("LoginLegacyName", Join(Names, "¨"))
|
||||||
FrmLoginLegacy.ComboName.ItemsSource = Names
|
FrmLoginLegacy.ComboName.ItemsSource = Names
|
||||||
FrmLoginLegacy.ComboName.Text = If(Names.Count > 0, Names(0), "")
|
FrmLoginLegacy.ComboName.Text = If(Names.Any, Names(0), "")
|
||||||
Case Else
|
Case Else
|
||||||
'第三方
|
'第三方
|
||||||
Dim Token As String = GetStringFromEnum(Setup.Get("LoginType"))
|
Dim Token As String = GetStringFromEnum(Setup.Get("LoginType"))
|
||||||
@@ -238,12 +238,12 @@ Public Class Application
|
|||||||
Select Case Token
|
Select Case Token
|
||||||
Case "Nide"
|
Case "Nide"
|
||||||
FrmLoginNide.ComboName.ItemsSource = Dict.Keys
|
FrmLoginNide.ComboName.ItemsSource = Dict.Keys
|
||||||
FrmLoginNide.ComboName.Text = If(Dict.Keys.Count > 0, Dict.Keys(0), "")
|
FrmLoginNide.ComboName.Text = If(Dict.Keys.Any, Dict.Keys(0), "")
|
||||||
FrmLoginNide.TextPass.Password = If(Dict.Values.Count > 0, Dict.Values(0), "")
|
FrmLoginNide.TextPass.Password = If(Dict.Values.Any, Dict.Values(0), "")
|
||||||
Case "Auth"
|
Case "Auth"
|
||||||
FrmLoginAuth.ComboName.ItemsSource = Dict.Keys
|
FrmLoginAuth.ComboName.ItemsSource = Dict.Keys
|
||||||
FrmLoginAuth.ComboName.Text = If(Dict.Keys.Count > 0, Dict.Keys(0), "")
|
FrmLoginAuth.ComboName.Text = If(Dict.Keys.Any, Dict.Keys(0), "")
|
||||||
FrmLoginAuth.TextPass.Password = If(Dict.Values.Count > 0, Dict.Values(0), "")
|
FrmLoginAuth.TextPass.Password = If(Dict.Values.Any, Dict.Values(0), "")
|
||||||
End Select
|
End Select
|
||||||
End Select
|
End Select
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -8,10 +8,12 @@
|
|||||||
Private Sub MyScrollViewer_PreviewMouseWheel(sender As Object, e As MouseWheelEventArgs) Handles Me.PreviewMouseWheel
|
Private Sub MyScrollViewer_PreviewMouseWheel(sender As Object, e As MouseWheelEventArgs) Handles Me.PreviewMouseWheel
|
||||||
If e.Delta = 0 OrElse ActualHeight = 0 OrElse ScrollableHeight = 0 Then Exit Sub
|
If e.Delta = 0 OrElse ActualHeight = 0 OrElse ScrollableHeight = 0 Then Exit Sub
|
||||||
Dim SourceType = e.Source.GetType
|
Dim SourceType = e.Source.GetType
|
||||||
If Content.TemplatedParent Is Nothing AndAlso
|
If Content.TemplatedParent Is Nothing AndAlso (
|
||||||
((GetType(ComboBox).IsAssignableFrom(SourceType) AndAlso CType(e.Source, ComboBox).IsDropDownOpen) OrElse
|
(GetType(ComboBox).IsAssignableFrom(SourceType) AndAlso CType(e.Source, ComboBox).IsDropDownOpen) OrElse
|
||||||
(GetType(TextBox).IsAssignableFrom(SourceType) AndAlso CType(e.Source, TextBox).AcceptsReturn) OrElse
|
(GetType(TextBox).IsAssignableFrom(SourceType) AndAlso CType(e.Source, TextBox).AcceptsReturn) OrElse
|
||||||
GetType(ComboBoxItem).IsAssignableFrom(SourceType)) Then
|
GetType(ComboBoxItem).IsAssignableFrom(SourceType) OrElse
|
||||||
|
TypeOf e.Source Is CheckBox
|
||||||
|
) Then
|
||||||
'如果当前是在对有滚动条的下拉框或文本框执行,则不接管操作
|
'如果当前是在对有滚动条的下拉框或文本框执行,则不接管操作
|
||||||
Exit Sub
|
Exit Sub
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ Public Class FormMain
|
|||||||
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
||||||
'统计更新日志条目
|
'统计更新日志条目
|
||||||
#If BETA Then
|
#If BETA Then
|
||||||
|
If LastVersion < 321 Then 'Release 2.7.1
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复启动部分整合包导致设置丢失的 Bug"))
|
||||||
|
BugCount += 1
|
||||||
|
End If
|
||||||
If LastVersion < 319 Then 'Release 2.7.0
|
If LastVersion < 319 Then 'Release 2.7.0
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持更新 Mod"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持更新 Mod"))
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持查看可更新的 Mod 的更新日志"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持查看可更新的 Mod 的更新日志"))
|
||||||
@@ -96,7 +100,15 @@ Public Class FormMain
|
|||||||
'3:BUG+ IMP* FEAT-
|
'3:BUG+ IMP* FEAT-
|
||||||
'2:BUG* IMP-
|
'2:BUG* IMP-
|
||||||
'1:BUG-
|
'1:BUG-
|
||||||
If LastVersion < 318 Then 'Snapshot 2.7.1
|
If LastVersion < 322 Then 'Snapshot 2.7.2
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 启动游戏前进行内存优化 设置"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化 MC 性能"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复安装 OptiFine 有概率失败的 Bug"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复启动 Fabric 1.20.5+ 时无法正确选择 Java 的 Bug"))
|
||||||
|
FeatureCount += 18
|
||||||
|
BugCount += 18
|
||||||
|
End If
|
||||||
|
If LastVersion < 320 Then 'Snapshot 2.7.1
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复启动部分整合包导致设置丢失的 Bug"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复启动部分整合包导致设置丢失的 Bug"))
|
||||||
BugCount += 1
|
BugCount += 1
|
||||||
End If
|
End If
|
||||||
@@ -430,6 +442,8 @@ Public Class FormMain
|
|||||||
Log("[Start] 最高版本号从 " & LowerVersionCode & " 升高到 " & VersionCode)
|
Log("[Start] 最高版本号从 " & LowerVersionCode & " 升高到 " & VersionCode)
|
||||||
End If
|
End If
|
||||||
#End If
|
#End If
|
||||||
|
'被移除的窗口设置选项
|
||||||
|
If Setup.Get("LaunchArgumentWindowType") = 5 Then Setup.Set("LaunchArgumentWindowType", 1)
|
||||||
'修改主题设置项名称
|
'修改主题设置项名称
|
||||||
If LowerVersionCode <= 207 Then
|
If LowerVersionCode <= 207 Then
|
||||||
Dim UnlockedTheme As New List(Of String) From {"2"}
|
Dim UnlockedTheme As New List(Of String) From {"2"}
|
||||||
@@ -653,7 +667,7 @@ Public Class FormMain
|
|||||||
If e.ChangedButton = MouseButton.XButton1 OrElse e.ChangedButton = MouseButton.XButton2 Then TriggerPageBack()
|
If e.ChangedButton = MouseButton.XButton1 OrElse e.ChangedButton = MouseButton.XButton2 Then TriggerPageBack()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub TriggerPageBack()
|
Private Sub TriggerPageBack()
|
||||||
If PageCurrent = PageType.Download AndAlso PageCurrentSub = PageSubType.DownloadInstall Then
|
If PageCurrent = PageType.Download AndAlso PageCurrentSub = PageSubType.DownloadInstall AndAlso FrmDownloadInstall.IsInSelectPage Then
|
||||||
FrmDownloadInstall.ExitSelectPage()
|
FrmDownloadInstall.ExitSelectPage()
|
||||||
Else
|
Else
|
||||||
PageBack()
|
PageBack()
|
||||||
@@ -761,7 +775,7 @@ Public Class FormMain
|
|||||||
RunInNewThread(
|
RunInNewThread(
|
||||||
Sub()
|
Sub()
|
||||||
Dim FilePath As String = FilePathList.First
|
Dim FilePath As String = FilePathList.First
|
||||||
Log("[System] 接受文件拖拽:" & FilePath & If(FilePathList.Count > 0, $" 等 {FilePathList.Count} 个文件", ""), LogLevel.Developer)
|
Log("[System] 接受文件拖拽:" & FilePath & If(FilePathList.Any, $" 等 {FilePathList.Count} 个文件", ""), LogLevel.Developer)
|
||||||
'基础检查
|
'基础检查
|
||||||
If Directory.Exists(FilePathList.First) AndAlso Not File.Exists(FilePathList.First) Then
|
If Directory.Exists(FilePathList.First) AndAlso Not File.Exists(FilePathList.First) Then
|
||||||
Hint("请拖入一个文件,而非文件夹!", HintType.Critical)
|
Hint("请拖入一个文件,而非文件夹!", HintType.Critical)
|
||||||
@@ -1176,8 +1190,11 @@ Install:
|
|||||||
''' 通过点击返回按钮或手动触发返回来改变页面。
|
''' 通过点击返回按钮或手动触发返回来改变页面。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub PageBack() Handles BtnTitleInner.Click
|
Public Sub PageBack() Handles BtnTitleInner.Click
|
||||||
If Not PageStack.Any() Then Exit Sub
|
If PageStack.Any() Then
|
||||||
PageChangeActual(PageStack(0))
|
PageChangeActual(PageStack(0))
|
||||||
|
Else
|
||||||
|
PageChange(PageType.Launch)
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'实际处理页面切换
|
'实际处理页面切换
|
||||||
@@ -1357,23 +1374,22 @@ Install:
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub PanMainLeft_Resize(NewWidth As Double)
|
Private Sub PanMainLeft_Resize(NewWidth As Double)
|
||||||
Dim Delta As Double = NewWidth - RectLeftBackground.Width
|
Dim Delta As Double = NewWidth - RectLeftBackground.Width
|
||||||
If Math.Abs(Delta) < 0.1 Then Exit Sub
|
If Math.Abs(Delta) > 0.1 AndAlso AniControlEnabled = 0 Then
|
||||||
If AniControlEnabled = 0 Then
|
|
||||||
If PanMain.Opacity < 0.1 Then PanMainLeft.IsHitTestVisible = False '避免左边栏指向背景未能完美覆盖左边栏
|
If PanMain.Opacity < 0.1 Then PanMainLeft.IsHitTestVisible = False '避免左边栏指向背景未能完美覆盖左边栏
|
||||||
If NewWidth > 0 Then
|
If NewWidth > 0 Then
|
||||||
'宽度足够,显示
|
'宽度足够,显示
|
||||||
AniStart({
|
AniStart({
|
||||||
AaWidth(RectLeftBackground, NewWidth - RectLeftBackground.Width, 400,, New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
AaWidth(RectLeftBackground, NewWidth - RectLeftBackground.Width, 400,, New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
||||||
AaOpacity(RectLeftShadow, 1 - RectLeftShadow.Opacity, 200),
|
AaOpacity(RectLeftShadow, 1 - RectLeftShadow.Opacity, 200),
|
||||||
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 250)
|
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 250)
|
||||||
}, "FrmMain LeftChange", True)
|
}, "FrmMain LeftChange", True)
|
||||||
Else
|
Else
|
||||||
'宽度不足,隐藏
|
'宽度不足,隐藏
|
||||||
AniStart({
|
AniStart({
|
||||||
AaWidth(RectLeftBackground, -RectLeftBackground.Width, 200,, New AniEaseOutFluent),
|
AaWidth(RectLeftBackground, -RectLeftBackground.Width, 200,, New AniEaseOutFluent),
|
||||||
AaOpacity(RectLeftShadow, -RectLeftShadow.Opacity, 200),
|
AaOpacity(RectLeftShadow, -RectLeftShadow.Opacity, 200),
|
||||||
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 170)
|
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 170)
|
||||||
}, "FrmMain LeftChange", True)
|
}, "FrmMain LeftChange", True)
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
RectLeftBackground.Width = NewWidth
|
RectLeftBackground.Width = NewWidth
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ Public Module ModBase
|
|||||||
#Region "声明"
|
#Region "声明"
|
||||||
|
|
||||||
'下列版本信息由更新器自动修改
|
'下列版本信息由更新器自动修改
|
||||||
Public Const VersionBaseName As String = "2.7.1" '不含分支前缀的显示用版本名
|
Public Const VersionBaseName As String = "2.7.2" '不含分支前缀的显示用版本名
|
||||||
Public Const VersionStandardCode As String = "2.7.1." & VersionBranchCode '标准格式的四段式版本号
|
Public Const VersionStandardCode As String = "2.7.2." & VersionBranchCode '标准格式的四段式版本号
|
||||||
#If BETA Then
|
#If BETA Then
|
||||||
Public Const VersionCode As Integer = 319 'Release
|
Public Const VersionCode As Integer = 321 'Release
|
||||||
#Else
|
#Else
|
||||||
Public Const VersionCode As Integer = 320 'Snapshot
|
Public Const VersionCode As Integer = 322 'Snapshot
|
||||||
#End If
|
#End If
|
||||||
'自动生成的版本信息
|
'自动生成的版本信息
|
||||||
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
||||||
@@ -58,7 +58,7 @@ Public Module ModBase
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 程序的打开计时。
|
''' 程序的打开计时。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public ApplicationStartTick As Long
|
Public ApplicationStartTick As Long = GetTimeTick()
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 程序打开时的时间。
|
''' 程序打开时的时间。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -76,6 +76,10 @@ Public Module ModBase
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Is32BitSystem As Boolean = Not Environment.Is64BitOperatingSystem
|
Public Is32BitSystem As Boolean = Not Environment.Is64BitOperatingSystem
|
||||||
''' <summary>
|
''' <summary>
|
||||||
|
''' 是否使用 GBK 编码。
|
||||||
|
''' </summary>
|
||||||
|
Public IsGBKEncoding As Boolean = Encoding.Default.CodePage = 936
|
||||||
|
''' <summary>
|
||||||
''' 操作系统版本。Win10 为 10.0。
|
''' 操作系统版本。Win10 为 10.0。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public OsVersion As Version = Environment.OSVersion.Version
|
Public OsVersion As Version = Environment.OSVersion.Version
|
||||||
@@ -726,8 +730,8 @@ Public Module ModBase
|
|||||||
Public Function GetFileNameFromPath(FilePath As String) As String
|
Public Function GetFileNameFromPath(FilePath As String) As String
|
||||||
FilePath = FilePath.Replace("/", "\")
|
FilePath = FilePath.Replace("/", "\")
|
||||||
If FilePath.EndsWithF("\") Then Throw New Exception("不包含文件名:" & FilePath)
|
If FilePath.EndsWithF("\") Then Throw New Exception("不包含文件名:" & FilePath)
|
||||||
If FilePath.Contains("\") Then FilePath = FilePath.Substring(FilePath.LastIndexOfF("\") + 1)
|
|
||||||
If FilePath.Contains("?") Then FilePath = FilePath.Substring(0, FilePath.IndexOfF("?")) '去掉网络参数后的 ?
|
If FilePath.Contains("?") Then FilePath = FilePath.Substring(0, FilePath.IndexOfF("?")) '去掉网络参数后的 ?
|
||||||
|
If FilePath.Contains("\") Then FilePath = FilePath.Substring(FilePath.LastIndexOfF("\") + 1)
|
||||||
Dim length As Integer = FilePath.Length
|
Dim length As Integer = FilePath.Length
|
||||||
If length = 0 Then Throw New Exception("不包含文件名:" & FilePath)
|
If length = 0 Then Throw New Exception("不包含文件名:" & FilePath)
|
||||||
If length > 250 Then Throw New PathTooLongException("文件名过长:" & FilePath)
|
If length > 250 Then Throw New PathTooLongException("文件名过长:" & FilePath)
|
||||||
@@ -1215,43 +1219,35 @@ Re:
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 尝试根据后缀名判断文件种类并解压文件,支持 gz 与 zip,会尝试将 jar 以 zip 方式解压。
|
''' 尝试根据后缀名判断文件种类并解压文件,支持 gz 与 zip,会尝试将 jar 以 zip 方式解压。
|
||||||
''' 会尝试创建,但不会清空目标文件夹。
|
''' 会尝试创建,但不会清空目标文件夹。
|
||||||
''' 成功返回 True,并非压缩文件或失败返回 False。
|
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing) As Boolean
|
Public Sub ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing)
|
||||||
Try
|
Directory.CreateDirectory(DestDirectory)
|
||||||
Directory.CreateDirectory(DestDirectory)
|
If CompressFilePath.EndsWithF(".gz", True) Then
|
||||||
If CompressFilePath.EndsWithF(".gz", True) Then
|
'以 gz 方式解压
|
||||||
'以 gz 方式解压
|
Dim stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress)
|
||||||
Dim stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress)
|
Dim decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", ""), FileMode.OpenOrCreate, FileAccess.Write)
|
||||||
Dim decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", ""), FileMode.OpenOrCreate, FileAccess.Write)
|
Dim data As Integer = stream.ReadByte()
|
||||||
Dim data As Integer = stream.ReadByte()
|
While data <> -1
|
||||||
While data <> -1
|
decompressedFile.WriteByte(data)
|
||||||
decompressedFile.WriteByte(data)
|
data = stream.ReadByte()
|
||||||
data = stream.ReadByte()
|
End While
|
||||||
End While
|
decompressedFile.Close()
|
||||||
decompressedFile.Close()
|
stream.Close()
|
||||||
stream.Close()
|
Else
|
||||||
Return True
|
'以 zip 方式解压
|
||||||
Else
|
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030")))
|
||||||
'以 zip 方式解压
|
For Each Entry As ZipArchiveEntry In Archive.Entries
|
||||||
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030")))
|
Dim DestinationPath As String = IO.Path.Combine(DestDirectory, Entry.FullName)
|
||||||
For Each Entry As ZipArchiveEntry In Archive.Entries
|
If DestinationPath.EndsWithF("\") OrElse DestinationPath.EndsWithF("/") Then
|
||||||
Dim DestinationPath As String = IO.Path.Combine(DestDirectory, Entry.FullName)
|
Continue For '不创建空文件夹
|
||||||
If DestinationPath.EndsWithF("\") OrElse DestinationPath.EndsWithF("/") Then
|
Else
|
||||||
Continue For '不创建空文件夹
|
Directory.CreateDirectory(GetPathFromFullPath(DestinationPath))
|
||||||
Else
|
Entry.ExtractToFile(DestinationPath, True)
|
||||||
Directory.CreateDirectory(GetPathFromFullPath(DestinationPath))
|
End If
|
||||||
Entry.ExtractToFile(DestinationPath, True)
|
Next
|
||||||
End If
|
End Using
|
||||||
Next
|
End If
|
||||||
End Using
|
End Sub
|
||||||
Return True
|
|
||||||
End If
|
|
||||||
Catch ex As Exception
|
|
||||||
Log(ex, "尝试解压文件失败")
|
|
||||||
Return False
|
|
||||||
End Try
|
|
||||||
End Function
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 删除文件夹,返回删除的文件个数。通过参数选择是否抛出异常。
|
''' 删除文件夹,返回删除的文件个数。通过参数选择是否抛出异常。
|
||||||
@@ -1342,7 +1338,7 @@ Re:
|
|||||||
Loop
|
Loop
|
||||||
DescList = DescList.Distinct.ToList
|
DescList = DescList.Distinct.ToList
|
||||||
Dim Desc As String = Join(DescList, vbCrLf & "→ ")
|
Dim Desc As String = Join(DescList, vbCrLf & "→ ")
|
||||||
Dim Stack As String = If(StackList.Count > 0, vbCrLf & Join(StackList, vbCrLf), "")
|
Dim Stack As String = If(StackList.Any, vbCrLf & Join(StackList, vbCrLf), "")
|
||||||
|
|
||||||
'常见错误(记得同时修改下面的)
|
'常见错误(记得同时修改下面的)
|
||||||
Dim CommonReason As String = Nothing
|
Dim CommonReason As String = Nothing
|
||||||
@@ -1541,6 +1537,12 @@ Re:
|
|||||||
Next
|
Next
|
||||||
Return tmp.ToString()
|
Return tmp.ToString()
|
||||||
End Function
|
End Function
|
||||||
|
''' <summary>
|
||||||
|
''' 检查字符串中的字符是否均为 ASCII 字符。
|
||||||
|
''' </summary>
|
||||||
|
<Extension> Public Function IsASCII(Input As String) As Boolean
|
||||||
|
Return Input.All(Function(c) AscW(c) < 128)
|
||||||
|
End Function
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 高速的 StartsWith。
|
''' 高速的 StartsWith。
|
||||||
@@ -2073,7 +2075,7 @@ NextElement:
|
|||||||
''' <param name="SortRule">传入两个对象,若第一个对象应该排在前面,则返回 True。</param>
|
''' <param name="SortRule">传入两个对象,若第一个对象应该排在前面,则返回 True。</param>
|
||||||
Public Function Sort(Of T)(List As IList(Of T), SortRule As CompareThreadStart(Of T)) As List(Of T)
|
Public Function Sort(Of T)(List As IList(Of T), SortRule As CompareThreadStart(Of T)) As List(Of T)
|
||||||
Dim NewList As New List(Of T)
|
Dim NewList As New List(Of T)
|
||||||
While List.Count > 0
|
While List.Any
|
||||||
Dim Highest = List(0)
|
Dim Highest = List(0)
|
||||||
For i = 1 To List.Count - 1
|
For i = 1 To List.Count - 1
|
||||||
If SortRule(List(i), Highest) Then Highest = List(i)
|
If SortRule(List(i), Highest) Then Highest = List(i)
|
||||||
@@ -2646,7 +2648,7 @@ Retry:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function Shuffle(Of T)(array As IList(Of T)) As IList(Of T)
|
Public Function Shuffle(Of T)(array As IList(Of T)) As IList(Of T)
|
||||||
Shuffle = New List(Of T)
|
Shuffle = New List(Of T)
|
||||||
Do While array.Count > 0
|
Do While array.Any
|
||||||
Dim i As Integer = RandomInteger(0, array.Count - 1)
|
Dim i As Integer = RandomInteger(0, array.Count - 1)
|
||||||
Shuffle.Add(array(i))
|
Shuffle.Add(array(i))
|
||||||
array.RemoveAt(i)
|
array.RemoveAt(i)
|
||||||
|
|||||||
@@ -571,7 +571,7 @@ Restart:
|
|||||||
Public LoaderTaskbarProgress As Double = 0 '平滑后的进度
|
Public LoaderTaskbarProgress As Double = 0 '平滑后的进度
|
||||||
Private LoaderTaskbarProgressLast As Shell.TaskbarItemProgressState = Shell.TaskbarItemProgressState.None
|
Private LoaderTaskbarProgressLast As Shell.TaskbarItemProgressState = Shell.TaskbarItemProgressState.None
|
||||||
|
|
||||||
Public Sub LoaderTaskbarAdd(Loader As LoaderBase)
|
Public Sub LoaderTaskbarAdd(Of T)(Loader As LoaderCombo(Of T))
|
||||||
If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRemove(Loader)
|
If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRemove(Loader)
|
||||||
SyncLock LoaderTaskbarLock
|
SyncLock LoaderTaskbarLock
|
||||||
LoaderTaskbar.Add(Loader)
|
LoaderTaskbar.Add(Loader)
|
||||||
@@ -587,11 +587,11 @@ Restart:
|
|||||||
'外显任务是否已经全部完成
|
'外显任务是否已经全部完成
|
||||||
Dim IsAllDownloadTaskCompleted As Boolean = True
|
Dim IsAllDownloadTaskCompleted As Boolean = True
|
||||||
For Each Loader In LoaderTaskbar
|
For Each Loader In LoaderTaskbar
|
||||||
If Loader.Show AndAlso Loader.State = LoadState.Loading Then IsAllDownloadTaskCompleted = False
|
If Loader.State = LoadState.Loading Then IsAllDownloadTaskCompleted = False
|
||||||
Next
|
Next
|
||||||
'若单个任务已中止或全部任务已完成,则刷新并移除
|
'若单个任务已中止或全部任务已完成,则刷新并移除
|
||||||
For Each Task In LoaderTaskbar.ToList()
|
For Each Task In LoaderTaskbar.ToList()
|
||||||
If (IsAllDownloadTaskCompleted OrElse Task.State = LoadState.Aborted OrElse Task.State = LoadState.Waiting) AndAlso Task.Show Then
|
If IsAllDownloadTaskCompleted OrElse Task.State = LoadState.Aborted OrElse Task.State = LoadState.Waiting Then
|
||||||
If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRefresh(Task)
|
If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRefresh(Task)
|
||||||
LoaderTaskbar.Remove(Task)
|
LoaderTaskbar.Remove(Task)
|
||||||
Log($"[Taskbar] {Task.Name} 已移出任务列表")
|
Log($"[Taskbar] {Task.Name} 已移出任务列表")
|
||||||
@@ -628,7 +628,6 @@ Restart:
|
|||||||
Dim Total As Double = 0, Count As Integer = 0
|
Dim Total As Double = 0, Count As Integer = 0
|
||||||
SyncLock LoaderTaskbarLock
|
SyncLock LoaderTaskbarLock
|
||||||
For Each Task In LoaderTaskbar.ToList
|
For Each Task In LoaderTaskbar.ToList
|
||||||
If Not Task.Show Then Continue For
|
|
||||||
Total += Task.Progress
|
Total += Task.Progress
|
||||||
Count += 1 '避免多线程影响导致计数出错
|
Count += 1 '避免多线程影响导致计数出错
|
||||||
Next
|
Next
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Imports System.Net
|
Imports System.Net
|
||||||
|
Imports PCL.ModNet
|
||||||
|
|
||||||
Public Module ModNet
|
Public Module ModNet
|
||||||
Public Const NetDownloadEnd As String = ".PCLDownloading"
|
Public Const NetDownloadEnd As String = ".PCLDownloading"
|
||||||
@@ -235,11 +236,11 @@ RequestFinished:
|
|||||||
''' 以多线程下载网页文件的方式获取网页源代码。
|
''' 以多线程下载网页文件的方式获取网页源代码。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
''' <param name="Urls">网页的 Url 列表。</param>
|
''' <param name="Urls">网页的 Url 列表。</param>
|
||||||
Public Function NetGetCodeByDownload(Urls As String(), Optional Timeout As Integer = 45000, Optional IsJson As Boolean = False, Optional UseBrowserUserAgent As Boolean = False) As String
|
Public Function NetGetCodeByDownload(Urls As IEnumerable(Of String), Optional Timeout As Integer = 45000, Optional IsJson As Boolean = False, Optional UseBrowserUserAgent As Boolean = False) As String
|
||||||
Dim Temp As String = PathTemp & "Cache\Code\" & Urls(0).GetHashCode() & "_" & GetUuid()
|
Dim Temp As String = PathTemp & "Cache\Code\" & Urls.First.GetHashCode() & "_" & GetUuid()
|
||||||
Dim NewTask As New LoaderDownload("源码获取 " & GetUuid() & "#", New List(Of NetFile) From {New NetFile(Urls, Temp, New FileChecker With {.IsJson = IsJson}, UseBrowserUserAgent)})
|
Dim NewTask As New LoaderDownload("源码获取 " & GetUuid() & "#", New List(Of NetFile) From {New NetFile(Urls, Temp, New FileChecker With {.IsJson = IsJson}, UseBrowserUserAgent)})
|
||||||
Try
|
Try
|
||||||
NewTask.WaitForExitTime(Timeout, TimeoutMessage:="连接服务器超时(第一下载源:" & Urls(0) & ")")
|
NewTask.WaitForExitTime(Timeout, TimeoutMessage:="连接服务器超时(第一下载源:" & Urls.First & ")")
|
||||||
NetGetCodeByDownload = ReadFile(Temp)
|
NetGetCodeByDownload = ReadFile(Temp)
|
||||||
File.Delete(Temp)
|
File.Delete(Temp)
|
||||||
Finally
|
Finally
|
||||||
@@ -448,7 +449,7 @@ RequestFinished:
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 速度下限。
|
''' 速度下限。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public NetTaskSpeedLimitLow As Long = 1024 * 1024L
|
Public NetTaskSpeedLimitLow As Long = 256 * 1024L '256K/s
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 速度上限。若无限制则为 -1。
|
''' 速度上限。若无限制则为 -1。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -601,7 +602,7 @@ RequestFinished:
|
|||||||
SyncLock Task.LockChain
|
SyncLock Task.LockChain
|
||||||
If NextThread Is Nothing Then
|
If NextThread Is Nothing Then
|
||||||
If Task.IsUnknownSize Then
|
If Task.IsUnknownSize Then
|
||||||
Return 1024 * 1024 * 1024 '1G
|
Return 5 * 1024 * 1024 * 1024L '5G
|
||||||
Else
|
Else
|
||||||
Return Task.FileSize - 1
|
Return Task.FileSize - 1
|
||||||
End If
|
End If
|
||||||
@@ -616,7 +617,7 @@ RequestFinished:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public ReadOnly Property DownloadUndone As Long
|
Public ReadOnly Property DownloadUndone As Long
|
||||||
Get
|
Get
|
||||||
Return DownloadEnd + 1 - (DownloadStart + DownloadDone)
|
Return DownloadEnd - (DownloadStart + DownloadDone) + 1
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -715,7 +716,7 @@ RequestFinished:
|
|||||||
CurrentSource = Sources(Id)
|
CurrentSource = Sources(Id)
|
||||||
End While
|
End While
|
||||||
Return CurrentSource
|
Return CurrentSource
|
||||||
ElseIf SourcesOnce.Count > 0 Then
|
ElseIf SourcesOnce.Any Then
|
||||||
'仅存在单线程可用源
|
'仅存在单线程可用源
|
||||||
Return SourcesOnce(0)
|
Return SourcesOnce(0)
|
||||||
Else
|
Else
|
||||||
@@ -728,7 +729,7 @@ RequestFinished:
|
|||||||
''' 是否已经没有可用源了。
|
''' 是否已经没有可用源了。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function IsSourceFailed(Optional AllowOnceSource As Boolean = True) As Boolean
|
Public Function IsSourceFailed(Optional AllowOnceSource As Boolean = True) As Boolean
|
||||||
If AllowOnceSource AndAlso SourcesOnce.Count > 0 Then Return False
|
If AllowOnceSource AndAlso SourcesOnce.Any Then Return False
|
||||||
SyncLock LockSource
|
SyncLock LockSource
|
||||||
For Each Source As NetSource In Sources
|
For Each Source As NetSource In Sources
|
||||||
If Not Source.IsFailed Then Return False
|
If Not Source.IsFailed Then Return False
|
||||||
@@ -754,15 +755,12 @@ RequestFinished:
|
|||||||
''' 导致下载失败的原因。
|
''' 导致下载失败的原因。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Ex As New List(Of Exception)
|
Public Ex As New List(Of Exception)
|
||||||
'''' <summary>
|
|
||||||
'''' 文件进行整体重试的计数。
|
|
||||||
'''' </summary>
|
|
||||||
'Private RetryCount As Integer = 0
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 作为文件组成部分的线程链表。
|
''' 作为文件组成部分的线程链表。
|
||||||
|
''' 如果没有线程,可以为 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Threads As NetThread
|
Public Threads As NetThread
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 文件的总大小。若为 -2 则为未获取,若为 -1 则为无法获取准确大小。
|
''' 文件的总大小。若为 -2 则为未获取,若为 -1 则为无法获取准确大小。
|
||||||
@@ -844,10 +842,10 @@ RequestFinished:
|
|||||||
Case NetState.Get
|
Case NetState.Get
|
||||||
Return 0.04
|
Return 0.04
|
||||||
Case NetState.Download
|
Case NetState.Download
|
||||||
'正在下载中,对应 5% ~ 99%
|
'正在下载中,对应 5% ~ 98%
|
||||||
Dim OriginalProgress As Double = If(IsUnknownSize, 0.5, DownloadDone / Math.Max(FileSize, 1))
|
Dim OriginalProgress As Double = If(IsUnknownSize, 0.5, DownloadDone / Math.Max(FileSize, 1))
|
||||||
OriginalProgress = 1 - (1 - OriginalProgress) ^ 0.9
|
OriginalProgress = 1 - (1 - OriginalProgress) ^ 0.9
|
||||||
Return OriginalProgress * 0.94 + 0.05
|
Return OriginalProgress * 0.93 + 0.05
|
||||||
Case NetState.Merge
|
Case NetState.Merge
|
||||||
Return 0.99
|
Return 0.99
|
||||||
Case NetState.Finish, NetState.Error
|
Case NetState.Finish, NetState.Error
|
||||||
@@ -878,14 +876,13 @@ RequestFinished:
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
Private Const FilePieceLimit As Long = 256 * 1024
|
Private Const FilePieceLimit As Long = 256 * 1024
|
||||||
Public ReadOnly RandomCode As Integer = RandomInteger(0, 999999)
|
|
||||||
Public ReadOnly LockCount As New Object
|
Public ReadOnly LockCount As New Object
|
||||||
Public ReadOnly LockState As New Object
|
Public ReadOnly LockState As New Object
|
||||||
Public ReadOnly LockChain As New Object
|
Public ReadOnly LockChain As New Object
|
||||||
Public ReadOnly LockSource As New Object
|
Public ReadOnly LockSource As New Object
|
||||||
Public ReadOnly LockTasks As New Object
|
Public ReadOnly LockTasks As New Object
|
||||||
|
|
||||||
Private ReadOnly Uuid As Integer = GetUuid()
|
Public ReadOnly Uuid As Integer = GetUuid()
|
||||||
Public Overrides Function Equals(obj As Object) As Boolean
|
Public Overrides Function Equals(obj As Object) As Boolean
|
||||||
Dim file = TryCast(obj, NetFile)
|
Dim file = TryCast(obj, NetFile)
|
||||||
Return file IsNot Nothing AndAlso Uuid = file.Uuid
|
Return file IsNot Nothing AndAlso Uuid = file.Uuid
|
||||||
@@ -914,14 +911,15 @@ RequestFinished:
|
|||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 尝试开始一个新的下载线程。
|
''' 尝试开始一个新的下载线程。
|
||||||
|
''' 如果失败,返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function TryBeginThread() As Boolean
|
Public Function TryBeginThread() As NetThread
|
||||||
Try
|
Try
|
||||||
|
|
||||||
'条件检测
|
'条件检测
|
||||||
If NetTaskThreadCount >= NetTaskThreadLimit OrElse IsSourceFailed() OrElse
|
If NetTaskThreadCount >= NetTaskThreadLimit OrElse IsSourceFailed() OrElse
|
||||||
(IsNoSplit AndAlso Threads IsNot Nothing AndAlso Threads.State <> NetState.Error) Then Return False
|
(IsNoSplit AndAlso Threads IsNot Nothing AndAlso Threads.State <> NetState.Error) Then Return Nothing
|
||||||
If State >= NetState.Merge OrElse State = NetState.WaitForCheck Then Return False
|
If State >= NetState.Merge OrElse State = NetState.WaitForCheck Then Return Nothing
|
||||||
SyncLock LockState
|
SyncLock LockState
|
||||||
If State < NetState.Connect Then State = NetState.Connect
|
If State < NetState.Connect Then State = NetState.Connect
|
||||||
End SyncLock
|
End SyncLock
|
||||||
@@ -936,7 +934,7 @@ RequestFinished:
|
|||||||
'单线程
|
'单线程
|
||||||
If IsSourceFailed(False) Then
|
If IsSourceFailed(False) Then
|
||||||
'确认没有其他线程正使用此点
|
'确认没有其他线程正使用此点
|
||||||
If SourcesOnce(0).Thread IsNot Nothing AndAlso SourcesOnce(0).Thread.State <> NetState.Error Then Return False
|
If SourcesOnce(0).Thread IsNot Nothing AndAlso SourcesOnce(0).Thread.State <> NetState.Error Then Return Nothing
|
||||||
'占用此点
|
'占用此点
|
||||||
Capture:
|
Capture:
|
||||||
SmailFileCache = Nothing
|
SmailFileCache = Nothing
|
||||||
@@ -952,14 +950,8 @@ Capture:
|
|||||||
If Threads Is Nothing Then
|
If Threads Is Nothing Then
|
||||||
StartPosition = 0
|
StartPosition = 0
|
||||||
StartSource = GetSource(FirstThreadSource)
|
StartSource = GetSource(FirstThreadSource)
|
||||||
If StartSource Is Nothing Then
|
FirstThreadSource = StartSource.Id + 1
|
||||||
'没有可用源了
|
GoTo StartThread
|
||||||
Throw New Exception("无可用源,请反馈此问题。")
|
|
||||||
Else
|
|
||||||
'有可用源
|
|
||||||
FirstThreadSource = StartSource.Id + 1
|
|
||||||
GoTo StartThread
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
'寻找失败点
|
'寻找失败点
|
||||||
For Each Thread As NetThread In Threads
|
For Each Thread As NetThread In Threads
|
||||||
@@ -971,24 +963,25 @@ Capture:
|
|||||||
Next
|
Next
|
||||||
'是否禁用多线程,以及规定碎片大小
|
'是否禁用多线程,以及规定碎片大小
|
||||||
Dim TargetUrl As String = GetSource().Url
|
Dim TargetUrl As String = GetSource().Url
|
||||||
If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") OrElse TargetUrl.Contains("github.com") Then Return False
|
If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") OrElse TargetUrl.Contains("github.com") OrElse TargetUrl.Contains("modrinth.com") Then Return Nothing
|
||||||
'寻找最大碎片
|
'寻找最大碎片
|
||||||
|
'FUTURE: 下载引擎重做,计算下载源平均链接时间和线程下载速度,按最高时间节省来开启多线程
|
||||||
Dim FilePieceMax As NetThread = Threads
|
Dim FilePieceMax As NetThread = Threads
|
||||||
For Each Thread As NetThread In Threads
|
For Each Thread As NetThread In Threads
|
||||||
If Thread.DownloadUndone > FilePieceMax.DownloadUndone Then FilePieceMax = Thread
|
If Thread.DownloadUndone > FilePieceMax.DownloadUndone Then FilePieceMax = Thread
|
||||||
Next
|
Next
|
||||||
If FilePieceMax Is Nothing OrElse FilePieceMax.DownloadUndone < FilePieceLimit Then Return False
|
If FilePieceMax Is Nothing OrElse FilePieceMax.DownloadUndone < FilePieceLimit Then Return Nothing
|
||||||
StartPosition = FilePieceMax.DownloadEnd - FilePieceMax.DownloadUndone * 0.4
|
StartPosition = FilePieceMax.DownloadEnd - FilePieceMax.DownloadUndone * 0.4
|
||||||
StartSource = GetSource()
|
StartSource = GetSource()
|
||||||
|
|
||||||
'开始线程
|
'开始线程
|
||||||
StartThread:
|
StartThread:
|
||||||
If (StartPosition > FileSize AndAlso FileSize >= 0 AndAlso Not IsUnknownSize) OrElse StartPosition < 0 OrElse IsNothing(StartSource) Then Return False
|
If (StartPosition > FileSize AndAlso FileSize >= 0 AndAlso Not IsUnknownSize) OrElse StartPosition < 0 OrElse IsNothing(StartSource) Then Return Nothing
|
||||||
'构建线程
|
'构建线程
|
||||||
Dim ThreadUuid As Integer = GetUuid()
|
Dim ThreadUuid As Integer = GetUuid()
|
||||||
SyncLock LockTasks
|
SyncLock LockTasks
|
||||||
If Not Tasks.Any() Then Return False '由于中断,已没有可用任务
|
If Not Tasks.Any() Then Return Nothing '由于中断,已没有可用任务
|
||||||
Th = New Thread(AddressOf Thread) With {.Name = "NetTask " & Tasks(0).Uuid & "/" & Uuid & " Download " & ThreadUuid & "#", .Priority = ThreadPriority.BelowNormal}
|
Th = New Thread(AddressOf Thread) With {.Name = $"NetTask {Tasks(0).Uuid}/{Uuid} Download {ThreadUuid}#", .Priority = ThreadPriority.BelowNormal}
|
||||||
End SyncLock
|
End SyncLock
|
||||||
ThreadInfo = New NetThread With {.Uuid = ThreadUuid, .DownloadStart = StartPosition, .Thread = Th, .Source = StartSource, .Task = Me, .State = NetState.WaitForDownload}
|
ThreadInfo = New NetThread With {.Uuid = ThreadUuid, .DownloadStart = StartPosition, .Thread = Th, .Source = StartSource, .Task = Me, .State = NetState.WaitForDownload}
|
||||||
'链表处理
|
'链表处理
|
||||||
@@ -1012,11 +1005,11 @@ StartThread:
|
|||||||
If IsSourceFailed(False) Then SourcesOnce(0).Thread = ThreadInfo
|
If IsSourceFailed(False) Then SourcesOnce(0).Thread = ThreadInfo
|
||||||
End SyncLock
|
End SyncLock
|
||||||
Th.Start(ThreadInfo)
|
Th.Start(ThreadInfo)
|
||||||
Return True
|
Return ThreadInfo
|
||||||
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "尝试开始下载线程失败(" & If(LocalName, "Nothing") & ")", LogLevel.Hint)
|
Log(ex, "尝试开始下载线程失败(" & If(LocalName, "Nothing") & ")", LogLevel.Hint)
|
||||||
Return False
|
Return Nothing
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -1040,35 +1033,44 @@ StartThread:
|
|||||||
HttpRequest.Timeout = Timeout
|
HttpRequest.Timeout = Timeout
|
||||||
HttpRequest.AddRange(Info.DownloadStart)
|
HttpRequest.AddRange(Info.DownloadStart)
|
||||||
SecretHeadersSign(Info.Source.Url, HttpRequest, UseBrowserUserAgent)
|
SecretHeadersSign(Info.Source.Url, HttpRequest, UseBrowserUserAgent)
|
||||||
|
Dim ContentLength As Long = 0
|
||||||
Using HttpResponse As HttpWebResponse = HttpRequest.GetResponse()
|
Using HttpResponse As HttpWebResponse = HttpRequest.GetResponse()
|
||||||
|
If ModeDebug AndAlso HttpResponse.ResponseUri.OriginalString <> Info.Source.Url Then
|
||||||
|
Log($"[Download] {LocalName} {Info.Uuid}#:重定向至 {HttpResponse.ResponseUri.OriginalString}")
|
||||||
|
End If
|
||||||
'文件大小校验
|
'文件大小校验
|
||||||
Dim ThreadFileSize = HttpResponse.ContentLength
|
ContentLength = HttpResponse.ContentLength
|
||||||
If ThreadFileSize = -1 Then
|
If ContentLength = -1 Then
|
||||||
If FileSize > 1 Then
|
If FileSize > 1 Then
|
||||||
Log("[Download] " & LocalName & " " & Info.Uuid & "#:文件大小未知,但已从其他下载源获取,不作处理")
|
If Info.DownloadStart = 0 Then
|
||||||
|
Log($"[Download] {LocalName} {Info.Uuid}#:文件大小未知,但已从其他下载源获取,不作处理")
|
||||||
|
Else
|
||||||
|
Log($"[Download] {LocalName} {Info.Uuid}#:ContentLength 返回了 -1,无法确定是否支持分段下载,视作不支持")
|
||||||
|
GoTo NotSupportRange
|
||||||
|
End If
|
||||||
Else
|
Else
|
||||||
FileSize = -1 : IsUnknownSize = True
|
FileSize = -1 : IsUnknownSize = True
|
||||||
Log("[Download] " & LocalName & " " & Info.Uuid & "#:文件大小未知")
|
Log($"[Download] {LocalName} {Info.Uuid}#:文件大小未知")
|
||||||
End If
|
End If
|
||||||
ElseIf ThreadFileSize < 0 Then
|
ElseIf ContentLength < 0 Then
|
||||||
Throw New Exception("获取片大小失败,结果为 " & ThreadFileSize & "。")
|
Throw New Exception("获取片大小失败,结果为 " & ContentLength & "。")
|
||||||
ElseIf Info.IsFirstThread Then
|
ElseIf Info.IsFirstThread Then
|
||||||
If Check IsNot Nothing Then
|
If Check IsNot Nothing Then
|
||||||
If ThreadFileSize < Check.MinSize AndAlso Check.MinSize > 0 Then
|
If ContentLength < Check.MinSize AndAlso Check.MinSize > 0 Then
|
||||||
Throw New Exception("文件大小不足,获取结果为 " & ThreadFileSize & ",要求至少为 " & Check.MinSize & "。")
|
Throw New Exception($"文件大小不足,获取结果为 {ContentLength},要求至少为 {Check.MinSize}。")
|
||||||
End If
|
End If
|
||||||
If ThreadFileSize <> Check.ActualSize AndAlso Check.ActualSize > 0 Then
|
If ContentLength <> Check.ActualSize AndAlso Check.ActualSize > 0 Then
|
||||||
Throw New Exception("文件大小不一致,获取结果为 " & ThreadFileSize & ",要求必须为 " & Check.ActualSize & "。")
|
Throw New Exception($"文件大小不一致,获取结果为 {ContentLength},要求必须为 {Check.ActualSize}。")
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
FileSize = ThreadFileSize : IsUnknownSize = False
|
FileSize = ContentLength : IsUnknownSize = False
|
||||||
Log("[Download] " & LocalName & ":文件大小 " & ThreadFileSize & " B" & "(" & GetString(ThreadFileSize) & ")")
|
Log($"[Download] {LocalName} {Info.Uuid}#:文件大小 {ContentLength}({GetString(ContentLength)})")
|
||||||
'若文件大小大于 50 M,进行剩余磁盘空间校验
|
'若文件大小大于 50 M,进行剩余磁盘空间校验
|
||||||
If ThreadFileSize > 50 * 1024 * 1024 Then
|
If ContentLength > 50 * 1024 * 1024 Then
|
||||||
For Each Drive As DriveInfo In DriveInfo.GetDrives
|
For Each Drive As DriveInfo In DriveInfo.GetDrives
|
||||||
Dim DriveName As String = Drive.Name.First.ToString
|
Dim DriveName As String = Drive.Name.First.ToString
|
||||||
Dim RequiredSpace = If(PathTemp.StartsWithF(DriveName), ThreadFileSize * 1.1, 0) +
|
Dim RequiredSpace = If(PathTemp.StartsWithF(DriveName), ContentLength * 1.1, 0) +
|
||||||
If(LocalPath.StartsWithF(DriveName), ThreadFileSize + 5 * 1024 * 1024, 0)
|
If(LocalPath.StartsWithF(DriveName), ContentLength + 5 * 1024 * 1024, 0)
|
||||||
If Drive.TotalFreeSpace < RequiredSpace Then
|
If Drive.TotalFreeSpace < RequiredSpace Then
|
||||||
Throw New Exception(DriveName & " 盘空间不足,无法进行下载。" & vbCrLf & "需要至少 " & GetString(RequiredSpace) & " 空间,但当前仅剩余 " & GetString(Drive.TotalFreeSpace) & "。" &
|
Throw New Exception(DriveName & " 盘空间不足,无法进行下载。" & vbCrLf & "需要至少 " & GetString(RequiredSpace) & " 空间,但当前仅剩余 " & GetString(Drive.TotalFreeSpace) & "。" &
|
||||||
If(PathTemp.StartsWithF(DriveName), vbCrLf & vbCrLf & "下载时需要与文件同等大小的空间存放缓存,你可以在设置中调整缓存文件夹的位置。", ""))
|
If(PathTemp.StartsWithF(DriveName), vbCrLf & vbCrLf & "下载时需要与文件同等大小的空间存放缓存,你可以在设置中调整缓存文件夹的位置。", ""))
|
||||||
@@ -1076,8 +1078,9 @@ StartThread:
|
|||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
ElseIf FileSize < 0 Then
|
ElseIf FileSize < 0 Then
|
||||||
Throw New Exception("非首线程运行时,尚未获取文件大小。")
|
Throw New Exception("非首线程运行时,尚未获取文件大小")
|
||||||
ElseIf Info.DownloadStart > 0 AndAlso ThreadFileSize = FileSize Then
|
ElseIf Info.DownloadStart > 0 AndAlso ContentLength = FileSize Then
|
||||||
|
NotSupportRange:
|
||||||
SyncLock LockSource
|
SyncLock LockSource
|
||||||
If SourcesOnce.Contains(Info.Source) Then
|
If SourcesOnce.Contains(Info.Source) Then
|
||||||
GoTo SourceBreak
|
GoTo SourceBreak
|
||||||
@@ -1085,10 +1088,11 @@ StartThread:
|
|||||||
SourcesOnce.Add(Info.Source)
|
SourcesOnce.Add(Info.Source)
|
||||||
End If
|
End If
|
||||||
End SyncLock
|
End SyncLock
|
||||||
Throw New WebException("该下载源不支持断点续传。")
|
Throw New WebException($"该下载源不支持分段下载:Range 起始于 {Info.DownloadStart},预期 ContentLength 为 {FileSize - Info.DownloadStart},返回 ContentLength 为 {ContentLength},总文件大小 {FileSize}")
|
||||||
ElseIf Not FileSize - Info.DownloadStart = ThreadFileSize Then
|
ElseIf Not FileSize - Info.DownloadStart = ContentLength Then
|
||||||
Throw New WebException("获取到的片大小不一致:线程结果为 " & ThreadFileSize & " B,任务结果为 " & FileSize & "B,起点为 " & Info.DownloadStart & "B。")
|
Throw New WebException($"获取到的分段大小不一致:Range 起始于 {Info.DownloadStart},预期 ContentLength 为 {FileSize - Info.DownloadStart},返回 ContentLength 为 {ContentLength},总文件大小 {FileSize}")
|
||||||
End If
|
End If
|
||||||
|
'Log($"[Download] {LocalName} {Info.Uuid}#:通过大小检查,文件大小 {FileSize},起始点 {Info.DownloadStart},ContentLength {ContentLength}")
|
||||||
Info.State = NetState.Get
|
Info.State = NetState.Get
|
||||||
SyncLock LockState
|
SyncLock LockState
|
||||||
If State < NetState.Get Then State = NetState.Get
|
If State < NetState.Get Then State = NetState.Get
|
||||||
@@ -1108,7 +1112,7 @@ StartThread:
|
|||||||
Dim HttpData As Byte() = New Byte(16384) {}
|
Dim HttpData As Byte() = New Byte(16384) {}
|
||||||
HttpDataCount = HttpStream.Read(HttpData, 0, 16384)
|
HttpDataCount = HttpStream.Read(HttpData, 0, 16384)
|
||||||
While (IsUnknownSize OrElse Info.DownloadUndone > 0) AndAlso '判断是否下载完成
|
While (IsUnknownSize OrElse Info.DownloadUndone > 0) AndAlso '判断是否下载完成
|
||||||
HttpDataCount > 0 AndAlso Not IsProgramEnded AndAlso State < NetState.Merge AndAlso (Not Info.Source.IsFailed OrElse Info.Equals(Info.Source.Thread))
|
HttpDataCount > 0 AndAlso Not IsProgramEnded AndAlso State < NetState.Merge AndAlso (Not Info.Source.IsFailed OrElse Info.Equals(Info.Source.Thread))
|
||||||
'限速
|
'限速
|
||||||
While NetTaskSpeedLimitHigh > 0 AndAlso NetTaskSpeedLimitLeft <= 0
|
While NetTaskSpeedLimitHigh > 0 AndAlso NetTaskSpeedLimitLeft <= 0
|
||||||
Threading.Thread.Sleep(16)
|
Threading.Thread.Sleep(16)
|
||||||
@@ -1170,17 +1174,17 @@ StartThread:
|
|||||||
End Using
|
End Using
|
||||||
End Using
|
End Using
|
||||||
SourceBreak:
|
SourceBreak:
|
||||||
If HttpDataCount = 0 AndAlso Info.DownloadUndone > 0 AndAlso Not IsUnknownSize Then
|
If State = NetState.Error OrElse Info.Source.IsFailed OrElse (Info.DownloadUndone > 0 AndAlso Not IsUnknownSize) Then
|
||||||
'服务器无返回数据
|
|
||||||
Throw New Exception("服务器无返回数据,但下载尚未完成")
|
|
||||||
ElseIf State = NetState.Error OrElse Info.Source.IsFailed OrElse (Info.DownloadUndone > 0 AndAlso Not IsUnknownSize) Then
|
|
||||||
'被外部中断
|
'被外部中断
|
||||||
Info.State = NetState.Error
|
Info.State = NetState.Error
|
||||||
Log("[Download] " & LocalName & " " & Info.Uuid & "#:中断")
|
Log($"[Download] {LocalName} {Info.Uuid}#:中断")
|
||||||
|
ElseIf HttpDataCount = 0 AndAlso Info.DownloadUndone > 0 AndAlso Not IsUnknownSize Then
|
||||||
|
'服务器无返回数据
|
||||||
|
Throw New Exception($"返回的 ContentLength 过多:ContentLength 为 {ContentLength},但获取到的总数据量仅为 {Info.DownloadDone}(全文件总数据量 {DownloadDone})")
|
||||||
Else
|
Else
|
||||||
'本线程完成
|
'本线程完成
|
||||||
Info.State = NetState.Finish
|
Info.State = NetState.Finish
|
||||||
If ModeDebug Then Log("[Download] " & LocalName & " " & Info.Uuid & "#:完成,已下载 " & GetString(Info.DownloadDone))
|
If ModeDebug Then Log($"[Download] {LocalName} {Info.Uuid}#:完成,已下载 {Info.DownloadDone}")
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
'状态变更
|
'状态变更
|
||||||
@@ -1212,11 +1216,11 @@ SourceBreak:
|
|||||||
'End SyncLock
|
'End SyncLock
|
||||||
Info.Source.Ex = ex
|
Info.Source.Ex = ex
|
||||||
'根据情况判断,是否在多线程下禁用下载源(连续错误过多,或不支持断点续传)
|
'根据情况判断,是否在多线程下禁用下载源(连续错误过多,或不支持断点续传)
|
||||||
'BMCLAPI 的部分源在高频率请求下会返回 403,所以不应因此禁用下载源
|
|
||||||
If ex.Message.Contains("该下载源不支持") OrElse ex.Message.Contains("未能解析") OrElse ex.Message.Contains("(404)") OrElse
|
If ex.Message.Contains("该下载源不支持") OrElse ex.Message.Contains("未能解析") OrElse ex.Message.Contains("(404)") OrElse
|
||||||
ex.Message.Contains("(502)") OrElse ex.Message.Contains("无返回数据") OrElse ex.Message.Contains("空间不足") OrElse ex.Message.Contains("获取到的片大小不一致") OrElse
|
ex.Message.Contains("(502)") OrElse ex.Message.Contains("无返回数据") OrElse ex.Message.Contains("空间不足") OrElse ex.Message.Contains("获取到的分段大小不一致") OrElse
|
||||||
(Info.Source.FailCount >= MathClamp(NetTaskThreadLimit, 5, 40) AndAlso DownloadDone < 1) OrElse
|
(ex.Message.Contains("(403)") AndAlso Not Info.Source.Url.ContainsF("bmclapi")) OrElse 'BMCLAPI 的部分源在高频率请求下会返回 403,所以不应因此禁用下载源
|
||||||
Info.Source.FailCount > NetTaskThreadLimit Then
|
(Info.Source.FailCount >= MathClamp(NetTaskThreadLimit, 5, 30) AndAlso DownloadDone < 1) OrElse
|
||||||
|
Info.Source.FailCount > NetTaskThreadLimit + 2 Then
|
||||||
Dim IsThisFail As Boolean = False
|
Dim IsThisFail As Boolean = False
|
||||||
SyncLock LockSource
|
SyncLock LockSource
|
||||||
If Info.Source.Thread IsNot Nothing AndAlso Info.Source.Thread.Equals(Info) Then
|
If Info.Source.Thread IsNot Nothing AndAlso Info.Source.Thread.Equals(Info) Then
|
||||||
@@ -1232,8 +1236,8 @@ Wrong:
|
|||||||
End SyncLock
|
End SyncLock
|
||||||
'本线程引发下载源被禁用
|
'本线程引发下载源被禁用
|
||||||
If IsThisFail Then
|
If IsThisFail Then
|
||||||
Log("[Download] " & LocalName & " " & Uuid & "#:下载源被禁用(" & Info.Source.Id & "):" & Info.Source.Url)
|
Log($"[Download] {LocalName} {Info.Uuid}#:下载源被禁用({Info.Source.Id}):{Info.Source.Url}")
|
||||||
Log(ex, "下载源 " & Info.Source.Id & " 已被禁用", If(ex.Message.Contains("不支持断点续传") OrElse ex.Message.Contains("(404)") OrElse ex.Message.Contains("(416)"), LogLevel.Developer, LogLevel.Debug))
|
Log(ex, "下载源 " & Info.Source.Id & " 已被禁用", If(ex.Message.Contains("不支持分段下载") OrElse ex.Message.Contains("(404)") OrElse ex.Message.Contains("(416)"), LogLevel.Developer, LogLevel.Debug))
|
||||||
If IsSourceFailed() Then
|
If IsSourceFailed() Then
|
||||||
'没有可用源
|
'没有可用源
|
||||||
Log("[Download] 文件 " & LocalName & " 已无可用下载源")
|
Log("[Download] 文件 " & LocalName & " 已无可用下载源")
|
||||||
@@ -1265,6 +1269,7 @@ Wrong:
|
|||||||
SyncLock NetTaskThreadCountLock
|
SyncLock NetTaskThreadCountLock
|
||||||
NetTaskThreadCount -= 1
|
NetTaskThreadCount -= 1
|
||||||
End SyncLock
|
End SyncLock
|
||||||
|
'可能在没有下载完的时候开始合并文件了,这造成了大多数合并失败
|
||||||
If ((FileSize >= 0 AndAlso DownloadDone >= FileSize) OrElse (FileSize = -1 AndAlso DownloadDone > 0)) AndAlso State < NetState.Merge Then Merge()
|
If ((FileSize >= 0 AndAlso DownloadDone >= FileSize) OrElse (FileSize = -1 AndAlso DownloadDone > 0)) AndAlso State < NetState.Merge Then Merge()
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
@@ -1287,7 +1292,6 @@ Wrong:
|
|||||||
Try
|
Try
|
||||||
Retry:
|
Retry:
|
||||||
SyncLock LockChain
|
SyncLock LockChain
|
||||||
If ModeDebug Then Log("[Download] " & LocalName & ":正在合并文件")
|
|
||||||
'创建文件夹
|
'创建文件夹
|
||||||
If File.Exists(LocalPath) Then File.Delete(LocalPath)
|
If File.Exists(LocalPath) Then File.Delete(LocalPath)
|
||||||
Dim Info As New FileInfo(LocalPath)
|
Dim Info As New FileInfo(LocalPath)
|
||||||
@@ -1295,6 +1299,7 @@ Retry:
|
|||||||
'合并文件
|
'合并文件
|
||||||
If IsNoSplit Then
|
If IsNoSplit Then
|
||||||
'仅有一个线程,从缓存中输出
|
'仅有一个线程,从缓存中输出
|
||||||
|
If ModeDebug Then Log($"[Download] {LocalName}:下载结束,从缓存输出文件")
|
||||||
MergeFile = New FileStream(LocalPath, FileMode.Create)
|
MergeFile = New FileStream(LocalPath, FileMode.Create)
|
||||||
AddWriter = New BinaryWriter(MergeFile)
|
AddWriter = New BinaryWriter(MergeFile)
|
||||||
AddWriter.Write(SmailFileCache.ToArray)
|
AddWriter.Write(SmailFileCache.ToArray)
|
||||||
@@ -1302,17 +1307,19 @@ Retry:
|
|||||||
MergeFile.Dispose() : MergeFile = Nothing
|
MergeFile.Dispose() : MergeFile = Nothing
|
||||||
ElseIf Threads.DownloadDone = DownloadDone AndAlso Threads.Temp IsNot Nothing Then
|
ElseIf Threads.DownloadDone = DownloadDone AndAlso Threads.Temp IsNot Nothing Then
|
||||||
'仅有一个文件,直接复制
|
'仅有一个文件,直接复制
|
||||||
|
If ModeDebug Then Log($"[Download] {LocalName}:下载结束,仅有一个文件,无需合并")
|
||||||
CopyFile(Threads.Temp, LocalPath)
|
CopyFile(Threads.Temp, LocalPath)
|
||||||
Else
|
Else
|
||||||
'有多个线程,合并
|
'有多个线程,合并
|
||||||
|
If ModeDebug Then Log($"[Download] {LocalName}:下载结束,开始合并文件")
|
||||||
MergeFile = New FileStream(LocalPath, FileMode.Create)
|
MergeFile = New FileStream(LocalPath, FileMode.Create)
|
||||||
AddWriter = New BinaryWriter(MergeFile)
|
AddWriter = New BinaryWriter(MergeFile)
|
||||||
For Each Thread As NetThread In Threads
|
For Each Thread As NetThread In Threads
|
||||||
If Thread.DownloadDone = 0 OrElse Thread.Temp Is Nothing Then Continue For
|
If Thread.DownloadDone = 0 OrElse Thread.Temp Is Nothing Then Continue For
|
||||||
Using fs As New FileStream(Thread.Temp, FileMode.Open, FileAccess.Read, FileShare.Read)
|
Using fs As New FileStream(Thread.Temp, FileMode.Open, FileAccess.Read, FileShare.Read)
|
||||||
Dim TempReader As New BinaryReader(fs)
|
Using TempReader As New BinaryReader(fs)
|
||||||
AddWriter.Write(TempReader.ReadBytes(fs.Length))
|
AddWriter.Write(TempReader.ReadBytes(Thread.DownloadDone))
|
||||||
TempReader.Close()
|
End Using
|
||||||
End Using
|
End Using
|
||||||
Next
|
Next
|
||||||
AddWriter.Dispose() : AddWriter = Nothing
|
AddWriter.Dispose() : AddWriter = Nothing
|
||||||
@@ -1329,9 +1336,9 @@ Retry:
|
|||||||
'检查文件
|
'检查文件
|
||||||
Dim CheckResult As String = Check?.Check(LocalPath)
|
Dim CheckResult As String = Check?.Check(LocalPath)
|
||||||
If CheckResult IsNot Nothing Then
|
If CheckResult IsNot Nothing Then
|
||||||
Log("[Download] " & Uuid & "# 的下载线程细节:")
|
Log($"[Download] {LocalName} 合并文件失败,下载线程细节:")
|
||||||
For Each Th As NetThread In Threads
|
For Each Th As NetThread In Threads
|
||||||
Log("[Download] " & Th.Uuid & "#,状态 " & GetStringFromEnum(CType(Th.State, [Enum])) & ",字节范围 " & Th.DownloadStart & "~" & (Th.DownloadStart + Th.DownloadDone) & ",字节剩余 " & Th.DownloadUndone)
|
Log($"[Download] {Th.Uuid}#,状态 {GetStringFromEnum(Th.State)},范围 {Th.DownloadStart}~{Th.DownloadStart + Th.DownloadDone},完成 {Th.DownloadDone},剩余 {Th.DownloadUndone}")
|
||||||
Next
|
Next
|
||||||
Throw New Exception(CheckResult)
|
Throw New Exception(CheckResult)
|
||||||
End If
|
End If
|
||||||
@@ -1379,11 +1386,6 @@ Retry:
|
|||||||
SyncLock NetManager.LockRemain
|
SyncLock NetManager.LockRemain
|
||||||
NetManager.FileRemain -= 1
|
NetManager.FileRemain -= 1
|
||||||
Log("[Download] " & LocalName & ":已失败,剩余文件 " & NetManager.FileRemain)
|
Log("[Download] " & LocalName & ":已失败,剩余文件 " & NetManager.FileRemain)
|
||||||
'If NetManage.FileRemainList.Contains(LocalPath) Then
|
|
||||||
' NetManage.FileRemainList.Remove(LocalPath)
|
|
||||||
'Else
|
|
||||||
' Log("ERROR " & LocalPath)
|
|
||||||
'End If
|
|
||||||
End SyncLock
|
End SyncLock
|
||||||
For Each Task In Tasks
|
For Each Task In Tasks
|
||||||
Task.OnFileFail(Me)
|
Task.OnFileFail(Me)
|
||||||
@@ -1396,7 +1398,7 @@ Retry:
|
|||||||
'确认任务移除
|
'确认任务移除
|
||||||
SyncLock LockTasks
|
SyncLock LockTasks
|
||||||
Tasks.Remove(CausedByTask)
|
Tasks.Remove(CausedByTask)
|
||||||
If Tasks.Count > 0 Then Exit Sub
|
If Tasks.Any Then Exit Sub
|
||||||
End SyncLock
|
End SyncLock
|
||||||
'确认中断
|
'确认中断
|
||||||
SyncLock LockState
|
SyncLock LockState
|
||||||
@@ -1406,11 +1408,6 @@ Retry:
|
|||||||
SyncLock NetManager.LockRemain
|
SyncLock NetManager.LockRemain
|
||||||
NetManager.FileRemain -= 1
|
NetManager.FileRemain -= 1
|
||||||
If ModeDebug Then Log("[Download] " & LocalName & ":已取消,剩余文件 " & NetManager.FileRemain)
|
If ModeDebug Then Log("[Download] " & LocalName & ":已取消,剩余文件 " & NetManager.FileRemain)
|
||||||
'If NetManage.FileRemainList.Contains(LocalPath) Then
|
|
||||||
' NetManage.FileRemainList.Remove(LocalPath)
|
|
||||||
'Else
|
|
||||||
' Log("ERROR " & LocalPath)
|
|
||||||
'End If
|
|
||||||
End SyncLock
|
End SyncLock
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -1426,11 +1423,6 @@ Retry:
|
|||||||
SyncLock NetManager.LockRemain
|
SyncLock NetManager.LockRemain
|
||||||
NetManager.FileRemain -= 1
|
NetManager.FileRemain -= 1
|
||||||
If PrintLog Then Log("[Download] " & LocalName & ":已完成,剩余文件 " & NetManager.FileRemain)
|
If PrintLog Then Log("[Download] " & LocalName & ":已完成,剩余文件 " & NetManager.FileRemain)
|
||||||
'If NetManage.FileRemainList.Contains(LocalPath) Then
|
|
||||||
' NetManage.FileRemainList.Remove(LocalPath)
|
|
||||||
'Else
|
|
||||||
' Log("ERROR " & LocalPath)
|
|
||||||
'End If
|
|
||||||
End SyncLock
|
End SyncLock
|
||||||
SyncLock LockTasks
|
SyncLock LockTasks
|
||||||
For Each Task In Tasks
|
For Each Task In Tasks
|
||||||
@@ -1507,7 +1499,7 @@ FinishExCatch:
|
|||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 刷新公开属性。由 NetManager 每 0.2 秒调用一次。
|
''' 刷新公开属性。由 NetManager 每 0.1 秒调用一次。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub RefreshStat()
|
Public Sub RefreshStat()
|
||||||
'计算进度
|
'计算进度
|
||||||
@@ -1519,15 +1511,15 @@ FinishExCatch:
|
|||||||
NewProgress += File.Progress * 0.2
|
NewProgress += File.Progress * 0.2
|
||||||
TotalProgress += 0.2
|
TotalProgress += 0.2
|
||||||
Else
|
Else
|
||||||
NewProgress += File.Progress '* If(File.Progress < 1, 0.9, 1)
|
NewProgress += File.Progress
|
||||||
TotalProgress += 1
|
TotalProgress += 1
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End SyncLock
|
End SyncLock
|
||||||
If TotalProgress > 0 Then NewProgress /= TotalProgress
|
If TotalProgress > 0 Then NewProgress /= TotalProgress
|
||||||
'刷新进度
|
'刷新进度
|
||||||
If NewProgress < 1 AndAlso NewProgress > 0 Then NewProgress = 1 - (1 - NewProgress) ^ 0.9 'MathBezier(NewProgress, 0, 0.05, 1, 0.8, 0.0001)
|
If NewProgress < 1 AndAlso NewProgress > 0 Then NewProgress = 2 * (NewProgress ^ 3) - 3 * (NewProgress ^ 2) + 2 * NewProgress '2x^3-3x^2+2x,模拟开头和结尾更慢的情况
|
||||||
_Progress = NewProgress * 0.99 + 0.01
|
_Progress = NewProgress
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Sub New(Name As String, FileTasks As List(Of NetFile))
|
Public Sub New(Name As String, FileTasks As List(Of NetFile))
|
||||||
@@ -1556,71 +1548,72 @@ NextElement:
|
|||||||
End SyncLock
|
End SyncLock
|
||||||
State = LoadState.Loading
|
State = LoadState.Loading
|
||||||
'开始执行
|
'开始执行
|
||||||
RunInNewThread(Sub()
|
RunInNewThread(
|
||||||
Try
|
Sub()
|
||||||
'输入检测
|
Try
|
||||||
If Not Files.Any() Then
|
'输入检测
|
||||||
OnFinish()
|
If Not Files.Any() Then
|
||||||
Exit Sub
|
OnFinish()
|
||||||
End If
|
Exit Sub
|
||||||
For Each File As NetFile In Files
|
End If
|
||||||
If File Is Nothing Then Throw New ArgumentException("存在空文件请求!")
|
For Each File As NetFile In Files
|
||||||
For Each Source As NetSource In File.Sources
|
If File Is Nothing Then Throw New ArgumentException("存在空文件请求!")
|
||||||
If Not (Source.Url.StartsWithF("https://", True) OrElse Source.Url.StartsWithF("http://", True)) Then
|
For Each Source As NetSource In File.Sources
|
||||||
Source.Ex = New ArgumentException("输入的下载链接不正确!")
|
If Not (Source.Url.StartsWithF("https://", True) OrElse Source.Url.StartsWithF("http://", True)) Then
|
||||||
Source.IsFailed = True
|
Source.Ex = New ArgumentException("输入的下载链接不正确!")
|
||||||
End If
|
Source.IsFailed = True
|
||||||
Next
|
End If
|
||||||
If File.IsSourceFailed() Then Throw New ArgumentException("输入的下载链接不正确!")
|
Next
|
||||||
If Not File.LocalPath.ToLower.Contains(":\") Then Throw New ArgumentException("输入的本地文件地址不正确!")
|
If File.IsSourceFailed() Then Throw New ArgumentException("输入的下载链接不正确!")
|
||||||
If File.LocalPath.EndsWithF("\") Then Throw New ArgumentException("请输入含文件名的完整文件路径!")
|
If Not File.LocalPath.ToLower.Contains(":\") Then Throw New ArgumentException("输入的本地文件地址不正确!")
|
||||||
'文件夹检测
|
If File.LocalPath.EndsWithF("\") Then Throw New ArgumentException("请输入含文件名的完整文件路径!")
|
||||||
Dim DirPath As String = New FileInfo(File.LocalPath).Directory.FullName
|
'文件夹检测
|
||||||
If Not Directory.Exists(DirPath) Then Directory.CreateDirectory(DirPath)
|
Dim DirPath As String = New FileInfo(File.LocalPath).Directory.FullName
|
||||||
Next
|
If Not Directory.Exists(DirPath) Then Directory.CreateDirectory(DirPath)
|
||||||
'接入下载管理器
|
Next
|
||||||
NetManager.Start(Me)
|
'接入下载管理器
|
||||||
'将文件分配给多个线程以进行已存在查找
|
NetManager.Start(Me)
|
||||||
Dim Folders As New List(Of String) '可能会用于已存在查找的文件夹列表
|
'将文件分配给多个线程以进行已存在查找
|
||||||
Dim FoldersFinal As New List(Of String) '最终用于查找的列表
|
Dim Folders As New List(Of String) '可能会用于已存在查找的文件夹列表
|
||||||
If Not Setup.Get("SystemDebugSkipCopy") Then '在设置中禁用复制
|
Dim FoldersFinal As New List(Of String) '最终用于查找的列表
|
||||||
Folders.Add(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\") '总是添加官启文件夹,因为 HMCL 会把所有文件存在这里
|
If Not Setup.Get("SystemDebugSkipCopy") Then '在设置中禁用复制
|
||||||
For Each Folder In McFolderList
|
Folders.Add(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\") '总是添加官启文件夹,因为 HMCL 会把所有文件存在这里
|
||||||
Folders.Add(Folder.Path)
|
For Each Folder In McFolderList
|
||||||
Next
|
Folders.Add(Folder.Path)
|
||||||
Folders = Folders.Distinct.ToList
|
Next
|
||||||
For Each Folder In Folders
|
Folders = Folders.Distinct.ToList
|
||||||
If Folder <> PathMcFolder AndAlso Directory.Exists(Folder) Then FoldersFinal.Add(Folder)
|
For Each Folder In Folders
|
||||||
Next
|
If Folder <> PathMcFolder AndAlso Directory.Exists(Folder) Then FoldersFinal.Add(Folder)
|
||||||
End If
|
Next
|
||||||
'最多 5 个线程,最少每个线程分配 10 个文件
|
End If
|
||||||
SyncLock FilesLock
|
'最多 5 个线程,最少每个线程分配 10 个文件
|
||||||
Dim FilesPerThread As Integer = Math.Max(5, Files.Count / 10 + 1)
|
SyncLock FilesLock
|
||||||
Dim FilesInThread As New List(Of NetFile)
|
Dim FilesPerThread As Integer = Math.Max(5, Files.Count / 10 + 1)
|
||||||
For Each File In Files
|
Dim FilesInThread As New List(Of NetFile)
|
||||||
FilesInThread.Add(File)
|
For Each File In Files
|
||||||
If FilesInThread.Count = FilesPerThread Then
|
FilesInThread.Add(File)
|
||||||
Dim FilesToRun As New List(Of NetFile)
|
If FilesInThread.Count = FilesPerThread Then
|
||||||
FilesToRun.AddRange(FilesInThread)
|
Dim FilesToRun As New List(Of NetFile)
|
||||||
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
FilesToRun.AddRange(FilesInThread)
|
||||||
FilesInThread.Clear()
|
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
||||||
End If
|
FilesInThread.Clear()
|
||||||
Next
|
End If
|
||||||
If FilesInThread.Count > 0 Then
|
Next
|
||||||
Dim FilesToRun As New List(Of NetFile)
|
If FilesInThread.Any Then
|
||||||
FilesToRun.AddRange(FilesInThread)
|
Dim FilesToRun As New List(Of NetFile)
|
||||||
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
FilesToRun.AddRange(FilesInThread)
|
||||||
FilesInThread.Clear()
|
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
||||||
End If
|
FilesInThread.Clear()
|
||||||
End SyncLock
|
End If
|
||||||
Catch ex As Exception
|
End SyncLock
|
||||||
OnFail(New List(Of Exception) From {ex})
|
Catch ex As Exception
|
||||||
End Try
|
OnFail(New List(Of Exception) From {ex})
|
||||||
End Sub, "NetTask " & Uuid & " Main")
|
End Try
|
||||||
|
End Sub, "NetTask " & Uuid & " Main")
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub StartCopy(Files As List(Of NetFile), FolderList As List(Of String))
|
Private Sub StartCopy(Files As List(Of NetFile), FolderList As List(Of String))
|
||||||
Try
|
Try
|
||||||
If ModeDebug Then Log("[Download] 检查线程分配文件数:" & Files.Count)
|
If ModeDebug Then Log("[Download] 检查线程分配文件数:" & Files.Count & ",线程名:" & Thread.CurrentThread.Name)
|
||||||
'试图从已存在的 Minecraft 文件夹中寻找目标文件
|
'试图从已存在的 Minecraft 文件夹中寻找目标文件
|
||||||
Dim ExistFiles As New List(Of KeyValuePair(Of NetFile, String)) '{NetFile, Target As String}
|
Dim ExistFiles As New List(Of KeyValuePair(Of NetFile, String)) '{NetFile, Target As String}
|
||||||
For Each File As NetFile In Files
|
For Each File As NetFile In Files
|
||||||
@@ -1702,14 +1695,13 @@ Retry:
|
|||||||
If ExList Is Nothing OrElse Not ExList.Any() Then ExList = New List(Of Exception) From {New Exception("未知错误!")}
|
If ExList Is Nothing OrElse Not ExList.Any() Then ExList = New List(Of Exception) From {New Exception("未知错误!")}
|
||||||
'寻找第一个不是 404 的下载源
|
'寻找第一个不是 404 的下载源
|
||||||
Dim UsefulExs = ExList.Where(Function(e) Not e.Message.Contains("(404)")).ToList
|
Dim UsefulExs = ExList.Where(Function(e) Not e.Message.Contains("(404)")).ToList
|
||||||
[Error] = If(UsefulExs.Count > 0, UsefulExs(0), ExList(0))
|
[Error] = If(UsefulExs.Any, UsefulExs(0), ExList(0))
|
||||||
'获取实际失败的文件
|
'获取实际失败的文件
|
||||||
SyncLock FilesLock
|
SyncLock FilesLock
|
||||||
For Each File In Files
|
For Each File In Files
|
||||||
If File.State = NetState.Error Then
|
If File.State = NetState.Error Then
|
||||||
[Error] = New Exception("文件下载失败:" & File.LocalPath & vbCrLf & Join(
|
[Error] = New Exception("文件下载失败:" & File.LocalPath & vbCrLf & Join(
|
||||||
File.Sources.Select(Function(s) If(s.Ex Is Nothing, s.Url, s.Ex.Message & "(" & s.Url & ")")).ToList(),
|
File.Sources.Select(Function(s) If(s.Ex Is Nothing, s.Url, s.Ex.Message & "(" & s.Url & ")")), vbCrLf), [Error])
|
||||||
vbCrLf), [Error])
|
|
||||||
Exit For
|
Exit For
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
@@ -1794,9 +1786,9 @@ Retry:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Private SpeedLastDone As Long = 0
|
Private SpeedLastDone As Long = 0
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 最近 10 次下载速度的记录,较新的在后面。间隔为 0.2 秒,故记录了 2 秒的速度。
|
''' 至多最近 30 次下载速度的记录,较新的在前面。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public SpeedLast As New List(Of Long) From {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
Private SpeedLast As New List(Of Long)
|
||||||
'这些属性由 RefreshStat 刷新
|
'这些属性由 RefreshStat 刷新
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 当前的全局下载速度,单位为 Byte / 秒。
|
''' 当前的全局下载速度,单位为 Byte / 秒。
|
||||||
@@ -1808,28 +1800,29 @@ Retry:
|
|||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 进度与下载速度由下载管理线程每隔约 0.2 秒刷新一次。
|
''' 进度与下载速度由下载管理线程每隔约 0.1 秒刷新一次。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub RefreshStat()
|
Private Sub RefreshStat()
|
||||||
Try
|
Try
|
||||||
Dim DeltaTime As Long = GetTimeTick() - RefreshStatLast
|
Dim DeltaTime As Long = GetTimeTick() - RefreshStatLast
|
||||||
RefreshStatLast += DeltaTime
|
RefreshStatLast += DeltaTime
|
||||||
#Region "刷新整体速度"
|
#Region "刷新整体速度"
|
||||||
'计算即时速度
|
'计算瞬时速度
|
||||||
Dim ActualSpeed As Double = Math.Max(0, (DownloadDone - SpeedLastDone) / (DeltaTime / 1000))
|
Dim ActualSpeed As Double = Math.Max(0, (DownloadDone - SpeedLastDone) / (DeltaTime / 1000))
|
||||||
SpeedLast.Add(ActualSpeed)
|
SpeedLast.Insert(0, ActualSpeed)
|
||||||
SpeedLast.RemoveAt(0)
|
If SpeedLast.Count >= 31 Then SpeedLast.RemoveAt(30)
|
||||||
SpeedLastDone = DownloadDone
|
SpeedLastDone = DownloadDone
|
||||||
'计算用于显示的速度
|
'计算用于显示的速度
|
||||||
'If SpeedLast(9) = 0 Then
|
Dim SpeedSum As Long = 0, SpeedDiv As Long = 0, Weight = SpeedLast.Count
|
||||||
' Speed = 0
|
For Each SpeedRecord In SpeedLast
|
||||||
'Else
|
SpeedSum += SpeedRecord * Weight
|
||||||
Speed = (SpeedLast(9) + SpeedLast(8) * 0.9 + SpeedLast(7) * 0.8 + SpeedLast(6) * 0.7 + SpeedLast(5) * 0.6 + SpeedLast(4) * 0.5 + SpeedLast(3) * 0.4 + SpeedLast(2) * 0.3 + SpeedLast(1) * 0.2 + SpeedLast(0) * 0.1) / 5.5
|
SpeedDiv += Weight
|
||||||
'End If
|
Weight -= 1
|
||||||
|
Next
|
||||||
|
Speed = If(SpeedDiv > 0, SpeedSum / SpeedDiv, 0)
|
||||||
'计算新的速度下限
|
'计算新的速度下限
|
||||||
SpeedLast.Add(ActualSpeed)
|
Dim Limit As Long = 0
|
||||||
SpeedLast.RemoveAt(0)
|
If SpeedLast.Count >= 10 Then Limit = SpeedLast.Take(10).Average * 0.85 '取近 1 秒的平均速度的 85%
|
||||||
Dim Limit As Long = Math.Min(Math.Min(Math.Min(Math.Min(SpeedLast(5), SpeedLast(6)), SpeedLast(7)), SpeedLast(8)), SpeedLast(9)) * 0.9
|
|
||||||
If Limit > NetTaskSpeedLimitLow Then
|
If Limit > NetTaskSpeedLimitLow Then
|
||||||
NetTaskSpeedLimitLow = Limit
|
NetTaskSpeedLimitLow = Limit
|
||||||
Log("[Download] " & "速度下限已提升到 " & GetString(Limit))
|
Log("[Download] " & "速度下限已提升到 " & GetString(Limit))
|
||||||
@@ -1854,128 +1847,65 @@ Retry:
|
|||||||
Private Sub StartManager()
|
Private Sub StartManager()
|
||||||
If IsManagerStarted Then Exit Sub
|
If IsManagerStarted Then Exit Sub
|
||||||
IsManagerStarted = True
|
IsManagerStarted = True
|
||||||
RunInNewThread(
|
Dim ThreadStarter =
|
||||||
Sub()
|
Sub(Id As Integer) '0 或 1
|
||||||
Try
|
Try
|
||||||
Dim LastLoopTime As Long
|
|
||||||
While True
|
While True
|
||||||
LastLoopTime = GetTimeTick()
|
Thread.Sleep(20)
|
||||||
'若已完成,则清空
|
'若已完成,则清空
|
||||||
If FileRemain = 0 AndAlso Files.Count > 0 Then
|
If Id = 0 AndAlso FileRemain = 0 AndAlso Files.Any() Then
|
||||||
SyncLock LockFiles
|
SyncLock LockFiles
|
||||||
Files.Clear()
|
Files.Clear()
|
||||||
End SyncLock
|
End SyncLock
|
||||||
End If
|
End If
|
||||||
'开启新线程
|
'获取文件列表
|
||||||
If Speed < NetTaskSpeedLimitLow OrElse FileRemain > NetTaskThreadLimit Then
|
Dim AllFiles As List(Of NetFile)
|
||||||
'速度小于下限或剩余文件还贼多,尝试开启线程
|
SyncLock LockFiles
|
||||||
Dim IsSuccess As Boolean = False
|
AllFiles = Files.Values.ToList()
|
||||||
Dim NewThreadCount As Integer
|
End SyncLock
|
||||||
'确定最大线程追加数
|
Dim WaitingFiles As New List(Of NetFile)
|
||||||
NewThreadCount = Math.Max(FileRemain, MathClamp(NetTaskThreadCount / 2, 1, 4))
|
Dim OngoingFiles As New List(Of NetFile)
|
||||||
NewThreadCount = Math.Floor(NewThreadCount / 2) '双线程启用减半
|
For Each File As NetFile In AllFiles
|
||||||
NewThreadCount = MathClamp(NewThreadCount, 1, NetTaskThreadLimit)
|
If File.Uuid Mod 2 = Id Then Continue For
|
||||||
'循环追加
|
If File.State = NetState.WaitForDownload Then
|
||||||
Do
|
WaitingFiles.Add(File)
|
||||||
IsSuccess = False
|
ElseIf File.State < NetState.Merge Then
|
||||||
'启动 Wait 的文件后立即会变成 Connect,导致第二次循环再次调用,所以需要先暂时存储进去……
|
OngoingFiles.Add(File)
|
||||||
'此外为了减少 LockFiles 的占用时间,所以先遍历列表再开始
|
End If
|
||||||
Dim FilesWaiting As New List(Of NetFile)
|
Next
|
||||||
Dim FilesLoading As New List(Of NetFile)
|
'为等待中的文件开始线程
|
||||||
SyncLock LockFiles
|
For Each File As NetFile In WaitingFiles
|
||||||
For Each File As NetFile In Files.Values
|
If NetTaskThreadCount >= NetTaskThreadLimit Then Continue While '最大线程数检查
|
||||||
If File.RandomCode Mod 2 = 0 Then Continue For
|
Dim NewThread = File.TryBeginThread()
|
||||||
If File.State = NetState.WaitForDownload Then
|
If NewThread IsNot Nothing AndAlso NewThread.Source.Url.Contains("bmclapi.") Then Thread.Sleep(40) '减少 BMCLAPI 请求频率,避免 Too Many Requests
|
||||||
FilesWaiting.Add(File)
|
Next
|
||||||
ElseIf File.State < NetState.Merge Then
|
'为进行中的文件追加线程
|
||||||
FilesLoading.Add(File)
|
If Speed >= NetTaskSpeedLimitLow Then Continue While '下载速度足够,无需新增
|
||||||
End If
|
For Each File As NetFile In OngoingFiles
|
||||||
Next
|
If NetTaskThreadCount >= NetTaskThreadLimit Then Continue While '最大线程数检查
|
||||||
End SyncLock
|
'线程种类计数
|
||||||
'为文件列表中的文件开始线程
|
Dim PreparingCount = 0, DownloadingCount = 0
|
||||||
For Each File As NetFile In FilesWaiting
|
If File.Threads IsNot Nothing Then
|
||||||
If NewThreadCount = 0 Then Exit For
|
For Each Thread As NetThread In File.Threads.ToList
|
||||||
If File.TryBeginThread() Then
|
If Thread.State < NetState.Download Then
|
||||||
IsSuccess = True
|
PreparingCount += 1
|
||||||
NewThreadCount -= 1
|
ElseIf Thread.State = NetState.Download Then
|
||||||
|
DownloadingCount += 1
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
For Each File As NetFile In FilesLoading
|
End If
|
||||||
If NewThreadCount = 0 Then Exit For
|
'新增线程
|
||||||
If File.TryBeginThread() Then
|
If PreparingCount > DownloadingCount Then Continue For '准备中的线程已多于下载中的线程,不再新增
|
||||||
IsSuccess = True
|
Dim NewThread = File.TryBeginThread()
|
||||||
NewThreadCount -= 1
|
If NewThread IsNot Nothing AndAlso NewThread.Source.Url.Contains("bmclapi.") Then Thread.Sleep(40) '减少 BMCLAPI 请求频率,避免 Too Many Requests
|
||||||
End If
|
Next
|
||||||
Next
|
|
||||||
'等待 40 ms:BMCLAPI 部分时候有 20QPS 的限制
|
|
||||||
Thread.Sleep(40)
|
|
||||||
Loop While NewThreadCount > 0 AndAlso IsSuccess
|
|
||||||
End If
|
|
||||||
'等待 40 ms
|
|
||||||
Thread.Sleep(40)
|
|
||||||
End While
|
End While
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "下载管理启动线程 1 出错", LogLevel.Assert)
|
Log(ex, $"下载管理启动线程 {Id} 出错", LogLevel.Assert)
|
||||||
End Try
|
End Try
|
||||||
End Sub, "NetManager ThreadStarter Single")
|
End Sub
|
||||||
RunInNewThread(
|
RunInNewThread(Sub() ThreadStarter(0), "NetManager ThreadStarter 0")
|
||||||
Sub()
|
RunInNewThread(Sub() ThreadStarter(1), "NetManager ThreadStarter 1")
|
||||||
Try
|
|
||||||
Dim LastLoopTime As Long
|
|
||||||
While True
|
|
||||||
LastLoopTime = GetTimeTick()
|
|
||||||
'开启新线程
|
|
||||||
If Speed < NetTaskSpeedLimitLow OrElse FileRemain > NetTaskThreadLimit Then
|
|
||||||
'速度小于下限或剩余文件还贼多,尝试开启线程
|
|
||||||
Dim IsSuccess As Boolean = False
|
|
||||||
Dim NewThreadCount As Integer
|
|
||||||
'确定最大线程追加数
|
|
||||||
NewThreadCount = Math.Max(FileRemain, MathClamp(NetTaskThreadCount / 2, 1, 4))
|
|
||||||
NewThreadCount = Math.Floor(NewThreadCount / 2) '双线程启用减半
|
|
||||||
NewThreadCount = MathClamp(NewThreadCount, 1, NetTaskThreadLimit)
|
|
||||||
'循环追加
|
|
||||||
Do
|
|
||||||
IsSuccess = False
|
|
||||||
'启动 Wait 的文件后立即会变成 Connect,导致第二次循环再次调用,所以需要先暂时存储进去……
|
|
||||||
'此外为了减少 LockFiles 的占用时间,所以先遍历列表再开始
|
|
||||||
Dim FilesWaiting As New List(Of NetFile)
|
|
||||||
Dim FilesLoading As New List(Of NetFile)
|
|
||||||
SyncLock LockFiles
|
|
||||||
For Each File As NetFile In Files.Values
|
|
||||||
If File.RandomCode Mod 2 = 1 Then Continue For
|
|
||||||
If File.State = NetState.WaitForDownload Then
|
|
||||||
FilesWaiting.Add(File)
|
|
||||||
ElseIf File.State < NetState.Merge Then
|
|
||||||
FilesLoading.Add(File)
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
End SyncLock
|
|
||||||
'为文件列表中的文件开始线程
|
|
||||||
For Each File As NetFile In FilesWaiting
|
|
||||||
If NewThreadCount = 0 Then Exit For
|
|
||||||
If File.TryBeginThread() Then
|
|
||||||
IsSuccess = True
|
|
||||||
NewThreadCount -= 1
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
For Each File As NetFile In FilesLoading
|
|
||||||
If NewThreadCount = 0 Then Exit For
|
|
||||||
If File.TryBeginThread() Then
|
|
||||||
IsSuccess = True
|
|
||||||
NewThreadCount -= 1
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
'等待 40 ms:BMCLAPI 部分时候有 20QPS 的限制
|
|
||||||
Thread.Sleep(40)
|
|
||||||
Loop While NewThreadCount > 0 AndAlso IsSuccess
|
|
||||||
End If
|
|
||||||
'等待 40 ms
|
|
||||||
Thread.Sleep(40)
|
|
||||||
End While
|
|
||||||
Catch ex As Exception
|
|
||||||
Log(ex, "下载管理启动线程 2 出错", LogLevel.Assert)
|
|
||||||
End Try
|
|
||||||
End Sub, "NetManager ThreadStarter Odd")
|
|
||||||
RunInNewThread(
|
RunInNewThread(
|
||||||
Sub()
|
Sub()
|
||||||
Try
|
Try
|
||||||
@@ -1989,8 +1919,8 @@ Retry:
|
|||||||
NetTaskSpeedLimitLeftLast = TimeNow
|
NetTaskSpeedLimitLeftLast = TimeNow
|
||||||
'刷新公开属性
|
'刷新公开属性
|
||||||
RefreshStat()
|
RefreshStat()
|
||||||
'等待直至 170 ms
|
'等待直至 80 ms
|
||||||
Do While GetTimeTick() - LastLoopTime < 170
|
Do While GetTimeTick() - LastLoopTime < 80
|
||||||
Thread.Sleep(10)
|
Thread.Sleep(10)
|
||||||
Loop
|
Loop
|
||||||
End While
|
End While
|
||||||
|
|||||||
@@ -414,10 +414,10 @@
|
|||||||
Json("Website") = Website
|
Json("Website") = Website
|
||||||
If LastUpdate IsNot Nothing Then Json("LastUpdate") = LastUpdate
|
If LastUpdate IsNot Nothing Then Json("LastUpdate") = LastUpdate
|
||||||
Json("DownloadCount") = DownloadCount
|
Json("DownloadCount") = DownloadCount
|
||||||
If ModLoaders IsNot Nothing AndAlso ModLoaders.Count > 0 Then Json("ModLoaders") = New JArray(ModLoaders.Select(Function(m) CInt(m)))
|
If ModLoaders IsNot Nothing AndAlso ModLoaders.Any Then Json("ModLoaders") = New JArray(ModLoaders.Select(Function(m) CInt(m)))
|
||||||
Json("Tags") = New JArray(Tags)
|
Json("Tags") = New JArray(Tags)
|
||||||
If LogoUrl IsNot Nothing Then Json("LogoUrl") = LogoUrl
|
If LogoUrl IsNot Nothing Then Json("LogoUrl") = LogoUrl
|
||||||
If GameVersions.Count > 0 Then Json("GameVersions") = New JArray(GameVersions)
|
If GameVersions.Any Then Json("GameVersions") = New JArray(GameVersions)
|
||||||
Json("CacheTime") = Date.Now '用于检查缓存时间
|
Json("CacheTime") = Date.Now '用于检查缓存时间
|
||||||
Return Json
|
Return Json
|
||||||
End Function
|
End Function
|
||||||
@@ -596,7 +596,7 @@
|
|||||||
SubtitleList = SubtitleList.Distinct().ToList()
|
SubtitleList = SubtitleList.Distinct().ToList()
|
||||||
'设置标题与描述
|
'设置标题与描述
|
||||||
Dim Subtitle As String = ""
|
Dim Subtitle As String = ""
|
||||||
If SubtitleList.Count > 0 Then
|
If SubtitleList.Any Then
|
||||||
For Each Ex In SubtitleList
|
For Each Ex In SubtitleList
|
||||||
Dim IsModLoaderDescription As Boolean =
|
Dim IsModLoaderDescription As Boolean =
|
||||||
Ex.ToLower.Contains("forge") OrElse Ex.ToLower.Contains("fabric") OrElse Ex.ToLower.Contains("quilt")
|
Ex.ToLower.Contains("forge") OrElse Ex.ToLower.Contains("fabric") OrElse Ex.ToLower.Contains("quilt")
|
||||||
@@ -1356,9 +1356,9 @@ Retry:
|
|||||||
Dim Info As String = ""
|
Dim Info As String = ""
|
||||||
Select Case Type
|
Select Case Type
|
||||||
Case CompType.Mod
|
Case CompType.Mod
|
||||||
Info += If(ModLoaders.Count > 0,
|
Info += If(ModLoaders.Any,
|
||||||
"适用于 " & Join(ModLoaders.Select(Function(m) GetStringFromEnum(m)).ToList, "/") & ",", "")
|
"适用于 " & Join(ModLoaders.Select(Function(m) GetStringFromEnum(m)).ToList, "/") & ",", "")
|
||||||
Info += If(ModeDebug AndAlso Dependencies.Count > 0, Dependencies.Count & " 个前置 Mod,", "")
|
Info += If(ModeDebug AndAlso Dependencies.Any, Dependencies.Count & " 个前置 Mod,", "")
|
||||||
Case CompType.ModPack
|
Case CompType.ModPack
|
||||||
If GameVersions.All(Function(v) v.Contains("w")) Then
|
If GameVersions.All(Function(v) v.Contains("w")) Then
|
||||||
Info += $"游戏版本 {Join(GameVersions, "、")},"
|
Info += $"游戏版本 {Join(GameVersions, "、")},"
|
||||||
@@ -1452,7 +1452,7 @@ Retry:
|
|||||||
SelectMany(Function(f) f.RawDependencies).Distinct().ToList
|
SelectMany(Function(f) f.RawDependencies).Distinct().ToList
|
||||||
Dim UndoneDeps = Deps.Where(Function(f) Not CompProjectCache.ContainsKey(f)).ToList
|
Dim UndoneDeps = Deps.Where(Function(f) Not CompProjectCache.ContainsKey(f)).ToList
|
||||||
'获取前置 Mod 工程信息
|
'获取前置 Mod 工程信息
|
||||||
If UndoneDeps.Count > 0 Then
|
If UndoneDeps.Any Then
|
||||||
Log($"[Comp] {ProjectId} 文件列表中还需要获取信息的前置 Mod:{Join(UndoneDeps, ",")}")
|
Log($"[Comp] {ProjectId} 文件列表中还需要获取信息的前置 Mod:{Join(UndoneDeps, ",")}")
|
||||||
Dim Projects As JArray
|
Dim Projects As JArray
|
||||||
If TargetProject.FromCurseForge Then
|
If TargetProject.FromCurseForge Then
|
||||||
@@ -1467,7 +1467,7 @@ Retry:
|
|||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
'更新前置 Mod 信息
|
'更新前置 Mod 信息
|
||||||
If Deps.Count > 0 Then
|
If Deps.Any Then
|
||||||
For Each DepProject In Deps.Select(Function(id) CompProjectCache(id))
|
For Each DepProject In Deps.Select(Function(id) CompProjectCache(id))
|
||||||
For Each File In CompFilesCache(ProjectId)
|
For Each File In CompFilesCache(ProjectId)
|
||||||
If File.RawDependencies.Contains(DepProject.Id) AndAlso DepProject.Id <> ProjectId Then
|
If File.RawDependencies.Contains(DepProject.Id) AndAlso DepProject.Id <> ProjectId Then
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
Log(ex, "读取可能的崩溃日志文件失败(" & FilePath & ")")
|
Log(ex, "读取可能的崩溃日志文件失败(" & FilePath & ")")
|
||||||
End Try
|
End Try
|
||||||
Next
|
Next
|
||||||
If LatestLog IsNot Nothing AndAlso LatestLog.Count > 0 Then
|
If LatestLog IsNot Nothing AndAlso LatestLog.Any Then
|
||||||
Dim RawOutput As String = Join(LatestLog, vbCrLf)
|
Dim RawOutput As String = Join(LatestLog, vbCrLf)
|
||||||
Log("[Crash] 以下为游戏输出的最后一段内容:" & vbCrLf & RawOutput)
|
Log("[Crash] 以下为游戏输出的最后一段内容:" & vbCrLf & RawOutput)
|
||||||
WriteFile(TempFolder & "RawOutput.log", RawOutput)
|
WriteFile(TempFolder & "RawOutput.log", RawOutput)
|
||||||
@@ -110,21 +110,20 @@
|
|||||||
Public Sub Import(FilePath As String)
|
Public Sub Import(FilePath As String)
|
||||||
Log("[Crash] 步骤 1:自主导入日志文件")
|
Log("[Crash] 步骤 1:自主导入日志文件")
|
||||||
|
|
||||||
'解压压缩包
|
'尝试视作压缩包解压
|
||||||
Try
|
Try
|
||||||
Dim Info As New FileInfo(FilePath)
|
Dim Info As New FileInfo(FilePath)
|
||||||
If Not Info.Exists OrElse Info.Length = 0 Then Exit Try
|
If Info.Exists AndAlso Info.Length > 0 AndAlso Not FilePath.EndsWithF(".jar", True) Then
|
||||||
If Not FilePath.EndsWithF(".jar", True) AndAlso ExtractFile(FilePath, TempFolder & "Temp\") Then
|
ExtractFile(FilePath, TempFolder & "Temp\")
|
||||||
'解压成功
|
|
||||||
Log("[Crash] 已解压导入的日志文件:" & FilePath)
|
Log("[Crash] 已解压导入的日志文件:" & FilePath)
|
||||||
Else
|
GoTo Extracted
|
||||||
'解压失败
|
|
||||||
CopyFile(FilePath, TempFolder & "Temp\" & GetFileNameFromPath(FilePath))
|
|
||||||
Log("[Crash] 已复制导入的日志文件:" & FilePath)
|
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch
|
||||||
Log(ex, "解压导入文件中的压缩包失败")
|
|
||||||
End Try
|
End Try
|
||||||
|
'并非压缩包
|
||||||
|
CopyFile(FilePath, TempFolder & "Temp\" & GetFileNameFromPath(FilePath))
|
||||||
|
Log("[Crash] 已复制导入的日志文件:" & FilePath)
|
||||||
|
Extracted:
|
||||||
|
|
||||||
'导入其中的日志文件
|
'导入其中的日志文件
|
||||||
For Each TargetFile As FileInfo In New DirectoryInfo(TempFolder & "Temp\").EnumerateFiles.ToList()
|
For Each TargetFile As FileInfo In New DirectoryInfo(TempFolder & "Temp\").EnumerateFiles.ToList()
|
||||||
@@ -389,9 +388,9 @@
|
|||||||
|
|
||||||
'1. 精准日志匹配,中/高优先级
|
'1. 精准日志匹配,中/高优先级
|
||||||
AnalyzeCrit1()
|
AnalyzeCrit1()
|
||||||
If CrashReasons.Count > 0 Then GoTo Done
|
If CrashReasons.Any Then GoTo Done
|
||||||
AnalyzeCrit2()
|
AnalyzeCrit2()
|
||||||
If CrashReasons.Count > 0 Then GoTo Done
|
If CrashReasons.Any Then GoTo Done
|
||||||
|
|
||||||
'2. 堆栈分析
|
'2. 堆栈分析
|
||||||
If LogAll.Contains("orge") OrElse LogAll.Contains("abric") OrElse LogAll.Contains("uilt") OrElse LogAll.Contains("iteloader") Then
|
If LogAll.Contains("orge") OrElse LogAll.Contains("abric") OrElse LogAll.Contains("uilt") OrElse LogAll.Contains("iteloader") Then
|
||||||
@@ -406,7 +405,7 @@
|
|||||||
If LogMc IsNot Nothing Then
|
If LogMc IsNot Nothing Then
|
||||||
Dim Fatals = RegexSearch(LogMc, "/FATAL] [\w\W]+?(?=[\n]+\[)")
|
Dim Fatals = RegexSearch(LogMc, "/FATAL] [\w\W]+?(?=[\n]+\[)")
|
||||||
Log("[Crash] 开始进行 Minecraft 日志堆栈分析,发现 " & Fatals.Count & " 个报错项")
|
Log("[Crash] 开始进行 Minecraft 日志堆栈分析,发现 " & Fatals.Count & " 个报错项")
|
||||||
If Fatals.Count > 0 Then
|
If Fatals.Any Then
|
||||||
For Each Fatal In Fatals
|
For Each Fatal In Fatals
|
||||||
Keywords.AddRange(AnalyzeStackKeyword(Fatal))
|
Keywords.AddRange(AnalyzeStackKeyword(Fatal))
|
||||||
Next
|
Next
|
||||||
@@ -419,7 +418,7 @@
|
|||||||
Keywords.AddRange(AnalyzeStackKeyword(StackLogs))
|
Keywords.AddRange(AnalyzeStackKeyword(StackLogs))
|
||||||
End If
|
End If
|
||||||
'Mod 名称分析
|
'Mod 名称分析
|
||||||
If Keywords.Count > 0 Then
|
If Keywords.Any Then
|
||||||
Dim Names = AnalyzeModName(Keywords)
|
Dim Names = AnalyzeModName(Keywords)
|
||||||
If Names Is Nothing Then
|
If Names Is Nothing Then
|
||||||
AppendReason(CrashReason.堆栈分析发现关键字, Keywords)
|
AppendReason(CrashReason.堆栈分析发现关键字, Keywords)
|
||||||
@@ -442,7 +441,7 @@ Done:
|
|||||||
Else
|
Else
|
||||||
Log("[Crash] 步骤 3:分析崩溃原因完成,找到 " & CrashReasons.Count & " 条可能的原因")
|
Log("[Crash] 步骤 3:分析崩溃原因完成,找到 " & CrashReasons.Count & " 条可能的原因")
|
||||||
For Each Reason In CrashReasons
|
For Each Reason In CrashReasons
|
||||||
Log("[Crash] - " & GetStringFromEnum(Reason.Key) & If(Reason.Value.Count > 0, "(" & Join(Reason.Value, ";") & ")", ""))
|
Log("[Crash] - " & GetStringFromEnum(Reason.Key) & If(Reason.Value.Any, "(" & Join(Reason.Value, ";") & ")", ""))
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -458,7 +457,7 @@ Done:
|
|||||||
Else
|
Else
|
||||||
CrashReasons.Add(Reason, New List(Of String)(If(Additional, {})))
|
CrashReasons.Add(Reason, New List(Of String)(If(Additional, {})))
|
||||||
End If
|
End If
|
||||||
Log("[Crash] 可能的崩溃原因:" & GetStringFromEnum(Reason) & If(Additional IsNot Nothing AndAlso Additional.Count > 0, "(" & Join(Additional, ";") & ")", ""))
|
Log("[Crash] 可能的崩溃原因:" & GetStringFromEnum(Reason) & If(Additional IsNot Nothing AndAlso Additional.Any, "(" & Join(Additional, ";") & ")", ""))
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub AppendReason(Reason As CrashReason, Additional As String)
|
Private Sub AppendReason(Reason As CrashReason, Additional As String)
|
||||||
AppendReason(Reason, If(String.IsNullOrEmpty(Additional), Nothing, New List(Of String) From {Additional}))
|
AppendReason(Reason, If(String.IsNullOrEmpty(Additional), Nothing, New List(Of String) From {Additional}))
|
||||||
@@ -567,7 +566,6 @@ Done:
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
If LogCrash.Contains("Multiple entries with same key: ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Multiple entries with same key: )[^=]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
If LogCrash.Contains("Multiple entries with same key: ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Multiple entries with same key: )[^=]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||||
If LogCrash.Contains("due to errors, provided by ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=due to errors, provided by ')[^']+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
|
||||||
If LogCrash.Contains("LoaderExceptionModCrash: Caught exception from ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=LoaderExceptionModCrash: Caught exception from )[^\n]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
If LogCrash.Contains("LoaderExceptionModCrash: Caught exception from ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=LoaderExceptionModCrash: Caught exception from )[^\n]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||||
If LogCrash.Contains("Failed loading config file ") Then AppendReason(CrashReason.Mod配置文件导致游戏崩溃, {TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Failed loading config file .+ for modid )[^\n]+"), "").TrimEnd(vbCrLf)).First, If(RegexSeek(LogCrash, "(?<=Failed loading config file ).+(?= of type)"), "").TrimEnd(vbCrLf)})
|
If LogCrash.Contains("Failed loading config file ") Then AppendReason(CrashReason.Mod配置文件导致游戏崩溃, {TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Failed loading config file .+ for modid )[^\n]+"), "").TrimEnd(vbCrLf)).First, If(RegexSeek(LogCrash, "(?<=Failed loading config file ).+(?= of type)"), "").TrimEnd(vbCrLf)})
|
||||||
End If
|
End If
|
||||||
@@ -612,6 +610,9 @@ Done:
|
|||||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "[^./ \]]+(?=.mixins.json)")
|
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "[^./ \]]+(?=.mixins.json)")
|
||||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=mixins.)[^./ \]]+(?=.json)")
|
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=mixins.)[^./ \]]+(?=.json)")
|
||||||
AppendReason(CrashReason.ModMixin失败, TryAnalyzeModName(If(ModId, "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
AppendReason(CrashReason.ModMixin失败, TryAnalyzeModName(If(ModId, "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||||
|
Else
|
||||||
|
'在 #3104 的情况下,这一句导致 OptiFabric 的 Mixin 失败错判为 Fabric Loader 加载失败
|
||||||
|
If LogMc.Contains("due to errors, provided by ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogMc, "(?<=due to errors, provided by ')[^']+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||||
End If
|
End If
|
||||||
'极短的程序输出
|
'极短的程序输出
|
||||||
If Not (LogMc.Contains("at net.") OrElse LogMc.Contains("INFO]")) AndAlso LogHs Is Nothing AndAlso LogCrash Is Nothing AndAlso LogMc.Length < 100 Then
|
If Not (LogMc.Contains("at net.") OrElse LogMc.Contains("INFO]")) AndAlso LogHs Is Nothing AndAlso LogCrash Is Nothing AndAlso LogMc.Length < 100 Then
|
||||||
@@ -678,7 +679,7 @@ NextStack:
|
|||||||
Next
|
Next
|
||||||
PossibleWords = PossibleWords.Distinct.ToList
|
PossibleWords = PossibleWords.Distinct.ToList
|
||||||
Log("[Crash] 从堆栈信息中找到 " & PossibleWords.Count & " 个可能的 Mod ID 关键词")
|
Log("[Crash] 从堆栈信息中找到 " & PossibleWords.Count & " 个可能的 Mod ID 关键词")
|
||||||
If PossibleWords.Count > 0 Then Log("[Crash] - " & Join(PossibleWords, ", "))
|
If PossibleWords.Any Then Log("[Crash] - " & Join(PossibleWords, ", "))
|
||||||
If PossibleWords.Count > 10 Then
|
If PossibleWords.Count > 10 Then
|
||||||
Log("[Crash] 关键词过多,考虑匹配出错,不纳入考虑")
|
Log("[Crash] 关键词过多,考虑匹配出错,不纳入考虑")
|
||||||
Return New List(Of String)
|
Return New List(Of String)
|
||||||
@@ -847,7 +848,7 @@ NextStack:
|
|||||||
FileName = "游戏崩溃前的输出.txt"
|
FileName = "游戏崩溃前的输出.txt"
|
||||||
End Select
|
End Select
|
||||||
If File.Exists(OutputFile) Then
|
If File.Exists(OutputFile) Then
|
||||||
WriteFile(TempFolder & "Report\" & FileName, SecretFilter(ReadFile(OutputFile)))
|
WriteFile(TempFolder & "Report\" & FileName, SecretFilter(ReadFile(OutputFile), If(FileName = "启动脚本.bat", "F", "*")))
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
'导出报告
|
'导出报告
|
||||||
@@ -903,7 +904,7 @@ NextStack:
|
|||||||
Results.Add("你正在使用 32 位的操作系统,这会导致 Minecraft 无法使用所需的内存,进而造成崩溃。\n\n你或许只能重装 64 位的操作系统来解决此问题。\n如果你的电脑内存在 2GB 以内,那或许只能换台电脑了……\h")
|
Results.Add("你正在使用 32 位的操作系统,这会导致 Minecraft 无法使用所需的内存,进而造成崩溃。\n\n你或许只能重装 64 位的操作系统来解决此问题。\n如果你的电脑内存在 2GB 以内,那或许只能换台电脑了……\h")
|
||||||
End If
|
End If
|
||||||
Case CrashReason.Mod缺少前置或MC版本错误
|
Case CrashReason.Mod缺少前置或MC版本错误
|
||||||
If Additional.Count > 0 Then
|
If Additional.Any Then
|
||||||
Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n未满足的依赖项:\n - " & Join(Additional, "\n - ") & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n未满足的依赖项:\n - " & Join(Additional, "\n - ") & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
||||||
Else
|
Else
|
||||||
Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
Public Overrides Function ToString() As String
|
Public Overrides Function ToString() As String
|
||||||
Dim VersionString = Version.ToString
|
Dim VersionString = Version.ToString
|
||||||
If VersionString.StartsWithF("1.") Then VersionString = Mid(VersionString, 3)
|
If VersionString.StartsWithF("1.") Then VersionString = Mid(VersionString, 3)
|
||||||
Return If(IsJre, "JRE ", "JDK ") & VersionCode & " (" & VersionString & ")," & If(Is64Bit, "64", "32") & " 位" & If(IsUserImport, ",手动导入", "") & ":" & PathFolder
|
Return If(IsJre, "JRE ", "JDK ") & VersionCode & " (" & VersionString & ")" & If(Is64Bit, "", ",32 位") & If(IsUserImport, ",手动导入", "") & ":" & PathFolder
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
'构造
|
'构造
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
Next
|
Next
|
||||||
|
|
||||||
'检查特定的 Java
|
'检查特定的 Java
|
||||||
If TargetJavaList.Count > 0 Then
|
If TargetJavaList.Any Then
|
||||||
TargetJavaList = JavaCheckList(TargetJavaList)
|
TargetJavaList = JavaCheckList(TargetJavaList)
|
||||||
Log("[Java] 检查后找到 " & TargetJavaList.Count & " 个特定路径下的 Java:")
|
Log("[Java] 检查后找到 " & TargetJavaList.Count & " 个特定路径下的 Java:")
|
||||||
For Each Java In TargetJavaList
|
For Each Java In TargetJavaList
|
||||||
@@ -534,7 +534,7 @@ NoUserJava:
|
|||||||
Log("[Java] 位于 " & Folder & " 的 Java 不含符号链接")
|
Log("[Java] 位于 " & Folder & " 的 Java 不含符号链接")
|
||||||
JavaWithoutReparse.Add(Pair.Key, Pair.Value)
|
JavaWithoutReparse.Add(Pair.Key, Pair.Value)
|
||||||
Next
|
Next
|
||||||
If JavaWithoutReparse.Count > 0 Then JavaPreList = JavaWithoutReparse
|
If JavaWithoutReparse.Any Then JavaPreList = JavaWithoutReparse
|
||||||
|
|
||||||
'若不全为特殊引用,则清除特殊引用的地址
|
'若不全为特殊引用,则清除特殊引用的地址
|
||||||
Dim JavaWithoutInherit As New Dictionary(Of String, Boolean)
|
Dim JavaWithoutInherit As New Dictionary(Of String, Boolean)
|
||||||
@@ -546,7 +546,7 @@ NoUserJava:
|
|||||||
JavaWithoutInherit.Add(Pair.Key, Pair.Value)
|
JavaWithoutInherit.Add(Pair.Key, Pair.Value)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
If JavaWithoutInherit.Count > 0 Then JavaPreList = JavaWithoutInherit
|
If JavaWithoutInherit.Any Then JavaPreList = JavaWithoutInherit
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ Public Module ModLaunch
|
|||||||
''' 记录启动日志。
|
''' 记录启动日志。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub McLaunchLog(Text As String)
|
Public Sub McLaunchLog(Text As String)
|
||||||
Text = SecretFilter(Text)
|
Text = SecretFilter(Text, "*")
|
||||||
RunInUi(Sub() FrmLaunchRight.LabLog.Text += vbCrLf & "[" & GetTimeNow() & "] " & Text)
|
RunInUi(Sub() FrmLaunchRight.LabLog.Text += vbCrLf & "[" & GetTimeNow() & "] " & Text)
|
||||||
Log("[Launch] " & Text)
|
Log("[Launch] " & Text)
|
||||||
End Sub
|
End Sub
|
||||||
@@ -101,10 +101,10 @@ Public Module ModLaunch
|
|||||||
'正式加载
|
'正式加载
|
||||||
Try
|
Try
|
||||||
'构造主加载器
|
'构造主加载器
|
||||||
Dim LaunchLoader As New LoaderCombo(Of Object)("Minecraft 启动", {
|
Dim Loaders As New List(Of LoaderBase) From {
|
||||||
New LoaderTask(Of Integer, Integer)("获取 Java", AddressOf McLaunchJava) With {.ProgressWeight = 4, .Block = False, .Show = False},
|
New LoaderTask(Of Integer, Integer)("获取 Java", AddressOf McLaunchJava) With {.ProgressWeight = 4, .Block = False},
|
||||||
McLoginLoader,
|
McLoginLoader,
|
||||||
New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground, True)) With {.ProgressWeight = 15, .Show = False, .Block = True},
|
New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground, True)) With {.ProgressWeight = 15, .Show = False},
|
||||||
New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
|
New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
|
||||||
New LoaderTask(Of List(Of McLibToken), Integer)("解压文件", AddressOf McLaunchNatives) With {.ProgressWeight = 2},
|
New LoaderTask(Of List(Of McLibToken), Integer)("解压文件", AddressOf McLaunchNatives) With {.ProgressWeight = 2},
|
||||||
New LoaderTask(Of Integer, Integer)("预启动处理", AddressOf McLaunchPrerun) With {.ProgressWeight = 1},
|
New LoaderTask(Of Integer, Integer)("预启动处理", AddressOf McLaunchPrerun) With {.ProgressWeight = 1},
|
||||||
@@ -112,7 +112,12 @@ Public Module ModLaunch
|
|||||||
New LoaderTask(Of Integer, Process)("启动进程", AddressOf McLaunchRun) With {.ProgressWeight = 2},
|
New LoaderTask(Of Integer, Process)("启动进程", AddressOf McLaunchRun) With {.ProgressWeight = 2},
|
||||||
New LoaderTask(Of Process, Integer)("等待游戏窗口出现", AddressOf McLaunchWait) With {.ProgressWeight = 1},
|
New LoaderTask(Of Process, Integer)("等待游戏窗口出现", AddressOf McLaunchWait) With {.ProgressWeight = 1},
|
||||||
New LoaderTask(Of Integer, Integer)("结束处理", AddressOf McLaunchEnd) With {.ProgressWeight = 1}
|
New LoaderTask(Of Integer, Integer)("结束处理", AddressOf McLaunchEnd) With {.ProgressWeight = 1}
|
||||||
}) With {.Show = False}
|
}
|
||||||
|
If Setup.Get("LaunchArgumentRam") Then
|
||||||
|
CType(Loaders(2), LoaderCombo(Of String)).Block = False
|
||||||
|
Loaders.Insert(3, New LoaderTask(Of Integer, Integer)("内存优化", AddressOf McLaunchMemoryOptimize) With {.ProgressWeight = 30})
|
||||||
|
End If
|
||||||
|
Dim LaunchLoader As New LoaderCombo(Of Object)("Minecraft 启动", Loaders) With {.Show = False}
|
||||||
If McLoginLoader.State = LoadState.Finished Then McLoginLoader.State = LoadState.Waiting '要求重启登录主加载器,它会自行决定是否启动副加载器
|
If McLoginLoader.State = LoadState.Finished Then McLoginLoader.State = LoadState.Waiting '要求重启登录主加载器,它会自行决定是否启动副加载器
|
||||||
'等待加载器执行并更新 UI
|
'等待加载器执行并更新 UI
|
||||||
McLaunchLoaderReal = LaunchLoader
|
McLaunchLoaderReal = LaunchLoader
|
||||||
@@ -163,6 +168,28 @@ NextInner:
|
|||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
|
#Region "内存优化"
|
||||||
|
|
||||||
|
Private Sub McLaunchMemoryOptimize(Loader As LoaderTask(Of Integer, Integer))
|
||||||
|
McLaunchLog("内存优化开始")
|
||||||
|
Dim Finished As Boolean = False
|
||||||
|
RunInNewThread(
|
||||||
|
Sub()
|
||||||
|
PageOtherTest.MemoryOptimize(False)
|
||||||
|
Finished = True
|
||||||
|
End Sub, "Launch Memory Optimize")
|
||||||
|
Do While Not Finished AndAlso Not Loader.IsAborted
|
||||||
|
If Loader.Progress < 0.7 Then
|
||||||
|
Loader.Progress += 0.007 '10s
|
||||||
|
Else
|
||||||
|
Loader.Progress += (0.95 - Loader.Progress) * 0.02 '最快 += 0.005
|
||||||
|
End If
|
||||||
|
Thread.Sleep(100)
|
||||||
|
Loop
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
#End Region
|
||||||
|
|
||||||
#Region "预检测"
|
#Region "预检测"
|
||||||
|
|
||||||
Private Sub McLaunchPrecheck()
|
Private Sub McLaunchPrecheck()
|
||||||
@@ -247,7 +274,7 @@ NextInner:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public BaseUrl As String
|
Public BaseUrl As String
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 登录所使用的标识符,如 “Mojang”、“Nide”,用于存储缓存等。
|
''' 登录所使用的标识符,目前只可能为 “Auth” 或 “Nide”,用于存储缓存等。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Token As String
|
Public Token As String
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -526,7 +553,13 @@ SkipLogin:
|
|||||||
McLaunchLog("登录方式:" & Input.Description & "(" & LogUsername & ")")
|
McLaunchLog("登录方式:" & Input.Description & "(" & LogUsername & ")")
|
||||||
Data.Progress = 0.05
|
Data.Progress = 0.05
|
||||||
'尝试登录
|
'尝试登录
|
||||||
If (Not Data.Input.ForceReselectProfile) AndAlso Setup.Get("Cache" & Input.Token & "Username") = Data.Input.UserName AndAlso Setup.Get("Cache" & Input.Token & "Pass") = Data.Input.Password AndAlso Not Setup.Get("Cache" & Input.Token & "Access") = "" AndAlso Not Setup.Get("Cache" & Input.Token & "Client") = "" AndAlso Not Setup.Get("Cache" & Input.Token & "Uuid") = "" AndAlso Not Setup.Get("Cache" & Input.Token & "Name") = "" Then
|
If (Not Data.Input.ForceReselectProfile) AndAlso
|
||||||
|
Setup.Get("Cache" & Input.Token & "Username") = Data.Input.UserName AndAlso
|
||||||
|
Setup.Get("Cache" & Input.Token & "Pass") = Data.Input.Password AndAlso
|
||||||
|
Setup.Get("Cache" & Input.Token & "Access") <> "" AndAlso
|
||||||
|
Setup.Get("Cache" & Input.Token & "Client") <> "" AndAlso
|
||||||
|
Setup.Get("Cache" & Input.Token & "Uuid") <> "" AndAlso
|
||||||
|
Setup.Get("Cache" & Input.Token & "Name") <> "" Then
|
||||||
'尝试验证登录
|
'尝试验证登录
|
||||||
Try
|
Try
|
||||||
If Data.IsAborted Then Throw New ThreadInterruptedException
|
If Data.IsAborted Then Throw New ThreadInterruptedException
|
||||||
@@ -990,14 +1023,14 @@ SystemBrowser:
|
|||||||
Case 1
|
Case 1
|
||||||
'Steve
|
'Steve
|
||||||
Do Until McSkinSex(Uuid) = "Steve"
|
Do Until McSkinSex(Uuid) = "Steve"
|
||||||
If Uuid.EndsWithF("FFFFF") Then Uuid = Mid(Uuid, 1, 32 - 5) & "00000"
|
If Uuid.EndsWithF("FFFFF") Then Uuid = Uuid.Substring(0, 27) & "00000"
|
||||||
Uuid = Mid(Uuid, 1, 32 - 5) & (Long.Parse(Right(Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
Uuid = Uuid.Substring(0, 27) & (Long.Parse(Uuid.Substring(27), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X").PadLeft(5, "0")
|
||||||
Loop
|
Loop
|
||||||
Case 2
|
Case 2
|
||||||
'Alex
|
'Alex
|
||||||
Do Until McSkinSex(Uuid) = "Alex"
|
Do Until McSkinSex(Uuid) = "Alex"
|
||||||
If Uuid.EndsWithF("FFFFF") Then Uuid = Mid(Uuid, 1, 32 - 5) & "00000"
|
If Uuid.EndsWithF("FFFFF") Then Uuid = Uuid.Substring(0, 27) & "00000"
|
||||||
Uuid = Mid(Uuid, 1, 32 - 5) & (Long.Parse(Right(Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
Uuid = Uuid.Substring(0, 27) & (Long.Parse(Uuid.Substring(27), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X").PadLeft(5, "0")
|
||||||
Loop
|
Loop
|
||||||
Case 3
|
Case 3
|
||||||
'使用正版用户名
|
'使用正版用户名
|
||||||
@@ -1096,22 +1129,25 @@ SystemBrowser:
|
|||||||
If McVersionCurrent.Version.HasForge Then
|
If McVersionCurrent.Version.HasForge Then
|
||||||
If McVersionCurrent.Version.McName = "1.7.2" Then
|
If McVersionCurrent.Version.McName = "1.7.2" Then
|
||||||
'1.7.2:必须 Java 7
|
'1.7.2:必须 Java 7
|
||||||
MinVer = New Version(1, 7, 0, 0) : MaxVer = New Version(1, 7, 999, 999)
|
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 McVersionCurrent.Version.McCodeMain <= 12 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
|
ElseIf McVersionCurrent.Version.McCodeMain <= 12 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
|
||||||
'<=1.12:Java 8
|
'<=1.12:Java 8
|
||||||
MaxVer = New Version(1, 8, 999, 999)
|
MaxVer = New Version(1, 8, 999, 999)
|
||||||
ElseIf McVersionCurrent.Version.McCodeMain <= 14 AndAlso McVersionCurrent.Version.McCodeMain >= 13 Then
|
ElseIf McVersionCurrent.Version.McCodeMain <= 14 AndAlso McVersionCurrent.Version.McCodeMain >= 13 Then
|
||||||
'1.13 - 1.14:Java 8 - 10
|
'1.13 - 1.14:Java 8 - 10
|
||||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 10, 999, 999)
|
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 McVersionCurrent.Version.McCodeMain = 15 Then
|
ElseIf McVersionCurrent.Version.McCodeMain = 15 Then
|
||||||
'1.15:Java 8 - 15
|
'1.15:Java 8 - 15
|
||||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999)
|
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 VersionSortBoolean(McVersionCurrent.Version.ForgeVersion, "34.0.0") AndAlso VersionSortBoolean("36.2.25", McVersionCurrent.Version.ForgeVersion) Then
|
ElseIf VersionSortBoolean(McVersionCurrent.Version.ForgeVersion, "34.0.0") AndAlso VersionSortBoolean("36.2.25", McVersionCurrent.Version.ForgeVersion) Then
|
||||||
'1.16,Forge 34.X ~ 36.2.25:最高 Java 8u320
|
'1.16,Forge 34.X ~ 36.2.25:最高 Java 8u320
|
||||||
MaxVer = New Version(1, 8, 0, 320)
|
MaxVer = If(New Version(1, 8, 0, 320) < MaxVer, New Version(1, 8, 0, 320), MaxVer)
|
||||||
ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 19 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305
|
ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 19 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305
|
||||||
'1.18:若安装了 OptiFine,最高 Java 18
|
'1.18:若安装了 OptiFine,最高 Java 18
|
||||||
MaxVer = New Version(1, 18, 999, 999)
|
MaxVer = If(New Version(1, 18, 999, 999) < MaxVer, New Version(1, 18, 999, 999), MaxVer)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
@@ -1119,10 +1155,10 @@ SystemBrowser:
|
|||||||
If McVersionCurrent.Version.HasFabric Then
|
If McVersionCurrent.Version.HasFabric Then
|
||||||
If McVersionCurrent.Version.McCodeMain >= 15 AndAlso McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain <> -1 Then
|
If McVersionCurrent.Version.McCodeMain >= 15 AndAlso McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain <> -1 Then
|
||||||
'1.15 - 1.16:Java 8+
|
'1.15 - 1.16:Java 8+
|
||||||
MinVer = New Version(1, 8, 0, 0)
|
MinVer = If(New Version(1, 8, 0, 0) > MinVer, New Version(1, 8, 0, 0), MinVer)
|
||||||
ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 Then
|
ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 Then
|
||||||
'1.18+:Java 17+
|
'1.18+:Java 17+
|
||||||
MinVer = New Version(1, 17, 0, 0)
|
MinVer = If(New Version(1, 17, 0, 0) > MinVer, New Version(1, 17, 0, 0), MinVer)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
@@ -1202,17 +1238,20 @@ SystemBrowser:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function ExtractJavaWrapper() As String
|
Public Function ExtractJavaWrapper() As String
|
||||||
Dim WrapperPath As String = GetJavaWrapperDir() & "\JavaWrapper.jar"
|
Dim WrapperPath As String = GetJavaWrapperDir() & "\JavaWrapper.jar"
|
||||||
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
SyncLock ExtractJavaWrapperLock '避免 OptiFine 和 Forge 安装时同时释放 Java Wrapper 导致冲突
|
||||||
|
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
||||||
|
End SyncLock
|
||||||
Log("[Java] 已释放 Java Wrapper:" & WrapperPath)
|
Log("[Java] 已释放 Java Wrapper:" & WrapperPath)
|
||||||
Return WrapperPath
|
Return WrapperPath
|
||||||
End Function
|
End Function
|
||||||
|
Private ExtractJavaWrapperLock As New Object
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
|
''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function GetJavaWrapperDir() As String
|
Public Function GetJavaWrapperDir() As String
|
||||||
If Encoding.UTF8.GetByteCount(PathAppdata) = PathAppdata.Length Then
|
If PathAppdata.IsASCII() Then
|
||||||
Return PathAppdata.TrimEnd("\")
|
Return PathAppdata.TrimEnd("\")
|
||||||
ElseIf Encoding.UTF8.GetByteCount(PathTemp) = PathTemp.Length Then
|
ElseIf PathTemp.IsASCII() Then
|
||||||
Log("[Java] Wrapper:AppData 路径中包含非 ASCII 字符,换用 Temp 目录")
|
Log("[Java] Wrapper:AppData 路径中包含非 ASCII 字符,换用 Temp 目录")
|
||||||
Return PathTemp.TrimEnd("\")
|
Return PathTemp.TrimEnd("\")
|
||||||
Else
|
Else
|
||||||
@@ -1276,9 +1315,7 @@ SystemBrowser:
|
|||||||
'不包含端口号
|
'不包含端口号
|
||||||
Arguments += " --server " & Server & " --port 25565"
|
Arguments += " --server " & Server & " --port 25565"
|
||||||
End If
|
End If
|
||||||
If McVersionCurrent.Version.HasOptiFine Then 'OptiFine 警告
|
If McVersionCurrent.Version.HasOptiFine Then Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
|
||||||
Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
'自定义
|
'自定义
|
||||||
@@ -1300,10 +1337,11 @@ SystemBrowser:
|
|||||||
Dim ArgumentJvm As String = Setup.Get("VersionAdvanceJvm", Version:=McVersionCurrent)
|
Dim ArgumentJvm As String = Setup.Get("VersionAdvanceJvm", Version:=McVersionCurrent)
|
||||||
If ArgumentJvm = "" Then ArgumentJvm = Setup.Get("LaunchAdvanceJvm")
|
If ArgumentJvm = "" Then ArgumentJvm = Setup.Get("LaunchAdvanceJvm")
|
||||||
If Not ArgumentJvm.Contains("-Dlog4j2.formatMsgNoLookups=true") Then ArgumentJvm += " -Dlog4j2.formatMsgNoLookups=true"
|
If Not ArgumentJvm.Contains("-Dlog4j2.formatMsgNoLookups=true") Then ArgumentJvm += " -Dlog4j2.formatMsgNoLookups=true"
|
||||||
|
ArgumentJvm = ArgumentJvm.Replace(" -XX:MaxDirectMemorySize=256M", "") '#3511 的清理
|
||||||
DataList.Insert(0, ArgumentJvm) '可变 JVM 参数
|
DataList.Insert(0, ArgumentJvm) '可变 JVM 参数
|
||||||
DataList.Add("-Xmn256m")
|
DataList.Add("-Xmn" & Math.Floor(PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) * 1024 * 0.5) & "m")
|
||||||
DataList.Add("-Xmx" & Math.Floor(PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) * 1024) & "m")
|
DataList.Add("-Xmx" & Math.Floor(PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) * 1024) & "m")
|
||||||
DataList.Add("""-Djava.library.path=" & Version.Path & Version.Name & "-natives""")
|
DataList.Add("""-Djava.library.path=" & GetNativesFolder() & """")
|
||||||
DataList.Add("-cp ${classpath}") '把支持库添加进启动参数表
|
DataList.Add("-cp ${classpath}") '把支持库添加进启动参数表
|
||||||
|
|
||||||
'统一通行证
|
'统一通行证
|
||||||
@@ -1415,6 +1453,9 @@ NextVersion:
|
|||||||
DeDuplicateDataList.Add(CurrentEntry.Trim.Replace("McEmu= ", "McEmu="))
|
DeDuplicateDataList.Add(CurrentEntry.Trim.Replace("McEmu= ", "McEmu="))
|
||||||
Next
|
Next
|
||||||
|
|
||||||
|
'#3511 的清理
|
||||||
|
DeDuplicateDataList.Remove("-XX:MaxDirectMemorySize=256M")
|
||||||
|
|
||||||
'去重
|
'去重
|
||||||
Dim Result As String = Join(DeDuplicateDataList.Distinct.ToList, " ")
|
Dim Result As String = Join(DeDuplicateDataList.Distinct.ToList, " ")
|
||||||
|
|
||||||
@@ -1535,7 +1576,7 @@ NextVersion:
|
|||||||
|
|
||||||
'基础参数
|
'基础参数
|
||||||
GameArguments.Add("${classpath_separator}", ";")
|
GameArguments.Add("${classpath_separator}", ";")
|
||||||
GameArguments.Add("${natives_directory}", Version.Path & Version.Name & "-natives")
|
GameArguments.Add("${natives_directory}", GetNativesFolder())
|
||||||
GameArguments.Add("${library_directory}", PathMcFolder & "libraries")
|
GameArguments.Add("${library_directory}", PathMcFolder & "libraries")
|
||||||
GameArguments.Add("${libraries_directory}", PathMcFolder & "libraries")
|
GameArguments.Add("${libraries_directory}", PathMcFolder & "libraries")
|
||||||
GameArguments.Add("${launcher_name}", "PCL")
|
GameArguments.Add("${launcher_name}", "PCL")
|
||||||
@@ -1552,9 +1593,26 @@ NextVersion:
|
|||||||
GameArguments.Add("${access_token}", McLoginLoader.Output.AccessToken)
|
GameArguments.Add("${access_token}", McLoginLoader.Output.AccessToken)
|
||||||
GameArguments.Add("${auth_session}", McLoginLoader.Output.AccessToken)
|
GameArguments.Add("${auth_session}", McLoginLoader.Output.AccessToken)
|
||||||
GameArguments.Add("${user_type}", "msa") '#1221
|
GameArguments.Add("${user_type}", "msa") '#1221
|
||||||
Dim GameSize As Size = Setup.GetLaunchArgumentWindowSize()
|
|
||||||
GameArguments.Add("${resolution_width}", GameSize.Width)
|
'窗口尺寸参数
|
||||||
GameArguments.Add("${resolution_height}", GameSize.Height)
|
Dim GameSize As Size
|
||||||
|
Select Case Setup.Get("LaunchArgumentWindowType")
|
||||||
|
Case 2
|
||||||
|
Dim Result As Size
|
||||||
|
RunInUiWait(Sub() Result = New Size(GetPixelSize(FrmMain.PanForm.ActualWidth), GetPixelSize(FrmMain.PanForm.ActualHeight)))
|
||||||
|
GameSize = Result
|
||||||
|
Case 3
|
||||||
|
GameSize = New Size(Math.Max(100, Setup.Get("LaunchArgumentWindowWidth") - 2), Math.Max(100, Setup.Get("LaunchArgumentWindowHeight") - 2))
|
||||||
|
Case Else
|
||||||
|
GameSize = New Size(875 - 2, 540 - 2)
|
||||||
|
End Select
|
||||||
|
GameSize.Height -= 29.5 * DPI / 96 '标题栏高度
|
||||||
|
If McVersionCurrent.Version.McCodeMain <= 12 AndAlso McLaunchJavaSelected.VersionCode <= 8 Then '修复 #3463:1.12.2-,JRE 8 下窗口大小为设置大小的 DPI% 倍
|
||||||
|
GameSize.Width /= DPI / 96
|
||||||
|
GameSize.Height /= DPI / 96
|
||||||
|
End If
|
||||||
|
GameArguments.Add("${resolution_width}", Math.Round(GameSize.Width))
|
||||||
|
GameArguments.Add("${resolution_height}", Math.Round(GameSize.Height))
|
||||||
|
|
||||||
'Assets 相关参数
|
'Assets 相关参数
|
||||||
GameArguments.Add("${game_assets}", PathMcFolder & "assets\virtual\legacy") '1.5.2 的 pre-1.6 资源索引应与 legacy 合并
|
GameArguments.Add("${game_assets}", PathMcFolder & "assets\virtual\legacy") '1.5.2 的 pre-1.6 资源索引应与 legacy 合并
|
||||||
@@ -1586,7 +1644,8 @@ NextVersion:
|
|||||||
Private Sub McLaunchNatives(Loader As LoaderTask(Of List(Of McLibToken), Integer))
|
Private Sub McLaunchNatives(Loader As LoaderTask(Of List(Of McLibToken), Integer))
|
||||||
|
|
||||||
'创建文件夹
|
'创建文件夹
|
||||||
Directory.CreateDirectory(McVersionCurrent.Path & McVersionCurrent.Name & "-natives")
|
Dim Target As String = GetNativesFolder() & "\"
|
||||||
|
Directory.CreateDirectory(Target)
|
||||||
|
|
||||||
'解压文件
|
'解压文件
|
||||||
McLaunchLog("正在解压 Natives 文件")
|
McLaunchLog("正在解压 Natives 文件")
|
||||||
@@ -1605,7 +1664,7 @@ NextVersion:
|
|||||||
Dim FileName As String = Entry.FullName
|
Dim FileName As String = Entry.FullName
|
||||||
If FileName.EndsWithF(".dll", True) Then
|
If FileName.EndsWithF(".dll", True) Then
|
||||||
'实际解压文件的步骤
|
'实际解压文件的步骤
|
||||||
Dim FilePath As String = McVersionCurrent.Path & McVersionCurrent.Name & "-natives\" & FileName
|
Dim FilePath As String = Target & FileName
|
||||||
ExistFiles.Add(FilePath)
|
ExistFiles.Add(FilePath)
|
||||||
Dim OriginalFile As New FileInfo(FilePath)
|
Dim OriginalFile As New FileInfo(FilePath)
|
||||||
If OriginalFile.Exists Then
|
If OriginalFile.Exists Then
|
||||||
@@ -1631,7 +1690,7 @@ NextVersion:
|
|||||||
Next
|
Next
|
||||||
|
|
||||||
'删除多余文件
|
'删除多余文件
|
||||||
For Each FileName As String In Directory.GetFiles(McVersionCurrent.Path & McVersionCurrent.Name & "-natives")
|
For Each FileName As String In Directory.GetFiles(Target)
|
||||||
If ExistFiles.Contains(FileName) Then Continue For
|
If ExistFiles.Contains(FileName) Then Continue For
|
||||||
Try
|
Try
|
||||||
McLaunchLog("删除:" & FileName)
|
McLaunchLog("删除:" & FileName)
|
||||||
@@ -1644,6 +1703,16 @@ NextVersion:
|
|||||||
Next
|
Next
|
||||||
|
|
||||||
End Sub
|
End Sub
|
||||||
|
''' <summary>
|
||||||
|
''' 获取 Natives 文件夹路径,不以 \ 结尾。
|
||||||
|
''' </summary>
|
||||||
|
Private Function GetNativesFolder() As String
|
||||||
|
Dim Result As String = McVersionCurrent.Path & McVersionCurrent.Name & "-natives"
|
||||||
|
If IsGBKEncoding OrElse Result.IsASCII() Then Return Result
|
||||||
|
Result = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\bin\natives"
|
||||||
|
If Result.IsASCII() Then Return Result
|
||||||
|
Return OsDrive & "ProgramData\PCL\natives"
|
||||||
|
End Function
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
@@ -1758,7 +1827,7 @@ NextVersion:
|
|||||||
Select Case Setup.Get("LaunchArgumentWindowType")
|
Select Case Setup.Get("LaunchArgumentWindowType")
|
||||||
Case 0 '全屏
|
Case 0 '全屏
|
||||||
WriteIni(SetupFileAddress, "fullscreen", "true")
|
WriteIni(SetupFileAddress, "fullscreen", "true")
|
||||||
Case 5 '保持默认
|
Case 1 '默认
|
||||||
Case Else '其他
|
Case Else '其他
|
||||||
WriteIni(SetupFileAddress, "fullscreen", "false")
|
WriteIni(SetupFileAddress, "fullscreen", "false")
|
||||||
End Select
|
End Select
|
||||||
@@ -1936,7 +2005,7 @@ IgnoreCustomSkin:
|
|||||||
"""" & McLaunchJavaSelected.PathJava & """ " & McLaunchArgument & vbCrLf &
|
"""" & McLaunchJavaSelected.PathJava & """ " & McLaunchArgument & vbCrLf &
|
||||||
"echo 游戏已退出。" & vbCrLf &
|
"echo 游戏已退出。" & vbCrLf &
|
||||||
"pause"
|
"pause"
|
||||||
WriteFile(If(McLaunchLoader.Input.SaveBatch, Path & "PCL\LatestLaunch.bat"), SecretFilter(CmdString),
|
WriteFile(If(McLaunchLoader.Input.SaveBatch, Path & "PCL\LatestLaunch.bat"), SecretFilter(CmdString, "F"),
|
||||||
Encoding:=If(Encoding.Default.Equals(Encoding.UTF8), Encoding.UTF8, Encoding.GetEncoding("GB18030")))
|
Encoding:=If(Encoding.Default.Equals(Encoding.UTF8), Encoding.UTF8, Encoding.GetEncoding("GB18030")))
|
||||||
If McLaunchLoader.Input.SaveBatch IsNot Nothing Then
|
If McLaunchLoader.Input.SaveBatch IsNot Nothing Then
|
||||||
McLaunchLog("导出启动脚本完成,强制结束启动过程")
|
McLaunchLog("导出启动脚本完成,强制结束启动过程")
|
||||||
@@ -2058,7 +2127,7 @@ IgnoreCustomSkin:
|
|||||||
McLaunchLog("")
|
McLaunchLog("")
|
||||||
McLaunchLog("~ 基础参数 ~")
|
McLaunchLog("~ 基础参数 ~")
|
||||||
McLaunchLog("PCL 版本:" & VersionDisplayName & " (" & VersionCode & ")")
|
McLaunchLog("PCL 版本:" & VersionDisplayName & " (" & VersionCode & ")")
|
||||||
McLaunchLog("游戏版本:" & McVersionCurrent.Version.ToString & "(" & McVersionCurrent.Version.McCodeMain & "." & McVersionCurrent.Version.McCodeSub & ")")
|
McLaunchLog("游戏版本:" & McVersionCurrent.Version.ToString & "(识别为 1." & McVersionCurrent.Version.McCodeMain & "." & McVersionCurrent.Version.McCodeSub & ")")
|
||||||
McLaunchLog("资源版本:" & McAssetsGetIndexName(McVersionCurrent))
|
McLaunchLog("资源版本:" & McAssetsGetIndexName(McVersionCurrent))
|
||||||
McLaunchLog("版本继承:" & If(McVersionCurrent.InheritVersion = "", "无", McVersionCurrent.InheritVersion))
|
McLaunchLog("版本继承:" & If(McVersionCurrent.InheritVersion = "", "无", McVersionCurrent.InheritVersion))
|
||||||
McLaunchLog("分配的内存:" & PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) & " GB(" & Math.Round(PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) * 1024) & " MB)")
|
McLaunchLog("分配的内存:" & PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) & " GB(" & Math.Round(PageVersionSetup.GetRam(McVersionCurrent, Not McLaunchJavaSelected.Is64Bit) * 1024) & " MB)")
|
||||||
@@ -2068,6 +2137,7 @@ IgnoreCustomSkin:
|
|||||||
McLaunchLog("HMCL 格式:" & McVersionCurrent.IsHmclFormatJson)
|
McLaunchLog("HMCL 格式:" & McVersionCurrent.IsHmclFormatJson)
|
||||||
McLaunchLog("Java 信息:" & If(McLaunchJavaSelected IsNot Nothing, McLaunchJavaSelected.ToString, "无可用 Java"))
|
McLaunchLog("Java 信息:" & If(McLaunchJavaSelected IsNot Nothing, McLaunchJavaSelected.ToString, "无可用 Java"))
|
||||||
McLaunchLog("环境变量:" & If(McLaunchJavaSelected IsNot Nothing, If(McLaunchJavaSelected.HasEnvironment, "已设置", "未设置"), "未设置"))
|
McLaunchLog("环境变量:" & If(McLaunchJavaSelected IsNot Nothing, If(McLaunchJavaSelected.HasEnvironment, "已设置", "未设置"), "未设置"))
|
||||||
|
McLaunchLog("Natives 文件夹:" & GetNativesFolder())
|
||||||
McLaunchLog("")
|
McLaunchLog("")
|
||||||
McLaunchLog("~ 登录参数 ~")
|
McLaunchLog("~ 登录参数 ~")
|
||||||
McLaunchLog("玩家用户名:" & McLoginLoader.Output.Name)
|
McLaunchLog("玩家用户名:" & McLoginLoader.Output.Name)
|
||||||
|
|||||||
@@ -181,7 +181,7 @@
|
|||||||
If AniControlEnabled = 0 AndAlso
|
If AniControlEnabled = 0 AndAlso
|
||||||
Setup.Get("VersionServerAuthServer", Version:=value) <> Setup.Get("CacheAuthServerServer") AndAlso
|
Setup.Get("VersionServerAuthServer", Version:=value) <> Setup.Get("CacheAuthServerServer") AndAlso
|
||||||
Setup.Get("VersionServerLogin", Version:=value) = 4 Then
|
Setup.Get("VersionServerLogin", Version:=value) = 4 Then
|
||||||
Setup.Set("CacheNideServer", "")
|
Setup.Set("CacheAuthAccess", "")
|
||||||
Log("[Launch] 服务器改变,要求重新登录 Authlib-Injector")
|
Log("[Launch] 服务器改变,要求重新登录 Authlib-Injector")
|
||||||
End If
|
End If
|
||||||
If Setup.Get("VersionServerLogin", Version:=value) = 4 Then
|
If Setup.Get("VersionServerLogin", Version:=value) = 4 Then
|
||||||
@@ -216,8 +216,8 @@
|
|||||||
'尚未判断
|
'尚未判断
|
||||||
Dim ModFolder As New DirectoryInfo(Path & "mods\")
|
Dim ModFolder As New DirectoryInfo(Path & "mods\")
|
||||||
Dim SaveFolder As New DirectoryInfo(Path & "saves\")
|
Dim SaveFolder As New DirectoryInfo(Path & "saves\")
|
||||||
If (ModFolder.Exists AndAlso ModFolder.EnumerateFiles.Count > 0) OrElse
|
If (ModFolder.Exists AndAlso ModFolder.EnumerateFiles.Any) OrElse
|
||||||
(SaveFolder.Exists AndAlso SaveFolder.EnumerateFiles.Count > 0) Then
|
(SaveFolder.Exists AndAlso SaveFolder.EnumerateFiles.Any) Then
|
||||||
'自动开启
|
'自动开启
|
||||||
Setup.Set("VersionArgumentIndie", 1, Version:=Me)
|
Setup.Set("VersionArgumentIndie", 1, Version:=Me)
|
||||||
Log("[Setup] 已自动开启单版本隔离:" & Name)
|
Log("[Setup] 已自动开启单版本隔离:" & Name)
|
||||||
@@ -1234,7 +1234,7 @@ OnLoaded:
|
|||||||
For Each Version As McVersion In VersionList
|
For Each Version As McVersion In VersionList
|
||||||
If Version.IsStar AndAlso Not Version.DisplayType = McVersionCardType.Hidden Then StaredVersions.Add(Version)
|
If Version.IsStar AndAlso Not Version.DisplayType = McVersionCardType.Hidden Then StaredVersions.Add(Version)
|
||||||
Next
|
Next
|
||||||
If StaredVersions.Count > 0 Then VersionListOriginal.Add(McVersionCardType.Star, StaredVersions)
|
If StaredVersions.Any Then VersionListOriginal.Add(McVersionCardType.Star, StaredVersions)
|
||||||
|
|
||||||
'预先筛选出愚人节的版本
|
'预先筛选出愚人节的版本
|
||||||
McVersionFilter(VersionList, VersionListOriginal, {McVersionState.Error}, McVersionCardType.Error)
|
McVersionFilter(VersionList, VersionListOriginal, {McVersionState.Error}, McVersionCardType.Error)
|
||||||
@@ -1308,8 +1308,8 @@ OnLoaded:
|
|||||||
|
|
||||||
'将剩余的东西添加进去
|
'将剩余的东西添加进去
|
||||||
VersionRubbish.AddRange(VersionList)
|
VersionRubbish.AddRange(VersionList)
|
||||||
If VersionUseful.Count > 0 Then VersionListOriginal.Add(McVersionCardType.OriginalLike, VersionUseful)
|
If VersionUseful.Any Then VersionListOriginal.Add(McVersionCardType.OriginalLike, VersionUseful)
|
||||||
If VersionRubbish.Count > 0 Then VersionListOriginal.Add(McVersionCardType.Rubbish, VersionRubbish)
|
If VersionRubbish.Any Then VersionListOriginal.Add(McVersionCardType.Rubbish, VersionRubbish)
|
||||||
|
|
||||||
'按照自定义版本分类重新添加
|
'按照自定义版本分类重新添加
|
||||||
For Each VersionPair In VersionListOriginal
|
For Each VersionPair In VersionListOriginal
|
||||||
@@ -1429,7 +1429,7 @@ OnLoaded:
|
|||||||
NextVersion:
|
NextVersion:
|
||||||
Next
|
Next
|
||||||
'加入版本列表,并从剩余中删除
|
'加入版本列表,并从剩余中删除
|
||||||
If KeepList.Count > 0 Then
|
If KeepList.Any Then
|
||||||
Target.Add(CardType, KeepList)
|
Target.Add(CardType, KeepList)
|
||||||
For Each Version As McVersion In KeepList
|
For Each Version As McVersion In KeepList
|
||||||
VersionList.Remove(Version)
|
VersionList.Remove(Version)
|
||||||
@@ -1450,7 +1450,7 @@ NextVersion:
|
|||||||
Next
|
Next
|
||||||
NextVersion:
|
NextVersion:
|
||||||
Next
|
Next
|
||||||
If KeepList.Count > 0 Then
|
If KeepList.Any Then
|
||||||
For Each Version As McVersion In KeepList
|
For Each Version As McVersion In KeepList
|
||||||
VersionList.Remove(Version)
|
VersionList.Remove(Version)
|
||||||
Next
|
Next
|
||||||
@@ -1515,7 +1515,7 @@ NextVersion:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function McSkinGetAddress(Uuid As String, Type As String) As String
|
Public Function McSkinGetAddress(Uuid As String, Type As String) As String
|
||||||
If Uuid = "" Then Throw New Exception("Uuid 为空。")
|
If Uuid = "" Then Throw New Exception("Uuid 为空。")
|
||||||
If Uuid.StartsWithF("000000") Then Throw New Exception("离线 Uuid 无正版皮肤文件。")
|
If Uuid.StartsWithF("00000") Then Throw New Exception("离线 Uuid 无正版皮肤文件。")
|
||||||
'尝试读取缓存
|
'尝试读取缓存
|
||||||
Dim CacheSkinAddress As String = ReadIni(PathTemp & "Cache\Skin\Index" & Type & ".ini", Uuid)
|
Dim CacheSkinAddress As String = ReadIni(PathTemp & "Cache\Skin\Index" & Type & ".ini", Uuid)
|
||||||
If Not CacheSkinAddress = "" Then Return CacheSkinAddress
|
If Not CacheSkinAddress = "" Then Return CacheSkinAddress
|
||||||
@@ -2048,8 +2048,7 @@ NextVersion:
|
|||||||
If Version.InheritVersion = "" Then Exit Do
|
If Version.InheritVersion = "" Then Exit Do
|
||||||
Version = New McVersion(PathMcFolder & "versions\" & Version.InheritVersion)
|
Version = New McVersion(PathMcFolder & "versions\" & Version.InheritVersion)
|
||||||
Loop
|
Loop
|
||||||
Catch ex As Exception
|
Catch
|
||||||
Log(ex, "获取资源文件索引下载地址失败")
|
|
||||||
End Try
|
End Try
|
||||||
'无法获取到下载地址
|
'无法获取到下载地址
|
||||||
If ReturnLegacyOnError Then
|
If ReturnLegacyOnError Then
|
||||||
@@ -2239,10 +2238,11 @@ NextVersion:
|
|||||||
'弹窗结果
|
'弹窗结果
|
||||||
If MsgResult = 2 Then
|
If MsgResult = 2 Then
|
||||||
'下载
|
'下载
|
||||||
RunInUi(Sub()
|
RunInUi(
|
||||||
PageDownloadInstall.McVersionWaitingForSelect = VersionName
|
Sub()
|
||||||
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
|
PageDownloadInstall.McVersionWaitingForSelect = VersionName
|
||||||
End Sub)
|
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
|
||||||
|
End Sub)
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ Public Module ModMod
|
|||||||
For Each Token In AuthorJson
|
For Each Token In AuthorJson
|
||||||
Author.Add(Token.ToString)
|
Author.Add(Token.ToString)
|
||||||
Next
|
Next
|
||||||
If Author.Count > 0 Then Authors = Join(Author, ", ")
|
If Author.Any Then Authors = Join(Author, ", ")
|
||||||
End If
|
End If
|
||||||
Dim Reqs As JArray = InfoObject("requiredMods")
|
Dim Reqs As JArray = InfoObject("requiredMods")
|
||||||
If Reqs IsNot Nothing Then
|
If Reqs IsNot Nothing Then
|
||||||
@@ -393,7 +393,7 @@ GotFabric:
|
|||||||
For Each Token In AuthorJson
|
For Each Token In AuthorJson
|
||||||
Author.Add(Token.ToString)
|
Author.Add(Token.ToString)
|
||||||
Next
|
Next
|
||||||
If Author.Count > 0 Then Authors = Join(Author, ", ")
|
If Author.Any Then Authors = Join(Author, ", ")
|
||||||
End If
|
End If
|
||||||
'If (Not FabricObject.ContainsKey("serverSideOnly")) OrElse FabricObject("serverSideOnly")("value").ToObject(Of Boolean) = False Then
|
'If (Not FabricObject.ContainsKey("serverSideOnly")) OrElse FabricObject("serverSideOnly")("value").ToObject(Of Boolean) = False Then
|
||||||
' '添加 Minecraft 依赖
|
' '添加 Minecraft 依赖
|
||||||
@@ -438,7 +438,7 @@ GotFabric:
|
|||||||
Line = Line.Substring(0, Line.IndexOfF("#"))
|
Line = Line.Substring(0, Line.IndexOfF("#"))
|
||||||
End If
|
End If
|
||||||
Line = Line.Trim(New Char() {" "c, " "c, " "c}) '去除头尾的空格
|
Line = Line.Trim(New Char() {" "c, " "c, " "c}) '去除头尾的空格
|
||||||
If Line.Count > 0 Then Lines.Add(Line) '去除空行
|
If Line.Any Then Lines.Add(Line) '去除空行
|
||||||
Next
|
Next
|
||||||
'读取文件数据
|
'读取文件数据
|
||||||
Dim TomlData As New List(Of KeyValuePair(Of String, Dictionary(Of String, Object))) From {New KeyValuePair(Of String, Dictionary(Of String, Object))("", New Dictionary(Of String, Object))}
|
Dim TomlData As New List(Of KeyValuePair(Of String, Dictionary(Of String, Object))) From {New KeyValuePair(Of String, Dictionary(Of String, Object))("", New Dictionary(Of String, Object))}
|
||||||
@@ -925,7 +925,7 @@ Finished:
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'联网加载 Mod 详情
|
'联网加载 Mod 详情
|
||||||
Private Const LocalModCacheVersion As Integer = 2
|
Private Const LocalModCacheVersion As Integer = 3
|
||||||
Public McModDetailLoader As New LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer)("Mod List Detail Loader", AddressOf McModDetailLoad)
|
Public McModDetailLoader As New LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer)("Mod List Detail Loader", AddressOf McModDetailLoad)
|
||||||
Private Sub McModDetailLoad(Loader As LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer))
|
Private Sub McModDetailLoad(Loader As LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer))
|
||||||
Dim Mods As List(Of McMod) = Loader.Input.Key
|
Dim Mods As List(Of McMod) = Loader.Input.Key
|
||||||
@@ -965,6 +965,7 @@ Finished:
|
|||||||
Dim ModrinthMapping As New Dictionary(Of String, List(Of McMod))
|
Dim ModrinthMapping As New Dictionary(Of String, List(Of McMod))
|
||||||
For Each Entry In Mods
|
For Each Entry In Mods
|
||||||
If Not ModrinthVersion.ContainsKey(Entry.ModrinthHash) Then Continue For
|
If Not ModrinthVersion.ContainsKey(Entry.ModrinthHash) Then Continue For
|
||||||
|
If ModrinthVersion(Entry.ModrinthHash)("files")(0)("hashes")("sha1") <> Entry.ModrinthHash Then Continue For
|
||||||
Dim ProjectId = ModrinthVersion(Entry.ModrinthHash)("project_id").ToString
|
Dim ProjectId = ModrinthVersion(Entry.ModrinthHash)("project_id").ToString
|
||||||
If CompProjectCache.ContainsKey(ProjectId) AndAlso Entry.Comp Is Nothing Then Entry.Comp = CompProjectCache(ProjectId) '读取已加载的缓存,加快结果出现速度
|
If CompProjectCache.ContainsKey(ProjectId) AndAlso Entry.Comp Is Nothing Then Entry.Comp = CompProjectCache(ProjectId) '读取已加载的缓存,加快结果出现速度
|
||||||
If Not ModrinthMapping.ContainsKey(ProjectId) Then ModrinthMapping(ProjectId) = New List(Of McMod)
|
If Not ModrinthMapping.ContainsKey(ProjectId) Then ModrinthMapping(ProjectId) = New List(Of McMod)
|
||||||
|
|||||||
@@ -244,16 +244,17 @@ Retry:
|
|||||||
ModList.Add(ModEntry("fileID"))
|
ModList.Add(ModEntry("fileID"))
|
||||||
If ModEntry("required") IsNot Nothing AndAlso Not ModEntry("required").ToObject(Of Boolean) Then ModOptionalList.Add(ModEntry("fileID"))
|
If ModEntry("required") IsNot Nothing AndAlso Not ModEntry("required").ToObject(Of Boolean) Then ModOptionalList.Add(ModEntry("fileID"))
|
||||||
Next
|
Next
|
||||||
If ModList.Count > 0 Then
|
If ModList.Any Then
|
||||||
|
Dim ModDownloadLoaders As New List(Of LoaderBase)
|
||||||
'获取 Mod 下载信息
|
'获取 Mod 下载信息
|
||||||
InstallLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
|
ModDownloadLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
|
||||||
Sub(Task As LoaderTask(Of Integer, JArray))
|
Sub(Task As LoaderTask(Of Integer, JArray))
|
||||||
Task.Output = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json"))("data")
|
Task.Output = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json"))("data")
|
||||||
'如果文件已被删除,则 API 会跳过那一项
|
'如果文件已被删除,则 API 会跳过那一项
|
||||||
If ModList.Count > Task.Output.Count Then Throw New Exception("整合包所需要的部分 Mod 版本已被 Mod 作者删除,因此无法完成整合包安装,请联系整合包作者更新整合包中的 Mod 版本")
|
If ModList.Count > Task.Output.Count Then Throw New Exception("整合包所需要的部分 Mod 版本已被 Mod 作者删除,因此无法完成整合包安装,请联系整合包作者更新整合包中的 Mod 版本")
|
||||||
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
||||||
'构造 NetFile
|
'构造 NetFile
|
||||||
InstallLoaders.Add(New LoaderTask(Of JArray, List(Of NetFile))("构造 Mod 下载信息",
|
ModDownloadLoaders.Add(New LoaderTask(Of JArray, List(Of NetFile))("构造 Mod 下载信息",
|
||||||
Sub(Task As LoaderTask(Of JArray, List(Of NetFile)))
|
Sub(Task As LoaderTask(Of JArray, List(Of NetFile)))
|
||||||
Dim FileList As New Dictionary(Of Integer, NetFile)
|
Dim FileList As New Dictionary(Of Integer, NetFile)
|
||||||
For Each ModJson In Task.Input
|
For Each ModJson In Task.Input
|
||||||
@@ -288,7 +289,10 @@ Retry:
|
|||||||
Task.Output = FileList.Values.ToList
|
Task.Output = FileList.Values.ToList
|
||||||
End Sub) With {.ProgressWeight = ModList.Count / 200, .Show = False}) '每 200 Mod 需要 1s
|
End Sub) With {.ProgressWeight = ModList.Count / 200, .Show = False}) '每 200 Mod 需要 1s
|
||||||
'下载 Mod 文件
|
'下载 Mod 文件
|
||||||
InstallLoaders.Add(New LoaderDownload("下载 Mod", New List(Of NetFile)) With {.ProgressWeight = ModList.Count * 1.5}) '每个 Mod 需要 1.5s
|
ModDownloadLoaders.Add(New LoaderDownload("下载 Mod", New List(Of NetFile)) With {.ProgressWeight = ModList.Count * 1.5}) '每个 Mod 需要 1.5s
|
||||||
|
'构造加载器
|
||||||
|
InstallLoaders.Add(New LoaderCombo(Of Integer)("下载 Mod(主加载器)", ModDownloadLoaders) With
|
||||||
|
{.Show = False, .ProgressWeight = ModDownloadLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'构造加载器
|
'构造加载器
|
||||||
@@ -299,43 +303,35 @@ Retry:
|
|||||||
.ForgeVersion = ForgeVersion,
|
.ForgeVersion = ForgeVersion,
|
||||||
.FabricVersion = FabricVersion
|
.FabricVersion = FabricVersion
|
||||||
}
|
}
|
||||||
Dim InstallExpectTime As Double = 0
|
|
||||||
For Each InstallLoader In InstallLoaders
|
|
||||||
InstallExpectTime += InstallLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||||
If MergeLoaders Is Nothing Then Exit Sub
|
If MergeLoaders Is Nothing Then Exit Sub
|
||||||
Dim MergeExpectTime As Double = 0
|
'构造 Libraries 加载器
|
||||||
For Each MergeLoader In MergeLoaders
|
|
||||||
MergeExpectTime += MergeLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
|
||||||
Dim LoadersLib As New List(Of LoaderBase)
|
Dim LoadersLib As New List(Of LoaderBase)
|
||||||
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
||||||
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
||||||
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
||||||
Sub(Task As LoaderTask(Of String, String))
|
Sub(Task As LoaderTask(Of String, String))
|
||||||
'设置图标
|
'设置图标
|
||||||
Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
|
Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
|
||||||
If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
|
If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
|
||||||
File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
|
File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
|
||||||
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
||||||
WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
|
WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
|
||||||
Log("[ModPack] 已设置整合包 Logo:" & Logo)
|
Log("[ModPack] 已设置整合包 Logo:" & Logo)
|
||||||
End If
|
End If
|
||||||
'删除原始整合包文件
|
'删除原始整合包文件
|
||||||
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
||||||
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
||||||
Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
|
Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
|
||||||
File.Delete(Target)
|
File.Delete(Target)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
||||||
|
|
||||||
'重复任务检查
|
'重复任务检查
|
||||||
Dim LoaderName As String = "CurseForge 整合包安装:" & VersionName & " "
|
Dim LoaderName As String = "CurseForge 整合包安装:" & VersionName & " "
|
||||||
@@ -438,10 +434,10 @@ Retry:
|
|||||||
End If
|
End If
|
||||||
'添加下载文件
|
'添加下载文件
|
||||||
FileList.Add(New NetFile(File("downloads").Select(Function(t) t.ToString.Replace("://edge.forgecdn", "://media.forgecdn")).ToArray, '修复 #2390
|
FileList.Add(New NetFile(File("downloads").Select(Function(t) t.ToString.Replace("://edge.forgecdn", "://media.forgecdn")).ToArray, '修复 #2390
|
||||||
PathMcFolder & "versions\" & VersionName & "\" & File("path").ToString,
|
PathMcFolder & "versions\" & VersionName & "\" & File("path").ToString,
|
||||||
New FileChecker(ActualSize:=File("fileSize").ToObject(Of Long), Hash:=File("hashes")("sha1").ToString), True))
|
New FileChecker(ActualSize:=File("fileSize").ToObject(Of Long), Hash:=File("hashes")("sha1").ToString), True))
|
||||||
Next
|
Next
|
||||||
If FileList.Count > 0 Then
|
If FileList.Any Then
|
||||||
InstallLoaders.Add(New LoaderDownload("下载额外文件", FileList) With {.ProgressWeight = FileList.Count * 1.5}) '每个 Mod 需要 1.5s
|
InstallLoaders.Add(New LoaderDownload("下载额外文件", FileList) With {.ProgressWeight = FileList.Count * 1.5}) '每个 Mod 需要 1.5s
|
||||||
End If
|
End If
|
||||||
|
|
||||||
@@ -453,43 +449,35 @@ Retry:
|
|||||||
.ForgeVersion = ForgeVersion,
|
.ForgeVersion = ForgeVersion,
|
||||||
.FabricVersion = FabricVersion
|
.FabricVersion = FabricVersion
|
||||||
}
|
}
|
||||||
Dim InstallExpectTime As Double = 0
|
|
||||||
For Each InstallLoader In InstallLoaders
|
|
||||||
InstallExpectTime += InstallLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||||
If MergeLoaders Is Nothing Then Exit Sub
|
If MergeLoaders Is Nothing Then Exit Sub
|
||||||
Dim MergeExpectTime As Double = 0
|
'构造 Libraries 加载器
|
||||||
For Each MergeLoader In MergeLoaders
|
|
||||||
MergeExpectTime += MergeLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
|
||||||
Dim LoadersLib As New List(Of LoaderBase)
|
Dim LoadersLib As New List(Of LoaderBase)
|
||||||
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
||||||
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
||||||
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
||||||
Sub(Task As LoaderTask(Of String, String))
|
Sub(Task As LoaderTask(Of String, String))
|
||||||
'设置图标
|
'设置图标
|
||||||
Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
|
Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
|
||||||
If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
|
If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
|
||||||
File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
|
File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
|
||||||
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
||||||
WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
|
WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
|
||||||
Log("[ModPack] 已设置整合包 Logo:" & Logo)
|
Log("[ModPack] 已设置整合包 Logo:" & Logo)
|
||||||
End If
|
End If
|
||||||
'删除原始整合包文件
|
'删除原始整合包文件
|
||||||
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
||||||
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
||||||
Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
|
Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
|
||||||
File.Delete(Target)
|
File.Delete(Target)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
||||||
|
|
||||||
'重复任务检查
|
'重复任务检查
|
||||||
Dim LoaderName As String = "Modrinth 整合包安装:" & VersionName & " "
|
Dim LoaderName As String = "Modrinth 整合包安装:" & VersionName & " "
|
||||||
@@ -554,16 +542,8 @@ Retry:
|
|||||||
.TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
|
.TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
|
||||||
.MinecraftName = Json("gameVersion").ToString
|
.MinecraftName = Json("gameVersion").ToString
|
||||||
}
|
}
|
||||||
Dim InstallExpectTime As Double = 0
|
|
||||||
For Each InstallLoader In InstallLoaders
|
|
||||||
InstallExpectTime += InstallLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||||
If MergeLoaders Is Nothing Then Exit Sub
|
If MergeLoaders Is Nothing Then Exit Sub
|
||||||
Dim MergeExpectTime As Double = 0
|
|
||||||
For Each MergeLoader In MergeLoaders
|
|
||||||
MergeExpectTime += MergeLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
||||||
Dim LoadersLib As New List(Of LoaderBase)
|
Dim LoadersLib As New List(Of LoaderBase)
|
||||||
LoadersLib.Add(New LoaderTask(Of String, String)("重命名版本 Json(副加载器)",
|
LoadersLib.Add(New LoaderTask(Of String, String)("重命名版本 Json(副加载器)",
|
||||||
@@ -584,8 +564,8 @@ Retry:
|
|||||||
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase) From {
|
Dim Loaders As New List(Of LoaderBase) From {
|
||||||
New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeExpectTime},
|
New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeLoaders.Sum(Function(l) l.ProgressWeight)},
|
||||||
New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallExpectTime},
|
New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)},
|
||||||
New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8}
|
New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,24 +684,16 @@ Retry:
|
|||||||
End Select
|
End Select
|
||||||
Next
|
Next
|
||||||
'构造加载器
|
'构造加载器
|
||||||
Dim InstallExpectTime As Double = 0
|
|
||||||
For Each InstallLoader In InstallLoaders
|
|
||||||
InstallExpectTime += InstallLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||||
If MergeLoaders Is Nothing Then Exit Sub
|
If MergeLoaders Is Nothing Then Exit Sub
|
||||||
Dim MergeExpectTime As Double = 0
|
'构造 Libraries 加载器
|
||||||
For Each MergeLoader In MergeLoaders
|
|
||||||
MergeExpectTime += MergeLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
|
||||||
Dim LoadersLib As New List(Of LoaderBase)
|
Dim LoadersLib As New List(Of LoaderBase)
|
||||||
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
||||||
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
||||||
|
|
||||||
'重复任务检查
|
'重复任务检查
|
||||||
@@ -802,24 +774,16 @@ Retry:
|
|||||||
.ForgeVersion = If(Addons.ContainsKey("forge"), Addons("forge"), Nothing),
|
.ForgeVersion = If(Addons.ContainsKey("forge"), Addons("forge"), Nothing),
|
||||||
.FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
|
.FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
|
||||||
}
|
}
|
||||||
Dim InstallExpectTime As Double = 0
|
|
||||||
For Each InstallLoader In InstallLoaders
|
|
||||||
InstallExpectTime += InstallLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||||
If MergeLoaders Is Nothing Then Exit Sub
|
If MergeLoaders Is Nothing Then Exit Sub
|
||||||
Dim MergeExpectTime As Double = 0
|
'构造 Libraries 加载器
|
||||||
For Each MergeLoader In MergeLoaders
|
|
||||||
MergeExpectTime += MergeLoader.ProgressWeight
|
|
||||||
Next
|
|
||||||
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
|
||||||
Dim LoadersLib As New List(Of LoaderBase)
|
Dim LoadersLib As New List(Of LoaderBase)
|
||||||
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
|
||||||
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallExpectTime})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
||||||
|
|
||||||
'重复任务检查
|
'重复任务检查
|
||||||
|
|||||||
@@ -276,17 +276,18 @@
|
|||||||
IsWindowFinished = True
|
IsWindowFinished = True
|
||||||
'最大化
|
'最大化
|
||||||
If Setup.Get("LaunchArgumentWindowType") = 4 Then
|
If Setup.Get("LaunchArgumentWindowType") = 4 Then
|
||||||
RunInNewThread(Sub()
|
RunInNewThread(
|
||||||
Try
|
Sub()
|
||||||
'如果最大化导致屏幕渲染大小不对,那是 MC 的 Bug,不是我的 Bug
|
Try
|
||||||
'……虽然我很想这样说,但总有人反馈,算了
|
'如果最大化导致屏幕渲染大小不对,那是 MC 的 Bug,不是我的 Bug
|
||||||
Thread.Sleep(2000)
|
'……虽然我很想这样说,但总有人反馈,算了
|
||||||
ShowWindow(WindowHandle, 3)
|
Thread.Sleep(2000)
|
||||||
WatcherLog($"已最大化 Minecraft 窗口:{MinecraftWindowHandle.ToInt64}")
|
ShowWindow(WindowHandle, 3)
|
||||||
Catch ex As Exception
|
WatcherLog($"已最大化 Minecraft 窗口:{MinecraftWindowHandle.ToInt64}")
|
||||||
Log(ex, "最大化 Minecraft 窗口时出现错误")
|
Catch ex As Exception
|
||||||
End Try
|
Log(ex, "最大化 Minecraft 窗口时出现错误")
|
||||||
End Sub, "MinecraftWindowMaximize")
|
End Try
|
||||||
|
End Sub, "MinecraftWindowMaximize")
|
||||||
End If
|
End If
|
||||||
ElseIf Not IsWindowAppeared Then
|
ElseIf Not IsWindowAppeared Then
|
||||||
'已找到 FML 窗口
|
'已找到 FML 窗口
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ Public Module ModMusic
|
|||||||
Thread.Sleep(100)
|
Thread.Sleep(100)
|
||||||
End While
|
End While
|
||||||
'当前音乐已播放结束,继续下一曲
|
'当前音乐已播放结束,继续下一曲
|
||||||
If CurrentWave.PlaybackState = NAudio.Wave.PlaybackState.Stopped AndAlso MusicAllList.Count > 0 Then MusicStartPlay(DequeueNextMusicAddress)
|
If CurrentWave.PlaybackState = NAudio.Wave.PlaybackState.Stopped AndAlso MusicAllList.Any Then MusicStartPlay(DequeueNextMusicAddress)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log("[Music] 播放音乐失败的文件完整路径:" & MusicCurrent)
|
Log("[Music] 播放音乐失败的文件完整路径:" & MusicCurrent)
|
||||||
If TypeOf ex Is NAudio.MmException AndAlso (ex.Message.Contains("NoDriver") OrElse ex.Message.Contains("BadDeviceId")) Then
|
If TypeOf ex Is NAudio.MmException AndAlso (ex.Message.Contains("NoDriver") OrElse ex.Message.Contains("BadDeviceId")) Then
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ Imports System.Runtime.InteropServices
|
|||||||
|
|
||||||
'查看程序集特性的值
|
'查看程序集特性的值
|
||||||
|
|
||||||
<Assembly: AssemblyTitle("Plain Craft Launcher 2 启动器")>
|
<Assembly: AssemblyTitle("Plain Craft Launcher 启动器")>
|
||||||
<Assembly: AssemblyDescription("Minecraft 启动器 (制作:龙腾猫跃)")>
|
<Assembly: AssemblyDescription("Minecraft 启动器 (制作:龙腾猫跃)")>
|
||||||
<Assembly: AssemblyCompany("")>
|
<Assembly: AssemblyCompany("")>
|
||||||
<Assembly: AssemblyProduct("Plain Craft Launcher 2")>
|
<Assembly: AssemblyProduct("Plain Craft Launcher")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 龙腾猫跃 2016-2024. All Rights Reserved.")>
|
<Assembly: AssemblyCopyright("Copyright © 龙腾猫跃 2016. All Rights Reserved.")>
|
||||||
<Assembly: AssemblyConfiguration("PCL2 Config Mark")>
|
<Assembly: AssemblyConfiguration("PCL2 Config Mark")>
|
||||||
<Assembly: ComVisible(False)>
|
<Assembly: ComVisible(False)>
|
||||||
|
|
||||||
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||||
' 方法是按如下所示使用“*”
|
' 方法是按如下所示使用“*”
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2.7.1.0")>
|
<Assembly: AssemblyVersion("2.7.2.0")>
|
||||||
<Assembly: AssemblyFileVersion("2.7.1.0")>
|
<Assembly: AssemblyFileVersion("2.7.2.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("")>
|
<Assembly: NeutralResourcesLanguage("")>
|
||||||
|
|||||||
@@ -487,7 +487,7 @@ Public Module ModDownloadLib
|
|||||||
outputWaitHandle.WaitOne(10000)
|
outputWaitHandle.WaitOne(10000)
|
||||||
errorWaitHandle.WaitOne(10000)
|
errorWaitHandle.WaitOne(10000)
|
||||||
process.Dispose()
|
process.Dispose()
|
||||||
If TotalLength < 1000 Then Throw New Exception("安装器运行出错,末行为 " & LastResult)
|
If TotalLength < 1000 OrElse LastResult.Contains("at ") Then Throw New Exception("安装器运行出错,末行为 " & LastResult)
|
||||||
End Using
|
End Using
|
||||||
End Using
|
End Using
|
||||||
End SyncLock
|
End SyncLock
|
||||||
@@ -538,7 +538,7 @@ Public Module ModDownloadLib
|
|||||||
'OptiFine 中文镜像源
|
'OptiFine 中文镜像源
|
||||||
Sources.Add("https://optifine.cn/download/" & DownloadInfo.NameFile)
|
Sources.Add("https://optifine.cn/download/" & DownloadInfo.NameFile)
|
||||||
'构造文件请求
|
'构造文件请求
|
||||||
Task.Output = New List(Of NetFile) From {New NetFile(Sources.ToArray, Target, New FileChecker(MinSize:=64 * 1024))}
|
Task.Output = New List(Of NetFile) From {New NetFile(Sources.ToArray, Target, New FileChecker(MinSize:=300 * 1024))}
|
||||||
End Sub) With {.ProgressWeight = 8})
|
End Sub) With {.ProgressWeight = 8})
|
||||||
Loaders.Add(New LoaderDownload("下载 OptiFine 主文件", New List(Of NetFile)) With {.ProgressWeight = 8})
|
Loaders.Add(New LoaderDownload("下载 OptiFine 主文件", New List(Of NetFile)) With {.ProgressWeight = 8})
|
||||||
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("等待原版下载",
|
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("等待原版下载",
|
||||||
@@ -548,8 +548,8 @@ Public Module ModDownloadLib
|
|||||||
Dim TargetLoaders As List(Of LoaderBase) =
|
Dim TargetLoaders As List(Of LoaderBase) =
|
||||||
ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
|
ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
|
||||||
Where(Function(l) l.State <> LoadState.Finished).ToList
|
Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||||
If TargetLoaders.Count > 0 Then Log("[Download] OptiFine 安装正在等待原版文件下载完成")
|
If TargetLoaders.Any Then Log("[Download] OptiFine 安装正在等待原版文件下载完成")
|
||||||
Do While TargetLoaders.Count > 0 AndAlso Not Task.IsAborted
|
Do While TargetLoaders.Any AndAlso Not Task.IsAborted
|
||||||
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
|
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||||
Thread.Sleep(50)
|
Thread.Sleep(50)
|
||||||
Loop
|
Loop
|
||||||
@@ -560,12 +560,10 @@ Public Module ModDownloadLib
|
|||||||
Dim ClientName As String = GetFolderNameFromPath(ClientFolder)
|
Dim ClientName As String = GetFolderNameFromPath(ClientFolder)
|
||||||
Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit)
|
Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit)
|
||||||
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then
|
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then
|
||||||
CopyFile(ClientFolder & ClientName & ".json",
|
CopyFile($"{ClientFolder}{ClientName}.json", $"{McFolder}versions\{DownloadInfo.Inherit}\{DownloadInfo.Inherit}.json")
|
||||||
McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
|
|
||||||
End If
|
End If
|
||||||
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then
|
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then
|
||||||
CopyFile(ClientFolder & ClientName & ".jar",
|
CopyFile($"{ClientFolder}{ClientName}.jar", $"{McFolder}versions\{DownloadInfo.Inherit}\{DownloadInfo.Inherit}.jar")
|
||||||
McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
|
|
||||||
End If
|
End If
|
||||||
End SyncLock
|
End SyncLock
|
||||||
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
||||||
@@ -1283,20 +1281,20 @@ Retry:
|
|||||||
'获取下载信息
|
'获取下载信息
|
||||||
If DownloadInfo Is Nothing Then
|
If DownloadInfo Is Nothing Then
|
||||||
Loaders.Add(New LoaderTask(Of String, String)("获取 Mod 加载器详细信息",
|
Loaders.Add(New LoaderTask(Of String, String)("获取 Mod 加载器详细信息",
|
||||||
Sub(Task As LoaderTask(Of String, String))
|
Sub(Task As LoaderTask(Of String, String))
|
||||||
'获取 Forge 版本列表
|
'获取 Forge 版本列表
|
||||||
Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("McDownloadForgeLoader " & Inherit, AddressOf DlForgeVersionMain)
|
Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("McDownloadForgeLoader " & Inherit, AddressOf DlForgeVersionMain)
|
||||||
ForgeLoader.WaitForExit(Inherit)
|
ForgeLoader.WaitForExit(Inherit)
|
||||||
Task.Progress = 0.8
|
Task.Progress = 0.8
|
||||||
'查找对应版本
|
'查找对应版本
|
||||||
For Each ForgeVersion In ForgeLoader.Output
|
For Each ForgeVersion In ForgeLoader.Output
|
||||||
If ForgeVersion.Version = Version Then
|
If ForgeVersion.Version = Version Then
|
||||||
DownloadInfo = ForgeVersion
|
DownloadInfo = ForgeVersion
|
||||||
Exit Sub
|
Exit Sub
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
Throw New Exception("未能找到 Forge " & Inherit & "-" & Version & " 的详细信息!")
|
Throw New Exception("未能找到 Forge " & Inherit & "-" & Version & " 的详细信息!")
|
||||||
End Sub) With {.ProgressWeight = 3})
|
End Sub) With {.ProgressWeight = 3})
|
||||||
End If
|
End If
|
||||||
'下载 Forge 主文件
|
'下载 Forge 主文件
|
||||||
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("准备 Mod 加载器下载",
|
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("准备 Mod 加载器下载",
|
||||||
@@ -1383,8 +1381,8 @@ Retry:
|
|||||||
Dim TargetLoaders As List(Of LoaderBase) =
|
Dim TargetLoaders As List(Of LoaderBase) =
|
||||||
ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
|
ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
|
||||||
Where(Function(l) l.State <> LoadState.Finished).ToList
|
Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||||
If TargetLoaders.Count > 0 Then Log("[Download] Forge 安装正在等待原版文件下载完成")
|
If TargetLoaders.Any Then Log("[Download] Forge 安装正在等待原版文件下载完成")
|
||||||
Do While TargetLoaders.Count > 0 AndAlso Not Task.IsAborted
|
Do While TargetLoaders.Any AndAlso Not Task.IsAborted
|
||||||
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
|
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||||
Thread.Sleep(50)
|
Thread.Sleep(50)
|
||||||
Loop
|
Loop
|
||||||
@@ -1441,7 +1439,7 @@ Retry:
|
|||||||
End Try
|
End Try
|
||||||
'拷贝新增的版本 Json
|
'拷贝新增的版本 Json
|
||||||
Dim DeltaList = New DirectoryInfo(McFolder & "versions\").EnumerateDirectories.
|
Dim DeltaList = New DirectoryInfo(McFolder & "versions\").EnumerateDirectories.
|
||||||
SkipWhile(Function(i) OldList.Contains(i.FullName)).ToList()
|
SkipWhile(Function(i) OldList.Contains(i.FullName)).ToList()
|
||||||
If DeltaList.Count > 1 Then
|
If DeltaList.Count > 1 Then
|
||||||
'它可能和 OptiFine 安装同时运行,导致增加的文件不止一个(这导致了 #151)
|
'它可能和 OptiFine 安装同时运行,导致增加的文件不止一个(这导致了 #151)
|
||||||
'也可能是因为 Forge 安装器的 Bug,生成了一个名字错误的文件夹,所以需要检查文件夹是否为空
|
'也可能是因为 Forge 安装器的 Bug,生成了一个名字错误的文件夹,所以需要检查文件夹是否为空
|
||||||
@@ -1537,7 +1535,7 @@ Retry:
|
|||||||
Public Sub ForgeDownloadListItemPreload(Stack As StackPanel, Entrys As List(Of DlForgeVersionEntry), OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean)
|
Public Sub ForgeDownloadListItemPreload(Stack As StackPanel, Entrys As List(Of DlForgeVersionEntry), OnClick As MyListItem.ClickEventHandler, IsSaveOnly As Boolean)
|
||||||
'获取推荐版本与最新版本
|
'获取推荐版本与最新版本
|
||||||
Dim FreshVersion As DlForgeVersionEntry = Nothing
|
Dim FreshVersion As DlForgeVersionEntry = Nothing
|
||||||
If Entrys.Count > 0 Then
|
If Entrys.Any Then
|
||||||
FreshVersion = Entrys(0)
|
FreshVersion = Entrys(0)
|
||||||
Else
|
Else
|
||||||
Log("[System] 未找到可用的 Forge 版本", LogLevel.Debug)
|
Log("[System] 未找到可用的 Forge 版本", LogLevel.Debug)
|
||||||
@@ -2014,7 +2012,7 @@ Retry:
|
|||||||
|
|
||||||
Dim LoaderList As New List(Of LoaderBase)
|
Dim LoaderList As New List(Of LoaderBase)
|
||||||
'添加忽略标识
|
'添加忽略标识
|
||||||
LoaderList.Add(New LoaderTask(Of Integer, Integer)("添加忽略标识", Sub() WriteFile(OutputFolder & ".pclignore", "用于临时地 PCL 的版本列表中屏蔽此版本。")) With {.Show = False, .Block = False})
|
LoaderList.Add(New LoaderTask(Of Integer, Integer)("添加忽略标识", Sub() WriteFile(OutputFolder & ".pclignore", "用于临时地在 PCL 的版本列表中屏蔽此版本。")) With {.Show = False, .Block = False})
|
||||||
'Fabric API
|
'Fabric API
|
||||||
If Request.FabricApi IsNot Nothing Then
|
If Request.FabricApi IsNot Nothing Then
|
||||||
LoaderList.Add(New LoaderDownload("下载 Fabric API", New List(Of NetFile) From {Request.FabricApi.ToNetFile(New McVersion(OutputFolder).GetPathIndie(True) & "mods\")}) With {.ProgressWeight = 3, .Block = False})
|
LoaderList.Add(New LoaderDownload("下载 Fabric API", New List(Of NetFile) From {Request.FabricApi.ToNetFile(New McVersion(OutputFolder).GetPathIndie(True) & "mods\")}) With {.ProgressWeight = 3, .Block = False})
|
||||||
@@ -2164,7 +2162,7 @@ Retry:
|
|||||||
For i = 0 To RawArguments.Count - 1
|
For i = 0 To RawArguments.Count - 1
|
||||||
If RawArguments(i).StartsWithF("-") Then
|
If RawArguments(i).StartsWithF("-") Then
|
||||||
SplitArguments.Add(RawArguments(i))
|
SplitArguments.Add(RawArguments(i))
|
||||||
ElseIf SplitArguments.Count > 0 AndAlso SplitArguments.Last.StartsWithF("-") AndAlso Not SplitArguments.Last.Contains(" ") Then
|
ElseIf SplitArguments.Any AndAlso SplitArguments.Last.StartsWithF("-") AndAlso Not SplitArguments.Last.Contains(" ") Then
|
||||||
SplitArguments(SplitArguments.Count - 1) = SplitArguments.Last & " " & RawArguments(i)
|
SplitArguments(SplitArguments.Count - 1) = SplitArguments.Last & " " & RawArguments(i)
|
||||||
Else
|
Else
|
||||||
SplitArguments.Add(RawArguments(i))
|
SplitArguments.Add(RawArguments(i))
|
||||||
@@ -2172,6 +2170,7 @@ Retry:
|
|||||||
Next
|
Next
|
||||||
Dim RealArguments As String = Join(SplitArguments.Distinct.ToList, " ")
|
Dim RealArguments As String = Join(SplitArguments.Distinct.ToList, " ")
|
||||||
'合并
|
'合并
|
||||||
|
'相关讨论见 #2801
|
||||||
OutputJson = MinecraftJson
|
OutputJson = MinecraftJson
|
||||||
If HasOptiFine Then
|
If HasOptiFine Then
|
||||||
'合并 OptiFine
|
'合并 OptiFine
|
||||||
|
|||||||
@@ -210,10 +210,10 @@
|
|||||||
If Project.Type = CompType.Mod Then
|
If Project.Type = CompType.Mod Then
|
||||||
'获取 Mod 所需的加载器种类
|
'获取 Mod 所需的加载器种类
|
||||||
Dim AllowForge As Boolean? = Nothing, AllowFabric As Boolean? = Nothing
|
Dim AllowForge As Boolean? = Nothing, AllowFabric As Boolean? = Nothing
|
||||||
If File.ModLoaders.Count > 0 Then '从文件中获取
|
If File.ModLoaders.Any Then '从文件中获取
|
||||||
AllowForge = File.ModLoaders.Contains(CompModLoaderType.Forge)
|
AllowForge = File.ModLoaders.Contains(CompModLoaderType.Forge)
|
||||||
AllowFabric = File.ModLoaders.Contains(CompModLoaderType.Fabric)
|
AllowFabric = File.ModLoaders.Contains(CompModLoaderType.Fabric)
|
||||||
ElseIf Project.ModLoaders.Count > 0 Then '从工程中获取
|
ElseIf Project.ModLoaders.Any Then '从工程中获取
|
||||||
AllowForge = Project.ModLoaders.Contains(CompModLoaderType.Forge)
|
AllowForge = Project.ModLoaders.Contains(CompModLoaderType.Forge)
|
||||||
AllowFabric = Project.ModLoaders.Contains(CompModLoaderType.Fabric)
|
AllowFabric = Project.ModLoaders.Contains(CompModLoaderType.Fabric)
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
<StackPanel Margin="25,37,25,15">
|
<StackPanel Margin="25,37,25,15">
|
||||||
<local:MyHint Text="你尚未选择安装 Fabric API,这会导致大多数 Mod 无法使用!" Margin="0,1,0,7" x:Name="HintFabricAPI" IsWarn="True" />
|
<local:MyHint Text="你尚未选择安装 Fabric API,这会导致大多数 Mod 无法使用!" Margin="0,1,0,7" x:Name="HintFabricAPI" IsWarn="True" />
|
||||||
<local:MyHint Text="你尚未选择安装 OptiFabric,这会导致 OptiFine 无法使用!" Margin="0,1,0,7" x:Name="HintOptiFabric" IsWarn="True" />
|
<local:MyHint Text="你尚未选择安装 OptiFabric,这会导致 OptiFine 无法使用!" Margin="0,1,0,7" x:Name="HintOptiFabric" IsWarn="True" />
|
||||||
<local:MyHint Text="安装结束后,请在 Mod 下载中搜索 OptiFabric Origins 并下载,否则 OptiFine 会无法使用!" Margin="0,1,0,7" x:Name="HintOptiFabricOld" IsWarn="False" />
|
|
||||||
<Grid Margin="0,0,0,11">
|
<Grid Margin="0,0,0,11">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#Region "页面切换"
|
#Region "页面切换"
|
||||||
|
|
||||||
'页面切换动画
|
'页面切换动画
|
||||||
Private IsInSelectPage As Boolean = False
|
Public IsInSelectPage As Boolean = False
|
||||||
Private IsFirstLoaded As Boolean = False
|
Private IsFirstLoaded As Boolean = False
|
||||||
Private Sub EnterSelectPage()
|
Private Sub EnterSelectPage()
|
||||||
If IsInSelectPage Then Exit Sub
|
If IsInSelectPage Then Exit Sub
|
||||||
@@ -273,11 +273,13 @@
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private IsReloading As Boolean = False '#3742 中,LoadOptiFineGetError 会初始化 LoadOptiFine,触发事件 LoadOptiFine.StateChanged,导致再次调用 SelectReload
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 重载已选择的项目的显示。
|
''' 重载已选择的项目的显示。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub SelectReload() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
|
Private Sub SelectReload() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
|
||||||
If SelectedMinecraftId Is Nothing Then Exit Sub
|
If SelectedMinecraftId Is Nothing OrElse IsReloading Then Exit Sub
|
||||||
|
IsReloading = True
|
||||||
'主预览
|
'主预览
|
||||||
SelectNameUpdate()
|
SelectNameUpdate()
|
||||||
ItemSelect.Title = TextSelectName.Text
|
ItemSelect.Title = TextSelectName.Text
|
||||||
@@ -385,17 +387,12 @@
|
|||||||
'主警告
|
'主警告
|
||||||
HintFabricAPI.Visibility = If(SelectedFabric IsNot Nothing AndAlso SelectedFabricApi Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
HintFabricAPI.Visibility = If(SelectedFabric IsNot Nothing AndAlso SelectedFabricApi Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing AndAlso SelectedOptiFabric Is Nothing Then
|
If SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing AndAlso SelectedOptiFabric Is Nothing Then
|
||||||
If SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15") Then
|
HintOptiFabric.Visibility = Visibility.Visible
|
||||||
HintOptiFabric.Visibility = Visibility.Collapsed
|
|
||||||
HintOptiFabricOld.Visibility = Visibility.Visible
|
|
||||||
Else
|
|
||||||
HintOptiFabric.Visibility = Visibility.Visible
|
|
||||||
HintOptiFabricOld.Visibility = Visibility.Collapsed
|
|
||||||
End If
|
|
||||||
Else
|
Else
|
||||||
HintOptiFabric.Visibility = Visibility.Collapsed
|
HintOptiFabric.Visibility = Visibility.Collapsed
|
||||||
HintOptiFabricOld.Visibility = Visibility.Collapsed
|
|
||||||
End If
|
End If
|
||||||
|
'结束
|
||||||
|
IsReloading = False
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 清空已选择的项目。
|
''' 清空已选择的项目。
|
||||||
@@ -1037,7 +1034,6 @@
|
|||||||
''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadOptiFabricGetError() As String
|
Private Function LoadOptiFabricGetError() As String
|
||||||
If SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15") Then Return "不兼容老版本 Fabric,请手动下载 OptiFabric Origins"
|
|
||||||
If LoadOptiFabric Is Nothing OrElse LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
|
If LoadOptiFabric Is Nothing OrElse LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
|
||||||
If LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFabric.State, Object).Error.Message
|
If LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFabric.State, Object).Error.Message
|
||||||
If DlOptiFabricLoader.Output Is Nothing Then
|
If DlOptiFabricLoader.Output Is Nothing Then
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
||||||
<local:MyComboBoxItem Content="1.20.6" />
|
<local:MyComboBoxItem Content="1.20.6" />
|
||||||
<local:MyComboBoxItem Content="1.20.4" />
|
<local:MyComboBoxItem Content="1.20.4" />
|
||||||
<local:MyComboBoxItem Content="1.20.2" />
|
|
||||||
<local:MyComboBoxItem Content="1.20.1" />
|
<local:MyComboBoxItem Content="1.20.1" />
|
||||||
<local:MyComboBoxItem Content="1.19.4" />
|
<local:MyComboBoxItem Content="1.19.4" />
|
||||||
<local:MyComboBoxItem Content="1.19.2" />
|
<local:MyComboBoxItem Content="1.19.2" />
|
||||||
@@ -44,11 +43,9 @@
|
|||||||
<local:MyComboBoxItem Content="1.16.5" />
|
<local:MyComboBoxItem Content="1.16.5" />
|
||||||
<local:MyComboBoxItem Content="1.15.2" />
|
<local:MyComboBoxItem Content="1.15.2" />
|
||||||
<local:MyComboBoxItem Content="1.14.4" />
|
<local:MyComboBoxItem Content="1.14.4" />
|
||||||
<local:MyComboBoxItem Content="1.13.2" />
|
|
||||||
<local:MyComboBoxItem Content="1.12.2" />
|
<local:MyComboBoxItem Content="1.12.2" />
|
||||||
<local:MyComboBoxItem Content="1.11.2" />
|
<local:MyComboBoxItem Content="1.11.2" />
|
||||||
<local:MyComboBoxItem Content="1.10.2" />
|
<local:MyComboBoxItem Content="1.10.2" />
|
||||||
<local:MyComboBoxItem Content="1.9.4" />
|
|
||||||
<local:MyComboBoxItem Content="1.8.9" />
|
<local:MyComboBoxItem Content="1.8.9" />
|
||||||
<local:MyComboBoxItem Content="1.7.10" />
|
<local:MyComboBoxItem Content="1.7.10" />
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
@@ -122,4 +119,4 @@
|
|||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyScrollViewer>
|
</local:MyScrollViewer>
|
||||||
</local:MyPageRight>
|
</local:MyPageRight>
|
||||||
@@ -34,7 +34,6 @@
|
|||||||
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
||||||
<local:MyComboBoxItem Content="1.20.6" />
|
<local:MyComboBoxItem Content="1.20.6" />
|
||||||
<local:MyComboBoxItem Content="1.20.4" />
|
<local:MyComboBoxItem Content="1.20.4" />
|
||||||
<local:MyComboBoxItem Content="1.20.2" />
|
|
||||||
<local:MyComboBoxItem Content="1.20.1" />
|
<local:MyComboBoxItem Content="1.20.1" />
|
||||||
<local:MyComboBoxItem Content="1.19.4" />
|
<local:MyComboBoxItem Content="1.19.4" />
|
||||||
<local:MyComboBoxItem Content="1.19.2" />
|
<local:MyComboBoxItem Content="1.19.2" />
|
||||||
@@ -43,11 +42,9 @@
|
|||||||
<local:MyComboBoxItem Content="1.16.5" />
|
<local:MyComboBoxItem Content="1.16.5" />
|
||||||
<local:MyComboBoxItem Content="1.15.2" />
|
<local:MyComboBoxItem Content="1.15.2" />
|
||||||
<local:MyComboBoxItem Content="1.14.4" />
|
<local:MyComboBoxItem Content="1.14.4" />
|
||||||
<local:MyComboBoxItem Content="1.13.2" />
|
|
||||||
<local:MyComboBoxItem Content="1.12.2" />
|
<local:MyComboBoxItem Content="1.12.2" />
|
||||||
<local:MyComboBoxItem Content="1.11.2" />
|
<local:MyComboBoxItem Content="1.11.2" />
|
||||||
<local:MyComboBoxItem Content="1.10.2" />
|
<local:MyComboBoxItem Content="1.10.2" />
|
||||||
<local:MyComboBoxItem Content="1.9.4" />
|
|
||||||
<local:MyComboBoxItem Content="1.8.9" />
|
<local:MyComboBoxItem Content="1.8.9" />
|
||||||
<local:MyComboBoxItem Content="1.7.10" />
|
<local:MyComboBoxItem Content="1.7.10" />
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
@@ -111,4 +108,4 @@
|
|||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyScrollViewer>
|
</local:MyScrollViewer>
|
||||||
</local:MyPageRight>
|
</local:MyPageRight>
|
||||||
@@ -19,51 +19,53 @@
|
|||||||
RefreshButtonsUI()
|
RefreshButtonsUI()
|
||||||
|
|
||||||
'加载版本
|
'加载版本
|
||||||
RunInNewThread(Sub()
|
RunInNewThread(
|
||||||
'确认 Minecraft 文件夹存在
|
Sub()
|
||||||
PathMcFolder = Setup.Get("LaunchFolderSelect").ToString.Replace("$", Path)
|
'确认 Minecraft 文件夹存在
|
||||||
If PathMcFolder = "" OrElse Not Directory.Exists(PathMcFolder) Then
|
PathMcFolder = Setup.Get("LaunchFolderSelect").ToString.Replace("$", Path)
|
||||||
'无效的文件夹
|
If PathMcFolder = "" OrElse Not Directory.Exists(PathMcFolder) Then
|
||||||
If PathMcFolder = "" Then
|
'无效的文件夹
|
||||||
Log("[Launch] 没有已储存的 Minecraft 文件夹")
|
If PathMcFolder = "" Then
|
||||||
Else
|
Log("[Launch] 没有已储存的 Minecraft 文件夹")
|
||||||
Log("[Launch] Minecraft 文件夹无效,该文件夹已不存在:" & PathMcFolder, LogLevel.Debug)
|
Else
|
||||||
End If
|
Log("[Launch] Minecraft 文件夹无效,该文件夹已不存在:" & PathMcFolder, LogLevel.Debug)
|
||||||
McFolderListLoader.WaitForExit(IsForceRestart:=True)
|
End If
|
||||||
Setup.Set("LaunchFolderSelect", McFolderList(0).Path.Replace(Path, "$"))
|
McFolderListLoader.WaitForExit(IsForceRestart:=True)
|
||||||
End If
|
Setup.Set("LaunchFolderSelect", McFolderList(0).Path.Replace(Path, "$"))
|
||||||
Log("[Launch] Minecraft 文件夹:" & PathMcFolder)
|
End If
|
||||||
If Setup.Get("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
|
Log("[Launch] Minecraft 文件夹:" & PathMcFolder)
|
||||||
'确认 Minecraft 版本存在
|
If Setup.Get("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
|
||||||
Dim Selection As String = Setup.Get("LaunchVersionSelect")
|
'确认 Minecraft 版本存在
|
||||||
Dim Version As McVersion
|
Dim Selection As String = Setup.Get("LaunchVersionSelect")
|
||||||
If Selection = "" Then
|
Dim Version As McVersion
|
||||||
Version = Nothing
|
If Selection = "" Then
|
||||||
Else
|
Version = Nothing
|
||||||
Version = New McVersion(Selection)
|
Else
|
||||||
End If
|
Version = New McVersion(Selection)
|
||||||
If IsNothing(Version) OrElse Not (Version.Path.StartsWith(PathMcFolder) AndAlso Version.Check) Then
|
End If
|
||||||
'无效的版本
|
If IsNothing(Version) OrElse Not (Version.Path.StartsWith(PathMcFolder) AndAlso Version.Check) Then
|
||||||
Log("[Launch] Minecraft 版本无效" & If(IsNothing(Version), ",没有有效版本", ":" & Version.Path), If(IsNothing(Version), LogLevel.Normal, LogLevel.Debug))
|
'无效的版本
|
||||||
If Not McVersionListLoader.State = LoadState.Finished Then LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
|
Log("[Launch] Minecraft 版本无效" & If(IsNothing(Version), ",没有有效版本", ":" & Version.Path), If(IsNothing(Version), LogLevel.Normal, LogLevel.Debug))
|
||||||
If Not McVersionList.Any() OrElse McVersionList.First.Value(0).Logo.Contains("RedstoneBlock") Then
|
If Not McVersionListLoader.State = LoadState.Finished Then LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
|
||||||
Version = Nothing
|
If Not McVersionList.Any() OrElse McVersionList.First.Value(0).Logo.Contains("RedstoneBlock") Then
|
||||||
Setup.Set("LaunchVersionSelect", "")
|
Version = Nothing
|
||||||
Log("[Launch] 无可用 Minecraft 版本")
|
Setup.Set("LaunchVersionSelect", "")
|
||||||
Else
|
Log("[Launch] 无可用 Minecraft 版本")
|
||||||
Version = McVersionList.First.Value(0)
|
Else
|
||||||
Setup.Set("LaunchVersionSelect", Version.Name)
|
Version = McVersionList.First.Value(0)
|
||||||
Log("[Launch] 自动选择 Minecraft 版本:" & Version.Path)
|
Setup.Set("LaunchVersionSelect", Version.Name)
|
||||||
End If
|
Log("[Launch] 自动选择 Minecraft 版本:" & Version.Path)
|
||||||
End If
|
End If
|
||||||
RunInUi(Sub()
|
End If
|
||||||
McVersionCurrent = Version '绕这一圈是为了避免 McVersionCheck 触发第二次版本改变
|
RunInUi(
|
||||||
IsLoadFinished = True
|
Sub()
|
||||||
RefreshButtonsUI()
|
McVersionCurrent = Version '绕这一圈是为了避免 McVersionCheck 触发第二次版本改变
|
||||||
RefreshPage(False, False) '有可能选择的版本变化了,需要重新刷新
|
IsLoadFinished = True
|
||||||
If McLoginAble() = "" Then McLoginLoader.Start() '自动登录
|
RefreshButtonsUI()
|
||||||
End Sub)
|
RefreshPage(False, False) '有可能选择的版本变化了,需要重新刷新
|
||||||
End Sub, "Version Check", ThreadPriority.AboveNormal)
|
If McLoginAble() = "" Then McLoginLoader.Start() '自动登录
|
||||||
|
End Sub)
|
||||||
|
End Sub, "Version Check", ThreadPriority.AboveNormal)
|
||||||
|
|
||||||
'改变页面
|
'改变页面
|
||||||
Dim LoginType As McLoginType = Setup.Get("LoginType")
|
Dim LoginType As McLoginType = Setup.Get("LoginType")
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ Download:
|
|||||||
End If
|
End If
|
||||||
Case 3
|
Case 3
|
||||||
Select Case Setup.Get("UiCustomPreset")
|
Select Case Setup.Get("UiCustomPreset")
|
||||||
Case 0 '你知道吗
|
Case 0
|
||||||
Log("[Page] 主页预设:你知道吗")
|
Log("[Page] 主页预设:你知道吗")
|
||||||
Content = "
|
Content = "
|
||||||
<local:MyCard Title=""你知道吗?"" Margin=""0,0,0,15"">
|
<local:MyCard Title=""你知道吗?"" Margin=""0,0,0,15"">
|
||||||
@@ -76,7 +76,7 @@ Download:
|
|||||||
EventType=""刷新主页"" EventData=""/""
|
EventType=""刷新主页"" EventData=""/""
|
||||||
Logo=""M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z"" />
|
Logo=""M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z"" />
|
||||||
</local:MyCard>"
|
</local:MyCard>"
|
||||||
Case 1 '回声洞
|
Case 1
|
||||||
Log("[Page] 主页预设:回声洞")
|
Log("[Page] 主页预设:回声洞")
|
||||||
Content = "
|
Content = "
|
||||||
<local:MyCard Title=""回声洞"" Margin=""0,0,0,15"">
|
<local:MyCard Title=""回声洞"" Margin=""0,0,0,15"">
|
||||||
@@ -85,17 +85,17 @@ Download:
|
|||||||
EventType=""刷新主页"" EventData=""/""
|
EventType=""刷新主页"" EventData=""/""
|
||||||
Logo=""M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z"" />
|
Logo=""M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z"" />
|
||||||
</local:MyCard>"
|
</local:MyCard>"
|
||||||
Case 2 '新闻
|
Case 2
|
||||||
Log("[Page] 主页预设:Minecraft 新闻")
|
Log("[Page] 主页预设:Minecraft 新闻")
|
||||||
Url = "http://pcl.mcnews.thestack.top"
|
Url = "http://pcl.mcnews.thestack.top"
|
||||||
GoTo Download
|
GoTo Download
|
||||||
Case 3 '简单主页
|
Case 3
|
||||||
Log("[Page] 主页预设:简单主页")
|
Log("[Page] 主页预设:简单主页")
|
||||||
Url = "https://gitee.com/mfn233/PCL-Mainpage/raw/main/Custom.xaml"
|
Url = "https://gitee.com/mfn233/PCL-Mainpage/raw/main/Custom.xaml"
|
||||||
GoTo Download
|
GoTo Download
|
||||||
Case 4 '历史上的今天
|
Case 4
|
||||||
Log("[Page] 主页预设:历史上的今天")
|
Log("[Page] 主页预设:每日整合包推荐")
|
||||||
Url = "https://pclnews.52chye.cn/custom.xaml"
|
Url = "https://pclsub.sodamc.com/"
|
||||||
GoTo Download
|
GoTo Download
|
||||||
End Select
|
End Select
|
||||||
End Select
|
End Select
|
||||||
|
|||||||
@@ -85,50 +85,51 @@
|
|||||||
Hint("正在更改皮肤……")
|
Hint("正在更改皮肤……")
|
||||||
IsChanging = True
|
IsChanging = True
|
||||||
'开始实际获取
|
'开始实际获取
|
||||||
RunInNewThread(Async Sub()
|
RunInNewThread(
|
||||||
Try
|
Async Sub()
|
||||||
|
Try
|
||||||
Retry:
|
Retry:
|
||||||
If McLoginMsLoader.State = LoadState.Loading Then McLoginMsLoader.WaitForExit() '等待登录结束
|
If McLoginMsLoader.State = LoadState.Loading Then McLoginMsLoader.WaitForExit() '等待登录结束
|
||||||
Dim AccessToken As String = Setup.Get("CacheMsAccess")
|
Dim AccessToken As String = Setup.Get("CacheMsAccess")
|
||||||
Dim Uuid As String = Setup.Get("CacheMsUuid")
|
Dim Uuid As String = Setup.Get("CacheMsUuid")
|
||||||
|
|
||||||
Dim Client As New Net.Http.HttpClient With {.Timeout = New TimeSpan(0, 0, 30)}
|
Dim Client As New Net.Http.HttpClient With {.Timeout = New TimeSpan(0, 0, 30)}
|
||||||
Client.DefaultRequestHeaders.Authorization = New Net.Http.Headers.AuthenticationHeaderValue("Bearer", AccessToken)
|
Client.DefaultRequestHeaders.Authorization = New Net.Http.Headers.AuthenticationHeaderValue("Bearer", AccessToken)
|
||||||
Client.DefaultRequestHeaders.Accept.Add(New Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"))
|
Client.DefaultRequestHeaders.Accept.Add(New Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"))
|
||||||
Client.DefaultRequestHeaders.UserAgent.Add(New Net.Http.Headers.ProductInfoHeaderValue("MojangSharp", "0.1"))
|
Client.DefaultRequestHeaders.UserAgent.Add(New Net.Http.Headers.ProductInfoHeaderValue("MojangSharp", "0.1"))
|
||||||
Dim Contents As New Net.Http.MultipartFormDataContent From {
|
Dim Contents As New Net.Http.MultipartFormDataContent From {
|
||||||
{New Net.Http.StringContent(If(SkinInfo.IsSlim, "slim", "classic")), "variant"},
|
{New Net.Http.StringContent(If(SkinInfo.IsSlim, "slim", "classic")), "variant"},
|
||||||
{New Net.Http.ByteArrayContent(File.ReadAllBytes(SkinInfo.LocalFile)), "file", GetFileNameFromPath(SkinInfo.LocalFile)}
|
{New Net.Http.ByteArrayContent(File.ReadAllBytes(SkinInfo.LocalFile)), "file", GetFileNameFromPath(SkinInfo.LocalFile)}
|
||||||
}
|
}
|
||||||
Dim Result As String = Await (Await Client.PostAsync(New Uri("https://api.minecraftservices.com/minecraft/profile/skins"), Contents)).Content.ReadAsStringAsync
|
Dim Result As String = Await (Await Client.PostAsync(New Uri("https://api.minecraftservices.com/minecraft/profile/skins"), Contents)).Content.ReadAsStringAsync
|
||||||
If Result.Contains("request requires user authentication") Then
|
If Result.Contains("request requires user authentication") Then
|
||||||
Hint("正在登录,将在登录完成后继续更改皮肤……")
|
Hint("正在登录,将在登录完成后继续更改皮肤……")
|
||||||
McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
|
McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
|
||||||
GoTo Retry
|
GoTo Retry
|
||||||
ElseIf Result.Contains("""error""") Then
|
ElseIf Result.Contains("""error""") Then
|
||||||
Hint("更改皮肤失败:" & GetJson(Result)("error"), HintType.Critical)
|
Hint("更改皮肤失败:" & GetJson(Result)("error"), HintType.Critical)
|
||||||
Exit Sub
|
Exit Sub
|
||||||
End If
|
End If
|
||||||
'获取新皮肤地址
|
'获取新皮肤地址
|
||||||
Log("[Skin] 皮肤修改返回值:" & vbCrLf & Result)
|
Log("[Skin] 皮肤修改返回值:" & vbCrLf & Result)
|
||||||
Dim ResultJson As JObject = GetJson(Result)
|
Dim ResultJson As JObject = GetJson(Result)
|
||||||
For Each Skin As JObject In ResultJson("skins")
|
For Each Skin As JObject In ResultJson("skins")
|
||||||
If Skin("state").ToString = "ACTIVE" Then
|
If Skin("state").ToString = "ACTIVE" Then
|
||||||
MySkin.ReloadCache(Skin("url"))
|
MySkin.ReloadCache(Skin("url"))
|
||||||
Exit Sub
|
Exit Sub
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
Throw New Exception("未知错误(" & Result & ")")
|
Throw New Exception("未知错误(" & Result & ")")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
If ex.GetType.Equals(GetType(Tasks.TaskCanceledException)) Then
|
If ex.GetType.Equals(GetType(Tasks.TaskCanceledException)) Then
|
||||||
Hint("更改皮肤失败:与 Mojang 皮肤服务器的连接超时,请检查你的网络是否通畅!", HintType.Critical)
|
Hint("更改皮肤失败:与 Mojang 皮肤服务器的连接超时,请检查你的网络是否通畅!", HintType.Critical)
|
||||||
Else
|
Else
|
||||||
Log(ex, "更改皮肤失败", LogLevel.Hint)
|
Log(ex, "更改皮肤失败", LogLevel.Hint)
|
||||||
End If
|
End If
|
||||||
Finally
|
Finally
|
||||||
IsChanging = False
|
IsChanging = False
|
||||||
End Try
|
End Try
|
||||||
End Sub, "Ms Skin Upload")
|
End Sub, "Ms Skin Upload")
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'保存皮肤
|
'保存皮肤
|
||||||
|
|||||||
@@ -237,7 +237,7 @@
|
|||||||
If Not Version.Modable Then Continue For
|
If Not Version.Modable Then Continue For
|
||||||
'4. 该版本的隔离文件夹下不存在 mods
|
'4. 该版本的隔离文件夹下不存在 mods
|
||||||
Dim ModIndieFolder As New DirectoryInfo(Version.Path & "mods\")
|
Dim ModIndieFolder As New DirectoryInfo(Version.Path & "mods\")
|
||||||
If ModIndieFolder.Exists AndAlso ModIndieFolder.EnumerateFiles.Count > 0 Then Exit Sub
|
If ModIndieFolder.Exists AndAlso ModIndieFolder.EnumerateFiles.Any Then Exit Sub
|
||||||
'满足以上全部条件则视为根目录整合包
|
'满足以上全部条件则视为根目录整合包
|
||||||
Setup.Set("VersionArgumentIndie", 2, Version:=Version)
|
Setup.Set("VersionArgumentIndie", 2, Version:=Version)
|
||||||
Log("[Setup] 已自动关闭单版本隔离:" & Version.Name, LogLevel.Debug)
|
Log("[Setup] 已自动关闭单版本隔离:" & Version.Name, LogLevel.Debug)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
<local:MyComboBoxItem Content="中(平衡)" IsSelected="True" />
|
<local:MyComboBoxItem Content="中(平衡)" IsSelected="True" />
|
||||||
<local:MyComboBoxItem Content="低(优先保证其他程序运行,但可能让游戏卡顿,适合挂机时使用)" />
|
<local:MyComboBoxItem Content="低(优先保证其他程序运行,但可能让游戏卡顿,适合挂机时使用)" />
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
<TextBlock VerticalAlignment="Center" Grid.Row="10" HorizontalAlignment="Left" Text="游戏窗口" Margin="0,0,25,0" />
|
<TextBlock VerticalAlignment="Center" Grid.Row="10" HorizontalAlignment="Left" Text="窗口大小" Margin="0,0,25,0" />
|
||||||
<Grid x:Name="PanArgumentWindow" Grid.Row="10" Grid.ColumnSpan="2" Grid.Column="1">
|
<Grid x:Name="PanArgumentWindow" Grid.Row="10" Grid.ColumnSpan="2" Grid.Column="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
@@ -125,11 +125,10 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<local:MyComboBox x:Name="ComboArgumentWindowType" Tag="LaunchArgumentWindowType">
|
<local:MyComboBox x:Name="ComboArgumentWindowType" Tag="LaunchArgumentWindowType">
|
||||||
<local:MyComboBoxItem Content="全屏" />
|
<local:MyComboBoxItem Content="全屏" />
|
||||||
<local:MyComboBoxItem Content="默认大小" IsSelected="True" ToolTip="以 854×480 的默认窗口大小启动 Minecraft" />
|
<local:MyComboBoxItem Content="默认" IsSelected="True" />
|
||||||
<local:MyComboBoxItem Content="与启动器窗口大小一致" />
|
<local:MyComboBoxItem Content="与启动器尺寸一致" />
|
||||||
<local:MyComboBoxItem Content="自定义大小" ToolTip="注意:Forge 1.12 存在 Bug,会导致高度设定无效" />
|
<local:MyComboBoxItem Content="自定义尺寸" ToolTip="Forge 1.12.2 等个别版本存在 Bug,会导致高度设定无效" />
|
||||||
<local:MyComboBoxItem Content="最大化" />
|
<local:MyComboBoxItem Content="最大化" />
|
||||||
<local:MyComboBoxItem Content="保持游戏默认" />
|
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
<local:MyTextBox Padding="0,0,5,0" Visibility="Collapsed" Grid.Column="1" Margin="50,0,0,0" x:Name="TextArgumentWindowWidth" Tag="LaunchArgumentWindowWidth" Width="60" HorizontalContentAlignment="Center" Text="854">
|
<local:MyTextBox Padding="0,0,5,0" Visibility="Collapsed" Grid.Column="1" Margin="50,0,0,0" x:Name="TextArgumentWindowWidth" Tag="LaunchArgumentWindowWidth" Width="60" HorizontalContentAlignment="Center" Text="854">
|
||||||
<local:MyTextBox.ValidateRules>
|
<local:MyTextBox.ValidateRules>
|
||||||
@@ -138,7 +137,7 @@
|
|||||||
</local:MyTextBox>
|
</local:MyTextBox>
|
||||||
<TextBlock x:Name="LabArgumentWindowMiddle" Visibility="Collapsed" Grid.Column="2" Text=" × " VerticalAlignment="Center" FontSize="18" />
|
<TextBlock x:Name="LabArgumentWindowMiddle" Visibility="Collapsed" Grid.Column="2" Text=" × " VerticalAlignment="Center" FontSize="18" />
|
||||||
<local:MyTextBox Padding="0,0,5,0" Visibility="Collapsed" Grid.Column="3" Width="60" HorizontalContentAlignment="Center" x:Name="TextArgumentWindowHeight" Tag="LaunchArgumentWindowHeight" Text="480"
|
<local:MyTextBox Padding="0,0,5,0" Visibility="Collapsed" Grid.Column="3" Width="60" HorizontalContentAlignment="Center" x:Name="TextArgumentWindowHeight" Tag="LaunchArgumentWindowHeight" Text="480"
|
||||||
ToolTip="注意:Forge 1.12.2 等个别版本存在 Bug,会导致高度设定无效" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5">
|
ToolTip="Forge 1.12.2 等个别版本存在 Bug,会导致高度设定无效" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5">
|
||||||
<local:MyTextBox.ValidateRules>
|
<local:MyTextBox.ValidateRules>
|
||||||
<local:ValidateInteger Min="1" Max="9999" />
|
<local:ValidateInteger Min="1" Max="9999" />
|
||||||
</local:MyTextBox.ValidateRules>
|
</local:MyTextBox.ValidateRules>
|
||||||
@@ -175,11 +174,16 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="9" />
|
<RowDefinition Height="9" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="9" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<local:MyRadioBox Text="自动配置" Width="110" Checked="True" x:Name="RadioRamType0" Tag="LaunchRamType/0" Margin="0,0,20,0"
|
<local:MyRadioBox Text="自动配置" Width="110" Checked="True" x:Name="RadioRamType0" Tag="LaunchRamType/0" Margin="0,0,20,0"
|
||||||
ToolTip="根据安装的 Mod 量与电脑剩余内存,动态调整为游戏分配的内存" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="-10" ToolTipService.VerticalOffset="-3" />
|
ToolTip="根据安装的 Mod 量与电脑剩余内存,动态调整为游戏分配的内存" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="-10" ToolTipService.VerticalOffset="-3" />
|
||||||
<local:MyRadioBox Grid.Row="2" Text="自定义" x:Name="RadioRamType1" Tag="LaunchRamType/1" Margin="0,0,20,0" />
|
<local:MyRadioBox Grid.Row="2" Text="自定义" x:Name="RadioRamType1" Tag="LaunchRamType/1" Margin="0,0,20,0" />
|
||||||
<local:MySlider Grid.Row="2" Grid.Column="1" IsEnabled="False" x:Name="SliderRamCustom" Tag="LaunchRamCustom" MaxValue="49" Value="13" />
|
<local:MySlider Grid.Row="2" Grid.Column="1" IsEnabled="False" x:Name="SliderRamCustom" Tag="LaunchRamCustom" MaxValue="49" Value="13" />
|
||||||
|
<local:MyCheckBox Grid.Row="4" Grid.ColumnSpan="3" Text="启动游戏前进行内存优化" Height="22" x:Name="CheckArgumentRam" Tag="LaunchArgumentRam"
|
||||||
|
ToolTipService.Placement="Left" ToolTipService.HorizontalOffset="525" ToolTipService.VerticalOffset="-30"
|
||||||
|
ToolTip="内存优化能将当前物理内存占用降低约 1/3,不仅限于 MC!
如果使用机械硬盘,这还可能会导致一小段时间的严重卡顿。
使用 --memory 参数启动 PCL 可以静默执行内存优化。" />
|
||||||
<!--<local:MyTextBox Grid.Row="2" Grid.Column="3" Width="100" VerticalAlignment="Center" Margin="30,0,0,0" Text="2048 MB" />-->
|
<!--<local:MyTextBox Grid.Row="2" Grid.Column="3" Width="100" VerticalAlignment="Center" Margin="30,0,0,0" Text="2048 MB" />-->
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="PanRamDisplay" Margin="0,11,2,0" SnapsToDevicePixels="True" Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="1">
|
<Grid x:Name="PanRamDisplay" Margin="0,11,2,0" SnapsToDevicePixels="True" Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="1">
|
||||||
@@ -229,7 +233,7 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数头" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数头" Margin="0,0,25,0" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="LaunchAdvanceJvm" Grid.Column="1" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,在没有确定把握的情况下请不要尝试修改。
你可以通过点击左侧选项卡的初始化按钮来恢复到默认设置。" MaxLength="4000" Text="-XX:+UseG1GC -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignoreInvalidMinecraftCertificates=True -Dfml.ignorePatchDiscrepancies=True -Dlog4j2.formatMsgNoLookups=true"
|
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="LaunchAdvanceJvm" Grid.Column="1" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,在没有确定把握的情况下请不要尝试修改。
你可以通过点击左侧选项卡的初始化按钮来恢复到默认设置。" MaxLength="4000"
|
||||||
Height="57" AcceptsReturn="True" TextWrapping="Wrap" VerticalContentAlignment="Top" Padding="0,5" />
|
Height="57" AcceptsReturn="True" TextWrapping="Wrap" VerticalContentAlignment="Top" Padding="0,5" />
|
||||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数尾" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数尾" Margin="0,0,25,0" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="LaunchAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。" />
|
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="LaunchAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。" />
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
ComboArgumentWindowType.SelectedIndex = Setup.Get("LaunchArgumentWindowType")
|
ComboArgumentWindowType.SelectedIndex = Setup.Get("LaunchArgumentWindowType")
|
||||||
TextArgumentWindowWidth.Text = Setup.Get("LaunchArgumentWindowWidth")
|
TextArgumentWindowWidth.Text = Setup.Get("LaunchArgumentWindowWidth")
|
||||||
TextArgumentWindowHeight.Text = Setup.Get("LaunchArgumentWindowHeight")
|
TextArgumentWindowHeight.Text = Setup.Get("LaunchArgumentWindowHeight")
|
||||||
|
CheckArgumentRam.Checked = Setup.Get("LaunchArgumentRam")
|
||||||
RefreshJavaComboBox()
|
RefreshJavaComboBox()
|
||||||
|
|
||||||
'游戏内存
|
'游戏内存
|
||||||
@@ -71,6 +72,7 @@
|
|||||||
Setup.Reset("LaunchArgumentWindowWidth")
|
Setup.Reset("LaunchArgumentWindowWidth")
|
||||||
Setup.Reset("LaunchArgumentWindowHeight")
|
Setup.Reset("LaunchArgumentWindowHeight")
|
||||||
Setup.Reset("LaunchArgumentPriority")
|
Setup.Reset("LaunchArgumentPriority")
|
||||||
|
Setup.Reset("LaunchArgumentRam")
|
||||||
Setup.Reset("LaunchRamType")
|
Setup.Reset("LaunchRamType")
|
||||||
Setup.Reset("LaunchRamCustom")
|
Setup.Reset("LaunchRamCustom")
|
||||||
Setup.Reset("LaunchSkinType")
|
Setup.Reset("LaunchSkinType")
|
||||||
@@ -108,7 +110,7 @@
|
|||||||
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndie.SelectionChanged, ComboArgumentVisibie.SelectionChanged, ComboArgumentWindowType.SelectionChanged, ComboArgumentPriority.SelectionChanged
|
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndie.SelectionChanged, ComboArgumentVisibie.SelectionChanged, ComboArgumentWindowType.SelectionChanged, ComboArgumentPriority.SelectionChanged
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
||||||
End Sub
|
End Sub
|
||||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceAssets.Change, CheckAdvanceJava.Change, CheckAdvanceRunWait.Change
|
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceAssets.Change, CheckAdvanceJava.Change, CheckAdvanceRunWait.Change, CheckArgumentRam.Change
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -352,19 +354,19 @@
|
|||||||
'可安装 Mod 的版本
|
'可安装 Mod 的版本
|
||||||
Dim ModDir As New DirectoryInfo(Version.PathIndie & "mods\")
|
Dim ModDir As New DirectoryInfo(Version.PathIndie & "mods\")
|
||||||
Dim ModCount As Integer = If(ModDir.Exists, ModDir.GetFiles.Length, 0)
|
Dim ModCount As Integer = If(ModDir.Exists, ModDir.GetFiles.Length, 0)
|
||||||
RamMininum = 0.4 + ModCount / 150
|
RamMininum = 0.5 + ModCount / 150
|
||||||
RamTarget1 = 1.5 + ModCount / 100
|
RamTarget1 = 1.5 + ModCount / 90
|
||||||
RamTarget2 = 3 + ModCount / 60
|
RamTarget2 = 2.7 + ModCount / 50
|
||||||
RamTarget3 = 6 + ModCount / 30
|
RamTarget3 = 4.5 + ModCount / 25
|
||||||
ElseIf Version IsNot Nothing AndAlso Version.Version.HasOptiFine Then
|
ElseIf Version IsNot Nothing AndAlso Version.Version.HasOptiFine Then
|
||||||
'OptiFine 版本
|
'OptiFine 版本
|
||||||
RamMininum = 0.3
|
RamMininum = 0.5
|
||||||
RamTarget1 = 1.5
|
RamTarget1 = 1.5
|
||||||
RamTarget2 = 3
|
RamTarget2 = 3
|
||||||
RamTarget3 = 6
|
RamTarget3 = 5
|
||||||
Else
|
Else
|
||||||
'普通版本
|
'普通版本
|
||||||
RamMininum = 0.3
|
RamMininum = 0.5
|
||||||
RamTarget1 = 1.5
|
RamTarget1 = 1.5
|
||||||
RamTarget2 = 2.5
|
RamTarget2 = 2.5
|
||||||
RamTarget3 = 4
|
RamTarget3 = 4
|
||||||
@@ -372,27 +374,23 @@
|
|||||||
Dim RamDelta As Double
|
Dim RamDelta As Double
|
||||||
'预分配内存,阶段一,0 ~ T1,100%
|
'预分配内存,阶段一,0 ~ T1,100%
|
||||||
RamDelta = RamTarget1
|
RamDelta = RamTarget1
|
||||||
RamAvailable = Math.Max(0, RamAvailable - 0.1)
|
RamGive += Math.Min(RamAvailable, RamDelta)
|
||||||
RamGive += Math.Min(RamAvailable * 1, RamDelta)
|
RamAvailable -= RamDelta
|
||||||
RamAvailable -= RamDelta / 1 + 0.1
|
|
||||||
If RamAvailable < 0.1 Then GoTo PreFin
|
If RamAvailable < 0.1 Then GoTo PreFin
|
||||||
'预分配内存,阶段二,T1 ~ T2,80%
|
'预分配内存,阶段二,T1 ~ T2,70%
|
||||||
RamDelta = RamTarget2 - RamTarget1
|
RamDelta = RamTarget2 - RamTarget1
|
||||||
RamAvailable = Math.Max(0, RamAvailable - 0.1)
|
RamGive += Math.Min(RamAvailable * 0.7, RamDelta)
|
||||||
RamGive += Math.Min(RamAvailable * 0.8, RamDelta)
|
RamAvailable -= RamDelta / 0.7
|
||||||
RamAvailable -= RamDelta / 0.8 + 0.1
|
|
||||||
If RamAvailable < 0.1 Then GoTo PreFin
|
If RamAvailable < 0.1 Then GoTo PreFin
|
||||||
'预分配内存,阶段三,T2 ~ T3,60%
|
'预分配内存,阶段三,T2 ~ T3,40%
|
||||||
RamDelta = RamTarget3 - RamTarget2
|
RamDelta = RamTarget3 - RamTarget2
|
||||||
RamAvailable = Math.Max(0, RamAvailable - 0.2)
|
|
||||||
RamGive += Math.Min(RamAvailable * 0.6, RamDelta)
|
|
||||||
RamAvailable -= RamDelta / 0.6 + 0.2
|
|
||||||
If RamAvailable < 0.1 Then GoTo PreFin
|
|
||||||
'预分配内存,阶段四,T3 ~ T3 * 2,40%
|
|
||||||
RamDelta = RamTarget3
|
|
||||||
RamAvailable = Math.Max(0, RamAvailable - 0.3)
|
|
||||||
RamGive += Math.Min(RamAvailable * 0.4, RamDelta)
|
RamGive += Math.Min(RamAvailable * 0.4, RamDelta)
|
||||||
RamAvailable -= RamDelta / 0.4 + 0.3
|
RamAvailable -= RamDelta / 0.4
|
||||||
|
If RamAvailable < 0.1 Then GoTo PreFin
|
||||||
|
'预分配内存,阶段四,T3 ~ T3 * 2,15%
|
||||||
|
RamDelta = RamTarget3
|
||||||
|
RamGive += Math.Min(RamAvailable * 0.15, RamDelta)
|
||||||
|
RamAvailable -= RamDelta / 0.15
|
||||||
If RamAvailable < 0.1 Then GoTo PreFin
|
If RamAvailable < 0.1 Then GoTo PreFin
|
||||||
PreFin:
|
PreFin:
|
||||||
'不低于最低值
|
'不低于最低值
|
||||||
@@ -444,7 +442,7 @@ PreFin:
|
|||||||
Log(ex, "更新设置 Java 下拉框失败", LogLevel.Feedback)
|
Log(ex, "更新设置 Java 下拉框失败", LogLevel.Feedback)
|
||||||
End Try
|
End Try
|
||||||
'更新选择项
|
'更新选择项
|
||||||
If SelectedItem Is Nothing AndAlso JavaList.Count > 0 Then SelectedItem = ComboArgumentJava.Items(0) '选中 “自动选择”
|
If SelectedItem Is Nothing AndAlso JavaList.Any Then SelectedItem = ComboArgumentJava.Items(0) '选中 “自动选择”
|
||||||
ComboArgumentJava.SelectedItem = SelectedItem
|
ComboArgumentJava.SelectedItem = SelectedItem
|
||||||
'结束处理
|
'结束处理
|
||||||
If SelectedItem Is Nothing Then
|
If SelectedItem Is Nothing Then
|
||||||
@@ -515,15 +513,16 @@ PreFin:
|
|||||||
Hint("正在搜索 Java,请稍候!", HintType.Critical)
|
Hint("正在搜索 Java,请稍候!", HintType.Critical)
|
||||||
Exit Sub
|
Exit Sub
|
||||||
End If
|
End If
|
||||||
RunInThread(Sub()
|
RunInThread(
|
||||||
Hint("正在搜索 Java!")
|
Sub()
|
||||||
JavaSearchLoader.WaitForExit(IsForceRestart:=True)
|
Hint("正在搜索 Java!")
|
||||||
If Not JavaList.Any() Then
|
JavaSearchLoader.WaitForExit(IsForceRestart:=True)
|
||||||
Hint("未找到可用的 Java!", HintType.Critical)
|
If Not JavaList.Any() Then
|
||||||
Else
|
Hint("未找到可用的 Java!", HintType.Critical)
|
||||||
Hint("已找到 " & JavaList.Count & " 个 Java,请检查下拉框查看列表!", HintType.Finish)
|
Else
|
||||||
End If
|
Hint("已找到 " & JavaList.Count & " 个 Java,请检查下拉框查看列表!", HintType.Finish)
|
||||||
End Sub)
|
End If
|
||||||
|
End Sub)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
@@ -548,12 +547,24 @@ PreFin:
|
|||||||
If AniControlEnabled <> 0 Then Exit Sub
|
If AniControlEnabled <> 0 Then Exit Sub
|
||||||
If ComboArgumentVisibie.SelectedIndex = 0 Then
|
If ComboArgumentVisibie.SelectedIndex = 0 Then
|
||||||
If MyMsgBox("若在游戏启动后立即关闭启动器,崩溃检测、更改游戏标题等功能将失效。" & vbCrLf &
|
If MyMsgBox("若在游戏启动后立即关闭启动器,崩溃检测、更改游戏标题等功能将失效。" & vbCrLf &
|
||||||
"如果想保留这些功能,可以选择让启动器在游戏启动后隐藏,游戏退出后自动关闭。", "提示", "继续", "取消") = 2 Then
|
"如果想保留这些功能,可以选择让启动器在游戏启动后隐藏,游戏退出后自动关闭。", "提醒", "继续", "取消") = 2 Then
|
||||||
ComboArgumentVisibie.SelectedItem = e.RemovedItems(0)
|
ComboArgumentVisibie.SelectedItem = e.RemovedItems(0)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
'开启自动内存优化的警告
|
||||||
|
Private Sub CheckArgumentRam_Change() Handles CheckArgumentRam.Change
|
||||||
|
If AniControlEnabled <> 0 Then Exit Sub
|
||||||
|
If Not CheckArgumentRam.Checked Then Return
|
||||||
|
If MyMsgBox("内存优化耗时较长,这会拖慢游戏的启动过程,建议仅在电脑内存不充裕时开启此选项。" & vbCrLf &
|
||||||
|
"如果你在使用机械硬盘,这还可能会导致一小段时间的严重卡顿。" &
|
||||||
|
If(IsAdmin(), "", $"{vbCrLf}{vbCrLf}每次启动游戏,PCL 都需要申请管理员权限以进行内存优化。{vbCrLf}若想自动授予权限,可以右键 PCL,打开 属性 → 兼容性 → 以管理员身份运行此程序。"),
|
||||||
|
"提醒", "确定", "取消") = 2 Then
|
||||||
|
CheckArgumentRam.Checked = False
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
#Region "高级设置"
|
#Region "高级设置"
|
||||||
|
|||||||
@@ -126,23 +126,21 @@
|
|||||||
|
|
||||||
'滑动条
|
'滑动条
|
||||||
Private Sub SliderLoad()
|
Private Sub SliderLoad()
|
||||||
SliderDownloadThread.GetHintText = Function(Value As Integer)
|
SliderDownloadThread.GetHintText = Function(v) v + 1
|
||||||
Return Value + 1
|
SliderDownloadSpeed.GetHintText =
|
||||||
End Function
|
Function(v)
|
||||||
SliderDownloadSpeed.GetHintText = Function(Value As Integer)
|
Select Case v
|
||||||
If Value <= 14 Then
|
Case Is <= 14
|
||||||
Return (Value + 1) * 0.1 & " M/s"
|
Return (v + 1) * 0.1 & " M/s"
|
||||||
ElseIf Value <= 31 Then
|
Case Is <= 31
|
||||||
Return (Value - 11) * 0.5 & " M/s"
|
Return (v - 11) * 0.5 & " M/s"
|
||||||
ElseIf Value <= 41 Then
|
Case Is <= 41
|
||||||
Return (Value - 21) & " M/s"
|
Return (v - 21) & " M/s"
|
||||||
Else
|
Case Else
|
||||||
Return "无限制"
|
Return "无限制"
|
||||||
End If
|
End Select
|
||||||
End Function
|
End Function
|
||||||
SliderDebugAnim.GetHintText = Function(Value As Integer)
|
SliderDebugAnim.GetHintText = Function(v) If(v > 29, "关闭", (v / 10 + 0.1) & "x")
|
||||||
Return If(Value > 29, "关闭", (Value / 10 + 0.1) & "x")
|
|
||||||
End Function
|
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub SliderDownloadThread_PreviewChange(sender As Object, e As RouteEventArgs) Handles SliderDownloadThread.PreviewChange
|
Private Sub SliderDownloadThread_PreviewChange(sender As Object, e As RouteEventArgs) Handles SliderDownloadThread.PreviewChange
|
||||||
If SliderDownloadThread.Value < 100 Then Exit Sub
|
If SliderDownloadThread.Value < 100 Then Exit Sub
|
||||||
|
|||||||
@@ -177,7 +177,7 @@
|
|||||||
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
||||||
Try
|
Try
|
||||||
Dim Result = McModCheck(PageVersionLeft.Version, McModLoader.Output)
|
Dim Result = McModCheck(PageVersionLeft.Version, McModLoader.Output)
|
||||||
If Result.Count > 0 Then
|
If Result.Any Then
|
||||||
MyMsgBox(Join(Result, vbCrLf & vbCrLf), "Mod 检查结果")
|
MyMsgBox(Join(Result, vbCrLf & vbCrLf), "Mod 检查结果")
|
||||||
Else
|
Else
|
||||||
Hint("Mod 检查完成,未发现任何问题!", HintType.Finish)
|
Hint("Mod 检查完成,未发现任何问题!", HintType.Finish)
|
||||||
@@ -620,13 +620,13 @@
|
|||||||
If ModEntry.ModId IsNot Nothing Then
|
If ModEntry.ModId IsNot Nothing Then
|
||||||
DebugInfo.Add("Mod ID:" & ModEntry.ModId)
|
DebugInfo.Add("Mod ID:" & ModEntry.ModId)
|
||||||
End If
|
End If
|
||||||
If ModEntry.Dependencies.Count > 0 Then
|
If ModEntry.Dependencies.Any Then
|
||||||
DebugInfo.Add("依赖于:")
|
DebugInfo.Add("依赖于:")
|
||||||
For Each Dep In ModEntry.Dependencies
|
For Each Dep In ModEntry.Dependencies
|
||||||
DebugInfo.Add(" - " & Dep.Key & If(Dep.Value Is Nothing, "", ",版本:" & Dep.Value))
|
DebugInfo.Add(" - " & Dep.Key & If(Dep.Value Is Nothing, "", ",版本:" & Dep.Value))
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
If DebugInfo.Count > 0 Then
|
If DebugInfo.Any Then
|
||||||
ContentLines.Add("")
|
ContentLines.Add("")
|
||||||
ContentLines.AddRange(DebugInfo)
|
ContentLines.AddRange(DebugInfo)
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
If Indie = -1 Then
|
If Indie = -1 Then
|
||||||
Dim ModFolder As New DirectoryInfo(PageVersionLeft.Version.Path & "mods\")
|
Dim ModFolder As New DirectoryInfo(PageVersionLeft.Version.Path & "mods\")
|
||||||
Dim SaveFolder As New DirectoryInfo(PageVersionLeft.Version.Path & "saves\")
|
Dim SaveFolder As New DirectoryInfo(PageVersionLeft.Version.Path & "saves\")
|
||||||
If (ModFolder.Exists AndAlso ModFolder.EnumerateFiles.Count > 0) OrElse (SaveFolder.Exists AndAlso SaveFolder.EnumerateFiles.Count > 0) Then
|
If (ModFolder.Exists AndAlso ModFolder.EnumerateFiles.Any) OrElse (SaveFolder.Exists AndAlso SaveFolder.EnumerateFiles.Any) Then
|
||||||
'自动开启
|
'自动开启
|
||||||
Setup.Set("VersionArgumentIndie", 1, Version:=PageVersionLeft.Version)
|
Setup.Set("VersionArgumentIndie", 1, Version:=PageVersionLeft.Version)
|
||||||
Log("[Setup] 已自动开启单版本隔离:" & PageVersionLeft.Version.Name)
|
Log("[Setup] 已自动开启单版本隔离:" & PageVersionLeft.Version.Name)
|
||||||
@@ -438,7 +438,7 @@ PreFin:
|
|||||||
Log(ex, "更新版本设置 Java 下拉框失败", LogLevel.Feedback)
|
Log(ex, "更新版本设置 Java 下拉框失败", LogLevel.Feedback)
|
||||||
End Try
|
End Try
|
||||||
'更新选择项
|
'更新选择项
|
||||||
If SelectedItem Is Nothing AndAlso JavaList.Count > 0 Then
|
If SelectedItem Is Nothing AndAlso JavaList.Any Then
|
||||||
If SelectedBySetup = "" Then
|
If SelectedBySetup = "" Then
|
||||||
SelectedItem = ComboArgumentJava.Items(1) '选中 “自动选择”
|
SelectedItem = ComboArgumentJava.Items(1) '选中 “自动选择”
|
||||||
Else
|
Else
|
||||||
|
|||||||
Binary file not shown.
@@ -29,8 +29,8 @@
|
|||||||
<!-- Windows Vista -->
|
<!-- Windows Vista -->
|
||||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||||
|
|
||||||
<!-- Windows 7 -->
|
<!-- Windows 7 --><!--
|
||||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
||||||
|
|
||||||
<!-- Windows 8 -->
|
<!-- Windows 8 -->
|
||||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<!-- Windows 8.1 -->
|
<!-- Windows 8.1 -->
|
||||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
||||||
|
|
||||||
<!-- Windows 10 -->
|
<!-- Windows 10+ -->
|
||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|||||||
Reference in New Issue
Block a user