From bdcbab700e1a9975088ac318f052c0848dae4daf Mon Sep 17 00:00:00 2001 From: allMagicNB <116283787+allMagicNB@users.noreply.github.com> Date: Sat, 7 Dec 2024 23:07:41 +0800 Subject: [PATCH 1/8] + PCL2Help.zip --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa9c3a7b..7fc62a73 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,6 +36,7 @@ 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" + curl -o "Plain Craft Launcher 2\Resourses\Help.zip" "https://github.com/LTCatt/PCL2Help/archive/refs/heads/master.zip" - name: Build run: msbuild "Plain Craft Launcher 2\Plain Craft Launcher 2.vbproj" -p:Configuration=${{ matrix.configuration }} - name: Upload a Build Artifact From f300858ced5f7b2adfc82a28c418a0d122d431dc Mon Sep 17 00:00:00 2001 From: allMagicNB <116283787+allMagicNB@users.noreply.github.com> Date: Sat, 7 Dec 2024 23:39:29 +0800 Subject: [PATCH 2/8] fix --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7fc62a73..437ee6c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ 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" - curl -o "Plain Craft Launcher 2\Resourses\Help.zip" "https://github.com/LTCatt/PCL2Help/archive/refs/heads/master.zip" + curl -o "Plain Craft Launcher 2\Resources\Help.zip" "https://github.com/LTCatt/PCL2Help/archive/refs/heads/master.zip" - name: Build run: msbuild "Plain Craft Launcher 2\Plain Craft Launcher 2.vbproj" -p:Configuration=${{ matrix.configuration }} - name: Upload a Build Artifact From bce8e715718f6aa852dacbcc8aff51f0b13546fc Mon Sep 17 00:00:00 2001 From: allMagicNB <116283787+allMagicNB@users.noreply.github.com> Date: Sun, 8 Dec 2024 06:59:23 +0800 Subject: [PATCH 3/8] fix --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 437ee6c2..fbd87c96 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ 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" - curl -o "Plain Craft Launcher 2\Resources\Help.zip" "https://github.com/LTCatt/PCL2Help/archive/refs/heads/master.zip" + curl -o "Plain Craft Launcher 2\Resources\Help.zip" "https://codeload.github.com/LTCatt/PCL2Help/zip/refs/heads/master" - name: Build run: msbuild "Plain Craft Launcher 2\Plain Craft Launcher 2.vbproj" -p:Configuration=${{ matrix.configuration }} - name: Upload a Build Artifact From 38b3cefa89c59062009eb0bc64dd70335fbce097 Mon Sep 17 00:00:00 2001 From: allMagicNB <116283787+allMagicNB@users.noreply.github.com> Date: Sun, 8 Dec 2024 19:29:23 +0800 Subject: [PATCH 4/8] fix --- .github/workflows/build.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbd87c96..bf88c42b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +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" - curl -o "Plain Craft Launcher 2\Resources\Help.zip" "https://codeload.github.com/LTCatt/PCL2Help/zip/refs/heads/master" + 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 From 68f8b3eeac33c78b1e7ad248a876bc41b761613a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E8=85=BE=E7=8C=AB=E8=B7=83?= <1043137532@qq.com> Date: Sun, 8 Dec 2024 20:21:23 +0800 Subject: [PATCH 5/8] 2.8.11 --- Plain Craft Launcher 2/Application.xaml.vb | 4 +- Plain Craft Launcher 2/Controls/MyImage.vb | 4 +- .../Controls/MyListItem.xaml.vb | 2 + .../Controls/MyRadioButton.xaml | 2 +- .../Controls/MyScrollViewer.vb | 3 + Plain Craft Launcher 2/FormMain.xaml.vb | 166 ++- .../Modules/Base/ModBase.vb | 46 +- Plain Craft Launcher 2/Modules/Base/ModNet.vb | 2 +- .../Modules/Minecraft/ModComp.vb | 77 +- .../Modules/Minecraft/ModDownload.vb | 181 ++-- .../Modules/Minecraft/ModJava.vb | 19 +- .../Modules/Minecraft/ModLaunch.vb | 33 +- .../Modules/Minecraft/ModMinecraft.vb | 14 +- .../Modules/Minecraft/MyLocalModItem.xaml | 4 +- .../Modules/Minecraft/MyLocalModItem.xaml.vb | 96 +- Plain Craft Launcher 2/Modules/ModMusic.vb | 119 ++- Plain Craft Launcher 2/Modules/ModSecret.vb | 8 +- .../My Project/AssemblyInfo.vb | 4 +- .../PageDownload/PageDownloadCompDetail.xaml | 9 +- .../PageDownloadCompDetail.xaml.vb | 125 ++- .../PageDownload/PageDownloadLeft.xaml.vb | 2 + .../PageDownload/PageDownloadMod.xaml.vb | 36 +- .../Pages/PageLaunch/PageLaunchRight.xaml.vb | 6 +- .../PageLaunch/PageLoginAuthSkin.xaml.vb | 4 +- .../PageLaunch/PageLoginNideSkin.xaml.vb | 3 +- .../Pages/PageLink/PageLinkIoi.xaml.vb | 2 - .../Pages/PageOther/PageOtherAbout.xaml | 217 ++-- .../Pages/PageOther/PageOtherLeft.xaml | 4 +- .../Pages/PageOther/PageOtherLeft.xaml.vb | 14 +- .../Pages/PageSetup/ModSetup.vb | 24 +- .../Pages/PageSetup/PageSetupLaunch.xaml | 11 +- .../Pages/PageSetup/PageSetupLaunch.xaml.vb | 11 +- .../Pages/PageSetup/PageSetupSystem.xaml | 5 +- .../Pages/PageSetup/PageSetupUI.xaml | 8 +- .../Pages/PageSetup/PageSetupUI.xaml.vb | 42 +- .../Pages/PageVersion/PageVersionMod.xaml | 25 +- .../Pages/PageVersion/PageVersionMod.xaml.vb | 66 +- .../PageVersion/PageVersionSetup.xaml.vb | 3 +- Plain Craft Launcher 2/Resources/Help.zip | Bin 79164 -> 82725 bytes Plain Craft Launcher 2/Resources/ModData.txt | 966 ++++++++++++++---- .../Resources/java-wrapper.jar | Bin 18321 -> 15761 bytes 41 files changed, 1588 insertions(+), 779 deletions(-) diff --git a/Plain Craft Launcher 2/Application.xaml.vb b/Plain Craft Launcher 2/Application.xaml.vb index 4c66c770..4233f8f2 100644 --- a/Plain Craft Launcher 2/Application.xaml.vb +++ b/Plain Craft Launcher 2/Application.xaml.vb @@ -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) @@ -114,7 +114,7 @@ WaitRetry: 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) diff --git a/Plain Craft Launcher 2/Controls/MyImage.vb b/Plain Craft Launcher 2/Controls/MyImage.vb index 0a950f7d..92ba1c07 100644 --- a/Plain Craft Launcher 2/Controls/MyImage.vb +++ b/Plain Craft Launcher 2/Controls/MyImage.vb @@ -128,8 +128,8 @@ RetryStart: '下载 ActualSource = LoadingSource '显示加载中图片 TempDownloadingPath = TempPath & RandomInteger(0, 10000000) - Directory.CreateDirectory(GetPathFromFullPath(TempPath)) - Using Client As New System.Net.WebClient + 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 diff --git a/Plain Craft Launcher 2/Controls/MyListItem.xaml.vb b/Plain Craft Launcher 2/Controls/MyListItem.xaml.vb index 85bb4215..02594cf1 100644 --- a/Plain Craft Launcher 2/Controls/MyListItem.xaml.vb +++ b/Plain Craft Launcher 2/Controls/MyListItem.xaml.vb @@ -654,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 diff --git a/Plain Craft Launcher 2/Controls/MyRadioButton.xaml b/Plain Craft Launcher 2/Controls/MyRadioButton.xaml index e5753e03..aa42f53c 100644 --- a/Plain Craft Launcher 2/Controls/MyRadioButton.xaml +++ b/Plain Craft Launcher 2/Controls/MyRadioButton.xaml @@ -4,6 +4,6 @@ HorizontalAlignment="Center" VerticalAlignment="Center" Background="{StaticResource ColorBrushSemiTransparent}" CornerRadius="13.5" MinHeight="27" MaxHeight="27"> - + diff --git a/Plain Craft Launcher 2/Controls/MyScrollViewer.vb b/Plain Craft Launcher 2/Controls/MyScrollViewer.vb index ad18da92..42da8906 100644 --- a/Plain Craft Launcher 2/Controls/MyScrollViewer.vb +++ b/Plain Craft Launcher 2/Controls/MyScrollViewer.vb @@ -45,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 diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb index 35d01e23..2c06c45d 100644 --- a/Plain Craft Launcher 2/FormMain.xaml.vb +++ b/Plain Craft Launcher 2/FormMain.xaml.vb @@ -82,8 +82,13 @@ Public Class FormMain '3:BUG+ IMP* FEAT- '2:BUG* IMP- '1:BUG- + If LastVersion < 344 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)(4, "Mod 详情页面会按 Mod 加载器分类卡片")) FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持安装同时包含 modpack 文件和启动器的懒人包")) FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化整合包导入流程")) FeatureCount += 20 @@ -295,10 +300,10 @@ Public Class FormMain 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)) '更改窗口 @@ -329,7 +334,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 @@ -782,47 +787,8 @@ Public Class FormMain End Sub) Exit Sub End If - 'Mod 安装 - If {"jar", "litemod", "disabled", "old"}.Any(Function(t) t = Extension) Then - Log("[System] 文件为 jar/litemod 格式,尝试作为 Mod 安装") - '检查回收站:回收站中的文件有错误的文件名 - If FilePathList.First.Contains(":\$RECYCLE.BIN\") Then - Hint("请先将文件从回收站还原,再拖入 PCL!", HintType.Critical) - Exit Sub - End If - '获取并检查目标版本 - 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 - 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] 文件为压缩包,尝试作为整合包安装") @@ -1063,9 +1029,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 @@ -1134,9 +1097,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) @@ -1165,14 +1125,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 ''' ''' 通过点击返回按钮或手动触发返回来改变页面。 ''' @@ -1203,9 +1155,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 '返回到更上层的子页面 @@ -1299,37 +1251,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 ''' @@ -1342,12 +1298,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 '主页面 → 主页面,无事发生 @@ -1366,16 +1322,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 diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb index 83f8d6c3..6155e634 100644 --- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb +++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb @@ -12,13 +12,13 @@ Public Module ModBase #Region "声明" '下列版本信息由更新器自动修改 - Public Const VersionBaseName As String = "2.8.10" '不含分支前缀的显示用版本名 - Public Const VersionStandardCode As String = "2.8.10." & VersionBranchCode '标准格式的四段式版本号 + Public Const VersionBaseName As String = "2.8.11" '不含分支前缀的显示用版本名 + Public Const VersionStandardCode As String = "2.8.11." & VersionBranchCode '标准格式的四段式版本号 Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换 #If BETA Then Public Const VersionCode As Integer = 342 'Release #Else - Public Const VersionCode As Integer = 343 'Snapshot + Public Const VersionCode As Integer = 344 'Snapshot #End If '自动生成的版本信息 Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName @@ -971,7 +971,7 @@ Public Module ModBase End Using End Function ''' - ''' 弹出选取文件对话框并且要求选取文件。 + ''' 弹出选取文件对话框,要求选择一个文件。 ''' ''' 要求的格式。如:“常用图片文件(*.png;*.jpg)|*.png;*.jpg”。 ''' 弹窗的标题。 @@ -985,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 ''' - ''' 弹出选取文件夹对话框并且要求选取文件夹,以 \ 结尾。如果没有选择就返回空字符串。 + ''' 弹出选取文件对话框,要求选择多个文件。 + ''' + ''' 要求的格式。如:“常用图片文件(*.png;*.jpg)|*.png;*.jpg”。 + ''' 弹窗的标题。 + 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 + ''' + ''' 弹出选取文件夹对话框,要求选取文件夹。 + ''' 返回以 \ 结尾的完整路径,如果没有选择则返回空字符串。 ''' 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} @@ -1880,6 +1900,8 @@ RetryDir: ''' Public Class SafeList(Of T) Inherits SynchronizedCollection(Of T) + Implements IEnumerable, IEnumerable(Of T) + '构造函数 Public Sub New() MyBase.New() End Sub @@ -1892,7 +1914,13 @@ RetryDir: Public Shared Widening Operator CType(Data As SafeList(Of T)) As List(Of T) Return New List(Of T)(Data) End Operator - Public Overloads Function GetEnumerator() As IEnumerator(Of T) + '基于 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 @@ -2048,7 +2076,7 @@ NextElement: GetTimeSpanString = TotalMonthes & " 个月" ElseIf TotalMonthes >= 1 Then '1~4 月,“2 个月 13 天” - GetTimeSpanString = TotalMonthes & " 个月" & If((Span.Days Mod 30) > 0, " " & (Span.Days Mod 30) & " 天", "") + GetTimeSpanString = TotalMonthes & " 月" & If((Span.Days Mod 30) > 0, " " & (Span.Days Mod 30) & " 天", "") ElseIf Span.TotalDays >= 4 Then '4~30 天,“23 天” GetTimeSpanString = Span.Days & " 天" diff --git a/Plain Craft Launcher 2/Modules/Base/ModNet.vb b/Plain Craft Launcher 2/Modules/Base/ModNet.vb index 9dc67057..f046d349 100644 --- a/Plain Craft Launcher 2/Modules/Base/ModNet.vb +++ b/Plain Craft Launcher 2/Modules/Base/ModNet.vb @@ -930,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 diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb index 97e7bde8..36cc7ee5 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb @@ -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()} @@ -1156,7 +1162,7 @@ Retry: ''' Public ReadOnly ModLoaders As List(Of CompModLoaderType) ''' - ''' 支持的游戏版本列表。类型包括:"1.18.5","1.18","1.18 快照","21w15a","未知版本"。 + ''' 支持的游戏版本列表。类型包括:"1.18.5","1.18","1.18 预览版","21w15a","未知版本"。 ''' Public ReadOnly GameVersions As List(Of String) ''' @@ -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.BeforeFirst("-") & " 快照", 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)} @@ -1420,14 +1426,12 @@ Retry: ''' ''' 已知文件信息的缓存。 ''' - Private CompFilesCache As New Dictionary(Of String, List(Of CompFile)) + Public CompFilesCache As New Dictionary(Of String, List(Of CompFile)) ''' ''' 获取某个工程下的全部文件列表。 ''' 必须在工作线程执行,失败会抛出异常。 ''' 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 '存在缓存 @@ -1438,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 diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb index 832b372c..81c1a664 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb @@ -167,24 +167,25 @@ End Structure ''' ''' Minecraft 客户端 版本列表,主加载器。 + ''' 若要求镜像源必须包含某个版本,则将该版本 ID 作为输入(#5195)。 ''' - 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 @@ ''' ''' Minecraft 客户端 版本列表,Mojang 官方源加载器。 ''' - 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 @@ ''' ''' Minecraft 客户端 版本列表,BMCLAPI 源加载器。 ''' - 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 @@ ''' Public Function DlClientListGet(Id As String) Try - '确认 Minecraft 版本列表已完成获取 + '确认版本格式标准 + 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() + DlClientListLoader.WaitForExit(Id) Case LoadState.Failed, LoadState.Aborted, LoadState.Waiting - DlClientListLoader.WaitForExit(IsForceRestart:=True) + DlClientListLoader.WaitForExit(Id, 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 - '查找版本并开始 + '重新查找版本 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 @@ -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 @@ -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))) diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb index 1eee00a3..d11075e0 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb @@ -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 diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb index ecf4dcc6..62e457f5 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb @@ -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 @@ -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 @@ -1643,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 diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb index ca8315bd..2d87c220 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb @@ -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 @@ -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: ''' ''' 比较两个版本名的排序器。 ''' - 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 ''' diff --git a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml index d626409b..445f44b8 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml +++ b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml @@ -30,12 +30,12 @@ - + - + diff --git a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb index df794e64..f826928d 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb @@ -303,30 +303,33 @@ Public Class MyLocalModItem #End Region + 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 @@ -476,20 +479,57 @@ Public Class MyLocalModItem '触发更新 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 Not LabSubtitle.IsTextTrimmed 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 diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index 93062feb..6a7e34d1 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -14,8 +14,8 @@ ''' 初始化音乐播放列表。 ''' ''' 强制全部重新载入列表。 - ''' 在重载列表时避免让某项成为第一项。 - Private Sub MusicListInit(ForceReload As Boolean, Optional IgnoreFirst As String = "") + ''' 在重载列表时避免让某项成为第一项。 + 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,6 +42,7 @@ End Sub ''' ''' 获取下一首播放的音乐路径并将其从列表中移除。 + ''' 如果没有,可能会返回 Nothing。 ''' Private Function DequeueNextMusicAddress() As String '初始化,确保存在音乐 @@ -50,10 +51,10 @@ If MusicWaitingList.Any() Then DequeueNextMusicAddress = MusicWaitingList(0) MusicWaitingList.RemoveAt(0) - If Not MusicWaitingList.Any() Then MusicListInit(False, DequeueNextMusicAddress) Else - DequeueNextMusicAddress = "" + DequeueNextMusicAddress = Nothing End If + If Not MusicWaitingList.Any() Then MusicListInit(False, DequeueNextMusicAddress) End Function #End Region @@ -64,44 +65,45 @@ ''' 刷新背景音乐按钮 UI 与设置页 UI。 ''' 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 + 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 - '有背景音乐 - 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() + 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 ''' @@ -132,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 @@ -183,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() @@ -199,11 +209,10 @@ ''' 开始播放音乐。 ''' Private Sub MusicStartPlay(Address As String, Optional IsFirstLoad As Boolean = False) - If Not Address = "" Then - Log("[Music] 播放开始:" & Address) - MusicCurrent = Address - RunInNewThread(Sub() MusicLoop(IsFirstLoad), "Music", ThreadPriority.BelowNormal) - End If + If Address Is Nothing Then Return + Log("[Music] 播放开始:" & Address) + MusicCurrent = Address + RunInNewThread(Sub() MusicLoop(IsFirstLoad), "Music", ThreadPriority.BelowNormal) End Sub '播放与暂停 @@ -293,7 +302,8 @@ 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) @@ -301,6 +311,9 @@ '将播放错误的音乐从列表中移除 MusicAllList.Remove(MusicCurrent) MusicWaitingList.Remove(MusicCurrent) + MusicRefreshUI() + '等待 2 秒后继续播放 + Thread.Sleep(2000) If TypeOf ex Is FileNotFoundException Then MusicRefreshPlay(True, IsFirstLoad) Else diff --git a/Plain Craft Launcher 2/Modules/ModSecret.vb b/Plain Craft Launcher 2/Modules/ModSecret.vb index f5c2c24d..52fd4d23 100644 --- a/Plain Craft Launcher 2/Modules/ModSecret.vb +++ b/Plain Craft Launcher 2/Modules/ModSecret.vb @@ -109,9 +109,7 @@ Friend Module ModSecret Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode End If Client.Headers("Referer") = "http://" & VersionCode & ".pcl2.open.server/" - If Url.Contains("api.curseforge") Then - Client.Headers("x-api-key") = CurseForgeAPIKey - End If + If Url.Contains("api.curseforge.com") Then Client.Headers("x-api-key") = CurseForgeAPIKey End Sub ''' ''' 设置 Headers 的 UA、Referer。 @@ -125,9 +123,7 @@ Friend Module ModSecret Request.UserAgent = "PCL2/" & VersionStandardCode End If Request.Referer = "http://" & VersionCode & ".pcl2.open.server/" - If Url.Contains("api.curseforge") Then - Request.Headers("x-api-key") = CurseForgeAPIKey - End If + If Url.Contains("api.curseforge.com") Then Request.Headers("x-api-key") = CurseForgeAPIKey End Sub #End Region diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb index a3e1e307..8b6b7360 100644 --- a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb +++ b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb @@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices ' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 ' 方法是按如下所示使用“*” - - + + diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml index 7333268e..28f238f5 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml @@ -20,8 +20,13 @@ - - + + + + + + + diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb index 055b2f14..c988751a 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb @@ -59,30 +59,86 @@ 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, $"所选版本:{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)) + 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 + '检查是否符合版本筛选器 + If VersionFilter IsNot Nothing AndAlso + GetGroupedVersionName(GameVersion, IsMajorVersionFilter, True) <> VersionFilter Then Continue For '决定添加到哪个卡片 - Dim Ver As String - If GameVersion Is Nothing Then - Ver = "未知版本" - ElseIf GameVersion.Contains("w") OrElse GameVersion.Contains("pre") OrElse GameVersion.Contains("rc") Then - Ver = "快照版本" - ElseIf GameVersion.StartsWithF("1.0") Then - Ver = "远古版本" - Else - Ver = GameVersion - End If + Dim Ver As String = GetGroupedVersionName(GameVersion, False, False) '遍历加入的加载器列表 Dim Loaders As New List(Of String) - If Project.Type = CompType.Mod Then + 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 @@ -101,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 '增加卡片 @@ -118,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 @@ -128,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 @@ -249,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 @@ -315,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) & " " diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb index e085dd77..f2eb250e 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb @@ -113,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 diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb index ae9ee479..113ff253 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb @@ -1,12 +1,44 @@ Public Class PageDownloadMod Public Const PageSize = 40 + ''' + ''' 在切换到该页面时自动设置的目标版本。 + ''' + 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 @@ -118,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 diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb index 0d3032b5..595aecb2 100644 --- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb @@ -105,7 +105,7 @@ 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] 主页预设:主页市场") @@ -123,6 +123,10 @@ Download: 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)) diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb index ca21ffa7..fec81e62 100644 --- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb @@ -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 diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginNideSkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginNideSkin.xaml.vb index bceb7c86..84fa7730 100644 --- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginNideSkin.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginNideSkin.xaml.vb @@ -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 diff --git a/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb b/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb index c1cbe612..f1e63121 100644 --- a/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb @@ -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 diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml index 45677238..81421633 100644 --- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml +++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml @@ -104,126 +104,107 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml b/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml index 119a07ce..874928f7 100644 --- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml +++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml @@ -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" /> - - diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml.vb index ffa5a72d..59df7428 100644 --- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml.vb @@ -125,7 +125,12 @@ 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。", "反馈", "提交新反馈", "查看反馈列表", "取消") @@ -135,7 +140,12 @@ 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 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") diff --git a/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb b/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb index 444fc8ac..6dbe50c4 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb +++ b/Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb @@ -203,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 @@ -313,6 +317,12 @@ Dim E As SetupEntry = SetupDict(Key) [Set](Key, E.DefaultValue, E, ForceReload, Version) End Sub + ''' + ''' 获取某个设置项的默认值。 + ''' + 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 diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml index bb076935..8b692a43 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml +++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml @@ -220,7 +220,7 @@ - + @@ -232,8 +232,13 @@ - - + + + + diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb index 6567b4e0..a30267bd 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb @@ -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 AndAlso Not JavaList.Count = 0, 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({ @@ -573,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 diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml index d3d32a34..bf1c1da0 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml +++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml @@ -78,9 +78,8 @@ - + diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml index e619cc75..0e2f9127 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml +++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml @@ -72,10 +72,10 @@ - + - - + + @@ -225,6 +225,7 @@ + @@ -247,6 +248,7 @@ + diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb index 7773249b..f48e8eaf 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb @@ -452,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 @@ -675,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 diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml index 854458ef..d00296d6 100644 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml +++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml @@ -16,11 +16,13 @@ + - - - - + + + + + @@ -37,10 +39,19 @@ - + - - + + + + + + + + + + + diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb index fb7e3aea..459a65bd 100644 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb @@ -46,6 +46,7 @@ '强制刷新 Try CompProjectCache.Clear() + CompFilesCache.Clear() File.Delete(PathTemp & "Cache\LocalMod.json") Log("[Mod] 由于点击刷新按钮,清理本地 Mod 信息缓存") Catch ex As Exception @@ -322,8 +323,65 @@ ''' ''' 安装 Mod。 ''' - 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 + ''' + ''' 尝试安装 Mod。 + ''' 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。 + ''' + 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 + + ''' + ''' 下载 Mod。 + ''' + 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 @@ -522,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 diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb index 0334a386..bc2ed251 100644 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb @@ -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 AndAlso Not JavaList.Count = 0, 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({ @@ -491,6 +491,7 @@ PreFin: 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 & "如果你不会迁移存档,不建议修改这项设置!", diff --git a/Plain Craft Launcher 2/Resources/Help.zip b/Plain Craft Launcher 2/Resources/Help.zip index 972bf25170aff4c12d70b0f0d9fcd9e30984d619..6a3b014104d8bfda03ba57c20bf90f601322d41b 100644 GIT binary patch delta 40070 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 delta 36424 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 From b37c264e32a39fac9c85294c95949acdfd051227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E8=85=BE=E7=8C=AB=E8=B7=83?= <1043137532@qq.com> Date: Sun, 8 Dec 2024 20:58:40 +0800 Subject: [PATCH 6/8] Update PageOtherTest.xaml.vb --- Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml.vb b/Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml.vb index af35b458..041421a7 100644 --- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml.vb @@ -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 "为便于维护,开源内容中不包含百宝箱功能……" From f678dfe8533d2704f39fd0472a2bc2f218edde14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E8=85=BE=E7=8C=AB=E8=B7=83?= <1043137532@qq.com> Date: Sun, 8 Dec 2024 21:11:57 +0800 Subject: [PATCH 7/8] fix: #5238 --- Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb b/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb index 5b03a131..d3bcaf43 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb @@ -96,7 +96,7 @@ '记录当前展开的卡片标题(#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)) From 6ed0c6e4fefa0101be207a54f7f00e798ec688ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E8=85=BE=E7=8C=AB=E8=B7=83?= <1043137532@qq.com> Date: Sun, 8 Dec 2024 22:09:43 +0800 Subject: [PATCH 8/8] =?UTF-8?q?2.8.11=EF=BC=88=E9=87=8D=E6=96=B0=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plain Craft Launcher 2/FormMain.xaml.vb | 2 +- Plain Craft Launcher 2/Modules/Base/ModBase.vb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb index 2c06c45d..da83ab53 100644 --- a/Plain Craft Launcher 2/FormMain.xaml.vb +++ b/Plain Craft Launcher 2/FormMain.xaml.vb @@ -82,7 +82,7 @@ Public Class FormMain '3:BUG+ IMP* FEAT- '2:BUG* IMP- '1:BUG- - If LastVersion < 344 Then 'Snapshot 2.8.11 + 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 diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb index 6155e634..c21918a4 100644 --- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb +++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb @@ -18,7 +18,7 @@ Public Module ModBase #If BETA Then Public Const VersionCode As Integer = 342 'Release #Else - Public Const VersionCode As Integer = 344 'Snapshot + Public Const VersionCode As Integer = 345 'Snapshot #End If '自动生成的版本信息 Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName