Merge branch 'main' into fix/setup-binding
This commit is contained in:
@@ -12,7 +12,7 @@ body:
|
|||||||
required: false
|
required: false
|
||||||
- label: "**我已尝试使用 HMCL 启动,HMCL 没有出现问题。** 如果 HMCL 也无法启动就不是 PCL 导致的问题,请 **不要** 提交反馈。[下载 HMCL](https://hmcl.huangyuhui.net/download)"
|
- label: "**我已尝试使用 HMCL 启动,HMCL 没有出现问题。** 如果 HMCL 也无法启动就不是 PCL 导致的问题,请 **不要** 提交反馈。[下载 HMCL](https://hmcl.huangyuhui.net/download)"
|
||||||
required: true
|
required: true
|
||||||
- label: "我已在 [Issues 页面](https://github.com/Hex-Dragon/PCL2/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Hex-Dragon/PCL2/discussions/1930) 中搜索,确认了这一 Bug 未被提交过。"
|
- label: "我已在 [Issues 页面](https://github.com/Meloong-Git/PCL/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Meloong-Git/PCL/discussions/1930) 中搜索,确认了这一 Bug 未被提交过。"
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: "yml-2"
|
id: "yml-2"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ body:
|
|||||||
required: false
|
required: false
|
||||||
- label: "我知晓大多数此类问题都是网络环境不佳导致的,但我确实认为我的问题可能是 PCL 导致的,和网络环境无关。"
|
- label: "我知晓大多数此类问题都是网络环境不佳导致的,但我确实认为我的问题可能是 PCL 导致的,和网络环境无关。"
|
||||||
required: true
|
required: true
|
||||||
- label: "我已在 [Issues 页面](https://github.com/Hex-Dragon/PCL2/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Hex-Dragon/PCL2/discussions/1930) 中搜索,确认了这一 Bug 未被提交过。"
|
- label: "我已在 [Issues 页面](https://github.com/Meloong-Git/PCL/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Meloong-Git/PCL/discussions/1930) 中搜索,确认了这一 Bug 未被提交过。"
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: "yml-2"
|
id: "yml-2"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ body:
|
|||||||
label: "检查项"
|
label: "检查项"
|
||||||
description: "请逐个检查下列项目,并勾选确认。"
|
description: "请逐个检查下列项目,并勾选确认。"
|
||||||
options:
|
options:
|
||||||
- label: "我已在 [Issues 页面](https://github.com/Hex-Dragon/PCL2/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Hex-Dragon/PCL2/discussions/1930) 中搜索,确认了这一 Bug 未被提交过。"
|
- label: "我已在 [Issues 页面](https://github.com/Meloong-Git/PCL/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Meloong-Git/PCL/discussions/1930) 中搜索,确认了这一 Bug 未被提交过。"
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: "yml-2"
|
id: "yml-2"
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ body:
|
|||||||
label: "检查项"
|
label: "检查项"
|
||||||
description: "请逐个检查下列项目,并勾选确认。"
|
description: "请逐个检查下列项目,并勾选确认。"
|
||||||
options:
|
options:
|
||||||
- label: "我已在 [Issues 页面](https://github.com/Hex-Dragon/PCL2/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Hex-Dragon/PCL2/discussions/1930) 中搜索,确认了这一建议未被提交过。"
|
- label: "我已在 [Issues 页面](https://github.com/Meloong-Git/PCL/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Meloong-Git/PCL/discussions/1930) 中搜索,确认了这一建议未被提交过。"
|
||||||
required: true
|
required: true
|
||||||
- label: "我已查看 [功能投票页面](https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8/),确认了这一建议未在投票列表中。"
|
- label: "我已查看 [功能投票页面](https://github.com/Meloong-Git/PCL/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8/),确认了这一建议未在投票列表中。"
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: "yml-2"
|
id: "yml-2"
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: 主页预设反馈
|
- name: 主页预设反馈
|
||||||
url: https://github.com/Hex-Dragon/PCL2/discussions/categories/自定义主页
|
url: https://github.com/Meloong-Git/PCL/discussions/categories/自定义主页
|
||||||
about: 提交与预设的主页(设置 → 个性化 → 主页预设)中的具体内容相关的反馈
|
about: 提交与预设的主页(设置 → 个性化 → 主页预设)中的具体内容相关的反馈
|
||||||
- name: 帮助文档反馈
|
- name: 帮助文档反馈
|
||||||
url: https://github.com/LTCatt/PCL2Help/issues
|
url: https://github.com/LTCatt/PCL2Help/issues
|
||||||
about: 提交与 PCL 帮助文档(更多 → 帮助)中的具体内容相关的反馈
|
about: 提交与 PCL 帮助文档(更多 → 帮助)中的具体内容相关的反馈
|
||||||
- name: 提问
|
- name: 提问
|
||||||
url: https://github.com/Hex-Dragon/PCL2/discussions/new?category=%E6%8F%90%E9%97%AE
|
url: https://github.com/Meloong-Git/PCL/discussions/new?category=%E6%8F%90%E9%97%AE
|
||||||
about: 我想问一些 PCL 相关的问题……
|
about: 我想问一些 PCL 相关的问题……
|
||||||
- name: 讨论
|
- name: 讨论
|
||||||
url: https://github.com/Hex-Dragon/PCL2/discussions/new?category=%E8%AE%A8%E8%AE%BA
|
url: https://github.com/Meloong-Git/PCL/discussions/new?category=%E8%AE%A8%E8%AE%BA
|
||||||
about: 我想讨论一些 PCL 相关的事情……
|
about: 我想讨论一些 PCL 相关的事情……
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ body:
|
|||||||
label: "检查项"
|
label: "检查项"
|
||||||
description: "请逐个检查下列项目,并勾选确认。"
|
description: "请逐个检查下列项目,并勾选确认。"
|
||||||
options:
|
options:
|
||||||
- label: "我已在 [Issues 页面](https://github.com/Hex-Dragon/PCL2/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Hex-Dragon/PCL2/discussions/1930) 中搜索,确认了这一提案未被提交过。"
|
- label: "我已在 [Issues 页面](https://github.com/Meloong-Git/PCL/issues?q=is%3Aissue+) 和 [常见&难检反馈及问题列表](https://github.com/Meloong-Git/PCL/discussions/1930) 中搜索,确认了这一提案未被提交过。"
|
||||||
required: true
|
required: true
|
||||||
- label: "我已查看 [功能投票页面](https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8/),确认了这一提案未在投票列表中。"
|
- label: "我已查看 [功能投票页面](https://github.com/Meloong-Git/PCL/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8/),确认了这一提案未在投票列表中。"
|
||||||
required: true
|
required: true
|
||||||
- label: "我知晓还没做的新功能真的太多了,忙不过来,所以新功能提案几乎不会被处理,也不建议再提交新功能提案 qwq……"
|
- label: "我知晓还没做的新功能真的太多了,忙不过来,所以新功能提案几乎不会被处理,也不建议再提交新功能提案 qwq……"
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Update Help
|
- name: Update Help
|
||||||
run: |
|
run: |
|
||||||
$workpath = [System.Environment]::CurrentDirectory
|
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
git clone https://github.com/LTCatt/PCL2Help.git -b master --single-branch --depth 1
|
git clone https://github.com/LTCatt/PCL2Help.git -b master --single-branch --depth 1
|
||||||
Set-Location PCL2Help
|
Set-Location PCL2Help
|
||||||
@@ -52,8 +51,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Replace
|
- name: Replace
|
||||||
run: |
|
run: |
|
||||||
(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 OAuthClientId As String = If(Environment.GetEnvironmentVariable("PCL_MS_CLIENT_ID"), "")', 'Public OAuthClientId As String = If(Environment.GetEnvironmentVariable("PCL_MS_CLIENT_ID"), "${{ 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\ModSecret.vb") -replace 'Public CurseForgeAPIKey As String = If(Environment.GetEnvironmentVariable("PCL_CURSEFORGE_API_KEY"), "")', 'Public CurseForgeAPIKey As String = If(Environment.GetEnvironmentVariable("PCL_CURSEFORGE_API_KEY"), "${{ 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"
|
(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"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
@@ -44,6 +44,6 @@
|
|||||||
这些规则主要是为了阻止恶意的使用和 “山寨版” 的出现,常规、善意的使用都没啥问题的,放心吧!
|
这些规则主要是为了阻止恶意的使用和 “山寨版” 的出现,常规、善意的使用都没啥问题的,放心吧!
|
||||||
|
|
||||||
如果你只是参考了一小段代码,署个名就行啦,不用担心。
|
如果你只是参考了一小段代码,署个名就行啦,不用担心。
|
||||||
如果对具体细节有疑问,欢迎在 https://github.com/Hex-Dragon/PCL2/discussions/new?category=%E6%8F%90%E9%97%AE 发帖询问!
|
如果对具体细节有疑问,欢迎在 https://github.com/Meloong-Git/PCL/discussions/new?category=%E6%8F%90%E9%97%AE 发帖询问!
|
||||||
|
|
||||||
多谢大家啦!
|
多谢大家啦!
|
||||||
|
|||||||
@@ -30,6 +30,10 @@
|
|||||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
||||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
|
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="13.0.0.0"/>
|
||||||
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Application x:Class="Application"
|
<Application x:Class="Application"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:behaviors="clr-namespace:PCL.Controls.Behaviors"
|
||||||
xmlns:local="clr-namespace:PCL"
|
xmlns:local="clr-namespace:PCL"
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||||
StartupUri="FormMain.xaml"
|
StartupUri="FormMain.xaml"
|
||||||
@@ -302,6 +303,7 @@
|
|||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Setter Property="behaviors:ClipboardInterceptor.EnableSafeClipboard" Value="True" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="PasswordBox">
|
<Style TargetType="PasswordBox">
|
||||||
<Setter Property="FontSize" Value="13" />
|
<Setter Property="FontSize" Value="13" />
|
||||||
@@ -343,6 +345,7 @@
|
|||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Setter Property="behaviors:ClipboardInterceptor.EnableSafeClipboard" Value="True" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<!-- ComboBox -->
|
<!-- ComboBox -->
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ WaitRetry:
|
|||||||
ServicePointManager.Expect100Continue = True
|
ServicePointManager.Expect100Continue = True
|
||||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 Or SecurityProtocolType.Tls Or SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls12
|
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 Or SecurityProtocolType.Tls Or SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls12
|
||||||
ServicePointManager.DefaultConnectionLimit = 1024
|
ServicePointManager.DefaultConnectionLimit = 1024
|
||||||
|
ServicePointManager.UseNagleAlgorithm = False
|
||||||
'计时
|
'计时
|
||||||
Log("[Start] 第一阶段加载用时:" & GetTimeTick() - ApplicationStartTick & " ms")
|
Log("[Start] 第一阶段加载用时:" & GetTimeTick() - ApplicationStartTick & " ms")
|
||||||
ApplicationStartTick = GetTimeTick()
|
ApplicationStartTick = GetTimeTick()
|
||||||
@@ -181,53 +182,29 @@ WaitRetry:
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'动态 DLL 调用
|
'动态 DLL 调用
|
||||||
Private Shared AssemblyNAudio As Assembly
|
|
||||||
Private Shared AssemblyJson As Assembly
|
|
||||||
Private Shared AssemblyDialog As Assembly
|
|
||||||
Private Shared AssemblyImazenWebp As Assembly
|
|
||||||
Private Shared ReadOnly AssemblyNAudioLock As New Object
|
|
||||||
Private Shared ReadOnly AssemblyJsonLock As New Object
|
|
||||||
Private Shared ReadOnly AssemblyDialogLock As New Object
|
|
||||||
Private Shared ReadOnly AssemblyImazenWebpLock As New Object
|
|
||||||
Private Declare Function SetDllDirectory Lib "kernel32" Alias "SetDllDirectoryA" (lpPathName As String) As Boolean
|
Private Declare Function SetDllDirectory Lib "kernel32" Alias "SetDllDirectoryA" (lpPathName As String) As Boolean
|
||||||
Public Shared Function AssemblyResolve(sender As Object, args As ResolveEventArgs) As Assembly
|
Public Shared Function AssemblyResolve(sender As Object, Args As ResolveEventArgs) As Assembly
|
||||||
If args.Name.StartsWithF("NAudio") Then
|
'缓存
|
||||||
SyncLock AssemblyNAudioLock
|
Static Prefixes As String() = {"NAudio", "Newtonsoft.Json", "Ookii.Dialogs.Wpf", "Imazen.WebP", "CacheCow.Common", "CacheCow.Client.FileStore", "CacheCow.Client", "System.Net.Http.Formatting"}
|
||||||
If AssemblyNAudio Is Nothing Then
|
Static Locks As New Dictionary(Of String, Object)(StringComparer.Ordinal)
|
||||||
Log("[Start] 加载 DLL:NAudio")
|
Static LoadedAssembly As New Dictionary(Of String, Assembly)(StringComparer.Ordinal)
|
||||||
AssemblyNAudio = Assembly.Load(GetResources("NAudio"))
|
'查找对应的 DLL
|
||||||
End If
|
Dim Prefix As String = Prefixes.FirstOrDefault(Function(p) Args.Name.StartsWithF(p))
|
||||||
Return AssemblyNAudio
|
If Prefix Is Nothing Then Return Nothing
|
||||||
End SyncLock
|
'加载 DLL
|
||||||
ElseIf args.Name.StartsWithF("Newtonsoft.Json") Then
|
If Not Locks.ContainsKey(Prefix) Then Locks(Prefix) = New Object()
|
||||||
SyncLock AssemblyJsonLock
|
SyncLock Locks(Prefix)
|
||||||
If AssemblyJson Is Nothing Then
|
If Not LoadedAssembly.ContainsKey(Prefix) Then
|
||||||
Log("[Start] 加载 DLL:Json")
|
Log($"[Start] 加载 DLL:{Prefix}")
|
||||||
AssemblyJson = Assembly.Load(GetResources("Json"))
|
LoadedAssembly(Prefix) = Assembly.Load(GetResources(Prefix))
|
||||||
End If
|
'WebP 特判
|
||||||
Return AssemblyJson
|
If Prefix = "Imazen.WebP" Then
|
||||||
End SyncLock
|
SetDllDirectory(PathPure.TrimEnd("\"c))
|
||||||
ElseIf args.Name.StartsWithF("Ookii.Dialogs.Wpf") Then
|
|
||||||
SyncLock AssemblyDialogLock
|
|
||||||
If AssemblyDialog Is Nothing Then
|
|
||||||
Log("[Start] 加载 DLL:Dialogs")
|
|
||||||
AssemblyDialog = Assembly.Load(GetResources("Dialogs"))
|
|
||||||
End If
|
|
||||||
Return AssemblyDialog
|
|
||||||
End SyncLock
|
|
||||||
ElseIf args.Name.StartsWithF("Imazen.WebP") Then
|
|
||||||
SyncLock AssemblyImazenWebpLock
|
|
||||||
If AssemblyImazenWebp Is Nothing Then
|
|
||||||
Log("[Start] 加载 DLL:Imazen.WebP")
|
|
||||||
AssemblyImazenWebp = Assembly.Load(GetResources("Imazen_WebP"))
|
|
||||||
SetDllDirectory(PathPure.TrimEnd("\"))
|
|
||||||
WriteFile(PathPure & "libwebp.dll", GetResources("libwebp64"))
|
WriteFile(PathPure & "libwebp.dll", GetResources("libwebp64"))
|
||||||
End If
|
End If
|
||||||
Return AssemblyImazenWebp
|
|
||||||
End SyncLock
|
|
||||||
Else
|
|
||||||
Return Nothing
|
|
||||||
End If
|
End If
|
||||||
|
Return LoadedAssembly(Prefix)
|
||||||
|
End SyncLock
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
'切换窗口
|
'切换窗口
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
' Author: uye (owner of the MaaAssistantArknights team)
|
||||||
|
' Original Source: MaaAssistantArknights project - https://github.com/MaaAssistantArknights/MaaAssistantArknights
|
||||||
|
' License: Apache License 2.0 (this file only)
|
||||||
|
'
|
||||||
|
' This file is originally developed for MaaAssistantArknights and licensed under AGPL v3.0.
|
||||||
|
' As the original author and copyright holder,
|
||||||
|
' I hereby re-license this file under the Apache License 2.0 for use in the Plain Craft Launcher project.
|
||||||
|
'
|
||||||
|
' This file is contributed under the spirit of good faith and open cooperation.
|
||||||
|
' It does not implement any core launcher functions of PCL.
|
||||||
|
'
|
||||||
|
' Description:
|
||||||
|
' Provides a WPF clipboard handling fix to avoid OpenClipboard exceptions
|
||||||
|
' in TextBox, RichTextBox, and DataGrid under Windows focus issues or clipboard hooks.
|
||||||
|
'
|
||||||
|
' Date: 2025-07-03
|
||||||
|
|
||||||
|
Imports System.Windows
|
||||||
|
Imports System.Windows.Controls
|
||||||
|
Imports System.Windows.Input
|
||||||
|
Imports System.Windows.Documents
|
||||||
|
Imports System.Linq
|
||||||
|
|
||||||
|
Namespace Controls.Behaviors
|
||||||
|
Public NotInheritable Class ClipboardInterceptor
|
||||||
|
Private Sub New()
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Shared ReadOnly EnableSafeClipboardProperty As DependencyProperty =
|
||||||
|
DependencyProperty.RegisterAttached("EnableSafeClipboard", GetType(Boolean), GetType(ClipboardInterceptor),
|
||||||
|
New PropertyMetadata(False, AddressOf OnEnableSafeClipboardChanged))
|
||||||
|
|
||||||
|
Public Shared Sub SetEnableSafeClipboard(element As DependencyObject, value As Boolean)
|
||||||
|
element.SetValue(EnableSafeClipboardProperty, value)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Shared Function GetEnableSafeClipboard(element As DependencyObject) As Boolean
|
||||||
|
Return CBool(element.GetValue(EnableSafeClipboardProperty))
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Private Shared Sub OnEnableSafeClipboardChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
|
||||||
|
If TypeOf d Is TextBox AndAlso CBool(e.NewValue) Then
|
||||||
|
AddCommandBindingsToTextBox(DirectCast(d, TextBox))
|
||||||
|
ElseIf TypeOf d Is RichTextBox AndAlso CBool(e.NewValue) Then
|
||||||
|
AddCommandBindingsToRichTextBox(DirectCast(d, RichTextBox))
|
||||||
|
ElseIf TypeOf d Is DataGrid AndAlso CBool(e.NewValue) Then
|
||||||
|
AddCommandBindingsToDataGrid(DirectCast(d, DataGrid))
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub AddCommandBindingsToTextBox(tb As TextBox)
|
||||||
|
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyTextBox))
|
||||||
|
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutTextBox))
|
||||||
|
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteTextBox))
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub AddCommandBindingsToRichTextBox(rtb As RichTextBox)
|
||||||
|
rtb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyRichTextBox))
|
||||||
|
rtb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutRichTextBox))
|
||||||
|
rtb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteRichTextBox))
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub AddCommandBindingsToDataGrid(dg As DataGrid)
|
||||||
|
dg.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyDataGrid))
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnCopyTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim tb = TryCast(sender, TextBox)
|
||||||
|
If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
|
||||||
|
|
||||||
|
Try
|
||||||
|
Forms.Clipboard.Clear()
|
||||||
|
Forms.Clipboard.SetDataObject(tb.SelectedText, True)
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnCutTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim tb = TryCast(sender, TextBox)
|
||||||
|
If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
|
||||||
|
|
||||||
|
Try
|
||||||
|
Forms.Clipboard.Clear()
|
||||||
|
Forms.Clipboard.SetDataObject(tb.SelectedText, True)
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
|
||||||
|
tb.SelectedText = String.Empty
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnPasteTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim tb = TryCast(sender, TextBox)
|
||||||
|
If tb Is Nothing Then Return
|
||||||
|
|
||||||
|
If Forms.Clipboard.ContainsText() Then
|
||||||
|
Dim pasteText = Forms.Clipboard.GetText()
|
||||||
|
Dim start = tb.SelectionStart
|
||||||
|
|
||||||
|
tb.SelectedText = pasteText
|
||||||
|
tb.CaretIndex = start + pasteText.Length
|
||||||
|
tb.SelectionLength = 0
|
||||||
|
End If
|
||||||
|
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnCopyRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim rtb = TryCast(sender, RichTextBox)
|
||||||
|
If rtb Is Nothing Then Return
|
||||||
|
|
||||||
|
Dim textRange = New TextRange(rtb.Selection.Start, rtb.Selection.End)
|
||||||
|
If String.IsNullOrEmpty(textRange.Text) Then Return
|
||||||
|
|
||||||
|
Try
|
||||||
|
Forms.Clipboard.Clear()
|
||||||
|
Forms.Clipboard.SetDataObject(textRange.Text, True)
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnCutRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim rtb = TryCast(sender, RichTextBox)
|
||||||
|
If rtb Is Nothing Then Return
|
||||||
|
|
||||||
|
Dim selection = New TextRange(rtb.Selection.Start, rtb.Selection.End)
|
||||||
|
If String.IsNullOrEmpty(selection.Text) Then Return
|
||||||
|
|
||||||
|
Try
|
||||||
|
Forms.Clipboard.Clear()
|
||||||
|
Forms.Clipboard.SetDataObject(selection.Text, True)
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
|
||||||
|
selection.Text = String.Empty
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnPasteRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim rtb = TryCast(sender, RichTextBox)
|
||||||
|
If rtb Is Nothing Then Return
|
||||||
|
|
||||||
|
If Not Forms.Clipboard.ContainsText() Then Return
|
||||||
|
|
||||||
|
Dim pasteText = Forms.Clipboard.GetText()
|
||||||
|
Dim selection = rtb.Selection
|
||||||
|
|
||||||
|
selection.Text = pasteText
|
||||||
|
|
||||||
|
Dim caretPos = selection.End
|
||||||
|
rtb.CaretPosition = caretPos
|
||||||
|
rtb.Selection.Select(caretPos, caretPos)
|
||||||
|
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub OnCopyDataGrid(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
|
Dim dg = TryCast(sender, DataGrid)
|
||||||
|
If dg Is Nothing OrElse dg.SelectedCells Is Nothing OrElse dg.SelectedCells.Count = 0 Then Return
|
||||||
|
|
||||||
|
Dim sb = New System.Text.StringBuilder()
|
||||||
|
Dim rowGroups = dg.SelectedCells.GroupBy(Function(c) c.Item)
|
||||||
|
|
||||||
|
For Each row In rowGroups
|
||||||
|
Dim rowText = String.Join(vbTab, row.Select(Function(cell)
|
||||||
|
Dim tb = TryCast(cell.Column.GetCellContent(cell.Item), TextBlock)
|
||||||
|
Return If(tb IsNot Nothing, tb.Text, "")
|
||||||
|
End Function))
|
||||||
|
sb.AppendLine(rowText)
|
||||||
|
Next
|
||||||
|
|
||||||
|
Dim sbStr = sb.ToString().TrimEnd(ControlChars.Cr, ControlChars.Lf)
|
||||||
|
|
||||||
|
Try
|
||||||
|
Forms.Clipboard.Clear()
|
||||||
|
Forms.Clipboard.SetDataObject(sbStr, True)
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
MainGrid.Children.Add(MainSwap)
|
MainGrid.Children.Add(MainSwap)
|
||||||
End If
|
End If
|
||||||
'改变默认的折叠
|
'改变默认的折叠
|
||||||
If IsSwaped AndAlso SwapControl IsNot Nothing Then
|
If IsSwapped AndAlso SwapControl IsNot Nothing Then
|
||||||
MainSwap.RenderTransform = New RotateTransform(If(SwapLogoRight, 270, 0))
|
MainSwap.RenderTransform = New RotateTransform(If(SwapLogoRight, 270, 0))
|
||||||
'取消由于高度变化被迫触发的高度动画
|
'取消由于高度变化被迫触发的高度动画
|
||||||
Dim RawUseAnimation As Boolean = UseAnimation
|
Dim RawUseAnimation As Boolean = UseAnimation
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
Private ActualUsedHeight As Double '回滚实际高度(例如 NaN)
|
Private ActualUsedHeight As Double '回滚实际高度(例如 NaN)
|
||||||
Private Sub MySizeChanged(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
|
Private Sub MySizeChanged(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
|
||||||
If Not UseAnimation Then Return
|
If Not UseAnimation Then Return
|
||||||
Dim DeltaHeight As Double = If(IsSwaped, SwapedHeight, e.NewSize.Height) - e.PreviousSize.Height
|
Dim DeltaHeight As Double = If(IsSwapped, SwapedHeight, e.NewSize.Height) - e.PreviousSize.Height
|
||||||
'卡片的进入时动画已被页面通用切换动画替代
|
'卡片的进入时动画已被页面通用切换动画替代
|
||||||
If e.PreviousSize.Height = 0 OrElse IsHeightAnimating OrElse Math.Abs(DeltaHeight) < 1 OrElse ActualHeight = 0 Then Return
|
If e.PreviousSize.Height = 0 OrElse IsHeightAnimating OrElse Math.Abs(DeltaHeight) < 1 OrElse ActualHeight = 0 Then Return
|
||||||
StartHeightAnimation(DeltaHeight, e.PreviousSize.Height, False)
|
StartHeightAnimation(DeltaHeight, e.PreviousSize.Height, False)
|
||||||
@@ -269,18 +269,18 @@
|
|||||||
Sub()
|
Sub()
|
||||||
IsHeightAnimating = False
|
IsHeightAnimating = False
|
||||||
Height = ActualUsedHeight
|
Height = ActualUsedHeight
|
||||||
If IsSwaped AndAlso SwapControl IsNot Nothing Then SwapControl.Visibility = Visibility.Collapsed
|
If IsSwapped AndAlso SwapControl IsNot Nothing Then SwapControl.Visibility = Visibility.Collapsed
|
||||||
End Sub,, True))
|
End Sub,, True))
|
||||||
AniStart(AnimList, "MyCard Height " & Uuid)
|
AniStart(AnimList, "MyCard Height " & Uuid)
|
||||||
IsHeightAnimating = True
|
IsHeightAnimating = True
|
||||||
ActualUsedHeight = If(IsSwaped, SwapedHeight, Height)
|
ActualUsedHeight = If(IsSwapped, SwapedHeight, Height)
|
||||||
Height = PreviousHeight
|
Height = PreviousHeight
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 通知 MyCard,控件内容已改变,需要中断动画并更新高度。
|
''' 通知 MyCard,控件内容已改变,需要中断动画并更新高度。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub TriggerForceResize()
|
Public Sub TriggerForceResize()
|
||||||
Height = If(IsSwaped, SwapedHeight, Double.NaN)
|
Height = If(IsSwapped, SwapedHeight, Double.NaN)
|
||||||
AniStop("MyCard Height " & Uuid)
|
AniStop("MyCard Height " & Uuid)
|
||||||
IsHeightAnimating = False
|
IsHeightAnimating = False
|
||||||
End Sub
|
End Sub
|
||||||
@@ -300,26 +300,45 @@
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 是否已被折叠。
|
''' 是否已被折叠。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Property IsSwaped As Boolean
|
Public Property IsSwapped As Boolean
|
||||||
Get
|
Get
|
||||||
Return _IsSwaped
|
Return _IsSwapped
|
||||||
End Get
|
End Get
|
||||||
Set(value As Boolean)
|
Set(value As Boolean)
|
||||||
If _IsSwaped = value Then Return
|
If _IsSwapped = value Then Return
|
||||||
_IsSwaped = value
|
_IsSwapped = value
|
||||||
If SwapControl Is Nothing Then Return
|
If SwapControl Is Nothing Then Return
|
||||||
'展开
|
'展开
|
||||||
If Not IsSwaped AndAlso TypeOf SwapControl Is StackPanel Then StackInstall(SwapControl, SwapType, Title)
|
If Not IsSwapped AndAlso TypeOf SwapControl Is StackPanel Then StackInstall(SwapControl, SwapType, Title)
|
||||||
'若尚未加载,会在 Loaded 事件中触发无动画的折叠,不需要在这里进行
|
'若尚未加载,会在 Loaded 事件中触发无动画的折叠,不需要在这里进行
|
||||||
If Not IsLoaded Then Return
|
If Not IsLoaded Then Return
|
||||||
'更新高度
|
'更新高度
|
||||||
SwapControl.Visibility = Visibility.Visible
|
SwapControl.Visibility = Visibility.Visible
|
||||||
TriggerForceResize()
|
TriggerForceResize()
|
||||||
'改变箭头
|
'改变箭头
|
||||||
AniStart(AaRotateTransform(MainSwap, If(_IsSwaped, If(SwapLogoRight, 270, 0), 180) - CType(MainSwap.RenderTransform, RotateTransform).Angle, 250,, New AniEaseOutFluent(AniEasePower.ExtraStrong)), "MyCard Swap " & Uuid, True)
|
AniStart(AaRotateTransform(MainSwap, If(_IsSwapped, If(SwapLogoRight, 270, 0), 180) - CType(MainSwap.RenderTransform, RotateTransform).Angle, 250,, New AniEaseOutFluent(AniEasePower.ExtraStrong)), "MyCard Swap " & Uuid, True)
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
Private _IsSwaped As Boolean = False
|
Private _IsSwapped As Boolean = False
|
||||||
|
''' <summary>
|
||||||
|
''' 是否已被折叠。(已过时,请使用 IsSwapped)
|
||||||
|
''' </summary>
|
||||||
|
<Obsolete("IsSwaped 存在拼写错误,请换用 IsSwapped 属性。")>
|
||||||
|
Public Property IsSwaped As Boolean
|
||||||
|
Get
|
||||||
|
Return GetValue(IsSwapedProperty)
|
||||||
|
End Get
|
||||||
|
Set(value As Boolean)
|
||||||
|
SetValue(IsSwapedProperty, value)
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Public Shared ReadOnly IsSwapedProperty As DependencyProperty = DependencyProperty.Register("IsSwaped", GetType(Boolean), GetType(MyCard), New PropertyMetadata(False, AddressOf OnIsSwapedPropertyChanged))
|
||||||
|
Private Shared Sub OnIsSwapedPropertyChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
|
||||||
|
Dim self = TryCast(d, MyCard)
|
||||||
|
If self IsNot Nothing Then
|
||||||
|
self.IsSwapped = CType(e.NewValue, Boolean)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
Public Property SwapLogoRight As Boolean = False
|
Public Property SwapLogoRight As Boolean = False
|
||||||
Private IsMouseDown As Boolean = False
|
Private IsMouseDown As Boolean = False
|
||||||
@@ -328,8 +347,8 @@
|
|||||||
Public Const SwapedHeight As Integer = 40
|
Public Const SwapedHeight As Integer = 40
|
||||||
Private Sub MyCard_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
|
Private Sub MyCard_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
|
||||||
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
||||||
If Not IsSwaped AndAlso
|
If Not IsSwapped AndAlso
|
||||||
(SwapControl Is Nothing OrElse Pos > If(IsSwaped, SwapedHeight, SwapedHeight - 6) OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Return '检测点击位置;或已经不在可视树上的误判
|
(SwapControl Is Nothing OrElse Pos > If(IsSwapped, SwapedHeight, SwapedHeight - 6) OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Return '检测点击位置;或已经不在可视树上的误判
|
||||||
IsMouseDown = True
|
IsMouseDown = True
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub MyCard_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
|
Private Sub MyCard_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
|
||||||
@@ -337,8 +356,8 @@
|
|||||||
IsMouseDown = False
|
IsMouseDown = False
|
||||||
|
|
||||||
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
Dim Pos As Double = Mouse.GetPosition(Me).Y
|
||||||
If Not IsSwaped AndAlso
|
If Not IsSwapped AndAlso
|
||||||
(SwapControl Is Nothing OrElse Pos > If(IsSwaped, SwapedHeight, SwapedHeight - 6) OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Return '检测点击位置;或已经不在可视树上的误判
|
(SwapControl Is Nothing OrElse Pos > If(IsSwapped, SwapedHeight, SwapedHeight - 6) OrElse (Pos = 0 AndAlso Not IsMouseDirectlyOver)) Then Return '检测点击位置;或已经不在可视树上的误判
|
||||||
|
|
||||||
Dim ee = New RouteEventArgs(True)
|
Dim ee = New RouteEventArgs(True)
|
||||||
RaiseEvent PreviewSwap(Me, ee)
|
RaiseEvent PreviewSwap(Me, ee)
|
||||||
@@ -347,8 +366,8 @@
|
|||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
|
|
||||||
IsSwaped = Not IsSwaped
|
IsSwapped = Not IsSwapped
|
||||||
Log("[Control] " & If(IsSwaped, "折叠卡片", "展开卡片") & If(Title Is Nothing, "", ":" & Title))
|
Log("[Control] " & If(IsSwapped, "折叠卡片", "展开卡片") & If(Title Is Nothing, "", ":" & Title))
|
||||||
RaiseEvent Swap(Me, ee)
|
RaiseEvent Swap(Me, ee)
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub MyCard_MouseLeave_Swap(sender As Object, e As MouseEventArgs) Handles Me.MouseLeave
|
Private Sub MyCard_MouseLeave_Swap(sender As Object, e As MouseEventArgs) Handles Me.MouseLeave
|
||||||
|
|||||||
@@ -264,7 +264,7 @@
|
|||||||
If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
|
If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
|
||||||
'有动画
|
'有动画
|
||||||
AniStart({
|
AniStart({
|
||||||
AaColor(Me, BorderBrushProperty, ForeColorName, AnimationTime),
|
AaColor(Me, BorderBrushProperty, ForeColorName, AnimationTime),
|
||||||
AaColor(Me, BackgroundProperty, BackColorName, AnimationTime)
|
AaColor(Me, BackgroundProperty, BackColorName, AnimationTime)
|
||||||
}, "MyTextBox Color " & Uuid)
|
}, "MyTextBox Color " & Uuid)
|
||||||
Else
|
Else
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
Private Const AnimationTimeIn As Integer = 100
|
Private Const AnimationTimeIn As Integer = 100
|
||||||
Private Const AnimationTimeOut As Integer = 200
|
Private Const AnimationTimeOut As Integer = 200
|
||||||
Private ColorName As String
|
Private ColorName As String
|
||||||
Private Sub RefreshColor() Handles Me.MouseEnter, Me.MouseLeave, Me.IsEnabledChanged, Me.MouseLeftButtonDown, Me.MouseLeftButtonUp
|
Private Sub RefreshColor() Handles Me.MouseEnter, Me.MouseLeave, Me.IsEnabledChanged, Me.MouseLeftButtonDown, Me.MouseLeftButtonUp
|
||||||
'判断当前颜色
|
'判断当前颜色
|
||||||
Dim ForeName As String
|
Dim ForeName As String
|
||||||
Dim Time As Integer
|
Dim Time As Integer
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Imports System.ComponentModel
|
Imports System.ComponentModel
|
||||||
|
Imports System.Windows.Interop
|
||||||
|
|
||||||
Public Class FormMain
|
Public Class FormMain
|
||||||
|
|
||||||
@@ -10,6 +11,19 @@ Public Class FormMain
|
|||||||
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
||||||
'统计更新日志条目
|
'统计更新日志条目
|
||||||
#If BETA Then
|
#If BETA Then
|
||||||
|
If LastVersion < 367 Then 'Release 2.10.6
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:启用 MCIM 社区资源镜像源,以缓解社区资源难以下载的问题"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:正版登录出错时无法给出正确的错误信息"))
|
||||||
|
FeatureCount += 9
|
||||||
|
BugCount += 9
|
||||||
|
End If
|
||||||
|
If LastVersion < 365 Then 'Release 2.10.5
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:下载资源时,会单独记忆每种资源上次下载到的文件夹,以防混淆"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:网络底层框架与下载稳定性"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:无法启动一部分 LabyMod 和 GTNH 客户端"))
|
||||||
|
FeatureCount += 22
|
||||||
|
BugCount += 26
|
||||||
|
End If
|
||||||
If LastVersion < 361 Then 'Release 2.10.3
|
If LastVersion < 361 Then 'Release 2.10.3
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法安装部分使用老版本 PCL 导出的整合包"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法安装部分使用老版本 PCL 导出的整合包"))
|
||||||
End If
|
End If
|
||||||
@@ -82,6 +96,25 @@ Public Class FormMain
|
|||||||
'3:BUG+ IMP* FEAT-
|
'3:BUG+ IMP* FEAT-
|
||||||
'2:BUG* IMP-
|
'2:BUG* IMP-
|
||||||
'1:BUG-
|
'1:BUG-
|
||||||
|
If LastVersion < 366 Then 'Snapshot 2.10.6
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:启用 MCIM 社区资源镜像源,以缓解社区资源难以下载的问题"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:正版登录出错时无法给出正确的错误信息"))
|
||||||
|
FeatureCount += 9
|
||||||
|
BugCount += 9
|
||||||
|
End If
|
||||||
|
If LastVersion < 364 Then 'Snapshot 2.10.5
|
||||||
|
If LastVersion >= 363 Then
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:无法添加新的正版账号"))
|
||||||
|
BugCount += 1
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
If LastVersion < 363 Then 'Snapshot 2.10.4
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:下载资源时,会单独记忆每种资源上次下载到的文件夹,以防混淆"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:网络底层框架与下载稳定性"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:无法启动一部分 LabyMod 和 GTNH 客户端"))
|
||||||
|
FeatureCount += 22
|
||||||
|
BugCount += 26
|
||||||
|
End If
|
||||||
If LastVersion < 362 Then 'Snapshot 2.10.3
|
If LastVersion < 362 Then 'Snapshot 2.10.3
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法安装部分使用老版本 PCL 导出的整合包"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法安装部分使用老版本 PCL 导出的整合包"))
|
||||||
End If
|
End If
|
||||||
@@ -225,7 +258,7 @@ Public Class FormMain
|
|||||||
If Not Setup.IsUnset("LaunchArgumentIndie") Then
|
If Not Setup.IsUnset("LaunchArgumentIndie") Then
|
||||||
Log("[Start] 从老 PCL 迁移版本隔离")
|
Log("[Start] 从老 PCL 迁移版本隔离")
|
||||||
Setup.Set("LaunchArgumentIndieV2", Setup.Get("LaunchArgumentIndie"))
|
Setup.Set("LaunchArgumentIndieV2", Setup.Get("LaunchArgumentIndie"))
|
||||||
ElseIf Not Setup.IsUnset("WindowHeight") Then
|
ElseIf Not Setup.IsUnset("LaunchVersionSelect") Then
|
||||||
Log("[Start] 从老 PCL 升级,但此前未调整版本隔离,使用老的版本隔离默认值")
|
Log("[Start] 从老 PCL 升级,但此前未调整版本隔离,使用老的版本隔离默认值")
|
||||||
Setup.Set("LaunchArgumentIndieV2", Setup.GetDefault("LaunchArgumentIndie"))
|
Setup.Set("LaunchArgumentIndieV2", Setup.GetDefault("LaunchArgumentIndie"))
|
||||||
Else
|
Else
|
||||||
@@ -242,13 +275,18 @@ Public Class FormMain
|
|||||||
'加载 UI
|
'加载 UI
|
||||||
InitializeComponent()
|
InitializeComponent()
|
||||||
Opacity = 0
|
Opacity = 0
|
||||||
''开启管理员权限下的文件拖拽,但下列代码也没用(#2531)
|
'开启管理员权限下的文件拖拽
|
||||||
'If IsAdmin() Then
|
If IsAdmin() Then
|
||||||
' Log("[Start] PCL 正以管理员权限运行")
|
Static Helper As New DragHelper
|
||||||
' ChangeWindowMessageFilter(&H233, 1)
|
AddHandler SourceInitialized,
|
||||||
' ChangeWindowMessageFilter(&H4A, 1)
|
Sub()
|
||||||
' ChangeWindowMessageFilter(&H49, 1)
|
Dim WpfHelper As New WindowInteropHelper(Me)
|
||||||
'End If
|
Helper.HwndIntPtrSource = HwndSource.FromHwnd(WpfHelper.Handle)
|
||||||
|
Helper.AddHook()
|
||||||
|
End Sub
|
||||||
|
AddHandler Closing, Sub() Helper.RemoveDragHook()
|
||||||
|
AddHandler Helper.DragDrop, Sub() FileDrag(Helper.DropFilePaths)
|
||||||
|
End If
|
||||||
'切换到首页
|
'切换到首页
|
||||||
If Not IsNothing(FrmLaunchLeft.Parent) Then FrmLaunchLeft.SetValue(ContentPresenter.ContentProperty, Nothing)
|
If Not IsNothing(FrmLaunchLeft.Parent) Then FrmLaunchLeft.SetValue(ContentPresenter.ContentProperty, Nothing)
|
||||||
If Not IsNothing(FrmLaunchRight.Parent) Then FrmLaunchRight.SetValue(ContentPresenter.ContentProperty, Nothing)
|
If Not IsNothing(FrmLaunchRight.Parent) Then FrmLaunchRight.SetValue(ContentPresenter.ContentProperty, Nothing)
|
||||||
@@ -365,7 +403,9 @@ Public Class FormMain
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "清理自动更新文件失败")
|
Log(ex, "清理自动更新文件失败")
|
||||||
End Try
|
End Try
|
||||||
End Sub, "Start Loader", ThreadPriority.Lowest)
|
'上报
|
||||||
|
Telemetry("启动")
|
||||||
|
End Sub, "初始化", ThreadPriority.Lowest)
|
||||||
|
|
||||||
Log("[Start] 第三阶段加载用时:" & GetTimeTick() - ApplicationStartTick & " ms")
|
Log("[Start] 第三阶段加载用时:" & GetTimeTick() - ApplicationStartTick & " ms")
|
||||||
End Sub
|
End Sub
|
||||||
@@ -540,7 +580,7 @@ Public Class FormMain
|
|||||||
If ReturnCode = ProcessReturnValues.Exception Then
|
If ReturnCode = ProcessReturnValues.Exception Then
|
||||||
If Not IsLogShown Then
|
If Not IsLogShown Then
|
||||||
FeedbackInfo()
|
FeedbackInfo()
|
||||||
Log("请在 https://github.com/Hex-Dragon/PCL2/issues 提交错误报告,以便于作者解决此问题!")
|
Log("请在 https://github.com/Meloong-Git/PCL/issues 提交错误报告,以便于作者解决此问题!")
|
||||||
IsLogShown = True
|
IsLogShown = True
|
||||||
ShellOnly(Path & "PCL\Log1.txt")
|
ShellOnly(Path & "PCL\Log1.txt")
|
||||||
End If
|
End If
|
||||||
@@ -591,11 +631,12 @@ Public Class FormMain
|
|||||||
'按键事件
|
'按键事件
|
||||||
Private Sub FormMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
Private Sub FormMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||||
If e.IsRepeat Then Return
|
If e.IsRepeat Then Return
|
||||||
'调用弹窗:回车选择第一个,Esc 选择最后一个
|
'修复按下 Alt 后误认为弹出系统菜单导致的冻结
|
||||||
If PanMsg.Children.Count > 0 Then
|
If e.SystemKey = Key.LeftAlt OrElse e.SystemKey = Key.RightAlt Then e.Handled = True
|
||||||
|
'在有弹窗时:回车选择第一个,Esc 选择最后一个
|
||||||
|
If PanMsg.Children.Any Then
|
||||||
If e.Key = Key.Enter Then
|
If e.Key = Key.Enter Then
|
||||||
CType(PanMsg.Children(0), Object).Btn1_Click()
|
CType(PanMsg.Children(0), Object).Btn1_Click()
|
||||||
Return
|
|
||||||
ElseIf e.Key = Key.Escape Then
|
ElseIf e.Key = Key.Escape Then
|
||||||
Dim Msg As Object = PanMsg.Children(0)
|
Dim Msg As Object = PanMsg.Children(0)
|
||||||
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
||||||
@@ -605,9 +646,14 @@ Public Class FormMain
|
|||||||
Else
|
Else
|
||||||
Msg.Btn1_Click()
|
Msg.Btn1_Click()
|
||||||
End If
|
End If
|
||||||
|
End If
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
End If
|
|
||||||
|
'==========================
|
||||||
|
' 在没有弹窗时:继续检查……
|
||||||
|
'==========================
|
||||||
|
|
||||||
'按 ESC 返回上一级
|
'按 ESC 返回上一级
|
||||||
If e.Key = Key.Escape Then TriggerPageBack()
|
If e.Key = Key.Escape Then TriggerPageBack()
|
||||||
'更改隐藏版本可见性
|
'更改隐藏版本可见性
|
||||||
@@ -641,8 +687,6 @@ Public Class FormMain
|
|||||||
FrmLaunchLeft.LaunchButtonClick()
|
FrmLaunchLeft.LaunchButtonClick()
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
'修复按下 Alt 后误认为弹出系统菜单导致的冻结
|
|
||||||
If e.SystemKey = Key.LeftAlt OrElse e.SystemKey = Key.RightAlt Then e.Handled = True
|
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub FormMain_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseDown
|
Private Sub FormMain_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseDown
|
||||||
'鼠标侧键返回上一级
|
'鼠标侧键返回上一级
|
||||||
@@ -707,6 +751,7 @@ Public Class FormMain
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub FrmMain_Drop(sender As Object, e As DragEventArgs) Handles Me.Drop
|
Private Sub FrmMain_Drop(sender As Object, e As DragEventArgs) Handles Me.Drop
|
||||||
Try
|
Try
|
||||||
|
ShowWindowToTop()
|
||||||
If e.Data.GetDataPresent(DataFormats.Text) Then
|
If e.Data.GetDataPresent(DataFormats.Text) Then
|
||||||
'获取文本
|
'获取文本
|
||||||
Try
|
Try
|
||||||
@@ -845,7 +890,7 @@ Public Class FormMain
|
|||||||
'错误报告分析
|
'错误报告分析
|
||||||
Try
|
Try
|
||||||
Log("[System] 尝试进行错误报告分析")
|
Log("[System] 尝试进行错误报告分析")
|
||||||
Dim Analyzer As New CrashAnalyzer(GetUuid())
|
Dim Analyzer As New CrashAnalyzer
|
||||||
Analyzer.Import(FilePath)
|
Analyzer.Import(FilePath)
|
||||||
If Not Analyzer.Prepare() Then Exit Try
|
If Not Analyzer.Prepare() Then Exit Try
|
||||||
Analyzer.Analyze()
|
Analyzer.Analyze()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Imports System.Globalization
|
Imports System.Globalization
|
||||||
Imports System.IO.Compression
|
Imports System.IO.Compression
|
||||||
Imports System.Reflection
|
Imports System.Net.Sockets
|
||||||
Imports System.Runtime.CompilerServices
|
Imports System.Runtime.CompilerServices
|
||||||
Imports System.Security.Cryptography
|
Imports System.Security.Cryptography
|
||||||
Imports System.Security.Principal
|
Imports System.Security.Principal
|
||||||
@@ -13,13 +13,13 @@ Public Module ModBase
|
|||||||
#Region "声明"
|
#Region "声明"
|
||||||
|
|
||||||
'下列版本信息由更新器自动修改
|
'下列版本信息由更新器自动修改
|
||||||
Public Const VersionBaseName As String = "2.10.3" '不含分支前缀的显示用版本名
|
Public Const VersionBaseName As String = "2.10.6" '不含分支前缀的显示用版本名
|
||||||
Public Const VersionStandardCode As String = "2.10.3." & VersionBranchCode '标准格式的四段式版本号
|
Public Const VersionStandardCode As String = "2.10.6." & VersionBranchCode '标准格式的四段式版本号
|
||||||
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
||||||
#If BETA Then
|
#If BETA Then
|
||||||
Public Const VersionCode As Integer = 361 'Release
|
Public Const VersionCode As Integer = 367 'Release
|
||||||
#Else
|
#Else
|
||||||
Public Const VersionCode As Integer = 362 'Snapshot
|
Public Const VersionCode As Integer = 366 'Snapshot
|
||||||
#End If
|
#End If
|
||||||
'自动生成的版本信息
|
'自动生成的版本信息
|
||||||
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
||||||
@@ -791,8 +791,8 @@ Public Module ModBase
|
|||||||
Public Sub CopyFile(FromPath As String, ToPath As String)
|
Public Sub CopyFile(FromPath As String, ToPath As String)
|
||||||
Try
|
Try
|
||||||
'还原文件路径
|
'还原文件路径
|
||||||
If Not FromPath.Contains(":\") Then FromPath = Path & FromPath
|
FromPath = ShortenPath(If(FromPath.Contains(":\"), FromPath, Path & FromPath))
|
||||||
If Not ToPath.Contains(":\") Then ToPath = Path & ToPath
|
ToPath = ShortenPath(If(ToPath.Contains(":\"), ToPath, Path & ToPath))
|
||||||
'如果复制同一个文件则跳过
|
'如果复制同一个文件则跳过
|
||||||
If FromPath = ToPath Then Return
|
If FromPath = ToPath Then Return
|
||||||
'确保目录存在
|
'确保目录存在
|
||||||
@@ -861,7 +861,7 @@ Public Module ModBase
|
|||||||
''' <param name="Append">是否将文件内容追加到当前文件,而不是覆盖它。</param>
|
''' <param name="Append">是否将文件内容追加到当前文件,而不是覆盖它。</param>
|
||||||
Public Sub WriteFile(FilePath As String, Text As String, Optional Append As Boolean = False, Optional Encoding As Encoding = Nothing)
|
Public Sub WriteFile(FilePath As String, Text As String, Optional Append As Boolean = False, Optional Encoding As Encoding = Nothing)
|
||||||
'处理相对路径
|
'处理相对路径
|
||||||
If Not FilePath.Contains(":\") Then FilePath = Path & FilePath
|
FilePath = ShortenPath(If(FilePath.Contains(":\"), FilePath, Path & FilePath))
|
||||||
'确保目录存在
|
'确保目录存在
|
||||||
Directory.CreateDirectory(GetPathFromFullPath(FilePath))
|
Directory.CreateDirectory(GetPathFromFullPath(FilePath))
|
||||||
'写入文件
|
'写入文件
|
||||||
@@ -886,7 +886,7 @@ Public Module ModBase
|
|||||||
''' <param name="Append">是否将文件内容追加到当前文件,而不是覆盖它。</param>
|
''' <param name="Append">是否将文件内容追加到当前文件,而不是覆盖它。</param>
|
||||||
Public Sub WriteFile(FilePath As String, Content As Byte(), Optional Append As Boolean = False)
|
Public Sub WriteFile(FilePath As String, Content As Byte(), Optional Append As Boolean = False)
|
||||||
'处理相对路径
|
'处理相对路径
|
||||||
If Not FilePath.Contains(":\") Then FilePath = Path & FilePath
|
FilePath = ShortenPath(If(FilePath.Contains(":\"), FilePath, Path & FilePath))
|
||||||
'确保目录存在
|
'确保目录存在
|
||||||
Directory.CreateDirectory(GetPathFromFullPath(FilePath))
|
Directory.CreateDirectory(GetPathFromFullPath(FilePath))
|
||||||
'写入文件
|
'写入文件
|
||||||
@@ -1294,11 +1294,11 @@ Re:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing,
|
Public Sub ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing,
|
||||||
Optional ProgressIncrementHandler As Action(Of Double) = Nothing)
|
Optional ProgressIncrementHandler As Action(Of Double) = Nothing)
|
||||||
Directory.CreateDirectory(DestDirectory)
|
Directory.CreateDirectory(ShortenPath(DestDirectory))
|
||||||
If CompressFilePath.EndsWithF(".gz", True) Then
|
If CompressFilePath.EndsWithF(".gz", True) Then
|
||||||
'以 gz 方式解压
|
'以 gz 方式解压
|
||||||
Dim stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress)
|
Dim stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress)
|
||||||
Dim decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", ""), FileMode.OpenOrCreate, FileAccess.Write)
|
Dim decompressedFile As New FileStream(ShortenPath(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", "")), FileMode.OpenOrCreate, FileAccess.Write)
|
||||||
Dim data As Integer = stream.ReadByte()
|
Dim data As Integer = stream.ReadByte()
|
||||||
While data <> -1
|
While data <> -1
|
||||||
decompressedFile.WriteByte(data)
|
decompressedFile.WriteByte(data)
|
||||||
@@ -1309,10 +1309,10 @@ Re:
|
|||||||
Else
|
Else
|
||||||
'以 zip 方式解压
|
'以 zip 方式解压
|
||||||
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030")))
|
Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030")))
|
||||||
Dim TotalCount As Integer = Archive.Entries.Count
|
Dim TotalCount As Long = Archive.Entries.Count
|
||||||
For Each Entry As ZipArchiveEntry In Archive.Entries
|
For Each Entry As ZipArchiveEntry In Archive.Entries
|
||||||
If ProgressIncrementHandler IsNot Nothing Then ProgressIncrementHandler(1 / TotalCount)
|
If ProgressIncrementHandler IsNot Nothing AndAlso TotalCount > 0 Then ProgressIncrementHandler(1 / TotalCount)
|
||||||
Dim DestinationPath As String = IO.Path.Combine(DestDirectory, Entry.FullName)
|
Dim DestinationPath As String = ShortenPath(IO.Path.Combine(DestDirectory, Entry.FullName))
|
||||||
If DestinationPath.EndsWithF("\") OrElse DestinationPath.EndsWithF("/") Then
|
If DestinationPath.EndsWithF("\") OrElse DestinationPath.EndsWithF("/") Then
|
||||||
Continue For '不创建空文件夹
|
Continue For '不创建空文件夹
|
||||||
Else
|
Else
|
||||||
@@ -1387,10 +1387,10 @@ RetryDir:
|
|||||||
ToPath = ToPath.Replace("/", "\")
|
ToPath = ToPath.Replace("/", "\")
|
||||||
If Not ToPath.EndsWithF("\") Then ToPath &= "\"
|
If Not ToPath.EndsWithF("\") Then ToPath &= "\"
|
||||||
Dim AllFiles = EnumerateFiles(FromPath).ToList
|
Dim AllFiles = EnumerateFiles(FromPath).ToList
|
||||||
Dim FileCount As Integer = AllFiles.Count
|
Dim FileCount As Long = AllFiles.Count
|
||||||
For Each File In AllFiles
|
For Each File In AllFiles
|
||||||
CopyFile(File.FullName, File.FullName.Replace(FromPath, ToPath))
|
CopyFile(File.FullName, File.FullName.Replace(FromPath, ToPath))
|
||||||
If ProgressIncrementHandler IsNot Nothing Then ProgressIncrementHandler(1 / FileCount)
|
If ProgressIncrementHandler IsNot Nothing AndAlso FileCount > 0 Then ProgressIncrementHandler(1 / FileCount)
|
||||||
Next
|
Next
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -1449,22 +1449,8 @@ RetryDir:
|
|||||||
IsInner = True
|
IsInner = True
|
||||||
Loop
|
Loop
|
||||||
|
|
||||||
'常见错误(记得同时修改下面的)
|
|
||||||
Dim CommonReason As String = Nothing
|
|
||||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
|
||||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
|
||||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
|
||||||
CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
|
||||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
|
||||||
CommonReason = "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
|
|
||||||
ElseIf TypeOf InnerEx Is Runtime.InteropServices.COMException Then
|
|
||||||
CommonReason = "由于操作系统或显卡存在问题,导致出现错误。请尝试重启 PCL。"
|
|
||||||
ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
|
|
||||||
"操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) DescList.Any(Function(l) l.Contains(s))) Then
|
|
||||||
CommonReason = "你的网络环境不佳,导致难以连接到服务器。请稍后重试,或使用 VPN 以改善网络环境。"
|
|
||||||
End If
|
|
||||||
|
|
||||||
'构造输出信息
|
'构造输出信息
|
||||||
|
Dim CommonReason As String = AnalyzeCommonReason(InnerEx, DescList)
|
||||||
If CommonReason Is Nothing Then
|
If CommonReason Is Nothing Then
|
||||||
Return DescList.Join(vbCrLf)
|
Return DescList.Join(vbCrLf)
|
||||||
Else
|
Else
|
||||||
@@ -1492,22 +1478,8 @@ RetryDir:
|
|||||||
DescList = DescList.Distinct.ToList
|
DescList = DescList.Distinct.ToList
|
||||||
Dim Desc As String = Join(DescList, vbCrLf & "→ ")
|
Dim Desc As String = Join(DescList, vbCrLf & "→ ")
|
||||||
|
|
||||||
'常见错误(记得同时修改上面的)
|
|
||||||
Dim CommonReason As String = Nothing
|
|
||||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
|
||||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
|
||||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
|
||||||
CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
|
||||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
|
||||||
CommonReason = "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
|
|
||||||
ElseIf TypeOf InnerEx Is Runtime.InteropServices.COMException Then
|
|
||||||
CommonReason = "由于操作系统或显卡存在问题,导致出现错误。请尝试重启 PCL。"
|
|
||||||
ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
|
|
||||||
"操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
|
|
||||||
CommonReason = "你的网络环境不佳,导致难以连接到服务器。请稍后重试,或使用 VPN 以改善网络环境。"
|
|
||||||
End If
|
|
||||||
|
|
||||||
'构造输出信息
|
'构造输出信息
|
||||||
|
Dim CommonReason As String = AnalyzeCommonReason(InnerEx, DescList)
|
||||||
If CommonReason IsNot Nothing Then
|
If CommonReason IsNot Nothing Then
|
||||||
Return CommonReason & "详细错误:" & DescList.First
|
Return CommonReason & "详细错误:" & DescList.First
|
||||||
Else
|
Else
|
||||||
@@ -1515,6 +1487,24 @@ RetryDir:
|
|||||||
Return Join(DescList, " ← ")
|
Return Join(DescList, " ← ")
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
|
Private Function AnalyzeCommonReason(InnerEx As Exception, DescList As List(Of String)) As String
|
||||||
|
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||||
|
Return "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
||||||
|
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||||
|
Return "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
||||||
|
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||||
|
Return "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
|
||||||
|
ElseIf TypeOf InnerEx Is Runtime.InteropServices.COMException Then
|
||||||
|
Return "由于操作系统或显卡存在问题,导致出现错误。请尝试重启 PCL。"
|
||||||
|
ElseIf TypeOf InnerEx Is SocketException AndAlso DescList.Any(Function(l) l.Contains("WSAStartup")) Then
|
||||||
|
Return "请尝试卸载中国移动云盘,然后再试。"
|
||||||
|
ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
|
||||||
|
"操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) DescList.Any(Function(l) l.Contains(s))) Then
|
||||||
|
Return "你的网络环境不佳,导致难以连接到服务器。请稍后重试,或使用 VPN 以改善网络环境。"
|
||||||
|
Else
|
||||||
|
Return Nothing
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 返回一个枚举对应的字符串。
|
''' 返回一个枚举对应的字符串。
|
||||||
@@ -1551,12 +1541,12 @@ RetryDir:
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 JSON 对象。
|
''' 获取 JSON 对象。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function GetJson(Data As String)
|
Public Function GetJson(Data As String) As JToken
|
||||||
Try
|
Try
|
||||||
Return JsonConvert.DeserializeObject(Data, New JsonSerializerSettings With {.DateTimeZoneHandling = DateTimeZoneHandling.Local})
|
Return JsonConvert.DeserializeObject(Data, New JsonSerializerSettings With {.DateTimeZoneHandling = DateTimeZoneHandling.Local})
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Dim Length As Integer = If(Data, "").Length
|
Dim Length As Integer = If(Data, "").Length
|
||||||
Throw New Exception("格式化 JSON 失败:" & If(Length > 2000, Data.Substring(0, 500) & $"...(全长 {Length} 个字符)..." & Right(Data, 500), Data))
|
Throw New Exception("格式化 JSON 失败:" & If(Length > 2000, Data.Substring(0, 500) & $"...(全长 {Length} 个字符)..." & Right(Data, 500), Data), ex)
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
@@ -2131,6 +2121,19 @@ RetryDir:
|
|||||||
End Function
|
End Function
|
||||||
End Class
|
End Class
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' 将二维数组转换为字典。
|
||||||
|
''' </summary>
|
||||||
|
<Extension> Public Function ToDictionary(Of T)(arr As T(,)) As Dictionary(Of T, T)
|
||||||
|
Dim result As New Dictionary(Of T, T)
|
||||||
|
If arr.Length = 0 Then Return result
|
||||||
|
If arr.GetLength(1) <> 2 Then Throw New ArgumentException("数组必须为两列,第一列为 Key,第二列为 Value。")
|
||||||
|
For i As Integer = 0 To arr.GetLength(0) - 1
|
||||||
|
result(arr(i, 0)) = arr(i, 1)
|
||||||
|
Next
|
||||||
|
Return result
|
||||||
|
End Function
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
|
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -2179,10 +2182,10 @@ RetryDir:
|
|||||||
End Function
|
End Function
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 判断当前系统语言是否为 zh-CN。
|
''' 判断当前系统语言是否为中文。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function IsSystemLanguageChinese() As Boolean
|
Public Function IsSystemLanguageChinese() As Boolean
|
||||||
Return CultureInfo.CurrentCulture.Name = "zh-CN" OrElse CultureInfo.CurrentUICulture.Name = "zh-CN"
|
Return CultureInfo.CurrentCulture.Name.StartsWithF("zh-") OrElse CultureInfo.CurrentUICulture.Name.StartsWithF("zh-")
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private Uuid As Integer = 1
|
Private Uuid As Integer = 1
|
||||||
@@ -2225,6 +2228,9 @@ NextElement:
|
|||||||
Next i
|
Next i
|
||||||
Return ResultArray
|
Return ResultArray
|
||||||
End Function
|
End Function
|
||||||
|
<Extension> Public Function Any(Arr As UIElementCollection) As Boolean
|
||||||
|
Return Arr?.Count > 0
|
||||||
|
End Function
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取格式类似于“11:08:52.037”的当前时间的字符串。
|
''' 获取格式类似于“11:08:52.037”的当前时间的字符串。
|
||||||
@@ -2462,7 +2468,7 @@ NextElement:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub RunInThread(Action As Action)
|
Public Sub RunInThread(Action As Action)
|
||||||
If RunInUi() Then
|
If RunInUi() Then
|
||||||
RunInNewThread(Action, "Runtime Invoke " & GetUuid() & "#")
|
RunInNewThread(Action, "Invoke " & GetUuid())
|
||||||
Else
|
Else
|
||||||
Action()
|
Action()
|
||||||
End If
|
End If
|
||||||
@@ -2625,10 +2631,6 @@ Retry:
|
|||||||
''' 相对增减控件的左边距。
|
''' 相对增减控件的左边距。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub DeltaLeft(control As FrameworkElement, newValue As Double)
|
Public Sub DeltaLeft(control As FrameworkElement, newValue As Double)
|
||||||
'安全性检查
|
|
||||||
DebugAssert(Not Double.IsNaN(newValue))
|
|
||||||
DebugAssert(Not Double.IsInfinity(newValue))
|
|
||||||
|
|
||||||
If TypeOf control Is Window Then
|
If TypeOf control Is Window Then
|
||||||
'窗口改变
|
'窗口改变
|
||||||
CType(control, Window).Left += newValue
|
CType(control, Window).Left += newValue
|
||||||
@@ -2640,8 +2642,6 @@ Retry:
|
|||||||
Case HorizontalAlignment.Right
|
Case HorizontalAlignment.Right
|
||||||
control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right - newValue, control.Margin.Bottom)
|
control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right - newValue, control.Margin.Bottom)
|
||||||
'control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, CType(control.Parent, Object).ActualWidth - control.ActualWidth - newValue, control.Margin.Bottom)
|
'control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, CType(control.Parent, Object).ActualWidth - control.ActualWidth - newValue, control.Margin.Bottom)
|
||||||
Case Else
|
|
||||||
DebugAssert(False)
|
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -2649,17 +2649,12 @@ Retry:
|
|||||||
''' 设置控件的左边距。(仅针对置左控件)
|
''' 设置控件的左边距。(仅针对置左控件)
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub SetLeft(control As FrameworkElement, newValue As Double)
|
Public Sub SetLeft(control As FrameworkElement, newValue As Double)
|
||||||
DebugAssert(control.HorizontalAlignment = HorizontalAlignment.Left)
|
|
||||||
control.Margin = New Thickness(newValue, control.Margin.Top, control.Margin.Right, control.Margin.Bottom)
|
control.Margin = New Thickness(newValue, control.Margin.Top, control.Margin.Right, control.Margin.Bottom)
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 相对增减控件的上边距。
|
''' 相对增减控件的上边距。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub DeltaTop(control As FrameworkElement, newValue As Double)
|
Public Sub DeltaTop(control As FrameworkElement, newValue As Double)
|
||||||
'安全性检查
|
|
||||||
DebugAssert(Not Double.IsNaN(newValue))
|
|
||||||
DebugAssert(Not Double.IsInfinity(newValue))
|
|
||||||
|
|
||||||
If TypeOf control Is Window Then
|
If TypeOf control Is Window Then
|
||||||
'窗口改变
|
'窗口改变
|
||||||
CType(control, Window).Top += newValue
|
CType(control, Window).Top += newValue
|
||||||
@@ -2671,11 +2666,8 @@ Retry:
|
|||||||
Case VerticalAlignment.Bottom
|
Case VerticalAlignment.Bottom
|
||||||
control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, control.Margin.Bottom - newValue)
|
control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, control.Margin.Bottom - newValue)
|
||||||
'control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, CType(control.Parent, Object).ActualWidth - control.ActualWidth - newValue, control.Margin.Bottom)
|
'control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, CType(control.Parent, Object).ActualWidth - control.ActualWidth - newValue, control.Margin.Bottom)
|
||||||
Case Else
|
|
||||||
DebugAssert(False)
|
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'If Double.IsNaN(newValue) OrElse Double.IsInfinity(newValue) Then Return '安全性检查
|
'If Double.IsNaN(newValue) OrElse Double.IsInfinity(newValue) Then Return '安全性检查
|
||||||
'Select Case control.VerticalAlignment
|
'Select Case control.VerticalAlignment
|
||||||
' Case VerticalAlignment.Top, VerticalAlignment.Stretch, VerticalAlignment.Center
|
' Case VerticalAlignment.Top, VerticalAlignment.Stretch, VerticalAlignment.Center
|
||||||
@@ -2689,7 +2681,6 @@ Retry:
|
|||||||
''' 设置控件的顶边距。(仅针对置上控件)
|
''' 设置控件的顶边距。(仅针对置上控件)
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub SetTop(control As FrameworkElement, newValue As Double)
|
Public Sub SetTop(control As FrameworkElement, newValue As Double)
|
||||||
DebugAssert(control.VerticalAlignment = VerticalAlignment.Top)
|
|
||||||
control.Margin = New Thickness(control.Margin.Left, newValue, control.Margin.Right, control.Margin.Bottom)
|
control.Margin = New Thickness(control.Margin.Left, newValue, control.Margin.Right, control.Margin.Bottom)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -2760,11 +2751,11 @@ Retry:
|
|||||||
Using Reader As New XamlXmlReader(Stream)
|
Using Reader As New XamlXmlReader(Stream)
|
||||||
While Reader.Read()
|
While Reader.Read()
|
||||||
For Each BlackListType In {GetType(WebBrowser), GetType(Frame), GetType(MediaElement), GetType(ObjectDataProvider), GetType(XamlReader), GetType(Window), GetType(XmlDataProvider)}
|
For Each BlackListType In {GetType(WebBrowser), GetType(Frame), GetType(MediaElement), GetType(ObjectDataProvider), GetType(XamlReader), GetType(Window), GetType(XmlDataProvider)}
|
||||||
If Reader.Type IsNot Nothing AndAlso BlackListType.IsAssignableFrom(Reader.Type.UnderlyingType) Then Throw New UnauthorizedAccessException($"不允许使用 {BlackListType.Name} 类型。")
|
If Reader.Type IsNot Nothing AndAlso BlackListType.IsAssignableFrom(Reader.Type.UnderlyingType) Then Throw New UnauthorizedAccessException($"基于安全考虑,不允许使用 {BlackListType.Name} 类型。")
|
||||||
If Reader.Value IsNot Nothing AndAlso Reader.Value = BlackListType.Name Then Throw New UnauthorizedAccessException($"不允许使用 {BlackListType.Name} 值。")
|
If Reader.Value IsNot Nothing AndAlso Reader.Value = BlackListType.Name Then Throw New UnauthorizedAccessException($"基于安全考虑,不允许使用 {BlackListType.Name} 值。")
|
||||||
Next
|
Next
|
||||||
For Each BlackListMember In {"Code", "FactoryMethod", "Static"}
|
For Each BlackListMember In {"Code", "FactoryMethod", "Static"}
|
||||||
If Reader.Member IsNot Nothing AndAlso Reader.Member.Name = BlackListMember Then Throw New UnauthorizedAccessException($"不允许使用 {BlackListMember} 成员。")
|
If Reader.Member IsNot Nothing AndAlso Reader.Member.Name = BlackListMember Then Throw New UnauthorizedAccessException($"基于安全考虑,不允许使用 {BlackListMember} 成员。")
|
||||||
Next
|
Next
|
||||||
End While
|
End While
|
||||||
End Using
|
End Using
|
||||||
@@ -2922,7 +2913,7 @@ Retry:
|
|||||||
'处理错误会导致再次调用 Log() 导致无限循环
|
'处理错误会导致再次调用 Log() 导致无限循环
|
||||||
|
|
||||||
'输出日志
|
'输出日志
|
||||||
Dim AppendText As String = "[" & GetTimeNow() & "] " & Text & vbCrLf '减轻同步锁占用
|
Dim AppendText As String = $"[{GetTimeNow()}] <{If(Thread.CurrentThread.Name = "", "主线程", Thread.CurrentThread.Name)}> {Text}{vbCrLf}" '减轻同步锁占用
|
||||||
If ModeDebug Then
|
If ModeDebug Then
|
||||||
SyncLock LogListLock
|
SyncLock LogListLock
|
||||||
LogList.Append(AppendText)
|
LogList.Append(AppendText)
|
||||||
@@ -2973,6 +2964,13 @@ Retry:
|
|||||||
End If
|
End If
|
||||||
End Select
|
End Select
|
||||||
|
|
||||||
|
'上报
|
||||||
|
If Level >= LogLevel.Hint Then
|
||||||
|
Telemetry("PCL 错误",
|
||||||
|
"Level", GetStringFromEnum(Level),
|
||||||
|
"Title", FilterUserName(FilterAccessToken(Title, "*"), "*"),
|
||||||
|
"Exception", FilterUserName(FilterAccessToken(Text, "*"), "*"))
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 输出错误信息。
|
''' 输出错误信息。
|
||||||
@@ -2986,7 +2984,7 @@ Retry:
|
|||||||
Dim ExFull As String = Desc & ":" & GetExceptionDetail(Ex)
|
Dim ExFull As String = Desc & ":" & GetExceptionDetail(Ex)
|
||||||
|
|
||||||
'输出日志
|
'输出日志
|
||||||
Dim AppendText As String = "[" & GetTimeNow() & "] " & Desc & ":" & GetExceptionDetail(Ex, True) & vbCrLf '减轻同步锁占用
|
Dim AppendText As String = $"[{GetTimeNow()}] <{If(Thread.CurrentThread.Name = "", "主线程", Thread.CurrentThread.Name)}> {Desc}:{GetExceptionDetail(Ex, True)}{vbCrLf}" '减轻同步锁占用
|
||||||
If ModeDebug Then
|
If ModeDebug Then
|
||||||
SyncLock LogListLock
|
SyncLock LogListLock
|
||||||
LogList.Append(AppendText)
|
LogList.Append(AppendText)
|
||||||
@@ -3039,6 +3037,13 @@ Retry:
|
|||||||
End If
|
End If
|
||||||
End Select
|
End Select
|
||||||
|
|
||||||
|
'上报
|
||||||
|
If Level >= LogLevel.Hint Then
|
||||||
|
Telemetry("PCL 异常",
|
||||||
|
"Level", GetStringFromEnum(Level),
|
||||||
|
"Title", FilterUserName(FilterAccessToken(Title, "*"), "*"),
|
||||||
|
"Exception", FilterUserName(FilterAccessToken(ExFull, "*"), "*"))
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'反馈
|
'反馈
|
||||||
@@ -3048,7 +3053,7 @@ Retry:
|
|||||||
If ForceOpenLog OrElse (ShowMsgbox AndAlso MyMsgBox("若你在汇报一个 Bug,请点击 打开文件夹 按钮,并上传 Log(1~5).txt 中包含错误信息的文件。" & vbCrLf & "游戏崩溃一般与启动器无关,请不要因为游戏崩溃而提交反馈。", "反馈提交提醒", "打开文件夹", "不需要") = 1) Then
|
If ForceOpenLog OrElse (ShowMsgbox AndAlso MyMsgBox("若你在汇报一个 Bug,请点击 打开文件夹 按钮,并上传 Log(1~5).txt 中包含错误信息的文件。" & vbCrLf & "游戏崩溃一般与启动器无关,请不要因为游戏崩溃而提交反馈。", "反馈提交提醒", "打开文件夹", "不需要") = 1) Then
|
||||||
OpenExplorer(Path & "PCL\Log1.txt")
|
OpenExplorer(Path & "PCL\Log1.txt")
|
||||||
End If
|
End If
|
||||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/issues/")
|
OpenWebsite("https://github.com/Meloong-Git/PCL/issues/")
|
||||||
End Sub
|
End Sub
|
||||||
Public Function CanFeedback(ShowHint As Boolean) As Boolean
|
Public Function CanFeedback(ShowHint As Boolean) As Boolean
|
||||||
If False.Equals(PageSetupSystem.IsLauncherNewest) Then
|
If False.Equals(PageSetupSystem.IsLauncherNewest) Then
|
||||||
@@ -3075,9 +3080,23 @@ Retry:
|
|||||||
"文件位置:" & Path)
|
"文件位置:" & Path)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'断言
|
'遥测
|
||||||
Public Sub DebugAssert(Exp As Boolean)
|
Public Sub Telemetry([Event] As String, ParamArray Datas As String())
|
||||||
If Not Exp Then Throw New Exception("断言命中")
|
If Not Setup.Get("SystemSystemTelemetry") Then Return '用户关闭了遥测
|
||||||
|
If Not ClsBaseUrl.StartsWithF("http") Then Return '开源版没有设置遥测地址
|
||||||
|
RunInNewThread(
|
||||||
|
Sub()
|
||||||
|
Try
|
||||||
|
Log($"[System] 匿名数据上报:{[Event]}")
|
||||||
|
Dim Url As String = $"{ClsBaseUrl}&Event={WebUtility.UrlEncode([Event])}"
|
||||||
|
For i = 0 To Datas.Length - 1 Step 2
|
||||||
|
Url &= "&" & WebUtility.UrlEncode(Datas(i)) & "=" & WebUtility.UrlEncode(Datas(i + 1).Replace(vbCrLf, vbLf))
|
||||||
|
Next
|
||||||
|
NetRequestByClient(Url, MakeLog:=False)
|
||||||
|
Catch
|
||||||
|
Log("[System] 匿名数据上报失败", LogLevel.Debug)
|
||||||
|
End Try
|
||||||
|
End Sub, "Telemetry", ThreadPriority.Lowest)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'获取当前的堆栈信息
|
'获取当前的堆栈信息
|
||||||
|
|||||||
@@ -339,7 +339,7 @@
|
|||||||
[Error] = ex
|
[Error] = ex
|
||||||
State = LoadState.Failed
|
State = LoadState.Failed
|
||||||
End Try
|
End Try
|
||||||
End Sub) With {.Name = Name, .Priority = ThreadPriority}
|
End Sub) With {.Name = "L/" & Name, .Priority = ThreadPriority}
|
||||||
LastRunningThread.Start() '不能使用 RunInNewThread,否则在函数返回前线程就会运行完,导致误判 IsAborted
|
LastRunningThread.Start() '不能使用 RunInNewThread,否则在函数返回前线程就会运行完,导致误判 IsAborted
|
||||||
End Sub
|
End Sub
|
||||||
Public Overrides Sub Abort()
|
Public Overrides Sub Abort()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1076,7 +1076,7 @@ Retry:
|
|||||||
Try
|
Try
|
||||||
'获取工程列表
|
'获取工程列表
|
||||||
Log("[Comp] 开始从 CurseForge 获取工程列表:" & CurseForgeUrl)
|
Log("[Comp] 开始从 CurseForge 获取工程列表:" & CurseForgeUrl)
|
||||||
Dim RequestResult As JObject = DlModRequest(CurseForgeUrl, IsJson:=True)
|
Dim RequestResult As JObject = DlModRequest(CurseForgeUrl)
|
||||||
Task.Progress += 0.2
|
Task.Progress += 0.2
|
||||||
Dim ProjectList As New List(Of CompProject)
|
Dim ProjectList As New List(Of CompProject)
|
||||||
For Each JsonEntry As JObject In RequestResult("data")
|
For Each JsonEntry As JObject In RequestResult("data")
|
||||||
@@ -1107,7 +1107,7 @@ Retry:
|
|||||||
Sub()
|
Sub()
|
||||||
Try
|
Try
|
||||||
Log("[Comp] 开始从 Modrinth 获取工程列表:" & ModrinthUrl)
|
Log("[Comp] 开始从 Modrinth 获取工程列表:" & ModrinthUrl)
|
||||||
Dim RequestResult As JObject = DlModRequest(ModrinthUrl, IsJson:=True)
|
Dim RequestResult As JObject = DlModRequest(ModrinthUrl)
|
||||||
Task.Progress += 0.2
|
Task.Progress += 0.2
|
||||||
Dim ProjectList As New List(Of CompProject)
|
Dim ProjectList As New List(Of CompProject)
|
||||||
For Each JsonEntry As JObject In RequestResult("hits")
|
For Each JsonEntry As JObject In RequestResult("hits")
|
||||||
@@ -1137,6 +1137,11 @@ Retry:
|
|||||||
If ModrinthThread IsNot Nothing Then ModrinthThread.Join()
|
If ModrinthThread IsNot Nothing Then ModrinthThread.Join()
|
||||||
If Task.IsAborted Then Return
|
If Task.IsAborted Then Return
|
||||||
|
|
||||||
|
'筛除不是 Forge 的 Mod
|
||||||
|
If IsOldForgeRequest Then
|
||||||
|
RawResults = RawResults.Where(Function(p) Not p.ModLoaders.Any() OrElse p.ModLoaders.Contains(CompModLoaderType.Forge)).ToList
|
||||||
|
End If
|
||||||
|
|
||||||
'确保存在结果
|
'确保存在结果
|
||||||
Storage.ErrorMessage = Nothing
|
Storage.ErrorMessage = Nothing
|
||||||
If Not RawResults.Any() Then
|
If Not RawResults.Any() Then
|
||||||
@@ -1167,11 +1172,6 @@ Retry:
|
|||||||
ModrinthThread?.Interrupt()
|
ModrinthThread?.Interrupt()
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
'筛除不是 Forge 的 Mod
|
|
||||||
If IsOldForgeRequest Then
|
|
||||||
RawResults = RawResults.Where(Function(p) Not p.ModLoaders.Any() OrElse p.ModLoaders.Contains(CompModLoaderType.Forge)).ToList
|
|
||||||
End If
|
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
#Region "提取非重复项,存储于 RealResults"
|
#Region "提取非重复项,存储于 RealResults"
|
||||||
@@ -1396,7 +1396,7 @@ Retry:
|
|||||||
'DownloadAddress
|
'DownloadAddress
|
||||||
Dim Url = Data("downloadUrl").ToString
|
Dim Url = Data("downloadUrl").ToString
|
||||||
If Url = "" Then Url = $"https://media.forgecdn.net/files/{CInt(Id.ToString.Substring(0, 4))}/{CInt(Id.ToString.Substring(4))}/{FileName}"
|
If Url = "" Then Url = $"https://media.forgecdn.net/files/{CInt(Id.ToString.Substring(0, 4))}/{CInt(Id.ToString.Substring(4))}/{FileName}"
|
||||||
Url = Url.Replace(FileName, Net.WebUtility.UrlEncode(FileName)) '对文件名进行编码
|
Url = Url.Replace(FileName, WebUtility.UrlEncode(FileName)) '对文件名进行编码
|
||||||
DownloadUrls = HandleCurseForgeDownloadUrls(Url) '对脑残 CurseForge 的下载地址进行多种修正
|
DownloadUrls = HandleCurseForgeDownloadUrls(Url) '对脑残 CurseForge 的下载地址进行多种修正
|
||||||
DownloadUrls.AddRange(DownloadUrls.Select(Function(u) DlSourceModGet(u)).ToList) '添加镜像源,这个写法是为了让镜像源排在后面
|
DownloadUrls.AddRange(DownloadUrls.Select(Function(u) DlSourceModGet(u)).ToList) '添加镜像源,这个写法是为了让镜像源排在后面
|
||||||
DownloadUrls = DownloadUrls.Distinct.ToList '最终去重
|
DownloadUrls = DownloadUrls.Distinct.ToList '最终去重
|
||||||
@@ -1492,9 +1492,8 @@ Retry:
|
|||||||
Return {
|
Return {
|
||||||
Url.Replace("-service.overwolf.wtf", ".forgecdn.net").Replace("://edge.", "://mediafilez.").Replace("://media.", "://mediafilez."),
|
Url.Replace("-service.overwolf.wtf", ".forgecdn.net").Replace("://edge.", "://mediafilez.").Replace("://media.", "://mediafilez."),
|
||||||
Url.Replace("://edge.", "://mediafilez.").Replace("://media.", "://mediafilez."),
|
Url.Replace("://edge.", "://mediafilez.").Replace("://media.", "://mediafilez."),
|
||||||
Url.Replace("-service.overwolf.wtf", ".forgecdn.net").Replace("://edge.", "://media."),
|
|
||||||
Url.Replace("-service.overwolf.wtf", ".forgecdn.net"),
|
Url.Replace("-service.overwolf.wtf", ".forgecdn.net"),
|
||||||
Url.Replace("://edge.", "://media."),
|
Url.Replace("://media.", "://edge."),
|
||||||
Url
|
Url
|
||||||
}.Distinct.ToList
|
}.Distinct.ToList
|
||||||
End Function
|
End Function
|
||||||
@@ -1591,27 +1590,40 @@ Retry:
|
|||||||
If CompProjectCache.ContainsKey(ProjectId) Then '存在缓存
|
If CompProjectCache.ContainsKey(ProjectId) Then '存在缓存
|
||||||
TargetProject = CompProjectCache(ProjectId)
|
TargetProject = CompProjectCache(ProjectId)
|
||||||
ElseIf FromCurseForge Then 'CurseForge
|
ElseIf FromCurseForge Then 'CurseForge
|
||||||
TargetProject = New CompProject(DlModRequest("https://api.curseforge.com/v1/mods/" & ProjectId, IsJson:=True)("data"))
|
TargetProject = New CompProject(DlModRequest("https://api.curseforge.com/v1/mods/" & ProjectId)("data"))
|
||||||
Else 'Modrinth
|
Else 'Modrinth
|
||||||
TargetProject = New CompProject(DlModRequest("https://api.modrinth.com/v2/project/" & ProjectId, IsJson:=True))
|
TargetProject = New CompProject(DlModRequest("https://api.modrinth.com/v2/project/" & ProjectId))
|
||||||
End If
|
End If
|
||||||
'获取工程对象的文件列表
|
'获取工程对象的文件列表
|
||||||
If Not CompFilesCache.ContainsKey(ProjectId) Then '有缓存也不能直接返回,这时候前置可能没获取(#5173)
|
If Not CompFilesCache.ContainsKey(ProjectId) Then '有缓存也不能直接返回,这时候前置可能没获取(#5173)
|
||||||
Log("[Comp] 开始获取文件列表:" & ProjectId)
|
Log("[Comp] 开始获取文件列表:" & ProjectId)
|
||||||
Dim ResultJsonArray As JArray
|
Dim ResultJsonArray As JArray = Nothing
|
||||||
If FromCurseForge Then
|
If FromCurseForge Then
|
||||||
'CurseForge
|
'CurseForge
|
||||||
|
For RetryCount As Integer = 0 To 2
|
||||||
|
Dim ResultJson As JObject = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=" &
|
||||||
|
(10000 + RetryCount)) '每次重试多请求一个文件,以避免触发 CDN 缓存
|
||||||
'HMCL 一次性请求了 10000 个文件,虽然不知道会不会出问题但先这样吧……(#5522)
|
'HMCL 一次性请求了 10000 个文件,虽然不知道会不会出问题但先这样吧……(#5522)
|
||||||
ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=10000", IsJson:=True)("data")
|
|
||||||
'之前只请求一部分文件的方法备份如下:
|
'之前只请求一部分文件的方法备份如下:
|
||||||
'If TargetProject.Type = CompType.Mod Then 'Mod 使用每个版本最新的文件
|
'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")
|
' ResultJsonArray = DlModRequest("https://api.curseforge.com/v1/mods/files", HttpMethod.Post, "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json")("data")
|
||||||
'Else '否则使用全部文件
|
'Else '否则使用全部文件
|
||||||
' ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999", IsJson:=True)("data")
|
' ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999")("data")
|
||||||
'End If
|
'End If
|
||||||
|
If ResultJson("pagination")("resultCount").ToObject(Of Integer) = ResultJson("pagination")("totalCount").ToObject(Of Integer) Then
|
||||||
|
ResultJsonArray = ResultJson("data")
|
||||||
|
Exit For
|
||||||
|
ElseIf RetryCount < 2 Then
|
||||||
|
Log($"[Comp] CurseForge 返回的文件列表存在缺失,即将进行第 {RetryCount + 1} 次重试", LogLevel.Debug) '#6224
|
||||||
|
Log($"[Comp] 返回的原始内容如下:{vbCrLf}{ResultJson}")
|
||||||
|
Else
|
||||||
|
Log($"[Comp] CurseForge 返回的文件列表存在缺失,返回的原始内容如下:{vbCrLf}{ResultJson}")
|
||||||
|
Throw New Exception("CurseForge 返回的文件列表存在缺失")
|
||||||
|
End If
|
||||||
|
Next
|
||||||
Else
|
Else
|
||||||
'Modrinth
|
'Modrinth
|
||||||
ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version", IsJson:=True)
|
ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version")
|
||||||
End If
|
End If
|
||||||
CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
|
CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
|
||||||
Where(Function(a) a.Available).ToList.
|
Where(Function(a) a.Available).ToList.
|
||||||
@@ -1625,10 +1637,10 @@ Retry:
|
|||||||
Log($"[Comp] {ProjectId} 文件列表中还需要获取信息的前置:{Join(UndoneDeps, ",")}")
|
Log($"[Comp] {ProjectId} 文件列表中还需要获取信息的前置:{Join(UndoneDeps, ",")}")
|
||||||
Dim Projects As JArray
|
Dim Projects As JArray
|
||||||
If TargetProject.FromCurseForge Then
|
If TargetProject.FromCurseForge Then
|
||||||
Projects = GetJson(DlModRequest("https://api.curseforge.com/v1/mods",
|
Projects = DlModRequest("https://api.curseforge.com/v1/mods",
|
||||||
"POST", "{""modIds"": [" & Join(UndoneDeps, ",") & "]}", "application/json"))("data")
|
HttpMethod.Post, "{""modIds"": [" & Join(UndoneDeps, ",") & "]}", "application/json")("data")
|
||||||
Else
|
Else
|
||||||
Projects = DlModRequest($"https://api.modrinth.com/v2/projects?ids=[""{Join(UndoneDeps, """,""")}""]", IsJson:=True)
|
Projects = DlModRequest($"https://api.modrinth.com/v2/projects?ids=[""{Join(UndoneDeps, """,""")}""]")
|
||||||
End If
|
End If
|
||||||
For Each Project In Projects
|
For Each Project In Projects
|
||||||
Dim Unused As New CompProject(Project) '在 New 的时候会添加缓存以便之后读取
|
Dim Unused As New CompProject(Project) '在 New 的时候会添加缓存以便之后读取
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
'构造函数
|
'构造函数
|
||||||
Private TempFolder As String
|
Private TempFolder As String
|
||||||
Public Sub New(UUID As Integer)
|
Private TargetVersion As McVersion
|
||||||
|
Public Sub New(Optional TargetVersion As McVersion = Nothing)
|
||||||
|
Me.TargetVersion = TargetVersion
|
||||||
'构建文件结构
|
'构建文件结构
|
||||||
TempFolder = RequestTaskTempFolder()
|
TempFolder = RequestTaskTempFolder()
|
||||||
Directory.CreateDirectory(TempFolder & "Temp\")
|
Directory.CreateDirectory(TempFolder & "Temp\")
|
||||||
@@ -339,6 +341,7 @@ Extracted:
|
|||||||
''' 导致崩溃的原因枚举。
|
''' 导致崩溃的原因枚举。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Enum CrashReason
|
Private Enum CrashReason
|
||||||
|
Java虚拟机参数有误
|
||||||
Mod文件被解压
|
Mod文件被解压
|
||||||
MixinBootstrap缺失
|
MixinBootstrap缺失
|
||||||
内存不足
|
内存不足
|
||||||
@@ -482,10 +485,12 @@ Done:
|
|||||||
'崩溃报告分析,高优先级
|
'崩溃报告分析,高优先级
|
||||||
If LogCrash IsNot Nothing Then
|
If LogCrash IsNot Nothing Then
|
||||||
If LogCrash.Contains("Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass") Then AppendReason(CrashReason.Java版本过高)
|
If LogCrash.Contains("Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass") Then AppendReason(CrashReason.Java版本过高)
|
||||||
|
If LogCrash.Contains("Failed loading config file ") Then AppendReason(CrashReason.Mod配置文件导致游戏崩溃, {TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Failed loading config file .+ for modid )[^\n]+"), "").TrimEnd(vbCrLf)).First, If(RegexSeek(LogCrash, "(?<=Failed loading config file ).+(?= of type)"), "").TrimEnd(vbCrLf)})
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'游戏日志分析
|
'游戏日志分析
|
||||||
If LogMc IsNot Nothing Then
|
If LogMc IsNot Nothing Then
|
||||||
|
If LogMc.Contains("Unrecognized option:") Then AppendReason(CrashReason.Java虚拟机参数有误)
|
||||||
If LogMc.Contains("Found multiple arguments for option fml.forgeVersion, but you asked for only one") Then AppendReason(CrashReason.版本Json中存在多个Forge)
|
If LogMc.Contains("Found multiple arguments for option fml.forgeVersion, but you asked for only one") Then AppendReason(CrashReason.版本Json中存在多个Forge)
|
||||||
If LogMc.Contains("The driver does not appear to support OpenGL") Then AppendReason(CrashReason.显卡不支持OpenGL)
|
If LogMc.Contains("The driver does not appear to support OpenGL") Then AppendReason(CrashReason.显卡不支持OpenGL)
|
||||||
If LogMc.Contains("java.lang.ClassCastException: java.base/jdk") Then AppendReason(CrashReason.使用JDK)
|
If LogMc.Contains("java.lang.ClassCastException: java.base/jdk") Then AppendReason(CrashReason.使用JDK)
|
||||||
@@ -508,13 +513,13 @@ Done:
|
|||||||
If LogMc.Contains("Couldn't set pixel format") Then AppendReason(CrashReason.显卡驱动不支持导致无法设置像素格式)
|
If LogMc.Contains("Couldn't set pixel format") Then AppendReason(CrashReason.显卡驱动不支持导致无法设置像素格式)
|
||||||
If LogMc.Contains("java.lang.OutOfMemoryError") OrElse LogMc.Contains("an out of memory error") Then AppendReason(CrashReason.内存不足)
|
If LogMc.Contains("java.lang.OutOfMemoryError") OrElse LogMc.Contains("an out of memory error") Then AppendReason(CrashReason.内存不足)
|
||||||
If LogMc.Contains("java.lang.RuntimeException: Shaders Mod detected. Please remove it, OptiFine has built-in support for shaders.") Then AppendReason(CrashReason.ShadersMod与OptiFine同时安装)
|
If LogMc.Contains("java.lang.RuntimeException: Shaders Mod detected. Please remove it, OptiFine has built-in support for shaders.") Then AppendReason(CrashReason.ShadersMod与OptiFine同时安装)
|
||||||
If LogMc.Contains("java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier") Then AppendReason(CrashReason.低版本Forge与高版本Java不兼容)
|
If LogMc.Contains("java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier") OrElse LogMc.Contains("java.lang.NoSuchMethodError: 'void sun.security.util.ManifestEntryVerifier") Then AppendReason(CrashReason.低版本Forge与高版本Java不兼容)
|
||||||
If LogMc.Contains("1282: Invalid operation") Then AppendReason(CrashReason.光影或资源包导致OpenGL1282错误)
|
If LogMc.Contains("1282: Invalid operation") Then AppendReason(CrashReason.光影或资源包导致OpenGL1282错误)
|
||||||
If LogMc.Contains("signer information does not match signer information of other classes in the same package") Then AppendReason(CrashReason.文件或内容校验失败, If(RegexSeek(LogMc, "(?<=class "")[^']+(?=""'s signer information)"), "").TrimEnd(vbCrLf))
|
If LogMc.Contains("signer information does not match signer information of other classes in the same package") Then AppendReason(CrashReason.文件或内容校验失败, If(RegexSeek(LogMc, "(?<=class "")[^']+(?=""'s signer information)"), "").TrimEnd(vbCrLf))
|
||||||
If LogMc.Contains("Maybe try a lower resolution resourcepack?") Then AppendReason(CrashReason.材质过大或显卡配置不足)
|
If LogMc.Contains("Maybe try a lower resolution resourcepack?") Then AppendReason(CrashReason.材质过大或显卡配置不足)
|
||||||
If LogMc.Contains("java.lang.NoSuchMethodError: net.minecraft.world.server.ChunkManager$ProxyTicketManager.shouldForceTicks(J)Z") AndAlso LogMc.Contains("OptiFine") Then AppendReason(CrashReason.OptiFine导致无法加载世界)
|
If LogMc.Contains("java.lang.NoSuchMethodError: net.minecraft.world.server.ChunkManager$ProxyTicketManager.shouldForceTicks(J)Z") AndAlso LogMc.Contains("OptiFine") Then AppendReason(CrashReason.OptiFine导致无法加载世界)
|
||||||
If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
|
If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
|
||||||
If LogMc.Contains("com.electronwill.nightconfig.core.io.ParsingException: Not enough data available") Then AppendReason(CrashReason.NightConfig的Bug)
|
If LogMc.Contains("com.electronwill.nightconfig.core.io.ParsingException: Not enough data available") AndAlso Not CrashReasons.ContainsKey(CrashReason.Mod配置文件导致游戏崩溃) Then AppendReason(CrashReason.NightConfig的Bug)
|
||||||
If LogMc.Contains("Cannot find launch target fmlclient, unable to launch") Then AppendReason(CrashReason.Forge安装不完整)
|
If LogMc.Contains("Cannot find launch target fmlclient, unable to launch") Then AppendReason(CrashReason.Forge安装不完整)
|
||||||
If LogMc.Contains("Invalid paths argument, contained no existing paths") AndAlso LogMc.Contains("libraries\net\minecraftforge\fmlcore") Then AppendReason(CrashReason.Forge安装不完整)
|
If LogMc.Contains("Invalid paths argument, contained no existing paths") AndAlso LogMc.Contains("libraries\net\minecraftforge\fmlcore") Then AppendReason(CrashReason.Forge安装不完整)
|
||||||
If LogMc.Contains("Invalid module name: '' is not a Java identifier") Then AppendReason(CrashReason.Mod名称包含特殊字符)
|
If LogMc.Contains("Invalid module name: '' is not a Java identifier") Then AppendReason(CrashReason.Mod名称包含特殊字符)
|
||||||
@@ -576,7 +581,6 @@ Done:
|
|||||||
End If
|
End If
|
||||||
If LogCrash.Contains("Multiple entries with same key: ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Multiple entries with same key: )[^=]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
If LogCrash.Contains("Multiple entries with same key: ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Multiple entries with same key: )[^=]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||||
If LogCrash.Contains("LoaderExceptionModCrash: Caught exception from ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=LoaderExceptionModCrash: Caught exception from )[^\n]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
If LogCrash.Contains("LoaderExceptionModCrash: Caught exception from ") Then AppendReason(CrashReason.确定Mod导致游戏崩溃, TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=LoaderExceptionModCrash: Caught exception from )[^\n]+"), "").TrimEnd((vbCrLf & " ").ToCharArray)))
|
||||||
If LogCrash.Contains("Failed loading config file ") Then AppendReason(CrashReason.Mod配置文件导致游戏崩溃, {TryAnalyzeModName(If(RegexSeek(LogCrash, "(?<=Failed loading config file .+ for modid )[^\n]+"), "").TrimEnd(vbCrLf)).First, If(RegexSeek(LogCrash, "(?<=Failed loading config file ).+(?= of type)"), "").TrimEnd(vbCrLf)})
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
End Sub
|
End Sub
|
||||||
@@ -856,12 +860,13 @@ NextStack:
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 弹出崩溃弹窗,并指导导出崩溃报告。
|
''' 弹出崩溃弹窗,并指导导出崩溃报告。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub Output(IsHandAnalyze As Boolean, Optional ExtraFiles As List(Of String) = Nothing)
|
Public Sub Output(IsManualAnalyze As Boolean, Optional ExtraFiles As List(Of String) = Nothing)
|
||||||
'弹窗提示
|
'弹窗提示
|
||||||
FrmMain.ShowWindowToTop()
|
FrmMain.ShowWindowToTop()
|
||||||
Select Case MyMsgBox(GetAnalyzeResult(IsHandAnalyze), If(IsHandAnalyze, "错误报告分析结果", "Minecraft 出现错误"),
|
Dim Detail As String = GetAnalyzeResult(IsManualAnalyze)
|
||||||
"确定", If(IsHandAnalyze OrElse DirectFile Is Nothing, "", "查看日志"), If(IsHandAnalyze, "", "导出错误报告"),
|
Select Case MyMsgBox(Detail, If(IsManualAnalyze, "错误报告分析结果", "Minecraft 出现错误"),
|
||||||
Button2Action:=If(IsHandAnalyze OrElse DirectFile Is Nothing, Nothing,
|
"确定", If(IsManualAnalyze OrElse DirectFile Is Nothing, "", "查看日志"), If(IsManualAnalyze, "", "导出错误报告"),
|
||||||
|
Button2Action:=If(IsManualAnalyze OrElse DirectFile Is Nothing, Nothing,
|
||||||
Sub()
|
Sub()
|
||||||
'弹窗选择:查看日志
|
'弹窗选择:查看日志
|
||||||
If File.Exists(DirectFile.Value.Key) Then
|
If File.Exists(DirectFile.Value.Key) Then
|
||||||
@@ -918,6 +923,11 @@ NextStack:
|
|||||||
End Try
|
End Try
|
||||||
OpenExplorer(FileAddress)
|
OpenExplorer(FileAddress)
|
||||||
End Select
|
End Select
|
||||||
|
'上报
|
||||||
|
If IsManualAnalyze Then Return
|
||||||
|
Telemetry("Minecraft 崩溃",
|
||||||
|
"Version", If(TargetVersion Is Nothing, "null", TargetVersion.Version.ToString),
|
||||||
|
"Detail", FilterUserName(Detail, "*"))
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取崩溃分析的结果描述。
|
''' 获取崩溃分析的结果描述。
|
||||||
@@ -938,6 +948,8 @@ NextStack:
|
|||||||
For Each Reason In CrashReasons
|
For Each Reason In CrashReasons
|
||||||
Dim Additional As List(Of String) = Reason.Value
|
Dim Additional As List(Of String) = Reason.Value
|
||||||
Select Case Reason.Key
|
Select Case Reason.Key
|
||||||
|
Case CrashReason.Java虚拟机参数有误
|
||||||
|
Results.Add("由于 Java 虚拟机参数有误,导致游戏无法继续运行。\n请检查高级启动选项中设置的 Java 虚拟机参数是否有误。")
|
||||||
Case CrashReason.Mod文件被解压
|
Case CrashReason.Mod文件被解压
|
||||||
Results.Add("由于 Mod 文件被解压了,导致游戏无法继续运行。\n直接把整个 Mod 文件放进 Mod 文件夹中即可,若解压就会导致游戏出错。\n\n请删除 Mod 文件夹中已被解压的 Mod,然后再启动游戏。")
|
Results.Add("由于 Mod 文件被解压了,导致游戏无法继续运行。\n直接把整个 Mod 文件放进 Mod 文件夹中即可,若解压就会导致游戏出错。\n\n请删除 Mod 文件夹中已被解压的 Mod,然后再启动游戏。")
|
||||||
Case CrashReason.内存不足
|
Case CrashReason.内存不足
|
||||||
@@ -1018,9 +1030,14 @@ NextStack:
|
|||||||
End If
|
End If
|
||||||
Case CrashReason.特定实体导致崩溃
|
Case CrashReason.特定实体导致崩溃
|
||||||
If Additional.Count = 1 Then
|
If Additional.Count = 1 Then
|
||||||
Results.Add("游戏似乎因为实体 " & Additional.First & " 出现了问题。\n\n你可以创建一个新世界,并生成一个该实体,然后观察游戏的运行情况:\n - 若正常运行,则是该实体导致出错,你或许需要使用一些方式删除此实体。\n - 若仍然出错,问题就可能来自其他原因……\h")
|
Dim entityInfo As String = Additional.First
|
||||||
|
If entityInfo.StartsWith("minecraft:player") Then
|
||||||
|
Results.Add("游戏似乎因为玩家实体 " & entityInfo & " 出现了问题。\n\n这通常是因为玩家数据损坏或世界存档问题导致的。\n请尝试以下解决方案:\n - 创建一个新世界,观察游戏是否正常运行\n - 如果新世界正常,可能需要删除或修复当前世界的玩家数据文件\n - 也可能是某个 Mod 与玩家实体处理存在冲突,尝试逐个禁用近期安装的 Mod\n - 如果问题持续存在,建议备份重要数据后重新创建世界\h")
|
||||||
Else
|
Else
|
||||||
Results.Add("游戏似乎因为世界中的某些实体出现了问题。\n\n你可以创建一个新世界,并生成各种实体,观察游戏的运行情况:\n - 若正常运行,则是某些实体导致出错,你或许需要删除该世界。\n - 若仍然出错,问题就可能来自其他原因……\h")
|
Results.Add("游戏似乎因为实体 " & entityInfo & " 出现了问题。\n\n请尝试以下解决方案:\n - 创建一个新世界,并尝试生成该类型的实体,观察游戏运行情况\n - 如果新世界中该实体正常,问题可能在于当前世界的数据损坏\n - 如果新世界中仍然崩溃,可能是某个 Mod 导致了实体处理异常\n - 尝试逐个禁用可能影响实体的 Mod(如生物类、AI 类 Mod)\n - 也可以尝试使用指令删除该坐标附近的实体\h")
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Results.Add("游戏似乎因为世界中的某些实体出现了问题。\n\n请尝试以下解决方案:\n - 创建一个新世界,观察游戏的运行情况\n - 如果新世界正常运行,则是当前世界的实体数据导致出错\n - 可以尝试使用指令清理异常实体\n - 如果问题持续存在,可能是某个处理实体的 Mod 存在问题\n - 建议逐个禁用近期安装的 Mod,特别是涉及生物、AI 或实体处理的 Mod\h")
|
||||||
End If
|
End If
|
||||||
Case CrashReason.OptiFine与Forge不兼容
|
Case CrashReason.OptiFine与Forge不兼容
|
||||||
Results.Add("由于 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n\n请前往 OptiFine 官网(https://optifine.net/downloads)查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏。")
|
Results.Add("由于 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n\n请前往 OptiFine 官网(https://optifine.net/downloads)查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏。")
|
||||||
@@ -1102,7 +1119,7 @@ NextStack:
|
|||||||
If(Not Results.Any(Function(r) r.EndsWithF("\h")) OrElse IsHandAnalyze, "",
|
If(Not Results.Any(Function(r) r.EndsWithF("\h")) OrElse IsHandAnalyze, "",
|
||||||
vbCrLf & "如果要寻求帮助,请把错误报告文件发给对方,而不是发送这个窗口的照片或者截图。" &
|
vbCrLf & "如果要寻求帮助,请把错误报告文件发给对方,而不是发送这个窗口的照片或者截图。" &
|
||||||
If(If(PageSetupSystem.IsLauncherNewest(), True), "",
|
If(If(PageSetupSystem.IsLauncherNewest(), True), "",
|
||||||
vbCrLf & vbCrLf & "此外,你正在使用老版本 PCL,更新 PCL 或许也能解决这个问题。" & vbCrLf & "你可以点击 设置 → 启动器 → 检查更新 来更新 PCL。"))
|
vbCrLf & vbCrLf & "此外,你正在使用老版本 PCL,更新 PCL 或许也能解决这个问题。" & vbCrLf & "你可以点击 [设置 → 其他 → 启动器 → 检查更新] 更新 PCL。"))
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -198,7 +198,7 @@
|
|||||||
Private IsNewClientVersionHinted As Boolean = False
|
Private IsNewClientVersionHinted As Boolean = False
|
||||||
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of String, DlClientListResult))
|
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||||
Dim StartTime As Long = GetTimeTick()
|
Dim StartTime As Long = GetTimeTick()
|
||||||
Dim Json As JObject = NetGetCodeByRequestRetry("https://launchermeta.mojang.com/mc/game/version_manifest.json", IsJson:=True)
|
Dim Json As JObject = GetJson(NetRequestByClientRetry("https://launchermeta.mojang.com/mc/game/version_manifest.json"))
|
||||||
Try
|
Try
|
||||||
Dim Versions As JArray = Json("versions")
|
Dim Versions As JArray = Json("versions")
|
||||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlClientListBmclapiLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
Public DlClientListBmclapiLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
||||||
Private Sub DlClientListBmclapiMain(Loader As LoaderTask(Of String, DlClientListResult))
|
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)
|
Dim Json As JObject = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json"))
|
||||||
Try
|
Try
|
||||||
Dim Versions As JArray = Json("versions")
|
Dim Versions As JArray = Json("versions")
|
||||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||||
@@ -377,7 +377,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlOptiFineListOfficialLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Official", AddressOf DlOptiFineListOfficialMain)
|
Public DlOptiFineListOfficialLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Official", AddressOf DlOptiFineListOfficialMain)
|
||||||
Private Sub DlOptiFineListOfficialMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
Private Sub DlOptiFineListOfficialMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
||||||
Dim Result As String = NetGetCodeByClient("https://optifine.net/downloads", Encoding.Default)
|
Dim Result As String = NetRequestByClientRetry("https://optifine.net/downloads", Encoding:=Encoding.Default)
|
||||||
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
||||||
Try
|
Try
|
||||||
'获取所有版本信息
|
'获取所有版本信息
|
||||||
@@ -413,7 +413,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlOptiFineListBmclapiLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Bmclapi", AddressOf DlOptiFineListBmclapiMain)
|
Public DlOptiFineListBmclapiLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Bmclapi", AddressOf DlOptiFineListBmclapiMain)
|
||||||
Private Sub DlOptiFineListBmclapiMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
Private Sub DlOptiFineListBmclapiMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
||||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/optifine/versionList", IsJson:=True)
|
Dim Json As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/optifine/versionList"))
|
||||||
Try
|
Try
|
||||||
Dim Versions As New List(Of DlOptiFineListEntry)
|
Dim Versions As New List(Of DlOptiFineListEntry)
|
||||||
For Each Token As JObject In Json
|
For Each Token As JObject In Json
|
||||||
@@ -483,7 +483,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlForgeListOfficialLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Official", AddressOf DlForgeListOfficialMain)
|
Public DlForgeListOfficialLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Official", AddressOf DlForgeListOfficialMain)
|
||||||
Private Sub DlForgeListOfficialMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
Private Sub DlForgeListOfficialMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
||||||
Dim Result As String = NetGetCodeByRequestRetry("https://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.2.4.html", Encoding.Default, "text/html", UseBrowserUserAgent:=True)
|
Dim Result As String = NetRequestByClientRetry("https://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.2.4.html", Encoding:=Encoding.Default, Accept:="text/html", UseBrowserUserAgent:=True)
|
||||||
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
||||||
'获取所有版本信息
|
'获取所有版本信息
|
||||||
Dim Names As List(Of String) = RegexSearch(Result, "(?<=a href=""index_)[0-9.]+(_pre[0-9]?)?(?=.html)")
|
Dim Names As List(Of String) = RegexSearch(Result, "(?<=a href=""index_)[0-9.]+(_pre[0-9]?)?(?=.html)")
|
||||||
@@ -497,7 +497,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlForgeListBmclapiLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Bmclapi", AddressOf DlForgeListBmclapiMain)
|
Public DlForgeListBmclapiLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Bmclapi", AddressOf DlForgeListBmclapiMain)
|
||||||
Private Sub DlForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
Private Sub DlForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
||||||
Dim Result As String = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft", Encoding.Default)
|
Dim Result As String = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft", Encoding:=Encoding.Default)
|
||||||
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
||||||
'获取所有版本信息
|
'获取所有版本信息
|
||||||
Dim Names As List(Of String) = RegexSearch(Result, "[0-9.]+(_pre[0-9]?)?")
|
Dim Names As List(Of String) = RegexSearch(Result, "[0-9.]+(_pre[0-9]?)?")
|
||||||
@@ -594,7 +594,7 @@
|
|||||||
VersionName = Version
|
VersionName = Version
|
||||||
Me.Version = New Version(Version)
|
Me.Version = New Version(Version)
|
||||||
Me.Inherit = Inherit
|
Me.Inherit = Inherit
|
||||||
FileVersion = Version & If(Branch Is Nothing, "", "-" & Branch)
|
FileVersion = Version & If(Branch Is Nothing, "", "-" & Branch)
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|
||||||
@@ -629,7 +629,7 @@
|
|||||||
Public Sub DlForgeVersionOfficialMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
Public Sub DlForgeVersionOfficialMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
||||||
Dim Result As String
|
Dim Result As String
|
||||||
Try
|
Try
|
||||||
Result = NetGetCodeByLoader("https://files.minecraftforge.net/maven/net/minecraftforge/forge/index_" &
|
Result = NetRequestByLoader("https://files.minecraftforge.net/maven/net/minecraftforge/forge/index_" &
|
||||||
Loader.Input.Replace("-", "_") & '兼容 Forge 1.7.10-pre4,#4057
|
Loader.Input.Replace("-", "_") & '兼容 Forge 1.7.10-pre4,#4057
|
||||||
".html", UseBrowserUserAgent:=True)
|
".html", UseBrowserUserAgent:=True)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -700,9 +700,8 @@
|
|||||||
''' Forge 版本列表,BMCLAPI。
|
''' Forge 版本列表,BMCLAPI。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub DlForgeVersionBmclapiMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
Public Sub DlForgeVersionBmclapiMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
||||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
|
Dim Json As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
|
||||||
Loader.Input.Replace("-", "_"), '兼容 Forge 1.7.10-pre4,#4057
|
Loader.Input.Replace("-", "_"))) '兼容 Forge 1.7.10-pre4,#4057
|
||||||
IsJson:=True)
|
|
||||||
Dim Versions As New List(Of DlForgeVersionEntry)
|
Dim Versions As New List(Of DlForgeVersionEntry)
|
||||||
Try
|
Try
|
||||||
Dim Recommended As String = McDownloadForgeRecommendedGet(Loader.Input)
|
Dim Recommended As String = McDownloadForgeRecommendedGet(Loader.Input)
|
||||||
@@ -836,8 +835,8 @@
|
|||||||
Public DlNeoForgeListOfficialLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Official", AddressOf DlNeoForgeListOfficialMain)
|
Public DlNeoForgeListOfficialLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Official", AddressOf DlNeoForgeListOfficialMain)
|
||||||
Private Sub DlNeoForgeListOfficialMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
|
Private Sub DlNeoForgeListOfficialMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
|
||||||
'获取版本列表 JSON
|
'获取版本列表 JSON
|
||||||
Dim ResultLatest As String = NetGetCodeByLoader("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge", UseBrowserUserAgent:=True, IsJson:=True)
|
Dim ResultLatest As String = NetRequestByClientRetry("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge")
|
||||||
Dim ResultLegacy As String = NetGetCodeByLoader("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/forge", UseBrowserUserAgent:=True, IsJson:=True)
|
Dim ResultLegacy As String = NetRequestByClientRetry("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/forge")
|
||||||
If ResultLatest.Length < 100 OrElse ResultLegacy.Length < 100 Then Throw New Exception("获取到的版本列表长度不足(" & ResultLatest & ")")
|
If ResultLatest.Length < 100 OrElse ResultLegacy.Length < 100 Then Throw New Exception("获取到的版本列表长度不足(" & ResultLatest & ")")
|
||||||
'解析
|
'解析
|
||||||
Try
|
Try
|
||||||
@@ -854,8 +853,8 @@
|
|||||||
Public DlNeoForgeListBmclapiLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Bmclapi", AddressOf DlNeoForgeListBmclapiMain)
|
Public DlNeoForgeListBmclapiLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Bmclapi", AddressOf DlNeoForgeListBmclapiMain)
|
||||||
Public Sub DlNeoForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
|
Public Sub DlNeoForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
|
||||||
'获取版本列表 JSON
|
'获取版本列表 JSON
|
||||||
Dim ResultLatest As String = NetGetCodeByLoader("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/neoforge", UseBrowserUserAgent:=True, IsJson:=True)
|
Dim ResultLatest As String = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/neoforge")
|
||||||
Dim ResultLegacy As String = NetGetCodeByLoader("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/forge", UseBrowserUserAgent:=True, IsJson:=True)
|
Dim ResultLegacy As String = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/forge")
|
||||||
If ResultLatest.Length < 100 OrElse ResultLegacy.Length < 100 Then Throw New Exception("获取到的版本列表长度不足(" & ResultLatest & ")")
|
If ResultLatest.Length < 100 OrElse ResultLegacy.Length < 100 Then Throw New Exception("获取到的版本列表长度不足(" & ResultLatest & ")")
|
||||||
'解析
|
'解析
|
||||||
Try
|
Try
|
||||||
@@ -960,7 +959,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlLiteLoaderListOfficialLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Official", AddressOf DlLiteLoaderListOfficialMain)
|
Public DlLiteLoaderListOfficialLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Official", AddressOf DlLiteLoaderListOfficialMain)
|
||||||
Private Sub DlLiteLoaderListOfficialMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
Private Sub DlLiteLoaderListOfficialMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://dl.liteloader.com/versions/versions.json", IsJson:=True)
|
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://dl.liteloader.com/versions/versions.json"))
|
||||||
Try
|
Try
|
||||||
Dim Json As JObject = Result("versions")
|
Dim Json As JObject = Result("versions")
|
||||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||||
@@ -988,7 +987,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlLiteLoaderListBmclapiLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Bmclapi", AddressOf DlLiteLoaderListBmclapiMain)
|
Public DlLiteLoaderListBmclapiLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Bmclapi", AddressOf DlLiteLoaderListBmclapiMain)
|
||||||
Private Sub DlLiteLoaderListBmclapiMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
Private Sub DlLiteLoaderListBmclapiMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json", IsJson:=True)
|
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json"))
|
||||||
Try
|
Try
|
||||||
Dim Json As JObject = Result("versions")
|
Dim Json As JObject = Result("versions")
|
||||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||||
@@ -1059,7 +1058,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlFabricListOfficialLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Official", AddressOf DlFabricListOfficialMain)
|
Public DlFabricListOfficialLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Official", AddressOf DlFabricListOfficialMain)
|
||||||
Private Sub DlFabricListOfficialMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
Private Sub DlFabricListOfficialMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://meta.fabricmc.net/v2/versions", IsJson:=True)
|
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://meta.fabricmc.net/v2/versions"))
|
||||||
Try
|
Try
|
||||||
Dim Output = New DlFabricListResult With {.IsOfficial = True, .SourceName = "Fabric 官方源", .Value = Result}
|
Dim Output = New DlFabricListResult With {.IsOfficial = True, .SourceName = "Fabric 官方源", .Value = Result}
|
||||||
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
||||||
@@ -1074,7 +1073,7 @@
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DlFabricListBmclapiLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Bmclapi", AddressOf DlFabricListBmclapiMain)
|
Public DlFabricListBmclapiLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Bmclapi", AddressOf DlFabricListBmclapiMain)
|
||||||
Private Sub DlFabricListBmclapiMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
Private Sub DlFabricListBmclapiMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/fabric-meta/v2/versions", IsJson:=True)
|
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/fabric-meta/v2/versions"))
|
||||||
Try
|
Try
|
||||||
Dim Output = New DlFabricListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Result}
|
Dim Output = New DlFabricListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Result}
|
||||||
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
||||||
@@ -1101,72 +1100,37 @@
|
|||||||
#Region "DlMod | Mod 镜像源请求"
|
#Region "DlMod | Mod 镜像源请求"
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 对可能涉及 Mod 镜像源的请求进行处理,返回字符串或 JObject。
|
''' 对可能涉及 Mod 镜像源的请求进行处理,返回 JToken。
|
||||||
''' 调用 NetGetCodeByRequest,会进行重试。
|
|
||||||
''' </summary>
|
|
||||||
Public Function DlModRequest(Url As String, Optional IsJson As Boolean = False) As Object
|
|
||||||
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
|
|
||||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
|
||||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 20))
|
|
||||||
'Dim McimUrl As String = DlSourceModGet(Url)
|
|
||||||
'If McimUrl <> Url Then
|
|
||||||
' Select Case Setup.Get("ToolDownloadMod")
|
|
||||||
' Case 0
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 5))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 15))
|
|
||||||
' Case 1
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 5))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 15))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
|
||||||
' Case Else
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 15))
|
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
|
||||||
' End Select
|
|
||||||
'End If
|
|
||||||
Dim Exs As String = ""
|
|
||||||
For Each Source In Urls
|
|
||||||
Try
|
|
||||||
Return NetGetCodeByRequestOnce(Source.Key, Encode:=Encoding.UTF8, Timeout:=Source.Value * 1000, IsJson:=IsJson, UseBrowserUserAgent:=True)
|
|
||||||
Catch ex As Exception
|
|
||||||
Exs += ex.Message + vbCrLf
|
|
||||||
End Try
|
|
||||||
Next
|
|
||||||
Throw New Exception(Exs)
|
|
||||||
End Function
|
|
||||||
|
|
||||||
''' <summary>
|
|
||||||
''' 对可能涉及 Mod 镜像源的请求进行处理。
|
|
||||||
''' 调用 NetRequest,会进行重试。
|
''' 调用 NetRequest,会进行重试。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function DlModRequest(Url As String, Method As String, Data As String, ContentType As String) As String
|
Public Function DlModRequest(Url As String, Optional Method As HttpMethod = Nothing,
|
||||||
|
Optional Content As String = Nothing, Optional ContentType As String = Nothing) As JToken
|
||||||
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
|
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
|
||||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
Dim McimUrl As String = DlSourceModGet(Url)
|
||||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 20))
|
If McimUrl <> Url Then
|
||||||
'Dim McimUrl As String = DlSourceModGet(Url)
|
Select Case Setup.Get("ToolDownloadMod")
|
||||||
'If McimUrl <> Url Then
|
Case 0
|
||||||
' Select Case Setup.Get("ToolDownloadMod")
|
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
||||||
' Case 0
|
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 5))
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
Case 1
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 15))
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 10)) '至少 10s,要不然有时候远端服务器来不及完成
|
||||||
' Case 1
|
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 5))
|
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 15))
|
Case Else
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 10))
|
||||||
' Case Else
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 15))
|
End Select
|
||||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
Else
|
||||||
' End Select
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 10))
|
||||||
'End If
|
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||||
|
End If
|
||||||
Dim Exs As String = ""
|
Dim Exs As String = ""
|
||||||
For Each Source In Urls
|
For Each Source In Urls
|
||||||
Try
|
Try
|
||||||
Return NetRequestOnce(Source.Key, Method, Data, ContentType, Timeout:=Source.Value * 1000)
|
Return GetJson(NetRequestByClient(Source.Key, Method, Content, ContentType, Timeout:=Source.Value * 1000, Encoding:=Encoding.UTF8))
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Exs += ex.Message + vbCrLf
|
Exs += ex.Message + vbCrLf
|
||||||
End Try
|
End Try
|
||||||
@@ -1269,7 +1233,14 @@
|
|||||||
|
|
||||||
'Mod 下载源
|
'Mod 下载源
|
||||||
Public Function DlSourceModGet(Original As String) As String
|
Public Function DlSourceModGet(Original As String) As String
|
||||||
Return Original
|
Return Original.
|
||||||
|
Replace("api.modrinth.com", "mod.mcimirror.top/modrinth").
|
||||||
|
Replace("staging-api.modrinth.com", "mod.mcimirror.top/modrinth").
|
||||||
|
Replace("cdn.modrinth.com", "mod.mcimirror.top").
|
||||||
|
Replace("api.curseforge.com", "mod.mcimirror.top/curseforge").
|
||||||
|
Replace("edge.forgecdn.net", "mod.mcimirror.top").
|
||||||
|
Replace("mediafilez.forgecdn.net", "mod.mcimirror.top").
|
||||||
|
Replace("media.forgecdn.net", "mod.mcimirror.top")
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
'Loader 自动切换
|
'Loader 自动切换
|
||||||
|
|||||||
@@ -117,6 +117,7 @@
|
|||||||
If Output = "" Then Throw New ApplicationException("尝试运行该 Java 失败")
|
If Output = "" Then Throw New ApplicationException("尝试运行该 Java 失败")
|
||||||
If ModeDebug Then Log("[Java] Java 检查输出:" & PathFolder & "java.exe" & vbCrLf & Output)
|
If ModeDebug Then Log("[Java] Java 检查输出:" & PathFolder & "java.exe" & vbCrLf & Output)
|
||||||
If Output.Contains("/lib/ext exists") Then Throw New ApplicationException("无法运行该 Java,请在删除 Java 文件夹中的 /lib/ext 文件夹后再试")
|
If Output.Contains("/lib/ext exists") Then Throw New ApplicationException("无法运行该 Java,请在删除 Java 文件夹中的 /lib/ext 文件夹后再试")
|
||||||
|
If Output.Contains("a fatal error") Then Throw New ApplicationException("无法运行该 Java,该 Java 或系统存在问题")
|
||||||
'获取详细信息
|
'获取详细信息
|
||||||
Dim VersionString = If(RegexSeek(Output, "(?<=version "")[^""]+"), If(RegexSeek(Output, "(?<=openjdk )[0-9]+"), "")).Replace("_", ".").Split("-").First
|
Dim VersionString = If(RegexSeek(Output, "(?<=version "")[^""]+"), If(RegexSeek(Output, "(?<=openjdk )[0-9]+"), "")).Replace("_", ".").Split("-").First
|
||||||
If VersionString.Split(".").Count > 4 Then VersionString = VersionString.Replace(".0.", ".") '#3493,VersionString = "21.0.2.0.2"
|
If VersionString.Split(".").Count > 4 Then VersionString = VersionString.Replace(".0.", ".") '#3493,VersionString = "21.0.2.0.2"
|
||||||
@@ -459,10 +460,12 @@ NoUserJava:
|
|||||||
''' 将 Java 按照适用性排序。
|
''' 将 Java 按照适用性排序。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function JavaSorter(Left As JavaEntry, Right As JavaEntry) As Boolean
|
Public Function JavaSorter(Left As JavaEntry, Right As JavaEntry) As Boolean
|
||||||
|
Dim PathInfo As New DirectoryInfo(ShortenPath(Path))
|
||||||
|
Dim PathMcInfo As New DirectoryInfo(ShortenPath(PathMcFolder))
|
||||||
'1. 尽量在当前文件夹或当前 Minecraft 文件夹
|
'1. 尽量在当前文件夹或当前 Minecraft 文件夹
|
||||||
Dim ProgramPathParent As String, MinecraftPathParent As String = ""
|
Dim ProgramPathParent As String, MinecraftPathParent As String = ""
|
||||||
ProgramPathParent = If(New DirectoryInfo(Path).Parent, New DirectoryInfo(Path)).FullName
|
ProgramPathParent = If(PathInfo.Parent, PathInfo).FullName
|
||||||
If PathMcFolder <> "" Then MinecraftPathParent = If(New DirectoryInfo(PathMcFolder).Parent, New DirectoryInfo(PathMcFolder)).FullName
|
If PathMcFolder <> "" Then MinecraftPathParent = If(PathMcInfo.Parent, PathMcInfo).FullName
|
||||||
If Left.PathFolder.StartsWithF(ProgramPathParent) AndAlso Not Right.PathFolder.StartsWithF(ProgramPathParent) Then Return True
|
If Left.PathFolder.StartsWithF(ProgramPathParent) AndAlso Not Right.PathFolder.StartsWithF(ProgramPathParent) Then Return True
|
||||||
If Not Left.PathFolder.StartsWithF(ProgramPathParent) AndAlso Right.PathFolder.StartsWithF(ProgramPathParent) Then Return False
|
If Not Left.PathFolder.StartsWithF(ProgramPathParent) AndAlso Right.PathFolder.StartsWithF(ProgramPathParent) Then Return False
|
||||||
If PathMcFolder <> "" Then
|
If PathMcFolder <> "" Then
|
||||||
@@ -529,6 +532,8 @@ NoUserJava:
|
|||||||
If Disk.DriveType = DriveType.Network Then Continue For '跳过网络驱动器(#3705)
|
If Disk.DriveType = DriveType.Network Then Continue For '跳过网络驱动器(#3705)
|
||||||
JavaSearchFolder(Disk.Name, JavaPreList, False)
|
JavaSearchFolder(Disk.Name, JavaPreList, False)
|
||||||
Next
|
Next
|
||||||
|
'查找 .jdks 文件夹中的 Java
|
||||||
|
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\.jdks\", JavaPreList, False, True)
|
||||||
'查找 APPDATA 文件夹中的 Java
|
'查找 APPDATA 文件夹中的 Java
|
||||||
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\", JavaPreList, False)
|
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\", JavaPreList, False)
|
||||||
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\", JavaPreList, False)
|
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\", JavaPreList, False)
|
||||||
@@ -677,14 +682,14 @@ Wait:
|
|||||||
'若该目录有 Java,则加入结果
|
'若该目录有 Java,则加入结果
|
||||||
If File.Exists(Path & "javaw.exe") Then Results(Path) = Source
|
If File.Exists(Path & "javaw.exe") Then Results(Path) = Source
|
||||||
'查找其下的所有文件夹
|
'查找其下的所有文件夹
|
||||||
'不应使用网易的 Java:https://github.com/Hex-Dragon/PCL2/issues/1279#issuecomment-2761489121
|
'不应使用网易的 Java:https://github.com/Meloong-Git/PCL/issues/1279#issuecomment-2761489121
|
||||||
Dim Keywords = {"java", "jdk", "env", "环境", "run", "软件", "jre", "mc", "dragon",
|
Dim Keywords = {"java", "jdk", "env", "环境", "run", "软件", "jre", "mc", "dragon", "bin",
|
||||||
"soft", "cache", "temp", "corretto", "roaming", "users", "craft", "program", "世界", "net",
|
"soft", "cache", "temp", "corretto", "roaming", "users", "craft", "program", "世界", "net",
|
||||||
"游戏", "oracle", "game", "file", "data", "jvm", "服务", "server", "客户", "client", "整合",
|
"游戏", "oracle", "game", "file", "data", "jvm", "服务", "server", "客户", "client", "整合",
|
||||||
"应用", "运行", "前置", "mojang", "官启", "新建文件夹", "eclipse", "microsoft", "hotspot",
|
"应用", "运行", "前置", "mojang", "官启", "新建文件夹", "eclipse", "microsoft", "hotspot",
|
||||||
"runtime", "x86", "x64", "forge", "原版", "optifine", "官方", "启动", "hmcl", "mod", "高清",
|
"runtime", "x86", "x64", "forge", "原版", "optifine", "官方", "启动", "hmcl", "mod", "高清",
|
||||||
"download", "launch", "程序", "path", "version", "baka", "pcl", "zulu", "local", "packages",
|
"download", "launch", "程序", "path", "version", "baka", "pcl", "zulu", "local", "packages",
|
||||||
"4297127d64ec6", "1.", "启动"}
|
"4297127d64ec6", "1.", "启动", "jbr-"}
|
||||||
For Each FolderInfo As DirectoryInfo In OriginalPath.EnumerateDirectories
|
For Each FolderInfo As DirectoryInfo In OriginalPath.EnumerateDirectories
|
||||||
If FolderInfo.Attributes.HasFlag(FileAttributes.ReparsePoint) Then Continue For '跳过符号链接
|
If FolderInfo.Attributes.HasFlag(FileAttributes.ReparsePoint) Then Continue For '跳过符号链接
|
||||||
Dim SearchEntry = GetFolderNameFromPath(FolderInfo.Name).ToLower '用于搜索的字符串
|
Dim SearchEntry = GetFolderNameFromPath(FolderInfo.Name).ToLower '用于搜索的字符串
|
||||||
@@ -745,7 +750,7 @@ Wait:
|
|||||||
Private LastJavaBaseDir As String = Nothing '用于在下载中断或失败时删除未完成下载的 Java 文件夹,防止残留只下了一半但 -version 能跑的 Java
|
Private LastJavaBaseDir As String = Nothing '用于在下载中断或失败时删除未完成下载的 Java 文件夹,防止残留只下了一半但 -version 能跑的 Java
|
||||||
Private Sub JavaFileList(Loader As LoaderTask(Of Integer, List(Of NetFile)))
|
Private Sub JavaFileList(Loader As LoaderTask(Of Integer, List(Of NetFile)))
|
||||||
Log("[Java] 开始获取 Java 下载信息")
|
Log("[Java] 开始获取 Java 下载信息")
|
||||||
Dim IndexFileStr As String = NetGetCodeByLoader(DlVersionListOrder(
|
Dim IndexFileStr As String = NetRequestByLoader(DlVersionListOrder(
|
||||||
{"https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"},
|
{"https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"},
|
||||||
{"https://bmclapi2.bangbang93.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"}
|
{"https://bmclapi2.bangbang93.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"}
|
||||||
), IsJson:=True)
|
), IsJson:=True)
|
||||||
@@ -757,7 +762,7 @@ Wait:
|
|||||||
Dim Address As String = TargetEntry.Value("manifest")("url")
|
Dim Address As String = TargetEntry.Value("manifest")("url")
|
||||||
Log($"[Java] 准备下载 Java {TargetEntry.Value("version")("name")}({TargetEntry.Key}):{Address}")
|
Log($"[Java] 准备下载 Java {TargetEntry.Value("version")("name")}({TargetEntry.Key}):{Address}")
|
||||||
'获取文件列表
|
'获取文件列表
|
||||||
Dim ListFileStr As String = NetGetCodeByLoader(DlSourceOrder({Address}, {Address.Replace("piston-meta.mojang.com", "bmclapi2.bangbang93.com")}), IsJson:=True)
|
Dim ListFileStr As String = NetRequestByLoader(DlSourceOrder({Address}, {Address.Replace("piston-meta.mojang.com", "bmclapi2.bangbang93.com")}), IsJson:=True)
|
||||||
LastJavaBaseDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\runtime\" & TargetEntry.Key & "\"
|
LastJavaBaseDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\runtime\" & TargetEntry.Key & "\"
|
||||||
Dim Results As New List(Of NetFile)
|
Dim Results As New List(Of NetFile)
|
||||||
For Each File As JProperty In CType(GetJson(ListFileStr), JObject)("files")
|
For Each File As JProperty In CType(GetJson(ListFileStr), JObject)("files")
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ Public Module ModLaunch
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub McLaunchLog(Text As String)
|
Public Sub McLaunchLog(Text As String)
|
||||||
Text = FilterUserName(FilterAccessToken(Text, "*"), "*")
|
Text = FilterUserName(FilterAccessToken(Text, "*"), "*")
|
||||||
RunInUi(Sub() FrmLaunchRight.LabLog.Text += vbCrLf & "[" & GetTimeNow() & "] " & Text)
|
RunInUi(Sub() FrmLaunchRight.LabLog.Text += $"{vbCrLf}[{GetTimeNow()}] {Text}")
|
||||||
Log("[Launch] " & Text)
|
Log("[Launch] " & Text)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -101,6 +101,8 @@ Public Module ModLaunch
|
|||||||
If Not ex.Message.StartsWithF("$$") Then Hint(ex.Message, HintType.Critical)
|
If Not ex.Message.StartsWithF("$$") Then Hint(ex.Message, HintType.Critical)
|
||||||
Throw
|
Throw
|
||||||
End Try
|
End Try
|
||||||
|
Dim IsSavingBatch As Boolean = CurrentLaunchOptions?.SaveBatch IsNot Nothing
|
||||||
|
|
||||||
'正式加载
|
'正式加载
|
||||||
Try
|
Try
|
||||||
'构造主加载器
|
'构造主加载器
|
||||||
@@ -145,9 +147,15 @@ Public Module ModLaunch
|
|||||||
Select Case LaunchLoader.State
|
Select Case LaunchLoader.State
|
||||||
Case LoadState.Finished
|
Case LoadState.Finished
|
||||||
Hint(McVersionCurrent.Name & " 启动成功!", HintType.Finish)
|
Hint(McVersionCurrent.Name & " 启动成功!", HintType.Finish)
|
||||||
|
'上报
|
||||||
|
If Not IsSavingBatch Then
|
||||||
|
Telemetry("Minecraft 启动成功",
|
||||||
|
"Version", McVersionCurrent.Version.ToString,
|
||||||
|
"LoginType", GetStringFromEnum(CType(Setup.Get("LoginType"), McLoginType)))
|
||||||
|
End If
|
||||||
Case LoadState.Aborted
|
Case LoadState.Aborted
|
||||||
If AbortHint Is Nothing Then
|
If AbortHint Is Nothing Then
|
||||||
Hint(If(CurrentLaunchOptions?.SaveBatch Is Nothing, "已取消启动!", "已取消导出启动脚本!"), HintType.Info)
|
Hint(If(IsSavingBatch, "已取消导出启动脚本!", "已取消启动!"), HintType.Info)
|
||||||
Else
|
Else
|
||||||
Hint(AbortHint, HintType.Finish)
|
Hint(AbortHint, HintType.Finish)
|
||||||
End If
|
End If
|
||||||
@@ -162,7 +170,7 @@ NextInner:
|
|||||||
If CurrentEx.Message.StartsWithF("$") Then
|
If CurrentEx.Message.StartsWithF("$") Then
|
||||||
'若有以 $ 开头的错误信息,则以此为准显示提示
|
'若有以 $ 开头的错误信息,则以此为准显示提示
|
||||||
'若错误信息为 $$,则不提示
|
'若错误信息为 $$,则不提示
|
||||||
If Not CurrentEx.Message = "$$" Then MyMsgBox(CurrentEx.Message.TrimStart("$"), If(CurrentLaunchOptions?.SaveBatch Is Nothing, "启动失败", "导出启动脚本失败"))
|
If Not CurrentEx.Message = "$$" Then MyMsgBox(CurrentEx.Message.TrimStart("$"), If(IsSavingBatch, "导出启动脚本失败", "启动失败"))
|
||||||
Throw
|
Throw
|
||||||
ElseIf CurrentEx.InnerException IsNot Nothing Then
|
ElseIf CurrentEx.InnerException IsNot Nothing Then
|
||||||
'检查下一级错误
|
'检查下一级错误
|
||||||
@@ -172,8 +180,15 @@ NextInner:
|
|||||||
'没有特殊处理过的错误信息
|
'没有特殊处理过的错误信息
|
||||||
McLaunchLog("错误:" & GetExceptionDetail(ex))
|
McLaunchLog("错误:" & GetExceptionDetail(ex))
|
||||||
Log(ex,
|
Log(ex,
|
||||||
If(CurrentLaunchOptions?.SaveBatch Is Nothing, "Minecraft 启动失败", "导出启动脚本失败"), LogLevel.Msgbox,
|
If(IsSavingBatch, "导出启动脚本失败", "Minecraft 启动失败"), LogLevel.Msgbox,
|
||||||
If(CurrentLaunchOptions?.SaveBatch Is Nothing, "启动失败", "导出启动脚本失败"))
|
If(IsSavingBatch, "导出启动脚本失败", "启动失败"))
|
||||||
|
'上报
|
||||||
|
If Not IsSavingBatch Then
|
||||||
|
Telemetry("Minecraft 启动失败",
|
||||||
|
"Version", McVersionCurrent.Version.ToString,
|
||||||
|
"LoginType", GetStringFromEnum(CType(Setup.Get("LoginType"), McLoginType)),
|
||||||
|
"Exception", FilterUserName(FilterAccessToken(GetExceptionDetail(ex), "*"), "*"))
|
||||||
|
End If
|
||||||
Throw
|
Throw
|
||||||
End If
|
End If
|
||||||
End Try
|
End Try
|
||||||
@@ -684,11 +699,10 @@ LoginFinish:
|
|||||||
'发送登录请求
|
'发送登录请求
|
||||||
Dim RequestData As New JObject(
|
Dim RequestData As New JObject(
|
||||||
New JProperty("accessToken", AccessToken), New JProperty("clientToken", ClientToken), New JProperty("requestUser", True))
|
New JProperty("accessToken", AccessToken), New JProperty("clientToken", ClientToken), New JProperty("requestUser", True))
|
||||||
NetRequestRetry(
|
NetRequestByClientRetry(
|
||||||
Url:=Data.Input.BaseUrl & "/validate",
|
Data.Input.BaseUrl & "/validate", HttpMethod.Post,
|
||||||
Method:="POST",
|
Content:=RequestData.ToString(Newtonsoft.Json.Formatting.None),
|
||||||
Data:=RequestData.ToString(0),
|
Headers:={{"Accept-Language", "zh-CN"}},
|
||||||
Headers:=New Dictionary(Of String, String) From {{"Accept-Language", "zh-CN"}},
|
|
||||||
ContentType:="application/json; charset=utf-8") '没有返回值的
|
ContentType:="application/json; charset=utf-8") '没有返回值的
|
||||||
'将登录结果输出
|
'将登录结果输出
|
||||||
Data.Output.AccessToken = AccessToken
|
Data.Output.AccessToken = AccessToken
|
||||||
@@ -701,10 +715,9 @@ LoginFinish:
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub McLoginRequestRefresh(ByRef Data As LoaderTask(Of McLoginServer, McLoginResult), RequestUser As Boolean)
|
Private Sub McLoginRequestRefresh(ByRef Data As LoaderTask(Of McLoginServer, McLoginResult), RequestUser As Boolean)
|
||||||
McLaunchLog("刷新登录开始(Refresh, " & Data.Input.Token & ")")
|
McLaunchLog("刷新登录开始(Refresh, " & Data.Input.Token & ")")
|
||||||
Dim LoginJson As JObject = GetJson(NetRequestRetry(
|
Dim LoginJson As JObject = GetJson(NetRequestByClientRetry(
|
||||||
Url:=Data.Input.BaseUrl & "/refresh",
|
Data.Input.BaseUrl & "/refresh", HttpMethod.Post,
|
||||||
Method:="POST",
|
Content:=New JObject(
|
||||||
Data:=New JObject(
|
|
||||||
New JProperty("selectedProfile", New JObject(
|
New JProperty("selectedProfile", New JObject(
|
||||||
New JProperty("name", Setup.Get($"Cache{Data.Input.Token}Name")),
|
New JProperty("name", Setup.Get($"Cache{Data.Input.Token}Name")),
|
||||||
New JProperty("id", Setup.Get($"Cache{Data.Input.Token}Uuid"))
|
New JProperty("id", Setup.Get($"Cache{Data.Input.Token}Uuid"))
|
||||||
@@ -712,7 +725,7 @@ LoginFinish:
|
|||||||
New JProperty("accessToken", Setup.Get($"Cache{Data.Input.Token}Access")),
|
New JProperty("accessToken", Setup.Get($"Cache{Data.Input.Token}Access")),
|
||||||
New JProperty("requestUser", True)
|
New JProperty("requestUser", True)
|
||||||
).ToString(Newtonsoft.Json.Formatting.None),
|
).ToString(Newtonsoft.Json.Formatting.None),
|
||||||
Headers:=New Dictionary(Of String, String) From {{"Accept-Language", "zh-CN"}},
|
Headers:={{"Accept-Language", "zh-CN"}},
|
||||||
ContentType:="application/json; charset=utf-8"))
|
ContentType:="application/json; charset=utf-8"))
|
||||||
'将登录结果输出
|
'将登录结果输出
|
||||||
If LoginJson("selectedProfile") Is Nothing Then Throw New Exception("选择的角色 " & Setup.Get("Cache" & Data.Input.Token & "Name") & " 无效!")
|
If LoginJson("selectedProfile") Is Nothing Then Throw New Exception("选择的角色 " & Setup.Get("Cache" & Data.Input.Token & "Name") & " 无效!")
|
||||||
@@ -739,11 +752,10 @@ LoginFinish:
|
|||||||
New JProperty("username", Data.Input.UserName),
|
New JProperty("username", Data.Input.UserName),
|
||||||
New JProperty("password", Data.Input.Password),
|
New JProperty("password", Data.Input.Password),
|
||||||
New JProperty("requestUser", True))
|
New JProperty("requestUser", True))
|
||||||
Dim LoginJson As JObject = GetJson(NetRequestRetry(
|
Dim LoginJson As JObject = GetJson(NetRequestByClientRetry(
|
||||||
Url:=Data.Input.BaseUrl & "/authenticate",
|
Data.Input.BaseUrl & "/authenticate", HttpMethod.Post,
|
||||||
Method:="POST",
|
Content:=RequestData.ToString(Newtonsoft.Json.Formatting.None),
|
||||||
Data:=RequestData.ToString(0),
|
Headers:={{"Accept-Language", "zh-CN"}},
|
||||||
Headers:=New Dictionary(Of String, String) From {{"Accept-Language", "zh-CN"}},
|
|
||||||
ContentType:="application/json; charset=utf-8"))
|
ContentType:="application/json; charset=utf-8"))
|
||||||
'检查登录结果
|
'检查登录结果
|
||||||
If LoginJson("availableProfiles").Count = 0 Then
|
If LoginJson("availableProfiles").Count = 0 Then
|
||||||
@@ -840,7 +852,7 @@ LoginFinish:
|
|||||||
If(Data.Input.UserName.Contains("@"), "", " - 登录账号应为邮箱或统一通行证账号,而非游戏角色 ID。" & vbCrLf) &
|
If(Data.Input.UserName.Contains("@"), "", " - 登录账号应为邮箱或统一通行证账号,而非游戏角色 ID。" & vbCrLf) &
|
||||||
" - 只注册了账号,但没有加入对应服务器。")
|
" - 只注册了账号,但没有加入对应服务器。")
|
||||||
End Select
|
End Select
|
||||||
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") OrElse AllMessage.Contains("网络请求失败") Then
|
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") OrElse AllMessage.Contains("网络请求失败") OrElse AllMessage.Contains("408") OrElse AllMessage.Contains("由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。") Then
|
||||||
Throw New Exception("$登录失败:你的网络环境不佳,导致难以连接到海外服务器。" & vbCrLf & "请稍后重试,或使用加速器或 VPN 以改善网络环境。")
|
Throw New Exception("$登录失败:你的网络环境不佳,导致难以连接到海外服务器。" & vbCrLf & "请稍后重试,或使用加速器或 VPN 以改善网络环境。")
|
||||||
ElseIf ex.Message.StartsWithF("$") Then
|
ElseIf ex.Message.StartsWithF("$") Then
|
||||||
Throw
|
Throw
|
||||||
@@ -858,8 +870,9 @@ LoginFinish:
|
|||||||
'初始请求
|
'初始请求
|
||||||
Retry:
|
Retry:
|
||||||
McLaunchLog("开始微软登录步骤 1/6(原始登录)")
|
McLaunchLog("开始微软登录步骤 1/6(原始登录)")
|
||||||
Dim PrepareJson As JObject = GetJson(NetRequestRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
|
Dim PrepareJson As JObject = GetJson(NetRequestByClientRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", HttpMethod.Post,
|
||||||
$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded"))
|
Content:=$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access",
|
||||||
|
ContentType:="application/x-www-form-urlencoded"))
|
||||||
McLaunchLog("网页登录地址:" & PrepareJson("verification_uri").ToString)
|
McLaunchLog("网页登录地址:" & PrepareJson("verification_uri").ToString)
|
||||||
|
|
||||||
'弹窗
|
'弹窗
|
||||||
@@ -888,13 +901,22 @@ Retry:
|
|||||||
|
|
||||||
Dim Result As String
|
Dim Result As String
|
||||||
Try
|
Try
|
||||||
Result = NetRequestMultiple("https://login.live.com/oauth20_token.srf", "POST",
|
Result = NetRequestByClientMultiple("https://login.live.com/oauth20_token.srf", HttpMethod.Post,
|
||||||
$"client_id={OAuthClientId}&refresh_token={Uri.EscapeDataString(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
Content:=$"client_id={OAuthClientId}&refresh_token={Uri.EscapeDataString(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
||||||
"application/x-www-form-urlencoded", 2)
|
ContentType:="application/x-www-form-urlencoded",
|
||||||
Catch ex As Exception
|
Headers:={{"Accept-Language", "en-US,en;q=0.5"}, {"X-Requested-With", "XMLHttpRequest"}},
|
||||||
If ex.Message.ContainsF("must sign in again", True) OrElse ex.Message.ContainsF("password expired", True) OrElse
|
ThreadCount:=2)
|
||||||
(ex.Message.Contains("refresh_token") AndAlso ex.Message.Contains("is not valid")) Then '#269
|
Catch ex As ResponsedWebException
|
||||||
|
Dim Response = ex.Response
|
||||||
|
If Response.ContainsF("must sign in again", True) OrElse Response.ContainsF("password expired", True) OrElse
|
||||||
|
(Response.Contains("refresh_token") AndAlso Response.Contains("is not valid")) Then '#269
|
||||||
Return {"Relogin", ""}
|
Return {"Relogin", ""}
|
||||||
|
ElseIf Response.Contains("Account security interrupt") Then
|
||||||
|
MyMsgBox("该账号由于安全问题无法登陆,请前往微软账户页获取更多信息。", "登录失败", "我知道了", IsWarn:=True)
|
||||||
|
Throw New Exception("$$")
|
||||||
|
ElseIf Response.Contains("service abuse") Then
|
||||||
|
MyMsgBox("非常抱歉,该账号已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
|
||||||
|
Throw New Exception("$$")
|
||||||
Else
|
Else
|
||||||
Throw
|
Throw
|
||||||
End If
|
End If
|
||||||
@@ -918,8 +940,8 @@ Retry:
|
|||||||
""RelyingParty"": ""http://auth.xboxlive.com"",
|
""RelyingParty"": ""http://auth.xboxlive.com"",
|
||||||
""TokenType"": ""JWT""
|
""TokenType"": ""JWT""
|
||||||
}"
|
}"
|
||||||
Dim Result As String = NetRequestMultiple("https://user.auth.xboxlive.com/user/authenticate", "POST", Request, "application/json", 3)
|
Dim Result As String = NetRequestByClientMultiple("https://user.auth.xboxlive.com/user/authenticate", HttpMethod.Post,
|
||||||
|
Content:=Request, ContentType:="application/json")
|
||||||
Dim ResultJson As JObject = GetJson(Result)
|
Dim ResultJson As JObject = GetJson(Result)
|
||||||
Dim XBLToken As String = ResultJson("Token").ToString
|
Dim XBLToken As String = ResultJson("Token").ToString
|
||||||
Return XBLToken
|
Return XBLToken
|
||||||
@@ -940,21 +962,22 @@ Retry:
|
|||||||
}"
|
}"
|
||||||
Dim Result As String
|
Dim Result As String
|
||||||
Try
|
Try
|
||||||
Result = NetRequestMultiple("https://xsts.auth.xboxlive.com/xsts/authorize", "POST", Request, "application/json", 3)
|
Result = NetRequestByClientMultiple("https://xsts.auth.xboxlive.com/xsts/authorize", HttpMethod.Post,
|
||||||
Catch ex As Net.WebException
|
Content:=Request, ContentType:="application/json")
|
||||||
|
Catch ex As ResponsedWebException
|
||||||
'参考 https://github.com/PrismarineJS/prismarine-auth/blob/master/src/common/Constants.js
|
'参考 https://github.com/PrismarineJS/prismarine-auth/blob/master/src/common/Constants.js
|
||||||
If ex.Message.Contains("2148916227") Then
|
If ex.Response.Contains("2148916227") Then
|
||||||
MyMsgBox("该账号似乎已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
|
MyMsgBox("该账号似乎已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
|
||||||
Throw New Exception("$$")
|
Throw New Exception("$$")
|
||||||
ElseIf ex.Message.Contains("2148916233") Then
|
ElseIf ex.Response.Contains("2148916233") Then
|
||||||
If MyMsgBox("你尚未注册 Xbox 账户,请在注册后再登录。", "登录提示", "注册", "取消") = 1 Then
|
If MyMsgBox("你尚未注册 Xbox 账户,请在注册后再登录。", "登录提示", "注册", "取消") = 1 Then
|
||||||
OpenWebsite("https://signup.live.com/signup")
|
OpenWebsite("https://signup.live.com/signup")
|
||||||
End If
|
End If
|
||||||
Throw New Exception("$$")
|
Throw New Exception("$$")
|
||||||
ElseIf ex.Message.Contains("2148916235") Then
|
ElseIf ex.Response.Contains("2148916235") Then
|
||||||
MyMsgBox($"你的网络所在的国家或地区无法登录微软账号。{vbCrLf}请使用加速器或 VPN。", "登录失败", "我知道了")
|
MyMsgBox($"你的网络所在的国家或地区无法登录微软账号。{vbCrLf}请使用加速器或 VPN。", "登录失败", "我知道了")
|
||||||
Throw New Exception("$$")
|
Throw New Exception("$$")
|
||||||
ElseIf ex.Message.Contains("2148916238") Then
|
ElseIf ex.Response.Contains("2148916238") Then
|
||||||
If MyMsgBox("该账号年龄不足,你需要先修改出生日期,然后才能登录。" & vbCrLf &
|
If MyMsgBox("该账号年龄不足,你需要先修改出生日期,然后才能登录。" & vbCrLf &
|
||||||
"该账号目前填写的年龄是否在 13 岁以上?", "登录提示", "13 岁以上", "12 岁以下", "我不知道") = 1 Then
|
"该账号目前填写的年龄是否在 13 岁以上?", "登录提示", "13 岁以上", "12 岁以下", "我不知道") = 1 Then
|
||||||
OpenWebsite("https://account.live.com/editprof.aspx")
|
OpenWebsite("https://account.live.com/editprof.aspx")
|
||||||
@@ -971,10 +994,15 @@ Retry:
|
|||||||
End If
|
End If
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
|
Try '这个 Try 块仅为了追踪 #6683 而添加
|
||||||
Dim ResultJson As JObject = GetJson(Result)
|
Dim ResultJson As JObject = GetJson(Result)
|
||||||
Dim XSTSToken As String = ResultJson("Token").ToString
|
Dim XSTSToken As String = ResultJson("Token").ToString
|
||||||
Dim UHS As String = ResultJson("DisplayClaims")("xui")(0)("uhs").ToString
|
Dim UHS As String = ResultJson("DisplayClaims")("xui")(0)("uhs").ToString
|
||||||
Return {XSTSToken, UHS}
|
Return {XSTSToken, UHS}
|
||||||
|
Catch
|
||||||
|
Log("[Launch] 返回内容:" & vbCrLf & Result)
|
||||||
|
Throw
|
||||||
|
End Try
|
||||||
End Function
|
End Function
|
||||||
'微软登录步骤 4:从 {XSTSToken, UHS} 获取 Minecraft AccessToken
|
'微软登录步骤 4:从 {XSTSToken, UHS} 获取 Minecraft AccessToken
|
||||||
Private Function MsLoginStep4(Tokens As String()) As String
|
Private Function MsLoginStep4(Tokens As String()) As String
|
||||||
@@ -983,14 +1011,15 @@ Retry:
|
|||||||
Dim Request As String = New JObject(New JProperty("identityToken", $"XBL3.0 x={Tokens(1)};{Tokens(0)}")).ToString(0)
|
Dim Request As String = New JObject(New JProperty("identityToken", $"XBL3.0 x={Tokens(1)};{Tokens(0)}")).ToString(0)
|
||||||
Dim Result As String
|
Dim Result As String
|
||||||
Try
|
Try
|
||||||
Result = NetRequestRetry("https://api.minecraftservices.com/authentication/login_with_xbox", "POST", Request, "application/json")
|
Result = NetRequestByClientRetry("https://api.minecraftservices.com/authentication/login_with_xbox", HttpMethod.Post,
|
||||||
|
Content:=Request, ContentType:="application/json")
|
||||||
Catch ex As Net.WebException
|
Catch ex As Net.WebException
|
||||||
Dim Message As String = GetExceptionSummary(ex)
|
Dim Message As String = GetExceptionSummary(ex)
|
||||||
If Message.Contains("(429)") Then
|
If Message.Contains("(429)") Then
|
||||||
Log(ex, "微软登录第 5 步汇报 429")
|
Log(ex, "微软登录第 4 步汇报 429")
|
||||||
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
||||||
ElseIf Message.Contains("(403)") Then
|
ElseIf Message.Contains("(403)") Then
|
||||||
Log(ex, "微软登录第 5 步汇报 403")
|
Log(ex, "微软登录第 4 步汇报 403")
|
||||||
Throw New Exception("$当前 IP 的登录尝试异常。" & vbCrLf & "如果你使用了 VPN 或加速器,请把它们关掉或更换节点后再试!")
|
Throw New Exception("$当前 IP 的登录尝试异常。" & vbCrLf & "如果你使用了 VPN 或加速器,请把它们关掉或更换节点后再试!")
|
||||||
Else
|
Else
|
||||||
Throw
|
Throw
|
||||||
@@ -1005,7 +1034,8 @@ Retry:
|
|||||||
Private Sub MsLoginStep5(AccessToken As String)
|
Private Sub MsLoginStep5(AccessToken As String)
|
||||||
McLaunchLog("开始微软登录步骤 5/6")
|
McLaunchLog("开始微软登录步骤 5/6")
|
||||||
|
|
||||||
Dim Result As String = NetRequestMultiple("https://api.minecraftservices.com/entitlements/mcstore", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
Dim Result As String = NetRequestByClientMultiple("https://api.minecraftservices.com/entitlements/mcstore",
|
||||||
|
ContentType:="application/json", ThreadCount:=2, Headers:={{"Authorization", "Bearer " & AccessToken}})
|
||||||
Try
|
Try
|
||||||
Dim ResultJson As JObject = GetJson(Result)
|
Dim ResultJson As JObject = GetJson(Result)
|
||||||
If Not (ResultJson.ContainsKey("items") AndAlso ResultJson("items").Any) Then
|
If Not (ResultJson.ContainsKey("items") AndAlso ResultJson("items").Any) Then
|
||||||
@@ -1016,7 +1046,7 @@ Retry:
|
|||||||
Throw New Exception("$$")
|
Throw New Exception("$$")
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "微软登录第 6 步异常:" & Result)
|
Log(ex, "微软登录第 5 步异常:" & Result)
|
||||||
Throw
|
Throw
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
@@ -1026,14 +1056,15 @@ Retry:
|
|||||||
|
|
||||||
Dim Result As String
|
Dim Result As String
|
||||||
Try
|
Try
|
||||||
Result = NetRequestMultiple("https://api.minecraftservices.com/minecraft/profile", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
Result = NetRequestByClientMultiple("https://api.minecraftservices.com/minecraft/profile",
|
||||||
|
ContentType:="application/json", ThreadCount:=2, Headers:={{"Authorization", "Bearer " & AccessToken}})
|
||||||
Catch ex As Net.WebException
|
Catch ex As Net.WebException
|
||||||
Dim Message As String = GetExceptionSummary(ex)
|
Dim Message As String = GetExceptionSummary(ex)
|
||||||
If Message.Contains("(429)") Then
|
If Message.Contains("(429)") Then
|
||||||
Log(ex, "微软登录第 7 步汇报 429")
|
Log(ex, "微软登录第 6 步汇报 429")
|
||||||
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
||||||
ElseIf Message.Contains("(404)") Then
|
ElseIf Message.Contains("(404)") Then
|
||||||
Log(ex, "微软登录第 7 步汇报 404")
|
Log(ex, "微软登录第 6 步汇报 404")
|
||||||
RunInNewThread(
|
RunInNewThread(
|
||||||
Sub()
|
Sub()
|
||||||
Select Case MyMsgBox("请先创建 Minecraft 玩家档案,然后再重新登录。", "登录失败", "创建档案", "取消")
|
Select Case MyMsgBox("请先创建 Minecraft 玩家档案,然后再重新登录。", "登录失败", "创建档案", "取消")
|
||||||
@@ -1099,7 +1130,7 @@ Retry:
|
|||||||
If Len(Uuid) = 32 Then Return Uuid
|
If Len(Uuid) = 32 Then Return Uuid
|
||||||
'从官网获取
|
'从官网获取
|
||||||
Try
|
Try
|
||||||
Dim GotJson As JObject = NetGetCodeByRequestRetry("https://api.mojang.com/users/profiles/minecraft/" & Name, IsJson:=True)
|
Dim GotJson As JObject = GetJson(NetRequestByClientRetry("https://api.mojang.com/users/profiles/minecraft/" & Name))
|
||||||
If GotJson Is Nothing Then Throw New FileNotFoundException("正版玩家档案不存在(" & Name & ")")
|
If GotJson Is Nothing Then Throw New FileNotFoundException("正版玩家档案不存在(" & Name & ")")
|
||||||
Uuid = If(GotJson("id"), "")
|
Uuid = If(GotJson("id"), "")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -1205,6 +1236,12 @@ Retry:
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
'LiteLoader 检测
|
||||||
|
If McVersionCurrent.Version.HasLiteLoader AndAlso McVersionCurrent.Version.IsStandardVersion Then '不管非标准版本
|
||||||
|
'最高 Java 8
|
||||||
|
MaxVer = If(New Version(1, 8, 999, 999) < MaxVer, New Version(1, 8, 999, 999), MaxVer)
|
||||||
|
End If
|
||||||
|
|
||||||
'统一通行证检测
|
'统一通行证检测
|
||||||
If Setup.Get("LoginType") = McLoginType.Nide Then
|
If Setup.Get("LoginType") = McLoginType.Nide Then
|
||||||
'至少 Java 8u101
|
'至少 Java 8u101
|
||||||
@@ -1349,23 +1386,13 @@ Retry:
|
|||||||
McLaunchLog("新版 Game 参数获取成功")
|
McLaunchLog("新版 Game 参数获取成功")
|
||||||
End If
|
End If
|
||||||
'编码参数(#4700、#5892、#5909)
|
'编码参数(#4700、#5892、#5909)
|
||||||
|
If McLaunchJavaSelected.VersionCode >= 18 Then 'Dfile.encoding 需要放在 Dstdout.encoding 后面(#6934)
|
||||||
|
If Not Arguments.Contains("-Dfile.encoding=") Then Arguments = "-Dfile.encoding=COMPAT " & Arguments
|
||||||
|
End If
|
||||||
If McLaunchJavaSelected.VersionCode > 8 Then
|
If McLaunchJavaSelected.VersionCode > 8 Then
|
||||||
If Not Arguments.Contains("-Dstdout.encoding=") Then Arguments = "-Dstdout.encoding=UTF-8 " & Arguments
|
If Not Arguments.Contains("-Dstdout.encoding=") Then Arguments = "-Dstdout.encoding=UTF-8 " & Arguments
|
||||||
If Not Arguments.Contains("-Dstderr.encoding=") Then Arguments = "-Dstderr.encoding=UTF-8 " & Arguments
|
If Not Arguments.Contains("-Dstderr.encoding=") Then Arguments = "-Dstderr.encoding=UTF-8 " & Arguments
|
||||||
End If
|
End If
|
||||||
If McLaunchJavaSelected.VersionCode >= 18 Then
|
|
||||||
If Not Arguments.Contains("-Dfile.encoding=") Then Arguments = "-Dfile.encoding=COMPAT " & Arguments
|
|
||||||
End If
|
|
||||||
'替换参数
|
|
||||||
Dim ReplaceArguments = McLaunchArgumentsReplace(McVersionCurrent, Loader)
|
|
||||||
If String.IsNullOrWhiteSpace(ReplaceArguments("${version_type}")) Then
|
|
||||||
'若自定义信息为空,则去掉该部分
|
|
||||||
Arguments = Arguments.Replace(" --versionType ${version_type}", "")
|
|
||||||
ReplaceArguments("${version_type}") = """"""
|
|
||||||
End If
|
|
||||||
For Each entry As KeyValuePair(Of String, String) In ReplaceArguments
|
|
||||||
Arguments = Arguments.Replace(entry.Key, If(entry.Value.Contains(" ") OrElse entry.Value.Contains(":\"), """" & entry.Value & """", entry.Value))
|
|
||||||
Next
|
|
||||||
'MJSB
|
'MJSB
|
||||||
Arguments = Arguments.Replace(" -Dos.name=Windows 10", " -Dos.name=""Windows 10""")
|
Arguments = Arguments.Replace(" -Dos.name=Windows 10", " -Dos.name=""Windows 10""")
|
||||||
'全屏
|
'全屏
|
||||||
@@ -1374,31 +1401,47 @@ Retry:
|
|||||||
For Each Arg In CurrentLaunchOptions.ExtraArgs
|
For Each Arg In CurrentLaunchOptions.ExtraArgs
|
||||||
Arguments += " " & Arg.Trim
|
Arguments += " " & Arg.Trim
|
||||||
Next
|
Next
|
||||||
|
'自定义
|
||||||
|
Dim ArgumentGame As String = Setup.Get("VersionAdvanceGame", Version:=McVersionCurrent)
|
||||||
|
Arguments += " " & If(ArgumentGame = "", Setup.Get("LaunchAdvanceGame"), ArgumentGame)
|
||||||
|
'进行参数替换
|
||||||
|
Dim ReplaceArguments = McLaunchArgumentsReplace(McVersionCurrent, Loader)
|
||||||
|
If String.IsNullOrWhiteSpace(ReplaceArguments("${version_type}")) Then
|
||||||
|
'若自定义信息为空,则去掉该部分
|
||||||
|
Arguments = Arguments.Replace(" --versionType ${version_type}", "")
|
||||||
|
ReplaceArguments("${version_type}") = """"""
|
||||||
|
End If
|
||||||
|
Dim FinalArguments As String = ""
|
||||||
|
For Each Argument In Arguments.Split(" ")
|
||||||
|
For Each Entry As KeyValuePair(Of String, String) In ReplaceArguments
|
||||||
|
Argument = Argument.Replace(Entry.Key, Entry.Value)
|
||||||
|
Next
|
||||||
|
If (Argument.Contains(" ") OrElse Argument.Contains(":\")) AndAlso Not Argument.EndsWithF("""") Then Argument = $"""{Argument}"""
|
||||||
|
FinalArguments += Argument & " "
|
||||||
|
Next
|
||||||
|
FinalArguments = FinalArguments.TrimEnd
|
||||||
'进服
|
'进服
|
||||||
Dim Server As String = If(String.IsNullOrEmpty(CurrentLaunchOptions.ServerIp), Setup.Get("VersionServerEnter", McVersionCurrent), CurrentLaunchOptions.ServerIp)
|
Dim Server As String = If(String.IsNullOrEmpty(CurrentLaunchOptions.ServerIp), Setup.Get("VersionServerEnter", McVersionCurrent), CurrentLaunchOptions.ServerIp)
|
||||||
If Server.Length > 0 Then
|
If Server.Length > 0 Then
|
||||||
If McVersionCurrent.ReleaseTime > New Date(2023, 4, 4) Then
|
If McVersionCurrent.ReleaseTime > New Date(2023, 4, 4) Then
|
||||||
'QuickPlay
|
'QuickPlay
|
||||||
Arguments += $" --quickPlayMultiplayer ""{Server}"""
|
FinalArguments += $" --quickPlayMultiplayer ""{Server}"""
|
||||||
Else
|
Else
|
||||||
'老版本
|
'老版本
|
||||||
If Server.Contains(":") Then
|
If Server.Contains(":") Then
|
||||||
'包含端口号
|
'包含端口号
|
||||||
Arguments += " --server " & Server.Split(":")(0) & " --port " & Server.Split(":")(1)
|
FinalArguments += $" --server {Server.Split(":")(0)} --port {Server.Split(":")(1)}"
|
||||||
Else
|
Else
|
||||||
'不包含端口号
|
'不包含端口号
|
||||||
Arguments += " --server " & Server & " --port 25565"
|
FinalArguments += $" --server {Server} --port 25565"
|
||||||
End If
|
End If
|
||||||
If McVersionCurrent.Version.HasOptiFine Then Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
|
If McVersionCurrent.Version.HasOptiFine Then Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
'自定义
|
|
||||||
Dim ArgumentGame As String = Setup.Get("VersionAdvanceGame", Version:=McVersionCurrent)
|
|
||||||
Arguments += " " & If(ArgumentGame = "", Setup.Get("LaunchAdvanceGame"), ArgumentGame)
|
|
||||||
'输出
|
'输出
|
||||||
McLaunchLog("Minecraft 启动参数:")
|
McLaunchLog("Minecraft 启动参数:")
|
||||||
McLaunchLog(Arguments)
|
McLaunchLog(FinalArguments)
|
||||||
McLaunchArgument = Arguments
|
McLaunchArgument = FinalArguments
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'Jvm 部分(第一段)
|
'Jvm 部分(第一段)
|
||||||
@@ -1424,11 +1467,12 @@ Retry:
|
|||||||
End If
|
End If
|
||||||
'Authlib-Injector
|
'Authlib-Injector
|
||||||
If McLoginLoader.Output.Type = "Auth" Then
|
If McLoginLoader.Output.Type = "Auth" Then
|
||||||
|
If McLaunchJavaSelected.VersionCode >= 6 Then DataList.Add("-Djavax.net.ssl.trustStoreType=WINDOWS-ROOT") '信任系统根证书(5252#)
|
||||||
Dim Server As String = If(McLoginLoader.Input.Type = McLoginType.Legacy,
|
Dim Server As String = If(McLoginLoader.Input.Type = McLoginType.Legacy,
|
||||||
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
||||||
Setup.Get("VersionServerAuthServer", McVersionCurrent))
|
Setup.Get("VersionServerAuthServer", McVersionCurrent))
|
||||||
Try
|
Try
|
||||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
Dim Response As String = NetRequestByClientRetry(Server, Encoding:=Encoding.UTF8)
|
||||||
DataList.Insert(0, "-javaagent:""" & PathPure & "authlib-injector.jar""=" & Server &
|
DataList.Insert(0, "-javaagent:""" & PathPure & "authlib-injector.jar""=" & Server &
|
||||||
" -Dauthlibinjector.side=client" &
|
" -Dauthlibinjector.side=client" &
|
||||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||||
@@ -1493,11 +1537,12 @@ NextVersion:
|
|||||||
End If
|
End If
|
||||||
'Authlib-Injector
|
'Authlib-Injector
|
||||||
If McLoginLoader.Output.Type = "Auth" Then
|
If McLoginLoader.Output.Type = "Auth" Then
|
||||||
|
If McLaunchJavaSelected.VersionCode >= 6 Then DataList.Add("-Djavax.net.ssl.trustStoreType=WINDOWS-ROOT") '信任系统根证书(5252#)
|
||||||
Dim Server As String = If(McLoginLoader.Input.Type = McLoginType.Legacy,
|
Dim Server As String = If(McLoginLoader.Input.Type = McLoginType.Legacy,
|
||||||
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
||||||
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
||||||
Try
|
Try
|
||||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
Dim Response As String = NetRequestByClientRetry(Server, Encoding:=Encoding.UTF8)
|
||||||
DataList.Insert(0, "-javaagent:""" & PathPure & "authlib-injector.jar""=" & Server &
|
DataList.Insert(0, "-javaagent:""" & PathPure & "authlib-injector.jar""=" & Server &
|
||||||
" -Dauthlibinjector.side=client" &
|
" -Dauthlibinjector.side=client" &
|
||||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||||
@@ -1531,10 +1576,8 @@ NextVersion:
|
|||||||
DeDuplicateDataList.Add(CurrentEntry.Trim.Replace("McEmu= ", "McEmu="))
|
DeDuplicateDataList.Add(CurrentEntry.Trim.Replace("McEmu= ", "McEmu="))
|
||||||
Next
|
Next
|
||||||
|
|
||||||
'#3511 的清理
|
|
||||||
DeDuplicateDataList.Remove("-XX:MaxDirectMemorySize=256M")
|
|
||||||
|
|
||||||
'去重
|
'去重
|
||||||
|
DeDuplicateDataList.Remove("-XX:MaxDirectMemorySize=256M") '#3511 的清理
|
||||||
Dim Result As String = Join(DeDuplicateDataList.Distinct.ToList, " ")
|
Dim Result As String = Join(DeDuplicateDataList.Distinct.ToList, " ")
|
||||||
|
|
||||||
'添加 MainClass
|
'添加 MainClass
|
||||||
@@ -1671,6 +1714,7 @@ NextVersion:
|
|||||||
GameArguments.Add("${access_token}", McLoginLoader.Output.AccessToken)
|
GameArguments.Add("${access_token}", McLoginLoader.Output.AccessToken)
|
||||||
GameArguments.Add("${auth_session}", McLoginLoader.Output.AccessToken)
|
GameArguments.Add("${auth_session}", McLoginLoader.Output.AccessToken)
|
||||||
GameArguments.Add("${user_type}", "msa") '#1221
|
GameArguments.Add("${user_type}", "msa") '#1221
|
||||||
|
GameArguments.Add("${primary_jar}", Version.Path & Version.Name & ".jar") '#6942
|
||||||
|
|
||||||
'窗口尺寸参数
|
'窗口尺寸参数
|
||||||
Dim GameSize As Size
|
Dim GameSize As Size
|
||||||
|
|||||||
@@ -169,8 +169,8 @@ Public Module ModMinecraft
|
|||||||
_McVersionCurrent = value '由于有可能是 Nothing,导致无法初始化,才得这样弄一圈
|
_McVersionCurrent = value '由于有可能是 Nothing,导致无法初始化,才得这样弄一圈
|
||||||
_McVersionLast = value
|
_McVersionLast = value
|
||||||
If value Is Nothing Then Return
|
If value Is Nothing Then Return
|
||||||
'重置缓存的 Mod 文件夹
|
'重置缓存的下载文件夹
|
||||||
PageDownloadCompDetail.CachedFolder = Nothing
|
PageDownloadCompDetail.CachedFolder.Clear()
|
||||||
'统一通行证重判
|
'统一通行证重判
|
||||||
If AniControlEnabled = 0 AndAlso
|
If AniControlEnabled = 0 AndAlso
|
||||||
Setup.Get("VersionServerNide", Version:=value) <> Setup.Get("CacheNideServer") AndAlso
|
Setup.Get("VersionServerNide", Version:=value) <> Setup.Get("CacheNideServer") AndAlso
|
||||||
@@ -440,6 +440,33 @@ VersionSearchFinish:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public ReleaseTime As New Date(1970, 1, 1, 15, 0, 0)
|
Public ReleaseTime As New Date(1970, 1, 1, 15, 0, 0)
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' 获取该版本的 JSON 路径。
|
||||||
|
''' </summary>
|
||||||
|
Public Function GetJsonPath() As String
|
||||||
|
Dim JsonPath As String = Path & Name & ".json"
|
||||||
|
If Not File.Exists(JsonPath) Then
|
||||||
|
'尝试寻找 JSON 文件
|
||||||
|
JsonPath = Nothing
|
||||||
|
For Each JsonCandidatePath In Directory.GetFiles(Path, "*.json")
|
||||||
|
Try
|
||||||
|
Dim JsonCandidate As JObject = GetJson(ReadFile(JsonCandidatePath))
|
||||||
|
If Not JsonCandidate.ContainsKey("mainClass") Then Continue For
|
||||||
|
If Not JsonCandidate.ContainsKey("type") Then Continue For
|
||||||
|
If Not JsonCandidate.ContainsKey("id") Then Continue For
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
JsonPath = JsonCandidatePath
|
||||||
|
Exit For
|
||||||
|
Next
|
||||||
|
If JsonPath Is Nothing Then
|
||||||
|
Throw New Exception($"未找到版本 JSON 文件:{Path}{Name}.json")
|
||||||
|
Else
|
||||||
|
Log("[Minecraft] 未找到同名版本 JSON,自动换用 " & JsonPath, LogLevel.Debug)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return JsonPath
|
||||||
|
End Function
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 该版本的 Json 文本。
|
''' 该版本的 Json 文本。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -452,17 +479,7 @@ VersionSearchFinish:
|
|||||||
Return TrimedJson.StartsWithF("{") AndAlso TrimedJson.EndsWithF("}")
|
Return TrimedJson.StartsWithF("{") AndAlso TrimedJson.EndsWithF("}")
|
||||||
End Function
|
End Function
|
||||||
If _JsonText Is Nothing Then
|
If _JsonText Is Nothing Then
|
||||||
Dim JsonPath As String = Path & Name & ".json"
|
Dim JsonPath As String = GetJsonPath()
|
||||||
If Not File.Exists(JsonPath) Then
|
|
||||||
'如果文件夹下只有一个 JSON 文件,则将其作为版本 JSON
|
|
||||||
Dim JsonFiles As String() = Directory.GetFiles(Path, "*.json")
|
|
||||||
If JsonFiles.Count = 1 Then
|
|
||||||
JsonPath = JsonFiles(0)
|
|
||||||
Log("[Minecraft] 未找到同名版本 JSON,自动换用 " & JsonPath, LogLevel.Debug)
|
|
||||||
Else
|
|
||||||
Throw New Exception($"未找到版本 JSON 文件:{Path}{Name}.json")
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
_JsonText = ReadFile(JsonPath)
|
_JsonText = ReadFile(JsonPath)
|
||||||
'如果 ReadFile 失败会返回空字符串;这可能是由于文件被临时占用,故延时后重试
|
'如果 ReadFile 失败会返回空字符串;这可能是由于文件被临时占用,故延时后重试
|
||||||
If Not FastJsonCheck(_JsonText) Then
|
If Not FastJsonCheck(_JsonText) Then
|
||||||
@@ -540,9 +557,15 @@ Recheck:
|
|||||||
'继续循环
|
'继续循环
|
||||||
If Inherit.InheritVersion = InheritVersion Then Throw New Exception("版本依赖项出现嵌套:" & InheritVersion)
|
If Inherit.InheritVersion = InheritVersion Then Throw New Exception("版本依赖项出现嵌套:" & InheritVersion)
|
||||||
InheritVersion = Inherit.InheritVersion
|
InheritVersion = Inherit.InheritVersion
|
||||||
'合并
|
'合并 Libraries 项:子版本放在前面,父版本放在后面(5978#:如果多个 jar 包中含有相同的类,Java 8 和之前的版本按照 -cp 指定的顺序选择第一个)
|
||||||
|
Dim CurrentLib As JArray = _JsonObject("libraries").DeepClone()
|
||||||
|
For Each LibToken In Inherit.JsonObject("libraries")
|
||||||
|
CurrentLib.Add(LibToken)
|
||||||
|
Next
|
||||||
|
'合并其他项:子版本优先于父版本
|
||||||
Inherit.JsonObject.Merge(_JsonObject)
|
Inherit.JsonObject.Merge(_JsonObject)
|
||||||
_JsonObject = Inherit.JsonObject
|
_JsonObject = Inherit.JsonObject
|
||||||
|
_JsonObject("libraries") = CurrentLib
|
||||||
GoTo Recheck
|
GoTo Recheck
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -580,21 +603,19 @@ Recheck:
|
|||||||
Get
|
Get
|
||||||
If Not JsonVersionInited Then
|
If Not JsonVersionInited Then
|
||||||
JsonVersionInited = True
|
JsonVersionInited = True
|
||||||
If File.Exists(Path & Name & ".jar") Then
|
|
||||||
Try
|
Try
|
||||||
|
If Not File.Exists($"{Path}{Name}.jar") Then Exit Try
|
||||||
Using JarArchive As New ZipArchive(New FileStream(Path & Name & ".jar", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
Using JarArchive As New ZipArchive(New FileStream(Path & Name & ".jar", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
Dim VersionJson As ZipArchiveEntry = JarArchive.GetEntry("version.json")
|
Dim VersionJson As ZipArchiveEntry = JarArchive.GetEntry("version.json")
|
||||||
If VersionJson IsNot Nothing Then
|
If VersionJson Is Nothing Then Exit Try
|
||||||
Using VersionJsonStream As New StreamReader(VersionJson.Open)
|
Using VersionJsonStream As New StreamReader(VersionJson.Open)
|
||||||
_JsonVersion = GetJson(VersionJsonStream.ReadToEnd)
|
_JsonVersion = GetJson(VersionJsonStream.ReadToEnd)
|
||||||
End Using
|
End Using
|
||||||
End If
|
|
||||||
End Using
|
End Using
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "从版本 jar 中读取 version.json 失败")
|
Log(ex, $"从版本 jar 中读取 version.json 失败({Path}{Name}.jar)")
|
||||||
End Try
|
End Try
|
||||||
End If
|
End If
|
||||||
End If
|
|
||||||
Return _JsonVersion
|
Return _JsonVersion
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
@@ -968,7 +989,7 @@ ExitDataLoad:
|
|||||||
If ToString = "" Then
|
If ToString = "" Then
|
||||||
Return "原版 " & McName
|
Return "原版 " & McName
|
||||||
Else
|
Else
|
||||||
Return McName & ToString & If(ModeDebug, " (" & SortCode & "#)", "")
|
Return McName & ToString
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
@@ -1538,7 +1559,7 @@ OnLoaded:
|
|||||||
''' 要求玩家选择一个皮肤文件,并进行相关校验。
|
''' 要求玩家选择一个皮肤文件,并进行相关校验。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function McSkinSelect() As McSkinInfo
|
Public Function McSkinSelect() As McSkinInfo
|
||||||
Dim FileName As String = SelectFile("皮肤文件(*.png;*.jpg;*.webp)|*.png;*.jpg;*.webp", "选择皮肤文件")
|
Dim FileName As String = SelectFile("皮肤文件(*.png;*.jpg;*.jpeg;*.webp)|*.png;*.jpg;*.jpeg;*.webp", "选择皮肤文件")
|
||||||
|
|
||||||
'验证有效性
|
'验证有效性
|
||||||
If FileName = "" Then Return New McSkinInfo With {.IsVaild = False}
|
If FileName = "" Then Return New McSkinInfo With {.IsVaild = False}
|
||||||
@@ -1589,7 +1610,7 @@ OnLoaded:
|
|||||||
Case Else
|
Case Else
|
||||||
Throw New ArgumentException("皮肤地址种类无效:" & If(Type, "null"))
|
Throw New ArgumentException("皮肤地址种类无效:" & If(Type, "null"))
|
||||||
End Select
|
End Select
|
||||||
Dim SkinString = NetGetCodeByRequestRetry(Url & Uuid)
|
Dim SkinString = NetRequestByClientRetry(Url & Uuid)
|
||||||
If SkinString = "" Then Throw New Exception("皮肤返回值为空,可能是未设置自定义皮肤的用户")
|
If SkinString = "" Then Throw New Exception("皮肤返回值为空,可能是未设置自定义皮肤的用户")
|
||||||
'处理皮肤地址
|
'处理皮肤地址
|
||||||
Dim SkinValue As String
|
Dim SkinValue As String
|
||||||
@@ -1610,7 +1631,8 @@ OnLoaded:
|
|||||||
If SkinJson("textures") Is Nothing OrElse SkinJson("textures")("skin") Is Nothing OrElse SkinJson("textures")("skin")("url") Is Nothing Then
|
If SkinJson("textures") Is Nothing OrElse SkinJson("textures")("skin") Is Nothing OrElse SkinJson("textures")("skin")("url") Is Nothing Then
|
||||||
Throw New Exception("用户未设置自定义皮肤")
|
Throw New Exception("用户未设置自定义皮肤")
|
||||||
Else
|
Else
|
||||||
SkinValue = SkinJson("textures")("skin")("url").ToString.Replace("http:", "https:")
|
Dim SkinUrl As String = SkinJson("textures")("skin")("url").ToString
|
||||||
|
SkinValue = If(SkinUrl.Contains("minecraft.net/"), SkinUrl.Replace("http://", "https://"), SkinUrl)
|
||||||
End If
|
End If
|
||||||
'保存缓存
|
'保存缓存
|
||||||
WriteIni(PathTemp & "Cache\Skin\Index" & Type & ".ini", Uuid, SkinValue)
|
WriteIni(PathTemp & "Cache\Skin\Index" & Type & ".ini", Uuid, SkinValue)
|
||||||
@@ -1627,9 +1649,9 @@ OnLoaded:
|
|||||||
Dim FileAddress As String = PathTemp & "Cache\Skin\" & GetHash(Address) & ".png"
|
Dim FileAddress As String = PathTemp & "Cache\Skin\" & GetHash(Address) & ".png"
|
||||||
SyncLock McSkinDownloadLock
|
SyncLock McSkinDownloadLock
|
||||||
If Not File.Exists(FileAddress) Then
|
If Not File.Exists(FileAddress) Then
|
||||||
NetDownloadByClient(Address, FileAddress & NetDownloadEnd)
|
NetDownloadByClient(Address, FileAddress & ".PCLDownloading")
|
||||||
File.Delete(FileAddress)
|
File.Delete(FileAddress)
|
||||||
FileSystem.Rename(FileAddress & NetDownloadEnd, FileAddress)
|
FileSystem.Rename(FileAddress & ".PCLDownloading", FileAddress)
|
||||||
Log("[Minecraft] 皮肤下载成功:" & FileAddress)
|
Log("[Minecraft] 皮肤下载成功:" & FileAddress)
|
||||||
End If
|
End If
|
||||||
Return FileAddress
|
Return FileAddress
|
||||||
@@ -1772,10 +1794,10 @@ OnLoaded:
|
|||||||
|
|
||||||
'获取当前支持库列表
|
'获取当前支持库列表
|
||||||
Log("[Minecraft] 获取支持库列表:" & Version.Name)
|
Log("[Minecraft] 获取支持库列表:" & Version.Name)
|
||||||
McLibListGet = McLibListGetWithJson(Version.JsonObject)
|
Dim Result = McLibListGetWithJson(Version.JsonObject)
|
||||||
If Not IncludeVersionJar Then Return McLibListGet
|
|
||||||
|
|
||||||
'需要添加原版 Jar
|
'需要添加原版 Jar
|
||||||
|
If IncludeVersionJar Then
|
||||||
Dim RealVersion As McVersion
|
Dim RealVersion As McVersion
|
||||||
Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
|
Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
|
||||||
If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
|
If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
|
||||||
@@ -1812,21 +1834,20 @@ OnLoaded:
|
|||||||
ClientSHA1 = Nothing
|
ClientSHA1 = Nothing
|
||||||
End If
|
End If
|
||||||
'把所需的原版 Jar 添加进去
|
'把所需的原版 Jar 添加进去
|
||||||
McLibListGet.Add(New McLibToken With {.LocalPath = RealVersion.Path & RealVersion.Name & ".jar", .Size = 0, .IsNatives = False, .Url = ClientUrl, .SHA1 = ClientSHA1})
|
Result.Add(New McLibToken With {.LocalPath = RealVersion.Path & RealVersion.Name & ".jar", .Size = 0, .IsNatives = False, .Url = ClientUrl, .SHA1 = ClientSHA1})
|
||||||
|
End If
|
||||||
|
|
||||||
|
Return Result
|
||||||
End Function
|
End Function
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 Minecraft 某一版本忽视继承的支持库列表,即结果中没有继承项。
|
''' 获取 Minecraft 某一版本忽视继承的支持库列表,即结果中没有继承项。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function McLibListGetWithJson(JsonObject As JObject, Optional KeepSameNameDifferentVersionResult As Boolean = False, Optional CustomMcFolder As String = Nothing) As List(Of McLibToken)
|
Public Function McLibListGetWithJson(JsonObject As JObject, Optional KeepSameNameDifferentVersionResult As Boolean = False, Optional CustomMcFolder As String = Nothing) As List(Of McLibToken)
|
||||||
CustomMcFolder = If(CustomMcFolder, PathMcFolder)
|
CustomMcFolder = If(CustomMcFolder, PathMcFolder)
|
||||||
Dim BasicArray As New List(Of McLibToken)
|
|
||||||
|
|
||||||
'添加基础 Json 项
|
|
||||||
Dim AllLibs As JArray = JsonObject("libraries")
|
|
||||||
|
|
||||||
'转换为 LibToken
|
'转换为 LibToken
|
||||||
For Each Library As JObject In AllLibs.Children
|
Dim BasicArray As New List(Of McLibToken)
|
||||||
|
For Each Library As JObject In CType(JsonObject("libraries"), JArray).Children
|
||||||
|
|
||||||
'清理 null 项(BakaXL 会把没有的项序列化为 null,但会被 Newtonsoft 转换为 JValue,导致 Is Nothing = false;这导致了 #409)
|
'清理 null 项(BakaXL 会把没有的项序列化为 null,但会被 Newtonsoft 转换为 JValue,导致 Is Nothing = false;这导致了 #409)
|
||||||
For i = Library.Properties.Count - 1 To 0 Step -1
|
For i = Library.Properties.Count - 1 To 0 Step -1
|
||||||
@@ -1945,8 +1966,7 @@ OnLoaded:
|
|||||||
Try
|
Try
|
||||||
Log("[Minecraft] 开始获取统一通行证下载信息")
|
Log("[Minecraft] 开始获取统一通行证下载信息")
|
||||||
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
|
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
|
||||||
DownloadInfo = GetJson(NetGetCodeByLoader({
|
DownloadInfo = GetJson(NetRequestByClientRetry("https://auth.mc-user.com:233/" & Setup.Get("VersionServerNide", Version:=Version)))
|
||||||
"https://auth.mc-user.com:233/" & Setup.Get("VersionServerNide", Version:=Version)}, IsJson:=True))
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "获取统一通行证下载信息失败")
|
Log(ex, "获取统一通行证下载信息失败")
|
||||||
End Try
|
End Try
|
||||||
@@ -1968,10 +1988,9 @@ OnLoaded:
|
|||||||
'获取下载信息
|
'获取下载信息
|
||||||
Try
|
Try
|
||||||
Log("[Minecraft] 开始获取 Authlib-Injector 下载信息")
|
Log("[Minecraft] 开始获取 Authlib-Injector 下载信息")
|
||||||
DownloadInfo = GetJson(NetGetCodeByLoader({
|
DownloadInfo = GetJson(NetRequestByClientRetry(
|
||||||
"https://authlib-injector.yushi.moe/artifact/latest.json",
|
"https://authlib-injector.yushi.moe/artifact/latest.json",
|
||||||
"https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json"
|
BackupUrl:="https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json"))
|
||||||
}, IsJson:=True))
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "获取 Authlib-Injector 下载信息失败")
|
Log(ex, "获取 Authlib-Injector 下载信息失败")
|
||||||
End Try
|
End Try
|
||||||
@@ -2016,12 +2035,16 @@ OnLoaded:
|
|||||||
'获取
|
'获取
|
||||||
For Each Token As McLibToken In Libs
|
For Each Token As McLibToken In Libs
|
||||||
'检查文件
|
'检查文件
|
||||||
Dim Checker As New FileChecker(ActualSize:=If(Token.Size = 0, -1, Token.Size), Hash:=Token.SHA1)
|
Dim Checker As FileChecker
|
||||||
|
If Token.Name.ContainsF("labymod") Then
|
||||||
|
Checker = New FileChecker '不检查 LabyMod 的文件,它们提供的文件校验信息是错的(#3225)
|
||||||
|
Else
|
||||||
|
Checker = New FileChecker(ActualSize:=If(Token.Size = 0, -1, Token.Size), Hash:=Token.SHA1)
|
||||||
|
End If
|
||||||
If Checker.Check(Token.LocalPath) Is Nothing Then Continue For
|
If Checker.Check(Token.LocalPath) Is Nothing Then Continue For
|
||||||
'文件不符合,添加下载
|
'文件不符合,添加下载
|
||||||
Dim Urls As New List(Of String)
|
Dim Urls As New List(Of String)
|
||||||
If Token.Url Is Nothing AndAlso Token.Name = "net.minecraftforge:forge:universal" Then
|
If Token.Url Is Nothing AndAlso Token.Name = "net.minecraftforge:forge:universal" Then '特判修复 Forge 部分 universal 文件缺失 URL(#5455)
|
||||||
'特判修复 Forge 部分 universal 文件缺失 URL(#5455)
|
|
||||||
Token.Url = "https://maven.minecraftforge.net" & Token.LocalPath.Replace(CustomMcFolder & "libraries", "").Replace("\", "/")
|
Token.Url = "https://maven.minecraftforge.net" & Token.LocalPath.Replace(CustomMcFolder & "libraries", "").Replace("\", "/")
|
||||||
End If
|
End If
|
||||||
If Token.Url IsNot Nothing Then
|
If Token.Url IsNot Nothing Then
|
||||||
@@ -2193,16 +2216,16 @@ OnLoaded:
|
|||||||
Dim LocalPath As String
|
Dim LocalPath As String
|
||||||
If Json("map_to_resources") IsNot Nothing AndAlso Json("map_to_resources").ToObject(Of Boolean) Then
|
If Json("map_to_resources") IsNot Nothing AndAlso Json("map_to_resources").ToObject(Of Boolean) Then
|
||||||
'Remap
|
'Remap
|
||||||
LocalPath = Version.PathIndie & "resources\" & File.Name.Replace("/", "\")
|
LocalPath = $"{Version.PathIndie}resources\{File.Name}"
|
||||||
ElseIf Json("virtual") IsNot Nothing AndAlso Json("virtual").ToObject(Of Boolean) Then
|
ElseIf Json("virtual") IsNot Nothing AndAlso Json("virtual").ToObject(Of Boolean) Then
|
||||||
'Virtual
|
'Virtual
|
||||||
LocalPath = PathMcFolder & "assets\virtual\legacy\" & File.Name.Replace("/", "\")
|
LocalPath = $"{PathMcFolder}assets\virtual\legacy\{File.Name}"
|
||||||
Else
|
Else
|
||||||
'正常
|
'正常
|
||||||
LocalPath = PathMcFolder & "assets\objects\" & Left(File.Value("hash").ToString, 2) & "\" & File.Value("hash").ToString
|
LocalPath = $"{PathMcFolder}assets\objects\{Left(File.Value("hash").ToString, 2)}\{File.Value("hash")}"
|
||||||
End If
|
End If
|
||||||
Result.Add(New McAssetsToken With {
|
Result.Add(New McAssetsToken With {
|
||||||
.LocalPath = LocalPath,
|
.LocalPath = LocalPath.Replace("/", "\"),
|
||||||
.SourcePath = File.Name,
|
.SourcePath = File.Name,
|
||||||
.Hash = File.Value("hash").ToString,
|
.Hash = File.Value("hash").ToString,
|
||||||
.Size = File.Value("size").ToString
|
.Size = File.Value("size").ToString
|
||||||
@@ -2392,7 +2415,7 @@ NextEntry:
|
|||||||
Public Function FilterUserName(Raw As String, FilterChar As Char) As String
|
Public Function FilterUserName(Raw As String, FilterChar As Char) As String
|
||||||
If Raw.Contains(":\Users\") Then
|
If Raw.Contains(":\Users\") Then
|
||||||
For Each Token In RegexSearch(Raw, "(?<=:\\Users\\)[^\\]+")
|
For Each Token In RegexSearch(Raw, "(?<=:\\Users\\)[^\\]+")
|
||||||
Raw = Raw.Replace(Token, New String(FilterChar, Token.Count))
|
Raw = Raw.Replace("\" & Token, "\" & New String(FilterChar, Token.Count))
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
Return Raw
|
Return Raw
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Imports System.IO.Compression
|
Imports System.IO.Compression
|
||||||
|
|
||||||
Public Module ModMod
|
Public Module ModMod
|
||||||
Private Const LocalModCacheVersion As Integer = 7
|
Private Const LocalModCacheVersion As Integer = 8
|
||||||
|
|
||||||
Public Class McMod
|
Public Class McMod
|
||||||
|
|
||||||
@@ -688,7 +688,7 @@ Finished:
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public ReadOnly Property CanUpdate As Boolean
|
Public ReadOnly Property CanUpdate As Boolean
|
||||||
Get
|
Get
|
||||||
Return Not Setup.Get("UiHiddenFunctionModUpdate") AndAlso ChangelogUrls.Any()
|
Return Not Setup.Get("UiHiddenFunctionModUpdate") AndAlso Not Setup.Get("VersionAdvanceDisableModUpdate", Version:=PageVersionLeft.Version) AndAlso ChangelogUrls.Any()
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
|
||||||
@@ -946,8 +946,8 @@ Finished:
|
|||||||
Try
|
Try
|
||||||
'步骤 1:获取 Hash 与对应的工程 ID
|
'步骤 1:获取 Hash 与对应的工程 ID
|
||||||
Dim ModrinthHashes = Mods.Select(Function(m) m.ModrinthHash).ToList()
|
Dim ModrinthHashes = Mods.Select(Function(m) m.ModrinthHash).ToList()
|
||||||
Dim ModrinthVersion = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files", "POST",
|
Dim ModrinthVersion As JObject = DlModRequest("https://api.modrinth.com/v2/version_files", HttpMethod.Post,
|
||||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")), JObject)
|
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")
|
||||||
Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息")
|
Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息")
|
||||||
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
||||||
If ModrinthVersion.Count = 0 Then Return
|
If ModrinthVersion.Count = 0 Then Return
|
||||||
@@ -967,9 +967,8 @@ Finished:
|
|||||||
Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息")
|
Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息")
|
||||||
'步骤 3:获取工程信息
|
'步骤 3:获取工程信息
|
||||||
If Not ModrinthMapping.Any() Then Return
|
If Not ModrinthMapping.Any() Then Return
|
||||||
Dim ModrinthProject = CType(GetJson(DlModRequest(
|
Dim ModrinthProject As JArray = DlModRequest(
|
||||||
$"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]",
|
$"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]")
|
||||||
"GET", "", "application/json")), JArray)
|
|
||||||
For Each ProjectJson In ModrinthProject
|
For Each ProjectJson In ModrinthProject
|
||||||
Dim Project As New CompProject(ProjectJson)
|
Dim Project As New CompProject(ProjectJson)
|
||||||
For Each Entry In ModrinthMapping(Project.Id)
|
For Each Entry In ModrinthMapping(Project.Id)
|
||||||
@@ -978,9 +977,9 @@ Finished:
|
|||||||
Next
|
Next
|
||||||
Log($"[Mod] 已从 Modrinth 获取本地 Mod 信息,继续获取更新信息")
|
Log($"[Mod] 已从 Modrinth 获取本地 Mod 信息,继续获取更新信息")
|
||||||
'步骤 4:获取更新信息
|
'步骤 4:获取更新信息
|
||||||
Dim ModrinthUpdate = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files/update", "POST",
|
Dim ModrinthUpdate As JObject = DlModRequest("https://api.modrinth.com/v2/version_files/update", HttpMethod.Post,
|
||||||
$"{{""hashes"": [""{ModrinthMapping.SelectMany(Function(l) l.Value.Select(Function(m) m.ModrinthHash)).Join(""",""")}""], ""algorithm"": ""sha1"",
|
$"{{""hashes"": [""{ModrinthMapping.SelectMany(Function(l) l.Value.Select(Function(m) m.ModrinthHash)).Join(""",""")}""], ""algorithm"": ""sha1"",
|
||||||
""loaders"": [""{ModLoaders.Join(""",""").ToLower}""],""game_versions"": [""{McVersion}""]}}", "application/json")), JObject)
|
""loaders"": [""{ModLoaders.Join(""",""").ToLower}""],""game_versions"": [""{McVersion}""]}}", "application/json")
|
||||||
For Each Entry In Mods
|
For Each Entry In Mods
|
||||||
If Not ModrinthUpdate.ContainsKey(Entry.ModrinthHash) OrElse Entry.CompFile Is Nothing Then Continue For
|
If Not ModrinthUpdate.ContainsKey(Entry.ModrinthHash) OrElse Entry.CompFile Is Nothing Then Continue For
|
||||||
Dim UpdateFile As New CompFile(ModrinthUpdate(Entry.ModrinthHash), CompType.Mod)
|
Dim UpdateFile As New CompFile(ModrinthUpdate(Entry.ModrinthHash), CompType.Mod)
|
||||||
@@ -1015,8 +1014,8 @@ Finished:
|
|||||||
CurseForgeHashes.Add(Entry.CurseForgeHash)
|
CurseForgeHashes.Add(Entry.CurseForgeHash)
|
||||||
If Loader.IsAbortedWithThread(CurrentTaskThread) Then Return
|
If Loader.IsAbortedWithThread(CurrentTaskThread) Then Return
|
||||||
Next
|
Next
|
||||||
Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432", "POST",
|
Dim CurseForgeRaw As JContainer = DlModRequest("https://api.curseforge.com/v1/fingerprints/432", HttpMethod.Post,
|
||||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer)
|
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")("data")("exactMatches")
|
||||||
Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息")
|
Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息")
|
||||||
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
||||||
If Not CurseForgeRaw.Any() Then Return
|
If Not CurseForgeRaw.Any() Then Return
|
||||||
@@ -1038,8 +1037,8 @@ Finished:
|
|||||||
Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息")
|
Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息")
|
||||||
'步骤 3:获取工程信息
|
'步骤 3:获取工程信息
|
||||||
If Not CurseForgeMapping.Any() Then Return
|
If Not CurseForgeMapping.Any() Then Return
|
||||||
Dim CurseForgeProject = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods", "POST",
|
Dim CurseForgeProject = DlModRequest("https://api.curseforge.com/v1/mods", HttpMethod.Post,
|
||||||
$"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")), JObject)("data")
|
$"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")("data")
|
||||||
Dim UpdateFileIds As New Dictionary(Of Integer, List(Of McMod)) 'FileId -> 本地 Mod 文件列表
|
Dim UpdateFileIds As New Dictionary(Of Integer, List(Of McMod)) 'FileId -> 本地 Mod 文件列表
|
||||||
Dim FileIdToProjectSlug As New Dictionary(Of Integer, String)
|
Dim FileIdToProjectSlug As New Dictionary(Of Integer, String)
|
||||||
For Each ProjectJson In CurseForgeProject
|
For Each ProjectJson In CurseForgeProject
|
||||||
@@ -1079,8 +1078,8 @@ Finished:
|
|||||||
Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息")
|
Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息")
|
||||||
'步骤 4:获取更新文件信息
|
'步骤 4:获取更新文件信息
|
||||||
If Not UpdateFileIds.Any() Then Return
|
If Not UpdateFileIds.Any() Then Return
|
||||||
Dim CurseForgeFiles = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST",
|
Dim CurseForgeFiles = DlModRequest("https://api.curseforge.com/v1/mods/files", HttpMethod.Post,
|
||||||
$"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")), JObject)("data")
|
$"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")("data")
|
||||||
Dim UpdateFiles As New Dictionary(Of McMod, CompFile)
|
Dim UpdateFiles As New Dictionary(Of McMod, CompFile)
|
||||||
For Each FileJson In CurseForgeFiles
|
For Each FileJson In CurseForgeFiles
|
||||||
Dim File As New CompFile(FileJson, CompType.Mod)
|
Dim File As New CompFile(FileJson, CompType.Mod)
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ Retry:
|
|||||||
If File.Exists(OverridesIni) Then
|
If File.Exists(OverridesIni) Then
|
||||||
WriteIni(OverridesIni, "VersionArgumentIndie", 1) '开启版本隔离
|
WriteIni(OverridesIni, "VersionArgumentIndie", 1) '开启版本隔离
|
||||||
WriteIni(OverridesIni, "VersionArgumentIndieV2", True)
|
WriteIni(OverridesIni, "VersionArgumentIndieV2", True)
|
||||||
|
WriteIni(OverridesIni, "IsStar", False)
|
||||||
CopyFile(OverridesIni, VersionIni) '覆写已有的 ini
|
CopyFile(OverridesIni, VersionIni) '覆写已有的 ini
|
||||||
Else
|
Else
|
||||||
WriteIni(VersionIni, "VersionArgumentIndie", 1) '开启版本隔离
|
WriteIni(VersionIni, "VersionArgumentIndie", 1) '开启版本隔离
|
||||||
@@ -244,7 +245,7 @@ Retry:
|
|||||||
'获取 Mod 下载信息
|
'获取 Mod 下载信息
|
||||||
ModDownloadLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
|
ModDownloadLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
|
||||||
Sub(Task As LoaderTask(Of Integer, JArray))
|
Sub(Task As LoaderTask(Of Integer, JArray))
|
||||||
Task.Output = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json"))("data")
|
Task.Output = DlModRequest("https://api.curseforge.com/v1/mods/files", HttpMethod.Post, "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json")("data")
|
||||||
'如果文件已被删除,则 API 会跳过那一项
|
'如果文件已被删除,则 API 会跳过那一项
|
||||||
If ModList.Count > Task.Output.Count Then Throw New Exception("整合包中的部分 Mod 版本已被 Mod 作者删除,所以没法继续安装了,请向整合包作者反馈该问题")
|
If ModList.Count > Task.Output.Count Then Throw New Exception("整合包中的部分 Mod 版本已被 Mod 作者删除,所以没法继续安装了,请向整合包作者反馈该问题")
|
||||||
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
||||||
|
|||||||
@@ -349,14 +349,14 @@
|
|||||||
State = MinecraftState.Crashed
|
State = MinecraftState.Crashed
|
||||||
'崩溃分析
|
'崩溃分析
|
||||||
WatcherLog("Minecraft 已崩溃,将在 2 秒后开始崩溃分析")
|
WatcherLog("Minecraft 已崩溃,将在 2 秒后开始崩溃分析")
|
||||||
Hint("检测到 Minecraft 出现错误,错误分析已开始……")
|
Hint("检测到 Minecraft 出现错误,错误分析已开始……", HintType.Critical)
|
||||||
FeedbackInfo()
|
FeedbackInfo()
|
||||||
RunInNewThread(
|
RunInNewThread(
|
||||||
Sub()
|
Sub()
|
||||||
Try
|
Try
|
||||||
Thread.Sleep(2000)
|
Thread.Sleep(2000)
|
||||||
WatcherLog("崩溃分析开始")
|
WatcherLog("崩溃分析开始")
|
||||||
Dim Analyzer As New CrashAnalyzer(PID)
|
Dim Analyzer As New CrashAnalyzer(Version)
|
||||||
Analyzer.Collect(Version.PathIndie, LatestLog.ToList)
|
Analyzer.Collect(Version.PathIndie, LatestLog.ToList)
|
||||||
Analyzer.Prepare()
|
Analyzer.Prepare()
|
||||||
Analyzer.Analyze(Version)
|
Analyzer.Analyze(Version)
|
||||||
|
|||||||
@@ -115,6 +115,10 @@
|
|||||||
PageOtherTest.StartCustomDownload(Data(0), "未知")
|
PageOtherTest.StartCustomDownload(Data(0), "未知")
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
|
Case "修改设置"
|
||||||
|
Setup.Set(Data(0), Data(1))
|
||||||
|
Hint($"已写入设置:{Data(0)} → {Data(1)}", HintType.Finish)
|
||||||
|
|
||||||
Case Else
|
Case Else
|
||||||
MyMsgBox("未知的事件类型:" & Type & vbCrLf & "请检查事件类型填写是否正确,或者 PCL 是否为最新版本。", "事件执行失败")
|
MyMsgBox("未知的事件类型:" & Type & vbCrLf & "请检查事件类型填写是否正确,或者 PCL 是否为最新版本。", "事件执行失败")
|
||||||
End Select
|
End Select
|
||||||
|
|||||||
@@ -247,7 +247,7 @@
|
|||||||
Log("[Music] 已恢复播放")
|
Log("[Music] 已恢复播放")
|
||||||
Try
|
Try
|
||||||
MusicNAudio?.Play()
|
MusicNAudio?.Play()
|
||||||
Catch 'https://github.com/Hex-Dragon/PCL2/pull/5415#issuecomment-2751135223
|
Catch 'https://github.com/Meloong-Git/PCL/pull/5415#issuecomment-2751135223
|
||||||
MusicNAudio?.Stop()
|
MusicNAudio?.Stop()
|
||||||
MusicNAudio?.Play()
|
MusicNAudio?.Play()
|
||||||
End Try
|
End Try
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ Friend Module ModSecret
|
|||||||
'在开源版的注册表与常规版的注册表隔离,以防数据冲突
|
'在开源版的注册表与常规版的注册表隔离,以防数据冲突
|
||||||
Public Const RegFolder As String = "PCLDebug"
|
Public Const RegFolder As String = "PCLDebug"
|
||||||
'用于微软登录的 ClientId
|
'用于微软登录的 ClientId
|
||||||
Public Const OAuthClientId As String = ""
|
Public OAuthClientId As String = If(Environment.GetEnvironmentVariable("PCL_MS_CLIENT_ID"), "")
|
||||||
'CurseForge API Key
|
'CurseForge API Key
|
||||||
Public Const CurseForgeAPIKey As String = ""
|
Public CurseForgeAPIKey As String = If(Environment.GetEnvironmentVariable("PCL_CURSEFORGE_API_KEY"), "")
|
||||||
|
'用于匿名数据收集的腾讯云日志服务上报 URL,形如 https://{region}.cls.tencentcs.com/track?topic_id={topic_id}
|
||||||
|
Public Const ClsBaseUrl As String = ""
|
||||||
|
|
||||||
Friend Sub SecretOnApplicationStart()
|
Friend Sub SecretOnApplicationStart()
|
||||||
'提升 UI 线程优先级
|
'提升 UI 线程优先级
|
||||||
@@ -71,37 +73,23 @@ Friend Module ModSecret
|
|||||||
|
|
||||||
#Region "网络鉴权"
|
#Region "网络鉴权"
|
||||||
|
|
||||||
Friend Function SecretCdnSign(UrlWithMark As String)
|
Friend Function SecretCdnSign(UrlWithMark As String) As String
|
||||||
If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
|
If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
|
||||||
Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
|
Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
|
||||||
End Function
|
End Function
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 设置 Headers 的 UA、Referer。
|
''' 设置 Headers 的 UA、Referer。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Friend Sub SecretHeadersSign(Url As String, ByRef Client As WebClient, Optional UseBrowserUserAgent As Boolean = False)
|
Friend Sub SecretHeadersSign(Url As String, ByRef Req As HttpRequestMessage, Optional UseBrowserUserAgent As Boolean = False)
|
||||||
If Url.Contains("baidupcs.com") OrElse Url.Contains("baidu.com") Then
|
If Url.Contains("baidupcs.com") OrElse Url.Contains("baidu.com") Then
|
||||||
Client.Headers("User-Agent") = "LogStatistic" '#4951
|
Req.Headers.Add("User-Agent", "LogStatistic") '#4951
|
||||||
ElseIf UseBrowserUserAgent Then
|
ElseIf UseBrowserUserAgent Then
|
||||||
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
Req.Headers.Add("User-Agent", $"PCL2/{VersionStandardCode} Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36")
|
||||||
Else
|
Else
|
||||||
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode
|
Req.Headers.Add("User-Agent", $"PCL2/{VersionStandardCode}")
|
||||||
End If
|
End If
|
||||||
Client.Headers("Referer") = "http://" & VersionCode & ".open.pcl2.server/"
|
Req.Headers.Add("Referer", $"http://{VersionCode}.open.pcl2.server/")
|
||||||
If Url.Contains("api.curseforge.com") Then Client.Headers("x-api-key") = CurseForgeAPIKey
|
If Url.Contains("api.curseforge.com") Then Req.Headers.Add("x-api-key", CurseForgeAPIKey)
|
||||||
End Sub
|
|
||||||
''' <summary>
|
|
||||||
''' 设置 Headers 的 UA、Referer。
|
|
||||||
''' </summary>
|
|
||||||
Friend Sub SecretHeadersSign(Url As String, ByRef Request As HttpWebRequest, Optional UseBrowserUserAgent As Boolean = False)
|
|
||||||
If Url.Contains("baidupcs.com") OrElse Url.Contains("baidu.com") Then
|
|
||||||
Request.UserAgent = "LogStatistic" '#4951
|
|
||||||
ElseIf UseBrowserUserAgent Then
|
|
||||||
Request.UserAgent = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
|
||||||
Else
|
|
||||||
Request.UserAgent = "PCL2/" & VersionStandardCode
|
|
||||||
End If
|
|
||||||
Request.Referer = "http://" & VersionCode & ".open.pcl2.server/"
|
|
||||||
If Url.Contains("api.curseforge.com") Then Request.Headers("x-api-key") = CurseForgeAPIKey
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
@@ -225,11 +213,17 @@ Friend Module ModSecret
|
|||||||
If Not FrmMain.IsLoaded Then Return
|
If Not FrmMain.IsLoaded Then Return
|
||||||
'顶部条背景
|
'顶部条背景
|
||||||
Dim Brush = New LinearGradientBrush With {.EndPoint = New Point(1, 0), .StartPoint = New Point(0, 0)}
|
Dim Brush = New LinearGradientBrush With {.EndPoint = New Point(1, 0), .StartPoint = New Point(0, 0)}
|
||||||
Brush.GradientStops.Add(New GradientStop With {.Offset = 0, .Color = New MyColor().FromHSL2(ColorHue - 21, ColorSat, 53 + ColorLightAdjust)})
|
If TypeOf ColorHueTopbarDelta Is Integer Then
|
||||||
Brush.GradientStops.Add(New GradientStop With {.Offset = 0.33, .Color = New MyColor().FromHSL2(ColorHue - 7, ColorSat, 47 + ColorLightAdjust)})
|
Brush.GradientStops.Add(New GradientStop With {.Offset = 0, .Color = New MyColor().FromHSL2(ColorHue - ColorHueTopbarDelta, ColorSat, 48 + ColorLightAdjust)})
|
||||||
Brush.GradientStops.Add(New GradientStop With {.Offset = 0.67, .Color = New MyColor().FromHSL2(ColorHue + 7, ColorSat, 47 + ColorLightAdjust)})
|
Brush.GradientStops.Add(New GradientStop With {.Offset = 0.5, .Color = New MyColor().FromHSL2(ColorHue, ColorSat, 54 + ColorLightAdjust)})
|
||||||
Brush.GradientStops.Add(New GradientStop With {.Offset = 1, .Color = New MyColor().FromHSL2(ColorHue + 21, ColorSat, 53 + ColorLightAdjust)})
|
Brush.GradientStops.Add(New GradientStop With {.Offset = 1, .Color = New MyColor().FromHSL2(ColorHue + ColorHueTopbarDelta, ColorSat, 48 + ColorLightAdjust)})
|
||||||
|
Else
|
||||||
|
Brush.GradientStops.Add(New GradientStop With {.Offset = 0, .Color = New MyColor().FromHSL2(ColorHue + ColorHueTopbarDelta(0), ColorSat, 48 + ColorLightAdjust)})
|
||||||
|
Brush.GradientStops.Add(New GradientStop With {.Offset = 0.5, .Color = New MyColor().FromHSL2(ColorHue + ColorHueTopbarDelta(1), ColorSat, 54 + ColorLightAdjust)})
|
||||||
|
Brush.GradientStops.Add(New GradientStop With {.Offset = 1, .Color = New MyColor().FromHSL2(ColorHue + ColorHueTopbarDelta(2), ColorSat, 48 + ColorLightAdjust)})
|
||||||
|
End If
|
||||||
FrmMain.PanTitle.Background = Brush
|
FrmMain.PanTitle.Background = Brush
|
||||||
|
FrmMain.PanTitle.Background.Freeze()
|
||||||
'主页面背景
|
'主页面背景
|
||||||
If Setup.Get("UiBackgroundColorful") Then
|
If Setup.Get("UiBackgroundColorful") Then
|
||||||
Brush = New LinearGradientBrush With {.EndPoint = New Point(0.1, 1), .StartPoint = New Point(0.9, 0)}
|
Brush = New LinearGradientBrush With {.EndPoint = New Point(0.1, 1), .StartPoint = New Point(0.9, 0)}
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
Imports System.Net
|
|
||||||
|
|
||||||
Public Class CookieWebClient
|
|
||||||
Inherits WebClient
|
|
||||||
|
|
||||||
Public Sub New(container As CookieContainer, Headers As Dictionary(Of String, String))
|
|
||||||
Me.New(container)
|
|
||||||
For Each keyVal In Headers
|
|
||||||
Me.Headers(keyVal.Key) = keyVal.Value
|
|
||||||
Next
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Public Sub New()
|
|
||||||
Me.New(New CookieContainer())
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Public Sub New(container As CookieContainer)
|
|
||||||
Me.container = container
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Private Shadows ReadOnly container As New CookieContainer()
|
|
||||||
|
|
||||||
''' <summary>
|
|
||||||
''' 以毫秒为单位的超时。
|
|
||||||
''' </summary>
|
|
||||||
Public Timeout As Integer = 600000
|
|
||||||
|
|
||||||
Protected Overrides Function GetWebRequest(address As Uri) As WebRequest
|
|
||||||
Dim r As WebRequest = MyBase.GetWebRequest(address)
|
|
||||||
Dim request = TryCast(r, HttpWebRequest)
|
|
||||||
|
|
||||||
If request IsNot Nothing Then
|
|
||||||
request.CookieContainer = container
|
|
||||||
request.Timeout = Timeout
|
|
||||||
End If
|
|
||||||
|
|
||||||
Return r
|
|
||||||
End Function
|
|
||||||
|
|
||||||
Protected Overrides Function GetWebResponse(request As WebRequest, result As IAsyncResult) As WebResponse
|
|
||||||
Dim response As WebResponse = MyBase.GetWebResponse(request, result)
|
|
||||||
ReadCookies(response)
|
|
||||||
Return response
|
|
||||||
End Function
|
|
||||||
|
|
||||||
Protected Overrides Function GetWebResponse(request As WebRequest) As WebResponse
|
|
||||||
Dim response As WebResponse = MyBase.GetWebResponse(request)
|
|
||||||
ReadCookies(response)
|
|
||||||
Return response
|
|
||||||
End Function
|
|
||||||
|
|
||||||
Private Sub ReadCookies(r As WebResponse)
|
|
||||||
Dim response = TryCast(r, HttpWebResponse)
|
|
||||||
If response IsNot Nothing Then
|
|
||||||
Dim cookies As CookieCollection = response.Cookies
|
|
||||||
container.Add(cookies)
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
End Class
|
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
'来源:https://blog.csdn.net/simpleman2000/article/details/140952294
|
||||||
|
|
||||||
|
Imports System.ComponentModel
|
||||||
|
Imports System.Runtime.InteropServices
|
||||||
|
Imports System.Windows.Interop
|
||||||
|
|
||||||
|
Public Class DragHelper
|
||||||
|
|
||||||
|
Public Event DragDrop As EventHandler
|
||||||
|
|
||||||
|
Public Property DropFilePaths As String()
|
||||||
|
Get
|
||||||
|
Return _DropFilePathsBackingField
|
||||||
|
End Get
|
||||||
|
Private Set(value As String())
|
||||||
|
_DropFilePathsBackingField = value
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Private _DropFilePathsBackingField As String()
|
||||||
|
|
||||||
|
Public Property DropPoint As POINT
|
||||||
|
Get
|
||||||
|
Return _DropPointBackingField
|
||||||
|
End Get
|
||||||
|
Private Set(value As POINT)
|
||||||
|
_DropPointBackingField = value
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Private _DropPointBackingField As POINT
|
||||||
|
|
||||||
|
Public Property HwndIntPtrSource As HwndSource
|
||||||
|
|
||||||
|
Public Sub AddHook()
|
||||||
|
RemoveDragHook()
|
||||||
|
HwndIntPtrSource.AddHook(AddressOf WndProc)
|
||||||
|
Dim handle As IntPtr = HwndIntPtrSource.Handle
|
||||||
|
If IsUserAnAdmin() Then RevokeDragDrop(handle)
|
||||||
|
DragAcceptFiles(handle, True)
|
||||||
|
ChangeMessageFilter(handle)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub RemoveDragHook()
|
||||||
|
HwndIntPtrSource.RemoveHook(AddressOf WndProc)
|
||||||
|
DragAcceptFiles(HwndIntPtrSource.Handle, False)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Function WndProc(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
|
||||||
|
Dim filePaths As String() = Nothing
|
||||||
|
Dim point As New POINT()
|
||||||
|
|
||||||
|
If TryGetDropInfo(msg, wParam, filePaths, point) Then
|
||||||
|
DropPoint = point
|
||||||
|
DropFilePaths = filePaths
|
||||||
|
RaiseEvent DragDrop(Me, EventArgs.Empty)
|
||||||
|
handled = True
|
||||||
|
End If
|
||||||
|
Return IntPtr.Zero
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<DllImport("user32.dll", SetLastError:=True)>
|
||||||
|
Private Shared Function ChangeWindowMessageFilterEx(hWnd As IntPtr, msg As UInteger, action As UInteger, ByRef pChangeFilterStruct As CHANGEFILTERSTRUCT) As Boolean
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<DllImport("user32.dll", SetLastError:=True)>
|
||||||
|
Private Shared Function ChangeWindowMessageFilter(msg As UInteger, flags As UInteger) As Boolean
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<DllImport("shell32.dll")>
|
||||||
|
Private Shared Sub DragAcceptFiles(hWnd As IntPtr, fAccept As Boolean)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
<DllImport("shell32.dll", CharSet:=CharSet.Unicode)>
|
||||||
|
Private Shared Function DragQueryFile(hWnd As IntPtr, iFile As UInteger, lpszFile As StringBuilder, cch As Integer) As UInteger
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<DllImport("shell32.dll")>
|
||||||
|
Private Shared Function DragQueryPoint(hDrop As IntPtr, ByRef lppt As POINT) As Boolean
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<DllImport("shell32.dll")>
|
||||||
|
Private Shared Sub DragFinish(hDrop As IntPtr)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
<DllImport("ole32.dll")>
|
||||||
|
Private Shared Function RevokeDragDrop(hWnd As IntPtr) As Integer
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<DllImport("shell32.dll")>
|
||||||
|
Private Shared Function IsUserAnAdmin() As Boolean
|
||||||
|
End Function
|
||||||
|
|
||||||
|
<StructLayout(LayoutKind.Sequential)>
|
||||||
|
Public Structure POINT
|
||||||
|
Public X As Integer
|
||||||
|
Public Y As Integer
|
||||||
|
End Structure
|
||||||
|
|
||||||
|
<StructLayout(LayoutKind.Sequential)>
|
||||||
|
Private Structure CHANGEFILTERSTRUCT
|
||||||
|
Public cbSize As UInteger
|
||||||
|
Public ExtStatus As UInteger
|
||||||
|
End Structure
|
||||||
|
|
||||||
|
Private Const WM_COPYGLOBALDATA As UInteger = &H49
|
||||||
|
Private Const WM_COPYDATA As UInteger = &H4A
|
||||||
|
Private Const WM_DROPFILES As UInteger = &H233
|
||||||
|
Private Const MSGFLT_ALLOW As UInteger = 1
|
||||||
|
Private Const MSGFLT_ADD As UInteger = 1
|
||||||
|
Private Const MAX_PATH As Integer = 260
|
||||||
|
|
||||||
|
Private Shared Sub ChangeMessageFilter(handle As IntPtr)
|
||||||
|
Dim ver As Version = Environment.OSVersion.Version
|
||||||
|
Dim isVistaOrHigher As Boolean = ver >= New Version(6, 0)
|
||||||
|
Dim isNt61OrHiger As Boolean = ver >= New Version(6, 1)
|
||||||
|
|
||||||
|
If isVistaOrHigher Then
|
||||||
|
Dim status As New CHANGEFILTERSTRUCT With {.cbSize = 8}
|
||||||
|
For Each msg As UInteger In New UInteger() {WM_DROPFILES, WM_COPYGLOBALDATA, WM_COPYDATA}
|
||||||
|
Dim [error] As Boolean = False
|
||||||
|
If isNt61OrHiger Then
|
||||||
|
[error] = Not ChangeWindowMessageFilterEx(handle, msg, MSGFLT_ALLOW, status)
|
||||||
|
Else
|
||||||
|
[error] = Not ChangeWindowMessageFilter(msg, MSGFLT_ADD)
|
||||||
|
End If
|
||||||
|
|
||||||
|
If [error] Then Throw New Win32Exception(Marshal.GetLastWin32Error())
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Function TryGetDropInfo(msg As Integer, wParam As IntPtr, ByRef dropFilePaths As String(), ByRef dropPoint As POINT) As Boolean
|
||||||
|
dropFilePaths = Nothing
|
||||||
|
dropPoint = New POINT()
|
||||||
|
|
||||||
|
If msg <> WM_DROPFILES Then Return False
|
||||||
|
|
||||||
|
Dim fileCount As UInteger = DragQueryFile(wParam, UInteger.MaxValue, Nothing, 0)
|
||||||
|
ReDim dropFilePaths(CInt(fileCount) - 1)
|
||||||
|
|
||||||
|
For i As UInteger = 0 To CInt(fileCount) - 1
|
||||||
|
Dim sb As New StringBuilder(MAX_PATH)
|
||||||
|
Dim result As UInteger = DragQueryFile(wParam, i, sb, sb.Capacity)
|
||||||
|
If result > 0 Then dropFilePaths(i) = sb.ToString()
|
||||||
|
Next
|
||||||
|
|
||||||
|
DragQueryPoint(wParam, dropPoint)
|
||||||
|
DragFinish(wParam)
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
|
||||||
|
End Class
|
||||||
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||||
' 方法是按如下所示使用“*”
|
' 方法是按如下所示使用“*”
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2.10.3.0")>
|
<Assembly: AssemblyVersion("2.10.6.0")>
|
||||||
<Assembly: AssemblyFileVersion("2.10.3.0")>
|
<Assembly: AssemblyFileVersion("2.10.6.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("")>
|
<Assembly: NeutralResourcesLanguage("")>
|
||||||
|
|||||||
+55
-15
@@ -63,9 +63,9 @@ Namespace My.Resources
|
|||||||
'''<summary>
|
'''<summary>
|
||||||
''' 查找 System.Byte[] 类型的本地化资源。
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Friend ReadOnly Property Custom() As Byte()
|
Friend ReadOnly Property CacheCow_Client() As Byte()
|
||||||
Get
|
Get
|
||||||
Dim obj As Object = ResourceManager.GetObject("Custom", resourceCulture)
|
Dim obj As Object = ResourceManager.GetObject("CacheCow.Client", resourceCulture)
|
||||||
Return CType(obj,Byte())
|
Return CType(obj,Byte())
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
@@ -73,9 +73,29 @@ Namespace My.Resources
|
|||||||
'''<summary>
|
'''<summary>
|
||||||
''' 查找 System.Byte[] 类型的本地化资源。
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Friend ReadOnly Property Dialogs() As Byte()
|
Friend ReadOnly Property CacheCow_Client_FileStore() As Byte()
|
||||||
Get
|
Get
|
||||||
Dim obj As Object = ResourceManager.GetObject("Dialogs", resourceCulture)
|
Dim obj As Object = ResourceManager.GetObject("CacheCow.Client.FileStore", resourceCulture)
|
||||||
|
Return CType(obj,Byte())
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
|
'''</summary>
|
||||||
|
Friend ReadOnly Property CacheCow_Common() As Byte()
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("CacheCow.Common", resourceCulture)
|
||||||
|
Return CType(obj,Byte())
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
|
'''</summary>
|
||||||
|
Friend ReadOnly Property Custom() As Byte()
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("Custom", resourceCulture)
|
||||||
Return CType(obj,Byte())
|
Return CType(obj,Byte())
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
@@ -105,7 +125,7 @@ Namespace My.Resources
|
|||||||
'''</summary>
|
'''</summary>
|
||||||
Friend ReadOnly Property Imazen_WebP() As Byte()
|
Friend ReadOnly Property Imazen_WebP() As Byte()
|
||||||
Get
|
Get
|
||||||
Dim obj As Object = ResourceManager.GetObject("Imazen_WebP", resourceCulture)
|
Dim obj As Object = ResourceManager.GetObject("Imazen.WebP", resourceCulture)
|
||||||
Return CType(obj,Byte())
|
Return CType(obj,Byte())
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
@@ -120,16 +140,6 @@ Namespace My.Resources
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' 查找 System.Byte[] 类型的本地化资源。
|
|
||||||
'''</summary>
|
|
||||||
Friend ReadOnly Property Json() As Byte()
|
|
||||||
Get
|
|
||||||
Dim obj As Object = ResourceManager.GetObject("Json", resourceCulture)
|
|
||||||
Return CType(obj,Byte())
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' 查找 System.Byte[] 类型的本地化资源。
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
'''</summary>
|
'''</summary>
|
||||||
@@ -160,6 +170,36 @@ Namespace My.Resources
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
|
'''</summary>
|
||||||
|
Friend ReadOnly Property Newtonsoft_Json() As Byte()
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("Newtonsoft.Json", resourceCulture)
|
||||||
|
Return CType(obj,Byte())
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
|
'''</summary>
|
||||||
|
Friend ReadOnly Property Ookii_Dialogs_Wpf() As Byte()
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("Ookii.Dialogs.Wpf", resourceCulture)
|
||||||
|
Return CType(obj,Byte())
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
|
'''</summary>
|
||||||
|
Friend ReadOnly Property System_Net_Http_Formatting() As Byte()
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("System.Net.Http.Formatting", resourceCulture)
|
||||||
|
Return CType(obj,Byte())
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' 查找 System.Byte[] 类型的本地化资源。
|
''' 查找 System.Byte[] 类型的本地化资源。
|
||||||
'''</summary>
|
'''</summary>
|
||||||
|
|||||||
@@ -118,27 +118,30 @@
|
|||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
|
<data name="CacheCow.Client" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\CacheCow.Client.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name="CacheCow.Client.FileStore" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\CacheCow.Client.FileStore.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name="CacheCow.Common" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\CacheCow.Common.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
<data name="Custom" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="Custom" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\resources\custom.xaml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\resources\custom.xaml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Dialogs" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\resources\ookii.dialogs.wpf.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name="ForgeInstaller" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="ForgeInstaller" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\forge-installer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\forge-installer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Help" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="Help" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\Help.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\Help.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Imazen_WebP" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="Imazen.WebP" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\Imazen.WebP.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\Imazen.WebP.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="JavaWrapper" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="JavaWrapper" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\java-wrapper.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\java-wrapper.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Json" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\Newtonsoft.Json.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</data>
|
|
||||||
<data name="libwebp64" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="libwebp64" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\libwebp64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\libwebp64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -148,6 +151,15 @@
|
|||||||
<data name="NAudio" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="NAudio" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\NAudio.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\NAudio.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Newtonsoft.Json" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Newtonsoft.Json.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name="Ookii.Dialogs.Wpf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\resources\ookii.dialogs.wpf.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name="System.Net.Http.Formatting" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\System.Net.Http.Formatting.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
<data name="Transformer" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="Transformer" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\transformer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\transformer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -97,7 +97,7 @@
|
|||||||
Dim Titles As New List(Of String)
|
Dim Titles As New List(Of String)
|
||||||
If FrmMain.PageCurrent.Page = FormMain.PageType.CompDetail Then
|
If FrmMain.PageCurrent.Page = FormMain.PageType.CompDetail Then
|
||||||
For Each Card As MyCard In FrmDownloadCompDetail.PanResults.Children
|
For Each Card As MyCard In FrmDownloadCompDetail.PanResults.Children
|
||||||
If Card.Title <> "" AndAlso Not Card.IsSwaped Then Titles.Add(Card.Title)
|
If Card.Title <> "" AndAlso Not Card.IsSwapped Then Titles.Add(Card.Title)
|
||||||
Next
|
Next
|
||||||
Log("[Comp] 记录当前已展开的卡片:" & String.Join("、", Titles))
|
Log("[Comp] 记录当前已展开的卡片:" & String.Join("、", Titles))
|
||||||
FrmMain.PageCurrent.Additional(1) = Titles
|
FrmMain.PageCurrent.Additional(1) = Titles
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
|
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
|
||||||
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320">
|
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320">
|
||||||
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
||||||
<local:MyComboBoxItem Content="1.21.5" />
|
<local:MyComboBoxItem Content="1.21.8" />
|
||||||
<local:MyComboBoxItem Content="1.21.1" />
|
<local:MyComboBoxItem Content="1.21.1" />
|
||||||
<local:MyComboBoxItem Content="1.20.6" />
|
<local:MyComboBoxItem Content="1.20.6" />
|
||||||
<local:MyComboBoxItem Content="1.20.1" />
|
<local:MyComboBoxItem Content="1.20.1" />
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ Public Class PageComp
|
|||||||
''' 在切换到页面时,应自动将筛选项设置为与该目标 MC 版本和加载器相同。
|
''' 在切换到页面时,应自动将筛选项设置为与该目标 MC 版本和加载器相同。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Shared TargetVersion As McVersion = Nothing
|
Public Shared TargetVersion As McVersion = Nothing
|
||||||
|
''' <summary>
|
||||||
|
''' 在切换到该页面时自动设置的搜索框内的内容。
|
||||||
|
''' </summary>
|
||||||
|
Public Shared TargetName As String = Nothing
|
||||||
|
|
||||||
'在点击 MyCompItem 时会获取 Loader 的输入,以使资源详情页面可以应用相同的筛选项
|
'在点击 MyCompItem 时会获取 Loader 的输入,以使资源详情页面可以应用相同的筛选项
|
||||||
Public Loader As New LoaderTask(Of CompProjectRequest, Integer)("社区资源获取:XXX", AddressOf CompProjectsGet, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
|
Public Loader As New LoaderTask(Of CompProjectRequest, Integer)("社区资源获取:XXX", AddressOf CompProjectsGet, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
|
||||||
@@ -94,6 +98,10 @@ Public Class PageComp
|
|||||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
|
ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
|
||||||
End If
|
End If
|
||||||
TargetVersion = Nothing
|
TargetVersion = Nothing
|
||||||
|
If TargetName IsNot Nothing Then
|
||||||
|
TextSearchName.Text = TargetName
|
||||||
|
TargetName = Nothing
|
||||||
|
End If
|
||||||
'如果已经完成请求,则重新开始
|
'如果已经完成请求,则重新开始
|
||||||
If IsLoaderInited Then StartNewSearch()
|
If IsLoaderInited Then StartNewSearch()
|
||||||
ScrollToHome()
|
ScrollToHome()
|
||||||
|
|||||||
@@ -73,11 +73,14 @@
|
|||||||
'筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
|
'筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
|
||||||
Private Function GetResults() As List(Of CompFile)
|
Private Function GetResults() As List(Of CompFile)
|
||||||
Dim Results As List(Of CompFile) = CompFileLoader.Output
|
Dim Results As List(Of CompFile) = CompFileLoader.Output
|
||||||
If PageType = CompType.Any Then
|
Select Case PageType
|
||||||
|
Case CompType.Any
|
||||||
Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
|
Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
|
||||||
Else
|
Case CompType.Shader, CompType.ResourcePack
|
||||||
|
'不筛选光影和资源包,否则原版光影会因为是资源包格式而被过滤(#6473)
|
||||||
|
Case Else
|
||||||
Results = Results.Where(Function(r) r.Type = PageType).ToList
|
Results = Results.Where(Function(r) r.Type = PageType).ToList
|
||||||
End If
|
End Select
|
||||||
Return Results
|
Return Results
|
||||||
End Function
|
End Function
|
||||||
Private Sub Load_OnFinish()
|
Private Sub Load_OnFinish()
|
||||||
@@ -202,7 +205,7 @@
|
|||||||
CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
|
CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
|
||||||
MyCard.StackInstall(NewStack, If(PageType = CompType.ModPack, 9, 8), Pair.Key) '9 是安装,8 是另存为
|
MyCard.StackInstall(NewStack, If(PageType = CompType.ModPack, 9, 8), Pair.Key) '9 是安装,8 是另存为
|
||||||
Else
|
Else
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
End If
|
End If
|
||||||
'增加提示
|
'增加提示
|
||||||
If Pair.Key = "其他版本" Then
|
If Pair.Key = "其他版本" Then
|
||||||
@@ -211,7 +214,7 @@
|
|||||||
Next
|
Next
|
||||||
'如果只有一张卡片,展开第一张卡片
|
'如果只有一张卡片,展开第一张卡片
|
||||||
If PanResults.Children.Count = 1 Then
|
If PanResults.Children.Count = 1 Then
|
||||||
CType(PanResults.Children(0), MyCard).IsSwaped = False
|
CType(PanResults.Children(0), MyCard).IsSwapped = False
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
|
Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
|
||||||
@@ -305,7 +308,7 @@
|
|||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
'资源下载;整合包另存为
|
'资源下载;整合包另存为
|
||||||
Public Shared CachedFolder As String = Nothing '仅在本次缓存的下载文件夹
|
Public Shared CachedFolder As New Dictionary(Of CompType, String) '仅在本次缓存的下载文件夹
|
||||||
Public Sub Save_Click(sender As Object, e As EventArgs)
|
Public Sub Save_Click(sender As Object, e As EventArgs)
|
||||||
Dim File As CompFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
|
Dim File As CompFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
|
||||||
RunInNewThread(
|
RunInNewThread(
|
||||||
@@ -356,8 +359,8 @@
|
|||||||
Return False
|
Return False
|
||||||
End Function
|
End Function
|
||||||
'获取常规资源默认下载位置
|
'获取常规资源默认下载位置
|
||||||
If CachedFolder IsNot Nothing Then
|
If CachedFolder.ContainsKey(Project.Type) Then
|
||||||
DefaultFolder = CachedFolder
|
DefaultFolder = CachedFolder(Project.Type)
|
||||||
Log($"[Comp] 使用上次下载时的文件夹作为默认下载位置:{DefaultFolder}")
|
Log($"[Comp] 使用上次下载时的文件夹作为默认下载位置:{DefaultFolder}")
|
||||||
ElseIf McVersionCurrent IsNot Nothing AndAlso IsVersionSuitable(McVersionCurrent) Then
|
ElseIf McVersionCurrent IsNot Nothing AndAlso IsVersionSuitable(McVersionCurrent) Then
|
||||||
DefaultFolder = $"{McVersionCurrent.PathIndie}{SubFolder}"
|
DefaultFolder = $"{McVersionCurrent.PathIndie}{SubFolder}"
|
||||||
@@ -422,7 +425,7 @@
|
|||||||
If Not Target.Contains("\") Then Return
|
If Not Target.Contains("\") Then Return
|
||||||
'构造步骤加载器
|
'构造步骤加载器
|
||||||
Dim LoaderName As String = Desc & "下载:" & GetFileNameWithoutExtentionFromPath(Target) & " "
|
Dim LoaderName As String = Desc & "下载:" & GetFileNameWithoutExtentionFromPath(Target) & " "
|
||||||
If Target <> DefaultFolder AndAlso File.Type = CompType.Mod Then CachedFolder = GetPathFromFullPath(Target)
|
If Target <> DefaultFolder Then CachedFolder(Project.Type) = GetPathFromFullPath(Target)
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.ToNetFile(Target)}) With {.ProgressWeight = 6, .Block = True})
|
Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.ToNetFile(Target)}) With {.ProgressWeight = 6, .Block = True})
|
||||||
'启动
|
'启动
|
||||||
|
|||||||
@@ -570,7 +570,8 @@ pause"
|
|||||||
'官方源
|
'官方源
|
||||||
Dim PageData As String
|
Dim PageData As String
|
||||||
Try
|
Try
|
||||||
PageData = NetGetCodeByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile, New UTF8Encoding(False), 15000, "text/html", True)
|
PageData = NetRequestByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile,
|
||||||
|
Encoding:=New UTF8Encoding(False), Timeout:=15000, Accept:="text/html", UseBrowserUserAgent:=True)
|
||||||
Task.Progress = 0.8
|
Task.Progress = 0.8
|
||||||
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
||||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
||||||
@@ -733,7 +734,8 @@ Retry:
|
|||||||
'官方源
|
'官方源
|
||||||
Dim PageData As String
|
Dim PageData As String
|
||||||
Try
|
Try
|
||||||
PageData = NetGetCodeByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile, New UTF8Encoding(False), 15000, "text/html", True)
|
PageData = NetRequestByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile,
|
||||||
|
Encoding:=New UTF8Encoding(False), Timeout:=15000, Accept:="text/html", UseBrowserUserAgent:=True)
|
||||||
Task.Progress = 0.8
|
Task.Progress = 0.8
|
||||||
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
||||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
||||||
@@ -1340,7 +1342,7 @@ Retry:
|
|||||||
If Json("data") IsNot Nothing AndAlso Json("data")("MOJMAPS") IsNot Nothing Then
|
If Json("data") IsNot Nothing AndAlso Json("data")("MOJMAPS") IsNot Nothing Then
|
||||||
'下载原版 Json 文件
|
'下载原版 Json 文件
|
||||||
Task.Progress = 0.4
|
Task.Progress = 0.4
|
||||||
Dim RawJson As JObject = GetJson(NetGetCodeByLoader(DlSourceLauncherOrMetaGet(DlClientListGet(Inherit)), IsJson:=True))
|
Dim RawJson As JObject = GetJson(NetRequestByLoader(DlSourceLauncherOrMetaGet(DlClientListGet(Inherit)), IsJson:=True))
|
||||||
'[net.minecraft:client:1.17.1-20210706.113038:mappings@txt] 或 @tsrg]
|
'[net.minecraft:client:1.17.1-20210706.113038:mappings@txt] 或 @tsrg]
|
||||||
Dim OriginalName As String = Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).BeforeFirst("@")
|
Dim OriginalName As String = Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).BeforeFirst("@")
|
||||||
Dim Address = McLibGet(OriginalName).Replace(".jar", "-mappings." & Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Split("@")(1))
|
Dim Address = McLibGet(OriginalName).Replace(".jar", "-mappings." & Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Split("@")(1))
|
||||||
@@ -1641,10 +1643,11 @@ Retry:
|
|||||||
Public Sub McDownloadForgeRecommendedRefresh()
|
Public Sub McDownloadForgeRecommendedRefresh()
|
||||||
If IsForgeRecommendedRefreshed Then Return
|
If IsForgeRecommendedRefreshed Then Return
|
||||||
IsForgeRecommendedRefreshed = True
|
IsForgeRecommendedRefreshed = True
|
||||||
RunInNewThread(Sub()
|
RunInNewThread(
|
||||||
|
Sub()
|
||||||
Try
|
Try
|
||||||
Log("[Download] 刷新 Forge 推荐版本缓存开始")
|
Log("[Download] 刷新 Forge 推荐版本缓存开始")
|
||||||
Dim Result As String = NetGetCodeByLoader("https://bmclapi2.bangbang93.com/forge/promos")
|
Dim Result As String = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/promos")
|
||||||
If Result.Length < 1000 Then Throw New Exception("获取的结果过短(" & Result & ")")
|
If Result.Length < 1000 Then Throw New Exception("获取的结果过短(" & Result & ")")
|
||||||
Dim ResultJson As JContainer = GetJson(Result)
|
Dim ResultJson As JContainer = GetJson(Result)
|
||||||
'获取所有推荐版本列表
|
'获取所有推荐版本列表
|
||||||
|
|||||||
@@ -88,7 +88,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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Version}
|
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Version}
|
||||||
NewCard.Children.Add(NewStack)
|
NewCard.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
''非官方源警示
|
''非官方源警示
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<local:MyHint Text="必须安装 OptiFabric 才能正常使用 OptiFine!" Margin="0,10,0,0" x:Name="HintOptiFabric" Theme="Red" />
|
<local:MyHint Text="必须安装 OptiFabric 才能正常使用 OptiFine!" Margin="0,10,0,0" x:Name="HintOptiFabric" Theme="Red" />
|
||||||
<local:MyHint Text="安装结束后,请在 Mod 下载中搜索 OptiFabric Origins 并下载,否则 OptiFine 会无法使用!" Margin="0,10,0,0" x:Name="HintOptiFabricOld" Theme="Yellow" />
|
<local:MyHint Text="安装结束后,请在 Mod 下载中搜索 OptiFabric Origins 并下载,否则 OptiFine 会无法使用!" Margin="0,10,0,0" x:Name="HintOptiFabricOld" Theme="Yellow" />
|
||||||
<local:MyHint Text="OptiFine 与一部分 Mod 的兼容性不佳,请谨慎安装。" Margin="0,10,0,0" x:Name="HintModOptiFine" Theme="Yellow" />
|
<local:MyHint Text="OptiFine 与一部分 Mod 的兼容性不佳,请谨慎安装。" Margin="0,10,0,0" x:Name="HintModOptiFine" Theme="Yellow" />
|
||||||
<local:MyCard Title="Forge" Height="40" Margin="0,12,0,0" x:Name="CardForge" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="Forge" Height="40" Margin="0,12,0,0" x:Name="CardForge" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanForge" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanForge" />
|
||||||
<Grid x:Name="PanForgeInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
<Grid x:Name="PanForgeInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
<Grid.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="NeoForge" Height="40" Margin="0,12,0,0" x:Name="CardNeoForge" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="NeoForge" Height="40" Margin="0,12,0,0" x:Name="CardNeoForge" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanNeoForge" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanNeoForge" />
|
||||||
<Grid x:Name="PanNeoForgeInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
<Grid x:Name="PanNeoForgeInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
<Grid.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="Fabric" Height="40" Margin="0,12,0,0" x:Name="CardFabric" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="Fabric" Height="40" Margin="0,12,0,0" x:Name="CardFabric" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabric" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabric" />
|
||||||
<Grid x:Name="PanFabricInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
<Grid x:Name="PanFabricInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
<Grid.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="Fabric API" Height="40" Margin="0,12,0,0" x:Name="CardFabricApi" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="Fabric API" Height="40" Margin="0,12,0,0" x:Name="CardFabricApi" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabricApi" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabricApi" />
|
||||||
<Grid x:Name="PanFabricApiInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
<Grid x:Name="PanFabricApiInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
<Grid.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="OptiFine" Height="40" Margin="0,12,0,0" x:Name="CardOptiFine" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="OptiFine" Height="40" Margin="0,12,0,0" x:Name="CardOptiFine" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top">
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top">
|
||||||
<StackPanel Name="PanOptiFine" />
|
<StackPanel Name="PanOptiFine" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="OptiFabric" Height="40" Margin="0,12,0,0" x:Name="CardOptiFabric" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="OptiFabric" Height="40" Margin="0,12,0,0" x:Name="CardOptiFabric" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanOptiFabric" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanOptiFabric" />
|
||||||
<Grid x:Name="PanOptiFabricInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
<Grid x:Name="PanOptiFabricInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
<Grid.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="LiteLoader" Height="40" Margin="0,12,0,0" x:Name="CardLiteLoader" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
|
<local:MyCard Title="LiteLoader" Height="40" Margin="0,12,0,0" x:Name="CardLiteLoader" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanLiteLoader" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanLiteLoader" />
|
||||||
<Grid x:Name="PanLiteLoaderInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
<Grid x:Name="PanLiteLoaderInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
<Grid.RenderTransform>
|
<Grid.RenderTransform>
|
||||||
|
|||||||
@@ -54,18 +54,13 @@
|
|||||||
|
|
||||||
DisabledPageAnimControls.Remove(BtnStart)
|
DisabledPageAnimControls.Remove(BtnStart)
|
||||||
BtnStart.Show = True
|
BtnStart.Show = True
|
||||||
CardOptiFine.IsSwaped = True
|
CardOptiFine.IsSwapped = True
|
||||||
CardLiteLoader.IsSwaped = True
|
CardLiteLoader.IsSwapped = True
|
||||||
CardForge.IsSwaped = True
|
CardForge.IsSwapped = True
|
||||||
CardNeoForge.IsSwaped = True
|
CardNeoForge.IsSwapped = True
|
||||||
CardFabric.IsSwaped = True
|
CardFabric.IsSwapped = True
|
||||||
CardFabricApi.IsSwaped = True
|
CardFabricApi.IsSwapped = True
|
||||||
CardOptiFabric.IsSwaped = True
|
CardOptiFabric.IsSwapped = True
|
||||||
|
|
||||||
If Not Setup.Get("HintInstallBack") Then
|
|
||||||
Setup.Set("HintInstallBack", True)
|
|
||||||
Hint("点击 Minecraft 项即可返回游戏主版本选择页面!")
|
|
||||||
End If
|
|
||||||
|
|
||||||
'如果在选择页面按了刷新键,选择页的东西可能会由于动画被隐藏,但不会由于加载结束而再次显示,因此这里需要手动恢复
|
'如果在选择页面按了刷新键,选择页的东西可能会由于动画被隐藏,但不会由于加载结束而再次显示,因此这里需要手动恢复
|
||||||
For Each Control In GetAllAnimControls(PanSelect)
|
For Each Control In GetAllAnimControls(PanSelect)
|
||||||
@@ -318,8 +313,8 @@
|
|||||||
'OptiFine
|
'OptiFine
|
||||||
Dim OptiFineError As String = LoadOptiFineGetError()
|
Dim OptiFineError As String = LoadOptiFineGetError()
|
||||||
CardOptiFine.MainSwap.Visibility = If(OptiFineError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardOptiFine.MainSwap.Visibility = If(OptiFineError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If OptiFineError IsNot Nothing Then CardOptiFine.IsSwaped = True '例如在同时展开卡片时选择了不兼容项则强制折叠
|
If OptiFineError IsNot Nothing Then CardOptiFine.IsSwapped = True '例如在同时展开卡片时选择了不兼容项则强制折叠
|
||||||
SetOptiFineInfoShow(CardOptiFine.IsSwaped)
|
SetOptiFineInfoShow(CardOptiFine.IsSwapped)
|
||||||
If SelectedOptiFine Is Nothing Then
|
If SelectedOptiFine Is Nothing Then
|
||||||
BtnOptiFineClear.Visibility = Visibility.Collapsed
|
BtnOptiFineClear.Visibility = Visibility.Collapsed
|
||||||
ImgOptiFine.Visibility = Visibility.Collapsed
|
ImgOptiFine.Visibility = Visibility.Collapsed
|
||||||
@@ -338,8 +333,8 @@
|
|||||||
CardLiteLoader.Visibility = Visibility.Visible
|
CardLiteLoader.Visibility = Visibility.Visible
|
||||||
Dim LiteLoaderError As String = LoadLiteLoaderGetError()
|
Dim LiteLoaderError As String = LoadLiteLoaderGetError()
|
||||||
CardLiteLoader.MainSwap.Visibility = If(LiteLoaderError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardLiteLoader.MainSwap.Visibility = If(LiteLoaderError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If LiteLoaderError IsNot Nothing Then CardLiteLoader.IsSwaped = True '例如在同时展开卡片时选择了不兼容项则强制折叠
|
If LiteLoaderError IsNot Nothing Then CardLiteLoader.IsSwapped = True '例如在同时展开卡片时选择了不兼容项则强制折叠
|
||||||
SetLiteLoaderInfoShow(CardLiteLoader.IsSwaped)
|
SetLiteLoaderInfoShow(CardLiteLoader.IsSwapped)
|
||||||
If SelectedLiteLoader Is Nothing Then
|
If SelectedLiteLoader Is Nothing Then
|
||||||
BtnLiteLoaderClear.Visibility = Visibility.Collapsed
|
BtnLiteLoaderClear.Visibility = Visibility.Collapsed
|
||||||
ImgLiteLoader.Visibility = Visibility.Collapsed
|
ImgLiteLoader.Visibility = Visibility.Collapsed
|
||||||
@@ -355,8 +350,8 @@
|
|||||||
'Forge
|
'Forge
|
||||||
Dim ForgeError As String = LoadForgeGetError()
|
Dim ForgeError As String = LoadForgeGetError()
|
||||||
CardForge.MainSwap.Visibility = If(ForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardForge.MainSwap.Visibility = If(ForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If ForgeError IsNot Nothing Then CardForge.IsSwaped = True
|
If ForgeError IsNot Nothing Then CardForge.IsSwapped = True
|
||||||
SetForgeInfoShow(CardForge.IsSwaped)
|
SetForgeInfoShow(CardForge.IsSwapped)
|
||||||
If SelectedForge Is Nothing Then
|
If SelectedForge Is Nothing Then
|
||||||
BtnForgeClear.Visibility = Visibility.Collapsed
|
BtnForgeClear.Visibility = Visibility.Collapsed
|
||||||
ImgForge.Visibility = Visibility.Collapsed
|
ImgForge.Visibility = Visibility.Collapsed
|
||||||
@@ -375,8 +370,8 @@
|
|||||||
CardNeoForge.Visibility = Visibility.Visible
|
CardNeoForge.Visibility = Visibility.Visible
|
||||||
Dim NeoForgeError As String = LoadNeoForgeGetError()
|
Dim NeoForgeError As String = LoadNeoForgeGetError()
|
||||||
CardNeoForge.MainSwap.Visibility = If(NeoForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardNeoForge.MainSwap.Visibility = If(NeoForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If NeoForgeError IsNot Nothing Then CardNeoForge.IsSwaped = True
|
If NeoForgeError IsNot Nothing Then CardNeoForge.IsSwapped = True
|
||||||
SetNeoForgeInfoShow(CardNeoForge.IsSwaped)
|
SetNeoForgeInfoShow(CardNeoForge.IsSwapped)
|
||||||
If SelectedNeoForge Is Nothing Then
|
If SelectedNeoForge Is Nothing Then
|
||||||
BtnNeoForgeClear.Visibility = Visibility.Collapsed
|
BtnNeoForgeClear.Visibility = Visibility.Collapsed
|
||||||
ImgNeoForge.Visibility = Visibility.Collapsed
|
ImgNeoForge.Visibility = Visibility.Collapsed
|
||||||
@@ -396,8 +391,8 @@
|
|||||||
CardFabric.Visibility = Visibility.Visible
|
CardFabric.Visibility = Visibility.Visible
|
||||||
Dim FabricError As String = LoadFabricGetError()
|
Dim FabricError As String = LoadFabricGetError()
|
||||||
CardFabric.MainSwap.Visibility = If(FabricError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardFabric.MainSwap.Visibility = If(FabricError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If FabricError IsNot Nothing Then CardFabric.IsSwaped = True
|
If FabricError IsNot Nothing Then CardFabric.IsSwapped = True
|
||||||
SetFabricInfoShow(CardFabric.IsSwaped)
|
SetFabricInfoShow(CardFabric.IsSwapped)
|
||||||
If SelectedFabric Is Nothing Then
|
If SelectedFabric Is Nothing Then
|
||||||
BtnFabricClear.Visibility = Visibility.Collapsed
|
BtnFabricClear.Visibility = Visibility.Collapsed
|
||||||
ImgFabric.Visibility = Visibility.Collapsed
|
ImgFabric.Visibility = Visibility.Collapsed
|
||||||
@@ -417,8 +412,8 @@
|
|||||||
CardFabricApi.Visibility = Visibility.Visible
|
CardFabricApi.Visibility = Visibility.Visible
|
||||||
Dim FabricApiError As String = LoadFabricApiGetError()
|
Dim FabricApiError As String = LoadFabricApiGetError()
|
||||||
CardFabricApi.MainSwap.Visibility = If(FabricApiError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardFabricApi.MainSwap.Visibility = If(FabricApiError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If FabricApiError IsNot Nothing OrElse SelectedFabric Is Nothing Then CardFabricApi.IsSwaped = True
|
If FabricApiError IsNot Nothing OrElse SelectedFabric Is Nothing Then CardFabricApi.IsSwapped = True
|
||||||
SetFabricApiInfoShow(CardFabricApi.IsSwaped)
|
SetFabricApiInfoShow(CardFabricApi.IsSwapped)
|
||||||
If SelectedFabricApi Is Nothing Then
|
If SelectedFabricApi Is Nothing Then
|
||||||
BtnFabricApiClear.Visibility = Visibility.Collapsed
|
BtnFabricApiClear.Visibility = Visibility.Collapsed
|
||||||
ImgFabricApi.Visibility = Visibility.Collapsed
|
ImgFabricApi.Visibility = Visibility.Collapsed
|
||||||
@@ -438,8 +433,8 @@
|
|||||||
CardOptiFabric.Visibility = Visibility.Visible
|
CardOptiFabric.Visibility = Visibility.Visible
|
||||||
Dim OptiFabricError As String = LoadOptiFabricGetError()
|
Dim OptiFabricError As String = LoadOptiFabricGetError()
|
||||||
CardOptiFabric.MainSwap.Visibility = If(OptiFabricError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardOptiFabric.MainSwap.Visibility = If(OptiFabricError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
If OptiFabricError IsNot Nothing OrElse SelectedFabric Is Nothing Then CardOptiFabric.IsSwaped = True
|
If OptiFabricError IsNot Nothing OrElse SelectedFabric Is Nothing Then CardOptiFabric.IsSwapped = True
|
||||||
SetOptiFabricInfoShow(CardOptiFabric.IsSwaped)
|
SetOptiFabricInfoShow(CardOptiFabric.IsSwapped)
|
||||||
If SelectedOptiFabric Is Nothing Then
|
If SelectedOptiFabric Is Nothing Then
|
||||||
BtnOptiFabricClear.Visibility = Visibility.Collapsed
|
BtnOptiFabricClear.Visibility = Visibility.Collapsed
|
||||||
ImgOptiFabric.Visibility = Visibility.Collapsed
|
ImgOptiFabric.Visibility = Visibility.Collapsed
|
||||||
@@ -639,7 +634,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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
PanMinecraft.Children.Add(NewCard)
|
PanMinecraft.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
'自动选择版本
|
'自动选择版本
|
||||||
@@ -676,6 +671,11 @@
|
|||||||
VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
|
VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
|
||||||
Return "与 Forge 不兼容"
|
Return "与 Forge 不兼容"
|
||||||
End If
|
End If
|
||||||
|
'检查 Fabric 1.20.5+:全部不兼容
|
||||||
|
If SelectedFabric IsNot Nothing AndAlso
|
||||||
|
VersionSortInteger(SelectedMinecraftId, "1.20.4") > 0 Then
|
||||||
|
Return "与 Fabric 不兼容"
|
||||||
|
End If
|
||||||
'检查 Forge 版本
|
'检查 Forge 版本
|
||||||
Dim HasAny As Boolean = False
|
Dim HasAny As Boolean = False
|
||||||
Dim HasRequiredVersion As Boolean = False
|
Dim HasRequiredVersion As Boolean = False
|
||||||
@@ -750,14 +750,14 @@
|
|||||||
OptiFabric_Loaded()
|
OptiFabric_Loaded()
|
||||||
Forge_Loaded()
|
Forge_Loaded()
|
||||||
NeoForge_Loaded()
|
NeoForge_Loaded()
|
||||||
CardOptiFine.IsSwaped = True
|
CardOptiFine.IsSwapped = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub OptiFine_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFineClear.MouseLeftButtonUp
|
Private Sub OptiFine_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFineClear.MouseLeftButtonUp
|
||||||
SelectedOptiFine = Nothing
|
SelectedOptiFine = Nothing
|
||||||
SelectedOptiFabric = Nothing
|
SelectedOptiFabric = Nothing
|
||||||
AutoSelectedOptiFabric = False
|
AutoSelectedOptiFabric = False
|
||||||
CardOptiFine.IsSwaped = True
|
CardOptiFine.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
Forge_Loaded()
|
Forge_Loaded()
|
||||||
NeoForge_Loaded()
|
NeoForge_Loaded()
|
||||||
@@ -811,12 +811,12 @@
|
|||||||
'选择与清除
|
'选择与清除
|
||||||
Private Sub LiteLoader_Selected(sender As MyListItem, e As EventArgs)
|
Private Sub LiteLoader_Selected(sender As MyListItem, e As EventArgs)
|
||||||
SelectedLiteLoader = sender.Tag
|
SelectedLiteLoader = sender.Tag
|
||||||
CardLiteLoader.IsSwaped = True
|
CardLiteLoader.IsSwapped = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub LiteLoader_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnLiteLoaderClear.MouseLeftButtonUp
|
Private Sub LiteLoader_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnLiteLoaderClear.MouseLeftButtonUp
|
||||||
SelectedLiteLoader = Nothing
|
SelectedLiteLoader = Nothing
|
||||||
CardLiteLoader.IsSwaped = True
|
CardLiteLoader.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -897,14 +897,14 @@
|
|||||||
'选择与清除
|
'选择与清除
|
||||||
Private Sub Forge_Selected(sender As MyListItem, e As EventArgs)
|
Private Sub Forge_Selected(sender As MyListItem, e As EventArgs)
|
||||||
SelectedForge = sender.Tag
|
SelectedForge = sender.Tag
|
||||||
CardForge.IsSwaped = True
|
CardForge.IsSwapped = True
|
||||||
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedOptiFine = Nothing
|
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedOptiFine = Nothing
|
||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub Forge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnForgeClear.MouseLeftButtonUp
|
Private Sub Forge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnForgeClear.MouseLeftButtonUp
|
||||||
SelectedForge = Nothing
|
SelectedForge = Nothing
|
||||||
CardForge.IsSwaped = True
|
CardForge.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
SelectReload()
|
SelectReload()
|
||||||
@@ -959,13 +959,13 @@
|
|||||||
'选择与清除
|
'选择与清除
|
||||||
Private Sub NeoForge_Selected(sender As MyListItem, e As EventArgs)
|
Private Sub NeoForge_Selected(sender As MyListItem, e As EventArgs)
|
||||||
SelectedNeoForge = sender.Tag
|
SelectedNeoForge = sender.Tag
|
||||||
CardNeoForge.IsSwaped = True
|
CardNeoForge.IsSwapped = True
|
||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub NeoForge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnNeoForgeClear.MouseLeftButtonUp
|
Private Sub NeoForge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnNeoForgeClear.MouseLeftButtonUp
|
||||||
SelectedNeoForge = Nothing
|
SelectedNeoForge = Nothing
|
||||||
CardNeoForge.IsSwaped = True
|
CardNeoForge.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
SelectReload()
|
SelectReload()
|
||||||
@@ -981,6 +981,11 @@
|
|||||||
Private Function LoadFabricGetError() As String
|
Private Function LoadFabricGetError() As String
|
||||||
If LoadFabric Is Nothing OrElse LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
|
If LoadFabric Is Nothing OrElse LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
|
||||||
If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadFabric.State, Object).Error.Message
|
If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadFabric.State, Object).Error.Message
|
||||||
|
'检查 OptiFine 1.20.5+:没有 OptiFabric 故全部不兼容
|
||||||
|
If SelectedOptiFine IsNot Nothing AndAlso
|
||||||
|
VersionSortInteger(SelectedMinecraftId, "1.20.4") > 0 Then
|
||||||
|
Return "与 OptiFine 不兼容"
|
||||||
|
End If
|
||||||
For Each Version As JObject In DlFabricListLoader.Output.Value("game")
|
For Each Version As JObject In DlFabricListLoader.Output.Value("game")
|
||||||
If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3") Then
|
If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3") Then
|
||||||
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
||||||
@@ -1020,7 +1025,7 @@
|
|||||||
SelectedFabric = sender.Tag("version").ToString
|
SelectedFabric = sender.Tag("version").ToString
|
||||||
FabricApi_Loaded()
|
FabricApi_Loaded()
|
||||||
OptiFabric_Loaded()
|
OptiFabric_Loaded()
|
||||||
CardFabric.IsSwaped = True
|
CardFabric.IsSwapped = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub Fabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricClear.MouseLeftButtonUp
|
Private Sub Fabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricClear.MouseLeftButtonUp
|
||||||
@@ -1029,7 +1034,7 @@
|
|||||||
AutoSelectedFabricApi = False
|
AutoSelectedFabricApi = False
|
||||||
SelectedOptiFabric = Nothing
|
SelectedOptiFabric = Nothing
|
||||||
AutoSelectedOptiFabric = False
|
AutoSelectedOptiFabric = False
|
||||||
CardFabric.IsSwaped = True
|
CardFabric.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -1141,12 +1146,12 @@
|
|||||||
'选择与清除
|
'选择与清除
|
||||||
Private Sub FabricApi_Selected(sender As MyListItem, e As EventArgs)
|
Private Sub FabricApi_Selected(sender As MyListItem, e As EventArgs)
|
||||||
SelectedFabricApi = sender.Tag
|
SelectedFabricApi = sender.Tag
|
||||||
CardFabricApi.IsSwaped = True
|
CardFabricApi.IsSwapped = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub FabricApi_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricApiClear.MouseLeftButtonUp
|
Private Sub FabricApi_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricApiClear.MouseLeftButtonUp
|
||||||
SelectedFabricApi = Nothing
|
SelectedFabricApi = Nothing
|
||||||
CardFabricApi.IsSwaped = True
|
CardFabricApi.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -1233,12 +1238,12 @@
|
|||||||
'选择与清除
|
'选择与清除
|
||||||
Private Sub OptiFabric_Selected(sender As MyListItem, e As EventArgs)
|
Private Sub OptiFabric_Selected(sender As MyListItem, e As EventArgs)
|
||||||
SelectedOptiFabric = sender.Tag
|
SelectedOptiFabric = sender.Tag
|
||||||
CardOptiFabric.IsSwaped = True
|
CardOptiFabric.IsSwapped = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub OptiFabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFabricClear.MouseLeftButtonUp
|
Private Sub OptiFabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFabricClear.MouseLeftButtonUp
|
||||||
SelectedOptiFabric = Nothing
|
SelectedOptiFabric = Nothing
|
||||||
CardOptiFabric.IsSwaped = True
|
CardOptiFabric.IsSwapped = True
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
SelectReload()
|
SelectReload()
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -34,7 +34,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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
@@ -23,7 +23,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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
@@ -38,7 +38,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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
LabTitle.Text = "登录 Minecraft"
|
LabTitle.Text = "登录 Minecraft"
|
||||||
LabCaption.Text =
|
LabCaption.Text =
|
||||||
$"登录网页将自动开启,请在网页中输入 {UserCode}(已自动复制)。" & vbCrLf & vbCrLf &
|
$"登录网页将自动开启,请在网页中输入 {UserCode}(已自动复制)。" & vbCrLf & vbCrLf &
|
||||||
$"如果网络环境不佳,网页可能一直加载不出来,届时请使用使用加速器或 VPN 以改善网络环境。" & vbCrLf &
|
$"如果网络环境不佳,网页可能一直加载不出来,届时请使用加速器或 VPN 以改善网络环境。" & vbCrLf &
|
||||||
$"你也可以用其他设备打开 {Website} 并输入上述代码。"
|
$"你也可以用其他设备打开 {Website} 并输入上述代码。"
|
||||||
Btn1.EventData = Website
|
Btn1.EventData = Website
|
||||||
Btn2.EventData = UserCode
|
Btn2.EventData = UserCode
|
||||||
@@ -105,13 +105,16 @@
|
|||||||
Dim UnknownFailureCount As Integer = 0
|
Dim UnknownFailureCount As Integer = 0
|
||||||
Do While Not MyConverter.IsExited
|
Do While Not MyConverter.IsExited
|
||||||
Try
|
Try
|
||||||
Dim Result = NetRequestOnce(
|
Dim Result = NetRequestByClient(
|
||||||
"https://login.microsoftonline.com/consumers/oauth2/v2.0/token", "POST",
|
"https://login.microsoftonline.com/consumers/oauth2/v2.0/token", HttpMethod.Post,
|
||||||
|
Content:=
|
||||||
"grant_type=urn:ietf:params:oauth:grant-type:device_code" & "&" &
|
"grant_type=urn:ietf:params:oauth:grant-type:device_code" & "&" &
|
||||||
"client_id=" & OAuthClientId & "&" &
|
"client_id=" & OAuthClientId & "&" &
|
||||||
"device_code=" & DeviceCode & "&" &
|
"device_code=" & DeviceCode & "&" &
|
||||||
"scope=XboxLive.signin%20offline_access",
|
"scope=XboxLive.signin%20offline_access",
|
||||||
"application/x-www-form-urlencoded", 5000 + UnknownFailureCount * 5000, MakeLog:=False)
|
ContentType:="application/x-www-form-urlencoded",
|
||||||
|
Timeout:=5000 + UnknownFailureCount * 5000,
|
||||||
|
MakeLog:=False)
|
||||||
'获取结果
|
'获取结果
|
||||||
Dim ResultJson As JObject = GetJson(Result)
|
Dim ResultJson As JObject = GetJson(Result)
|
||||||
McLaunchLog($"令牌过期时间:{ResultJson("expires_in")} 秒")
|
McLaunchLog($"令牌过期时间:{ResultJson("expires_in")} 秒")
|
||||||
@@ -119,21 +122,29 @@
|
|||||||
Finished({ResultJson("access_token").ToString, ResultJson("refresh_token").ToString})
|
Finished({ResultJson("access_token").ToString, ResultJson("refresh_token").ToString})
|
||||||
Return
|
Return
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
If ex.Message.Contains("authorization_declined") Then
|
If TypeOf ex Is ResponsedWebException Then
|
||||||
|
Dim Response = CType(ex, ResponsedWebException).Response
|
||||||
|
If Response.Contains("authorization_declined") Then
|
||||||
Finished(New Exception("$你拒绝了 PCL 申请的权限……"))
|
Finished(New Exception("$你拒绝了 PCL 申请的权限……"))
|
||||||
Return
|
Return
|
||||||
ElseIf ex.Message.Contains("expired_token") Then
|
ElseIf Response.Contains("expired_token") Then
|
||||||
Finished(New Exception("$登录用时太长啦,重新试试吧!"))
|
Finished(New Exception("$登录用时太长啦,重新试试吧!"))
|
||||||
Return
|
Return
|
||||||
ElseIf ex.Message.Contains("service abuse") Then
|
ElseIf Response.Contains("Account security interrupt") Then
|
||||||
|
Finished(New Exception("$该账号由于安全问题无法登陆,请前往微软账户页获取更多信息。"))
|
||||||
|
Return
|
||||||
|
ElseIf Response.Contains("service abuse") Then
|
||||||
Finished(New Exception("$非常抱歉,该账号已被微软封禁,无法登录。"))
|
Finished(New Exception("$非常抱歉,该账号已被微软封禁,无法登录。"))
|
||||||
Return
|
Return
|
||||||
ElseIf ex.Message.Contains("AADSTS70000") Then '可能不能判 “invalid_grant”,见 #269
|
ElseIf Response.Contains("AADSTS70000") Then '可能不能判 “invalid_grant”,见 #269
|
||||||
Finished(New RestartException)
|
Finished(New RestartException)
|
||||||
Return
|
Return
|
||||||
ElseIf ex.Message.Contains("authorization_pending") Then
|
ElseIf Response.Contains("authorization_pending") Then
|
||||||
Thread.Sleep(2000)
|
Thread.Sleep(2000)
|
||||||
ElseIf UnknownFailureCount <= 2 Then
|
Continue Do
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
If UnknownFailureCount <= 2 Then
|
||||||
UnknownFailureCount += 1
|
UnknownFailureCount += 1
|
||||||
Log(ex, $"登录轮询第 {UnknownFailureCount} 次失败")
|
Log(ex, $"登录轮询第 {UnknownFailureCount} 次失败")
|
||||||
Thread.Sleep(2000)
|
Thread.Sleep(2000)
|
||||||
|
|||||||
@@ -259,12 +259,13 @@ Retry:
|
|||||||
End Sub)
|
End Sub)
|
||||||
If SelId Is Nothing Then Return
|
If SelId Is Nothing Then Return
|
||||||
'发送请求
|
'发送请求
|
||||||
Dim Result As String = NetRequestRetry("https://api.minecraftservices.com/minecraft/profile/capes/active",
|
Dim Result As String = NetRequestByClientRetry("https://api.minecraftservices.com/minecraft/profile/capes/active",
|
||||||
If(SelId = 0, "DELETE", "PUT"),
|
If(SelId = 0, HttpMethod.Delete, HttpMethod.Put),
|
||||||
If(SelId = 0, "", New JObject(New JProperty("capeId", SkinData("capes")(SelId - 1)("id"))).ToString(0)),
|
Content:=If(SelId = 0, "", New JObject(New JProperty("capeId", SkinData("capes")(SelId - 1)("id"))).ToString(0)),
|
||||||
"application/json", Headers:=New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
ContentType:="application/json",
|
||||||
|
Headers:={{"Authorization", "Bearer " & AccessToken}})
|
||||||
If Result.Contains("""errorMessage""") Then
|
If Result.Contains("""errorMessage""") Then
|
||||||
Hint("更改披风失败:" & GetJson(Result)("errorMessage"), HintType.Critical)
|
Hint("更改披风失败:" & GetJson(Result)("errorMessage").ToString, HintType.Critical)
|
||||||
Return
|
Return
|
||||||
Else
|
Else
|
||||||
Hint("更改披风成功!", HintType.Finish)
|
Hint("更改披风成功!", HintType.Finish)
|
||||||
|
|||||||
@@ -243,11 +243,13 @@
|
|||||||
If Not IsNothing(PageNew) AndAlso Not IsNothing(PageNew.Parent) Then PageNew.SetValue(ContentPresenter.ContentProperty, Nothing)
|
If Not IsNothing(PageNew) AndAlso Not IsNothing(PageNew.Parent) Then PageNew.SetValue(ContentPresenter.ContentProperty, Nothing)
|
||||||
If Anim Then
|
If Anim Then
|
||||||
'动画
|
'动画
|
||||||
Dispatcher.Invoke(Sub()
|
Dispatcher.Invoke(
|
||||||
|
Sub()
|
||||||
'执行动画
|
'执行动画
|
||||||
AniStart({
|
AniStart({
|
||||||
AaOpacity(PanLogin, -PanLogin.Opacity, 100,, New AniEaseOutFluent),
|
AaOpacity(PanLogin, -PanLogin.Opacity, 100,, New AniEaseOutFluent),
|
||||||
AaCode(Sub()
|
AaCode(
|
||||||
|
Sub()
|
||||||
AniControlEnabled += 1
|
AniControlEnabled += 1
|
||||||
PanLogin.Children.Clear()
|
PanLogin.Children.Clear()
|
||||||
PanLogin.Children.Add(PageNew)
|
PanLogin.Children.Add(PageNew)
|
||||||
|
|||||||
@@ -88,11 +88,11 @@ Download:
|
|||||||
</local:MyCard>"
|
</local:MyCard>"
|
||||||
Case 2
|
Case 2
|
||||||
Log("[Page] 主页预设:Minecraft 新闻")
|
Log("[Page] 主页预设:Minecraft 新闻")
|
||||||
Url = "http://pcl.mcnews.thestack.top"
|
Url = "https://pcl.mcnews.thestack.top"
|
||||||
GoTo Download
|
GoTo Download
|
||||||
Case 3
|
Case 3
|
||||||
Log("[Page] 主页预设:简单主页")
|
Log("[Page] 主页预设:简单主页")
|
||||||
Url = "https://raw.gitcode.com/mfn233/PCL-Mainpage/raw/main/Custom.xaml"
|
Url = "https://pclhomeplazaoss.lingyunawa.top:26994/d/Homepages/MFn233/Custom.xaml"
|
||||||
GoTo Download
|
GoTo Download
|
||||||
Case 4
|
Case 4
|
||||||
Log("[Page] 主页预设:每日整合包推荐")
|
Log("[Page] 主页预设:每日整合包推荐")
|
||||||
@@ -128,7 +128,7 @@ Download:
|
|||||||
GoTo Download
|
GoTo Download
|
||||||
Case 12
|
Case 12
|
||||||
Log("[Page] 主页预设:PCL GitHub 仪表盘")
|
Log("[Page] 主页预设:PCL GitHub 仪表盘")
|
||||||
Url = "https://raw.gitcode.com/Deep-Dark-Forest/PCL2-GitHub-Dashboard-Homepage/raw/main/custom.xaml"
|
Url = "https://ddf.pcl-community.org/Custom.xaml"
|
||||||
GoTo Download
|
GoTo Download
|
||||||
End Select
|
End Select
|
||||||
End Select
|
End Select
|
||||||
@@ -155,7 +155,7 @@ Download:
|
|||||||
Dim Version As String = ""
|
Dim Version As String = ""
|
||||||
Dim NeedDownload As Boolean = True
|
Dim NeedDownload As Boolean = True
|
||||||
Try
|
Try
|
||||||
Version = NetGetCodeByRequestOnce(VersionAddress, Timeout:=10000)
|
Version = NetRequestByClientRetry(VersionAddress)
|
||||||
If Version.Length > 1000 Then Throw New Exception($"获取的主页版本过长({Version.Length} 字符)")
|
If Version.Length > 1000 Then Throw New Exception($"获取的主页版本过长({Version.Length} 字符)")
|
||||||
Dim CurrentVersion As String = Setup.Get("CacheSavedPageVersion")
|
Dim CurrentVersion As String = Setup.Get("CacheSavedPageVersion")
|
||||||
If Version <> "" AndAlso CurrentVersion <> "" AndAlso Version = CurrentVersion Then
|
If Version <> "" AndAlso CurrentVersion <> "" AndAlso Version = CurrentVersion Then
|
||||||
@@ -170,7 +170,7 @@ Download:
|
|||||||
End Try
|
End Try
|
||||||
'实际下载
|
'实际下载
|
||||||
If NeedDownload Then
|
If NeedDownload Then
|
||||||
Dim FileContent As String = NetGetCodeByRequestRetry(Address)
|
Dim FileContent As String = NetRequestByClientRetry(Address)
|
||||||
Log($"[Page] 已联网下载主页,内容长度:{FileContent.Length},来源:{Address}")
|
Log($"[Page] 已联网下载主页,内容长度:{FileContent.Length},来源:{Address}")
|
||||||
Setup.Set("CacheSavedPageUrl", Address)
|
Setup.Set("CacheSavedPageUrl", Address)
|
||||||
Setup.Set("CacheSavedPageVersion", Version)
|
Setup.Set("CacheSavedPageVersion", Version)
|
||||||
@@ -230,7 +230,9 @@ Download:
|
|||||||
Try
|
Try
|
||||||
'修改时应同时修改 PageOtherHelpDetail.Init
|
'修改时应同时修改 PageOtherHelpDetail.Init
|
||||||
Content = HelpArgumentReplace(Content)
|
Content = HelpArgumentReplace(Content)
|
||||||
If Content.Contains("xmlns") Then Content = Content.RegexReplace("xmlns[^""']*(""|')[^""']*(""|')", "").Replace("xmlns", "") '禁止声明命名空间
|
Do While Content.Contains("xmlns")
|
||||||
|
Content = Content.RegexReplace("xmlns[^""']*(""|')[^""']*(""|')", "").Replace("xmlns", "") '禁止声明命名空间
|
||||||
|
Loop
|
||||||
Content = "<StackPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:sys=""clr-namespace:System;assembly=mscorlib"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:local=""clr-namespace:PCL;assembly=Plain Craft Launcher 2"">" & Content & "</StackPanel>"
|
Content = "<StackPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:sys=""clr-namespace:System;assembly=mscorlib"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:local=""clr-namespace:PCL;assembly=Plain Craft Launcher 2"">" & Content & "</StackPanel>"
|
||||||
Log($"[Page] 实例化:加载主页 UI 开始,最终内容长度:{Content.Count}")
|
Log($"[Page] 实例化:加载主页 UI 开始,最终内容长度:{Content.Count}")
|
||||||
PanCustom.Children.Add(GetObjectFromXML(Content))
|
PanCustom.Children.Add(GetObjectFromXML(Content))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:PCL"
|
xmlns:local="clr-namespace:PCL"
|
||||||
mc:Ignorable="d" d:DesignWidth="297.6">
|
mc:Ignorable="d" d:DesignWidth="297.6">
|
||||||
<StackPanel Margin="0,0,0,5">
|
<StackPanel Margin="0,0,0,5" x:Name="PanMain">
|
||||||
<local:MyHint x:Name="HintChinese" Theme="Red" Text="玩家名如果包含英文、数字、下划线以外的内容,可能会无法进入 Minecraft 1.18 以后的世界!" Margin="0,0,0,15" Visibility="Collapsed" />
|
<local:MyHint x:Name="HintChinese" Theme="Red" Text="玩家名如果包含英文、数字、下划线以外的内容,可能会无法进入 Minecraft 1.18 以后的世界!" Margin="0,0,0,15" Visibility="Collapsed" />
|
||||||
<local:MySkin HorizontalAlignment="Center" x:Name="Skin" HasCape="False" Margin="0,0,0,15" />
|
<local:MySkin HorizontalAlignment="Center" x:Name="Skin" HasCape="False" Margin="0,0,0,15" />
|
||||||
<local:MyComboBox IsEditable="True" x:Name="ComboName" Height="28" IsTextSearchEnabled="False" HintText="游戏用户名" />
|
<local:MyComboBox IsEditable="True" x:Name="ComboName" Height="28" IsTextSearchEnabled="False" HintText="游戏用户名" />
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ Public Class PageLoginLegacy
|
|||||||
Private Sub ComboLegacy_TextChanged(sender As Object, e As TextChangedEventArgs) Handles ComboName.TextChanged
|
Private Sub ComboLegacy_TextChanged(sender As Object, e As TextChangedEventArgs) Handles ComboName.TextChanged
|
||||||
If Setup.Get("LaunchSkinType") = 0 Then PageLaunchLeft.SkinLegacy.Start(IsForceRestart:=True)
|
If Setup.Get("LaunchSkinType") = 0 Then PageLaunchLeft.SkinLegacy.Start(IsForceRestart:=True)
|
||||||
HintChinese.Visibility = If(RegexCheck(ComboName.Text, "^[0-9A-Za-z_]*$"), Visibility.Collapsed, Visibility.Visible)
|
HintChinese.Visibility = If(RegexCheck(ComboName.Text, "^[0-9A-Za-z_]*$"), Visibility.Collapsed, Visibility.Visible)
|
||||||
|
RunInUi(Sub() PanMain.InvalidateMeasure(), True) '由于 WPF 的 Bug,它不一定会自动更新 HintChinese 的大小(#6627)
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub Skin_Click() Handles Skin.Click
|
Private Sub Skin_Click() Handles Skin.Click
|
||||||
If (Setup.Get("UiHiddenPageSetup") OrElse Setup.Get("UiHiddenSetupLaunch")) AndAlso Not PageSetupUI.HiddenForceShow Then
|
If (Setup.Get("UiHiddenPageSetup") OrElse Setup.Get("UiHiddenSetupLaunch")) AndAlso Not PageSetupUI.HiddenForceShow Then
|
||||||
|
|||||||
@@ -23,10 +23,11 @@
|
|||||||
<local:MyIconButton.ContextMenu>
|
<local:MyIconButton.ContextMenu>
|
||||||
<ContextMenu Closed="HidePanel" HorizontalOffset="10" VerticalOffset="18">
|
<ContextMenu Closed="HidePanel" HorizontalOffset="10" VerticalOffset="18">
|
||||||
<local:MyMenuItem Click="BtnSkinEdit_Click" Header="修改皮肤"/>
|
<local:MyMenuItem Click="BtnSkinEdit_Click" Header="修改皮肤"/>
|
||||||
<local:MyMenuItem Click="BtnSkinSave_Click" Header="保存皮肤"/>
|
<local:MyMenuItem Click="BtnSkinSave_Click" Header="保存皮肤文件"/>
|
||||||
<local:MyMenuItem Click="BtnSkinRefresh_Click" Header="刷新头像"/>
|
|
||||||
<Separator />
|
<Separator />
|
||||||
<local:MyMenuItem Click="BtnSkinCape_Click" Header="修改披风"/>
|
<local:MyMenuItem Click="BtnSkinCape_Click" Header="修改披风"/>
|
||||||
|
<Separator />
|
||||||
|
<local:MyMenuItem Click="BtnSkinRefresh_Click" Header="刷新"/>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</local:MyIconButton.ContextMenu>
|
</local:MyIconButton.ContextMenu>
|
||||||
</local:MyIconButton>
|
</local:MyIconButton>
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ Retry:
|
|||||||
McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
|
McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
|
||||||
GoTo Retry
|
GoTo Retry
|
||||||
ElseIf Result.Contains("""error""") Then
|
ElseIf Result.Contains("""error""") Then
|
||||||
Hint("更改皮肤失败:" & GetJson(Result)("error"), HintType.Critical)
|
Hint("更改皮肤失败:" & GetJson(Result)("error").ToString, HintType.Critical)
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
'获取新皮肤地址
|
'获取新皮肤地址
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
<ColumnDefinition Width="150" />
|
<ColumnDefinition Width="150" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<local:MyListItem IsHitTestVisible="False" Title="龙腾猫跃" Margin="-5,0,15,0" Info="Plain Craft Launcher 的作者!" Grid.Row="0" Grid.Column="1" />
|
<local:MyListItem IsHitTestVisible="False" Title="龙腾猫跃" Margin="-5,0,15,0" Info="Plain Craft Launcher 的开发者!" Grid.Row="0" Grid.Column="1" />
|
||||||
<local:MyListItem IsHitTestVisible="False" Title="Plain Craft Launcher 2" Margin="-5,0,15,0" Info="当前版本:%VERSION%(%VERSIONCODE%.%BRANCH%)" Grid.Row="1" Grid.Column="1" x:Name="ItemAboutPcl" />
|
<local:MyListItem IsHitTestVisible="False" Title="Plain Craft Launcher 2" Margin="-5,0,15,0" Info="当前版本:%VERSION%(%VERSIONCODE%.%BRANCH%)" Grid.Row="1" Grid.Column="1" x:Name="ItemAboutPcl" />
|
||||||
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/Logo.png" Grid.Row="1" Margin="3">
|
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/Logo.png" Grid.Row="1" Margin="3">
|
||||||
<Image.Clip>
|
<Image.Clip>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
</Image.Clip>
|
</Image.Clip>
|
||||||
</Image>
|
</Image>
|
||||||
<local:MyButton Text="赞助作者" Grid.Column="2" Grid.Row="0" Height="35" EventType="打开网页" EventData="https://afdian.com/a/LTCat" />
|
<local:MyButton Text="赞助 PCL !" Grid.Column="2" Grid.Row="0" Height="35" EventType="打开网页" EventData="https://afdian.com/a/LTCat" ColorType="Highlight" />
|
||||||
<local:MyButton Text="查看源代码" Grid.Column="2" Grid.Row="1" Height="35" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2" />
|
<local:MyButton Text="查看源代码" Grid.Column="2" Grid.Row="1" Height="35" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
@@ -51,11 +51,12 @@
|
|||||||
<ColumnDefinition Width="150" />
|
<ColumnDefinition Width="150" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<local:MyListItem Title="bangbang93" Margin="-5,0,15,0" IsHitTestVisible="False" Info="提供 BMCLAPI 镜像源和 Forge 安装工具,详见 https://bmclapi.bangbang93.com" Grid.Row="0" Grid.Column="1" />
|
<local:MyListItem Title="bangbang93" Margin="-5,0,15,0" IsHitTestVisible="False" Info="提供 BMCLAPI 镜像源和 Forge 安装工具,详见 https://bmclapi.bangbang93.com" Grid.Row="0" Grid.Column="1" />
|
||||||
<local:MyButton x:Name="BtnAboutBmclapi" Text="赞助镜像源" Grid.Row="0" Grid.Column="2" Height="35" />
|
<local:MyButton Text="赞助镜像源" Grid.Row="0" Grid.Column="2" Height="35" EventType="打开网页" EventData="https://afdian.com/a/bangbang93" />
|
||||||
<local:MyListItem Title="MC 百科" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Mod 名称的中文翻译和更多相关信息!" Grid.Row="1" Grid.Column="1" />
|
<local:MyListItem Title="MC 百科" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Mod 名称的中文翻译和更多相关信息!" Grid.Row="1" Grid.Column="1" />
|
||||||
<local:MyButton x:Name="BtnAboutWiki" Text="打开百科" Grid.Row="1" Grid.Column="2" Height="35" />
|
<local:MyButton Text="打开百科" Grid.Row="1" Grid.Column="2" Height="35" EventType="打开网页" EventData="https://www.mcmod.cn" />
|
||||||
<local:MyListItem Title="00ll00" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Java Launch Wrapper 和一些重要服务支持!" Grid.Row="2" Grid.Column="1" />
|
<local:MyListItem Title="z0z0r4" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 MCIM 社区资源镜像源和帮助库图床!" Grid.Row="2" Grid.Column="1" />
|
||||||
<local:MyListItem Title="z0z0r4" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 MCIM 中国 Mod 下载镜像源和帮助库图床!" Grid.Row="3" Grid.Column="1" />
|
<local:MyButton Text="MCIM 主页" Grid.Row="2" Grid.Column="2" Height="35" EventType="打开网页" EventData="https://github.com/mcmod-info-mirror" />
|
||||||
|
<local:MyListItem Title="00ll00" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Java Launch Wrapper 和一些重要服务支持!" Grid.Row="3" Grid.Column="1" />
|
||||||
<local:MyListItem Title="Patrick" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="设计并制作了 PCL 图标,让我从做图标的水深火热中得到了解脱……" Grid.Row="4" Grid.Column="1" />
|
<local:MyListItem Title="Patrick" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="设计并制作了 PCL 图标,让我从做图标的水深火热中得到了解脱……" Grid.Row="4" Grid.Column="1" />
|
||||||
<local:MyListItem Title="Hao_Tian" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="在内测中找出了一大堆没人想得到的诡异 Bug,有非同寻常的 Bug 体质" Grid.Row="5" Grid.Column="1" />
|
<local:MyListItem Title="Hao_Tian" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="在内测中找出了一大堆没人想得到的诡异 Bug,有非同寻常的 Bug 体质" Grid.Row="5" Grid.Column="1" />
|
||||||
<local:MyListItem Title="Minecraft 中文论坛" Margin="-5,0,15,0" IsHitTestVisible="False" Info="虽然已经关站了,但感谢此前提供了 MCBBS 镜像源……" Grid.Row="6" Grid.Column="1" />
|
<local:MyListItem Title="Minecraft 中文论坛" Margin="-5,0,15,0" IsHitTestVisible="False" Info="虽然已经关站了,但感谢此前提供了 MCBBS 镜像源……" Grid.Row="6" Grid.Column="1" />
|
||||||
@@ -70,12 +71,12 @@
|
|||||||
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
</Image.Clip>
|
</Image.Clip>
|
||||||
</Image>
|
</Image>
|
||||||
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/00ll00.png" Grid.Row="2" Margin="3">
|
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/z0z0r4.png" Grid.Row="2" Margin="3">
|
||||||
<Image.Clip>
|
<Image.Clip>
|
||||||
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
</Image.Clip>
|
</Image.Clip>
|
||||||
</Image>
|
</Image>
|
||||||
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/z0z0r4.png" Grid.Row="3" Margin="3">
|
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/00ll00.png" Grid.Row="3" Margin="3">
|
||||||
<Image.Clip>
|
<Image.Clip>
|
||||||
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
</Image.Clip>
|
</Image.Clip>
|
||||||
@@ -104,265 +105,246 @@
|
|||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="赞助者">
|
<local:MyCard Margin="0,0,0,15" Title="赞助者">
|
||||||
<StackPanel Margin="25,40,10,20">
|
<StackPanel Margin="25,40,10,20">
|
||||||
<TextBlock HorizontalAlignment="Left" Text="以下是 2025 年 5 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
<TextBlock HorizontalAlignment="Left" Text="以下是 2025 年 7 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
||||||
<WrapPanel Margin="0,0,0,10">
|
<WrapPanel Margin="0,0,0,10">
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Alliance" />
|
<TextBlock Width="120" Margin="0,1.5" Text="ZSF" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="风之轻语" />
|
<TextBlock Width="120" Margin="0,1.5" Text="TizhleF" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="大博文" />
|
<TextBlock Width="120" Margin="0,1.5" Text="方源" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="狐狸不吃酸葡萄" />
|
<TextBlock Width="120" Margin="0,1.5" Text="日月空呵" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="仰望星空的牧星人" />
|
<TextBlock Width="120" Margin="0,1.5" Text="贾明志" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="某个网友" />
|
<TextBlock Width="120" Margin="0,1.5" Text="百瑞" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Flying___pig" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="绝世" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Jwac" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="万玖" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="墨忆" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="天刹" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Cess" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="ender_glass" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="TT" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="白玄.雪狼" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="MUCT" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="崇昀" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="绪" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="吾皇万岁" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Ander·Les" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Eoctopus" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="时光飞逝一下午" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Carl7412" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="ShinyChariot" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="骨故谷" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="?" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Jinji希子" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="自然选择" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="云念" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="钱尹鹏" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="TBONC" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="祈农" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="凤凰院凶真" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="ShuangDaoRen" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="PXZ233" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="二十二今天有没有" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="天魕" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="南华清" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="66112447" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="夏行子" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="周俊成" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="乌漆嘛黑" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="肘击恶魔佐巴扬" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Pari~" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="红云" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Link-an" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="想要钱用不完" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="花宝" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="生于春天的雷电" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="被偷去的睡眠" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="liuxuan" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="寒枫凌" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="雀色时" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="架" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="终成究竟觉" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="S0D1UM" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="吞仔送命" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="白浪宇宙" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Crimson" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Mibo_MkIX" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="G.snine18^7" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="两把雨伞" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="古明地苑" />
|
||||||
|
<TextBlock Width="240" Margin="0,1.5" Text="MarbleMionshevic" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text=":〈" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="紫罗兰" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="asai" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="隔壁小明" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="就爱唱歌" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="沫神鹤" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="风已消逝" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="光意留闪" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="我们长征的路上" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="芸芷" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="函数极限" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="冰川泥" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="XunWei" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="sirous" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="路过某打酱油的" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Gnight07" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="结构德古拉" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="myyukee" />
|
||||||
|
<TextBlock Width="240" Margin="0,1.5" Text="云之彼端约定的地方" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="苏玖" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="赤沃净" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="YYC" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="晨曦酒庄高冷男" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="herald112" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Foxman" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="KoreQAQ" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="TechOfRevo" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="lqs" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="简某" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="源起于此" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="爱莉希雅" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text=" 和忧" />
|
||||||
|
<TextBlock Width="240" Margin="0,1.5" Text="全明星小面包批发商DIO" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="碎序" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="U" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Dumlet" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="johnqian" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="KANG" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="owod" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="九" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="苑煜" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="壹" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="UA-Ming" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="可爱小探姬" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="霜月" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="bud" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="小虐SAIKYO" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="zealotand" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="comico" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="万山松" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="依梦明天" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="化形彧九尾" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="知崎" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="LOG175" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="绵" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="scp00813" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="宝宝" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="9527" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="ICE_xwx" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="羽笙喵喵" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="ssvgg(☉ x ☉)" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Happymeals" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="shen12244" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="一般路过AAA" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Niko" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="qroiwopqri" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="TringDron" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="有屳則名" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="TX2006" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="滑天下之大稽" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="中东悍匪" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="鬼泣々离殇" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="蒼崎青子" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="wyh114514" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="飞飞在睡觉。" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="柚西" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="XIAOSHUAI" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="saxioh" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="baibaibai" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="事屑Jerry" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Rs32" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="SPDish" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="风早九夜" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Reg" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="hellord" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="时本ki" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="mamana" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="放肆的微笑" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="人没逝" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="wddjww" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="xiao澄" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="银狼碎片" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="OniKata_Kayoko" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="曦" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="Echo" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="画卿颜" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="夏 " />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="jiege45" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="甜食先生" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="虚莫妄玄" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="天恒" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="我有馄饨" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="布布曼" />
|
||||||
|
<TextBlock Width="120" Margin="0,1.5" Text="qwqewe" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="114514" />
|
<TextBlock Width="120" Margin="0,1.5" Text="114514" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Emmanuel" />
|
<TextBlock Width="120" Margin="0,1.5" Text="YJ_42" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="云漫雾影" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Xricron" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="**葵" />
|
<TextBlock Width="120" Margin="0,1.5" Text="抛弃大脑" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="吴同学" />
|
<TextBlock Width="120" Margin="0,1.5" Text="10455885" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Anderson521314" />
|
<TextBlock Width="120" Margin="0,1.5" Text="羽渡白砂" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Alrosa" />
|
<TextBlock Width="120" Margin="0,1.5" Text="沙" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="可爱电鳗" />
|
<TextBlock Width="120" Margin="0,1.5" Text="sukous" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="小野冢小町" />
|
<TextBlock Width="120" Margin="0,1.5" Text="册那" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="田坎村西头王二狗" />
|
<TextBlock Width="120" Margin="0,1.5" Text="KMYLS" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="令月廿一" />
|
<TextBlock Width="120" Margin="0,1.5" Text="kakadeso" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Mrdandan" />
|
<TextBlock Width="120" Margin="0,1.5" Text="懒猫" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="111" />
|
<TextBlock Width="120" Margin="0,1.5" Text="清岚" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="27733" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Atopos" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="韦韦神父" />
|
<TextBlock Width="120" Margin="0,1.5" Text="苦尽柑来" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="土豆" />
|
<TextBlock Width="120" Margin="0,1.5" Text="脑洞大开的血魔" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="隔岸流年" />
|
<TextBlock Width="120" Margin="0,1.5" Text="ももかわるこ" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="冥吻" />
|
<TextBlock Width="120" Margin="0,1.5" Text="空中的风" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="向阳" />
|
<TextBlock Width="120" Margin="0,1.5" Text="黑夜幽灵" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="轻浮" />
|
<TextBlock Width="120" Margin="0,1.5" Text="H1saNe" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="小涵0v0" />
|
<TextBlock Width="120" Margin="0,1.5" Text="故风" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="祈愿小狐" />
|
<TextBlock Width="120" Margin="0,1.5" Text="臭氧化碳" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="爱莉爱莉爱" />
|
<TextBlock Width="120" Margin="0,1.5" Text="云阿云" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Bydold" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="SMRWXH" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="翷月" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="husky" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Hz_yuki" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="先知" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="2683672592" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="龖龖" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="陨树" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Gripen" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="棒槌" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="北北ovo" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="TombName" />
|
|
||||||
<TextBlock Width="240" Margin="0,1.5" Text="莳倾梦のshiqingmeng" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Bortor" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="OuO6006" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="MKSeKai" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="清尘墨雨" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="墨染柊" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="福福" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="夕尽暮染" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="光年摆渡人" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="梦清韩" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="孤城辞典" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="灰" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="小周周" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="孤星痕" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="月孤" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="团团" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="J_ONE" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="初尘ya" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="MooBHise" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="凌之芬芳" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="土豆回锅土豆" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Reisen" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Rong" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="FiZone" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="橡素" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="逆光の思" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Edifier" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="迭风" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="mumu" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="欧润几" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="SiberianHusky" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="虫" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="闪电" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Bob_Marcus" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="瘦瘦爱吃呕吼" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="盛夏" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="飞起来的Mine" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="cc" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="简麟" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="郴州火车迷" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="守白" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="天长地忙" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="月无痕" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="HWW" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="樱岛麻衣" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="桌子" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="bushihuankong" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="戏梦simi" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Metal_Yoshika" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="H+H" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="junhuigege" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Kallen" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="x" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="随便玩" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="魇夜星渊" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="taomiao13579" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="无敌大鱼" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="忆兀安" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="无梦" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="SlyBlackCat" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="180" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="总督大人" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="sc99" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Fumi" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="豪放" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Canqiu" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="朱利安" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="白露辰霜" />
|
|
||||||
<TextBlock Width="240" Margin="0,1.5" Text="点燃心中火的大音乐家" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="度你入魔" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="小宝" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="无" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="青出梦名" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="雾日斋主人" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="鸣纳" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="苏卜辰" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="3827" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="水里游的老鹰" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="雪桜" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Yukiteru" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="零依" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="玻璃糖罐" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="JFF_2005" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="流星" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="ccc" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="PennyLee2023" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="伯劳" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Sy5H" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Fomalhaut" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="PERLICA" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="北冥鱼吃" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="千万别自闭" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="00号玩家" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="亗竹" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="云一梦" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="久念" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="继晷" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="史蒂夫" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="椎罗太难了" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="DiamondSYP" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="木林西" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="雩月" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="6628" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="ZoCc" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="wan_yao" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="White_c" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="尉迟羽晨" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="栀梓" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="小命" />
|
<TextBlock Width="120" Margin="0,1.5" Text="小命" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="金" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="倾墨画君颜" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="南宫若兮" />
|
<TextBlock Width="120" Margin="0,1.5" Text="南宫若兮" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="沐言" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Landsilde" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="傻预备" />
|
<TextBlock Width="120" Margin="0,1.5" Text="zzz" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="蒸木" />
|
<TextBlock Width="120" Margin="0,1.5" Text="星期三" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="那菈" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Ashburn" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="suanqiu" />
|
<TextBlock Width="120" Margin="0,1.5" Text="123" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="人见人爱的熊熊" />
|
<TextBlock Width="120" Margin="0,1.5" Text="九日" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Furan255" />
|
<TextBlock Width="120" Margin="0,1.5" Text="古神" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="MachineCrab" />
|
<TextBlock Width="120" Margin="0,1.5" Text="月宫星耀" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="五只大花狗" />
|
<TextBlock Width="120" Margin="0,1.5" Text="郁子恒是FW" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="威尔特" />
|
<TextBlock Width="240" Margin="0,1.5" Text="每天吃吃吃吃吃不饱" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="StarNCosmos" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Freezhao" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Eason" />
|
<TextBlock Width="120" Margin="0,1.5" Text="ZHypocrite" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="风之幻城" />
|
<TextBlock Width="120" Margin="0,1.5" Text="十下小雨" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="王舒晨" />
|
<TextBlock Width="120" Margin="0,1.5" Text="九 十" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="H" />
|
<TextBlock Width="120" Margin="0,1.5" Text="RuthlessXdream" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="咏夕" />
|
<TextBlock Width="120" Margin="0,1.5" Text="zv-vz" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="不及君子柒" />
|
<TextBlock Width="120" Margin="0,1.5" Text="汐沄的随记" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="GUAN_SKD" />
|
<TextBlock Width="120" Margin="0,1.5" Text="REMOTE" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="雅柏菲卡" />
|
<TextBlock Width="120" Margin="0,1.5" Text="昔阳" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="AtDusk" />
|
<TextBlock Width="120" Margin="0,1.5" Text="七度ユキノ" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="九月想睡觉" />
|
<TextBlock Width="120" Margin="0,1.5" Text="KNISX" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="六七" />
|
<TextBlock Width="120" Margin="0,1.5" Text="RainbowDashRD" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="老登" />
|
<TextBlock Width="120" Margin="0,1.5" Text="夢曦" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="wd_xuan" />
|
<TextBlock Width="120" Margin="0,1.5" Text="跳雨风" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Wake" />
|
<TextBlock Width="120" Margin="0,1.5" Text="望言苏" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Jannik" />
|
<TextBlock Width="120" Margin="0,1.5" Text="四分白Fortenz" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="cybone" />
|
<TextBlock Width="120" Margin="0,1.5" Text="UUZ" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="mc12345zhl123" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Ankairis" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="解" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Jn1E" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Akights" />
|
<TextBlock Width="120" Margin="0,1.5" Text="云山如昨好" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="秋刀驴" />
|
<TextBlock Width="120" Margin="0,1.5" Text="LYJ0415" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="樟涛竹" />
|
<TextBlock Width="120" Margin="0,1.5" Text="空?" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="sikuno" />
|
<TextBlock Width="120" Margin="0,1.5" Text="Awfrlu+" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="鬼目" />
|
<TextBlock Width="120" Margin="0,1.5" Text="懒帝" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="拜拜白" />
|
<TextBlock Width="120" Margin="0,1.5" Text="北安丶七叔" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="绮铃kirin" />
|
<TextBlock Width="120" Margin="0,1.5" Text="xkw" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="洛逍遥" />
|
<TextBlock Width="120" Margin="0,1.5" Text="KINO" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="文文新闻" />
|
<TextBlock Width="120" Margin="0,1.5" Text="POTATO" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="GM" />
|
<TextBlock Width="120" Margin="0,1.5" Text="少昊氏" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="小咪" />
|
<TextBlock Width="240" Margin="0,1.5" Text="狂踹瘸子那條好腿丶" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Fuxi Fuji" />
|
<TextBlock Width="240" Margin="0,1.5" Text="Thallium_Ash【铊尘】(坨坨)" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="?独爱蝉HIA" />
|
<TextBlock Width="120" Margin="0,1.5" Text="陌雨泠涯" />
|
||||||
<TextBlock Width="240" Margin="0,1.5" Text="没有咖啡的猫屎咖啡" />
|
<TextBlock Width="120" Margin="0,1.5" Text="bajie79" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="雪风保佑我" />
|
<TextBlock Width="120" Margin="0,1.5" Text="紘垰" />
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="zhnj" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="火苟" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="梦尽" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="阿泽free" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="阿乐" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="米线" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="依凡" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="涟燃556" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="夏季" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Game_ReAi" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="秦屎皇" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="6" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Zik yeung" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="awawa" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="智慧村村长" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="海中燕" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="就叫我好人吧" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="梦的回响" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="。。" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="墨子吉安" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="有风" />
|
|
||||||
<TextBlock Width="240" Margin="0,1.5" Text="孙嘉昊まごかひろし" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="C" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Haio" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="陆光" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="chuveiro" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="无名氏34613" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="mr_kevin_x" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="来早点" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="烤肉真香" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Chr0n0s" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="七" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="H?O" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="瑞霖RLD" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="AAcfun" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="鼬嘁" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="名为冉冉的猫" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="hduqggd55379" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="唠叨的土豆" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Lonely_Grey" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="Vergilio" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="このdioた" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="没睡醒的肉啊" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="铃鸢" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="lvke" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="V-Merlin" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="美式加冰?" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="半岛弥音" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="clclFL" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="事与愿违" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="SamXU1322" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="OCEANI" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="shenpli" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="咸鱼嫌鱼咸" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="kirsnow" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="白庶" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="pengyihang" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="憨憨剑踏" />
|
|
||||||
<TextBlock Width="120" Margin="0,1.5" Text="SinceCN" />
|
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<Grid Height="35">
|
<Grid Height="35">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -377,11 +359,13 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="法律信息" IsSwaped="True" CanSwap="True">
|
<local:MyCard Margin="0,0,0,15" Title="法律信息" IsSwapped="True" CanSwap="True">
|
||||||
<StackPanel Margin="25,39,23,20">
|
<StackPanel Margin="25,39,23,20">
|
||||||
<TextBlock Text="隐私说明" TextWrapping="Wrap" Margin="0,6,0,4" FontWeight="Bold" />
|
<TextBlock Text="匿名数据收集" TextWrapping="Wrap" Margin="0,6,0,4" FontWeight="Bold" />
|
||||||
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="本软件的 User Agent 中包含启动器的版本号,以统计各版本的用户数量。 除此之外,本软件不会向开发者上传任何其他信息。" TextWrapping="Wrap" />
|
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="当下载失败、PCL 出错、游戏崩溃等事件时,PCL 会匿名上报信息,以通知龙猫 “哦吼,出错了”,让龙猫能更好地修 Bug……(PCL 不会上传或收集任何个人信息,包括上报的东西里面也没有!)
你可以在 设置 → 其他 → 启动器 中关闭上报,不过龙猫就不知道你遇到了什么 Bug 了……" TextWrapping="Wrap" />
|
||||||
<TextBlock Text="其他信息" TextWrapping="Wrap" Margin="0,12,0,4" FontWeight="Bold" />
|
<TextBlock Text="隐私声明与个人信息保护政策" TextWrapping="Wrap" Margin="0,10,0,4" FontWeight="Bold" />
|
||||||
|
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="PCL 没有收集个人信息,所以这里其实啥都不用写……
留个这个其实只是为了让你知道 PCL 没有收集个人信息,诶嘿。" TextWrapping="Wrap" />
|
||||||
|
<TextBlock Text="其他信息" TextWrapping="Wrap" Margin="0,10,0,4" FontWeight="Bold" />
|
||||||
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="Copyright © 龙腾猫跃 2016. All Rights Reserved. 计算机软件著作权登记号:2020SR0875133 违法违规行为举报投诉邮箱:hexdragon@vip.qq.com 非 MINECRAFT 官方产品。未经 MOJANG 或 MICROSOFT 批准,也不与 MOJANG 或 MICROSOFT 关联。" TextWrapping="Wrap" />
|
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="Copyright © 龙腾猫跃 2016. All Rights Reserved. 计算机软件著作权登记号:2020SR0875133 违法违规行为举报投诉邮箱:hexdragon@vip.qq.com 非 MINECRAFT 官方产品。未经 MOJANG 或 MICROSOFT 批准,也不与 MOJANG 或 MICROSOFT 关联。" TextWrapping="Wrap" />
|
||||||
<StackPanel Orientation="Horizontal" Height="35" HorizontalAlignment="Left" Margin="0,12,0,0">
|
<StackPanel Orientation="Horizontal" Height="35" HorizontalAlignment="Left" Margin="0,12,0,0">
|
||||||
<local:MyButton Text="用户协议与免责声明" Width="170" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight" EventType="打开网页" EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW" />
|
<local:MyButton Text="用户协议与免责声明" Width="170" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight" EventType="打开网页" EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW" />
|
||||||
@@ -389,7 +373,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="许可与版权声明" IsSwaped="True" CanSwap="True">
|
<local:MyCard Margin="0,0,0,15" Title="许可与版权声明" IsSwapped="True" CanSwap="True">
|
||||||
<Grid Margin="25,42,23,4">
|
<Grid Margin="25,42,23,4">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
|
|||||||
@@ -18,12 +18,6 @@
|
|||||||
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Sub BtnAboutBmclapi_Click(sender As Object, e As EventArgs) Handles BtnAboutBmclapi.Click
|
|
||||||
OpenWebsite("https://afdian.com/a/bangbang93")
|
|
||||||
End Sub
|
|
||||||
Private Sub BtnAboutWiki_Click(sender As Object, e As EventArgs) Handles BtnAboutWiki.Click
|
|
||||||
OpenWebsite("https://www.mcmod.cn")
|
|
||||||
End Sub
|
|
||||||
Public Shared Sub CopyUniqueAddress() Handles BtnDonateCopy.Click
|
Public Shared Sub CopyUniqueAddress() Handles BtnDonateCopy.Click
|
||||||
ClipboardSet(UniqueAddress)
|
ClipboardSet(UniqueAddress)
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
If Type = "指南" Then
|
If Type = "指南" Then
|
||||||
MyCard.StackInstall(NewStack, 11, "指南")
|
MyCard.StackInstall(NewStack, 11, "指南")
|
||||||
Else
|
Else
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
End If
|
End If
|
||||||
PanList.Children.Add(NewCard)
|
PanList.Children.Add(NewCard)
|
||||||
Next
|
Next
|
||||||
|
|||||||
@@ -137,7 +137,7 @@
|
|||||||
Case 1
|
Case 1
|
||||||
Feedback(True, False)
|
Feedback(True, False)
|
||||||
Case 2
|
Case 2
|
||||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/issues/")
|
OpenWebsite("https://github.com/Meloong-Git/PCL/issues/")
|
||||||
End Select
|
End Select
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub TryVote(sender As Object, e As RouteEventArgs) Handles ItemVote.Changed
|
Private Sub TryVote(sender As Object, e As RouteEventArgs) Handles ItemVote.Changed
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
Public Shared Sub TryVote()
|
Public Shared Sub TryVote()
|
||||||
If MyMsgBox("是否要打开新功能投票网页?" & vbCrLf & "如果无法打开该网页,请使用 VPN 以改善网络环境。",
|
If MyMsgBox("是否要打开新功能投票网页?" & vbCrLf & "如果无法打开该网页,请使用 VPN 以改善网络环境。",
|
||||||
"新功能投票", "打开", "取消") = 2 Then Return
|
"新功能投票", "打开", "取消") = 2 Then Return
|
||||||
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")
|
OpenWebsite("https://github.com/Meloong-Git/PCL/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8?discussions_q=category%3A%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8+sort%3Adate_created")
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -317,6 +317,9 @@
|
|||||||
Public Sub Delete_Click(sender As Object, e As RoutedEventArgs)
|
Public Sub Delete_Click(sender As Object, e As RoutedEventArgs)
|
||||||
Dim Folder As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
Dim Folder As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||||
Dim DeleteText As String = If((Folder.Type = McFolderType.Original OrElse Folder.Type = McFolderType.RenamedOriginal) AndAlso Folder.Path = Path & ".minecraft\" AndAlso McFolderList.Count = 1, "清空", "删除")
|
Dim DeleteText As String = If((Folder.Type = McFolderType.Original OrElse Folder.Type = McFolderType.RenamedOriginal) AndAlso Folder.Path = Path & ".minecraft\" AndAlso McFolderList.Count = 1, "清空", "删除")
|
||||||
|
If Folder.Path.EndsWith(":\") OrElse Folder.Path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) & "\" OrElse Folder.Path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) & "\" Then '#7030
|
||||||
|
If MyMsgBox("将要删除的游戏文件夹是系统关键目录(" & Folder.Path & "),确定要删除吗?", "删除警告", "取消", "确认", "取消", IsWarn:=True) <> 2 Then Return
|
||||||
|
End If
|
||||||
If MyMsgBox("你确定要" & DeleteText & "这个文件夹吗?" & vbCrLf & "目标文件夹:" & Folder.Path & vbCrLf & vbCrLf & "这会导致该文件夹中的所有存档与其他文件永久丢失,且不可恢复!", "删除警告", "取消", "确认", "取消") <> 2 Then Return
|
If MyMsgBox("你确定要" & DeleteText & "这个文件夹吗?" & vbCrLf & "目标文件夹:" & Folder.Path & vbCrLf & vbCrLf & "这会导致该文件夹中的所有存档与其他文件永久丢失,且不可恢复!", "删除警告", "取消", "确认", "取消") <> 2 Then Return
|
||||||
If MyMsgBox("如果你在该文件夹中存放了除 MC 以外的其他文件,这些文件也会被一同删除!" & vbCrLf & "继续删除会导致该文件夹中的所有文件永久丢失,请在仔细确认后再继续!" & vbCrLf & "目标文件夹:" & Folder.Path & vbCrLf & vbCrLf & "这是最后一次警告!", "删除警告", "确认" & DeleteText, "取消", IsWarn:=True) <> 1 Then Return
|
If MyMsgBox("如果你在该文件夹中存放了除 MC 以外的其他文件,这些文件也会被一同删除!" & vbCrLf & "继续删除会导致该文件夹中的所有文件永久丢失,请在仔细确认后再继续!" & vbCrLf & "目标文件夹:" & Folder.Path & vbCrLf & vbCrLf & "这是最后一次警告!", "删除警告", "确认" & DeleteText, "取消", IsWarn:=True) <> 1 Then Return
|
||||||
'移出列表
|
'移出列表
|
||||||
|
|||||||
@@ -81,15 +81,15 @@
|
|||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
'确定卡片是否展开
|
'确定卡片是否展开
|
||||||
If Card.Key = McVersionCardType.Rubbish OrElse Card.Key = McVersionCardType.Error OrElse Card.Key = McVersionCardType.Fool Then
|
If Card.Key = McVersionCardType.Rubbish OrElse Card.Key = McVersionCardType.Error OrElse Card.Key = McVersionCardType.Fool Then
|
||||||
NewCard.IsSwaped = True
|
NewCard.IsSwapped = True
|
||||||
Else
|
Else
|
||||||
MyCard.StackInstall(NewStack, 0, CardTitle)
|
MyCard.StackInstall(NewStack, 0, CardTitle)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
|
|
||||||
'若只有一个卡片,则强制展开
|
'若只有一个卡片,则强制展开
|
||||||
If PanMain.Children.Count = 1 AndAlso CType(PanMain.Children(0), MyCard).IsSwaped Then
|
If PanMain.Children.Count = 1 AndAlso CType(PanMain.Children(0), MyCard).IsSwapped Then
|
||||||
CType(PanMain.Children(0), MyCard).IsSwaped = False
|
CType(PanMain.Children(0), MyCard).IsSwapped = False
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'判断应该显示哪一个页面
|
'判断应该显示哪一个页面
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
DeleteDirectory(Version.Path)
|
DeleteDirectory(Version.Path)
|
||||||
Hint("版本 " & Version.Name & " 已永久删除!", HintType.Finish)
|
Hint("版本 " & Version.Name & " 已永久删除!", HintType.Finish)
|
||||||
Else
|
Else
|
||||||
FileIO.FileSystem.DeleteDirectory(Version.Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
FileIO.FileSystem.DeleteDirectory(Version.Path, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||||
Hint("版本 " & Version.Name & " 已删除到回收站!", HintType.Finish)
|
Hint("版本 " & Version.Name & " 已删除到回收站!", HintType.Finish)
|
||||||
End If
|
End If
|
||||||
Case 2
|
Case 2
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
{"HintDownloadThread", New SetupEntry(False, Source:=SetupSource.Registry)},
|
{"HintDownloadThread", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||||
{"HintNotice", New SetupEntry(0, Source:=SetupSource.Registry)},
|
{"HintNotice", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||||
{"HintDownload", New SetupEntry(0, Source:=SetupSource.Registry)},
|
{"HintDownload", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||||
{"HintInstallBack", New SetupEntry(False, Source:=SetupSource.Registry)},
|
|
||||||
{"HintHide", New SetupEntry(False, Source:=SetupSource.Registry)},
|
{"HintHide", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||||
{"HintHandInstall", New SetupEntry(False, Source:=SetupSource.Registry)},
|
{"HintHandInstall", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||||
{"HintBuy", New SetupEntry(False, Source:=SetupSource.Registry)},
|
{"HintBuy", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||||
@@ -42,6 +41,7 @@
|
|||||||
{"SystemSystemCache", New SetupEntry("", Source:=SetupSource.Registry)},
|
{"SystemSystemCache", New SetupEntry("", Source:=SetupSource.Registry)},
|
||||||
{"SystemSystemUpdate", New SetupEntry(0)},
|
{"SystemSystemUpdate", New SetupEntry(0)},
|
||||||
{"SystemSystemActivity", New SetupEntry(0)},
|
{"SystemSystemActivity", New SetupEntry(0)},
|
||||||
|
{"SystemSystemTelemetry", New SetupEntry(True, Source:=SetupSource.Registry)},
|
||||||
{"CacheExportConfig", New SetupEntry("", Source:=SetupSource.Registry)},
|
{"CacheExportConfig", New SetupEntry("", Source:=SetupSource.Registry)},
|
||||||
{"CacheSavedPageUrl", New SetupEntry("", Source:=SetupSource.Registry)},
|
{"CacheSavedPageUrl", New SetupEntry("", Source:=SetupSource.Registry)},
|
||||||
{"CacheSavedPageVersion", New SetupEntry("", Source:=SetupSource.Registry)},
|
{"CacheSavedPageVersion", New SetupEntry("", Source:=SetupSource.Registry)},
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
{"ToolDownloadTranslateV2", New SetupEntry(1, Source:=SetupSource.Registry)},
|
{"ToolDownloadTranslateV2", New SetupEntry(1, Source:=SetupSource.Registry)},
|
||||||
{"ToolDownloadIgnoreQuilt", New SetupEntry(True, Source:=SetupSource.Registry)},
|
{"ToolDownloadIgnoreQuilt", New SetupEntry(True, Source:=SetupSource.Registry)},
|
||||||
{"ToolDownloadCert", New SetupEntry(False, Source:=SetupSource.Registry)},
|
{"ToolDownloadCert", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||||
{"ToolDownloadMod", New SetupEntry(1, Source:=SetupSource.Registry)},
|
{"ToolDownloadMod", New SetupEntry(2, Source:=SetupSource.Registry)},
|
||||||
{"ToolModLocalNameStyle", New SetupEntry(0, Source:=SetupSource.Registry)},
|
{"ToolModLocalNameStyle", New SetupEntry(0, Source:=SetupSource.Registry)},
|
||||||
{"ToolUpdateAlpha", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
|
{"ToolUpdateAlpha", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
|
||||||
{"ToolUpdateRelease", New SetupEntry(False, Source:=SetupSource.Registry)},
|
{"ToolUpdateRelease", New SetupEntry(False, Source:=SetupSource.Registry)},
|
||||||
@@ -181,6 +181,7 @@
|
|||||||
{"VersionAdvanceRun", New SetupEntry("", Source:=SetupSource.Version)},
|
{"VersionAdvanceRun", New SetupEntry("", Source:=SetupSource.Version)},
|
||||||
{"VersionAdvanceRunWait", New SetupEntry(True, Source:=SetupSource.Version)},
|
{"VersionAdvanceRunWait", New SetupEntry(True, Source:=SetupSource.Version)},
|
||||||
{"VersionAdvanceDisableJLW", New SetupEntry(False, Source:=SetupSource.Version)},
|
{"VersionAdvanceDisableJLW", New SetupEntry(False, Source:=SetupSource.Version)},
|
||||||
|
{"VersionAdvanceDisableModUpdate", New SetupEntry(False, Source:=SetupSource.Version)},
|
||||||
{"VersionRamType", New SetupEntry(2, Source:=SetupSource.Version)},
|
{"VersionRamType", New SetupEntry(2, Source:=SetupSource.Version)},
|
||||||
{"VersionRamCustom", New SetupEntry(15, Source:=SetupSource.Version)},
|
{"VersionRamCustom", New SetupEntry(15, Source:=SetupSource.Version)},
|
||||||
{"VersionRamOptimize", New SetupEntry(0, Source:=SetupSource.Version)},
|
{"VersionRamOptimize", New SetupEntry(0, Source:=SetupSource.Version)},
|
||||||
@@ -610,7 +611,7 @@
|
|||||||
FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
|
FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
|
||||||
FrmSetupUI.HintCustom.Text = $"从指定网址联网获取主页内容。服主也可以用于动态更新服务器公告。{vbCrLf}如果你制作了稳定运行的联网主页,可以点击这条提示投稿,若合格即可加入预设!"
|
FrmSetupUI.HintCustom.Text = $"从指定网址联网获取主页内容。服主也可以用于动态更新服务器公告。{vbCrLf}如果你制作了稳定运行的联网主页,可以点击这条提示投稿,若合格即可加入预设!"
|
||||||
FrmSetupUI.HintCustom.EventType = "打开网页"
|
FrmSetupUI.HintCustom.EventType = "打开网页"
|
||||||
FrmSetupUI.HintCustom.EventData = "https://github.com/Hex-Dragon/PCL2/discussions/2528"
|
FrmSetupUI.HintCustom.EventData = "https://github.com/Meloong-Git/PCL/discussions/2528"
|
||||||
Case 3 '预设
|
Case 3 '预设
|
||||||
FrmSetupUI.PanCustomPreset.Visibility = Visibility.Visible
|
FrmSetupUI.PanCustomPreset.Visibility = Visibility.Visible
|
||||||
FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
|
FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
|
||||||
|
|||||||
@@ -171,7 +171,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard x:Name="CardSkin" Margin="0,0,0,15" Title="离线皮肤" CanSwap="True" IsSwaped="True">
|
<local:MyCard x:Name="CardSkin" Margin="0,0,0,15" Title="离线皮肤" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,25,15">
|
<StackPanel Margin="25,40,25,15">
|
||||||
<local:MyHint Text="由于技术问题,此功能只保证对 1.19.2 以前的版本有效!" Theme="Yellow" Margin="0,0,0,10" />
|
<local:MyHint Text="由于技术问题,此功能只保证对 1.19.2 以前的版本有效!" Theme="Yellow" Margin="0,0,0,10" />
|
||||||
<Grid Margin="-1,0,0,0">
|
<Grid Margin="-1,0,0,0">
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<local:MyButton x:Name="BtnSkinSave" Text="保存皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Row="1" />
|
<local:MyButton x:Name="BtnSkinSave" Text="保存皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Row="1" />
|
||||||
<local:MyButton x:Name="BtnSkinCache" Text="刷新缓存" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新并重新下载 PCL 当前显示的皮肤" Grid.Row="1" Grid.Column="1" />
|
<local:MyButton x:Name="BtnSkinCache" Text="刷新" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新并重新下载 PCL 当前显示的皮肤" Grid.Row="1" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="PanSkinChange" Margin="0,14,0,2" Height="35" Visibility="Collapsed">
|
<Grid x:Name="PanSkinChange" Margin="0,14,0,2" Height="35" Visibility="Collapsed">
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="高级启动选项" IsSwaped="True" CanSwap="True">
|
<local:MyCard Margin="0,0,0,15" Title="高级启动选项" IsSwapped="True" CanSwap="True">
|
||||||
<Grid Margin="25,40,25,15">
|
<Grid Margin="25,40,25,15">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
@@ -235,15 +235,15 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<StackPanel VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,25,0">
|
<StackPanel VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,25,0">
|
||||||
<TextBlock Text="JVM 参数头部" VerticalAlignment="Center" />
|
<TextBlock Text="Java 虚拟机参数" VerticalAlignment="Center" />
|
||||||
<local:MyIconButton Height="23" Margin="0,1,0,0" x:Name="BtnAdvanceJvmReset" VerticalAlignment="Center"
|
<local:MyIconButton Height="23" Margin="0,1,0,0" x:Name="BtnAdvanceJvmReset" VerticalAlignment="Center"
|
||||||
ToolTip="还原" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1"
|
ToolTip="还原" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1"
|
||||||
Logo="M530 0c287 0 521 229 521 511s-233 511-521 511c-233 0-436-151-500-368a63 63 0 0 1 44-79 65 65 0 0 1 80 43c48 162 200 276 375 276 215 0 390-171 390-383s-174-383-390-383c-103 0-199 39-270 106l21-5a63 63 0 0 1 33 123l-157 42a65 65 0 0 1-90-42l-49-183a65 65 0 1 1 126-33l6 26A524 524 0 0 1 530 0z" LogoScale="0.9" />
|
Logo="M530 0c287 0 521 229 521 511s-233 511-521 511c-233 0-436-151-500-368a63 63 0 0 1 44-79 65 65 0 0 1 80 43c48 162 200 276 375 276 215 0 390-171 390-383s-174-383-390-383c-103 0-199 39-270 106l21-5a63 63 0 0 1 33 123l-157 42a65 65 0 0 1-90-42l-49-183a65 65 0 1 1 126-33l6 26A524 524 0 0 1 530 0z" LogoScale="0.9" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.ColumnSpan="2" Tag="LaunchAdvanceJvm" Grid.Column="1" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,除非有确定把握,否则请不要修改" MaxLength="4000"
|
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.ColumnSpan="2" Tag="LaunchAdvanceJvm" Grid.Column="1" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,除非有确定把握,否则请不要修改。
支持 Minecraft 版本 JSON 中的字符串替换标记,例如 ${library_directory}。" MaxLength="4000"
|
||||||
Height="100" AcceptsReturn="True" TextWrapping="Wrap" VerticalContentAlignment="Top" Padding="0,5" VerticalScrollBarVisibility="Auto" />
|
Height="100" AcceptsReturn="True" TextWrapping="Wrap" VerticalContentAlignment="Top" Padding="0,5" VerticalScrollBarVisibility="Auto" />
|
||||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="游戏参数尾部" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="游戏参数" Margin="0,0,25,0" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="LaunchAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。" />
|
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="LaunchAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如,输入 --demo 则会以试玩模式启动游戏。
支持 Minecraft 版本 JSON 中的字符串替换标记,例如 ${library_directory}。" />
|
||||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动前执行命令" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动前执行命令" Margin="0,0,25,0" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceRun" Grid.Row="4" Grid.ColumnSpan="2" Tag="LaunchAdvanceRun" Grid.Column="1" HintText=""
|
<local:MyTextBox x:Name="TextAdvanceRun" Grid.Row="4" Grid.ColumnSpan="2" Tag="LaunchAdvanceRun" Grid.Column="1" HintText=""
|
||||||
ToolTip="在 MC 启动前执行特定命令或程序,语法与 Windows 的命令提示符一致。

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

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

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

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

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

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

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

涉及路径的操作最好都打上双引号,以避免路径中的空格导致运行失败。
执行命令时,命令行所在的目录是当前的 .minecraft 文件夹。" />
|
||||||
|
|||||||
@@ -62,16 +62,18 @@
|
|||||||
<RowDefinition Height="7" />
|
<RowDefinition Height="7" />
|
||||||
<RowDefinition Height="28" />
|
<RowDefinition Height="28" />
|
||||||
<RowDefinition Height="7" />
|
<RowDefinition Height="7" />
|
||||||
|
<RowDefinition Height="28" />
|
||||||
|
<RowDefinition Height="7" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<!--<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="下载源" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="来源" Margin="0,0,25,0" />
|
||||||
<local:MyComboBox x:Name="ComboDownloadMod" Grid.Row="0" Grid.ColumnSpan="2" Tag="ToolDownloadMod" Grid.Column="1">
|
<local:MyComboBox x:Name="ComboDownloadMod" Grid.Row="0" Grid.ColumnSpan="2" Tag="ToolDownloadMod" Grid.Column="1">
|
||||||
<local:MyComboBoxItem Content="尽量使用镜像源(暂时无效)" />
|
<local:MyComboBoxItem Content="尽量使用镜像源(可能缺少刚刚更新的版本)" />
|
||||||
<local:MyComboBoxItem Content="仅在官方源加载缓慢时改用镜像源" />
|
<local:MyComboBoxItem Content="仅在官方源加载缓慢时改用镜像源" />
|
||||||
<local:MyComboBoxItem Content="尽量使用官方源" IsSelected="True" />
|
<local:MyComboBoxItem Content="尽量使用官方源" IsSelected="True" />
|
||||||
</local:MyComboBox>-->
|
</local:MyComboBox>
|
||||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="文件名格式" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="文件名格式" Margin="0,0,25,0" />
|
||||||
<local:MyComboBox Grid.Row="0" x:Name="ComboDownloadTranslateV2" Grid.ColumnSpan="2" Tag="ToolDownloadTranslateV2" Grid.Column="1"
|
<local:MyComboBox Grid.Row="2" x:Name="ComboDownloadTranslateV2" Grid.ColumnSpan="2" Tag="ToolDownloadTranslateV2" Grid.Column="1"
|
||||||
ToolTip="下载社区资源时,其默认文件名的格式">
|
ToolTip="下载社区资源时,其默认文件名的格式">
|
||||||
<local:MyComboBoxItem Content="【机械动力】create-1.21.1-6.0.4" />
|
<local:MyComboBoxItem Content="【机械动力】create-1.21.1-6.0.4" />
|
||||||
<local:MyComboBoxItem Content="[机械动力] create-1.21.1-6.0.4" IsSelected="True" />
|
<local:MyComboBoxItem Content="[机械动力] create-1.21.1-6.0.4" IsSelected="True" />
|
||||||
@@ -79,13 +81,13 @@
|
|||||||
<local:MyComboBoxItem Content="create-1.21.1-6.0.4-机械动力" />
|
<local:MyComboBoxItem Content="create-1.21.1-6.0.4-机械动力" />
|
||||||
<local:MyComboBoxItem Content="create-1.21.1-6.0.4" />
|
<local:MyComboBoxItem Content="create-1.21.1-6.0.4" />
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Mod 管理样式" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Mod 管理样式" Margin="0,0,25,0" />
|
||||||
<local:MyComboBox Grid.Row="2" x:Name="ComboModLocalNameStyle" Grid.ColumnSpan="2" Tag="ToolModLocalNameStyle" Grid.Column="1"
|
<local:MyComboBox Grid.Row="4" x:Name="ComboModLocalNameStyle" Grid.ColumnSpan="2" Tag="ToolModLocalNameStyle" Grid.Column="1"
|
||||||
ToolTip="在 Mod 管理页面中,Mod 项的显示方式">
|
ToolTip="在 Mod 管理页面中,Mod 项的显示方式">
|
||||||
<local:MyComboBoxItem Content="标题显示译名,详情显示文件名" IsSelected="True" />
|
<local:MyComboBoxItem Content="标题显示译名,详情显示文件名" IsSelected="True" />
|
||||||
<local:MyComboBoxItem Content="标题显示文件名,详情显示译名" />
|
<local:MyComboBoxItem Content="标题显示文件名,详情显示译名" />
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
<local:MyCheckBox Margin="0,2,0,4" Text="在显示 Mod 加载器时忽略 Quilt" Grid.Row="4" Height="22" Grid.ColumnSpan="2"
|
<local:MyCheckBox Margin="0,2,0,4" Text="在显示 Mod 加载器时忽略 Quilt" Grid.Row="6" Height="22" Grid.ColumnSpan="2"
|
||||||
x:Name="CheckDownloadIgnoreQuilt" Tag="ToolDownloadIgnoreQuilt" />
|
x:Name="CheckDownloadIgnoreQuilt" Tag="ToolDownloadIgnoreQuilt" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@@ -109,7 +111,7 @@
|
|||||||
<local:MyCheckBox Text="自动设置为中文" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="5" x:Name="CheckHelpChinese" Tag="ToolHelpChinese" />
|
<local:MyCheckBox Text="自动设置为中文" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="5" x:Name="CheckHelpChinese" Tag="ToolHelpChinese" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="系统">
|
<local:MyCard Margin="0,0,0,15" Title="启动器">
|
||||||
<Grid Margin="25,40,25,20">
|
<Grid Margin="25,40,25,20">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||||
@@ -124,6 +126,7 @@
|
|||||||
<RowDefinition Height="5" />
|
<RowDefinition Height="5" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动器更新" Margin="0,0,25,0" />
|
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动器更新" Margin="0,0,25,0" />
|
||||||
<local:MyComboBox x:Name="ComboSystemUpdate" Tag="SystemSystemUpdate" Grid.Column="1">
|
<local:MyComboBox x:Name="ComboSystemUpdate" Tag="SystemSystemUpdate" Grid.Column="1">
|
||||||
@@ -145,7 +148,10 @@
|
|||||||
<local:ValidateFolderPath UseMinecraftCharCheck="False" />
|
<local:ValidateFolderPath UseMinecraftCharCheck="False" />
|
||||||
</local:MyTextBox.ValidateRules>
|
</local:MyTextBox.ValidateRules>
|
||||||
</local:MyTextBox>
|
</local:MyTextBox>
|
||||||
<Grid Height="35" Grid.Row="6" Grid.ColumnSpan="5" Margin="0,12,0,0">
|
<local:MyCheckBox Margin="0,5,0,4" Text="匿名数据收集" Grid.Row="6" Height="22" Grid.ColumnSpan="2"
|
||||||
|
x:Name="CheckSystemTelemetry" Tag="SystemSystemTelemetry"
|
||||||
|
ToolTip="当下载失败、PCL 出错、游戏崩溃等事件时,PCL 会匿名上报情况,以通知龙猫 “哦吼,出错了”,让龙猫能更好地修 Bug……
你可以关闭上报,不过龙猫就不知道你遇到了什么 Bug 了…… PCL 不会上传或收集任何个人信息,包括上报的东西里面也没有!" />
|
||||||
|
<Grid Height="35" Grid.Row="7" Grid.ColumnSpan="5" Margin="0,12,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||||
@@ -155,7 +161,7 @@
|
|||||||
<local:MyButton Grid.Column="1" x:Name="BtnSystemSettingExp" MinWidth="140" Text="导出设置" Padding="13,0" Margin="0,0,20,0" />
|
<local:MyButton Grid.Column="1" x:Name="BtnSystemSettingExp" MinWidth="140" Text="导出设置" Padding="13,0" Margin="0,0,20,0" />
|
||||||
<local:MyButton Grid.Column="2" x:Name="BtnSystemSettingImp" MinWidth="140" Text="导入设置" Padding="13,0" Margin="0,0,20,0" />
|
<local:MyButton Grid.Column="2" x:Name="BtnSystemSettingImp" MinWidth="140" Text="导入设置" Padding="13,0" Margin="0,0,20,0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Height="35" Grid.Row="7" Grid.ColumnSpan="5" Margin="0,12,0,0" x:Name="PanDonate">
|
<Grid Height="35" Grid.Row="8" Grid.ColumnSpan="5" Margin="0,12,0,0" x:Name="PanDonate">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||||
@@ -182,7 +188,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard> -->
|
</local:MyCard> -->
|
||||||
<local:MyCard x:Name="CardDebug" Margin="0,0,0,15" Title="调试选项" CanSwap="True" IsSwaped="True">
|
<local:MyCard x:Name="CardDebug" Margin="0,0,0,15" Title="调试选项" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,25,15">
|
<StackPanel Margin="25,40,25,15">
|
||||||
<Grid x:Name="PanDebugAnim" Height="22" Margin="0,0,0,10">
|
<Grid x:Name="PanDebugAnim" Height="22" Margin="0,0,0,10">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -198,7 +204,7 @@
|
|||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<local:MyCheckBox Grid.Column="0" Text="禁止在下载时复制已存在的文件" Height="22" x:Name="CheckDebugSkipCopy" Tag="SystemDebugSkipCopy" ToolTip="在下载时不直接复制已经存在的文件,而是重新下载每个文件。
只建议在测试下载速度时开启。" />
|
<local:MyCheckBox Grid.Column="0" Text="禁止在下载时从其他文件夹复制文件" Height="22" x:Name="CheckDebugSkipCopy" Tag="SystemDebugSkipCopy" ToolTip="在下载时不直接复制其他 MC 文件夹中已经存在的相同文件,而是重新下载文件。
只建议在测试下载速度时开启。" />
|
||||||
<local:MyCheckBox Grid.Column="1" Text="调试模式" Height="22" x:Name="CheckDebugMode" Tag="SystemDebugMode" ToolTip="显示调试信息与更多错误信息。
这会导致启动器性能略有下降,若无特殊需要不建议开启。" />
|
<local:MyCheckBox Grid.Column="1" Text="调试模式" Height="22" x:Name="CheckDebugMode" Tag="SystemDebugMode" ToolTip="显示调试信息与更多错误信息。
这会导致启动器性能略有下降,若无特殊需要不建议开启。" />
|
||||||
<local:MyCheckBox Grid.Column="2" Text="添加延迟" Height="22" x:Name="CheckDebugDelay" Tag="SystemDebugDelay" ToolTip="在各个环节添加随机的延迟,拖慢加载速度,以测试部分功能是否正常运行。
这会严重影响启动器运行,若无特殊需要不建议开启。" />
|
<local:MyCheckBox Grid.Column="2" Text="添加延迟" Height="22" x:Name="CheckDebugDelay" Tag="SystemDebugDelay" ToolTip="在各个环节添加随机的延迟,拖慢加载速度,以测试部分功能是否正常运行。
这会严重影响启动器运行,若无特殊需要不建议开启。" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
'Mod 与整合包
|
'Mod 与整合包
|
||||||
ComboDownloadTranslateV2.SelectedIndex = Setup.Get("ToolDownloadTranslateV2")
|
ComboDownloadTranslateV2.SelectedIndex = Setup.Get("ToolDownloadTranslateV2")
|
||||||
'ComboDownloadMod.SelectedIndex = Setup.Get("ToolDownloadMod")
|
ComboDownloadMod.SelectedIndex = Setup.Get("ToolDownloadMod")
|
||||||
ComboModLocalNameStyle.SelectedIndex = Setup.Get("ToolModLocalNameStyle")
|
ComboModLocalNameStyle.SelectedIndex = Setup.Get("ToolModLocalNameStyle")
|
||||||
CheckDownloadIgnoreQuilt.Checked = Setup.Get("ToolDownloadIgnoreQuilt")
|
CheckDownloadIgnoreQuilt.Checked = Setup.Get("ToolDownloadIgnoreQuilt")
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
ComboSystemUpdate.SelectedIndex = Setup.Get("SystemSystemUpdate")
|
ComboSystemUpdate.SelectedIndex = Setup.Get("SystemSystemUpdate")
|
||||||
ComboSystemActivity.SelectedIndex = Setup.Get("SystemSystemActivity")
|
ComboSystemActivity.SelectedIndex = Setup.Get("SystemSystemActivity")
|
||||||
TextSystemCache.Text = Setup.Get("SystemSystemCache")
|
TextSystemCache.Text = Setup.Get("SystemSystemCache")
|
||||||
|
CheckSystemTelemetry.Checked = Setup.Get("SystemSystemTelemetry")
|
||||||
|
|
||||||
'调试选项
|
'调试选项
|
||||||
CheckDebugMode.Checked = Setup.Get("SystemDebugMode")
|
CheckDebugMode.Checked = Setup.Get("SystemDebugMode")
|
||||||
@@ -81,6 +82,7 @@
|
|||||||
Setup.Reset("SystemSystemCache")
|
Setup.Reset("SystemSystemCache")
|
||||||
Setup.Reset("SystemSystemUpdate")
|
Setup.Reset("SystemSystemUpdate")
|
||||||
Setup.Reset("SystemSystemActivity")
|
Setup.Reset("SystemSystemActivity")
|
||||||
|
Setup.Reset("SystemSystemTelemetry")
|
||||||
|
|
||||||
Log("[Setup] 已初始化启动器页设置")
|
Log("[Setup] 已初始化启动器页设置")
|
||||||
Hint("已初始化启动器页设置!", HintType.Finish, False)
|
Hint("已初始化启动器页设置!", HintType.Finish, False)
|
||||||
@@ -92,13 +94,13 @@
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'将控件改变路由到设置改变
|
'将控件改变路由到设置改变
|
||||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadIgnoreQuilt.Change, CheckDownloadCert.Change
|
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadIgnoreQuilt.Change, CheckDownloadCert.Change, CheckSystemTelemetry.Change
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||||
End Sub
|
End Sub
|
||||||
Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderDebugAnim.Change, SliderDownloadThread.Change, SliderDownloadSpeed.Change
|
Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderDebugAnim.Change, SliderDownloadThread.Change, SliderDownloadSpeed.Change
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Value)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Value)
|
||||||
End Sub
|
End Sub
|
||||||
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboDownloadVersion.SelectionChanged, ComboModLocalNameStyle.SelectionChanged, ComboDownloadTranslateV2.SelectionChanged, ComboSystemUpdate.SelectionChanged, ComboSystemActivity.SelectionChanged, ComboDownloadSource.SelectionChanged
|
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboDownloadVersion.SelectionChanged, ComboModLocalNameStyle.SelectionChanged, ComboDownloadTranslateV2.SelectionChanged, ComboSystemUpdate.SelectionChanged, ComboSystemActivity.SelectionChanged, ComboDownloadSource.SelectionChanged, ComboDownloadMod.SelectionChanged
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
||||||
End Sub
|
End Sub
|
||||||
Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextSystemCache.ValidatedTextChanged
|
Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextSystemCache.ValidatedTextChanged
|
||||||
|
|||||||
@@ -274,7 +274,7 @@
|
|||||||
|
|
||||||
'顶部栏
|
'顶部栏
|
||||||
Private Sub BtnLogoChange_Click(sender As Object, e As EventArgs) Handles BtnLogoChange.Click
|
Private Sub BtnLogoChange_Click(sender As Object, e As EventArgs) Handles BtnLogoChange.Click
|
||||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif;*.webp)|*.png;*.jpg;*.gif;*.webp", "选择图片")
|
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.jpeg;*.gif;*.webp)|*.png;*.jpg;*.jpeg;*.gif;*.webp", "选择图片")
|
||||||
If FileName = "" Then Return
|
If FileName = "" Then Return
|
||||||
Try
|
Try
|
||||||
'拷贝文件
|
'拷贝文件
|
||||||
@@ -319,7 +319,7 @@ Refresh:
|
|||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
'没有图片则要求选择
|
'没有图片则要求选择
|
||||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif;*.webp)|*.png;*.jpg;*.gif;*.webp", "选择图片")
|
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpeg;*.jpg;*.gif;*.webp)|*.png;*.jpeg;*.jpg;*.gif;*.webp", "选择图片")
|
||||||
If FileName = "" Then
|
If FileName = "" Then
|
||||||
FrmMain.ImageTitleLogo.Source = Nothing
|
FrmMain.ImageTitleLogo.Source = Nothing
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
@@ -357,7 +357,9 @@ Refresh:
|
|||||||
PanMusicVolume.Visibility = Visibility.Visible
|
PanMusicVolume.Visibility = Visibility.Visible
|
||||||
PanMusicDetail.Visibility = Visibility.Visible
|
PanMusicDetail.Visibility = Visibility.Visible
|
||||||
BtnMusicClear.Visibility = Visibility.Visible
|
BtnMusicClear.Visibility = Visibility.Visible
|
||||||
CardMusic.Title = "背景音乐(" & EnumerateFiles(Path & "PCL\Musics\").Count & " 首)"
|
CardMusic.Title = "背景音乐(" &
|
||||||
|
EnumerateFiles(Path & "PCL\Musics\").Count(Function(f) Not {".ini", ".jpg", ".txt", ".cfg", ".lrc", ".db", ".png"}.Contains(f.Extension.ToLower)) &
|
||||||
|
" 首)"
|
||||||
Else
|
Else
|
||||||
PanMusicVolume.Visibility = Visibility.Collapsed
|
PanMusicVolume.Visibility = Visibility.Collapsed
|
||||||
PanMusicDetail.Visibility = Visibility.Collapsed
|
PanMusicDetail.Visibility = Visibility.Collapsed
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
<local:MyCheckBox.Tag>
|
<local:MyCheckBox.Tag>
|
||||||
<local:ExportOption
|
<local:ExportOption
|
||||||
Title="Mod 设置"
|
Title="Mod 设置"
|
||||||
Rules="config/|!config/jei/world/|!config/worldedit/|config/worldedit/worldedit.properties|!config/spark/|config/spark/config.json|defaultconfigs/|journeymap/config/|journeymap/server/|TrashSlotSaveState.json|customfov.txt|gg.essential.mod/|essential/|!essential/*/|!essential/*.jar*|!essential/screenshot-checksum-caches.json|!essential/microsoft_accounts.json|paragliderSettings.nbt|local/client_config.json|local/ftbl.json|local/client/sidebar_buttons.json|local/client/ftbutilities.cfg|local/client/ftblib.cfg|local/client/xencraft.cfg|liteloader.properties|default_reference.xml|CustomSkinLoader/CustomSkinLoader.json"
|
Rules="config/|!config/jei/world/|!config/worldedit/|config/worldedit/worldedit.properties|!config/spark/|config/spark/config.json|defaultconfigs/|journeymap/config/|journeymap/server/|TrashSlotSaveState.json|customfov.txt|gg.essential.mod/|essential/|!essential/*/|!essential/*.jar*|!essential/screenshot-checksum-caches.json|!essential/microsoft_accounts.json|paragliderSettings.nbt|local/client_config.json|local/ftbl.json|local/client/sidebar_buttons.json|local/client/ftbutilities.cfg|local/client/ftblib.cfg|local/client/xencraft.cfg|liteloader.properties|default_reference.xml|CustomSkinLoader/CustomSkinLoader.json|!config/tacz/custom"
|
||||||
DefaultChecked="True" />
|
DefaultChecked="True" />
|
||||||
</local:MyCheckBox.Tag>
|
</local:MyCheckBox.Tag>
|
||||||
</local:MyCheckBox>
|
</local:MyCheckBox>
|
||||||
@@ -133,6 +133,14 @@
|
|||||||
DefaultChecked="False" />
|
DefaultChecked="False" />
|
||||||
</local:MyCheckBox.Tag>
|
</local:MyCheckBox.Tag>
|
||||||
</local:MyCheckBox>
|
</local:MyCheckBox>
|
||||||
|
<local:MyCheckBox>
|
||||||
|
<local:MyCheckBox.Tag>
|
||||||
|
<local:ExportOption
|
||||||
|
Title="TaCZ 枪包"
|
||||||
|
Rules="tacz/|config/tacz/custom/"
|
||||||
|
DefaultChecked="False" />
|
||||||
|
</local:MyCheckBox.Tag>
|
||||||
|
</local:MyCheckBox>
|
||||||
<local:MyCheckBox>
|
<local:MyCheckBox>
|
||||||
<local:MyCheckBox.Tag>
|
<local:MyCheckBox.Tag>
|
||||||
<local:ExportOption
|
<local:ExportOption
|
||||||
@@ -235,7 +243,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Title="高级选项" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="高级选项" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,37,23,20">
|
<StackPanel Margin="25,37,23,20">
|
||||||
<local:MyHint Text="建议仅在无法稳定连接 CurseForge 或 Modrinth 时才打包资源文件。
请不要公开发布含资源文件的整合包,这会违反部分 Mod 的使用协议!"
|
<local:MyHint Text="建议仅在无法稳定连接 CurseForge 或 Modrinth 时才打包资源文件。
请不要公开发布含资源文件的整合包,这会违反部分 Mod 的使用协议!"
|
||||||
Theme="Yellow" Margin="0,2,0,8" Visibility="{Binding Checked, ElementName=CheckAdvancedInclude, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
Theme="Yellow" Margin="0,2,0,8" Visibility="{Binding Checked, ElementName=CheckAdvancedInclude, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
||||||
|
|||||||
@@ -564,8 +564,8 @@ Public Class PageVersionExport
|
|||||||
Sub()
|
Sub()
|
||||||
Try
|
Try
|
||||||
Dim ModrinthHashes = Loader.Input.Select(Function(m) m.ModrinthHash)
|
Dim ModrinthHashes = Loader.Input.Select(Function(m) m.ModrinthHash)
|
||||||
Dim ModrinthRaw = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files", "POST",
|
Dim ModrinthRaw As JObject = DlModRequest("https://api.modrinth.com/v2/version_files", HttpMethod.Post,
|
||||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")), JObject)
|
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")
|
||||||
For Each ModFile In Loader.Input
|
For Each ModFile In Loader.Input
|
||||||
'查找对应的文件
|
'查找对应的文件
|
||||||
If Not ModrinthRaw.ContainsKey(ModFile.ModrinthHash) Then Continue For
|
If Not ModrinthRaw.ContainsKey(ModFile.ModrinthHash) Then Continue For
|
||||||
@@ -589,8 +589,8 @@ Public Class PageVersionExport
|
|||||||
Try
|
Try
|
||||||
If ModrinthUploadMode Then Return 'Modrinth 上传模式下,不能从 CurseForge 获取信息
|
If ModrinthUploadMode Then Return 'Modrinth 上传模式下,不能从 CurseForge 获取信息
|
||||||
Dim CurseForgeHashes = Loader.Input.Select(Function(m) m.CurseForgeHash)
|
Dim CurseForgeHashes = Loader.Input.Select(Function(m) m.CurseForgeHash)
|
||||||
Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432/", "POST",
|
Dim CurseForgeRaw As JContainer = DlModRequest("https://api.curseforge.com/v1/fingerprints/432/", HttpMethod.Post,
|
||||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer)
|
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")("data")("exactMatches")
|
||||||
For Each ResultJson As JObject In CurseForgeRaw
|
For Each ResultJson As JObject In CurseForgeRaw
|
||||||
If Not ResultJson.ContainsKey("file") Then Continue For
|
If Not ResultJson.ContainsKey("file") Then Continue For
|
||||||
Dim File As JObject = ResultJson("file")
|
Dim File As JObject = ResultJson("file")
|
||||||
|
|||||||
@@ -381,7 +381,9 @@ Install:
|
|||||||
''' 下载 Mod。
|
''' 下载 Mod。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub BtnManageDownload_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageDownload.Click, BtnHintDownload.Click
|
Private Sub BtnManageDownload_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageDownload.Click, BtnHintDownload.Click
|
||||||
PageComp.TargetVersion = PageVersionLeft.Version '将当前版本设置为筛选器
|
'预设置当前版本和搜索框内容
|
||||||
|
PageComp.TargetVersion = PageVersionLeft.Version
|
||||||
|
PageComp.TargetName = SearchBox.Text
|
||||||
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadMod)
|
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadMod)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -428,6 +430,11 @@ Install:
|
|||||||
If FrmMain.PageRight IsNot Me Then Return
|
If FrmMain.PageRight IsNot Me Then Return
|
||||||
If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then ChangeAllSelected(True)
|
If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then ChangeAllSelected(True)
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub SearchBox_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles SearchBox.PreviewKeyDown
|
||||||
|
'Ctrl + A 会被搜索框捕获,导致无法全选,所以在按下 Ctrl + A 时转移焦点以便捕获
|
||||||
|
If SearchBox.Text.Any Then Return
|
||||||
|
If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then PanBack.Focus()
|
||||||
|
End Sub
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
@@ -636,14 +643,14 @@ Install:
|
|||||||
Try
|
Try
|
||||||
For Each Entry As McMod In ModList
|
For Each Entry As McMod In ModList
|
||||||
If File.Exists(Entry.Path) Then
|
If File.Exists(Entry.Path) Then
|
||||||
My.Computer.FileSystem.DeleteFile(Entry.Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
My.Computer.FileSystem.DeleteFile(Entry.Path, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||||
Else
|
Else
|
||||||
Log($"[Mod] 未找到更新前的 Mod 文件,跳过对它的删除:{Entry.Path}", LogLevel.Debug)
|
Log($"[Mod] 未找到更新前的 Mod 文件,跳过对它的删除:{Entry.Path}", LogLevel.Debug)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
For Each Entry As KeyValuePair(Of String, String) In FileCopyList
|
For Each Entry As KeyValuePair(Of String, String) In FileCopyList
|
||||||
If File.Exists(Entry.Value) Then
|
If File.Exists(Entry.Value) Then
|
||||||
My.Computer.FileSystem.DeleteFile(Entry.Value, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
My.Computer.FileSystem.DeleteFile(Entry.Value, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||||
Log($"[Mod] 更新后的 Mod 文件已存在,将会把它放入回收站:{Entry.Value}", LogLevel.Debug)
|
Log($"[Mod] 更新后的 Mod 文件已存在,将会把它放入回收站:{Entry.Value}", LogLevel.Debug)
|
||||||
End If
|
End If
|
||||||
If Directory.Exists(GetPathFromFullPath(Entry.Value)) Then
|
If Directory.Exists(GetPathFromFullPath(Entry.Value)) Then
|
||||||
@@ -732,7 +739,7 @@ Install:
|
|||||||
If IsShiftPressed Then
|
If IsShiftPressed Then
|
||||||
File.Delete(ModEntity.Path)
|
File.Delete(ModEntity.Path)
|
||||||
Else
|
Else
|
||||||
My.Computer.FileSystem.DeleteFile(ModEntity.Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
My.Computer.FileSystem.DeleteFile(ModEntity.Path, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||||
End If
|
End If
|
||||||
Catch ex As OperationCanceledException
|
Catch ex As OperationCanceledException
|
||||||
Log(ex, "删除 Mod 被主动取消")
|
Log(ex, "删除 Mod 被主动取消")
|
||||||
|
|||||||
@@ -116,12 +116,14 @@
|
|||||||
Dim TempName As String = NewName & "_temp"
|
Dim TempName As String = NewName & "_temp"
|
||||||
Dim TempPath As String = PathMcFolder & "versions\" & TempName & "\"
|
Dim TempPath As String = PathMcFolder & "versions\" & TempName & "\"
|
||||||
Dim IsCaseChangedOnly As Boolean = NewName.ToLower = OldName.ToLower
|
Dim IsCaseChangedOnly As Boolean = NewName.ToLower = OldName.ToLower
|
||||||
'重新加载版本 Json 信息,避免 HMCL 项被合并
|
'重新读取版本 JSON 信息,避免 JsonObject 中已被合并的项被重新存储
|
||||||
Dim JsonObject As JObject
|
Dim JsonObject As JObject
|
||||||
Try
|
Try
|
||||||
JsonObject = GetJson(ReadFile(PageVersionLeft.Version.Path & PageVersionLeft.Version.Name & ".json"))
|
Dim JsonPath As String = PageVersionLeft.Version.GetJsonPath()
|
||||||
|
JsonObject = GetJson(ReadFile(JsonPath))
|
||||||
|
File.Delete(JsonPath)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "重命名读取 json 时失败")
|
Log(ex, "在重命名读取 json 时失败")
|
||||||
JsonObject = PageVersionLeft.Version.JsonObject
|
JsonObject = PageVersionLeft.Version.JsonObject
|
||||||
End Try
|
End Try
|
||||||
'重命名主文件夹
|
'重命名主文件夹
|
||||||
@@ -130,27 +132,26 @@
|
|||||||
'清理 ini 缓存
|
'清理 ini 缓存
|
||||||
IniClearCache(PageVersionLeft.Version.PathIndie & "options.txt")
|
IniClearCache(PageVersionLeft.Version.PathIndie & "options.txt")
|
||||||
IniClearCache(PageVersionLeft.Version.Path & "PCL\Setup.ini")
|
IniClearCache(PageVersionLeft.Version.Path & "PCL\Setup.ini")
|
||||||
'遍历重命名所有文件与文件夹
|
'重命名 jar 文件与 natives 文件夹
|
||||||
For Each Entry As DirectoryInfo In New DirectoryInfo(NewPath).EnumerateDirectories
|
'不能进行遍历重命名,否则在版本名很短的时候容易误伤其他文件(#6443)
|
||||||
If Not Entry.Name.Contains(OldName) Then Continue For
|
If Directory.Exists($"{NewPath}{OldName}-natives") Then
|
||||||
If IsCaseChangedOnly Then
|
If IsCaseChangedOnly Then
|
||||||
My.Computer.FileSystem.RenameDirectory(Entry.FullName, Entry.Name & "_temp")
|
My.Computer.FileSystem.RenameDirectory($"{NewPath}{OldName}-natives", $"{OldName}natives_temp")
|
||||||
My.Computer.FileSystem.RenameDirectory(Entry.FullName & "_temp", Entry.Name.Replace(OldName, NewName))
|
My.Computer.FileSystem.RenameDirectory($"{NewPath}{OldName}-natives_temp", $"{NewName}-natives")
|
||||||
Else
|
Else
|
||||||
DeleteDirectory(NewPath & Entry.Name.Replace(OldName, NewName))
|
DeleteDirectory($"{NewPath}{NewName}-natives")
|
||||||
My.Computer.FileSystem.RenameDirectory(Entry.FullName, Entry.Name.Replace(OldName, NewName))
|
My.Computer.FileSystem.RenameDirectory($"{NewPath}{OldName}-natives", $"{NewName}-natives")
|
||||||
End If
|
End If
|
||||||
Next
|
End If
|
||||||
For Each Entry As FileInfo In New DirectoryInfo(NewPath).EnumerateFiles
|
If File.Exists($"{NewPath}{OldName}.jar") Then
|
||||||
If Not Entry.Name.Contains(OldName) Then Continue For
|
|
||||||
If IsCaseChangedOnly Then
|
If IsCaseChangedOnly Then
|
||||||
My.Computer.FileSystem.RenameFile(Entry.FullName, Entry.Name & "_temp")
|
My.Computer.FileSystem.RenameFile($"{NewPath}{OldName}.jar", $"{OldName}_temp.jar")
|
||||||
My.Computer.FileSystem.RenameFile(Entry.FullName & "_temp", Entry.Name.Replace(OldName, NewName))
|
My.Computer.FileSystem.RenameFile($"{NewPath}{OldName}_temp.jar", $"{NewName}.jar")
|
||||||
Else
|
Else
|
||||||
If File.Exists(NewPath & Entry.Name.Replace(OldName, NewName)) Then File.Delete(NewPath & Entry.Name.Replace(OldName, NewName))
|
File.Delete($"{NewPath}{NewName}.jar")
|
||||||
My.Computer.FileSystem.RenameFile(Entry.FullName, Entry.Name.Replace(OldName, NewName))
|
My.Computer.FileSystem.RenameFile($"{NewPath}{OldName}.jar", $"{NewName}.jar")
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Next
|
|
||||||
'替换版本设置文件中的路径
|
'替换版本设置文件中的路径
|
||||||
If File.Exists(NewPath & "PCL\Setup.ini") Then
|
If File.Exists(NewPath & "PCL\Setup.ini") Then
|
||||||
WriteFile(NewPath & "PCL\Setup.ini", ReadFile(NewPath & "PCL\Setup.ini").Replace(OldPath, NewPath))
|
WriteFile(NewPath & "PCL\Setup.ini", ReadFile(NewPath & "PCL\Setup.ini").Replace(OldPath, NewPath))
|
||||||
@@ -159,15 +160,13 @@
|
|||||||
If ReadIni(PathMcFolder & "PCL.ini", "Version") = OldName Then
|
If ReadIni(PathMcFolder & "PCL.ini", "Version") = OldName Then
|
||||||
WriteIni(PathMcFolder & "PCL.ini", "Version", NewName)
|
WriteIni(PathMcFolder & "PCL.ini", "Version", NewName)
|
||||||
End If
|
End If
|
||||||
'更改版本 Json
|
'写入版本 Json
|
||||||
If File.Exists(NewPath & NewName & ".json") Then
|
|
||||||
Try
|
Try
|
||||||
JsonObject("id") = NewName
|
JsonObject("id") = NewName
|
||||||
WriteFile(NewPath & NewName & ".json", JsonObject.ToString)
|
WriteFile(NewPath & NewName & ".json", JsonObject.ToString)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "重命名版本 json 失败")
|
Log(ex, "重命名版本 json 失败")
|
||||||
End Try
|
End Try
|
||||||
End If
|
|
||||||
'刷新与提示
|
'刷新与提示
|
||||||
Hint("重命名成功!", HintType.Finish)
|
Hint("重命名成功!", HintType.Finish)
|
||||||
PageVersionLeft.Version = New McVersion(NewName).Load()
|
PageVersionLeft.Version = New McVersion(NewName).Load()
|
||||||
@@ -185,7 +184,7 @@
|
|||||||
'选择 自定义 时修改图片
|
'选择 自定义 时修改图片
|
||||||
Try
|
Try
|
||||||
If ComboDisplayLogo.SelectedItem Is ItemDisplayLogoCustom Then
|
If ComboDisplayLogo.SelectedItem Is ItemDisplayLogoCustom Then
|
||||||
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif", "选择图片")
|
Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpeg;*.jpg;*.gif;*.webp)|*.png;*.jpeg;*.jpg;*.gif;*.webp", "选择图片")
|
||||||
If FileName = "" Then
|
If FileName = "" Then
|
||||||
Reload() '还原选项
|
Reload() '还原选项
|
||||||
Return
|
Return
|
||||||
@@ -331,7 +330,7 @@
|
|||||||
DeleteDirectory(PageVersionLeft.Version.Path)
|
DeleteDirectory(PageVersionLeft.Version.Path)
|
||||||
Hint("版本 " & PageVersionLeft.Version.Name & " 已永久删除!", HintType.Finish)
|
Hint("版本 " & PageVersionLeft.Version.Name & " 已永久删除!", HintType.Finish)
|
||||||
Else
|
Else
|
||||||
FileIO.FileSystem.DeleteDirectory(PageVersionLeft.Version.Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
FileIO.FileSystem.DeleteDirectory(PageVersionLeft.Version.Path, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||||
Hint("版本 " & PageVersionLeft.Version.Name & " 已删除到回收站!", HintType.Finish)
|
Hint("版本 " & PageVersionLeft.Version.Name & " 已删除到回收站!", HintType.Finish)
|
||||||
End If
|
End If
|
||||||
Case 2
|
Case 2
|
||||||
|
|||||||
@@ -192,7 +192,7 @@
|
|||||||
<local:MyButton x:Name="BtnServerAuthLittle" Height="35" MinWidth="150" Margin="0,12,0,0" Text="设置为 LittleSkin" HorizontalAlignment="Left" ColorType="Highlight" />
|
<local:MyButton x:Name="BtnServerAuthLittle" Height="35" MinWidth="150" Margin="0,12,0,0" Text="设置为 LittleSkin" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard x:Name="CardAdvance" Margin="0,0,0,15" Title="高级启动选项" IsSwaped="True" CanSwap="True">
|
<local:MyCard x:Name="CardAdvance" Margin="0,0,0,15" Title="高级启动选项" IsSwapped="True" CanSwap="True">
|
||||||
<Grid Margin="25,40,25,15">
|
<Grid Margin="25,40,25,15">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||||
@@ -208,17 +208,19 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数头部" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Java 虚拟机参数" Margin="0,0,25,0" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="VersionAdvanceJvm" Grid.Column="1" MaxLength="4000" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,在没有确定把握的情况下请不要尝试修改。
若留空,则跟随全局设置的值。" HintText="跟随全局设置"
|
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="VersionAdvanceJvm" Grid.Column="1" MaxLength="4000" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,在没有确定把握的情况下请不要尝试修改。
支持 Minecraft 版本 JSON 中的字符串替换标记,例如 ${library_directory}。

若留空,则跟随全局设置的值。" HintText="跟随全局设置"
|
||||||
Height="100" AcceptsReturn="True" TextWrapping="Wrap" VerticalContentAlignment="Top" Padding="0,5" VerticalScrollBarVisibility="Auto" />
|
Height="100" AcceptsReturn="True" TextWrapping="Wrap" VerticalContentAlignment="Top" Padding="0,5" VerticalScrollBarVisibility="Auto" />
|
||||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="游戏参数尾部" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="游戏参数" Margin="0,0,25,0" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="VersionAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。
若留空,则跟随全局设置的值。" HintText="跟随全局设置" />
|
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="VersionAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如,输入 --demo 则会以试玩模式启动游戏。
支持 Minecraft 版本 JSON 中的字符串替换标记,例如 ${library_directory}。

若留空,则跟随全局设置的值。" HintText="跟随全局设置" />
|
||||||
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动前执行命令" Margin="0,0,25,3" />
|
<TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="启动前执行命令" Margin="0,0,25,3" />
|
||||||
<local:MyTextBox x:Name="TextAdvanceRun" Grid.Row="4" Grid.ColumnSpan="2" Tag="VersionAdvanceRun" Grid.Column="1" HintText="" Margin="0,0,0,3"
|
<local:MyTextBox x:Name="TextAdvanceRun" Grid.Row="4" Grid.ColumnSpan="2" Tag="VersionAdvanceRun" Grid.Column="1" HintText="" Margin="0,0,0,3"
|
||||||
ToolTip="该项不会覆盖全局设置:启动时会先执行全局设置的命令,再执行版本设置的命令。

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

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

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

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

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

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

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

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

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

涉及路径的操作最好都打上双引号,以避免路径中的空格导致运行失败。
执行命令时,命令行所在的目录是当前的 .minecraft 文件夹。" />
|
||||||
<local:MyCheckBox Grid.Row="5" Grid.Column="1" x:Name="CheckAdvanceRunWait" Tag="VersionAdvanceRunWait" Visibility="Collapsed"
|
<local:MyCheckBox Grid.Row="5" Grid.Column="1" x:Name="CheckAdvanceRunWait" Tag="VersionAdvanceRunWait" Visibility="Collapsed"
|
||||||
Text="等待命令执行完成后再继续启动" Margin="0,5,0,0" />
|
Text="等待命令执行完成后再继续启动" Margin="0,5,0,0" />
|
||||||
<StackPanel Margin="0,12,0,4" Grid.Row="6" Grid.ColumnSpan="2" HorizontalAlignment="Left">
|
<StackPanel Margin="0,12,0,4" Grid.Row="6" Grid.ColumnSpan="2" HorizontalAlignment="Left">
|
||||||
|
<local:MyCheckBox Height="28" Text="禁止 Mod 更新" x:Name="CheckAdvanceDisableModUpdate" Tag="VersionAdvanceDisableModUpdate"
|
||||||
|
ToolTipService.Placement="Right" />
|
||||||
<local:MyCheckBox Height="28" Text="忽略 Java 兼容性警告" x:Name="CheckAdvanceJava" Tag="VersionAdvanceJava"
|
<local:MyCheckBox Height="28" Text="忽略 Java 兼容性警告" x:Name="CheckAdvanceJava" Tag="VersionAdvanceJava"
|
||||||
ToolTipService.Placement="Right"
|
ToolTipService.Placement="Right"
|
||||||
ToolTip="如果手动选择了与当前版本不兼容的 Java,则自动跳过兼容性警告弹窗,强制使用手动选择的 Java。" />
|
ToolTip="如果手动选择了与当前版本不兼容的 Java,则自动跳过兼容性警告弹窗,强制使用手动选择的 Java。" />
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
CheckAdvanceAssetsV2.Checked = Setup.Get("VersionAdvanceAssetsV2", Version:=PageVersionLeft.Version)
|
CheckAdvanceAssetsV2.Checked = Setup.Get("VersionAdvanceAssetsV2", Version:=PageVersionLeft.Version)
|
||||||
CheckAdvanceJava.Checked = Setup.Get("VersionAdvanceJava", Version:=PageVersionLeft.Version)
|
CheckAdvanceJava.Checked = Setup.Get("VersionAdvanceJava", Version:=PageVersionLeft.Version)
|
||||||
CheckAdvanceDisableJLW.Checked = Setup.Get("VersionAdvanceDisableJLW", Version:=PageVersionLeft.Version)
|
CheckAdvanceDisableJLW.Checked = Setup.Get("VersionAdvanceDisableJLW", Version:=PageVersionLeft.Version)
|
||||||
|
CheckAdvanceDisableModUpdate.Checked = Setup.Get("VersionAdvanceDisableModUpdate", Version:=PageVersionLeft.Version)
|
||||||
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Log(ex, "重载版本独立设置时出错", LogLevel.Feedback)
|
Log(ex, "重载版本独立设置时出错", LogLevel.Feedback)
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
Setup.Reset("VersionAdvanceRun", Version:=PageVersionLeft.Version)
|
Setup.Reset("VersionAdvanceRun", Version:=PageVersionLeft.Version)
|
||||||
Setup.Reset("VersionAdvanceRunWait", Version:=PageVersionLeft.Version)
|
Setup.Reset("VersionAdvanceRunWait", Version:=PageVersionLeft.Version)
|
||||||
Setup.Reset("VersionAdvanceDisableJLW", Version:=PageVersionLeft.Version)
|
Setup.Reset("VersionAdvanceDisableJLW", Version:=PageVersionLeft.Version)
|
||||||
|
Setup.Reset("VersionAdvanceDisableModUpdate", Version:=PageVersionLeft.Version)
|
||||||
|
|
||||||
Setup.Reset("VersionArgumentJavaSelect", Version:=PageVersionLeft.Version)
|
Setup.Reset("VersionArgumentJavaSelect", Version:=PageVersionLeft.Version)
|
||||||
JavaSearchLoader.Start(IsForceRestart:=True)
|
JavaSearchLoader.Start(IsForceRestart:=True)
|
||||||
@@ -125,7 +127,7 @@
|
|||||||
Private Shared Sub CheckBoxLikeComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndieV2.SelectionChanged
|
Private Shared Sub CheckBoxLikeComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndieV2.SelectionChanged
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex = 0, Version:=PageVersionLeft.Version)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex = 0, Version:=PageVersionLeft.Version)
|
||||||
End Sub
|
End Sub
|
||||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceRunWait.Change, CheckAdvanceAssetsV2.Change, CheckAdvanceJava.Change, CheckAdvanceDisableJLW.Change
|
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceRunWait.Change, CheckAdvanceAssetsV2.Change, CheckAdvanceJava.Change, CheckAdvanceDisableJLW.Change, CheckAdvanceDisableModUpdate.Change
|
||||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked, Version:=PageVersionLeft.Version)
|
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked, Version:=PageVersionLeft.Version)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -355,6 +357,15 @@ PreFin:
|
|||||||
|
|
||||||
#Region "服务器"
|
#Region "服务器"
|
||||||
|
|
||||||
|
'自动替换标点
|
||||||
|
Private Sub TextServerEnter_Change() Handles TextServerEnter.TextChanged
|
||||||
|
Dim NewText = TextServerEnter.Text.Replace(":", ":").Replace("。", ".")
|
||||||
|
If NewText = TextServerEnter.Text Then Return
|
||||||
|
Dim CurrentPosition = TextServerEnter.SelectionStart '重设焦点
|
||||||
|
TextServerEnter.Text = NewText
|
||||||
|
TextServerEnter.SelectionStart = CurrentPosition
|
||||||
|
End Sub
|
||||||
|
|
||||||
'全局
|
'全局
|
||||||
Private ComboServerLoginLast As Integer
|
Private ComboServerLoginLast As Integer
|
||||||
Private Sub ComboServerLogin_Changed() Handles ComboServerLogin.SelectionChanged, TextServerNide.ValidatedTextChanged, TextServerAuthServer.ValidatedTextChanged, TextServerAuthRegister.ValidatedTextChanged
|
Private Sub ComboServerLogin_Changed() Handles ComboServerLogin.SelectionChanged, TextServerNide.ValidatedTextChanged, TextServerAuthServer.ValidatedTextChanged, TextServerAuthRegister.ValidatedTextChanged
|
||||||
|
|||||||
@@ -140,6 +140,21 @@
|
|||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="CacheCow.Client, Version=2.13.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>Resources\CacheCow.Client.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="CacheCow.Client.FileStore, Version=2.13.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>Resources\CacheCow.Client.FileStore.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="CacheCow.Common, Version=2.13.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>Resources\CacheCow.Common.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Imazen.WebP, Version=10.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Imazen.WebP, Version=10.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>Resources\Imazen.WebP.dll</HintPath>
|
<HintPath>Resources\Imazen.WebP.dll</HintPath>
|
||||||
@@ -149,8 +164,9 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>Resources\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Ookii.Dialogs.Wpf, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0c15020868fd6249, processorArchitecture=MSIL">
|
<Reference Include="Ookii.Dialogs.Wpf, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0c15020868fd6249, processorArchitecture=MSIL">
|
||||||
@@ -158,13 +174,20 @@
|
|||||||
<HintPath>Resources\Ookii.Dialogs.Wpf.dll</HintPath>
|
<HintPath>Resources\Ookii.Dialogs.Wpf.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.IO.Compression" />
|
<Reference Include="System.IO.Compression" />
|
||||||
<Reference Include="System.IO.Compression.FileSystem" />
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
<Reference Include="System.Management" />
|
<Reference Include="System.Management" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>Resources\System.Net.Http.Formatting.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Numerics" />
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.Runtime.Caching" />
|
||||||
<Reference Include="System.ServiceModel" />
|
<Reference Include="System.ServiceModel" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
@@ -182,6 +205,7 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
|
<Compile Include="Controls\Behaviors\ClipboardInterceptor.vb" />
|
||||||
<Compile Include="Controls\IMyRadio.vb" />
|
<Compile Include="Controls\IMyRadio.vb" />
|
||||||
<Compile Include="Controls\MyComboBox.vb" />
|
<Compile Include="Controls\MyComboBox.vb" />
|
||||||
<Compile Include="Controls\MyComboBoxItem.vb" />
|
<Compile Include="Controls\MyComboBoxItem.vb" />
|
||||||
@@ -202,6 +226,7 @@
|
|||||||
<Compile Include="Modules\Minecraft\ModJava.vb" />
|
<Compile Include="Modules\Minecraft\ModJava.vb" />
|
||||||
<Compile Include="Modules\Minecraft\ModMod.vb" />
|
<Compile Include="Modules\Minecraft\ModMod.vb" />
|
||||||
<Compile Include="Modules\Minecraft\ModModpack.vb" />
|
<Compile Include="Modules\Minecraft\ModModpack.vb" />
|
||||||
|
<Compile Include="Modules\ThirdParty\DragHelper.vb" />
|
||||||
<Compile Include="Pages\PageVersion\MyLocalModItem.xaml.vb">
|
<Compile Include="Pages\PageVersion\MyLocalModItem.xaml.vb">
|
||||||
<DependentUpon>MyLocalModItem.xaml</DependentUpon>
|
<DependentUpon>MyLocalModItem.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -235,9 +260,6 @@
|
|||||||
<Compile Include="Modules\ModDevelop.vb" />
|
<Compile Include="Modules\ModDevelop.vb" />
|
||||||
<Compile Include="Modules\Minecraft\ModWatcher.vb" />
|
<Compile Include="Modules\Minecraft\ModWatcher.vb" />
|
||||||
<Compile Include="Modules\ModSecret.vb" />
|
<Compile Include="Modules\ModSecret.vb" />
|
||||||
<Compile Include="Modules\Reference\CookieWebClient.vb">
|
|
||||||
<SubType>Component</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Pages\PageDownload\Comp\PageComp.xaml.vb">
|
<Compile Include="Pages\PageDownload\Comp\PageComp.xaml.vb">
|
||||||
<DependentUpon>PageComp.xaml</DependentUpon>
|
<DependentUpon>PageComp.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -724,6 +746,7 @@
|
|||||||
<Import Include="System.IO" />
|
<Import Include="System.IO" />
|
||||||
<Import Include="System.Linq" />
|
<Import Include="System.Linq" />
|
||||||
<Import Include="System.Net" />
|
<Import Include="System.Net" />
|
||||||
|
<Import Include="System.Net.Http" />
|
||||||
<Import Include="System.Text" />
|
<Import Include="System.Text" />
|
||||||
<Import Include="System.Threading" />
|
<Import Include="System.Threading" />
|
||||||
<Import Include="System.Xml.Linq" />
|
<Import Include="System.Xml.Linq" />
|
||||||
@@ -961,5 +984,18 @@
|
|||||||
<None Include="Resources\Imazen.WebP.dll" />
|
<None Include="Resources\Imazen.WebP.dll" />
|
||||||
<None Include="Resources\libwebp64.dll" />
|
<None Include="Resources\libwebp64.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Resources\CacheCow.Client.FileStore.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Resources\CacheCow.Common.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Resources\CacheCow.Client.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Resources\System.Net.Http.Formatting.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,7 +3,7 @@
|
|||||||
下列内容均基于 WPF 框架。你可以在继续之前先尝试自学 XAML 与 WPF 的基础,这能让你更轻松地理解下列内容。
|
下列内容均基于 WPF 框架。你可以在继续之前先尝试自学 XAML 与 WPF 的基础,这能让你更轻松地理解下列内容。
|
||||||
你也可以使用 Ctrl + F 快速查找。例如,若需要改变文本颜色,则搜索 “颜色” 即可。 -->
|
你也可以使用 Ctrl + F 快速查找。例如,若需要改变文本颜色,则搜索 “颜色” 即可。 -->
|
||||||
|
|
||||||
<local:MyCard Title="纯文本" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="纯文本" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="每个 local:MyCard 代表一张卡片,你可以添加、删除格式类似的 MyCard 来添加多个卡片。每个 TextBlock 代表一段文本,你可以在 Text 属性中书写任何你想写的内容,也可以自行添加更多的 TextBlock。" />
|
Text="每个 local:MyCard 代表一张卡片,你可以添加、删除格式类似的 MyCard 来添加多个卡片。每个 TextBlock 代表一段文本,你可以在 Text 属性中书写任何你想写的内容,也可以自行添加更多的 TextBlock。" />
|
||||||
@@ -14,17 +14,17 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="卡片、提示条" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="卡片、提示条" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<local:MyHint Text="local:MyHint 代表提示条。" />
|
<local:MyHint Text="local:MyHint 代表提示条。" />
|
||||||
<local:MyHint Margin="0,8,0,2" Theme="Blue"
|
<local:MyHint Margin="0,8,0,2" Theme="Blue"
|
||||||
Text="将提示条的 Theme 属性改为 Blue、Yellow 或 Red 即可修改配色。
使用左边的那堆字符可以在任意地方手动换行,如果需要使用等号、引号等特殊字符,可以自行百度 XAML 转义字符。" />
|
Text="将提示条的 Theme 属性改为 Blue、Yellow 或 Red 即可修改配色。
使用左边的那堆字符可以在任意地方手动换行,如果需要使用等号、引号等特殊字符,可以自行百度 XAML 转义字符。" />
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,6,0,0"
|
<TextBlock TextWrapping="Wrap" Margin="0,6,0,0"
|
||||||
Text="卡片(local:MyCard)的 Title 属性决定了它的标题。
为卡片添加 CanSwap 属性让它可以被折叠,True 代表是,False 代表否。在此基础上,再使用 IsSwaped 属性调整它是否默认被折叠。" />
|
Text="卡片(local:MyCard)的 Title 属性决定了它的标题。
为卡片添加 CanSwap 属性让它可以被折叠,True 代表是,False 代表否。在此基础上,再使用 IsSwapped 属性调整它是否默认被折叠。" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="长宽属性、图片" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="长宽属性、图片" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4" Width="320" HorizontalAlignment="Right"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4" Width="320" HorizontalAlignment="Right"
|
||||||
Text="任意项目都可以添加 Width 与 Height 属性来控制宽高。HorizontalAlignment 属性可以控制对齐:Center 代表居中,Right 代表居右,例如这段文本就被居右了。" />
|
Text="任意项目都可以添加 Width 与 Height 属性来控制宽高。HorizontalAlignment 属性可以控制对齐:Center 代表居中,Right 代表居右,例如这段文本就被居右了。" />
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="按钮" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="按钮" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="添加 local:MyButton 即可新建一个按钮。你需要限定它的尺寸与位置,并通过 Padding 属性进一步控制它的内边距。" />
|
Text="添加 local:MyButton 即可新建一个按钮。你需要限定它的尺寸与位置,并通过 Padding 属性进一步控制它的内边距。" />
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="事件 1:打开网页、弹出窗口" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="事件 1:打开网页、弹出窗口" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||||
Text="将按钮的 EventType 属性设为 打开网页,然后在 EventData 属性中写入网址,即可通过点击按钮打开网页。" />
|
Text="将按钮的 EventType 属性设为 打开网页,然后在 EventData 属性中写入网址,即可通过点击按钮打开网页。" />
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="事件 2:启动游戏" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="事件 2:启动游戏" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="将 EventType 设置为 启动游戏,EventData 设置为具体的游戏版本,即可通过点击按钮启动游戏。如果当前游戏文件夹没有该版本,则无法启动。" />
|
Text="将 EventType 设置为 启动游戏,EventData 设置为具体的游戏版本,即可通过点击按钮启动游戏。如果当前游戏文件夹没有该版本,则无法启动。" />
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="事件 3:执行命令" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="事件 3:执行命令" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="将 EventType 设置为 执行命令(或 打开文件),EventData 设置为文件路径,即可点击打开特定文件或启动程序。" />
|
Text="将 EventType 设置为 执行命令(或 打开文件),EventData 设置为文件路径,即可点击打开特定文件或启动程序。" />
|
||||||
@@ -106,14 +106,14 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="事件 4:其他事件类型" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="事件 4:其他事件类型" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock Margin="0,4,0,6" FontWeight="Bold"
|
<TextBlock Margin="0,4,0,6" FontWeight="Bold"
|
||||||
Text="EventType 共有以下种类:" />
|
Text="EventType 共有以下种类:" />
|
||||||
<TextBlock Margin="0,0,0,4"
|
<TextBlock Margin="0,0,0,4"
|
||||||
Text="· 打开网页、启动游戏、打开文件:已在上方的卡片中介绍" />
|
Text="· 打开网页、启动游戏、打开文件:已在上方的卡片中介绍" />
|
||||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||||
Text="查看 PCL 源代码" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2/blob/main/Plain%20Craft%20Launcher%202/FormMain.xaml.vb"/>
|
Text="查看 PCL 源代码" EventType="打开网页" EventData="https://github.com/Meloong-Git/PCL/blob/main/Plain%20Craft%20Launcher%202/FormMain.xaml.vb"/>
|
||||||
<TextBlock Margin="0,0,0,4"
|
<TextBlock Margin="0,0,0,4"
|
||||||
Text="· 今日人品、清理垃圾、内存优化、安装整合包:触发对应功能" />
|
Text="· 今日人品、清理垃圾、内存优化、安装整合包:触发对应功能" />
|
||||||
<TextBlock Margin="0,0,0,4"
|
<TextBlock Margin="0,0,0,4"
|
||||||
@@ -134,10 +134,18 @@
|
|||||||
Text="切换到下载页面" EventType="切换页面" EventData="1|1"/>
|
Text="切换到下载页面" EventType="切换页面" EventData="1|1"/>
|
||||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||||
Text="切换到启动器设置" EventType="切换页面" EventData="3|2"/>
|
Text="切换到启动器设置" EventType="切换页面" EventData="3|2"/>
|
||||||
|
<TextBlock Margin="0,4,0,4"
|
||||||
|
Text="· 下载版本:切换到 EventData 对应的 Minecraft 下载页面"/>
|
||||||
|
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||||
|
Text="下载 Minecraft 1.12.2" EventType="下载版本" EventData="1.12.2"/>
|
||||||
|
<TextBlock Margin="0,4,0,4"
|
||||||
|
Text="· 修改设置:将 PCL 的特定设置修改为特定值"/>
|
||||||
|
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||||
|
Text="将窗口改为半透明" EventType="修改设置" EventData="UiLauncherTransparent|400"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="StackPanel 横向布局" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="StackPanel 横向布局" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||||
Text="你需要使用 StackPanel 在一行里塞下多个按钮。你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
|
Text="你需要使用 StackPanel 在一行里塞下多个按钮。你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
|
||||||
@@ -162,7 +170,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="列表项 1:基础" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="列表项 1:基础" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="你也可以使用列表项 “local:MyListItem” 来替代按钮,其使用方式与按钮类似。" />
|
Text="你也可以使用列表项 “local:MyListItem” 来替代按钮,其使用方式与按钮类似。" />
|
||||||
@@ -179,7 +187,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="列表项 2:内置图片" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="列表项 2:内置图片" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="PCL 内置了一些 Minecraft 方块与物品图片,可以直接使用。"/>
|
Text="PCL 内置了一些 Minecraft 方块与物品图片,可以直接使用。"/>
|
||||||
@@ -217,7 +225,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="主题色" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="主题色" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,15"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,15"
|
||||||
Text="你可以用类似 {DynamicResource ColorBrush5} 的格式使用 PCL 当前的主题颜色,修改末尾的数字编号以改变颜色浓度。" />
|
Text="你可以用类似 {DynamicResource ColorBrush5} 的格式使用 PCL 当前的主题颜色,修改末尾的数字编号以改变颜色浓度。" />
|
||||||
@@ -238,7 +246,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="替换标记" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="替换标记" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="在花括号 {} 中写入特定内容,PCL 会在加载时对其进行替换。
例如,path 会被替换为 PCL 可执行文件所在文件夹({path}),用于在 EventData 中指定特定文件,或是加载图片。" />
|
Text="在花括号 {} 中写入特定内容,PCL 会在加载时对其进行替换。
例如,path 会被替换为 PCL 可执行文件所在文件夹({path}),用于在 EventData 中指定特定文件,或是加载图片。" />
|
||||||
@@ -249,7 +257,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="进阶:Grid 布局" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="进阶:Grid 布局" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="如果要实现更复杂的布局,则必须使用 Grid。Grid 可以让按钮们自动适应窗口宽度:随意拉伸 PCL 窗口,按钮大小会自动改变。" />
|
Text="如果要实现更复杂的布局,则必须使用 Grid。Grid 可以让按钮们自动适应窗口宽度:随意拉伸 PCL 窗口,按钮大小会自动改变。" />
|
||||||
@@ -272,7 +280,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="进阶:图标按钮" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="进阶:图标按钮" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
|
||||||
Text="MyIconTextButton 是一种带有自定义矢量图标的按钮变体,它同样支持 EventType 与 EventData 属性。
通过设置 Logo 属性来控制它的图标,设置 LogoScale 属性还可以调整图标的缩放比例。" />
|
Text="MyIconTextButton 是一种带有自定义矢量图标的按钮变体,它同样支持 EventType 与 EventData 属性。
通过设置 Logo 属性来控制它的图标,设置 LogoScale 属性还可以调整图标的缩放比例。" />
|
||||||
@@ -297,12 +305,12 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
<local:MyCard Title="进阶:联网主页" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
|
<local:MyCard Title="进阶:联网主页" Margin="0,0,0,15" CanSwap="True" IsSwapped="True">
|
||||||
<StackPanel Margin="25,40,23,15">
|
<StackPanel Margin="25,40,23,15">
|
||||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||||
Text="如果你在尝试制作联网更新的主页,可以查看下方的 GitHub 讨论页。
你可以根据其中的介绍为主页添加版本号检查以节省流量,也可以通过检查 Referer 和 User Agent 来确定对方的 PCL 版本。" />
|
Text="如果你在尝试制作联网更新的主页,可以查看下方的 GitHub 讨论页。
你可以根据其中的介绍为主页添加版本号检查以节省流量,也可以通过检查 Referer 和 User Agent 来确定对方的 PCL 版本。" />
|
||||||
<local:MyButton Margin="0,0,0,8" Height="35" HorizontalAlignment="Center" Padding="20,0,20,0"
|
<local:MyButton Margin="0,0,0,8" Height="35" HorizontalAlignment="Center" Padding="20,0,20,0"
|
||||||
Text="打开 GitHub 讨论页" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2/discussions/2528" />
|
Text="打开 GitHub 讨论页" EventType="打开网页" EventData="https://github.com/Meloong-Git/PCL/discussions/2528" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|
||||||
@@ -332,7 +340,7 @@ local:MyImage(图片):
|
|||||||
local:MyCard(卡片):
|
local:MyCard(卡片):
|
||||||
- Title:设置显示的标题文本
|
- Title:设置显示的标题文本
|
||||||
- CanSwap:卡片是否可以折叠,True 为是,False 为否
|
- CanSwap:卡片是否可以折叠,True 为是,False 为否
|
||||||
- IsSwaped:卡片是否默认折叠,要求 CanSwap 必须为 True
|
- IsSwapped:卡片是否默认折叠,要求 CanSwap 必须为 True
|
||||||
- HorizontalAlignment:若使用,要求 CanSwap 必须为 False
|
- HorizontalAlignment:若使用,要求 CanSwap 必须为 False
|
||||||
- UseAnimation:是否在展开等高度改变时触发动画;True 为是(默认),False 为否
|
- UseAnimation:是否在展开等高度改变时触发动画;True 为是(默认),False 为否
|
||||||
- SwapLogoRight:卡片折叠时的箭头是朝下还是朝右;True 为朝右,False 为朝下(默认)
|
- SwapLogoRight:卡片折叠时的箭头是朝下还是朝右;True 为朝右,False 为朝下(默认)
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
# Plain Craft Launcher
|
# Plain Craft Launcher
|
||||||
|
|
||||||
[](https://github.com/Hex-Dragon/PCL2/)
|
[](https://github.com/Meloong-Git/PCL/)
|
||||||
[](https://github.com/Hex-Dragon/PCL2/issues)
|
[](https://github.com/Meloong-Git/PCL/issues)
|
||||||
[](https://space.bilibili.com/11343203/dynamic)
|
[](https://space.bilibili.com/11343203/dynamic)
|
||||||
[](https://afdian.com/@LTCat)
|
[](https://afdian.com/@LTCat)
|
||||||
|
|
||||||
@@ -13,5 +13,5 @@
|
|||||||
|
|
||||||
### 相关资源
|
### 相关资源
|
||||||
- [PCL 下载](https://afdian.com/p/0164034c016c11ebafcb52540025c377):下载可免费使用的正式版 PCL!
|
- [PCL 下载](https://afdian.com/p/0164034c016c11ebafcb52540025c377):下载可免费使用的正式版 PCL!
|
||||||
- [PCL 功能投票](https://github.com/Hex-Dragon/PCL2/discussions/2):来参加投票吧,开发者会优先处理票数较高的项目!
|
- [PCL 功能投票](https://github.com/Meloong-Git/PCL/discussions/2):来参加投票吧,开发者会优先处理票数较高的项目!
|
||||||
- [帮助文档库](https://github.com/LTCatt/PCL2Help):PCL 内置帮助文档的存储库
|
- [帮助文档库](https://github.com/LTCatt/PCL2Help):PCL 内置帮助文档的存储库
|
||||||
|
|||||||
Reference in New Issue
Block a user