Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8bb82b033 | ||
|
|
7083b0f4f4 | ||
|
|
6ed0c6e4fe | ||
|
|
f678dfe853 | ||
|
|
b37c264e32 | ||
|
|
68f8b3eeac | ||
|
|
37354d15f7 | ||
|
|
38b3cefa89 | ||
|
|
bce8e71571 | ||
|
|
f300858ced | ||
|
|
bdcbab700e | ||
|
|
b8eb669351 | ||
|
|
b9d69a3258 | ||
|
|
e454f0c640 | ||
|
|
454c9ea377 | ||
|
|
4f258c8078 | ||
|
|
4b2e2d8eef | ||
|
|
1242d97a1c | ||
|
|
6225391afa | ||
|
|
b1a0e9a79d | ||
|
|
347bc8fb82 | ||
|
|
6bdf7e235a | ||
|
|
d7424d4d2b | ||
|
|
37561a842b | ||
|
|
e04e462737 | ||
|
|
ba262a1741 | ||
|
|
df11fa5a9d | ||
|
|
b6a52f90f6 | ||
|
|
531706e73b | ||
|
|
66a2406e0a | ||
|
|
6ec48abe77 | ||
|
|
9aecc1920a | ||
|
|
75cc86d2a2 | ||
|
|
8abf4707a1 | ||
|
|
b6cc6c10c3 | ||
|
|
5d16cf24bb | ||
|
|
05acfc6b51 | ||
|
|
2a46c9f5ce | ||
|
|
47585e5c9d | ||
|
|
114d9dd079 | ||
|
|
9aff4288b8 | ||
|
|
cb322b6fa0 | ||
|
|
6f1db2d079 | ||
|
|
07ac34dafe | ||
|
|
4638ed72f2 | ||
|
|
b04ee5f28f | ||
|
|
7756187dee | ||
|
|
6a10bd5406 | ||
|
|
134857b62f | ||
|
|
ade7bcff64 | ||
|
|
d599245369 | ||
|
|
70936254de | ||
|
|
564ee333aa | ||
|
|
4a2666a998 | ||
|
|
cadb9bb4a0 | ||
|
|
c2d20e422b | ||
|
|
3f8e64450a | ||
|
|
c5ae532fd5 | ||
|
|
fb1caf0c8f | ||
|
|
2ad1a6bae2 | ||
|
|
6de59a7f5b | ||
|
|
8d266c8a0b | ||
|
|
e1d58151cf | ||
|
|
7ba082c3f2 | ||
|
|
494e4f6516 | ||
|
|
0a9d115fd5 | ||
|
|
106be2fbaf | ||
|
|
ac9011a323 | ||
|
|
50112b70bd | ||
|
|
71d915f3ef | ||
|
|
e6c1b192ce | ||
|
|
788f7c9a96 | ||
|
|
e782d0ed2d | ||
|
|
a6aa7847c0 | ||
|
|
805a0e1544 | ||
|
|
94476384bd | ||
|
|
b1c01873b7 | ||
|
|
76bf3c40d0 | ||
|
|
d48ab143be | ||
|
|
fad37c9b46 | ||
|
|
ddb6ef9426 | ||
|
|
c9fb9b9eea | ||
|
|
d2620297ca | ||
|
|
2427fb7619 | ||
|
|
3af99aca0a | ||
|
|
8b0d9e5a5c |
No files matched your search
@@ -1,6 +1,6 @@
|
||||
name: "Minecraft 崩溃"
|
||||
description: "PCL 提示 “Minecraft 出现错误”,或游戏崩溃"
|
||||
labels: [· Bug, 新反馈]
|
||||
labels: [· Bug, 新提交]
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: "yml-1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "下载或登录时卡住或失败"
|
||||
description: "下载游戏、Mod 或整合包,或登录正版账号时出现问题"
|
||||
labels: [· Bug, 新反馈]
|
||||
labels: [· Bug, 新提交]
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: "yml-1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "综合 Bug 反馈"
|
||||
description: "遇见了没有细分选项的其他 Bug"
|
||||
labels: [· Bug, 新反馈]
|
||||
labels: [· Bug, 新提交]
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: "yml-1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "优化建议"
|
||||
description: "对已有功能的小幅度优化或改进建议"
|
||||
labels: [· 优化, 新反馈]
|
||||
labels: [· 优化, 新提交]
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: "yml-1"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 主页预设反馈
|
||||
url: https://github.com/Hex-Dragon/PCL2/discussions/categories/自定义主页
|
||||
about: 提交与预设的主页(设置 → 个性化 → 主页预设)中的具体内容相关的反馈
|
||||
- name: 帮助文档反馈
|
||||
url: https://github.com/LTCatt/PCL2Help/issues
|
||||
about: 提交与 PCL 帮助文档(更多 → 帮助)中的具体内容相关的反馈
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "新功能提案"
|
||||
description: "对已有功能的大幅度修改,或添加一个新内容或选项"
|
||||
labels: [· 新功能, 新反馈]
|
||||
labels: [· 新功能, 新提交]
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: "yml-1"
|
||||
|
||||
@@ -36,6 +36,13 @@ jobs:
|
||||
(gc "Plain Craft Launcher 2\Modules\ModSecret.vb") -replace 'Public Const OAuthClientId As String = ""', 'Public Const OAuthClientId As String = "${{ secrets.CLIENT_ID }}"' | Out-File "Plain Craft Launcher 2\Modules\ModSecret.vb"
|
||||
(gc "Plain Craft Launcher 2\Modules\ModSecret.vb") -replace 'Public Const CurseForgeAPIKey As String = ""', 'Public Const CurseForgeAPIKey As String = "${{ secrets.CURSEFORGE_API_KEY }}"' | Out-File "Plain Craft Launcher 2\Modules\ModSecret.vb"
|
||||
(gc "Plain Craft Launcher 2\Modules\Base\ModBase.vb") -replace 'Public Const CommitHash As String = ""', 'Public Const CommitHash As String = "${{ github.sha }}"' | Out-File "Plain Craft Launcher 2\Modules\Base\ModBase.vb"
|
||||
rm "Plain Craft Launcher 2\Resources\Help.zip"
|
||||
aria2c "--out=Plain Craft Launcher 2\Resources\Help.zip" "https://codeload.github.com/LTCatt/PCL2Help/zip/refs/heads/master"
|
||||
7z x "Plain Craft Launcher 2\Resources\Help.zip" -o"Plain Craft Launcher 2\Resources"
|
||||
rm "Plain Craft Launcher 2\Resources\Help.zip"
|
||||
rm "Plain Craft Launcher 2\Resources\PCL2Help-master\*.*"
|
||||
7z a "Plain Craft Launcher 2\Resources\Help.zip" ".\Plain Craft Launcher 2\Resources\PCL2Help-master\*"
|
||||
rm "Plain Craft Launcher 2\Resources\PCL2Help-master\" -Recurse
|
||||
- name: Build
|
||||
run: msbuild "Plain Craft Launcher 2\Plain Craft Launcher 2.vbproj" -p:Configuration=${{ matrix.configuration }}
|
||||
- name: Upload a Build Artifact
|
||||
|
||||
@@ -2,24 +2,25 @@
|
||||
|
||||
一、承诺与声明。
|
||||
|
||||
开发者承诺,在您遵守本指南的情况下,不会追究您的责任,但最终裁量权仍由开发者保留。
|
||||
开发者承诺,在您遵守本指南且善意使用的情况下,不会追究您的责任,但最终裁量权仍由开发者保留。
|
||||
法律上,开发者仍保留所有权利(All Rights Reserved),且可能随时修改本指南,本指南并不是永久性保证。
|
||||
|
||||
二、少量使用情形。
|
||||
|
||||
如果您仅合理使用本存储库中的少量内容,或是参考实现思路,您必须:
|
||||
1、给出适当的署名,且提供指向本存储库的链接。
|
||||
1、给出适当的署名,且提供指向本存储库的链接。GitHub 上的 Fork 可视为满足此条。
|
||||
2、不得以任何方式暗示开发者为您或您的使用作担保。
|
||||
|
||||
三、大量使用情形。
|
||||
|
||||
如果您基于该存储库创作衍生作品,或合理使用了本存储库中的较大量内容,您必须:
|
||||
1、给出适当的署名,且提供指向本存储库的链接。GitHub 上的 Fork 可视为满足此条。
|
||||
2、不得以任何方式暗示开发者为您或您的使用作担保,且需要给出适当的说明,表示这是非官方内容。
|
||||
3、使用本指南文件作为协议,不得附加额外条款。
|
||||
4、该衍生作品不能被允许用于再次分发。包括但不限于用于制作整合包。
|
||||
5、该衍生作品的名称必须以 “PCL” 或 “Plain Craft Launcher” 开头,并在其后添加后缀,例如 “PCL 启动修复版”、“PCL PR Collection”。
|
||||
6、该衍生作品不得包含 PCL 的赞助功能,或是其他作用相似的功能。包括但不限于主题功能、回声洞投稿功能等。
|
||||
2、不得以任何方式暗示开发者为您或您的使用作担保。
|
||||
3、给出适当的说明,以明确表示该衍生作品是非官方内容。
|
||||
4、使用本指南文件作为协议,不得附加额外条款。
|
||||
5、该衍生作品的名称必须以 “PCL” 或 “Plain Craft Launcher” 开头,并在其后添加后缀。例如 “PCL 整合包优化版”、“PCL PR Collection”。
|
||||
6、该衍生作品不得包含 PCL 的赞助解锁功能,或与其用途相近的功能。包括但不限于:主题切换(自定义软件颜色/皮肤)、回声洞投稿等。
|
||||
7、以善意目的进行合理使用,不要用 PCL 来干坏事、恰烂钱、整烂活。开发者可能会将撤销所有授权作为最终手段。
|
||||
|
||||
————————————
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Public Class Application
|
||||
'内存优化
|
||||
Dim Ram = My.Computer.Info.AvailablePhysicalMemory
|
||||
Try
|
||||
PageOtherTest.MemoryOptimizeInternal()
|
||||
PageOtherTest.MemoryOptimizeInternal(False)
|
||||
Catch ex As Exception
|
||||
MsgBox(ex.Message, MsgBoxStyle.Critical, "内存优化失败")
|
||||
Environment.Exit(-1)
|
||||
@@ -72,9 +72,17 @@ Public Class Application
|
||||
Directory.CreateDirectory(PathAppdata)
|
||||
'检测单例
|
||||
#If Not DEBUG Then
|
||||
Dim ShouldWaitForExit As Boolean = e.Args.Length > 0 AndAlso e.Args(0) = "--wait" '要求等待已有的 PCL 退出
|
||||
Dim WaitRetryCount As Integer = 0
|
||||
WaitRetry:
|
||||
Dim WindowHwnd As IntPtr = FindWindow(Nothing, "Plain Craft Launcher ")
|
||||
If WindowHwnd = IntPtr.Zero Then FindWindow(Nothing, "Plain Craft Launcher 2 ")
|
||||
If WindowHwnd <> IntPtr.Zero Then
|
||||
If ShouldWaitForExit AndAlso WaitRetryCount < 20 Then '至多等待 10 秒
|
||||
WaitRetryCount += 1
|
||||
Thread.Sleep(500)
|
||||
GoTo WaitRetry
|
||||
End If
|
||||
'将已有的 PCL 窗口拖出来
|
||||
ShowWindowToTop(WindowHwnd)
|
||||
'播放提示音并退出
|
||||
@@ -102,11 +110,11 @@ Public Class Application
|
||||
Log($"[Start] 程序版本:{VersionDisplayName} ({VersionCode}{If(CommitHash = "", "", $",#{CommitHash}")})")
|
||||
Log($"[Start] 识别码:{UniqueAddress}{If(ThemeCheckOne(9), ",已解锁反馈主题", "")}")
|
||||
Log($"[Start] 程序路径:{PathWithName}")
|
||||
Log($"[Start] 系统编码:{Encoding.Default} ({Encoding.Default.CodePage}, GBK={IsGBKEncoding})")
|
||||
Log($"[Start] 系统编码:{Encoding.Default.HeaderName} ({Encoding.Default.CodePage}, GBK={IsGBKEncoding})")
|
||||
Log($"[Start] 管理员权限:{IsAdmin()}")
|
||||
'检测异常环境
|
||||
If Path.Contains(IO.Path.GetTempPath()) OrElse Path.Contains("AppData\Local\Temp\") Then
|
||||
MyMsgBox("请将 PCL 从压缩文件中解压,或是更换文件夹后再继续使用!" & vbCrLf & "程序目前在临时文件夹中运行,设置、游戏存档等可能无法保存,且部分功能将无法使用。", "环境警告", "我知道了", IsWarn:=True)
|
||||
MyMsgBox("请将 PCL 从压缩包中解压之后再使用!" & vbCrLf & "在当前环境下运行可能会导致丢失游戏存档或设置,部分功能也可能无法使用!", "环境警告", "我知道了", IsWarn:=True)
|
||||
End If
|
||||
If Is32BitSystem Then
|
||||
MyMsgBox("PCL 和新版 Minecraft 均不再支持 32 位系统,部分功能将无法使用。" & vbCrLf & "非常建议重装为 64 位系统后再进行游戏!", "环境警告", "我知道了", IsWarn:=True)
|
||||
@@ -162,7 +170,7 @@ Public Class Application
|
||||
ExceptionString.Contains(".NET Framework") OrElse ' “自动错误判断” 的结果分析
|
||||
ExceptionString.Contains("未能加载文件或程序集") Then
|
||||
OpenWebsite("https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/thank-you/net462-offline-installer")
|
||||
MsgBox("你的 .NET Framework 版本过低或损坏,请在打开的网页中重新下载并安装 .NET Framework 4.6.2 后重试!", MsgBoxStyle.Information, "运行环境错误")
|
||||
MsgBox("你的 .NET Framework 版本过低或损坏,请下载并重新安装 .NET Framework 4.6.2!", MsgBoxStyle.Information, "运行环境错误")
|
||||
FormMain.EndProgramForce(Result.Cancel)
|
||||
Else
|
||||
FeedbackInfo()
|
||||
@@ -210,8 +218,8 @@ Public Class Application
|
||||
If AssemblyImazenWebp Is Nothing Then
|
||||
Log("[Start] 加载 DLL:Imazen.WebP")
|
||||
AssemblyImazenWebp = Assembly.Load(GetResources("Imazen_WebP"))
|
||||
SetDllDirectory(PathTemp)
|
||||
File.WriteAllBytes(PathTemp & "libwebp.dll", GetResources("libwebp64"))
|
||||
SetDllDirectory(PathPure.TrimEnd("\"))
|
||||
WriteFile(PathPure & "libwebp.dll", GetResources("libwebp64"))
|
||||
End If
|
||||
Return AssemblyImazenWebp
|
||||
End SyncLock
|
||||
|
||||
@@ -293,26 +293,28 @@
|
||||
Public Const SwapedHeight As Integer = 40
|
||||
Private Sub MyCard_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
|
||||
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
||||
If Not IsSwaped AndAlso (IsNothing(SwapControl) OrElse Pos > SwapedHeight OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Exit Sub '检测点击位置;或已经不在可视树上的误判
|
||||
If Not IsSwaped AndAlso
|
||||
(SwapControl Is Nothing OrElse Pos > SwapedHeight OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Exit Sub '检测点击位置;或已经不在可视树上的误判
|
||||
IsMouseDown = True
|
||||
End Sub
|
||||
Private Sub MyCard_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
|
||||
If IsMouseDown Then
|
||||
If Not IsMouseDown Then Return
|
||||
IsMouseDown = False
|
||||
|
||||
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
||||
If Not IsSwaped AndAlso
|
||||
(SwapControl Is Nothing OrElse Pos > SwapedHeight OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Exit Sub '检测点击位置;或已经不在可视树上的误判
|
||||
|
||||
Dim ee = New RouteEventArgs(True)
|
||||
RaiseEvent PreviewSwap(Me, ee)
|
||||
If ee.Handled Then
|
||||
IsMouseDown = False
|
||||
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
||||
If Not IsSwaped AndAlso (IsNothing(SwapControl) OrElse Pos > SwapedHeight OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Exit Sub '检测点击位置;或已经不在可视树上的误判
|
||||
|
||||
Dim ee = New RouteEventArgs(True)
|
||||
RaiseEvent PreviewSwap(Me, ee)
|
||||
If ee.Handled Then
|
||||
IsMouseDown = False
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
IsSwaped = Not IsSwaped
|
||||
Log("[Control] " & If(IsSwaped, "折叠卡片", "展开卡片") & If(Title Is Nothing, "", ":" & Title))
|
||||
RaiseEvent Swap(Me, ee)
|
||||
Return
|
||||
End If
|
||||
|
||||
IsSwaped = Not IsSwaped
|
||||
Log("[Control] " & If(IsSwaped, "折叠卡片", "展开卡片") & If(Title Is Nothing, "", ":" & Title))
|
||||
RaiseEvent Swap(Me, ee)
|
||||
End Sub
|
||||
Private Sub MyCard_MouseLeave_Swap(sender As Object, e As MouseEventArgs) Handles Me.MouseLeave
|
||||
IsMouseDown = False
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
Public Class MyImage
|
||||
Inherits Image
|
||||
|
||||
#Region "公开属性"
|
||||
|
||||
''' <summary>
|
||||
''' 网络图片的缓存有效期。
|
||||
''' 在这个时间后,才会重新尝试下载图片。
|
||||
''' </summary>
|
||||
Public FileCacheExpiredTime As New TimeSpan(7, 0, 0, 0) '7 天
|
||||
|
||||
''' <summary>
|
||||
''' 是否允许将网络图片存储到本地用作缓存。
|
||||
''' </summary>
|
||||
Public Property EnableCache As Boolean
|
||||
Get
|
||||
Return GetValue(EnableCacheProperty)
|
||||
End Get
|
||||
Set(value As Boolean)
|
||||
SetValue(EnableCacheProperty, value)
|
||||
End Set
|
||||
End Property
|
||||
Public Shared Shadows ReadOnly EnableCacheProperty As DependencyProperty = DependencyProperty.Register(
|
||||
"EnableCache", GetType(Boolean), GetType(MyImage), New PropertyMetadata(True))
|
||||
|
||||
''' <summary>
|
||||
''' 与 Image 的 Source 类似。
|
||||
''' 若输入以 http 开头的字符串,则会尝试下载图片然后显示,图片会保存为本地缓存。
|
||||
''' 支持 WebP 格式的图片。
|
||||
''' </summary>
|
||||
Public Shadows Property Source As String '覆写 Image 的 Source 属性
|
||||
Get
|
||||
Return _Source
|
||||
End Get
|
||||
Set(value As String)
|
||||
If value = "" Then value = Nothing
|
||||
If _Source = value Then Exit Property
|
||||
_Source = value
|
||||
If Not IsInitialized Then Exit Property '属性读取顺序修正:在完成 XAML 属性读取后再触发图片加载(#4868)
|
||||
Load()
|
||||
End Set
|
||||
End Property
|
||||
Private _Source As String = ""
|
||||
Public Shared Shadows ReadOnly SourceProperty As DependencyProperty = DependencyProperty.Register(
|
||||
"Source", GetType(String), GetType(MyImage), New PropertyMetadata(New PropertyChangedCallback(
|
||||
Sub(sender, e) If sender IsNot Nothing Then CType(sender, MyImage).Source = e.NewValue.ToString())))
|
||||
|
||||
''' <summary>
|
||||
''' 当 Source 首次下载失败时,会从该备用地址加载图片。
|
||||
''' </summary>
|
||||
Public Property FallbackSource As String
|
||||
Get
|
||||
Return _FallbackSource
|
||||
End Get
|
||||
Set(value As String)
|
||||
_FallbackSource = value
|
||||
End Set
|
||||
End Property
|
||||
Private _FallbackSource As String = Nothing
|
||||
|
||||
''' <summary>
|
||||
''' 正在下载网络图片时显示的本地图片。
|
||||
''' </summary>
|
||||
Public Property LoadingSource As String
|
||||
Get
|
||||
Return _LoadingSource
|
||||
End Get
|
||||
Set(value As String)
|
||||
_LoadingSource = value
|
||||
End Set
|
||||
End Property
|
||||
Private _LoadingSource As String = "pack://application:,,,/images/Icons/NoIcon.png"
|
||||
|
||||
#End Region
|
||||
|
||||
''' <summary>
|
||||
''' 实际被呈现的图片地址。
|
||||
''' </summary>
|
||||
Public Property ActualSource As String
|
||||
Get
|
||||
Return _ActualSource
|
||||
End Get
|
||||
Set(value As String)
|
||||
If value = "" Then value = Nothing
|
||||
If _ActualSource = value Then Exit Property
|
||||
_ActualSource = value
|
||||
Try
|
||||
Dim Bitmap As MyBitmap = If(value Is Nothing, Nothing, New MyBitmap(value)) '在这里先触发可能的文件读取,尽量避免在 UI 线程中读取文件
|
||||
RunInUiWait(Sub() MyBase.Source = Bitmap)
|
||||
Catch ex As Exception
|
||||
Log(ex, $"加载图片失败({value})")
|
||||
Try
|
||||
If value.StartsWithF(PathTemp) AndAlso File.Exists(value) Then File.Delete(value)
|
||||
Catch
|
||||
End Try
|
||||
End Try
|
||||
End Set
|
||||
End Property
|
||||
Private _ActualSource As String = Nothing
|
||||
|
||||
Private Sub Load() _
|
||||
Handles Me.Initialized '属性读取顺序修正:在完成 XAML 属性读取后再触发图片加载(#4868)
|
||||
'空
|
||||
If Source Is Nothing Then
|
||||
ActualSource = Nothing
|
||||
Exit Sub
|
||||
End If
|
||||
'本地图片
|
||||
If Not Source.StartsWithF("http") Then
|
||||
ActualSource = Source
|
||||
Exit Sub
|
||||
End If
|
||||
'从缓存加载网络图片
|
||||
Dim Url As String = Source
|
||||
Dim Retried As Boolean = False
|
||||
Dim TempPath As String = GetTempPath(Url)
|
||||
Dim TempFile As New FileInfo(TempPath)
|
||||
Dim EnableCache As Boolean = Me.EnableCache
|
||||
If EnableCache AndAlso TempFile.Exists Then
|
||||
ActualSource = TempPath
|
||||
If (Date.Now - TempFile.LastWriteTime) < FileCacheExpiredTime Then Exit Sub '无需刷新缓存
|
||||
End If
|
||||
RunInNewThread(
|
||||
Sub()
|
||||
Dim TempDownloadingPath As String = Nothing
|
||||
Try
|
||||
RetryStart:
|
||||
'下载
|
||||
ActualSource = LoadingSource '显示加载中图片
|
||||
TempDownloadingPath = TempPath & RandomInteger(0, 10000000)
|
||||
Directory.CreateDirectory(GetPathFromFullPath(TempPath)) '重新实现下载,以避免携带 Header(#5072)
|
||||
Using Client As New Net.WebClient
|
||||
Client.DownloadFile(Url, TempDownloadingPath)
|
||||
End Using
|
||||
If Url <> Source AndAlso Url <> FallbackSource Then
|
||||
'已经更换了地址
|
||||
File.Delete(TempDownloadingPath)
|
||||
ElseIf EnableCache Then
|
||||
'保存缓存并显示
|
||||
If File.Exists(TempPath) Then File.Delete(TempPath)
|
||||
Rename(TempDownloadingPath, TempPath)
|
||||
RunInUi(Sub() ActualSource = TempPath)
|
||||
Else
|
||||
'直接显示
|
||||
RunInUiWait(Sub() ActualSource = TempDownloadingPath)
|
||||
File.Delete(TempDownloadingPath)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Try
|
||||
If TempPath IsNot Nothing Then File.Delete(TempPath)
|
||||
If TempDownloadingPath IsNot Nothing Then File.Delete(TempDownloadingPath)
|
||||
Catch
|
||||
End Try
|
||||
If Not Retried Then
|
||||
'更换备用地址
|
||||
Log(ex, $"下载图片可重试地失败({Url})", LogLevel.Developer)
|
||||
Retried = True
|
||||
Url = If(FallbackSource, Source)
|
||||
'空
|
||||
If Url Is Nothing Then
|
||||
ActualSource = Nothing
|
||||
Exit Sub
|
||||
End If
|
||||
'本地图片
|
||||
If Not Url.StartsWithF("http") Then
|
||||
ActualSource = Url
|
||||
Exit Sub
|
||||
End If
|
||||
'从缓存加载网络图片
|
||||
TempPath = GetTempPath(Url)
|
||||
TempFile = New FileInfo(TempPath)
|
||||
If EnableCache AndAlso TempFile.Exists() Then
|
||||
ActualSource = TempPath
|
||||
If (Date.Now - TempFile.CreationTime) < FileCacheExpiredTime Then Exit Sub '无需刷新缓存
|
||||
End If
|
||||
'下载
|
||||
If Source = Url Then Thread.Sleep(1000) '延迟 1s 重试
|
||||
GoTo RetryStart
|
||||
Else
|
||||
Log(ex, $"下载图片失败({Url})", LogLevel.Hint)
|
||||
End If
|
||||
End Try
|
||||
End Sub, "MyImage PicLoader " & GetUuid() & "#", ThreadPriority.BelowNormal)
|
||||
End Sub
|
||||
Public Shared Function GetTempPath(Url As String) As String
|
||||
Return $"{PathTemp}MyImage\{GetHash(Url)}.png"
|
||||
End Function
|
||||
|
||||
End Class
|
||||
@@ -212,33 +212,26 @@
|
||||
If Not _Logo = "" Then
|
||||
If _Logo.StartsWithF("http", True) Then
|
||||
'网络图片
|
||||
PathLogo = New Image With {
|
||||
PathLogo = New MyImage With {
|
||||
.Tag = Me,
|
||||
.IsHitTestVisible = LogoClickable,
|
||||
.Source = New ImageSourceConverter().ConvertFromString(_Logo),
|
||||
.Source = _Logo,
|
||||
.RenderTransformOrigin = New Point(0.5, 0.5),
|
||||
.RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale},
|
||||
.SnapsToDevicePixels = True, .UseLayoutRounding = False}
|
||||
RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.Linear)
|
||||
ElseIf _Logo.EndsWithF(".png", True) OrElse _Logo.EndsWithF(".jpg", True) Then
|
||||
ElseIf _Logo.EndsWithF(".png", True) OrElse _Logo.EndsWithF(".jpg", True) OrElse _Logo.EndsWithF(".webp", True) Then
|
||||
'位图
|
||||
Dim Bitmap = New MyBitmap(_Logo)
|
||||
PathLogo = New Canvas With {
|
||||
.Tag = Me,
|
||||
.IsHitTestVisible = LogoClickable,
|
||||
.Background = Bitmap,
|
||||
.Background = New MyBitmap(_Logo),
|
||||
.RenderTransformOrigin = New Point(0.5, 0.5),
|
||||
.RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale},
|
||||
.SnapsToDevicePixels = True, .UseLayoutRounding = False}
|
||||
'If Bitmap.Pic.Width = 16 AndAlso Bitmap.Pic.Height = 16 Then
|
||||
' '使用最适合 16x16 物品图片显示的大小
|
||||
' RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.NearestNeighbor)
|
||||
' PathLogo.HorizontalAlignment = HorizontalAlignment.Center : PathLogo.VerticalAlignment = VerticalAlignment.Center
|
||||
' PathLogo.Width = GetWPFSize(Math.Floor(GetPixelSize(32) / 16) * 16) : PathLogo.Height = PathLogo.Width
|
||||
'Else
|
||||
PathLogo.HorizontalAlignment = HorizontalAlignment.Stretch : PathLogo.VerticalAlignment = VerticalAlignment.Stretch
|
||||
RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.HighQuality)
|
||||
'End If
|
||||
.SnapsToDevicePixels = True, .UseLayoutRounding = False,
|
||||
.HorizontalAlignment = HorizontalAlignment.Stretch, .VerticalAlignment = VerticalAlignment.Stretch
|
||||
}
|
||||
RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.Linear)
|
||||
Else
|
||||
'矢量图
|
||||
PathLogo = New Shapes.Path With {
|
||||
@@ -327,8 +320,8 @@
|
||||
Private Sub OnSizeChanged() Handles Me.SizeChanged
|
||||
ColumnCheck.Width = New GridLength(If(_Type = CheckType.None OrElse _Type = CheckType.Clickable, If(Height < 40, 4, 2), 6))
|
||||
ColumnLogo.Width = New GridLength(If(_Logo = "", 0, 34) + If(Height < 40, 0, 4))
|
||||
If Not IsNothing(PathLogo) Then
|
||||
If _Logo.EndsWithF(".png", True) Then
|
||||
If PathLogo IsNot Nothing Then
|
||||
If _Logo.EndsWithF(".png", True) OrElse _Logo.EndsWithF(".jpg", True) OrElse _Logo.EndsWithF(".webp", True) Then
|
||||
PathLogo.Margin = New Thickness(4, 5, 3, 5)
|
||||
Else
|
||||
PathLogo.Margin = New Thickness(If(Height < 40, 6, 8), 8, If(Height < 40, 4, 6), 8)
|
||||
@@ -661,6 +654,8 @@
|
||||
Dim Unused = New HelpEntry(GetEventAbsoluteUrls(EventData, EventType)(0)).SetToListItem(Me)
|
||||
Catch ex As Exception
|
||||
Log(ex, "设置帮助 MyListItem 失败", LogLevel.Msgbox)
|
||||
EventType = Nothing
|
||||
EventData = Nothing
|
||||
End Try
|
||||
End If
|
||||
End Sub
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" Foreground="{DynamicResource ColorBrush2}" HorizontalAlignment="Left" Name="LabTitle" Margin="7,-1,70,9" Text="测试标题文本" VerticalAlignment="Top" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
<Rectangle x:Name="ShapeLine" Grid.Row="1" Height="2" Fill="{Binding Foreground, ElementName=LabTitle}" />
|
||||
<my:MyScrollViewer Grid.Row="3" VerticalAlignment="Top" x:Name="PanText" Margin="0,0,0,7" Padding="7,0,15,0"
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMuity="0.7">
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMult="0.7">
|
||||
<TextBlock VerticalAlignment="Top" TextTrimming="None" TextWrapping="Wrap" Name="LabText" FontSize="15" LineHeight="18"
|
||||
Foreground="#FF5C5C5C" FontWeight="Normal" Padding="1" />
|
||||
</my:MyScrollViewer>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" Foreground="{DynamicResource ColorBrush2}" HorizontalAlignment="Left" Name="LabTitle" Margin="7,-1,70,9" Text="测试标题文本" VerticalAlignment="Top" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
<Rectangle x:Name="ShapeLine" Grid.Row="1" Height="2" Fill="{Binding Foreground, ElementName=LabTitle}" />
|
||||
<my:MyScrollViewer Grid.Row="3" VerticalAlignment="Top" x:Name="PanCaption" Margin="0,0,0,17" Padding="7,0,15,0"
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMuity="0.7">
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMult="0.7">
|
||||
<StackPanel x:Name="PanSelection" Orientation="Vertical" />
|
||||
</my:MyScrollViewer>
|
||||
<StackPanel Grid.Row="4" Name="PanBtn" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="150,0,8,0" Orientation="Horizontal">
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" Foreground="{DynamicResource ColorBrush2}" HorizontalAlignment="Left" Name="LabTitle" Margin="7,-1,70,9" Text="测试标题文本" VerticalAlignment="Top" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
<Rectangle x:Name="ShapeLine" Grid.Row="1" Height="2" Fill="{Binding Foreground, ElementName=LabTitle}" />
|
||||
<my:MyScrollViewer Grid.Row="3" VerticalAlignment="Top" x:Name="PanCaption" Margin="0,0,0,17" Padding="7,0,15,0"
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMuity="0.7">
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMult="0.7">
|
||||
<TextBlock VerticalAlignment="Top" TextTrimming="None" TextWrapping="Wrap" Name="LabCaption" FontSize="15" LineHeight="18"
|
||||
Foreground="#FF5C5C5C" FontWeight="Normal" Padding="1" />
|
||||
</my:MyScrollViewer>
|
||||
|
||||
@@ -104,3 +104,7 @@
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
Public Interface IRefreshable
|
||||
Sub Refresh()
|
||||
End Interface
|
||||
@@ -157,9 +157,7 @@
|
||||
End Set
|
||||
End Property '内容
|
||||
Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register("Text", GetType(String), GetType(MyRadioBox), New PropertyMetadata(New PropertyChangedCallback(
|
||||
Sub(sender As DependencyObject, e As DependencyPropertyChangedEventArgs)
|
||||
If Not IsNothing(sender) Then CType(sender, MyRadioBox).LabText.Text = e.NewValue
|
||||
End Sub)))
|
||||
Sub(sender, e) If sender IsNot Nothing Then CType(sender, MyRadioBox).LabText.Text = e.NewValue)))
|
||||
|
||||
'点击事件
|
||||
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center" Background="{StaticResource ColorBrushSemiTransparent}" CornerRadius="13.5" MinHeight="27" MaxHeight="27">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path x:Name="ShapeLogo" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5" Margin="12,0,0,0" Stretch="Uniform" Fill="White" MaxHeight="16" MaxWidth="16" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="LabText" VerticalAlignment="Center" Grid.Column="1" Foreground="White" Margin="8,0,12,1" Grid.ColumnSpan="2" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
<TextBlock x:Name="LabText" VerticalAlignment="Center" Grid.Column="1" Foreground="White" Margin="8,0,12,0" Grid.ColumnSpan="2" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
@@ -117,9 +117,7 @@
|
||||
End Set
|
||||
End Property '内容
|
||||
Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register("Text", GetType(String), GetType(MyRadioButton), New PropertyMetadata(New PropertyChangedCallback(
|
||||
Sub(sender As DependencyObject, e As DependencyPropertyChangedEventArgs)
|
||||
If Not IsNothing(sender) Then CType(sender, MyRadioButton).LabText.Text = e.NewValue
|
||||
End Sub)))
|
||||
Sub(sender, e) If sender IsNot Nothing Then CType(sender, MyRadioButton).LabText.Text = e.NewValue)))
|
||||
Public Enum ColorState
|
||||
White
|
||||
Highlight
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Public Class MyScrollViewer
|
||||
Inherits ScrollViewer
|
||||
|
||||
Public Property DeltaMuity As Double = 1
|
||||
Public Property DeltaMult As Double = 1
|
||||
|
||||
|
||||
Private RealOffset As Double
|
||||
@@ -25,10 +25,12 @@
|
||||
Next
|
||||
End Sub
|
||||
Public Sub PerformVerticalOffsetDelta(Delta As Double)
|
||||
AniStart(AaDouble(Sub(AnimDelta As Double)
|
||||
RealOffset = MathClamp(RealOffset + AnimDelta, 0, ExtentHeight - ActualHeight)
|
||||
ScrollToVerticalOffset(RealOffset)
|
||||
End Sub, Delta * DeltaMuity, 300,, New AniEaseOutFluent(6)))
|
||||
AniStart(
|
||||
AaDouble(
|
||||
Sub(AnimDelta As Double)
|
||||
RealOffset = MathClamp(RealOffset + AnimDelta, 0, ExtentHeight - ActualHeight)
|
||||
ScrollToVerticalOffset(RealOffset)
|
||||
End Sub, Delta * DeltaMult, 300,, New AniEaseOutFluent(6)))
|
||||
End Sub
|
||||
Private Sub MyScrollViewer_ScrollChanged(sender As Object, e As ScrollChangedEventArgs) Handles Me.ScrollChanged
|
||||
RealOffset = VerticalOffset
|
||||
@@ -43,4 +45,7 @@
|
||||
ScrollBar = GetTemplateChild("PART_VerticalScrollBar")
|
||||
End Sub
|
||||
|
||||
Private Sub MyScrollViewer_PreviewGotKeyboardFocus(sender As Object, e As KeyboardFocusChangedEventArgs) Handles Me.PreviewGotKeyboardFocus
|
||||
If e.NewFocus IsNot Nothing AndAlso TypeOf e.NewFocus Is MySlider Then e.Handled = True '#3854,阻止获得焦点时自动滚动
|
||||
End Sub
|
||||
End Class
|
||||
@@ -90,21 +90,21 @@
|
||||
Get
|
||||
Return GetValue(EventTypeProperty)
|
||||
End Get
|
||||
|
||||
Set(value As String)
|
||||
SetValue(EventTypeProperty, value)
|
||||
End Set
|
||||
End Property
|
||||
Public Shared ReadOnly EventTypeProperty As DependencyProperty = DependencyProperty.Register("EventType", GetType(String), GetType(MyTextButton), New PropertyMetadata(Nothing))
|
||||
Public Shared ReadOnly EventTypeProperty As DependencyProperty = DependencyProperty.Register(
|
||||
"EventType", GetType(String), GetType(MyTextButton), New PropertyMetadata(Nothing))
|
||||
Public Property EventData As String
|
||||
Get
|
||||
Return GetValue(EventDataProperty)
|
||||
End Get
|
||||
|
||||
Set(value As String)
|
||||
SetValue(EventDataProperty, value)
|
||||
End Set
|
||||
End Property
|
||||
Public Shared ReadOnly EventDataProperty As DependencyProperty = DependencyProperty.Register("EventData", GetType(String), GetType(MyTextButton), New PropertyMetadata(Nothing))
|
||||
Public Shared ReadOnly EventDataProperty As DependencyProperty = DependencyProperty.Register(
|
||||
"EventData", GetType(String), GetType(MyTextButton), New PropertyMetadata(Nothing))
|
||||
|
||||
End Class
|
||||
@@ -104,7 +104,7 @@
|
||||
<GradientStop Color="{StaticResource ColorObject3}" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Grid.Background>
|
||||
<Image x:Name="ImgTitle" IsHitTestVisible="False" Stretch="UniformToFill" IsEnabled="False" RenderOptions.BitmapScalingMode="LowQuality" />
|
||||
<local:MyImage x:Name="ImgTitle" IsHitTestVisible="False" Stretch="UniformToFill" IsEnabled="False" RenderOptions.BitmapScalingMode="LowQuality" />
|
||||
<local:MyIconButton x:Name="BtnTitleClose" HorizontalAlignment="Right" Height="28" VerticalAlignment="Center" Width="28" Margin="0,0,12,0" Theme="White"
|
||||
LogoScale="0.72" Logo="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<local:MyIconButton x:Name="BtnTitleMin" HorizontalAlignment="Right" Height="28" VerticalAlignment="Center" Width="28" Margin="0,0,44,0" Theme="White"
|
||||
@@ -117,7 +117,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<Path x:Name="ShapeTitleLogo" Data="M26,29 v-25 h5 a7,7 180 0 1 0,14 h-5 M61,6.5 a10,11.5 180 1 0 0,18 M68,2.5 v24.5 h12 M98,2 v27 M107,2 v27" SnapsToDevicePixels="False" UseLayoutRounding="False" IsHitTestVisible="False" HorizontalAlignment="Left" Margin="19,15.5,0,15.5" Stretch="fill" Stroke="White" StrokeThickness="1.9" Width="53" />
|
||||
<TextBlock x:Name="LabTitleLogo" Visibility="Collapsed" SnapsToDevicePixels="False" UseLayoutRounding="False" IsHitTestVisible="False" HorizontalAlignment="Left" Margin="18,0,0,0" Foreground="White" FontSize="17" VerticalAlignment="Center" />
|
||||
<Image x:Name="ImageTitleLogo" SnapsToDevicePixels="False" UseLayoutRounding="False" IsHitTestVisible="False" HorizontalAlignment="Left" Margin="7" VerticalAlignment="Center" Visibility="Collapsed" />
|
||||
<local:MyImage x:Name="ImageTitleLogo" SnapsToDevicePixels="False" UseLayoutRounding="False" IsHitTestVisible="False" HorizontalAlignment="Left" Margin="7" VerticalAlignment="Center" Visibility="Collapsed" />
|
||||
<StackPanel Grid.Column="1" x:Name="PanTitleSelect" HorizontalAlignment="Left" Height="27" VerticalAlignment="Center" Orientation="Horizontal" Margin="13,0">
|
||||
<local:MyRadioButton x:Name="BtnTitleSelect0" Text="{DynamicResource LangTitleHome}" Tag="0" Margin="5,0" Checked="True" Padding="2,0"
|
||||
LogoScale="0.95" Logo="M985.403 552.96C985.403 812.702 773.041 1024 512 1024S38.597 812.702 38.597 552.96c0-158.208 79.163-304.955 211.771-392.625 31.074-20.52 72.94-11.973 93.46 19.101s12.012 72.94-19.062 93.46c-94.681 62.622-151.237 167.306-151.237 280.064 0 185.344 151.788 336.108 338.471 336.108S850.471 738.304 850.471 552.96c0-114.649-57.974-220.278-155.096-282.585-31.35-20.125-40.448-61.833-20.362-93.184s61.794-40.448 93.184-20.4c135.995 87.236 217.206 235.362 217.206 396.169zM512 560.128c37.258 0 67.466-30.208 67.466-67.466V67.466C579.466 30.208 549.258 0 512 0s-67.466 30.208-67.466 67.466v425.196c0 37.258 30.208 67.466 67.466 67.466z" />
|
||||
|
||||
@@ -10,6 +10,34 @@ Public Class FormMain
|
||||
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
||||
'统计更新日志条目
|
||||
#If BETA Then
|
||||
If LastVersion < 347 Then 'Release 2.8.12
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 管理页面添加下载 Mod、安装 Mod 选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 详情页面支持按加载器、游戏版本进行分类和筛选"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持安装同时包含 modpack 文件和启动器的懒人包"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化整合包导入流程"))
|
||||
FeatureCount += 43
|
||||
BugCount += 37
|
||||
End If
|
||||
If LastVersion < 342 Then 'Release 2.8.9
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持下载原版服务端"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "本地 Mod 的标题支持选择显示 Mod 原始文件名"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复搜索后启用/禁用 Mod 时出错的 Bug"))
|
||||
FeatureCount += 17
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 340 Then 'Release 2.8.8
|
||||
If LastVersion = 338 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复数个与新正版登录相关的严重 Bug"))
|
||||
FeatureCount += 3
|
||||
BugCount += 7
|
||||
End If
|
||||
If LastVersion < 338 Then 'Release 2.8.7
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "使用新的正版登录方式,以提高安全性"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化安装整合包、检索 Mod 的稳定性"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法加载部分 Mod 的图标的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复在 Mod 管理页面删除 Mod 导致报错的 Bug"))
|
||||
FeatureCount += 11
|
||||
BugCount += 21
|
||||
End If
|
||||
If LastVersion < 336 Then 'Release 2.8.6
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "下载 Mod 时会使用 MCIM 国内镜像源"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 管理页面允许筛选可更新/启用/禁用的 Mod"))
|
||||
@@ -56,84 +84,39 @@ Public Class FormMain
|
||||
FeatureCount += 10
|
||||
BugCount += 10
|
||||
End If
|
||||
If LastVersion < 317 Then 'Release 2.6.15
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法安装 Forge 的 Bug"))
|
||||
FeatureCount += 2
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 315 Then 'Release 2.6.14
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 MC 下载,尝试解决各种导致 MC 下载失败的问题"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "由于 MCBBS 关站,移除其相关内容"))
|
||||
FeatureCount += 17
|
||||
BugCount += 16
|
||||
End If
|
||||
If LastVersion < 313 Then 'Release 2.6.13
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法启动 Forge 1.18.3+ 的 Bug"))
|
||||
FeatureCount += 6
|
||||
BugCount += 10
|
||||
End If
|
||||
If LastVersion < 311 Then 'Release 2.6.12
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 管理页面将显示 Mod 的中文名、图标、标签等信息"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "从 Mod 管理页面查看 Mod 信息时会跳转到其下载详情页面"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重新设计 Mod 管理页面的交互与样式"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 Forge 1.18.3+ 的 Bug"))
|
||||
FeatureCount += 27
|
||||
BugCount += 25
|
||||
End If
|
||||
If LastVersion < 308 Then 'Release 2.6.10
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "为版本独立设置添加忽略 Java 兼容性警告选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复开始或结束游戏时可能报错的 Bug"))
|
||||
FeatureCount += 31
|
||||
BugCount += 37
|
||||
End If
|
||||
If LastVersion < 302 Then 'Release 2.6.7
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "再次修复网络条件差时可能无法下载 MC 的 Bug"))
|
||||
BugCount += 1
|
||||
End If
|
||||
If LastVersion < 300 Then 'Release 2.6.6
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持选择多种预设的主页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod 管理中允许多选 Mod 进行批量操作"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化崩溃分析,添加多种崩溃情况的判断"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化联网获取的主页的加载与缓存"))
|
||||
FeatureCount += 40
|
||||
BugCount += 34
|
||||
End If
|
||||
If LastVersion < 296 Then 'Release 2.6.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "新增内存优化功能,可以将所有程序的物理内存占用降低约 1/3"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "在选择 OptiFine 与 Fabric 后会自动选择 OptiFabric"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化崩溃分析,添加多种崩溃情况的判断"))
|
||||
FeatureCount += 21
|
||||
BugCount += 30
|
||||
End If
|
||||
If LastVersion < 293 Then 'Release 2.6.1
|
||||
BugCount += 1
|
||||
End If
|
||||
If LastVersion < 292 Then 'Release 2.6.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持在多个正版账号间切换"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "在缺少 Java 时会自动下载所需的 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重新制作正版登录页面"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "彻底移除 Mojang 登录"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 CurseForge / Modrinth 来源筛选"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "Mod / 整合包下载会单独列出筛选的版本"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "为下载管理和音乐播放按钮添加进度条"))
|
||||
FeatureCount += 24
|
||||
BugCount += 24
|
||||
End If
|
||||
If LastVersion < 286 Then 'Release 2.5.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持搜索、安装 Modrinth 的 Mod 与整合包"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "资源搜索页面支持翻页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在全局启动设置中添加了 启动前执行命令 选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "重做资源下载的资源项界面"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "在选择下载 Fabric 时会自动选择 Fabric API"))
|
||||
FeatureCount += 35
|
||||
BugCount += 36
|
||||
End If
|
||||
#Else
|
||||
'5: FEAT+
|
||||
'4: IMP+ FEAT*
|
||||
'3:BUG+ IMP* FEAT-
|
||||
'2:BUG* IMP-
|
||||
'1:BUG-
|
||||
If LastVersion < 346 Then 'Snapshot 2.8.12
|
||||
If LastVersion = 345 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复帮助页面报错的 Bug"))
|
||||
End If
|
||||
If LastVersion < 345 Then 'Snapshot 2.8.11
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 管理页面添加下载 Mod、安装 Mod 选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 详情页面支持按加载器、游戏版本进行分类和筛选"))
|
||||
FeatureCount += 23
|
||||
BugCount += 21
|
||||
End If
|
||||
If LastVersion < 343 Then 'Snapshot 2.8.10
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持安装同时包含 modpack 文件和启动器的懒人包"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化整合包导入流程"))
|
||||
FeatureCount += 20
|
||||
BugCount += 16
|
||||
End If
|
||||
If LastVersion < 341 Then 'Snapshot 2.8.9
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持下载原版服务端"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "本地 Mod 的标题支持选择显示 Mod 原始文件名"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复搜索后启用/禁用 Mod 时出错的 Bug"))
|
||||
FeatureCount += 17
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 339 Then 'Snapshot 2.8.8
|
||||
If LastVersion = 337 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复数个与新正版登录相关的严重 Bug"))
|
||||
FeatureCount += 3
|
||||
BugCount += 7
|
||||
End If
|
||||
If LastVersion < 337 Then 'Snapshot 2.8.7
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "使用新的正版登录方式,以提高安全性"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化安装整合包、检索 Mod 的稳定性"))
|
||||
@@ -215,117 +198,6 @@ Public Class FormMain
|
||||
FeatureCount += 10
|
||||
BugCount += 10
|
||||
End If
|
||||
If LastVersion < 316 Then 'Snapshot 2.6.15
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法安装 Forge 的 Bug"))
|
||||
FeatureCount += 2
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 314 Then 'Snapshot 2.6.14
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 MC 下载,尝试解决各种导致 MC 下载失败的问题"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "由于 MCBBS 关站,移除其相关内容"))
|
||||
FeatureCount += 17
|
||||
BugCount += 16
|
||||
End If
|
||||
If LastVersion < 312 Then 'Snapshot 2.6.13
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法启动 Forge 1.18.3+ 的 Bug"))
|
||||
FeatureCount += 6
|
||||
BugCount += 10
|
||||
End If
|
||||
If LastVersion < 310 Then 'Snapshot 2.6.12
|
||||
If LastVersion = 309 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod 管理页面添加启用、禁用单个 Mod 的快捷按钮"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 Forge 1.18.3+ 的 Bug"))
|
||||
FeatureCount += 13
|
||||
BugCount += 12
|
||||
End If
|
||||
If LastVersion < 309 Then 'Snapshot 2.6.11
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 管理页面将显示 Mod 的中文名、图标、标签等信息"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "从 Mod 管理页面查看 Mod 信息时会跳转到其下载详情页面"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重新设计 Mod 管理页面的交互与样式"))
|
||||
FeatureCount += 15
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 307 Then 'Snapshot 2.6.10
|
||||
FeatureCount += 2
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 306 Then 'Snapshot 2.6.9
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "为版本独立设置添加忽略 Java 兼容性警告选项"))
|
||||
FeatureCount += 9
|
||||
BugCount += 11
|
||||
End If
|
||||
If LastVersion < 305 Then 'Snapshot 2.6.8
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复开始或结束游戏时可能报错的 Bug"))
|
||||
FeatureCount += 20
|
||||
BugCount += 25
|
||||
End If
|
||||
If LastVersion < 303 Then 'Snapshot 2.6.7
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "再次修复网络条件差时可能无法下载 MC 的 Bug"))
|
||||
BugCount += 1
|
||||
End If
|
||||
If LastVersion < 301 Then 'Snapshot 2.6.6
|
||||
FeatureCount += 4
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 299 Then 'Snapshot 2.6.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持选择多种预设的主页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化联网获取的主页的加载与缓存"))
|
||||
FeatureCount += 18
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 298 Then 'Snapshot 2.6.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod 管理中允许多选 Mod 进行批量操作"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化崩溃分析,添加多种崩溃情况的判断"))
|
||||
FeatureCount += 18
|
||||
BugCount += 19
|
||||
End If
|
||||
If LastVersion < 297 Then 'Snapshot 2.6.3
|
||||
FeatureCount += 12
|
||||
BugCount += 14
|
||||
End If
|
||||
If LastVersion < 294 Then 'Snapshot 2.6.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "新增内存优化功能,可以将所有程序的物理内存占用降低约 1/3"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "在选择 OptiFine 与 Fabric 后会自动选择 OptiFabric"))
|
||||
FeatureCount += 9
|
||||
BugCount += 16
|
||||
End If
|
||||
If LastVersion < 291 Then 'Snapshot 2.6.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持在多个正版账号间切换"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "Mod / 整合包下载会单独列出筛选的版本"))
|
||||
FeatureCount += 10
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 289 Then 'Snapshot 2.5.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重新制作正版登录页面"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "彻底移除 Mojang 登录"))
|
||||
FeatureCount += 6
|
||||
BugCount += 14
|
||||
End If
|
||||
If LastVersion < 288 Then 'Snapshot 2.5.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "在缺少 Java 时会自动下载所需的 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 CurseForge / Modrinth 来源筛选"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "为下载管理和音乐播放按钮添加进度条"))
|
||||
FeatureCount += 8
|
||||
BugCount += 8
|
||||
End If
|
||||
If LastVersion < 285 Then 'Snapshot 2.5.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "重做资源下载的资源项界面"))
|
||||
If LastVersion = 284 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复打开部分帮助报错的 Bug"))
|
||||
FeatureCount += 8
|
||||
BugCount += 8
|
||||
End If
|
||||
If LastVersion < 284 Then 'Snapshot 2.5.1
|
||||
If LastVersion >= 275 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在全局启动设置中添加了 启动前执行命令 选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "在选择下载 Fabric 时会自动选择 Fabric API"))
|
||||
FeatureCount += 22
|
||||
BugCount += 21
|
||||
End If
|
||||
If LastVersion < 283 Then 'Snapshot 2.5.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持搜索、下载 Modrinth 中的 Mod 与整合包"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "资源搜索页面支持翻页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持安装 Modrinth 整合包"))
|
||||
FeatureCount += 5
|
||||
BugCount += 5
|
||||
End If
|
||||
#End If
|
||||
'整理更新日志文本
|
||||
Dim ContentList As New List(Of String)
|
||||
@@ -368,9 +240,6 @@ Public Class FormMain
|
||||
'触发降级
|
||||
DowngradeSub(LastVersion)
|
||||
End If
|
||||
''刷新语言
|
||||
'Lang = ReadReg("Lang", "zh_CN")
|
||||
'Application.Current.Resources.MergedDictionaries(1) = New ResourceDictionary With {.Source = New Uri("Resources\Language\" & Lang & ".xaml", UriKind.Relative)}
|
||||
'刷新主题
|
||||
ThemeCheckAll(False)
|
||||
Setup.Load("UiLauncherTheme")
|
||||
@@ -388,7 +257,9 @@ Public Class FormMain
|
||||
If Not IsNothing(FrmLaunchLeft.Parent) Then FrmLaunchLeft.SetValue(ContentPresenter.ContentProperty, Nothing)
|
||||
If Not IsNothing(FrmLaunchRight.Parent) Then FrmLaunchRight.SetValue(ContentPresenter.ContentProperty, Nothing)
|
||||
PanMainLeft.Child = FrmLaunchLeft
|
||||
PageLeft = FrmLaunchLeft
|
||||
PanMainRight.Child = FrmLaunchRight
|
||||
PageRight = FrmLaunchRight
|
||||
FrmLaunchRight.PageState = MyPageRight.PageStates.ContentStay
|
||||
'模式提醒
|
||||
#If DEBUG Then
|
||||
@@ -433,17 +304,17 @@ Public Class FormMain
|
||||
'加载窗口
|
||||
ThemeRefreshMain()
|
||||
Try
|
||||
Height = ReadReg("WindowHeight", MinHeight + 50)
|
||||
Width = ReadReg("WindowWidth", MinWidth + 50)
|
||||
Height = Setup.Get("WindowHeight")
|
||||
Width = Setup.Get("WindowWidth")
|
||||
Catch ex As Exception '修复 #2019
|
||||
Log(ex, "读取窗口默认大小失败", LogLevel.Hint)
|
||||
Height = MinHeight + 50
|
||||
Width = MinWidth + 50
|
||||
Height = MinHeight + 100
|
||||
Width = MinWidth + 100
|
||||
End Try
|
||||
#If DEBUG Then
|
||||
MinHeight = 50
|
||||
MinWidth = 50
|
||||
#End If
|
||||
'#If DEBUG Then
|
||||
' MinHeight = 50
|
||||
' MinWidth = 50
|
||||
'#End If
|
||||
Topmost = False
|
||||
If FrmStart IsNot Nothing Then FrmStart.Close(New TimeSpan(0, 0, 0, 0, 400 / AniSpeed))
|
||||
'更改窗口
|
||||
@@ -474,7 +345,7 @@ Public Class FormMain
|
||||
'EULA 提示
|
||||
If Not Setup.Get("SystemEula") Then
|
||||
Select Case MyMsgBox("在使用 PCL 前,请同意 PCL 的用户协议与免责声明。", "协议授权", "同意", "拒绝", "查看用户协议与免责声明",
|
||||
Button3Action:=Sub() OpenWebsite("https://shimo.im/docs/rGrd8pY8xWkt6ryW"))
|
||||
Button3Action:=Sub() OpenWebsite("https://shimo.im/docs/rGrd8pY8xWkt6ryW"))
|
||||
Case 1
|
||||
Setup.Set("SystemEula", True)
|
||||
Case 2
|
||||
@@ -577,6 +448,16 @@ Public Class FormMain
|
||||
Setup.Set("UiHiddenOtherHelp", False)
|
||||
Log("[Start] 已解除帮助页面的隐藏")
|
||||
End If
|
||||
'单向迁移微软登录结果(#4836)
|
||||
If Not Setup.Get("CacheMsV2Migrated") Then
|
||||
Setup.Set("CacheMsV2Migrated", True)
|
||||
Setup.Set("CacheMsV2OAuthRefresh", Setup.Get("CacheMsOAuthRefresh"))
|
||||
Setup.Set("CacheMsV2Access", Setup.Get("CacheMsAccess"))
|
||||
Setup.Set("CacheMsV2ProfileJson", Setup.Get("CacheMsProfileJson"))
|
||||
Setup.Set("CacheMsV2Uuid", Setup.Get("CacheMsUuid"))
|
||||
Setup.Set("CacheMsV2Name", Setup.Get("CacheMsName"))
|
||||
Log("[Start] 已从老版本迁移微软登录结果")
|
||||
End If
|
||||
'输出更新日志
|
||||
If LastVersionCode = 0 Then Exit Sub
|
||||
If LowerVersionCode >= VersionCode Then Exit Sub
|
||||
@@ -618,35 +499,35 @@ Public Class FormMain
|
||||
End If
|
||||
'关闭
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
IsHitTestVisible = False
|
||||
If PanBack.RenderTransform Is Nothing Then
|
||||
Dim TransformPos As New TranslateTransform(0, 0)
|
||||
Dim TransformRotate As New RotateTransform(0)
|
||||
Dim TransformScale As New ScaleTransform(1, 1)
|
||||
PanBack.RenderTransform = New TransformGroup() With {.Children = New TransformCollection({TransformRotate, TransformPos, TransformScale})}
|
||||
AniStart({
|
||||
AaOpacity(Me, -Opacity, 140, 40, New AniEaseOutFluent(AniEasePower.Weak)),
|
||||
AaDouble(
|
||||
Sub(i)
|
||||
TransformScale.ScaleX += i
|
||||
TransformScale.ScaleY += i
|
||||
End Sub, 0.88 - TransformScale.ScaleX, 180),
|
||||
AaDouble(Sub(i) TransformPos.Y += i, 20 - TransformPos.Y, 180, 0, New AniEaseOutFluent(AniEasePower.Weak)),
|
||||
AaDouble(Sub(i) TransformRotate.Angle += i, 0.6 - TransformRotate.Angle, 180, 0, New AniEaseInoutFluent(AniEasePower.Weak)),
|
||||
AaCode(
|
||||
Sub()
|
||||
IsHitTestVisible = False
|
||||
Top = -10000
|
||||
ShowInTaskbar = False
|
||||
End Sub, 210),
|
||||
AaCode(AddressOf EndProgramForce, 230)
|
||||
}, "Form Close")
|
||||
Else
|
||||
EndProgramForce()
|
||||
End If
|
||||
Log("[System] 收到关闭指令")
|
||||
End Sub)
|
||||
Sub()
|
||||
IsHitTestVisible = False
|
||||
If PanBack.RenderTransform Is Nothing Then
|
||||
Dim TransformPos As New TranslateTransform(0, 0)
|
||||
Dim TransformRotate As New RotateTransform(0)
|
||||
Dim TransformScale As New ScaleTransform(1, 1)
|
||||
PanBack.RenderTransform = New TransformGroup() With {.Children = New TransformCollection({TransformRotate, TransformPos, TransformScale})}
|
||||
AniStart({
|
||||
AaOpacity(Me, -Opacity, 140, 40, New AniEaseOutFluent(AniEasePower.Weak)),
|
||||
AaDouble(
|
||||
Sub(i)
|
||||
TransformScale.ScaleX += i
|
||||
TransformScale.ScaleY += i
|
||||
End Sub, 0.88 - TransformScale.ScaleX, 180),
|
||||
AaDouble(Sub(i) TransformPos.Y += i, 20 - TransformPos.Y, 180, 0, New AniEaseOutFluent(AniEasePower.Weak)),
|
||||
AaDouble(Sub(i) TransformRotate.Angle += i, 0.6 - TransformRotate.Angle, 180, 0, New AniEaseInoutFluent(AniEasePower.Weak)),
|
||||
AaCode(
|
||||
Sub()
|
||||
IsHitTestVisible = False
|
||||
Top = -10000
|
||||
ShowInTaskbar = False
|
||||
End Sub, 210),
|
||||
AaCode(AddressOf EndProgramForce, 230)
|
||||
}, "Form Close")
|
||||
Else
|
||||
EndProgramForce()
|
||||
End If
|
||||
Log("[System] 收到关闭指令")
|
||||
End Sub)
|
||||
End Sub
|
||||
Private Shared IsLogShown As Boolean = False
|
||||
Public Shared Sub EndProgramForce(Optional ReturnCode As Result = Result.Success)
|
||||
@@ -691,8 +572,8 @@ Public Class FormMain
|
||||
Public IsSizeSaveable As Boolean = False
|
||||
Private Sub FormMain_SizeChanged() Handles Me.SizeChanged, Me.Loaded
|
||||
If IsSizeSaveable Then
|
||||
WriteReg("WindowHeight", Height)
|
||||
WriteReg("WindowWidth", Width)
|
||||
Setup.Set("WindowHeight", Height)
|
||||
Setup.Set("WindowWidth", Width)
|
||||
End If
|
||||
RectForm.Rect = New Rect(0, 0, BorderForm.ActualWidth, BorderForm.ActualHeight)
|
||||
PanForm.Width = BorderForm.ActualWidth + 0.001
|
||||
@@ -721,7 +602,7 @@ Public Class FormMain
|
||||
Exit Sub
|
||||
ElseIf e.Key = Key.Escape Then
|
||||
Dim Msg As Object = PanMsg.Children(0)
|
||||
If TypeOf Msg Is MyMsgText AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
||||
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
||||
Msg.Btn3_Click()
|
||||
ElseIf Msg.Btn2.Visibility = Visibility.Visible Then
|
||||
Msg.Btn2_Click()
|
||||
@@ -750,6 +631,12 @@ Public Class FormMain
|
||||
PageSetupUI.HiddenRefresh()
|
||||
Exit Sub
|
||||
End If
|
||||
'按 F5 刷新页面
|
||||
If e.Key = Key.F5 Then
|
||||
If TypeOf PageLeft Is IRefreshable Then CType(PageLeft, IRefreshable).Refresh()
|
||||
If TypeOf PageRight Is IRefreshable Then CType(PageRight, IRefreshable).Refresh()
|
||||
Exit Sub
|
||||
End If
|
||||
'调用启动游戏
|
||||
If e.Key = Key.Enter AndAlso PageCurrent = FormMain.PageType.Launch Then
|
||||
If IsAprilEnabled AndAlso Not IsAprilGiveup Then
|
||||
@@ -887,14 +774,14 @@ Public Class FormMain
|
||||
If FilePathList.Count > 1 Then
|
||||
'必须要求全部为 jar 文件
|
||||
For Each File In FilePathList
|
||||
If Not {"jar", "litemod", "disabled", "old"}.Contains(File.After(".").ToLower) Then
|
||||
If Not {"jar", "litemod", "disabled", "old"}.Contains(File.AfterLast(".").ToLower) Then
|
||||
Hint("一次请只拖入一个文件!", HintType.Critical)
|
||||
Exit Sub
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
'自定义主页
|
||||
Dim Extension As String = FilePath.After(".").ToLower
|
||||
Dim Extension As String = FilePath.AfterLast(".").ToLower
|
||||
If Extension = "xaml" Then
|
||||
Log("[System] 文件后缀为 XAML,作为自定义主页加载")
|
||||
If File.Exists(Path & "PCL\Custom.xaml") Then
|
||||
@@ -903,53 +790,27 @@ Public Class FormMain
|
||||
End If
|
||||
End If
|
||||
CopyFile(FilePath, Path & "PCL\Custom.xaml")
|
||||
RunInUi(Sub()
|
||||
Setup.Set("UiCustomType", 1)
|
||||
FrmLaunchRight.ForceRefresh()
|
||||
Hint("已加载主页自定义文件!", HintType.Finish)
|
||||
End Sub)
|
||||
Exit Sub
|
||||
End If
|
||||
'Mod 安装
|
||||
If {"jar", "litemod", "disabled", "old"}.Any(Function(t) t = Extension) Then
|
||||
Log("[System] 文件为 jar/litemod 格式,尝试作为 Mod 安装")
|
||||
'获取并检查目标版本
|
||||
Dim TargetVersion As McVersion = McVersionCurrent
|
||||
If PageCurrent = PageType.VersionSetup Then TargetVersion = PageVersionLeft.Version
|
||||
If PageCurrent = PageType.VersionSelect OrElse TargetVersion Is Nothing OrElse Not TargetVersion.Modable Then
|
||||
'正在选择版本,或当前版本不能安装 Mod
|
||||
Hint("若要安装 Mod,请先选择一个可以安装 Mod 的版本!")
|
||||
ElseIf Not (PageCurrent = PageType.VersionSetup AndAlso PageCurrentSub = PageSubType.VersionMod) Then
|
||||
'未处于 Mod 管理页面
|
||||
If MyMsgBox($"是否要将这{If(FilePathList.Count = 1, "个", "些")}文件作为 Mod 安装到 {TargetVersion.Name}?", "Mod 安装确认", "确定", "取消") = 1 Then GoTo Install
|
||||
Else
|
||||
'处于 Mod 管理页面
|
||||
Install:
|
||||
Try
|
||||
For Each ModFile In FilePathList
|
||||
Dim NewFileName = GetFileNameFromPath(ModFile).Replace(".disabled", "")
|
||||
If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
|
||||
CopyFile(ModFile, TargetVersion.PathIndie & "mods\" & NewFileName)
|
||||
Next
|
||||
If FilePathList.Count = 1 Then
|
||||
Hint($"已安装 {GetFileNameFromPath(FilePathList.First).Replace(".disabled", "")}!", HintType.Finish)
|
||||
Else
|
||||
Hint($"已安装 {FilePathList.Count} 个 Mod!", HintType.Finish)
|
||||
End If
|
||||
'刷新列表
|
||||
If PageCurrent = PageType.VersionSetup AndAlso PageCurrentSub = PageSubType.VersionMod Then
|
||||
LoaderFolderRun(McModLoader, TargetVersion.PathIndie & "mods\", LoaderFolderRunType.ForceRun)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "复制 Mod 文件失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End If
|
||||
RunInUi(
|
||||
Sub()
|
||||
Setup.Set("UiCustomType", 1)
|
||||
FrmLaunchRight.ForceRefresh()
|
||||
Hint("已加载主页自定义文件!", HintType.Finish)
|
||||
End Sub)
|
||||
Exit Sub
|
||||
End If
|
||||
'安装 Mod
|
||||
If PageVersionMod.InstallMods(FilePathList) Then Exit Sub
|
||||
'安装整合包
|
||||
If {"zip", "rar", "mrpack"}.Any(Function(t) t = Extension) Then '部分压缩包是 zip 格式但后缀为 rar,总之试一试
|
||||
Log("[System] 文件为压缩包,尝试作为整合包安装")
|
||||
If ModpackInstall(FilePath, ShowHint:=False) IsNot Nothing Then Exit Sub
|
||||
Try
|
||||
ModpackInstall(FilePath)
|
||||
Exit Sub
|
||||
Catch ex As CancelledException
|
||||
Exit Sub '用户主动取消
|
||||
Catch ex As Exception
|
||||
'安装失败,继续往后尝试
|
||||
End Try
|
||||
End If
|
||||
'RAR 处理
|
||||
If Extension = "rar" Then
|
||||
@@ -1179,9 +1040,6 @@ Install:
|
||||
Case PageType.Download
|
||||
If FrmDownloadLeft Is Nothing Then FrmDownloadLeft = New PageDownloadLeft
|
||||
Return FrmDownloadLeft.PageID
|
||||
Case PageType.Link
|
||||
If FrmLinkLeft Is Nothing Then FrmLinkLeft = New PageLinkLeft
|
||||
Return FrmLinkLeft.PageID
|
||||
Case PageType.Setup
|
||||
If FrmSetupLeft Is Nothing Then FrmSetupLeft = New PageSetupLeft
|
||||
Return FrmSetupLeft.PageID
|
||||
@@ -1250,9 +1108,6 @@ Install:
|
||||
CType(PanTitleSelect.Children(Stack), MyRadioButton).SetChecked(True, True, PageNameGet(PageCurrent) = "")
|
||||
IsChangingPage = False
|
||||
Select Case Stack.Page
|
||||
Case PageType.Link
|
||||
If FrmLinkLeft Is Nothing Then FrmLinkLeft = New PageLinkLeft
|
||||
CType(FrmLinkLeft.PanItem.Children(SubType), MyListItem).SetChecked(True, True, Stack = PageCurrent)
|
||||
Case PageType.Download
|
||||
If FrmDownloadLeft Is Nothing Then FrmDownloadLeft = New PageDownloadLeft
|
||||
CType(FrmDownloadLeft.PanItem.Children(SubType), MyListItem).SetChecked(True, True, Stack = PageCurrent)
|
||||
@@ -1281,14 +1136,6 @@ Install:
|
||||
If IsChangingPage Then Exit Sub
|
||||
PageChangeActual(Val(sender.Tag))
|
||||
End Sub
|
||||
Private Sub CancelLink(sender As Object, e As RouteEventArgs) Handles BtnTitleSelect2.PreviewClick
|
||||
If MyMsgBox("由于联机提供商要求新联机强制付费,且高度商业化,PCL 将暂时关闭联机功能,不再使用该联机模块。" & vbCrLf &
|
||||
"PCL、HMCL、BakaXL 将合作开发新的跨启动器联机功能,在开发结束后将同步开放,请各位多多理解。",
|
||||
"联机功能已暂时关闭", "查看详情", "确定") = 1 Then
|
||||
OpenWebsite("https://www.bilibili.com/read/cv19845645")
|
||||
End If
|
||||
e.Handled = True
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 通过点击返回按钮或手动触发返回来改变页面。
|
||||
''' </summary>
|
||||
@@ -1319,9 +1166,9 @@ Install:
|
||||
If PageStack.Any Then
|
||||
'子页面 → 另一个子页面,更新
|
||||
AniStart({
|
||||
AaOpacity(LabTitleInner, -LabTitleInner.Opacity, 130),
|
||||
AaCode(Sub() LabTitleInner.Text = PageName,, True),
|
||||
AaOpacity(LabTitleInner, 1, 150, 30)
|
||||
AaOpacity(LabTitleInner, -LabTitleInner.Opacity, 130),
|
||||
AaCode(Sub() LabTitleInner.Text = PageName,, True),
|
||||
AaOpacity(LabTitleInner, 1, 150, 30)
|
||||
}, "FrmMain Titlebar SubLayer")
|
||||
If PageStack.Contains(Stack) Then
|
||||
'返回到更上层的子页面
|
||||
@@ -1415,37 +1262,41 @@ Install:
|
||||
AniControlEnabled -= 1
|
||||
'执行动画
|
||||
AniStart({
|
||||
AaCode(Sub()
|
||||
AniControlEnabled += 1
|
||||
'把新页面添加进容器
|
||||
PanMainLeft.Child = PageLeft
|
||||
PageLeft.Opacity = 0
|
||||
PanMainLeft.Background = Nothing
|
||||
AniControlEnabled -= 1
|
||||
RunInUi(Sub() PanMainLeft_Resize(PanMainLeft.ActualWidth), True)
|
||||
End Sub, 130),
|
||||
AaCode(Sub()
|
||||
'延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
|
||||
PageLeft.Opacity = 1
|
||||
PageLeft.TriggerShowAnimation()
|
||||
End Sub, 30, True)
|
||||
AaCode(
|
||||
Sub()
|
||||
AniControlEnabled += 1
|
||||
'把新页面添加进容器
|
||||
PanMainLeft.Child = PageLeft
|
||||
PageLeft.Opacity = 0
|
||||
PanMainLeft.Background = Nothing
|
||||
AniControlEnabled -= 1
|
||||
RunInUi(Sub() PanMainLeft_Resize(PanMainLeft.ActualWidth), True)
|
||||
End Sub, 130),
|
||||
AaCode(
|
||||
Sub()
|
||||
'延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
|
||||
PageLeft.Opacity = 1
|
||||
PageLeft.TriggerShowAnimation()
|
||||
End Sub, 30, True)
|
||||
}, "FrmMain PageChangeLeft")
|
||||
AniStart({
|
||||
AaCode(Sub()
|
||||
AniControlEnabled += 1
|
||||
CType(PanMainRight.Child, MyPageRight).PageOnForceExit()
|
||||
'把新页面添加进容器
|
||||
PanMainRight.Child = PageRight
|
||||
PageRight.Opacity = 0
|
||||
PanMainRight.Background = Nothing
|
||||
AniControlEnabled -= 1
|
||||
RunInUi(Sub() BtnExtraBack.ShowRefresh(), True)
|
||||
End Sub, 130),
|
||||
AaCode(Sub()
|
||||
'延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
|
||||
PageRight.Opacity = 1
|
||||
PageRight.PageOnEnter()
|
||||
End Sub, 30, True)
|
||||
AaCode(
|
||||
Sub()
|
||||
AniControlEnabled += 1
|
||||
CType(PanMainRight.Child, MyPageRight).PageOnForceExit()
|
||||
'把新页面添加进容器
|
||||
PanMainRight.Child = PageRight
|
||||
PageRight.Opacity = 0
|
||||
PanMainRight.Background = Nothing
|
||||
AniControlEnabled -= 1
|
||||
RunInUi(Sub() BtnExtraBack.ShowRefresh(), True)
|
||||
End Sub, 130),
|
||||
AaCode(
|
||||
Sub()
|
||||
'延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
|
||||
PageRight.Opacity = 1
|
||||
PageRight.PageOnEnter()
|
||||
End Sub, 30, True)
|
||||
}, "FrmMain PageChangeRight")
|
||||
End Sub
|
||||
''' <summary>
|
||||
@@ -1458,12 +1309,12 @@ Install:
|
||||
PanTitleMain.IsHitTestVisible = True
|
||||
PanTitleInner.IsHitTestVisible = False
|
||||
AniStart({
|
||||
AaOpacity(PanTitleInner, -PanTitleInner.Opacity, 150),
|
||||
AaX(PanTitleInner, -18 - PanTitleInner.Margin.Left, 150,, New AniEaseInFluent),
|
||||
AaOpacity(PanTitleMain, 1 - PanTitleMain.Opacity, 150, 200),
|
||||
AaX(PanTitleMain, -PanTitleMain.Margin.Left, 350, 200, New AniEaseOutBack(AniEasePower.Weak)),
|
||||
AaCode(Sub() PanTitleInner.Visibility = Visibility.Collapsed,, True)
|
||||
}, "FrmMain Titlebar FirstLayer")
|
||||
AaOpacity(PanTitleInner, -PanTitleInner.Opacity, 150),
|
||||
AaX(PanTitleInner, -18 - PanTitleInner.Margin.Left, 150,, New AniEaseInFluent),
|
||||
AaOpacity(PanTitleMain, 1 - PanTitleMain.Opacity, 150, 200),
|
||||
AaX(PanTitleMain, -PanTitleMain.Margin.Left, 350, 200, New AniEaseOutBack(AniEasePower.Weak)),
|
||||
AaCode(Sub() PanTitleInner.Visibility = Visibility.Collapsed,, True)
|
||||
}, "FrmMain Titlebar FirstLayer")
|
||||
PageStack.Clear()
|
||||
Else
|
||||
'主页面 → 主页面,无事发生
|
||||
@@ -1482,16 +1333,16 @@ Install:
|
||||
If NewWidth > 0 Then
|
||||
'宽度足够,显示
|
||||
AniStart({
|
||||
AaWidth(RectLeftBackground, NewWidth - RectLeftBackground.Width, 400,, New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
||||
AaOpacity(RectLeftShadow, 1 - RectLeftShadow.Opacity, 200),
|
||||
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 250)
|
||||
AaWidth(RectLeftBackground, NewWidth - RectLeftBackground.Width, 400,, New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
||||
AaOpacity(RectLeftShadow, 1 - RectLeftShadow.Opacity, 200),
|
||||
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 250)
|
||||
}, "FrmMain LeftChange", True)
|
||||
Else
|
||||
'宽度不足,隐藏
|
||||
AniStart({
|
||||
AaWidth(RectLeftBackground, -RectLeftBackground.Width, 200,, New AniEaseOutFluent),
|
||||
AaOpacity(RectLeftShadow, -RectLeftShadow.Opacity, 200),
|
||||
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 170)
|
||||
AaWidth(RectLeftBackground, -RectLeftBackground.Width, 200,, New AniEaseOutFluent),
|
||||
AaOpacity(RectLeftShadow, -RectLeftShadow.Opacity, 200),
|
||||
AaCode(Sub() PanMainLeft.IsHitTestVisible = True, 170)
|
||||
}, "FrmMain LeftChange", True)
|
||||
End If
|
||||
Else
|
||||
|
||||
@@ -12,13 +12,13 @@ Public Module ModBase
|
||||
#Region "声明"
|
||||
|
||||
'下列版本信息由更新器自动修改
|
||||
Public Const VersionBaseName As String = "2.8.7" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.8.7." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const VersionBaseName As String = "2.8.12" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.8.12." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
||||
#If BETA Then
|
||||
Public Const VersionCode As Integer = 336 'Release
|
||||
Public Const VersionCode As Integer = 347 'Release
|
||||
#Else
|
||||
Public Const VersionCode As Integer = 337 'Snapshot
|
||||
Public Const VersionCode As Integer = 346 'Snapshot
|
||||
#End If
|
||||
'自动生成的版本信息
|
||||
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
||||
@@ -176,6 +176,10 @@ Public Module ModBase
|
||||
''' </summary>
|
||||
Public Const IconButtonOffline As String = "M533.293176 788.841412a60.235294 60.235294 0 1 1 85.202824 85.202823l-42.616471 42.586353c-129.355294 129.385412-339.124706 129.385412-468.510117 0-129.385412-129.385412-129.385412-339.124706 0-468.510117l42.586353-42.616471a60.235294 60.235294 0 1 1 85.202823 85.202824l-42.61647 42.586352a210.823529 210.823529 0 1 0 298.164706 298.164706l42.586352-42.61647z m255.548236-255.548236l42.61647-42.586352a210.823529 210.823529 0 1 0-298.164706-298.164706l-42.586352 42.61647a60.235294 60.235294 0 1 1-85.202824-85.202823l42.616471-42.586353c129.355294-129.385412 339.124706-129.385412 468.510117 0 129.385412 129.385412 129.385412 339.124706 0 468.510117l-42.586353 42.616471a60.235294 60.235294 0 1 1-85.202823-85.202824zM192.542118 192.542118a60.235294 60.235294 0 0 1 85.202823 0l553.712941 553.712941a60.235294 60.235294 0 0 1-85.202823 85.202823L192.542118 277.744941a60.235294 60.235294 0 0 1 0-85.202823z"
|
||||
''' <summary>
|
||||
''' 图标,服务端,1x
|
||||
''' </summary>
|
||||
Public Const IconButtonServer As String = "M224 160a64 64 0 0 0-64 64v576a64 64 0 0 0 64 64h576a64 64 0 0 0 64-64V224a64 64 0 0 0-64-64H224z m0 384h576v256H224v-256z m192 96v64h320v-64H416z m-128 0v64h64v-64H288zM224 224h576v256H224V224z m192 96v64h320v-64H416z m-128 0v64h64v-64H288z"
|
||||
''' <summary>
|
||||
''' 图标,音符,1x
|
||||
''' </summary>
|
||||
Public Const IconMusic As String = "M348.293565 716.53287V254.797913c0-41.672348 28.004174-78.358261 68.919652-90.37913L815.994435 40.826435c62.775652-18.610087 125.907478 26.579478 125.907478 89.933913v539.158261c8.013913 42.25113-8.94887 89.177043-47.014956 127.109565a232.848696 232.848696 0 0 1-170.785392 65.758609c-61.885217-2.938435-111.081739-33.435826-129.113043-80.050087-18.031304-46.614261-2.137043-102.177391 41.672348-145.853218a232.848696 232.848696 0 0 1 170.785391-65.80313c21.014261 1.024 40.514783 5.164522 57.878261 12.065391V233.338435c0-12.109913-10.551652-20.034783-20.569044-20.034783a24.620522 24.620522 0 0 0-5.787826 0.934957L439.785739 338.18713a19.545043 19.545043 0 0 0-14.825739 19.144348v438.984348H423.846957c11.53113 43.987478-5.164522 94.208-45.412174 134.322087a232.848696 232.848696 0 0 1-170.785392 65.758609c-61.885217-2.938435-111.081739-33.435826-129.113043-80.050087-18.031304-46.614261-2.137043-102.177391 41.672348-145.853218a232.848696 232.848696 0 0 1 170.785391-65.80313c20.791652 1.024 40.069565 5.075478 57.299478 11.842783z"
|
||||
@@ -967,7 +971,7 @@ Public Module ModBase
|
||||
End Using
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 弹出选取文件对话框并且要求选取文件。
|
||||
''' 弹出选取文件对话框,要求选择一个文件。
|
||||
''' </summary>
|
||||
''' <param name="FileFilter">要求的格式。如:“常用图片文件(*.png;*.jpg)|*.png;*.jpg”。</param>
|
||||
''' <param name="Title">弹窗的标题。</param>
|
||||
@@ -981,12 +985,32 @@ Public Module ModBase
|
||||
fileDialog.Title = Title
|
||||
fileDialog.ValidateNames = True
|
||||
fileDialog.ShowDialog()
|
||||
SelectFile = fileDialog.FileName
|
||||
Log("[UI] 选择文件返回:" & SelectFile)
|
||||
Log("[UI] 选择单个文件返回:" & fileDialog.FileName)
|
||||
Return fileDialog.FileName
|
||||
End Using
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 弹出选取文件夹对话框并且要求选取文件夹。如果没有选择就返回空字符串。
|
||||
''' 弹出选取文件对话框,要求选择多个文件。
|
||||
''' </summary>
|
||||
''' <param name="FileFilter">要求的格式。如:“常用图片文件(*.png;*.jpg)|*.png;*.jpg”。</param>
|
||||
''' <param name="Title">弹窗的标题。</param>
|
||||
Public Function SelectFiles(FileFilter As String, Title As String) As String()
|
||||
Using fileDialog As New Forms.OpenFileDialog
|
||||
fileDialog.AddExtension = True
|
||||
fileDialog.AutoUpgradeEnabled = True
|
||||
fileDialog.CheckFileExists = True
|
||||
fileDialog.Filter = FileFilter
|
||||
fileDialog.Multiselect = True
|
||||
fileDialog.Title = Title
|
||||
fileDialog.ValidateNames = True
|
||||
fileDialog.ShowDialog()
|
||||
Log("[UI] 选择多个文件返回:" & fileDialog.FileNames.Join(","))
|
||||
Return fileDialog.FileNames
|
||||
End Using
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 弹出选取文件夹对话框,要求选取文件夹。
|
||||
''' 返回以 \ 结尾的完整路径,如果没有选择则返回空字符串。
|
||||
''' </summary>
|
||||
Public Function SelectFolder(Optional Title As String = "选择文件夹") As String
|
||||
Dim folderDialog As New Ookii.Dialogs.Wpf.VistaFolderBrowserDialog With {.ShowNewFolderButton = True, .RootFolder = Environment.SpecialFolder.Desktop, .Description = Title, .UseDescriptionForTitle = True}
|
||||
@@ -1203,7 +1227,8 @@ Re:
|
||||
''' 尝试根据后缀名判断文件种类并解压文件,支持 gz 与 zip,会尝试将 jar 以 zip 方式解压。
|
||||
''' 会尝试创建,但不会清空目标文件夹。
|
||||
''' </summary>
|
||||
Public Sub ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing)
|
||||
Public Sub ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing,
|
||||
Optional ProgressIncrementHandler As Action(Of Double) = Nothing)
|
||||
Directory.CreateDirectory(DestDirectory)
|
||||
If CompressFilePath.EndsWithF(".gz", True) Then
|
||||
'以 gz 方式解压
|
||||
@@ -1219,7 +1244,9 @@ Re:
|
||||
Else
|
||||
'以 zip 方式解压
|
||||
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030")))
|
||||
Dim TotalCount As Integer = Archive.Entries.Count
|
||||
For Each Entry As ZipArchiveEntry In Archive.Entries
|
||||
If ProgressIncrementHandler IsNot Nothing Then ProgressIncrementHandler(1 / TotalCount)
|
||||
Dim DestinationPath As String = IO.Path.Combine(DestDirectory, Entry.FullName)
|
||||
If DestinationPath.EndsWithF("\") OrElse DestinationPath.EndsWithF("/") Then
|
||||
Continue For '不创建空文件夹
|
||||
@@ -1289,13 +1316,16 @@ RetryDir:
|
||||
''' <summary>
|
||||
''' 复制文件夹,失败会抛出异常。
|
||||
''' </summary>
|
||||
Public Sub CopyDirectory(FromPath As String, ToPath As String)
|
||||
Public Sub CopyDirectory(FromPath As String, ToPath As String, Optional ProgressIncrementHandler As Action(Of Double) = Nothing)
|
||||
FromPath = FromPath.Replace("/", "\")
|
||||
If Not FromPath.EndsWithF("\") Then FromPath &= "\"
|
||||
ToPath = ToPath.Replace("/", "\")
|
||||
If Not ToPath.EndsWithF("\") Then ToPath &= "\"
|
||||
For Each File In EnumerateFiles(FromPath)
|
||||
Dim AllFiles = EnumerateFiles(FromPath).ToList
|
||||
Dim FileCount As Integer = AllFiles.Count
|
||||
For Each File In AllFiles
|
||||
CopyFile(File.FullName, File.FullName.Replace(FromPath, ToPath))
|
||||
If ProgressIncrementHandler IsNot Nothing Then ProgressIncrementHandler(1 / FileCount)
|
||||
Next
|
||||
End Sub
|
||||
''' <summary>
|
||||
@@ -1344,8 +1374,8 @@ RetryDir:
|
||||
|
||||
'常见错误(记得同时修改下面的)
|
||||
Dim CommonReason As String = Nothing
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。"
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||
CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||
@@ -1364,7 +1394,7 @@ RetryDir:
|
||||
If CommonReason Is Nothing Then
|
||||
Return Desc & Stack & TypeDesc
|
||||
Else
|
||||
Dim Result As String = DescList.First & vbCrLf & CommonReason & vbCrLf & "————————————" & vbCrLf
|
||||
Dim Result As String = CommonReason & vbCrLf & DescList.First & vbCrLf & "————————————" & vbCrLf
|
||||
DescList(0) = "详细错误信息:"
|
||||
Return Result & Join(DescList, vbCrLf & "→ ") & Stack & TypeDesc
|
||||
End If
|
||||
@@ -1392,8 +1422,8 @@ RetryDir:
|
||||
|
||||
'常见错误(记得同时修改上面的)
|
||||
Dim CommonReason As String = Nothing
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。"
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||
CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||
@@ -1407,7 +1437,7 @@ RetryDir:
|
||||
|
||||
'构造输出信息
|
||||
If CommonReason IsNot Nothing Then
|
||||
Return DescList.First & ":" & CommonReason
|
||||
Return CommonReason & "详细错误:" & DescList.First
|
||||
Else
|
||||
DescList.Reverse() '让最深层错误在最左边
|
||||
Return Join(DescList, " → ")
|
||||
@@ -1548,10 +1578,10 @@ RetryDir:
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 获取在子字符串之前的部分。
|
||||
''' 会裁切尽可能多的内容,但如果未找到子字符串则不裁切。
|
||||
''' 获取在子字符串第一次出现之前的部分,例如对 2024/11/08 拆切 / 会得到 2024。
|
||||
''' 如果未找到子字符串则不裁切。
|
||||
''' </summary>
|
||||
<Extension> Public Function Before(Str As String, Text As String, Optional IgnoreCase As Boolean = False) As String
|
||||
<Extension> Public Function BeforeFirst(Str As String, Text As String, Optional IgnoreCase As Boolean = False) As String
|
||||
Dim Pos As Integer = If(String.IsNullOrEmpty(Text), -1, Str.IndexOfF(Text, IgnoreCase))
|
||||
If Pos >= 0 Then
|
||||
Return Str.Substring(0, Pos)
|
||||
@@ -1560,10 +1590,34 @@ RetryDir:
|
||||
End If
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取在子字符串之后的部分。
|
||||
''' 会裁切尽可能多的内容,但如果未找到子字符串则不裁切。
|
||||
''' 获取在子字符串最后一次出现之前的部分,例如对 2024/11/08 拆切 / 会得到 2024/11。
|
||||
''' 如果未找到子字符串则不裁切。
|
||||
''' </summary>
|
||||
<Extension> Public Function After(Str As String, Text As String, Optional IgnoreCase As Boolean = False) As String
|
||||
<Extension> Public Function BeforeLast(Str As String, Text As String, Optional IgnoreCase As Boolean = False) As String
|
||||
Dim Pos As Integer = If(String.IsNullOrEmpty(Text), -1, Str.LastIndexOfF(Text, IgnoreCase))
|
||||
If Pos >= 0 Then
|
||||
Return Str.Substring(0, Pos)
|
||||
Else
|
||||
Return Str
|
||||
End If
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取在子字符串第一次出现之后的部分,例如对 2024/11/08 拆切 / 会得到 11/08。
|
||||
''' 如果未找到子字符串则不裁切。
|
||||
''' </summary>
|
||||
<Extension> Public Function AfterFirst(Str As String, Text As String, Optional IgnoreCase As Boolean = False) As String
|
||||
Dim Pos As Integer = If(String.IsNullOrEmpty(Text), -1, Str.IndexOfF(Text, IgnoreCase))
|
||||
If Pos >= 0 Then
|
||||
Return Str.Substring(Pos + Text.Length)
|
||||
Else
|
||||
Return Str
|
||||
End If
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取在子字符串最后一次出现之后的部分,例如对 2024/11/08 拆切 / 会得到 08。
|
||||
''' 如果未找到子字符串则不裁切。
|
||||
''' </summary>
|
||||
<Extension> Public Function AfterLast(Str As String, Text As String, Optional IgnoreCase As Boolean = False) As String
|
||||
Dim Pos As Integer = If(String.IsNullOrEmpty(Text), -1, Str.LastIndexOfF(Text, IgnoreCase))
|
||||
If Pos >= 0 Then
|
||||
Return Str.Substring(Pos + Text.Length)
|
||||
@@ -1572,8 +1626,8 @@ RetryDir:
|
||||
End If
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取处于两个子字符串之间的部分。
|
||||
''' 会裁切尽可能多的内容:匹配开始使用 LastIndexOf,匹配结束使用 IndexOf,但如果未找到子字符串则不裁切。
|
||||
''' 获取处于两个子字符串之间的部分,裁切尽可能多的内容。
|
||||
''' 如果未找到子字符串则不裁切。
|
||||
''' </summary>
|
||||
<Extension> Public Function Between(Str As String, After As String, Before As String, Optional IgnoreCase As Boolean = False) As String
|
||||
Dim StartPos As Integer = If(String.IsNullOrEmpty(After), -1, Str.LastIndexOfF(After, IgnoreCase))
|
||||
@@ -1808,10 +1862,10 @@ RetryDir:
|
||||
'进行搜索,获取相似信息
|
||||
For Each Entry In Entries
|
||||
Entry.Similarity = SearchSimilarityWeighted(Entry.SearchSource, Query)
|
||||
Entry.AbsoluteRight = False
|
||||
For Each Pair In Entry.SearchSource
|
||||
If Pair.Key.Replace(" ", "").ContainsF(Query.Replace(" ", ""), True) Then Entry.AbsoluteRight = True
|
||||
Next
|
||||
Entry.AbsoluteRight =
|
||||
Query.Split(" ").All( '对于按空格分割的每一段
|
||||
Function(QueryPart) Entry.SearchSource.Any( '若与任意一个搜索源完全匹配,则标记为完全匹配项
|
||||
Function(Source) Source.Key.Replace(" ", "").ContainsF(QueryPart, True)))
|
||||
Next
|
||||
'按照相似度进行排序
|
||||
Entries = Sort(Entries,
|
||||
@@ -1840,6 +1894,68 @@ RetryDir:
|
||||
|
||||
#Region "系统"
|
||||
|
||||
''' <summary>
|
||||
''' 线程安全的,可以直接使用 For Each 的 List。
|
||||
''' 在使用 For Each 循环时,列表的结果可能并非最新,但不会抛出异常。
|
||||
''' </summary>
|
||||
Public Class SafeList(Of T)
|
||||
Inherits SynchronizedCollection(Of T)
|
||||
Implements IEnumerable, IEnumerable(Of T)
|
||||
'构造函数
|
||||
Public Sub New()
|
||||
MyBase.New()
|
||||
End Sub
|
||||
Public Sub New(Data As IEnumerable(Of T))
|
||||
MyBase.New(New Object, Data)
|
||||
End Sub
|
||||
Public Shared Widening Operator CType(Data As List(Of T)) As SafeList(Of T)
|
||||
Return New SafeList(Of T)(Data)
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Data As SafeList(Of T)) As List(Of T)
|
||||
Return New List(Of T)(Data)
|
||||
End Operator
|
||||
'基于 SyncLock 覆写
|
||||
Public Overloads Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
|
||||
SyncLock SyncRoot
|
||||
Return Items.ToList.GetEnumerator()
|
||||
End SyncLock
|
||||
End Function
|
||||
Private Overloads Function GetEnumeratorGeneral() As IEnumerator Implements IEnumerable.GetEnumerator
|
||||
SyncLock SyncRoot
|
||||
Return Items.ToList.GetEnumerator()
|
||||
End SyncLock
|
||||
End Function
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
|
||||
''' </summary>
|
||||
Public PathPure As String = GetPureASCIIDir()
|
||||
Private Function GetPureASCIIDir() As String
|
||||
If (Path & "PCL").IsASCII() Then
|
||||
Return Path & "PCL\"
|
||||
ElseIf PathAppdata.IsASCII() Then
|
||||
Return PathAppdata
|
||||
ElseIf PathTemp.IsASCII() Then
|
||||
Return PathTemp
|
||||
Else
|
||||
Return OsDrive & "ProgramData\PCL\"
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 指示接取到这个异常的函数进行重试。
|
||||
''' </summary>
|
||||
Public Class RestartException
|
||||
Inherits Exception
|
||||
End Class
|
||||
''' <summary>
|
||||
''' 指示用户手动取消了操作,或用户已知晓操作被取消的原因。
|
||||
''' </summary>
|
||||
Public Class CancelledException
|
||||
Inherits Exception
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 当前程序是否拥有管理员权限。
|
||||
''' </summary>
|
||||
@@ -1956,10 +2072,10 @@ NextElement:
|
||||
'12~60 月,“1 年 2 个月”
|
||||
GetTimeSpanString = Math.Floor(TotalMonthes / 12) & " 年" & If((TotalMonthes Mod 12) > 0, " " & (TotalMonthes Mod 12) & " 个月", "")
|
||||
ElseIf TotalMonthes >= 4 Then
|
||||
'4~11 月,“5 月”
|
||||
GetTimeSpanString = TotalMonthes & " 月"
|
||||
'4~11 月,“5 个月”
|
||||
GetTimeSpanString = TotalMonthes & " 个月"
|
||||
ElseIf TotalMonthes >= 1 Then
|
||||
'1~4 月,“2 月 13 天”
|
||||
'1~4 月,“2 个月 13 天”
|
||||
GetTimeSpanString = TotalMonthes & " 月" & If((Span.Days Mod 30) > 0, " " & (Span.Days Mod 30) & " 天", "")
|
||||
ElseIf Span.TotalDays >= 4 Then
|
||||
'4~30 天,“23 天”
|
||||
@@ -2081,7 +2197,7 @@ NextElement:
|
||||
''' <summary>
|
||||
''' 在新的工作线程中执行代码。
|
||||
''' </summary>
|
||||
Public Function RunInNewThread(Action As Action, Name As String, Optional Priority As ThreadPriority = ThreadPriority.Normal) As Thread
|
||||
Public Function RunInNewThread(Action As Action, Optional Name As String = Nothing, Optional Priority As ThreadPriority = ThreadPriority.Normal) As Thread
|
||||
Dim th As New Thread(
|
||||
Sub()
|
||||
Try
|
||||
@@ -2091,7 +2207,7 @@ NextElement:
|
||||
Catch ex As Exception
|
||||
Log(ex, Name & ":线程执行失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub) With {.Name = Name, .Priority = Priority}
|
||||
End Sub) With {.Name = If(Name, "Runtime New Invoke " & GetUuid() & "#"), .Priority = Priority}
|
||||
th.Start()
|
||||
Return th
|
||||
End Function
|
||||
@@ -2430,6 +2546,14 @@ Retry:
|
||||
Return rect.Contains(bounds.TopLeft) OrElse rect.Contains(bounds.BottomRight)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 控件是否受到 TextTrimming 属性影响,导致内容被截取。
|
||||
''' </summary>
|
||||
<Extension> Public Function IsTextTrimmed(Control As TextBlock) As Boolean
|
||||
Control.Measure(New Size(Double.MaxValue, Double.MaxValue))
|
||||
Return Control.DesiredSize.Width > Control.ActualWidth
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "Debug"
|
||||
|
||||
@@ -288,15 +288,13 @@
|
||||
End SyncLock
|
||||
End Try
|
||||
'检验输入以确定情况
|
||||
If (Not IsForceRestart) AndAlso '不要求强行重启
|
||||
((Input IsNot Nothing AndAlso Input.Equals(Me.Input)) OrElse (Input Is Nothing AndAlso Me.Input Is Nothing)) AndAlso '输入相同
|
||||
(State = LoadState.Loading OrElse State = LoadState.Finished) AndAlso '正在加载或已加载成功
|
||||
If IsForceRestart Then Return True '强制要求重启
|
||||
If ((Input Is Nothing) <> (Me.Input Is Nothing)) OrElse (Input IsNot Nothing AndAlso Not Input.Equals(Me.Input)) Then Return True '输入不同
|
||||
If (State = LoadState.Loading OrElse State = LoadState.Finished) AndAlso '正在加载或已结束
|
||||
(IgnoreReloadTimeout OrElse ReloadTimeout = -1 OrElse LastFinishedTime = 0 OrElse GetTimeTick() - LastFinishedTime < ReloadTimeout) Then '没有超时
|
||||
'如果输入相同且未出错则不重试
|
||||
Return False
|
||||
Return False '则不重试
|
||||
Else
|
||||
'需要开始
|
||||
Return True
|
||||
Return True '需要开始
|
||||
End If
|
||||
End Function
|
||||
Public Overrides Sub Start(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = False)
|
||||
@@ -317,7 +315,7 @@
|
||||
Sub()
|
||||
Try
|
||||
IsForceRestarting = IsForceRestart
|
||||
If ModeDebug Then Log("[Loader] 加载线程 " & Name & " (" & Thread.CurrentThread.ManagedThreadId & ") 已启动")
|
||||
If ModeDebug Then Log("[Loader] 加载线程 " & Name & " (" & Thread.CurrentThread.ManagedThreadId & ") 已" & If(IsForceRestarting, "强制", "") & "启动")
|
||||
LoadDelegate(Me)
|
||||
If IsAborted Then
|
||||
Log("[Loader] 加载线程 " & Name & " (" & Thread.CurrentThread.ManagedThreadId & ") 已中断但线程正常运行至结束,输出被弃用(最新线程:" & If(LastRunningThread Is Nothing, -1, LastRunningThread.ManagedThreadId) & ")", LogLevel.Developer)
|
||||
@@ -441,12 +439,13 @@
|
||||
Exit Sub
|
||||
End If
|
||||
End SyncLock
|
||||
RunInThread(Sub()
|
||||
'中断加载器
|
||||
For Each Loader In Loaders
|
||||
Loader.Abort()
|
||||
Next
|
||||
End Sub)
|
||||
RunInThread(
|
||||
Sub()
|
||||
'中断加载器
|
||||
For Each Loader In Loaders
|
||||
Loader.Abort()
|
||||
Next
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -485,7 +484,7 @@
|
||||
Private Sub Update()
|
||||
If State = LoadState.Finished OrElse State = LoadState.Failed OrElse State = LoadState.Aborted Then Exit Sub
|
||||
Dim IsFinished As Boolean = True
|
||||
Dim Ignore As Boolean = False
|
||||
Dim Blocked As Boolean = False
|
||||
Dim Input As Object = Me.Input
|
||||
For Each Loader In Loaders
|
||||
Select Case Loader.State
|
||||
@@ -493,28 +492,30 @@
|
||||
'检查是否需要重启
|
||||
If Loader.GetType.Name.StartsWithF("LoaderTask") Then '类型名后面带有泛型,必须用 StartsWith
|
||||
If CType(Loader, Object).ShouldStart(If(Input IsNot Nothing AndAlso Loader.GetType.GenericTypeArguments.First Is Input.GetType, Input, Nothing), IgnoreReloadTimeout:=True) Then
|
||||
If ModeDebug Then Log("[Loader] 由于输入条件变更,重启已完成的加载器 " & Loader.Name)
|
||||
Log("[Loader] 由于输入条件变更,重启已完成的加载器 " & Loader.Name)
|
||||
GoTo Restart
|
||||
End If
|
||||
'更新下一个加载器的输入
|
||||
Input = CType(Loader, Object).Output
|
||||
End If
|
||||
'如果不让继续启动,且已有加载器正在加载中,就不继续启动
|
||||
If Loader.Block AndAlso Not IsFinished Then Blocked = True
|
||||
Case LoadState.Loading
|
||||
'检查是否需要重启
|
||||
If Loader.GetType.Name.StartsWithF("LoaderTask") Then
|
||||
If CType(Loader, Object).ShouldStart(If(Input IsNot Nothing AndAlso Loader.GetType.GenericTypeArguments.First Is Input.GetType, Input, Nothing), IgnoreReloadTimeout:=True) Then
|
||||
If ModeDebug Then Log("[Loader] 由于输入条件变更,重启进行中的加载器 " & Loader.Name, LogLevel.Developer)
|
||||
Log("[Loader] 由于输入条件变更,重启进行中的加载器 " & Loader.Name, LogLevel.Developer)
|
||||
GoTo Restart
|
||||
End If
|
||||
End If
|
||||
'已经有正在加载中的了,不需要再启动了
|
||||
IsFinished = False
|
||||
Ignore = True
|
||||
Blocked = True
|
||||
Case Else
|
||||
Restart:
|
||||
'未启动,则启动加载器
|
||||
IsFinished = False
|
||||
If Ignore Then Continue For
|
||||
If Blocked Then Continue For
|
||||
If Input IsNot Nothing Then
|
||||
'若输入类型与下一个加载器相同才继续
|
||||
Dim LoaderType As String = Loader.GetType.Name
|
||||
@@ -528,8 +529,8 @@ Restart:
|
||||
Else
|
||||
Loader.Start(IsForceRestart:=IsForceRestarting)
|
||||
End If
|
||||
'如果不让继续启动,那就不启动呗
|
||||
If Loader.Block Then Ignore = True
|
||||
'阻止继续
|
||||
If Loader.Block Then Blocked = True
|
||||
End Select
|
||||
Next
|
||||
If IsFinished Then
|
||||
@@ -567,7 +568,7 @@ Restart:
|
||||
End Class
|
||||
|
||||
'任务栏进度条
|
||||
Public LoaderTaskbar As New SynchronizedCollection(Of LoaderBase)
|
||||
Public LoaderTaskbar As New SafeList(Of LoaderBase)
|
||||
Public LoaderTaskbarProgress As Double = 0 '平滑后的进度
|
||||
Private LoaderTaskbarProgressLast As Shell.TaskbarItemProgressState = Shell.TaskbarItemProgressState.None
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ Retry:
|
||||
''' </summary>
|
||||
''' <param name="Url">网页的 Url。</param>
|
||||
''' <param name="Encode">网页的编码,通常为 UTF-8。</param>
|
||||
Public Function NetGetCodeByRequestMulty(Url As String, Optional Encode As Encoding = Nothing, Optional Accept As String = "", Optional IsJson As Boolean = False)
|
||||
Public Function NetGetCodeByRequestMultiple(Url As String, Optional Encode As Encoding = Nothing, Optional Accept As String = "", Optional IsJson As Boolean = False)
|
||||
Dim Threads As New List(Of Thread)
|
||||
Dim RequestResult = Nothing
|
||||
Dim RequestEx As Exception = Nothing
|
||||
@@ -329,7 +329,7 @@ Retry:
|
||||
''' <summary>
|
||||
''' 同时发送多个网络请求并要求返回内容。
|
||||
''' </summary>
|
||||
Public Function NetRequestMulty(Url As String, Method As String, Data As Object, ContentType As String, Optional RequestCount As Integer = 4, Optional Headers As Dictionary(Of String, String) = Nothing, Optional MakeLog As Boolean = True)
|
||||
Public Function NetRequestMultiple(Url As String, Method As String, Data As Object, ContentType As String, Optional RequestCount As Integer = 4, Optional Headers As Dictionary(Of String, String) = Nothing, Optional MakeLog As Boolean = True)
|
||||
Dim Threads As New List(Of Thread)
|
||||
Dim RequestResult = Nothing
|
||||
Dim RequestEx As Exception = Nothing
|
||||
@@ -701,8 +701,7 @@ RequestFinished:
|
||||
''' <summary>
|
||||
''' 所属的文件列表任务。
|
||||
''' </summary>
|
||||
Public Tasks As New Concurrent.ConcurrentBag(Of LoaderDownload)
|
||||
|
||||
Public Tasks As New SafeList(Of LoaderDownload)
|
||||
''' <summary>
|
||||
''' 所有下载源。
|
||||
''' </summary>
|
||||
@@ -931,7 +930,7 @@ RequestFinished:
|
||||
|
||||
'条件检测
|
||||
If NetTaskThreadCount >= NetTaskThreadLimit OrElse IsSourceFailed() OrElse
|
||||
(IsNoSplit AndAlso Threads IsNot Nothing AndAlso Threads.State <> NetState.Error) Then Return Nothing
|
||||
(IsNoSplit AndAlso Threads IsNot Nothing AndAlso Threads.State <> NetState.Error) Then Return Nothing
|
||||
If State >= NetState.Merge OrElse State = NetState.WaitForCheck Then Return Nothing
|
||||
SyncLock LockState
|
||||
If State < NetState.Connect Then State = NetState.Connect
|
||||
@@ -940,7 +939,6 @@ RequestFinished:
|
||||
Dim StartPosition As Long, StartSource As NetSource = Nothing
|
||||
Dim Th As Thread, ThreadInfo As NetThread
|
||||
SyncLock LockChain
|
||||
|
||||
'获取线程起点与下载源
|
||||
'不分割
|
||||
If IsNoSplit Then GoTo Capture
|
||||
@@ -976,7 +974,8 @@ Capture:
|
||||
Next
|
||||
'是否禁用多线程,以及规定碎片大小
|
||||
Dim TargetUrl As String = GetSource().Url
|
||||
If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") OrElse TargetUrl.Contains("github.com") OrElse TargetUrl.Contains("modrinth") Then Return Nothing
|
||||
If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("mcimirror") OrElse TargetUrl.Contains("github.com") OrElse
|
||||
TargetUrl.Contains("optifine.net") OrElse TargetUrl.Contains("modrinth") Then Return Nothing
|
||||
'寻找最大碎片
|
||||
'FUTURE: 下载引擎重做,计算下载源平均链接时间和线程下载速度,按最高时间节省来开启多线程
|
||||
Dim FilePieceMax As NetThread = Threads
|
||||
@@ -1050,6 +1049,15 @@ StartThread:
|
||||
If ModeDebug AndAlso HttpResponse.ResponseUri.OriginalString <> Info.Source.Url Then
|
||||
Log($"[Download] {LocalName} {Info.Uuid}#:重定向至 {HttpResponse.ResponseUri.OriginalString}")
|
||||
End If
|
||||
''从响应头获取文件名
|
||||
'If Info.IsFirstThread Then
|
||||
' Dim FileName As String = GetFileNameFromResponse(HttpResponse)
|
||||
' If ModeDebug Then Log($"[Download] {LocalName} {Info.Uuid}#:远程文件名:{If(FileName, "未提供")}")
|
||||
' If FileName IsNot Nothing AndAlso LocalName = "待定" Then
|
||||
' LocalName = FileName
|
||||
' Log($"[Download] {LocalName} {Info.Uuid}#:从响应头获取到文件名")
|
||||
' End If
|
||||
'End If
|
||||
'文件大小校验
|
||||
ContentLength = HttpResponse.ContentLength
|
||||
If ContentLength = -1 Then
|
||||
@@ -1134,7 +1142,7 @@ NotSupportRange:
|
||||
If NetTaskSpeedLimitHigh > 0 Then NetTaskSpeedLimitLeft -= RealDataCount
|
||||
End SyncLock
|
||||
Dim DeltaTime = GetTimeTick() - Info.LastReceiveTime
|
||||
If DeltaTime > 1000000 Then DeltaTime = 0 '时间刻反转导致出现极大值
|
||||
If DeltaTime > 1000000 Then DeltaTime = 1 '时间刻反转导致出现极大值
|
||||
If RealDataCount > 0 Then
|
||||
'有数据
|
||||
If Info.DownloadDone = 0 Then
|
||||
@@ -1175,7 +1183,7 @@ NotSupportRange:
|
||||
ResultStream.Write(HttpData, 0, RealDataCount)
|
||||
End If
|
||||
'检查速度是否过慢
|
||||
If DeltaTime > 1000 AndAlso DeltaTime > RealDataCount Then '数据包间隔大于 1s,且速度小于 1K/s
|
||||
If DeltaTime > 1500 AndAlso DeltaTime > RealDataCount Then '数据包间隔大于 1.5s,且速度小于 1.5K/s
|
||||
Throw New TimeoutException("由于速度过慢断开链接,下载 " & RealDataCount & " B,消耗 " & DeltaTime & " ms。")
|
||||
End If
|
||||
Info.LastReceiveTime = GetTimeTick()
|
||||
@@ -1232,7 +1240,7 @@ SourceBreak:
|
||||
'根据情况判断,是否在多线程下禁用下载源(连续错误过多,或不支持断点续传)
|
||||
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("(403)") OrElse ex.Message.Contains("(429)")) AndAlso Not Info.Source.Url.ContainsF("bmclapi")) OrElse 'BMCLAPI 的部分源在高频率请求下会返回 403、429,所以不应因此禁用下载源
|
||||
(ex.Message.Contains("(403)") AndAlso Not Info.Source.Url.ContainsF("bmclapi")) OrElse 'BMCLAPI 的部分源在高频率请求下会返回 403,所以不应因此禁用下载源
|
||||
(Info.Source.FailCount >= MathClamp(NetTaskThreadLimit, 5, 30) AndAlso DownloadDone < 1) OrElse
|
||||
Info.Source.FailCount > NetTaskThreadLimit + 2 Then
|
||||
Dim IsThisFail As Boolean = False
|
||||
@@ -1287,6 +1295,17 @@ Wrong:
|
||||
If ((FileSize >= 0 AndAlso DownloadDone >= FileSize) OrElse (FileSize = -1 AndAlso DownloadDone > 0)) AndAlso State < NetState.Merge Then Merge()
|
||||
End Try
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 从 HTTP 响应头中获取文件名。
|
||||
''' 如果没有,返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function GetFileNameFromResponse(response As HttpWebResponse) As String
|
||||
Dim header As String = response.Headers("Content-Disposition")
|
||||
If String.IsNullOrEmpty(header) Then Return Nothing
|
||||
'attachment; filename="filename.ext"
|
||||
If Not header.Contains("filename=") Then Return Nothing
|
||||
Return header.AfterLast("filename=").Trim(""""c, " "c).BeforeFirst(";")
|
||||
End Function
|
||||
|
||||
'下载文件的最终收束事件
|
||||
''' <summary>
|
||||
@@ -1403,7 +1422,7 @@ Retry:
|
||||
''' </summary>
|
||||
Public Sub Abort(CausedByTask As LoaderDownload)
|
||||
'从特定任务中移除,如果它还属于其他任务,则继续下载
|
||||
Tasks.TryTake(CausedByTask)
|
||||
Tasks.Remove(CausedByTask)
|
||||
If Tasks.Any Then Exit Sub
|
||||
'确认中断
|
||||
SyncLock LockState
|
||||
@@ -1451,8 +1470,7 @@ Retry:
|
||||
''' <summary>
|
||||
''' 需要下载的文件。
|
||||
''' </summary>
|
||||
Public Files As List(Of NetFile)
|
||||
Private ReadOnly FilesLock As New Object
|
||||
Public Files As SafeList(Of NetFile)
|
||||
''' <summary>
|
||||
''' 剩余未完成的文件数。(用于减轻 FilesLock 的占用)
|
||||
''' </summary>
|
||||
@@ -1465,9 +1483,7 @@ Retry:
|
||||
Public Overrides Property Progress As Double
|
||||
Get
|
||||
If State >= LoadState.Finished Then Return 1
|
||||
SyncLock FilesLock
|
||||
If Not Files.Any() Then Return 0 '必须返回 0,否则在获取列表的时候会错觉已经下载完了
|
||||
End SyncLock
|
||||
If Not Files.Any() Then Return 0 '必须返回 0,否则在获取列表的时候会错觉已经下载完了
|
||||
Return _Progress
|
||||
End Get
|
||||
Set(value As Double)
|
||||
@@ -1489,16 +1505,14 @@ Retry:
|
||||
Log("[Download] 由于同加载器中失败次数过多引发强制失败:连续失败了 " & value & " 次", LogLevel.Debug)
|
||||
On Error Resume Next
|
||||
Dim ExList As New List(Of Exception)
|
||||
SyncLock FilesLock
|
||||
For Each File In Files
|
||||
For Each Source In File.Sources
|
||||
If Source.Ex IsNot Nothing Then
|
||||
ExList.Add(Source.Ex)
|
||||
If ExList.Count > 10 Then GoTo FinishExCatch
|
||||
End If
|
||||
Next
|
||||
For Each File In Files
|
||||
For Each Source In File.Sources
|
||||
If Source.Ex IsNot Nothing Then
|
||||
ExList.Add(Source.Ex)
|
||||
If ExList.Count > 10 Then GoTo FinishExCatch
|
||||
End If
|
||||
Next
|
||||
End SyncLock
|
||||
Next
|
||||
FinishExCatch:
|
||||
OnFail(ExList)
|
||||
End If
|
||||
@@ -1515,17 +1529,15 @@ FinishExCatch:
|
||||
'计算进度
|
||||
Dim NewProgress As Double = 0
|
||||
Dim TotalProgress As Double = 0
|
||||
SyncLock FilesLock
|
||||
For Each File In Files
|
||||
If File.IsCopy Then
|
||||
NewProgress += File.Progress * 0.2
|
||||
TotalProgress += 0.2
|
||||
Else
|
||||
NewProgress += File.Progress
|
||||
TotalProgress += 1
|
||||
End If
|
||||
Next
|
||||
End SyncLock
|
||||
For Each File In Files
|
||||
If File.IsCopy Then
|
||||
NewProgress += File.Progress * 0.2
|
||||
TotalProgress += 0.2
|
||||
Else
|
||||
NewProgress += File.Progress
|
||||
TotalProgress += 1
|
||||
End If
|
||||
Next
|
||||
If TotalProgress > 0 Then NewProgress /= TotalProgress
|
||||
'刷新进度
|
||||
If NewProgress < 1 AndAlso NewProgress > 0 Then NewProgress = 2 * (NewProgress ^ 3) - 3 * (NewProgress ^ 2) + 2 * NewProgress '2x^3-3x^2+2x,模拟开头和结尾更慢的情况
|
||||
@@ -1534,27 +1546,25 @@ FinishExCatch:
|
||||
|
||||
Public Sub New(Name As String, FileTasks As List(Of NetFile))
|
||||
Me.Name = Name
|
||||
Files = FileTasks
|
||||
Files = New SafeList(Of NetFile)(FileTasks)
|
||||
End Sub
|
||||
Public Overrides Sub Start(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = False)
|
||||
SyncLock FilesLock
|
||||
If Input IsNot Nothing Then Files = Input
|
||||
'去重
|
||||
Dim ResultArray As New List(Of NetFile)
|
||||
For i = 0 To Files.Count - 1
|
||||
For ii = i + 1 To Files.Count - 1
|
||||
If Files(i).LocalPath = Files(ii).LocalPath Then GoTo NextElement
|
||||
Next
|
||||
ResultArray.Add(Files(i))
|
||||
If Input IsNot Nothing Then Files = New SafeList(Of NetFile)(Input)
|
||||
'去重
|
||||
Dim ResultArray As New SafeList(Of NetFile)
|
||||
For i = 0 To Files.Count - 1
|
||||
For ii = i + 1 To Files.Count - 1
|
||||
If Files(i).LocalPath = Files(ii).LocalPath Then GoTo NextElement
|
||||
Next
|
||||
ResultArray.Add(Files(i))
|
||||
NextElement:
|
||||
Next i
|
||||
Files = ResultArray
|
||||
'设置剩余文件数
|
||||
SyncLock FileRemainLock
|
||||
For Each File In Files
|
||||
If File.State <> NetState.Finish Then FileRemain += 1
|
||||
Next
|
||||
End SyncLock
|
||||
Next
|
||||
Files = ResultArray
|
||||
'设置剩余文件数
|
||||
SyncLock FileRemainLock
|
||||
For Each File In Files
|
||||
If File.State <> NetState.Finish Then FileRemain += 1
|
||||
Next
|
||||
End SyncLock
|
||||
State = LoadState.Loading
|
||||
'开始执行
|
||||
@@ -1597,25 +1607,23 @@ NextElement:
|
||||
Next
|
||||
End If
|
||||
'最多 5 个线程,最少每个线程分配 10 个文件
|
||||
SyncLock FilesLock
|
||||
Dim FilesPerThread As Integer = Math.Max(5, Files.Count / 10 + 1)
|
||||
Dim FilesInThread As New List(Of NetFile)
|
||||
For Each File In Files
|
||||
FilesInThread.Add(File)
|
||||
If FilesInThread.Count = FilesPerThread Then
|
||||
Dim FilesToRun As New List(Of NetFile)
|
||||
FilesToRun.AddRange(FilesInThread)
|
||||
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
||||
FilesInThread.Clear()
|
||||
End If
|
||||
Next
|
||||
If FilesInThread.Any Then
|
||||
Dim FilesPerThread As Integer = Math.Max(5, Files.Count / 10 + 1)
|
||||
Dim FilesInThread As New List(Of NetFile)
|
||||
For Each File In Files
|
||||
FilesInThread.Add(File)
|
||||
If FilesInThread.Count = FilesPerThread Then
|
||||
Dim FilesToRun As New List(Of NetFile)
|
||||
FilesToRun.AddRange(FilesInThread)
|
||||
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
||||
FilesInThread.Clear()
|
||||
End If
|
||||
End SyncLock
|
||||
Next
|
||||
If FilesInThread.Any Then
|
||||
Dim FilesToRun As New List(Of NetFile)
|
||||
FilesToRun.AddRange(FilesInThread)
|
||||
RunInNewThread(Sub() StartCopy(FilesToRun, FoldersFinal), "NetTask FileCopy " & Uuid)
|
||||
FilesInThread.Clear()
|
||||
End If
|
||||
Catch ex As Exception
|
||||
OnFail(New List(Of Exception) From {ex})
|
||||
End Try
|
||||
@@ -1710,24 +1718,20 @@ Retry:
|
||||
Dim UsefulExs = ExList.Where(Function(e) Not e.Message.Contains("(404)")).ToList
|
||||
[Error] = If(UsefulExs.Any, UsefulExs(0), ExList(0))
|
||||
'获取实际失败的文件
|
||||
SyncLock FilesLock
|
||||
For Each File In Files
|
||||
If File.State = NetState.Error Then
|
||||
[Error] = New Exception("文件下载失败:" & File.LocalPath & vbCrLf & Join(
|
||||
File.Sources.Select(Function(s) If(s.Ex Is Nothing, s.Url, s.Ex.Message & "(" & s.Url & ")")), vbCrLf), [Error])
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
End SyncLock
|
||||
For Each File In Files
|
||||
If File.State = NetState.Error Then
|
||||
[Error] = New Exception("文件下载失败:" & File.LocalPath & vbCrLf & Join(
|
||||
File.Sources.Select(Function(s) If(s.Ex Is Nothing, s.Url, s.Ex.Message & "(" & s.Url & ")")), vbCrLf), [Error])
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
'在设置 Error 对象后再更改为失败,避免 WaitForExit 无法捕获错误
|
||||
State = LoadState.Failed
|
||||
End SyncLock
|
||||
'中断所有文件
|
||||
SyncLock FilesLock
|
||||
For Each TaskFile In Files
|
||||
If TaskFile.State < NetState.Merge Then TaskFile.State = NetState.Error
|
||||
Next
|
||||
End SyncLock
|
||||
For Each TaskFile In Files
|
||||
If TaskFile.State < NetState.Merge Then TaskFile.State = NetState.Error
|
||||
Next
|
||||
'在退出同步锁后再进行日志输出
|
||||
Dim ErrOutput As New List(Of String)
|
||||
For Each Ex As Exception In ExList
|
||||
@@ -1742,11 +1746,9 @@ Retry:
|
||||
End SyncLock
|
||||
Log("[Download] " & Name & " 已取消!")
|
||||
'中断所有文件
|
||||
SyncLock FilesLock
|
||||
For Each TaskFile In Files
|
||||
TaskFile.Abort(Me)
|
||||
Next
|
||||
End SyncLock
|
||||
For Each TaskFile In Files
|
||||
TaskFile.Abort(Me)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -1768,8 +1770,7 @@ Retry:
|
||||
''' <summary>
|
||||
''' 当前的所有下载任务。
|
||||
''' </summary>
|
||||
Public Tasks As New List(Of LoaderDownload)
|
||||
Private ReadOnly LockTasks As New Object
|
||||
Public Tasks As New SafeList(Of LoaderDownload)
|
||||
|
||||
''' <summary>
|
||||
''' 已下载完成的大小。
|
||||
@@ -1842,11 +1843,9 @@ Retry:
|
||||
End If
|
||||
#End Region
|
||||
#Region "刷新下载任务属性"
|
||||
SyncLock LockTasks
|
||||
For Each Task In Tasks
|
||||
Task.RefreshStat()
|
||||
Next
|
||||
End SyncLock
|
||||
For Each Task In Tasks
|
||||
Task.RefreshStat()
|
||||
Next
|
||||
#End Region
|
||||
Catch ex As Exception
|
||||
Log(ex, "刷新下载公开属性失败")
|
||||
@@ -1992,9 +1991,7 @@ Retry:
|
||||
Task.Files(i) = File '回设
|
||||
Next
|
||||
End SyncLock
|
||||
SyncLock LockTasks
|
||||
Tasks.Add(Task)
|
||||
End SyncLock
|
||||
Tasks.Add(Task)
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
@@ -233,6 +233,8 @@ Public Class ValidateFolderName
|
||||
'检查特殊字符串
|
||||
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件夹名不可为 %!", True).Validate(Str)
|
||||
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
|
||||
'检查 NTFS 8.3 文件名(#4505)
|
||||
If RegexCheck(Str, ".{2,}~\d") Then Return "文件夹名不能包含这一特殊格式!"
|
||||
'检查文件夹重名
|
||||
Dim Arr As New List(Of String)
|
||||
If PathIgnore IsNot Nothing Then
|
||||
@@ -286,6 +288,8 @@ Public Class ValidateFileName
|
||||
'检查特殊字符串
|
||||
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件名不可为 %!", True).Validate(Str)
|
||||
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
|
||||
'检查 NTFS 8.3 文件名(#4505)
|
||||
If RegexCheck(Str, ".{2,}~\d") Then Return "文件名不能包含这一特殊格式!"
|
||||
'检查文件重名
|
||||
If ParentFolder IsNot Nothing Then
|
||||
Dim DirInfo As New DirectoryInfo(ParentFolder)
|
||||
@@ -351,6 +355,8 @@ Fin:
|
||||
'检查特殊字符串
|
||||
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件夹名不可为 %!").Validate(SubStr)
|
||||
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
|
||||
'检查 NTFS 8.3 文件名(#4505)
|
||||
If RegexCheck(Str, ".{2,}~\d") Then Return "文件夹名不能包含这一特殊格式!"
|
||||
Next
|
||||
Return ""
|
||||
End Function
|
||||
|
||||
@@ -7,7 +7,7 @@ Public Class MyBitmap
|
||||
''' <summary>
|
||||
''' 位图缓存。
|
||||
''' </summary>
|
||||
Public Shared BitmapCache As New Dictionary(Of String, MyBitmap)
|
||||
Public Shared BitmapCache As New Concurrent.ConcurrentDictionary(Of String, MyBitmap)
|
||||
|
||||
''' <summary>
|
||||
''' 存储的图片
|
||||
@@ -17,15 +17,19 @@ Public Class MyBitmap
|
||||
'自动类型转换
|
||||
'支持的类:Image,ImageSource,Bitmap,ImageBrush,BitmapSource
|
||||
Public Shared Widening Operator CType(Image As System.Drawing.Image) As MyBitmap
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return New MyBitmap(Image)
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As MyBitmap) As System.Drawing.Image
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return Image.Pic
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As ImageSource) As MyBitmap
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return New MyBitmap(Image)
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As MyBitmap) As ImageSource
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Dim Bitmap = Image.Pic
|
||||
Dim rect = New System.Drawing.Rectangle(0, 0, Bitmap.Width, Bitmap.Height)
|
||||
Dim bitmapData = Bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
|
||||
@@ -37,15 +41,19 @@ Public Class MyBitmap
|
||||
End Try
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As System.Drawing.Bitmap) As MyBitmap
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return New MyBitmap(Image)
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As MyBitmap) As System.Drawing.Bitmap
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return Image.Pic
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As ImageBrush) As MyBitmap
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return New MyBitmap(Image)
|
||||
End Operator
|
||||
Public Shared Widening Operator CType(Image As MyBitmap) As ImageBrush
|
||||
If Image Is Nothing Then Return Nothing
|
||||
Return New ImageBrush(New MyBitmap(Image.Pic))
|
||||
End Operator
|
||||
|
||||
@@ -61,7 +69,7 @@ Public Class MyBitmap
|
||||
Pic = BitmapCache(FilePathOrResourceName).Pic
|
||||
Else
|
||||
Pic = New MyBitmap(CType((New ImageSourceConverter).ConvertFromString(FilePathOrResourceName), ImageSource))
|
||||
BitmapCache.Add(FilePathOrResourceName, Pic)
|
||||
BitmapCache.TryAdd(FilePathOrResourceName, Pic)
|
||||
End If
|
||||
Else
|
||||
'使用这种自己接管 FileStream 的方法加载才能解除文件占用
|
||||
@@ -72,11 +80,9 @@ Public Class MyBitmap
|
||||
InputStream.Seek(0, SeekOrigin.Begin)
|
||||
If Header(0) = 82 AndAlso Header(1) = 73 Then
|
||||
'读取 WebP
|
||||
If Is32BitSystem Then Throw New Exception("不支持在 32 位系统下加载 WebP 图片。")
|
||||
Dim FileBytes(InputStream.Length - 1) As Byte
|
||||
InputStream.Read(FileBytes, 0, FileBytes.Length)
|
||||
Dim Decoder As New Imazen.WebP.SimpleDecoder()
|
||||
Pic = Decoder.DecodeFromBytes(FileBytes, FileBytes.Length)
|
||||
Pic = WebPDecoder.DecodeFromBytes(FileBytes) '将代码隔离在另外一个类中,这样只要不走进这个分支就不会加载 Imazen.WebP.dll
|
||||
Else
|
||||
Pic = New System.Drawing.Bitmap(InputStream)
|
||||
End If
|
||||
@@ -86,10 +92,9 @@ Public Class MyBitmap
|
||||
Pic = My.Application.TryFindResource(FilePathOrResourceName)
|
||||
If Pic Is Nothing Then
|
||||
Pic = New System.Drawing.Bitmap(1, 1)
|
||||
Log(ex, $"加载位图失败({FilePathOrResourceName})")
|
||||
Throw
|
||||
Throw New Exception($"加载 MyBitmap 失败({FilePathOrResourceName})", ex)
|
||||
Else
|
||||
Log(ex, $"指定类型有误的位图加载({FilePathOrResourceName})", LogLevel.Developer)
|
||||
Log(ex, $"指定类型有误的 MyBitmap 加载({FilePathOrResourceName})", LogLevel.Developer)
|
||||
Exit Try
|
||||
End If
|
||||
End Try
|
||||
@@ -116,6 +121,13 @@ Public Class MyBitmap
|
||||
Pic = New System.Drawing.Bitmap(MS)
|
||||
End Using
|
||||
End Sub
|
||||
Private Class WebPDecoder '将代码隔离在另外一个类中,这样只要不调用这个方法就不会加载 Imazen.WebP.dll
|
||||
Public Shared Function DecodeFromBytes(Bytes As Byte()) As System.Drawing.Bitmap
|
||||
If Is32BitSystem Then Throw New Exception("不支持在 32 位系统下加载 WebP 图片。")
|
||||
Dim Decoder As New Imazen.WebP.SimpleDecoder()
|
||||
Return Decoder.DecodeFromBytes(Bytes, Bytes.Length)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 获取裁切的图片,这个方法不会导致原对象改变且会返回一个新的对象。
|
||||
|
||||
@@ -271,7 +271,7 @@
|
||||
Next
|
||||
CurseForgeFileIds = Files.Select(Function(f) f.Key).Distinct.ToList
|
||||
GameVersions = Files.SelectMany(Function(f) f.Value).Where(Function(v) v.StartsWithF("1.")).
|
||||
Select(Function(v) CInt(Val(v.Split(".")(1).Before("-")))).Where(Function(v) v > 0).
|
||||
Select(Function(v) CInt(Val(v.Split(".")(1).BeforeFirst("-")))).Where(Function(v) v > 0).
|
||||
Distinct.OrderByDescending(Function(v) v).ToList
|
||||
ModLoaders = ModLoaders.Distinct.OrderBy(Of Integer)(Function(t) t).ToList
|
||||
'Type
|
||||
@@ -349,7 +349,7 @@
|
||||
'搜索结果的键为 versions,获取特定工程的键为 game_versions
|
||||
GameVersions = If(CType(If(Data("game_versions"), Data("versions")), JArray), New JArray).
|
||||
Select(Function(v) v.ToString).Where(Function(v) v.StartsWithF("1.")).
|
||||
Select(Of Integer)(Function(v) Val(v.Split(".")(1).Before("-"))).Where(Function(v) v > 0).
|
||||
Select(Of Integer)(Function(v) Val(v.Split(".")(1).BeforeFirst("-"))).Where(Function(v) v > 0).
|
||||
Distinct.OrderByDescending(Function(v) v).ToList
|
||||
'Type
|
||||
Select Case Data("project_type").ToString
|
||||
@@ -458,14 +458,14 @@
|
||||
If StartVersion = EndVersion Then
|
||||
SpaVersions.Add("1." & StartVersion)
|
||||
ElseIf McVersionHighest > -1 AndAlso StartVersion >= McVersionHighest Then
|
||||
If EndVersion <= 10 Then
|
||||
If EndVersion < 10 Then
|
||||
SpaVersions.Clear()
|
||||
SpaVersions.Add("全版本")
|
||||
Exit For
|
||||
Else
|
||||
SpaVersions.Add("1." & EndVersion & "+")
|
||||
End If
|
||||
ElseIf EndVersion <= 10 Then
|
||||
ElseIf EndVersion < 10 Then
|
||||
SpaVersions.Add("1." & StartVersion & "-")
|
||||
Exit For
|
||||
ElseIf StartVersion - EndVersion = 1 Then
|
||||
@@ -478,25 +478,31 @@
|
||||
End If
|
||||
'获取 Mod 加载器描述
|
||||
Dim ModLoaderDescriptionFull As String, ModLoaderDescriptionPart As String
|
||||
Select Case ModLoaders.Count
|
||||
Dim ModLoadersForDesc As New List(Of CompModLoaderType)(ModLoaders)
|
||||
If Setup.Get("ToolDownloadIgnoreQuilt") Then ModLoadersForDesc.Remove(CompModLoaderType.Quilt)
|
||||
Select Case ModLoadersForDesc.Count
|
||||
Case 0
|
||||
ModLoaderDescriptionFull = "未知"
|
||||
ModLoaderDescriptionPart = ""
|
||||
If ModLoaders.Count = 1 Then
|
||||
ModLoaderDescriptionFull = "仅 " & ModLoaders.Single.ToString
|
||||
ModLoaderDescriptionPart = ModLoaders.Single.ToString
|
||||
Else
|
||||
ModLoaderDescriptionFull = "未知"
|
||||
ModLoaderDescriptionPart = ""
|
||||
End If
|
||||
Case 1
|
||||
ModLoaderDescriptionFull = "仅 " & ModLoaders.Single.ToString
|
||||
ModLoaderDescriptionPart = ModLoaders.Single.ToString
|
||||
Case 2, 3
|
||||
If Setup.Get("ToolDownloadIgnoreQuilt") AndAlso
|
||||
ModLoaders.Contains(CompModLoaderType.Forge) AndAlso ModLoaders.Contains(CompModLoaderType.Fabric) Then
|
||||
ModLoaderDescriptionFull = "仅 " & ModLoadersForDesc.Single.ToString
|
||||
ModLoaderDescriptionPart = ModLoadersForDesc.Single.ToString
|
||||
Case Else
|
||||
If ModLoaders.Contains(CompModLoaderType.Forge) AndAlso
|
||||
(GameVersions.Max < 14 OrElse ModLoaders.Contains(CompModLoaderType.Fabric)) AndAlso
|
||||
(GameVersions.Max < 20 OrElse ModLoaders.Contains(CompModLoaderType.NeoForge)) AndAlso
|
||||
(GameVersions.Max < 14 OrElse ModLoaders.Contains(CompModLoaderType.Quilt) OrElse Setup.Get("ToolDownloadIgnoreQuilt")) Then
|
||||
ModLoaderDescriptionFull = "任意"
|
||||
ModLoaderDescriptionPart = ""
|
||||
Else
|
||||
ModLoaderDescriptionFull = ModLoaders.Join(" / ")
|
||||
ModLoaderDescriptionPart = ModLoaders.Join(" / ")
|
||||
ModLoaderDescriptionFull = ModLoadersForDesc.Join(" / ")
|
||||
ModLoaderDescriptionPart = ModLoadersForDesc.Join(" / ")
|
||||
End If
|
||||
Case Else
|
||||
ModLoaderDescriptionFull = "任意"
|
||||
ModLoaderDescriptionPart = ""
|
||||
End Select
|
||||
'实例化 UI
|
||||
Dim NewItem As New MyCompItem With {.Tag = Me, .Logo = GetControlLogo()}
|
||||
@@ -583,9 +589,9 @@
|
||||
'有中文翻译
|
||||
'尝试将文本分为三段:Title (EnglishName) - Suffix
|
||||
'检查时注意 Carpet:它没有中文译名,但有 Suffix
|
||||
Title = TranslatedName.Before(" (").Before(" - ")
|
||||
Title = TranslatedName.BeforeFirst(" (").BeforeFirst(" - ")
|
||||
Dim Suffix As String = ""
|
||||
If TranslatedName.After(")").Contains(" - ") Then Suffix = TranslatedName.After(")").After(" - ")
|
||||
If TranslatedName.AfterLast(")").Contains(" - ") Then Suffix = TranslatedName.AfterLast(")").AfterLast(" - ")
|
||||
Dim EnglishName As String = TranslatedName
|
||||
If Suffix <> "" Then EnglishName = EnglishName.Replace(" - " & Suffix, "")
|
||||
EnglishName = EnglishName.Replace(Title, "").Trim("("c, ")"c, " "c)
|
||||
@@ -758,7 +764,7 @@ NoSubtitle:
|
||||
Case CompType.ResourcePack
|
||||
'FUTURE: Res
|
||||
End Select
|
||||
Address += "&categoryId=" & If(Tag = "", "0", Tag.Before("/"))
|
||||
Address += "&categoryId=" & If(Tag = "", "0", Tag.BeforeFirst("/"))
|
||||
If ModLoader <> CompModLoaderType.Any Then Address += "&modLoaderType=" & CType(ModLoader, Integer)
|
||||
If Not String.IsNullOrEmpty(GameVersion) Then Address += "&gameVersion=" & GameVersion
|
||||
If Not String.IsNullOrEmpty(SearchText) Then Address += "&searchFilter=" & Net.WebUtility.UrlEncode(SearchText)
|
||||
@@ -779,7 +785,7 @@ NoSubtitle:
|
||||
'facets=[["categories:'game-mechanics'"],["categories:'forge'"],["versions:1.19.3"],["project_type:mod"]]
|
||||
Dim Facets As New List(Of String)
|
||||
Facets.Add($"[""project_type:{GetStringFromEnum(Type).ToLower}""]")
|
||||
If Not String.IsNullOrEmpty(Tag) Then Facets.Add($"[""categories:'{Tag.After("/")}'""]")
|
||||
If Not String.IsNullOrEmpty(Tag) Then Facets.Add($"[""categories:'{Tag.AfterLast("/")}'""]")
|
||||
If ModLoader <> CompModLoaderType.Any Then Facets.Add($"[""categories:'{GetStringFromEnum(ModLoader).ToLower}'""]")
|
||||
If Not String.IsNullOrEmpty(GameVersion) Then Facets.Add($"[""versions:'{GameVersion}'""]")
|
||||
Address += "&facets=[" & String.Join(",", Facets) & "]"
|
||||
@@ -887,7 +893,7 @@ NoSubtitle:
|
||||
If Not SearchResults(i).AbsoluteRight AndAlso i >= Math.Min(2, SearchResults.Count - 1) Then Exit For '把 3 个结果拼合以提高准确度
|
||||
If SearchResults(i).Item.CurseForgeSlug IsNot Nothing Then SearchResult += SearchResults(i).Item.CurseForgeSlug.Replace("-", " ").Replace("/", " ") & " "
|
||||
If SearchResults(i).Item.ModrinthSlug IsNot Nothing Then SearchResult += SearchResults(i).Item.ModrinthSlug.Replace("-", " ").Replace("/", " ") & " "
|
||||
SearchResult += SearchResults(i).Item.ChineseName.After(" (").TrimEnd(") ").Before(" - ").
|
||||
SearchResult += SearchResults(i).Item.ChineseName.AfterLast(" (").TrimEnd(") ").BeforeFirst(" - ").
|
||||
Replace(":", "").Replace("(", "").Replace(")", "").ToLower.Replace("/", " ") & " "
|
||||
Next
|
||||
Log("[Comp] 中文搜索原始关键词:" & SearchResult, LogLevel.Developer)
|
||||
@@ -1156,7 +1162,7 @@ Retry:
|
||||
''' </summary>
|
||||
Public ReadOnly ModLoaders As List(Of CompModLoaderType)
|
||||
''' <summary>
|
||||
''' 支持的游戏版本列表。类型包括:"1.18.5","1.18","1.18 快照","21w15a","未知版本"。
|
||||
''' 支持的游戏版本列表。类型包括:"1.18.5","1.18","1.18 预览版","21w15a","未知版本"。
|
||||
''' </summary>
|
||||
Public ReadOnly GameVersions As List(Of String)
|
||||
''' <summary>
|
||||
@@ -1272,7 +1278,7 @@ Retry:
|
||||
End If
|
||||
'GameVersions
|
||||
Dim RawVersions As List(Of String) = Data("gameVersions").Select(Function(t) t.ToString.Trim.ToLower).ToList
|
||||
GameVersions = RawVersions.Where(Function(v) v.StartsWithF("1.")).Select(Function(v) v.Replace("-snapshot", " 快照")).ToList
|
||||
GameVersions = RawVersions.Where(Function(v) v.StartsWithF("1.")).Select(Function(v) v.Replace("-snapshot", " 预览版")).ToList
|
||||
If GameVersions.Count > 1 Then
|
||||
GameVersions = Sort(GameVersions, AddressOf VersionSortBoolean).ToList
|
||||
If Type = CompType.ModPack Then GameVersions = New List(Of String) From {GameVersions(0)}
|
||||
@@ -1313,7 +1319,7 @@ Retry:
|
||||
'GameVersions
|
||||
Dim RawVersions As List(Of String) = Data("game_versions").Select(Function(t) t.ToString.Trim.ToLower).ToList
|
||||
GameVersions = RawVersions.Where(Function(v) v.StartsWithF("1.") OrElse v.StartsWithF("b1.")).
|
||||
Select(Function(v) If(v.Contains("-"), v.Before("-") & " 快照", If(v.StartsWithF("b1."), "远古版本", v))).ToList
|
||||
Select(Function(v) If(v.Contains("-"), v.BeforeFirst("-") & " 预览版", If(v.StartsWithF("b1."), "远古版本", v))).ToList
|
||||
If GameVersions.Count > 1 Then
|
||||
GameVersions = Sort(GameVersions, AddressOf VersionSortBoolean).ToList
|
||||
If Type = CompType.ModPack Then GameVersions = New List(Of String) From {GameVersions(0)}
|
||||
@@ -1362,28 +1368,26 @@ Retry:
|
||||
Optional BadDisplayName As Boolean = False) As MyListItem
|
||||
|
||||
'获取描述信息
|
||||
Dim Info As String = ""
|
||||
Dim Title As String = If(BadDisplayName, FileName, DisplayName)
|
||||
Dim Info As New List(Of String)
|
||||
If Title <> FileName.BeforeLast(".") Then Info.Add(FileName.BeforeLast("."))
|
||||
Select Case Type
|
||||
Case CompType.Mod
|
||||
Info += If(ModLoaders.Any,
|
||||
"适用于 " & Join(ModLoaders.Select(Function(m) GetStringFromEnum(m)).ToList, "/") & ",", "")
|
||||
Info += If(ModeDebug AndAlso Dependencies.Any, Dependencies.Count & " 个前置 Mod,", "")
|
||||
If Dependencies.Any Then Info.Add(Dependencies.Count & " 个前置 Mod")
|
||||
Case CompType.ModPack
|
||||
If GameVersions.All(Function(v) v.Contains("w")) Then
|
||||
Info += $"游戏版本 {Join(GameVersions, "、")},"
|
||||
End If
|
||||
If GameVersions.All(Function(v) v.Contains("w")) Then Info.Add($"游戏版本 {Join(GameVersions, "、")}")
|
||||
End Select
|
||||
If DownloadCount > 0 Then 'CurseForge 的下载次数经常错误地返回 0
|
||||
Info += If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载,", DownloadCount & " 次下载,")
|
||||
Info.Add("下载 " & If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次", DownloadCount & " 次"))
|
||||
End If
|
||||
Info += GetTimeSpanString(ReleaseDate - Date.Now, False) & "更新"
|
||||
Info += If(Status = CompFileStatus.Release, "", "," & StatusDescription)
|
||||
Info.Add("更新于 " & GetTimeSpanString(ReleaseDate - Date.Now, False))
|
||||
If Status <> CompFileStatus.Release Then Info.Add(StatusDescription)
|
||||
|
||||
'建立控件
|
||||
Dim NewItem As New MyListItem With {
|
||||
.Title = If(BadDisplayName, FileName, DisplayName),
|
||||
.Title = Title,
|
||||
.SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Me,
|
||||
.Info = Info
|
||||
.Info = Info.Join(",")
|
||||
}
|
||||
Select Case Status
|
||||
Case CompFileStatus.Release
|
||||
@@ -1422,14 +1426,12 @@ Retry:
|
||||
''' <summary>
|
||||
''' 已知文件信息的缓存。
|
||||
''' </summary>
|
||||
Private CompFilesCache As New Dictionary(Of String, List(Of CompFile))
|
||||
Public CompFilesCache As New Dictionary(Of String, List(Of CompFile))
|
||||
''' <summary>
|
||||
''' 获取某个工程下的全部文件列表。
|
||||
''' 必须在工作线程执行,失败会抛出异常。
|
||||
''' </summary>
|
||||
Public Function CompFilesGet(ProjectId As String, FromCurseForge As Boolean) As List(Of CompFile)
|
||||
'使用缓存
|
||||
If CompFilesCache.ContainsKey(ProjectId) Then Return CompFilesCache(ProjectId)
|
||||
'获取工程对象
|
||||
Dim TargetProject As CompProject
|
||||
If CompProjectCache.ContainsKey(ProjectId) Then '存在缓存
|
||||
@@ -1440,25 +1442,26 @@ Retry:
|
||||
TargetProject = New CompProject(DlModRequest("https://api.modrinth.com/v2/project/" & ProjectId, IsJson:=True))
|
||||
End If
|
||||
'获取工程对象的文件列表
|
||||
Log("[Comp] 开始获取文件列表:" & ProjectId)
|
||||
Dim ResultJsonArray As JArray
|
||||
If FromCurseForge Then
|
||||
'CurseForge
|
||||
If TargetProject.Type = CompType.Mod Then 'Mod 使用每个版本最新的文件
|
||||
ResultJsonArray = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json"))("data")
|
||||
Else '否则使用全部文件
|
||||
ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999", IsJson:=True)("data")
|
||||
If Not CompFilesCache.ContainsKey(ProjectId) Then '有缓存也不能直接返回,这时候前置 Mod 可能没获取(#5173)
|
||||
Log("[Comp] 开始获取文件列表:" & ProjectId)
|
||||
Dim ResultJsonArray As JArray
|
||||
If FromCurseForge Then
|
||||
'CurseForge
|
||||
If TargetProject.Type = CompType.Mod Then 'Mod 使用每个版本最新的文件
|
||||
ResultJsonArray = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json"))("data")
|
||||
Else '否则使用全部文件
|
||||
ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999", IsJson:=True)("data")
|
||||
End If
|
||||
Else
|
||||
'Modrinth
|
||||
ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version", IsJson:=True)
|
||||
End If
|
||||
Else
|
||||
'Modrinth
|
||||
ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version", IsJson:=True)
|
||||
CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
|
||||
Where(Function(a) a.Available).ToList.Distinct(Function(a, b) a.Id = b.Id) 'CurseForge 可能会重复返回相同项(#1330)
|
||||
End If
|
||||
CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
|
||||
Where(Function(a) a.Available).ToList.Distinct(Function(a, b) a.Id = b.Id) 'CurseForge 可能会重复返回相同项(#1330)
|
||||
'获取前置 Mod 列表
|
||||
If TargetProject.Type <> CompType.Mod Then Return CompFilesCache(ProjectId)
|
||||
Dim Deps As List(Of String) = CompFilesCache(ProjectId).
|
||||
SelectMany(Function(f) f.RawDependencies).Distinct().ToList
|
||||
Dim Deps As List(Of String) = CompFilesCache(ProjectId).SelectMany(Function(f) f.RawDependencies).Distinct().ToList
|
||||
Dim UndoneDeps = Deps.Where(Function(f) Not CompProjectCache.ContainsKey(f)).ToList
|
||||
'获取前置 Mod 工程信息
|
||||
If UndoneDeps.Any Then
|
||||
|
||||
@@ -381,6 +381,7 @@ Extracted:
|
||||
没有可用的分析文件
|
||||
使用32位Java导致JVM无法分配足够多的内存
|
||||
Mod重复安装
|
||||
Mod互不兼容
|
||||
OptiFine与Forge不兼容
|
||||
Fabric报错
|
||||
Fabric报错并给出解决方案
|
||||
@@ -389,7 +390,7 @@ Extracted:
|
||||
版本Json中存在多个Forge
|
||||
Mod过多导致超出ID限制
|
||||
NightConfig的Bug
|
||||
ShadersMod与Optifine同时安装
|
||||
ShadersMod与OptiFine同时安装
|
||||
Forge安装不完整
|
||||
Mod需要Java11
|
||||
Mod缺少前置或MC版本错误
|
||||
@@ -413,7 +414,7 @@ Extracted:
|
||||
'崩溃日志
|
||||
If LogCrash IsNot Nothing Then
|
||||
Log("[Crash] 开始进行崩溃日志堆栈分析")
|
||||
Keywords.AddRange(AnalyzeStackKeyword(LogCrash.Before("System Details")))
|
||||
Keywords.AddRange(AnalyzeStackKeyword(LogCrash.BeforeFirst("System Details")))
|
||||
End If
|
||||
'Minecraft 日志
|
||||
If LogMc IsNot Nothing Then
|
||||
@@ -516,7 +517,7 @@ Done:
|
||||
If LogMc.Contains("java.lang.ClassNotFoundException: org.spongepowered.asm.launch.MixinTweaker") Then AppendReason(CrashReason.MixinBootstrap缺失)
|
||||
If LogMc.Contains("Couldn't set pixel format") Then AppendReason(CrashReason.显卡驱动不支持导致无法设置像素格式)
|
||||
If LogMc.Contains("java.lang.OutOfMemoryError") OrElse LogMc.Contains("an out of memory error") Then AppendReason(CrashReason.内存不足)
|
||||
If LogMc.Contains("java.lang.RuntimeException: Shaders Mod detected. Please remove it, OptiFine has built-in support for shaders.") Then AppendReason(CrashReason.ShadersMod与Optifine同时安装)
|
||||
If LogMc.Contains("java.lang.RuntimeException: Shaders Mod detected. Please remove it, OptiFine has built-in support for shaders.") Then AppendReason(CrashReason.ShadersMod与OptiFine同时安装)
|
||||
If LogMc.Contains("java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier") Then AppendReason(CrashReason.低版本Forge与高版本Java不兼容)
|
||||
If LogMc.Contains("1282: Invalid operation") Then AppendReason(CrashReason.光影或资源包导致OpenGL1282错误)
|
||||
If LogMc.Contains("signer information does not match signer information of other classes in the same package") Then AppendReason(CrashReason.文件或内容校验失败, If(RegexSeek(LogMc, "(?<=class "")[^']+(?=""'s signer information)"), "").TrimEnd(vbCrLf))
|
||||
@@ -525,6 +526,7 @@ Done:
|
||||
If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
|
||||
If LogMc.Contains("com.electronwill.nightconfig.core.io.ParsingException: Not enough data available") Then AppendReason(CrashReason.NightConfig的Bug)
|
||||
If LogMc.Contains("Cannot find launch target fmlclient, unable to launch") Then AppendReason(CrashReason.Forge安装不完整)
|
||||
If LogMc.Contains("Invalid paths argument, contained no existing paths") AndAlso LogMc.Contains("libraries\net\minecraftforge\fmlcore") Then AppendReason(CrashReason.Forge安装不完整)
|
||||
If LogMc.Contains("Invalid module name: '' is not a Java identifier") Then AppendReason(CrashReason.Mod名称包含特殊字符)
|
||||
If LogMc.Contains("has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to") Then AppendReason(CrashReason.Mod需要Java11)
|
||||
If LogMc.Contains("java.lang.RuntimeException: java.lang.NoSuchMethodException: no such method: sun.misc.Unsafe.defineAnonymousClass(Class,byte[],Object[])Class/invokeVirtual") Then AppendReason(CrashReason.Mod需要Java11)
|
||||
@@ -540,12 +542,14 @@ Done:
|
||||
End If
|
||||
'确定的 Mod 导致崩溃
|
||||
If LogMc.Contains("Caught exception from ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(RegexSeek(LogMc, "(?<=Caught exception from )[^\n]+?")?.TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||
'Mod 重复安装
|
||||
'Mod 重复 / 前置问题
|
||||
If LogMc.Contains("DuplicateModsFoundException") Then AppendReason(CrashReason.Mod重复安装, RegexSearch(LogMc, "(?<=\n\t[\w]+ : [A-Z]{1}:[^\n]+(/|\\))[^/\\\n]+?.jar", RegularExpressions.RegexOptions.IgnoreCase))
|
||||
If LogMc.Contains("Found a duplicate mod") Then AppendReason(CrashReason.Mod重复安装, RegexSearch(If(RegexSeek(LogMc, "Found a duplicate mod[^\n]+"), ""), "[^\\/]+.jar", RegularExpressions.RegexOptions.IgnoreCase))
|
||||
If LogMc.Contains("Found duplicate mods") Then AppendReason(CrashReason.Mod重复安装, RegexSearch(LogMc, "(?<=Mod ID: ')\w+?(?=' from mod files:)").Distinct.ToList)
|
||||
If LogMc.Contains("ModResolutionException: Duplicate") Then AppendReason(CrashReason.Mod重复安装, RegexSearch(If(RegexSeek(LogMc, "ModResolutionException: Duplicate[^\n]+"), ""), "[^\\/]+.jar", RegularExpressions.RegexOptions.IgnoreCase))
|
||||
'Mod 缺少前置
|
||||
If LogMc.Contains("Incompatible mods found!") Then '#5006
|
||||
AppendReason(CrashReason.Mod互不兼容, If(RegexSeek(LogMc, "(?<=Incompatible mods found![\s\S]+: )[\s\S]+?(?=\tat )"), ""))
|
||||
End If
|
||||
If LogMc.Contains("Missing or unsupported mandatory dependencies:") Then
|
||||
AppendReason(CrashReason.Mod缺少前置或MC版本错误,
|
||||
RegexSearch(LogMc, "(?<=Missing or unsupported mandatory dependencies:)([\n\r]+\t(.*))+", RegularExpressions.RegexOptions.IgnoreCase).
|
||||
@@ -591,40 +595,57 @@ Done:
|
||||
''' </summary>
|
||||
Private Sub AnalyzeCrit2()
|
||||
|
||||
'Mixin 分析
|
||||
Dim MixinAnalyze =
|
||||
Function(LogText As String) As Boolean
|
||||
Dim IsMixin As Boolean =
|
||||
LogText.Contains("Mixin prepare failed ") OrElse LogText.Contains("Mixin apply failed ") OrElse
|
||||
LogText.Contains("MixinApplyError") OrElse LogText.Contains("MixinTransformerError") OrElse
|
||||
LogText.Contains("mixin.injection.throwables.") OrElse LogText.Contains(".json] FAILED during )")
|
||||
If Not IsMixin Then Return False
|
||||
'Mod 名称匹配
|
||||
Dim ModName As String = RegexSeek(LogText, "(?<=from mod )[^.\/ ]+(?=\] from)")
|
||||
If ModName Is Nothing Then ModName = RegexSeek(LogText, "(?<=for mod )[^.\/ ]+(?= failed)")
|
||||
If ModName IsNot Nothing Then
|
||||
AppendReason(CrashReason.ModMixin失败, TryAnalyzeModName(ModName.TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||
Return True
|
||||
End If
|
||||
'JSON 名称匹配
|
||||
For Each JsonName In RegexSearch(LogText, "(?<=^[^\t]+[ \[{(]{1})[^ \[{(]+\.[^ ]+(?=\.json)", RegularExpressions.RegexOptions.Multiline)
|
||||
AppendReason(CrashReason.ModMixin失败,
|
||||
TryAnalyzeModName(JsonName.Replace("mixins", "mixin").Replace(".mixin", "").Replace("mixin.", "")))
|
||||
Return True
|
||||
Next
|
||||
'没有明确匹配
|
||||
AppendReason(CrashReason.ModMixin失败)
|
||||
Return True
|
||||
End Function
|
||||
|
||||
'游戏日志分析
|
||||
If LogMc IsNot Nothing Then
|
||||
'Mixin 崩溃
|
||||
Dim IsMixin As Boolean = MixinAnalyze(LogMc)
|
||||
'常规信息
|
||||
If LogMc.Contains("An exception was thrown, the game will display an error screen and halt.") Then AppendReason(CrashReason.Forge报错, RegexSeek(LogMc, "(?<=the game will display an error screen and halt.[\n\r]+[^\n]+?Exception: )[\s\S]+?(?=\n\tat)")?.Trim(vbCrLf))
|
||||
If LogMc.Contains("A potential solution has been determined:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("A potential solution has been determined, this may resolve your problem:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined, this may resolve your problem:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("确定了一种可能的解决方法,这样做可能会解决你的问题:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=确定了一种可能的解决方法,这样做可能会解决你的问题:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
'Mixin 崩溃
|
||||
If LogMc.Contains("Mixin prepare failed ") OrElse LogMc.Contains("Mixin apply failed ") OrElse LogMc.Contains("MixinApplyError") OrElse
|
||||
LogMc.Contains("mixin.injection.throwables.") OrElse LogMc.Contains(".json] FAILED during )") Then
|
||||
Dim ModId As String = RegexSeek(LogMc, "(?<=in )[^./ ]+(?=.mixins.json.+failed injection check)")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=in mixins.)[^./ ]+(?=.json.+failed injection check)")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed .+ in )[^./ ]+(?=.mixins.json)")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed .+ in mixins.)[^./ ]+(?=.json)")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed mixins.)[^./ ]+(?=.json:)")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= in config \[)[^./ ]+(?=.mixins.json\] FAILED during )")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= in config \[mixins.)[^./ ]+(?=.json\] FAILED during )")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=from mod )[^./ ]+(?=\] from)")
|
||||
If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=for mod )[^./ ]+(?= failed)")
|
||||
'兜底名称判断
|
||||
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)))
|
||||
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)))
|
||||
If Not IsMixin AndAlso LogMc.Contains("due to errors, provided by ") Then '在 #3104 的情况下,这一句导致 OptiFabric 的 Mixin 失败错判为 Fabric Loader 加载失败
|
||||
AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogMc, "(?<=due to errors, provided by ')[^']+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||
End If
|
||||
End If
|
||||
|
||||
'崩溃报告分析
|
||||
If LogCrash IsNot Nothing Then
|
||||
'Mixin 崩溃
|
||||
MixinAnalyze(LogCrash)
|
||||
'常规信息
|
||||
If LogCrash.Contains("Suspected Mod") Then
|
||||
Dim Suspects = RegexSearch(LogCrash.Between("Suspected Mod", "Stacktrace"), "(?<=\n\t[^(\t]+\()[^)\n]+")
|
||||
If Suspects.Any Then AppendReason(CrashReason.怀疑Mod导致游戏崩溃, TryAnalyzeModName(Suspects))
|
||||
Dim SuspectsRaw As String = LogCrash.Between("Suspected Mod", "Stacktrace")
|
||||
If Not SuspectsRaw.StartsWithF("s: None") Then 'Suspected Mods: None
|
||||
Dim Suspects = RegexSearch(SuspectsRaw, "(?<=\n\t[^(\t]+\()[^)\n]+")
|
||||
If Suspects.Any Then AppendReason(CrashReason.怀疑Mod导致游戏崩溃, TryAnalyzeModName(Suspects))
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
|
||||
@@ -640,6 +661,8 @@ Done:
|
||||
If Not (LogMc.Contains("at net.") OrElse LogMc.Contains("INFO]")) AndAlso LogHs Is Nothing AndAlso LogCrash Is Nothing AndAlso LogMc.Length < 100 Then
|
||||
AppendReason(CrashReason.极短的程序输出, LogMc)
|
||||
End If
|
||||
'Mod 解析错误(常见于 Fabric 前置校验失败)
|
||||
If LogMc.Contains("Mod resolution failed") Then AppendReason(CrashReason.Mod加载器报错)
|
||||
'Mixin 失败可以导致大量 Mod 实例创建失败
|
||||
If LogMc.Contains("Failed to create mod instance.") Then AppendReason(CrashReason.Mod初始化失败, TryAnalyzeModName(If(RegexSeek(LogMc, "(?<=Failed to create mod instance. ModID: )[^,]+"), If(RegexSeek(LogMc, "(?<=Failed to create mod instance. ModId )[^\n]+(?= for )"), "")).TrimEnd(vbCrLf)))
|
||||
'注意:Fabric 的 Warnings were found! 不一定是崩溃原因,它可能是单纯的警报
|
||||
@@ -695,7 +718,7 @@ NextStack:
|
||||
If {"com", "org", "net", "asm", "fml", "mod", "jar", "sun", "lib", "map", "gui", "dev", "nio", "api", "dsi", "top", "mcp",
|
||||
"core", "init", "mods", "main", "file", "game", "load", "read", "done", "util", "tile", "item", "base", "oshi", "impl", "data", "pool", "task",
|
||||
"forge", "setup", "block", "model", "mixin", "event", "unimi", "netty", "world",
|
||||
"gitlab", "common", "server", "config", "loader", "launch", "entity", "assist", "client", "plugin", "modapi", "mojang", "shader", "events", "github", "recipe", "render", "packet", "events",
|
||||
"gitlab", "common", "server", "config", "mixins", "compat", "loader", "launch", "entity", "assist", "client", "plugin", "modapi", "mojang", "shader", "events", "github", "recipe", "render", "packet", "events",
|
||||
"preinit", "preload", "machine", "reflect", "channel", "general", "handler", "content", "systems", "modules", "service",
|
||||
"fastutil", "optifine", "internal", "platform", "override", "fabricmc", "neoforge",
|
||||
"injection", "listeners", "scheduler", "minecraft", "transformer", "transformers", "neoforged", "universal", "multipart", "minecraftforge", "blockentity", "spongepowered", "electronwill"
|
||||
@@ -738,13 +761,13 @@ NextStack:
|
||||
Details = Details.Replace("Fabric Mods", "¨")
|
||||
Log("[Crash] 崩溃报告中检测到 Fabric Mod 信息格式")
|
||||
End If
|
||||
Details = Details.After("¨")
|
||||
Details = Details.AfterLast("¨")
|
||||
|
||||
'[Forge] 获取所有包含 .jar 的行
|
||||
'[Fabric] 获取所有包含 Mod 信息的行
|
||||
Dim ModNameLines As New List(Of String)
|
||||
For Each Line In Details.Split(vbLf)
|
||||
If Line.ContainsF(".jar", True) OrElse
|
||||
If (Line.ContainsF(".jar", True) AndAlso Line.Length - Line.Replace(".jar", "").Length = 4) OrElse '只有一个 .jar
|
||||
(IsFabricDetail AndAlso Line.StartsWithF(vbTab & vbTab) AndAlso Not RegexCheck(Line, "\t\tfabric[\w-]*: Fabric")) Then ModNameLines.Add(Line)
|
||||
Next
|
||||
Log("[Crash] 崩溃报告中找到 " & ModNameLines.Count & " 个可能的 Mod 项目行")
|
||||
@@ -873,19 +896,23 @@ NextStack:
|
||||
If ExtraFiles IsNot Nothing Then OutputFiles.AddRange(ExtraFiles)
|
||||
For Each OutputFile In OutputFiles
|
||||
Dim FileName As String = GetFileNameFromPath(OutputFile)
|
||||
Dim FileEncoding As Encoding = Nothing
|
||||
Select Case FileName
|
||||
Case "LatestLaunch.bat"
|
||||
FileName = "启动脚本.bat"
|
||||
Case "Log1.txt"
|
||||
FileName = "PCL 启动器日志.txt"
|
||||
FileEncoding = Encoding.UTF8
|
||||
Case "RawOutput.log"
|
||||
FileName = "游戏崩溃前的输出.txt"
|
||||
FileEncoding = Encoding.UTF8
|
||||
End Select
|
||||
If File.Exists(OutputFile) Then
|
||||
Dim FileEncoding As Encoding = GetEncoding(ReadFileBytes(OutputFile))
|
||||
If FileEncoding Is Nothing Then FileEncoding = GetEncoding(ReadFileBytes(OutputFile))
|
||||
WriteFile(TempFolder & "Report\" & FileName,
|
||||
SecretFilter(ReadFile(OutputFile, FileEncoding), If(FileName = "启动脚本.bat", "F", "*")),
|
||||
Encoding:=FileEncoding)
|
||||
Log($"[Crash] 导出文件:{FileName},编码:{FileEncoding.HeaderName}")
|
||||
End If
|
||||
Next
|
||||
'导出报告
|
||||
@@ -909,7 +936,7 @@ NextStack:
|
||||
If IsHandAnalyze Then
|
||||
Return "很抱歉,PCL 无法确定错误原因。"
|
||||
Else
|
||||
Return $"很抱歉,你的游戏出现了一些问题……{vbCrLf}如果要寻求帮助,请导出错误报告并发给他人,而不是发送这个窗口的截图。"
|
||||
Return $"很抱歉,你的游戏出现了一些问题……{vbCrLf}如果要寻求帮助,请把错误报告文件发给对方,而不是发送这个窗口的照片或者截图。"
|
||||
End If
|
||||
End If
|
||||
|
||||
@@ -942,9 +969,9 @@ NextStack:
|
||||
End If
|
||||
Case CrashReason.Mod缺少前置或MC版本错误
|
||||
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
|
||||
Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
Results.Add("由于未安装正确的前置 Mod,导致游戏退出。\n请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
End If
|
||||
Case CrashReason.堆栈分析发现关键字
|
||||
If Additional.Count = 1 Then
|
||||
@@ -965,7 +992,9 @@ NextStack:
|
||||
Results.Add("以下 Mod 导致了游戏出错:\n - " & Join(Additional, "\n - ") & "\n\n你可以尝试依次禁用上述 Mod,然后观察游戏是否还会崩溃。\n\e\h")
|
||||
End If
|
||||
Case CrashReason.ModMixin失败
|
||||
If Additional.Count = 1 Then
|
||||
If Additional.Count = 0 Then
|
||||
Results.Add("部分 Mod 注入失败,导致游戏出错。\n这一般代表着部分 Mod 与其他 Mod 或当前环境不兼容,或是它存在 Bug。\n你可以尝试逐步禁用 Mod,然后观察游戏是否还会崩溃,以此定位导致崩溃的 Mod。\n\e\h")
|
||||
ElseIf Additional.Count = 1 Then
|
||||
Results.Add("名为 " & Additional.First & " 的 Mod 注入失败,导致游戏出错。\n这一般代表着它与其他 Mod 或当前环境不兼容,或是它存在 Bug。\n你可以尝试禁用此 Mod,然后观察游戏是否还会崩溃。\n\e\h")
|
||||
Else
|
||||
Results.Add("以下 Mod 导致了游戏出错:\n - " & Join(Additional, "\n - ") & "\n这一般代表着它们与其他 Mod 或当前环境不兼容,或是它存在 Bug。\n你可以尝试依次禁用上述 Mod,然后观察游戏是否还会崩溃。\n\e\h")
|
||||
@@ -980,7 +1009,7 @@ NextStack:
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("名为 " & Additional.First & " 的 Mod 初始化失败,导致游戏无法继续加载。\n你可以尝试禁用此 Mod,然后观察游戏是否还会崩溃。\n\e\h")
|
||||
Else
|
||||
Results.Add("以下 Mod 初始化失败,导致游戏无法继续加载:\n - " & Join(Additional, "\n - ") & "\n\n你可以尝试依次禁用上述 Mod,然后观察游戏是否还会崩溃。\n\e\h")
|
||||
Results.Add("以下 Mod 初始化失败,导致游戏出错:\n - " & Join(Additional, "\n - ") & "\n\n你可以尝试依次禁用上述 Mod,然后观察游戏是否还会崩溃。\n\e\h")
|
||||
End If
|
||||
Case CrashReason.特定方块导致崩溃
|
||||
If Additional.Count = 1 Then
|
||||
@@ -992,7 +1021,7 @@ NextStack:
|
||||
If Additional.Count >= 2 Then
|
||||
Results.Add("你重复安装了多个相同的 Mod:\n - " & Join(Additional, "\n - ") & "\n\n每个 Mod 只能出现一次,请删除重复的 Mod,然后再启动游戏。")
|
||||
Else
|
||||
Results.Add("你可能重复安装了多个相同的 Mod,导致游戏无法继续加载。\n\n每个 Mod 只能出现一次,请删除重复的 Mod,然后再启动游戏。\e\h")
|
||||
Results.Add("你可能重复安装了多个相同的 Mod,导致游戏出错。\n\n每个 Mod 只能出现一次,请删除重复的 Mod,然后再启动游戏。\e\h")
|
||||
End If
|
||||
Case CrashReason.特定实体导致崩溃
|
||||
If Additional.Count = 1 Then
|
||||
@@ -1002,12 +1031,12 @@ NextStack:
|
||||
End If
|
||||
Case CrashReason.OptiFine与Forge不兼容
|
||||
Results.Add("由于 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n\n请前往 OptiFine 官网(https://optifine.net/downloads)查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏。")
|
||||
Case CrashReason.ShadersMod与Optifine同时安装
|
||||
Results.Add("无需同时安装 Optifine 和 Shaders Mod,Optifine 已经集成了 Shaders Mod 的功能。\n在删除 Shaders Mod 后,游戏即可正常运行。")
|
||||
Case CrashReason.ShadersMod与OptiFine同时安装
|
||||
Results.Add("无需同时安装 Optifine 和 Shaders Mod,OptiFine 已经集成了 Shaders Mod 的功能。\n在删除 Shaders Mod 后,游戏即可正常运行。")
|
||||
Case CrashReason.低版本Forge与高版本Java不兼容
|
||||
Results.Add("由于低版本 Forge 与当前 Java 不兼容,导致了游戏崩溃。\n\n请尝试以下解决方案:\n - 更新 Forge 到 36.2.26 或更高版本\n - 换用版本低于 1.8.0.320 的 Java")
|
||||
Case CrashReason.版本Json中存在多个Forge
|
||||
Results.Add("可能由于使用其他启动器修改了 Forge 版本,当前版本的文件存在异常,导致了游戏崩溃。\n请尝试重新全新安装 Forge,而非使用其他启动器修改 Forge 版本。")
|
||||
Results.Add("可能由于其他启动器修改了 Forge 版本,当前版本的文件存在异常,导致了游戏崩溃。\n请尝试重新全新安装 Forge,而非使用其他启动器修改 Forge 版本。")
|
||||
Case CrashReason.玩家手动触发调试崩溃
|
||||
Results.Add("* 事实上,你的游戏没有任何问题,这是你自己触发的崩溃。\n* 你难道没有更重要的事要做吗?")
|
||||
Case CrashReason.Mod需要Java11
|
||||
@@ -1033,30 +1062,36 @@ NextStack:
|
||||
Case CrashReason.文件或内容校验失败
|
||||
Results.Add("部分文件或内容校验失败,导致游戏出现了问题。\n\n请尝试删除游戏(包括 Mod)并重新下载,或尝试在重新下载时使用 VPN。\h")
|
||||
Case CrashReason.Forge安装不完整
|
||||
Results.Add("由于 Forge 安装不完整,导致游戏无法正常运行。\n请尝试重新安装 Forge。\h")
|
||||
Results.Add("由于安装的 Forge 文件丢失,导致游戏无法正常运行。\n请重新安装一次相同版本的 Forge,然后再启动游戏。\n在打包游戏时删除 libraries 文件夹可能导致此错误。\h")
|
||||
Case CrashReason.Fabric报错
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("Fabric 提供了以下错误信息:\n" & Additional.First & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
||||
Else
|
||||
Results.Add("Fabric 可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。\h")
|
||||
Results.Add("Fabric 可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
End If
|
||||
Case CrashReason.Mod互不兼容
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("你所安装的 Mod 不兼容:\n" & Additional.First & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
||||
Else
|
||||
Results.Add("你所安装的 Mod 不兼容,Mod 加载器可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
End If
|
||||
Case CrashReason.Mod加载器报错
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("Mod 加载器提供了以下错误信息:\n" & Additional.First & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
||||
Else
|
||||
Results.Add("Mod 加载器可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。\h")
|
||||
Results.Add("Mod 加载器可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
End If
|
||||
Case CrashReason.Fabric报错并给出解决方案
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("Fabric 提供了以下解决方案:\n" & Additional.First & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
||||
Else
|
||||
Results.Add("Fabric 可能已经提供了解决方案,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。\h")
|
||||
Results.Add("Fabric 可能已经提供了解决方案,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
End If
|
||||
Case CrashReason.Forge报错
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("Forge 提供了以下错误信息:\n" & Additional.First & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。")
|
||||
Else
|
||||
Results.Add("Forge 可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。\h")
|
||||
Results.Add("Forge 可能已经提供了错误信息,请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h")
|
||||
End If
|
||||
Case CrashReason.没有可用的分析文件
|
||||
Results.Add("你的游戏出现了一些问题,但 PCL 未能找到相关记录文件,因此无法进行分析。\h")
|
||||
@@ -1072,7 +1107,7 @@ NextStack:
|
||||
Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr, vbCrLf).
|
||||
Trim(vbCrLf.ToCharArray) &
|
||||
If(Not Results.Any(Function(r) r.EndsWithF("\h")) OrElse IsHandAnalyze, "",
|
||||
vbCrLf & "如果要寻求帮助,请向他人发送错误报告文件,而不是发送这个窗口的截图。" &
|
||||
vbCrLf & "如果要寻求帮助,请把错误报告文件发给对方,而不是发送这个窗口的照片或者截图。" &
|
||||
If(If(PageSetupSystem.IsLauncherNewest(), True), "",
|
||||
vbCrLf & vbCrLf & "此外,你正在使用老版本 PCL,更新 PCL 或许也能解决这个问题。" & vbCrLf & "你可以点击 设置 → 启动器 → 检查更新 来更新 PCL。"))
|
||||
End Function
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
Task.Output = New List(Of NetFile) From {BackAssetsFile}
|
||||
'检查是否需要更新:每天只更新一次
|
||||
If File.Exists(RealAddress) AndAlso Math.Abs((File.GetLastWriteTime(RealAddress).Date - Now.Date).TotalDays) < 1 Then
|
||||
Log("[Download] 无需更新资源文件索引")
|
||||
Log("[Download] 无需更新资源文件索引,取消")
|
||||
Task.Abort()
|
||||
End If
|
||||
End Sub))
|
||||
@@ -167,24 +167,25 @@
|
||||
End Structure
|
||||
''' <summary>
|
||||
''' Minecraft 客户端 版本列表,主加载器。
|
||||
''' 若要求镜像源必须包含某个版本,则将该版本 ID 作为输入(#5195)。
|
||||
''' </summary>
|
||||
Public DlClientListLoader As New LoaderTask(Of Integer, DlClientListResult)("DlClientList Main", AddressOf DlClientListMain)
|
||||
Private Sub DlClientListMain(Loader As LoaderTask(Of Integer, DlClientListResult))
|
||||
Public DlClientListLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Main", AddressOf DlClientListMain)
|
||||
Private Sub DlClientListMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
Select Case Setup.Get("ToolDownloadVersion")
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)(DlClientListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)(DlClientListMojangLoader, 60)
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)(DlClientListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)(DlClientListMojangLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)(DlClientListMojangLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)(DlClientListBmclapiLoader, 35)
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)(DlClientListMojangLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)(DlClientListBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)(DlClientListMojangLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlClientListResult), Integer)(DlClientListBmclapiLoader, 60)
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)(DlClientListMojangLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of String, DlClientListResult), Integer)(DlClientListBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -193,9 +194,9 @@
|
||||
''' <summary>
|
||||
''' Minecraft 客户端 版本列表,Mojang 官方源加载器。
|
||||
''' </summary>
|
||||
Public DlClientListMojangLoader As New LoaderTask(Of Integer, DlClientListResult)("DlClientList Mojang", AddressOf DlClientListMojangMain)
|
||||
Public DlClientListMojangLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Mojang", AddressOf DlClientListMojangMain)
|
||||
Private IsNewClientVersionHinted As Boolean = False
|
||||
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of Integer, DlClientListResult))
|
||||
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
Dim Json As JObject = NetGetCodeByRequestRetry("https://launchermeta.mojang.com/mc/game/version_manifest.json", IsJson:=True)
|
||||
Try
|
||||
Dim Versions As JArray = Json("versions")
|
||||
@@ -225,14 +226,21 @@
|
||||
''' <summary>
|
||||
''' Minecraft 客户端 版本列表,BMCLAPI 源加载器。
|
||||
''' </summary>
|
||||
Public DlClientListBmclapiLoader As New LoaderTask(Of Integer, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
||||
Private Sub DlClientListBmclapiMain(Loader As LoaderTask(Of Integer, DlClientListResult))
|
||||
Public DlClientListBmclapiLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
||||
Private Sub DlClientListBmclapiMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
Dim Json As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json", IsJson:=True)
|
||||
Try
|
||||
Dim Versions As JArray = Json("versions")
|
||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||
'添加 PCL 特供项
|
||||
If File.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(GetJson(ReadFile(PathTemp & "Cache\download.json")))
|
||||
'检查是否有要求的版本(#5195)
|
||||
If Not String.IsNullOrEmpty(Loader.Input) Then
|
||||
Dim Id = Loader.Input
|
||||
If Not DlClientListLoader.Output.Value("versions").Any(Function(v) v("id") = Id) Then
|
||||
Throw New Exception("BMCLAPI 源未包含目标版本 " & Id)
|
||||
End If
|
||||
End If
|
||||
'返回
|
||||
Loader.Output = New DlClientListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Json}
|
||||
Catch ex As Exception
|
||||
@@ -245,26 +253,31 @@
|
||||
''' </summary>
|
||||
Public Function DlClientListGet(Id As String)
|
||||
Try
|
||||
'确认 Minecraft 版本列表已完成获取
|
||||
Select Case DlClientListLoader.State
|
||||
Case LoadState.Loading
|
||||
DlClientListLoader.WaitForExit()
|
||||
Case LoadState.Failed, LoadState.Aborted, LoadState.Waiting
|
||||
DlClientListLoader.WaitForExit(IsForceRestart:=True)
|
||||
End Select
|
||||
'确认版本格式标准
|
||||
Id = Id.Replace("_", "-") '1.7.10_pre4 在版本列表中显示为 1.7.10-pre4
|
||||
If Id <> "1.0" AndAlso Id.EndsWithF(".0") Then Id = Left(Id, Id.Length - 2) 'OptiFine 1.8 的下载会触发此问题,显示版本为 1.8.0
|
||||
'查找版本并开始
|
||||
'获取 Minecraft 版本列表
|
||||
Select Case DlClientListLoader.State
|
||||
Case LoadState.Finished
|
||||
'从当前的结果获取目标版本…
|
||||
For Each Version As JObject In DlClientListLoader.Output.Value("versions")
|
||||
If Version("id") = Id Then Return Version("url").ToString
|
||||
Next
|
||||
'…如果没有,则重新尝试获取(在版本刚更新时可能出现这种情况,#5195)
|
||||
DlClientListLoader.WaitForExit(Id, IsForceRestart:=True)
|
||||
Case LoadState.Loading
|
||||
DlClientListLoader.WaitForExit(Id)
|
||||
Case LoadState.Failed, LoadState.Aborted, LoadState.Waiting
|
||||
DlClientListLoader.WaitForExit(Id, IsForceRestart:=True)
|
||||
End Select
|
||||
'重新查找版本
|
||||
For Each Version As JObject In DlClientListLoader.Output.Value("versions")
|
||||
If Version("id") = Id Then
|
||||
Return Version("url").ToString
|
||||
End If
|
||||
If Version("id") = Id Then Return Version("url").ToString
|
||||
Next
|
||||
Log("未发现版本 " & Id & " 的 json 下载地址,版本列表返回为:" & vbCrLf & DlClientListLoader.Output.Value.ToString, LogLevel.Debug)
|
||||
Log($"未发现版本 {Id} 的 json 下载地址,版本列表返回为:{vbCrLf}{DlClientListLoader.Output.Value.ToString}", LogLevel.Debug)
|
||||
Return Nothing
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取版本 " & Id & " 的 json 下载地址失败")
|
||||
Log(ex, $"获取版本 {Id} 的 json 下载地址失败")
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
@@ -337,17 +350,17 @@
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListOfficialLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListOfficialLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListOfficialLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListBmclapiLoader, 35)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListOfficialLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListBmclapiLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlOptiFineListResult), Integer)(DlOptiFineListBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -443,17 +456,17 @@
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListOfficialLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListOfficialLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListOfficialLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListBmclapiLoader, 35)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListOfficialLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListBmclapiLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlForgeListResult), Integer)(DlForgeListBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -588,17 +601,17 @@
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionOfficialLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionOfficialLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionOfficialLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionBmclapiLoader, 35)
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionOfficialLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionBmclapiLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of String, List(Of DlForgeVersionEntry)), Integer)(DlForgeVersionBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -780,7 +793,7 @@
|
||||
Inherit = "1.20.1"
|
||||
Else '20.4.30-beta
|
||||
VersionName = ApiName
|
||||
Version = New Version(ApiName.Before("-"))
|
||||
Version = New Version(ApiName.BeforeFirst("-"))
|
||||
Inherit = $"1.{Version.Major}" & If(Version.Minor = 0, "", "." & Version.Minor)
|
||||
End If
|
||||
End Sub
|
||||
@@ -795,17 +808,17 @@
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 35)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListOfficialLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlNeoForgeListResult), Integer)(DlNeoForgeListBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -920,17 +933,17 @@
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListOfficialLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListOfficialLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListOfficialLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListBmclapiLoader, 35)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListOfficialLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListBmclapiLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlLiteLoaderListResult), Integer)(DlLiteLoaderListBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -1019,17 +1032,17 @@
|
||||
Case 0
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListBmclapiLoader, 30),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListOfficialLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListOfficialLoader, 30 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case 1
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListOfficialLoader, 5),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListBmclapiLoader, 35)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListBmclapiLoader, 5 + 30)
|
||||
}, Loader.IsForceRestarting)
|
||||
Case Else
|
||||
DlSourceLoader(Loader, New List(Of KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)) From {
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListOfficialLoader, 60),
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListBmclapiLoader, 60)
|
||||
New KeyValuePair(Of LoaderTask(Of Integer, DlFabricListResult), Integer)(DlFabricListBmclapiLoader, 60 + 60)
|
||||
}, Loader.IsForceRestarting)
|
||||
End Select
|
||||
End Sub
|
||||
@@ -1089,7 +1102,7 @@
|
||||
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
|
||||
If McimUrl <> Url Then
|
||||
Select Case Setup.Get("ToolDownloadMod")
|
||||
'UNDONE: 受 #4811 影响
|
||||
'TODO: 在 MCIM 源稳定后回调
|
||||
Case 0
|
||||
If ModeDebug Then
|
||||
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
||||
@@ -1138,7 +1151,7 @@
|
||||
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
|
||||
If McimUrl <> Url Then
|
||||
Select Case Setup.Get("ToolDownloadMod")
|
||||
'UNDONE: 受 #4811 影响
|
||||
'TODO: 在 MCIM 源稳定后回调
|
||||
Case 0
|
||||
If ModeDebug Then
|
||||
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
||||
@@ -1235,71 +1248,63 @@
|
||||
Optional IsForceRestart As Boolean = False)
|
||||
Dim WaitCycle As Integer = 0
|
||||
Do While True
|
||||
'检查加载结束
|
||||
Dim IsAllFailed As Boolean = True
|
||||
'检查状态
|
||||
Dim BeforeLoadersAllFailed As Boolean = True
|
||||
For Each SubLoader In LoaderList
|
||||
If WaitCycle = 0 Then
|
||||
'如果要强制刷新,就不使用已经加载好的值
|
||||
If IsForceRestart Then Exit For
|
||||
'如果输入不一样,就不使用已经加载好的值
|
||||
If WaitCycle = 0 Then '判断是否可以不加载,直接使用已经加载好的结果
|
||||
If IsForceRestart Then Continue For '强制刷新,不行
|
||||
If (SubLoader.Key.Input Is Nothing Xor MainLoader.Input Is Nothing) OrElse
|
||||
(SubLoader.Key.Input IsNot Nothing AndAlso Not SubLoader.Key.Input.Equals(MainLoader.Input)) Then Continue For
|
||||
(SubLoader.Key.Input IsNot Nothing AndAlso Not SubLoader.Key.Input.Equals(MainLoader.Input)) Then Continue For '父子加载器的输入不一样,也不行
|
||||
End If
|
||||
If SubLoader.Key.State <> LoadState.Failed Then IsAllFailed = False
|
||||
If SubLoader.Key.State <> LoadState.Failed Then BeforeLoadersAllFailed = False
|
||||
If SubLoader.Key.State = LoadState.Finished Then
|
||||
'检查加载器成功
|
||||
MainLoader.Output = SubLoader.Key.Output
|
||||
DlSourceLoaderAbort(LoaderList)
|
||||
Exit Sub
|
||||
ElseIf IsAllFailed Then
|
||||
ElseIf BeforeLoadersAllFailed Then
|
||||
'此前的加载器全部失败,直接启动后续加载器
|
||||
If WaitCycle < SubLoader.Value * 100 Then WaitCycle = SubLoader.Value * 100
|
||||
End If
|
||||
'由于 Forge BMCLAPI 没有可用版本导致强制失败
|
||||
'在没有可用版本时,官方源会一直卡住,直接使用 BMCLAPI 判定失败即可
|
||||
If SubLoader.Key.Error IsNot Nothing AndAlso SubLoader.Key.Error.Message.Contains("没有可用版本") Then
|
||||
For Each SubLoader2 In LoaderList
|
||||
If WaitCycle < SubLoader2.Value * 100 Then WaitCycle = SubLoader2.Value * 100
|
||||
Next
|
||||
End If
|
||||
Next
|
||||
'启动加载源
|
||||
'第一轮时:既然不直接使用已经加载好的结果,那就启动第一个加载器
|
||||
If WaitCycle = 0 Then
|
||||
'启动第一个源
|
||||
LoaderList(0).Key.Start(MainLoader.Input, IsForceRestart)
|
||||
'将其他源标记为未启动,以确保可以切换下载源(#184)
|
||||
For i = 1 To LoaderList.Count - 1
|
||||
LoaderList(i).Key.State = LoadState.Waiting
|
||||
LoaderList.First.Key.Start(MainLoader.Input, IsForceRestart)
|
||||
For Each Loader In LoaderList.Skip(1)
|
||||
Loader.Key.State = LoadState.Waiting '将其他源标记为未启动,以确保可以切换下载源(#184)
|
||||
Next
|
||||
End If
|
||||
'检查加载器失败或超时
|
||||
For i = 0 To LoaderList.Count - 1
|
||||
If WaitCycle = LoaderList(i).Value * 100 Then
|
||||
If i < LoaderList.Count - 1 Then
|
||||
'启动下一个源
|
||||
LoaderList(i + 1).Key.Start(MainLoader.Input, IsForceRestart)
|
||||
Else
|
||||
'失败
|
||||
Dim ErrorInfo As Exception = Nothing
|
||||
For ii = 0 To LoaderList.Count - 1
|
||||
LoaderList(ii).Key.Input = Nothing '重置输入,以免以同样的输入“重试加载”时直接失败
|
||||
If LoaderList(ii).Key.Error IsNot Nothing Then
|
||||
If ErrorInfo Is Nothing OrElse LoaderList(ii).Key.Error.Message.Contains("没有可用版本") Then
|
||||
ErrorInfo = LoaderList(ii).Key.Error
|
||||
End If
|
||||
If WaitCycle <> LoaderList(i).Value * 100 Then Continue For
|
||||
If i < LoaderList.Count - 1 AndAlso Not LoaderList.All(Function(l) l.Key.State = LoadState.Failed) Then
|
||||
'若还有下一个源,则启动下一个源
|
||||
LoaderList(i + 1).Key.Start(MainLoader.Input, IsForceRestart)
|
||||
Else
|
||||
'若没有,则失败
|
||||
Dim ErrorInfo As Exception = Nothing
|
||||
For ii = 0 To LoaderList.Count - 1
|
||||
LoaderList(ii).Key.Input = Nothing '重置输入,以免以同样的输入“重试加载”时直接失败
|
||||
If LoaderList(ii).Key.Error IsNot Nothing Then
|
||||
If ErrorInfo Is Nothing OrElse LoaderList(ii).Key.Error.Message.Contains("没有可用版本") Then
|
||||
ErrorInfo = LoaderList(ii).Key.Error
|
||||
End If
|
||||
Next
|
||||
If ErrorInfo Is Nothing Then ErrorInfo = New TimeoutException("下载源连接超时")
|
||||
DlSourceLoaderAbort(LoaderList)
|
||||
Throw ErrorInfo
|
||||
End If
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
If ErrorInfo Is Nothing Then ErrorInfo = New TimeoutException("下载源连接超时")
|
||||
DlSourceLoaderAbort(LoaderList)
|
||||
Throw ErrorInfo
|
||||
End If
|
||||
Exit For
|
||||
Next
|
||||
'计时
|
||||
Thread.Sleep(10)
|
||||
WaitCycle += 1
|
||||
'检查父加载器中断
|
||||
If MainLoader.IsAborted Then
|
||||
DlSourceLoaderAbort(LoaderList)
|
||||
Exit Sub
|
||||
End If
|
||||
Thread.Sleep(10)
|
||||
WaitCycle += 1
|
||||
Loop
|
||||
End Sub
|
||||
Private Sub DlSourceLoaderAbort(Of InputType, OutputType)(LoaderList As List(Of KeyValuePair(Of LoaderTask(Of InputType, OutputType), Integer)))
|
||||
|
||||
@@ -489,16 +489,18 @@ NoUserJava:
|
||||
Public JavaSearchLoader As New LoaderTask(Of Integer, Integer)("查找 Java", AddressOf JavaSearchLoaderSub) With {.ProgressWeight = 2}
|
||||
Private Sub JavaSearchLoaderSub(Loader As LoaderTask(Of Integer, Integer))
|
||||
If FrmSetupLaunch IsNot Nothing Then
|
||||
RunInUiWait(Sub()
|
||||
FrmSetupLaunch.ComboArgumentJava.Items.Clear()
|
||||
FrmSetupLaunch.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
|
||||
End Sub)
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
FrmSetupLaunch.ComboArgumentJava.Items.Clear()
|
||||
FrmSetupLaunch.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
|
||||
End Sub)
|
||||
End If
|
||||
If FrmVersionSetup IsNot Nothing Then
|
||||
RunInUiWait(Sub()
|
||||
FrmVersionSetup.ComboArgumentJava.Items.Clear()
|
||||
FrmVersionSetup.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
|
||||
End Sub)
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
FrmVersionSetup.ComboArgumentJava.Items.Clear()
|
||||
FrmVersionSetup.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
|
||||
End Sub)
|
||||
End If
|
||||
|
||||
Try
|
||||
@@ -520,6 +522,7 @@ NoUserJava:
|
||||
Next
|
||||
'查找磁盘中的 Java
|
||||
For Each Disk As DriveInfo In DriveInfo.GetDrives()
|
||||
If Disk.DriveType = DriveType.Network Then Continue For '跳过网络驱动器(#3705)
|
||||
JavaSearchFolder(Disk.Name, JavaPreList, False)
|
||||
Next
|
||||
'查找 APPDATA 文件夹中的 Java
|
||||
@@ -681,8 +684,8 @@ Wait:
|
||||
For Each FolderInfo As DirectoryInfo In OriginalPath.EnumerateDirectories
|
||||
If FolderInfo.Attributes.HasFlag(FileAttributes.ReparsePoint) Then Continue For '跳过符号链接
|
||||
Dim SearchEntry = GetFolderNameFromPath(FolderInfo.Name).ToLower '用于搜索的字符串
|
||||
If IsFullSearch OrElse FolderInfo.Parent.Name.ToLower = "users" OrElse
|
||||
Keywords.Any(Function(w) SearchEntry.Contains(w)) OrElse SearchEntry = "bin" Then
|
||||
If IsFullSearch OrElse
|
||||
FolderInfo.Parent.Name.ToLower = "users" OrElse Val(SearchEntry) > 0 OrElse Keywords.Any(Function(w) SearchEntry.Contains(w)) OrElse SearchEntry = "bin" Then
|
||||
JavaSearchFolder(FolderInfo, Results, Source)
|
||||
End If
|
||||
Next
|
||||
|
||||
@@ -106,7 +106,7 @@ Public Module ModLaunch
|
||||
'构造主加载器
|
||||
Dim Loaders As New List(Of LoaderBase) From {
|
||||
New LoaderTask(Of Integer, Integer)("获取 Java", AddressOf McLaunchJava) With {.ProgressWeight = 4, .Block = False},
|
||||
McLoginLoader,
|
||||
McLoginLoader, '.ProgressWeight = 15, .Block = False
|
||||
New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground)) With {.ProgressWeight = 15, .Show = False},
|
||||
New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
|
||||
New LoaderTask(Of List(Of McLibToken), Integer)("解压文件", AddressOf McLaunchNatives) With {.ProgressWeight = 2},
|
||||
@@ -225,9 +225,9 @@ NextInner:
|
||||
Select Case Setup.Get("SystemLaunchCount")
|
||||
Case 10, 20, 40, 60, 80, 100, 120, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000
|
||||
If MyMsgBox("PCL 已经为你启动了 " & Setup.Get("SystemLaunchCount") & " 次游戏啦!" & vbCrLf &
|
||||
"如果觉得 PCL 还算好用的话,也可以考虑赞助一下作者……一点心意也行……" & vbCrLf &
|
||||
"毕竟一个人开发也不容易(悲)……",
|
||||
"求赞助啦……", "这就赞助!", "但是我拒绝") = 1 Then
|
||||
"如果 PCL 还算好用的话,能不能考虑赞助一下 PCL……" & vbCrLf &
|
||||
"如果没有大家的支持,PCL 很难在免费、无任何广告的情况下维持数年的更新(磕头)……!",
|
||||
Setup.Get("SystemLaunchCount") & " 次启动!", "支持 PCL!", "但是我拒绝") = 1 Then
|
||||
OpenWebsite("https://afdian.com/a/LTCat")
|
||||
End If
|
||||
End Select
|
||||
@@ -237,10 +237,10 @@ NextInner:
|
||||
If Not Setup.Get("HintBuy") AndAlso Setup.Get("LoginType") <> McLoginType.Ms Then
|
||||
If IsSystemLanguageChinese() Then
|
||||
Select Case Setup.Get("SystemLaunchCount")
|
||||
Case 2, 5, 10, 15, 20, 40, 60, 80, 100, 125, 150, 175, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000
|
||||
Case 3, 8, 15, 30, 50, 70, 90, 110, 130, 180, 220, 280, 330, 380, 450, 550, 660, 750, 880, 950, 1100, 1300, 1500, 1700, 1900
|
||||
If MyMsgBox("你已经启动了 " & Setup.Get("SystemLaunchCount") & " 次 Minecraft 啦!" & vbCrLf &
|
||||
"如果觉得 Minecraft 还不错,可以购买正版支持一下,毕竟开发游戏也真的很不容易……" & vbCrLf & vbCrLf &
|
||||
"在你登录一次正版账号后,就不会再出现这个提示了!",
|
||||
"如果觉得 Minecraft 还不错,可以购买正版支持一下,毕竟开发游戏也真的很不容易……不要一直白嫖啦。" & vbCrLf & vbCrLf &
|
||||
"在登录一次正版账号后,就不会再出现这个提示了!",
|
||||
"考虑一下正版?", "支持正版游戏!", "下次一定") = 1 Then
|
||||
OpenWebsite("https://www.xbox.com/zh-cn/games/store/minecraft-java-bedrock-edition-for-pc/9nxp44l49shj")
|
||||
End If
|
||||
@@ -378,19 +378,19 @@ NextInner:
|
||||
'根据当前登录方式优先返回
|
||||
Select Case Setup.Get("LoginType")
|
||||
Case McLoginType.Ms
|
||||
If Setup.Get("CacheMsName") <> "" Then Return Setup.Get("CacheMsName")
|
||||
If Setup.Get("CacheMsV2Name") <> "" Then Return Setup.Get("CacheMsV2Name")
|
||||
Case McLoginType.Legacy
|
||||
If Setup.Get("LoginLegacyName") <> "" Then Return Setup.Get("LoginLegacyName").ToString.Before("¨")
|
||||
If Setup.Get("LoginLegacyName") <> "" Then Return Setup.Get("LoginLegacyName").ToString.BeforeFirst("¨")
|
||||
Case McLoginType.Nide
|
||||
If Setup.Get("CacheNideName") <> "" Then Return Setup.Get("CacheNideName")
|
||||
Case McLoginType.Auth
|
||||
If Setup.Get("CacheAuthName") <> "" Then Return Setup.Get("CacheAuthName")
|
||||
End Select
|
||||
'查找所有可能的项
|
||||
If Setup.Get("CacheMsName") <> "" Then Return Setup.Get("CacheMsName")
|
||||
If Setup.Get("CacheMsV2Name") <> "" Then Return Setup.Get("CacheMsV2Name")
|
||||
If Setup.Get("CacheNideName") <> "" Then Return Setup.Get("CacheNideName")
|
||||
If Setup.Get("CacheAuthName") <> "" Then Return Setup.Get("CacheAuthName")
|
||||
If Setup.Get("LoginLegacyName") <> "" Then Return Setup.Get("LoginLegacyName").ToString.Before("¨")
|
||||
If Setup.Get("LoginLegacyName") <> "" Then Return Setup.Get("LoginLegacyName").ToString.BeforeFirst("¨")
|
||||
Return Nothing
|
||||
End Function
|
||||
''' <summary>
|
||||
@@ -399,7 +399,7 @@ NextInner:
|
||||
Public Function McLoginAble() As String
|
||||
Select Case Setup.Get("LoginType")
|
||||
Case McLoginType.Ms
|
||||
If Setup.Get("CacheMsOAuthRefresh") = "" Then
|
||||
If Setup.Get("CacheMsV2OAuthRefresh") = "" Then
|
||||
Return FrmLoginMs.IsVaild()
|
||||
Else
|
||||
Return ""
|
||||
@@ -450,7 +450,7 @@ NextInner:
|
||||
Case McLoginType.Legacy
|
||||
LoginData = PageLoginLegacy.GetLoginData()
|
||||
Case McLoginType.Ms
|
||||
If Setup.Get("CacheMsOAuthRefresh") = "" Then
|
||||
If Setup.Get("CacheMsV2OAuthRefresh") = "" Then
|
||||
LoginData = PageLoginMs.GetLoginData()
|
||||
Else
|
||||
LoginData = PageLoginMsSkin.GetLoginData()
|
||||
@@ -501,7 +501,7 @@ NextInner:
|
||||
#Region "分方式登录模块"
|
||||
|
||||
'各个登录方式的主对象与输入构造
|
||||
Public McLoginMsLoader As New LoaderTask(Of McLoginMs, McLoginResult)("Loader Login Ms", AddressOf McLoginMsStart)
|
||||
Public McLoginMsLoader As New LoaderTask(Of McLoginMs, McLoginResult)("Loader Login Ms", AddressOf McLoginMsStart) With {.ReloadTimeout = 1}
|
||||
Public McLoginLegacyLoader As New LoaderTask(Of McLoginLegacy, McLoginResult)("Loader Login Legacy", AddressOf McLoginLegacyStart)
|
||||
Public McLoginNideLoader As New LoaderTask(Of McLoginServer, McLoginResult)("Loader Login Nide", AddressOf McLoginServerStart) With {.ReloadTimeout = 1000 * 60 * 10}
|
||||
Public McLoginAuthLoader As New LoaderTask(Of McLoginServer, McLoginResult)("Loader Login Auth", AddressOf McLoginServerStart) With {.ReloadTimeout = 1000 * 60 * 10}
|
||||
@@ -529,8 +529,8 @@ Relogin:
|
||||
OAuthTokens = MsLoginStep1New(Data)
|
||||
Else
|
||||
'有 RefreshToken
|
||||
OAuthTokens = MsLoginStep1Refresh(Input.OAuthRefreshToken) '要求重新打开登录网页认证
|
||||
If OAuthTokens(0) = "Relogin" Then GoTo Relogin
|
||||
OAuthTokens = MsLoginStep1Refresh(Input.OAuthRefreshToken)
|
||||
If OAuthTokens(0) = "Relogin" Then GoTo Relogin '要求重新打开登录网页认证
|
||||
End If
|
||||
If Data.IsAborted Then Throw New ThreadInterruptedException
|
||||
Data.Progress = 0.25
|
||||
@@ -552,11 +552,11 @@ Relogin:
|
||||
Dim Result = MsLoginStep6(AccessToken)
|
||||
Data.Progress = 0.98
|
||||
'输出登录结果
|
||||
Setup.Set("CacheMsOAuthRefresh", OAuthRefreshToken)
|
||||
Setup.Set("CacheMsAccess", AccessToken)
|
||||
Setup.Set("CacheMsUuid", Result(0))
|
||||
Setup.Set("CacheMsName", Result(1))
|
||||
Setup.Set("CacheMsProfileJson", Result(2))
|
||||
Setup.Set("CacheMsV2OAuthRefresh", OAuthRefreshToken)
|
||||
Setup.Set("CacheMsV2Access", AccessToken)
|
||||
Setup.Set("CacheMsV2Uuid", Result(0))
|
||||
Setup.Set("CacheMsV2Name", Result(1))
|
||||
Setup.Set("CacheMsV2ProfileJson", Result(2))
|
||||
Dim MsJson As JObject = GetJson(Setup.Get("LoginMsJson"))
|
||||
MsJson.Remove(Input.UserName) '如果更改了玩家名……
|
||||
MsJson(Result(1)) = OAuthRefreshToken
|
||||
@@ -805,7 +805,19 @@ LoginFinish:
|
||||
ErrorMessage = GetJson(DirectCast(ex, ResponsedWebException).Response)("errorMessage")
|
||||
Catch
|
||||
End Try
|
||||
If Not String.IsNullOrWhiteSpace(ErrorMessage) Then Throw New Exception("$登录失败:" & ErrorMessage)
|
||||
If Not String.IsNullOrWhiteSpace(ErrorMessage) Then
|
||||
If ErrorMessage.Contains("密码错误") OrElse ErrorMessage.ContainsF("Incorrect username or password", True) Then
|
||||
'密码错误,退出登录 (#5090)
|
||||
McLaunchLog("密码错误,退出登录")
|
||||
Select Case Data.Input.Type
|
||||
Case McLoginType.Auth
|
||||
RunInUi(AddressOf PageLoginAuthSkin.ExitLogin)
|
||||
Case McLoginType.Nide
|
||||
RunInUi(AddressOf PageLoginNideSkin.ExitLogin)
|
||||
End Select
|
||||
End If
|
||||
Throw New Exception("$登录失败:" & ErrorMessage)
|
||||
End If
|
||||
End If
|
||||
'通用关键字检测
|
||||
If AllMessage.Contains("403") Then
|
||||
@@ -838,9 +850,10 @@ LoginFinish:
|
||||
'参考:https://learn.microsoft.com/zh-cn/entra/identity-platform/v2-oauth2-device-code
|
||||
|
||||
'初始请求
|
||||
Retry:
|
||||
McLaunchLog("开始微软登录步骤 1/6(原始登录)")
|
||||
Dim PrepareJson As JObject = GetJson(NetRequestMulty("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
|
||||
$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded", 2))
|
||||
Dim PrepareJson As JObject = GetJson(NetRequestRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
|
||||
$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded"))
|
||||
McLaunchLog("网页登录地址:" & PrepareJson("verification_uri").ToString)
|
||||
|
||||
'弹窗
|
||||
@@ -849,24 +862,31 @@ LoginFinish:
|
||||
While Converter.Result Is Nothing
|
||||
Thread.Sleep(100)
|
||||
End While
|
||||
If TypeOf Converter.Result Is Exception Then
|
||||
If TypeOf Converter.Result Is RestartException Then
|
||||
If MyMsgBox($"请在登录时选择 {vbLQ}其他登录方法{vbRQ},然后选择 {vbLQ}使用我的密码{vbRQ}。{vbCrLf}如果没有该选项,请选择 {vbLQ}设置密码{vbRQ},设置完毕后再登录。",
|
||||
"需要使用密码登录", "重新登录", "设置密码", "取消",
|
||||
Button2Action:=Sub() OpenWebsite("https://account.live.com/password/Change")) = 1 Then
|
||||
GoTo Retry
|
||||
Else
|
||||
Throw New Exception("$$")
|
||||
End If
|
||||
ElseIf TypeOf Converter.Result Is Exception Then
|
||||
Throw CType(Converter.Result, Exception)
|
||||
Else
|
||||
Return Converter.Result
|
||||
End If
|
||||
End Function
|
||||
|
||||
'微软登录步骤 1,刷新登录:从 OAuth Code 或 OAuth RefreshToken 获取 {OAuth AccessToken, OAuth RefreshToken}
|
||||
Private Function MsLoginStep1Refresh(Code As String) As String()
|
||||
McLaunchLog("开始微软登录步骤 1/6(刷新登录)")
|
||||
|
||||
Dim Result As String
|
||||
Try
|
||||
Result = NetRequestMulty("https://login.live.com/oauth20_token.srf", "POST",
|
||||
Result = NetRequestMultiple("https://login.live.com/oauth20_token.srf", "POST",
|
||||
$"client_id={OAuthClientId}&refresh_token={Uri.EscapeDataString(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
||||
"application/x-www-form-urlencoded", 2)
|
||||
Catch ex As Exception
|
||||
If ex.Message.Contains("must sign in again") OrElse ex.Message.Contains("invalid_grant") Then '#269
|
||||
If ex.Message.Contains("must sign in again") OrElse (ex.Message.Contains("refresh_token") AndAlso ex.Message.Contains("is not valid")) Then '#269
|
||||
Return {"Relogin", ""}
|
||||
Else
|
||||
Throw
|
||||
@@ -878,7 +898,6 @@ LoginFinish:
|
||||
Dim RefreshToken As String = ResultJson("refresh_token").ToString
|
||||
Return {AccessToken, RefreshToken}
|
||||
End Function
|
||||
|
||||
'微软登录步骤 2:从 OAuth AccessToken 获取 XBLToken
|
||||
Private Function MsLoginStep2(AccessToken As String) As String
|
||||
McLaunchLog("开始微软登录步骤 2/6")
|
||||
@@ -891,8 +910,8 @@ LoginFinish:
|
||||
},
|
||||
""RelyingParty"": ""http://auth.xboxlive.com"",
|
||||
""TokenType"": ""JWT""
|
||||
}" 'TODO: 新版登录改为 ""RpsTicket"": ""d=" & AccessToken & """
|
||||
Dim Result As String = NetRequestMulty("https://user.auth.xboxlive.com/user/authenticate", "POST", Request, "application/json", 3)
|
||||
}"
|
||||
Dim Result As String = NetRequestMultiple("https://user.auth.xboxlive.com/user/authenticate", "POST", Request, "application/json", 3)
|
||||
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim XBLToken As String = ResultJson("Token").ToString
|
||||
@@ -914,7 +933,7 @@ LoginFinish:
|
||||
}"
|
||||
Dim Result As String
|
||||
Try
|
||||
Result = NetRequestMulty("https://xsts.auth.xboxlive.com/xsts/authorize", "POST", Request, "application/json", 3)
|
||||
Result = NetRequestMultiple("https://xsts.auth.xboxlive.com/xsts/authorize", "POST", Request, "application/json", 3)
|
||||
Catch ex As Net.WebException
|
||||
'参考 https://github.com/PrismarineJS/prismarine-auth/blob/master/src/common/Constants.js
|
||||
If ex.Message.Contains("2148916227") Then
|
||||
@@ -957,7 +976,7 @@ LoginFinish:
|
||||
Dim Request As String = New JObject(New JProperty("identityToken", $"XBL3.0 x={Tokens(1)};{Tokens(0)}")).ToString(0)
|
||||
Dim Result As String
|
||||
Try
|
||||
Result = NetRequestMulty("https://api.minecraftservices.com/authentication/login_with_xbox", "POST", Request, "application/json", 2)
|
||||
Result = NetRequestRetry("https://api.minecraftservices.com/authentication/login_with_xbox", "POST", Request, "application/json")
|
||||
Catch ex As Net.WebException
|
||||
Dim Message As String = GetExceptionSummary(ex)
|
||||
If Message.Contains("(429)") Then
|
||||
@@ -979,7 +998,7 @@ LoginFinish:
|
||||
Private Sub MsLoginStep5(AccessToken As String)
|
||||
McLaunchLog("开始微软登录步骤 5/6")
|
||||
|
||||
Dim Result As String = NetRequestMulty("https://api.minecraftservices.com/entitlements/mcstore", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
||||
Dim Result As String = NetRequestMultiple("https://api.minecraftservices.com/entitlements/mcstore", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
||||
Try
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
If Not (ResultJson.ContainsKey("items") AndAlso ResultJson("items").Any) Then
|
||||
@@ -1000,7 +1019,7 @@ LoginFinish:
|
||||
|
||||
Dim Result As String
|
||||
Try
|
||||
Result = NetRequestMulty("https://api.minecraftservices.com/minecraft/profile", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
||||
Result = NetRequestMultiple("https://api.minecraftservices.com/minecraft/profile", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
||||
Catch ex As Net.WebException
|
||||
Dim Message As String = GetExceptionSummary(ex)
|
||||
If Message.Contains("(429)") Then
|
||||
@@ -1255,8 +1274,7 @@ LoginFinish:
|
||||
''' 释放 Java Wrapper 并返回完整文件路径。
|
||||
''' </summary>
|
||||
Public Function ExtractJavaWrapper() As String
|
||||
Dim BaseDir As String = GetJavaWrapperDir()
|
||||
Dim WrapperPath As String = BaseDir & "\JavaWrapper.jar"
|
||||
Dim WrapperPath As String = PathPure & "JavaWrapper.jar"
|
||||
Log("[Java] 选定的 Java Wrapper 路径:" & WrapperPath)
|
||||
SyncLock ExtractJavaWrapperLock '避免 OptiFine 和 Forge 安装时同时释放 Java Wrapper 导致冲突
|
||||
Try
|
||||
@@ -1270,7 +1288,7 @@ LoginFinish:
|
||||
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
||||
Catch ex2 As Exception
|
||||
Log(ex2, "Java Wrapper 文件重新释放失败,将尝试更换文件名重新生成", LogLevel.Developer)
|
||||
WrapperPath = BaseDir & "\JavaWrapper2.jar"
|
||||
WrapperPath = PathPure & "JavaWrapper2.jar"
|
||||
Try
|
||||
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
||||
Catch ex3 As Exception
|
||||
@@ -1286,21 +1304,6 @@ LoginFinish:
|
||||
End Function
|
||||
Private ExtractJavaWrapperLock As New Object
|
||||
|
||||
''' <summary>
|
||||
''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
|
||||
''' </summary>
|
||||
Public Function GetJavaWrapperDir() As String
|
||||
If (Path & "PCL").IsASCII() Then
|
||||
Return Path & "PCL"
|
||||
ElseIf PathAppdata.IsASCII() Then
|
||||
Return PathAppdata.TrimEnd("\")
|
||||
ElseIf PathTemp.IsASCII() Then
|
||||
Return PathTemp.TrimEnd("\")
|
||||
Else
|
||||
Return OsDrive & "ProgramData\PCL"
|
||||
End If
|
||||
End Function
|
||||
|
||||
'主方法,合并 Jvm、Game、Replace 三部分的参数数据
|
||||
Private Sub McLaunchArgumentMain(Loader As LoaderTask(Of String, List(Of McLibToken)))
|
||||
McLaunchLog("开始获取 Minecraft 启动参数")
|
||||
@@ -1400,7 +1403,7 @@ LoginFinish:
|
||||
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
||||
Try
|
||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
||||
DataList.Insert(0, "-javaagent:""" & PathAppdata & "authlib-injector.jar""=" & Server &
|
||||
DataList.Insert(0, "-javaagent:""" & PathPure & "authlib-injector.jar""=" & Server &
|
||||
" -Dauthlibinjector.side=client" &
|
||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||
Catch ex As Exception
|
||||
@@ -1410,7 +1413,7 @@ LoginFinish:
|
||||
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
DataList.Add("-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
|
||||
DataList.Add("-Doolloo.jlw.tmpdir=""" & PathPure.TrimEnd("\") & """")
|
||||
DataList.Add("-jar """ & ExtractJavaWrapper() & """")
|
||||
|
||||
'添加 MainClass
|
||||
@@ -1467,7 +1470,7 @@ NextVersion:
|
||||
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
||||
Try
|
||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
||||
DataList.Insert(0, "-javaagent:""" & PathAppdata & "authlib-injector.jar""=" & Server &
|
||||
DataList.Insert(0, "-javaagent:""" & PathPure & "authlib-injector.jar""=" & Server &
|
||||
" -Dauthlibinjector.side=client" &
|
||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||
Catch ex As Exception
|
||||
@@ -1477,7 +1480,7 @@ NextVersion:
|
||||
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
DataList.Add("-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
|
||||
DataList.Add("-Doolloo.jlw.tmpdir=""" & PathPure.TrimEnd("\") & """")
|
||||
DataList.Add("-jar """ & ExtractJavaWrapper() & """")
|
||||
|
||||
'将 "-XXX" 与后面 "XXX" 合并到一起
|
||||
@@ -1652,8 +1655,11 @@ NextVersion:
|
||||
GameSize = New Size(875 - 2, 540 - 2)
|
||||
End Select
|
||||
GameSize.Height -= 29.5 * DPI / 96 '标题栏高度
|
||||
If McVersionCurrent.Version.McCodeMain <= 12 AndAlso McLaunchJavaSelected.VersionCode <= 8 AndAlso
|
||||
Not McVersionCurrent.Version.HasOptiFine AndAlso Not McVersionCurrent.Version.HasForge Then '修复 #3463:1.12.2-,JRE 8 下窗口大小为设置大小的 DPI% 倍
|
||||
If McVersionCurrent.Version.McCodeMain <= 12 AndAlso
|
||||
McLaunchJavaSelected.VersionCode <= 8 AndAlso McLaunchJavaSelected.Version.Revision >= 200 AndAlso McLaunchJavaSelected.Version.Revision <= 321 AndAlso
|
||||
Not McVersionCurrent.Version.HasOptiFine AndAlso Not McVersionCurrent.Version.HasForge Then
|
||||
'修复 #3463:1.12.2-,JRE 8u200~321 下窗口大小为设置大小的 DPI% 倍
|
||||
McLaunchLog($"已应用窗口大小过大修复({McLaunchJavaSelected.Version.Revision})")
|
||||
GameSize.Width /= DPI / 96
|
||||
GameSize.Height /= DPI / 96
|
||||
End If
|
||||
|
||||
@@ -85,7 +85,7 @@ Public Module ModMinecraft
|
||||
Next
|
||||
If Not Renamed Then CacheMcFolderList.Add(New McFolder With {.Name = Name, .Path = Path, .Type = McFolderType.Custom})
|
||||
Else
|
||||
Hint("无效的 Minecraft 文件夹:" & Path, HintType.Critical)
|
||||
Hint("无法访问 Minecraft 文件夹:" & Path, HintType.Critical)
|
||||
End If
|
||||
Next
|
||||
|
||||
@@ -1256,9 +1256,8 @@ OnLoaded:
|
||||
Dim VersionList As New List(Of McVersion)
|
||||
|
||||
#Region "循环加载每个版本的信息"
|
||||
Dim Dirs As DirectoryInfo() = New DirectoryInfo(Path & "versions").GetDirectories
|
||||
For Each Folder As DirectoryInfo In Dirs
|
||||
If Not Folder.EnumerateFiles.Any Then
|
||||
For Each Folder As DirectoryInfo In New DirectoryInfo(Path & "versions").GetDirectories
|
||||
If Not Folder.Exists OrElse Not Folder.EnumerateFiles.Any Then
|
||||
Log("[Minecraft] 跳过空文件夹:" & Folder.FullName)
|
||||
Continue For
|
||||
End If
|
||||
@@ -1292,8 +1291,11 @@ OnLoaded:
|
||||
|
||||
'单独列出收藏的版本
|
||||
Dim StaredVersions As New List(Of McVersion)
|
||||
For Each Version As McVersion In VersionList
|
||||
If Version.IsStar AndAlso Not Version.DisplayType = McVersionCardType.Hidden Then StaredVersions.Add(Version)
|
||||
For Each Version As McVersion In VersionList.ToList
|
||||
If Version.IsStar AndAlso Not Version.DisplayType = McVersionCardType.Hidden Then
|
||||
StaredVersions.Add(Version)
|
||||
VersionList.Remove(Version)
|
||||
End If
|
||||
Next
|
||||
If StaredVersions.Any Then VersionListOriginal.Add(McVersionCardType.Star, StaredVersions)
|
||||
|
||||
@@ -1528,7 +1530,7 @@ OnLoaded:
|
||||
''' 要求玩家选择一个皮肤文件,并进行相关校验。
|
||||
''' </summary>
|
||||
Public Function McSkinSelect() As McSkinInfo
|
||||
Dim FileName As String = SelectFile("皮肤文件(*.png)|*.png", "选择皮肤文件")
|
||||
Dim FileName As String = SelectFile("皮肤文件(*.png;*.jpg;*.webp)|*.png;*.jpg;*.webp", "选择皮肤文件")
|
||||
|
||||
'验证有效性
|
||||
If FileName = "" Then Return New McSkinInfo With {.IsVaild = False}
|
||||
@@ -1935,7 +1937,7 @@ OnLoaded:
|
||||
''' <summary>
|
||||
''' 获取版本缺失的支持库文件所对应的 NetTaskFile。
|
||||
''' </summary>
|
||||
Public Function McLibFix(Version As McVersion, Optional CoreJarOnly As Boolean = False) As List(Of NetFile)
|
||||
Public Function McLibFix(Version As McVersion) As List(Of NetFile)
|
||||
If Not Version.IsLoaded Then Version.Load() '确保例如 JumpLoader 等项被合并入 Json
|
||||
Dim Result As New List(Of NetFile)
|
||||
|
||||
@@ -1948,7 +1950,6 @@ OnLoaded:
|
||||
Catch ex As Exception
|
||||
Log(ex, "版本缺失主 jar 文件所必须的信息", LogLevel.Developer)
|
||||
End Try
|
||||
If CoreJarOnly Then Return Result
|
||||
|
||||
'Library 文件
|
||||
Result.AddRange(McLibFixFromLibToken(McLibListGet(Version, False), JumpLoaderFolder:=Version.PathIndie & ".jumploader\"))
|
||||
@@ -1957,15 +1958,15 @@ OnLoaded:
|
||||
If Setup.Get("VersionServerLogin", Version:=Version) = 3 Then
|
||||
Dim TargetFile = PathAppdata & "nide8auth.jar"
|
||||
Dim DownloadInfo As JObject = Nothing
|
||||
'获取下载信息
|
||||
Try
|
||||
Log("[Minecraft] 开始获取统一通行证下载信息")
|
||||
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
|
||||
DownloadInfo = GetJson(NetGetCodeByDownload({
|
||||
'获取下载信息
|
||||
Try
|
||||
Log("[Minecraft] 开始获取统一通行证下载信息")
|
||||
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
|
||||
DownloadInfo = GetJson(NetGetCodeByDownload({
|
||||
"https://auth.mc-user.com:233/" & Setup.Get("VersionServerNide", Version:=Version)}, IsJson:=True))
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取统一通行证下载信息失败")
|
||||
End Try
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取统一通行证下载信息失败")
|
||||
End Try
|
||||
'校验文件
|
||||
If DownloadInfo IsNot Nothing Then
|
||||
Dim Checker As New FileChecker(Hash:=DownloadInfo("jarHash").ToString)
|
||||
@@ -1978,9 +1979,8 @@ OnLoaded:
|
||||
End If
|
||||
|
||||
'Authlib-Injector 文件
|
||||
If Setup.Get("VersionServerLogin", Version:=Version) = 4 OrElse
|
||||
(PageLinkHiper.HiperState = LoadState.Finished AndAlso Setup.Get("LoginType") = McLoginType.Legacy) Then 'HiPer 登录转接
|
||||
Dim TargetFile = PathAppdata & "authlib-injector.jar"
|
||||
If Setup.Get("VersionServerLogin", Version:=Version) = 4 Then
|
||||
Dim TargetFile = PathPure & "\authlib-injector.jar"
|
||||
Dim DownloadInfo As JObject = Nothing
|
||||
'获取下载信息
|
||||
Try
|
||||
@@ -2001,9 +2001,9 @@ OnLoaded:
|
||||
Replace("bmclapi2.bangbang93.com/mirrors/authlib-injector", "authlib-injector.yushi.moe")
|
||||
Log("[Minecraft] Authlib-Injector 需要更新:" & DownloadAddress, LogLevel.Developer)
|
||||
Result.Add(New NetFile({
|
||||
DownloadAddress,
|
||||
DownloadAddress.Replace("authlib-injector.yushi.moe", "bmclapi2.bangbang93.com/mirrors/authlib-injector")
|
||||
}, TargetFile, New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)))
|
||||
DownloadAddress,
|
||||
DownloadAddress.Replace("authlib-injector.yushi.moe", "bmclapi2.bangbang93.com/mirrors/authlib-injector")
|
||||
}, TargetFile, New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)))
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
@@ -2308,8 +2308,8 @@ OnLoaded:
|
||||
End If
|
||||
Left = Left.ToLowerInvariant
|
||||
Right = Right.ToLowerInvariant
|
||||
Dim Lefts = RegexSearch(Left.Replace("快照", "snapshot"), "[a-z]+|[0-9]+")
|
||||
Dim Rights = RegexSearch(Right.Replace("快照", "snapshot"), "[a-z]+|[0-9]+")
|
||||
Dim Lefts = RegexSearch(Left.Replace("快照", "snapshot").Replace("预览版", "pre"), "[a-z]+|[0-9]+")
|
||||
Dim Rights = RegexSearch(Right.Replace("快照", "snapshot").Replace("预览版", "pre"), "[a-z]+|[0-9]+")
|
||||
Dim i As Integer = 0
|
||||
While True
|
||||
'两边均缺失,感觉是一个东西
|
||||
@@ -2358,15 +2358,11 @@ NextEntry:
|
||||
''' <summary>
|
||||
''' 比较两个版本名的排序器。
|
||||
''' </summary>
|
||||
Public Class VersionSorter
|
||||
Public Class VersionComparer
|
||||
Implements IComparer(Of String)
|
||||
Public IsDecreased As Boolean = True
|
||||
Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
|
||||
Return VersionSortInteger(x, y) * If(IsDecreased, -1, 1)
|
||||
Return VersionSortInteger(x, y)
|
||||
End Function
|
||||
Public Sub New(Optional IsDecreased As Boolean = True)
|
||||
Me.IsDecreased = IsDecreased
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
|
||||
@@ -688,7 +688,7 @@ Finished:
|
||||
''' </summary>
|
||||
Public ReadOnly Property CanUpdate As Boolean
|
||||
Get
|
||||
Return ChangelogUrls.Any()
|
||||
Return Not Setup.Get("UiHiddenFunctionModUpdate") AndAlso ChangelogUrls.Any()
|
||||
End Get
|
||||
End Property
|
||||
|
||||
@@ -702,7 +702,7 @@ Finished:
|
||||
Dim Info As New FileInfo(Path)
|
||||
Dim CacheKey As String = GetHash($"{RawPath}-{Info.LastWriteTime.ToLongTimeString}-{Info.Length}-C")
|
||||
Dim Cached As String = ReadIni(PathTemp & "Cache\ModHash.ini", CacheKey)
|
||||
If Cached <> "" Then
|
||||
If Cached <> "" AndAlso RegexCheck(Cached, "^\d+$") Then '#5062
|
||||
_CurseForgeHash = Cached
|
||||
Return _CurseForgeHash
|
||||
End If
|
||||
@@ -825,6 +825,7 @@ Finished:
|
||||
Finally
|
||||
RunInUiWait(Sub() If FrmVersionMod IsNot Nothing Then FrmVersionMod.Load.Text = "正在加载 Mod 列表")
|
||||
End Try
|
||||
FrmVersionMod.LoaderRun(LoaderFolderRunType.UpdateOnly)
|
||||
End If
|
||||
|
||||
'获取 Mod 文件夹下的可用文件列表
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Imports System.IO.Compression
|
||||
Imports System.Linq.Expressions
|
||||
|
||||
Public Module ModModpack
|
||||
|
||||
@@ -9,13 +10,22 @@ Public Module ModModpack
|
||||
Public Sub ModpackInstall()
|
||||
Dim File As String = SelectFile("整合包文件(*.rar;*.zip;*.mrpack)|*.rar;*.zip;*.mrpack", "选择整合包压缩文件") '选择整合包文件
|
||||
If String.IsNullOrEmpty(File) Then Exit Sub
|
||||
RunInThread(Sub() ModpackInstall(File))
|
||||
RunInThread(
|
||||
Sub()
|
||||
Try
|
||||
ModpackInstall(File)
|
||||
Catch ex As CancelledException
|
||||
Catch ex As Exception
|
||||
Log(ex, "手动安装整合包失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 安装一个给定的整合包文件,返回启动的安装加载器,如果未成功启动则返回 Nothing。
|
||||
''' 构建并启动安装给定的整合包文件的加载器,并返回该加载器。若失败则抛出异常。
|
||||
''' 必须在工作线程执行。
|
||||
''' </summary>
|
||||
Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional ShowHint As Boolean = True, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
''' <exception cref="CancelledException" />
|
||||
Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
Log("[ModPack] 整合包安装请求:" & If(File, "null"))
|
||||
Dim Archive As ZipArchive = Nothing
|
||||
Dim ArchiveBaseFolder As String = ""
|
||||
@@ -23,7 +33,7 @@ Public Module ModModpack
|
||||
'获取整合包种类与关键 Json
|
||||
Dim PackType As Integer = -1
|
||||
Try
|
||||
Archive = New ZipArchive(New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
Archive = New ZipArchive(New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
'从根目录判断整合包类型
|
||||
If Archive.GetEntry("mcbbs.packmeta") IsNot Nothing Then PackType = 3 : Exit Try 'MCBBS 整合包(优先于 manifest.json 判断)
|
||||
If Archive.GetEntry("mmc-pack.json") IsNot Nothing Then PackType = 2 : Exit Try 'MMC 整合包(优先于 manifest.json 判断,#4194)
|
||||
@@ -37,11 +47,11 @@ Public Module ModModpack
|
||||
End If
|
||||
End If
|
||||
If Archive.GetEntry("modpack.json") IsNot Nothing Then PackType = 1 : Exit Try 'HMCL 整合包
|
||||
If Archive.GetEntry("modpack.zip") IsNot Nothing OrElse Archive.GetEntry("modpack.mrpack") IsNot Nothing Then PackType = 9 : Exit Try '带启动器的压缩包
|
||||
'从一级目录判断整合包类型
|
||||
For Each Entry In Archive.Entries
|
||||
Dim FullNames As String() = Entry.FullName.Split("/")
|
||||
ArchiveBaseFolder = FullNames(0) & "/"
|
||||
If Entry.FullName.EndsWithF("/versions/") AndAlso FullNames.Count = 3 Then PackType = 9 : Exit Try '压缩包
|
||||
'确定为一级目录下
|
||||
If FullNames.Count <> 2 Then Continue For
|
||||
'判断是否为关键文件
|
||||
@@ -57,17 +67,15 @@ Public Module ModModpack
|
||||
End If
|
||||
End If
|
||||
If FullNames(1) = "modpack.json" Then PackType = 1 : Exit Try 'HMCL 整合包
|
||||
If FullNames(1) = "modpack.zip" OrElse FullNames(1) = "modpack.mrpack" Then PackType = 9 : Exit Try '带启动器的压缩包
|
||||
Next
|
||||
Catch ex As Exception
|
||||
If GetExceptionDetail(ex, True).Contains("Error.WinIOError") Then
|
||||
Log(ex, "打开整合包文件失败", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
|
||||
Return Nothing
|
||||
Throw New Exception("打开整合包文件失败", ex)
|
||||
ElseIf File.EndsWithF(".rar", True) Then
|
||||
Log(ex, "PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
|
||||
Return Nothing
|
||||
Throw New Exception("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", ex)
|
||||
Else
|
||||
Log(ex, "打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
|
||||
Return Nothing
|
||||
Throw New Exception("打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", ex)
|
||||
End If
|
||||
End Try
|
||||
'执行对应的安装方法
|
||||
@@ -88,21 +96,12 @@ Public Module ModModpack
|
||||
Log("[ModPack] 整合包种类:Modrinth")
|
||||
Return InstallPackModrinth(File, Archive, ArchiveBaseFolder, VersionName, Logo)
|
||||
Case 9
|
||||
Log("[ModPack] 整合包种类:压缩包")
|
||||
Archive.Dispose()
|
||||
Archive = Nothing
|
||||
Return InstallPackCompress(File, ArchiveBaseFolder)
|
||||
Log("[ModPack] 整合包种类:带启动器的压缩包")
|
||||
Return InstallPackLauncherPack(File, Archive, ArchiveBaseFolder)
|
||||
Case Else
|
||||
If ShowHint Then
|
||||
Hint("未能识别该整合包的种类,无法安装!", HintType.Critical)
|
||||
Else
|
||||
Log("[ModPack] 未能识别该整合包的种类,无法安装!")
|
||||
End If
|
||||
Return Nothing
|
||||
Log("[ModPack] 整合包种类:未能识别,假定为压缩包")
|
||||
Return InstallPackCompress(File, Archive)
|
||||
End Select
|
||||
Catch ex As Exception
|
||||
Log(ex, "准备安装整合包失败", LogLevel.Feedback)
|
||||
Return Nothing
|
||||
Finally
|
||||
If Archive IsNot Nothing Then Archive.Dispose()
|
||||
End Try
|
||||
@@ -111,7 +110,7 @@ Public Module ModModpack
|
||||
'整合包缓存清理
|
||||
Private IsInstallCacheCleared As Boolean = False
|
||||
Private IsInstallCacheClearing As Boolean = False
|
||||
Private Sub UnpackFiles(InstallTemp As String, FileAddress As String, Loader As LoaderBase)
|
||||
Private Sub ExtractModpackFiles(InstallTemp As String, FileAddress As String, Loader As LoaderBase, LoaderProgressDelta As Double)
|
||||
'清理缓存文件夹
|
||||
If Not IsInstallCacheCleared Then
|
||||
IsInstallCacheCleared = True
|
||||
@@ -138,7 +137,7 @@ Public Module ModModpack
|
||||
Retry:
|
||||
'完全不知道为啥会出现文件正在被另一进程使用的问题,总之多试试
|
||||
DeleteDirectory(InstallTemp)
|
||||
ExtractFile(FileAddress, InstallTemp, Encode)
|
||||
ExtractFile(FileAddress, InstallTemp, Encode, ProgressIncrementHandler:=Sub(Delta) Loader.Progress += Delta * LoaderProgressDelta)
|
||||
Catch ex As Exception
|
||||
Log(ex, "第 " & RetryCount & " 次解压尝试失败")
|
||||
If TypeOf ex Is ArgumentException Then
|
||||
@@ -151,7 +150,7 @@ Retry:
|
||||
RetryCount += 1
|
||||
GoTo Retry
|
||||
Else
|
||||
Throw
|
||||
Throw New Exception("解压整合包文件失败", ex)
|
||||
End If
|
||||
End Try
|
||||
End Sub
|
||||
@@ -166,20 +165,18 @@ Retry:
|
||||
Dim Json As JObject
|
||||
Try
|
||||
Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "manifest.json").Open))
|
||||
If Json("minecraft") Is Nothing OrElse Json("minecraft")("version") Is Nothing Then Throw New Exception("整合包未提供 Minecraft 版本信息")
|
||||
Catch ex As Exception
|
||||
Log(ex, "CurseForge 整合包安装信息存在问题", LogLevel.Hint)
|
||||
Return Nothing
|
||||
Throw New Exception("CurseForge 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
If Json("minecraft") Is Nothing OrElse Json("minecraft")("version") Is Nothing Then Throw New Exception("CurseForge 整合包未提供 Minecraft 版本信息")
|
||||
|
||||
'获取版本名
|
||||
Dim ShowRibble As Boolean = VersionName Is Nothing
|
||||
If VersionName Is Nothing Then
|
||||
VersionName = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
|
||||
If Validate.Validate(VersionName) <> "" Then VersionName = ""
|
||||
If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(VersionName) Then Return Nothing
|
||||
If String.IsNullOrEmpty(VersionName) Then Throw New CancelledException
|
||||
End If
|
||||
|
||||
'获取 Mod API 版本信息
|
||||
@@ -190,35 +187,19 @@ Retry:
|
||||
Dim Id As String = If(Entry("id"), "").ToString.ToLower
|
||||
If Id.StartsWithF("forge-") Then
|
||||
'Forge 指定
|
||||
If Id.Contains("recommended") Then
|
||||
Log("[ModPack] 该整合包版本过老,已不支持进行安装!", LogLevel.Hint)
|
||||
Return Nothing
|
||||
End If
|
||||
Try
|
||||
Log("[ModPack] 整合包 Forge 版本:" & Id)
|
||||
ForgeVersion = Id.Replace("forge-", "")
|
||||
Exit For
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取整合包 Forge 版本失败:" & Id)
|
||||
End Try
|
||||
If Id.Contains("recommended") Then Throw New Exception("该整合包版本过老,已不支持进行安装!")
|
||||
Log("[ModPack] 整合包 Forge 版本:" & Id)
|
||||
ForgeVersion = Id.Replace("forge-", "")
|
||||
ElseIf Id.StartsWithF("neoforge-") Then
|
||||
'NeoForge 指定
|
||||
Try
|
||||
Log("[ModPack] 整合包 NeoForge 版本:" & Id)
|
||||
NeoForgeVersion = Id.Replace("neoforge-", "")
|
||||
Exit For
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取整合包 NeoForge 版本失败:" & Id)
|
||||
End Try
|
||||
Log("[ModPack] 整合包 NeoForge 版本:" & Id)
|
||||
NeoForgeVersion = Id.Replace("neoforge-", "")
|
||||
ElseIf Id.StartsWithF("fabric-") Then
|
||||
'Fabric 指定
|
||||
Try
|
||||
Log("[ModPack] 整合包 Fabric 版本:" & Id)
|
||||
FabricVersion = Id.Replace("fabric-", "")
|
||||
Exit For
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取整合包 Fabric 版本失败:" & Id)
|
||||
End Try
|
||||
Log("[ModPack] 整合包 Fabric 版本:" & Id)
|
||||
FabricVersion = Id.Replace("fabric-", "")
|
||||
Else
|
||||
Log("[ModPack] 未知 Mod 加载器:" & Id)
|
||||
End If
|
||||
Next
|
||||
'解压与配置文件
|
||||
@@ -228,17 +209,17 @@ Retry:
|
||||
If OverrideHome <> "" Then
|
||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
UnpackFiles(InstallTemp, FileAddress, Task)
|
||||
Task.Progress = 0.5
|
||||
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
|
||||
Task.Progress = 0.6
|
||||
Dim OverridePath As String = InstallTemp & ArchiveBaseFolder & OverrideHome
|
||||
'复制结果
|
||||
If Directory.Exists(OverridePath) Then
|
||||
CopyDirectory(OverridePath, PathMcFolder & "versions\" & VersionName)
|
||||
CopyDirectory(OverridePath, PathMcFolder & "versions\" & VersionName, Sub(Delta) Task.Progress += Delta * 0.35)
|
||||
Log($"[ModPack] 整合包 override 复制:{OverridePath} -> {PathMcFolder & "versions\" & VersionName}")
|
||||
Else
|
||||
Log($"[ModPack] 整合包中未找到 override 文件夹:{OverridePath}")
|
||||
End If
|
||||
Task.Progress = 0.9
|
||||
Task.Progress = 0.95
|
||||
'开启版本隔离
|
||||
WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
|
||||
End Sub) With {
|
||||
@@ -260,9 +241,11 @@ Retry:
|
||||
'获取 Mod 下载信息
|
||||
ModDownloadLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
|
||||
Sub(Task As LoaderTask(Of Integer, JArray))
|
||||
Task.Output = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json"))("data")
|
||||
'由于 MCIM 缺少下载信息,只使用官方源获取列表
|
||||
'TODO: 在 MCIM 源稳定后回调回 DlModRequest
|
||||
Task.Output = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json"))("data")
|
||||
'如果文件已被删除,则 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 作者删除,所以没法继续安装了,请向整合包作者反馈该问题")
|
||||
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
||||
'构造 NetFile
|
||||
ModDownloadLoaders.Add(New LoaderTask(Of JArray, List(Of NetFile))("构造 Mod 下载信息",
|
||||
@@ -320,7 +303,6 @@ Retry:
|
||||
.FabricVersion = FabricVersion
|
||||
}
|
||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||
If MergeLoaders Is Nothing Then Return Nothing
|
||||
'构造 Libraries 加载器
|
||||
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})
|
||||
@@ -342,8 +324,8 @@ Retry:
|
||||
End If
|
||||
'删除原始整合包文件
|
||||
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
||||
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
||||
Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
|
||||
If File.Exists(Target) Then
|
||||
Log("[ModPack] 删除原始整合包文件:" & Target)
|
||||
File.Delete(Target)
|
||||
End If
|
||||
Next
|
||||
@@ -353,7 +335,7 @@ Retry:
|
||||
Dim LoaderName As String = "CurseForge 整合包安装:" & VersionName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -361,7 +343,7 @@ Retry:
|
||||
Loader.Start(Request.TargetVersionFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
|
||||
Return Loader
|
||||
End Function
|
||||
|
||||
@@ -372,11 +354,10 @@ Retry:
|
||||
Dim Json As JObject
|
||||
Try
|
||||
Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "modrinth.index.json").Open))
|
||||
If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("整合包未提供 Minecraft 版本信息")
|
||||
Catch ex As Exception
|
||||
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
|
||||
Return Nothing
|
||||
Throw New Exception("Modrinth 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("Modrinth 整合包未提供 Minecraft 版本信息")
|
||||
'获取 Mod API 版本信息
|
||||
Dim MinecraftVersion As String = Nothing
|
||||
Dim ForgeVersion As String = Nothing
|
||||
@@ -397,39 +378,40 @@ Retry:
|
||||
Log("[ModPack] 整合包 Fabric 版本:" & FabricVersion)
|
||||
Case "quilt-loader" 'eg. 1.0.0
|
||||
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
Case Else
|
||||
Hint($"无法安装整合包,其中出现了未知的 Mod 加载器 {Entry.Value}!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End Select
|
||||
Next
|
||||
'获取版本名
|
||||
Dim ShowRibble As Boolean = VersionName Is Nothing
|
||||
If VersionName Is Nothing Then
|
||||
VersionName = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
|
||||
If Validate.Validate(VersionName) <> "" Then VersionName = ""
|
||||
If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(VersionName) Then Return Nothing
|
||||
If String.IsNullOrEmpty(VersionName) Then Throw New CancelledException
|
||||
End If
|
||||
'解压和配置文件
|
||||
Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
|
||||
Dim InstallLoaders As New List(Of LoaderBase)
|
||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
UnpackFiles(InstallTemp, FileAddress, Task)
|
||||
Task.Progress = 0.5
|
||||
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
|
||||
Task.Progress = 0.6
|
||||
'复制 overrides 文件夹和 client-overrides 文件夹
|
||||
If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName)
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName,
|
||||
Sub(Delta) Task.Progress += Delta * 0.25)
|
||||
Else
|
||||
Log("[ModPack] 整合包中未找到 override 目录,已跳过")
|
||||
End If
|
||||
Task.Progress = 0.8
|
||||
Task.Progress = 0.85
|
||||
If Directory.Exists(InstallTemp & ArchiveBaseFolder & "client-overrides") Then
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", PathMcFolder & "versions\" & VersionName)
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", PathMcFolder & "versions\" & VersionName,
|
||||
Sub(Delta) Task.Progress += Delta * 0.1)
|
||||
End If
|
||||
Task.Progress = 0.9
|
||||
Task.Progress = 0.95
|
||||
'开启版本隔离
|
||||
WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
|
||||
End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||
@@ -469,7 +451,6 @@ Retry:
|
||||
.FabricVersion = FabricVersion
|
||||
}
|
||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||
If MergeLoaders Is Nothing Then Return Nothing
|
||||
'构造 Libraries 加载器
|
||||
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})
|
||||
@@ -491,8 +472,8 @@ Retry:
|
||||
End If
|
||||
'删除原始整合包文件
|
||||
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
||||
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
||||
Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
|
||||
If File.Exists(Target) Then
|
||||
Log("[ModPack] 删除原始整合包文件:" & Target)
|
||||
File.Delete(Target)
|
||||
End If
|
||||
Next
|
||||
@@ -502,7 +483,7 @@ Retry:
|
||||
Dim LoaderName As String = "Modrinth 整合包安装:" & VersionName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -510,9 +491,8 @@ Retry:
|
||||
Loader.Start(Request.TargetVersionFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
|
||||
Return Loader
|
||||
|
||||
End Function
|
||||
|
||||
'HMCL
|
||||
@@ -522,44 +502,39 @@ Retry:
|
||||
Try
|
||||
Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "modpack.json").Open, Encoding.UTF8))
|
||||
Catch ex As Exception
|
||||
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
|
||||
Return Nothing
|
||||
Throw New Exception("HMCL 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
'获取版本名
|
||||
Dim VersionName As String = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
|
||||
If Validate.Validate(VersionName) <> "" Then VersionName = ""
|
||||
If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(VersionName) Then Return Nothing
|
||||
If String.IsNullOrEmpty(VersionName) Then Throw New CancelledException
|
||||
'解压与配置文件
|
||||
Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
|
||||
Dim InstallLoaders As New List(Of LoaderBase)
|
||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
UnpackFiles(InstallTemp, FileAddress, Task)
|
||||
Task.Progress = 0.5
|
||||
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
|
||||
Task.Progress = 0.6
|
||||
'复制结果
|
||||
If Directory.Exists(InstallTemp & ArchiveBaseFolder & "minecraft") Then
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "minecraft", PathMcFolder & "versions\" & VersionName)
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "minecraft", PathMcFolder & "versions\" & VersionName, Sub(Delta) Task.Progress += Delta * 0.35)
|
||||
Else
|
||||
Log("[ModPack] 整合包中未找到 minecraft override 目录,已跳过")
|
||||
End If
|
||||
Task.Progress = 0.9
|
||||
Task.Progress = 0.95
|
||||
'开启版本隔离
|
||||
WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
|
||||
End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||
'构造加载器
|
||||
If Json("gameVersion") Is Nothing Then
|
||||
Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
|
||||
Return Nothing
|
||||
End If
|
||||
If Json("gameVersion") Is Nothing Then Throw New Exception("该 HMCL 整合包未提供游戏版本信息,无法安装!")
|
||||
Dim Request As New McInstallRequest With {
|
||||
.TargetVersionName = VersionName,
|
||||
.TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
|
||||
.MinecraftName = Json("gameVersion").ToString
|
||||
}
|
||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||
If MergeLoaders Is Nothing Then Return Nothing
|
||||
'构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
|
||||
Dim LoadersLib As New List(Of LoaderBase)
|
||||
LoadersLib.Add(New LoaderTask(Of String, String)("重命名版本 Json(副加载器)",
|
||||
@@ -589,7 +564,7 @@ Retry:
|
||||
Dim LoaderName As String = "HMCL 整合包安装:" & VersionName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -598,7 +573,7 @@ Retry:
|
||||
Loader.Start(Request.TargetVersionFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
|
||||
Return Loader
|
||||
End Function
|
||||
|
||||
@@ -610,30 +585,29 @@ Retry:
|
||||
PackJson = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "mmc-pack.json").Open, Encoding.UTF8))
|
||||
PackInstance = ReadFile(Archive.GetEntry(ArchiveBaseFolder & "instance.cfg").Open, Encoding.UTF8)
|
||||
Catch ex As Exception
|
||||
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
|
||||
Return Nothing
|
||||
Throw New Exception("MMC 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
'获取版本名
|
||||
Dim VersionName As String = If(RegexSeek(PackInstance, "(?<=\nname\=)[^\n]+"), "")
|
||||
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
|
||||
If Validate.Validate(VersionName) <> "" Then VersionName = ""
|
||||
If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(VersionName) Then Return Nothing
|
||||
If String.IsNullOrEmpty(VersionName) Then Throw New CancelledException
|
||||
'解压、配置设置文件
|
||||
Dim InstallTemp As String = $"{PathTemp}PackInstall\{RandomInteger(0, 100000)}\"
|
||||
Dim SetupFile As String = $"{PathMcFolder}versions\{VersionName}\PCL\Setup.ini"
|
||||
Dim InstallLoaders As New List(Of LoaderBase)
|
||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
UnpackFiles(InstallTemp, FileAddress, Task)
|
||||
Task.Progress = 0.5
|
||||
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
|
||||
Task.Progress = 0.6
|
||||
'复制结果
|
||||
If Directory.Exists(InstallTemp & ArchiveBaseFolder & ".minecraft") Then
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & ".minecraft", PathMcFolder & "versions\" & VersionName)
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & ".minecraft", PathMcFolder & "versions\" & VersionName, Sub(Delta) Task.Progress += Delta * 0.35)
|
||||
Else
|
||||
Log("[ModPack] 整合包中未找到 override .minecraft 目录,已跳过")
|
||||
End If
|
||||
Task.Progress = 0.9
|
||||
Task.Progress = 0.95
|
||||
'开启版本隔离
|
||||
WriteIni(SetupFile, "VersionArgumentIndie", 1)
|
||||
'读取 MMC 设置文件(#2655)
|
||||
@@ -676,10 +650,7 @@ Retry:
|
||||
End Try
|
||||
End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||
'构造版本安装请求
|
||||
If PackJson("components") Is Nothing Then
|
||||
Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
|
||||
Return Nothing
|
||||
End If
|
||||
If PackJson("components") Is Nothing Then Throw New Exception("该 MMC 整合包未提供游戏版本信息,无法安装!")
|
||||
Dim Request As New McInstallRequest With {.TargetVersionName = VersionName, .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\"}
|
||||
For Each Component In PackJson("components")
|
||||
Select Case If(Component("uid"), "").ToString
|
||||
@@ -695,12 +666,11 @@ Retry:
|
||||
Request.FabricVersion = Component("version")
|
||||
Case "org.quiltmc.quilt-loader" 'eg. 1.0.0
|
||||
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End Select
|
||||
Next
|
||||
'构造加载器
|
||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||
If MergeLoaders Is Nothing Then Return Nothing
|
||||
'构造 Libraries 加载器
|
||||
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})
|
||||
@@ -715,7 +685,7 @@ Retry:
|
||||
Dim LoaderName As String = "MMC 整合包安装:" & VersionName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -723,7 +693,7 @@ Retry:
|
||||
Loader.Start(Request.TargetVersionFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
|
||||
Return Loader
|
||||
End Function
|
||||
|
||||
@@ -736,51 +706,44 @@ Retry:
|
||||
Dim Entry = If(Archive.GetEntry(ArchiveBaseFolder & "mcbbs.packmeta"), Archive.GetEntry(ArchiveBaseFolder & "manifest.json"))
|
||||
Json = GetJson(ReadFile(Entry.Open, Encoding.UTF8))
|
||||
Catch ex As Exception
|
||||
Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
|
||||
Return Nothing
|
||||
Throw New Exception("MCBBS 整合包安装信息存在问题", ex)
|
||||
End Try
|
||||
'获取版本名
|
||||
Dim ShowRibble As Boolean = VersionName Is Nothing
|
||||
If VersionName Is Nothing Then
|
||||
VersionName = If(Json("name"), "")
|
||||
Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
|
||||
If Validate.Validate(VersionName) <> "" Then VersionName = ""
|
||||
If VersionName = "" Then VersionName = MyMsgBoxInput("输入版本名称", "", "", New ObjectModel.Collection(Of Validate) From {Validate})
|
||||
If String.IsNullOrEmpty(VersionName) Then Return Nothing
|
||||
If String.IsNullOrEmpty(VersionName) Then Throw New CancelledException
|
||||
End If
|
||||
'解压与配置文件
|
||||
Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
|
||||
Dim InstallLoaders As New List(Of LoaderBase)
|
||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
UnpackFiles(InstallTemp, FileAddress, Task)
|
||||
Task.Progress = 0.5
|
||||
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
|
||||
Task.Progress = 0.6
|
||||
'复制结果
|
||||
If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName)
|
||||
CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName,
|
||||
Sub(Delta) Task.Progress += 0.35 * Delta)
|
||||
Else
|
||||
Log("[ModPack] 整合包中未找到 overrides 目录,已跳过")
|
||||
End If
|
||||
Task.Progress = 0.9
|
||||
Task.Progress = 0.95
|
||||
'开启版本隔离
|
||||
WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
|
||||
End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||
'构造加载器
|
||||
If Json("addons") Is Nothing Then
|
||||
Hint("该整合包未提供游戏版本附加信息,无法安装!", HintType.Critical)
|
||||
Return Nothing
|
||||
End If
|
||||
If Json("addons") Is Nothing Then Throw New Exception("该 MCBBS 整合包未提供游戏版本附加信息,无法安装!")
|
||||
Dim Addons As New Dictionary(Of String, String)
|
||||
For Each Entry In Json("addons")
|
||||
Addons.Add(Entry("id"), Entry("version"))
|
||||
Next
|
||||
If Not Addons.ContainsKey("game") Then
|
||||
Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
|
||||
Return Nothing
|
||||
End If
|
||||
If Not Addons.ContainsKey("game") Then Throw New Exception("该 MCBBS 整合包未提供游戏版本信息,无法安装!")
|
||||
If Addons.ContainsKey("quilt") Then
|
||||
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
Dim Request As New McInstallRequest With {
|
||||
.TargetVersionName = VersionName,
|
||||
@@ -792,7 +755,6 @@ Retry:
|
||||
.FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
|
||||
}
|
||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
|
||||
If MergeLoaders Is Nothing Then Return Nothing
|
||||
'构造 Libraries 加载器
|
||||
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})
|
||||
@@ -807,7 +769,7 @@ Retry:
|
||||
Dim LoaderName As String = "MCBBS 整合包安装:" & VersionName & " "
|
||||
If LoaderTaskbar.Any(Function(l) l.Name = LoaderName) Then
|
||||
Hint("该整合包正在安装中!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
|
||||
'启动
|
||||
@@ -816,31 +778,101 @@ Retry:
|
||||
Loader.Start(Request.TargetVersionFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
|
||||
Return Loader
|
||||
End Function
|
||||
|
||||
'带启动器的压缩包
|
||||
Private Function InstallPackLauncherPack(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
'获取解压路径
|
||||
MyMsgBox("接下来请选择一个空文件夹,它会被安装到这个文件夹里。", "安装", "继续", ForceWait:=True)
|
||||
Dim TargetFolder As String = SelectFolder("选择安装目标(必须是一个空文件夹)")
|
||||
If String.IsNullOrEmpty(TargetFolder) Then Throw New CancelledException
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Critical) : Throw New CancelledException
|
||||
If Directory.GetFileSystemEntries(TargetFolder).Length > 0 Then Hint("请选择一个空文件夹作为安装目标!", HintType.Critical) : Throw New CancelledException
|
||||
'解压
|
||||
Dim Loader As New LoaderCombo(Of String)("解压压缩包", {
|
||||
New LoaderTask(Of String, Integer)("解压压缩包",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
ExtractModpackFiles(TargetFolder, FileAddress, Task, 0.9)
|
||||
Thread.Sleep(400) '避免文件争用
|
||||
'查找解压后的 exe 文件
|
||||
Dim Launcher As String = Nothing
|
||||
For Each ExeFile In Directory.GetFiles(TargetFolder, "*.exe", SearchOption.AllDirectories)
|
||||
Dim Info = FileVersionInfo.GetVersionInfo(ExeFile)
|
||||
Log($"[Modpack] 文件 {ExeFile} 的产品名标识为 {Info.ProductName}")
|
||||
If Info.ProductName = "Plain Craft Launcher" Then
|
||||
Launcher = ExeFile
|
||||
ElseIf (Info.ProductName.ContainsF("Launcher", True) OrElse Info.ProductName.ContainsF("启动器", True)) AndAlso
|
||||
Not Info.ProductName = "Plain Craft Launcher Admin Manager" Then
|
||||
If Launcher Is Nothing Then Launcher = ExeFile
|
||||
End If
|
||||
Next
|
||||
Task.Progress = 0.95
|
||||
'尝试使用附带的启动器打开
|
||||
If Launcher IsNot Nothing Then
|
||||
Log("[Modpack] 找到压缩包中附带的启动器:" & Launcher)
|
||||
If MyMsgBox($"整合包中似乎自带了启动器,是否换用它继续安装?{vbCrLf}通常推荐这样做,以获得最佳体验。{vbCrLf}即将打开:{Launcher}", "换用整合包启动器?", "继续", "取消") = 1 Then
|
||||
ShellOnly(Launcher, "--wait")
|
||||
Log("[Modpack] 为换用整合包中的启动器启动,强制结束程序")
|
||||
FrmMain.EndProgram(False)
|
||||
Return
|
||||
End If
|
||||
Else
|
||||
Log("[Modpack] 未找到压缩包中附带的启动器")
|
||||
End If
|
||||
'加入文件夹列表
|
||||
Dim VersionName As String = GetFolderNameFromPath(TargetFolder)
|
||||
PageSelectLeft.AddFolder(
|
||||
TargetFolder & ArchiveBaseFolder.Replace("/", "\").TrimStart("\"), '格式例如:包裹文件夹\.minecraft\(最短为空字符串)
|
||||
VersionName, False)
|
||||
'调用 modpack 文件进行安装
|
||||
Dim ModpackFile = Directory.GetFiles(TargetFolder, "modpack.*", SearchOption.AllDirectories).First
|
||||
Log("[Modpack] 调用 modpack 文件继续安装:" & ModpackFile)
|
||||
ModpackInstall(ModpackFile, VersionName)
|
||||
End Sub)
|
||||
})
|
||||
Loader.Start(TargetFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Return Loader
|
||||
End Function
|
||||
|
||||
'普通压缩包
|
||||
Private Function InstallPackCompress(FileAddress As String, ArchiveBaseFolder As String) As LoaderCombo(Of String)
|
||||
MyMsgBox("请在接下来打开的窗口中选择安装目标文件夹,它必须是一个空文件夹。", "安装提示", "继续", ForceWait:=True)
|
||||
Private Function InstallPackCompress(FileAddress As String, Archive As Compression.ZipArchive) As LoaderCombo(Of String)
|
||||
'尝试定位 .minecraft 文件夹:寻找形如 “/versions/XXX/XXX.json” 的路径
|
||||
Dim Match As RegularExpressions.Match = Nothing
|
||||
Dim Regex As New RegularExpressions.Regex("^.*\/(?=versions\/(?<ver>[^\/]+)\/(\k<ver>)\.json$)", RegularExpressions.RegexOptions.IgnoreCase)
|
||||
For Each Entry In Archive.Entries
|
||||
Dim EntryMatch = Regex.Match("/" & Entry.FullName)
|
||||
If EntryMatch.Success Then
|
||||
Match = EntryMatch
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
If Match Is Nothing Then Throw New Exception("未能找到适合的文件结构,这可能不是一个 MC 压缩包") '没有匹配
|
||||
Dim ArchiveBaseFolder As String = Match.Value.Replace("/", "\").TrimStart("\") '格式例如:包裹文件夹\.minecraft\(最短为空字符串)
|
||||
Dim VersionName As String = Match.Groups(1).Value
|
||||
Log("[ModPack] 检测到压缩包的 .minecraft 根目录:" & ArchiveBaseFolder & ",命中的版本名:" & VersionName)
|
||||
'获取解压路径
|
||||
MyMsgBox("接下来请选择一个空文件夹,它会被安装到这个文件夹里。", "安装", "继续", ForceWait:=True)
|
||||
Dim TargetFolder As String = SelectFolder("选择安装目标(必须是一个空文件夹)")
|
||||
If String.IsNullOrEmpty(TargetFolder) Then Return Nothing
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Critical) : Return Nothing
|
||||
If Directory.GetFileSystemEntries(TargetFolder).Length > 0 Then Hint("请选择一个空文件夹作为安装目标!", HintType.Critical) : Return Nothing
|
||||
'要求显示名称
|
||||
Dim NewName As String = MyMsgBoxInput("输入显示名称", "输入该文件夹在左边栏列表中显示的名称。", GetFolderNameFromPath(TargetFolder),
|
||||
New ObjectModel.Collection(Of Validate) From {New ValidateNullOrWhiteSpace, New ValidateLength(1, 30), New ValidateExcept({">", "|"})})
|
||||
If String.IsNullOrWhiteSpace(NewName) Then Return Nothing
|
||||
If String.IsNullOrEmpty(TargetFolder) Then Throw New CancelledException
|
||||
If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Critical) : Throw New CancelledException
|
||||
If Directory.GetFileSystemEntries(TargetFolder).Length > 0 Then Hint("请选择一个空文件夹作为安装目标!", HintType.Critical) : Throw New CancelledException
|
||||
'解压
|
||||
Dim Loader As New LoaderCombo(Of String)("安装压缩包", {
|
||||
New LoaderTask(Of String, Integer)("安装压缩包",
|
||||
Sub()
|
||||
UnpackFiles(TargetFolder, FileAddress, Nothing)
|
||||
PageSelectLeft.AddFolder(TargetFolder, NewName, False) '加入文件夹列表
|
||||
End Sub)
|
||||
})
|
||||
Loader.Start()
|
||||
Dim Loader As New LoaderCombo(Of String)("解压压缩包", {
|
||||
New LoaderTask(Of String, Integer)("解压压缩包",
|
||||
Sub(Task As LoaderTask(Of String, Integer))
|
||||
ExtractModpackFiles(TargetFolder, FileAddress, Task, 0.95)
|
||||
'加入文件夹列表
|
||||
PageSelectLeft.AddFolder(TargetFolder & ArchiveBaseFolder, GetFolderNameFromPath(TargetFolder), False)
|
||||
Thread.Sleep(400) '避免文件争用
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.VersionSelect))
|
||||
End Sub)
|
||||
}) With {.OnStateChanged = AddressOf McInstallState}
|
||||
Loader.Start(TargetFolder)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<Grid x:Class="MyCompItem"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:PCL"
|
||||
x:Name="PanBack" Height="64"
|
||||
RenderTransformOrigin="0.5,0.5" Background="{StaticResource ColorBrushSemiTransparent}" SnapsToDevicePixels="True">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -23,7 +24,7 @@
|
||||
<Border.Clip>
|
||||
<RectangleGeometry Rect="0,0,50,50" RadiusX="6" RadiusY="6" />
|
||||
</Border.Clip>
|
||||
<Image x:Name="PathLogo" RenderOptions.BitmapScalingMode="HighQuality" />
|
||||
<local:MyImage x:Name="PathLogo" RenderOptions.BitmapScalingMode="HighQuality" FallbackSource="pack://application:,,,/images/Icons/NoIcon.png" />
|
||||
</Border>
|
||||
<!-- 标题 -->
|
||||
<StackPanel Grid.Column="3" Grid.ColumnSpan="2" Grid.Row="1" VerticalAlignment="Bottom" Margin="0,1,0,0" Orientation="Horizontal"
|
||||
|
||||
@@ -4,87 +4,14 @@
|
||||
Public Uuid As Integer = GetUuid()
|
||||
|
||||
'Logo
|
||||
Private _Logo As String = ""
|
||||
Public Property Logo As String
|
||||
Get
|
||||
Return _Logo
|
||||
Return PathLogo.Source
|
||||
End Get
|
||||
Set(value As String)
|
||||
If _Logo = value OrElse value Is Nothing Then Exit Property
|
||||
_Logo = value
|
||||
Dim FileAddress = PathTemp & "CompLogo\" & GetHash(_Logo) & ".png"
|
||||
Try
|
||||
If _Logo.StartsWithF("http", True) Then
|
||||
'网络图片
|
||||
If File.Exists(FileAddress) Then
|
||||
PathLogo.Source = New MyBitmap(FileAddress)
|
||||
Else
|
||||
PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png")
|
||||
RunInNewThread(Sub() LogoLoader(FileAddress), "Comp Logo Loader " & Uuid & "#", ThreadPriority.BelowNormal)
|
||||
End If
|
||||
Else
|
||||
'位图
|
||||
PathLogo.Source = New MyBitmap(_Logo)
|
||||
End If
|
||||
Catch ex As IOException
|
||||
Log(ex, "加载资源工程图标时读取失败(" & FileAddress & ")")
|
||||
Catch ex As ArgumentException
|
||||
'考虑缓存的图片本身可能有误
|
||||
Log(ex, "可视化资源工程图标失败(" & FileAddress & ")")
|
||||
Try
|
||||
File.Delete(FileAddress)
|
||||
Log("[Comp] 已清理损坏的资源工程图标:" & FileAddress)
|
||||
Catch exx As Exception
|
||||
Log(exx, "清理损坏的资源工程图标缓存失败(" & FileAddress & ")", LogLevel.Hint)
|
||||
End Try
|
||||
Catch ex As Exception
|
||||
Log(ex, "加载资源工程图标失败(" & value & ")")
|
||||
End Try
|
||||
PathLogo.Source = value
|
||||
End Set
|
||||
End Property
|
||||
'后台加载 Logo
|
||||
Private Sub LogoLoader(LocalFileAddress As String)
|
||||
Dim Retried As Boolean = False
|
||||
Dim DownloadEnd As String = GetUuid()
|
||||
RetryStart:
|
||||
Try
|
||||
'CurseForge 图片使用缩略图
|
||||
Dim Url As String = _Logo
|
||||
If Url.Contains("/256/256/") AndAlso GetPixelSize(1) <= 1.25 AndAlso Not Retried Then
|
||||
Url = Url.Replace("/256/256/", "/64/64/") '#3075:部分 Mod 不存在 64x64 图标,所以重试时不再缩小
|
||||
End If
|
||||
'下载图片
|
||||
NetDownload(Url, LocalFileAddress & DownloadEnd, True)
|
||||
Dim LoadError As Exception = Nothing
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
Try
|
||||
'在地址更换时取消加载
|
||||
If LocalFileAddress <> $"{PathTemp}CompLogo\{GetHash(_Logo)}.png" Then Exit Sub
|
||||
'在完成正常加载后才保存缓存图片
|
||||
PathLogo.Source = New MyBitmap(LocalFileAddress & DownloadEnd)
|
||||
Catch ex As Exception
|
||||
Log(ex, $"读取资源工程图标失败({LocalFileAddress})")
|
||||
File.Delete(LocalFileAddress & DownloadEnd)
|
||||
LoadError = ex
|
||||
End Try
|
||||
End Sub)
|
||||
If LoadError IsNot Nothing Then Throw LoadError
|
||||
If File.Exists(LocalFileAddress) Then
|
||||
File.Delete(LocalFileAddress & DownloadEnd)
|
||||
Else
|
||||
FileIO.FileSystem.MoveFile(LocalFileAddress & DownloadEnd, LocalFileAddress)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
If Not Retried Then
|
||||
Retried = True
|
||||
GoTo RetryStart
|
||||
Else
|
||||
Log(ex, $"下载资源工程图标失败({_Logo})")
|
||||
RunInUi(Sub() PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png"))
|
||||
End If
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'标题
|
||||
Public Property Title As String
|
||||
@@ -169,7 +96,7 @@ RetryStart:
|
||||
'记录当前展开的卡片标题(#2712)
|
||||
Dim Titles As New List(Of String)
|
||||
If FrmMain.PageCurrent.Page = FormMain.PageType.CompDetail Then
|
||||
For Each Card As MyCard In FrmDownloadCompDetail.PanMain.Children
|
||||
For Each Card As MyCard In FrmDownloadCompDetail.PanResults.Children
|
||||
If Card.Title <> "" AndAlso Not Card.IsSwaped Then Titles.Add(Card.Title)
|
||||
Next
|
||||
Log("[Comp] 记录当前已展开的卡片:" & String.Join("、", Titles))
|
||||
|
||||
@@ -24,18 +24,18 @@
|
||||
<Border.Clip>
|
||||
<RectangleGeometry Rect="0,0,34,34" RadiusX="6" RadiusY="6" />
|
||||
</Border.Clip>
|
||||
<Image x:Name="PathLogo" RenderOptions.BitmapScalingMode="HighQuality" />
|
||||
<local:MyImage x:Name="PathLogo" RenderOptions.BitmapScalingMode="HighQuality" FallbackSource="pack://application:,,,/images/Icons/NoIcon.png" />
|
||||
</Border>
|
||||
<!-- 标题 -->
|
||||
<Grid Grid.Column="3" Grid.ColumnSpan="2" Grid.Row="1" VerticalAlignment="Bottom" Margin="0,1,0,0"
|
||||
SnapsToDevicePixels="False" UseLayoutRounding="False" x:Name="PanTitle">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" x:Name="ColumnTitle" />
|
||||
<ColumnDefinition Width="Auto" x:Name="ColumnSubtitle" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" x:Name="ColumnExtend" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="LabTitle" TextTrimming="WordEllipsis" FontSize="14" IsHitTestVisible="False" />
|
||||
<TextBlock x:Name="LabTitle" TextTrimming="CharacterEllipsis" FontSize="14" IsHitTestVisible="False" />
|
||||
<TextBlock x:Name="LabSubtitle" Grid.Column="1" HorizontalAlignment="Left"
|
||||
TextTrimming="CharacterEllipsis" FontSize="12" IsHitTestVisible="False"
|
||||
Foreground="{StaticResource ColorBrushGray1}" Opacity="0.4" VerticalAlignment="Bottom" Visibility="Collapsed" />
|
||||
@@ -52,6 +52,6 @@
|
||||
</Border>-->
|
||||
</StackPanel>
|
||||
<TextBlock x:Name="LabInfo" Grid.Row="2" Grid.Column="4" VerticalAlignment="Bottom" Margin="0,0,3,1"
|
||||
TextTrimming="CharacterEllipsis" FontSize="12" Foreground="{StaticResource ColorBrushGray3}"
|
||||
TextTrimming="CharacterEllipsis" FontSize="12" Foreground="{StaticResource ColorBrushGray4}"
|
||||
IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
</Grid>
|
||||
@@ -6,88 +6,14 @@ Public Class MyLocalModItem
|
||||
Public Uuid As Integer = GetUuid()
|
||||
|
||||
'Logo
|
||||
Private _Logo As String = ""
|
||||
Public Property Logo As String
|
||||
Get
|
||||
Return _Logo
|
||||
Return PathLogo.Source
|
||||
End Get
|
||||
Set(value As String)
|
||||
If _Logo = value OrElse value Is Nothing Then Exit Property
|
||||
_Logo = value
|
||||
If ModeDebug AndAlso Not _Logo = PathImage & "Icons/NoIcon.png" Then Log($"[LocalModItem] Mod {Title} 的图标:{value}")
|
||||
Dim FileAddress = PathTemp & "CompLogo\" & GetHash(_Logo) & ".png"
|
||||
Try
|
||||
If _Logo.StartsWithF("http", True) Then
|
||||
'网络图片
|
||||
If File.Exists(FileAddress) Then
|
||||
PathLogo.Source = New MyBitmap(FileAddress)
|
||||
Else
|
||||
PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png")
|
||||
RunInNewThread(Sub() LogoLoader(FileAddress), "Comp Logo Loader " & Uuid & "#", ThreadPriority.BelowNormal)
|
||||
End If
|
||||
Else
|
||||
'位图
|
||||
PathLogo.Source = New MyBitmap(_Logo)
|
||||
End If
|
||||
Catch ex As IOException
|
||||
Log(ex, "加载本地 Mod 图标时读取失败(" & FileAddress & ")")
|
||||
Catch ex As ArgumentException
|
||||
'考虑缓存的图片本身可能有误
|
||||
Log(ex, "可视化本地 Mod 图标失败(" & FileAddress & ")")
|
||||
Try
|
||||
File.Delete(FileAddress)
|
||||
Log("[LocalModItem] 已清理损坏的本地 Mod 图标:" & FileAddress)
|
||||
Catch exx As Exception
|
||||
Log(exx, "清理损坏的本地 Mod 图标缓存失败(" & FileAddress & ")", LogLevel.Hint)
|
||||
End Try
|
||||
Catch ex As Exception
|
||||
Log(ex, "加载本地 Mod 图标失败(" & value & ")")
|
||||
End Try
|
||||
PathLogo.Source = value
|
||||
End Set
|
||||
End Property
|
||||
'后台加载 Logo
|
||||
Private Sub LogoLoader(LocalFileAddress As String)
|
||||
Dim Retried As Boolean = False
|
||||
Dim DownloadEnd As String = GetUuid()
|
||||
RetryStart:
|
||||
Try
|
||||
'CurseForge 图片使用缩略图
|
||||
Dim Url As String = _Logo
|
||||
If Url.Contains("/256/256/") AndAlso GetPixelSize(1) <= 1.25 AndAlso Not Retried Then '#3075:部分 Mod 不存在 64x64 图标,所以重试时不再缩小
|
||||
Url = Url.Replace("/256/256/", "/64/64/")
|
||||
End If
|
||||
'下载图片
|
||||
NetDownload(Url, LocalFileAddress & DownloadEnd, True)
|
||||
Dim LoadError As Exception = Nothing
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
Try
|
||||
'在地址更换时取消加载
|
||||
If LocalFileAddress <> $"{PathTemp}CompLogo\{GetHash(_Logo)}.png" Then Exit Sub
|
||||
'在完成正常加载后才保存缓存图片
|
||||
PathLogo.Source = New MyBitmap(LocalFileAddress & DownloadEnd)
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取本地 Mod 图标失败(" & LocalFileAddress & ")")
|
||||
File.Delete(LocalFileAddress & DownloadEnd)
|
||||
LoadError = ex
|
||||
End Try
|
||||
End Sub)
|
||||
If LoadError IsNot Nothing Then Throw LoadError
|
||||
If File.Exists(LocalFileAddress) Then
|
||||
File.Delete(LocalFileAddress & DownloadEnd)
|
||||
Else
|
||||
FileIO.FileSystem.MoveFile(LocalFileAddress & DownloadEnd, LocalFileAddress)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
If Not Retried Then
|
||||
Retried = True
|
||||
GoTo RetryStart
|
||||
Else
|
||||
Log(ex, $"下载本地 Mod 图标失败({_Logo})")
|
||||
RunInUi(Sub() PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png"))
|
||||
End If
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'标题
|
||||
Private _Title As String
|
||||
@@ -143,9 +69,9 @@ RetryStart:
|
||||
For Each TagText In value
|
||||
Dim NewTag = GetObjectFromXML(
|
||||
"<Border xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
|
||||
Background=""#11000000"" Padding=""3,1"" CornerRadius=""3"" Margin=""0,0,3,0""
|
||||
Background=""#0C000000"" Padding=""3,1"" CornerRadius=""3"" Margin=""0,0,3,0""
|
||||
SnapsToDevicePixels=""True"" UseLayoutRounding=""False"">
|
||||
<TextBlock Text=""" & TagText & """ Foreground=""#868686"" FontSize=""11"" />
|
||||
<TextBlock Text=""" & TagText & """ Foreground=""#88000000"" FontSize=""11"" />
|
||||
</Border>")
|
||||
PanTags.Children.Add(NewTag)
|
||||
Next
|
||||
@@ -377,57 +303,75 @@ RetryStart:
|
||||
|
||||
#End Region
|
||||
|
||||
Public Sub Refresh()
|
||||
Private Function GetUpdateCompareDescription() As String
|
||||
Dim CurrentName = Entry.CompFile.FileName.Replace(".jar", "")
|
||||
Dim NewestName = Entry.UpdateFile.FileName.Replace(".jar", "")
|
||||
'简化名称对比
|
||||
Dim CurrentSegs = CurrentName.Split("-"c).ToList()
|
||||
Dim NewestSegs = NewestName.Split("-"c).ToList()
|
||||
Dim Shortened As Boolean = False
|
||||
For Each Seg In CurrentSegs.ToList()
|
||||
If Not NewestSegs.Contains(Seg) Then Continue For
|
||||
CurrentSegs.Remove(Seg)
|
||||
NewestSegs.Remove(Seg)
|
||||
Shortened = True
|
||||
Next
|
||||
If Shortened AndAlso CurrentSegs.Any() AndAlso NewestSegs.Any() Then
|
||||
CurrentName = Join(CurrentSegs, "-")
|
||||
NewestName = Join(NewestSegs, "-")
|
||||
Entry._Version = CurrentName '使用网络信息作为显示的版本号
|
||||
End If
|
||||
Return $"当前版本:{CurrentName}({GetTimeSpanString(Entry.CompFile.ReleaseDate - Date.Now, False)}){vbCrLf}最新版本:{NewestName}({GetTimeSpanString(Entry.UpdateFile.ReleaseDate - Date.Now, False)})"
|
||||
End Function
|
||||
Public Sub Refresh() Handles Me.Loaded
|
||||
RunInUi(
|
||||
Sub()
|
||||
'更新
|
||||
If Entry.CanUpdate Then
|
||||
BtnUpdate.Visibility = Visibility.Visible
|
||||
Dim CurrentName = Entry.CompFile.FileName.Replace(".jar", "")
|
||||
Dim NewestName = Entry.UpdateFile.FileName.Replace(".jar", "")
|
||||
'简化名称对比
|
||||
Dim CurrentSegs = CurrentName.Split("-"c).ToList()
|
||||
Dim NewestSegs = NewestName.Split("-"c).ToList()
|
||||
Dim Shortened As Boolean = False
|
||||
For Each Seg In CurrentSegs.ToList()
|
||||
If Not NewestSegs.Contains(Seg) Then Continue For
|
||||
CurrentSegs.Remove(Seg)
|
||||
NewestSegs.Remove(Seg)
|
||||
Shortened = True
|
||||
Next
|
||||
If Shortened AndAlso CurrentSegs.Any() AndAlso NewestSegs.Any() Then
|
||||
CurrentName = Join(CurrentSegs, "-")
|
||||
NewestName = Join(NewestSegs, "-")
|
||||
Entry._Version = CurrentName '使用网络信息作为显示的版本号
|
||||
End If
|
||||
BtnUpdate.ToolTip = $"当前版本:{CurrentName} ({Entry.CompFile.ReleaseDate:yyyy/MM/dd HH:mm:ss}){vbCrLf}最新版本:{NewestName} ({Entry.UpdateFile.ReleaseDate:yyyy/MM/dd HH:mm:ss}){vbCrLf}点击以更新,右键查看更新日志。"
|
||||
BtnUpdate.ToolTip = $"{GetUpdateCompareDescription()}{vbCrLf}点击以更新,右键查看更新日志。"
|
||||
Else
|
||||
BtnUpdate.Visibility = Visibility.Collapsed
|
||||
End If
|
||||
'标题
|
||||
If Entry.Comp Is Nothing Then
|
||||
Title = Entry.Name
|
||||
SubTitle = If(Entry.Version Is Nothing, "", " | " & Entry.Version)
|
||||
Else
|
||||
Dim Titles = Entry.Comp.GetControlTitle(False)
|
||||
Title = Titles.Key
|
||||
SubTitle = Titles.Value & If(Entry.Version Is Nothing, "", " | " & Entry.Version)
|
||||
End If
|
||||
If Checked Then
|
||||
LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5"))
|
||||
Else
|
||||
LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush1", "ColorBrushGray4"))
|
||||
End If
|
||||
'描述
|
||||
Dim NewDescription As String
|
||||
'标题与描述
|
||||
Dim DescFileName As String
|
||||
Select Case Entry.State
|
||||
Case McMod.McModState.Fine
|
||||
NewDescription = GetFileNameWithoutExtentionFromPath(Entry.Path)
|
||||
DescFileName = GetFileNameWithoutExtentionFromPath(Entry.Path)
|
||||
Case McMod.McModState.Disabled
|
||||
NewDescription = GetFileNameWithoutExtentionFromPath(Entry.Path.Replace(".disabled", "").Replace(".old", ""))
|
||||
DescFileName = GetFileNameWithoutExtentionFromPath(Entry.Path.Replace(".disabled", "").Replace(".old", ""))
|
||||
Case Else 'McMod.McModState.Unavailable
|
||||
NewDescription = GetFileNameFromPath(Entry.Path)
|
||||
DescFileName = GetFileNameFromPath(Entry.Path)
|
||||
End Select
|
||||
Dim NewDescription As String
|
||||
If Setup.Get("ToolModLocalNameStyle") = 1 Then
|
||||
'标题显示文件名,详情显示译名
|
||||
'标题
|
||||
Title = DescFileName
|
||||
SubTitle = ""
|
||||
'描述
|
||||
If Entry.Comp Is Nothing Then
|
||||
NewDescription = Entry.Name
|
||||
Else
|
||||
Dim Titles = Entry.Comp.GetControlTitle(False)
|
||||
NewDescription = Titles.Key & Titles.Value
|
||||
End If
|
||||
NewDescription = NewDescription.Replace(" | ", " / ")
|
||||
If Entry.Version IsNot Nothing Then NewDescription &= $" ({Entry.Version})"
|
||||
Else
|
||||
'标题显示译名,详情显示文件名
|
||||
'标题
|
||||
If Entry.Comp Is Nothing Then
|
||||
Title = Entry.Name
|
||||
SubTitle = If(Entry.Version Is Nothing, "", " | " & Entry.Version)
|
||||
Else
|
||||
Dim Titles = Entry.Comp.GetControlTitle(False)
|
||||
Title = Titles.Key
|
||||
SubTitle = Titles.Value & If(Entry.Version Is Nothing, "", " | " & Entry.Version)
|
||||
End If
|
||||
'描述
|
||||
NewDescription = DescFileName
|
||||
End If
|
||||
If Entry.Comp IsNot Nothing Then
|
||||
NewDescription += ": " & Entry.Comp.Description.Replace(vbCr, "").Replace(vbLf, "")
|
||||
ElseIf Entry.Description IsNot Nothing Then
|
||||
@@ -436,6 +380,11 @@ RetryStart:
|
||||
NewDescription += ": " & "存在错误,无法获取信息"
|
||||
End If
|
||||
Description = NewDescription
|
||||
If Checked Then
|
||||
LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5"))
|
||||
Else
|
||||
LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush1", "ColorBrushGray4"))
|
||||
End If
|
||||
'主 Logo
|
||||
Logo = If(Entry.Comp Is Nothing, PathImage & "Icons/NoIcon.png", Entry.Comp.GetControlLogo())
|
||||
'图标右下角的 Logo
|
||||
@@ -530,20 +479,57 @@ RetryStart:
|
||||
|
||||
'触发更新
|
||||
Private Sub BtnUpdate_Click(sender As Object, e As EventArgs) Handles BtnUpdate.Click
|
||||
If MyMsgBox($"是否要更新 {Entry.Name}?{vbCrLf}{vbCrLf}{GetUpdateCompareDescription()}", "Mod 更新确认", "更新", "取消") = 2 Then Return
|
||||
FrmVersionMod.UpdateMods({Entry})
|
||||
End Sub
|
||||
|
||||
'自适应(#4465)
|
||||
Private Sub PanTitle_SizeChanged(sender As Object, e As SizeChangedEventArgs) Handles PanTitle.SizeChanged
|
||||
If ColumnExtend.Width.IsStar AndAlso ColumnExtend.ActualWidth < 0.5 Then
|
||||
'压缩 Subtitle
|
||||
ColumnSubtitle.Width = New GridLength(1, GridUnitType.Star)
|
||||
ColumnExtend.Width = New GridLength(0, GridUnitType.Pixel)
|
||||
ElseIf Not ColumnExtend.Width.IsStar AndAlso ColumnSubtitle.ActualWidth > LabSubtitle.ActualWidth + 10 Then
|
||||
'向右展开 Subtitle
|
||||
ColumnSubtitle.Width = GridLength.Auto
|
||||
ColumnExtend.Width = New GridLength(1, GridUnitType.Star)
|
||||
End If
|
||||
Private Sub PanTitle_SizeChanged() Handles PanTitle.SizeChanged
|
||||
'0:全部舒展:Auto - Auto - (Auto) - 1*
|
||||
'1:压缩 Subtitle:Auto - 1* - (Auto) - 0
|
||||
'2:继续压缩 Title:1* - 0 - (Auto) - 0
|
||||
Dim CurrentCompressLevel As Integer =
|
||||
If(ColumnExtend.Width.IsStar, 0, If(ColumnTitle.Width.IsStar, 2, 1)) 'Subtitle 可能是 Collapsed
|
||||
Dim NewCompressLevel As Integer
|
||||
Select Case CurrentCompressLevel
|
||||
Case 0
|
||||
If ColumnExtend.ActualWidth < 0.5 Then
|
||||
NewCompressLevel = If(LabSubtitle.Visibility = Visibility.Collapsed, 2, 1)
|
||||
Else
|
||||
Return
|
||||
End If
|
||||
Case 1
|
||||
If ColumnSubtitle.ActualWidth < 0.5 Then
|
||||
NewCompressLevel = 2
|
||||
ElseIf Not LabSubtitle.IsTextTrimmed Then
|
||||
NewCompressLevel = 0
|
||||
Else
|
||||
Return
|
||||
End If
|
||||
Case 2
|
||||
If Not LabTitle.IsTextTrimmed Then
|
||||
NewCompressLevel = If(LabSubtitle.Visibility = Visibility.Collapsed, 0, 1)
|
||||
Else
|
||||
Return
|
||||
End If
|
||||
End Select
|
||||
Select Case NewCompressLevel
|
||||
Case 0
|
||||
'全部舒展:Auto - Auto - (Auto) - 1*
|
||||
ColumnTitle.Width = GridLength.Auto
|
||||
ColumnSubtitle.Width = GridLength.Auto
|
||||
ColumnExtend.Width = New GridLength(1, GridUnitType.Star)
|
||||
Case 1
|
||||
'压缩 Subtitle:Auto - 1* - (Auto) - 0
|
||||
ColumnTitle.Width = GridLength.Auto
|
||||
ColumnSubtitle.Width = New GridLength(1, GridUnitType.Star)
|
||||
ColumnExtend.Width = New GridLength(0, GridUnitType.Pixel)
|
||||
Case 2
|
||||
'继续压缩 Title:1* - 0 - (Auto) - 0
|
||||
ColumnTitle.Width = New GridLength(1, GridUnitType.Star)
|
||||
ColumnSubtitle.Width = New GridLength(0, GridUnitType.Pixel)
|
||||
ColumnExtend.Width = New GridLength(0, GridUnitType.Pixel)
|
||||
End Select
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -92,7 +92,18 @@
|
||||
MyMsgBox("EventData 必须为以 http:// 或 https:// 开头的网址。" & vbCrLf & "PCL 不支持其他乱七八糟的下载协议。", "事件执行失败")
|
||||
Exit Sub
|
||||
End If
|
||||
PageOtherTest.StartCustomDownload(Data(0), GetFileNameFromPath(Data(0)))
|
||||
Try
|
||||
Select Case Data.Length
|
||||
Case 1
|
||||
PageOtherTest.StartCustomDownload(Data(0), GetFileNameFromPath(Data(0)))
|
||||
Case 2
|
||||
PageOtherTest.StartCustomDownload(Data(0), Data(1))
|
||||
Case Else
|
||||
PageOtherTest.StartCustomDownload(Data(0), Data(1), Data(2))
|
||||
End Select
|
||||
Catch
|
||||
PageOtherTest.StartCustomDownload(Data(0), "未知")
|
||||
End Try
|
||||
|
||||
Case Else
|
||||
MyMsgBox("未知的事件类型:" & Type & vbCrLf & "请检查事件类型填写是否正确,或者 PCL 是否为最新版本。", "事件执行失败")
|
||||
@@ -128,7 +139,6 @@
|
||||
Dim LocalTemp1 As String = PathTemp & "CustomEvent\" & RawFileName
|
||||
Dim LocalTemp2 As String = PathTemp & "CustomEvent\" & RawFileName.Replace(".json", ".xaml")
|
||||
Log("[Event] 转换网络资源:" & RelativeUrl & " -> " & LocalTemp1)
|
||||
Hint("正在获取资源,请稍候……")
|
||||
Try
|
||||
NetDownload(RelativeUrl, LocalTemp1)
|
||||
NetDownload(RelativeUrl.Replace(".json", ".xaml"), LocalTemp1.Replace(".json", ".xaml"))
|
||||
|
||||
@@ -443,6 +443,10 @@ EndHint:
|
||||
#Region "帮助"
|
||||
|
||||
Public Class HelpEntry
|
||||
''' <summary>
|
||||
''' 原始信息路径。用于刷新。
|
||||
''' </summary>
|
||||
Public RawPath As String
|
||||
|
||||
'基础
|
||||
|
||||
@@ -501,6 +505,7 @@ EndHint:
|
||||
''' 从文件初始化 HelpEntry 对象,失败会抛出异常。
|
||||
''' </summary>
|
||||
Public Sub New(FilePath As String)
|
||||
RawPath = FilePath
|
||||
Dim JsonData As JObject = GetJson(HelpArgumentReplace(ReadFile(FilePath)))
|
||||
If JsonData Is Nothing Then Throw New FileNotFoundException("未找到帮助文件:" & FilePath, FilePath)
|
||||
'加载常规信息
|
||||
@@ -598,7 +603,7 @@ EndHint:
|
||||
'加载忽略列表
|
||||
Log("[Help] 发现 .helpignore 文件:" & File.FullName)
|
||||
For Each Line In ReadFile(File.FullName).Split(vbCrLf.ToCharArray)
|
||||
Dim RealString As String = Line.Before("#").Trim
|
||||
Dim RealString As String = Line.BeforeFirst("#").Trim
|
||||
If String.IsNullOrWhiteSpace(RealString) Then Continue For
|
||||
IgnoreList.Add(RealString)
|
||||
If ModeDebug Then Log("[Help] > " & RealString)
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
''' 初始化音乐播放列表。
|
||||
''' </summary>
|
||||
''' <param name="ForceReload">强制全部重新载入列表。</param>
|
||||
''' <param name="IgnoreFirst">在重载列表时避免让某项成为第一项。</param>
|
||||
Private Sub MusicListInit(ForceReload As Boolean, Optional IgnoreFirst As String = "")
|
||||
''' <param name="PreventFirst">在重载列表时避免让某项成为第一项。</param>
|
||||
Private Sub MusicListInit(ForceReload As Boolean, Optional PreventFirst As String = Nothing)
|
||||
If ForceReload Then MusicAllList = Nothing
|
||||
Try
|
||||
'初始化全部可用音乐列表
|
||||
@@ -31,10 +31,10 @@
|
||||
End If
|
||||
'打乱顺序播放
|
||||
MusicWaitingList = If(Setup.Get("UiMusicRandom"), Shuffle(New List(Of String)(MusicAllList)), New List(Of String)(MusicAllList))
|
||||
If Not IgnoreFirst = "" AndAlso Not Not MusicWaitingList.Any() AndAlso MusicWaitingList(0) = IgnoreFirst Then
|
||||
If PreventFirst IsNot Nothing AndAlso MusicWaitingList.FirstOrDefault = PreventFirst Then
|
||||
'若需要避免成为第一项的为第一项,则将它放在最后
|
||||
MusicWaitingList.RemoveAt(0)
|
||||
MusicWaitingList.Add(IgnoreFirst)
|
||||
MusicWaitingList.Add(PreventFirst)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "初始化音乐列表失败", LogLevel.Feedback)
|
||||
@@ -42,13 +42,18 @@
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 获取下一首播放的音乐路径并将其从列表中移除。
|
||||
''' 如果没有,可能会返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function DequeueNextMusicAddress() As String
|
||||
'初始化,确保存在音乐
|
||||
If MusicAllList Is Nothing OrElse Not MusicAllList.Any() OrElse Not MusicWaitingList.Any() Then MusicListInit(False)
|
||||
'出列下一个音乐,如果出列结束则生成新列表
|
||||
DequeueNextMusicAddress = MusicWaitingList(0)
|
||||
MusicWaitingList.RemoveAt(0)
|
||||
If MusicWaitingList.Any() Then
|
||||
DequeueNextMusicAddress = MusicWaitingList(0)
|
||||
MusicWaitingList.RemoveAt(0)
|
||||
Else
|
||||
DequeueNextMusicAddress = Nothing
|
||||
End If
|
||||
If Not MusicWaitingList.Any() Then MusicListInit(False, DequeueNextMusicAddress)
|
||||
End Function
|
||||
|
||||
@@ -60,44 +65,45 @@
|
||||
''' 刷新背景音乐按钮 UI 与设置页 UI。
|
||||
''' </summary>
|
||||
Private Sub MusicRefreshUI()
|
||||
RunInUi(Sub()
|
||||
Try
|
||||
RunInUi(
|
||||
Sub()
|
||||
Try
|
||||
|
||||
If Not MusicAllList.Any() Then
|
||||
'无背景音乐
|
||||
FrmMain.BtnExtraMusic.Show = False
|
||||
If Not MusicAllList.Any() Then
|
||||
'无背景音乐
|
||||
FrmMain.BtnExtraMusic.Show = False
|
||||
Else
|
||||
'有背景音乐
|
||||
FrmMain.BtnExtraMusic.Show = True
|
||||
Dim ToolTipText As String
|
||||
If MusicState = MusicStates.Pause Then
|
||||
FrmMain.BtnExtraMusic.Logo = Logo.IconPlay
|
||||
FrmMain.BtnExtraMusic.LogoScale = 0.8
|
||||
ToolTipText = "已暂停:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
|
||||
If MusicAllList.Count > 1 Then
|
||||
ToolTipText += vbCrLf & "左键恢复播放,右键播放下一曲。"
|
||||
Else
|
||||
'有背景音乐
|
||||
FrmMain.BtnExtraMusic.Show = True
|
||||
Dim ToolTipText As String
|
||||
If MusicState = MusicStates.Pause Then
|
||||
FrmMain.BtnExtraMusic.Logo = Logo.IconPlay
|
||||
FrmMain.BtnExtraMusic.LogoScale = 0.8
|
||||
ToolTipText = "已暂停:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
|
||||
If MusicAllList.Count > 1 Then
|
||||
ToolTipText += vbCrLf & "左键恢复播放,右键播放下一曲。"
|
||||
Else
|
||||
ToolTipText += vbCrLf & "左键恢复播放,右键重新从头播放。"
|
||||
End If
|
||||
Else
|
||||
FrmMain.BtnExtraMusic.Logo = Logo.IconMusic
|
||||
FrmMain.BtnExtraMusic.LogoScale = 1
|
||||
ToolTipText = "正在播放:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
|
||||
If MusicAllList.Count > 1 Then
|
||||
ToolTipText += vbCrLf & "左键暂停,右键播放下一曲。"
|
||||
Else
|
||||
ToolTipText += vbCrLf & "左键暂停,右键重新从头播放。"
|
||||
End If
|
||||
End If
|
||||
FrmMain.BtnExtraMusic.ToolTip = ToolTipText
|
||||
ToolTipService.SetVerticalOffset(FrmMain.BtnExtraMusic, If(ToolTipText.Contains(vbLf), 10, 16))
|
||||
ToolTipText += vbCrLf & "左键恢复播放,右键重新从头播放。"
|
||||
End If
|
||||
If FrmSetupUI IsNot Nothing Then FrmSetupUI.MusicRefreshUI()
|
||||
Else
|
||||
FrmMain.BtnExtraMusic.Logo = Logo.IconMusic
|
||||
FrmMain.BtnExtraMusic.LogoScale = 1
|
||||
ToolTipText = "正在播放:" & GetFileNameWithoutExtentionFromPath(MusicCurrent)
|
||||
If MusicAllList.Count > 1 Then
|
||||
ToolTipText += vbCrLf & "左键暂停,右键播放下一曲。"
|
||||
Else
|
||||
ToolTipText += vbCrLf & "左键暂停,右键重新从头播放。"
|
||||
End If
|
||||
End If
|
||||
FrmMain.BtnExtraMusic.ToolTip = ToolTipText
|
||||
ToolTipService.SetVerticalOffset(FrmMain.BtnExtraMusic, If(ToolTipText.Contains(vbLf), 10, 16))
|
||||
End If
|
||||
If FrmSetupUI IsNot Nothing Then FrmSetupUI.MusicRefreshUI()
|
||||
|
||||
Catch ex As Exception
|
||||
Log(ex, "刷新背景音乐 UI 失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub)
|
||||
Catch ex As Exception
|
||||
Log(ex, "刷新背景音乐 UI 失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -128,8 +134,12 @@
|
||||
Hint("重新播放:" & GetFileNameFromPath(MusicCurrent), HintType.Finish)
|
||||
Else
|
||||
Dim Address As String = DequeueNextMusicAddress()
|
||||
MusicStartPlay(Address)
|
||||
Hint("正在播放:" & GetFileNameFromPath(Address), HintType.Finish)
|
||||
If Address Is Nothing Then
|
||||
Hint("没有可以播放的音乐!", HintType.Critical)
|
||||
Else
|
||||
MusicStartPlay(Address)
|
||||
Hint("正在播放:" & GetFileNameFromPath(Address), HintType.Finish)
|
||||
End If
|
||||
End If
|
||||
MusicRefreshUI()
|
||||
End Sub
|
||||
@@ -179,11 +189,15 @@
|
||||
End If
|
||||
Else
|
||||
Dim Address As String = DequeueNextMusicAddress()
|
||||
Try
|
||||
MusicStartPlay(Address, IsFirstLoad)
|
||||
If ShowHint Then Hint("背景音乐已刷新:" & GetFileNameFromPath(Address), HintType.Finish, False)
|
||||
Catch
|
||||
End Try
|
||||
If Address Is Nothing Then
|
||||
If ShowHint Then Hint("没有可以播放的音乐!", HintType.Critical)
|
||||
Else
|
||||
Try
|
||||
MusicStartPlay(Address, IsFirstLoad)
|
||||
If ShowHint Then Hint("背景音乐已刷新:" & GetFileNameFromPath(Address), HintType.Finish, False)
|
||||
Catch
|
||||
End Try
|
||||
End If
|
||||
End If
|
||||
MusicRefreshUI()
|
||||
|
||||
@@ -195,6 +209,7 @@
|
||||
''' 开始播放音乐。
|
||||
''' </summary>
|
||||
Private Sub MusicStartPlay(Address As String, Optional IsFirstLoad As Boolean = False)
|
||||
If Address Is Nothing Then Return
|
||||
Log("[Music] 播放开始:" & Address)
|
||||
MusicCurrent = Address
|
||||
RunInNewThread(Sub() MusicLoop(IsFirstLoad), "Music", ThreadPriority.BelowNormal)
|
||||
@@ -280,22 +295,28 @@
|
||||
'当前音乐已播放结束,继续下一曲
|
||||
If CurrentWave.PlaybackState = NAudio.Wave.PlaybackState.Stopped AndAlso MusicAllList.Any Then MusicStartPlay(DequeueNextMusicAddress)
|
||||
Catch ex As Exception
|
||||
Log("[Music] 播放音乐失败的文件完整路径:" & MusicCurrent)
|
||||
Log(ex, "播放音乐出现内部错误(" & MusicCurrent & ")", LogLevel.Developer)
|
||||
If TypeOf ex Is NAudio.MmException AndAlso (ex.Message.Contains("NoDriver") OrElse ex.Message.Contains("BadDeviceId")) Then
|
||||
Hint("由于音频设备变更,音乐播放功能在重启 PCL 后才能恢复!", HintType.Critical)
|
||||
Thread.Sleep(1000000000)
|
||||
End If
|
||||
If ex.Message.Contains("Got a frame at sample rate") OrElse ex.Message.Contains("does not support changes to") Then
|
||||
Hint("播放音乐失败(" & GetFileNameFromPath(MusicCurrent) & "):PCL 不支持播放音频属性在中途发生变化的音乐", HintType.Critical)
|
||||
ElseIf Not (MusicCurrent.EndsWithF(".wav", True) OrElse MusicCurrent.EndsWithF(".mp3", True) OrElse MusicCurrent.EndsWithF(".flac", True)) Then
|
||||
ElseIf Not (MusicCurrent.EndsWithF(".wav", True) OrElse MusicCurrent.EndsWithF(".mp3", True) OrElse MusicCurrent.EndsWithF(".flac", True)) OrElse
|
||||
ex.Message.Contains("0xC00D36C4") Then '#5096:不支持给定的 URL 的字节流类型。 (异常来自 HRESULT:0xC00D36C4)
|
||||
Hint("播放音乐失败(" & GetFileNameFromPath(MusicCurrent) & "):PCL 可能不支持此音乐格式,请将格式转换为 .wav、.mp3 或 .flac 后再试", HintType.Critical)
|
||||
Else
|
||||
Log(ex, "播放音乐失败(" & GetFileNameFromPath(MusicCurrent) & ")", LogLevel.Hint)
|
||||
End If
|
||||
Thread.Sleep(1000)
|
||||
'将播放错误的音乐从列表中移除
|
||||
MusicAllList.Remove(MusicCurrent)
|
||||
MusicWaitingList.Remove(MusicCurrent)
|
||||
MusicRefreshUI()
|
||||
'等待 2 秒后继续播放
|
||||
Thread.Sleep(2000)
|
||||
If TypeOf ex Is FileNotFoundException Then
|
||||
MusicRefreshPlay(True, IsFirstLoad)
|
||||
ElseIf MusicAllList.Count > 1 Then
|
||||
Else
|
||||
MusicStartPlay(DequeueNextMusicAddress(), IsFirstLoad)
|
||||
End If
|
||||
Finally
|
||||
|
||||
@@ -101,29 +101,29 @@ Friend Module ModSecret
|
||||
''' 设置 Headers 的 UA、Referer。
|
||||
''' </summary>
|
||||
Friend Sub SecretHeadersSign(Url As String, ByRef Client As WebClient, Optional UseBrowserUserAgent As Boolean = False)
|
||||
If Url.Contains("modrinth.com") Then '根据 #4334,不添加 PCL 的 UA 反而能正常访问
|
||||
Client.Headers("User-Agent") = "Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
||||
If Url.Contains("baidupcs.com") OrElse Url.Contains("baidu.com") Then
|
||||
Client.Headers("User-Agent") = "LogStatistic" '#4951
|
||||
ElseIf UseBrowserUserAgent Then
|
||||
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
||||
Else
|
||||
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode
|
||||
End If
|
||||
Client.Headers("Referer") = "http://" & VersionCode & ".pcl2.open.server/"
|
||||
Client.Headers("x-api-key") = CurseForgeAPIKey
|
||||
If Url.Contains("api.curseforge.com") Then Client.Headers("x-api-key") = CurseForgeAPIKey
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 设置 Headers 的 UA、Referer。
|
||||
''' </summary>
|
||||
Friend Sub SecretHeadersSign(Url As String, ByRef Request As HttpWebRequest, Optional UseBrowserUserAgent As Boolean = False)
|
||||
If Url.Contains("modrinth.com") Then '根据 #4334,不添加 PCL 的 UA 反而能正常访问
|
||||
Request.UserAgent = "Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
||||
If Url.Contains("baidupcs.com") OrElse Url.Contains("baidu.com") Then
|
||||
Request.UserAgent = "LogStatistic" '#4951
|
||||
ElseIf UseBrowserUserAgent Then
|
||||
Request.UserAgent = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
||||
Else
|
||||
Request.UserAgent = "PCL2/" & VersionStandardCode
|
||||
End If
|
||||
Request.Referer = "http://" & VersionCode & ".pcl2.open.server/"
|
||||
Request.Headers("x-api-key") = CurseForgeAPIKey
|
||||
If Url.Contains("api.curseforge.com") Then Request.Headers("x-api-key") = CurseForgeAPIKey
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
|
||||
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||
' 方法是按如下所示使用“*”
|
||||
|
||||
<Assembly: AssemblyVersion("2.8.7.0")>
|
||||
<Assembly: AssemblyFileVersion("2.8.7.0")>
|
||||
<Assembly: AssemblyVersion("2.8.12.0")>
|
||||
<Assembly: AssemblyFileVersion("2.8.12.0")>
|
||||
<Assembly: NeutralResourcesLanguage("")>
|
||||
@@ -1,4 +1,5 @@
|
||||
Imports System.IO.Compression
|
||||
Imports System.Net.Http
|
||||
|
||||
Public Module ModDownloadLib
|
||||
|
||||
@@ -59,47 +60,6 @@ Public Module ModDownloadLib
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 保存某个 Minecraft 版本的核心文件(仅 Json 与核心 Jar)。
|
||||
''' </summary>
|
||||
''' <param name="Id">所下载的 Minecraft 的版本名。</param>
|
||||
''' <param name="JsonUrl">Json 文件的 Mojang 官方地址。</param>
|
||||
Public Sub McDownloadClientCore(Id As String, JsonUrl As String, Behaviour As NetPreDownloadBehaviour)
|
||||
Try
|
||||
Dim VersionFolder As String = SelectFolder()
|
||||
If Not VersionFolder.Contains("\") Then Exit Sub
|
||||
VersionFolder = VersionFolder & Id & "\"
|
||||
|
||||
'重复任务检查
|
||||
For Each OngoingLoader In LoaderTaskbar.ToList()
|
||||
If OngoingLoader.Name <> $"Minecraft {Id} 下载" Then Continue For
|
||||
If Behaviour = NetPreDownloadBehaviour.ExitWhileExistsOrDownloading Then Exit Sub
|
||||
Hint("该版本正在下载中!", HintType.Critical)
|
||||
Exit Sub
|
||||
Next
|
||||
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
'下载版本 Json 文件
|
||||
Loaders.Add(New LoaderDownload("下载版本 json 文件", New List(Of NetFile) From {
|
||||
New NetFile(DlSourceLauncherOrMetaGet(JsonUrl), VersionFolder & Id & ".json", New FileChecker(CanUseExistsFile:=False, IsJson:=True))
|
||||
}) With {.ProgressWeight = 2})
|
||||
'获取支持库文件地址
|
||||
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析核心 jar 文件下载地址",
|
||||
Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionFolder), True)) With {.ProgressWeight = 0.5, .Show = False})
|
||||
'下载支持库文件
|
||||
Loaders.Add(New LoaderDownload("下载核心 jar 文件", New List(Of NetFile)) With {.ProgressWeight = 5})
|
||||
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)("Minecraft " & Id & " 下载", Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
|
||||
Loader.Start(Id)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
|
||||
Catch ex As Exception
|
||||
Log(ex, "开始 Minecraft 下载失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 获取下载某个 Minecraft 版本的加载器列表。
|
||||
@@ -207,7 +167,12 @@ Public Module ModDownloadLib
|
||||
ToolTipService.SetVerticalOffset(BtnInfo, 30)
|
||||
ToolTipService.SetHorizontalOffset(BtnInfo, 2)
|
||||
AddHandler BtnInfo.Click, AddressOf McDownloadMenuLog
|
||||
sender.Buttons = {BtnInfo}
|
||||
Dim BtnServer As New MyIconButton With {.LogoScale = 1, .Logo = Logo.IconButtonServer, .ToolTip = "下载服务端"}
|
||||
ToolTipService.SetPlacement(BtnServer, Primitives.PlacementMode.Center)
|
||||
ToolTipService.SetVerticalOffset(BtnServer, 30)
|
||||
ToolTipService.SetHorizontalOffset(BtnServer, 2)
|
||||
AddHandler BtnServer.Click, AddressOf McDownloadMenuSaveServer
|
||||
sender.Buttons = {BtnServer, BtnInfo}
|
||||
End Sub
|
||||
Private Sub McDownloadMenuBuild(sender As Object, e As EventArgs)
|
||||
Dim BtnSave As New MyIconButton With {.Logo = Logo.IconButtonSave, .ToolTip = "另存为"}
|
||||
@@ -220,7 +185,12 @@ Public Module ModDownloadLib
|
||||
ToolTipService.SetVerticalOffset(BtnInfo, 30)
|
||||
ToolTipService.SetHorizontalOffset(BtnInfo, 2)
|
||||
AddHandler BtnInfo.Click, AddressOf McDownloadMenuLog
|
||||
sender.Buttons = {BtnSave, BtnInfo}
|
||||
Dim BtnServer As New MyIconButton With {.LogoScale = 1, .Logo = Logo.IconButtonServer, .ToolTip = "下载服务端"}
|
||||
ToolTipService.SetPlacement(BtnServer, Primitives.PlacementMode.Center)
|
||||
ToolTipService.SetVerticalOffset(BtnServer, 30)
|
||||
ToolTipService.SetHorizontalOffset(BtnServer, 2)
|
||||
AddHandler BtnServer.Click, AddressOf McDownloadMenuSaveServer
|
||||
sender.Buttons = {BtnSave, BtnInfo, BtnServer}
|
||||
End Sub
|
||||
Private Sub McDownloadMenuLog(sender As Object, e As RoutedEventArgs)
|
||||
Dim Version As JToken
|
||||
@@ -233,6 +203,83 @@ Public Module ModDownloadLib
|
||||
End If
|
||||
McUpdateLogShow(Version)
|
||||
End Sub
|
||||
Private Sub McDownloadMenuSaveServer(sender As Object, e As RoutedEventArgs)
|
||||
Dim Version As MyListItem
|
||||
If TypeOf sender Is MyListItem Then
|
||||
Version = sender
|
||||
ElseIf TypeOf sender.Parent Is MyListItem Then
|
||||
Version = sender.Parent
|
||||
Else
|
||||
Version = sender.Parent.Parent
|
||||
End If
|
||||
Try
|
||||
Dim Id = Version.Title
|
||||
Dim JsonUrl = Version.Tag("url").ToString
|
||||
Dim VersionFolder As String = SelectFolder()
|
||||
If Not VersionFolder.Contains("\") Then Exit Sub
|
||||
VersionFolder = VersionFolder & Id & "\"
|
||||
|
||||
'重复任务检查
|
||||
For Each OngoingLoader In LoaderTaskbar.ToList()
|
||||
If OngoingLoader.Name <> $"Minecraft {Id} 服务端下载" Then Continue For
|
||||
Hint("该服务端正在下载中!", HintType.Critical)
|
||||
Exit Sub
|
||||
Next
|
||||
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
'下载版本 JSON 文件
|
||||
Loaders.Add(New LoaderDownload("下载版本 JSON 文件", New List(Of NetFile) From {
|
||||
New NetFile(DlSourceLauncherOrMetaGet(JsonUrl), VersionFolder & Id & ".json", New FileChecker(CanUseExistsFile:=False, IsJson:=True))
|
||||
}) With {.ProgressWeight = 2})
|
||||
'构建服务端
|
||||
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("构建服务端",
|
||||
Sub(Task As LoaderTask(Of String, List(Of NetFile)))
|
||||
'分析服务端 JAR 文件下载地址
|
||||
Dim McVersion As New McVersion(VersionFolder)
|
||||
If McVersion.JsonObject("downloads") Is Nothing OrElse McVersion.JsonObject("downloads")("server") Is Nothing OrElse McVersion.JsonObject("downloads")("server")("url") Is Nothing Then
|
||||
File.Delete(VersionFolder & Id & ".json")
|
||||
If Not New DirectoryInfo(VersionFolder).GetFileSystemInfos.Any() Then Directory.Delete(VersionFolder)
|
||||
Task.Output = New List(Of NetFile)
|
||||
Hint($"Mojang 没有给 Minecraft {Id} 提供官方服务端下载,没法下,撤退!", HintType.Critical)
|
||||
Thread.Sleep(2000) '等玩家把上一个提示看完
|
||||
Task.Abort()
|
||||
Exit Sub
|
||||
End If
|
||||
Dim JarUrl As String = McVersion.JsonObject("downloads")("server")("url")
|
||||
Dim Checker As New FileChecker(MinSize:=1024, ActualSize:=If(McVersion.JsonObject("downloads")("server")("size"), -1), Hash:=McVersion.JsonObject("downloads")("server")("sha1"))
|
||||
Task.Output = New List(Of NetFile) From {New NetFile(DlSourceLauncherOrMetaGet(JarUrl), VersionFolder & Id & "-server.jar", Checker)}
|
||||
'添加启动脚本
|
||||
Dim Bat As String =
|
||||
$"@echo off
|
||||
title {Id} 原版服务端
|
||||
echo 如果服务端立即停止,请右键编辑该脚本,将下一行开头的 java 替换为适合该 Minecraft 版本的完整 java.exe 的路径。
|
||||
echo 你可以在 PCL 的 [设置 → 启动选项] 中查看已安装的 java,所需的 java.exe 一般在其中的 bin 文件夹下。
|
||||
echo ------------------------------
|
||||
echo 如果提示 ""You need to agree to the EULA in order to run the server"",请打开 eula.txt,按说明阅读并同意 Minecraft EULA 后,将该文件最后一行中的 eula=false 改为 eula=true。
|
||||
echo ------------------------------
|
||||
""java"" -server -XX:+UseG1GC -Xmx4096M -Xms1024M -XX:+UseCompressedOops -jar {Id}-server.jar nogui
|
||||
echo ----------------------
|
||||
echo 服务端已停止。
|
||||
pause"
|
||||
WriteFile(VersionFolder & "Launch Server.bat", Bat,
|
||||
Encoding:=If(Encoding.Default.Equals(Encoding.UTF8), Encoding.UTF8, Encoding.GetEncoding("GB18030")))
|
||||
'删除版本 JSON
|
||||
File.Delete(VersionFolder & Id & ".json")
|
||||
End Sub
|
||||
) With {.ProgressWeight = 0.5, .Show = False})
|
||||
'下载服务端文件
|
||||
Loaders.Add(New LoaderDownload("下载服务端文件", New List(Of NetFile)) With {.ProgressWeight = 5})
|
||||
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)("Minecraft " & Id & " 服务端下载", Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
|
||||
Loader.Start(Id)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Catch ex As Exception
|
||||
Log(ex, "开始 Minecraft 服务端下载失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub
|
||||
Public Sub McDownloadMenuSave(sender As Object, e As RoutedEventArgs)
|
||||
Dim Version As MyListItem
|
||||
If TypeOf sender Is MyListItem Then
|
||||
@@ -242,7 +289,41 @@ Public Module ModDownloadLib
|
||||
Else
|
||||
Version = sender.Parent.Parent
|
||||
End If
|
||||
McDownloadClientCore(Version.Title, Version.Tag("url").ToString, NetPreDownloadBehaviour.HintWhileExists)
|
||||
Try
|
||||
Dim Id = Version.Title
|
||||
Dim JsonUrl = Version.Tag("url").ToString
|
||||
Dim VersionFolder As String = SelectFolder()
|
||||
If Not VersionFolder.Contains("\") Then Exit Sub
|
||||
VersionFolder = VersionFolder & Id & "\"
|
||||
|
||||
'重复任务检查
|
||||
For Each OngoingLoader In LoaderTaskbar.ToList()
|
||||
If OngoingLoader.Name <> $"Minecraft {Id} 下载" Then Continue For
|
||||
Hint("该版本正在下载中!", HintType.Critical)
|
||||
Exit Sub
|
||||
Next
|
||||
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
'下载版本 JSON 文件
|
||||
Loaders.Add(New LoaderDownload("下载版本 JSON 文件", New List(Of NetFile) From {
|
||||
New NetFile(DlSourceLauncherOrMetaGet(JsonUrl), VersionFolder & Id & ".json", New FileChecker(CanUseExistsFile:=False, IsJson:=True))
|
||||
}) With {.ProgressWeight = 2})
|
||||
'获取支持库文件地址
|
||||
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析核心 JAR 文件下载地址",
|
||||
Sub(Task) Task.Output = New List(Of NetFile) From {DlClientJarGet(New McVersion(VersionFolder), False)}
|
||||
) With {.ProgressWeight = 0.5, .Show = False})
|
||||
'下载支持库文件
|
||||
Loaders.Add(New LoaderDownload("下载核心 JAR 文件", New List(Of NetFile)) With {.ProgressWeight = 5})
|
||||
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)("Minecraft " & Id & " 下载", Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
|
||||
Loader.Start(Id)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Catch ex As Exception
|
||||
Log(ex, "开始 Minecraft 下载失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 显示某 Minecraft 版本的更新日志。
|
||||
@@ -359,7 +440,7 @@ Public Module ModDownloadLib
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
Dim Arguments As String
|
||||
If UseJavaWrapper Then
|
||||
Arguments = $"-Doolloo.jlw.tmpdir=""{GetJavaWrapperDir()}"" -Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" -jar ""{ExtractJavaWrapper()}"" optifine.Installer"
|
||||
Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.TrimEnd("\")}"" -Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" -jar ""{ExtractJavaWrapper()}"" optifine.Installer"
|
||||
Else
|
||||
Arguments = $"-Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" optifine.Installer"
|
||||
End If
|
||||
@@ -478,10 +559,12 @@ Public Module ModDownloadLib
|
||||
Task.Progress = 0.1
|
||||
Dim Sources As New List(Of String)
|
||||
'BMCLAPI 源
|
||||
Dim BmclapiInherit As String = DownloadInfo.Inherit
|
||||
If BmclapiInherit = "1.8" OrElse BmclapiInherit = "1.9" Then BmclapiInherit &= ".0" '#4281
|
||||
If DownloadInfo.IsPreview Then
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/"))
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & BmclapiInherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/"))
|
||||
Else
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", ""))
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & BmclapiInherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", ""))
|
||||
End If
|
||||
'官方源
|
||||
Dim PageData As String
|
||||
@@ -489,12 +572,10 @@ Public Module ModDownloadLib
|
||||
PageData = NetGetCodeByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile, New UTF8Encoding(False), 15000, "text/html", True)
|
||||
Task.Progress = 0.8
|
||||
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources(0))
|
||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取 OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址失败")
|
||||
End Try
|
||||
'OptiFine 中文镜像源
|
||||
Sources.Add("https://optifine.cn/download/" & DownloadInfo.NameFile)
|
||||
'构造文件请求
|
||||
Task.Output = New List(Of NetFile) From {New NetFile(Sources.ToArray, Target, New FileChecker(MinSize:=300 * 1024))}
|
||||
End Sub) With {.ProgressWeight = 8})
|
||||
@@ -641,10 +722,12 @@ Retry:
|
||||
Sub(Task As LoaderTask(Of DlOptiFineListEntry, List(Of NetFile)))
|
||||
Dim Sources As New List(Of String)
|
||||
'BMCLAPI 源
|
||||
Dim BmclapiInherit As String = DownloadInfo.Inherit
|
||||
If BmclapiInherit = "1.8" OrElse BmclapiInherit = "1.9" Then BmclapiInherit &= ".0" '#4281
|
||||
If DownloadInfo.IsPreview Then
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/"))
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & BmclapiInherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/"))
|
||||
Else
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", ""))
|
||||
Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & BmclapiInherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", ""))
|
||||
End If
|
||||
'官方源
|
||||
Dim PageData As String
|
||||
@@ -652,7 +735,7 @@ Retry:
|
||||
PageData = NetGetCodeByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile, New UTF8Encoding(False), 15000, "text/html", True)
|
||||
Task.Progress = 0.8
|
||||
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources(0))
|
||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取 OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址失败")
|
||||
End Try
|
||||
@@ -1026,7 +1109,7 @@ Retry:
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
Dim Arguments As String
|
||||
If UseJavaWrapper Then
|
||||
Arguments = $"-Doolloo.jlw.tmpdir=""{GetJavaWrapperDir()}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{ExtractJavaWrapper()}"" com.bangbang93.ForgeInstaller ""{McFolder}"
|
||||
Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.TrimEnd("\")}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{ExtractJavaWrapper()}"" com.bangbang93.ForgeInstaller ""{McFolder}"
|
||||
Else
|
||||
Arguments = $"-cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" com.bangbang93.ForgeInstaller ""{McFolder}"
|
||||
End If
|
||||
@@ -1175,8 +1258,8 @@ Retry:
|
||||
End If
|
||||
If Not IsNeoForge AndAlso LoaderVersion.StartsWithF("1.") AndAlso LoaderVersion.Contains("-") Then
|
||||
'类似 1.19.3-41.2.8 格式,优先使用 Version 中要求的版本而非 Inherit(例如 1.19.3 却使用了 1.19 的 Forge)
|
||||
Inherit = LoaderVersion.Before("-")
|
||||
LoaderVersion = LoaderVersion.After("-")
|
||||
Inherit = LoaderVersion.BeforeFirst("-")
|
||||
LoaderVersion = LoaderVersion.AfterLast("-")
|
||||
End If
|
||||
Dim LoaderName As String = If(IsNeoForge, "NeoForge", "Forge")
|
||||
Dim IsCustomFolder As Boolean = McFolder <> PathMcFolder
|
||||
@@ -1236,7 +1319,7 @@ Retry:
|
||||
Loaders.Add(New LoaderDownload($"下载 {LoaderName} 主文件", New List(Of NetFile)) With {.ProgressWeight = 9})
|
||||
|
||||
'安装(仅在新版安装时需要原版 Jar)
|
||||
If IsNeoForge OrElse LoaderVersion.Before(".") >= 20 Then
|
||||
If IsNeoForge OrElse LoaderVersion.BeforeFirst(".") >= 20 Then
|
||||
Log($"[Download] 检测为{If(IsNeoForge, " Neo", "新版 ")}Forge:" & LoaderVersion)
|
||||
Dim Libs As List(Of McLibToken) = Nothing
|
||||
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))($"分析 {LoaderName} 支持库文件",
|
||||
@@ -1258,7 +1341,7 @@ Retry:
|
||||
Task.Progress = 0.4
|
||||
Dim RawJson As JObject = GetJson(NetGetCodeByDownload(DlSourceLauncherOrMetaGet(DlClientListGet(Inherit)), IsJson:=True))
|
||||
'[net.minecraft:client:1.17.1-20210706.113038:mappings@txt] 或 @tsrg]
|
||||
Dim OriginalName As String = Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Before("@")
|
||||
Dim OriginalName As String = Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).BeforeFirst("@")
|
||||
Dim Address = McLibGet(OriginalName).Replace(".jar", "-mappings." & Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Split("@")(1))
|
||||
Dim ClientMappings As JToken = RawJson("downloads")("client_mappings")
|
||||
Libs.Add(New McLibToken With {
|
||||
@@ -1381,8 +1464,6 @@ Retry:
|
||||
'没有新增文件夹
|
||||
Log("[Download] 未找到新增的版本文件夹")
|
||||
End If
|
||||
'新建 mods 文件夹
|
||||
Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
|
||||
Catch ex As Exception
|
||||
Throw New Exception($"安装新 {LoaderName} 版本失败", ex)
|
||||
Finally
|
||||
@@ -1398,54 +1479,52 @@ Retry:
|
||||
Else
|
||||
Log("[Download] 检测为非新版 Forge:" & LoaderVersion)
|
||||
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)($"安装 {LoaderName}(方式 B)",
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Dim Installer As ZipArchive = Nothing
|
||||
Try
|
||||
'解压并获取信息
|
||||
Installer = New ZipArchive(New FileStream(InstallerAddress, FileMode.Open))
|
||||
Task.Progress = 0.2
|
||||
Dim Json As JObject = GetJson(ReadFile(Installer.GetEntry("install_profile.json").Open))
|
||||
Task.Progress = 0.4
|
||||
'新建版本文件夹
|
||||
Directory.CreateDirectory(VersionFolder)
|
||||
Task.Progress = 0.5
|
||||
If Json("install") Is Nothing Then
|
||||
'中版:Legacy 方式 1
|
||||
Log("[Download] 开始进行 Forge 安装,Legacy 方式 1:" & InstallerAddress)
|
||||
'建立 Json 文件
|
||||
Dim JsonVersion As JObject = GetJson(ReadFile(Installer.GetEntry(Json("json").ToString.TrimStart("/")).Open))
|
||||
JsonVersion("id") = TargetVersion
|
||||
WriteFile(VersionFolder & TargetVersion & ".json", JsonVersion.ToString)
|
||||
Task.Progress = 0.6
|
||||
'解压支持库文件
|
||||
Installer.Dispose()
|
||||
ExtractFile(InstallerAddress, InstallerAddress & "_unrar\")
|
||||
CopyDirectory(InstallerAddress & "_unrar\maven\", McFolder & "libraries\")
|
||||
DeleteDirectory(InstallerAddress & "_unrar\")
|
||||
Else
|
||||
'旧版:Legacy 方式 2
|
||||
Log("[Download] 开始进行 Forge 安装,Legacy 方式 2:" & InstallerAddress)
|
||||
'解压 Jar 文件
|
||||
Dim JarAddress As String = McLibGet(Json("install")("path"), CustomMcFolder:=McFolder)
|
||||
If File.Exists(JarAddress) Then File.Delete(JarAddress)
|
||||
WriteFile(JarAddress, Installer.GetEntry(Json("install")("filePath")).Open)
|
||||
Task.Progress = 0.9
|
||||
'建立 Json 文件
|
||||
Json("versionInfo")("id") = TargetVersion
|
||||
If Json("versionInfo")("inheritsFrom") Is Nothing Then CType(Json("versionInfo"), JObject).Add("inheritsFrom", Inherit)
|
||||
WriteFile(VersionFolder & TargetVersion & ".json", Json("versionInfo").ToString)
|
||||
End If
|
||||
'新建 mods 文件夹
|
||||
Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
|
||||
Catch ex As Exception
|
||||
Throw New Exception("非新版方式安装 Forge 失败", ex)
|
||||
Finally
|
||||
Try
|
||||
'清理文件
|
||||
If Installer IsNot Nothing Then Installer.Dispose()
|
||||
If File.Exists(InstallerAddress) Then File.Delete(InstallerAddress)
|
||||
If Directory.Exists(InstallerAddress & "_unrar\") Then DeleteDirectory(InstallerAddress & "_unrar\")
|
||||
Catch ex As Exception
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Dim Installer As ZipArchive = Nothing
|
||||
Try
|
||||
'解压并获取信息
|
||||
Installer = New ZipArchive(New FileStream(InstallerAddress, FileMode.Open))
|
||||
Task.Progress = 0.2
|
||||
Dim Json As JObject = GetJson(ReadFile(Installer.GetEntry("install_profile.json").Open))
|
||||
Task.Progress = 0.4
|
||||
'新建版本文件夹
|
||||
Directory.CreateDirectory(VersionFolder)
|
||||
Task.Progress = 0.5
|
||||
If Json("install") Is Nothing Then
|
||||
'中版:Legacy 方式 1
|
||||
Log("[Download] 开始进行 Forge 安装,Legacy 方式 1:" & InstallerAddress)
|
||||
'建立 Json 文件
|
||||
Dim JsonVersion As JObject = GetJson(ReadFile(Installer.GetEntry(Json("json").ToString.TrimStart("/")).Open))
|
||||
JsonVersion("id") = TargetVersion
|
||||
WriteFile(VersionFolder & TargetVersion & ".json", JsonVersion.ToString)
|
||||
Task.Progress = 0.6
|
||||
'解压支持库文件
|
||||
Installer.Dispose()
|
||||
ExtractFile(InstallerAddress, InstallerAddress & "_unrar\")
|
||||
CopyDirectory(InstallerAddress & "_unrar\maven\", McFolder & "libraries\")
|
||||
DeleteDirectory(InstallerAddress & "_unrar\")
|
||||
Else
|
||||
'旧版:Legacy 方式 2
|
||||
Log("[Download] 开始进行 Forge 安装,Legacy 方式 2:" & InstallerAddress)
|
||||
'解压 Jar 文件
|
||||
Dim JarAddress As String = McLibGet(Json("install")("path"), CustomMcFolder:=McFolder)
|
||||
If File.Exists(JarAddress) Then File.Delete(JarAddress)
|
||||
WriteFile(JarAddress, Installer.GetEntry(Json("install")("filePath")).Open)
|
||||
Task.Progress = 0.9
|
||||
'建立 Json 文件
|
||||
Json("versionInfo")("id") = TargetVersion
|
||||
If Json("versionInfo")("inheritsFrom") Is Nothing Then CType(Json("versionInfo"), JObject).Add("inheritsFrom", Inherit)
|
||||
WriteFile(VersionFolder & TargetVersion & ".json", Json("versionInfo").ToString)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Throw New Exception("非新版方式安装 Forge 失败", ex)
|
||||
Finally
|
||||
Try
|
||||
'清理文件
|
||||
If Installer IsNot Nothing Then Installer.Dispose()
|
||||
If File.Exists(InstallerAddress) Then File.Delete(InstallerAddress)
|
||||
If Directory.Exists(InstallerAddress & "_unrar\") Then DeleteDirectory(InstallerAddress & "_unrar\")
|
||||
Catch ex As Exception
|
||||
Log(ex, "非新版方式安装 Forge 清理文件时出错")
|
||||
End Try
|
||||
End Try
|
||||
@@ -1765,8 +1844,6 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
"https://bmclapi2.bangbang93.com/fabric-meta/v2/versions/loader/" & MinecraftName & "/" & FabricVersion & "/profile/json",
|
||||
"https://meta.fabricmc.net/v2/versions/loader/" & MinecraftName & "/" & FabricVersion & "/profile/json"
|
||||
}, VersionFolder & Id & ".json", New FileChecker(IsJson:=True))}
|
||||
'新建 mods 文件夹
|
||||
Directory.CreateDirectory(New McVersion(VersionFolder).GetPathIndie(True) & "mods\")
|
||||
End Sub) With {.ProgressWeight = 0.5})
|
||||
Loaders.Add(New LoaderDownload("下载 Fabric 主文件", New List(Of NetFile)) With {.ProgressWeight = 2.5})
|
||||
|
||||
@@ -1798,7 +1875,7 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Public Function FabricApiDownloadListItem(Entry As CompFile, OnClick As MyListItem.ClickEventHandler) As MyListItem
|
||||
'建立控件
|
||||
Dim NewItem As New MyListItem With {
|
||||
.Title = Entry.DisplayName.Split("]")(1).Replace("Fabric API ", "").Replace(" build ", ".").Before("+").Trim, .SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Entry,
|
||||
.Title = Entry.DisplayName.Split("]")(1).Replace("Fabric API ", "").Replace(" build ", ".").BeforeFirst("+").Trim, .SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Entry,
|
||||
.Info = Entry.StatusDescription & ",发布于 " & Entry.ReleaseDate.ToString("yyyy'/'MM'/'dd HH':'mm"),
|
||||
.Logo = PathImage & "Blocks/Fabric.png"
|
||||
}
|
||||
@@ -1963,6 +2040,8 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Return True
|
||||
|
||||
Catch ex As CancelledException
|
||||
Return False
|
||||
Catch ex As Exception
|
||||
Log(ex, "开始合并安装失败", LogLevel.Feedback)
|
||||
Return False
|
||||
@@ -1970,8 +2049,8 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取合并安装加载器列表,并进行前期的缓存清理与 Java 检查工作。
|
||||
''' 如果出现已知问题且已提示用户,则返回 Nothing。出现异常则直接抛出。
|
||||
''' </summary>
|
||||
''' <exception cref="CancelledException" />
|
||||
Public Function McInstallLoader(Request As McInstallRequest, Optional DontFixLibraries As Boolean = False) As List(Of LoaderBase)
|
||||
'获取缓存目录
|
||||
Dim PathInstallTemp As String
|
||||
@@ -1983,11 +2062,10 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
|
||||
'清理缓存
|
||||
Try
|
||||
If Not IsInstallTempCleared Then
|
||||
IsInstallTempCleared = True
|
||||
DeleteDirectory(PathInstallTemp, True)
|
||||
Log("[Download] 已清理合并安装缓存")
|
||||
End If
|
||||
If IsInstallTempCleared Then Exit Try
|
||||
IsInstallTempCleared = True
|
||||
DeleteDirectory(PathInstallTemp, True)
|
||||
Log("[Download] 已清理合并安装缓存")
|
||||
Catch ex As Exception
|
||||
Log(ex, "清理合并安装缓存失败")
|
||||
End Try
|
||||
@@ -1998,7 +2076,7 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
If Directory.Exists(TempMcFolder) Then DeleteDirectory(TempMcFolder)
|
||||
Dim OptiFineFolder As String = Nothing
|
||||
If Request.OptiFineVersion IsNot Nothing Then
|
||||
If Request.OptiFineVersion.Contains("_HD_U_") Then Request.OptiFineVersion = "HD_U_" & Request.OptiFineVersion.After("_HD_U_") '#735
|
||||
If Request.OptiFineVersion.Contains("_HD_U_") Then Request.OptiFineVersion = "HD_U_" & Request.OptiFineVersion.AfterLast("_HD_U_") '#735
|
||||
Request.OptiFineEntry = New DlOptiFineListEntry With {
|
||||
.NameDisplay = Request.MinecraftName & " " & Request.OptiFineVersion.Replace("HD_U_", "").Replace("_", "").Replace("pre", " pre"),
|
||||
.Inherit = Request.MinecraftName,
|
||||
@@ -2025,9 +2103,11 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Dim OptiFineAsMod As Boolean = Request.OptiFineEntry IsNot Nothing AndAlso '1. 选择了 OptiFine
|
||||
(Request.FabricVersion IsNot Nothing OrElse '2. 选择了 Fabric...
|
||||
(Request.ForgeEntry IsNot Nothing AndAlso MinecraftCode >= 14 AndAlso MinecraftCode <= 15)) '...或者 Forge 1.14~15(#4134)
|
||||
Dim ModsFolder As String = New McVersion(OutputFolder).GetPathIndie(True) & "mods\"
|
||||
|
||||
If OptiFineAsMod Then
|
||||
Log("[Download] OptiFine 将作为 Mod 进行下载")
|
||||
OptiFineFolder = New McVersion(OutputFolder).GetPathIndie(True) & "mods\"
|
||||
OptiFineFolder = ModsFolder
|
||||
End If
|
||||
|
||||
'记录日志
|
||||
@@ -2041,7 +2121,7 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
'重复版本检查
|
||||
If File.Exists(OutputFolder & Request.TargetVersionName & ".json") Then
|
||||
Hint("版本 " & Request.TargetVersionName & " 已经存在!", HintType.Critical)
|
||||
Return Nothing
|
||||
Throw New CancelledException
|
||||
End If
|
||||
|
||||
Dim LoaderList As New List(Of LoaderBase)
|
||||
@@ -2049,11 +2129,11 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
LoaderList.Add(New LoaderTask(Of Integer, Integer)("添加忽略标识", Sub() WriteFile(OutputFolder & ".pclignore", "用于临时地在 PCL 的版本列表中屏蔽此版本。")) With {.Show = False, .Block = False})
|
||||
'Fabric API
|
||||
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(ModsFolder)}) With {.ProgressWeight = 3, .Block = False})
|
||||
End If
|
||||
'OptiFabric
|
||||
If Request.OptiFabric IsNot Nothing Then
|
||||
LoaderList.Add(New LoaderDownload("下载 OptiFabric", New List(Of NetFile) From {Request.OptiFabric.ToNetFile(New McVersion(OutputFolder).GetPathIndie(True) & "mods\")}) With {.ProgressWeight = 3, .Block = False})
|
||||
LoaderList.Add(New LoaderDownload("下载 OptiFabric", New List(Of NetFile) From {Request.OptiFabric.ToNetFile(ModsFolder)}) With {.ProgressWeight = 3, .Block = False})
|
||||
End If
|
||||
'原版
|
||||
Dim ClientLoader = New LoaderCombo(Of String)("下载原版 " & Request.MinecraftName, McDownloadClientLoader(Request.MinecraftName, Request.MinecraftJson, Request.TargetVersionName)) With {.Show = False, .ProgressWeight = 39, .Block = Request.ForgeVersion Is Nothing AndAlso Request.OptiFineEntry Is Nothing AndAlso Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing}
|
||||
@@ -2088,11 +2168,16 @@ Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
InstallMerge(OutputFolder, OutputFolder, OptiFineFolder, OptiFineAsMod, ForgeFolder, Request.ForgeVersion, NeoForgeFolder, Request.NeoForgeVersion, FabricFolder, LiteLoaderFolder)
|
||||
Task.Progress = 0.3
|
||||
If Directory.Exists(TempMcFolder & "libraries") Then CopyDirectory(TempMcFolder & "libraries", PathMcFolder & "libraries")
|
||||
If Directory.Exists(TempMcFolder & "mods") Then CopyDirectory(TempMcFolder & "mods", PathMcFolder & "mods")
|
||||
If Directory.Exists(TempMcFolder & "mods") Then CopyDirectory(TempMcFolder & "mods", ModsFolder)
|
||||
'新建 mods 文件夹
|
||||
If Request.ForgeVersion IsNot Nothing OrElse Request.FabricVersion IsNot Nothing OrElse Request.NeoForgeEntry IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing Then
|
||||
Directory.CreateDirectory(ModsFolder)
|
||||
Log("[Download] 自动创建 mods 文件夹:" & ModsFolder)
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = 2, .Block = True})
|
||||
'补全文件
|
||||
If Not DontFixLibraries AndAlso
|
||||
(Request.OptiFineEntry IsNot Nothing OrElse (Request.ForgeVersion IsNot Nothing AndAlso Request.ForgeVersion.Before(".") >= 20) OrElse Request.NeoForgeVersion IsNot Nothing OrElse Request.FabricVersion IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing) Then
|
||||
(Request.OptiFineEntry IsNot Nothing OrElse (Request.ForgeVersion IsNot Nothing AndAlso Request.ForgeVersion.BeforeFirst(".") >= 20) OrElse Request.NeoForgeVersion IsNot Nothing OrElse Request.FabricVersion IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing) Then
|
||||
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(OutputFolder))) With {.ProgressWeight = 1, .Show = False})
|
||||
LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
|
||||
|
||||
@@ -20,8 +20,13 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<StackPanel Grid.Row="1" Grid.RowSpan="2" Name="PanMain" Grid.IsSharedSizeScope="True" />
|
||||
<local:MyCard Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="True" x:Name="PanLoad" UseAnimation="False" Margin="0,0,0,8">
|
||||
<StackPanel Grid.Row="1" Grid.RowSpan="2" Name="PanMain" Grid.IsSharedSizeScope="True">
|
||||
<local:MyCard Margin="0,0,0,15" x:Name="CardFilter">
|
||||
<StackPanel x:Name="PanFilter" Margin="10,10,0,10" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" />
|
||||
</local:MyCard>
|
||||
<StackPanel Name="PanResults" />
|
||||
</StackPanel>
|
||||
<local:MyCard Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="True" x:Name="PanLoad" UseAnimation="False" Margin="0,0,0,8">
|
||||
<local:MyLoading Text="正在获取版本列表" Margin="20,20,20,17" x:Name="Load" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</local:MyCard>
|
||||
</Grid>
|
||||
|
||||
@@ -34,41 +34,121 @@
|
||||
End Select
|
||||
End Sub
|
||||
'结果 UI 化
|
||||
Private Class VersionSorterWithSelect
|
||||
Private Class CardSorter
|
||||
Implements IComparer(Of String)
|
||||
Public Top As String = ""
|
||||
Public Topmost As String = ""
|
||||
Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
|
||||
'相同
|
||||
If x = y Then Return 0
|
||||
If x = Top Then Return -1
|
||||
If y = Top Then Return 1
|
||||
'置顶
|
||||
If x = Topmost Then Return -1
|
||||
If y = Topmost Then Return 1
|
||||
'特殊版本
|
||||
Dim IsXSpecial As Boolean = x.EndsWithF("版本")
|
||||
Dim IsYSpecial As Boolean = y.EndsWithF("版本")
|
||||
If IsXSpecial AndAlso IsYSpecial Then Return x.CompareTo(y)
|
||||
If IsXSpecial Then Return 1
|
||||
If IsYSpecial Then Return -1
|
||||
'比较版本号
|
||||
Dim VersionCodeSort = -VersionSortInteger(x.Replace(x.BeforeFirst(" ") & " ", ""), y.Replace(y.BeforeFirst(" ") & " ", ""))
|
||||
If VersionCodeSort <> 0 Then Return VersionCodeSort
|
||||
'比较全部
|
||||
Return -VersionSortInteger(x, y)
|
||||
End Function
|
||||
Public Sub New(Optional Top As String = "")
|
||||
Me.Top = If(Top, "")
|
||||
Public Sub New(Optional Topmost As String = "")
|
||||
Me.Topmost = If(Topmost, "")
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
Private VersionFilter As String
|
||||
Private IsMajorVersionFilter As Boolean '是否按大版本号筛选(1.21 / 1.20 / 1.19 / ...)而非小版本号(1.21.1 / 1.21 / 1.20.4 / ...)
|
||||
Private Sub Load_OnFinish()
|
||||
'初始化筛选器
|
||||
Dim VersionFilters As List(Of String)
|
||||
|
||||
'按小版本号筛选?
|
||||
IsMajorVersionFilter = False
|
||||
VersionFilters = CompFileLoader.Output.SelectMany(Function(v) v.GameVersions).Select(Function(v) GetGroupedVersionName(v, IsMajorVersionFilter, True)).
|
||||
Distinct.OrderByDescending(Function(s) s, New VersionComparer).ToList
|
||||
'按大版本号筛选?
|
||||
If VersionFilters.Count >= 9 Then
|
||||
IsMajorVersionFilter = True
|
||||
VersionFilters = CompFileLoader.Output.SelectMany(Function(v) v.GameVersions).Select(Function(v) GetGroupedVersionName(v, IsMajorVersionFilter, True)).
|
||||
Distinct.OrderByDescending(Function(s) s, New VersionComparer).ToList
|
||||
End If
|
||||
|
||||
'UI 化筛选器
|
||||
PanFilter.Children.Clear()
|
||||
If VersionFilters.Count <= 2 Then
|
||||
CardFilter.Visibility = Visibility.Collapsed
|
||||
VersionFilter = Nothing
|
||||
Else
|
||||
CardFilter.Visibility = Visibility.Visible
|
||||
VersionFilters.Insert(0, "全部")
|
||||
'转化为按钮
|
||||
For Each Version As String In VersionFilters
|
||||
Dim NewButton As New MyRadioButton With {
|
||||
.Text = Version, .Margin = New Thickness(2, 0, 2, 0), .ColorType = MyRadioButton.ColorState.Highlight}
|
||||
NewButton.LabText.Margin = New Thickness(-2, 0, 8, 0)
|
||||
AddHandler NewButton.Check,
|
||||
Sub(sender As MyRadioButton, raiseByMouse As Boolean)
|
||||
PanScroll.ScrollToHome()
|
||||
VersionFilter = If(sender.Text = "全部", Nothing, sender.Text)
|
||||
UpdateFilterResult()
|
||||
End Sub
|
||||
PanFilter.Children.Add(NewButton)
|
||||
Next
|
||||
'自动选择
|
||||
Dim ToCheck As MyRadioButton = Nothing
|
||||
If TargetVersion <> "" Then
|
||||
Dim TargetFile = CompFileLoader.Output.FirstOrDefault(Function(v) v.GameVersions.Contains(TargetVersion))
|
||||
If TargetFile IsNot Nothing Then
|
||||
Dim TargetGroup = GetGroupedVersionName(TargetVersion, IsMajorVersionFilter, True)
|
||||
For Each Button As MyRadioButton In PanFilter.Children
|
||||
If Button.Text <> TargetGroup Then Continue For
|
||||
ToCheck = Button
|
||||
Exit For
|
||||
Next
|
||||
End If
|
||||
End If
|
||||
If ToCheck Is Nothing Then ToCheck = PanFilter.Children(0)
|
||||
ToCheck.Checked = True
|
||||
End If
|
||||
|
||||
'更新筛选结果(文件列表 UI 化)
|
||||
UpdateFilterResult()
|
||||
End Sub
|
||||
Private Sub UpdateFilterResult()
|
||||
Dim TargetCardName As String = If(TargetVersion <> "" OrElse TargetLoader <> CompModLoaderType.Any,
|
||||
$"所选版本:{TargetVersion} {If(TargetLoader <> CompModLoaderType.Any, TargetLoader, "")}", "")
|
||||
'初始化字典
|
||||
Dim Dict As New SortedDictionary(Of String, List(Of CompFile))(New VersionSorterWithSelect(TargetCardName))
|
||||
Dict.Add("未知版本", New List(Of CompFile))
|
||||
$"所选版本:{If(TargetLoader <> CompModLoaderType.Any, TargetLoader.ToString & " ", "")}{TargetVersion}", "")
|
||||
'归类到卡片下
|
||||
Dim Dict As New SortedDictionary(Of String, List(Of CompFile))(New CardSorter(TargetCardName))
|
||||
Dict.Add("其他版本", New List(Of CompFile))
|
||||
Dim SupportedLoaders As New List(Of Integer)([Enum].GetValues(GetType(CompModLoaderType)))
|
||||
For Each Version As CompFile In CompFileLoader.Output
|
||||
For Each GameVersion In Version.GameVersions
|
||||
'决定添加到哪个版本
|
||||
Dim TargetCard As String
|
||||
If GameVersion Is Nothing Then
|
||||
TargetCard = "未知版本"
|
||||
ElseIf GameVersion.Contains("w") OrElse GameVersion.Contains("pre") OrElse GameVersion.Contains("rc") Then
|
||||
TargetCard = "快照版本"
|
||||
ElseIf GameVersion.StartsWith("1.0") Then
|
||||
TargetCard = "远古版本"
|
||||
Else
|
||||
TargetCard = GameVersion
|
||||
'检查是否符合版本筛选器
|
||||
If VersionFilter IsNot Nothing AndAlso
|
||||
GetGroupedVersionName(GameVersion, IsMajorVersionFilter, True) <> VersionFilter Then Continue For
|
||||
'决定添加到哪个卡片
|
||||
Dim Ver As String = GetGroupedVersionName(GameVersion, False, False)
|
||||
'遍历加入的加载器列表
|
||||
Dim Loaders As New List(Of String)
|
||||
If Project.ModLoaders.Count > 1 AndAlso '至少有两个加载器
|
||||
Project.Type = CompType.Mod AndAlso '是 Mod
|
||||
Ver.StartsWith("1.") Then '不是 “快照版本” 之类的
|
||||
For Each Loader In Version.ModLoaders
|
||||
If Loader = CompModLoaderType.Quilt AndAlso Setup.Get("ToolDownloadIgnoreQuilt") Then Continue For
|
||||
If SupportedLoaders.Contains(Loader) Then Loaders.Add(Loader.ToString & " ")
|
||||
Next
|
||||
End If
|
||||
'实际进行添加
|
||||
If Not Dict.ContainsKey(TargetCard) Then Dict.Add(TargetCard, New List(Of CompFile))
|
||||
If Not Dict(TargetCard).Contains(Version) Then Dict(TargetCard).Add(Version)
|
||||
If Not Loaders.Any() Then Loaders.Add("") '保底加一个空的,确保它在一张卡片里
|
||||
'实际添加
|
||||
For Each Loader In Loaders
|
||||
Dim TargetCard As String = Loader & Ver
|
||||
If Not Dict.ContainsKey(TargetCard) Then Dict.Add(TargetCard, New List(Of CompFile))
|
||||
If Not Dict(TargetCard).Contains(Version) Then Dict(TargetCard).Add(Version)
|
||||
Next
|
||||
Next
|
||||
Next
|
||||
'添加筛选的版本的卡片
|
||||
@@ -77,16 +157,16 @@
|
||||
For Each Version As CompFile In CompFileLoader.Output
|
||||
If Version.GameVersions.Contains(TargetVersion) AndAlso
|
||||
(TargetLoader = CompModLoaderType.Any OrElse Version.ModLoaders.Contains(TargetLoader)) Then
|
||||
'检查是否符合版本筛选器
|
||||
If VersionFilter IsNot Nothing AndAlso
|
||||
Not Version.GameVersions.Any(Function(v) GetGroupedVersionName(v, IsMajorVersionFilter, True) = VersionFilter) Then Continue For
|
||||
If Not Dict(TargetCardName).Contains(Version) Then Dict(TargetCardName).Add(Version)
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
|
||||
#Region "转化为 UI"
|
||||
'转化为 UI
|
||||
Try
|
||||
'清空当前
|
||||
PanMain.Children.Clear()
|
||||
'转化为 UI
|
||||
PanResults.Children.Clear()
|
||||
For Each Pair As KeyValuePair(Of String, List(Of CompFile)) In Dict
|
||||
If Not Pair.Value.Any() Then Continue For
|
||||
'增加卡片
|
||||
@@ -94,7 +174,7 @@
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
|
||||
NewCard.Children.Add(NewStack)
|
||||
NewCard.SwapControl = NewStack
|
||||
PanMain.Children.Add(NewCard)
|
||||
PanResults.Children.Add(NewCard)
|
||||
'确定卡片是否展开
|
||||
If Pair.Key = TargetCardName OrElse
|
||||
(FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
|
||||
@@ -104,20 +184,29 @@
|
||||
NewCard.IsSwaped = True
|
||||
End If
|
||||
'增加提示
|
||||
If Pair.Key = "未知版本" Then
|
||||
NewStack.Children.Add(New MyHint With {.Text = "由于 API 的版本信息更新缓慢,可能无法识别刚更新不久的 MC 版本,只需等待几天即可自动恢复正常。", .IsWarn = False, .Margin = New Thickness(0, 0, 0, 7)})
|
||||
If Pair.Key = "其他版本" Then
|
||||
NewStack.Children.Add(New MyHint With {.Text = "由于版本信息更新缓慢,可能无法识别刚更新的 MC 版本,只需等待几天即可自动恢复正常。", .IsWarn = False, .Margin = New Thickness(0, 0, 0, 7)})
|
||||
End If
|
||||
Next
|
||||
'如果只有一张卡片,展开第一张卡片
|
||||
If PanMain.Children.Count = 1 Then
|
||||
CType(PanMain.Children(0), MyCard).IsSwaped = False
|
||||
If PanResults.Children.Count = 1 Then
|
||||
CType(PanResults.Children(0), MyCard).IsSwaped = False
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
|
||||
End Try
|
||||
#End Region
|
||||
|
||||
End Sub
|
||||
Private Function GetGroupedVersionName(Name As String, MajorOnly As Boolean, FoldOldRelease As Boolean) As String
|
||||
If Name Is Nothing Then
|
||||
Return "其他版本"
|
||||
ElseIf Name.Contains("w") Then
|
||||
Return "快照版本"
|
||||
ElseIf Name.StartsWith("1.0") OrElse Not Name.StartsWith("1.") OrElse (FoldOldRelease AndAlso Val(Name.Split(".")(1)) < 10) Then
|
||||
Return "远古版本"
|
||||
Else
|
||||
Return If(MajorOnly, "1." & Name.Split(".")(1).BeforeFirst(" "), Name)
|
||||
End If
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -167,14 +256,10 @@
|
||||
'构造步骤加载器
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
Dim Target As String = $"{PathMcFolder}versions\{VersionName}\原始整合包.{If(Project.FromCurseForge, "zip", "mrpack")}"
|
||||
Dim LogoFileAddress As String = PathTemp & "CompLogo\" & GetHash(CompItem.Logo) & ".png"
|
||||
Dim LogoFileAddress As String = MyImage.GetTempPath(CompItem.Logo)
|
||||
Loaders.Add(New LoaderDownload("下载整合包文件", New List(Of NetFile) From {File.ToNetFile(Target)}) With {.ProgressWeight = 10, .Block = True})
|
||||
Loaders.Add(New LoaderTask(Of Integer, Integer)("准备安装整合包",
|
||||
Sub()
|
||||
If ModpackInstall(Target, VersionName, Logo:=If(IO.File.Exists(LogoFileAddress), LogoFileAddress, Nothing)) Is Nothing Then
|
||||
Throw New Exception("整合包安装出现异常!")
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = 0.1})
|
||||
Sub() ModpackInstall(Target, VersionName, If(IO.File.Exists(LogoFileAddress), LogoFileAddress, Nothing))) With {.ProgressWeight = 0.1})
|
||||
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged =
|
||||
@@ -229,7 +314,7 @@
|
||||
If Not Version.IsLoaded Then Version.Load()
|
||||
If Not Version.Modable Then Return False
|
||||
If File.GameVersions.Any(Function(v) v.Contains(".")) AndAlso
|
||||
Not File.GameVersions.Any(Function(v) v.Contains(".") AndAlso v.Split(".")(1) = Version.Version.McCodeMain.ToString) Then Return False
|
||||
Not File.GameVersions.Any(Function(v) v.Contains(".") AndAlso v = Version.Version.McName) Then Return False
|
||||
If AllowForge Is Nothing OrElse AllowFabric Is Nothing Then Return True
|
||||
If AllowForge AndAlso (Version.Version.HasForge OrElse Version.Version.HasNeoForge) Then Return True
|
||||
If AllowFabric AndAlso Version.Version.HasFabric Then Return True
|
||||
@@ -277,7 +362,7 @@
|
||||
If Project.TranslatedName = Project.RawName Then
|
||||
FileName = File.FileName
|
||||
Else
|
||||
Dim ChineseName As String = Project.TranslatedName.Before(" (").Before(" - ").
|
||||
Dim ChineseName As String = Project.TranslatedName.BeforeFirst(" (").BeforeFirst(" - ").
|
||||
Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":")
|
||||
Select Case Setup.Get("ToolDownloadTranslate")
|
||||
Case 0
|
||||
@@ -295,10 +380,10 @@
|
||||
'弹窗要求选择保存位置
|
||||
Dim Target As String
|
||||
Target = SelectAs("选择保存位置", FileName,
|
||||
Desc & "文件|" &
|
||||
If(Project.Type = CompType.Mod,
|
||||
If(File.FileName.EndsWith(".litemod"), "*.litemod", "*.jar"),
|
||||
If(File.FileName.EndsWith(".mrpack"), "*.mrpack", "*.zip")), DefaultFolder)
|
||||
Desc & "文件|" &
|
||||
If(Project.Type = CompType.Mod,
|
||||
If(File.FileName.EndsWith(".litemod"), "*.litemod", "*.jar"),
|
||||
If(File.FileName.EndsWith(".mrpack"), "*.mrpack", "*.zip")), DefaultFolder)
|
||||
If Not Target.Contains("\") Then Exit Sub
|
||||
'构造步骤加载器
|
||||
Dim LoaderName As String = Desc & "下载:" & GetFileNameWithoutExtentionFromPath(Target) & " "
|
||||
|
||||
@@ -1076,12 +1076,12 @@
|
||||
If DisplayName.StartsWith("[" & MinecraftVersion & "]") Then Return True
|
||||
If Not DisplayName.Contains("/") OrElse Not DisplayName.Contains("]") Then Return False
|
||||
'直接的判断(例如 1.18.1/22w03a)
|
||||
For Each Part As String In DisplayName.Before("]").TrimStart("[").Split("/")
|
||||
For Each Part As String In DisplayName.BeforeFirst("]").TrimStart("[").Split("/")
|
||||
If Part = MinecraftVersion Then Return True
|
||||
Next
|
||||
'将版本名分割语素(例如 1.16.4/5)
|
||||
Dim Lefts = RegexSearch(DisplayName.Before("]"), "[a-z/]+|[0-9/]+")
|
||||
Dim Rights = RegexSearch(MinecraftVersion.Before("]"), "[a-z/]+|[0-9/]+")
|
||||
Dim Lefts = RegexSearch(DisplayName.BeforeFirst("]"), "[a-z/]+|[0-9/]+")
|
||||
Dim Rights = RegexSearch(MinecraftVersion.BeforeFirst("]"), "[a-z/]+|[0-9/]+")
|
||||
'对每段进行判断
|
||||
Dim i As Integer = 0
|
||||
While True
|
||||
|
||||
@@ -2,88 +2,90 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:PCL" AnimatedControl="{Binding ElementName=PanItem, Mode=OneWay}">
|
||||
<StackPanel Margin="0,12,0,0" Name="PanItem">
|
||||
<local:MyScrollViewer PanningMode="VerticalOnly" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Style="{StaticResource ScrollViewerFullMargin}">
|
||||
<StackPanel Margin="0,12,0,0" Name="PanItem">
|
||||
|
||||
<TextBlock x:Name="LabGame" Text="Minecraft" Margin="13,6,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemInstall" Checked="True" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="1" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="自动安装"
|
||||
<TextBlock x:Name="LabGame" Text="Minecraft" Margin="13,6,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemInstall" Checked="True" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="1" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="自动安装"
|
||||
LogoScale="0.87" Logo="M1091.291429 0H78.935771C35.34848 0.035109 0.029257 35.354331 0 78.935771v863.331475c0 43.534629 35.401143 78.994286 78.935771 78.994285H1091.291429c43.534629 0 78.994286-35.401143 78.994285-78.994285V78.871406C1170.156983 35.319223 1134.849463 0.064366 1091.291429 0z m-8.835658 87.771429v78.754377H87.771429v-78.760229h994.684342zM87.771429 933.425737V254.232869h994.684342v679.140205H87.771429v0.058515zM724.95104 340.00896l-206.19264 547.605943a43.903269 43.903269 0 0 1-82.154057-31.012572l206.139977-547.547428a43.944229 43.944229 0 0 1 82.20672 30.954057zM369.558674 545.909029l-85.489371 85.489371 85.489371 85.542034a43.885714 43.885714 0 0 1-62.025143 62.083657l-116.554605-116.560457a43.8272 43.8272 0 0 1 0-62.025143l116.560457-116.49024a43.885714 43.885714 0 0 1 62.019291 61.966629z m610.567315-37.566172a43.885714 43.885714 0 0 1 0 62.083657l-116.560458 116.560457a43.768686 43.768686 0 0 1-62.019291 0 43.885714 43.885714 0 0 1 0-62.083657l85.547886-85.547885-85.547886-85.542035a43.897417 43.897417 0 0 1 62.083657-62.083657l116.496092 116.618972z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="1" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemHand" IsScaleAnimationEnabled="False" Type="RadioBox" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="手动安装包"
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="1" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemHand" IsScaleAnimationEnabled="False" Type="RadioBox" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="手动安装包"
|
||||
LogoScale="1.02" Logo="M292.693 787.627c0 30.72-24.746 55.466-55.466 55.466s-55.467-24.746-55.467-55.466 24.747-55.467 55.467-55.467c30.72-0.853 55.466 24.747 55.466 55.467z M1000.96 241.493c-2.56-5.973-4.267-11.946-6.827-17.92-0.853-6.826-4.266-12.8-8.533-17.92-7.68-9.386-18.773-15.36-31.573-15.36-6.827 0-13.654 1.707-19.627 5.12l-15.36 15.36-17.067 17.067-21.333 21.333L749.227 381.44c-14.507 14.507-38.4 14.507-52.907 0l-54.613-54.613c-14.507-14.507-14.507-38.4 0-52.907l132.266-132.267 14.507-14.506 20.48-20.48 16.213-16.214c3.414-5.973 5.12-11.946 5.12-19.626 0-12.8-5.973-24.747-16.213-32.427-5.973-4.267-11.947-6.827-18.773-7.68-5.12-2.56-10.24-4.267-16.214-5.973-36.693-12.8-76.8-19.627-117.76-19.627-7.68 0-14.506 0-22.186 0.853-188.587 11.947-337.92 168.107-337.92 360.96 0 16.214 0.853 32.427 3.413 48.64L56.32 663.04c-73.387 74.24-73.387 193.707 0 267.093l33.28 33.28c73.387 73.387 193.707 73.387 267.093 0l240.64-241.493c21.334 4.267 42.667 5.973 64 5.973 190.294 0 346.454-146.773 360.107-333.653 0.853-8.533 0.853-17.92 0.853-27.307 0.854-44.373-6.826-86.186-21.333-125.44zM658.773 639.147c-28.16 0-54.613-4.267-79.36-11.094-4.266 7.68-10.24 14.507-16.213 21.334l-258.56 258.56c-43.52 43.52-115.2 43.52-158.72 0l-29.013-29.014c-43.52-44.373-43.52-115.2 0-158.72l212.48-212.48 46.08-46.08c5.973-5.973 12.8-11.093 19.626-15.36-8.533-26.453-12.8-54.613-12.8-83.626v-1.707c0-152.747 123.734-275.627 276.48-275.627 18.774 0 37.547 1.707 55.467 5.974L597.333 207.36c-52.053 52.053-52.053 137.387 0 189.44l29.867 29.867c52.053 52.053 137.387 52.053 189.44 0L930.987 312.32c2.56 16.213 4.266 33.28 4.266 50.347 0 152.746-123.733 276.48-276.48 276.48z" />
|
||||
<TextBlock x:Name="LabHand" Visibility="Collapsed" Text="▼ 手动安装包" Padding="11,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemClient" Visibility="Collapsed" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Minecraft"
|
||||
<TextBlock x:Name="LabHand" Visibility="Collapsed" Text="▼ 手动安装包" Padding="11,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemClient" Visibility="Collapsed" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Minecraft"
|
||||
LogoScale="0.98" Logo="M989.7 510.8l-202.3-101c-10.8-5.4-17.7-16.5-17.7-28.6V172.7c0-26.7-16.6-50.6-41.6-59.9L550.5 46.3c-24.2-9-50.8-9-74.9 0.1l-176.9 66.8c-24.9 9.4-41.4 33.2-41.4 59.9v207.1c0 12.1-6.9 23.2-17.7 28.6l-204 101.9C13.9 521.6 0.1 543.8 0.2 568.1l0.5 226c0 23.2 12.6 44.5 32.9 55.8l223.8 124.6 1.2 0.7c18.9 10.5 41.9 10.4 60.8-0.2l2-1.1L497 873.2c9.9-5.7 22.1-5.6 32 0.1l176.7 102.5c18.9 10.7 42 10.8 61 0.3l3-1.7L992.4 851c20.4-11.3 33-32.8 33-56l-0.3-226.9c0-24.3-13.7-46.5-35.4-57.3zM321 192l115.3 46.1c27 10.8 44.7 36.9 44.7 66v163c0 5.9-6.2 9.8-11.6 7.2L339 409.5c-10.9-5.4-17.7-16.5-17.8-28.6L321 192z m-63.7 703.4L82.5 809.6c-10.9-5.4-17.9-16.5-17.9-28.7l-0.4-189.5L217.9 668c24.1 12 39.4 36.7 39.4 63.6v163.8z m64-274.3c-20.1 10.1-43.7 10-63.8 0l-0.2-0.1-149.1-75 149.1-74.4 16.8-8.4c9.2-4.6 20-4.5 29.1 0.3l18.1 9.4 129.8 64.3c5.8 2.9 6 11.1 0.2 14.2l-130 69.7z m141.9 203.8l-141.8 70.6-0.8-163.6c-0.1-27 15.1-51.8 39.2-63.9l108.8-54.5c5.3-2.7 11.6 1.2 11.6 7.1l0.8 175.6c0 12.1-6.9 23.2-17.8 28.7zM385 144l128-48 128 48-103 38.6c-16.1 6-33.8 6-49.9 0L385 144z m320 48l0.6 187.8c0 12.2-6.8 23.3-17.7 28.7l-131.4 65.7c-5.3 2.7-11.6-1.2-11.6-7.2V304.1c0-29.1 17.7-55.2 44.7-66L705 192z m0.7 710.3l-143.8-77.2c-10.4-5.6-16.9-16.4-16.9-28.2v-176c0-5.9 6.3-9.8 11.6-7.2l109.3 54.6c24 12 39.2 36.5 39.3 63.4l0.5 170.6z m-2-280.5l-129.2-70.5c-5.7-3.1-5.5-11.3 0.3-14.2l131-65.3 16.1-8.5c9.1-4.8 19.9-4.9 29.1-0.3l18.7 9.3L916.9 546l-146.2 76.4c-21.1 11-46.2 10.8-67-0.6z m66 279.4l-0.6-169.1c-0.1-27 15.1-51.7 39.3-63.8L961 592v188.7c0 11.9-6.6 22.7-17 28.3l-174.3 92.2z">
|
||||
<!--Logo="M469.333333 213.333333V128a42.666667 42.666667 0 1 1 85.333334 0v85.333333h127.829333C847.722667 213.333333 981.333333 347.029333 981.333333 512.149333v319.936A106.496 106.496 0 0 1 874.730667 938.666667h-85.461334c-48.661333 0-107.221333-29.290667-136.469333-68.266667l-64-85.333333c-6.144-8.170667-23.957333-17.066667-34.24-17.066667h-85.12c-10.282667 0-28.096 8.896-34.24 17.066667l-64 85.333333c-29.226667 38.976-87.808 68.266667-136.469333 68.266667H149.269333A106.496 106.496 0 0 1 42.666667 832.085333V512.149333C42.666667 347.029333 176.277333 213.333333 341.504 213.333333H469.333333z m213.162667 85.333334H341.504A213.333333 213.333333 0 0 0 128 512.149333v319.936c0 11.818667 9.450667 21.248 21.269333 21.248h85.461334c21.802667 0 55.082667-16.64 68.202666-34.133333l64-85.333333c22.272-29.696 65.408-51.2 102.506667-51.2h85.12c37.098667 0 80.213333 21.504 102.506667 51.2l64 85.333333c13.12 17.493333 46.4 34.133333 68.202666 34.133333h85.461334a21.162667 21.162667 0 0 0 21.269333-21.248V512.149333A213.333333 213.333333 0 0 0 682.496 298.666667zM362.666667 469.333333h42.666666a42.666667 42.666667 0 1 1 0 85.333334h-42.666666v42.666666a42.666667 42.666667 0 1 1-85.333334 0v-42.666666h-42.666666a42.666667 42.666667 0 1 1 0-85.333334h42.666666v-42.666666a42.666667 42.666667 0 1 1 85.333334 0v42.666666z m341.333333-21.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m0 213.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m-106.666667-106.666666a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z m213.333334 0a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z">-->
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="4" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemOptiFine" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="5" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="OptiFine"
|
||||
<!--Logo="M469.333333 213.333333V128a42.666667 42.666667 0 1 1 85.333334 0v85.333333h127.829333C847.722667 213.333333 981.333333 347.029333 981.333333 512.149333v319.936A106.496 106.496 0 0 1 874.730667 938.666667h-85.461334c-48.661333 0-107.221333-29.290667-136.469333-68.266667l-64-85.333333c-6.144-8.170667-23.957333-17.066667-34.24-17.066667h-85.12c-10.282667 0-28.096 8.896-34.24 17.066667l-64 85.333333c-29.226667 38.976-87.808 68.266667-136.469333 68.266667H149.269333A106.496 106.496 0 0 1 42.666667 832.085333V512.149333C42.666667 347.029333 176.277333 213.333333 341.504 213.333333H469.333333z m213.162667 85.333334H341.504A213.333333 213.333333 0 0 0 128 512.149333v319.936c0 11.818667 9.450667 21.248 21.269333 21.248h85.461334c21.802667 0 55.082667-16.64 68.202666-34.133333l64-85.333333c22.272-29.696 65.408-51.2 102.506667-51.2h85.12c37.098667 0 80.213333 21.504 102.506667 51.2l64 85.333333c13.12 17.493333 46.4 34.133333 68.202666 34.133333h85.461334a21.162667 21.162667 0 0 0 21.269333-21.248V512.149333A213.333333 213.333333 0 0 0 682.496 298.666667zM362.666667 469.333333h42.666666a42.666667 42.666667 0 1 1 0 85.333334h-42.666666v42.666666a42.666667 42.666667 0 1 1-85.333334 0v-42.666666h-42.666666a42.666667 42.666667 0 1 1 0-85.333334h42.666666v-42.666666a42.666667 42.666667 0 1 1 85.333334 0v42.666666z m341.333333-21.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m0 213.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m-106.666667-106.666666a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z m213.333334 0a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z">-->
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="4" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemOptiFine" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="5" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="OptiFine"
|
||||
LogoScale="1.00" Logo="M439.667 538.133l-323.311-174.763c-6.554-3.641-13.836-5.098-20.389-5.098-23.301 0-45.147 20.389-45.147 48.788v341.516c0 35.681 18.205 67.721 48.060 83.741l323.311 174.763c6.554 3.641 13.836 5.825 20.389 5.825 23.301 0 45.147-21.117 45.147-49.516v-341.516c0-34.953-18.205-67.721-48.060-83.741zM414.909 920.427l-281.805-152.189c-4.369-2.913-9.467-9.467-9.467-19.661v-298.553l281.805 152.189c5.825 3.641 9.467 11.651 9.467 19.661v298.553zM952.304 358.274c-6.554 0-13.836 1.456-20.389 5.098l-323.311 175.491c-29.855 16.020-48.060 48.788-48.060 84.468v340.059c0 28.399 21.845 49.516 45.147 49.516 6.554 0 13.836-1.456 20.389-5.098l323.311-175.491c29.127-16.020 48.060-48.060 48.060-83.741v-341.516c0-28.399-21.845-48.788-45.147-48.788zM924.634 747.849c0 10.194-5.098 17.476-9.467 19.661l-281.805 152.917v-297.097c0-10.194 5.098-17.476 9.467-19.661l281.805-153.646v297.825zM902.060 283.272c15.292-8.010 22.574-21.845 21.117-34.953 1.456-13.836-5.825-26.943-21.117-34.953l-329.136-171.85c-14.563-8.010-31.312-11.651-48.788-11.651 0 0 0 0 0 0 0 0 0 0 0 0s-34.224 3.641-49.516 11.651l-329.865 171.122c-15.292 8.010-21.845 21.845-21.117 35.681-0.729 13.107 5.825 26.943 21.117 34.953l329.136 171.122c14.563 8.010 32.039 11.651 49.516 11.651 0 0 0 0 0.729 0 0 0 0 0 0.729 0s34.224-3.641 49.516-11.651l327.68-171.122zM523.407 393.227c-5.825 0-11.651-1.456-16.020-3.641l-272.338-141.266 272.338-141.995c4.369-2.185 10.194-3.641 16.748-3.641 5.825 0 11.651 1.456 16.020 3.641l272.338 141.995-273.067 141.266c-3.641 2.185-9.467 3.641-16.020 3.641z">
|
||||
<!--Logo="M12 0l-11 6v12.131l11 5.869 11-5.869v-12.066l-11-6.065zm-1 21.2l-6.664-3.555 4.201-2.801c1.08-.719-.066-2.359-1.243-1.575l-4.294 2.862v-7.901l8 4.363v8.607zm-6.867-14.63l6.867-3.746v4.426c0 1.323 2 1.324 2 0v-4.415l6.91 3.811-7.905 4.218-7.872-4.294zm8.867 6.03l8-4.269v7.8l-4.263-2.842c-1.181-.785-2.323.855-1.245 1.574l4.172 2.781-6.664 3.556v-8.6z">-->
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="5" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemForge" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="6" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Forge"
|
||||
<!--Logo="M12 0l-11 6v12.131l11 5.869 11-5.869v-12.066l-11-6.065zm-1 21.2l-6.664-3.555 4.201-2.801c1.08-.719-.066-2.359-1.243-1.575l-4.294 2.862v-7.901l8 4.363v8.607zm-6.867-14.63l6.867-3.746v4.426c0 1.323 2 1.324 2 0v-4.415l6.91 3.811-7.905 4.218-7.872-4.294zm8.867 6.03l8-4.269v7.8l-4.263-2.842c-1.181-.785-2.323.855-1.245 1.574l4.172 2.781-6.664 3.556v-8.6z">-->
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="5" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemForge" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="6" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Forge"
|
||||
LogoScale="1.00" Logo="M402.807089 481.189274c-12.040221-6.991228-27.412326-2.797719-34.397415 9.242502l-8.387018 14.512529c-6.987135 12.035104-2.793626 27.40721 9.246595 34.392298 12.040221 6.985088 27.408233 2.797719 34.393321-9.242502l8.387018-14.511505C418.930301 503.437997 414.842193 488.063845 402.807089 481.189274L402.807089 481.189274zM495.028467 919.955342 59.056024 919.955342c-18.485003 0-33.532721 15.046694-33.532721 33.536814 0 18.485003 15.046694 33.532721 33.532721 33.532721l435.972443 0c18.49012 0 33.537837-15.046694 33.537837-33.532721C528.566304 935.002037 513.518586 919.955342 495.028467 919.955342L495.028467 919.955342zM997.431901 660.155295 590.482469 446.039729l90.935082-157.474544c18.485003-32.031531 7.520277-73.090669-24.51023-91.581812L395.496589 46.070268c-32.031531-18.485003-73.094762-7.520277-91.579765 24.51023L18.74697 564.277644c-18.485003 32.031531-7.521301 73.089645 24.51023 91.579765l261.408685 150.907988c32.031531 18.491143 73.095785 7.526417 91.581812-24.505114l91.364871-158.330028 392.332527 239.48128c16.016789 9.247618 36.544311 3.76372 45.792952-12.249999l83.838454-145.219429C1019.033895 689.930435 1013.444597 669.39882 997.431901 660.155295L997.431901 660.155295zM355.078041 719.704552c-9.242502 16.012695-29.774117 21.497617-45.787836 12.251022L105.923448 614.57826c-16.016789-9.242502-21.497617-29.774117-12.255115-45.787836l251.522524-435.653171c9.246595-16.012695 29.774117-21.497617 45.792952-12.249999l203.25624 117.376291c16.018835 9.242502 21.497617 29.774117 12.255115 45.786813L355.078041 719.704552 355.078041 719.704552zM884.568391 788.601712 522.115382 564.492538l33.537837-58.048067L934.875147 701.539844 884.568391 788.601712 884.568391 788.601712zM520.184403 277.8174c-12.040221-6.987135-27.41335-2.792603-34.399461 9.246595l-75.456552 130.702807c-6.985088 12.040221-2.791579 27.412326 9.242502 34.397415 12.040221 6.987135 27.412326 2.791579 34.397415-9.242502l75.458599-130.706901C536.307615 300.174594 532.219507 284.807604 520.184403 277.8174L520.184403 277.8174zM520.184403 277.8174">
|
||||
<!--Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z">-->
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="6" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemNeoForge" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="7" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="NeoForge"
|
||||
<!--Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z">-->
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="6" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemNeoForge" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="7" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="NeoForge"
|
||||
LogoScale="0.95" Logo="M544.6 921.2l-23.7 32.6c14.1 10.2 33.3 10.2 47.5 0l-23.7-32.6zM114.6 608.5l-23.9 32.5 0.2 0.1 23.6-32.6z m-12.0-38.0l38.3 12.7v-0.2l-38.3-12.4z m49.2-152.6l-38.4-12.4 38.4 12.4zM250.2 114.4l-37.6-14.6a40.2 40.2 0 0 0-0.7 2.1l38.4 12.4z m4.3-6.4l27.0 29.9 0.2-0.2-27.2-29.7z m11.7-4.5V63.0v40.4z m11.7 4.5l28.0-29.0a40.5 40.5 0 0 0-0.8-0.8l-27.2 29.8z m4.4 7.3l-38.6 11.7a40.5 40.5 0 0 0 0.2 0.7l38.3-12.4zM381.0 417.7l-38.4 12.5a40.3 40.3 0 0 0 38.4 27.8v-40.3z m327.0 0v40.3c17.5 0 32.9-11.2 38.4-27.8L708.1 417.7z m98.5-303.3l-37.6-14.6a38.4 38.4 0 0 0-0.7 2.1l38.4 12.4z m4.3-6.4l27.1 29.9 0.1-0.2-27.2-29.7z m11.7-4.5v0z m11.7 4.5l28.0-29.0a38.4 38.4 0 0 0-0.8-0.8l-27.2 29.8z m4.3 7.3l-38.6 11.7a47.5 47.5 0 0 0 0.2 0.7l38.4-12.4z m98.5 303.3l-38.4 12.4 0.1 0.5 38.2-12.9z m51.2 151.9l38.7-11.3a34.5 34.5 0 0 0-0.5-1.6l-38.1 12.9z m-37.8 5.2l-430.0 312.6 47.5 65.3 429.9-312.6-47.5-65.3z m-382.5 312.6L138.3 575.8l-47.5 65.3L520.9 953.9l47.3-65.3zM138.5 576a6.4 6.4 0 0 1 2.3 3.2l-76.9 24.5c4.7 14.9 14.1 28.0 26.7 37.3l47.8-65.0z m2.3 3.2a6.4 6.4 0 0 1 0 4.0L64.1 557.9a74.3 74.3 0 0 0-0.2 45.8l76.9-24.5z m0 3.7l49.2-152.6-76.8-24.8L64.0 558.2l76.8 24.8z m49.2-152.5l98.5-303.3-76.8-25.0L113.3 405.3l76.8 25.0z m97.7-301.3a23.4 23.4 0 0 1-6.1 8.9L227.6 78.0a57.3 57.3 0 0 0-15.0 21.8l75.3 29.1z m-5.9 8.7a23.0 23.0 0 0 1-15.5 6.0V63.0a57.7 57.7 0 0 0-38.9 15.1l54.4 59.6z m-15.5 6.0a23.0 23.0 0 0 1-15.5-6.0l54.4-59.6A57.7 57.7 0 0 0 266.4 63.0v80.8z m-16.3-6.8a23.4 23.4 0 0 1-6.1-10.0l77.3-23.4a57.3 57.3 0 0 0-15.0-24.5l-56.1 58.0z m-5.8-9.2l98.4 302.5 76.8-25.0-98.5-302.5-76.8 25.0z m136.8 330.4H708.1V377.5H381.2v80.7z m365.4-27.8l98.5-303.3-76.8-25.0L669.6 405.3l76.8 25.0z m97.7-301.3a23.4 23.4 0 0 1-6.1 8.9l-54.1-59.9a57.3 57.3 0 0 0-15.0 21.8l75.3 29.1z m-5.9 8.7a23.0 23.0 0 0 1-15.5 6.0V63.0a57.7 57.7 0 0 0-38.9 15.1l54.4 59.6z m-15.5 6.0a23.0 23.0 0 0 1-15.5-6.0l54.4-59.6a57.7 57.7 0 0 0-38.9-15.1v80.8z m-16.3-6.8a23.4 23.4 0 0 1-6.1-10.0l77.3-23.4a57.4 57.4 0 0 0-14.9-24.5l-56.1 58.0z m-5.8-9.2l98.5 303.3 76.8-25.0-98.5-303.3-76.8 25.0z m98.6 303.8l51.2 151.9 76.5-25.8-51.2-151.9-76.5 25.8z m50.7 150.2a6.5 6.5 0 0 1 0.1-4.0l75.6 28.1c5.5-14.9 6.2-31.3 1.6-46.7l-77.5 22.6z m0.1-4.0a6.4 6.4 0 0 1 2.4-3.2l43.8 67.8c13.4-8.7 23.6-21.5 29.2-36.4l-75.6-28.1z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="7" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemFabric" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="8" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Fabric"
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="7" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemFabric" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="8" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Fabric"
|
||||
LogoScale="1.02" Logo="M826.453333 170.666667c-100.266667-93.866667-248.96-76.373333-256-75.52a31.786667 31.786667 0 0 0-26.666666 22.613333c-1.066667 3.2-101.546667 330.666667-426.666667 445.013333a29.013333 29.013333 0 0 0-7.893333 4.48l-1.493334 1.066667a29.44 29.44 0 0 0-5.973333 6.613333 31.786667 31.786667 0 0 0-3.626667 7.68 5.333333 5.333333 0 0 1 0 1.493334 30.506667 30.506667 0 0 0 0 8.96c7.466667 116.266667 45.013333 204.586667 112 262.826666a303.36 303.36 0 0 0 194.773334 71.466667h11.52a32.426667 32.426667 0 0 0 27.093333-19.626667 694.186667 694.186667 0 0 1 159.36-234.666666l-7.68 55.466666A31.786667 31.786667 0 0 0 621.44 768h4.48a32.213333 32.213333 0 0 0 31.786667-27.733333l15.573333-112.426667 112.426667 8.32a32 32 0 1 0 4.693333-64l-56.96-4.266667c36.48-25.813333 74.026667-50.56 112-75.52l51.626667-34.133333a31.573333 31.573333 0 0 0 14.08-24.746667c6.186667-115.2-21.76-203.306667-84.693334-262.826666zM620.8 573.013333l-1.706667 1.493334a219.093333 219.093333 0 0 0-87.466666-116.693334 222.933333 222.933333 0 0 0-95.146667-33.28c18.986667-21.333333 36.266667-42.666667 51.626667-64a198.613333 198.613333 0 0 1 202.453333 158.08c-20.053333 14.506667-39.893333 29.44-59.52 45.226667a29.866667 29.866667 0 0 0-10.24 9.173333z m-228.693333 292.266667a238.72 238.72 0 0 1-141.44-55.893333 213.333333 213.333333 0 0 1-34.986667-39.466667 123.946667 123.946667 0 0 0 44.373333 8.106667 168.533333 168.533333 0 0 0 69.12-16.213334 29.44 29.44 0 0 0 7.04-4.266666l106.666667-85.333334a32 32 0 1 0-39.893333-49.92L298.666667 704a78.293333 78.293333 0 0 1-69.546667 1.706667c-32.426667-17.066667-52.693333-61.653333-62.506667-93.44a709.333333 709.333333 0 0 0 202.453334-123.733334 187.52 187.52 0 0 1 128 21.333334 171.946667 171.946667 0 0 1 68.906666 109.653333 756.48 756.48 0 0 0-173.866666 245.76zM810.666667 438.4l-64 42.666667A256 256 0 0 0 529.706667 298.666667a810.666667 810.666667 0 0 0 69.12-140.8c37.973333-1.066667 123.946667 4.053333 183.68 59.946666 45.866667 42.666667 67.84 108.8 65.493333 195.84z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="8" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemLiteLoader" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="9" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="LiteLoader"
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="8" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemLiteLoader" Visibility="Collapsed" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="9" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="LiteLoader"
|
||||
LogoScale="1.06" Logo="M517.41 186.99l22.45 83.78h-55.04l-18.76-70.02c-2.85-10.63-13.78-16.95-24.42-14.1-10.63 2.85-16.95 13.78-14.1 24.42l16 59.71H388.5l-12.31-45.95c-10.45-38.99 12.69-79.08 51.69-89.52s79.08 12.68 89.53 51.68z M538.58 98c40.37 0 73.1 32.73 73.1 73.1v79.74h-53.16V171.1c0-11.01-8.93-19.94-19.94-19.94-11.01 0-19.94 8.93-19.94 19.94v79.74h-53.16V171.1c0-40.37 32.73-73.1 73.1-73.1z M512 224.26c191.58 0 346.88 155.3 346.88 346.88v61.8c0 28.85 3.33 59.94 9.98 93.27l1.29 6.28c12.43 59.1-21.15 118.2-78.28 137.78C691.18 904.75 597.9 922 512 922c-83.94 0-174.95-16.47-273.01-49.41l-6.85-2.32c-56.4-19.32-89.85-77.16-78.74-135.5l0.46-2.27c7.51-35.71 11.27-68.89 11.27-99.55v-61.8c0-189.66 152.21-343.77 341.14-346.83l5.73-0.06z m-4.64 66.49c-151.21 2.45-273.32 124.58-275.75 275.8l-0.04 4.59v61.8l-0.04 5.93c-0.45 33.74-4.7 69.49-12.65 107.3-5.53 26.27 9.4 52.53 34.79 61.23 94.08 32.23 180.19 48.15 258.32 48.15s164.25-15.92 258.32-48.15c25.39-8.7 40.32-34.97 34.79-61.23-7.95-37.81-12.2-73.56-12.65-107.3l-0.04-5.93v-61.8c0-153.33-123.05-277.91-275.79-280.39l-4.64-0.04-4.62 0.04z M500.66 717.38l-53.28-87.19c-3.83-6.26-1.85-14.44 4.41-18.27 0.76-0.46 1.56-0.85 2.39-1.15L512 589.74l57.82 21.03c6.9 2.51 10.46 10.13 7.95 17.03-0.3 0.83-0.69 1.63-1.15 2.39l-53.28 87.19c-3.83 6.26-12.01 8.24-18.27 4.41-1.8-1.1-3.31-2.61-4.41-4.41z M684.77 689.42m-46.52 0a46.52 46.52 0 1 0 93.04 0 46.52 46.52 0 1 0-93.04 0Z M339.23 689.42m-46.52 0a46.52 46.52 0 1 0 93.04 0 46.52 46.52 0 1 0-93.04 0Z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="9" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<TextBlock Text="资源" Margin="13,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemMod" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="11" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod"
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="9" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<TextBlock Text="资源" Margin="13,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemMod" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="11" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod"
|
||||
LogoScale="0.97" Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="11" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemPack" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="12" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="整合包"
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="11" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemPack" Type="RadioBox" IsScaleAnimationEnabled="False" Tag="12" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="整合包"
|
||||
LogoScale="0.98" Logo="M511.488 995.328a128.654222 128.654222 0 0 1-57.116444-13.112889L70.769778 791.808a126.833778 126.833778 0 0 1-70.769778-113.777778V311.608889a126.179556 126.179556 0 0 1 15.36-60.103111V248.604444c1.479111-2.901333 3.356444-5.603556 5.518222-8.021333a127.630222 127.630222 0 0 1 49.891556-42.325333L454.371556 13.368889a128.739556 128.739556 0 0 1 112.981333 0l383.601778 190.407111a126.862222 126.862222 0 0 1 72.049777 113.379556v360.874666a126.805333 126.805333 0 0 1-70.769777 115.939556L568.604444 984.32c-17.92 7.964444-37.461333 11.747556-57.116444 11.008z m42.638222-470.897778v370.204445l360.192-178.545778c14.449778-7.253333 23.552-21.987556 23.438222-38.087111v-335.928889L554.097778 524.430222zM85.248 330.666667v347.335111a42.268444 42.268444 0 0 0 23.438222 38.087111l360.192 178.545778V523.576889L85.248 330.666667zM135.537778 260.835556l375.950222 189.952 137.671111-65.564445L286.435556 188.074667 135.537778 260.864z m245.105778-118.471112l363.576888 197.973334 150.897778-71.480889-365.283555-180.224a42.922667 42.922667 0 0 0-37.518223 0l-111.672888 53.731555z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="12" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="12" ToolTip="刷新" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1" LogoScale="0.85" Click="Refresh" 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" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyScrollViewer>
|
||||
</local:MyPageLeft>
|
||||
@@ -1,4 +1,5 @@
|
||||
Public Class PageDownloadLeft
|
||||
Implements IRefreshable
|
||||
|
||||
#Region "页面切换"
|
||||
|
||||
@@ -61,7 +62,7 @@
|
||||
PageChangeRun(PageGet(ID))
|
||||
PageID = ID
|
||||
Catch ex As Exception
|
||||
Log(ex, "切换设置分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Log(ex, "切换分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Finally
|
||||
AniControlEnabled -= 1
|
||||
End Try
|
||||
@@ -91,7 +92,13 @@
|
||||
|
||||
'强制刷新
|
||||
Public Sub Refresh(sender As Object, e As EventArgs) '由边栏按钮匿名调用
|
||||
Select Case Val(sender.Tag)
|
||||
Refresh(Val(sender.Tag))
|
||||
End Sub
|
||||
Public Sub Refresh() Implements IRefreshable.Refresh
|
||||
Refresh(FrmMain.PageCurrentSub)
|
||||
End Sub
|
||||
Public Sub Refresh(SubType As FormMain.PageSubType)
|
||||
Select Case SubType
|
||||
Case FormMain.PageSubType.DownloadInstall
|
||||
DlClientListLoader.Start(IsForceRestart:=True)
|
||||
DlOptiFineListLoader.Start(IsForceRestart:=True)
|
||||
@@ -106,12 +113,14 @@
|
||||
PageDownloadMod.Storage = New CompProjectStorage
|
||||
PageDownloadMod.Page = 0
|
||||
CompProjectCache.Clear()
|
||||
CompFilesCache.Clear()
|
||||
If FrmDownloadMod IsNot Nothing Then FrmDownloadMod.PageLoaderRestart()
|
||||
ItemMod.Checked = True
|
||||
Case FormMain.PageSubType.DownloadPack
|
||||
PageDownloadPack.Storage = New CompProjectStorage
|
||||
PageDownloadPack.Page = 0
|
||||
CompProjectCache.Clear()
|
||||
CompFilesCache.Clear()
|
||||
If FrmDownloadPack IsNot Nothing Then FrmDownloadPack.PageLoaderRestart()
|
||||
ItemPack.Checked = True
|
||||
Case FormMain.PageSubType.DownloadClient
|
||||
|
||||
@@ -33,20 +33,17 @@
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
|
||||
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320">
|
||||
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="1.21.4" />
|
||||
<local:MyComboBoxItem Content="1.21.1" />
|
||||
<local:MyComboBoxItem Content="1.21" />
|
||||
<local:MyComboBoxItem Content="1.20.6" />
|
||||
<local:MyComboBoxItem Content="1.20.4" />
|
||||
<local:MyComboBoxItem Content="1.20.1" />
|
||||
<local:MyComboBoxItem Content="1.19.4" />
|
||||
<local:MyComboBoxItem Content="1.19.2" />
|
||||
<local:MyComboBoxItem Content="1.18.2" />
|
||||
<local:MyComboBoxItem Content="1.17.1" />
|
||||
<local:MyComboBoxItem Content="1.16.5" />
|
||||
<local:MyComboBoxItem Content="1.15.2" />
|
||||
<local:MyComboBoxItem Content="1.14.4" />
|
||||
<local:MyComboBoxItem Content="1.12.2" />
|
||||
<local:MyComboBoxItem Content="1.11.2" />
|
||||
<local:MyComboBoxItem Content="1.10.2" />
|
||||
<local:MyComboBoxItem Content="1.8.9" />
|
||||
<local:MyComboBoxItem Content="1.7.10" />
|
||||
|
||||
@@ -1,24 +1,62 @@
|
||||
Public Class PageDownloadMod
|
||||
|
||||
Public Const PageSize = 40
|
||||
''' <summary>
|
||||
''' 在切换到该页面时自动设置的目标版本。
|
||||
''' </summary>
|
||||
Public Shared TargetVersion As McVersion = Nothing
|
||||
|
||||
'加载器信息
|
||||
Public Shared Loader As New LoaderTask(Of CompProjectRequest, Integer)("CompProject Mod", AddressOf CompProjectsGet, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
|
||||
Public Shared Storage As New CompProjectStorage
|
||||
Public Shared Page As Integer = 0
|
||||
Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
|
||||
Private IsLoaderInited As Boolean = False
|
||||
Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Loaded
|
||||
'不知道从 Initialized 改成 Loaded 会不会有问题,但用 Initialized 会导致初始的筛选器修改被覆盖回默认值
|
||||
If TargetVersion IsNot Nothing Then
|
||||
'设置目标
|
||||
ResetFilter() '重置筛选器
|
||||
TextSearchVersion.Text = TargetVersion.Version.McName
|
||||
Dim GetTargetItemByName =
|
||||
Function(Name As String) As MyComboBoxItem
|
||||
For Each Item As MyComboBoxItem In ComboSearchLoader.Items
|
||||
If Item.Content = Name Then Return Item
|
||||
Next
|
||||
Return ComboSearchLoader.Items(0)
|
||||
End Function
|
||||
If TargetVersion.Version.HasForge Then
|
||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("Forge")
|
||||
ElseIf TargetVersion.Version.HasFabric Then
|
||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("Fabric")
|
||||
ElseIf TargetVersion.Version.HasNeoForge Then
|
||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
|
||||
End If
|
||||
TargetVersion = Nothing
|
||||
'如果已经完成请求,则重新开始
|
||||
If IsLoaderInited Then StartNewSearch()
|
||||
PanScroll.ScrollToHome()
|
||||
End If
|
||||
'加载器初始化
|
||||
If IsLoaderInited Then Return
|
||||
IsLoaderInited = True
|
||||
PageLoaderInit(Load, PanLoad, PanContent, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
|
||||
If McVersionHighest = -1 Then McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
|
||||
End Sub
|
||||
Private Shared Function LoaderInput() As CompProjectRequest
|
||||
Dim Request As New CompProjectRequest(CompType.Mod, Storage, (Page + 1) * PageSize)
|
||||
If FrmDownloadMod IsNot Nothing Then
|
||||
Dim ModLoader As CompModLoaderType = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag)
|
||||
Dim GameVersion As String = If(FrmDownloadMod.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
|
||||
If(FrmDownloadMod.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadMod.TextSearchVersion.Text.Contains("w"), FrmDownloadMod.TextSearchVersion.Text, Nothing))
|
||||
If GameVersion IsNot Nothing AndAlso GameVersion.Contains(".") AndAlso Val(GameVersion.Split(".")(1)) < 14 AndAlso '1.14-
|
||||
ModLoader = CompModLoaderType.Forge Then '选择了 Forge
|
||||
ModLoader = CompModLoaderType.Any '此时,视作没有筛选 Mod Loader(因为部分老 Mod 没有设置自己支持的加载器)
|
||||
End If
|
||||
With Request
|
||||
.SearchText = FrmDownloadMod.TextSearchName.Text
|
||||
.GameVersion = If(FrmDownloadMod.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
|
||||
If(FrmDownloadMod.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadMod.TextSearchVersion.Text.Contains("w"), FrmDownloadMod.TextSearchVersion.Text, Nothing))
|
||||
.GameVersion = GameVersion
|
||||
.Tag = FrmDownloadMod.ComboSearchTag.SelectedItem.Tag
|
||||
.ModLoader = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag)
|
||||
.ModLoader = ModLoader
|
||||
.Source = CType(Val(FrmDownloadMod.ComboSearchSource.SelectedItem.Tag), CompSourceType)
|
||||
End With
|
||||
End If
|
||||
@@ -112,7 +150,7 @@
|
||||
End Sub
|
||||
|
||||
'重置按钮
|
||||
Private Sub BtnSearchReset_Click(sender As Object, e As EventArgs) Handles BtnSearchReset.Click
|
||||
Private Sub ResetFilter() Handles BtnSearchReset.Click
|
||||
TextSearchName.Text = ""
|
||||
TextSearchVersion.Text = "全部 (也可自行输入)"
|
||||
TextSearchVersion.SelectedIndex = 0
|
||||
|
||||
@@ -8,14 +8,12 @@
|
||||
<StackPanel Orientation="Vertical" Margin="5">
|
||||
<local:MyCard Margin="20,20,20,0" Grid.IsSharedSizeScope="True" Title="OptiFine 简介" x:Name="CardTip">
|
||||
<StackPanel Margin="25,40,15,20">
|
||||
<TextBlock Name="LabConnect" Margin="0,0,0,11" Text="OptiFine 又名高清修复,它让你可以安装光影、使用高清材质,并且可以大幅提高游戏性能。" TextWrapping="Wrap" />
|
||||
<TextBlock Name="LabConnect" Margin="0,0,0,11" Text="OptiFine 又称为高清修复,以允许安装光影、使用高清材质、提高游戏性能,但与 Mod 的兼容性不佳。" TextWrapping="Wrap" />
|
||||
<Grid Height="35">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnChina" Grid.Column="0" MinWidth="140" Text="打开中文网" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||
<local:MyButton x:Name="BtnWeb" Grid.Column="1" MinWidth="140" Text="打开官网" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnWeb" Grid.Column="0" MinWidth="140" Text="打开官网" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -49,8 +49,5 @@
|
||||
Private Sub BtnWeb_Click(sender As Object, e As EventArgs) Handles BtnWeb.Click
|
||||
OpenWebsite("https://www.optifine.net/")
|
||||
End Sub
|
||||
Private Sub BtnChina_Click(sender As Object, e As EventArgs) Handles BtnChina.Click
|
||||
OpenWebsite("https://optifine.cn/home")
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -32,20 +32,17 @@
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
|
||||
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" IsEditable="True" MaxDropDownHeight="320">
|
||||
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="1.21.4" />
|
||||
<local:MyComboBoxItem Content="1.21.1" />
|
||||
<local:MyComboBoxItem Content="1.21" />
|
||||
<local:MyComboBoxItem Content="1.20.6" />
|
||||
<local:MyComboBoxItem Content="1.20.4" />
|
||||
<local:MyComboBoxItem Content="1.20.1" />
|
||||
<local:MyComboBoxItem Content="1.19.4" />
|
||||
<local:MyComboBoxItem Content="1.19.2" />
|
||||
<local:MyComboBoxItem Content="1.18.2" />
|
||||
<local:MyComboBoxItem Content="1.17.1" />
|
||||
<local:MyComboBoxItem Content="1.16.5" />
|
||||
<local:MyComboBoxItem Content="1.15.2" />
|
||||
<local:MyComboBoxItem Content="1.14.4" />
|
||||
<local:MyComboBoxItem Content="1.12.2" />
|
||||
<local:MyComboBoxItem Content="1.11.2" />
|
||||
<local:MyComboBoxItem Content="1.10.2" />
|
||||
<local:MyComboBoxItem Content="1.8.9" />
|
||||
<local:MyComboBoxItem Content="1.7.10" />
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<Window x:Class="FormLoginOAuth"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:PCL"
|
||||
mc:Ignorable="d"
|
||||
Height="720" Width="580" MinHeight="720" MinWidth="580" ResizeMode="CanResize" WindowStartupLocation="CenterScreen" Title="Microsoft 账户登录">
|
||||
<Grid>
|
||||
<Grid.Background>
|
||||
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||
<GradientStop Color="White" Offset="0"/>
|
||||
<GradientStop Color="{DynamicResource ColorObject8}" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Grid.Background>
|
||||
<StackPanel x:Name="PanLoading" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<local:MyLoading x:Name="Loading" Text="正在加载登录页面" HorizontalAlignment="Center" />
|
||||
<TextBlock Text="如果网络环境不佳,加载可能非常缓慢甚至一直加载不出来" Margin="0,25,0,0"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource ColorBrush1}" Opacity="0.7" />
|
||||
<TextBlock Text="此时请尝试使用 VPN 或加速器,然后重试"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource ColorBrush1}" Opacity="0.7" />
|
||||
</StackPanel>
|
||||
<WebBrowser x:Name="Browser1" Visibility="Collapsed" Tag="1" Margin="0,0,0,25" />
|
||||
<WebBrowser x:Name="Browser2" Visibility="Collapsed" Tag="2" Margin="0,0,0,25" />
|
||||
<WebBrowser x:Name="Browser3" Visibility="Collapsed" Tag="3" Margin="0,0,0,25" />
|
||||
<local:MyTextButton Text="如果遇到问题,可以点击这里使用系统浏览器登录" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,5" x:Name="HintSwitch" />
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,100 +0,0 @@
|
||||
Imports System.Windows.Navigation
|
||||
|
||||
Public Class FormLoginOAuth
|
||||
|
||||
Public Event OnLoginSuccess(code As String)
|
||||
Public Event OnLoginCanceled(IsSwitch As Boolean)
|
||||
|
||||
'跳转事件
|
||||
Private IsLoginSuccessed As Boolean = False
|
||||
Private IsSwitch As Boolean = False
|
||||
Private Sub Browser_Navigating(sender As WebBrowser, e As NavigatingCancelEventArgs) Handles Browser1.Navigating, Browser2.Navigating, Browser3.Navigating
|
||||
Dim Url As String = e.Uri.AbsoluteUri
|
||||
If ModeDebug Then Log("[Login] 登录浏览器 " & sender.Tag & " 导向:" & Url)
|
||||
If Url.Contains("code=") Then
|
||||
Dim Code As String = RegexSeek(Url, "(?<=code\=)[^&]+")
|
||||
Log("[Login] 抓取到 OAuth 返回码:" & Code)
|
||||
IsLoginSuccessed = True
|
||||
RaiseEvent OnLoginSuccess(Code)
|
||||
ElseIf Url.Contains("github.") Then
|
||||
Hint("PCL 不支持使用 GitHub 登录微软账号!", HintType.Critical)
|
||||
Close()
|
||||
End If
|
||||
End Sub
|
||||
|
||||
'已导航事件
|
||||
Private IsFirstLoaded As Boolean = False
|
||||
Private IsFirstLoadedLock As New Object
|
||||
Private Sub Browser_Navigated(sender As WebBrowser, e As NavigationEventArgs) Handles Browser1.Navigated, Browser2.Navigated, Browser3.Navigated
|
||||
SyncLock IsFirstLoadedLock
|
||||
If IsFirstLoaded Then Exit Sub
|
||||
IsFirstLoaded = True
|
||||
End SyncLock
|
||||
RunInThread(Sub()
|
||||
Thread.Sleep(1000)
|
||||
RunInUi(Sub()
|
||||
sender.Visibility = Visibility.Visible
|
||||
PanLoading.Visibility = Visibility.Collapsed
|
||||
Log("[Login] 已将登录窗口切换至浏览器")
|
||||
End Sub)
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
'窗体的进出事件
|
||||
Public Shared LoginUrl1 As String = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?prompt=login&client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=https:%2F%2Flogin.live.com%2Foauth20_desktop.srf"
|
||||
Public Shared LoginUrl2 As String = "https://login.live.com/oauth20_authorize.srf?prompt=login&client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=https:%2F%2Flogin.live.com%2Foauth20_desktop.srf"
|
||||
Private Sub FrmLoginOAuth_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
Browser1.Navigate(LoginUrl1)
|
||||
RunInThread(Sub()
|
||||
'估计是由于时间戳原因,同时导航会导致误报密码失败
|
||||
Thread.Sleep(2500)
|
||||
RunInUi(Sub()
|
||||
Try '防止在 Dispose 之后调用
|
||||
If Not IsFirstLoaded Then Browser2.Navigate(LoginUrl1)
|
||||
Catch
|
||||
End Try
|
||||
End Sub)
|
||||
Thread.Sleep(2500)
|
||||
RunInUi(Sub()
|
||||
Try
|
||||
If Not IsFirstLoaded Then Browser3.Navigate(LoginUrl2)
|
||||
Catch
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub)
|
||||
End Sub
|
||||
Private Sub FormLoginOAuth_Closed() Handles Me.Closed
|
||||
RunInThread(Sub()
|
||||
Thread.Sleep(1000) '释放会卡一下,所以稍等一下……
|
||||
RunInUiWait(Sub()
|
||||
Try
|
||||
Browser1.Dispose()
|
||||
Catch ex As Exception
|
||||
Log(ex, "释放微软登录浏览器 1 失败")
|
||||
End Try
|
||||
End Sub)
|
||||
Thread.Sleep(200)
|
||||
RunInUiWait(Sub()
|
||||
Try
|
||||
Browser2.Dispose()
|
||||
Catch ex As Exception
|
||||
Log(ex, "释放微软登录浏览器 2 失败")
|
||||
End Try
|
||||
End Sub)
|
||||
Thread.Sleep(200)
|
||||
RunInUiWait(Sub()
|
||||
Try
|
||||
Browser3.Dispose()
|
||||
Catch ex As Exception
|
||||
Log(ex, "释放微软登录浏览器 3 失败")
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub)
|
||||
If Not IsLoginSuccessed Then RaiseEvent OnLoginCanceled(IsSwitch)
|
||||
FrmMain.Focus()
|
||||
End Sub
|
||||
Private Sub HintSwitch_Click() Handles HintSwitch.Click
|
||||
IsSwitch = True
|
||||
Close()
|
||||
End Sub
|
||||
End Class
|
||||
@@ -24,7 +24,7 @@
|
||||
<TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" Foreground="{DynamicResource ColorBrush2}" HorizontalAlignment="Left" Name="LabTitle" Margin="7,-1,70,9" Text="测试标题文本" VerticalAlignment="Top" SnapsToDevicePixels="False" UseLayoutRounding="False" />
|
||||
<Rectangle x:Name="ShapeLine" Grid.Row="1" Height="2" Fill="{Binding Foreground, ElementName=LabTitle}" />
|
||||
<my:MyScrollViewer Grid.Row="3" VerticalAlignment="Top" x:Name="PanCaption" Margin="0,0,0,17" Padding="7,0,15,0"
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMuity="0.7">
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" DeltaMult="0.7">
|
||||
<TextBlock VerticalAlignment="Top" TextTrimming="None" TextWrapping="Wrap" Name="LabCaption" FontSize="15" LineHeight="18"
|
||||
Foreground="#FF5C5C5C" FontWeight="Normal" Padding="1" />
|
||||
</my:MyScrollViewer>
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
}, "MyMsgBox " & Uuid)
|
||||
End Sub
|
||||
|
||||
'实现回车和 Esc 的接口(#4857)
|
||||
Public Sub Btn1_Click() Handles Btn1.Click
|
||||
End Sub
|
||||
Public Sub Btn3_Click() Handles Btn3.Click
|
||||
Finished(New ThreadInterruptedException)
|
||||
End Sub
|
||||
@@ -93,7 +96,7 @@
|
||||
End Sub
|
||||
|
||||
Private Sub WorkThread()
|
||||
Thread.Sleep(4000)
|
||||
Thread.Sleep(3000)
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
OpenWebsite(Website)
|
||||
ClipboardSet(UserCode)
|
||||
@@ -122,12 +125,15 @@
|
||||
ElseIf ex.Message.Contains("expired_token") Then
|
||||
Finished(New Exception("$登录用时太长啦,重新试试吧!"))
|
||||
Return
|
||||
ElseIf ex.Message.Contains("AADSTS70000") Then '可能不能判 “invalid_grant”,见 #269
|
||||
Finished(New RestartException)
|
||||
Return
|
||||
ElseIf ex.Message.Contains("authorization_pending") Then
|
||||
Thread.Sleep(1000)
|
||||
Thread.Sleep(2000)
|
||||
ElseIf UnknownFailureCount <= 2 Then
|
||||
UnknownFailureCount += 1
|
||||
Log(ex, $"登录轮询第 {UnknownFailureCount} 次失败")
|
||||
Thread.Sleep(1000)
|
||||
Thread.Sleep(2000)
|
||||
Else
|
||||
Finished(New Exception("登录轮询失败", ex))
|
||||
Return
|
||||
|
||||
@@ -177,8 +177,8 @@
|
||||
Sub()
|
||||
Try
|
||||
'更新缓存
|
||||
WriteIni(PathTemp & "Cache\Skin\IndexMs.ini", Setup.Get("CacheMsUuid"), SkinAddress)
|
||||
Log(String.Format("[Skin] 已写入皮肤地址缓存 {0} -> {1}", Setup.Get("CacheMsUuid"), SkinAddress))
|
||||
WriteIni(PathTemp & "Cache\Skin\IndexMs.ini", Setup.Get("CacheMsV2Uuid"), SkinAddress)
|
||||
Log(String.Format("[Skin] 已写入皮肤地址缓存 {0} -> {1}", Setup.Get("CacheMsV2Uuid"), SkinAddress))
|
||||
'刷新控件
|
||||
For Each SkinLoader In {PageLaunchLeft.SkinMs, PageLaunchLeft.SkinLegacy}
|
||||
SkinLoader.WaitForExit(IsForceRestart:=True)
|
||||
@@ -242,7 +242,7 @@ Retry:
|
||||
{"Vanilla", "原版披风"}, {"Minecon2011", "Minecon 2011 参与者披风"}, {"Minecon2012", "Minecon 2012 参与者披风"},
|
||||
{"Minecon2013", "Minecon 2013 参与者披风"}, {"Minecon2015", "Minecon 2015 参与者披风"}, {"Minecon2016", "Minecon 2016 参与者披风"},
|
||||
{"Cherry Blossom", "樱花披风"}, {"15th Anniversary", "15 周年纪念披风"}, {"Purple Heart", "紫色心形披风"},
|
||||
{"Follower's", "追随者披风"}, {"MCC 15th Year", "MCC 15 周年披风"}
|
||||
{"Follower's", "追随者披风"}, {"MCC 15th Year", "MCC 15 周年披风"}, {"Minecraft Experience", "村民救援披风"}
|
||||
}
|
||||
Dim SelectionControl As New List(Of IMyRadio) From {New MyRadioBox With {.Text = "无披风"}}
|
||||
For Each Cape In SkinData("capes")
|
||||
|
||||
@@ -26,21 +26,15 @@
|
||||
If File.Exists(Path & "modpack.zip") Then PackInstallPath = Path & "modpack.zip"
|
||||
If File.Exists(Path & "modpack.mrpack") Then PackInstallPath = Path & "modpack.mrpack"
|
||||
If PackInstallPath IsNot Nothing Then
|
||||
If MyMsgBox($"PCL 即将在当前文件夹下自动安装整合包。", "自动安装", "继续", "取消") = 1 Then
|
||||
'确认自动安装
|
||||
Log("[Launch] 需自动安装整合包:" & PackInstallPath, LogLevel.Debug)
|
||||
Setup.Set("LaunchFolderSelect", "$.minecraft\")
|
||||
If Not Directory.Exists(Path & ".minecraft\") Then
|
||||
Directory.CreateDirectory(Path & ".minecraft\")
|
||||
Directory.CreateDirectory(Path & ".minecraft\versions\")
|
||||
McFolderLauncherProfilesJsonCreate(Path & ".minecraft\")
|
||||
End If
|
||||
McFolderListLoader.WaitForExit(IsForceRestart:=True)
|
||||
Else
|
||||
'取消自动安装
|
||||
Log("[Launch] 取消自动安装整合包:" & PackInstallPath, LogLevel.Debug)
|
||||
PackInstallPath = Nothing
|
||||
Log("[Launch] 需自动安装整合包:" & PackInstallPath, LogLevel.Debug)
|
||||
Setup.Set("LaunchFolderSelect", "$.minecraft\")
|
||||
If Not Directory.Exists(Path & ".minecraft\") Then
|
||||
Directory.CreateDirectory(Path & ".minecraft\")
|
||||
Directory.CreateDirectory(Path & ".minecraft\versions\")
|
||||
McFolderLauncherProfilesJsonCreate(Path & ".minecraft\")
|
||||
End If
|
||||
PageSelectLeft.AddFolder(Path & ".minecraft\", GetFolderNameFromPath(Path), False)
|
||||
McFolderListLoader.WaitForExit()
|
||||
End If
|
||||
'确认 Minecraft 文件夹存在
|
||||
PathMcFolder = Setup.Get("LaunchFolderSelect").ToString.Replace("$", Path)
|
||||
@@ -58,18 +52,19 @@
|
||||
If Setup.Get("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
|
||||
'自动整合包安装
|
||||
If PackInstallPath IsNot Nothing Then
|
||||
Dim InstallLoader = ModpackInstall(PackInstallPath)
|
||||
If InstallLoader Is Nothing Then
|
||||
Log("[Launch] 自动安装整合包失败:" & PackInstallPath)
|
||||
Else
|
||||
Log("[Launch] 自动安装整合包开始:" & PackInstallPath)
|
||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
|
||||
Try
|
||||
Dim InstallLoader = ModpackInstall(PackInstallPath, GetFolderNameFromPath(Path))
|
||||
Log("[Launch] 自动安装整合包已开始:" & PackInstallPath)
|
||||
InstallLoader.WaitForExit()
|
||||
If InstallLoader.State = LoadState.Finished Then
|
||||
Log("[Launch] 自动安装整合包成功,删除安装包:" & PackInstallPath)
|
||||
File.Delete(PackInstallPath)
|
||||
End If
|
||||
End If
|
||||
Catch ex As CancelledException
|
||||
Log(ex, "自动安装整合包被用户取消:" & PackInstallPath)
|
||||
Catch ex As Exception
|
||||
Log(ex, "自动安装整合包失败:" & PackInstallPath, LogLevel.Msgbox)
|
||||
End Try
|
||||
End If
|
||||
'确认 Minecraft 版本存在
|
||||
Dim Selection As String = Setup.Get("LaunchVersionSelect")
|
||||
@@ -296,7 +291,7 @@
|
||||
Case 0 '正版或离线
|
||||
UnknownType:
|
||||
If RadioLoginType5.Checked Then
|
||||
If Setup.Get("CacheMsAccess") = "" Then
|
||||
If Setup.Get("CacheMsV2Access") = "" Then
|
||||
Type = PageType.Ms
|
||||
Else
|
||||
Type = PageType.MsSkin
|
||||
@@ -311,7 +306,7 @@ UnknownType:
|
||||
RadioLoginType5.Visibility = Visibility.Visible
|
||||
RadioLoginType0.Visibility = Visibility.Visible
|
||||
Case 1 '仅正版
|
||||
If Setup.Get("CacheMsAccess") = "" Then
|
||||
If Setup.Get("CacheMsV2Access") = "" Then
|
||||
Type = PageType.Ms
|
||||
Else
|
||||
Type = PageType.MsSkin
|
||||
@@ -375,7 +370,7 @@ UnknownType:
|
||||
Public Shared SkinMs As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Ms", AddressOf SkinMsLoad, AddressOf SkinMsInput, ThreadPriority.AboveNormal)
|
||||
Private Shared Function SkinMsInput() As EqualableList(Of String)
|
||||
'获取名称
|
||||
Return New EqualableList(Of String) From {Setup.Get("CacheMsName"), Setup.Get("CacheMsUuid")}
|
||||
Return New EqualableList(Of String) From {Setup.Get("CacheMsV2Name"), Setup.Get("CacheMsV2Uuid")}
|
||||
End Function
|
||||
Private Shared Sub SkinMsLoad(Data As LoaderTask(Of EqualableList(Of String), String))
|
||||
'清空已有皮肤
|
||||
@@ -431,7 +426,7 @@ Finish:
|
||||
ElseIf Setup.Get("LoginLegacyName") = "" Then
|
||||
Return New EqualableList(Of String) From {0, ""}
|
||||
Else
|
||||
Return New EqualableList(Of String) From {0, If(Setup.Get("LoginLegacyName").ToString.Before("¨"), "")}
|
||||
Return New EqualableList(Of String) From {0, If(Setup.Get("LoginLegacyName").ToString.BeforeFirst("¨"), "")}
|
||||
End If
|
||||
Case 3
|
||||
Return New EqualableList(Of String) From {3, Setup.Get("LaunchSkinID")}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Public Class PageLaunchRight
|
||||
Implements IRefreshable
|
||||
|
||||
Private Sub Init() Handles Me.Loaded
|
||||
PanBack.ScrollToHome()
|
||||
@@ -92,7 +93,7 @@ Download:
|
||||
GoTo Download
|
||||
Case 3
|
||||
Log("[Page] 主页预设:简单主页")
|
||||
Url = "https://gitee.com/mfn233/PCL-Mainpage/raw/main/Custom.xaml"
|
||||
Url = "https://raw.gitcode.com/mfn233/PCL-Mainpage/raw/main/Custom.xaml"
|
||||
GoTo Download
|
||||
Case 4
|
||||
Log("[Page] 主页预设:每日整合包推荐")
|
||||
@@ -104,12 +105,28 @@ Download:
|
||||
GoTo Download
|
||||
Case 6
|
||||
Log("[Page] 主页预设:OpenBMCLAPI 仪表盘 Lite")
|
||||
Url = "https://pcl-bmcl.milulu.xyz/"
|
||||
Url = "https://pcl-bmcl.milu.ink/"
|
||||
GoTo Download
|
||||
Case 7
|
||||
Log("[Page] 主页预设:主页市场")
|
||||
Url = "https://homepage-market.pages.dev/Custom.xaml"
|
||||
GoTo Download
|
||||
Case 8
|
||||
Log("[Page] 主页预设:更新日志")
|
||||
Url = "https://updatehomepage.pages.dev/UpdateHomepage.xaml"
|
||||
GoTo Download
|
||||
Case 9
|
||||
Log("[Page] 主页预设:PCL 新功能说明书")
|
||||
Url = "https://raw.gitcode.com/WForst-Breeze/WhatsNewPCL/raw/main/Custom.xaml"
|
||||
GoTo Download
|
||||
Case 10
|
||||
Log("[Page] 主页预设:OpenMCIM Dashboard")
|
||||
Url = "https://files.mcimirror.top/PCL"
|
||||
GoTo Download
|
||||
Case 11
|
||||
Log("[Page] 主页预设:杂志主页")
|
||||
Url = "http://pclhomeplazaoss.lingyunawa.top:26994/d/Homepages/Ext1nguisher/Custom.xaml"
|
||||
GoTo Download
|
||||
End Select
|
||||
End Select
|
||||
RunInUi(Sub() LoadContent(Content))
|
||||
@@ -126,17 +143,17 @@ Download:
|
||||
If Address.Contains(".xaml") Then
|
||||
VersionAddress = Address.Replace(".xaml", ".xaml.ini")
|
||||
Else
|
||||
VersionAddress = Address.Before("?")
|
||||
VersionAddress = Address.BeforeFirst("?")
|
||||
If Not VersionAddress.EndsWith("/") Then VersionAddress += "/"
|
||||
VersionAddress += "version"
|
||||
If Address.Contains("?") Then VersionAddress += Address.After("?")
|
||||
If Address.Contains("?") Then VersionAddress += Address.AfterLast("?")
|
||||
End If
|
||||
'校验版本
|
||||
Dim Version As String = ""
|
||||
Dim NeedDownload As Boolean = True
|
||||
Try
|
||||
Version = NetGetCodeByRequestOnce(VersionAddress, Timeout:=10000)
|
||||
If Version.Length > 100 Then Throw New Exception($"获取的自定义主页版本过长({Version.Length} 字符)")
|
||||
If Version.Length > 1000 Then Throw New Exception($"获取的自定义主页版本过长({Version.Length} 字符)")
|
||||
Dim CurrentVersion As String = Setup.Get("CacheSavedPageVersion")
|
||||
If Version <> "" AndAlso CurrentVersion <> "" AndAlso Version = CurrentVersion Then
|
||||
Log($"[Page] 当前缓存的自定义主页已为最新,当前版本:{Version},检查源:{VersionAddress}")
|
||||
@@ -171,7 +188,7 @@ Download:
|
||||
''' 立即强制刷新自定义主页。
|
||||
''' 必须在 UI 线程调用。
|
||||
''' </summary>
|
||||
Public Sub ForceRefresh()
|
||||
Public Sub ForceRefresh() Implements IRefreshable.Refresh
|
||||
Log("[Page] 要求强制刷新自定义主页")
|
||||
ClearCache()
|
||||
'实际的刷新
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
ComboName.ItemsSource = Nothing
|
||||
Else
|
||||
ComboName.ItemsSource = Setup.Get("LoginAuthEmail").ToString.Split("¨")
|
||||
ComboName.Text = Setup.Get("LoginAuthEmail").ToString.Before("¨")
|
||||
If Setup.Get("LoginRemember") Then TextPass.Password = Setup.Get("LoginAuthPass").ToString.Before("¨").Trim
|
||||
ComboName.Text = Setup.Get("LoginAuthEmail").ToString.BeforeFirst("¨")
|
||||
If Setup.Get("LoginRemember") Then TextPass.Password = Setup.Get("LoginAuthPass").ToString.BeforeFirst("¨").Trim
|
||||
End If
|
||||
End If
|
||||
IsFirstLoad = False
|
||||
|
||||
@@ -70,9 +70,11 @@
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub
|
||||
Private Sub BtnExit_Click() Handles BtnExit.Click
|
||||
Public Shared Sub ExitLogin() Handles BtnExit.Click
|
||||
Setup.Set("CacheAuthAccess", "")
|
||||
Setup.Set("CacheAuthUuid", "")
|
||||
Setup.Set("CacheAuthName", "")
|
||||
McLoginAuthLoader.Input = Nothing '防止因为输入的用户名密码相同,直接使用了上次登录的加载器结果
|
||||
FrmLaunchLeft.RefreshPage(False, True)
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Public Class PageLoginLegacy
|
||||
ComboName.ItemsSource = Nothing
|
||||
Else
|
||||
ComboName.ItemsSource = Setup.Get("LoginLegacyName").ToString.Split("¨")
|
||||
ComboName.Text = Setup.Get("LoginLegacyName").ToString.Before("¨").Trim
|
||||
ComboName.Text = Setup.Get("LoginLegacyName").ToString.BeforeFirst("¨").Trim
|
||||
End If
|
||||
End If
|
||||
IsReloaded = True
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
''' 获取当前页面的登录信息。
|
||||
''' </summary>
|
||||
Public Shared Function GetLoginData() As McLoginMs
|
||||
If FrmLoginMs Is Nothing Then Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName")}
|
||||
If FrmLoginMs Is Nothing Then Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsV2OAuthRefresh"), .UserName = Setup.Get("CacheMsV2Name")}
|
||||
Dim Result As McLoginMs = Nothing
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
''' 刷新页面显示的所有信息。
|
||||
''' </summary>
|
||||
Public Sub Reload(KeepInput As Boolean)
|
||||
TextName.Text = Setup.Get("CacheMsName")
|
||||
TextName.Text = Setup.Get("CacheMsV2Name")
|
||||
'皮肤在 Loaded 加载
|
||||
End Sub
|
||||
''' <summary>
|
||||
@@ -20,9 +20,9 @@
|
||||
''' </summary>
|
||||
Public Shared Function GetLoginData() As McLoginMs
|
||||
If McLoginMsLoader.State = LoadState.Finished Then
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName"), .AccessToken = Setup.Get("CacheMsAccess"), .Uuid = Setup.Get("CacheMsUuid"), .ProfileJson = Setup.Get("CacheMsProfileJson")}
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsV2OAuthRefresh"), .UserName = Setup.Get("CacheMsV2Name"), .AccessToken = Setup.Get("CacheMsV2Access"), .Uuid = Setup.Get("CacheMsV2Uuid"), .ProfileJson = Setup.Get("CacheMsV2ProfileJson")}
|
||||
Else
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName")}
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsV2OAuthRefresh"), .UserName = Setup.Get("CacheMsV2Name")}
|
||||
End If
|
||||
End Function
|
||||
|
||||
@@ -50,11 +50,11 @@
|
||||
|
||||
'退出登录
|
||||
Private Sub BtnExit_Click() Handles BtnExit.Click
|
||||
Setup.Set("CacheMsOAuthRefresh", "")
|
||||
Setup.Set("CacheMsAccess", "")
|
||||
Setup.Set("CacheMsProfileJson", "")
|
||||
Setup.Set("CacheMsUuid", "")
|
||||
Setup.Set("CacheMsName", "")
|
||||
Setup.Set("CacheMsV2OAuthRefresh", "")
|
||||
Setup.Set("CacheMsV2Access", "")
|
||||
Setup.Set("CacheMsV2ProfileJson", "")
|
||||
Setup.Set("CacheMsV2Uuid", "")
|
||||
Setup.Set("CacheMsV2Name", "")
|
||||
McLoginMsLoader.Abort()
|
||||
FrmLaunchLeft.RefreshPage(False, True)
|
||||
End Sub
|
||||
@@ -90,8 +90,8 @@
|
||||
Try
|
||||
Retry:
|
||||
If McLoginMsLoader.State = LoadState.Loading Then McLoginMsLoader.WaitForExit() '等待登录结束
|
||||
Dim AccessToken As String = Setup.Get("CacheMsAccess")
|
||||
Dim Uuid As String = Setup.Get("CacheMsUuid")
|
||||
Dim AccessToken As String = Setup.Get("CacheMsV2Access")
|
||||
Dim Uuid As String = Setup.Get("CacheMsV2Uuid")
|
||||
|
||||
Dim Client As New Net.Http.HttpClient With {.Timeout = New TimeSpan(0, 0, 30)}
|
||||
Client.DefaultRequestHeaders.Authorization = New Net.Http.Headers.AuthenticationHeaderValue("Bearer", AccessToken)
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
ComboName.ItemsSource = Nothing
|
||||
Else
|
||||
ComboName.ItemsSource = Setup.Get("LoginNideEmail").ToString.Split("¨")
|
||||
ComboName.Text = Setup.Get("LoginNideEmail").ToString.Before("¨")
|
||||
If Setup.Get("LoginRemember") Then TextPass.Password = Setup.Get("LoginNidePass").ToString.Before("¨").Trim
|
||||
ComboName.Text = Setup.Get("LoginNideEmail").ToString.BeforeFirst("¨")
|
||||
If Setup.Get("LoginRemember") Then TextPass.Password = Setup.Get("LoginNidePass").ToString.BeforeFirst("¨").Trim
|
||||
End If
|
||||
End If
|
||||
IsFirstLoad = False
|
||||
|
||||
@@ -47,8 +47,9 @@
|
||||
Private Sub BtnEdit_Click(sender As Object, e As EventArgs) Handles BtnEdit.Click
|
||||
OpenWebsite("https://login.mc-user.com:233/account/changepw")
|
||||
End Sub
|
||||
Private Sub BtnExit_Click() Handles BtnExit.Click
|
||||
Public Shared Sub ExitLogin() Handles BtnExit.Click
|
||||
Setup.Set("CacheNideAccess", "")
|
||||
McLoginNideLoader.Input = Nothing '防止因为输入的用户名密码相同,直接使用了上次登录的加载器结果
|
||||
FrmLaunchLeft.RefreshPage(False, True)
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -111,8 +111,6 @@ Public Class PageLinkIoi
|
||||
End Sub
|
||||
'复制联机码
|
||||
Public Shared Sub BtnLeftCopy_Click() Handles BtnLeftCopy.Click
|
||||
ClipboardSet(IoiId.Substring(4) & SecretEncrypt(GetPlayerName), False)
|
||||
Hint("已复制联机码!", HintType.Finish)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -419,75 +417,6 @@ Public Class PageLinkIoi
|
||||
|
||||
'获取数据包
|
||||
Public Shared Sub ReceiveJson(JsonData As JObject, Optional NewSocket As Socket = Nothing)
|
||||
'获取数据
|
||||
Dim Id As String = JsonData("id"), Type As String = JsonData("type")
|
||||
Select Case Type
|
||||
Case "connect"
|
||||
Dim DisplayName As String = JsonData("name")
|
||||
Dim User As New LinkUserIoi(Id, DisplayName, NewSocket)
|
||||
'如果发生了双向连接
|
||||
If UserList.ContainsKey(Id) Then
|
||||
If Id > IoiId Then
|
||||
Log("[IOI] 双向连接,应当抛弃当前用户(" & DisplayName & ")")
|
||||
For Each Pair In UserList(User.Id).Ports.ToList
|
||||
User.Ports(Pair.Key) = Pair.Value
|
||||
Next
|
||||
UserList(Id).Dispose()
|
||||
Else
|
||||
'应当保留当前用户
|
||||
Log("[IOI] 双向连接,应当保留当前用户(" & DisplayName & ")")
|
||||
NewSocket.Dispose()
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
'加入列表
|
||||
UserList.Add(Id, User)
|
||||
'返回请求
|
||||
User.RelativeThread = RunInNewThread(Sub()
|
||||
SendPortsubBack(User, JsonData("version").ToObject(Of Integer))
|
||||
End Sub, "Link Connect " & DisplayName)
|
||||
'更新时间
|
||||
User.LastReceive = Date.Now
|
||||
Case "update"
|
||||
If Not UserList.ContainsKey(Id) Then Throw New Exception("未在列表中的用户发送了更新请求:" & Id)
|
||||
Dim User = UserList(Id)
|
||||
'拉满进度(该请求也作为反向连接回应出现,用于向正向连接方传达连接已完成信号)
|
||||
User.Progress = 1
|
||||
'更新名称
|
||||
Dim DisplayName As String = JsonData("name")
|
||||
User.DisplayName = DisplayName
|
||||
'更新房间列表
|
||||
If JsonData("rooms") IsNot Nothing Then
|
||||
User.Rooms = New List(Of RoomEntry)
|
||||
For Each RoomObject In JsonData("rooms")
|
||||
User.Rooms.Add(New RoomEntry(RoomObject("port"), RoomObject("name"), User))
|
||||
Next
|
||||
End If
|
||||
'更新 Ping
|
||||
Dim Stage As Integer = JsonData("stage"), Unique As Long = JsonData("unique")
|
||||
If Stage > 1 Then
|
||||
User.PingRecord.Enqueue((Date.Now - User.PingPending(Unique)).TotalMilliseconds / 2)
|
||||
If User.PingRecord.Count > 5 Then User.PingRecord.Dequeue()
|
||||
User.PingPending.Remove(Unique)
|
||||
End If
|
||||
'返回请求
|
||||
If Stage > 0 AndAlso Stage < 3 Then RunInNewThread(Sub()
|
||||
Try
|
||||
SendUpdateRequest(User, Stage + 1, Unique)
|
||||
Catch ex As Exception
|
||||
Log(ex, "发送回程请求失败")
|
||||
End Try
|
||||
End Sub, "Link Update " & DisplayName)
|
||||
'更新时间
|
||||
User.LastReceive = Date.Now
|
||||
Case "disconnect"
|
||||
'断开连接
|
||||
If Not UserList.ContainsKey(Id) Then Exit Sub
|
||||
UserRemove(UserList(Id), ShowLeaveMessage:=JsonData("message") Is Nothing)
|
||||
If JsonData("message") IsNot Nothing Then Hint(JsonData("message").ToString, If(JsonData("isError").ToObject(Of Boolean), HintType.Critical, HintType.Info))
|
||||
Case Else
|
||||
Throw New Exception("未知的操作种类:" & Type)
|
||||
End Select
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 从用户列表中移除一位用户。提示信息视作该用户主动离开。
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
PageChangeRun(PageGet(ID))
|
||||
PageID = ID
|
||||
Catch ex As Exception
|
||||
Log(ex, "切换设置分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Log(ex, "切换分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Finally
|
||||
AniControlEnabled -= 1
|
||||
End Try
|
||||
|
||||
@@ -104,82 +104,107 @@
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="赞助者">
|
||||
<StackPanel Margin="25,40,10,20">
|
||||
<TextBlock HorizontalAlignment="Left" Text="以下是 2024 年 8 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock HorizontalAlignment="Left" Text="以下是 2024 年 11 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
||||
<WrapPanel Margin="0,0,0,10">
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="没用的元元" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="鸮不是号鸟" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="兮兮要次糖糖" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="wxzsghh114514" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="地了排子" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="阿宅cheli" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="笑脸114514" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小麦A" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="未名小七TAO" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="雪冥" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="氟西汀" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="阿巴阿巴" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="侦探hj" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="666" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="萬帆WanFan" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="swayst" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="yuchen" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="鲸落猫南北" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="念池鱼思故渊" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="No_1died" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Error02" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="橙子皮" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="丨丨丨丨" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="零崽" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="叁無" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="火星上行走的柠檬精" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="北极椰子" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="流玉髓" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="咕咕" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小鹏1098" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="风雪" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="梦幻の小店" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="nhrnick" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="天天的周末" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="雪梨" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Z_ebra" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="acmzyh" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="yuyyyu" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="看看" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="墨霜夜" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="皇势力" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="曦予千山" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Lv50.疾旋鼬" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="雪暮" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="铁树" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ZHypocrite" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="闫雁" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="不知道叫啥" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="隔壁家老张" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="DZY" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Hugh" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Jto" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="JO极名字" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="啊猫" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="章九连" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="zeq_killjsj" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="重庆你周哥" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="我是桶子哥" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="chenxingyin" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="koimiaori" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Awfrlu+" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="古河渚上花" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="THE END" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="哎呀菜菜子" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="AptS:1547" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="安麓" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="彘彘彘彘彘彘" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="通大小学弟" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Ender__sun" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="此生浮" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="皮皮恒" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="charlesmin" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="snow" />
|
||||
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="枫星Maplestar" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="屑喵" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="DN_TheColdWinter" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小康康" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="李白" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Gim" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="秋前盛夏" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="默然" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="zyx1998" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="阿龟" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="麟兮" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="天龙" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="that month" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Hipop" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="落天邪" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="星尘想睡觉" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="滑天下之大稽" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="机械之咒" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="虐猫达人薛定谔" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Superafei" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="范UP" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="cfgfnh" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="南瓜派不好吃吐了" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="又许江南月" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="我有鱼鱼枕" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="万能充" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小黄" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="咸鱼淡鹤" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="cen_yi123456" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="折鹤z" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="吴风诗" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="MM775" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="鸽王" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="血月无华" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小石头" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="intogo" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="清初凉宫" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="时光回执" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="tangfg" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="zzz" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="红枣列巴" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="VERNON" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="このdioた" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="潜凉" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Pinuo_0" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="被打穿的四号坦克" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="太微" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Suspect" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="龙舞猫跃" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Lotus" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="薄暮之国的希里斯" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Stone0829" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="古冰语" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="甲申道格" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Percy" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="传说中的山羊" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="TARDIS" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="dawa" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="轻梦" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="景景景景景景色分明" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="yaemikosdog" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="乜常青" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="TMOFFMY" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="参差荇菜" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="At sea" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="MRailgun" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="mason_73" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="赵怀民" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="闲的无聊" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="剑歌时亦" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="BartenderJ" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="鱼兔兔" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="豆杀" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="风都未见君" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="重生开大运撞大运" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小林一直睡不醒" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Amorcks" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="陌生少年" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="hh-245" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="wang" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="魔鬼Devil_Tenth" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="星辰追梦者" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="caicai7162" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="redccol" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Zero_z1" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="上玄天" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="老师看我毕设惊了" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="32cc" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="上条真" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="天宇灵TUL" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="龙猫的狗" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="瀚海生辉" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Truman" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="TianChi_廻天" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="土豆明和" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="我好迷丶" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="水蓝蝾螈猫" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="mofacker" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="炎羽尘歌" />
|
||||
</WrapPanel>
|
||||
<Grid Height="35">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -266,18 +291,18 @@
|
||||
<local:MyButton Grid.Row="9" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
EventType="打开网页" EventData="https://iconmonstr.com/license/" />
|
||||
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="10" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
|
||||
<local:MyButton Grid.Row="11" Grid.Column="2" MinWidth="140" Text="查看原网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
EventType="打开网页" EventData="https://www.iconfont.cn/" />
|
||||
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" Text="libwebp wrapper for .NET" TextWrapping="Wrap" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2012 Imazen
Licensed under the MIT License." TextWrapping="Wrap" />
|
||||
<local:MyButton Grid.Row="13" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="libwebp wrapper for .NET" TextWrapping="Wrap" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="10" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2012 Imazen
Licensed under the MIT License." TextWrapping="Wrap" />
|
||||
<local:MyButton Grid.Row="11" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
EventType="打开网页" EventData="https://github.com/imazen/libwebp-net" />
|
||||
<local:MyButton Grid.Row="13" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
<local:MyButton Grid.Row="11" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
EventType="打开网页" EventData="https://github.com/imazen/libwebp-net/blob/master/LICENSE.txt" />
|
||||
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
|
||||
<local:MyButton Grid.Row="13" Grid.Column="2" MinWidth="140" Text="查看原网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||
EventType="打开网页" EventData="https://www.iconfont.cn/" />
|
||||
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Public Class PageOtherHelp
|
||||
Implements IRefreshable
|
||||
|
||||
#Region "初始化"
|
||||
|
||||
@@ -79,31 +80,35 @@
|
||||
End Try
|
||||
End Sub
|
||||
Public Shared Sub EnterHelpPage(Location As String)
|
||||
RunInThread(Sub()
|
||||
If Not HelpLoader.State = LoadState.Finished Then HelpLoader.WaitForExit(GetUuid)
|
||||
Dim Entry As New HelpEntry(Location)
|
||||
RunInUi(Sub()
|
||||
Dim FrmHelpDetail As New PageOtherHelpDetail
|
||||
If FrmHelpDetail.Init(Entry) Then
|
||||
FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.HelpDetail, .Additional = {Entry, FrmHelpDetail}})
|
||||
Else
|
||||
Log("[Help] 已取消进入帮助项目,这一般是由于 xaml 初始化失败,且用户在弹窗中手动放弃", LogLevel.Debug)
|
||||
End If
|
||||
End Sub)
|
||||
End Sub)
|
||||
RunInThread(
|
||||
Sub()
|
||||
If Not HelpLoader.State = LoadState.Finished Then HelpLoader.WaitForExit(GetUuid)
|
||||
Dim Entry As New HelpEntry(Location)
|
||||
RunInUi(
|
||||
Sub()
|
||||
Dim FrmHelpDetail As New PageOtherHelpDetail
|
||||
If FrmHelpDetail.Init(Entry) Then
|
||||
FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.HelpDetail, .Additional = {Entry, FrmHelpDetail}})
|
||||
Else
|
||||
Log("[Help] 已取消进入帮助项目,这一般是由于 xaml 初始化失败,且用户在弹窗中手动放弃", LogLevel.Debug)
|
||||
End If
|
||||
End Sub)
|
||||
End Sub)
|
||||
End Sub
|
||||
Public Shared Sub EnterHelpPage(Entry As HelpEntry)
|
||||
RunInThread(Sub()
|
||||
If Not HelpLoader.State = LoadState.Finished Then HelpLoader.WaitForExit(GetUuid)
|
||||
RunInUi(Sub()
|
||||
Dim FrmHelpDetail As New PageOtherHelpDetail
|
||||
If FrmHelpDetail.Init(Entry) Then
|
||||
FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.HelpDetail, .Additional = {Entry, FrmHelpDetail}})
|
||||
Else
|
||||
Log("[Help] 已取消进入帮助项目,这一般是由于 xaml 初始化失败,且用户在弹窗中手动放弃", LogLevel.Debug)
|
||||
End If
|
||||
End Sub)
|
||||
End Sub)
|
||||
RunInThread(
|
||||
Sub()
|
||||
If Not HelpLoader.State = LoadState.Finished Then HelpLoader.WaitForExit(GetUuid)
|
||||
RunInUi(
|
||||
Sub()
|
||||
Dim FrmHelpDetail As New PageOtherHelpDetail
|
||||
If FrmHelpDetail.Init(Entry) Then
|
||||
FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.HelpDetail, .Additional = {Entry, FrmHelpDetail}})
|
||||
Else
|
||||
Log("[Help] 已取消进入帮助项目,这一般是由于 xaml 初始化失败,且用户在弹窗中手动放弃", LogLevel.Debug)
|
||||
End If
|
||||
End Sub)
|
||||
End Sub)
|
||||
End Sub
|
||||
Public Shared Function GetHelpPage(Location As String) As PageOtherHelpDetail
|
||||
If Not HelpLoader.State = LoadState.Finished Then HelpLoader.WaitForExit(GetUuid)
|
||||
@@ -122,14 +127,15 @@
|
||||
If String.IsNullOrWhiteSpace(SearchBox.Text) Then
|
||||
'隐藏
|
||||
AniStart({
|
||||
AaOpacity(PanSearch, -PanSearch.Opacity, 100),
|
||||
AaCode(Sub()
|
||||
PanSearch.Height = 0
|
||||
PanSearch.Visibility = Visibility.Collapsed
|
||||
PanList.Visibility = Visibility.Visible
|
||||
End Sub,, True),
|
||||
AaOpacity(PanList, 1 - PanList.Opacity, 150, 30)
|
||||
}, "FrmOtherHelp Search Switch")
|
||||
AaOpacity(PanSearch, -PanSearch.Opacity, 100),
|
||||
AaCode(
|
||||
Sub()
|
||||
PanSearch.Height = 0
|
||||
PanSearch.Visibility = Visibility.Collapsed
|
||||
PanList.Visibility = Visibility.Visible
|
||||
End Sub,, True),
|
||||
AaOpacity(PanList, 1 - PanList.Opacity, 150, 30)
|
||||
}, "FrmOtherHelp Search Switch")
|
||||
Else
|
||||
'构造请求
|
||||
Dim QueryList As New List(Of SearchEntry(Of HelpEntry))
|
||||
@@ -163,15 +169,19 @@
|
||||
End If
|
||||
'显示
|
||||
AniStart({
|
||||
AaOpacity(PanList, -PanList.Opacity, 100),
|
||||
AaCode(Sub()
|
||||
PanList.Visibility = Visibility.Collapsed
|
||||
PanSearch.Visibility = Visibility.Visible
|
||||
PanSearch.TriggerForceResize()
|
||||
End Sub,, True),
|
||||
AaOpacity(PanSearch, 1 - PanSearch.Opacity, 150, 30)
|
||||
}, "FrmOtherHelp Search Switch")
|
||||
AaOpacity(PanList, -PanList.Opacity, 100),
|
||||
AaCode(
|
||||
Sub()
|
||||
PanList.Visibility = Visibility.Collapsed
|
||||
PanSearch.Visibility = Visibility.Visible
|
||||
PanSearch.TriggerForceResize()
|
||||
End Sub,, True),
|
||||
AaOpacity(PanSearch, 1 - PanSearch.Opacity, 150, 30)
|
||||
}, "FrmOtherHelp Search Switch")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Public Sub Refresh() Implements IRefreshable.Refresh
|
||||
PageOtherLeft.RefreshHelp()
|
||||
End Sub
|
||||
End Class
|
||||
@@ -1,6 +1,11 @@
|
||||
Public Class PageOtherHelpDetail
|
||||
Implements IRefreshable
|
||||
Public Entry As HelpEntry
|
||||
|
||||
Public Sub Refresh() Implements IRefreshable.Refresh
|
||||
Init(New HelpEntry(Entry.RawPath))
|
||||
End Sub
|
||||
|
||||
Private Sub PageOtherHelpDetail_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
PanBack.ScrollToTop()
|
||||
End Sub
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
LogoScale="0.98" Logo="M149.883623 873.911618c47.094581 47.094581 101.765247 83.95121 162.783444 109.75085 63.065787 26.618676 130.226755 40.337532 199.230553 40.337532 69.003799 0 136.164767-13.514097 199.230554-40.337532 61.018196-25.79964 115.688862-62.656269 162.783444-109.75085s83.95121-101.765247 109.75085-162.783444c26.618676-63.065787 40.337532-130.226755 40.337532-199.230554 0-69.003799-13.514097-136.164767-40.337532-199.230553-25.79964-61.018196-62.656269-115.688862-109.75085-162.783444-46.889822-46.889822-101.765247-83.95121-162.783444-109.75085C648.062388 13.514097 580.90142 0 511.89762 0s-136.164767 13.514097-199.230553 40.337532c-61.018196 25.79964-115.688862 62.656269-162.783444 109.75085s-83.95121 101.765247-109.75085 162.783444C13.514097 375.732853 0 442.893821 0 511.89762s13.514097 136.164767 40.337532 199.230554c25.594881 61.018196 62.656269 115.688862 109.546091 162.783444zM97.670066 511.89762c0-228.511098 185.921216-414.227554 414.227554-414.227554 228.511098 0 414.227554 185.921216 414.227555 414.227554S740.408718 926.125175 511.89762 926.125175c-228.511098 0-414.227554-185.716457-414.227554-414.227555z M539.130574 244.277544c-8.190362-4.709458-17.609278-7.371326-27.232954-7.371325-9.623675 0-19.042591 2.457109-27.232953 7.371325-16.790242 9.623675-27.232953 27.847231-27.232953 47.299341 0 30.09958 24.366327 54.465907 54.465906 54.465906 30.09958 0 54.465907-24.366327 54.465907-54.465906 0-19.45211-10.442711-37.470906-27.232953-47.299341zM566.363527 732.218356v-284.615077c0-30.09958-24.366327-54.465907-54.465907-54.465906-30.09958 0-54.465907 24.366327-54.465906 54.465906v284.615077c0 30.09958 24.366327 54.465907 54.465906 54.465907 30.09958 0 54.465907-24.366327 54.465907-54.465907z" />
|
||||
<local:MyListItem x:Name="ItemTest" IsScaleAnimationEnabled="False" Tag="2" MinPaddingRight="35" Type="RadioBox" Height="36" VerticalAlignment="Top" Title="百宝箱"
|
||||
LogoScale="0.97" Logo="M511.488 995.328a128.654222 128.654222 0 0 1-57.116444-13.112889L70.769778 791.808a126.833778 126.833778 0 0 1-70.769778-113.777778V311.608889a126.179556 126.179556 0 0 1 15.36-60.103111V248.604444c1.479111-2.901333 3.356444-5.603556 5.518222-8.021333a127.630222 127.630222 0 0 1 49.891556-42.325333L454.371556 13.368889a128.739556 128.739556 0 0 1 112.981333 0l383.601778 190.407111a126.862222 126.862222 0 0 1 72.049777 113.379556v360.874666a126.805333 126.805333 0 0 1-70.769777 115.939556L568.604444 984.32c-17.92 7.964444-37.461333 11.747556-57.116444 11.008z m42.638222-470.897778v370.204445l360.192-178.545778c14.449778-7.253333 23.552-21.987556 23.438222-38.087111v-335.928889L554.097778 524.430222zM85.248 330.666667v347.335111a42.268444 42.268444 0 0 0 23.438222 38.087111l360.192 178.545778V523.576889L85.248 330.666667zM135.537778 260.835556l375.950222 189.952 137.671111-65.564445L286.435556 188.074667 135.537778 260.864z m245.105778-118.471112l363.576888 197.973334 150.897778-71.480889-365.283555-180.224a42.922667 42.922667 0 0 0-37.518223 0l-111.672888 53.731555z" />
|
||||
<local:MyListItem x:Name="ItemFeedback" IsScaleAnimationEnabled="False" Type="Clickable" Tag="3" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="反馈"
|
||||
<local:MyListItem x:Name="ItemFeedback" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="3" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="反馈"
|
||||
LogoScale="0.9" Logo="M613.717333 64.426667l3.413334 3.242666 331.861333 331.861334a85.333333 85.333333 0 0 1 3.2 117.269333l-3.2 3.413333L573.162667 896H960a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H64a21.333333 21.333333 0 0 1-21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h295.338667L74.069333 610.709333a85.333333 85.333333 0 0 1-3.221333-117.269333l3.2-3.413333 422.4-422.357334a85.333333 85.333333 0 0 1 117.269333-3.221333z m-20.629333 99.882666l-21.418667 321.493334a85.333333 85.333333 0 0 1-74.944 79.04l-4.522666 0.426666-321.493334 21.44 295.552 295.530667 422.4-422.378667L593.066667 164.309333z m-86.442667 13.824L184.533333 500.266667l301.994667-20.117334 20.117333-301.994666z" />
|
||||
<local:MyListItem x:Name="ItemVote" IsScaleAnimationEnabled="False" Type="Clickable" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="新功能投票"
|
||||
<local:MyListItem x:Name="ItemVote" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="新功能投票"
|
||||
LogoScale="0.92" Logo="M979 1024H45c-24.9 0-45-20.1-45-45s20.1-45 45-45h934c24.9 0 45 20.1 45 45s-20.1 45-45 45zM135 887C60.6 887 0 826.4 0 752V334c0-74.4 60.6-135 135-135s135 60.6 135 135v418c0 74.4-60.6 135-135 135z m0-598c-24.8 0-45 20.2-45 45v418c0 24.8 20.2 45 45 45s45-20.2 45-45V334c0-24.8-20.2-45-45-45zM512 887c-74.4 0-135-60.6-135-135V532c0-74.4 60.6-135 135-135s135 60.6 135 135v220c0 74.4-60.6 135-135 135z m0-400c-24.8 0-45 20.2-45 45v220c0 24.8 20.2 45 45 45s45-20.2 45-45V532c0-24.8-20.2-45-45-45zM889 887c-74.4 0-135-60.6-135-135V135C754 60.6 814.6 0 889 0s135 60.6 135 135v617c0 74.4-60.6 135-135 135z m0-797c-24.8 0-45 20.2-45 45v617c0 24.8 20.2 45 45 45s45-20.2 45-45V135c0-24.8-20.2-45-45-45z" />
|
||||
</StackPanel>
|
||||
</local:MyPageLeft>
|
||||
@@ -83,7 +83,7 @@
|
||||
PageChangeRun(PageGet(ID))
|
||||
PageID = ID
|
||||
Catch ex As Exception
|
||||
Log(ex, "切换设置分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Log(ex, "切换分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Finally
|
||||
AniControlEnabled -= 1
|
||||
End Try
|
||||
@@ -125,19 +125,29 @@
|
||||
End Sub
|
||||
|
||||
'打开网页
|
||||
Public Shared Sub TryFeedback() Handles ItemFeedback.Click
|
||||
Private Sub TryFeedback(sender As Object, e As RouteEventArgs) Handles ItemFeedback.Changed
|
||||
If Not ItemFeedback.Checked Then Exit Sub
|
||||
TryFeedback()
|
||||
e.Handled = True
|
||||
End Sub
|
||||
Public Shared Sub TryFeedback()
|
||||
If Not CanFeedback(True) Then Exit Sub
|
||||
Select Case MyMsgBox("是否要打开反馈列表网页?" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
|
||||
"反馈提示", "提交新反馈", "查看反馈列表", "取消")
|
||||
Select Case MyMsgBox("在提交新反馈前,建议先搜索反馈列表,以避免重复提交。" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
|
||||
"反馈", "提交新反馈", "查看反馈列表", "取消")
|
||||
Case 1
|
||||
Feedback(True, False)
|
||||
Case 2
|
||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/issues/")
|
||||
End Select
|
||||
End Sub
|
||||
Public Shared Sub TryVote() Handles ItemVote.Click
|
||||
Private Sub TryVote(sender As Object, e As RouteEventArgs) Handles ItemVote.Changed
|
||||
If Not ItemVote.Checked Then Exit Sub
|
||||
TryVote()
|
||||
e.Handled = True
|
||||
End Sub
|
||||
Public Shared Sub TryVote()
|
||||
If MyMsgBox("是否要打开新功能投票网页?" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
|
||||
"提醒", "打开", "取消") = 2 Then Exit Sub
|
||||
"新功能投票", "打开", "取消") = 2 Then Exit Sub
|
||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8?discussions_q=category%3A%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8+sort%3Adate_created")
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
Public Shared Sub MemoryOptimize(ShowHint As Boolean)
|
||||
If ShowHint Then Hint("为便于维护,开源内容中不包含百宝箱功能……")
|
||||
End Sub
|
||||
Public Shared Sub MemoryOptimizeInternal()
|
||||
Public Shared Sub MemoryOptimizeInternal(ShowHint As Boolean)
|
||||
End Sub
|
||||
Public Shared Function GetRandomCave() As String
|
||||
Return "为便于维护,开源内容中不包含百宝箱功能……"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="5" />
|
||||
</Grid.RowDefinitions>
|
||||
<local:MyScrollViewer DeltaMuity="0.7" Grid.Row="1" MaxWidth="300" MinWidth="250" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Style="{StaticResource ScrollViewerFullMargin}">
|
||||
<local:MyScrollViewer DeltaMult="0.7" Grid.Row="1" MaxWidth="300" MinWidth="250" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Style="{StaticResource ScrollViewerFullMargin}">
|
||||
<StackPanel x:Name="PanList" />
|
||||
</local:MyScrollViewer>
|
||||
</Grid>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Public Class PageSelectLeft
|
||||
Implements IRefreshable
|
||||
|
||||
Private Sub PageSelectLeft_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
|
||||
AddHandler McFolderListLoader.PreviewFinish, Sub() If FrmSelectLeft IsNot Nothing Then RunInUiWait(AddressOf McFolderListUI)
|
||||
@@ -295,7 +296,7 @@
|
||||
For i = 0 To Folders.Count - 1
|
||||
If Folders(i) = "" Then Exit For
|
||||
If Folders(i).ToString.EndsWith(Folder.Path) Then
|
||||
Name = Folders(i).ToString.Before(">")
|
||||
Name = Folders(i).ToString.BeforeFirst(">")
|
||||
Folders.RemoveAt(i)
|
||||
Exit For
|
||||
End If
|
||||
@@ -347,8 +348,14 @@
|
||||
End Sub
|
||||
Public Sub Refresh_Click(sender As Object, e As RoutedEventArgs)
|
||||
Dim Data As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||
WriteIni(Data.Path & "PCL.ini", "VersionCache", "") '删除缓存以强制要求下一次加载时更新列表
|
||||
If Data.Path = PathMcFolder Then LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
RefreshCurrent(Data.Path)
|
||||
End Sub
|
||||
Public Sub RefreshCurrent() Implements IRefreshable.Refresh
|
||||
RefreshCurrent(PathMcFolder)
|
||||
End Sub
|
||||
Public Shared Sub RefreshCurrent(Folder As String)
|
||||
WriteIni(Folder & "PCL.ini", "VersionCache", "") '删除缓存以强制要求下一次加载时更新列表
|
||||
If Folder = PathMcFolder Then LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
End Sub
|
||||
Public Sub Rename_Click(sender As Object, e As RoutedEventArgs)
|
||||
Dim Folder As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||
|
||||
@@ -167,14 +167,16 @@
|
||||
ToolTipService.SetPlacement(BtnCont, Primitives.PlacementMode.Center)
|
||||
ToolTipService.SetVerticalOffset(BtnCont, 30)
|
||||
ToolTipService.SetHorizontalOffset(BtnCont, 2)
|
||||
AddHandler BtnCont.Click, Sub()
|
||||
PageVersionLeft.Version = Version
|
||||
FrmMain.PageChange(FormMain.PageType.VersionSetup, 0)
|
||||
End Sub
|
||||
AddHandler sender.MouseRightButtonUp, Sub()
|
||||
PageVersionLeft.Version = Version
|
||||
FrmMain.PageChange(FormMain.PageType.VersionSetup, 0)
|
||||
End Sub
|
||||
AddHandler BtnCont.Click,
|
||||
Sub()
|
||||
PageVersionLeft.Version = Version
|
||||
FrmMain.PageChange(FormMain.PageType.VersionSetup, 0)
|
||||
End Sub
|
||||
AddHandler sender.MouseRightButtonUp,
|
||||
Sub()
|
||||
PageVersionLeft.Version = Version
|
||||
FrmMain.PageChange(FormMain.PageType.VersionSetup, 0)
|
||||
End Sub
|
||||
sender.Buttons = {BtnStar, BtnDel, BtnCont}
|
||||
Else
|
||||
Dim BtnCont As New MyIconButton With {.LogoScale = 1.15, .Logo = Logo.IconButtonOpen}
|
||||
@@ -182,12 +184,8 @@
|
||||
ToolTipService.SetPlacement(BtnCont, Primitives.PlacementMode.Center)
|
||||
ToolTipService.SetVerticalOffset(BtnCont, 30)
|
||||
ToolTipService.SetHorizontalOffset(BtnCont, 2)
|
||||
AddHandler BtnCont.Click, Sub()
|
||||
PageVersionOverall.OpenVersionFolder(Version)
|
||||
End Sub
|
||||
AddHandler sender.MouseRightButtonUp, Sub()
|
||||
PageVersionOverall.OpenVersionFolder(Version)
|
||||
End Sub
|
||||
AddHandler BtnCont.Click, Sub() PageVersionOverall.OpenVersionFolder(Version)
|
||||
AddHandler sender.MouseRightButtonUp, Sub() PageVersionOverall.OpenVersionFolder(Version)
|
||||
sender.Buttons = {BtnStar, BtnDel, BtnCont}
|
||||
End If
|
||||
End Sub
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
''' </summary>
|
||||
Private ReadOnly SetupDict As New Dictionary(Of String, SetupEntry) From {
|
||||
{"Identify", New SetupEntry("", Source:=SetupSource.Registry)},
|
||||
{"WindowHeight", New SetupEntry(550)},
|
||||
{"WindowWidth", New SetupEntry(900)},
|
||||
{"HintDownloadThread", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||
{"HintNotice", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||
{"HintDownload", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||
@@ -42,6 +44,12 @@
|
||||
{"CacheMsProfileJson", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsV2Migrated", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||
{"CacheMsV2OAuthRefresh", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsV2Access", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsV2ProfileJson", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsV2Uuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheMsV2Name", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheNideAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheNideClient", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"CacheNideUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
|
||||
@@ -105,10 +113,10 @@
|
||||
{"ToolDownloadSpeed", New SetupEntry(42, Source:=SetupSource.Registry)},
|
||||
{"ToolDownloadVersion", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||
{"ToolDownloadTranslate", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||
{"ToolDownloadKeepModpack", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||
{"ToolDownloadIgnoreQuilt", New SetupEntry(True, Source:=SetupSource.Registry)},
|
||||
{"ToolDownloadCert", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||
{"ToolDownloadMod", New SetupEntry(1, Source:=SetupSource.Registry)},
|
||||
{"ToolModLocalNameStyle", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||
{"ToolUpdateAlpha", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
|
||||
{"ToolUpdateRelease", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||
{"ToolUpdateSnapshot", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||
@@ -145,6 +153,7 @@
|
||||
{"UiHiddenPageSetup", New SetupEntry(False)},
|
||||
{"UiHiddenPageOther", New SetupEntry(False)},
|
||||
{"UiHiddenFunctionSelect", New SetupEntry(False)},
|
||||
{"UiHiddenFunctionModUpdate", New SetupEntry(False)},
|
||||
{"UiHiddenFunctionHidden", New SetupEntry(False)},
|
||||
{"UiHiddenSetupLaunch", New SetupEntry(False)},
|
||||
{"UiHiddenSetupUi", New SetupEntry(False)},
|
||||
@@ -194,15 +203,19 @@
|
||||
|
||||
'加载状态:0/未读取 1/已读取未处理 2/已处理
|
||||
Public State As Byte = 0
|
||||
Public Type
|
||||
Public Type As Type
|
||||
|
||||
Public Sub New(Value, Optional Source = SetupSource.Normal, Optional Encoded = False)
|
||||
Me.DefaultValue = Value
|
||||
Me.DefaultValueEncoded = If(Encoded, SecretEncrypt(Value, "PCL" & UniqueAddress), Value)
|
||||
Me.Encoded = Encoded
|
||||
Me.Value = Value
|
||||
Me.Source = Source
|
||||
Type = If(Value, New Object).GetType
|
||||
Try
|
||||
Me.DefaultValue = Value
|
||||
Me.Encoded = Encoded
|
||||
Me.Value = Value
|
||||
Me.Source = Source
|
||||
Me.Type = If(Value, New Object).GetType
|
||||
Me.DefaultValueEncoded = If(Encoded, SecretEncrypt(Value, "PCL" & UniqueAddress), Value)
|
||||
Catch ex As Exception
|
||||
Log(ex, "初始化 SetupEntry 失败", LogLevel.Feedback) '#5095 的 fallback
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -304,6 +317,12 @@
|
||||
Dim E As SetupEntry = SetupDict(Key)
|
||||
[Set](Key, E.DefaultValue, E, ForceReload, Version)
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 获取某个设置项的默认值。
|
||||
''' </summary>
|
||||
Public Function GetDefault(Key As String) As String
|
||||
Return SetupDict(Key).DefaultValue
|
||||
End Function
|
||||
|
||||
Private Sub Read(Key As String, ByRef E As SetupEntry, Version As McVersion)
|
||||
Try
|
||||
@@ -592,7 +611,7 @@
|
||||
FrmSetupUI.PanLogoChange.Visibility = Visibility.Visible
|
||||
End If
|
||||
Try
|
||||
FrmMain.ImageTitleLogo.Source = New MyBitmap(Path & "PCL\Logo.png")
|
||||
FrmMain.ImageTitleLogo.Source = Path & "PCL\Logo.png"
|
||||
Catch ex As Exception
|
||||
FrmMain.ImageTitleLogo.Source = Nothing
|
||||
Log(ex, "显示标题栏图片失败", LogLevel.Msgbox)
|
||||
@@ -624,6 +643,9 @@
|
||||
Public Sub UiHiddenFunctionSelect(Value As Boolean)
|
||||
PageSetupUI.HiddenRefresh()
|
||||
End Sub
|
||||
Public Sub UiHiddenFunctionModUpdate(Value As Boolean)
|
||||
PageSetupUI.HiddenRefresh()
|
||||
End Sub
|
||||
Public Sub UiHiddenFunctionHidden(Value As Boolean)
|
||||
PageSetupUI.HiddenRefresh()
|
||||
End Sub
|
||||
|
||||
@@ -7,54 +7,7 @@
|
||||
PanScroll="{Binding ElementName=PanBack}">
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel x:Name="PanMain" Margin="25,10">
|
||||
<local:MyCard x:Name="CardSkin" Margin="0,15" Title="离线皮肤" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<local:MyHint Text="由于技术问题,此功能只保证对 1.19.2 以前的版本有效!" IsWarn="True" Margin="0,0,0,10" />
|
||||
<Grid Margin="-1,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyRadioBox Text="随机" x:Name="RadioSkinType0" Height="22" Tag="LaunchSkinType/0" Grid.Column="0" ToolTip="随机选择一个默认皮肤" />
|
||||
<local:MyRadioBox Text="Steve" x:Name="RadioSkinType1" Height="22" Tag="LaunchSkinType/1" Grid.Column="1" />
|
||||
<local:MyRadioBox Text="Alex" x:Name="RadioSkinType2" Height="22" Tag="LaunchSkinType/2" Grid.Column="2" />
|
||||
<local:MyRadioBox Text="正版皮肤" x:Name="RadioSkinType3" Height="22" Tag="LaunchSkinType/3" Grid.Column="3" ToolTip="使用某个正版玩家的皮肤" />
|
||||
<local:MyRadioBox Text="自定义" x:Name="RadioSkinType4" Height="22" Tag="LaunchSkinType/4" Grid.Column="4" ToolTip="以资源包的形式加载自定义皮肤。
使用此方式更换的皮肤在多人游戏中仅自己可见,且会替换游戏中所有的角色。" />
|
||||
</Grid>
|
||||
<Grid x:Name="PanSkinID" Margin="0,14,0,2" Visibility="Collapsed">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="正版玩家名" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextSkinID" Tag="LaunchSkinID" Grid.Column="1" MaxLength="50" />
|
||||
<Grid Height="35" Grid.Row="1" Grid.ColumnSpan="2" Margin="0,14,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnSkinSave" Text="保存皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Row="1" />
|
||||
<local:MyButton x:Name="BtnSkinCache" Text="刷新缓存" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新并重新下载 PCL 当前显示的皮肤" Grid.Row="1" Grid.Column="1" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid x:Name="PanSkinChange" Margin="0,14,0,2" Height="35" Visibility="Collapsed">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnSkinChange" Text="更改皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnSkinDelete" Text="重置皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ColorType="Red" Grid.Column="1" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard x:Name="CardArgument" Margin="0,0,0,15" Title="启动选项">
|
||||
<local:MyCard x:Name="CardArgument" Margin="0,15" Title="启动选项">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -217,10 +170,57 @@
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard x:Name="CardSkin" Margin="0,0,0,15" Title="离线皮肤" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<local:MyHint Text="由于技术问题,此功能只保证对 1.19.2 以前的版本有效!" IsWarn="True" Margin="0,0,0,10" />
|
||||
<Grid Margin="-1,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyRadioBox Text="随机" x:Name="RadioSkinType0" Height="22" Tag="LaunchSkinType/0" Grid.Column="0" ToolTip="随机选择一个默认皮肤" />
|
||||
<local:MyRadioBox Text="Steve" x:Name="RadioSkinType1" Height="22" Tag="LaunchSkinType/1" Grid.Column="1" />
|
||||
<local:MyRadioBox Text="Alex" x:Name="RadioSkinType2" Height="22" Tag="LaunchSkinType/2" Grid.Column="2" />
|
||||
<local:MyRadioBox Text="正版皮肤" x:Name="RadioSkinType3" Height="22" Tag="LaunchSkinType/3" Grid.Column="3" ToolTip="使用某个正版玩家的皮肤" />
|
||||
<local:MyRadioBox Text="自定义" x:Name="RadioSkinType4" Height="22" Tag="LaunchSkinType/4" Grid.Column="4" ToolTip="以资源包的形式加载自定义皮肤。
使用此方式更换的皮肤在多人游戏中仅自己可见,且会替换游戏中所有的角色。" />
|
||||
</Grid>
|
||||
<Grid x:Name="PanSkinID" Margin="0,14,0,2" Visibility="Collapsed">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="正版玩家名" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextSkinID" Tag="LaunchSkinID" Grid.Column="1" MaxLength="50" />
|
||||
<Grid Height="35" Grid.Row="1" Grid.ColumnSpan="2" Margin="0,14,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnSkinSave" Text="保存皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Row="1" />
|
||||
<local:MyButton x:Name="BtnSkinCache" Text="刷新缓存" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新并重新下载 PCL 当前显示的皮肤" Grid.Row="1" Grid.Column="1" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid x:Name="PanSkinChange" Margin="0,14,0,2" Height="35" Visibility="Collapsed">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnSkinChange" Text="更改皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnSkinDelete" Text="重置皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ColorType="Red" Grid.Column="1" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="高级启动选项" IsSwaped="True" CanSwap="True">
|
||||
<Grid Margin="25,40,25,15">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -232,14 +232,19 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<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"
|
||||
<StackPanel Grid.Row="0" VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,25,0">
|
||||
<TextBlock Text="JVM 参数头" VerticalAlignment="Center" />
|
||||
<local:MyIconButton Height="23" Margin="0,1,0,0" x:Name="BtnAdvanceJvmReset" VerticalAlignment="Center"
|
||||
ToolTip="还原" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1"
|
||||
Logo="M530 0c287 0 521 229 521 511s-233 511-521 511c-233 0-436-151-500-368a63 63 0 0 1 44-79 65 65 0 0 1 80 43c48 162 200 276 375 276 215 0 390-171 390-383s-174-383-390-383c-103 0-199 39-270 106l21-5a63 63 0 0 1 33 123l-157 42a65 65 0 0 1-90-42l-49-183a65 65 0 1 1 126-33l6 26A524 524 0 0 1 530 0z" LogoScale="0.9" />
|
||||
</StackPanel>
|
||||
<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" />
|
||||
<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 则会以试玩模式启动游戏。" />
|
||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动前执行命令" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextAdvanceRun" Grid.Row="4" Grid.ColumnSpan="2" Tag="LaunchAdvanceRun" Grid.Column="1" HintText=""
|
||||
ToolTip="在 MC 启动前执行特定命令或程序,语法与 Windows 的命令提示符一致。

可以使用以下替换标记实现相对路径(路径均以 \ 结尾):
 · {path}:PCL 的 exe 文件所在的文件夹
 · {minecraft}:.minecraft 文件夹
 · {verpath}:版本文件夹(.minecraft\versions\版本名\)
 · {verindie}:开启版本隔离时等同版本文件夹,未开启时等同 .minecraft 文件夹
 · {java}:游戏运行时的 Java 文件夹

除此之外,也支持以下替换标记:
 · {user}:玩家名字
 · {login}:玩家的登录方式
 · {uuid}:玩家的 UUID
 · {name}:游戏版本名
 · {date}、{time}:当前的系统时间
 · {version}:游戏对应的原版版本号

例如:
 · "{verpath}test.exe" :运行版本文件夹下的 test.exe 程序
 · "{java}java.exe" -jar "{verpath}test.jar" :用 Java 运行版本文件夹下的 test.jar
 · notepad "{verindie}option.txt" :使用记事本打开该版本的设置文件

涉及路径的操作最好都打上双引号,以避免路径中的空格导致运行失败。
执行命令时,命令行所在的目录是当前的 .minecraft 文件夹。" />
|
||||
ToolTip="在 MC 启动前执行特定命令或程序,语法与 Windows 的命令提示符一致。

可以使用以下替换标记实现相对路径(路径均以 \ 结尾):
 · {path}:PCL 的 exe 文件所在的文件夹
 · {minecraft}:.minecraft 文件夹
 · {verpath}:版本文件夹(.minecraft\versions\版本名\)
 · {verindie}:开启版本隔离时等同版本文件夹,未开启时等同 .minecraft 文件夹
 · {java}:游戏运行时的 Java 文件夹

除此之外,也支持以下替换标记:
 · {user}:玩家名字
 · {login}:玩家的登录方式
 · {uuid}:玩家的 UUID
 · {name}:游戏版本名
 · {date}、{time}:当前的系统时间
 · {version}:游戏对应的原版版本号

例如:
 · "{verpath}test.exe" :运行版本文件夹下的 test.exe 程序
 · "{java}java.exe" -jar "{verpath}test.jar" :用 Java 运行版本文件夹下的 test.jar
 · notepad "{verindie}options.txt" :使用记事本打开该版本的设置文件

涉及路径的操作最好都打上双引号,以避免路径中的空格导致运行失败。
执行命令时,命令行所在的目录是当前的 .minecraft 文件夹。" />
|
||||
<local:MyCheckBox Grid.Row="5" Grid.Column="1" x:Name="CheckAdvanceRunWait" Tag="LaunchAdvanceRunWait" Visibility="Collapsed"
|
||||
Text="等待命令执行完成后再继续启动" Margin="0,8,0,7" />
|
||||
<StackPanel Margin="0,12,0,4" Orientation="Horizontal" Grid.Row="6" Grid.ColumnSpan="2">
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
If(RamGame <> RamGameActual, " (可用 " & If(RamGameActual = Math.Floor(RamGameActual), RamGameActual & ".0", RamGameActual) & " GB)", "")
|
||||
LabRamUsed.Text = If(RamUsed = Math.Floor(RamUsed), RamUsed & ".0", RamUsed) & " GB"
|
||||
LabRamTotal.Text = " / " & If(RamTotal = Math.Floor(RamTotal), RamTotal & ".0", RamTotal) & " GB"
|
||||
LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaIs64Bit() AndAlso Not Is32BitSystem, Visibility.Visible, Visibility.Collapsed)
|
||||
LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaIs64Bit() AndAlso Not Is32BitSystem AndAlso JavaList.Any, Visibility.Visible, Visibility.Collapsed)
|
||||
If ShowAnim Then
|
||||
'宽度动画
|
||||
AniStart({
|
||||
@@ -551,15 +551,17 @@ PreFin:
|
||||
End Sub
|
||||
|
||||
'版本隔离警告
|
||||
Private IsReverting As Boolean = False
|
||||
Private Sub ComboArgumentIndie_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ComboArgumentIndie.SelectionChanged
|
||||
If AniControlEnabled <> 0 Then Exit Sub
|
||||
If IsReverting Then Exit Sub
|
||||
If MyMsgBox("调整版本隔离后,你可能得把游戏存档、Mod 等文件手动迁移到新的游戏文件夹中。" & vbCrLf &
|
||||
"如果修改后发现存档消失,把这项设置改回来就能恢复。" & vbCrLf &
|
||||
"如果你不会迁移存档,不建议修改这项设置!",
|
||||
"警告", "我知道我在做什么", "取消", IsWarn:=True) = 2 Then
|
||||
AniControlEnabled += 1
|
||||
IsReverting = True
|
||||
ComboArgumentIndie.SelectedItem = e.RemovedItems(0)
|
||||
AniControlEnabled -= 1
|
||||
IsReverting = False
|
||||
End If
|
||||
End Sub
|
||||
|
||||
@@ -571,6 +573,15 @@ PreFin:
|
||||
CheckAdvanceRunWait.Visibility = If(TextAdvanceRun.Text = "", Visibility.Collapsed, Visibility.Visible)
|
||||
End Sub
|
||||
|
||||
'JVM 参数重设
|
||||
Private Sub TextAdvanceJvm_TextChanged() Handles TextAdvanceJvm.ValidatedTextChanged
|
||||
BtnAdvanceJvmReset.Visibility = If(TextAdvanceJvm.Text = Setup.GetDefault("LaunchAdvanceJvm"), Visibility.Hidden, Visibility.Visible)
|
||||
End Sub
|
||||
Private Sub BtnAdvanceJvmReset_Click(sender As Object, e As EventArgs) Handles BtnAdvanceJvmReset.Click
|
||||
Setup.Reset("LaunchAdvanceJvm")
|
||||
Reload()
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
End Class
|
||||
@@ -115,7 +115,7 @@
|
||||
|
||||
PageID = ID
|
||||
Catch ex As Exception
|
||||
Log(ex, "切换设置分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Log(ex, "切换分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Finally
|
||||
AniControlEnabled -= 1
|
||||
End Try
|
||||
|
||||
@@ -7,9 +7,43 @@
|
||||
PanScroll="{Binding ElementName=PanBack}">
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel x:Name="PanMain" Margin="25,10">
|
||||
|
||||
<local:MyCard Margin="0,15" Title="下载">
|
||||
<StackPanel Margin="25,37,25,12">
|
||||
<StackPanel Margin="25,37,25,15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="7" />
|
||||
<RowDefinition Height="27" />
|
||||
<RowDefinition Height="27" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="版本列表源" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="ComboDownloadVersion" Grid.ColumnSpan="2" Tag="ToolDownloadVersion" Grid.Column="1">
|
||||
<local:MyComboBoxItem Content="尽量使用镜像源(加载快,但版本可能不是最新的)" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="仅在官方源加载缓慢时改用镜像源" />
|
||||
<local:MyComboBoxItem Content="尽量使用官方源(保证版本最新,但加载缓慢)" />
|
||||
</local:MyComboBox>
|
||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="最大线程数" Margin="0,0,25,0" />
|
||||
<local:MySlider x:Name="SliderDownloadThread" Grid.Row="2" Tag="ToolDownloadThread" MaxValue="255" Value="63" Grid.Column="1"
|
||||
ToolTip="线程数越多,限速的文件下载越快,但过高的线程数会造成下载时非常严重的卡顿。
一般而言,64 线程已可以保证足够的下载速度。" />
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="3" HorizontalAlignment="Left" Text="速度限制" Margin="0,0,25,0" />
|
||||
<local:MySlider x:Name="SliderDownloadSpeed" Grid.Row="3" Tag="ToolDownloadSpeed" MaxValue="42" Value="42" Grid.Column="1"
|
||||
ToolTip="设置下载的速度上限,以避免在下载时导致其他需要联网的程序卡死" />
|
||||
<TextBlock VerticalAlignment="Top" Grid.Row="4" HorizontalAlignment="Left" Text="目标文件夹" Margin="0,5,25,5" />
|
||||
<TextBlock Margin="0,5" HorizontalAlignment="Left" Text="请在 启动 → 版本选择 → 文件夹列表 中更改下载目标文件夹。
在某个文件夹或游戏版本上右键,即可选择打开对应文件夹。" Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Opacity="0.5" />
|
||||
<local:MyCheckBox Margin="0,2,0,4" Text="验证 SSL 证书" Grid.Row="5" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadCert" Tag="ToolDownloadCert"
|
||||
ToolTip="开启验证会提高安全性、降低盗号风险(见 #2767),但也可能导致正版登录失败(见 #3018)。" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="Mod 与整合包">
|
||||
<StackPanel Margin="25,37,25,15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
@@ -22,51 +56,30 @@
|
||||
<RowDefinition Height="7" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="7" />
|
||||
<RowDefinition Height="27" />
|
||||
<RowDefinition Height="27" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="版本列表获取" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="ComboDownloadVersion" Grid.ColumnSpan="2" Tag="ToolDownloadVersion" Grid.Column="1">
|
||||
<local:MyComboBoxItem Content="尽量使用镜像源(加载快,但版本可能不是最新的)" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="仅在官方源加载缓慢时改用镜像源" />
|
||||
<local:MyComboBoxItem Content="尽量使用官方源(保证版本最新,但加载缓慢)" />
|
||||
</local:MyComboBox>
|
||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Mod 信息获取" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="ComboDownloadMod" Grid.Row="2" Grid.ColumnSpan="2" Tag="ToolDownloadMod" Grid.Column="1">
|
||||
<local:MyComboBoxItem Content="尽量使用镜像源" />
|
||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="下载源" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="ComboDownloadMod" Grid.Row="0" Grid.ColumnSpan="2" Tag="ToolDownloadMod" Grid.Column="1">
|
||||
<local:MyComboBoxItem Content="尽量使用镜像源(暂时无效)" />
|
||||
<local:MyComboBoxItem Content="仅在官方源加载缓慢时改用镜像源" />
|
||||
<local:MyComboBoxItem Content="尽量使用官方源" IsSelected="True" />
|
||||
</local:MyComboBox>
|
||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Mod 命名风格" Margin="0,0,25,0" />
|
||||
<local:MyComboBox Grid.Row="4" x:Name="ComboDownloadTranslate" Grid.ColumnSpan="2" Tag="ToolDownloadTranslate" Grid.Column="1"
|
||||
ToolTip="决定下载的 Mod 的默认文件名中,中文译名应该放在哪个位置">
|
||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="下载文件名" Margin="0,0,25,0" />
|
||||
<local:MyComboBox Grid.Row="2" x:Name="ComboDownloadTranslate" Grid.ColumnSpan="2" Tag="ToolDownloadTranslate" Grid.Column="1"
|
||||
ToolTip="下载 Mod 时,Mod 的默认文件名中,中文译名应该放在哪个位置">
|
||||
<local:MyComboBoxItem Content="译名位于文件名开头:[遗物] relics-0.1.14" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="译名位于文件名开头:遗物-relics-0.1.14" />
|
||||
<local:MyComboBoxItem Content="译名位于文件名末尾:relics-0.1.14-遗物" />
|
||||
<local:MyComboBoxItem Content="不添加中文译名:relics-0.1.14" />
|
||||
</local:MyComboBox>
|
||||
<TextBlock Grid.Row="6" VerticalAlignment="Center" HorizontalAlignment="Left" Text="最大线程数" Margin="0,0,25,0" />
|
||||
<local:MySlider x:Name="SliderDownloadThread" Grid.Row="6" Tag="ToolDownloadThread" MaxValue="255" Value="63" Grid.Column="1"
|
||||
ToolTip="线程数越多,限速的文件下载越快,但过高的线程数会造成下载时非常严重的卡顿。
一般而言,64 线程已可以保证足够的下载速度。" />
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="7" HorizontalAlignment="Left" Text="速度限制" Margin="0,0,25,0" />
|
||||
<local:MySlider x:Name="SliderDownloadSpeed" Grid.Row="7" Tag="ToolDownloadSpeed" MaxValue="42" Value="42" Grid.Column="1"
|
||||
ToolTip="设置下载的速度上限,以避免在下载时导致其他需要联网的程序卡死" />
|
||||
<TextBlock VerticalAlignment="Top" Grid.Row="9" HorizontalAlignment="Left" Text="目标文件夹" Margin="0,5,25,5" />
|
||||
<TextBlock Margin="0,5" HorizontalAlignment="Left" Text="请在 启动 → 版本选择 → 文件夹列表 中更改下载目标文件夹。
在某个文件夹或游戏版本上右键,即可选择打开对应文件夹。" Grid.Row="9" Grid.Column="1" VerticalAlignment="Center" Opacity="0.5" />
|
||||
<local:MyCheckBox Margin="0,5,0,4" Text="安装整合包时保留原始压缩包" Grid.Row="10" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadKeepModpack" Tag="ToolDownloadKeepModpack"
|
||||
ToolTip="安装整合包时,在版本文件夹下保留用于安装的原始整合包压缩包文件" />
|
||||
<local:MyCheckBox Margin="0,2,0,4" Text="简化 Mod 加载器显示" Grid.Row="11" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadIgnoreQuilt" Tag="ToolDownloadIgnoreQuilt"
|
||||
ToolTip="下载 Mod 时,若该 Mod 支持 Forge 和 Fabric,则显示为支持任意 Mod 加载器。
例如,开启时 JEI 显示支持全版本,关闭后 JEI 就会显示仅支持 Forge / Fabric 全版本。" />
|
||||
<local:MyCheckBox Margin="0,2,0,4" Text="验证 SSL 证书" Grid.Row="12" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadCert" Tag="ToolDownloadCert"
|
||||
ToolTip="开启验证会提高安全性、降低盗号风险(见 #2767),但也可能导致正版登录失败(见 #3018)。" />
|
||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Mod 管理样式" Margin="0,0,25,0" />
|
||||
<local:MyComboBox Grid.Row="4" x:Name="ComboModLocalNameStyle" Grid.ColumnSpan="2" Tag="ToolModLocalNameStyle" Grid.Column="1"
|
||||
ToolTip="在 Mod 管理页面中,Mod 项的显示方式">
|
||||
<local:MyComboBoxItem Content="标题显示译名,详情显示文件名" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="标题显示文件名,详情显示译名" />
|
||||
</local:MyComboBox>
|
||||
<local:MyCheckBox Margin="0,2,0,4" Text="显示 Mod 加载器时忽略 Quilt" Grid.Row="6" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadIgnoreQuilt" Tag="ToolDownloadIgnoreQuilt" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -1,33 +1,5 @@
|
||||
Class PageSetupSystem
|
||||
|
||||
#Region "语言"
|
||||
'Private Sub PageSetupUI_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
' AniControlEnabled -= 1
|
||||
|
||||
' '读取设置
|
||||
' Select Case Lang
|
||||
' Case "zh_CN"
|
||||
' ComboLang.SelectedIndex = 0
|
||||
' Case "zh_HK"
|
||||
' ComboLang.SelectedIndex = 1
|
||||
' Case "en_US"
|
||||
' ComboLang.SelectedIndex = 2
|
||||
' End Select
|
||||
' CheckDebug.Checked = ReadReg("SystemDebugMode", "False")
|
||||
|
||||
' AniControlEnabled += 1
|
||||
'End Sub
|
||||
|
||||
'Private Sub RefreshLang() Handles ComboLang.SelectionChanged
|
||||
' If IsLoaded Then
|
||||
' If Not ComboLang.IsLoaded Then Exit Sub
|
||||
' Lang = CType(ComboLang.SelectedItem, MyComboBoxItem).Tag
|
||||
' Application.Current.Resources.MergedDictionaries(1) = New ResourceDictionary With {.Source = New Url("Languages\" & Lang & ".xaml", UrlKind.Relative)}
|
||||
' WriteReg("Lang", Lang)
|
||||
' End If
|
||||
'End Sub
|
||||
#End Region
|
||||
|
||||
Private Shadows IsLoaded As Boolean = False
|
||||
|
||||
Private Sub PageSetupSystem_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
@@ -58,11 +30,13 @@
|
||||
SliderDownloadThread.Value = Setup.Get("ToolDownloadThread")
|
||||
SliderDownloadSpeed.Value = Setup.Get("ToolDownloadSpeed")
|
||||
ComboDownloadVersion.SelectedIndex = Setup.Get("ToolDownloadVersion")
|
||||
CheckDownloadCert.Checked = Setup.Get("ToolDownloadCert")
|
||||
|
||||
'Mod 与整合包
|
||||
ComboDownloadTranslate.SelectedIndex = Setup.Get("ToolDownloadTranslate")
|
||||
ComboDownloadMod.SelectedIndex = Setup.Get("ToolDownloadMod")
|
||||
CheckDownloadKeepModpack.Checked = Setup.Get("ToolDownloadKeepModpack")
|
||||
ComboModLocalNameStyle.SelectedIndex = Setup.Get("ToolModLocalNameStyle")
|
||||
CheckDownloadIgnoreQuilt.Checked = Setup.Get("ToolDownloadIgnoreQuilt")
|
||||
CheckDownloadCert.Checked = Setup.Get("ToolDownloadCert")
|
||||
|
||||
'Minecraft 更新提示
|
||||
CheckUpdateRelease.Checked = Setup.Get("ToolUpdateRelease")
|
||||
@@ -91,10 +65,10 @@
|
||||
Setup.Reset("ToolDownloadSpeed")
|
||||
Setup.Reset("ToolDownloadVersion")
|
||||
Setup.Reset("ToolDownloadTranslate")
|
||||
Setup.Reset("ToolDownloadKeepModpack")
|
||||
Setup.Reset("ToolDownloadIgnoreQuilt")
|
||||
Setup.Reset("ToolDownloadCert")
|
||||
Setup.Reset("ToolDownloadMod")
|
||||
Setup.Reset("ToolModLocalNameStyle")
|
||||
Setup.Reset("ToolUpdateRelease")
|
||||
Setup.Reset("ToolUpdateSnapshot")
|
||||
Setup.Reset("ToolHelpChinese")
|
||||
@@ -116,13 +90,13 @@
|
||||
End Sub
|
||||
|
||||
'将控件改变路由到设置改变
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadKeepModpack.Change, CheckDownloadIgnoreQuilt.Change, CheckDownloadCert.Change
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadIgnoreQuilt.Change, CheckDownloadCert.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||
End Sub
|
||||
Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderDebugAnim.Change, SliderDownloadThread.Change, SliderDownloadSpeed.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Value)
|
||||
End Sub
|
||||
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboDownloadVersion.SelectionChanged, ComboDownloadTranslate.SelectionChanged, ComboSystemUpdate.SelectionChanged, ComboSystemActivity.SelectionChanged, ComboDownloadMod.SelectionChanged
|
||||
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboDownloadVersion.SelectionChanged, ComboModLocalNameStyle.SelectionChanged, ComboDownloadTranslate.SelectionChanged, ComboSystemUpdate.SelectionChanged, ComboSystemActivity.SelectionChanged, ComboDownloadMod.SelectionChanged
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
||||
End Sub
|
||||
Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextSystemCache.ValidatedTextChanged
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
</Grid>
|
||||
<local:MyCheckBox Text="打开启动器时显示 PCL 图标" Margin="-1,0,0,1" Height="22" x:Name="CheckLauncherLogo" Tag="UiLauncherLogo" />
|
||||
</StackPanel>
|
||||
<Border Background="#CCCCCCCC" Margin="-5,22,-5,-5" CornerRadius="4" Name="PanLauncherHide" Visibility="Collapsed">
|
||||
<Border Background="#DDDDDDDD" Margin="-8,23,-5,28" CornerRadius="4" Name="PanLauncherHide" Visibility="Collapsed">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock Text="需要小小赞助一下作者,才能修改主题颜色(悲)……" FontSize="15" Margin="0,2,0,0" />
|
||||
<local:MyButton Height="35" x:Name="BtnLauncherDonate" MinWidth="150" Text="支持作者" Padding="13,0" HorizontalAlignment="Center" Margin="0,9,0,0" ColorType="Highlight" />
|
||||
<TextBlock Text="如果可以小小赞助一下 PCL,就能解锁主题颜色更换功能啦……
多亏了大家的支持,PCL 才能在免费、无任何广告的情况下维持数年的更新(磕头)!" FontSize="13" Margin="0,0,0,0" />
|
||||
<local:MyButton Height="32" x:Name="BtnLauncherDonate" MinWidth="140" Text="支持 PCL 开发!" Padding="13,0" HorizontalAlignment="Center" Margin="0,9,0,0" ColorType="Highlight" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
@@ -225,6 +225,7 @@
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="下载地址" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextCustomNet" Tag="UiCustomNet" Grid.Column="1" MaxHeight="28">
|
||||
<local:MyTextBox.ValidateRules>
|
||||
<local:ValidateNullable />
|
||||
<local:ValidateHttp />
|
||||
</local:MyTextBox.ValidateRules>
|
||||
</local:MyTextBox>
|
||||
@@ -244,6 +245,10 @@
|
||||
<local:MyComboBoxItem Content="Minecraft 皮肤推荐(作者:wkea)" />
|
||||
<local:MyComboBoxItem Content="OpenBMCLAPI 仪表盘 Lite(作者:Silverteal、Mxmilu666)" />
|
||||
<local:MyComboBoxItem Content="PCL 主页市场(作者:凌云)" />
|
||||
<local:MyComboBoxItem Content="PCL 更新日志(作者:Joker2184)" />
|
||||
<local:MyComboBoxItem Content="PCL 新功能说明书(作者:WForst-Breeze)" />
|
||||
<local:MyComboBoxItem Content="OpenMCIM 仪表盘(作者:SALTWOOD)" />
|
||||
<local:MyComboBoxItem Content="杂志主页(作者:CreeperIsASpy)" />
|
||||
</local:MyComboBox>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
@@ -287,8 +292,9 @@
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="3" Grid.Column="6" Text="新功能投票" x:Name="CheckHiddenOtherVote" Tag="UiHiddenOtherVote" />
|
||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="特定功能" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="2" Text="邮箱隐藏" x:Name="CheckLauncherEmail" Tag="UiLauncherEmail" ToolTip="隐藏第三方登录的账号邮箱显示,并尽量将邮箱打码,以避免隐私泄露。
此选项的更改将在重启启动器后生效。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="3" Text="版本选择" x:Name="CheckHiddenFunctionSelect" Tag="UiHiddenFunctionSelect" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="4" Text="功能隐藏" x:Name="CheckHiddenFunctionHidden" Tag="UiHiddenFunctionHidden" ToolTip="仅隐藏本选项卡,设置的禁用内容依然有效。
可以在保留个性化设置页面的情况下避免隐藏设置被修改。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="3" Text="版本管理" x:Name="CheckHiddenFunctionSelect" Tag="UiHiddenFunctionSelect" ToolTip="隐藏启动按钮下方的版本选择与版本设置入口。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="4" Text="Mod 更新" x:Name="CheckHiddenFunctionModUpdate" Tag="UiHiddenFunctionModUpdate" ToolTip="禁止在 Mod 管理页面更新 Mod。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="5" Text="功能隐藏" x:Name="CheckHiddenFunctionHidden" Tag="UiHiddenFunctionHidden" ToolTip="仅隐藏本选项卡,设置的禁用内容依然有效。
可以在保留个性化设置页面的情况下避免隐藏设置被修改。" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -25,14 +25,15 @@
|
||||
Next
|
||||
End If
|
||||
|
||||
AniControlEnabled += 1
|
||||
Reload() '#4826,在每次进入页面时都刷新一下
|
||||
AniControlEnabled -= 1
|
||||
|
||||
'非重复加载部分
|
||||
If IsLoaded Then Exit Sub
|
||||
IsLoaded = True
|
||||
|
||||
AniControlEnabled += 1
|
||||
SliderLoad()
|
||||
Reload()
|
||||
AniControlEnabled -= 1
|
||||
|
||||
#If BETA Then
|
||||
PanLauncherHide.Visibility = Visibility.Visible
|
||||
@@ -97,6 +98,7 @@
|
||||
CheckHiddenPageSetup.Checked = Setup.Get("UiHiddenPageSetup")
|
||||
CheckHiddenPageOther.Checked = Setup.Get("UiHiddenPageOther")
|
||||
CheckHiddenFunctionSelect.Checked = Setup.Get("UiHiddenFunctionSelect")
|
||||
CheckHiddenFunctionModUpdate.Checked = Setup.Get("UiHiddenFunctionModUpdate")
|
||||
CheckHiddenFunctionHidden.Checked = Setup.Get("UiHiddenFunctionHidden")
|
||||
CheckHiddenSetupLaunch.Checked = Setup.Get("UiHiddenSetupLaunch")
|
||||
CheckHiddenSetupUI.Checked = Setup.Get("UiHiddenSetupUi")
|
||||
@@ -147,6 +149,7 @@
|
||||
Setup.Reset("UiHiddenPageSetup")
|
||||
Setup.Reset("UiHiddenPageOther")
|
||||
Setup.Reset("UiHiddenFunctionSelect")
|
||||
Setup.Reset("UiHiddenFunctionModUpdate")
|
||||
Setup.Reset("UiHiddenFunctionHidden")
|
||||
Setup.Reset("UiHiddenSetupLaunch")
|
||||
Setup.Reset("UiHiddenSetupUi")
|
||||
@@ -174,7 +177,7 @@
|
||||
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboBackgroundSuit.SelectionChanged, ComboCustomPreset.SelectionChanged
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
||||
End Sub
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckMusicStop.Change, CheckMusicRandom.Change, CheckMusicAuto.Change, CheckBackgroundColorful.Change, CheckLogoLeft.Change, CheckLauncherLogo.Change, CheckHiddenFunctionHidden.Change, CheckHiddenFunctionSelect.Change, CheckHiddenPageDownload.Change, CheckHiddenPageLink.Change, CheckHiddenPageOther.Change, CheckHiddenPageSetup.Change, CheckHiddenSetupLaunch.Change, CheckHiddenSetupSystem.Change, CheckHiddenSetupLink.Change, CheckHiddenSetupUI.Change, CheckHiddenOtherAbout.Change, CheckHiddenOtherFeedback.Change, CheckHiddenOtherVote.Change, CheckHiddenOtherHelp.Change, CheckHiddenOtherTest.Change, CheckMusicStart.Change, CheckLauncherEmail.Change
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckMusicStop.Change, CheckMusicRandom.Change, CheckMusicAuto.Change, CheckBackgroundColorful.Change, CheckLogoLeft.Change, CheckLauncherLogo.Change, CheckHiddenFunctionHidden.Change, CheckHiddenFunctionSelect.Change, CheckHiddenFunctionModUpdate.Change, CheckHiddenPageDownload.Change, CheckHiddenPageLink.Change, CheckHiddenPageOther.Change, CheckHiddenPageSetup.Change, CheckHiddenSetupLaunch.Change, CheckHiddenSetupSystem.Change, CheckHiddenSetupLink.Change, CheckHiddenSetupUI.Change, CheckHiddenOtherAbout.Change, CheckHiddenOtherFeedback.Change, CheckHiddenOtherVote.Change, CheckHiddenOtherHelp.Change, CheckHiddenOtherTest.Change, CheckMusicStart.Change, CheckLauncherEmail.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||
End Sub
|
||||
Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextLogoText.ValidatedTextChanged, TextCustomNet.ValidatedTextChanged
|
||||
@@ -269,17 +272,16 @@
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
|
||||
'顶部栏
|
||||
Private Sub BtnLogoChange_Click(sender As Object, e As EventArgs) Handles BtnLogoChange.Click
|
||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif", "选择图片")
|
||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif;*.webp)|*.png;*.jpg;*.gif;*.webp", "选择图片")
|
||||
If FileName = "" Then Exit Sub
|
||||
Try
|
||||
'拷贝文件
|
||||
File.Delete(Path & "PCL\Logo.png")
|
||||
CopyFile(FileName, Path & "PCL\Logo.png")
|
||||
'设置当前显示
|
||||
FrmMain.ImageTitleLogo.Source = New MyBitmap(Path & "PCL\Logo.png")
|
||||
FrmMain.ImageTitleLogo.Source = Path & "PCL\Logo.png"
|
||||
Catch ex As Exception
|
||||
If ex.Message.Contains("参数无效") Then
|
||||
Log("改变标题栏图片失败,该图片文件可能并非标准格式。" & vbCrLf &
|
||||
@@ -296,7 +298,7 @@ Refresh:
|
||||
'已有图片则不再选择
|
||||
If File.Exists(Path & "PCL\Logo.png") Then
|
||||
Try
|
||||
FrmMain.ImageTitleLogo.Source = New MyBitmap(Path & "PCL\Logo.png")
|
||||
FrmMain.ImageTitleLogo.Source = Path & "PCL\Logo.png"
|
||||
Catch ex As Exception
|
||||
If ex.Message.Contains("参数无效") Then
|
||||
Log("调整标题栏图片失败,该图片文件可能并非标准格式。" & vbCrLf &
|
||||
@@ -315,7 +317,7 @@ Refresh:
|
||||
Exit Sub
|
||||
End If
|
||||
'没有图片则要求选择
|
||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif", "选择图片")
|
||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif;*.webp)|*.png;*.jpg;*.gif;*.webp", "选择图片")
|
||||
If FileName = "" Then
|
||||
FrmMain.ImageTitleLogo.Source = Nothing
|
||||
e.Handled = True
|
||||
@@ -428,8 +430,8 @@ Refresh:
|
||||
RadioLauncherTheme5Gray.Opacity -= 0.23
|
||||
RadioLauncherTheme5.Opacity += 0.23
|
||||
AniStart({
|
||||
AaOpacity(RadioLauncherTheme5Gray, 1, 1000),
|
||||
AaOpacity(RadioLauncherTheme5, -1, 1000)
|
||||
AaOpacity(RadioLauncherTheme5Gray, 1, 1000 * AniSpeed),
|
||||
AaOpacity(RadioLauncherTheme5, -1, 1000 * AniSpeed)
|
||||
}, "ThemeUnlock")
|
||||
If RadioLauncherTheme5Gray.Opacity < 0.08 Then
|
||||
ThemeUnlock(5, UnlockHint:="隐藏主题 玄素黑 已解锁!")
|
||||
@@ -450,10 +452,10 @@ Refresh:
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
Private Sub LabLauncherTheme8Copy_MouseRightButtonUp() Handles LabLauncherTheme8Copy.MouseRightButtonUp
|
||||
Private Sub LabLauncherTheme8Copy_MouseRightButtonUp() Handles LabLauncherTheme8Copy.MouseRightButtonUp, RadioLauncherTheme8.MouseRightButtonUp
|
||||
OpenWebsite("https://afdian.com/a/LTCat")
|
||||
End Sub
|
||||
Private Sub LabLauncherTheme9Copy_MouseRightButtonUp() Handles LabLauncherTheme9Copy.MouseRightButtonUp
|
||||
Private Sub LabLauncherTheme9Copy_MouseRightButtonUp() Handles LabLauncherTheme9Copy.MouseRightButtonUp, RadioLauncherTheme9.MouseRightButtonUp
|
||||
PageOtherLeft.TryFeedback()
|
||||
End Sub
|
||||
|
||||
@@ -673,24 +675,26 @@ Refresh:
|
||||
SliderLauncherOpacity.GetHintText = Function(v) Math.Round(40 + v * 0.1) & "%"
|
||||
SliderLauncherHue.GetHintText = Function(v) v & "°"
|
||||
SliderLauncherSat.GetHintText = Function(v) v & "%"
|
||||
SliderLauncherDelta.GetHintText = Function(Value As Integer)
|
||||
If Value > 90 Then
|
||||
Return "+" & (Value - 90)
|
||||
ElseIf Value = 90 Then
|
||||
Return 0
|
||||
Else
|
||||
Return Value - 90
|
||||
End If
|
||||
End Function
|
||||
SliderLauncherLight.GetHintText = Function(Value As Integer)
|
||||
If Value > 20 Then
|
||||
Return "+" & (Value - 20)
|
||||
ElseIf Value = 20 Then
|
||||
Return 0
|
||||
Else
|
||||
Return Value - 20
|
||||
End If
|
||||
End Function
|
||||
SliderLauncherDelta.GetHintText =
|
||||
Function(Value As Integer)
|
||||
If Value > 90 Then
|
||||
Return "+" & (Value - 90)
|
||||
ElseIf Value = 90 Then
|
||||
Return 0
|
||||
Else
|
||||
Return Value - 90
|
||||
End If
|
||||
End Function
|
||||
SliderLauncherLight.GetHintText =
|
||||
Function(Value As Integer)
|
||||
If Value > 20 Then
|
||||
Return "+" & (Value - 20)
|
||||
ElseIf Value = 20 Then
|
||||
Return 0
|
||||
Else
|
||||
Return Value - 20
|
||||
End If
|
||||
End Function
|
||||
SliderBackgroundOpacity.GetHintText = Function(v) Math.Round(v * 0.1) & "%"
|
||||
SliderBackgroundBlur.GetHintText = Function(v) v & " 像素"
|
||||
End Sub
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
PageChangeRun(PageGet(ID))
|
||||
PageID = ID
|
||||
Catch ex As Exception
|
||||
Log(ex, "切换设置分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Log(ex, "切换分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Finally
|
||||
AniControlEnabled -= 1
|
||||
End Try
|
||||
@@ -88,17 +88,7 @@
|
||||
#End Region
|
||||
|
||||
Public Sub Refresh(sender As Object, e As EventArgs) '由边栏按钮匿名调用
|
||||
'强制刷新
|
||||
Try
|
||||
CompProjectCache.Clear()
|
||||
File.Delete(PathTemp & "Cache\LocalMod.json")
|
||||
Log("[Mod] 由于点击刷新按钮,清理本地 Mod 信息缓存")
|
||||
Catch ex As Exception
|
||||
Log(ex, "强制刷新时清理本地 Mod 信息缓存失败")
|
||||
End Try
|
||||
If FrmVersionMod IsNot Nothing Then FrmVersionMod.ReloadModList(True) '无需 Else,还没加载刷个鬼的新
|
||||
ItemMod.Checked = True
|
||||
Hint("正在刷新……", Log:=False)
|
||||
PageVersionMod.Refresh()
|
||||
End Sub
|
||||
|
||||
Public Sub Reset(sender As Object, e As EventArgs)
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnManageOpen" Grid.Column="0" MinWidth="140" Text="打开 Mod 文件夹" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||
<local:MyButton x:Name="BtnManageSelectAll" Grid.Column="1" MinWidth="140" Text="全选" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnManageInstall" Grid.Column="2" MinWidth="140" Text="安装 Mod" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnManageCheck" Grid.Column="3" MinWidth="140" Text="检查 Mod" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ToolTip="快速检查 Mod 的版本要求、重复、前置缺失等问题。
结果仅供参考,由于部分 Mod 标注的信息有误,可能并不准确。" Visibility="Collapsed" />
|
||||
<local:MyButton x:Name="BtnManageOpen" Grid.Column="0" MinWidth="110" Text="打开文件夹" Padding="13,0" Margin="0,0,15,0" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||
<local:MyButton x:Name="BtnManageInstall" Grid.Column="1" MinWidth="110" Text="从文件安装" Padding="13,0" Margin="0,0,15,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnManageDownload" Grid.Column="2" MinWidth="110" Text="下载新 Mod" Padding="13,0" Margin="0,0,15,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnManageSelectAll" Grid.Column="3" MinWidth="110" Text="全选" Padding="13,0" Margin="0,0,15,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnManageCheck" Grid.Column="4" MinWidth="110" Text="检查 Mod" Padding="13,0" Margin="0,0,15,0" HorizontalAlignment="Left" ToolTip="快速检查 Mod 的版本要求、重复、前置缺失等问题。
结果仅供参考,由于部分 Mod 标注的信息有误,可能并不准确。" Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
<local:MyCard x:Name="PanListBack" VerticalAlignment="Top" Opacity="0" Margin="0,0,0,14" Title=" " MinHeight="55">
|
||||
@@ -37,10 +39,19 @@
|
||||
</local:MyScrollViewer>
|
||||
<local:MyCard HorizontalAlignment="Center" VerticalAlignment="Center" Margin="40" x:Name="PanEmpty">
|
||||
<StackPanel Margin="20,17">
|
||||
<TextBlock Margin="0,0,0,9" HorizontalAlignment="Center" Text="未找到 Mod" FontSize="19" UseLayoutRounding="True" SnapsToDevicePixels="True" Foreground="{DynamicResource ColorBrush3}" />
|
||||
<TextBlock Margin="0,0,0,9" HorizontalAlignment="Center" Text="尚未安装 Mod" FontSize="19" UseLayoutRounding="True" SnapsToDevicePixels="True" Foreground="{DynamicResource ColorBrush3}" />
|
||||
<Rectangle HorizontalAlignment="Stretch" Height="2" Fill="{DynamicResource ColorBrush3}" />
|
||||
<TextBlock Margin="10,15,10,0" Text="要安装 Mod,请直接将 Mod 文件拖入 PCL 窗口。
如果你确定你已经安装了 Mod,但仍然看到了这条提示,则是版本隔离设置有误,请在启动设置中调整版本隔离选项。" TextWrapping="Wrap" />
|
||||
<local:MyButton Height="35" HorizontalAlignment="Center" x:Name="BtnHintOpen" MinWidth="140" Text="打开 Mod 文件夹" Margin="0,15,0,0" Padding="13,0" ColorType="Highlight" />
|
||||
<TextBlock Margin="10,10,10,0" Text="你可以下载新的 Mod,或者从已经下载好的文件安装 Mod。
如果你已经安装了 Mod,可能是版本隔离设置有误,请在设置中调整版本隔离选项。" TextWrapping="Wrap" />
|
||||
<Grid Margin="15,20,0,5" Height="35" HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton Height="35" HorizontalAlignment="Center" Grid.Column="0" x:Name="BtnHintDownload" MinWidth="140" Text="下载 Mod" Margin="0,0,17,0" Padding="13,0" ColorType="Highlight" />
|
||||
<local:MyButton Height="35" HorizontalAlignment="Center" Grid.Column="1" x:Name="BtnHintInstall" MinWidth="140" Text="从文件安装 Mod" Margin="0,0,17,0" Padding="13,0" />
|
||||
<local:MyButton Height="35" HorizontalAlignment="Center" Grid.Column="2" x:Name="BtnHintOpen" MinWidth="140" Text="打开 Mod 文件夹" Margin="0,0,17,0" Padding="13,0" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
</Grid>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Public Class PageVersionMod
|
||||
Implements IRefreshable
|
||||
|
||||
#Region "初始化"
|
||||
|
||||
@@ -30,22 +31,43 @@
|
||||
''' 刷新 Mod 列表。
|
||||
''' </summary>
|
||||
Public Sub ReloadModList(Optional ForceReload As Boolean = False)
|
||||
If LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", If(ForceReload, LoaderFolderRunType.ForceRun, LoaderFolderRunType.RunOnUpdated)) Then
|
||||
If LoaderRun(If(ForceReload, LoaderFolderRunType.ForceRun, LoaderFolderRunType.RunOnUpdated)) Then
|
||||
Log("[System] 已刷新 Mod 列表")
|
||||
Filter = FilterType.All
|
||||
PanBack.ScrollToHome()
|
||||
SearchBox.Text = ""
|
||||
End If
|
||||
End Sub
|
||||
'强制刷新
|
||||
Private Sub RefreshSelf() Implements IRefreshable.Refresh
|
||||
Refresh()
|
||||
End Sub
|
||||
Public Shared Sub Refresh()
|
||||
'强制刷新
|
||||
Try
|
||||
CompProjectCache.Clear()
|
||||
CompFilesCache.Clear()
|
||||
File.Delete(PathTemp & "Cache\LocalMod.json")
|
||||
Log("[Mod] 由于点击刷新按钮,清理本地 Mod 信息缓存")
|
||||
Catch ex As Exception
|
||||
Log(ex, "强制刷新时清理本地 Mod 信息缓存失败")
|
||||
End Try
|
||||
If FrmVersionMod IsNot Nothing Then FrmVersionMod.ReloadModList(True) '无需 Else,还没加载刷个鬼的新
|
||||
FrmVersionLeft.ItemMod.Checked = True
|
||||
Hint("正在刷新……", Log:=False)
|
||||
End Sub
|
||||
|
||||
Private Sub LoaderInit() Handles Me.Initialized
|
||||
PageLoaderInit(Load, PanLoad, PanAllBack, Nothing, McModLoader, AddressOf LoadUIFromLoaderOutput, AutoRun:=False)
|
||||
End Sub
|
||||
Private Sub Load_Click(sender As Object, e As MouseButtonEventArgs) Handles Load.Click
|
||||
If McModLoader.State = LoadState.Failed Then
|
||||
LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", LoaderFolderRunType.ForceRun)
|
||||
LoaderRun(LoaderFolderRunType.ForceRun)
|
||||
End If
|
||||
End Sub
|
||||
Public Function LoaderRun(Type As LoaderFolderRunType) As Boolean
|
||||
Return LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", Type)
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -133,13 +155,13 @@
|
||||
''' </summary>
|
||||
Public Sub RefreshUI()
|
||||
If PanList Is Nothing Then Exit Sub
|
||||
Dim ShowMods = GetShowingMods(True).ToList()
|
||||
Dim ShowingMods = If(IsSearching, SearchResult, If(McModLoader.Output, New List(Of McMod))).Where(Function(m) CanPassFilter(m)).ToList
|
||||
'重新列出列表
|
||||
AniControlEnabled += 1
|
||||
If ShowMods.Any() Then
|
||||
If ShowingMods.Any() Then
|
||||
PanList.Visibility = Visibility.Visible
|
||||
PanList.Children.Clear()
|
||||
For Each TargetMod In ShowMods
|
||||
For Each TargetMod In ShowingMods
|
||||
Dim Item As MyLocalModItem = ModItems(TargetMod.RawFileName)
|
||||
Item.Checked = SelectedMods.Contains(TargetMod.RawFileName) '更新选中状态
|
||||
PanList.Children.Add(Item)
|
||||
@@ -148,7 +170,7 @@
|
||||
PanList.Visibility = Visibility.Collapsed
|
||||
End If
|
||||
AniControlEnabled -= 1
|
||||
SelectedMods = SelectedMods.Where(Function(m) ShowMods.Any(Function(s) s.RawFileName = m)).ToList '取消选中已经不显示的 Mod
|
||||
SelectedMods = SelectedMods.Where(Function(m) ShowingMods.Any(Function(s) s.RawFileName = m)).ToList '取消选中已经不显示的 Mod
|
||||
RefreshBars()
|
||||
End Sub
|
||||
|
||||
@@ -166,7 +188,7 @@
|
||||
Dim DisabledCount As Integer = 0
|
||||
Dim UpdateCount As Integer = 0
|
||||
Dim UnavalialeCount As Integer = 0
|
||||
For Each ModItem In GetShowingMods(False)
|
||||
For Each ModItem In If(IsSearching, SearchResult, If(McModLoader.Output, New List(Of McMod)))
|
||||
AnyCount += 1
|
||||
If ModItem.CanUpdate Then UpdateCount += 1
|
||||
If ModItem.State.Equals(McMod.McModState.Fine) Then EnabledCount += 1
|
||||
@@ -295,14 +317,71 @@
|
||||
''' 全选。
|
||||
''' </summary>
|
||||
Private Sub BtnManageSelectAll_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageSelectAll.Click
|
||||
ChangeAllSelected(SelectedMods.Count < GetShowingMods(True).Count)
|
||||
ChangeAllSelected(SelectedMods.Count < PanList.Children.Count)
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 安装 Mod。
|
||||
''' </summary>
|
||||
Private Sub BtnManageInstall_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageInstall.Click
|
||||
Hint("将 Mod 文件直接拖入 PCL 窗口即可安装!")
|
||||
Private Sub BtnManageInstall_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageInstall.Click, BtnHintInstall.Click
|
||||
Dim FileList = SelectFiles("Mod 文件(*.jar;*.litemod;*.disabled;*.old)|*.jar;*.litemod;*.disabled;*.old", "选择要安装的 Mod")
|
||||
If Not FileList.Any Then Return
|
||||
InstallMods(FileList)
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 尝试安装 Mod。
|
||||
''' 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。
|
||||
''' </summary>
|
||||
Public Shared Function InstallMods(FilePathList As IEnumerable(Of String)) As Boolean
|
||||
Dim Extension As String = FilePathList.First.AfterLast(".").ToLower
|
||||
'检查文件扩展名
|
||||
If Not {"jar", "litemod", "disabled", "old"}.Any(Function(t) t = Extension) Then Return False
|
||||
Log("[System] 文件为 jar/litemod 格式,尝试作为 Mod 安装")
|
||||
'检查回收站:回收站中的文件有错误的文件名
|
||||
If FilePathList.First.Contains(":\$RECYCLE.BIN\") Then
|
||||
Hint("请先将文件从回收站还原,再尝试安装!", HintType.Critical)
|
||||
Return True
|
||||
End If
|
||||
'获取并检查目标版本
|
||||
Dim TargetVersion As McVersion = McVersionCurrent
|
||||
If FrmMain.PageCurrent = FormMain.PageType.VersionSetup Then TargetVersion = PageVersionLeft.Version
|
||||
If FrmMain.PageCurrent = FormMain.PageType.VersionSelect OrElse TargetVersion Is Nothing OrElse Not TargetVersion.Modable Then
|
||||
'正在选择版本,或当前版本不能安装 Mod
|
||||
Hint("若要安装 Mod,请先选择一个可以安装 Mod 的版本!")
|
||||
ElseIf Not (FrmMain.PageCurrent = FormMain.PageType.VersionSetup AndAlso FrmMain.PageCurrentSub = FormMain.PageSubType.VersionMod) Then
|
||||
'未处于 Mod 管理页面
|
||||
If MyMsgBox($"是否要将这{If(FilePathList.Count = 1, "个", "些")}文件作为 Mod 安装到 {TargetVersion.Name}?", "Mod 安装确认", "确定", "取消") = 1 Then GoTo Install
|
||||
Else
|
||||
'处于 Mod 管理页面
|
||||
Install:
|
||||
Try
|
||||
For Each ModFile In FilePathList
|
||||
Dim NewFileName = GetFileNameFromPath(ModFile).Replace(".disabled", "")
|
||||
If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
|
||||
CopyFile(ModFile, TargetVersion.PathIndie & "mods\" & NewFileName)
|
||||
Next
|
||||
If FilePathList.Count = 1 Then
|
||||
Hint($"已安装 {GetFileNameFromPath(FilePathList.First).Replace(".disabled", "")}!", HintType.Finish)
|
||||
Else
|
||||
Hint($"已安装 {FilePathList.Count} 个 Mod!", HintType.Finish)
|
||||
End If
|
||||
'刷新列表
|
||||
If FrmMain.PageCurrent = FormMain.PageType.VersionSetup AndAlso FrmMain.PageCurrentSub = FormMain.PageSubType.VersionMod Then
|
||||
LoaderFolderRun(McModLoader, TargetVersion.PathIndie & "mods\", LoaderFolderRunType.ForceRun)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "复制 Mod 文件失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End If
|
||||
Return True
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 下载 Mod。
|
||||
''' </summary>
|
||||
Private Sub BtnManageDownload_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageDownload.Click, BtnHintDownload.Click
|
||||
PageDownloadMod.TargetVersion = PageVersionLeft.Version '将当前版本设置为筛选器
|
||||
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadMod)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -329,9 +408,11 @@
|
||||
Private Sub ChangeAllSelected(Value As Boolean)
|
||||
AniControlEnabled += 1
|
||||
SelectedMods.Clear()
|
||||
For Each Item As MyLocalModItem In GetShowingMods(True).Select(Function(m) ModItems(m.RawFileName))
|
||||
Item.Checked = Value
|
||||
If Value Then SelectedMods.Add(Item.Entry.RawFileName)
|
||||
For Each Item As MyLocalModItem In ModItems.Values
|
||||
'#4992,Mod 从过滤器看可能不应在列表中,但因为刚切换状态所以依然保留在列表中,所以应该从列表 UI 判断,而非从过滤器判断
|
||||
Dim ShouldSelected As Boolean = Value AndAlso PanList.Children.Contains(Item)
|
||||
Item.Checked = ShouldSelected
|
||||
If ShouldSelected Then SelectedMods.Add(Item.Entry.RawFileName)
|
||||
Next
|
||||
AniControlEnabled -= 1
|
||||
RefreshBars()
|
||||
@@ -381,14 +462,6 @@
|
||||
Unavailable = 4
|
||||
End Enum
|
||||
|
||||
''' <summary>
|
||||
''' 获取所有应该显示在 UI 中的 Mod。
|
||||
''' </summary>
|
||||
Private Function GetShowingMods(ApplyFilter As Boolean) As IEnumerable(Of McMod)
|
||||
If McModLoader.Output Is Nothing Then Return New List(Of McMod)
|
||||
Return If(IsSearching, SearchResult, McModLoader.Output).Where(Function(m) Not ApplyFilter OrElse CanPassFilter(m))
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 检查该 Mod 项是否符合当前筛选的类别。
|
||||
''' </summary>
|
||||
@@ -467,9 +540,16 @@
|
||||
'更改 Loader 中的列表
|
||||
Dim NewModEntity As New McMod(NewPath)
|
||||
NewModEntity.FromJson(ModEntity.ToJson)
|
||||
Dim IndexOfLoader As Integer = McModLoader.Output.IndexOf(ModEntity)
|
||||
McModLoader.Output.RemoveAt(IndexOfLoader)
|
||||
McModLoader.Output.Insert(IndexOfLoader, NewModEntity)
|
||||
If McModLoader.Output.Contains(ModEntity) Then
|
||||
Dim IndexOfLoader As Integer = McModLoader.Output.IndexOf(ModEntity)
|
||||
McModLoader.Output.RemoveAt(IndexOfLoader)
|
||||
McModLoader.Output.Insert(IndexOfLoader, NewModEntity)
|
||||
End If
|
||||
If SearchResult IsNot Nothing AndAlso SearchResult.Contains(ModEntity) Then '#4862
|
||||
Dim IndexOfResult As Integer = SearchResult.IndexOf(ModEntity)
|
||||
SearchResult.Remove(ModEntity)
|
||||
SearchResult.Insert(IndexOfResult, NewModEntity)
|
||||
End If
|
||||
'更改 UI 中的列表
|
||||
Dim NewItem As MyLocalModItem = McModListItem(NewModEntity)
|
||||
ModItems(ModEntity.RawFileName) = NewItem
|
||||
@@ -484,6 +564,7 @@
|
||||
Hint("由于文件被占用,Mod 的状态切换失败,请尝试关闭正在运行的游戏后再试!", HintType.Critical)
|
||||
ReloadModList(True)
|
||||
End If
|
||||
LoaderRun(LoaderFolderRunType.UpdateOnly)
|
||||
End Sub
|
||||
|
||||
'更新
|
||||
@@ -499,8 +580,8 @@
|
||||
Public Shared UpdatingVersions As New List(Of String)
|
||||
Public Sub UpdateMods(ModList As IEnumerable(Of McMod))
|
||||
'更新前警告
|
||||
If Not Setup.Get("HintUpdateMod") Then
|
||||
If MyMsgBox($"新版本 Mod 可能不兼容老版本的存档或者其他 Mod,这可能导致游戏崩溃,甚至存档损坏!{vbCrLf}除非整合包作者要求你更新,否则不要私自更新整合包里的 Mod!{vbCrLf}在更新 Mod 前,请先备份存档,并检查它的更新日志!{vbCrLf}更新时,老版本的 Mod 会被移动到回收站,以防万一。{vbCrLf}{vbCrLf}请在认真阅读上述警告后再继续!", "Mod 更新警告", "我已了解上述风险,继续更新", "取消", IsWarn:=True) = 1 Then
|
||||
If Not Setup.Get("HintUpdateMod") OrElse ModList.Count >= 15 Then
|
||||
If MyMsgBox($"新版本 Mod 可能不兼容旧存档或者其他 Mod,这可能导致游戏崩溃,甚至永久损坏存档!{vbCrLf}如果你在游玩整合包,请千万不要自行更新 Mod!{vbCrLf}{vbCrLf}在更新前,请先备份存档,并检查 Mod 的更新日志。{vbCrLf}如果更新后出现问题,你也可以在回收站找回更新前的 Mod。", "Mod 更新警告", "我已了解风险,继续更新", "取消", IsWarn:=True) = 1 Then
|
||||
Setup.Set("HintUpdateMod", True)
|
||||
Else
|
||||
Exit Sub
|
||||
@@ -574,7 +655,14 @@
|
||||
'结果提示
|
||||
Select Case Loader.State
|
||||
Case LoadState.Finished
|
||||
Hint(If(FinishedFileNames.Count > 1, $"已成功更新 {FinishedFileNames.Count} 个 Mod!", $"已成功更新:{FinishedFileNames.Single}"), HintType.Finish)
|
||||
Select Case FinishedFileNames.Count
|
||||
Case 0 '一般是由于 Mod 文件被占用,然后玩家主动取消
|
||||
Log($"[Mod] 没有 Mod 被成功更新")
|
||||
Case 1
|
||||
Hint($"已成功更新 {FinishedFileNames.Single}!", HintType.Finish)
|
||||
Case Else
|
||||
Hint($"已成功更新 {FinishedFileNames.Count} 个 Mod!", HintType.Finish)
|
||||
End Select
|
||||
Case LoadState.Failed
|
||||
Hint("Mod 更新失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
|
||||
Case LoadState.Aborted
|
||||
@@ -684,6 +772,7 @@
|
||||
Log(ex, "删除 Mod 出现未知错误", LogLevel.Feedback)
|
||||
ReloadModList(True)
|
||||
End Try
|
||||
LoaderRun(LoaderFolderRunType.UpdateOnly)
|
||||
End Sub
|
||||
|
||||
'取消选择
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="VersionAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。
若留空,则使用全局设置的值。" HintText="使用全局设置" />
|
||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动前执行命令" Margin="0,0,25,3" />
|
||||
<local:MyTextBox x:Name="TextAdvanceRun" Grid.Row="4" Grid.ColumnSpan="2" Tag="VersionAdvanceRun" Grid.Column="1" HintText="" Margin="0,0,0,3"
|
||||
ToolTip="该项不会覆盖全局设置:启动时会先执行全局设置的命令,再执行版本设置的命令。

在 MC 启动前执行特定命令或程序,语法与 Windows 的命令提示符一致。

可以使用以下替换标记实现相对路径(路径均以 \ 结尾):
 · {path}:PCL 的 exe 文件所在的文件夹
 · {minecraft}:.minecraft 文件夹
 · {verpath}:版本文件夹(.minecraft\versions\版本名\)
 · {verindie}:开启版本隔离时等同版本文件夹,未开启时等同 .minecraft 文件夹
 · {java}:游戏运行时的 Java 文件夹

除此之外,也支持以下替换标记:
 · {user}:玩家名字
 · {login}:玩家的登录方式
 · {uuid}:玩家的 UUID
 · {name}:游戏版本名
 · {date}、{time}:当前的系统时间
 · {version}:游戏对应的原版版本号

例如:
 · "{verpath}test.exe" :运行版本文件夹下的 test.exe 程序
 · "{java}java.exe" -jar "{verpath}test.jar" :用 Java 运行版本文件夹下的 test.jar
 · notepad "{verindie}option.txt" :使用记事本打开该版本的设置文件

涉及路径的操作最好都打上双引号,以避免路径中的空格导致运行失败。
执行命令时,命令行所在的目录是当前的 .minecraft 文件夹。" />
|
||||
ToolTip="该项不会覆盖全局设置:启动时会先执行全局设置的命令,再执行版本设置的命令。

在 MC 启动前执行特定命令或程序,语法与 Windows 的命令提示符一致。

可以使用以下替换标记实现相对路径(路径均以 \ 结尾):
 · {path}:PCL 的 exe 文件所在的文件夹
 · {minecraft}:.minecraft 文件夹
 · {verpath}:版本文件夹(.minecraft\versions\版本名\)
 · {verindie}:开启版本隔离时等同版本文件夹,未开启时等同 .minecraft 文件夹
 · {java}:游戏运行时的 Java 文件夹

除此之外,也支持以下替换标记:
 · {user}:玩家名字
 · {login}:玩家的登录方式
 · {uuid}:玩家的 UUID
 · {name}:游戏版本名
 · {date}、{time}:当前的系统时间
 · {version}:游戏对应的原版版本号

例如:
 · "{verpath}test.exe" :运行版本文件夹下的 test.exe 程序
 · "{java}java.exe" -jar "{verpath}test.jar" :用 Java 运行版本文件夹下的 test.jar
 · notepad "{verindie}options.txt" :使用记事本打开该版本的设置文件

涉及路径的操作最好都打上双引号,以避免路径中的空格导致运行失败。
执行命令时,命令行所在的目录是当前的 .minecraft 文件夹。" />
|
||||
<local:MyCheckBox Grid.Row="5" Grid.Column="1" x:Name="CheckAdvanceRunWait" Tag="VersionAdvanceRunWait" Visibility="Collapsed"
|
||||
Text="等待命令执行完成后再继续启动" Margin="0,5,0,0" />
|
||||
<StackPanel Margin="0,10,0,0" Orientation="Horizontal" Grid.Row="6" Grid.ColumnSpan="2">
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
If(RamGame <> RamGameActual, " (可用 " & If(RamGameActual = Math.Floor(RamGameActual), RamGameActual & ".0", RamGameActual) & " GB)", "")
|
||||
LabRamUsed.Text = If(RamUsed = Math.Floor(RamUsed), RamUsed & ".0", RamUsed) & " GB"
|
||||
LabRamTotal.Text = " / " & If(RamTotal = Math.Floor(RamTotal), RamTotal & ".0", RamTotal) & " GB"
|
||||
LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaIs64Bit(PageVersionLeft.Version) AndAlso Not Is32BitSystem, Visibility.Visible, Visibility.Collapsed)
|
||||
LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaIs64Bit(PageVersionLeft.Version) AndAlso Not Is32BitSystem AndAlso JavaList.Any, Visibility.Visible, Visibility.Collapsed)
|
||||
If ShowAnim Then
|
||||
'宽度动画
|
||||
AniStart({
|
||||
@@ -488,15 +488,17 @@ PreFin:
|
||||
#Region "其他设置"
|
||||
|
||||
'版本隔离警告
|
||||
Private IsReverting As Boolean = False
|
||||
Private Sub ComboArgumentIndie_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ComboArgumentIndie.SelectionChanged
|
||||
If AniControlEnabled <> 0 Then Exit Sub
|
||||
If IsReverting Then Exit Sub
|
||||
If MyMsgBox("调整版本隔离后,你可能得把游戏存档、Mod 等文件手动迁移到新的游戏文件夹中。" & vbCrLf &
|
||||
"如果修改后发现存档消失,把这项设置改回来就能恢复。" & vbCrLf &
|
||||
"如果你不会迁移存档,不建议修改这项设置!",
|
||||
"警告", "我知道我在做什么", "取消", IsWarn:=True) = 2 Then
|
||||
AniControlEnabled += 1
|
||||
IsReverting = True
|
||||
ComboArgumentIndie.SelectedItem = e.RemovedItems(0)
|
||||
AniControlEnabled -= 1
|
||||
IsReverting = False
|
||||
End If
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
<Compile Include="Controls\MyComboBox.vb" />
|
||||
<Compile Include="Controls\MyComboBoxItem.vb" />
|
||||
<Compile Include="Controls\MyCard.vb" />
|
||||
<Compile Include="Controls\MyImage.vb" />
|
||||
<Compile Include="Controls\MyPageRight.vb" />
|
||||
<Compile Include="Controls\MyPageLeft.vb" />
|
||||
<Compile Include="Controls\MyIconTextButton.xaml.vb">
|
||||
@@ -256,9 +257,6 @@
|
||||
<Compile Include="Pages\PageDownload\PageDownloadPack.xaml.vb">
|
||||
<DependentUpon>PageDownloadPack.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\PageLaunch\FormLoginOAuth.xaml.vb">
|
||||
<DependentUpon>FormLoginOAuth.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\PageLaunch\MyMsgLogin.xaml.vb">
|
||||
<DependentUpon>MyMsgLogin.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -514,10 +512,6 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\PageLaunch\FormLoginOAuth.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\PageLaunch\MyMsgLogin.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
||||
@@ -4,311 +4,309 @@
|
||||
你也可以使用 Ctrl + F 快速查找。例如,若需要改变文本颜色,则搜索 “颜色” 即可。 -->
|
||||
|
||||
<local:MyCard Title="纯文本" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="每个 local:MyCard 代表一张卡片,你可以添加、删除格式类似的 MyCard 来添加多个卡片。每个 TextBlock 代表一段文本,你可以在 Text 属性中书写任何你想写的内容,也可以自行添加更多的 TextBlock。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4" FontSize="11"
|
||||
Text="你可以通过添加、删除属性修改样式,例如上一行的 FontSize 就会将字号改为 11 号。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="20,5,20,0" Foreground="#8C7721"
|
||||
Text="它还有许多可以调整的属性:上一行的 Margin 调整了边距,Foreground 则会让文字变色。" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="卡片、提示条" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<local:MyHint Text="local:MyHint 代表提示条,它默认是警告样式。" />
|
||||
<local:MyHint Margin="0,8,0,2" IsWarn="False"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<local:MyHint Text="local:MyHint 代表提示条,它默认是警告样式。" />
|
||||
<local:MyHint Margin="0,8,0,2" IsWarn="False"
|
||||
Text="将提示条的 IsWarn 属性改为 False 即可改为提示样式。
使用左边的那堆字符可以在任意地方手动换行,如果需要使用等号、引号等特殊字符,可以自行百度 XAML 转义字符。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,6,0,0"
|
||||
Text="卡片(local:MyCard)的 Title 属性决定了它的标题。
为卡片添加 CanSwap 属性让它可以被折叠,True 代表是,False 代表否。在此基础上,再使用 IsSwaped 属性调整它是否默认被折叠。" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="长宽属性、图片" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4" Width="320" HorizontalAlignment="Right"
|
||||
Text="任意项目都可以添加 Width 与 Height 属性来控制宽高。HorizontalAlignment 属性可以控制对齐:Center 代表居中,Right 代表居右,例如这段文本就被居右了。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,6"
|
||||
Text="Image 代表图片,你需要在它的 Source 属性中填写一个网址或文件路径,它会从该处获取图片并显示。通常需要使用 Height 限制它的高度。" />
|
||||
<Image Height="50" HorizontalAlignment="Center" Source="https://zh.minecraft.wiki/images/Grass_Block_JE7_BE6.png?bf67e" />
|
||||
</StackPanel>
|
||||
Text="local:MyImage 代表图片,你需要在它的 Source 属性中填写一个网址或文件路径,它会从该处获取图片并显示。通常需要使用 Height 限制它的高度。" />
|
||||
<local:MyImage Height="50" HorizontalAlignment="Center" Source="https://www.baidu.com/img/flexible/logo/pc/result.png" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="按钮" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="添加 local:MyButton 即可新建一个按钮。你需要限定它的尺寸与位置,并通过 Padding 属性进一步控制它的内边距。" />
|
||||
<local:MyButton Margin="0,4,0,10" Height="35" HorizontalAlignment="Left" Padding="25,0,25,0"
|
||||
<local:MyButton Margin="0,4,0,10" Height="35" HorizontalAlignment="Left" Padding="25,0,25,0"
|
||||
Text="这是一个按钮!一个按钮!" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="你可以修改 ColorType 属性来调整按钮配色:Highlight 代表当前主题色,Red 代表红色。ToolTip 属性还可以让你在鼠标悬浮在上面的时候显示提示文本。" />
|
||||
<local:MyButton Margin="0,4,0,10" Width="250" Height="35" ColorType="Highlight"
|
||||
<local:MyButton Margin="0,4,0,10" Width="250" Height="35" ColorType="Highlight"
|
||||
Text="把鼠标停在这里别动……" ToolTip="……就能看到这句话!" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="local:MyTextButton 是没有边框的 “纯文本按钮”,其作用与 local:MyButton 一致。" />
|
||||
<local:MyTextButton Margin="0,8,0,10" HorizontalAlignment="Center"
|
||||
<local:MyTextButton Margin="0,8,0,10" HorizontalAlignment="Center"
|
||||
Text="一个精简版的文本按钮" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="按钮可以做到很多事,具体将在 “事件” 部分介绍。" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="事件 1:打开网页、弹出窗口" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
Text="将按钮的 EventType 属性设为 打开网页,然后在 EventData 属性中写入网址,即可通过点击按钮打开网页。" />
|
||||
<local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
<local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
Text="打开 Minecraft Wiki" EventType="打开网页" EventData="https://zh.minecraft.wiki/" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,10,0,10"
|
||||
Text="或者将 EventType 属性改为 弹出窗口,然后在 EventData 属性中写入弹窗的标题与内容……" />
|
||||
<local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
<local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
Text="显示一个弹窗" EventType="弹出窗口" EventData="这是标题|标题与内容以竖线间隔。\n你也可以直接在其中换行。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,10,0,0"
|
||||
Text="local:MyTextButton 同样可以设置 EventType 与 EventData 让它具有特定功能。" />
|
||||
<local:MyTextButton Margin="0,8,0,0" HorizontalAlignment="Center"
|
||||
<local:MyTextButton Margin="0,8,0,0" HorizontalAlignment="Center"
|
||||
Text="点击打开知乎" EventType="打开网页" EventData="https://www.zhihu.com/" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="事件 2:启动游戏" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="将 EventType 设置为 启动游戏,EventData 设置为具体的游戏版本,即可通过点击按钮启动游戏。如果当前游戏文件夹没有该版本,则无法启动。" />
|
||||
<local:MyButton Margin="0,4,0,10" Width="250" Height="35"
|
||||
<local:MyButton Margin="0,4,0,10" Width="250" Height="35"
|
||||
Text="启动 Minecraft 1.12.2" EventType="启动游戏" EventData="1.12.2" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="在 EventData 后面添加一条竖线(|),竖线后填写服务器 IP,即可在启动该版本的同时自动进入服务器。" />
|
||||
<local:MyButton Margin="0,4,0,0" Width="250" Height="35"
|
||||
<local:MyButton Margin="0,4,0,0" Width="250" Height="35"
|
||||
Text="启动 1.20.1 并进入 Hypixel" EventType="启动游戏" EventData="1.20.1|mc.hypixel.net" ToolTip="服务器 IP:mc.hypixel.net" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="在 EventData 中填写 \current,表示启动当前被选中的游戏版本,同样可以在后面填写服务器 IP。" />
|
||||
<local:MyButton Margin="0,4,0,10" Width="250" Height="35"
|
||||
<local:MyButton Margin="0,4,0,10" Width="250" Height="35"
|
||||
Text="启动当前选中版本并进入 Hypixel" EventType="启动游戏" EventData="\current|mc.hypixel.net" ToolTip="启动当前版本" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="事件 3:打开文件" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="将 EventType 设置为 打开文件,EventData 设置为文件路径,即可点击打开特定文件或启动程序。" />
|
||||
<local:MyButton Margin="0,4,0,8" Width="200" Height="35"
|
||||
<local:MyButton Margin="0,4,0,8" Width="200" Height="35"
|
||||
Text="打开记事本" EventType="打开文件" EventData="notepad.exe" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,4,0,0"
|
||||
Text="如果能在 PCL 文件夹中找到该文件,则会优先打开 PCL 文件夹中的文件。当然,你可以使用例如 C:\ 开头的绝对路径。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="此外,PCL 会将文件中的 “花括号 path” 替换为 PCL 可执行文件所在文件夹({path}),可以用于执行特定程序或加载图片。" />
|
||||
<local:MyButton Margin="0,4,0,10" Width="200" Height="35"
|
||||
<local:MyButton Margin="0,4,0,10" Width="200" Height="35"
|
||||
Text="打开 PCL 日志" EventType="打开文件" EventData="Log1.txt" ToolTip="PCL 的日志文件就在 PCL 文件夹内,且名为 Log1.txt" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="就像为游戏指定服务器 IP 一样,你也可以在 EventData 的竖线后为程序添加启动参数。" />
|
||||
<local:MyButton Margin="0,4,0,0" Width="200" Height="35"
|
||||
<local:MyButton Margin="0,4,0,0" Width="200" Height="35"
|
||||
Text="定位游戏启动脚本" EventType="打开文件" EventData="explorer.exe|/select,LatestLaunch.bat" ToolTip="PCL 会将上一次启动 MC 的脚本保存在 PCL 文件夹内,且名为 LatestLaunch.bat。
点击按钮会打开文件管理器,并且借助参数要求它选中这个文件。" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="事件 4:其他事件类型" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock Margin="0,4,0,6" FontWeight="Bold"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock Margin="0,4,0,6" FontWeight="Bold"
|
||||
Text="EventType 共有以下种类:" />
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 打开网页、启动游戏、打开文件:已在上方的卡片中介绍" />
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
Text="查看 PCL 源代码" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2/blob/main/Plain%20Craft%20Launcher%202/FormMain.xaml.vb"/>
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 今日人品、清理垃圾、内存优化、安装整合包:触发对应功能" />
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 复制文本:将 EventData 中的内容复制到剪贴板" />
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 刷新主页:点击重新加载主页。如果主页文件为联网更新,这会重新下载主页内容" />
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 下载文件:在点击时要求选择文件保存位置,并且下载 EventData 的链接中的文件" />
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 下载文件:在点击时要求选择文件保存位置,并且下载 EventData 的链接中的文件
 EventData 中也能可选地指定文件名或目标文件夹,格式为:链接|文件名|文件夹" />
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
Text="下载百度的 Logo" EventType="下载文件" EventData="https://www.baidu.com/img/flexible/logo/pc/result.png" />
|
||||
<TextBlock Margin="0,4,0,4"
|
||||
<TextBlock Margin="0,4,0,4"
|
||||
Text="· 打开帮助:跳转到 EventData 对应的帮助文件(输入相对 Help 文件夹的路径)"/>
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
Text="打开自定义帮助页面" EventType="打开帮助" EventData="帮助/自定义帮助.json"/>
|
||||
<TextBlock Margin="0,4,0,4"
|
||||
Text="· 切换页面:强制切换到 PCL 的某一页面(尝试切换到不太对头的页面会出现不可预知的 Bug,使用时请谨慎)
 EventData 为 页面种类|次要页面种类(PageType|PageSubType,例如 1|1)
 点击上方的 查看 PCL 源代码 按钮,在 1000 行左右的位置即可查找到对应数值"/>
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
<TextBlock Margin="0,4,0,4"
|
||||
Text="· 切换页面:强制切换到 PCL 的某一页面(尝试切换到不太对头的页面会出现不可预知的 Bug)
 EventData 为 页面种类|次要页面种类(PageType|PageSubType,例如 1|1)
 点击上方的 查看 PCL 源代码 按钮,在 1000 行左右的位置即可查找到对应数值"/>
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
Text="切换到下载页面" EventType="切换页面" EventData="1|1"/>
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
Text="切换到启动器设置" EventType="切换页面" EventData="3|2"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="StackPanel 横向布局" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
Text="你需要使用 StackPanel 在一行里塞下多个按钮。你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
|
||||
<!-- 这是第一行 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0" ColorType="Highlight"
|
||||
<!-- 这是第一行 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0" ColorType="Highlight"
|
||||
Text="打开 B 站" EventType="打开网页" EventData="https://www.bilibili.com/" />
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
Text="进入 Hypixel" EventType="启动游戏" EventData="1.16.3|mc.hypixel.net" ToolTip="使用 Minecraft 1.16.3 进入 Hypixel" />
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
Text="打开记事本" EventType="打开文件" EventData="notepad" />
|
||||
</StackPanel>
|
||||
<!-- 这是第二行 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10,0,0">
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0" ColorType="Red"
|
||||
</StackPanel>
|
||||
<!-- 这是第二行 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10,0,0">
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0" ColorType="Red"
|
||||
Text="复制召唤命令" EventType="复制文本" EventData="/execute as @a at @s run summon Creeper ~ ~2 ~" ToolTip="这条 Minecraft 命令会在每个玩家头顶召唤一只苦力怕!" />
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
Text="内存优化" EventType="内存优化" />
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
<local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
|
||||
Text="下载百度的 Logo" EventType="下载文件" EventData="https://www.baidu.com/img/flexible/logo/pc/result.png" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="列表项 1:基础" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="你也可以使用列表项 “local:MyListItem” 来替代按钮,其使用方式与按钮类似。" />
|
||||
<local:MyListItem Margin="-5,2,-5,8"
|
||||
Logo="https://www.baidu.com/favicon.ico" Title="百度" Info="百度一下,你就知道!"
|
||||
EventType="打开网页" EventData="https://www.baidu.com/" Type="Clickable" />
|
||||
<local:MyListItem Margin="-5,2,-5,8"
|
||||
Logo="https://www.baidu.com/favicon.ico" Title="百度" Info="百度一下,你就知道!"
|
||||
EventType="打开网页" EventData="https://www.baidu.com/" Type="Clickable" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="Logo 属性为列表项的图标,指定的可以是链接也可以是文件路径;Title 是大标题,Info 是可选的小标题(详细信息);Type 如果省略,该列表项则单纯只展示信息,仅当 Type 为 Clickable 才能触发点击效果。"/>
|
||||
<local:MyListItem Margin="-5,2,-5,8"
|
||||
<local:MyListItem Margin="-5,2,-5,8"
|
||||
Logo="pack://application:,,,/images/Blocks/Grass.png"
|
||||
EventType="打开帮助" EventData="帮助/自定义帮助.json" Type="Clickable" />
|
||||
EventType="打开帮助" EventData="帮助/自定义帮助.json" Type="Clickable" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="EventType、EventData 与按钮几乎一致,唯一不同的是,列表项不支持联网加载帮助文件。" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="列表项 2:内置图片" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="PCL 内置了一些 Minecraft 方块与物品图片,可以直接使用。"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="10,8,0,15" Height="30">
|
||||
<!-- 命令方块 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/CommandBlock.png"/>
|
||||
<!-- 圆石 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Cobblestone.png"/>
|
||||
<!-- 金块 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/GoldBlock.png"/>
|
||||
<!-- 草方块 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Grass.png"/>
|
||||
<!-- 草径 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/GrassPath.png"/>
|
||||
<!-- 铁砧 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Anvil.png"/>
|
||||
<!-- 红石块 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneBlock.png"/>
|
||||
<!-- 红石灯(亮) -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneLampOn.png"/>
|
||||
<!-- 红石灯(灭) -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneLampOff.png"/>
|
||||
<!-- 鸡蛋 -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Egg.png"/>
|
||||
<!-- 布料(Fabric 图标) -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Fabric.png"/>
|
||||
<!-- 狐狸(NeoForge 图标) -->
|
||||
<Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/NeoForge.png"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="10,8,0,15" Height="30">
|
||||
<!-- 命令方块 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/CommandBlock.png"/>
|
||||
<!-- 圆石 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Cobblestone.png"/>
|
||||
<!-- 金块 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/GoldBlock.png"/>
|
||||
<!-- 草方块 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Grass.png"/>
|
||||
<!-- 草径 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/GrassPath.png"/>
|
||||
<!-- 铁砧 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Anvil.png"/>
|
||||
<!-- 红石块 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneBlock.png"/>
|
||||
<!-- 红石灯(亮) -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneLampOn.png"/>
|
||||
<!-- 红石灯(灭) -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneLampOff.png"/>
|
||||
<!-- 鸡蛋 -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Egg.png"/>
|
||||
<!-- 布料(Fabric 图标) -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Fabric.png"/>
|
||||
<!-- 狐狸(NeoForge 图标) -->
|
||||
<local:MyImage Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/NeoForge.png"/>
|
||||
</StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="使用时,将上方对应行的 Source 复制到 MyListItem 的 Logo 属性处即可。"/>
|
||||
<local:MyListItem Margin="-5,0,-5,8"
|
||||
<local:MyListItem Margin="-5,0,-5,8"
|
||||
Logo="pack://application:,,,/images/Blocks/CommandBlock.png"
|
||||
Title="清理垃圾" Info="使用内置的命令方块图片作为 Logo" EventType="清理垃圾" Type="Clickable" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="主题色" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,15"
|
||||
Text="你可以用类似 {DynamicResource ColorBrush5} 的格式使用 PCL 当前的主题颜色,修改末尾的数字编号以改变颜色浓度。" />
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="8,4">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="8,4">
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 1 " Margin="5,0" Background="{DynamicResource ColorBrush1}" Foreground="#FFFFFF" />
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 2 " Margin="5,0" Background="{DynamicResource ColorBrush2}" Foreground="#FFFFFF" />
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 3 " Margin="5,0" Background="{DynamicResource ColorBrush3}" Foreground="#FFFFFF" />
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 4 " Margin="5,0" Background="{DynamicResource ColorBrush4}" Foreground="#FFFFFF" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="8,4">
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="8,4">
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 5 " Margin="5,0" Background="{DynamicResource ColorBrush5}" />
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 6 " Margin="5,0" Background="{DynamicResource ColorBrush6}" />
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 7 " Margin="5,0" Background="{DynamicResource ColorBrush7}" />
|
||||
<TextBlock TextWrapping="Wrap" Text=" 浓度 8 " Margin="5,0" Background="{DynamicResource ColorBrush8}" />
|
||||
</StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,15,0,8" Foreground="{DynamicResource ColorBrush2}" Background="{DynamicResource ColorBrush6}"
|
||||
</StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,15,0,8" Foreground="{DynamicResource ColorBrush2}" Background="{DynamicResource ColorBrush6}"
|
||||
Text="除了字体颜色,你也可以将主题色用于背景色、边框颜色等颜色参数。例如这行字的颜色为浓度 2,背景为浓度 6。" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="替换标记" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="在花括号 {} 中写入特定内容,PCL 会在加载时对其进行替换。
例如,path 会被替换为 PCL 可执行文件所在文件夹({path}),用于在 EventData 中指定特定文件,或是加载图片。" />
|
||||
<local:MyHint Margin="0,6,0,10" Text="以下特性于 PCL 2.6.5 (299) 加入,不适用于更早版本的 PCL。" IsWarn="False" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<local:MyHint Margin="0,6,0,10" Text="以下特性于 PCL 2.6.5 (299) 加入,不适用于更早版本的 PCL。" IsWarn="False" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="你也可以使用替换标记来获取随机内容:cave 会被替换为一条随机的回声洞内容,hint 则是 “你知道吗” 的内容。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="10,6,0,5" Foreground="{DynamicResource ColorBrush3}"
|
||||
<TextBlock TextWrapping="Wrap" Margin="10,6,0,5" Foreground="{DynamicResource ColorBrush3}"
|
||||
Text="你知道吗:{hint}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="进阶:Grid 布局" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="如果要实现更复杂的布局,则必须使用 Grid。Grid 可以让按钮们自动适应窗口宽度:随意拉伸 PCL 窗口,按钮大小会自动改变。" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
Text="你可以上网查找 “WPF Grid” 的相关教程,这里仅给出一个例子,不作详细介绍。你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1.6*" MinWidth="200" />
|
||||
<!-- 第二个按钮的宽度是第一个按钮的 1.6 倍,且至少为 200 -->
|
||||
<ColumnDefinition Width="150" />
|
||||
<!-- 如果不打 *,则会占用固定的宽度,也可以写 Auto 来自适应 -->
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- 为按钮添加 Grid.Column 属性指定它所在的列,不要添加 Width 与 HorizontalAlignment 属性 -->
|
||||
<local:MyButton Grid.Column="0" Margin="0,0,10,0" Height="35" ColorType="Highlight"
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1.6*" MinWidth="200" /> <!-- 第二个按钮的宽度是第一个按钮的 1.6 倍,且至少为 200 -->
|
||||
<ColumnDefinition Width="150" /> <!-- 如果不打 *,则会占用固定的宽度,也可以写 Auto 来自适应 -->
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- 为按钮添加 Grid.Column 属性指定它所在的列,不要添加 Width 与 HorizontalAlignment 属性 -->
|
||||
<local:MyButton Grid.Column="0" Margin="0,0,10,0" Height="35" ColorType="Highlight"
|
||||
Text="打开 B 站" EventType="打开网页" EventData="https://www.bilibili.com/" />
|
||||
<local:MyButton Grid.Column="1" Margin="0,0,10,0" Height="35"
|
||||
<local:MyButton Grid.Column="1" Margin="0,0,10,0" Height="35"
|
||||
Text="进入 Hypixel" EventType="启动游戏" EventData="1.16.3|mc.hypixel.net" ToolTip="使用 Minecraft 1.16.3 进入 Hypixel" />
|
||||
<local:MyButton Grid.Column="2" Margin="0,0,10,0" Height="35"
|
||||
<local:MyButton Grid.Column="2" Margin="0,0,10,0" Height="35"
|
||||
Text="打开记事本" EventType="打开文件" EventData="notepad" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="进阶:图标按钮" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<local:MyHint Margin="0,0,0,10" Text="以下特性于 PCL 2.6.5 (299) 加入,不适用于更早版本的 PCL。" IsWarn="False" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<local:MyHint Margin="0,0,0,10" Text="以下特性于 PCL 2.6.5 (299) 加入,不适用于更早版本的 PCL。" IsWarn="False" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="MyIconTextButton 是一种带有自定义矢量图标的按钮变体,它同样支持 EventType 与 EventData 属性。
通过设置 Logo 属性来控制它的图标,设置 LogoScale 属性还可以调整图标的缩放比例。" />
|
||||
<local:MyIconTextButton Margin="0,4,0,8" Height="35" HorizontalAlignment="Center"
|
||||
<local:MyIconTextButton Margin="0,4,0,8" Height="35" HorizontalAlignment="Center"
|
||||
Text="查看 SVG Path 简介" EventType="打开网页" EventData="https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths"
|
||||
LogoScale="1.02" Logo="M1091 0H78C35 0 0 35 0 78v863c0 43 35 78 78 78H1091c43 0 78-35 78-78V78C1170 35 1134 0 1091 0z m-8 87v78H87v-78h994zM87 933V254h994v679H87v0zM724 340l-206 547a43 43 0 0 1-82-31l206-547a43 43 0 0 1 82 30zM369 545l-85 85 85 85a43 43 0 0 1-62 62l-116-116a43 43 0 0 1 0-62l116-116a43 43 0 0 1 62 61z m610-37a43 43 0 0 1 0 62l-116 116a43 43 0 0 1-62 0 43 43 0 0 1 0-62l85-85-85-85a43 43 0 0 1 62-62l116 116z" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="Logo 属性的内容是 SVG Path 的值,你需要使用 SVG 编辑器或者从图标资源网站(如 IconFont)查找它。不要自己写,写不懂的。
此外,它还有两种 ColorType:Black(默认)和 Highlight。" />
|
||||
<local:MyIconTextButton Margin="0,4,0,8" Height="35" HorizontalAlignment="Center"
|
||||
<local:MyIconTextButton Margin="0,4,0,8" Height="35" HorizontalAlignment="Center"
|
||||
ColorType="Highlight" Text="打开 IconFont" EventType="打开网页" EventData="https://www.iconfont.cn/"
|
||||
LogoScale="1" Logo="M510 959c-51-31-40-86-74-120-61-63-168-66-231-138C-5 457 196 3 593 70c231 39 407 363 250 592-67 98-198 106-277 213-23 23-11 81-55 83zM176 432c-9 176 240 167 240 9 0-80-72-145-166-111-66 23-71 49-74 101z m509 129c212 59 217-307 0-231-102 36-90 206 0 231z m-213 111c33 7 44-91 9-92-19 19-64 79-9 92z m83 0H575c23-37-8-87-46-92 3 37-11 92 27 92z" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="如果只想要图标,不要文字,还可以使用 MyIconButton。它不能设置 Text 属性,只有一个图标可以按。
它的 Theme 属性可以设置为 Color(默认)、White、Black、Red。" />
|
||||
<local:MyIconButton Margin="0,4,0,0" Width="25" Height="25" HorizontalAlignment="Center"
|
||||
<local:MyIconButton Margin="0,4,0,0" Width="25" Height="25" HorizontalAlignment="Center"
|
||||
Theme="Black" EventType="弹出窗口" EventData="事件|MyIconButton 当然也支持 EventType 和 EventData——要不然介绍它干啥?"
|
||||
LogoScale="1" Logo="M149 873c47 47 101 83 162 109 63 26 130 40 199 40 69 0 136-13 199-40 61-25 115-62 162-109s83-101 109-162c26-63 40-130 40-199 0-69-13-136-40-199-25-61-62-115-109-162-46-46-101-83-162-109C648 13 580 0 511 0s-136 13-199 40c-61 25-115 62-162 109s-83 101-109 162C13 375 0 442 0 511s13 136 40 199c25 61 62 115 109 162zM97 511c0-228 185-414 414-414 228 0 414 185 414 414S740 926 511 926c-228 0-414-185-414-414z M539 244c-8-4-17-7-27-7-9 0-19 2-27 7-16 9-27 27-27 47 0 30 24 54 54 54 30 0 54-24 54-54 0-19-10-37-27-47zM566 732v-284c0-30-24-54-54-54-30 0-54 24-54 54v284c0 30 24 54 54 54 30 0 54-24 54-54z" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||
Text="如果只想显示一个图标,不想让它是能按的按钮,可以使用 WPF 自带的 Path 等绘图控件,感兴趣的话可以自行搜索。想偷懒也可以把 MyIconButton 的 IsHitTestVisible 属性改为 False……" />
|
||||
<Path Margin="0,4,0,0" Width="20" Height="20" HorizontalAlignment="Center"
|
||||
<Path Margin="0,4,0,0" Width="20" Height="20" HorizontalAlignment="Center"
|
||||
Stretch="Uniform" Fill="{DynamicResource ColorBrush1}"
|
||||
Data="M149 873c47 47 101 83 162 109 63 26 130 40 199 40 69 0 136-13 199-40 61-25 115-62 162-109s83-101 109-162c26-63 40-130 40-199 0-69-13-136-40-199-25-61-62-115-109-162-46-46-101-83-162-109C648 13 580 0 511 0s-136 13-199 40c-61 25-115 62-162 109s-83 101-109 162C13 375 0 442 0 511s13 136 40 199c25 61 62 115 109 162zM97 511c0-228 185-414 414-414 228 0 414 185 414 414S740 926 511 926c-228 0-414-185-414-414z M539 244c-8-4-17-7-27-7-9 0-19 2-27 7-16 9-27 27-27 47 0 30 24 54 54 54 30 0 54-24 54-54 0-19-10-37-27-47zM566 732v-284c0-30-24-54-54-54-30 0-54 24-54 54v284c0 30 24 54 54 54 30 0 54-24 54-54z" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<local:MyCard Title="进阶:联网自定义主页" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<local:MyHint Margin="0,0,0,10" Text="以下特性于 PCL 2.6.5 (299) 加入,不适用于更早版本的 PCL。" IsWarn="False" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
<StackPanel Margin="25,40,23,15">
|
||||
<local:MyHint Margin="0,0,0,10" Text="以下特性于 PCL 2.6.5 (299) 加入,不适用于更早版本的 PCL。" IsWarn="False" />
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
Text="如果你在尝试制作联网更新的自定义主页,可以查看下方的 GitHub 讨论页。
你可以根据其中的介绍为主页添加版本号检查以节省流量,也可以通过检查 Referer 和 User Agent 来确定对方的 PCL 版本。" />
|
||||
<local:MyButton Margin="0,0,0,8" Height="35" HorizontalAlignment="Center" Padding="20,0,20,0"
|
||||
<local:MyButton Margin="0,0,0,8" Height="35" HorizontalAlignment="Center" Padding="20,0,20,0"
|
||||
Text="打开 GitHub 讨论页" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2/discussions/2528" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
<!--
|
||||
@@ -317,9 +315,9 @@
|
||||
- Width、Height:设置宽度与高度
|
||||
- ToolTip:设置鼠标指向时的提示文本
|
||||
- Margin:调整外边距(格式为 左,上,右,下。例如 Margin="0,0,0,2" 即为 2 单位的下边距)
|
||||
- HorizontalAlignment:设置横向对齐方式,居左:Left、居中:Center、居右:Right、拉伸(默认):Stretch
|
||||
- VerticalAlignment:设置纵向对齐方式,居上:Top、居中:Center、居下:Bottom、拉伸(默认):Stretch
|
||||
- IsHitTestVisible:该控件是否响应交互(点击、指向动画等),True 为是(默认),False 为否
|
||||
- HorizontalAlignment:设置横向对齐方式;居左:Left、居中:Center、居右:Right、拉伸(默认):Stretch
|
||||
- VerticalAlignment:设置纵向对齐方式;居上:Top、居中:Center、居下:Bottom、拉伸(默认):Stretch
|
||||
- IsHitTestVisible:该控件是否响应交互(点击、指向动画等);True 为是(默认),False 为否
|
||||
|
||||
TextBlock(纯文本):
|
||||
- Text:设置显示的文本(如果要使用引号等特殊字符,自行百度 XAML 转义)
|
||||
@@ -328,17 +326,20 @@ TextBlock(纯文本):
|
||||
- FontWeight:设置为 Bold 时,文字加粗
|
||||
- Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
|
||||
|
||||
Image(图片):
|
||||
local:MyImage(图片):
|
||||
- Source:要显示的图片的网址,或 PCL 内置图片位置
|
||||
- FallbackSource:当 Source 首次下载失败时,会从该备用地址加载图片
|
||||
- LoadingSource:正在下载网络图片时显示的本地图片(不支持联网下载);默认为 pack://application:,,,/images/Icons/NoIcon.png
|
||||
- EnableCache:若图片是联网获取的,是否将图片保存到本地缓存,在 7 天内不再重新下载;True 为是(默认),False 为否
|
||||
|
||||
local:MyCard(卡片):
|
||||
- Title:设置显示的标题文本
|
||||
- CanSwap:卡片是否可以折叠,True 为是,False 为否
|
||||
- IsSwaped:卡片是否默认折叠,要求 CanSwap 必须为 True
|
||||
- HorizontalAlignment:若使用,要求 CanSwap 必须为 False
|
||||
- UseAnimation:是否在展开等高度改变时触发动画,True 为是(默认),False 为否
|
||||
- SwapLogoRight:卡片折叠时的箭头是朝下还是朝右,True 为朝右,False 为朝下(默认)
|
||||
- HasMouseAnimation:是否在鼠标指向时改变卡片颜色,True 为是(默认),False 为否
|
||||
- UseAnimation:是否在展开等高度改变时触发动画;True 为是(默认),False 为否
|
||||
- SwapLogoRight:卡片折叠时的箭头是朝下还是朝右;True 为朝右,False 为朝下(默认)
|
||||
- HasMouseAnimation:是否在鼠标指向时改变卡片颜色;True 为是(默认),False 为否
|
||||
|
||||
local:MyHint(提示条):
|
||||
- Text:设置显示的文本(
 代表换行)
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -1,27 +1,17 @@
|
||||
# Plain Craft Launcher 源代码库
|
||||
# Plain Craft Launcher
|
||||
|
||||
[](https://github.com/Hex-Dragon/PCL2/)
|
||||
[](https://github.com/Hex-Dragon/PCL2/issues)
|
||||
[](https://afdian.com/@LTCat)
|
||||
[](https://github.com/Hex-Dragon/PCL2/)
|
||||
[](https://github.com/Hex-Dragon/PCL2/issues)
|
||||
[](https://space.bilibili.com/11343203/dynamic)
|
||||
[](https://afdian.com/@LTCat)
|
||||
|
||||
包含 PCL 的大部分源代码,包括 UI 库、动画模块、下载模块、Minecraft 启动模块等!<br/>
|
||||
代码并不是实时更新的,它会在每次 PCL 发布更新时同步一次。<br/>
|
||||
非常感谢社区的大力支持!
|
||||
|
||||
<br/>
|
||||
|
||||
## 介绍
|
||||
|
||||
这里提供了 PCL 的大多数源代码,包括 UI 库、动画模块、下载模块、Minecraft 启动模块等!
|
||||
|
||||
PCL 的代码绝大多数其实都是几年前学生时代的产物了……那时候英语还不过关……所以经常出现奇葩命名,还有令人高血压的高耦合啊,没做单例啊,瞎勾八乱糊啊之类的问题……额,我也不可能把这一堆玩意儿再从头写一次,各位就基于能跑就行的原则凑合凑合着看吧,求求别喷了……
|
||||
|
||||
<br/>
|
||||
|
||||
## 相关内容
|
||||
- [PCL 功能投票](https://github.com/Hex-Dragon/PCL2/discussions/2):来参加投票吧,开发者会优先处理票数较高的帖子!
|
||||
- [程序下载](https://afdian.com/p/0164034c016c11ebafcb52540025c377):下载免费的正式版 PCL。
|
||||
- [帮助文档库](https://github.com/LTCatt/PCL2Help):PCL 帮助文档在 GitHub 上的存储库(是的,帮助库在另一个 Repo……)
|
||||
|
||||
<br/>
|
||||
|
||||
## 一些无趣的小细节
|
||||
- 别想在这里面找到解密游戏的线索,那部分的代码被我抠掉了
|
||||
- 解锁隐藏主题的相关代码也被抠掉了,所以别想着用翻源代码这种歪门邪道来绕过解密了.jpg
|
||||
- 源代码库并不是即时更新的,而是在每次 PCL 发布更新时(手动)同步一次
|
||||
### 相关资源
|
||||
- [PCL 下载](https://afdian.com/p/0164034c016c11ebafcb52540025c377):下载可免费使用的正式版 PCL!
|
||||
- [PCL 功能投票](https://github.com/Hex-Dragon/PCL2/discussions/2):来参加投票吧,开发者会优先处理票数较高的项目!
|
||||
- [帮助文档库](https://github.com/LTCatt/PCL2Help):PCL 内置帮助文档的存储库
|
||||
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user