Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28ef67ee0f | ||
|
|
add4153067 | ||
|
|
3e474b89ef | ||
|
|
b5cfebe8aa | ||
|
|
4486e7ea2c | ||
|
|
4d91d0b27e | ||
|
|
14e14b9810 | ||
|
|
d6575df6ab | ||
|
|
eed6c92f5a | ||
|
|
ae8de397ae | ||
|
|
2de22b780c | ||
|
|
4d954ae45d | ||
|
|
3d63ceba57 | ||
|
|
8b234d8e4f | ||
|
|
d6a5a8b83e | ||
|
|
885b3eada6 | ||
|
|
deb902904b | ||
|
|
1458ce95ce | ||
|
|
d8efb76bf0 | ||
|
|
a843b22f38 | ||
|
|
08e4414f34 | ||
|
|
ff225e9f37 | ||
|
|
96b6ef294b | ||
|
|
f271d7212c | ||
|
|
ad583c29c2 | ||
|
|
f98dcd8fef | ||
|
|
9b49235cda | ||
|
|
f090a63c54 | ||
|
|
c332a4dc94 | ||
|
|
6770e55214 | ||
|
|
dd028bb6d8 | ||
|
|
5126b257f8 | ||
|
|
35398052bb | ||
|
|
17031e1a65 | ||
|
|
e40a41a761 | ||
|
|
5ae813825c | ||
|
|
48684f8f85 | ||
|
|
3f5392d76d | ||
|
|
9af03d499a | ||
|
|
d6043c7d32 | ||
|
|
a38e20870b | ||
|
|
72a2b5da8c | ||
|
|
f3017b6b62 | ||
|
|
5274ae8499 | ||
|
|
83e34b84fa | ||
|
|
65812b8754 | ||
|
|
6616afde6d | ||
|
|
7cd5747f4f | ||
|
|
70ec0b66f9 | ||
|
|
74e5eb82f5 | ||
|
|
5e31a1d937 | ||
|
|
81619cbfc7 | ||
|
|
300d1ecf66 | ||
|
|
6dbb5c98cc | ||
|
|
da8a50abd3 | ||
|
|
7ecf306445 | ||
|
|
3adf47aa2c | ||
|
|
70a2f28073 | ||
|
|
9c9216c02c | ||
|
|
f2ae0fbaa9 | ||
|
|
36c03d1654 | ||
|
|
ebd20195be | ||
|
|
5a94854809 | ||
|
|
d2e210320b | ||
|
|
73d705aa5b | ||
|
|
9a0ad08498 | ||
|
|
443d306d31 | ||
|
|
acaff10bf0 | ||
|
|
f3680f0b78 | ||
|
|
74657d54c7 | ||
|
|
52ddb97938 | ||
|
|
31f0b81652 | ||
|
|
ca729067c1 | ||
|
|
855ff55495 | ||
|
|
a174c4856a |
No files matched your search
@@ -12,7 +12,7 @@ body:
|
||||
required: false
|
||||
- label: "**我已尝试使用 HMCL 启动,HMCL 没有出现问题。** 如果 HMCL 也无法启动就不是 PCL 导致的问题,请 **不要** 提交反馈。[下载 HMCL](https://hmcl.huangyuhui.net/download)"
|
||||
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
|
||||
- type: textarea
|
||||
id: "yml-2"
|
||||
|
||||
@@ -12,7 +12,7 @@ body:
|
||||
required: false
|
||||
- label: "我知晓大多数此类问题都是网络环境不佳导致的,但我确实认为我的问题可能是 PCL 导致的,和网络环境无关。"
|
||||
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
|
||||
- type: textarea
|
||||
id: "yml-2"
|
||||
|
||||
@@ -8,7 +8,7 @@ body:
|
||||
label: "检查项"
|
||||
description: "请逐个检查下列项目,并勾选确认。"
|
||||
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
|
||||
- type: textarea
|
||||
id: "yml-2"
|
||||
|
||||
@@ -8,9 +8,9 @@ body:
|
||||
label: "检查项"
|
||||
description: "请逐个检查下列项目,并勾选确认。"
|
||||
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
|
||||
- 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
|
||||
- type: textarea
|
||||
id: "yml-2"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 主页预设反馈
|
||||
url: https://github.com/Hex-Dragon/PCL2/discussions/categories/自定义主页
|
||||
url: https://github.com/Meloong-Git/PCL/discussions/categories/自定义主页
|
||||
about: 提交与预设的主页(设置 → 个性化 → 主页预设)中的具体内容相关的反馈
|
||||
- name: 帮助文档反馈
|
||||
url: https://github.com/LTCatt/PCL2Help/issues
|
||||
about: 提交与 PCL 帮助文档(更多 → 帮助)中的具体内容相关的反馈
|
||||
- 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 相关的问题……
|
||||
- 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 相关的事情……
|
||||
@@ -8,9 +8,9 @@ body:
|
||||
label: "检查项"
|
||||
description: "请逐个检查下列项目,并勾选确认。"
|
||||
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
|
||||
- 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
|
||||
- label: "我知晓还没做的新功能真的太多了,忙不过来,所以新功能提案几乎不会被处理,也不建议再提交新功能提案 qwq……"
|
||||
required: true
|
||||
|
||||
@@ -38,7 +38,6 @@ jobs:
|
||||
|
||||
- name: Update Help
|
||||
run: |
|
||||
$workpath = [System.Environment]::CurrentDirectory
|
||||
Set-Location ..
|
||||
git clone https://github.com/LTCatt/PCL2Help.git -b master --single-branch --depth 1
|
||||
Set-Location PCL2Help
|
||||
@@ -52,8 +51,8 @@ jobs:
|
||||
|
||||
- name: Replace
|
||||
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 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 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 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"
|
||||
|
||||
- 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"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
|
||||
</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>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -181,53 +181,29 @@ WaitRetry:
|
||||
End Sub
|
||||
|
||||
'动态 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
|
||||
Public Shared Function AssemblyResolve(sender As Object, args As ResolveEventArgs) As Assembly
|
||||
If args.Name.StartsWithF("NAudio") Then
|
||||
SyncLock AssemblyNAudioLock
|
||||
If AssemblyNAudio Is Nothing Then
|
||||
Log("[Start] 加载 DLL:NAudio")
|
||||
AssemblyNAudio = Assembly.Load(GetResources("NAudio"))
|
||||
End If
|
||||
Return AssemblyNAudio
|
||||
End SyncLock
|
||||
ElseIf args.Name.StartsWithF("Newtonsoft.Json") Then
|
||||
SyncLock AssemblyJsonLock
|
||||
If AssemblyJson Is Nothing Then
|
||||
Log("[Start] 加载 DLL:Json")
|
||||
AssemblyJson = Assembly.Load(GetResources("Json"))
|
||||
End If
|
||||
Return AssemblyJson
|
||||
End SyncLock
|
||||
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("\"))
|
||||
Public Shared Function AssemblyResolve(sender As Object, Args As ResolveEventArgs) As Assembly
|
||||
'缓存
|
||||
Static Prefixes As String() = {"NAudio", "Newtonsoft.Json", "Ookii.Dialogs.Wpf", "Imazen.WebP", "CacheCow.Common", "CacheCow.Client.FileStore", "CacheCow.Client", "System.Net.Http.Formatting"}
|
||||
Static Locks As New Dictionary(Of String, Object)(StringComparer.Ordinal)
|
||||
Static LoadedAssembly As New Dictionary(Of String, Assembly)(StringComparer.Ordinal)
|
||||
'查找对应的 DLL
|
||||
Dim Prefix As String = Prefixes.FirstOrDefault(Function(p) Args.Name.StartsWithF(p))
|
||||
If Prefix Is Nothing Then Return Nothing
|
||||
'加载 DLL
|
||||
If Not Locks.ContainsKey(Prefix) Then Locks(Prefix) = New Object()
|
||||
SyncLock Locks(Prefix)
|
||||
If Not LoadedAssembly.ContainsKey(Prefix) Then
|
||||
Log($"[Start] 加载 DLL:{Prefix}")
|
||||
LoadedAssembly(Prefix) = Assembly.Load(GetResources(Prefix))
|
||||
'WebP 特判
|
||||
If Prefix = "Imazen.WebP" Then
|
||||
SetDllDirectory(PathPure.TrimEnd("\"c))
|
||||
WriteFile(PathPure & "libwebp.dll", GetResources("libwebp64"))
|
||||
End If
|
||||
Return AssemblyImazenWebp
|
||||
End SyncLock
|
||||
Else
|
||||
Return Nothing
|
||||
End If
|
||||
End If
|
||||
Return LoadedAssembly(Prefix)
|
||||
End SyncLock
|
||||
End Function
|
||||
|
||||
'切换窗口
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Imports System.ComponentModel
|
||||
Imports System.Windows.Interop
|
||||
|
||||
Public Class FormMain
|
||||
|
||||
@@ -82,6 +83,19 @@ Public Class FormMain
|
||||
'3:BUG+ IMP* FEAT-
|
||||
'2:BUG* IMP-
|
||||
'1:BUG-
|
||||
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
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法安装部分使用老版本 PCL 导出的整合包"))
|
||||
End If
|
||||
@@ -225,7 +239,7 @@ Public Class FormMain
|
||||
If Not Setup.IsUnset("LaunchArgumentIndie") Then
|
||||
Log("[Start] 从老 PCL 迁移版本隔离")
|
||||
Setup.Set("LaunchArgumentIndieV2", Setup.Get("LaunchArgumentIndie"))
|
||||
ElseIf Not Setup.IsUnset("WindowHeight") Then
|
||||
ElseIf Not Setup.IsUnset("LaunchVersionSelect") Then
|
||||
Log("[Start] 从老 PCL 升级,但此前未调整版本隔离,使用老的版本隔离默认值")
|
||||
Setup.Set("LaunchArgumentIndieV2", Setup.GetDefault("LaunchArgumentIndie"))
|
||||
Else
|
||||
@@ -242,9 +256,19 @@ Public Class FormMain
|
||||
'加载 UI
|
||||
InitializeComponent()
|
||||
Opacity = 0
|
||||
''开启管理员权限下的文件拖拽,但下列代码也没用(#2531)
|
||||
'If IsAdmin() Then
|
||||
' Log("[Start] PCL 正以管理员权限运行")
|
||||
'开启管理员权限下的文件拖拽
|
||||
If IsAdmin() Then
|
||||
Static Helper As New DragHelper
|
||||
AddHandler SourceInitialized,
|
||||
Sub()
|
||||
Dim WpfHelper As New WindowInteropHelper(Me)
|
||||
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 IsAdmin() Then '下列代码没用(#2531)
|
||||
' ChangeWindowMessageFilter(&H233, 1)
|
||||
' ChangeWindowMessageFilter(&H4A, 1)
|
||||
' ChangeWindowMessageFilter(&H49, 1)
|
||||
@@ -365,7 +389,7 @@ Public Class FormMain
|
||||
Catch ex As Exception
|
||||
Log(ex, "清理自动更新文件失败")
|
||||
End Try
|
||||
End Sub, "Start Loader", ThreadPriority.Lowest)
|
||||
End Sub, "初始化", ThreadPriority.Lowest)
|
||||
|
||||
Log("[Start] 第三阶段加载用时:" & GetTimeTick() - ApplicationStartTick & " ms")
|
||||
End Sub
|
||||
@@ -540,7 +564,7 @@ Public Class FormMain
|
||||
If ReturnCode = ProcessReturnValues.Exception Then
|
||||
If Not IsLogShown Then
|
||||
FeedbackInfo()
|
||||
Log("请在 https://github.com/Hex-Dragon/PCL2/issues 提交错误报告,以便于作者解决此问题!")
|
||||
Log("请在 https://github.com/Meloong-Git/PCL/issues 提交错误报告,以便于作者解决此问题!")
|
||||
IsLogShown = True
|
||||
ShellOnly(Path & "PCL\Log1.txt")
|
||||
End If
|
||||
@@ -591,11 +615,12 @@ Public Class FormMain
|
||||
'按键事件
|
||||
Private Sub FormMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||
If e.IsRepeat Then Return
|
||||
'调用弹窗:回车选择第一个,Esc 选择最后一个
|
||||
If PanMsg.Children.Count > 0 Then
|
||||
'修复按下 Alt 后误认为弹出系统菜单导致的冻结
|
||||
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
|
||||
CType(PanMsg.Children(0), Object).Btn1_Click()
|
||||
Return
|
||||
ElseIf e.Key = Key.Escape Then
|
||||
Dim Msg As Object = PanMsg.Children(0)
|
||||
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
||||
@@ -605,9 +630,14 @@ Public Class FormMain
|
||||
Else
|
||||
Msg.Btn1_Click()
|
||||
End If
|
||||
Return
|
||||
End If
|
||||
Return
|
||||
End If
|
||||
|
||||
'==========================
|
||||
' 在没有弹窗时:继续检查……
|
||||
'==========================
|
||||
|
||||
'按 ESC 返回上一级
|
||||
If e.Key = Key.Escape Then TriggerPageBack()
|
||||
'更改隐藏版本可见性
|
||||
@@ -641,8 +671,6 @@ Public Class FormMain
|
||||
FrmLaunchLeft.LaunchButtonClick()
|
||||
End If
|
||||
End If
|
||||
'修复按下 Alt 后误认为弹出系统菜单导致的冻结
|
||||
If e.SystemKey = Key.LeftAlt OrElse e.SystemKey = Key.RightAlt Then e.Handled = True
|
||||
End Sub
|
||||
Private Sub FormMain_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseDown
|
||||
'鼠标侧键返回上一级
|
||||
@@ -707,6 +735,7 @@ Public Class FormMain
|
||||
End Sub
|
||||
Private Sub FrmMain_Drop(sender As Object, e As DragEventArgs) Handles Me.Drop
|
||||
Try
|
||||
ShowWindowToTop()
|
||||
If e.Data.GetDataPresent(DataFormats.Text) Then
|
||||
'获取文本
|
||||
Try
|
||||
|
||||
@@ -13,13 +13,13 @@ Public Module ModBase
|
||||
#Region "声明"
|
||||
|
||||
'下列版本信息由更新器自动修改
|
||||
Public Const VersionBaseName As String = "2.10.3" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.10.3." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const VersionBaseName As String = "2.10.5" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.10.5." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
||||
#If BETA Then
|
||||
Public Const VersionCode As Integer = 361 'Release
|
||||
#Else
|
||||
Public Const VersionCode As Integer = 362 'Snapshot
|
||||
Public Const VersionCode As Integer = 364 'Snapshot
|
||||
#End If
|
||||
'自动生成的版本信息
|
||||
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
||||
@@ -1551,7 +1551,7 @@ RetryDir:
|
||||
''' <summary>
|
||||
''' 获取 JSON 对象。
|
||||
''' </summary>
|
||||
Public Function GetJson(Data As String)
|
||||
Public Function GetJson(Data As String) As JToken
|
||||
Try
|
||||
Return JsonConvert.DeserializeObject(Data, New JsonSerializerSettings With {.DateTimeZoneHandling = DateTimeZoneHandling.Local})
|
||||
Catch ex As Exception
|
||||
@@ -2131,6 +2131,19 @@ RetryDir:
|
||||
End Function
|
||||
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>
|
||||
@@ -2179,10 +2192,10 @@ RetryDir:
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 判断当前系统语言是否为 zh-CN。
|
||||
''' 判断当前系统语言是否为中文。
|
||||
''' </summary>
|
||||
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
|
||||
|
||||
Private Uuid As Integer = 1
|
||||
@@ -2225,6 +2238,9 @@ NextElement:
|
||||
Next i
|
||||
Return ResultArray
|
||||
End Function
|
||||
<Extension> Public Function Any(Arr As UIElementCollection) As Boolean
|
||||
Return Arr?.Count > 0
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 获取格式类似于“11:08:52.037”的当前时间的字符串。
|
||||
@@ -2462,7 +2478,7 @@ NextElement:
|
||||
''' </summary>
|
||||
Public Sub RunInThread(Action As Action)
|
||||
If RunInUi() Then
|
||||
RunInNewThread(Action, "Runtime Invoke " & GetUuid() & "#")
|
||||
RunInNewThread(Action, "Invoke " & GetUuid())
|
||||
Else
|
||||
Action()
|
||||
End If
|
||||
@@ -2760,11 +2776,11 @@ Retry:
|
||||
Using Reader As New XamlXmlReader(Stream)
|
||||
While Reader.Read()
|
||||
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.Value IsNot Nothing AndAlso Reader.Value = BlackListType.Name 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} 值。")
|
||||
Next
|
||||
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
|
||||
End While
|
||||
End Using
|
||||
@@ -2922,7 +2938,7 @@ Retry:
|
||||
'处理错误会导致再次调用 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
|
||||
SyncLock LogListLock
|
||||
LogList.Append(AppendText)
|
||||
@@ -2986,7 +3002,7 @@ Retry:
|
||||
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
|
||||
SyncLock LogListLock
|
||||
LogList.Append(AppendText)
|
||||
@@ -3048,7 +3064,7 @@ Retry:
|
||||
If ForceOpenLog OrElse (ShowMsgbox AndAlso MyMsgBox("若你在汇报一个 Bug,请点击 打开文件夹 按钮,并上传 Log(1~5).txt 中包含错误信息的文件。" & vbCrLf & "游戏崩溃一般与启动器无关,请不要因为游戏崩溃而提交反馈。", "反馈提交提醒", "打开文件夹", "不需要") = 1) Then
|
||||
OpenExplorer(Path & "PCL\Log1.txt")
|
||||
End If
|
||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/issues/")
|
||||
OpenWebsite("https://github.com/Meloong-Git/PCL/issues/")
|
||||
End Sub
|
||||
Public Function CanFeedback(ShowHint As Boolean) As Boolean
|
||||
If False.Equals(PageSetupSystem.IsLauncherNewest) Then
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
[Error] = ex
|
||||
State = LoadState.Failed
|
||||
End Try
|
||||
End Sub) With {.Name = Name, .Priority = ThreadPriority}
|
||||
End Sub) With {.Name = "L/" & Name, .Priority = ThreadPriority}
|
||||
LastRunningThread.Start() '不能使用 RunInNewThread,否则在函数返回前线程就会运行完,导致误判 IsAborted
|
||||
End Sub
|
||||
Public Overrides Sub Abort()
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1076,7 +1076,7 @@ Retry:
|
||||
Try
|
||||
'获取工程列表
|
||||
Log("[Comp] 开始从 CurseForge 获取工程列表:" & CurseForgeUrl)
|
||||
Dim RequestResult As JObject = DlModRequest(CurseForgeUrl, IsJson:=True)
|
||||
Dim RequestResult As JObject = DlModRequest(CurseForgeUrl)
|
||||
Task.Progress += 0.2
|
||||
Dim ProjectList As New List(Of CompProject)
|
||||
For Each JsonEntry As JObject In RequestResult("data")
|
||||
@@ -1107,7 +1107,7 @@ Retry:
|
||||
Sub()
|
||||
Try
|
||||
Log("[Comp] 开始从 Modrinth 获取工程列表:" & ModrinthUrl)
|
||||
Dim RequestResult As JObject = DlModRequest(ModrinthUrl, IsJson:=True)
|
||||
Dim RequestResult As JObject = DlModRequest(ModrinthUrl)
|
||||
Task.Progress += 0.2
|
||||
Dim ProjectList As New List(Of CompProject)
|
||||
For Each JsonEntry As JObject In RequestResult("hits")
|
||||
@@ -1137,6 +1137,11 @@ Retry:
|
||||
If ModrinthThread IsNot Nothing Then ModrinthThread.Join()
|
||||
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
|
||||
If Not RawResults.Any() Then
|
||||
@@ -1167,11 +1172,6 @@ Retry:
|
||||
ModrinthThread?.Interrupt()
|
||||
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
|
||||
|
||||
#Region "提取非重复项,存储于 RealResults"
|
||||
@@ -1396,7 +1396,7 @@ Retry:
|
||||
'DownloadAddress
|
||||
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}"
|
||||
Url = Url.Replace(FileName, Net.WebUtility.UrlEncode(FileName)) '对文件名进行编码
|
||||
Url = Url.Replace(FileName, WebUtility.UrlEncode(FileName)) '对文件名进行编码
|
||||
DownloadUrls = HandleCurseForgeDownloadUrls(Url) '对脑残 CurseForge 的下载地址进行多种修正
|
||||
DownloadUrls.AddRange(DownloadUrls.Select(Function(u) DlSourceModGet(u)).ToList) '添加镜像源,这个写法是为了让镜像源排在后面
|
||||
DownloadUrls = DownloadUrls.Distinct.ToList '最终去重
|
||||
@@ -1492,9 +1492,8 @@ Retry:
|
||||
Return {
|
||||
Url.Replace("-service.overwolf.wtf", ".forgecdn.net").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("://edge.", "://media."),
|
||||
Url.Replace("://media.", "://edge."),
|
||||
Url
|
||||
}.Distinct.ToList
|
||||
End Function
|
||||
@@ -1591,27 +1590,40 @@ Retry:
|
||||
If CompProjectCache.ContainsKey(ProjectId) Then '存在缓存
|
||||
TargetProject = CompProjectCache(ProjectId)
|
||||
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
|
||||
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
|
||||
'获取工程对象的文件列表
|
||||
If Not CompFilesCache.ContainsKey(ProjectId) Then '有缓存也不能直接返回,这时候前置可能没获取(#5173)
|
||||
Log("[Comp] 开始获取文件列表:" & ProjectId)
|
||||
Dim ResultJsonArray As JArray
|
||||
Dim ResultJsonArray As JArray = Nothing
|
||||
If FromCurseForge Then
|
||||
'CurseForge
|
||||
'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 使用每个版本最新的文件
|
||||
' ResultJsonArray = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json"))("data")
|
||||
'Else '否则使用全部文件
|
||||
' ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999", IsJson:=True)("data")
|
||||
'End If
|
||||
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)
|
||||
'之前只请求一部分文件的方法备份如下:
|
||||
'If TargetProject.Type = CompType.Mod Then 'Mod 使用每个版本最新的文件
|
||||
' ResultJsonArray = DlModRequest("https://api.curseforge.com/v1/mods/files", HttpMethod.Post, "{""fileIds"": [" & Join(TargetProject.CurseForgeFileIds, ",") & "]}", "application/json")("data")
|
||||
'Else '否则使用全部文件
|
||||
' ResultJsonArray = DlModRequest($"https://api.curseforge.com/v1/mods/{ProjectId}/files?pageSize=999")("data")
|
||||
'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
|
||||
'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
|
||||
CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
|
||||
Where(Function(a) a.Available).ToList.
|
||||
@@ -1625,10 +1637,10 @@ Retry:
|
||||
Log($"[Comp] {ProjectId} 文件列表中还需要获取信息的前置:{Join(UndoneDeps, ",")}")
|
||||
Dim Projects As JArray
|
||||
If TargetProject.FromCurseForge Then
|
||||
Projects = GetJson(DlModRequest("https://api.curseforge.com/v1/mods",
|
||||
"POST", "{""modIds"": [" & Join(UndoneDeps, ",") & "]}", "application/json"))("data")
|
||||
Projects = DlModRequest("https://api.curseforge.com/v1/mods",
|
||||
HttpMethod.Post, "{""modIds"": [" & Join(UndoneDeps, ",") & "]}", "application/json")("data")
|
||||
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
|
||||
For Each Project In Projects
|
||||
Dim Unused As New CompProject(Project) '在 New 的时候会添加缓存以便之后读取
|
||||
|
||||
@@ -1018,9 +1018,9 @@ NextStack:
|
||||
End If
|
||||
Case CrashReason.特定实体导致崩溃
|
||||
If Additional.Count = 1 Then
|
||||
Results.Add("游戏似乎因为实体 " & Additional.First & " 出现了问题。\n\n你可以创建一个新世界,并生成一个该实体,然后观察游戏的运行情况:\n - 若正常运行,则是该实体导致出错,你或许需要使用一些方式删除此实体。\n - 若仍然出错,问题就可能来自其他原因……\h")
|
||||
Results.Add("游戏似乎因为实体 " & Additional.First & " 出现了问题。\n\n你可以创建一个新世界,并生成一个该实体,然后观察游戏的运行情况。\h")
|
||||
Else
|
||||
Results.Add("游戏似乎因为世界中的某些实体出现了问题。\n\n你可以创建一个新世界,并生成各种实体,观察游戏的运行情况:\n - 若正常运行,则是某些实体导致出错,你或许需要删除该世界。\n - 若仍然出错,问题就可能来自其他原因……\h")
|
||||
Results.Add("游戏似乎因为世界中的某些实体出现了问题。\n\n你可以创建一个新世界,并生成各种实体,然后观察游戏的运行情况。\h")
|
||||
End If
|
||||
Case CrashReason.OptiFine与Forge不兼容
|
||||
Results.Add("由于 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n\n请前往 OptiFine 官网(https://optifine.net/downloads)查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏。")
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
Private IsNewClientVersionHinted As Boolean = False
|
||||
Private Sub DlClientListMojangMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
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
|
||||
Dim Versions As JArray = Json("versions")
|
||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||
@@ -235,7 +235,7 @@
|
||||
''' </summary>
|
||||
Public DlClientListBmclapiLoader As New LoaderTask(Of String, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
||||
Private Sub DlClientListBmclapiMain(Loader As LoaderTask(Of String, DlClientListResult))
|
||||
Dim Json As JObject = 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
|
||||
Dim Versions As JArray = Json("versions")
|
||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||
@@ -377,7 +377,7 @@
|
||||
''' </summary>
|
||||
Public DlOptiFineListOfficialLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Official", AddressOf DlOptiFineListOfficialMain)
|
||||
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 & ")")
|
||||
Try
|
||||
'获取所有版本信息
|
||||
@@ -413,7 +413,7 @@
|
||||
''' </summary>
|
||||
Public DlOptiFineListBmclapiLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Bmclapi", AddressOf DlOptiFineListBmclapiMain)
|
||||
Private Sub DlOptiFineListBmclapiMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/optifine/versionList", IsJson:=True)
|
||||
Dim Json As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/optifine/versionList"))
|
||||
Try
|
||||
Dim Versions As New List(Of DlOptiFineListEntry)
|
||||
For Each Token As JObject In Json
|
||||
@@ -483,7 +483,7 @@
|
||||
''' </summary>
|
||||
Public DlForgeListOfficialLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Official", AddressOf DlForgeListOfficialMain)
|
||||
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 & ")")
|
||||
'获取所有版本信息
|
||||
Dim Names As List(Of String) = RegexSearch(Result, "(?<=a href=""index_)[0-9.]+(_pre[0-9]?)?(?=.html)")
|
||||
@@ -497,7 +497,7 @@
|
||||
''' </summary>
|
||||
Public DlForgeListBmclapiLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Bmclapi", AddressOf DlForgeListBmclapiMain)
|
||||
Private Sub DlForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
||||
Dim Result As 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 & ")")
|
||||
'获取所有版本信息
|
||||
Dim Names As List(Of String) = RegexSearch(Result, "[0-9.]+(_pre[0-9]?)?")
|
||||
@@ -629,7 +629,7 @@
|
||||
Public Sub DlForgeVersionOfficialMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
||||
Dim Result As String
|
||||
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
|
||||
".html", UseBrowserUserAgent:=True)
|
||||
Catch ex As Exception
|
||||
@@ -700,9 +700,8 @@
|
||||
''' Forge 版本列表,BMCLAPI。
|
||||
''' </summary>
|
||||
Public Sub DlForgeVersionBmclapiMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
|
||||
Loader.Input.Replace("-", "_"), '兼容 Forge 1.7.10-pre4,#4057
|
||||
IsJson:=True)
|
||||
Dim Json As JArray = GetJson(NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" &
|
||||
Loader.Input.Replace("-", "_"))) '兼容 Forge 1.7.10-pre4,#4057
|
||||
Dim Versions As New List(Of DlForgeVersionEntry)
|
||||
Try
|
||||
Dim Recommended As String = McDownloadForgeRecommendedGet(Loader.Input)
|
||||
@@ -836,8 +835,8 @@
|
||||
Public DlNeoForgeListOfficialLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Official", AddressOf DlNeoForgeListOfficialMain)
|
||||
Private Sub DlNeoForgeListOfficialMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
|
||||
'获取版本列表 JSON
|
||||
Dim ResultLatest As String = NetGetCodeByLoader("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge", UseBrowserUserAgent:=True, IsJson:=True)
|
||||
Dim ResultLegacy As String = NetGetCodeByLoader("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/forge", UseBrowserUserAgent:=True, IsJson:=True)
|
||||
Dim ResultLatest As String = NetRequestByClientRetry("https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge")
|
||||
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 & ")")
|
||||
'解析
|
||||
Try
|
||||
@@ -854,8 +853,8 @@
|
||||
Public DlNeoForgeListBmclapiLoader As New LoaderTask(Of Integer, DlNeoForgeListResult)("DlNeoForgeList Bmclapi", AddressOf DlNeoForgeListBmclapiMain)
|
||||
Public Sub DlNeoForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlNeoForgeListResult))
|
||||
'获取版本列表 JSON
|
||||
Dim ResultLatest As String = NetGetCodeByLoader("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/neoforge", UseBrowserUserAgent:=True, IsJson:=True)
|
||||
Dim ResultLegacy As String = NetGetCodeByLoader("https://bmclapi2.bangbang93.com/neoforge/meta/api/maven/details/releases/net/neoforged/forge", 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 = 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 & ")")
|
||||
'解析
|
||||
Try
|
||||
@@ -960,7 +959,7 @@
|
||||
''' </summary>
|
||||
Public DlLiteLoaderListOfficialLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Official", AddressOf DlLiteLoaderListOfficialMain)
|
||||
Private Sub DlLiteLoaderListOfficialMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://dl.liteloader.com/versions/versions.json", IsJson:=True)
|
||||
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://dl.liteloader.com/versions/versions.json"))
|
||||
Try
|
||||
Dim Json As JObject = Result("versions")
|
||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||
@@ -988,7 +987,7 @@
|
||||
''' </summary>
|
||||
Public DlLiteLoaderListBmclapiLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Bmclapi", AddressOf DlLiteLoaderListBmclapiMain)
|
||||
Private Sub DlLiteLoaderListBmclapiMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||
Dim Result As JObject = 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
|
||||
Dim Json As JObject = Result("versions")
|
||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||
@@ -1059,7 +1058,7 @@
|
||||
''' </summary>
|
||||
Public DlFabricListOfficialLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Official", AddressOf DlFabricListOfficialMain)
|
||||
Private Sub DlFabricListOfficialMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://meta.fabricmc.net/v2/versions", IsJson:=True)
|
||||
Dim Result As JObject = GetJson(NetRequestByClientRetry("https://meta.fabricmc.net/v2/versions"))
|
||||
Try
|
||||
Dim Output = New DlFabricListResult With {.IsOfficial = True, .SourceName = "Fabric 官方源", .Value = Result}
|
||||
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
||||
@@ -1074,7 +1073,7 @@
|
||||
''' </summary>
|
||||
Public DlFabricListBmclapiLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Bmclapi", AddressOf DlFabricListBmclapiMain)
|
||||
Private Sub DlFabricListBmclapiMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||
Dim Result As JObject = 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
|
||||
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("获取到的列表缺乏必要项")
|
||||
@@ -1101,72 +1100,36 @@
|
||||
#Region "DlMod | Mod 镜像源请求"
|
||||
|
||||
''' <summary>
|
||||
''' 对可能涉及 Mod 镜像源的请求进行处理,返回字符串或 JObject。
|
||||
''' 调用 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 镜像源的请求进行处理。
|
||||
''' 对可能涉及 Mod 镜像源的请求进行处理,返回 JToken。
|
||||
''' 调用 NetRequest,会进行重试。
|
||||
''' </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))
|
||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 5))
|
||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 20))
|
||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 10)) '至少 10s,要不然有时候远端服务器来不及完成
|
||||
Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||
'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))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||
' 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)(Url, 10))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
|
||||
' 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))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 10))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(Url, 30))
|
||||
' Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 30))
|
||||
' End Select
|
||||
'End If
|
||||
Dim Exs As String = ""
|
||||
For Each Source In Urls
|
||||
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
|
||||
Exs += ex.Message + vbCrLf
|
||||
End Try
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
If Output = "" Then Throw New ApplicationException("尝试运行该 Java 失败")
|
||||
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("a fatal error") Then Throw New ApplicationException("无法运行该 Java,该 Java 或系统存在问题")
|
||||
'获取详细信息
|
||||
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"
|
||||
@@ -459,10 +460,12 @@ NoUserJava:
|
||||
''' 将 Java 按照适用性排序。
|
||||
''' </summary>
|
||||
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 文件夹
|
||||
Dim ProgramPathParent As String, MinecraftPathParent As String = ""
|
||||
ProgramPathParent = If(New DirectoryInfo(Path).Parent, New DirectoryInfo(Path)).FullName
|
||||
If PathMcFolder <> "" Then MinecraftPathParent = If(New DirectoryInfo(PathMcFolder).Parent, New DirectoryInfo(PathMcFolder)).FullName
|
||||
ProgramPathParent = If(PathInfo.Parent, PathInfo).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 Not Left.PathFolder.StartsWithF(ProgramPathParent) AndAlso Right.PathFolder.StartsWithF(ProgramPathParent) Then Return False
|
||||
If PathMcFolder <> "" Then
|
||||
@@ -529,6 +532,8 @@ NoUserJava:
|
||||
If Disk.DriveType = DriveType.Network Then Continue For '跳过网络驱动器(#3705)
|
||||
JavaSearchFolder(Disk.Name, JavaPreList, False)
|
||||
Next
|
||||
'查找 .jdks 文件夹中的 Java
|
||||
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\.jdks\", JavaPreList, False)
|
||||
'查找 APPDATA 文件夹中的 Java
|
||||
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\", JavaPreList, False)
|
||||
JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\", JavaPreList, False)
|
||||
@@ -677,8 +682,8 @@ Wait:
|
||||
'若该目录有 Java,则加入结果
|
||||
If File.Exists(Path & "javaw.exe") Then Results(Path) = Source
|
||||
'查找其下的所有文件夹
|
||||
'不应使用网易的 Java:https://github.com/Hex-Dragon/PCL2/issues/1279#issuecomment-2761489121
|
||||
Dim Keywords = {"java", "jdk", "env", "环境", "run", "软件", "jre", "mc", "dragon",
|
||||
'不应使用网易的 Java:https://github.com/Meloong-Git/PCL/issues/1279#issuecomment-2761489121
|
||||
Dim Keywords = {"java", "jdk", "env", "环境", "run", "软件", "jre", "mc", "dragon", "bin",
|
||||
"soft", "cache", "temp", "corretto", "roaming", "users", "craft", "program", "世界", "net",
|
||||
"游戏", "oracle", "game", "file", "data", "jvm", "服务", "server", "客户", "client", "整合",
|
||||
"应用", "运行", "前置", "mojang", "官启", "新建文件夹", "eclipse", "microsoft", "hotspot",
|
||||
@@ -745,7 +750,7 @@ Wait:
|
||||
Private LastJavaBaseDir As String = Nothing '用于在下载中断或失败时删除未完成下载的 Java 文件夹,防止残留只下了一半但 -version 能跑的 Java
|
||||
Private Sub JavaFileList(Loader As LoaderTask(Of Integer, List(Of NetFile)))
|
||||
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://bmclapi2.bangbang93.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"}
|
||||
), IsJson:=True)
|
||||
@@ -757,7 +762,7 @@ Wait:
|
||||
Dim Address As String = TargetEntry.Value("manifest")("url")
|
||||
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 & "\"
|
||||
Dim Results As New List(Of NetFile)
|
||||
For Each File As JProperty In CType(GetJson(ListFileStr), JObject)("files")
|
||||
|
||||
@@ -684,11 +684,10 @@ LoginFinish:
|
||||
'发送登录请求
|
||||
Dim RequestData As New JObject(
|
||||
New JProperty("accessToken", AccessToken), New JProperty("clientToken", ClientToken), New JProperty("requestUser", True))
|
||||
NetRequestRetry(
|
||||
Url:=Data.Input.BaseUrl & "/validate",
|
||||
Method:="POST",
|
||||
Data:=RequestData.ToString(0),
|
||||
Headers:=New Dictionary(Of String, String) From {{"Accept-Language", "zh-CN"}},
|
||||
NetRequestByClientRetry(
|
||||
Data.Input.BaseUrl & "/validate", HttpMethod.Post,
|
||||
Content:=RequestData.ToString(Newtonsoft.Json.Formatting.None),
|
||||
Headers:={{"Accept-Language", "zh-CN"}},
|
||||
ContentType:="application/json; charset=utf-8") '没有返回值的
|
||||
'将登录结果输出
|
||||
Data.Output.AccessToken = AccessToken
|
||||
@@ -701,10 +700,9 @@ LoginFinish:
|
||||
End Sub
|
||||
Private Sub McLoginRequestRefresh(ByRef Data As LoaderTask(Of McLoginServer, McLoginResult), RequestUser As Boolean)
|
||||
McLaunchLog("刷新登录开始(Refresh, " & Data.Input.Token & ")")
|
||||
Dim LoginJson As JObject = GetJson(NetRequestRetry(
|
||||
Url:=Data.Input.BaseUrl & "/refresh",
|
||||
Method:="POST",
|
||||
Data:=New JObject(
|
||||
Dim LoginJson As JObject = GetJson(NetRequestByClientRetry(
|
||||
Data.Input.BaseUrl & "/refresh", HttpMethod.Post,
|
||||
Content:=New JObject(
|
||||
New JProperty("selectedProfile", New JObject(
|
||||
New JProperty("name", Setup.Get($"Cache{Data.Input.Token}Name")),
|
||||
New JProperty("id", Setup.Get($"Cache{Data.Input.Token}Uuid"))
|
||||
@@ -712,7 +710,7 @@ LoginFinish:
|
||||
New JProperty("accessToken", Setup.Get($"Cache{Data.Input.Token}Access")),
|
||||
New JProperty("requestUser", True)
|
||||
).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"))
|
||||
'将登录结果输出
|
||||
If LoginJson("selectedProfile") Is Nothing Then Throw New Exception("选择的角色 " & Setup.Get("Cache" & Data.Input.Token & "Name") & " 无效!")
|
||||
@@ -739,11 +737,10 @@ LoginFinish:
|
||||
New JProperty("username", Data.Input.UserName),
|
||||
New JProperty("password", Data.Input.Password),
|
||||
New JProperty("requestUser", True))
|
||||
Dim LoginJson As JObject = GetJson(NetRequestRetry(
|
||||
Url:=Data.Input.BaseUrl & "/authenticate",
|
||||
Method:="POST",
|
||||
Data:=RequestData.ToString(0),
|
||||
Headers:=New Dictionary(Of String, String) From {{"Accept-Language", "zh-CN"}},
|
||||
Dim LoginJson As JObject = GetJson(NetRequestByClientRetry(
|
||||
Data.Input.BaseUrl & "/authenticate", HttpMethod.Post,
|
||||
Content:=RequestData.ToString(Newtonsoft.Json.Formatting.None),
|
||||
Headers:={{"Accept-Language", "zh-CN"}},
|
||||
ContentType:="application/json; charset=utf-8"))
|
||||
'检查登录结果
|
||||
If LoginJson("availableProfiles").Count = 0 Then
|
||||
@@ -858,8 +855,9 @@ LoginFinish:
|
||||
'初始请求
|
||||
Retry:
|
||||
McLaunchLog("开始微软登录步骤 1/6(原始登录)")
|
||||
Dim PrepareJson As JObject = GetJson(NetRequestRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
|
||||
$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded"))
|
||||
Dim PrepareJson As JObject = GetJson(NetRequestByClientRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", HttpMethod.Post,
|
||||
Content:=$"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access",
|
||||
ContentType:="application/x-www-form-urlencoded"))
|
||||
McLaunchLog("网页登录地址:" & PrepareJson("verification_uri").ToString)
|
||||
|
||||
'弹窗
|
||||
@@ -888,9 +886,11 @@ Retry:
|
||||
|
||||
Dim Result As String
|
||||
Try
|
||||
Result = NetRequestMultiple("https://login.live.com/oauth20_token.srf", "POST",
|
||||
$"client_id={OAuthClientId}&refresh_token={Uri.EscapeDataString(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
||||
"application/x-www-form-urlencoded", 2)
|
||||
Result = NetRequestByClientMultiple("https://login.live.com/oauth20_token.srf", HttpMethod.Post,
|
||||
Content:=$"client_id={OAuthClientId}&refresh_token={Uri.EscapeDataString(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
|
||||
ContentType:="application/x-www-form-urlencoded",
|
||||
Headers:={{"Accept-Language", "en-US,en;q=0.5"}, {"X-Requested-With", "XMLHttpRequest"}},
|
||||
ThreadCount:=2)
|
||||
Catch ex As Exception
|
||||
If ex.Message.ContainsF("must sign in again", True) OrElse ex.Message.ContainsF("password expired", True) OrElse
|
||||
(ex.Message.Contains("refresh_token") AndAlso ex.Message.Contains("is not valid")) Then '#269
|
||||
@@ -918,8 +918,8 @@ Retry:
|
||||
""RelyingParty"": ""http://auth.xboxlive.com"",
|
||||
""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 XBLToken As String = ResultJson("Token").ToString
|
||||
Return XBLToken
|
||||
@@ -940,7 +940,8 @@ Retry:
|
||||
}"
|
||||
Dim Result As String
|
||||
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,
|
||||
Content:=Request, ContentType:="application/json")
|
||||
Catch ex As Net.WebException
|
||||
'参考 https://github.com/PrismarineJS/prismarine-auth/blob/master/src/common/Constants.js
|
||||
If ex.Message.Contains("2148916227") Then
|
||||
@@ -971,10 +972,15 @@ Retry:
|
||||
End If
|
||||
End Try
|
||||
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim XSTSToken As String = ResultJson("Token").ToString
|
||||
Dim UHS As String = ResultJson("DisplayClaims")("xui")(0)("uhs").ToString
|
||||
Return {XSTSToken, UHS}
|
||||
Try '这个 Try 块仅为了追踪 #6683 而添加
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
Dim XSTSToken As String = ResultJson("Token").ToString
|
||||
Dim UHS As String = ResultJson("DisplayClaims")("xui")(0)("uhs").ToString
|
||||
Return {XSTSToken, UHS}
|
||||
Catch
|
||||
Log("[Launch] 返回内容:" & vbCrLf & Result)
|
||||
Throw
|
||||
End Try
|
||||
End Function
|
||||
'微软登录步骤 4:从 {XSTSToken, UHS} 获取 Minecraft AccessToken
|
||||
Private Function MsLoginStep4(Tokens As String()) As String
|
||||
@@ -983,14 +989,15 @@ Retry:
|
||||
Dim Request As String = New JObject(New JProperty("identityToken", $"XBL3.0 x={Tokens(1)};{Tokens(0)}")).ToString(0)
|
||||
Dim Result As String
|
||||
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
|
||||
Dim Message As String = GetExceptionSummary(ex)
|
||||
If Message.Contains("(429)") Then
|
||||
Log(ex, "微软登录第 5 步汇报 429")
|
||||
Log(ex, "微软登录第 4 步汇报 429")
|
||||
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
||||
ElseIf Message.Contains("(403)") Then
|
||||
Log(ex, "微软登录第 5 步汇报 403")
|
||||
Log(ex, "微软登录第 4 步汇报 403")
|
||||
Throw New Exception("$当前 IP 的登录尝试异常。" & vbCrLf & "如果你使用了 VPN 或加速器,请把它们关掉或更换节点后再试!")
|
||||
Else
|
||||
Throw
|
||||
@@ -1005,7 +1012,8 @@ Retry:
|
||||
Private Sub MsLoginStep5(AccessToken As String)
|
||||
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
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
If Not (ResultJson.ContainsKey("items") AndAlso ResultJson("items").Any) Then
|
||||
@@ -1016,7 +1024,7 @@ Retry:
|
||||
Throw New Exception("$$")
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "微软登录第 6 步异常:" & Result)
|
||||
Log(ex, "微软登录第 5 步异常:" & Result)
|
||||
Throw
|
||||
End Try
|
||||
End Sub
|
||||
@@ -1026,14 +1034,15 @@ Retry:
|
||||
|
||||
Dim Result As String
|
||||
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
|
||||
Dim Message As String = GetExceptionSummary(ex)
|
||||
If Message.Contains("(429)") Then
|
||||
Log(ex, "微软登录第 7 步汇报 429")
|
||||
Log(ex, "微软登录第 6 步汇报 429")
|
||||
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
||||
ElseIf Message.Contains("(404)") Then
|
||||
Log(ex, "微软登录第 7 步汇报 404")
|
||||
Log(ex, "微软登录第 6 步汇报 404")
|
||||
RunInNewThread(
|
||||
Sub()
|
||||
Select Case MyMsgBox("请先创建 Minecraft 玩家档案,然后再重新登录。", "登录失败", "创建档案", "取消")
|
||||
@@ -1099,7 +1108,7 @@ Retry:
|
||||
If Len(Uuid) = 32 Then Return Uuid
|
||||
'从官网获取
|
||||
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 & ")")
|
||||
Uuid = If(GotJson("id"), "")
|
||||
Catch ex As Exception
|
||||
@@ -1205,6 +1214,12 @@ Retry:
|
||||
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
|
||||
'至少 Java 8u101
|
||||
@@ -1356,16 +1371,6 @@ Retry:
|
||||
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
|
||||
Arguments = Arguments.Replace(" -Dos.name=Windows 10", " -Dos.name=""Windows 10""")
|
||||
'全屏
|
||||
@@ -1374,31 +1379,47 @@ Retry:
|
||||
For Each Arg In CurrentLaunchOptions.ExtraArgs
|
||||
Arguments += " " & Arg.Trim
|
||||
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)
|
||||
If Server.Length > 0 Then
|
||||
If McVersionCurrent.ReleaseTime > New Date(2023, 4, 4) Then
|
||||
'QuickPlay
|
||||
Arguments += $" --quickPlayMultiplayer ""{Server}"""
|
||||
FinalArguments += $" --quickPlayMultiplayer ""{Server}"""
|
||||
Else
|
||||
'老版本
|
||||
If Server.Contains(":") Then
|
||||
'包含端口号
|
||||
Arguments += " --server " & Server.Split(":")(0) & " --port " & Server.Split(":")(1)
|
||||
FinalArguments += $" --server {Server.Split(":")(0)} --port {Server.Split(":")(1)}"
|
||||
Else
|
||||
'不包含端口号
|
||||
Arguments += " --server " & Server & " --port 25565"
|
||||
FinalArguments += $" --server {Server} --port 25565"
|
||||
End If
|
||||
If McVersionCurrent.Version.HasOptiFine Then Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
|
||||
End If
|
||||
End If
|
||||
'自定义
|
||||
Dim ArgumentGame As String = Setup.Get("VersionAdvanceGame", Version:=McVersionCurrent)
|
||||
Arguments += " " & If(ArgumentGame = "", Setup.Get("LaunchAdvanceGame"), ArgumentGame)
|
||||
'输出
|
||||
McLaunchLog("Minecraft 启动参数:")
|
||||
McLaunchLog(Arguments)
|
||||
McLaunchArgument = Arguments
|
||||
McLaunchLog(FinalArguments)
|
||||
McLaunchArgument = FinalArguments
|
||||
End Sub
|
||||
|
||||
'Jvm 部分(第一段)
|
||||
@@ -1424,11 +1445,12 @@ Retry:
|
||||
End If
|
||||
'Authlib-Injector
|
||||
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,
|
||||
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
||||
Setup.Get("VersionServerAuthServer", McVersionCurrent))
|
||||
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 &
|
||||
" -Dauthlibinjector.side=client" &
|
||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||
@@ -1493,11 +1515,12 @@ NextVersion:
|
||||
End If
|
||||
'Authlib-Injector
|
||||
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,
|
||||
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
||||
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
||||
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 &
|
||||
" -Dauthlibinjector.side=client" &
|
||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||
@@ -1531,10 +1554,8 @@ NextVersion:
|
||||
DeDuplicateDataList.Add(CurrentEntry.Trim.Replace("McEmu= ", "McEmu="))
|
||||
Next
|
||||
|
||||
'#3511 的清理
|
||||
DeDuplicateDataList.Remove("-XX:MaxDirectMemorySize=256M")
|
||||
|
||||
'去重
|
||||
DeDuplicateDataList.Remove("-XX:MaxDirectMemorySize=256M") '#3511 的清理
|
||||
Dim Result As String = Join(DeDuplicateDataList.Distinct.ToList, " ")
|
||||
|
||||
'添加 MainClass
|
||||
|
||||
@@ -169,8 +169,8 @@ Public Module ModMinecraft
|
||||
_McVersionCurrent = value '由于有可能是 Nothing,导致无法初始化,才得这样弄一圈
|
||||
_McVersionLast = value
|
||||
If value Is Nothing Then Return
|
||||
'重置缓存的 Mod 文件夹
|
||||
PageDownloadCompDetail.CachedFolder = Nothing
|
||||
'重置缓存的下载文件夹
|
||||
PageDownloadCompDetail.CachedFolder.Clear()
|
||||
'统一通行证重判
|
||||
If AniControlEnabled = 0 AndAlso
|
||||
Setup.Get("VersionServerNide", Version:=value) <> Setup.Get("CacheNideServer") AndAlso
|
||||
@@ -440,6 +440,33 @@ VersionSearchFinish:
|
||||
''' </summary>
|
||||
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>
|
||||
''' 该版本的 Json 文本。
|
||||
''' </summary>
|
||||
@@ -452,17 +479,7 @@ VersionSearchFinish:
|
||||
Return TrimedJson.StartsWithF("{") AndAlso TrimedJson.EndsWithF("}")
|
||||
End Function
|
||||
If _JsonText Is Nothing Then
|
||||
Dim JsonPath As String = Path & Name & ".json"
|
||||
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
|
||||
Dim JsonPath As String = GetJsonPath()
|
||||
_JsonText = ReadFile(JsonPath)
|
||||
'如果 ReadFile 失败会返回空字符串;这可能是由于文件被临时占用,故延时后重试
|
||||
If Not FastJsonCheck(_JsonText) Then
|
||||
@@ -540,9 +557,15 @@ Recheck:
|
||||
'继续循环
|
||||
If Inherit.InheritVersion = InheritVersion Then Throw New Exception("版本依赖项出现嵌套:" & 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)
|
||||
_JsonObject = Inherit.JsonObject
|
||||
_JsonObject("libraries") = CurrentLib
|
||||
GoTo Recheck
|
||||
End If
|
||||
Catch ex As Exception
|
||||
@@ -580,20 +603,18 @@ Recheck:
|
||||
Get
|
||||
If Not JsonVersionInited Then
|
||||
JsonVersionInited = True
|
||||
If File.Exists(Path & Name & ".jar") Then
|
||||
Try
|
||||
Using JarArchive As New ZipArchive(New FileStream(Path & Name & ".jar", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
Dim VersionJson As ZipArchiveEntry = JarArchive.GetEntry("version.json")
|
||||
If VersionJson IsNot Nothing Then
|
||||
Using VersionJsonStream As New StreamReader(VersionJson.Open)
|
||||
_JsonVersion = GetJson(VersionJsonStream.ReadToEnd)
|
||||
End Using
|
||||
End If
|
||||
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))
|
||||
Dim VersionJson As ZipArchiveEntry = JarArchive.GetEntry("version.json")
|
||||
If VersionJson Is Nothing Then Exit Try
|
||||
Using VersionJsonStream As New StreamReader(VersionJson.Open)
|
||||
_JsonVersion = GetJson(VersionJsonStream.ReadToEnd)
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
Log(ex, "从版本 jar 中读取 version.json 失败")
|
||||
End Try
|
||||
End If
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
Log(ex, $"从版本 jar 中读取 version.json 失败({Path}{Name}.jar)")
|
||||
End Try
|
||||
End If
|
||||
Return _JsonVersion
|
||||
End Get
|
||||
@@ -1538,7 +1559,7 @@ OnLoaded:
|
||||
''' 要求玩家选择一个皮肤文件,并进行相关校验。
|
||||
''' </summary>
|
||||
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}
|
||||
@@ -1589,7 +1610,7 @@ OnLoaded:
|
||||
Case Else
|
||||
Throw New ArgumentException("皮肤地址种类无效:" & If(Type, "null"))
|
||||
End Select
|
||||
Dim SkinString = NetGetCodeByRequestRetry(Url & Uuid)
|
||||
Dim SkinString = NetRequestByClientRetry(Url & Uuid)
|
||||
If SkinString = "" Then Throw New Exception("皮肤返回值为空,可能是未设置自定义皮肤的用户")
|
||||
'处理皮肤地址
|
||||
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
|
||||
Throw New Exception("用户未设置自定义皮肤")
|
||||
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
|
||||
'保存缓存
|
||||
WriteIni(PathTemp & "Cache\Skin\Index" & Type & ".ini", Uuid, SkinValue)
|
||||
@@ -1627,9 +1649,9 @@ OnLoaded:
|
||||
Dim FileAddress As String = PathTemp & "Cache\Skin\" & GetHash(Address) & ".png"
|
||||
SyncLock McSkinDownloadLock
|
||||
If Not File.Exists(FileAddress) Then
|
||||
NetDownloadByClient(Address, FileAddress & NetDownloadEnd)
|
||||
NetDownloadByClient(Address, FileAddress & ".PCLDownloading")
|
||||
File.Delete(FileAddress)
|
||||
FileSystem.Rename(FileAddress & NetDownloadEnd, FileAddress)
|
||||
FileSystem.Rename(FileAddress & ".PCLDownloading", FileAddress)
|
||||
Log("[Minecraft] 皮肤下载成功:" & FileAddress)
|
||||
End If
|
||||
Return FileAddress
|
||||
@@ -1772,61 +1794,60 @@ OnLoaded:
|
||||
|
||||
'获取当前支持库列表
|
||||
Log("[Minecraft] 获取支持库列表:" & Version.Name)
|
||||
McLibListGet = McLibListGetWithJson(Version.JsonObject)
|
||||
If Not IncludeVersionJar Then Return McLibListGet
|
||||
Dim Result = McLibListGetWithJson(Version.JsonObject)
|
||||
|
||||
'需要添加原版 Jar
|
||||
Dim RealVersion As McVersion
|
||||
Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
|
||||
If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
|
||||
'HMCL 项直接使用自身的 Jar
|
||||
'根据 Inherit 获取最深层版本
|
||||
Dim OriginalVersion As McVersion = Version
|
||||
'1.17+ 的 Forge 不寻找 Inherit
|
||||
If Not ((Version.Version.HasForge OrElse Version.Version.HasNeoForge) AndAlso Version.Version.McCodeMain >= 17) Then
|
||||
Do Until OriginalVersion.InheritVersion = ""
|
||||
If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
|
||||
OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
|
||||
Loop
|
||||
If IncludeVersionJar Then
|
||||
Dim RealVersion As McVersion
|
||||
Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
|
||||
If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
|
||||
'HMCL 项直接使用自身的 Jar
|
||||
'根据 Inherit 获取最深层版本
|
||||
Dim OriginalVersion As McVersion = Version
|
||||
'1.17+ 的 Forge 不寻找 Inherit
|
||||
If Not ((Version.Version.HasForge OrElse Version.Version.HasNeoForge) AndAlso Version.Version.McCodeMain >= 17) Then
|
||||
Do Until OriginalVersion.InheritVersion = ""
|
||||
If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
|
||||
OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
|
||||
Loop
|
||||
End If
|
||||
'需要新建对象,否则后面的 Check 会导致 McVersionCurrent 的 State 变回 Original
|
||||
'复现:启动一个 Snapshot 版本
|
||||
RealVersion = New McVersion(OriginalVersion.Path)
|
||||
Else
|
||||
'Json 已提供 Jar 字段,使用该字段的信息
|
||||
RealVersion = New McVersion(RequiredJar)
|
||||
End If
|
||||
'需要新建对象,否则后面的 Check 会导致 McVersionCurrent 的 State 变回 Original
|
||||
'复现:启动一个 Snapshot 版本
|
||||
RealVersion = New McVersion(OriginalVersion.Path)
|
||||
Else
|
||||
'Json 已提供 Jar 字段,使用该字段的信息
|
||||
RealVersion = New McVersion(RequiredJar)
|
||||
Dim ClientUrl As String, ClientSHA1 As String
|
||||
'判断需求的版本是否存在
|
||||
'不能调用 RealVersion.Check(),可能会莫名其妙地触发 CheckPermission 正被另一进程使用,导致误判前置不存在
|
||||
If Not File.Exists(RealVersion.Path & RealVersion.Name & ".json") Then
|
||||
RealVersion = Version
|
||||
Log("[Minecraft] 可能缺少前置版本 " & RealVersion.Name & ",找不到对应的 json 文件", LogLevel.Debug)
|
||||
End If
|
||||
'获取详细下载信息
|
||||
If RealVersion.JsonObject("downloads") IsNot Nothing AndAlso RealVersion.JsonObject("downloads")("client") IsNot Nothing Then
|
||||
ClientUrl = RealVersion.JsonObject("downloads")("client")("url")
|
||||
ClientSHA1 = RealVersion.JsonObject("downloads")("client")("sha1")
|
||||
Else
|
||||
ClientUrl = Nothing
|
||||
ClientSHA1 = Nothing
|
||||
End If
|
||||
'把所需的原版 Jar 添加进去
|
||||
Result.Add(New McLibToken With {.LocalPath = RealVersion.Path & RealVersion.Name & ".jar", .Size = 0, .IsNatives = False, .Url = ClientUrl, .SHA1 = ClientSHA1})
|
||||
End If
|
||||
Dim ClientUrl As String, ClientSHA1 As String
|
||||
'判断需求的版本是否存在
|
||||
'不能调用 RealVersion.Check(),可能会莫名其妙地触发 CheckPermission 正被另一进程使用,导致误判前置不存在
|
||||
If Not File.Exists(RealVersion.Path & RealVersion.Name & ".json") Then
|
||||
RealVersion = Version
|
||||
Log("[Minecraft] 可能缺少前置版本 " & RealVersion.Name & ",找不到对应的 json 文件", LogLevel.Debug)
|
||||
End If
|
||||
'获取详细下载信息
|
||||
If RealVersion.JsonObject("downloads") IsNot Nothing AndAlso RealVersion.JsonObject("downloads")("client") IsNot Nothing Then
|
||||
ClientUrl = RealVersion.JsonObject("downloads")("client")("url")
|
||||
ClientSHA1 = RealVersion.JsonObject("downloads")("client")("sha1")
|
||||
Else
|
||||
ClientUrl = Nothing
|
||||
ClientSHA1 = Nothing
|
||||
End If
|
||||
'把所需的原版 Jar 添加进去
|
||||
McLibListGet.Add(New McLibToken With {.LocalPath = RealVersion.Path & RealVersion.Name & ".jar", .Size = 0, .IsNatives = False, .Url = ClientUrl, .SHA1 = ClientSHA1})
|
||||
|
||||
Return Result
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取 Minecraft 某一版本忽视继承的支持库列表,即结果中没有继承项。
|
||||
''' </summary>
|
||||
Public Function McLibListGetWithJson(JsonObject As JObject, Optional KeepSameNameDifferentVersionResult As Boolean = False, Optional CustomMcFolder As String = Nothing) As List(Of McLibToken)
|
||||
CustomMcFolder = If(CustomMcFolder, PathMcFolder)
|
||||
Dim BasicArray As New List(Of McLibToken)
|
||||
|
||||
'添加基础 Json 项
|
||||
Dim AllLibs As JArray = JsonObject("libraries")
|
||||
|
||||
'转换为 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)
|
||||
For i = Library.Properties.Count - 1 To 0 Step -1
|
||||
@@ -1945,8 +1966,7 @@ OnLoaded:
|
||||
Try
|
||||
Log("[Minecraft] 开始获取统一通行证下载信息")
|
||||
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
|
||||
DownloadInfo = GetJson(NetGetCodeByLoader({
|
||||
"https://auth.mc-user.com:233/" & Setup.Get("VersionServerNide", Version:=Version)}, IsJson:=True))
|
||||
DownloadInfo = GetJson(NetRequestByClientRetry("https://auth.mc-user.com:233/" & Setup.Get("VersionServerNide", Version:=Version)))
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取统一通行证下载信息失败")
|
||||
End Try
|
||||
@@ -1968,10 +1988,9 @@ OnLoaded:
|
||||
'获取下载信息
|
||||
Try
|
||||
Log("[Minecraft] 开始获取 Authlib-Injector 下载信息")
|
||||
DownloadInfo = GetJson(NetGetCodeByLoader({
|
||||
DownloadInfo = GetJson(NetRequestByClientRetry(
|
||||
"https://authlib-injector.yushi.moe/artifact/latest.json",
|
||||
"https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json"
|
||||
}, IsJson:=True))
|
||||
BackupUrl:="https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json"))
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取 Authlib-Injector 下载信息失败")
|
||||
End Try
|
||||
@@ -2016,12 +2035,16 @@ OnLoaded:
|
||||
'获取
|
||||
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
|
||||
'文件不符合,添加下载
|
||||
Dim Urls As New List(Of String)
|
||||
If Token.Url Is Nothing AndAlso Token.Name = "net.minecraftforge:forge:universal" Then
|
||||
'特判修复 Forge 部分 universal 文件缺失 URL(#5455)
|
||||
If Token.Url Is Nothing AndAlso Token.Name = "net.minecraftforge:forge:universal" Then '特判修复 Forge 部分 universal 文件缺失 URL(#5455)
|
||||
Token.Url = "https://maven.minecraftforge.net" & Token.LocalPath.Replace(CustomMcFolder & "libraries", "").Replace("\", "/")
|
||||
End If
|
||||
If Token.Url IsNot Nothing Then
|
||||
@@ -2193,16 +2216,16 @@ OnLoaded:
|
||||
Dim LocalPath As String
|
||||
If Json("map_to_resources") IsNot Nothing AndAlso Json("map_to_resources").ToObject(Of Boolean) Then
|
||||
'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
|
||||
'Virtual
|
||||
LocalPath = PathMcFolder & "assets\virtual\legacy\" & File.Name.Replace("/", "\")
|
||||
LocalPath = $"{PathMcFolder}assets\virtual\legacy\{File.Name}"
|
||||
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
|
||||
Result.Add(New McAssetsToken With {
|
||||
.LocalPath = LocalPath,
|
||||
.LocalPath = LocalPath.Replace("/", "\"),
|
||||
.SourcePath = File.Name,
|
||||
.Hash = File.Value("hash").ToString,
|
||||
.Size = File.Value("size").ToString
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Imports System.IO.Compression
|
||||
|
||||
Public Module ModMod
|
||||
Private Const LocalModCacheVersion As Integer = 7
|
||||
Private Const LocalModCacheVersion As Integer = 8
|
||||
|
||||
Public Class McMod
|
||||
|
||||
@@ -946,8 +946,8 @@ Finished:
|
||||
Try
|
||||
'步骤 1:获取 Hash 与对应的工程 ID
|
||||
Dim ModrinthHashes = Mods.Select(Function(m) m.ModrinthHash).ToList()
|
||||
Dim ModrinthVersion = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files", "POST",
|
||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")), JObject)
|
||||
Dim ModrinthVersion As JObject = DlModRequest("https://api.modrinth.com/v2/version_files", HttpMethod.Post,
|
||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")
|
||||
Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息")
|
||||
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
||||
If ModrinthVersion.Count = 0 Then Return
|
||||
@@ -967,9 +967,8 @@ Finished:
|
||||
Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息")
|
||||
'步骤 3:获取工程信息
|
||||
If Not ModrinthMapping.Any() Then Return
|
||||
Dim ModrinthProject = CType(GetJson(DlModRequest(
|
||||
$"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]",
|
||||
"GET", "", "application/json")), JArray)
|
||||
Dim ModrinthProject As JArray = DlModRequest(
|
||||
$"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]")
|
||||
For Each ProjectJson In ModrinthProject
|
||||
Dim Project As New CompProject(ProjectJson)
|
||||
For Each Entry In ModrinthMapping(Project.Id)
|
||||
@@ -978,9 +977,9 @@ Finished:
|
||||
Next
|
||||
Log($"[Mod] 已从 Modrinth 获取本地 Mod 信息,继续获取更新信息")
|
||||
'步骤 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"",
|
||||
""loaders"": [""{ModLoaders.Join(""",""").ToLower}""],""game_versions"": [""{McVersion}""]}}", "application/json")), JObject)
|
||||
""loaders"": [""{ModLoaders.Join(""",""").ToLower}""],""game_versions"": [""{McVersion}""]}}", "application/json")
|
||||
For Each Entry In Mods
|
||||
If Not ModrinthUpdate.ContainsKey(Entry.ModrinthHash) OrElse Entry.CompFile Is Nothing Then Continue For
|
||||
Dim UpdateFile As New CompFile(ModrinthUpdate(Entry.ModrinthHash), CompType.Mod)
|
||||
@@ -1015,8 +1014,8 @@ Finished:
|
||||
CurseForgeHashes.Add(Entry.CurseForgeHash)
|
||||
If Loader.IsAbortedWithThread(CurrentTaskThread) Then Return
|
||||
Next
|
||||
Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432", "POST",
|
||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer)
|
||||
Dim CurseForgeRaw As JContainer = DlModRequest("https://api.curseforge.com/v1/fingerprints/432", HttpMethod.Post,
|
||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")("data")("exactMatches")
|
||||
Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息")
|
||||
'步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系
|
||||
If Not CurseForgeRaw.Any() Then Return
|
||||
@@ -1038,8 +1037,8 @@ Finished:
|
||||
Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息")
|
||||
'步骤 3:获取工程信息
|
||||
If Not CurseForgeMapping.Any() Then Return
|
||||
Dim CurseForgeProject = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods", "POST",
|
||||
$"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")), JObject)("data")
|
||||
Dim CurseForgeProject = DlModRequest("https://api.curseforge.com/v1/mods", HttpMethod.Post,
|
||||
$"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")("data")
|
||||
Dim UpdateFileIds As New Dictionary(Of Integer, List(Of McMod)) 'FileId -> 本地 Mod 文件列表
|
||||
Dim FileIdToProjectSlug As New Dictionary(Of Integer, String)
|
||||
For Each ProjectJson In CurseForgeProject
|
||||
@@ -1079,8 +1078,8 @@ Finished:
|
||||
Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息")
|
||||
'步骤 4:获取更新文件信息
|
||||
If Not UpdateFileIds.Any() Then Return
|
||||
Dim CurseForgeFiles = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST",
|
||||
$"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")), JObject)("data")
|
||||
Dim CurseForgeFiles = DlModRequest("https://api.curseforge.com/v1/mods/files", HttpMethod.Post,
|
||||
$"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")("data")
|
||||
Dim UpdateFiles As New Dictionary(Of McMod, CompFile)
|
||||
For Each FileJson In CurseForgeFiles
|
||||
Dim File As New CompFile(FileJson, CompType.Mod)
|
||||
|
||||
@@ -244,7 +244,7 @@ Retry:
|
||||
'获取 Mod 下载信息
|
||||
ModDownloadLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
|
||||
Sub(Task As LoaderTask(Of Integer, JArray))
|
||||
Task.Output = GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json"))("data")
|
||||
Task.Output = DlModRequest("https://api.curseforge.com/v1/mods/files", HttpMethod.Post, "{""fileIds"": [" & Join(ModList, ",") & "]}", "application/json")("data")
|
||||
'如果文件已被删除,则 API 会跳过那一项
|
||||
If ModList.Count > Task.Output.Count Then Throw New Exception("整合包中的部分 Mod 版本已被 Mod 作者删除,所以没法继续安装了,请向整合包作者反馈该问题")
|
||||
End Sub) With {.ProgressWeight = ModList.Count / 10}) '每 10 Mod 需要 1s
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
Log("[Music] 已恢复播放")
|
||||
Try
|
||||
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?.Play()
|
||||
End Try
|
||||
|
||||
@@ -9,9 +9,9 @@ Friend Module ModSecret
|
||||
'在开源版的注册表与常规版的注册表隔离,以防数据冲突
|
||||
Public Const RegFolder As String = "PCLDebug"
|
||||
'用于微软登录的 ClientId
|
||||
Public Const OAuthClientId As String = ""
|
||||
Public OAuthClientId As String = If(Environment.GetEnvironmentVariable("PCL_MS_CLIENT_ID"), "")
|
||||
'CurseForge API Key
|
||||
Public Const CurseForgeAPIKey As String = ""
|
||||
Public CurseForgeAPIKey As String = If(Environment.GetEnvironmentVariable("PCL_CURSEFORGE_API_KEY"), "")
|
||||
|
||||
Friend Sub SecretOnApplicationStart()
|
||||
'提升 UI 线程优先级
|
||||
@@ -71,37 +71,23 @@ Friend Module ModSecret
|
||||
|
||||
#Region "网络鉴权"
|
||||
|
||||
Friend Function SecretCdnSign(UrlWithMark As String)
|
||||
Friend Function SecretCdnSign(UrlWithMark As String) As String
|
||||
If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
|
||||
Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 设置 Headers 的 UA、Referer。
|
||||
''' </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
|
||||
Client.Headers("User-Agent") = "LogStatistic" '#4951
|
||||
Req.Headers.Add("User-Agent", "LogStatistic") '#4951
|
||||
ElseIf UseBrowserUserAgent Then
|
||||
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
|
||||
Req.Headers.Add("User-Agent", $"PCL2/{VersionStandardCode} Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36")
|
||||
Else
|
||||
Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode
|
||||
Req.Headers.Add("User-Agent", $"PCL2/{VersionStandardCode}")
|
||||
End If
|
||||
Client.Headers("Referer") = "http://" & VersionCode & ".open.pcl2.server/"
|
||||
If Url.Contains("api.curseforge.com") Then Client.Headers("x-api-key") = CurseForgeAPIKey
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 设置 Headers 的 UA、Referer。
|
||||
''' </summary>
|
||||
Friend Sub SecretHeadersSign(Url As String, ByRef Request As HttpWebRequest, Optional UseBrowserUserAgent As Boolean = False)
|
||||
If Url.Contains("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
|
||||
Req.Headers.Add("Referer", $"http://{VersionCode}.open.pcl2.server/")
|
||||
If Url.Contains("api.curseforge.com") Then Req.Headers.Add("x-api-key", CurseForgeAPIKey)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -225,11 +211,17 @@ Friend Module ModSecret
|
||||
If Not FrmMain.IsLoaded Then Return
|
||||
'顶部条背景
|
||||
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)})
|
||||
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.67, .Color = New MyColor().FromHSL2(ColorHue + 7, ColorSat, 47 + ColorLightAdjust)})
|
||||
Brush.GradientStops.Add(New GradientStop With {.Offset = 1, .Color = New MyColor().FromHSL2(ColorHue + 21, ColorSat, 53 + ColorLightAdjust)})
|
||||
If TypeOf ColorHueTopbarDelta Is Integer Then
|
||||
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.5, .Color = New MyColor().FromHSL2(ColorHue, ColorSat, 54 + 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.Freeze()
|
||||
'主页面背景
|
||||
If Setup.Get("UiBackgroundColorful") Then
|
||||
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 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: AssemblyFileVersion("2.10.3.0")>
|
||||
<Assembly: AssemblyVersion("2.10.5.0")>
|
||||
<Assembly: AssemblyFileVersion("2.10.5.0")>
|
||||
<Assembly: NeutralResourcesLanguage("")>
|
||||
+55
-15
@@ -63,9 +63,9 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' 查找 System.Byte[] 类型的本地化资源。
|
||||
'''</summary>
|
||||
Friend ReadOnly Property Custom() As Byte()
|
||||
Friend ReadOnly Property CacheCow_Client() As Byte()
|
||||
Get
|
||||
Dim obj As Object = ResourceManager.GetObject("Custom", resourceCulture)
|
||||
Dim obj As Object = ResourceManager.GetObject("CacheCow.Client", resourceCulture)
|
||||
Return CType(obj,Byte())
|
||||
End Get
|
||||
End Property
|
||||
@@ -73,9 +73,29 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' 查找 System.Byte[] 类型的本地化资源。
|
||||
'''</summary>
|
||||
Friend ReadOnly Property Dialogs() As Byte()
|
||||
Friend ReadOnly Property CacheCow_Client_FileStore() As Byte()
|
||||
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())
|
||||
End Get
|
||||
End Property
|
||||
@@ -105,7 +125,7 @@ Namespace My.Resources
|
||||
'''</summary>
|
||||
Friend ReadOnly Property Imazen_WebP() As Byte()
|
||||
Get
|
||||
Dim obj As Object = ResourceManager.GetObject("Imazen_WebP", resourceCulture)
|
||||
Dim obj As Object = ResourceManager.GetObject("Imazen.WebP", resourceCulture)
|
||||
Return CType(obj,Byte())
|
||||
End Get
|
||||
End Property
|
||||
@@ -120,16 +140,6 @@ Namespace My.Resources
|
||||
End Get
|
||||
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>
|
||||
''' 查找 System.Byte[] 类型的本地化资源。
|
||||
'''</summary>
|
||||
@@ -160,6 +170,36 @@ Namespace My.Resources
|
||||
End Get
|
||||
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>
|
||||
''' 查找 System.Byte[] 类型的本地化资源。
|
||||
'''</summary>
|
||||
|
||||
@@ -118,27 +118,30 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<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">
|
||||
<value>..\resources\custom.xaml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</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">
|
||||
<value>..\Resources\forge-installer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<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>
|
||||
</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>
|
||||
</data>
|
||||
<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>
|
||||
</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">
|
||||
<value>..\Resources\libwebp64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
@@ -148,6 +151,15 @@
|
||||
<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>
|
||||
</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">
|
||||
<value>..\Resources\transformer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
|
||||
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320">
|
||||
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="1.21.5" />
|
||||
<local:MyComboBoxItem Content="1.21.8" />
|
||||
<local:MyComboBoxItem Content="1.21.1" />
|
||||
<local:MyComboBoxItem Content="1.20.6" />
|
||||
<local:MyComboBoxItem Content="1.20.1" />
|
||||
|
||||
@@ -68,6 +68,10 @@ Public Class PageComp
|
||||
''' 在切换到页面时,应自动将筛选项设置为与该目标 MC 版本和加载器相同。
|
||||
''' </summary>
|
||||
Public Shared TargetVersion As McVersion = Nothing
|
||||
''' <summary>
|
||||
''' 在切换到该页面时自动设置的搜索框内的内容。
|
||||
''' </summary>
|
||||
Public Shared TargetName As String = Nothing
|
||||
|
||||
'在点击 MyCompItem 时会获取 Loader 的输入,以使资源详情页面可以应用相同的筛选项
|
||||
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")
|
||||
End If
|
||||
TargetVersion = Nothing
|
||||
If TargetName IsNot Nothing Then
|
||||
TextSearchName.Text = TargetName
|
||||
TargetName = Nothing
|
||||
End If
|
||||
'如果已经完成请求,则重新开始
|
||||
If IsLoaderInited Then StartNewSearch()
|
||||
ScrollToHome()
|
||||
|
||||
@@ -73,11 +73,14 @@
|
||||
'筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
|
||||
Private Function GetResults() As List(Of CompFile)
|
||||
Dim Results As List(Of CompFile) = CompFileLoader.Output
|
||||
If PageType = CompType.Any Then
|
||||
Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
|
||||
Else
|
||||
Results = Results.Where(Function(r) r.Type = PageType).ToList
|
||||
End If
|
||||
Select Case PageType
|
||||
Case CompType.Any
|
||||
Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
|
||||
Case CompType.Shader, CompType.ResourcePack
|
||||
'不筛选光影和资源包,否则原版光影会因为是资源包格式而被过滤(#6473)
|
||||
Case Else
|
||||
Results = Results.Where(Function(r) r.Type = PageType).ToList
|
||||
End Select
|
||||
Return Results
|
||||
End Function
|
||||
Private Sub Load_OnFinish()
|
||||
@@ -305,7 +308,7 @@
|
||||
End Try
|
||||
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)
|
||||
Dim File As CompFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
|
||||
RunInNewThread(
|
||||
@@ -356,8 +359,8 @@
|
||||
Return False
|
||||
End Function
|
||||
'获取常规资源默认下载位置
|
||||
If CachedFolder IsNot Nothing Then
|
||||
DefaultFolder = CachedFolder
|
||||
If CachedFolder.ContainsKey(Project.Type) Then
|
||||
DefaultFolder = CachedFolder(Project.Type)
|
||||
Log($"[Comp] 使用上次下载时的文件夹作为默认下载位置:{DefaultFolder}")
|
||||
ElseIf McVersionCurrent IsNot Nothing AndAlso IsVersionSuitable(McVersionCurrent) Then
|
||||
DefaultFolder = $"{McVersionCurrent.PathIndie}{SubFolder}"
|
||||
@@ -422,7 +425,7 @@
|
||||
If Not Target.Contains("\") Then Return
|
||||
'构造步骤加载器
|
||||
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)
|
||||
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
|
||||
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
|
||||
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
||||
@@ -733,7 +734,8 @@ Retry:
|
||||
'官方源
|
||||
Dim PageData As String
|
||||
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
|
||||
Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0))
|
||||
Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources.Last)
|
||||
@@ -1340,7 +1342,7 @@ Retry:
|
||||
If Json("data") IsNot Nothing AndAlso Json("data")("MOJMAPS") IsNot Nothing Then
|
||||
'下载原版 Json 文件
|
||||
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]
|
||||
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))
|
||||
@@ -1641,30 +1643,31 @@ Retry:
|
||||
Public Sub McDownloadForgeRecommendedRefresh()
|
||||
If IsForgeRecommendedRefreshed Then Return
|
||||
IsForgeRecommendedRefreshed = True
|
||||
RunInNewThread(Sub()
|
||||
Try
|
||||
Log("[Download] 刷新 Forge 推荐版本缓存开始")
|
||||
Dim Result As String = NetGetCodeByLoader("https://bmclapi2.bangbang93.com/forge/promos")
|
||||
If Result.Length < 1000 Then Throw New Exception("获取的结果过短(" & Result & ")")
|
||||
Dim ResultJson As JContainer = GetJson(Result)
|
||||
'获取所有推荐版本列表
|
||||
Dim RecommendedList As New List(Of String)
|
||||
For Each Version As JObject In ResultJson
|
||||
If Version("name") Is Nothing OrElse Version("build") Is Nothing Then Continue For
|
||||
Dim Name As String = Version("name")
|
||||
If Not Name.EndsWithF("-recommended") Then Continue For
|
||||
'内容为:"1.15.2":"31.2.0"
|
||||
RecommendedList.Add("""" & Name.Replace("-recommended", """:""" & Version("build")("version").ToString & """"))
|
||||
Next
|
||||
If RecommendedList.Count < 5 Then Throw New Exception("获取的推荐版本数过少(" & Result & ")")
|
||||
'保存
|
||||
Dim CacheJson As String = "{" & Join(RecommendedList, ",") & "}"
|
||||
WriteFile(PathTemp & "Cache\ForgeRecommendedList.json", CacheJson)
|
||||
Log("[Download] 刷新 Forge 推荐版本缓存成功")
|
||||
Catch ex As Exception
|
||||
Log(ex, "刷新 Forge 推荐版本缓存失败")
|
||||
End Try
|
||||
End Sub, "ForgeRecommendedRefresh")
|
||||
RunInNewThread(
|
||||
Sub()
|
||||
Try
|
||||
Log("[Download] 刷新 Forge 推荐版本缓存开始")
|
||||
Dim Result As String = NetRequestByClientRetry("https://bmclapi2.bangbang93.com/forge/promos")
|
||||
If Result.Length < 1000 Then Throw New Exception("获取的结果过短(" & Result & ")")
|
||||
Dim ResultJson As JContainer = GetJson(Result)
|
||||
'获取所有推荐版本列表
|
||||
Dim RecommendedList As New List(Of String)
|
||||
For Each Version As JObject In ResultJson
|
||||
If Version("name") Is Nothing OrElse Version("build") Is Nothing Then Continue For
|
||||
Dim Name As String = Version("name")
|
||||
If Not Name.EndsWithF("-recommended") Then Continue For
|
||||
'内容为:"1.15.2":"31.2.0"
|
||||
RecommendedList.Add("""" & Name.Replace("-recommended", """:""" & Version("build")("version").ToString & """"))
|
||||
Next
|
||||
If RecommendedList.Count < 5 Then Throw New Exception("获取的推荐版本数过少(" & Result & ")")
|
||||
'保存
|
||||
Dim CacheJson As String = "{" & Join(RecommendedList, ",") & "}"
|
||||
WriteFile(PathTemp & "Cache\ForgeRecommendedList.json", CacheJson)
|
||||
Log("[Download] 刷新 Forge 推荐版本缓存成功")
|
||||
Catch ex As Exception
|
||||
Log(ex, "刷新 Forge 推荐版本缓存失败")
|
||||
End Try
|
||||
End Sub, "ForgeRecommendedRefresh")
|
||||
End Sub
|
||||
Private IsForgeRecommendedRefreshed As Boolean = False
|
||||
|
||||
|
||||
@@ -676,6 +676,11 @@
|
||||
VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
|
||||
Return "与 Forge 不兼容"
|
||||
End If
|
||||
'检查 Fabric 1.20.5+:全部不兼容
|
||||
If SelectedFabric IsNot Nothing AndAlso
|
||||
VersionSortInteger(SelectedMinecraftId, "1.20.4") > 0 Then
|
||||
Return "与 Fabric 不兼容"
|
||||
End If
|
||||
'检查 Forge 版本
|
||||
Dim HasAny As Boolean = False
|
||||
Dim HasRequiredVersion As Boolean = False
|
||||
@@ -981,6 +986,11 @@
|
||||
Private Function LoadFabricGetError() As String
|
||||
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
|
||||
'检查 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")
|
||||
If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3") Then
|
||||
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
LabTitle.Text = "登录 Minecraft"
|
||||
LabCaption.Text =
|
||||
$"登录网页将自动开启,请在网页中输入 {UserCode}(已自动复制)。" & vbCrLf & vbCrLf &
|
||||
$"如果网络环境不佳,网页可能一直加载不出来,届时请使用使用加速器或 VPN 以改善网络环境。" & vbCrLf &
|
||||
$"如果网络环境不佳,网页可能一直加载不出来,届时请使用加速器或 VPN 以改善网络环境。" & vbCrLf &
|
||||
$"你也可以用其他设备打开 {Website} 并输入上述代码。"
|
||||
Btn1.EventData = Website
|
||||
Btn2.EventData = UserCode
|
||||
@@ -105,13 +105,16 @@
|
||||
Dim UnknownFailureCount As Integer = 0
|
||||
Do While Not MyConverter.IsExited
|
||||
Try
|
||||
Dim Result = NetRequestOnce(
|
||||
"https://login.microsoftonline.com/consumers/oauth2/v2.0/token", "POST",
|
||||
"grant_type=urn:ietf:params:oauth:grant-type:device_code" & "&" &
|
||||
"client_id=" & OAuthClientId & "&" &
|
||||
"device_code=" & DeviceCode & "&" &
|
||||
"scope=XboxLive.signin%20offline_access",
|
||||
"application/x-www-form-urlencoded", 5000 + UnknownFailureCount * 5000, MakeLog:=False)
|
||||
Dim Result = NetRequestByClient(
|
||||
"https://login.microsoftonline.com/consumers/oauth2/v2.0/token", HttpMethod.Post,
|
||||
Content:=
|
||||
"grant_type=urn:ietf:params:oauth:grant-type:device_code" & "&" &
|
||||
"client_id=" & OAuthClientId & "&" &
|
||||
"device_code=" & DeviceCode & "&" &
|
||||
"scope=XboxLive.signin%20offline_access",
|
||||
ContentType:="application/x-www-form-urlencoded",
|
||||
Timeout:=5000 + UnknownFailureCount * 5000,
|
||||
MakeLog:=False)
|
||||
'获取结果
|
||||
Dim ResultJson As JObject = GetJson(Result)
|
||||
McLaunchLog($"令牌过期时间:{ResultJson("expires_in")} 秒")
|
||||
@@ -119,21 +122,29 @@
|
||||
Finished({ResultJson("access_token").ToString, ResultJson("refresh_token").ToString})
|
||||
Return
|
||||
Catch ex As Exception
|
||||
If ex.Message.Contains("authorization_declined") Then
|
||||
Finished(New Exception("$你拒绝了 PCL 申请的权限……"))
|
||||
Return
|
||||
ElseIf ex.Message.Contains("expired_token") Then
|
||||
Finished(New Exception("$登录用时太长啦,重新试试吧!"))
|
||||
Return
|
||||
ElseIf ex.Message.Contains("service abuse") Then
|
||||
Finished(New Exception("$非常抱歉,该账号已被微软封禁,无法登录。"))
|
||||
Return
|
||||
ElseIf ex.Message.Contains("AADSTS70000") Then '可能不能判 “invalid_grant”,见 #269
|
||||
Finished(New RestartException)
|
||||
Return
|
||||
ElseIf ex.Message.Contains("authorization_pending") Then
|
||||
Thread.Sleep(2000)
|
||||
ElseIf UnknownFailureCount <= 2 Then
|
||||
If TypeOf ex Is ResponsedWebException Then
|
||||
Dim Response = CType(ex, ResponsedWebException).Response
|
||||
If Response.Contains("authorization_declined") Then
|
||||
Finished(New Exception("$你拒绝了 PCL 申请的权限……"))
|
||||
Return
|
||||
ElseIf Response.Contains("expired_token") Then
|
||||
Finished(New Exception("$登录用时太长啦,重新试试吧!"))
|
||||
Return
|
||||
ElseIf Response.Contains("Account security interrupt") Then
|
||||
Finished(New Exception("$该账号由于安全问题无法登陆,请前往微软账户页获取更多信息。"))
|
||||
Return
|
||||
ElseIf Response.Contains("service abuse") Then
|
||||
Finished(New Exception("$非常抱歉,该账号已被微软封禁,无法登录。"))
|
||||
Return
|
||||
ElseIf Response.Contains("AADSTS70000") Then '可能不能判 “invalid_grant”,见 #269
|
||||
Finished(New RestartException)
|
||||
Return
|
||||
ElseIf Response.Contains("authorization_pending") Then
|
||||
Thread.Sleep(2000)
|
||||
Continue Do
|
||||
End If
|
||||
End If
|
||||
If UnknownFailureCount <= 2 Then
|
||||
UnknownFailureCount += 1
|
||||
Log(ex, $"登录轮询第 {UnknownFailureCount} 次失败")
|
||||
Thread.Sleep(2000)
|
||||
|
||||
@@ -259,12 +259,13 @@ Retry:
|
||||
End Sub)
|
||||
If SelId Is Nothing Then Return
|
||||
'发送请求
|
||||
Dim Result As String = NetRequestRetry("https://api.minecraftservices.com/minecraft/profile/capes/active",
|
||||
If(SelId = 0, "DELETE", "PUT"),
|
||||
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}})
|
||||
Dim Result As String = NetRequestByClientRetry("https://api.minecraftservices.com/minecraft/profile/capes/active",
|
||||
If(SelId = 0, HttpMethod.Delete, HttpMethod.Put),
|
||||
Content:=If(SelId = 0, "", New JObject(New JProperty("capeId", SkinData("capes")(SelId - 1)("id"))).ToString(0)),
|
||||
ContentType:="application/json",
|
||||
Headers:={{"Authorization", "Bearer " & AccessToken}})
|
||||
If Result.Contains("""errorMessage""") Then
|
||||
Hint("更改披风失败:" & GetJson(Result)("errorMessage"), HintType.Critical)
|
||||
Hint("更改披风失败:" & GetJson(Result)("errorMessage").ToString, HintType.Critical)
|
||||
Return
|
||||
Else
|
||||
Hint("更改披风成功!", HintType.Finish)
|
||||
|
||||
@@ -156,7 +156,7 @@ Download:
|
||||
Dim Version As String = ""
|
||||
Dim NeedDownload As Boolean = True
|
||||
Try
|
||||
Version = NetGetCodeByRequestOnce(VersionAddress, Timeout:=10000)
|
||||
Version = NetRequestByClientRetry(VersionAddress)
|
||||
If Version.Length > 1000 Then Throw New Exception($"获取的主页版本过长({Version.Length} 字符)")
|
||||
Dim CurrentVersion As String = Setup.Get("CacheSavedPageVersion")
|
||||
If Version <> "" AndAlso CurrentVersion <> "" AndAlso Version = CurrentVersion Then
|
||||
@@ -171,7 +171,7 @@ Download:
|
||||
End Try
|
||||
'实际下载
|
||||
If NeedDownload Then
|
||||
Dim FileContent As String = NetGetCodeByRequestRetry(Address)
|
||||
Dim FileContent As String = NetRequestByClientRetry(Address)
|
||||
Log($"[Page] 已联网下载主页,内容长度:{FileContent.Length},来源:{Address}")
|
||||
Setup.Set("CacheSavedPageUrl", Address)
|
||||
Setup.Set("CacheSavedPageVersion", Version)
|
||||
@@ -231,7 +231,9 @@ Download:
|
||||
Try
|
||||
'修改时应同时修改 PageOtherHelpDetail.Init
|
||||
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>"
|
||||
Log($"[Page] 实例化:加载主页 UI 开始,最终内容长度:{Content.Count}")
|
||||
PanCustom.Children.Add(GetObjectFromXML(Content))
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:PCL"
|
||||
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: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="游戏用户名" />
|
||||
|
||||
@@ -64,6 +64,7 @@ Public Class PageLoginLegacy
|
||||
Private Sub ComboLegacy_TextChanged(sender As Object, e As TextChangedEventArgs) Handles ComboName.TextChanged
|
||||
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)
|
||||
RunInUi(Sub() PanMain.InvalidateMeasure(), True) '由于 WPF 的 Bug,它不一定会自动更新 HintChinese 的大小(#6627)
|
||||
End Sub
|
||||
Private Sub Skin_Click() Handles Skin.Click
|
||||
If (Setup.Get("UiHiddenPageSetup") OrElse Setup.Get("UiHiddenSetupLaunch")) AndAlso Not PageSetupUI.HiddenForceShow Then
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
<local:MyIconButton.ContextMenu>
|
||||
<ContextMenu Closed="HidePanel" HorizontalOffset="10" VerticalOffset="18">
|
||||
<local:MyMenuItem Click="BtnSkinEdit_Click" Header="修改皮肤"/>
|
||||
<local:MyMenuItem Click="BtnSkinSave_Click" Header="保存皮肤"/>
|
||||
<local:MyMenuItem Click="BtnSkinRefresh_Click" Header="刷新头像"/>
|
||||
<local:MyMenuItem Click="BtnSkinSave_Click" Header="保存皮肤文件"/>
|
||||
<Separator />
|
||||
<local:MyMenuItem Click="BtnSkinCape_Click" Header="修改披风"/>
|
||||
<Separator />
|
||||
<local:MyMenuItem Click="BtnSkinRefresh_Click" Header="刷新"/>
|
||||
</ContextMenu>
|
||||
</local:MyIconButton.ContextMenu>
|
||||
</local:MyIconButton>
|
||||
|
||||
@@ -107,7 +107,7 @@ Retry:
|
||||
McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
|
||||
GoTo Retry
|
||||
ElseIf Result.Contains("""error""") Then
|
||||
Hint("更改皮肤失败:" & GetJson(Result)("error"), HintType.Critical)
|
||||
Hint("更改皮肤失败:" & GetJson(Result)("error").ToString, HintType.Critical)
|
||||
Return
|
||||
End If
|
||||
'获取新皮肤地址
|
||||
|
||||
@@ -104,264 +104,288 @@
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="赞助者">
|
||||
<StackPanel Margin="25,40,10,20">
|
||||
<TextBlock HorizontalAlignment="Left" Text="以下是 2025 年 5 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
||||
<WrapPanel Margin="0,0,0,10">
<TextBlock Width="120" Margin="0,1.5" Text="Alliance" />
|
||||
<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="114514" />
|
||||
<TextBlock HorizontalAlignment="Left" Text="以下是 2025 年 6 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
||||
<WrapPanel Margin="0,0,0,10">
<TextBlock Width="120" Margin="0,1.5" Text="星月" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Nemo" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="长歌当天" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="飒黎lIlIlI" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="hy" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="SaDhhJe" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="风铃子啊" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="柠娜" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="W丶北辰" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="才KRE" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Yang_mistakeof" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="close eyes" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="顾顾" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="LTuuxj" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="花吃" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="FICazk" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="屑屑你" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="凉凉" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="WDSJ" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Tohka" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="lz" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="哦嚯嚯嚯皮筋头" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="陈肖杰" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="MC小满" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="残光" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="玖玖璃" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="水晶OTZ" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="伯克礼" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="白猫海贼船" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="zhang1232" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Never" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Fish_pomelo" />
|
||||
<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="_章333_" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="孙杰" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="wby" />
|
||||
<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="zzxniubi" />
|
||||
<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="oran9e" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="赤冰雨" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Urizen" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text=":)" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="skyqyzm" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="橘子皮丶" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="额外awa" />
|
||||
<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="sxy192425" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="李好啊" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="MH_Nine" />
|
||||
<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="DHLH" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Xayj" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="绳网用户#37" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="LLLL" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="深绯红" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="奇伢七星" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Akapigo" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Shink_guns" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Aqua 极&坏." />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="大事化小蛋糕" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Nakiya233" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="花小妖" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="septebr" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="一只马喽" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="下暴雨BWB" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="QAQ" />
|
||||
<TextBlock Width="240" Margin="0,1.5" Text="sl土豆社区服主B友" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Wang" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="......" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ResTmoW" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="bochibochibo" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="铸魂之灵" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="柏柏柏" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Mart1s" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="KuruM148" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="KaiTouCrow" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="LIE-SHAN" />
|
||||
<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="Miraclepoi" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="XiaoLI" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="啊吧啊吧的肥宅" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="不娶雨婷不改名" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="oppo19" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="博麗靈夢" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="莹 of yours" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ChinaFZXPVP" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="城之内sama" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ENXI" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="steve_c418" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="洛长安" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="magic_muggle" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小猫游六喵" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="JY" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="雪豹起司可颂" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="wlsy" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="齐先生爱溜达" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="是小泠啊" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="xioyiao" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="BunnyMiku" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="dadagga" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="无极之笔" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="xiaoyu" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="王梓杰" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="wjbjjd" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Candy_Mo" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="lettmin_" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="七九·Alnasl" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="辉" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="何为最优解" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="crazy丶天人" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="XsBlueSky" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="冬将軍" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="tiechui" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Liu2Shi2Pu2" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Yu_s" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="刘四妹" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="枝皙" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="CC" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Slana23" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="MMMy" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Venuse" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="microjie" />
|
||||
<TextBlock Width="240" Margin="0,1.5" Text="Miner#Cetyleno~^" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="春江花月夜" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="落南子" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="AL1Su-爱丽丝" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="我木有呆毛" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="乌羽" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="知性de含羞草" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="星の殇" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="IED LTAM" />
|
||||
<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="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="jjj" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="clilick" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="我很快乐" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Phoenix tamer" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Lsp77" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="太阳神" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ikun0014" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="IncredibleYu" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="在下粉毛控" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="SuperCrazyK" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="阿柔" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="HaKNa" />
|
||||
<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="20018" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="波比科普员" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Xiao_JIA" />
|
||||
<TextBlock Width="240" Margin="0,1.5" Text="龙腾我是你的头号粉丝" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="keer1563" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="百鬼まル" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="DPSYnt" />
|
||||
<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="ktyxlan_lan" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="琳琅039" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="黑色额度" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="sahaua" />
|
||||
<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="NQ" />
|
||||
<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="ZGW2008" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="没事多喝感冒灵" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="一梦筱筱" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="twokness" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="hhy7171" />
|
||||
<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="dddr" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="天气热" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Emmanuel" />
|
||||
<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="Anderson521314" />
|
||||
<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="田坎村西头王二狗" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="令月廿一" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Mrdandan" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="111" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="27733" />
|
||||
<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="小涵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="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="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="那菈" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="suanqiu" />
|
||||
<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="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="StarNCosmos" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Eason" />
|
||||
<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="咏夕" />
|
||||
<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="雅柏菲卡" />
|
||||
<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="老登" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="wd_xuan" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Wake" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Jannik" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="cybone" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="mc12345zhl123" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="解" />
|
||||
<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="sikuno" />
|
||||
<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="洛逍遥" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="文文新闻" />
|
||||
<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="Fuxi Fuji" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="?独爱蝉HIA" />
|
||||
<TextBlock Width="240" 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="461863352" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="庭" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Xing_K" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="yzt" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="nuycn" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="鸡人" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="爱无界i" />
|
||||
<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="cai1" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="小比登T^T" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="hb" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="caizzz" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="yyin" />
|
||||
<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="御坂1354号" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="木子" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="萤火焱攸" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="盼盼不是Panda" />
|
||||
<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" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ZhuTan12" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="tom" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="洛竹" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="foob" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="Garylu" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="阮绍轩" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="xin822" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="BAIgivele" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="ljc" />
|
||||
<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="vvvghjvvv" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="法斯" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="DASENSUN" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="HTS" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="握不住信新心" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="sycuuj133" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="天杉大将军" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="风见翎" />
|
||||
<TextBlock Width="120" Margin="0,1.5" Text="江心Rain" />
|
||||
</WrapPanel>
|
||||
<Grid Height="35">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
Case 1
|
||||
Feedback(True, False)
|
||||
Case 2
|
||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/issues/")
|
||||
OpenWebsite("https://github.com/Meloong-Git/PCL/issues/")
|
||||
End Select
|
||||
End Sub
|
||||
Private Sub TryVote(sender As Object, e As RouteEventArgs) Handles ItemVote.Changed
|
||||
@@ -148,7 +148,7 @@
|
||||
Public Shared Sub TryVote()
|
||||
If MyMsgBox("是否要打开新功能投票网页?" & vbCrLf & "如果无法打开该网页,请使用 VPN 以改善网络环境。",
|
||||
"新功能投票", "打开", "取消") = 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 Class
|
||||
@@ -227,7 +227,7 @@
|
||||
DeleteDirectory(Version.Path)
|
||||
Hint("版本 " & Version.Name & " 已永久删除!", HintType.Finish)
|
||||
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)
|
||||
End If
|
||||
Case 2
|
||||
|
||||
@@ -610,7 +610,7 @@
|
||||
FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
|
||||
FrmSetupUI.HintCustom.Text = $"从指定网址联网获取主页内容。服主也可以用于动态更新服务器公告。{vbCrLf}如果你制作了稳定运行的联网主页,可以点击这条提示投稿,若合格即可加入预设!"
|
||||
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 '预设
|
||||
FrmSetupUI.PanCustomPreset.Visibility = Visibility.Visible
|
||||
FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnSkinSave" Text="保存皮肤" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Row="1" />
|
||||
<local:MyButton x:Name="BtnSkinCache" Text="刷新缓存" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新并重新下载 PCL 当前显示的皮肤" Grid.Row="1" Grid.Column="1" />
|
||||
<local:MyButton x:Name="BtnSkinCache" Text="刷新" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新并重新下载 PCL 当前显示的皮肤" Grid.Row="1" Grid.Column="1" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid x:Name="PanSkinChange" Margin="0,14,0,2" Height="35" Visibility="Collapsed">
|
||||
@@ -240,10 +240,10 @@
|
||||
ToolTip="还原" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="200" ToolTipService.VerticalOffset="-1"
|
||||
Logo="M530 0c287 0 521 229 521 511s-233 511-521 511c-233 0-436-151-500-368a63 63 0 0 1 44-79 65 65 0 0 1 80 43c48 162 200 276 375 276 215 0 390-171 390-383s-174-383-390-383c-103 0-199 39-270 106l21-5a63 63 0 0 1 33 123l-157 42a65 65 0 0 1-90-42l-49-183a65 65 0 1 1 126-33l6 26A524 524 0 0 1 530 0z" LogoScale="0.9" />
|
||||
</StackPanel>
|
||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.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" />
|
||||
<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" />
|
||||
<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 文件夹。" />
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</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="2" Text="添加延迟" Height="22" x:Name="CheckDebugDelay" Tag="SystemDebugDelay" ToolTip="在各个环节添加随机的延迟,拖慢加载速度,以测试部分功能是否正常运行。
这会严重影响启动器运行,若无特殊需要不建议开启。" />
|
||||
</Grid>
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
|
||||
'顶部栏
|
||||
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
|
||||
Try
|
||||
'拷贝文件
|
||||
@@ -319,7 +319,7 @@ Refresh:
|
||||
Return
|
||||
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
|
||||
FrmMain.ImageTitleLogo.Source = Nothing
|
||||
e.Handled = True
|
||||
@@ -357,7 +357,9 @@ Refresh:
|
||||
PanMusicVolume.Visibility = Visibility.Visible
|
||||
PanMusicDetail.Visibility = Visibility.Visible
|
||||
BtnMusicClear.Visibility = Visibility.Visible
|
||||
CardMusic.Title = "背景音乐(" & EnumerateFiles(Path & "PCL\Musics\").Count & " 首)"
|
||||
CardMusic.Title = "背景音乐(" &
|
||||
EnumerateFiles(Path & "PCL\Musics\").Count(Function(f) {".ini", ".jpg", ".txt", ".cfg", ".lrc", ".db", ".png"}.Contains(f.Extension.ToLower)) &
|
||||
" 首)"
|
||||
Else
|
||||
PanMusicVolume.Visibility = Visibility.Collapsed
|
||||
PanMusicDetail.Visibility = Visibility.Collapsed
|
||||
|
||||
@@ -564,8 +564,8 @@ Public Class PageVersionExport
|
||||
Sub()
|
||||
Try
|
||||
Dim ModrinthHashes = Loader.Input.Select(Function(m) m.ModrinthHash)
|
||||
Dim ModrinthRaw = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files", "POST",
|
||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")), JObject)
|
||||
Dim ModrinthRaw As JObject = DlModRequest("https://api.modrinth.com/v2/version_files", HttpMethod.Post,
|
||||
$"{{""hashes"": [""{ModrinthHashes.Join(""",""")}""], ""algorithm"": ""sha1""}}", "application/json")
|
||||
For Each ModFile In Loader.Input
|
||||
'查找对应的文件
|
||||
If Not ModrinthRaw.ContainsKey(ModFile.ModrinthHash) Then Continue For
|
||||
@@ -589,8 +589,8 @@ Public Class PageVersionExport
|
||||
Try
|
||||
If ModrinthUploadMode Then Return 'Modrinth 上传模式下,不能从 CurseForge 获取信息
|
||||
Dim CurseForgeHashes = Loader.Input.Select(Function(m) m.CurseForgeHash)
|
||||
Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432/", "POST",
|
||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer)
|
||||
Dim CurseForgeRaw As JContainer = DlModRequest("https://api.curseforge.com/v1/fingerprints/432/", HttpMethod.Post,
|
||||
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")("data")("exactMatches")
|
||||
For Each ResultJson As JObject In CurseForgeRaw
|
||||
If Not ResultJson.ContainsKey("file") Then Continue For
|
||||
Dim File As JObject = ResultJson("file")
|
||||
|
||||
@@ -381,7 +381,9 @@ Install:
|
||||
''' 下载 Mod。
|
||||
''' </summary>
|
||||
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)
|
||||
End Sub
|
||||
|
||||
@@ -428,6 +430,11 @@ Install:
|
||||
If FrmMain.PageRight IsNot Me Then Return
|
||||
If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then ChangeAllSelected(True)
|
||||
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
|
||||
|
||||
@@ -636,14 +643,14 @@ Install:
|
||||
Try
|
||||
For Each Entry As McMod In ModList
|
||||
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
|
||||
Log($"[Mod] 未找到更新前的 Mod 文件,跳过对它的删除:{Entry.Path}", LogLevel.Debug)
|
||||
End If
|
||||
Next
|
||||
For Each Entry As KeyValuePair(Of String, String) In FileCopyList
|
||||
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)
|
||||
End If
|
||||
If Directory.Exists(GetPathFromFullPath(Entry.Value)) Then
|
||||
@@ -732,7 +739,7 @@ Install:
|
||||
If IsShiftPressed Then
|
||||
File.Delete(ModEntity.Path)
|
||||
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
|
||||
Catch ex As OperationCanceledException
|
||||
Log(ex, "删除 Mod 被主动取消")
|
||||
|
||||
@@ -116,12 +116,14 @@
|
||||
Dim TempName As String = NewName & "_temp"
|
||||
Dim TempPath As String = PathMcFolder & "versions\" & TempName & "\"
|
||||
Dim IsCaseChangedOnly As Boolean = NewName.ToLower = OldName.ToLower
|
||||
'重新加载版本 Json 信息,避免 HMCL 项被合并
|
||||
'重新读取版本 JSON 信息,避免 JsonObject 中已被合并的项被重新存储
|
||||
Dim JsonObject As JObject
|
||||
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
|
||||
Log(ex, "重命名读取 json 时失败")
|
||||
Log(ex, "在重命名读取 json 时失败")
|
||||
JsonObject = PageVersionLeft.Version.JsonObject
|
||||
End Try
|
||||
'重命名主文件夹
|
||||
@@ -130,27 +132,26 @@
|
||||
'清理 ini 缓存
|
||||
IniClearCache(PageVersionLeft.Version.PathIndie & "options.txt")
|
||||
IniClearCache(PageVersionLeft.Version.Path & "PCL\Setup.ini")
|
||||
'遍历重命名所有文件与文件夹
|
||||
For Each Entry As DirectoryInfo In New DirectoryInfo(NewPath).EnumerateDirectories
|
||||
If Not Entry.Name.Contains(OldName) Then Continue For
|
||||
'重命名 jar 文件与 natives 文件夹
|
||||
'不能进行遍历重命名,否则在版本名很短的时候容易误伤其他文件(#6443)
|
||||
If Directory.Exists($"{NewPath}{OldName}-natives") Then
|
||||
If IsCaseChangedOnly Then
|
||||
My.Computer.FileSystem.RenameDirectory(Entry.FullName, Entry.Name & "_temp")
|
||||
My.Computer.FileSystem.RenameDirectory(Entry.FullName & "_temp", Entry.Name.Replace(OldName, NewName))
|
||||
My.Computer.FileSystem.RenameDirectory($"{NewPath}{OldName}-natives", $"{OldName}natives_temp")
|
||||
My.Computer.FileSystem.RenameDirectory($"{NewPath}{OldName}-natives_temp", $"{NewName}-natives")
|
||||
Else
|
||||
DeleteDirectory(NewPath & Entry.Name.Replace(OldName, NewName))
|
||||
My.Computer.FileSystem.RenameDirectory(Entry.FullName, Entry.Name.Replace(OldName, NewName))
|
||||
DeleteDirectory($"{NewPath}{NewName}-natives")
|
||||
My.Computer.FileSystem.RenameDirectory($"{NewPath}{OldName}-natives", $"{NewName}-natives")
|
||||
End If
|
||||
Next
|
||||
For Each Entry As FileInfo In New DirectoryInfo(NewPath).EnumerateFiles
|
||||
If Not Entry.Name.Contains(OldName) Then Continue For
|
||||
End If
|
||||
If File.Exists($"{NewPath}{OldName}.jar") Then
|
||||
If IsCaseChangedOnly Then
|
||||
My.Computer.FileSystem.RenameFile(Entry.FullName, Entry.Name & "_temp")
|
||||
My.Computer.FileSystem.RenameFile(Entry.FullName & "_temp", Entry.Name.Replace(OldName, NewName))
|
||||
My.Computer.FileSystem.RenameFile($"{NewPath}{OldName}.jar", $"{OldName}_temp.jar")
|
||||
My.Computer.FileSystem.RenameFile($"{NewPath}{OldName}_temp.jar", $"{NewName}.jar")
|
||||
Else
|
||||
If File.Exists(NewPath & Entry.Name.Replace(OldName, NewName)) Then File.Delete(NewPath & Entry.Name.Replace(OldName, NewName))
|
||||
My.Computer.FileSystem.RenameFile(Entry.FullName, Entry.Name.Replace(OldName, NewName))
|
||||
File.Delete($"{NewPath}{NewName}.jar")
|
||||
My.Computer.FileSystem.RenameFile($"{NewPath}{OldName}.jar", $"{NewName}.jar")
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
'替换版本设置文件中的路径
|
||||
If File.Exists(NewPath & "PCL\Setup.ini") Then
|
||||
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
|
||||
WriteIni(PathMcFolder & "PCL.ini", "Version", NewName)
|
||||
End If
|
||||
'更改版本 Json
|
||||
If File.Exists(NewPath & NewName & ".json") Then
|
||||
Try
|
||||
JsonObject("id") = NewName
|
||||
WriteFile(NewPath & NewName & ".json", JsonObject.ToString)
|
||||
Catch ex As Exception
|
||||
Log(ex, "重命名版本 json 失败")
|
||||
End Try
|
||||
End If
|
||||
'写入版本 Json
|
||||
Try
|
||||
JsonObject("id") = NewName
|
||||
WriteFile(NewPath & NewName & ".json", JsonObject.ToString)
|
||||
Catch ex As Exception
|
||||
Log(ex, "重命名版本 json 失败")
|
||||
End Try
|
||||
'刷新与提示
|
||||
Hint("重命名成功!", HintType.Finish)
|
||||
PageVersionLeft.Version = New McVersion(NewName).Load()
|
||||
@@ -185,7 +184,7 @@
|
||||
'选择 自定义 时修改图片
|
||||
Try
|
||||
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
|
||||
Reload() '还原选项
|
||||
Return
|
||||
@@ -331,7 +330,7 @@
|
||||
DeleteDirectory(PageVersionLeft.Version.Path)
|
||||
Hint("版本 " & PageVersionLeft.Version.Name & " 已永久删除!", HintType.Finish)
|
||||
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)
|
||||
End If
|
||||
Case 2
|
||||
|
||||
@@ -209,10 +209,10 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数头部" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="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" />
|
||||
<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" />
|
||||
<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 文件夹。" />
|
||||
|
||||
@@ -140,6 +140,21 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<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">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>Resources\Imazen.WebP.dll</HintPath>
|
||||
@@ -149,8 +164,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>Resources\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<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>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Management" />
|
||||
<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.Runtime.Caching" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -202,6 +225,7 @@
|
||||
<Compile Include="Modules\Minecraft\ModJava.vb" />
|
||||
<Compile Include="Modules\Minecraft\ModMod.vb" />
|
||||
<Compile Include="Modules\Minecraft\ModModpack.vb" />
|
||||
<Compile Include="Modules\ThirdParty\DragHelper.vb" />
|
||||
<Compile Include="Pages\PageVersion\MyLocalModItem.xaml.vb">
|
||||
<DependentUpon>MyLocalModItem.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -235,9 +259,6 @@
|
||||
<Compile Include="Modules\ModDevelop.vb" />
|
||||
<Compile Include="Modules\Minecraft\ModWatcher.vb" />
|
||||
<Compile Include="Modules\ModSecret.vb" />
|
||||
<Compile Include="Modules\Reference\CookieWebClient.vb">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Pages\PageDownload\Comp\PageComp.xaml.vb">
|
||||
<DependentUpon>PageComp.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -724,6 +745,7 @@
|
||||
<Import Include="System.IO" />
|
||||
<Import Include="System.Linq" />
|
||||
<Import Include="System.Net" />
|
||||
<Import Include="System.Net.Http" />
|
||||
<Import Include="System.Text" />
|
||||
<Import Include="System.Threading" />
|
||||
<Import Include="System.Xml.Linq" />
|
||||
@@ -961,5 +983,18 @@
|
||||
<None Include="Resources\Imazen.WebP.dll" />
|
||||
<None Include="Resources\libwebp64.dll" />
|
||||
</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" />
|
||||
</Project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -113,7 +113,7 @@
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="· 打开网页、启动游戏、打开文件:已在上方的卡片中介绍" />
|
||||
<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"
|
||||
Text="· 今日人品、清理垃圾、内存优化、安装整合包:触发对应功能" />
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
@@ -134,6 +134,10 @@
|
||||
Text="切换到下载页面" EventType="切换页面" EventData="1|1"/>
|
||||
<local:MyButton Margin="0,5,0,6" Width="250" Height="35"
|
||||
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"/>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -302,7 +306,7 @@
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
|
||||
Text="如果你在尝试制作联网更新的主页,可以查看下方的 GitHub 讨论页。
你可以根据其中的介绍为主页添加版本号检查以节省流量,也可以通过检查 Referer 和 User Agent 来确定对方的 PCL 版本。" />
|
||||
<local:MyButton Margin="0,0,0,8" Height="35" HorizontalAlignment="Center" Padding="20,0,20,0"
|
||||
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>
|
||||
</local:MyCard>
|
||||
|
||||
|
||||
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
|
||||
|
||||
[](https://github.com/Hex-Dragon/PCL2/)
|
||||
[](https://github.com/Hex-Dragon/PCL2/issues)
|
||||
[](https://github.com/Meloong-Git/PCL/)
|
||||
[](https://github.com/Meloong-Git/PCL/issues)
|
||||
[](https://space.bilibili.com/11343203/dynamic)
|
||||
[](https://afdian.com/@LTCat)
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
|
||||
### 相关资源
|
||||
- [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 内置帮助文档的存储库
|
||||
Reference in new issue
Block a user