Files
PCL-ISE/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadModify.vb
T
2026-10-17 03:39:13 +08:00

728 lines
48 KiB
VB.net
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
''' <summary>
''' 版本修改页:完整还原已安装组件后,复用安装页的选择交互。
''' </summary>
Public Class PageDownloadModify
Inherits PageDownloadInstall
Private InitLoader As LoaderTask(Of McInstance, Object)
Private ForgeVersionLoader As LoaderTask(Of String, List(Of DlForgeVersionEntry))
Private InitialTarget As McComponents '进入时的组件快照
''' <summary>
''' 原版的版本号是否可靠(不是通过 json 模糊分析)。
''' </summary>
Private IsVanillaVersionReliable As Boolean
Private OriginalName As String
Private CustomLogo As String
''' <summary>
''' 开始修改 MC 版本时,记录当前选择的组件,以在修改 MC 版本后尝试自动选中相同组件。
''' </summary>
Private ReadOnly PendingComponents As New Dictionary(Of MyLoading, String)
Private IsRestoringComponents As Boolean
Public Overrides Sub LoaderInit() '父级 Handles Me.Initialized
ControlInit()
InitLoader = New LoaderTask(Of McInstance, Object)("初始化版本修改", AddressOf LoadInstance)
PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, InitLoader, AddressOf LoadInstanceFinished, Function() PageInstanceLeft.Instance)
End Sub
Public Overrides Sub Init() '父级 Handles Me.Loaded
PanBack.ScrollToHome()
Static IsLoad As Boolean = False
If IsLoad Then PageLoaderRestart()
IsLoad = True
End Sub
Private Sub PageUnloaded() Handles Me.Unloaded
InitLoader.Cancel()
End Sub
''' <summary>
''' 读取或初始化版本的安装清单。
''' </summary>
Private Sub LoadInstance(Task As LoaderTask(Of McInstance, Object))
'旧状态清理
RunInUiWait(
Sub()
AniStop("FrmDownloadInstall SelectPageSwitch")
IsSelectNameEdited = False
ClearSelected()
PendingComponents.Clear()
InitialTarget = Nothing
IsInSelectPage = False
PanAllBack.IsHitTestVisible = False
End Sub)
Task.Input.Config.DiscardCache()
'获取 Components
Dim Manifest = Configs.McInstallManifest.Get(Task.Input.Config)
If Manifest IsNot Nothing AndAlso Manifest.SchemaVersion > Versions.McInstallManifestVersion Then
Logger.Warn($"安装清单由更新版本的 PCL 创建(清单版本:{Manifest.SchemaVersion},当前版本:{Versions.McInstallManifestVersion})")
Throw New Exception($"更新 PCL 后才能修改它!点击【设置 → 其他 → 检查更新】以更新。")
End If
If Manifest IsNot Nothing Then
Dim LatestManifest = Manifest.RefreshModComponents(Task.Input.PathIndie)
If LatestManifest IsNot Manifest Then
Manifest = LatestManifest
Configs.McInstallManifest.Set(Manifest, Task.Input.Config)
Task.Input.Config.Save()
End If
End If
Dim Components As McComponents
Dim OptiFineVersion As String = Nothing
If Manifest IsNot Nothing Then
'有清单:从清单读取
Components = Manifest.Components
If Components Is Nothing Then Throw New Exception("安装清单缺少组件信息,无法还原已安装组件。")
IsVanillaVersionReliable = True
Else
'无清单:通过版本 JSON 获取
Dim VersionInfo = New McInstance(Task.Input.PathVersion).Version
If VersionInfo.VanillaName = "Unknown" Then Throw New Exception("无法确定 Minecraft 版本,无法修改")
Dim UnknownLoaders = VersionInfo.ModLoaderVersions.
Where(Function(Loader) String.IsNullOrWhiteSpace(Loader.Value) OrElse Loader.Value = "未知版本").
Select(Function(Loader) Loader.Key.ToString()).ToList()
If UnknownLoaders.Any() Then Throw New Exception($"无法确定 {UnknownLoaders.Join("、")} 的版本,无法修改")
Components = New McComponents(VersionInfo.VanillaName, VersionInfo.ModLoaderVersions)
OptiFineVersion = VersionInfo.OptiFine
IsVanillaVersionReliable = VersionInfo.Reliable
End If
Dim MinecraftVersion = Components.MinecraftVersion
If String.IsNullOrWhiteSpace(MinecraftVersion) Then Throw New Exception("无法确定当前 Minecraft 版本,请检查版本文件")
'等待子列表加载器完成获取
Dim LoaderList As New Dictionary(Of String, LoaderBase) From {
{"Minecraft", DlClientListLoader}, {"OptiFine", DlOptiFineListLoader}, {"LiteLoader", DlLiteLoaderListLoader},
{"NeoForge", DlNeoForgeListLoader}, {"Fabric", DlFabricListLoader}, {"Fabric API", DlFabricApiLoader}, {"OptiFabric", DlOptiFabricLoader}}
Dim ForgeLoader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = Nothing
If McVersion.IsStandardFormat(MinecraftVersion) Then
ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("DlForgeVersion " & MinecraftVersion, AddressOf DlForgeVersionMain)
LoaderList.Add("Forge", ForgeLoader)
End If
For Each Loader In LoaderList.Values
Loader.Start(If(Loader Is ForgeLoader, MinecraftVersion, Nothing), Task.IsForceRestarting)
Next
Do
If Task.IsCanceled Then Return
For Each Pair In LoaderList
Dim Loader = Pair.Value
If Loader.State = LoadState.Failed Then
If Loader Is ForgeLoader AndAlso Loader.Error.Message = "无" Then Continue For 'Forge 无版本时不报错
Throw New Exception($"获取 {Pair.Key} 版本列表失败,请稍后再试,或使用 VPN 改善网络环境", Loader.Error)
ElseIf Loader.State = LoadState.Canceled Then
Throw New Exception($"获取 {Pair.Key} 版本列表被中断,请稍后再试,或使用 VPN 改善网络环境")
End If
Next
If LoaderList.Values.All(Function(Loader) Loader.State = LoadState.Finished OrElse Loader.State = LoadState.Failed) Then Exit Do
Task.Progress = 0.7 * LoaderList.Values.Average(Function(Loader) Loader.Progress)
Thread.Sleep(10)
Loop
If Task.IsCanceled Then Return
Task.Progress = 0.7
'Minecraft
MinecraftVersions = CType(DlClientListLoader.Output.Value("versions").DeepClone(), JArray)
VanillaData = MinecraftVersions.OfType(Of JObject).FirstOrDefault(
Function(v) v("id").ToString.Replace("∞", "infinite") = MinecraftVersion.Replace("∞", "infinite"))
If VanillaData Is Nothing Then Throw New Exception($"Minecraft 列表中没有已安装的 {MinecraftVersion}")
VanillaData("id") = MinecraftVersion
'OptiFine
If Manifest IsNot Nothing Then
SelectedOptiFine = Components.OptiFineEntry?.ToObject(Of DlOptiFineListEntry)()
If SelectedOptiFine IsNot Nothing AndAlso Not DlOptiFineListLoader.Output.Value.Any(Function(v) v.FileName = SelectedOptiFine.FileName) Then
'如果 OptiFine 是 pre 版,可能只在 BMCLAPI 下有,官方源删了。如果是这种缺失数据的情况,换用 BMCLAPI 源作为输出
If DlOptiFineListBmclapiLoader.State <> LoadState.Finished Then DlOptiFineListBmclapiLoader.WaitForExit()
DlOptiFineListLoader.Output = DlOptiFineListBmclapiLoader.Output
End If
ElseIf OptiFineVersion IsNot Nothing AndAlso OptiFineVersion <> "未知版本" Then
SelectedOptiFine = DlOptiFineListLoader.Output.Value.FirstOrDefault(
Function(v) v.Inherit = MinecraftVersion AndAlso
v.InstanceName.AfterLast("-OptiFine_").Replace("HD_U_", "") = OptiFineVersion.Replace("HD_U_", ""))
If SelectedOptiFine Is Nothing Then Throw New Exception($"OptiFine 列表中没有已安装的 {OptiFineVersion}")
End If
'Forge
If Components.ModLoaderVersions.ContainsKey(ModLoaders.Forge) Then
SelectedForge = ForgeLoader?.Output?.FirstOrDefault(
Function(v) v.Inherit = MinecraftVersion AndAlso v.VersionName = Components.ModLoaderVersions(ModLoaders.Forge) AndAlso
v.Category <> "universal" AndAlso v.Category <> "client" AndAlso (SelectedOptiFine Is Nothing OrElse IsOptiFineSuitForForge(SelectedOptiFine, v)))
If SelectedForge Is Nothing Then Throw New Exception($"Forge 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.Forge)}")
End If
'NeoForge
If Components.ModLoaderVersions.ContainsKey(ModLoaders.NeoForge) Then
SelectedNeoForge = DlNeoForgeListLoader.Output.Value.FirstOrDefault(
Function(v) v.Inherit = MinecraftVersion AndAlso v.VersionName = Components.ModLoaderVersions(ModLoaders.NeoForge))
If SelectedNeoForge Is Nothing Then Throw New Exception($"NeoForge 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.NeoForge)}")
End If
'Fabric
If Components.ModLoaderVersions.ContainsKey(ModLoaders.Fabric) Then
Dim FabricEntry = DlFabricListLoader.Output.Value("loader").OfType(Of JObject).FirstOrDefault(
Function(v) v("version").ToString = Components.ModLoaderVersions(ModLoaders.Fabric),
Function(v) v("version").ToString.Replace("+build", "") = Components.ModLoaderVersions(ModLoaders.Fabric))
If FabricEntry Is Nothing OrElse Not DlFabricListLoader.Output.Value("game").OfType(Of JObject).
Any(Function(v) v("version").ToString = MinecraftVersion.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3")) Then
Throw New Exception($"Fabric 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.Fabric)}")
End If
SelectedFabric = FabricEntry("version").ToString
End If
'LiteLoader
If Components.ModLoaderVersions.ContainsKey(ModLoaders.LiteLoader) Then
SelectedLiteLoader = DlLiteLoaderListLoader.Output.Value.FirstOrDefault(
Function(v) v.Inherit = MinecraftVersion AndAlso v.JsonToken("version").ToString = Components.ModLoaderVersions(ModLoaders.LiteLoader))
If SelectedLiteLoader Is Nothing Then Throw New Exception($"LiteLoader 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.LiteLoader)}")
End If
'Fabric API
If Components.FabricApiVersion IsNot Nothing Then
SelectedFabricApi = DlFabricApiLoader.Output.FirstOrDefault(
Function(v) (v.Version = Components.FabricApiVersion OrElse v.Id = Components.FabricApiVersion OrElse
v.Display = Components.FabricApiVersion) AndAlso IsFabricApiCompatible(v, MinecraftVersion))
If SelectedFabricApi Is Nothing Then Throw New Exception($"Fabric API 列表中没有已安装的 {Components.FabricApiVersion}")
End If
'OptiFabric
If Components.OptiFabricVersion IsNot Nothing Then
SelectedOptiFabric = DlOptiFabricLoader.Output.FirstOrDefault(
Function(v) (v.Version = Components.OptiFabricVersion OrElse v.Id = Components.OptiFabricVersion OrElse
v.Display = Components.OptiFabricVersion) AndAlso IsOptiFabricCompatible(v, MinecraftVersion))
If SelectedOptiFabric Is Nothing Then Throw New Exception($"OptiFabric 列表中没有已安装的 {Components.OptiFabricVersion}")
End If
'扫描尚未识别的 Mod 组件
Dim ManagedFiles As New List(Of McInstallManifest.ManagedFile)
If Manifest IsNot Nothing Then ManagedFiles.AddRange(Manifest.ManagedFiles)
#Region "从 mods 文件夹中获取以 Mod 形式安装的组件信息"
'获取 mods 文件夹下的 jar 文件与 SHA1
Dim Mods As New Lazy(Of List(Of (File As FileInfo, Sha1 As String)))(
Function()
Dim ModsFolder = Task.Input.PathIndie & "mods\"
Dim Files = DirectoryUtils.EnumerateFiles(ModsFolder, searchPattern:="*.jar").ToList()
If SelectedLiteLoader IsNot Nothing Then 'LiteLoader 的 OptiFine 安装目录
Files.AddRange(DirectoryUtils.EnumerateFiles(Path.Combine(ModsFolder, MinecraftVersion), searchPattern:="*.jar"))
End If
Dim Entries As New List(Of (File As FileInfo, Sha1 As String))
For Each FilePath In Files
If Task.IsCanceled Then Return Entries
Dim File = FileUtils.GetInfo(FilePath)
Entries.Add((File, New LocalResourceFile(File).ModrinthHash))
Task.Progress = 0.7 + 0.28 * Entries.Count / Files.Count
Next
Return Entries
End Function)
'Fabric API
If SelectedFabric IsNot Nothing AndAlso SelectedFabricApi Is Nothing Then
Dim FabricApiList = DlFabricApiLoader.Output.Where(Function(v) IsFabricApiCompatible(v, MinecraftVersion)).ToList()
Dim Matches As New List(Of (File As FileInfo, Sha1 As String, Version As ResourceVersion))
For Each Entry In Mods.Value
Dim Match = FabricApiList.FirstOrDefault(Function(v) v.Hash = Entry.Sha1)
If Match Is Nothing Then Continue For
Matches.Add((Entry.File, Entry.Sha1, Match))
Next
Dim SelectedFile = SelectMod("Fabric API", Matches)
If SelectedFile IsNot Nothing Then
SelectedFabricApi = SelectedFile.Value.Version
ManagedFiles.Add(New McInstallManifest.ManagedFile("mods/" & SelectedFile.Value.File.Name.Lower(), SelectedFile.Value.Sha1, SelectedFile.Value.File.LastWriteTimeUtc, "FabricApi"))
End If
End If
If Task.IsCanceled Then Return
'OptiFabric
If SelectedFabric IsNot Nothing AndAlso SelectedOptiFabric Is Nothing Then
Dim OptiFabricList = DlOptiFabricLoader.Output.Where(Function(v) IsOptiFabricCompatible(v, MinecraftVersion)).ToList()
Dim HasMd5 = OptiFabricList.Any(Function(v) If(v.Hash, "").Length = 32) 'CurseForge 的 OptiFabric 信息可能提供 SHA1 或 MD5
Dim Matches As New List(Of (File As FileInfo, Sha1 As String, Version As ResourceVersion))
For Each Entry In Mods.Value
Dim Match = OptiFabricList.FirstOrDefault(Function(v) v.Hash = Entry.Sha1)
If Match Is Nothing AndAlso HasMd5 Then
Dim Md5 = CryptographyUtils.ComputeFileHash(Entry.File.FullName, CryptographyUtils.HashMethod.Md5)
Match = OptiFabricList.FirstOrDefault(Function(v) v.Hash = Md5)
End If
If Match Is Nothing Then Continue For
Matches.Add((Entry.File, Entry.Sha1, Match))
Next
Dim SelectedFile = SelectMod("OptiFabric", Matches)
If SelectedFile IsNot Nothing Then
SelectedOptiFabric = SelectedFile.Value.Version
ManagedFiles.Add(New McInstallManifest.ManagedFile("mods/" & SelectedFile.Value.File.Name.Lower(), SelectedFile.Value.Sha1, SelectedFile.Value.File.LastWriteTimeUtc, "OptiFabric"))
End If
End If
If Task.IsCanceled Then Return
'OptiFine
Dim OptiFineFiles As New List(Of (File As FileInfo, Sha1 As String, OriginalName As String))
If SelectedOptiFine Is Nothing AndAlso (SelectedForge IsNot Nothing OrElse SelectedLiteLoader IsNot Nothing OrElse SelectedFabric IsNot Nothing) Then 'OptiFine 只在有 Mod 加载器时才看在不在 mods 文件夹中
Static OptiFineHashes As JObject = FileUtils.ReadAsJson("Minecraft\OptiFineHashes.json", type:=GetType(Resource)) 'JSON 内容:{"SHA1": "原始文件名", ...}
OptiFineFiles = Mods.Value.
Select(Function(Entry) (Entry.File, Entry.Sha1, OriginalName:=OptiFineHashes(Entry.Sha1)?.ToString())). '用本地文件的 SHA1 匹配下载时的原始文件名,再根据原始文件名取得下载源信息
Where(Function(Entry) Entry.OriginalName IsNot Nothing).ToList()
Dim Matches As New List(Of (File As FileInfo, Sha1 As String, Version As DlOptiFineListEntry))
For Each Entry In OptiFineFiles '遍历 hash 匹配到了的本地文件
Dim Match = DlOptiFineListLoader.Output.Value.FirstOrDefault(
Function(v) v.Inherit = MinecraftVersion AndAlso v.FileName = Entry.OriginalName AndAlso (SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(v, SelectedForge)))
If Match Is Nothing Then
Hint($"无法从 OptiFine 列表还原 {Entry.File.Name} 对应的 {Entry.OriginalName},将跳过该文件。")
Continue For
End If
Matches.Add((Entry.File, Entry.Sha1, Match))
Next
Dim SelectedFile = SelectMod("OptiFine", Matches)
If SelectedFile IsNot Nothing Then
SelectedOptiFine = SelectedFile.Value.Version
Dim RelativePath = PathUtils.RemoveExtendedPrefix(SelectedFile.Value.File.FullName).Substring(Task.Input.PathIndie.Length).Replace("\", "/").Lower()
ManagedFiles.Add(New McInstallManifest.ManagedFile(RelativePath, SelectedFile.Value.Sha1, SelectedFile.Value.File.LastWriteTimeUtc, "OptiFine"))
End If
End If
If Task.IsCanceled Then Return
#End Region
'保存 Manifest
If IsVanillaVersionReliable Then
Components = New McComponents(MinecraftVersion, Components.ModLoaderVersions,
If(SelectedOptiFine Is Nothing, Nothing, JObject.FromObject(SelectedOptiFine)),
If(SelectedFabricApi?.Version, If(SelectedFabricApi?.Id, SelectedFabricApi?.Display)),
If(SelectedOptiFabric?.Version, If(SelectedOptiFabric?.Id, SelectedOptiFabric?.Display)))
If Manifest Is Nothing OrElse Not Components.IsEquivalentTo(Manifest.Components) OrElse Not ManagedFiles.SequenceEqual(Manifest.ManagedFiles) Then
Configs.McInstallManifest.Set(New McInstallManifest(Versions.McInstallManifestVersion, Components, Date.UtcNow, ManagedFiles), Task.Input.Config)
Task.Input.Config.Save()
Logger.Info($"已为 {Task.Input.Name} 更新安装清单")
End If
End If
If Task.IsCanceled Then Return
ForgeVersionLoader = ForgeLoader
End Sub
Private Function SelectMod(Of T)(ComponentName As String, Matches As List(Of (File As FileInfo, Sha1 As String, Version As T))) As (File As FileInfo, Sha1 As String, Version As T)?
If Matches.Count = 0 Then Return Nothing
If Matches.Count = 1 Then Return Matches(0)
Dim Choice As Integer? = Nothing
RunInUiWait(Sub() Choice = MyMsgBoxSelect(Matches.Select(Function(Entry) CType(New MyRadioBox With {.Text = Entry.File.Name}, IMyRadio)), $"选择当前使用的 {ComponentName}"))
If Not Choice.HasValue Then Throw New Exception($"发现了多个 {ComponentName}")
Return Matches(Choice.Value)
End Function
''' <summary>
''' 初始化修改页
''' </summary>
Private Sub LoadInstanceFinished(Task As LoaderTask(Of McInstance, Object))
'还原原版信息
OriginalName = Task.Input.Name
CustomLogo = Nothing
If ReadIni(Task.Input.PathVersion & "PCL\Setup.ini", "LogoCustom", False) Then
CustomLogo = If(Task.Input.Logo.EndsWithF("PCL\Logo.png"), Task.Input.PathVersion & "PCL\Logo.png", Task.Input.Logo)
End If
Dim Item = McDownloadListItem(VanillaData, Nothing, False).Init()
VanillaName = Item.Title
VanillaIcon = Item.Logo
LabMinecraftVersion.Text = VanillaName
TextSelectName.Text = OriginalName
IsSelectNameEdited = Not String.Equals(OriginalName, GetSelectName(), StringComparison.Ordinal)
TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {
New ValidateFolderName(McFolderSelected & "versions", IgnoreList:=New List(Of String) From {OriginalName})}
'修改页 UI
CardMinecraft.Visibility = Visibility.Visible
BtnBack.Visibility = Visibility.Collapsed
ImgLogo.Margin = New Thickness(15, 15, 0, 0)
TextSelectName.Margin = New Thickness(56, 16, 16, 0)
LabSelectName.Text = $"原名 :   {OriginalName}"
UpdateOriginalNameVisibility()
BtnStart.Text = "开始修改"
BtnStart.Logo = FrmInstanceLeft.ItemModify.Logo
AutoSelectedFabricApi = SelectedFabric IsNot Nothing
AutoSelectedOptiFabric = SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing
If ForgeVersionLoader IsNot Nothing Then LoadForge.State = ForgeVersionLoader
PrepareSelectPage()
ReloadComponentLists()
'进入动画
PanMinecraft.Visibility = Visibility.Collapsed
PanMinecraft.Opacity = 0
PanMinecraft.RenderTransform = New TranslateTransform(-50, 0)
PanSelect.Opacity = 1
PanSelect.RenderTransform = New TranslateTransform
PanBack.IsHitTestVisible = True
PanAllBack.IsHitTestVisible = True
InitialTarget = GetSelectedComponents()
'设置原始数据
BtnMinecraftRestore.Tag = VanillaData
BtnOptiFineRestore.Tag = SelectedOptiFine
BtnForgeRestore.Tag = SelectedForge
BtnNeoForgeRestore.Tag = SelectedNeoForge
BtnFabricRestore.Tag = SelectedFabric
BtnFabricApiRestore.Tag = SelectedFabricApi
BtnOptiFabricRestore.Tag = SelectedOptiFabric
BtnLiteLoaderRestore.Tag = SelectedLiteLoader
ImgMinecraftOld.Source = VanillaIcon
LabMinecraftOld.Text = LabMinecraftVersion.Text
LabOptiFineOld.Text = If(SelectedOptiFine Is Nothing, "无", LabOptiFine.Text)
LabForgeOld.Text = If(SelectedForge Is Nothing, "无", LabForge.Text)
LabNeoForgeOld.Text = If(SelectedNeoForge Is Nothing, "无", LabNeoForge.Text)
LabFabricOld.Text = If(SelectedFabric Is Nothing, "无", LabFabric.Text)
LabLiteLoaderOld.Text = If(SelectedLiteLoader Is Nothing, "无", LabLiteLoader.Text)
LabFabricApiOld.Text = If(SelectedFabricApi Is Nothing, "无", LabFabricApi.Text)
LabOptiFabricOld.Text = If(SelectedOptiFabric Is Nothing, "无", LabOptiFabric.Text)
RefreshComparisons()
End Sub
Public Overrides Function GetSelectLogo() As String
Return If(CustomLogo, MyBase.GetSelectLogo())
End Function
Public Overrides Sub ShowMinecraftVersionList()
If IsInSelectPage Then
'把当前已选择的组件记录到 PendingComponents
Dim Components = GetSelectedComponents()
For Each Component In {
(Loader:=LoadOptiFine, Version:=Components.OptiFineVersion),
(Loader:=LoadFabricApi, Version:=Components.FabricApiVersion),
(Loader:=LoadOptiFabric, Version:=Components.OptiFabricVersion),
(Loader:=LoadForge, Version:=SelectedForge?.VersionName),
(Loader:=LoadNeoForge, Version:=SelectedNeoForge?.VersionName),
(Loader:=LoadFabric, Version:=SelectedFabric),
(Loader:=LoadLiteLoader, Version:=SelectedLiteLoader?.JsonToken?("version").ToString())}
'保留尚未加载完成的组件选择
If Component.Version IsNot Nothing Then PendingComponents(Component.Loader) = Component.Version
Next
End If
MyBase.ShowMinecraftVersionList()
End Sub
Public Overrides Sub ReloadSelected()
If IsRestoringComponents Then Return
If IsInSelectPage AndAlso VanillaName IsNot Nothing AndAlso PendingComponents.Any() Then
IsRestoringComponents = True
Try
Dim HasProcessed As Boolean = False
'优先恢复 Mod 加载器,再匹配兼容的附加组件
For Each LoadingComponent In {LoadFabric, LoadForge, LoadNeoForge, LoadLiteLoader, LoadOptiFine, LoadFabricApi, LoadOptiFabric}
Dim Version As String = Nothing
If Not PendingComponents.TryGetValue(LoadingComponent, Version) Then Continue For
If Not LoadingComponent.State.IsLoader Then Continue For
Dim Loader = DirectCast(LoadingComponent.State, LoaderBase)
'检查前置组件
If LoadingComponent Is LoadOptiFine Then
If {LoadFabric, LoadForge, LoadNeoForge, LoadLiteLoader}.Any(Function(Component) PendingComponents.ContainsKey(Component)) Then Continue For
ElseIf LoadingComponent Is LoadFabricApi Then
If PendingComponents.ContainsKey(LoadFabric) Then Continue For
ElseIf LoadingComponent Is LoadForge Then
If Not McVersion.IsStandardFormat(VanillaName) Then
PendingComponents.Remove(LoadingComponent)
Continue For
End If
If DirectCast(Loader, LoaderTask(Of String, List(Of DlForgeVersionEntry))).Input <> VanillaName Then Continue For
If Loader.State = LoadState.Failed AndAlso Loader.Error.Message = "无" Then
PendingComponents.Remove(LoadingComponent)
Continue For
End If
ElseIf LoadingComponent Is LoadOptiFabric Then
If PendingComponents.ContainsKey(LoadFabric) OrElse PendingComponents.ContainsKey(LoadOptiFine) Then Continue For
End If
If Loader.State <> LoadState.Finished Then Continue For
'移除已处理的组件
PendingComponents.Remove(LoadingComponent)
HasProcessed = True
'匹配目标 MC 版本下兼容的组件
If LoadingComponent Is LoadFabric Then
If SelectedFabric Is Nothing AndAlso LoadFabricGetError() Is Nothing Then
Dim Versions = DlFabricListLoader.Output.Value("loader").OfType(Of JObject)
SelectedFabric = If(Versions.FirstOrDefault(Function(v) v("version").ToString = Version), Versions.FirstOrDefault())?("version").ToString()
End If
ElseIf LoadingComponent Is LoadOptiFine Then
If SelectedOptiFine Is Nothing AndAlso LoadOptiFineGetError() Is Nothing Then
Dim Versions = DlOptiFineListLoader.Output.Value.Where(Function(v) v.Inherit = VanillaName AndAlso
(SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(v, SelectedForge)))
SelectedOptiFine = If(Versions.FirstOrDefault(Function(v) v.InstanceName.AfterLast("-OptiFine_") = Version),
Versions.OrderBy(Function(v) v.IsPreview).
ThenByDescending(Function(v) v.DisplayName, Comparer(Of String).Create(AddressOf McUtils.CompareVersion)).FirstOrDefault())
End If
ElseIf LoadingComponent Is LoadForge Then
If SelectedForge Is Nothing AndAlso LoadForgeGetError() Is Nothing Then
Dim Versions = DirectCast(Loader, LoaderTask(Of String, List(Of DlForgeVersionEntry))).Output.Where(
Function(v) v.Inherit = VanillaName AndAlso
v.Category <> "universal" AndAlso v.Category <> "client" AndAlso
(SelectedOptiFine Is Nothing OrElse IsOptiFineSuitForForge(SelectedOptiFine, v)))
SelectedForge = If(Versions.FirstOrDefault(Function(v) v.VersionName = Version), Versions.OrderByDescending(Function(v) v).FirstOrDefault())
End If
ElseIf LoadingComponent Is LoadNeoForge Then
If SelectedNeoForge Is Nothing AndAlso LoadNeoForgeGetError() Is Nothing Then
Dim Versions = DlNeoForgeListLoader.Output.Value.Where(Function(v) v.Inherit = VanillaName)
SelectedNeoForge = If(Versions.FirstOrDefault(Function(v) v.VersionName = Version), Versions.FirstOrDefault())
End If
ElseIf LoadingComponent Is LoadLiteLoader Then
If SelectedLiteLoader Is Nothing AndAlso LoadLiteLoaderGetError() Is Nothing Then
Dim Versions = DlLiteLoaderListLoader.Output.Value.Where(Function(v) v.Inherit = VanillaName)
SelectedLiteLoader = If(Versions.FirstOrDefault(Function(v) v.JsonToken("version").ToString = Version), Versions.FirstOrDefault())
End If
ElseIf LoadingComponent Is LoadFabricApi Then
If SelectedFabricApi Is Nothing AndAlso LoadFabricApiGetError() Is Nothing Then
Dim Versions = DlFabricApiLoader.Output.Where(Function(v) IsFabricApiCompatible(v, VanillaName))
SelectedFabricApi = If(Versions.FirstOrDefault(Function(v) v.Version = Version OrElse v.Id = Version OrElse v.Display = Version),
Versions.OrderByDescending(Function(v) v.ReleaseDate).FirstOrDefault())
End If
If SelectedFabricApi IsNot Nothing Then AutoSelectedFabricApi = True
ElseIf LoadingComponent Is LoadOptiFabric Then
If SelectedOptiFabric Is Nothing AndAlso LoadOptiFabricGetError() Is Nothing Then
Dim Versions = DlOptiFabricLoader.Output.Where(Function(v) IsOptiFabricCompatible(v, VanillaName))
SelectedOptiFabric = If(Versions.FirstOrDefault(Function(v) v.Version = Version OrElse v.Id = Version OrElse v.Display = Version),
Versions.OrderByDescending(Function(v) v.ReleaseDate).FirstOrDefault())
End If
If SelectedOptiFabric IsNot Nothing Then AutoSelectedOptiFabric = True
End If
Next
'更新组件列表
If HasProcessed Then ReloadComponentLists()
Finally
IsRestoringComponents = False
End Try
End If
'刷新当前选择与原始版本的对比
MyBase.ReloadSelected()
If InitialTarget IsNot Nothing Then RefreshComparisons()
End Sub
Private Sub RefreshComparisons()
Dim Current = GetSelectedComponents()
ImgMinecraftNew.Source = VanillaIcon
'Minecraft
Dim IsMinecraftUnchanged = InitialTarget.MinecraftVersion = Current.MinecraftVersion
ShowComparison(PanMinecraftCompare, PanMinecraftInfo, InitialTarget.MinecraftVersion, Current.MinecraftVersion,
LabMinecraftVersion.Text, BtnMinecraftRestore, True)
'OptiFine
Dim OriginalOptiFine = TryCast(BtnOptiFineRestore.Tag, DlOptiFineListEntry)
ShowComparison(PanOptiFineCompare, PanOptiFineInfo, InitialTarget.OptiFineVersion, Current.OptiFineVersion,
LabOptiFine.Text, BtnOptiFineRestore, InitialTarget.OptiFineEntry Is Nothing OrElse
IsMinecraftUnchanged AndAlso CardOptiFine.MainSwap.Visibility = Visibility.Visible AndAlso OriginalOptiFine IsNot Nothing AndAlso
(SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(OriginalOptiFine, SelectedForge)), BtnOptiFineClear)
'Fabric API
ShowComparison(PanFabricApiCompare, PanFabricApiInfo, InitialTarget.FabricApiVersion, Current.FabricApiVersion,
LabFabricApi.Text, BtnFabricApiRestore, InitialTarget.FabricApiVersion Is Nothing OrElse
IsMinecraftUnchanged AndAlso SelectedFabric IsNot Nothing AndAlso CardFabricApi.MainSwap.Visibility = Visibility.Visible, BtnFabricApiClear)
'OptiFabric
ShowComparison(PanOptiFabricCompare, PanOptiFabricInfo, InitialTarget.OptiFabricVersion, Current.OptiFabricVersion,
LabOptiFabric.Text, BtnOptiFabricRestore, InitialTarget.OptiFabricVersion Is Nothing OrElse
IsMinecraftUnchanged AndAlso SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing AndAlso CardOptiFabric.MainSwap.Visibility = Visibility.Visible, BtnOptiFabricClear)
'Mod Loader
For Each Loader In {
(Kind:=ModLoaders.Forge, Card:=CardForge, ComparePanel:=PanForgeCompare, CurrentPanel:=PanForgeInfo, Label:=LabForge, RestoreButton:=BtnForgeRestore, ClearButton:=BtnForgeClear),
(Kind:=ModLoaders.NeoForge, Card:=CardNeoForge, ComparePanel:=PanNeoForgeCompare, CurrentPanel:=PanNeoForgeInfo, Label:=LabNeoForge, RestoreButton:=BtnNeoForgeRestore, ClearButton:=BtnNeoForgeClear),
(Kind:=ModLoaders.Fabric, Card:=CardFabric, ComparePanel:=PanFabricCompare, CurrentPanel:=PanFabricInfo, Label:=LabFabric, RestoreButton:=BtnFabricRestore, ClearButton:=BtnFabricClear),
(Kind:=ModLoaders.LiteLoader, Card:=CardLiteLoader, ComparePanel:=PanLiteLoaderCompare, CurrentPanel:=PanLiteLoaderInfo, Label:=LabLiteLoader, RestoreButton:=BtnLiteLoaderRestore, ClearButton:=BtnLiteLoaderClear)}
Dim OldVersion As String = Nothing, NewVersion As String = Nothing
InitialTarget.ModLoaderVersions.TryGetValue(Loader.Kind, OldVersion)
Current.ModLoaderVersions.TryGetValue(Loader.Kind, NewVersion)
Dim CanRestore = OldVersion Is Nothing OrElse IsMinecraftUnchanged AndAlso
Loader.Card.MainSwap.Visibility = Visibility.Visible AndAlso Loader.RestoreButton.Tag IsNot Nothing
If Loader.Kind = ModLoaders.Forge AndAlso OldVersion IsNot Nothing AndAlso CanRestore Then
CanRestore = SelectedOptiFine Is Nothing OrElse IsOptiFineSuitForForge(SelectedOptiFine, DirectCast(Loader.RestoreButton.Tag, DlForgeVersionEntry))
End If
If Loader.Kind = ModLoaders.Fabric AndAlso OldVersion IsNot Nothing Then
Dim TargetVersion = VanillaName.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3")
CanRestore = CardFabric.Visibility = Visibility.Visible AndAlso CardFabric.MainSwap.Visibility = Visibility.Visible AndAlso
DlFabricListLoader.Output.Value("loader").OfType(Of JObject).Any(Function(v) v("version").ToString = OldVersion) AndAlso
DlFabricListLoader.Output.Value("game").OfType(Of JObject).Any(Function(v) v("version").ToString = TargetVersion)
End If
ShowComparison(Loader.ComparePanel, Loader.CurrentPanel, OldVersion, NewVersion, Loader.Label.Text,
Loader.RestoreButton, CanRestore, Loader.ClearButton)
Next
UpdateStartButton()
End Sub
Private Sub ShowComparison(ComparePanel As Grid, CurrentPanel As FrameworkElement, OldVersion As String, NewVersion As String, NewText As String,
RestoreButton As MyIconButton, CanRestore As Boolean, Optional ClearButton As FrameworkElement = Nothing)
'获取不可安装的原因
Dim UnavailableReason As String = Nothing
If NewVersion Is Nothing Then
If RestoreButton Is BtnOptiFineRestore Then
UnavailableReason = LoadOptiFineGetError()
ElseIf RestoreButton Is BtnForgeRestore Then
UnavailableReason = If(McVersion.IsStandardFormat(VanillaName), LoadForgeGetError(), "无")
ElseIf RestoreButton Is BtnNeoForgeRestore Then
UnavailableReason = If(CardNeoForge.Visibility = Visibility.Collapsed, "无", LoadNeoForgeGetError())
ElseIf RestoreButton Is BtnFabricRestore Then
UnavailableReason = If(CardFabric.Visibility = Visibility.Collapsed, "无", LoadFabricGetError())
ElseIf RestoreButton Is BtnLiteLoaderRestore Then
UnavailableReason = If(CardLiteLoader.Visibility = Visibility.Collapsed, "无", LoadLiteLoaderGetError())
ElseIf RestoreButton Is BtnFabricApiRestore Then
UnavailableReason = LoadFabricApiGetError()
ElseIf RestoreButton Is BtnOptiFabricRestore Then
UnavailableReason = LoadOptiFabricGetError()
End If
NewText = If(UnavailableReason, "可以添加")
End If
'修改对比
Dim IsPending = NewVersion Is Nothing AndAlso (NewText = "获取中……" OrElse NewText.StartsWithF("获取失败:"))
Dim IsChanged = OldVersion <> NewVersion AndAlso Not IsPending
CanRestore = IsChanged AndAlso OldVersion IsNot Nothing AndAlso CanRestore
ComparePanel.Visibility = If(IsChanged, Visibility.Visible, Visibility.Collapsed)
CurrentPanel.Visibility = If(IsChanged, Visibility.Collapsed, Visibility.Visible)
'还原与取消安装按钮
RestoreButton.Visibility = If(CanRestore, Visibility.Visible, Visibility.Collapsed)
If ClearButton IsNot Nothing Then ClearButton.ToolTip = If(OldVersion Is Nothing, "取消安装", "移除")
Dim HasClearButton = ClearButton IsNot Nothing AndAlso ClearButton.Visibility = Visibility.Visible
RestoreButton.Margin = New Thickness(0, 5, If(CanRestore AndAlso HasClearButton, 60, 32), 0)
ComparePanel.Margin = New Thickness(ComparePanel.Margin.Left, ComparePanel.Margin.Top,
If(CanRestore AndAlso HasClearButton, 110, 80), ComparePanel.Margin.Bottom)
If Not IsChanged Then Return
'显示修改前已安装组件的对比卡片
If OldVersion IsNot Nothing Then
Dim Card = CType(ComparePanel.Parent, MyCard)
If Card.Visibility = Visibility.Collapsed Then
Card.IsSwapped = True
If Card.MainSwap IsNot Nothing Then Card.MainSwap.Visibility = Visibility.Collapsed
Card.Visibility = Visibility.Visible
End If
End If
Dim OldSide = CType(ComparePanel.Children(0), DockPanel)
Dim NewSide = CType(ComparePanel.Children(2), DockPanel)
OldSide.Children(0).Visibility = If(OldVersion Is Nothing, Visibility.Collapsed, Visibility.Visible)
CType(OldSide.Children(1), TextBlock).Margin = If(OldVersion Is Nothing, New Thickness(0), New Thickness(7, 0, 0, 0))
NewSide.Children(0).Visibility = If(NewVersion Is Nothing, Visibility.Collapsed, Visibility.Visible)
Dim NewLabel = CType(NewSide.Children(1), TextBlock)
NewLabel.Margin = If(NewVersion Is Nothing, New Thickness(0), New Thickness(7, 0, 0, 0))
NewLabel.Text = If(NewVersion Is Nothing, "移除", NewText)
If NewVersion Is Nothing AndAlso UnavailableReason IsNot Nothing Then
NewLabel.Inlines.Add(New Run($"({If(UnavailableReason = "无", "无可用版本", UnavailableReason)})") With {.Foreground = ColorGray4})
End If
End Sub
Private Sub RestoreComponent(sender As Object, e As EventArgs) Handles BtnMinecraftRestore.Click, BtnOptiFineRestore.Click, BtnForgeRestore.Click,
BtnNeoForgeRestore.Click, BtnFabricRestore.Click, BtnFabricApiRestore.Click, BtnOptiFabricRestore.Click, BtnLiteLoaderRestore.Click
Dim Button = DirectCast(sender, MyIconButton)
'恢复初始选择
If Button Is BtnMinecraftRestore Then
IsRestoringComponents = True
Try
PendingComponents.Clear()
MinecraftSelected(McDownloadListItem(DirectCast(Button.Tag, JObject), Nothing, False).Init(), Nothing)
If ForgeVersionLoader IsNot Nothing Then LoadForge.State = ForgeVersionLoader
'恢复初始的组件
SelectedOptiFine = TryCast(BtnOptiFineRestore.Tag, DlOptiFineListEntry)
SelectedForge = TryCast(BtnForgeRestore.Tag, DlForgeVersionEntry)
SelectedNeoForge = TryCast(BtnNeoForgeRestore.Tag, DlNeoForgeListEntry)
SelectedFabric = TryCast(BtnFabricRestore.Tag, String)
SelectedLiteLoader = TryCast(BtnLiteLoaderRestore.Tag, DlLiteLoaderListEntry)
SelectedFabricApi = TryCast(BtnFabricApiRestore.Tag, ResourceVersion)
SelectedOptiFabric = TryCast(BtnOptiFabricRestore.Tag, ResourceVersion)
AutoSelectedFabricApi = SelectedFabric IsNot Nothing
AutoSelectedOptiFabric = SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing
Finally
IsRestoringComponents = False
End Try
ReloadComponentLists()
Return
ElseIf Button Is BtnOptiFineRestore Then
SelectedOptiFine = TryCast(Button.Tag, DlOptiFineListEntry)
AutoSelectedOptiFabric = SelectedOptiFine IsNot Nothing AndAlso SelectedFabric IsNot Nothing
If SelectedOptiFine Is Nothing Then SelectedOptiFabric = Nothing
ElseIf Button Is BtnForgeRestore Then
SelectedForge = TryCast(Button.Tag, DlForgeVersionEntry)
ElseIf Button Is BtnNeoForgeRestore Then
SelectedNeoForge = TryCast(Button.Tag, DlNeoForgeListEntry)
ElseIf Button Is BtnFabricRestore Then
SelectedFabric = TryCast(Button.Tag, String)
AutoSelectedFabricApi = SelectedFabric IsNot Nothing
AutoSelectedOptiFabric = SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing
If SelectedFabric Is Nothing Then
SelectedFabricApi = Nothing
SelectedOptiFabric = Nothing
End If
ElseIf Button Is BtnFabricApiRestore Then
SelectedFabricApi = TryCast(Button.Tag, ResourceVersion)
AutoSelectedFabricApi = True
ElseIf Button Is BtnOptiFabricRestore Then
SelectedOptiFabric = TryCast(Button.Tag, ResourceVersion)
AutoSelectedOptiFabric = True
ElseIf Button Is BtnLiteLoaderRestore Then
SelectedLiteLoader = TryCast(Button.Tag, DlLiteLoaderListEntry)
End If
DirectCast(Button.Parent, MyCard).IsSwapped = True
'刷新组件
ReloadComponentLists()
End Sub
Private Sub CardMinecraft_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles CardMinecraft.MouseLeftButtonUp
ShowMinecraftVersionList()
e.Handled = True
End Sub
Private Sub UpdateStartButton() Handles TextSelectName.TextChanged, TextSelectName.ValidateChanged
BtnStart.IsEnabled = TextSelectName.IsValidated AndAlso InitialTarget IsNot Nothing AndAlso
Not PendingComponents.Any() AndAlso
(Not IsVanillaVersionReliable OrElse Not InitialTarget.IsEquivalentTo(GetSelectedComponents()) OrElse
Not String.Equals(TextSelectName.Text, OriginalName, StringComparison.Ordinal))
End Sub
Private Sub UpdateOriginalNameVisibility() Handles TextSelectName.TextChanged
Dim IsNameChanged = Not String.Equals(TextSelectName.Text, OriginalName, StringComparison.Ordinal)
Dim NewVisibility = If(IsNameChanged, Visibility.Visible, Visibility.Collapsed)
If LabSelectName.Visibility = NewVisibility Then Return
LabSelectName.Visibility = NewVisibility
BtnOriginalNameRestore.Visibility = NewVisibility
Dim RightMargin = If(IsNameChanged, 40, 16)
If IsInSelectPage AndAlso AniControlEnabled = 0 Then
AniStart(AaDouble(Sub(Delta) TextSelectName.Margin = New Thickness(56, 16, TextSelectName.Margin.Right + Delta, 0),
RightMargin - TextSelectName.Margin.Right, 150,, New AniEaseOutFluent), "DownloadModify Name Margin")
Else
AniStop("DownloadModify Name Margin")
TextSelectName.Margin = New Thickness(56, 16, RightMargin, 0)
End If
End Sub
Private Sub BtnOriginalNameRestore_Click(sender As Object, e As EventArgs) Handles BtnOriginalNameRestore.Click
TextSelectName.Text = OriginalName
IsSelectNameEdited = Not String.Equals(OriginalName, GetSelectName(), StringComparison.Ordinal)
End Sub
Public Overrides Sub StartInstall(Request As McInstallRequest)
UpdateStartButton()
If Not BtnStart.IsEnabled Then Return
Dim TargetInstance = InitLoader.Input
Dim Target = Request.Components
Dim InstanceName = Request.NewInstanceName
Dim IsNameChanged = Not String.Equals(InstanceName, TargetInstance.Name, StringComparison.Ordinal)
Request.NewInstanceName = If(IsNameChanged, InstanceName, Nothing)
Request.InstanceFolder = TargetInstance.PathVersion
'警告
Dim Warnings As New List(Of String)
If (SelectedForge IsNot Nothing OrElse SelectedNeoForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) AndAlso
Not PathUtils.IsSame(TargetInstance.PathIndie, TargetInstance.PathVersion) Then
Warnings.Add("该版本尚未开启版本隔离,可能与别的 MC 版本共用同一个 Mod 和存档文件夹。" & vbCrLf &
"修改版本后,已有的 Mod、存档等需要手动迁移到新的游戏目录。")
End If
Dim IsMinecraftVersionChanged = InitialTarget.MinecraftVersion <> Target.MinecraftVersion
If Not IsVanillaVersionReliable AndAlso Not IsMinecraftVersionChanged Then
Warnings.Add($"PCL 未能精准识别该版本,请确认它是不是 Minecraft {InitialTarget.MinecraftVersion},如果不正确,请取消并选择正确的版本!")
End If
If Not Configs.HintModifyInstanceWarning.Get() Then
Warnings.Add("如果该版本安装了 PCL 不兼容的加载器,或经过第三方修改,这些改动将会丢失!")
End If
Dim IsModLoaderChanged As Boolean = False
For Each Loader In InitialTarget.ModLoaderVersions.Keys.Union(Target.ModLoaderVersions.Keys)
Dim CurrentVersion As String = Nothing, TargetVersion As String = Nothing
Dim HasCurrent = InitialTarget.ModLoaderVersions.TryGetValue(Loader, CurrentVersion)
Dim HasTarget = Target.ModLoaderVersions.TryGetValue(Loader, TargetVersion)
If HasCurrent <> HasTarget OrElse CurrentVersion <> TargetVersion Then
IsModLoaderChanged = True
Exit For
End If
Next
If (IsModLoaderChanged OrElse IsMinecraftVersionChanged) AndAlso InitialTarget.ModLoaderVersions.Any Then
Warnings.Add("现有的 Mod、资源包等在修改后可能会不兼容!")
End If
If Warnings.Any() Then
If MyMsgBox("请注意:" & vbCrLf & "• " & Warnings.Join(vbCrLf & "• "), "修改确认", "开始修改", "取消", IsWarn:=True) <> 1 Then Return
End If
If Not Configs.HintModifyInstanceWarning.Get() Then Configs.HintModifyInstanceWarning.Set(True)
'开始修改
If IsVanillaVersionReliable AndAlso InitialTarget.IsEquivalentTo(Target) Then
'仅重命名
Try
Dim OldPath = TargetInstance.PathVersion
Dim RenamedInstance = TargetInstance.Rename(InstanceName)
If PageInstanceLeft.Instance IsNot Nothing AndAlso PathUtils.IsSame(PageInstanceLeft.Instance.PathVersion, OldPath) Then PageInstanceLeft.Instance = RenamedInstance
If McInstanceSelected IsNot Nothing AndAlso PathUtils.IsSame(McInstanceSelected.PathVersion, OldPath) Then McInstanceSelected = RenamedInstance
PageInstanceLeft.ReloadCurrentJava()
Hint("重命名成功!", HintType.Green)
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
FrmMain.PageBack()
Catch ex As Exception
Logger.Error(ex, "重命名版本失败", LogBehavior.Alert)
End Try
Else
'实际修改
If McModificationStart(Request, TargetInstance) Then FrmMain.PageBack()
End If
End Sub
End Class