From c86fdc3af17b6b5f3ea63bd8e68aef3576eea3a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BE=99=E8=85=BE=E7=8C=AB=E8=B7=83?= <1043137532@qq.com>
Date: Thu, 21 May 2026 01:15:20 +0800
Subject: [PATCH] 2.12.8.1
---
MeloongCore | 2 +-
Plain Craft Launcher 2/Application.xaml | 1 -
Plain Craft Launcher 2/Application.xaml.vb | 82 ++++++-------------
Plain Craft Launcher 2/Controls/MyButton.xaml | 2 +-
.../Controls/MyCheckBox.xaml | 2 +-
.../Controls/MyExtraButton.xaml | 2 +-
.../Controls/MyIconTextButton.xaml | 2 +-
Plain Craft Launcher 2/Controls/MyImage.vb | 2 +-
.../Controls/MyListItem.xaml | 2 +-
.../Controls/MyRadioBox.xaml | 2 +-
.../Controls/MyRadioBox.xaml.vb | 4 -
.../Controls/MyRadioButton.xaml | 2 +-
.../Controls/MyRadioButton.xaml.vb | 1 -
Plain Craft Launcher 2/FormMain.xaml.vb | 11 ++-
.../Modules/Base/ModBase.vb | 47 ++++-------
.../Modules/Base/ModLoader.vb | 7 +-
Plain Craft Launcher 2/Modules/Base/ModNet.vb | 10 +--
.../Modules/Minecraft/ModLaunch.vb | 55 ++++++-------
.../Modules/Minecraft/ModMinecraft.vb | 4 +-
.../Modules/Minecraft/ModWatcher.vb | 16 ++--
Plain Craft Launcher 2/Modules/ModMain.vb | 5 +-
Plain Craft Launcher 2/Modules/ModSecret.vb | 47 -----------
.../Modules/Resource/LocalResourceFile.vb | 6 +-
.../Modules/Resource/ResourceSearcher.vb | 1 +
.../My Project/AssemblyInfo.vb | 4 +-
.../Pages/PageInstance/MyLocalModItem.xaml | 2 +-
.../PageInstance/PageInstanceExport.xaml | 9 ++
.../PageInstance/PageInstanceExport.xaml.vb | 6 +-
.../PageInstance/PageInstanceMod.xaml.vb | 18 ++--
.../Pages/PageLaunch/MySkin.xaml.vb | 34 ++++++--
.../Pages/PageLaunch/PageLaunchRight.xaml.vb | 8 +-
.../Pages/PageLaunch/PageLoginMsSkin.xaml | 4 +-
.../Pages/PageLaunch/PageLoginMsSkin.xaml.vb | 52 +++++++++---
.../Pages/PageLink/PageLinkMain.xaml.vb | 2 +-
.../Pages/PageOther/PageOtherAbout.xaml | 69 ++++++++++++++++
.../Pages/PageSetup/Settings.vb | 7 +-
36 files changed, 275 insertions(+), 255 deletions(-)
diff --git a/MeloongCore b/MeloongCore
index 5ee6f88..f30c861 160000
--- a/MeloongCore
+++ b/MeloongCore
@@ -1 +1 @@
-Subproject commit 5ee6f88cde9def4bb93c9086567f28410319871c
+Subproject commit f30c861f6ea5ae9a52a93ffa71357d20ce0090ab
diff --git a/Plain Craft Launcher 2/Application.xaml b/Plain Craft Launcher 2/Application.xaml
index fde857c..e523a44 100644
--- a/Plain Craft Launcher 2/Application.xaml
+++ b/Plain Craft Launcher 2/Application.xaml
@@ -368,7 +368,6 @@
-
diff --git a/Plain Craft Launcher 2/Application.xaml.vb b/Plain Craft Launcher 2/Application.xaml.vb
index 872bc91..851baf0 100644
--- a/Plain Craft Launcher 2/Application.xaml.vb
+++ b/Plain Craft Launcher 2/Application.xaml.vb
@@ -91,37 +91,8 @@ RetryCacheCheck:
End Try
DirectoryUtils.Create(PathTemp & "Cache\")
DirectoryUtils.Create(PathAppdata)
-
-#If DEBUG Then
- Dim FileLockPath = Path.Combine(PathAppdata.TrimEnd("\"), "PCL.dev.Lock")
-#Else
- Dim FileLockPath = Path.Combine(PathAppdata.TrimEnd("\"), "PCL.Lock")
-#End If
-
'要求单例
- If BuildType <> BuildTypes.Debug Then
- If Not GetProgramLock(FileLockPath) Then
- Dim IsLocked = False
- Dim ShouldWaitForExit As Boolean = e.Args.Length > 0 AndAlso e.Args(0) = "--wait" '要求等待已有的 PCL 退出
- If Not ShouldWaitForExit Then
- DropToTopByLock(FileLockPath)
- Beep()
- Environment.Exit(ProcessReturnValues.Cancel)
- End If
- For i = 0 To 10
- If GetProgramLock(FileLockPath) Then
- IsLocked = True
- Exit For
- End If
- Thread.Sleep(500)
- Next
- If Not IsLocked Then
- DropToTopByLock(FileLockPath)
- Beep()
- Environment.Exit(ProcessReturnValues.Cancel)
- End If
- End If
- End If
+ WaitingMutex(e)
'设置 ToolTipService 默认值
ToolTipService.InitialShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(300))
ToolTipService.BetweenShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(400))
@@ -173,38 +144,37 @@ RetryCacheCheck:
FormMain.EndProgramForce(ProcessReturnValues.Exception)
End Try
End Sub
-
- Private Shared KernelLock As Mutex
-
'''
- ''' 尝试获取单例锁
+ ''' 要求程序以单例运行。
+ ''' 如果已在运行,则将其窗口拖出来并播放提示音,然后结束当前进程。
'''
- ''' 文件锁位置
- ''' 一个值用于指示是否获得文件锁
- Private Function GetProgramLock(LockPath As String) As Boolean
+ Private Shared Sub WaitingMutex(e As StartupEventArgs)
+ If BuildType = BuildTypes.Debug Then Return
Try
- Dim IsLocked = False
- KernelLock = New Mutex(True, "Local\Plain Craft Launcher", IsLocked)
- If Not IsLocked Then Return False
- Logger.Info("获取单例锁成功")
- File.WriteAllText(LockPath, Process.GetCurrentProcess().Id.ToString())
- Return IsLocked
+ Dim MutexCreatedNew As Boolean
+ PclMutex = New Mutex(True, "PCL_SingletonMutex", MutexCreatedNew)
+ If MutexCreatedNew Then Return
+ Logger.Warn("已有一个 PCL 实例正在运行")
+ '等待已有的 PCL 退出
+ If e.Args.Length > 0 AndAlso e.Args(0) = "--wait" Then
+ Try
+ If PclMutex.WaitOne(10000) Then Return '等待至多 10 秒
+ Catch Ignored As AbandonedMutexException
+ Return '已有实例异常退出,继续启动
+ End Try
+ End If
+ '将已有的 PCL 窗口拖出来
+ Dim WindowHwnd As IntPtr = FindWindow(Nothing, "Plain Craft Launcher ")
+ If WindowHwnd = IntPtr.Zero Then WindowHwnd = FindWindow(Nothing, "Plain Craft Launcher 2 ")
+ If WindowHwnd <> IntPtr.Zero Then ShowWindowToTop(WindowHwnd)
+ '播放提示音并退出
+ Beep()
+ Environment.[Exit](ProcessReturnValues.Cancel)
Catch ex As Exception
-
+ Logger.Warn(ex, "单例检查失败")
End Try
-
- Return False
- End Function
-
- '''
- ''' 从文件锁中尝试拖出进程
- '''
- Public Sub DropToTopByLock(LockPath As String)
- Dim Pid As Integer
- If Not Integer.TryParse(File.ReadAllText(LockPath), Pid) Then Return
- Dim Handle = Process.GetProcessById(Pid)?.MainWindowHandle
- If Handle <> Intptr.Zero Then ShowWindowToTop(Handle)
End Sub
+ Private Shared PclMutex As Mutex
'结束
Private Sub Application_SessionEnding(sender As Object, e As SessionEndingCancelEventArgs) Handles Me.SessionEnding
diff --git a/Plain Craft Launcher 2/Controls/MyButton.xaml b/Plain Craft Launcher 2/Controls/MyButton.xaml
index a952e94..ad6142d 100644
--- a/Plain Craft Launcher 2/Controls/MyButton.xaml
+++ b/Plain Craft Launcher 2/Controls/MyButton.xaml
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FocusVisualStyle="{x:Null}" x:Name="PanBack"
- Focusable="True" UseLayoutRounding="False" SnapsToDevicePixels="False" Background="{StaticResource ColorBrushSemiTransparent}" Cursor="Hand">
+ Focusable="True" UseLayoutRounding="False" SnapsToDevicePixels="False" Background="{StaticResource ColorBrushSemiTransparent}">
diff --git a/Plain Craft Launcher 2/Controls/MyCheckBox.xaml b/Plain Craft Launcher 2/Controls/MyCheckBox.xaml
index 34b2a45..c0cac06 100644
--- a/Plain Craft Launcher 2/Controls/MyCheckBox.xaml
+++ b/Plain Craft Launcher 2/Controls/MyCheckBox.xaml
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MyCheckBox"
FocusVisualStyle="{x:Null}"
- MinWidth="20" x:Name="PanBack" UseLayoutRounding="False" SnapsToDevicePixels="False" MinHeight="20" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True" d:DesignWidth="126.4" d:DesignHeight="44.8" Cursor="Hand">
+ MinWidth="20" x:Name="PanBack" UseLayoutRounding="False" SnapsToDevicePixels="False" MinHeight="20" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True" d:DesignWidth="126.4" d:DesignHeight="44.8">
diff --git a/Plain Craft Launcher 2/Controls/MyExtraButton.xaml b/Plain Craft Launcher 2/Controls/MyExtraButton.xaml
index 27686cd..f8a0d88 100644
--- a/Plain Craft Launcher 2/Controls/MyExtraButton.xaml
+++ b/Plain Craft Launcher 2/Controls/MyExtraButton.xaml
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="PanBack" mc:Ignorable="d" x:Class="MyExtraButton"
- Width="40" RenderTransformOrigin="0.5,0.5" ToolTipService.Placement="Left" ToolTipService.VerticalOffset="16" ToolTipService.HorizontalOffset="-8" Height="0" Cursor="Hand">
+ Width="40" RenderTransformOrigin="0.5,0.5" ToolTipService.Placement="Left" ToolTipService.VerticalOffset="16" ToolTipService.HorizontalOffset="-8" Height="0">
diff --git a/Plain Craft Launcher 2/Controls/MyIconTextButton.xaml b/Plain Craft Launcher 2/Controls/MyIconTextButton.xaml
index 5e1c188..abd786d 100644
--- a/Plain Craft Launcher 2/Controls/MyIconTextButton.xaml
+++ b/Plain Craft Launcher 2/Controls/MyIconTextButton.xaml
@@ -1,7 +1,7 @@
+ HorizontalAlignment="Center" VerticalAlignment="Center" Background="{StaticResource ColorBrushSemiTransparent}" CornerRadius="13.5" MinHeight="27" MaxHeight="27">
diff --git a/Plain Craft Launcher 2/Controls/MyImage.vb b/Plain Craft Launcher 2/Controls/MyImage.vb
index 06a18fe..f4f007e 100644
--- a/Plain Craft Launcher 2/Controls/MyImage.vb
+++ b/Plain Craft Launcher 2/Controls/MyImage.vb
@@ -112,7 +112,7 @@
End If
'从缓存加载网络图片
Dim EnableCache As Boolean = Me.EnableCache
- Dim TempPath As String = $"{PathTemp}MyImage\{GetHash(Source)}.png{If(EnableCache, "", GetUuid())}" '不启用缓存时在末尾加上随机字符串,避免冲突
+ Dim TempPath As String = $"{PathTemp}MyImage\{Source.GetStableHashCode()}.png{If(EnableCache, "", GetUuid())}" '不启用缓存时在末尾加上随机字符串,避免冲突
Dim TempFile = FileUtils.GetInfo(TempPath)
If EnableCache AndAlso TempFile.Exists Then
ActualSource = TempPath '显示缓存的图片
diff --git a/Plain Craft Launcher 2/Controls/MyListItem.xaml b/Plain Craft Launcher 2/Controls/MyListItem.xaml
index 9c722d6..1624ab8 100644
--- a/Plain Craft Launcher 2/Controls/MyListItem.xaml
+++ b/Plain Craft Launcher 2/Controls/MyListItem.xaml
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="PanBack"
- RenderTransformOrigin="0.5,0.5" Background="{StaticResource ColorBrushSemiTransparent}" Height="42" Cursor="Hand">
+ RenderTransformOrigin="0.5,0.5" Background="{StaticResource ColorBrushSemiTransparent}" Height="42">
diff --git a/Plain Craft Launcher 2/Controls/MyRadioBox.xaml b/Plain Craft Launcher 2/Controls/MyRadioBox.xaml
index e13890e..2a8849e 100644
--- a/Plain Craft Launcher 2/Controls/MyRadioBox.xaml
+++ b/Plain Craft Launcher 2/Controls/MyRadioBox.xaml
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FocusVisualStyle="{x:Null}"
- MinWidth="20" x:Name="PanBack" UseLayoutRounding="False" SnapsToDevicePixels="False" MinHeight="20" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True" Cursor="Hand">
+ MinWidth="20" x:Name="PanBack" UseLayoutRounding="False" SnapsToDevicePixels="False" MinHeight="20" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True">
diff --git a/Plain Craft Launcher 2/Controls/MyRadioBox.xaml.vb b/Plain Craft Launcher 2/Controls/MyRadioBox.xaml.vb
index a5f1510..71bfccc 100644
--- a/Plain Craft Launcher 2/Controls/MyRadioBox.xaml.vb
+++ b/Plain Craft Launcher 2/Controls/MyRadioBox.xaml.vb
@@ -99,7 +99,6 @@ Public Class MyRadioBox
End Try
End Sub
Private Sub SyncUI()
- Cursor = If(Checked, Nothing, Cursors.Hand)
If AniControlEnabled = 0 AndAlso IsLoaded Then '防止默认属性变更触发动画
If Checked Then
'由无变有
@@ -198,9 +197,6 @@ Public Class MyRadioBox
Private Const AnimationTimeOfMouseIn As Integer = 100 '鼠标指向动画长度
Private Const AnimationTimeOfMouseOut As Integer = 200 '鼠标指向动画长度
Private Const AnimationTimeOfCheck As Integer = 150 '勾选状态变更动画长度
- Private Sub MyRadioBox_Loaded() Handles Me.Loaded
- Cursor = If(Checked, Nothing, Cursors.Hand)
- End Sub
Private Sub Radiobox_IsEnabledChanged() Handles Me.IsEnabledChanged
If Me.IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
'有动画
diff --git a/Plain Craft Launcher 2/Controls/MyRadioButton.xaml b/Plain Craft Launcher 2/Controls/MyRadioButton.xaml
index 4fb214b..aa42f53 100644
--- a/Plain Craft Launcher 2/Controls/MyRadioButton.xaml
+++ b/Plain Craft Launcher 2/Controls/MyRadioButton.xaml
@@ -1,7 +1,7 @@
+ HorizontalAlignment="Center" VerticalAlignment="Center" Background="{StaticResource ColorBrushSemiTransparent}" CornerRadius="13.5" MinHeight="27" MaxHeight="27">
diff --git a/Plain Craft Launcher 2/Controls/MyRadioButton.xaml.vb b/Plain Craft Launcher 2/Controls/MyRadioButton.xaml.vb
index 23d77f8..a7d3a7e 100644
--- a/Plain Craft Launcher 2/Controls/MyRadioButton.xaml.vb
+++ b/Plain Craft Launcher 2/Controls/MyRadioButton.xaml.vb
@@ -167,7 +167,6 @@ Public Class MyRadioButton
Private Const AnimationTimeOfMouseOut As Integer = 150 '鼠标移出动画长度
Private Const AnimationTimeOfCheck As Integer = 120 '勾选状态变更动画长度
Private Sub RefreshColor(Optional obj = Nothing, Optional e = Nothing) Handles Me.MouseEnter, Me.MouseLeave, Me.Loaded
- Cursor = If(Checked, Nothing, Cursors.Hand)
Try
If IsLoaded AndAlso AniControlEnabled = 0 AndAlso Not False.Equals(e) Then '防止默认属性变更触发动画,若强制不执行动画,则 e 为 False
diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb
index 5ab4ed7..1d7d171 100644
--- a/Plain Craft Launcher 2/FormMain.xaml.vb
+++ b/Plain Craft Launcher 2/FormMain.xaml.vb
@@ -11,10 +11,10 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
If BuildType = BuildTypes.Release Then
- If LastVersion < 400 Then 'Release 2.12.8.0
+ If LastVersion < 402 Then 'Release 2.12.8.1
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:升级框架到 .NET Framework 4.8"))
- FeatureCount += 28
- BugCount += 19
+ FeatureCount += 35
+ BugCount += 21
End If
If LastVersion < 398 Then 'Release 2.12.7.3
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:下载游戏、整合包的稳定性"))
@@ -74,6 +74,11 @@ Public Class FormMain
'3:BUG+ IMP* FEAT-
'2:BUG* IMP-
'1:BUG-
+ If LastVersion < 401 Then 'Snapshot 2.12.8.1
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:可能无法更换披风"))
+ FeatureCount += 8
+ BugCount += 6
+ End If
If LastVersion < 399 Then 'Snapshot 2.12.8.0
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:升级框架到 .NET Framework 4.8"))
FeatureCount += 28
diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
index 4ab2286..b51d89c 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
@@ -10,12 +10,12 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
- Public Const VersionBaseName As String = "2.12.8.0" '显示用版本名
+ Public Const VersionBaseName As String = "2.12.8.1" '显示用版本名
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
#If RELEASE Then
- Public Const VersionCode As Integer = 400 '正式版
+ Public Const VersionCode As Integer = 402 '正式版
#Else
- Public Const VersionCode As Integer = 399 '快照版
+ Public Const VersionCode As Integer = 401 '快照版
#End If
'版本信息
@@ -710,13 +710,13 @@ Public Module ModBase
End If
If Not String.IsNullOrEmpty(Hash) Then
If Hash.Length < 35 Then 'MD5
- Dim md5 As String = HashUtils.ComputeFromFile(LocalPath, HashUtils.HashMethod.Md5)
+ Dim md5 As String = CryptographyUtils.ComputeFileHash(LocalPath, CryptographyUtils.HashMethod.Md5)
If Hash.Lower <> md5 Then Return "文件 MD5 应为 " & Hash & ",实际为 " & md5
ElseIf Hash.Length = 64 Then 'SHA256
- Dim sha256 As String = HashUtils.ComputeFromFile(LocalPath, HashUtils.HashMethod.Sha256)
+ Dim sha256 As String = CryptographyUtils.ComputeFileHash(LocalPath, CryptographyUtils.HashMethod.Sha256)
If Hash.Lower <> sha256 Then Return "文件 SHA256 应为 " & Hash & ",实际为 " & sha256
Else 'SHA1 (40)
- Dim sha1 As String = HashUtils.ComputeFromFile(LocalPath, HashUtils.HashMethod.Sha1)
+ Dim sha1 As String = CryptographyUtils.ComputeFileHash(LocalPath, CryptographyUtils.HashMethod.Sha1)
If Hash.Lower <> sha1 Then Return "文件 SHA1 应为 " & Hash & ",实际为 " & sha1
End If
End If
@@ -793,30 +793,6 @@ Public Module ModBase
End Try
End Function
- '''
- ''' 获取字符串哈希值。
- '''
- Public Function GetHash(Str As String) As ULong
- Dim Result As ULong = 5381
- For Each v In Str
- Result = (Result << 5) Xor Result Xor CType(AscW(v), ULong)
- Next
- Return Result Xor &HA98F501BC684032FUL
- End Function
- '''
- ''' 获取字符串 MD5。
- '''
- Public Function GetStringMD5(Str As String) As String
- Using h = MD5Cng.Create()
- Dim hashedDataBytes = h.ComputeHash(Encoding.UTF8.GetBytes(Str))
- Dim tmp As New StringBuilder(hashedDataBytes.Length * 2)
- For Each i As Byte In hashedDataBytes
- tmp.Append(i.ToString("x2"))
- Next
- Return tmp.ToString()
- End Using
- End Function
-
'''
''' 不会报错的 Val。
''' 如果输入有误,返回 0。
@@ -1399,12 +1375,17 @@ Public Module ModBase
''' 将程序中的资源释放到文件。
'''
Public Sub ExtractResources(FilePath As String, ResourceName As String)
- Logger.Info($"将资源写入到文件:{ResourceName} → {FilePath}")
Dim Resource = My.Resources.ResourceManager.GetObject(ResourceName)
If TypeOf Resource Is Byte() Then
- FileUtils.Write(FilePath, DirectCast(Resource, Byte()))
+ Dim Bytes = DirectCast(Resource, Byte())
+ If FileUtils.Exists(FilePath) AndAlso CryptographyUtils.ComputeFileHash(FilePath) = CryptographyUtils.ComputeHash(Bytes) Then Return
+ Logger.Info($"将资源写入到文件:{ResourceName} → {FilePath}")
+ FileUtils.Write(FilePath, Bytes)
ElseIf TypeOf Resource Is String Then
- FileUtils.Write(FilePath, DirectCast(Resource, String))
+ Dim Content = DirectCast(Resource, String)
+ If FileUtils.Exists(FilePath) AndAlso FileUtils.ReadAsString(FilePath) = Content Then Return
+ Logger.Info($"将资源写入到文件:{ResourceName} → {FilePath}")
+ FileUtils.Write(FilePath, Content)
Else
Throw New Exception($"资源 {ResourceName} 的类型不支持:{Resource.GetType.Name}")
End If
diff --git a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
index 2adc2e2..0b785f9 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
@@ -8,7 +8,6 @@
Implements ILoadingTrigger
Public ReadOnly Property IsLoader As Boolean = True Implements ILoadingTrigger.IsLoader
- Protected Shared LogBlackList As String() = {"EasyTier CLI"}
'基础属性
'''
@@ -90,7 +89,7 @@
Dim OldState = _State
If value = LoadState.Finished AndAlso Settings.Get(Of Boolean)("SystemDebugDelay") Then Thread.Sleep(RandomInteger(100, 2000))
_State = value
- If Not LogBlackList.Contains(Name) Then Logger.Info($"加载器 {Name} 状态改变:{value}")
+ Logger.Log($"加载器 {Name} 状态改变:{value}", If(value = LoadState.Failed, LogLevel.Error, LogLevel.Info))
'实现 ILoadingTrigger 接口与 OnStateChanged 回调
RunInUi(
Sub()
@@ -319,13 +318,13 @@
Sub()
Try
IsForceRestarting = IsForceRestart
- If Not LogBlackList.Contains(Name) Then Logger.Trace(Function() $"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已{If(IsForceRestarting, "强制", "")}启动")
+ Logger.Trace(Function() $"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已{If(IsForceRestarting, "强制", "")}启动")
LoadDelegate(Me)
If IsInterrupted Then
Logger.Warn($"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已中断但线程正常运行至结束,输出被弃用(最新线程:{If(LastRunningThread Is Nothing, -1, LastRunningThread.ManagedThreadId)})")
Return
End If
- If Not LogBlackList.Contains(Name) Then Logger.Trace(Function() $"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已完成")
+ Logger.Trace(Function() $"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 已完成")
RaisePreviewFinish()
State = LoadState.Finished
LastFinishedTime = GetTimeMs() '未中断,本次输出有效
diff --git a/Plain Craft Launcher 2/Modules/Base/ModNet.vb b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
index fad8b5d..72ab616 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModNet.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
@@ -261,8 +261,11 @@ Retry:
})
End If
End SyncLock
- CancelToken.Dispose() : CancelToken = New CancellationTokenSource(Timeout)
- Response = RequestClient.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
+ ResilientUtils.RetryOn(Of FileNotFoundException, IOException)( 'CacheCow 读取缓存时若文件被占用,会调用不存在的 System.Net.Http.Formatting.resources,抛出此异常(#8150)
+ Sub()
+ CancelToken.Dispose() : CancelToken = New CancellationTokenSource(Timeout)
+ Response = RequestClient.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
+ End Sub)
Dim ResponseBytes As Byte()
CancelToken.Dispose() : CancelToken = New CancellationTokenSource(Timeout)
Using ResponseStream = Response.Content.ReadAsStreamAsync().GetResultWithTimeout(CancelToken, Timeout)
@@ -286,9 +289,6 @@ Retry:
Throw
Catch ex As HttpRequestException
Throw
- Catch ex As FileNotFoundException
- '由于 CacheCow 读取缓存失败,然后系统调用不存在的 System.Net.Http.Formatting.resources 抛出(#8150)
- Throw New Exception($"网络请求时读取缓存失败", ex)
Catch ex As Exception
RecordIPReliability(HostIp, -1)
If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then 'CancellationToken 超时
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
index ee40936..7eb0032 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
@@ -333,7 +333,7 @@ NextInner:
Me.Type = Type
End Sub
Public Overrides Function GetHashCode() As Integer
- Return GetHash(UserName & Password & BaseUrl & Token & Type) Mod Integer.MaxValue
+ Return (UserName & Password & BaseUrl & Token & Type).GetStableHashCode() Mod Integer.MaxValue
End Function
End Class
@@ -353,7 +353,7 @@ NextInner:
Type = McLoginType.Ms
End Sub
Public Overrides Function GetHashCode() As Integer
- Return GetHash(OAuthRefreshToken & AccessToken & Uuid & UserName & ProfileJson) Mod Integer.MaxValue
+ Return (OAuthRefreshToken & AccessToken & Uuid & UserName & ProfileJson).GetStableHashCode() Mod Integer.MaxValue
End Function
End Class
Public Class McLoginLegacy
@@ -375,7 +375,7 @@ NextInner:
Type = McLoginType.Legacy
End Sub
Public Overrides Function GetHashCode() As Integer
- Return GetHash(UserName & SkinType & SkinName & Type) Mod Integer.MaxValue
+ Return (UserName & SkinType & SkinName & Type).GetStableHashCode() Mod Integer.MaxValue
End Function
End Class
@@ -535,21 +535,15 @@ NextInner:
Data.Progress = 0.05
'检查是否已经登录完成
Dim ExpiresAt = Settings.Get(Of Long)("CacheMsV2Expires")
-
If Not Data.IsForceRestarting AndAlso '不要求强行重启
- ExpiresAt > 0 AndAlso ExpiresAt > GetUnixTimestampUtc() Then 'AccessToken 尚未过期
- 'https://github.com/Meloong-Git/PCL/issues/8638
- '如果是程序刚启动时调用的登录,此时加载器的状态为 Waiting,GetLoginData 函数会返回不带 ProfileJson 的数据作为输入
- If String.IsNullOrEmpty(Input.ProfileJson) Then
- Input = PageLoginMsSkin.GetLoginData(True)
- End If
+ ExpiresAt > 0 AndAlso ExpiresAt > GetUnixTimestampUtc() AndAlso 'AccessToken 尚未过期
+ Input.UserName = Settings.Get(Of String)("CacheMsV2Name") Then
Data.Output = New McLoginResult With {
- .AccessToken = Input.AccessToken,
- .Name = Input.UserName,
- .Uuid = Input.Uuid,
- .Type = "Microsoft",
- .ClientToken = Input.Uuid,
- .ProfileJson = Input.ProfileJson
+ .Name = Input.UserName, .Type = "Microsoft",
+ .AccessToken = Settings.Get(Of String)("CacheMsV2Access"),
+ .Uuid = Settings.Get(Of String)("CacheMsV2Uuid"),
+ .ClientToken = Settings.Get(Of String)("CacheMsV2Uuid"),
+ .ProfileJson = Settings.Get(Of String)("CacheMsV2ProfileJson")
}
McLaunchLog("无需登录,AccessToken 尚未过期")
GoTo SkipLogin
@@ -1018,16 +1012,18 @@ Retry:
Result = NetRequestByClientRetry("https://api.minecraftservices.com/authentication/login_with_xbox", HttpMethod.Post,
Content:=Request, ContentType:="application/json", RequireJson:=True)
Catch ex As HttpRequestCodeException
- Select Case ex.StatusCode
- Case 429
- Logger.Warn(ex, "微软登录第 4 步汇报 429")
- Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
- Case HttpStatusCode.Forbidden
- Logger.Warn(ex, "微软登录第 4 步汇报 403")
- Throw New Exception("$当前 IP 的登录尝试异常。" & vbCrLf & "如果你使用了 VPN 或加速器,请把它们关掉或更换节点后再试!")
- Case Else
- Throw
- End Select
+ If ex.StatusCode = 429 Then
+ Logger.Warn(ex, "微软登录第 4 步汇报 429")
+ Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
+ ElseIf ex.StatusCode = HttpStatusCode.Forbidden Then
+ Logger.Warn(ex, "微软登录第 4 步汇报 403")
+ Throw New Exception("$当前 IP 的登录尝试异常。" & vbCrLf & "如果你使用了 VPN 或加速器,请把它们关掉或更换节点后再试!")
+ ElseIf ex.Response?.Contains("ACCOUNT_SUSPENDED") Then '#8655
+ MyMsgBox("该账号似乎已被微软封禁,无法登录。", "登录失败", "我知道了", IsWarn:=True)
+ Throw New Exception("$$")
+ Else
+ Throw
+ End If
End Try
Dim ResultJson As JObject = GetJson(Result)
@@ -1152,7 +1148,7 @@ Retry:
Return Uuid
End Function
Public Function McLoginLegacyUuid(Name As String)
- Dim FullUuid As String = Name.Length.ToString("X").EnsureLength("0", 16) & GetHash(Name).ToString("X").EnsureLength("0", 16)
+ Dim FullUuid As String = Name.Length.ToString("X").EnsureLength("0", 16) & Name.GetStableHashCode().ToString("X").EnsureLength("0", 16)
Return FullUuid.Substring(0, 12) & "3" & FullUuid.Substring(13, 3) & "9" & FullUuid.Substring(17, 15)
End Function
@@ -1445,14 +1441,13 @@ NextInstance:
End If
'JLW
- '修复 Java 18- 在 Windows UTF-8 Beta 模式(非 GBK 编码)下命令行参数乱码的问题(JDK-8272352)
+ '非 GBK 编码下命令行参数乱码的问题(JDK-8272352)
Dim UseJLW As Boolean =
Not Settings.Get(Of Boolean)("LaunchAdvanceDisableJLW") AndAlso Not Settings.Get(Of Boolean)("VersionAdvanceDisableJLW", McInstanceSelected) AndAlso
- McLaunchJavaSelected.MajorVersion <= 18 AndAlso 'Java 19+ 已经修复了该 Bug
Not IsGBKEncoding AndAlso Not McFolderSelected.IsAsciiOnly() '仅在该环境下才会触发该 Bug
If UseJLW AndAlso CustomArg.Contains("-javaagent") Then
UseJLW = False
- McLaunchLog("由于使用自定义 javaagent,已禁用 JLW,这可能导致游戏崩溃!", LogLevel.Warn)
+ McLaunchLog("由于使用了自定义 javaagent,已禁用 JLW,这可能导致游戏崩溃!", LogLevel.Warn)
End If
If UseJLW Then
If McLaunchJavaSelected.MajorVersion >= 9 Then
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
index 5833d96..47d93ac 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
@@ -1286,7 +1286,7 @@ ExitDataLoad:
GoTo OnLoaded
End If
'有可用版本
- Dim FolderListCheck As Integer = GetHash(Versions.MCINSTANCE_CACHE_VERSION & "#" & FolderList.Join("#"c)) Mod (Integer.MaxValue - 1) '根据文件夹名列表生成辨识码
+ Dim FolderListCheck As Integer = (Versions.MCINSTANCE_CACHE_VERSION & "#" & FolderList.Join("#"c)).GetStableHashCode() Mod (Integer.MaxValue - 1) '根据文件夹名列表生成辨识码
If Not McInstanceListForceRefresh AndAlso Val(ReadIni(PathMc & "PCL.ini", "InstanceCache")) = FolderListCheck Then
'可以使用缓存
Dim Result = InitMcInstanceListWithCache(PathMc)
@@ -1747,7 +1747,7 @@ OnLoaded:
'''
Public Function McSkinDownload(Address As String) As String
Dim SkinName As String = PathUtils.GetLastPart(Address)
- Dim FileAddress As String = PathTemp & "Cache\Skin\" & GetHash(Address) & ".png"
+ Dim FileAddress As String = PathTemp & "Cache\Skin\" & Address.GetStableHashCode() & ".png"
SyncLock McSkinDownloadLock
If Not FileUtils.Exists(FileAddress) Then
NetDownloadByClient(Address, FileAddress & ".PCLDownloading")
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
index 1935c28..830f1ea 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
@@ -162,11 +162,11 @@
'Else
If State = MinecraftState.Loading Then
'窗口未出现
- WatcherLog("Minecraft 尚未加载完成,可能已崩溃")
+ WatcherLog("Minecraft 尚未加载完成,可能已崩溃", LogLevel.Error)
Crashed()
ElseIf GameProcess.ExitCode <> 0 AndAlso State = MinecraftState.Running AndAlso Instance.ReleaseTime.Year >= 2012 Then
'返回值不为 0 且未结束
- WatcherLog("Minecraft 返回值异常,可能已崩溃")
+ WatcherLog("Minecraft 返回值异常,可能已崩溃", LogLevel.Error)
Crashed()
ElseIf State <> MinecraftState.Crashed Then
'正常关闭
@@ -215,15 +215,15 @@
ElseIf Text.Contains("Crash report saved to") OrElse Text.Contains("This crash report has been saved to:") Then
' Text.Contains("Minecraft ran into a problem! Report saved to:") Then
'Minecraft 崩溃,忽略 VanillaFix
- WatcherLog("识别为崩溃的 Log:" & Text)
+ WatcherLog("识别为崩溃的 Log:" & Text, LogLevel.Error)
Crashed()
ElseIf Text.Contains("Could not save crash report to") Then
'Minecraft 崩溃,无法保存崩溃日志
- WatcherLog("识别为崩溃的 Log:" & Text)
+ WatcherLog("识别为崩溃的 Log:" & Text, LogLevel.Error)
Crashed()
ElseIf Text.Contains("/ERROR]: Unable to launch") OrElse Text.Contains("An exception was thrown, the game will display an error screen and halt.") Then
'Forge 崩溃
- WatcherLog("识别为崩溃的 Log:" & Text)
+ WatcherLog("识别为崩溃的 Log:" & Text, LogLevel.Error)
Crashed()
'ElseIf Text.Contains("Shutdown failure!") Then
' 'Minecraft 强行崩溃,由于点 X 强行关闭也会触发这句话,所以不可用
@@ -231,8 +231,8 @@
End If
End If
End Sub
- Private Sub WatcherLog(Text As String)
- McLaunchLog("[" & PID & "] " & Text)
+ Private Sub WatcherLog(Text As String, Optional Level As LogLevel = LogLevel.Info)
+ McLaunchLog("[" & PID & "] " & Text, Level)
End Sub
'进度更新
@@ -349,7 +349,7 @@
If State = MinecraftState.Crashed OrElse State = MinecraftState.Ended Then Return
State = MinecraftState.Crashed
'崩溃分析
- WatcherLog("Minecraft 已崩溃,将在 2 秒后开始崩溃分析")
+ WatcherLog("Minecraft 已崩溃,将在 2 秒后开始崩溃分析", LogLevel.Error)
Hint("检测到 Minecraft 出现错误,错误分析已开始……", HintType.Red)
FeedbackInfo()
RunInNewThread(
diff --git a/Plain Craft Launcher 2/Modules/ModMain.vb b/Plain Craft Launcher 2/Modules/ModMain.vb
index 70afc56..0972d21 100644
--- a/Plain Craft Launcher 2/Modules/ModMain.vb
+++ b/Plain Craft Launcher 2/Modules/ModMain.vb
@@ -850,7 +850,8 @@ NextFile:
Text = Text.Replace("{path}", Replacer(PathUtils.CurrentFolder))
Text = Text.Replace("{path_with_name}", Replacer(PathExe))
Text = Text.Replace("{path_temp}", Replacer(PathTemp))
- Text = Text.Replace("{pcl_md5}", Function() Replacer(HashUtils.ComputeFromFile(PathExe, HashUtils.HashMethod.Md5)))
+ Text = Text.Replace("{pcl_md5}", Function() Replacer(CryptographyUtils.ComputeFileHash(PathExe, CryptographyUtils.HashMethod.Md5)))
+ Text = Text.Replace("{pcl_sha1}", Function() Replacer(CryptographyUtils.ComputeFileHash(PathExe, CryptographyUtils.HashMethod.Sha1)))
'时间
If ReplaceTime Then '在窗口标题中,时间会被后续动态替换,所以此时不应该替换
Text = Text.Replace("{date}", Replacer(Date.Now.ToString("yyyy'/'M'/'d")))
@@ -976,7 +977,7 @@ NextFile:
'''
Public Sub FeedbackInfo()
On Error Resume Next
- Logger.Info($"诊断信息:{vbCrLf}" &
+ Logger.Warn($"诊断信息:{vbCrLf}" &
"操作系统:" & My.Computer.Info.OSFullName & "(32 位:" & Is32BitSystem & ")" & vbCrLf &
"剩余内存:" & Int(My.Computer.Info.AvailablePhysicalMemory / 1024 / 1024) & " M / " & Int(My.Computer.Info.TotalPhysicalMemory / 1024 / 1024) & " M" & vbCrLf &
"DPI:" & DPI & "(" & Math.Round(DPI / 96, 2) * 100 & "%)" & vbCrLf &
diff --git a/Plain Craft Launcher 2/Modules/ModSecret.vb b/Plain Craft Launcher 2/Modules/ModSecret.vb
index 97e5e19..09ed647 100644
--- a/Plain Craft Launcher 2/Modules/ModSecret.vb
+++ b/Plain Craft Launcher 2/Modules/ModSecret.vb
@@ -1,7 +1,5 @@
'由于包含加解密等安全信息,本文件中的部分代码已被删除
-Imports System.Security.Cryptography
-
Friend Module ModSecret
'标注 PCL 的不同分支,仅用于替换标记
@@ -40,51 +38,6 @@ Friend Module ModSecret
#End Region
-#Region "字符串加解密"
-
- '''
- ''' 获取八位密钥。
- '''
- Private Function SecretKeyGet(Key As String) As String
- Return "00000000"
- End Function
- '''
- ''' 加密字符串。
- '''
- Friend Function SecretEncrypt(SourceString As String, Optional Key As String = "") As String
- Key = SecretKeyGet(Key)
- Dim btKey As Byte() = Encoding.UTF8.GetBytes(Key)
- Dim btIV As Byte() = Encoding.UTF8.GetBytes("87160295")
- Dim des As New DESCryptoServiceProvider
- Using MS As New MemoryStream
- Dim inData As Byte() = Encoding.UTF8.GetBytes(SourceString)
- Using cs As New CryptoStream(MS, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write)
- cs.Write(inData, 0, inData.Length)
- cs.FlushFinalBlock()
- Return Convert.ToBase64String(MS.ToArray())
- End Using
- End Using
- End Function
- '''
- ''' 解密字符串。
- '''
- Friend Function SecretDecrypt(SourceString As String, Optional Key As String = "") As String
- Key = SecretKeyGet(Key)
- Dim btKey As Byte() = Encoding.UTF8.GetBytes(Key)
- Dim btIV As Byte() = Encoding.UTF8.GetBytes("87160295")
- Dim des As New DESCryptoServiceProvider
- Using MS As New MemoryStream
- Dim inData As Byte() = Convert.FromBase64String(SourceString)
- Using cs As New CryptoStream(MS, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write)
- cs.Write(inData, 0, inData.Length)
- cs.FlushFinalBlock()
- Return Encoding.UTF8.GetString(MS.ToArray())
- End Using
- End Using
- End Function
-
-#End Region
-
#Region "主题"
Public Color1 As New MyColor(52, 61, 74)
diff --git a/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb b/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb
index a38028e..62337e9 100644
--- a/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb
@@ -418,7 +418,7 @@ Finished:
Get
If _CurseForgeHash Is Nothing Then
'读取缓存
- Dim CacheKey As String = GetHash($"{EnabledFullName}-{File.LastWriteTime.ToLongTimeString}-{File.Length}-C")
+ Dim CacheKey As String = $"{EnabledFullName}-{File.LastWriteTime.ToLongTimeString}-{File.Length}-C".GetStableHashCode()
Dim Cached As String = ReadIni(PathTemp & "Cache\ModHash.ini", CacheKey)
If Cached <> "" AndAlso Cached.RegexCheck("^\d+$") Then '#5062
_CurseForgeHash = Cached
@@ -473,14 +473,14 @@ Finished:
Get
If _ModrinthHash Is Nothing Then
'读取缓存
- Dim CacheKey As String = GetHash($"{EnabledFullName}-{File.LastWriteTime.ToLongTimeString}-{File.Length}-M")
+ Dim CacheKey As String = $"{EnabledFullName}-{File.LastWriteTime.ToLongTimeString}-{File.Length}-M".GetStableHashCode()
Dim Cached As String = ReadIni(PathTemp & "Cache\ModHash.ini", CacheKey)
If Cached <> "" Then
_ModrinthHash = Cached
Return _ModrinthHash
End If
'计算 SHA1
- _ModrinthHash = HashUtils.ComputeFromFile(File.FullName, HashUtils.HashMethod.Sha1)
+ _ModrinthHash = CryptographyUtils.ComputeFileHash(File.FullName, CryptographyUtils.HashMethod.Sha1)
'写入缓存
WriteIni(PathTemp & "Cache\ModHash.ini", CacheKey, _ModrinthHash)
End If
diff --git a/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb b/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb
index a286cfc..a7686cf 100644
--- a/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb
@@ -189,6 +189,7 @@
#Region "中文搜索"
Dim RawSearchText As String = If(Request.SearchText, "").Trim
+ RawSearchText = StrConv(RawSearchText, VbStrConv.SimplifiedChinese) '繁体转简体
RawSearchText = RawSearchText.Lower
Logger.Info($"工程列表搜索原始文本:{RawSearchText}")
diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
index 08bc312..c39a58e 100644
--- a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
+++ b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
' 方法是按如下所示使用“*”
-
-
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageInstance/MyLocalModItem.xaml b/Plain Craft Launcher 2/Pages/PageInstance/MyLocalModItem.xaml
index ac889ca..445f44b 100644
--- a/Plain Craft Launcher 2/Pages/PageInstance/MyLocalModItem.xaml
+++ b/Plain Craft Launcher 2/Pages/PageInstance/MyLocalModItem.xaml
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PCL;assembly="
x:Name="PanBack" Height="44"
- RenderTransformOrigin="0.5,0.5" Background="{StaticResource ColorBrushSemiTransparent}" SnapsToDevicePixels="True" Cursor="Hand">
+ RenderTransformOrigin="0.5,0.5" Background="{StaticResource ColorBrushSemiTransparent}" SnapsToDevicePixels="True">
diff --git a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceExport.xaml b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceExport.xaml
index e29a1f2..db2ee7c 100644
--- a/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceExport.xaml
+++ b/Plain Craft Launcher 2/Pages/PageInstance/PageInstanceExport.xaml
@@ -222,6 +222,15 @@
+
+
+
+
+
HashUtils.ComputeFromFile(NewPath, HashUtils.HashMethod.Md5) Then
+ If CryptographyUtils.ComputeFileHash(ModEntity.File.FullName) <> CryptographyUtils.ComputeFileHash(NewPath) Then
MyMsgBox($"目前同时存在启用和禁用的两个 Mod 文件:{vbCrLf} - {PathUtils.GetLastPart(NewPath)}{vbCrLf} - {ModEntity.File.Name}{vbCrLf}{vbCrLf}注意,这两个文件的内容并不相同。{vbCrLf}在手动删除或重命名其中一个文件后,才能继续操作。", "存在文件冲突")
Continue For
End If
@@ -608,8 +608,8 @@ Install:
Next
For Each Entry As KeyValuePair(Of String, String) In FileCopyList
If FileUtils.Exists(Entry.Value) Then
- FileUtils.Delete(Entry.Value, True)
Logger.Warn($"更新后的 Mod 文件已存在,将会把它放入回收站:{Entry.Value}")
+ FileUtils.Delete(Entry.Value, True)
End If
If DirectoryUtils.Exists(PathUtils.RemoveLastPart(Entry.Value)) Then
FileUtils.Move(Entry.Key, Entry.Value)
@@ -723,18 +723,10 @@ Install:
End If
'显示结果提示
If Not IsSuccessful Then Return
- If IsShiftPressed Then
- If ModList.IsSingle Then
- Hint($"已彻底删除 {ModList.Single.File.Name}!", HintType.Green)
- Else
- Hint($"已彻底删除 {ModList.Count} 个文件!", HintType.Green)
- End If
+ If ModList.IsSingle Then
+ Hint($"已删除 {ModList.Single.File.Name}!", HintType.Green)
Else
- If ModList.IsSingle Then
- Hint($"已将 {ModList.Single.File.Name} 删除到回收站!", HintType.Green)
- Else
- Hint($"已将 {ModList.Count} 个文件删除到回收站!", HintType.Green)
- End If
+ Hint($"已删除 {ModList.Count} 个文件!", HintType.Green)
End If
Catch ex As OperationCanceledException
Logger.Warn(ex, "删除 Mod 被主动取消")
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb
index e35d3a4..627a499 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb
@@ -149,7 +149,7 @@
RunInThread(
Sub()
Try
- Hint("正在刷新头像……")
+ Hint("正在刷新皮肤……")
'清空缓存
Logger.Info("正在清空皮肤缓存")
If DirectoryUtils.Exists(PathTemp & "Cache\Skin") Then DirectoryUtils.Delete(PathTemp & "Cache\Skin")
@@ -162,7 +162,7 @@
For Each SkinLoader In If(sender IsNot Nothing, {sender}, {PageLaunchLeft.SkinLegacy, PageLaunchLeft.SkinMs})
SkinLoader.WaitForExit(IsForceRestart:=True)
Next
- Hint("已刷新头像!", HintType.Green)
+ Hint("已刷新皮肤!", HintType.Green)
Catch ex As Exception
Logger.Error(ex, "刷新皮肤缓存失败", LogBehavior.Alert)
End Try
@@ -216,13 +216,13 @@
Hint("登录失败,无法更改披风!", HintType.Red)
Return
End If
- Hint("正在获取披风列表,请稍候……")
+ If McLoginMsLoader.State <> LoadState.Finished Then Hint("正在获取披风列表,请稍候……")
IsChanging = True
'开始实际获取
RunInNewThread(
Sub()
- Try
Retry:
+ Try
'获取登录信息
If McLoginMsLoader.State <> LoadState.Finished Then McLoginMsLoader.WaitForExit(PageLoginMsSkin.GetLoginData())
If McLoginMsLoader.State <> LoadState.Finished Then
@@ -256,7 +256,7 @@ Retry:
Next
SelectedIndex = MyMsgBoxSelect(SelectionControl, "选择披风", "确定", "取消")
Catch ex As Exception
- Logger.Error(ex, "获取玩家披风列表失败")
+ Logger.Error(ex, "获取玩家皮肤列表失败")
End Try
End Sub)
If SelectedIndex Is Nothing Then Return
@@ -279,7 +279,29 @@ Retry:
McLoginMsLoader.Output.ProfileJson = SkinData.ToString()
End If
Catch ex As Exception
- Logger.Error(ex, "更改披风失败", LogBehavior.Toast)
+ If TypeOf ex Is HttpRequestCodeException Then
+ Dim requestException As HttpRequestCodeException = CType(ex, HttpRequestCodeException)
+ Select Case requestException.StatusCode
+ Case HttpStatusCode.BadRequest
+ Logger.Warn(ex, "更改披风时遭遇 400 错误")
+ If requestException.Response?.Contains("""error""") Then
+ Hint("更改披风失败:" & GetJson(requestException.Response)("error").ToString, HintType.Red)
+ Return
+ ElseIf requestException.Response?.Contains("""errorMessage""") Then
+ Hint("更改披风失败:" & GetJson(requestException.Response)("errorMessage").ToString, HintType.Red)
+ Return
+ End If
+ Case HttpStatusCode.Unauthorized
+ Logger.Warn(ex, "更改披风时遭遇 401 错误")
+ Hint("正在重新登录,将在登录后自动更改披风……")
+ McLoginMsLoader.Start(PageLoginMsSkin.GetLoginData(), IsForceRestart:=True)
+ GoTo Retry
+ End Select
+ ElseIf ex.IsBadNetwork Then
+ Hint("更改披风失败:连接 Mojang 服务器超时,请稍后再试,或使用 VPN 改善网络环境", HintType.Red)
+ Else
+ Logger.Error(ex, "更改披风失败", LogBehavior.Toast)
+ End If
Finally
IsChanging = False
End Try
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
index c30354a..f545141 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
@@ -170,7 +170,7 @@ Public Class PageLaunchRight
Settings.Set("CacheSavedPageVersion", Version)
FileUtils.Write(PathTemp & "Cache\Custom.xaml", FileContent)
'若内容变更则要求刷新
- If LoadedContentHash <> FileContent.GetHashCode() AndAlso ShouldRefresh Then Refresh()
+ If LoadedContentHash <> FileContent.GetStableHashCode() AndAlso ShouldRefresh Then Refresh()
Catch ex As Exception
Logger.Error(ex, $"下载主页失败({Address})", If(ModeDebug, LogBehavior.Alert, LogBehavior.Toast))
End Try
@@ -196,7 +196,7 @@ Public Class PageLaunchRight
''' 清空主页缓存信息。
'''
Private Sub ClearCache()
- LoadedContentHash = -1
+ LoadedContentHash = Nothing
OnlineLoader.Input = ("", True)
Settings.Set("CacheSavedPageUrl", "")
Settings.Set("CacheSavedPageVersion", "")
@@ -211,7 +211,7 @@ Public Class PageLaunchRight
Try
SyncLock LoadContentLock
'如果加载目标内容一致则不加载
- Dim Hash = If(Content, "").GetHashCode()
+ Dim Hash = If(Content, "").GetStableHashCode()
If Hash = LoadedContentHash Then Return
LoadedContentHash = Hash
'实际加载内容
@@ -261,7 +261,7 @@ Public Class PageLaunchRight
OnLoadContentFailed(e.Exception)
End Sub
- Private LoadedContentHash As Integer = -1
+ Private LoadedContentHash As ULong? = Nothing
Private LoadContentLock As New Object
#End Region
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml
index edd0547..9d334ca 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml
@@ -23,11 +23,11 @@
+
-
-
+
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
index 441c74a..bc12c52 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
@@ -18,8 +18,8 @@
'''
''' 获取当前页面的登录信息。
'''
- Public Shared Function GetLoginData(Optional IgnoreState As Boolean = False) As McLoginMs
- If IgnoreState OrElse McLoginMsLoader.State = LoadState.Finished Then
+ Public Shared Function GetLoginData() As McLoginMs
+ If McLoginMsLoader.State = LoadState.Finished Then
Return New McLoginMs With {.OAuthRefreshToken = Settings.Get(Of String)("CacheMsV2OAuthRefresh"), .UserName = Settings.Get(Of String)("CacheMsV2Name"), .AccessToken = Settings.Get(Of String)("CacheMsV2Access"), .Uuid = Settings.Get(Of String)("CacheMsV2Uuid"), .ProfileJson = Settings.Get(Of String)("CacheMsV2ProfileJson")}
Else
Return New McLoginMs With {.OAuthRefreshToken = Settings.Get(Of String)("CacheMsV2OAuthRefresh"), .UserName = Settings.Get(Of String)("CacheMsV2Name")}
@@ -105,9 +105,6 @@ Retry:
Hint("正在重新登录,将在登录后自动更改皮肤……")
McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
GoTo Retry
- ElseIf Result.Contains("""error""") Then
- Hint("更改皮肤失败:" & GetJson(Result)("error").ToString, HintType.Red)
- Return
End If
'获取新皮肤地址
Logger.Info($"皮肤修改返回值:{vbCrLf}{Result}")
@@ -121,13 +118,26 @@ Retry:
Next
Throw New Exception("未知错误(" & Result & ")")
Catch ex As Exception
- If ex.IsBadNetwork Then
- Hint("更改皮肤失败:连接皮肤服务器超时,请稍后再试,或使用 VPN 改善网络环境", HintType.Red)
- ElseIf TypeOf ex Is HttpRequestCodeException AndAlso CType(ex, HttpRequestCodeException).StatusCode = HttpStatusCode.Unauthorized Then
- Logger.Warn(ex, "更改皮肤时遭遇 401 错误")
- Hint("正在重新登录,将在登录后自动更改皮肤……")
- McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
- GoTo Retry
+ If TypeOf ex Is HttpRequestCodeException Then
+ Dim requestException As HttpRequestCodeException = CType(ex, HttpRequestCodeException)
+ Select Case requestException.StatusCode
+ Case HttpStatusCode.BadRequest
+ Logger.Warn(ex, "更改皮肤时遭遇 400 错误")
+ If requestException.Response?.Contains("""error""") Then
+ Hint("更改皮肤失败:" & GetJson(requestException.Response)("error").ToString, HintType.Red)
+ Return
+ ElseIf requestException.Response?.Contains("""errorMessage""") Then
+ Hint("更改皮肤失败:" & GetJson(requestException.Response)("errorMessage").ToString, HintType.Red)
+ Return
+ End If
+ Case HttpStatusCode.Unauthorized
+ Logger.Warn(ex, "更改皮肤时遭遇 401 错误")
+ Hint("正在重新登录,将在登录后自动更改皮肤……")
+ McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
+ GoTo Retry
+ End Select
+ ElseIf ex.IsBadNetwork Then
+ Hint("更改皮肤失败:连接 Mojang 服务器超时,请稍后再试,或使用 VPN 改善网络环境", HintType.Red)
Else
Logger.Error(ex, "更改皮肤失败", LogBehavior.Toast)
End If
@@ -151,6 +161,24 @@ Retry:
Skin.BtnSkinCape_Click()
End Sub
+ '刷新披风
+ Public Sub BtnSkinCapeRefresh_Click(sender As Object, e As RoutedEventArgs)
+ RunInThread(
+ Sub()
+ Try
+ Hint("正在刷新披风列表……")
+ If McLaunchLoader.State = LoadState.Loading Then
+ McLoginMsLoader.WaitForExit()
+ Else
+ McLoginMsLoader.WaitForExit(GetLoginData(), IsForceRestart:=True)
+ End If
+ Hint("已刷新披风列表!", HintType.Green)
+ Catch ex As Exception
+ Logger.Error(ex, "刷新披风列表失败", LogBehavior.Toast)
+ End Try
+ End Sub)
+ End Sub
+
#End Region
End Class
diff --git a/Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml.vb b/Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml.vb
index 5b795ae..37fd025 100644
--- a/Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml.vb
@@ -522,7 +522,7 @@ Public Class PageLinkMain
'获取启动参数
Dim Arguments As String = ServerConfig("Link")("Argument")
Arguments += $" --network-name={NetworkName} --network-secret={NetworkSecret} --listeners {ListenersPort} --rpc-portal {RPCPort} --private-mode true"
- Dim HostName = If(IsServerSide, "Server-", "Client-") & Math.Abs(Identify.GetHashCode).ConvertRadix(36)
+ Dim HostName = If(IsServerSide, "Server-", "Client-") & Identify.GetStableHashCode().ConvertRadix(36).TrimStart("-"c).EnsureLength("0", 6)
If IsServerSide Then
Arguments += $" -i 10.114.114.114 --hostname={HostName} --tcp-whitelist={ServerPort} --udp-whitelist={ServerPort}"
Else
diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
index 3f37fce..2f1aeb3 100644
--- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
+++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
@@ -123,6 +123,7 @@
+
@@ -150,6 +151,8 @@
+
+
@@ -164,7 +167,9 @@
+
+
@@ -179,6 +184,7 @@
+
@@ -198,6 +204,7 @@
+
@@ -236,25 +243,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -266,6 +288,7 @@
+
@@ -273,11 +296,15 @@
+
+
+
+
@@ -323,6 +350,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -343,11 +381,13 @@
+
+
@@ -367,6 +407,7 @@
+
@@ -374,12 +415,15 @@
+
+
+
@@ -390,6 +434,7 @@
+
@@ -427,8 +472,14 @@
+
+
+
+
+
+
@@ -443,6 +494,7 @@
+
@@ -457,6 +509,7 @@
+
@@ -469,6 +522,7 @@
+
@@ -496,14 +550,19 @@
+
+
+
+
+
@@ -511,6 +570,7 @@
+
@@ -518,6 +578,7 @@
+
@@ -528,16 +589,19 @@
+
+
+
@@ -549,11 +613,13 @@
+
+
@@ -564,7 +630,9 @@
+
+
@@ -574,6 +642,7 @@
+
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb b/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb
index a6c2148..ea4f0c0 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb
+++ b/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb
@@ -1,4 +1,5 @@
Public Class Settings
+ 'TODO: 目前仅有此处在使用 DES 加密,后续考虑更换加密算法
Public Shared ReadOnly Entries As Dictionary(Of String, Setting) = (New List(Of Setting) From {
New Setting("Identify", "", Source:=Sources.Registry),
New Setting("WindowHeight", 550),
@@ -248,7 +249,7 @@
If Encrypted Then
Try
If Value Is Nothing Then Value = ""
- Value = SecretEncrypt(Value, "PCL" & Identify)
+ Value = CryptographyUtils.DesEncrypt(Value, "PCL" & Identify)
Catch ex As Exception
Logger.Warn(ex, $"加密设置失败:{Key}")
End Try
@@ -318,7 +319,7 @@
'正常读取
Try
Dim GotValue As String = Nothing '先用 String 储存,避免类型转换
- Dim DefaultValue As String = If(Entry.Encrypted, SecretEncrypt(Entry.DefaultValue, "PCL" & Identify), Entry.DefaultValue)
+ Dim DefaultValue As String = If(Entry.Encrypted, CryptographyUtils.DesEncrypt(Entry.DefaultValue, "PCL" & Identify), Entry.DefaultValue)
Select Case Entry.Source
Case Sources.Normal
GotValue = ReadIni("Setup", Key, DefaultValue)
@@ -336,7 +337,7 @@
GotValue = Entry.DefaultValue
Else
Try
- GotValue = SecretDecrypt(GotValue, "PCL" & Identify)
+ GotValue = CryptographyUtils.DesDecrypt(GotValue, "PCL" & Identify)
Catch ex As Exception
Logger.Warn(ex, $"解密设置失败:{Key}")
GotValue = Entry.DefaultValue