diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb index e768b96cd..58356def5 100644 --- a/Plain Craft Launcher 2/FormMain.xaml.vb +++ b/Plain Craft Launcher 2/FormMain.xaml.vb @@ -641,7 +641,7 @@ Public Class FormMain Try If PageCurrent = PageType.VersionSetup AndAlso PageCurrentSub = PageSubType.VersionMod Then 'Mod 管理自动刷新 - FrmVersionMod.ReloadModList() + FrmVersionMod.ReloadCompFileList() ElseIf PageCurrent = PageType.VersionSelect Then '版本选择自动刷新 LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.RunOnUpdated, MaxDepth:=1, ExtraPath:="versions\") @@ -775,7 +775,7 @@ Public Class FormMain Exit Sub End If '安装 Mod - If PageVersionMod.InstallMods(FilePathList) Then Exit Sub + If PageVersionCompResource.InstallMods(FilePathList) Then Exit Sub '处理资源安装 If PageCurrent = PageType.VersionSetup AndAlso {"zip"}.Any(Function(i) i = Extension) Then Select Case PageCurrentSub @@ -797,7 +797,7 @@ Public Class FormMain End If CopyFile(FilePath, DestFile) Hint($"已导入 {GetFileNameFromPath(FilePath)}", HintType.Finish) - If FrmVersionResourcePack IsNot Nothing Then RunInUi(Sub() FrmVersionResourcePack.Reload()) + If FrmVersionResourcePack IsNot Nothing Then RunInUi(Sub() FrmVersionResourcePack.ReloadCompFileList()) Exit Sub Case PageSubType.VersionShader Dim DestFile = PageVersionLeft.Version.PathIndie + "shaderpacks\" + GetFileNameFromPath(FilePath) @@ -807,7 +807,7 @@ Public Class FormMain End If CopyFile(FilePath, DestFile) Hint($"已导入 {GetFileNameFromPath(FilePath)}", HintType.Finish) - If FrmVersionShader IsNot Nothing Then RunInUi(Sub() FrmVersionShader.Reload()) + If FrmVersionShader IsNot Nothing Then RunInUi(Sub() FrmVersionShader.ReloadCompFileList()) Exit Sub End Select End If diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb index 8cfa563df..89c1db167 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb @@ -24,14 +24,52 @@ Public Module ModComp ''' Other = 4 End Enum - Public Enum CompModLoaderType + Public Enum CompLoaderType 'https://docs.curseforge.com/?http#tocS_ModLoaderType + ''' + ''' 模组加载器 + ''' Any = 0 + ''' + ''' 模组加载器 + ''' Forge = 1 + ''' + ''' 模组加载器 + ''' LiteLoader = 3 + ''' + ''' 模组加载器 + ''' Fabric = 4 + ''' + ''' 模组加载器 + ''' Quilt = 5 + ''' + ''' 模组加载器 + ''' NeoForge = 6 + ''' + ''' 材质包 + ''' + Minecraft = 7 + ''' + ''' 光影包 + ''' + Canvas = 8 + ''' + ''' 光影包 + ''' + Iris = 9 + ''' + ''' 光影包 + ''' + OptiFine = 10 + ''' + ''' 光影包 + ''' + Vanilla = 11 End Enum Public Enum CompSourceType CurseForge = 1 @@ -163,7 +201,7 @@ Public Module ModComp ''' ''' 支持的 Mod 加载器列表。可能为空。 ''' - Public ReadOnly ModLoaders As List(Of CompModLoaderType) + Public ReadOnly ModLoaders As List(Of CompLoaderType) ''' ''' 描述性标签的内容。已转换为中文。 ''' @@ -261,9 +299,9 @@ Public Module ModComp If Data.ContainsKey("LastUpdate") Then LastUpdate = Data("LastUpdate") DownloadCount = Data("DownloadCount") If Data.ContainsKey("ModLoaders") Then - ModLoaders = CType(Data("ModLoaders"), JArray).Select(Function(t) CType(t.ToObject(Of Integer), CompModLoaderType)).ToList + ModLoaders = CType(Data("ModLoaders"), JArray).Select(Function(t) CType(t.ToObject(Of Integer), CompLoaderType)).ToList Else - ModLoaders = New List(Of CompModLoaderType) + ModLoaders = New List(Of CompLoaderType) End If Tags = CType(Data("Tags"), JArray).Select(Function(t) t.ToString).ToList If Data.ContainsKey("LogoUrl") Then LogoUrl = Data("LogoUrl") @@ -293,7 +331,7 @@ Public Module ModComp End If End If 'FileIndexes / GameVersions / ModLoaders - ModLoaders = New List(Of CompModLoaderType) + ModLoaders = New List(Of CompLoaderType) Dim Files As New List(Of KeyValuePair(Of Integer, List(Of String))) 'FileId, GameVersions For Each File In If(Data("latestFiles"), New JArray) Dim NewFile As New CompFile(File, Type) @@ -424,116 +462,116 @@ Public Module ModComp End Select 'Tags & ModLoaders Tags = New List(Of String) - ModLoaders = New List(Of CompModLoaderType) + ModLoaders = New List(Of CompLoaderType) If Data?("loaders") IsNot Nothing Then For Each Category In Data("loaders").Select(Function(t) t.ToString) Select Case Category - Case "forge" : ModLoaders.Add(CompModLoaderType.Forge) - Case "fabric" : ModLoaders.Add(CompModLoaderType.Fabric) - Case "quilt" : ModLoaders.Add(CompModLoaderType.Quilt) - Case "neoforge" : ModLoaders.Add(CompModLoaderType.NeoForge) + Case "forge" : ModLoaders.Add(CompLoaderType.Forge) + Case "fabric" : ModLoaders.Add(CompLoaderType.Fabric) + Case "quilt" : ModLoaders.Add(CompLoaderType.Quilt) + Case "neoforge" : ModLoaders.Add(CompLoaderType.NeoForge) End Select Next End If For Each Category In Data("categories").Select(Function(t) t.ToString) - Select Case Category + Select Case Category '加载器 - Case "forge" : ModLoaders.Add(CompModLoaderType.Forge) - Case "fabric" : ModLoaders.Add(CompModLoaderType.Fabric) - Case "quilt" : ModLoaders.Add(CompModLoaderType.Quilt) - Case "neoforge" : ModLoaders.Add(CompModLoaderType.NeoForge) + Case "forge" : ModLoaders.Add(CompLoaderType.Forge) + Case "fabric" : ModLoaders.Add(CompLoaderType.Fabric) + Case "quilt" : ModLoaders.Add(CompLoaderType.Quilt) + Case "neoforge" : ModLoaders.Add(CompLoaderType.NeoForge) 'Mod - Case "worldgen" : Tags.Add("世界元素") - Case "technology" : Tags.Add("科技") - Case "food" : Tags.Add("食物/烹饪") - Case "game-mechanics" : Tags.Add("游戏机制") - Case "transportation" : Tags.Add("运输") - Case "storage" : Tags.Add("仓储") - Case "magic" : Tags.Add("魔法") - Case "adventure" : Tags.Add("冒险") - Case "decoration" : Tags.Add("装饰") - Case "mobs" : Tags.Add("生物") - Case "equipment" : Tags.Add("装备") - Case "optimization" : Tags.Add("性能优化") - Case "social" : Tags.Add("服务器") - Case "utility" : Tags.Add("改良") - Case "library" : Tags.Add("支持库") + Case "worldgen" : Tags.Add("世界元素") + Case "technology" : Tags.Add("科技") + Case "food" : Tags.Add("食物/烹饪") + Case "game-mechanics" : Tags.Add("游戏机制") + Case "transportation" : Tags.Add("运输") + Case "storage" : Tags.Add("仓储") + Case "magic" : Tags.Add("魔法") + Case "adventure" : Tags.Add("冒险") + Case "decoration" : Tags.Add("装饰") + Case "mobs" : Tags.Add("生物") + Case "equipment" : Tags.Add("装备") + Case "optimization" : Tags.Add("性能优化") + Case "social" : Tags.Add("服务器") + Case "utility" : Tags.Add("改良") + Case "library" : Tags.Add("支持库") '整合包 - Case "multiplayer" : Tags.Add("多人") - Case "optimization" : Tags.Add("性能优化") - Case "challenging" : Tags.Add("硬核") - Case "combat" : Tags.Add("战斗") - Case "quests" : Tags.Add("任务") - Case "technology" : Tags.Add("科技") - Case "magic" : Tags.Add("魔法") - Case "adventure" : Tags.Add("冒险") - Case "kitchen-sink" : Tags.Add("大杂烩") - Case "lightweight" : Tags.Add("轻量") + Case "multiplayer" : Tags.Add("多人") + Case "optimization" : Tags.Add("性能优化") + Case "challenging" : Tags.Add("硬核") + Case "combat" : Tags.Add("战斗") + Case "quests" : Tags.Add("任务") + Case "technology" : Tags.Add("科技") + Case "magic" : Tags.Add("魔法") + Case "adventure" : Tags.Add("冒险") + Case "kitchen-sink" : Tags.Add("大杂烩") + Case "lightweight" : Tags.Add("轻量") '光影包 - Case "cartoon" : Tags.Add("卡通") - Case "cursed" : Tags.Add("Cursed") - Case "fantasy" : Tags.Add("幻想") - Case "realistic" : Tags.Add("写实") - Case "semi-realistic" : Tags.Add("半写实") - Case "vanilla-like" : Tags.Add("原版风") - - Case "atmosphere" : Tags.Add("大气环境") - Case "bloom" : Tags.Add("植被") - Case "colored-lighting" : Tags.Add("光源着色") - Case "foliage" : Tags.Add("树叶") - Case "path-tracing" : Tags.Add("路径追踪") - Case "pbr" : Tags.Add("PBR") - Case "reflections" : Tags.Add("反射") - Case "shadows" : Tags.Add("阴影") - - Case "potato" : Tags.Add("土豆画质") - Case "low" : Tags.Add("低性能影响") - Case "medium" : Tags.Add("中性能影响") - Case "high" : Tags.Add("高性能影响") - Case "screenshot" : Tags.Add("极致画质") - - Case "canvas" : Tags.Add("Canvas") - Case "iris" : Tags.Add("Iris") - Case "optifine" : Tags.Add("OptiFine") - Case "vanilla" : Tags.Add("原版光影") + Case "cartoon" : Tags.Add("卡通") + Case "cursed" : Tags.Add("Cursed") + Case "fantasy" : Tags.Add("幻想") + Case "realistic" : Tags.Add("写实") + Case "semi-realistic" : Tags.Add("半写实") + Case "vanilla-like" : Tags.Add("原版风") + + Case "atmosphere" : Tags.Add("大气环境") + Case "bloom" : Tags.Add("植被") + Case "colored-lighting" : Tags.Add("光源着色") + Case "foliage" : Tags.Add("树叶") + Case "path-tracing" : Tags.Add("路径追踪") + Case "pbr" : Tags.Add("PBR") + Case "reflections" : Tags.Add("反射") + Case "shadows" : Tags.Add("阴影") + + Case "potato" : Tags.Add("土豆画质") + Case "low" : Tags.Add("低性能影响") + Case "medium" : Tags.Add("中性能影响") + Case "high" : Tags.Add("高性能影响") + Case "screenshot" : Tags.Add("极致画质") + + Case "canvas" : Tags.Add("Canvas") + Case "iris" : Tags.Add("Iris") + Case "optifine" : Tags.Add("OptiFine") + Case "vanilla" : Tags.Add("原版光影") '资源包 - Case "8x-" : Tags.Add("8x-") - Case "16x" : Tags.Add("16x") - Case "32x" : Tags.Add("32x") - Case "48x" : Tags.Add("48x") - Case "64x" : Tags.Add("64x") - Case "128x" : Tags.Add("128x") - Case "256x" : Tags.Add("256x") - Case "512x+" : Tags.Add("512x+") - Case "audio" : Tags.Add("声音") - Case "blocks" : Tags.Add("方块") - Case "combat" : Tags.Add("战斗") - Case "core-shaders" : Tags.Add("核心着色器") - Case "cursed" : Tags.Add("Cursed") - Case "decoration" : Tags.Add("装饰") - Case "entities" : Tags.Add("实体") - Case "environment" : Tags.Add("环境") - Case "equipment" : Tags.Add("装备") - Case "fonts" : Tags.Add("字体") - Case "gui" : Tags.Add("GUI") - Case "items" : Tags.Add("物品") - Case "locale" : Tags.Add("本地化") - Case "modded" : Tags.Add("Modded") - Case "models" : Tags.Add("模型") - Case "realistic" : Tags.Add("写实") - Case "simplistic" : Tags.Add("扁平") - Case "themed" : Tags.Add("主题") - Case "tweaks" : Tags.Add("优化") - Case "utility" : Tags.Add("实用") - Case "vanilla-like" : Tags.Add("类原生") - End Select - Next - If Not Tags.Any() Then Tags.Add("杂项") - Tags.Sort() - ModLoaders.Sort() + Case "8x-" : Tags.Add("8x-") + Case "16x" : Tags.Add("16x") + Case "32x" : Tags.Add("32x") + Case "48x" : Tags.Add("48x") + Case "64x" : Tags.Add("64x") + Case "128x" : Tags.Add("128x") + Case "256x" : Tags.Add("256x") + Case "512x+" : Tags.Add("512x+") + Case "audio" : Tags.Add("声音") + Case "blocks" : Tags.Add("方块") + Case "combat" : Tags.Add("战斗") + Case "core-shaders" : Tags.Add("核心着色器") + Case "cursed" : Tags.Add("Cursed") + Case "decoration" : Tags.Add("装饰") + Case "entities" : Tags.Add("实体") + Case "environment" : Tags.Add("环境") + Case "equipment" : Tags.Add("装备") + Case "fonts" : Tags.Add("字体") + Case "gui" : Tags.Add("GUI") + Case "items" : Tags.Add("物品") + Case "locale" : Tags.Add("本地化") + Case "modded" : Tags.Add("Modded") + Case "models" : Tags.Add("模型") + Case "realistic" : Tags.Add("写实") + Case "simplistic" : Tags.Add("扁平") + Case "themed" : Tags.Add("主题") + Case "tweaks" : Tags.Add("优化") + Case "utility" : Tags.Add("实用") + Case "vanilla-like" : Tags.Add("类原生") + End Select + Next + If Not Tags.Any() Then Tags.Add("杂项") + Tags.Sort() + ModLoaders.Sort() #End Region - End If End If + End If '保存缓存 CompProjectCache(Id) = Me End Sub @@ -609,8 +647,8 @@ Public Module ModComp End If '获取 Mod 加载器描述 Dim ModLoaderDescriptionFull As String, ModLoaderDescriptionPart As String - Dim ModLoadersForDesc As New List(Of CompModLoaderType)(ModLoaders) - If Setup.Get("ToolDownloadIgnoreQuilt") Then ModLoadersForDesc.Remove(CompModLoaderType.Quilt) + Dim ModLoadersForDesc As New List(Of CompLoaderType)(ModLoaders) + If Setup.Get("ToolDownloadIgnoreQuilt") Then ModLoadersForDesc.Remove(CompLoaderType.Quilt) Select Case ModLoadersForDesc.Count Case 0 If ModLoaders.Count = 1 Then @@ -625,10 +663,10 @@ Public Module ModComp ModLoaderDescriptionPart = ModLoadersForDesc.Single.ToString Case Else Dim MaxVersion As Integer = If(GameVersions.Any, GameVersions.Max, 99) - If ModLoaders.Contains(CompModLoaderType.Forge) AndAlso - (MaxVersion < 14 OrElse ModLoaders.Contains(CompModLoaderType.Fabric)) AndAlso - (MaxVersion < 20 OrElse ModLoaders.Contains(CompModLoaderType.NeoForge)) AndAlso - (MaxVersion < 14 OrElse ModLoaders.Contains(CompModLoaderType.Quilt) OrElse Setup.Get("ToolDownloadIgnoreQuilt")) Then + If ModLoaders.Contains(CompLoaderType.Forge) AndAlso + (MaxVersion < 14 OrElse ModLoaders.Contains(CompLoaderType.Fabric)) AndAlso + (MaxVersion < 20 OrElse ModLoaders.Contains(CompLoaderType.NeoForge)) AndAlso + (MaxVersion < 14 OrElse ModLoaders.Contains(CompLoaderType.Quilt) OrElse Setup.Get("ToolDownloadIgnoreQuilt")) Then ModLoaderDescriptionFull = "任意" ModLoaderDescriptionPart = "" Else @@ -864,7 +902,7 @@ NoSubtitle: ''' ''' 筛选 Mod 加载器类别。 ''' - Public ModLoader As CompModLoaderType = CompModLoaderType.Any + Public ModLoader As CompLoaderType = CompLoaderType.Any ''' ''' 筛选 MC 版本。 ''' @@ -908,7 +946,7 @@ NoSubtitle: Address += "&classId=6552" End Select Address += "&categoryId=" & If(Tag = "", "0", Tag.BeforeFirst("/")) - If ModLoader <> CompModLoaderType.Any Then Address += "&modLoaderType=" & CType(ModLoader, Integer) + If ModLoader <> CompLoaderType.Any Then Address += "&modLoaderType=" & CType(ModLoader, Integer) If Not String.IsNullOrEmpty(GameVersion) Then Address += "&gameVersion=" & GameVersion If Not String.IsNullOrEmpty(SearchText) Then Address += "&searchFilter=" & Net.WebUtility.UrlEncode(SearchText) If Storage.CurseForgeOffset > 0 Then Address += "&index=" & Storage.CurseForgeOffset @@ -929,7 +967,7 @@ NoSubtitle: Dim Facets As New List(Of String) Facets.Add($"[""project_type:{GetStringFromEnum(Type).ToLower}""]") If Not String.IsNullOrEmpty(Tag) Then Facets.Add($"[""categories:'{Tag.AfterLast("/")}'""]") - If ModLoader <> CompModLoaderType.Any Then Facets.Add($"[""categories:'{GetStringFromEnum(ModLoader).ToLower}'""]") + If ModLoader <> CompLoaderType.Any Then Facets.Add($"[""categories:'{GetStringFromEnum(ModLoader).ToLower}'""]") If Not String.IsNullOrEmpty(GameVersion) Then Facets.Add($"[""versions:'{GameVersion}'""]") Address += "&facets=[" & String.Join(",", Facets) & "]" Return Address @@ -1001,7 +1039,7 @@ NoSubtitle: #Region "拒绝 1.13- Quilt(这个版本根本没有 Quilt)" - If Task.Input.ModLoader = CompModLoaderType.Quilt AndAlso VersionSortInteger(If(Task.Input.GameVersion, "1.15"), "1.14") = -1 Then + If Task.Input.ModLoader = CompLoaderType.Quilt AndAlso VersionSortInteger(If(Task.Input.GameVersion, "1.15"), "1.14") = -1 Then Throw New Exception("Quilt 不支持 Minecraft " & Task.Input.GameVersion) End If @@ -1303,7 +1341,7 @@ Retry: ''' ''' 支持的 Mod 加载器列表。可能为空。 ''' - Public ReadOnly ModLoaders As List(Of CompModLoaderType) + Public ReadOnly ModLoaders As List(Of CompLoaderType) ''' ''' 支持的游戏版本列表。类型包括:"1.18.5","1.18","1.18 预览版","21w15a","未知版本"。 ''' @@ -1383,7 +1421,7 @@ Retry: Status = CType(Data("Status").ToObject(Of Integer), CompFileStatus) If Data.ContainsKey("FileName") Then FileName = Data("FileName").ToString If Data.ContainsKey("DownloadUrls") Then DownloadUrls = Data("DownloadUrls").ToObject(Of List(Of String)) - If Data.ContainsKey("ModLoaders") Then ModLoaders = Data("ModLoaders").ToObject(Of List(Of CompModLoaderType)) + If Data.ContainsKey("ModLoaders") Then ModLoaders = Data("ModLoaders").ToObject(Of List(Of CompLoaderType)) If Data.ContainsKey("Hash") Then Hash = Data("Hash").ToString If Data.ContainsKey("GameVersions") Then GameVersions = Data("GameVersions").ToObject(Of List(Of String)) If Data.ContainsKey("RawDependencies") Then RawDependencies = Data("RawDependencies").ToObject(Of List(Of String)) @@ -1431,11 +1469,11 @@ Retry: GameVersions = New List(Of String) From {"未知版本"} End If 'ModLoaders - ModLoaders = New List(Of CompModLoaderType) - If RawVersions.Contains("forge") Then ModLoaders.Add(CompModLoaderType.Forge) - If RawVersions.Contains("fabric") Then ModLoaders.Add(CompModLoaderType.Fabric) - If RawVersions.Contains("quilt") Then ModLoaders.Add(CompModLoaderType.Quilt) - If RawVersions.Contains("neoforge") Then ModLoaders.Add(CompModLoaderType.NeoForge) + ModLoaders = New List(Of CompLoaderType) + If RawVersions.Contains("forge") Then ModLoaders.Add(CompLoaderType.Forge) + If RawVersions.Contains("fabric") Then ModLoaders.Add(CompLoaderType.Fabric) + If RawVersions.Contains("quilt") Then ModLoaders.Add(CompLoaderType.Quilt) + If RawVersions.Contains("neoforge") Then ModLoaders.Add(CompLoaderType.NeoForge) #End Region Else #Region "Modrinth" @@ -1475,11 +1513,11 @@ Retry: End If 'ModLoaders Dim RawLoaders As List(Of String) = Data("loaders").Select(Function(v) v.ToString).ToList - ModLoaders = New List(Of CompModLoaderType) - If RawLoaders.Contains("forge") Then ModLoaders.Add(CompModLoaderType.Forge) - If RawLoaders.Contains("neoforge") Then ModLoaders.Add(CompModLoaderType.NeoForge) - If RawLoaders.Contains("fabric") Then ModLoaders.Add(CompModLoaderType.Fabric) - If RawLoaders.Contains("quilt") Then ModLoaders.Add(CompModLoaderType.Quilt) + ModLoaders = New List(Of CompLoaderType) + If RawLoaders.Contains("forge") Then ModLoaders.Add(CompLoaderType.Forge) + If RawLoaders.Contains("neoforge") Then ModLoaders.Add(CompLoaderType.NeoForge) + If RawLoaders.Contains("fabric") Then ModLoaders.Add(CompLoaderType.Fabric) + If RawLoaders.Contains("quilt") Then ModLoaders.Add(CompLoaderType.Quilt) #End Region End If End If @@ -1959,7 +1997,7 @@ Retry: Dim Ids As New List(Of String)({ProjectId}) Dim CompProjects = CompRequest.GetCompProjectsByIds(Ids) RunInUi(Sub() FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail, - .Additional = {CompProjects.First(), New List(Of String), String.Empty, CompModLoaderType.Any}})) + .Additional = {CompProjects.First(), New List(Of String), String.Empty, CompLoaderType.Any}})) End If End While End Sub diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLocalComp.vb similarity index 65% rename from Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb rename to Plain Craft Launcher 2/Modules/Minecraft/ModLocalComp.vb index 93d4773d4..d1382e41f 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLocalComp.vb @@ -1,21 +1,21 @@ Imports System.IO.Compression -Public Module ModMod +Public Module ModLocalComp Private Const LocalModCacheVersion As Integer = 7 - Public Class McMod + Public Class LocalCompFile #Region "基础" ''' - ''' Mod 文件的地址。 + ''' 资源的文件的地址。 ''' Public ReadOnly Path As String Public Sub New(Path As String) Me.Path = If(Path, "") End Sub ''' - ''' Mod 的完整路径,去除最后的 .disabled 和 .old。 + ''' Mod 资源的完整路径,去除最后的 .disabled 和 .old。 ''' Public ReadOnly Property RawPath As String Get @@ -24,7 +24,7 @@ Public Module ModMod End Property ''' - ''' Mod 的完整文件名。 + ''' 资源的完整文件名。 ''' Public ReadOnly Property FileName As String Get @@ -33,7 +33,7 @@ Public Module ModMod End Property ''' - ''' Mod 的完整文件名,去除最后的 .disabled 和 .old。 + ''' Mod 资源的完整文件名,去除最后的 .disabled 和 .old。 ''' Public ReadOnly Property RawFileName As String Get @@ -42,21 +42,21 @@ Public Module ModMod End Property ''' - ''' Mod 的状态。 + ''' 资源的状态。对于 Mod 有 Disabled ''' - Public ReadOnly Property State As McModState + Public ReadOnly Property State As LocalFileStatus Get Load() If Not IsFileAvailable Then - Return McModState.Unavailable + Return LocalFileStatus.Unavailable ElseIf Path.EndsWithF(".disabled", True) OrElse Path.EndsWithF(".old", True) Then - Return McModState.Disabled + Return LocalFileStatus.Disabled Else - Return McModState.Fine + Return LocalFileStatus.Fine End If End Get End Property - Public Enum McModState As Integer + Public Enum LocalFileStatus As Integer Fine = 0 Disabled = 1 Unavailable = 2 @@ -285,16 +285,16 @@ Public Module ModMod Dim Jar As ZipArchive = Nothing Try '基础可用性检查、打开 Jar 文件 - If Path.Length < 2 Then Throw New FileNotFoundException("错误的 Mod 文件路径(" & If(Path, "null") & ")") - If Not File.Exists(Path) Then Throw New FileNotFoundException("未找到 Mod 文件(" & Path & ")") + If Path.Length < 2 Then Throw New FileNotFoundException("错误的资源文件路径(" & If(Path, "null") & ")") + If Not File.Exists(Path) Then Throw New FileNotFoundException("未找到资源文件(" & Path & ")") Jar = New ZipArchive(New FileStream(Path, FileMode.Open)) '信息获取 LookupMetadata(Jar) Catch ex As UnauthorizedAccessException - Log(ex, "Mod 文件由于无权限无法打开(" & Path & ")", LogLevel.Developer) + Log(ex, "资源文件由于无权限无法打开(" & Path & ")", LogLevel.Developer) _FileUnavailableReason = New UnauthorizedAccessException("没有读取此文件的权限,请尝试右键以管理员身份运行 PCL", ex) Catch ex As Exception - Log(ex, "Mod 文件无法打开(" & Path & ")", LogLevel.Developer) + Log(ex, "资源文件无法打开(" & Path & ")", LogLevel.Developer) _FileUnavailableReason = ex Finally If Jar IsNot Nothing Then Jar.Dispose() @@ -307,7 +307,6 @@ Public Module ModMod ''' 从 Jar 文件中获取 Mod 信息。 ''' Private Sub LookupMetadata(Jar As ZipArchive) - #Region "尝试使用 mcmod.info" Try '获取信息文件 @@ -511,7 +510,7 @@ GotFabric: If TomlSubData.Key.ToLower = $"dependencies.{ModId.ToLower}" Then Dim DepEntry As Dictionary(Of String, Object) = TomlSubData.Value If DepEntry.ContainsKey("modId") AndAlso DepEntry.ContainsKey("mandatory") AndAlso DepEntry("mandatory") AndAlso - DepEntry.ContainsKey("side") AndAlso Not DepEntry("side").ToString.ToLower = "server" Then + DepEntry.ContainsKey("side") AndAlso Not DepEntry("side").ToString.ToLower = "server" Then AddDependency(DepEntry("modId"), If(DepEntry.ContainsKey("versionRange"), DepEntry("versionRange"), Nothing)) End If End If @@ -606,7 +605,6 @@ Finished: End If If _Version IsNot Nothing AndAlso Not (_Version.Contains(".") OrElse _Version.Contains("-")) Then Version = Nothing #End Region - End Sub #End Region @@ -616,7 +614,7 @@ Finished: ''' ''' 当任何网络信息更新时触发。 ''' - Public Event OnCompUpdate(sender As McMod) + Public Event OnCompUpdate(sender As LocalCompFile) ''' ''' 该 Mod 关联的网络项目。 @@ -701,7 +699,7 @@ Finished: '读取缓存 Dim Info As New FileInfo(Path) Dim CacheKey As String = GetHash($"{RawPath}-{Info.LastWriteTime.ToLongTimeString}-{Info.Length}-C") - Dim Cached As String = ReadIni(PathTemp & "Cache\ModHash.ini", CacheKey) + Dim Cached As String = ReadIni(PathTemp & "Cache\CompHash.ini", CacheKey) If Cached <> "" AndAlso RegexCheck(Cached, "^\d+$") Then '#5062 _CurseForgeHash = Cached Return _CurseForgeHash @@ -741,7 +739,7 @@ Finished: h = h Xor (h >> 15) _CurseForgeHash = h '写入缓存 - WriteIni(PathTemp & "Cache\ModHash.ini", CacheKey, h.ToString) + WriteIni(PathTemp & "Cache\CompHash.ini", CacheKey, h.ToString) End If Return _CurseForgeHash End Get @@ -757,7 +755,7 @@ Finished: '读取缓存 Dim Info As New FileInfo(Path) Dim CacheKey As String = GetHash($"{RawPath}-{Info.LastWriteTime.ToLongTimeString}-{Info.Length}-M") - Dim Cached As String = ReadIni(PathTemp & "Cache\ModHash.ini", CacheKey) + Dim Cached As String = ReadIni(PathTemp & "Cache\CompHash.ini", CacheKey) If Cached <> "" Then _ModrinthHash = Cached Return _ModrinthHash @@ -765,7 +763,7 @@ Finished: '计算 SHA1 _ModrinthHash = GetFileSHA1(Path) '写入缓存 - WriteIni(PathTemp & "Cache\ModHash.ini", CacheKey, _ModrinthHash) + WriteIni(PathTemp & "Cache\CompHash.ini", CacheKey, _ModrinthHash) End If Return _ModrinthHash End Get @@ -780,7 +778,7 @@ Finished: Return $"{State} - {Path}" End Function Public Overrides Function Equals(obj As Object) As Boolean - Dim target = TryCast(obj, McMod) + Dim target = TryCast(obj, LocalCompFile) Return target IsNot Nothing AndAlso Path = target.Path End Function @@ -807,347 +805,368 @@ Finished: End Class - '加载 Mod 列表 - Public McModLoader As New LoaderTask(Of String, List(Of McMod))("Mod List Loader", AddressOf McModLoad) - Private Sub McModLoad(Loader As LoaderTask(Of String, List(Of McMod))) - Try - RunInUiWait(Sub() If FrmVersionMod IsNot Nothing Then FrmVersionMod.Load.ShowProgress = False) + Public Class CompLocalLoader + Private _GameVersion As String + Private _Loaders As List(Of CompLoaderType) + Private _Frm As PageVersionCompResource + + Public Sub New(TargetFrm As PageVersionCompResource, TargetGameVersion As String, TargetLoaders As List(Of CompLoaderType)) + Me._GameVersion = TargetGameVersion + Me._Loaders = TargetLoaders + Me._Frm = TargetFrm + End Sub + + '加载资源列表 + Public CompResourceListLoader As New LoaderTask(Of String, List(Of LocalCompFile))("Comp Resource List Loader", AddressOf CompResourceListLoad) + Private Sub CompResourceListLoad(Loader As LoaderTask(Of String, List(Of LocalCompFile))) + Try + RunInUiWait(Sub() If _Frm IsNot Nothing Then _Frm.Load.ShowProgress = False) + + '等待 Mod 更新完成 + If PageVersionCompResource.UpdatingVersions.Contains(Loader.Input) Then + Log($"[Mod] 等待资源更新完成后才能继续加载资源列表:" & Loader.Input) + Try + RunInUiWait(Sub() If _Frm IsNot Nothing Then _Frm.Load.Text = "正在更新资源") + Do Until Not PageVersionCompResource.UpdatingVersions.Contains(Loader.Input) + If Loader.IsAborted Then Exit Sub + Thread.Sleep(100) + Loop + Finally + RunInUiWait(Sub() If _Frm IsNot Nothing Then _Frm.Load.Text = "正在加载资源列表") + End Try + _Frm.LoaderRun(LoaderFolderRunType.UpdateOnly) + End If - '等待 Mod 更新完成 - If PageVersionMod.UpdatingVersions.Contains(Loader.Input) Then - Log($"[Mod] 等待 Mod 更新完成后才能继续加载 Mod 列表:" & Loader.Input) + '获取 Mod 文件夹下的可用文件列表 + Dim ModFileList As New List(Of FileInfo) + If Directory.Exists(Loader.Input) Then + Dim RawName As String = Loader.Input.ToLower + For Each File As FileInfo In EnumerateFiles(Loader.Input) + If File.DirectoryName.ToLower & "\" <> RawName Then + '仅当 Forge 1.13- 且文件夹名与版本号相同时,才加载该子文件夹下的 Mod + If Not (PageVersionLeft.Version IsNot Nothing AndAlso PageVersionLeft.Version.Version.HasForge AndAlso + PageVersionLeft.Version.Version.McCodeMain < 13 AndAlso + File.Directory.Name = "1." & PageVersionLeft.Version.Version.McCodeMain & "." & PageVersionLeft.Version.Version.McCodeSub) Then + Continue For + End If + End If + If LocalCompFile.IsModFile(File.FullName) Then ModFileList.Add(File) + Next + End If + + '确定是否显示进度 + Loader.Progress = 0.05 + If ModFileList.Count > 50 Then RunInUi(Sub() If _Frm IsNot Nothing Then _Frm.Load.ShowProgress = True) + + '获取本地文件缓存 + Dim CachePath As String = PathTemp & "Cache\LocalComp.json" + Dim Cache As New JObject Try - RunInUiWait(Sub() If FrmVersionMod IsNot Nothing Then FrmVersionMod.Load.Text = "正在更新 Mod") - Do Until Not PageVersionMod.UpdatingVersions.Contains(Loader.Input) - If Loader.IsAborted Then Exit Sub - Thread.Sleep(100) - Loop - Finally - RunInUiWait(Sub() If FrmVersionMod IsNot Nothing Then FrmVersionMod.Load.Text = "正在加载 Mod 列表") + Dim CacheContent As String = ReadFile(CachePath) + If Not String.IsNullOrWhiteSpace(CacheContent) Then + Cache = GetJson(CacheContent) + If Not Cache.ContainsKey("version") OrElse Cache("version").ToObject(Of Integer) <> LocalModCacheVersion Then + Log($"[Mod] 本地 Mod 信息缓存版本已过期,将弃用这些缓存信息", LogLevel.Debug) + Cache = New JObject + End If + End If + Catch ex As Exception + Log(ex, "读取本地 Mod 信息缓存失败,已重置") + Cache = New JObject End Try - FrmVersionMod.LoaderRun(LoaderFolderRunType.UpdateOnly) - End If + Cache("version") = LocalModCacheVersion - '获取 Mod 文件夹下的可用文件列表 - Dim ModFileList As New List(Of FileInfo) - If Directory.Exists(Loader.Input) Then - Dim RawName As String = Loader.Input.ToLower - For Each File As FileInfo In EnumerateFiles(Loader.Input) - If File.DirectoryName.ToLower & "\" <> RawName Then - '仅当 Forge 1.13- 且文件夹名与版本号相同时,才加载该子文件夹下的 Mod - If Not (PageVersionLeft.Version IsNot Nothing AndAlso PageVersionLeft.Version.Version.HasForge AndAlso - PageVersionLeft.Version.Version.McCodeMain < 13 AndAlso - File.Directory.Name = "1." & PageVersionLeft.Version.Version.McCodeMain & "." & PageVersionLeft.Version.Version.McCodeSub) Then + '加载 Mod 列表 + Dim ModList As New List(Of LocalCompFile) + Dim ModUpdateList As New List(Of LocalCompFile) + For Each ModFile As FileInfo In ModFileList + Loader.Progress += 0.94 / ModFileList.Count + If Loader.IsAborted Then Exit Sub + '加载 McMod 对象 + Dim ModEntry As New LocalCompFile(ModFile.FullName) + ModEntry.Load() + Dim DumpMod As LocalCompFile = ModList.FirstOrDefault(Function(m) m.RawFileName = ModEntry.RawFileName) + If DumpMod IsNot Nothing Then + Dim DisabledMod As LocalCompFile = If(DumpMod.State = LocalCompFile.LocalFileStatus.Disabled, DumpMod, ModEntry) + Log($"[Mod] 重复的 Mod 文件:{DumpMod.FileName} 与 {ModEntry.FileName},已忽略 {DisabledMod.FileName}", LogLevel.Debug) + If DisabledMod Is ModEntry Then Continue For + Else + ModList.Remove(DisabledMod) + ModUpdateList.Remove(DisabledMod) End If End If - If McMod.IsModFile(File.FullName) Then ModFileList.Add(File) + ModList.Add(ModEntry) + '读取 Comp 缓存 + If ModEntry.State = LocalCompFile.LocalFileStatus.Unavailable Then Continue For + Dim CacheKey = ModEntry.ModrinthHash & PageVersionLeft.Version.Version.McName & GetCurrentVersionModLoader().Join("") + If Cache.ContainsKey(CacheKey) Then + ModEntry.FromJson(Cache(CacheKey)) + '如果缓存中的信息在 6 小时以内更新过,则无需重新获取 + If ModEntry.CompLoaded AndAlso Date.Now - Cache(CacheKey)("Comp")("CacheTime").ToObject(Of Date) < New TimeSpan(6, 0, 0) Then Continue For + End If + ModUpdateList.Add(ModEntry) Next - End If + Loader.Progress = 0.99 + Log($"[Mod] 共有 {ModList.Count} 个 Mod,其中 {ModUpdateList.Where(Function(m) m.Comp Is Nothing).Count} 个需要联网获取信息,{ModUpdateList.Where(Function(m) m.Comp IsNot Nothing).Count} 个需要更新信息") - '确定是否显示进度 - Loader.Progress = 0.05 - If ModFileList.Count > 50 Then RunInUi(Sub() If FrmVersionMod IsNot Nothing Then FrmVersionMod.Load.ShowProgress = True) - - '获取本地文件缓存 - Dim CachePath As String = PathTemp & "Cache\LocalMod.json" - Dim Cache As New JObject - Try - Dim CacheContent As String = ReadFile(CachePath) - If Not String.IsNullOrWhiteSpace(CacheContent) Then - Cache = GetJson(CacheContent) - If Not Cache.ContainsKey("version") OrElse Cache("version").ToObject(Of Integer) <> LocalModCacheVersion Then - Log($"[Mod] 本地 Mod 信息缓存版本已过期,将弃用这些缓存信息", LogLevel.Debug) - Cache = New JObject + '排序 + ModList = Sort(ModList, + Function(Left As LocalCompFile, Right As LocalCompFile) As Boolean + If (Left.State = LocalCompFile.LocalFileStatus.Unavailable) <> (Right.State = LocalCompFile.LocalFileStatus.Unavailable) Then + Return Left.State = LocalCompFile.LocalFileStatus.Unavailable + Else + Return Not Right.FileName.CompareTo(Left.FileName) End If - End If - Catch ex As Exception - Log(ex, "读取本地 Mod 信息缓存失败,已重置") - Cache = New JObject - End Try - Cache("version") = LocalModCacheVersion + End Function) - '加载 Mod 列表 - Dim ModList As New List(Of McMod) - Dim ModUpdateList As New List(Of McMod) - For Each ModFile As FileInfo In ModFileList - Loader.Progress += 0.94 / ModFileList.Count + '回设 If Loader.IsAborted Then Exit Sub - '加载 McMod 对象 - Dim ModEntry As New McMod(ModFile.FullName) - ModEntry.Load() - Dim DumpMod As McMod = ModList.FirstOrDefault(Function(m) m.RawFileName = ModEntry.RawFileName) - If DumpMod IsNot Nothing Then - Dim DisabledMod As McMod = If(DumpMod.State = McMod.McModState.Disabled, DumpMod, ModEntry) - Log($"[Mod] 重复的 Mod 文件:{DumpMod.FileName} 与 {ModEntry.FileName},已忽略 {DisabledMod.FileName}", LogLevel.Debug) - If DisabledMod Is ModEntry Then - Continue For - Else - ModList.Remove(DisabledMod) - ModUpdateList.Remove(DisabledMod) - End If - End If - ModList.Add(ModEntry) - '读取 Comp 缓存 - If ModEntry.State = McMod.McModState.Unavailable Then Continue For - Dim CacheKey = ModEntry.ModrinthHash & PageVersionLeft.Version.Version.McName & GetTargetModLoaders().Join("") - If Cache.ContainsKey(CacheKey) Then - ModEntry.FromJson(Cache(CacheKey)) - '如果缓存中的信息在 6 小时以内更新过,则无需重新获取 - If ModEntry.CompLoaded AndAlso Date.Now - Cache(CacheKey)("Comp")("CacheTime").ToObject(Of Date) < New TimeSpan(6, 0, 0) Then Continue For - End If - ModUpdateList.Add(ModEntry) - Next - Loader.Progress = 0.99 - Log($"[Mod] 共有 {ModList.Count} 个 Mod,其中 {ModUpdateList.Where(Function(m) m.Comp Is Nothing).Count} 个需要联网获取信息,{ModUpdateList.Where(Function(m) m.Comp IsNot Nothing).Count} 个需要更新信息") + Loader.Output = ModList - '排序 - ModList = Sort(ModList, - Function(Left As McMod, Right As McMod) As Boolean - If (Left.State = McMod.McModState.Unavailable) <> (Right.State = McMod.McModState.Unavailable) Then - Return Left.State = McMod.McModState.Unavailable - Else - Return Not Right.FileName.CompareTo(Left.FileName) + '开始联网加载 + If ModUpdateList.Any() Then + 'TODO: 添加信息获取中提示 + CompUpdateDetailLoader.Start(New KeyValuePair(Of List(Of LocalCompFile), JObject)(ModUpdateList, Cache), IsForceRestart:=True) End If - End Function) - - '回设 - If Loader.IsAborted Then Exit Sub - Loader.Output = ModList - - '开始联网加载 - If ModUpdateList.Any() Then - 'TODO: 添加信息获取中提示 - McModDetailLoader.Start(New KeyValuePair(Of List(Of McMod), JObject)(ModUpdateList, Cache), IsForceRestart:=True) - End If - Catch ex As Exception - Log(ex, "Mod 列表加载失败", LogLevel.Debug) - Throw - End Try - End Sub - '联网加载 Mod 详情 - Public McModDetailLoader As New LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer)("Mod List Detail Loader", AddressOf McModDetailLoad) - Private Sub McModDetailLoad(Loader As LoaderTask(Of KeyValuePair(Of List(Of McMod), JObject), Integer)) - Dim Mods As List(Of McMod) = Loader.Input.Key - Dim Cache As JObject = Loader.Input.Value - '获取作为检查目标的加载器和版本 - Dim TargetMcVersion As McVersionInfo = PageVersionLeft.Version.Version - Dim ModLoaders = GetTargetModLoaders() - Dim McVersion = TargetMcVersion.McName - '暂不向下扩展检查的 MC 小版本 - '例如:Mod 在更新 1.16.5 后,对早期的 1.16.2 版本发布了修补补丁,这会导致 PCL 将 1.16.5 版本的 Mod 降级到 1.16.2 - 'If TargetMcVersion.McCodeMain > 0 AndAlso TargetMcVersion.McCodeMain < 99 Then - ' McVersions.Add($"1.{TargetMcVersion.McCodeMain}") - ' For i = 1 To TargetMcVersion.McCodeSub - ' McVersions.Add($"1.{TargetMcVersion.McCodeMain}.{i}") - ' Next - 'End If - 'McVersions = McVersions.Distinct().ToList() - '开始网络获取 - Log($"[Mod] 目标加载器:{ModLoaders.Join("/")},版本:{McVersion}") - Dim EndedThreadCount As Integer = 0, IsFailed As Boolean = False - Dim MainThread As Thread = Thread.CurrentThread - '从 Modrinth 获取信息 - RunInNewThread( - Sub() - 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) - Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息") - '步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系 - If ModrinthVersion.Count = 0 Then Exit Sub - Dim ModrinthMapping As New Dictionary(Of String, List(Of McMod)) - For Each Entry In Mods - If Not ModrinthVersion.ContainsKey(Entry.ModrinthHash) Then Continue For - If ModrinthVersion(Entry.ModrinthHash)("files")(0)("hashes")("sha1") <> Entry.ModrinthHash Then Continue For - Dim ProjectId = ModrinthVersion(Entry.ModrinthHash)("project_id").ToString - If CompProjectCache.ContainsKey(ProjectId) AndAlso Entry.Comp Is Nothing Then Entry.Comp = CompProjectCache(ProjectId) '读取已加载的缓存,加快结果出现速度 - If Not ModrinthMapping.ContainsKey(ProjectId) Then ModrinthMapping(ProjectId) = New List(Of McMod) - ModrinthMapping(ProjectId).Add(Entry) - '记录对应的 CompFile - Dim File As New CompFile(ModrinthVersion(Entry.ModrinthHash), CompType.Mod) - If Entry.CompFile Is Nothing OrElse Entry.CompFile.ReleaseDate < File.ReleaseDate Then Entry.CompFile = File - Next - If Loader.IsAbortedWithThread(MainThread) Then Exit Sub - Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息") - '步骤 3:获取工程信息 - If Not ModrinthMapping.Any() Then Exit Sub - Dim ModrinthProject = CType(GetJson(DlModRequest( - $"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]", - "GET", "", "application/json")), JArray) - For Each ProjectJson In ModrinthProject - Dim Project As New CompProject(ProjectJson) - For Each Entry In ModrinthMapping(Project.Id) - Entry.Comp = Project - Next - Next - Log($"[Mod] 已从 Modrinth 获取本地 Mod 信息,继续获取更新信息") - '步骤 4:获取更新信息 - Dim ModrinthUpdate = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files/update", "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) - 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) - If Not UpdateFile.Available Then Continue For - If ModeDebug Then Log($"[Mod] 本地文件 {Entry.CompFile.FileName} 在 Modrinth 上的最新版为 {UpdateFile.FileName}") - If Entry.CompFile.ReleaseDate >= UpdateFile.ReleaseDate OrElse Entry.CompFile.Hash = UpdateFile.Hash Then Continue For - '设置更新日志与更新文件 - If Entry.UpdateFile IsNot Nothing AndAlso UpdateFile.Hash = Entry.UpdateFile.Hash Then '合并 - Entry.ChangelogUrls.Add($"https://modrinth.com/mod/{ModrinthUpdate(Entry.ModrinthHash)("project_id")}/changelog?g={McVersion}") - UpdateFile.DownloadUrls.AddRange(Entry.UpdateFile.DownloadUrls) '合并下载源 - Entry.UpdateFile = UpdateFile '优先使用 Modrinth 的文件 - ElseIf Entry.UpdateFile Is Nothing OrElse UpdateFile.ReleaseDate >= Entry.UpdateFile.ReleaseDate Then '替换 - Entry.ChangelogUrls = New List(Of String) From {$"https://modrinth.com/mod/{ModrinthUpdate(Entry.ModrinthHash)("project_id")}/changelog?g={McVersion}"} - Entry.UpdateFile = UpdateFile - End If - Next - Log($"[Mod] 从 Modrinth 获取本地 Mod 信息结束") Catch ex As Exception - Log(ex, "从 Modrinth 获取本地 Mod 信息失败") - IsFailed = True - Finally - EndedThreadCount += 1 + Log(ex, "Mod 列表加载失败", LogLevel.Debug) + Throw End Try - End Sub, "Mod List Detail Loader Modrinth") - '从 CurseForge 获取信息 - RunInNewThread( - Sub() - Try - '步骤 1:获取 Hash 与对应的工程 ID - Dim CurseForgeHashes As New List(Of UInteger) - For Each Entry In Mods - CurseForgeHashes.Add(Entry.CurseForgeHash) - If Loader.IsAbortedWithThread(MainThread) Then Exit Sub - Next - Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432", "POST", - $"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer) - Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息") - '步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系 - If Not CurseForgeRaw.Any() Then Exit Sub - Dim CurseForgeMapping As New Dictionary(Of Integer, List(Of McMod)) - For Each Project In CurseForgeRaw - Dim ProjectId = Project("id").ToString - Dim Hash As UInteger = Project("file")("fileFingerprint") + End Sub + '联网加载 Mod 详情 + Public CompUpdateDetailLoader As New LoaderTask(Of KeyValuePair(Of List(Of LocalCompFile), JObject), Integer)("Comp List Detail Loader", AddressOf CompUpdateDetailLoad) + Private Sub CompUpdateDetailLoad(Loader As LoaderTask(Of KeyValuePair(Of List(Of LocalCompFile), JObject), Integer)) + Dim Mods As List(Of LocalCompFile) = Loader.Input.Key + Dim Cache As JObject = Loader.Input.Value + '获取作为检查目标的加载器和版本 + Dim ModLoaders = _Loaders + Dim McVersion = _GameVersion + '暂不向下扩展检查的 MC 小版本 + '例如:Mod 在更新 1.16.5 后,对早期的 1.16.2 版本发布了修补补丁,这会导致 PCL 将 1.16.5 版本的 Mod 降级到 1.16.2 + 'If TargetMcVersion.McCodeMain > 0 AndAlso TargetMcVersion.McCodeMain < 99 Then + ' McVersions.Add($"1.{TargetMcVersion.McCodeMain}") + ' For i = 1 To TargetMcVersion.McCodeSub + ' McVersions.Add($"1.{TargetMcVersion.McCodeMain}.{i}") + ' Next + 'End If + 'McVersions = McVersions.Distinct().ToList() + '开始网络获取 + Log($"[Mod] 目标加载器:{ModLoaders.Join("/")},版本:{McVersion}") + Dim EndedThreadCount As Integer = 0, IsFailed As Boolean = False + Dim MainThread As Thread = Thread.CurrentThread + '从 Modrinth 获取信息 + RunInNewThread( + Sub() + 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) + Log($"[Mod] 从 Modrinth 获取到 {ModrinthVersion.Count} 个本地 Mod 的对应信息") + '步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系 + If ModrinthVersion.Count = 0 Then Exit Sub + Dim ModrinthMapping As New Dictionary(Of String, List(Of LocalCompFile)) For Each Entry In Mods - If Entry.CurseForgeHash <> Hash Then Continue For + If Not ModrinthVersion.ContainsKey(Entry.ModrinthHash) Then Continue For + If ModrinthVersion(Entry.ModrinthHash)("files")(0)("hashes")("sha1") <> Entry.ModrinthHash Then Continue For + Dim ProjectId = ModrinthVersion(Entry.ModrinthHash)("project_id").ToString If CompProjectCache.ContainsKey(ProjectId) AndAlso Entry.Comp Is Nothing Then Entry.Comp = CompProjectCache(ProjectId) '读取已加载的缓存,加快结果出现速度 - If Not CurseForgeMapping.ContainsKey(ProjectId) Then CurseForgeMapping(ProjectId) = New List(Of McMod) - CurseForgeMapping(ProjectId).Add(Entry) + If Not ModrinthMapping.ContainsKey(ProjectId) Then ModrinthMapping(ProjectId) = New List(Of LocalCompFile) + ModrinthMapping(ProjectId).Add(Entry) '记录对应的 CompFile - Dim File As New CompFile(Project("file"), CompType.Mod) + Dim File As New CompFile(ModrinthVersion(Entry.ModrinthHash), CompType.Mod) If Entry.CompFile Is Nothing OrElse Entry.CompFile.ReleaseDate < File.ReleaseDate Then Entry.CompFile = File Next - Next - If Loader.IsAbortedWithThread(MainThread) Then Exit Sub - Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息") - '步骤 3:获取工程信息 - If Not CurseForgeMapping.Any() Then Exit Sub - Dim CurseForgeProject = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods", "POST", - $"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")), JObject)("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 - If ProjectJson("isAvailable") IsNot Nothing AndAlso Not ProjectJson("isAvailable").ToObject(Of Boolean) Then Continue For - '设置 Entry 中的工程信息 - Dim Project As New CompProject(ProjectJson) - For Each Entry In CurseForgeMapping(Project.Id) '倒查防止 CurseForge 返回的内容有漏 - If Entry.Comp IsNot Nothing AndAlso Not Entry.Comp.FromCurseForge Then - Entry.Comp = Entry.Comp '再次触发修改事件 - Continue For + If Loader.IsAbortedWithThread(MainThread) Then Exit Sub + Log($"[Mod] 需要从 Modrinth 获取 {ModrinthMapping.Count} 个本地 Mod 的工程信息") + '步骤 3:获取工程信息 + If Not ModrinthMapping.Any() Then Exit Sub + Dim ModrinthProject = CType(GetJson(DlModRequest( + $"https://api.modrinth.com/v2/projects?ids=[""{ModrinthMapping.Keys.Join(""",""")}""]", + "GET", "", "application/json")), JArray) + For Each ProjectJson In ModrinthProject + Dim Project As New CompProject(ProjectJson) + For Each Entry In ModrinthMapping(Project.Id) + Entry.Comp = Project + Next + Next + Log($"[Mod] 已从 Modrinth 获取本地 Mod 信息,继续获取更新信息") + '步骤 4:获取更新信息 + Dim ModrinthUpdate = CType(GetJson(DlModRequest("https://api.modrinth.com/v2/version_files/update", "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) + 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) + If Not UpdateFile.Available Then Continue For + If ModeDebug Then Log($"[Mod] 本地文件 {Entry.CompFile.FileName} 在 Modrinth 上的最新版为 {UpdateFile.FileName}") + If Entry.CompFile.ReleaseDate >= UpdateFile.ReleaseDate OrElse Entry.CompFile.Hash = UpdateFile.Hash Then Continue For + '设置更新日志与更新文件 + If Entry.UpdateFile IsNot Nothing AndAlso UpdateFile.Hash = Entry.UpdateFile.Hash Then '合并 + Entry.ChangelogUrls.Add($"https://modrinth.com/mod/{ModrinthUpdate(Entry.ModrinthHash)("project_id")}/changelog?g={McVersion}") + UpdateFile.DownloadUrls.AddRange(Entry.UpdateFile.DownloadUrls) '合并下载源 + Entry.UpdateFile = UpdateFile '优先使用 Modrinth 的文件 + ElseIf Entry.UpdateFile Is Nothing OrElse UpdateFile.ReleaseDate >= Entry.UpdateFile.ReleaseDate Then '替换 + Entry.ChangelogUrls = New List(Of String) From {$"https://modrinth.com/mod/{ModrinthUpdate(Entry.ModrinthHash)("project_id")}/changelog?g={McVersion}"} + Entry.UpdateFile = UpdateFile End If - Entry.Comp = Project Next - '查找或许版本更新的文件列表 - If ModLoaders.Count = 1 Then 'TODO: 结果有多个 ModLoader 时提示无法检测更新 - Dim NewestVersion As String = Nothing - Dim NewestFileIds As New List(Of Integer) - For Each IndexEntry In ProjectJson("latestFilesIndexes") - If IndexEntry("modLoader") Is Nothing OrElse ModLoaders.Single <> IndexEntry("modLoader").ToObject(Of Integer) Then Continue For 'ModLoader 唯一且匹配 - Dim IndexVersion As String = IndexEntry("gameVersion") - If IndexVersion <> McVersion Then Continue For 'MC 版本匹配 - '由于 latestFilesIndexes 是按时间从新到老排序的,所以只需取第一个;如果需要检查多个 releaseType 下的文件,将 > -1 改为 = 1,但这应当并不会获取到更新的文件 - If NewestVersion IsNot Nothing AndAlso VersionSortInteger(NewestVersion, IndexVersion) > -1 Then Continue For '只保留最新 MC 版本 - If NewestVersion <> IndexVersion Then - NewestVersion = IndexVersion - NewestFileIds.Clear() + Log($"[Mod] 从 Modrinth 获取本地 Mod 信息结束") + Catch ex As Exception + Log(ex, "从 Modrinth 获取本地 Mod 信息失败") + IsFailed = True + Finally + EndedThreadCount += 1 + End Try + End Sub, "Mod List Detail Loader Modrinth") + '从 CurseForge 获取信息 + RunInNewThread( + Sub() + Try + '步骤 1:获取 Hash 与对应的工程 ID + Dim CurseForgeHashes As New List(Of UInteger) + For Each Entry In Mods + CurseForgeHashes.Add(Entry.CurseForgeHash) + If Loader.IsAbortedWithThread(MainThread) Then Exit Sub + Next + Dim CurseForgeRaw = CType(CType(GetJson(DlModRequest("https://api.curseforge.com/v1/fingerprints/432", "POST", + $"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")), JObject)("data")("exactMatches"), JContainer) + Log($"[Mod] 从 CurseForge 获取到 {CurseForgeRaw.Count} 个本地 Mod 的对应信息") + '步骤 2:尝试读取工程信息缓存,构建其他 Mod 的对应关系 + If Not CurseForgeRaw.Any() Then Exit Sub + Dim CurseForgeMapping As New Dictionary(Of Integer, List(Of LocalCompFile)) + For Each Project In CurseForgeRaw + Dim ProjectId = Project("id").ToString + Dim Hash As UInteger = Project("file")("fileFingerprint") + For Each Entry In Mods + If Entry.CurseForgeHash <> Hash Then Continue For + If CompProjectCache.ContainsKey(ProjectId) AndAlso Entry.Comp Is Nothing Then Entry.Comp = CompProjectCache(ProjectId) '读取已加载的缓存,加快结果出现速度 + If Not CurseForgeMapping.ContainsKey(ProjectId) Then CurseForgeMapping(ProjectId) = New List(Of LocalCompFile) + CurseForgeMapping(ProjectId).Add(Entry) + '记录对应的 CompFile + Dim File As New CompFile(Project("file"), CompType.Mod) + If Entry.CompFile Is Nothing OrElse Entry.CompFile.ReleaseDate < File.ReleaseDate Then Entry.CompFile = File + Next + Next + If Loader.IsAbortedWithThread(MainThread) Then Exit Sub + Log($"[Mod] 需要从 CurseForge 获取 {CurseForgeMapping.Count} 个本地 Mod 的工程信息") + '步骤 3:获取工程信息 + If Not CurseForgeMapping.Any() Then Exit Sub + Dim CurseForgeProject = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods", "POST", + $"{{""modIds"": [{CurseForgeMapping.Keys.Join(",")}]}}", "application/json")), JObject)("data") + Dim UpdateFileIds As New Dictionary(Of Integer, List(Of LocalCompFile)) 'FileId -> 本地 Mod 文件列表 + Dim FileIdToProjectSlug As New Dictionary(Of Integer, String) + For Each ProjectJson In CurseForgeProject + If ProjectJson("isAvailable") IsNot Nothing AndAlso Not ProjectJson("isAvailable").ToObject(Of Boolean) Then Continue For + '设置 Entry 中的工程信息 + Dim Project As New CompProject(ProjectJson) + For Each Entry In CurseForgeMapping(Project.Id) '倒查防止 CurseForge 返回的内容有漏 + If Entry.Comp IsNot Nothing AndAlso Not Entry.Comp.FromCurseForge Then + Entry.Comp = Entry.Comp '再次触发修改事件 + Continue For End If - NewestFileIds.Add(IndexEntry("fileId").ToObject(Of Integer)) + Entry.Comp = Project Next - For Each FileId In NewestFileIds - If Not UpdateFileIds.ContainsKey(FileId) Then UpdateFileIds(FileId) = New List(Of McMod) - UpdateFileIds(FileId).AddRange(CurseForgeMapping(Project.Id)) - FileIdToProjectSlug(FileId) = Project.Slug + '查找或许版本更新的文件列表 + If ModLoaders.Count = 1 Then 'TODO: 结果有多个 ModLoader 时提示无法检测更新 + Dim NewestVersion As String = Nothing + Dim NewestFileIds As New List(Of Integer) + For Each IndexEntry In ProjectJson("latestFilesIndexes") + If IndexEntry("modLoader") Is Nothing OrElse ModLoaders.Single <> IndexEntry("modLoader").ToObject(Of Integer) Then Continue For 'ModLoader 唯一且匹配 + Dim IndexVersion As String = IndexEntry("gameVersion") + If IndexVersion <> McVersion Then Continue For 'MC 版本匹配 + '由于 latestFilesIndexes 是按时间从新到老排序的,所以只需取第一个;如果需要检查多个 releaseType 下的文件,将 > -1 改为 = 1,但这应当并不会获取到更新的文件 + If NewestVersion IsNot Nothing AndAlso VersionSortInteger(NewestVersion, IndexVersion) > -1 Then Continue For '只保留最新 MC 版本 + If NewestVersion <> IndexVersion Then + NewestVersion = IndexVersion + NewestFileIds.Clear() + End If + NewestFileIds.Add(IndexEntry("fileId").ToObject(Of Integer)) + Next + For Each FileId In NewestFileIds + If Not UpdateFileIds.ContainsKey(FileId) Then UpdateFileIds(FileId) = New List(Of LocalCompFile) + UpdateFileIds(FileId).AddRange(CurseForgeMapping(Project.Id)) + FileIdToProjectSlug(FileId) = Project.Slug + Next + End If + Next + Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息") + '步骤 4:获取更新文件信息 + If Not UpdateFileIds.Any() Then Exit Sub + Dim CurseForgeFiles = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", + $"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")), JObject)("data") + Dim UpdateFiles As New Dictionary(Of LocalCompFile, CompFile) + For Each FileJson In CurseForgeFiles + Dim File As New CompFile(FileJson, CompType.Mod) + If Not File.Available Then Continue For + For Each Entry As LocalCompFile In UpdateFileIds(File.Id) + If UpdateFiles.ContainsKey(Entry) AndAlso UpdateFiles(Entry).ReleaseDate >= File.ReleaseDate Then Continue For + UpdateFiles(Entry) = File Next - End If - Next - Log($"[Mod] 已从 CurseForge 获取本地 Mod 信息,需要获取 {UpdateFileIds.Count} 个用于检查更新的文件信息") - '步骤 4:获取更新文件信息 - If Not UpdateFileIds.Any() Then Exit Sub - Dim CurseForgeFiles = CType(GetJson(DlModRequest("https://api.curseforge.com/v1/mods/files", "POST", - $"{{""fileIds"": [{UpdateFileIds.Keys.Join(",")}]}}", "application/json")), JObject)("data") - Dim UpdateFiles As New Dictionary(Of McMod, CompFile) - For Each FileJson In CurseForgeFiles - Dim File As New CompFile(FileJson, CompType.Mod) - If Not File.Available Then Continue For - For Each Entry As McMod In UpdateFileIds(File.Id) - If UpdateFiles.ContainsKey(Entry) AndAlso UpdateFiles(Entry).ReleaseDate >= File.ReleaseDate Then Continue For - UpdateFiles(Entry) = File Next - Next - For Each Pair In UpdateFiles - Dim Entry As McMod = Pair.Key - Dim UpdateFile As CompFile = Pair.Value - If ModeDebug Then Log($"[Mod] 本地文件 {Entry.CompFile.FileName} 在 CurseForge 上的最新版为 {UpdateFile.FileName}") - If Entry.CompFile.ReleaseDate >= UpdateFile.ReleaseDate OrElse Entry.CompFile.Hash = UpdateFile.Hash Then Continue For - '设置更新日志与更新文件 - If Entry.UpdateFile IsNot Nothing AndAlso UpdateFile.Hash = Entry.UpdateFile.Hash Then '合并 - Entry.ChangelogUrls.Add($"https://www.curseforge.com/minecraft/mc-mods/{FileIdToProjectSlug(UpdateFile.Id)}/files/{UpdateFile.Id}") - Entry.UpdateFile.DownloadUrls.AddRange(UpdateFile.DownloadUrls) '合并下载源 - ElseIf Entry.UpdateFile Is Nothing OrElse UpdateFile.ReleaseDate > Entry.UpdateFile.ReleaseDate Then '替换 - Entry.ChangelogUrls = New List(Of String) From {$"https://www.curseforge.com/minecraft/mc-mods/{FileIdToProjectSlug(UpdateFile.Id)}/files/{UpdateFile.Id}"} - Entry.UpdateFile = UpdateFile - End If - Next - Log($"[Mod] 从 CurseForge 获取 Mod 更新信息结束") - Catch ex As Exception - Log(ex, "从 CurseForge 获取本地 Mod 信息失败") - IsFailed = True - Finally - EndedThreadCount += 1 - End Try - End Sub, "Mod List Detail Loader CurseForge") - '等待线程结束 - Do Until EndedThreadCount = 2 - If Loader.IsAborted Then Exit Sub - Thread.Sleep(10) - Loop - '保存缓存 - Mods = Mods.Where(Function(m) m.Comp IsNot Nothing).ToList() - Log($"[Mod] 联网获取本地 Mod 信息完成,为 {Mods.Count} 个 Mod 更新缓存") - If Not Mods.Any() Then Exit Sub - For Each Entry In Mods - Entry.CompLoaded = Not IsFailed - Cache(Entry.ModrinthHash & McVersion & ModLoaders.Join("")) = Entry.ToJson() - Next - WriteFile(PathTemp & "Cache\LocalMod.json", Cache.ToString(If(ModeDebug, Newtonsoft.Json.Formatting.Indented, Newtonsoft.Json.Formatting.None))) - '刷新边栏 - RunInUi(Sub() FrmVersionMod?.RefreshBars()) - End Sub - Private Function GetTargetModLoaders() As List(Of CompModLoaderType) - Dim ModLoaders As New List(Of CompModLoaderType) - If PageVersionLeft.Version.Version.HasForge Then ModLoaders.Add(CompModLoaderType.Forge) - If PageVersionLeft.Version.Version.HasNeoForge Then ModLoaders.Add(CompModLoaderType.NeoForge) - If PageVersionLeft.Version.Version.HasFabric Then ModLoaders.Add(CompModLoaderType.Fabric) - If PageVersionLeft.Version.Version.HasQuilt Then ModLoaders.AddRange({CompModLoaderType.Fabric, CompModLoaderType.Quilt}) - If PageVersionLeft.Version.Version.HasLiteLoader Then ModLoaders.Add(CompModLoaderType.LiteLoader) - If Not ModLoaders.Any() Then ModLoaders.AddRange({CompModLoaderType.Forge, CompModLoaderType.NeoForge, CompModLoaderType.Fabric, CompModLoaderType.LiteLoader, CompModLoaderType.Quilt}) + For Each Pair In UpdateFiles + Dim Entry As LocalCompFile = Pair.Key + Dim UpdateFile As CompFile = Pair.Value + If ModeDebug Then Log($"[Mod] 本地文件 {Entry.CompFile.FileName} 在 CurseForge 上的最新版为 {UpdateFile.FileName}") + If Entry.CompFile.ReleaseDate >= UpdateFile.ReleaseDate OrElse Entry.CompFile.Hash = UpdateFile.Hash Then Continue For + '设置更新日志与更新文件 + If Entry.UpdateFile IsNot Nothing AndAlso UpdateFile.Hash = Entry.UpdateFile.Hash Then '合并 + Entry.ChangelogUrls.Add($"https://www.curseforge.com/minecraft/mc-mods/{FileIdToProjectSlug(UpdateFile.Id)}/files/{UpdateFile.Id}") + Entry.UpdateFile.DownloadUrls.AddRange(UpdateFile.DownloadUrls) '合并下载源 + ElseIf Entry.UpdateFile Is Nothing OrElse UpdateFile.ReleaseDate > Entry.UpdateFile.ReleaseDate Then '替换 + Entry.ChangelogUrls = New List(Of String) From {$"https://www.curseforge.com/minecraft/mc-mods/{FileIdToProjectSlug(UpdateFile.Id)}/files/{UpdateFile.Id}"} + Entry.UpdateFile = UpdateFile + End If + Next + Log($"[Mod] 从 CurseForge 获取 Mod 更新信息结束") + Catch ex As Exception + Log(ex, "从 CurseForge 获取本地 Mod 信息失败") + IsFailed = True + Finally + EndedThreadCount += 1 + End Try + End Sub, "Mod List Detail Loader CurseForge") + '等待线程结束 + Do Until EndedThreadCount = 2 + If Loader.IsAborted Then Exit Sub + Thread.Sleep(10) + Loop + '保存缓存 + Mods = Mods.Where(Function(m) m.Comp IsNot Nothing).ToList() + Log($"[Mod] 联网获取本地 Mod 信息完成,为 {Mods.Count} 个 Mod 更新缓存") + If Not Mods.Any() Then Exit Sub + For Each Entry In Mods + Entry.CompLoaded = Not IsFailed + Cache(Entry.ModrinthHash & McVersion & ModLoaders.Join("")) = Entry.ToJson() + Next + WriteFile(PathTemp & "Cache\LocalComp.json", Cache.ToString(If(ModeDebug, Newtonsoft.Json.Formatting.Indented, Newtonsoft.Json.Formatting.None))) + '刷新边栏 + RunInUi(Sub() _Frm.RefreshBars()) + End Sub + + End Class + Public Function GetCurrentVersionModLoader() As List(Of CompLoaderType) + Dim ModLoaders As New List(Of CompLoaderType) + If PageVersionLeft.Version.Version.HasForge Then ModLoaders.Add(CompLoaderType.Forge) + If PageVersionLeft.Version.Version.HasNeoForge Then ModLoaders.Add(CompLoaderType.NeoForge) + If PageVersionLeft.Version.Version.HasFabric Then ModLoaders.Add(CompLoaderType.Fabric) + If PageVersionLeft.Version.Version.HasQuilt Then ModLoaders.AddRange({CompLoaderType.Fabric, CompLoaderType.Quilt}) + If PageVersionLeft.Version.Version.HasLiteLoader Then ModLoaders.Add(CompLoaderType.LiteLoader) + If Not ModLoaders.Any() Then ModLoaders.AddRange({CompLoaderType.Forge, CompLoaderType.NeoForge, CompLoaderType.Fabric, CompLoaderType.LiteLoader, CompLoaderType.Quilt}) Return ModLoaders End Function + Public Function GetPathNameByCompType(TheType As CompType) As String + Select Case TheType + Case CompType.Mod : Return "mods" + Case CompType.ResourcePack : Return "resourcepacks" + Case CompType.Shader : Return "shaderpacks" + End Select + Return "Nothing" + End Function + #If DEBUG Then ''' ''' 检查 Mod 列表中存在的错误,返回错误信息的集合。 diff --git a/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb b/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb index 289c8111f..e8b7e7c4f 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml.vb @@ -104,13 +104,13 @@ End If '打开详情页 Dim TargetVersion As String - Dim TargetLoader As CompModLoaderType + Dim TargetLoader As CompLoaderType If FrmMain.PageCurrent.Page = FormMain.PageType.CompDetail Then TargetVersion = FrmMain.PageCurrent.Additional(2) TargetLoader = FrmMain.PageCurrent.Additional(3) ElseIf FrmMain.PageCurrent.Page = FormMain.PageType.Download AndAlso FrmMain.PageCurrentSub = FormMain.PageSubType.DownloadCompFavorites Then TargetVersion = "" - TargetLoader = CompModLoaderType.Any + TargetLoader = CompLoaderType.Any Else Select Case CType(sender.Tag, CompProject).Type Case CompType.Mod @@ -125,7 +125,7 @@ TargetVersion = "" 'If(PageDownloadResource.Loader.Input.GameVersion, "") End Select End If - If CType(sender.Tag, CompProject).Type <> CompType.Mod Then TargetLoader = CompModLoaderType.Any + If CType(sender.Tag, CompProject).Type <> CompType.Mod Then TargetLoader = CompLoaderType.Any FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail, .Additional = {sender.Tag, New List(Of String), TargetVersion, TargetLoader}}) End Sub diff --git a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalCompItem.xaml similarity index 99% rename from Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml rename to Plain Craft Launcher 2/Modules/Minecraft/MyLocalCompItem.xaml index 0066c3841..3a1408b06 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml +++ b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalCompItem.xaml @@ -1,4 +1,4 @@ - MouseButtonState.Pressed OrElse Not Swiping Then - Swiping = False - FrmVersionMod.CardSelect.IsHitTestVisible = True + If Mouse.LeftButton <> MouseButtonState.Pressed OrElse Not CurrentSwipe.Swiping Then + CurrentSwipe.Swiping = False + CurrentSwipe.TargetFrm.CardSelect.IsHitTestVisible = True Exit Sub End If '计算滑动范围 Dim Elements = CType(Parent, StackPanel).Children Dim Index As Integer = Elements.IndexOf(Me) - SwipeStart = MathClamp(Math.Min(SwipeStart, Index), 0, Elements.Count - 1) - SwipeEnd = MathClamp(Math.Max(SwipeEnd, Index), 0, Elements.Count - 1) + CurrentSwipe.Start = MathClamp(Math.Min(CurrentSwipe.Start, Index), 0, Elements.Count - 1) + CurrentSwipe.End = MathClamp(Math.Max(CurrentSwipe.End, Index), 0, Elements.Count - 1) '勾选所有范围中的项 - If SwipeStart = SwipeEnd Then Exit Sub - For i = SwipeStart To SwipeEnd - Dim Item As MyLocalModItem = Elements(i) + If CurrentSwipe.Start = CurrentSwipe.End Then Exit Sub + For i = CurrentSwipe.Start To CurrentSwipe.End + Dim Item As MyLocalCompItem = Elements(i) Item.InitLate(Item, e) - Item.Checked = SwipToState + Item.Checked = CurrentSwipe.SwipeToState Next End Sub @@ -188,7 +195,7 @@ Public Class MyLocalModItem Anim.Add(AaOpacity(RectCheck, 1 - RectCheck.Opacity, 30)) RectCheck.VerticalAlignment = VerticalAlignment.Center RectCheck.Margin = New Thickness(-3, 0, 0, 0) - Anim.Add(AaColor(LabTitle, TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5"), 200)) + Anim.Add(AaColor(LabTitle, TextBlock.ForegroundProperty, If(Entry.State = LocalCompFile.LocalFileStatus.Fine, "ColorBrush2", "ColorBrush5"), 200)) Else '由有变无 Anim.Add(AaHeight(RectCheck, -RectCheck.ActualHeight, 120,, New AniEaseInFluent(AniEasePower.Weak))) @@ -196,7 +203,7 @@ Public Class MyLocalModItem RectCheck.VerticalAlignment = VerticalAlignment.Center Anim.Add(AaColor(LabTitle, TextBlock.ForegroundProperty, If(LabTitle.TextDecorations Is Nothing, "ColorBrush1", "ColorBrushGray4"), 120)) End If - AniStart(Anim, "MyLocalModItem Checked " & Uuid) + AniStart(Anim, "MyLocalCompItem Checked " & Uuid) Else '不在窗口上时直接设置 RectCheck.VerticalAlignment = VerticalAlignment.Center @@ -204,13 +211,13 @@ Public Class MyLocalModItem If Checked Then RectCheck.Height = 32 RectCheck.Opacity = 1 - LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5")) + LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = LocalCompFile.LocalFileStatus.Fine, "ColorBrush2", "ColorBrush5")) Else RectCheck.Height = 0 RectCheck.Opacity = 0 - LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush1", "ColorBrushGray4")) + LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = LocalCompFile.LocalFileStatus.Fine, "ColorBrush1", "ColorBrushGray4")) End If - AniStop("MyLocalModItem Checked " & Uuid) + AniStop("MyLocalCompItem Checked " & Uuid) End If Catch ex As Exception Log(ex, "设置 Checked 失败") @@ -256,7 +263,7 @@ Public Class MyLocalModItem End Property '按钮 - Public ButtonHandler As Action(Of MyLocalModItem, EventArgs) + Public ButtonHandler As Action(Of MyLocalCompItem, EventArgs) Public ButtonStack As FrameworkElement Private _Buttons As IEnumerable(Of MyIconButton) Public Property Buttons As IEnumerable(Of MyIconButton) @@ -337,9 +344,9 @@ Public Class MyLocalModItem '标题与描述 Dim DescFileName As String Select Case Entry.State - Case McMod.McModState.Fine + Case LocalCompFile.LocalFileStatus.Fine DescFileName = GetFileNameWithoutExtentionFromPath(Entry.Path) - Case McMod.McModState.Disabled + Case LocalCompFile.LocalFileStatus.Disabled DescFileName = GetFileNameWithoutExtentionFromPath(Entry.Path.Replace(".disabled", "").Replace(".old", "")) Case Else 'McMod.McModState.Unavailable DescFileName = GetFileNameFromPath(Entry.Path) @@ -382,14 +389,14 @@ Public Class MyLocalModItem End If Description = NewDescription If Checked Then - LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5")) + LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = LocalCompFile.LocalFileStatus.Fine, "ColorBrush2", "ColorBrush5")) Else - LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush1", "ColorBrushGray4")) + LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = LocalCompFile.LocalFileStatus.Fine, "ColorBrush1", "ColorBrushGray4")) End If '主 Logo Logo = If(Entry.Comp Is Nothing, PathImage & "Icons/NoIcon.png", Entry.Comp.GetControlLogo()) '图标右下角的 Logo - If Entry.State = McMod.McModState.Fine Then + If Entry.State = LocalCompFile.LocalFileStatus.Fine Then If ImgState IsNot Nothing Then Children.Remove(ImgState) ImgState = Nothing @@ -483,9 +490,13 @@ Public Class MyLocalModItem '触发更新 Private Sub BtnUpdate_Click(sender As Object, e As EventArgs) Handles BtnUpdate.Click - Select Case MyMsgBox($"是否要更新 {Entry.Name}?{vbCrLf}{vbCrLf}{GetUpdateCompareDescription()}", "Mod 更新确认", "更新", "查看更新日志", "取消") + Select Case MyMsgBox($"是否要更新 {Entry.Name}?{vbCrLf}{vbCrLf}{GetUpdateCompareDescription()}", "更新确认", "更新", "查看更新日志", "取消") Case 1 '更新 - FrmVersionMod.UpdateMods({Entry}) + Select Case Entry.Comp.Type + Case CompType.Mod : FrmVersionMod.UpdateResource({Entry}) + Case CompType.ResourcePack : FrmVersionResourcePack.UpdateResource({Entry}) + Case CompType.Shader : FrmVersionShader.UpdateResource({Entry}) + End Select Case 2 '查看更新日志 ShowUpdateLog() Case 3 '取消 diff --git a/Plain Craft Launcher 2/Modules/ModMain.vb b/Plain Craft Launcher 2/Modules/ModMain.vb index 508c37fd2..2f6925c98 100644 --- a/Plain Craft Launcher 2/Modules/ModMain.vb +++ b/Plain Craft Launcher 2/Modules/ModMain.vb @@ -441,12 +441,12 @@ EndHint: '版本设置页面声明 Public FrmVersionLeft As PageVersionLeft Public FrmVersionOverall As PageVersionOverall - Public FrmVersionMod As PageVersionMod + Public FrmVersionMod As PageVersionCompResource Public FrmVersionModDisabled As PageVersionModDisabled Public FrmVersionScreenshot As PageVersionScreenshot Public FrmVersionWorld As PageVersionWorld - Public FrmVersionShader As PageVersionShader - Public FrmVersionResourcePack As PageVersionResourcePack + Public FrmVersionShader As PageVersionCompResource + Public FrmVersionResourcePack As PageVersionCompResource Public FrmVersionSetup As PageVersionSetup Public FrmVersionInstall As PageVersionInstall diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb index d4e555357..aa91e0d57 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb @@ -20,7 +20,7 @@ TargetLoader = FrmMain.PageCurrent.Additional(3) End Sub Private Project As CompProject - Private TargetVersion As String, TargetLoader As CompModLoaderType + Private TargetVersion As String, TargetLoader As CompLoaderType '自动重试 Private Sub Load_State(sender As Object, state As MyLoading.MyLoadingState, oldState As MyLoading.MyLoadingState) Handles Load.StateChanged Select Case CompFileLoader.State @@ -119,12 +119,12 @@ UpdateFilterResult() End Sub Private Sub UpdateFilterResult() - Dim TargetCardName As String = If(TargetVersion <> "" OrElse TargetLoader <> CompModLoaderType.Any, - $"所选版本:{If(TargetLoader <> CompModLoaderType.Any, TargetLoader.ToString & " ", "")}{TargetVersion}", "") + Dim TargetCardName As String = If(TargetVersion <> "" OrElse TargetLoader <> CompLoaderType.Any, + $"所选版本:{If(TargetLoader <> CompLoaderType.Any, TargetLoader.ToString & " ", "")}{TargetVersion}", "") '归类到卡片下 Dim Dict As New SortedDictionary(Of String, List(Of CompFile))(New CardSorter(TargetCardName)) Dict.Add("其他版本", New List(Of CompFile)) - Dim SupportedLoaders As New List(Of Integer)([Enum].GetValues(GetType(CompModLoaderType))) + Dim SupportedLoaders As New List(Of Integer)([Enum].GetValues(GetType(CompLoaderType))) For Each Version As CompFile In CompFileLoader.Output For Each GameVersion In Version.GameVersions '检查是否符合版本筛选器 @@ -138,7 +138,7 @@ Project.Type = CompType.Mod AndAlso '是 Mod Ver.StartsWith("1.") Then '不是 “快照版本” 之类的 For Each Loader In Version.ModLoaders - If Loader = CompModLoaderType.Quilt AndAlso Setup.Get("ToolDownloadIgnoreQuilt") Then Continue For + If Loader = CompLoaderType.Quilt AndAlso Setup.Get("ToolDownloadIgnoreQuilt") Then Continue For If SupportedLoaders.Contains(Loader) Then Loaders.Add(Loader.ToString & " ") Next End If @@ -156,7 +156,7 @@ Dict.Add(TargetCardName, New List(Of CompFile)) For Each Version As CompFile In CompFileLoader.Output If Version.GameVersions.Contains(TargetVersion) AndAlso - (TargetLoader = CompModLoaderType.Any OrElse Version.ModLoaders.Contains(TargetLoader)) Then + (TargetLoader = CompLoaderType.Any OrElse Version.ModLoaders.Contains(TargetLoader)) Then '检查是否符合版本筛选器 If VersionFilter IsNot Nothing AndAlso Not Version.GameVersions.Any(Function(v) GetGroupedVersionName(v, IsMajorVersionFilter, True) = VersionFilter) Then Continue For @@ -322,11 +322,11 @@ '获取 Mod 所需的加载器种类 Dim AllowForge As Boolean? = Nothing, AllowFabric As Boolean? = Nothing If File.ModLoaders.Any Then '从文件中获取 - AllowForge = File.ModLoaders.Contains(CompModLoaderType.Forge) OrElse File.ModLoaders.Contains(CompModLoaderType.NeoForge) - AllowFabric = File.ModLoaders.Contains(CompModLoaderType.Fabric) + AllowForge = File.ModLoaders.Contains(CompLoaderType.Forge) OrElse File.ModLoaders.Contains(CompLoaderType.NeoForge) + AllowFabric = File.ModLoaders.Contains(CompLoaderType.Fabric) ElseIf Project.ModLoaders.Any Then '从工程中获取 - AllowForge = Project.ModLoaders.Contains(CompModLoaderType.Forge) OrElse File.ModLoaders.Contains(CompModLoaderType.NeoForge) - AllowFabric = Project.ModLoaders.Contains(CompModLoaderType.Fabric) + AllowForge = Project.ModLoaders.Contains(CompLoaderType.Forge) OrElse File.ModLoaders.Contains(CompLoaderType.NeoForge) + AllowFabric = Project.ModLoaders.Contains(CompLoaderType.Fabric) End If If AllowForge IsNot Nothing AndAlso Not AllowForge AndAlso AllowFabric IsNot Nothing AndAlso Not AllowFabric Then diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompFavorites.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompFavorites.xaml.vb index 4a053a07e..56e8d3f9b 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompFavorites.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompFavorites.xaml.vb @@ -213,7 +213,7 @@ If TypeOf (CompItem.Tag) Is CompProject Then AddHandler CompItem.MouseRightButtonUp, Sub(sender As Object, e As EventArgs) FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail, - .Additional = {CompItem.Tag, New List(Of String), String.Empty, CompModLoaderType.Any}}) + .Additional = {CompItem.Tag, New List(Of String), String.Empty, CompLoaderType.Any}}) End Sub End If '---其它事件--- @@ -332,7 +332,7 @@ Exit Sub End If If 1 <> MyMsgBox($"批量下载功能仍旧处于测试状态{vbCrLf}使用此功能下载模组不会自动下载前置项。{vbCrLf}请在下载前仔细思考自己的需求,并仔细检查自己的选择,避免下载错误导致时间和网络流量的浪费。", "确定使用此功能?", Button1:="继续", Button2:="算了", IsWarn:=True) Then Exit Sub - Dim SupportedModLoader As New List(Of CompModLoaderType) + Dim SupportedModLoader As New List(Of CompLoaderType) Dim LoaderFirstSet As Boolean = True Dim HasMod As Boolean = False For Each Item In SelectedItemList ' 获取共同支持的 ModLoader @@ -353,7 +353,7 @@ Exit Sub End If ' 要求选择版本 - Dim DesiredModLoader As CompModLoaderType = CompModLoaderType.Any + Dim DesiredModLoader As CompLoaderType = CompLoaderType.Any If HasMod AndAlso SupportedModLoader.Count > 0 Then If SupportedModLoader.Count > 0 Then Dim MSelection As New List(Of IMyRadio) diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb index e9d839702..4ac5a698e 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb @@ -45,12 +45,12 @@ Private Shared Function LoaderInput() As CompProjectRequest Dim Request As New CompProjectRequest(CompType.Mod, Storage, (Page + 1) * PageSize) If FrmDownloadMod IsNot Nothing Then - Dim ModLoader As CompModLoaderType = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag) + Dim ModLoader As CompLoaderType = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag) Dim GameVersion As String = If(FrmDownloadMod.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing, If(FrmDownloadMod.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadMod.TextSearchVersion.Text.Contains("w"), FrmDownloadMod.TextSearchVersion.Text, Nothing)) If GameVersion IsNot Nothing AndAlso GameVersion.Contains(".") AndAlso Val(GameVersion.Split(".")(1)) < 14 AndAlso '1.14- - ModLoader = CompModLoaderType.Forge Then '选择了 Forge - ModLoader = CompModLoaderType.Any '此时,视作没有筛选 Mod Loader(因为部分老 Mod 没有设置自己支持的加载器) + ModLoader = CompLoaderType.Forge Then '选择了 Forge + ModLoader = CompLoaderType.Any '此时,视作没有筛选 Mod Loader(因为部分老 Mod 没有设置自己支持的加载器) End If With Request .SearchText = FrmDownloadMod.TextSearchName.Text @@ -70,7 +70,7 @@ '列表项 PanProjects.Children.Clear() For i = Math.Min(Page * PageSize, Storage.Results.Count - 1) To Math.Min((Page + 1) * PageSize - 1, Storage.Results.Count - 1) - PanProjects.Children.Add(Storage.Results(i).ToCompItem(Loader.Input.GameVersion Is Nothing, Loader.Input.ModLoader = CompModLoaderType.Any)) + PanProjects.Children.Add(Storage.Results(i).ToCompItem(Loader.Input.GameVersion Is Nothing, Loader.Input.ModLoader = CompLoaderType.Any)) Next '页码 CardPages.Visibility = If(Storage.Results.Count > 40 OrElse diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionCompResource.xaml similarity index 91% rename from Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml rename to Plain Craft Launcher 2/Pages/PageVersion/PageVersionCompResource.xaml index ee62cf1cf..2ed72e9dc 100644 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml +++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionCompResource.xaml @@ -2,13 +2,13 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:PCL" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - mc:Ignorable="d" x:Class="PageVersionMod" + mc:Ignorable="d" x:Class="PageVersionCompResource" PanScroll="{Binding ElementName=PanBack}"> - + @@ -20,7 +20,7 @@ - + @@ -42,24 +42,24 @@ - + - + - - - + + + - + diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionCompResource.xaml.vb similarity index 75% rename from Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb rename to Plain Craft Launcher 2/Pages/PageVersion/PageVersionCompResource.xaml.vb index 73ada4231..1078e2b88 100644 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionCompResource.xaml.vb @@ -1,15 +1,47 @@ -Public Class PageVersionMod +Public Class PageVersionCompResource Implements IRefreshable - #Region "初始化" + Private CurrentCompType As CompType = CompType.Mod + + Private CurrentLoader As CompLocalLoader + + Private CurrentSwipSelect As MyLocalCompItem.SwipeSelect + + Public Sub New(LoadCompType As CompType) + CurrentCompType = LoadCompType + Dim RequireLoaders As List(Of CompLoaderType) + Select Case CurrentCompType + Case CompType.Mod + RequireLoaders = GetCurrentVersionModLoader() + Case CompType.ResourcePack + RequireLoaders = {CompLoaderType.Minecraft}.ToList() + Case CompType.Shader + RequireLoaders = {CompLoaderType.OptiFine, CompLoaderType.Iris, CompLoaderType.Vanilla, CompLoaderType.Canvas}.ToList() + End Select + CurrentLoader = New CompLocalLoader(Me, PageVersionLeft.Version.Version.McName, RequireLoaders) + + CurrentSwipSelect = New MyLocalCompItem.SwipeSelect() With {.TargetFrm = Me} + + ' 此调用是设计器所必需的。 + InitializeComponent() + + ' 在 InitializeComponent() 调用之后添加任何初始化。 + + If {CompType.Shader, CompType.ResourcePack}.Contains(CurrentCompType) Then + BtnSelectEnable.Visibility = Visibility.Collapsed + BtnSelectDisable.Visibility = Visibility.Collapsed + End If + + End Sub + Private IsLoad As Boolean = False Public Sub PageOther_Loaded() Handles Me.Loaded If FrmMain.PageLast.Page <> FormMain.PageType.CompDetail Then PanBack.ScrollToHome() AniControlEnabled += 1 SelectedMods.Clear() - ReloadModList() + ReloadCompFileList() ChangeAllSelected(False) AniControlEnabled -= 1 @@ -30,9 +62,9 @@ ''' ''' 刷新 Mod 列表。 ''' - Public Sub ReloadModList(Optional ForceReload As Boolean = False) + Public Sub ReloadCompFileList(Optional ForceReload As Boolean = False) If LoaderRun(If(ForceReload, LoaderFolderRunType.ForceRun, LoaderFolderRunType.RunOnUpdated)) Then - Log("[System] 已刷新 Mod 列表") + Log($"[System] 已刷新 {CurrentCompType} 列表") Filter = FilterType.All PanBack.ScrollToHome() SearchBox.Text = "" @@ -40,33 +72,43 @@ End Sub '强制刷新 Private Sub RefreshSelf() Implements IRefreshable.Refresh - Refresh() + Refresh(CurrentCompType) End Sub - Public Shared Sub Refresh() + Public Shared Sub Refresh(WhichPage As CompType) '强制刷新 Try CompProjectCache.Clear() CompFilesCache.Clear() - File.Delete(PathTemp & "Cache\LocalMod.json") - Log("[Mod] 由于点击刷新按钮,清理本地 Mod 信息缓存") + File.Delete(PathTemp & "Cache\LocalComp.json") + Log("[CompResource] 由于点击刷新按钮,清理本地工程信息缓存") Catch ex As Exception - Log(ex, "强制刷新时清理本地 Mod 信息缓存失败") + Log(ex, "强制刷新时清理本地工程信息缓存失败") End Try - If FrmVersionMod IsNot Nothing Then FrmVersionMod.ReloadModList(True) '无需 Else,还没加载刷个鬼的新 - FrmVersionLeft.ItemMod.Checked = True + Select Case WhichPage + Case CompType.Mod + If FrmVersionMod IsNot Nothing Then FrmVersionMod.ReloadCompFileList(True) '无需 Else,还没加载刷个鬼的新 + FrmVersionLeft.ItemMod.Checked = True + Case CompType.ResourcePack + If FrmVersionResourcePack IsNot Nothing Then FrmVersionResourcePack.ReloadCompFileList(True) + FrmVersionLeft.ItemResourcePack.Checked = True + Case CompType.Shader + If FrmVersionShader IsNot Nothing Then FrmVersionShader.ReloadCompFileList(True) + FrmVersionLeft.ItemShader.Checked = True + End Select Hint("正在刷新……", Log:=False) End Sub Private Sub LoaderInit() Handles Me.Initialized - PageLoaderInit(Load, PanLoad, PanAllBack, Nothing, McModLoader, AddressOf LoadUIFromLoaderOutput, AutoRun:=False) + PageLoaderInit(Load, PanLoad, PanAllBack, Nothing, CurrentLoader.CompResourceListLoader, AddressOf LoadUIFromLoaderOutput, Function() CurrentCompType, AutoRun:=False) End Sub Private Sub Load_Click(sender As Object, e As MouseButtonEventArgs) Handles Load.Click - If McModLoader.State = LoadState.Failed Then + If CurrentLoader.CompResourceListLoader.State = LoadState.Failed Then LoaderRun(LoaderFolderRunType.ForceRun) End If End Sub Public Function LoaderRun(Type As LoaderFolderRunType) As Boolean - Return LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", Type) + Dim CompResourcePath As String = PageVersionLeft.Version.PathIndie & GetPathNameByCompType(CurrentCompType) & "\" + Return LoaderFolderRun(CurrentLoader.CompResourceListLoader, CompResourcePath, Type) End Function #End Region @@ -76,14 +118,14 @@ ''' ''' 已加载的 Mod UI 缓存,不确保按显示顺序排列。Key 为 Mod 的 RawFileName。 ''' - Public ModItems As New Dictionary(Of String, MyLocalModItem) + Public ModItems As New Dictionary(Of String, MyLocalCompItem) ''' ''' 将加载器结果的 Mod 列表加载为 UI。 ''' Private Sub LoadUIFromLoaderOutput() Try '判断应该显示哪一个页面 - If McModLoader.Output.Any() Then + If CurrentLoader.CompResourceListLoader.Output.Any() Then PanBack.Visibility = Visibility.Visible PanEmpty.Visibility = Visibility.Collapsed Else @@ -93,8 +135,8 @@ End If '修改缓存 ModItems.Clear() - For Each ModEntity As McMod In McModLoader.Output - ModItems(ModEntity.RawFileName) = McModListItem(ModEntity) + For Each ModEntity As LocalCompFile In CurrentLoader.CompResourceListLoader.Output + ModItems(ModEntity.RawFileName) = BuildLocalCompItem(ModEntity) Next '显示结果 Filter = FilterType.All @@ -102,23 +144,24 @@ RefreshUI() SetSortMethod(SortMethod.ModName) Catch ex As Exception - Log(ex, "加载 Mod 列表 UI 失败", LogLevel.Feedback) + Log(ex, $"加载 {CurrentCompType} 列表 UI 失败", LogLevel.Feedback) End Try End Sub - Private Function McModListItem(Entry As McMod) As MyLocalModItem + Private Function BuildLocalCompItem(Entry As LocalCompFile) As MyLocalCompItem AniControlEnabled += 1 - Dim NewItem As New MyLocalModItem With {.SnapsToDevicePixels = True, .Entry = Entry, - .ButtonHandler = AddressOf McModContent, .Checked = SelectedMods.Contains(Entry.RawFileName)} + Dim NewItem As New MyLocalCompItem With {.SnapsToDevicePixels = True, .Entry = Entry, + .ButtonHandler = AddressOf BuildLocalCompItemBtnHandler, .Checked = SelectedMods.Contains(Entry.RawFileName)} + NewItem.CurrentSwipe = CurrentSwipSelect AddHandler Entry.OnCompUpdate, AddressOf NewItem.Refresh 'AddHandler Entry.OnCompUpdate, Sub() RunInUi(Sub() DoSort()) NewItem.Refresh() AniControlEnabled -= 1 Return NewItem End Function - Private Sub McModContent(sender As MyLocalModItem, e As EventArgs) + Private Sub BuildLocalCompItemBtnHandler(sender As MyLocalCompItem, e As EventArgs) '点击事件 AddHandler sender.Changed, AddressOf CheckChanged - AddHandler sender.Click, Sub(ss As MyLocalModItem, ee As EventArgs) ss.Checked = Not ss.Checked + AddHandler sender.Click, Sub(ss As MyLocalCompItem, ee As EventArgs) ss.Checked = Not ss.Checked '图标按钮 Dim BtnOpen As New MyIconButton With {.LogoScale = 1.05, .Logo = Logo.IconButtonOpen, .Tag = sender} BtnOpen.ToolTip = "打开文件位置" @@ -139,15 +182,15 @@ ToolTipService.SetVerticalOffset(BtnDelete, 30) ToolTipService.SetHorizontalOffset(BtnDelete, 2) AddHandler BtnDelete.Click, AddressOf Delete_Click - Dim BtnED As New MyIconButton With {.LogoScale = 1, .Logo = If(sender.Entry.State = McMod.McModState.Fine, Logo.IconButtonStop, Logo.IconButtonCheck), .Tag = sender} - BtnED.ToolTip = If(sender.Entry.State = McMod.McModState.Fine, "禁用", "启用") - ToolTipService.SetPlacement(BtnED, Primitives.PlacementMode.Center) - ToolTipService.SetVerticalOffset(BtnED, 30) - ToolTipService.SetHorizontalOffset(BtnED, 2) - AddHandler BtnED.Click, AddressOf ED_Click - If sender.Entry.State = McMod.McModState.Unavailable Then + If CurrentCompType <> CompType.Mod OrElse sender.Entry.State = LocalCompFile.LocalFileStatus.Unavailable Then sender.Buttons = {BtnCont, BtnOpen, BtnDelete} Else + Dim BtnED As New MyIconButton With {.LogoScale = 1, .Logo = If(sender.Entry.State = LocalCompFile.LocalFileStatus.Fine, Logo.IconButtonStop, Logo.IconButtonCheck), .Tag = sender} + BtnED.ToolTip = If(sender.Entry.State = LocalCompFile.LocalFileStatus.Fine, "禁用", "启用") + ToolTipService.SetPlacement(BtnED, Primitives.PlacementMode.Center) + ToolTipService.SetVerticalOffset(BtnED, 30) + ToolTipService.SetHorizontalOffset(BtnED, 2) + AddHandler BtnED.Click, AddressOf ED_Click sender.Buttons = {BtnCont, BtnOpen, BtnED, BtnDelete} End If End Sub @@ -157,14 +200,14 @@ ''' Public Sub RefreshUI() If PanList Is Nothing Then Exit Sub - Dim ShowingMods = If(IsSearching, SearchResult, If(McModLoader.Output, New List(Of McMod))).Where(Function(m) CanPassFilter(m)).ToList + Dim ShowingMods = If(IsSearching, SearchResult, If(CurrentLoader.CompResourceListLoader.Output, New List(Of LocalCompFile))).Where(Function(m) CanPassFilter(m)).ToList '重新列出列表 AniControlEnabled += 1 If ShowingMods.Any() Then PanList.Visibility = Visibility.Visible PanList.Children.Clear() For Each TargetMod In ShowingMods - Dim Item As MyLocalModItem = ModItems(TargetMod.RawFileName) + Dim Item As MyLocalCompItem = ModItems(TargetMod.RawFileName) Item.Checked = SelectedMods.Contains(TargetMod.RawFileName) '更新选中状态 PanList.Children.Add(Item) Next @@ -190,12 +233,12 @@ Dim DisabledCount As Integer = 0 Dim UpdateCount As Integer = 0 Dim UnavalialeCount As Integer = 0 - For Each ModItem In If(IsSearching, SearchResult, If(McModLoader.Output, New List(Of McMod))) + For Each ModItem In If(IsSearching, SearchResult, If(CurrentLoader.CompResourceListLoader.Output, New List(Of LocalCompFile))) AnyCount += 1 If ModItem.CanUpdate Then UpdateCount += 1 - If ModItem.State.Equals(McMod.McModState.Fine) Then EnabledCount += 1 - If ModItem.State.Equals(McMod.McModState.Disabled) Then DisabledCount += 1 - If ModItem.State.Equals(McMod.McModState.Unavailable) Then UnavalialeCount += 1 + If ModItem.State.Equals(LocalCompFile.LocalFileStatus.Fine) Then EnabledCount += 1 + If ModItem.State.Equals(LocalCompFile.LocalFileStatus.Disabled) Then DisabledCount += 1 + If ModItem.State.Equals(LocalCompFile.LocalFileStatus.Unavailable) Then UnavalialeCount += 1 Next '显示 BtnFilterAll.Text = If(IsSearching, "搜索结果", "全部") & $" ({AnyCount})" @@ -221,12 +264,12 @@ Dim HasUpdate As Boolean = False Dim HasEnabled As Boolean = False Dim HasDisabled As Boolean = False - For Each ModEntity In McModLoader.Output + For Each ModEntity In CurrentLoader.CompResourceListLoader.Output If SelectedMods.Contains(ModEntity.RawFileName) Then If ModEntity.CanUpdate Then HasUpdate = True - If ModEntity.State = McMod.McModState.Fine Then + If ModEntity.State = LocalCompFile.LocalFileStatus.Fine Then HasEnabled = True - ElseIf ModEntity.State = McMod.McModState.Disabled Then + ElseIf ModEntity.State = LocalCompFile.LocalFileStatus.Disabled Then HasDisabled = True End If End If @@ -290,8 +333,9 @@ ''' Private Sub BtnManageOpen_Click(sender As Object, e As EventArgs) Handles BtnManageOpen.Click, BtnHintOpen.Click Try - Directory.CreateDirectory(PageVersionLeft.Version.PathIndie & "mods\") - OpenExplorer("""" & PageVersionLeft.Version.PathIndie & "mods\""") + Dim CompFilePath = PageVersionLeft.Version.PathIndie & GetPathNameByCompType(CurrentCompType) & "\" + Directory.CreateDirectory(CompFilePath) + OpenExplorer("""" & CompFilePath & """") Catch ex As Exception Log(ex, "打开 Mods 文件夹失败", LogLevel.Msgbox) End Try @@ -303,7 +347,7 @@ ''' Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click Try - Dim Result = McModCheck(PageVersionLeft.Version, McModLoader.Output) + Dim Result = McModCheck(PageVersionLeft.Version, CompModLoader.Output) If Result.Any Then MyMsgBox(Join(Result, vbCrLf & vbCrLf), "Mod 检查结果") Else @@ -326,8 +370,13 @@ ''' 安装 Mod。 ''' Private Sub BtnManageInstall_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageInstall.Click, BtnHintInstall.Click - Dim FileList = SelectFiles("Mod 文件(*.jar;*.litemod;*.disabled;*.old)|*.jar;*.litemod;*.disabled;*.old", "选择要安装的 Mod") - If Not FileList.Any Then Return + Dim FileList As String() = Nothing + Select Case CurrentCompType + Case CompType.Mod : FileList = SelectFiles("Mod 文件(*.jar;*.litemod;*.disabled;*.old)|*.jar;*.litemod;*.disabled;*.old", "选择要安装的 Mod") + Case CompType.ResourcePack : FileList = SelectFiles("资源包文件(*.zip)|*.zip", "选择要安装的资源包") + Case CompType.Shader : FileList = SelectFiles("光影包文件(*.zip)|*.zip", "选择要安装的光影包") + End Select + If FileList Is Nothing OrElse Not FileList.Any Then Exit Sub InstallMods(FileList) End Sub ''' @@ -369,7 +418,7 @@ Install: End If '刷新列表 If FrmMain.PageCurrent = FormMain.PageType.VersionSetup AndAlso FrmMain.PageCurrentSub = FormMain.PageSubType.VersionMod Then - LoaderFolderRun(McModLoader, TargetVersion.PathIndie & "mods\", LoaderFolderRunType.ForceRun) + LoaderFolderRun(FrmVersionMod?.CurrentLoader.CompResourceListLoader, TargetVersion.PathIndie & "mods\", LoaderFolderRunType.ForceRun) End If Catch ex As Exception Log(ex, "复制 Mod 文件失败", LogLevel.Msgbox) @@ -383,7 +432,11 @@ Install: ''' Private Sub BtnManageDownload_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageDownload.Click, BtnHintDownload.Click PageDownloadMod.TargetVersion = PageVersionLeft.Version '将当前版本设置为筛选器 - FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadMod) + Select Case CurrentCompType + Case CompType.Mod : FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadMod) + Case CompType.ResourcePack : FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadResourcePack) + Case CompType.Shader : FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadShader) + End Select End Sub #End Region @@ -394,7 +447,7 @@ Install: Public SelectedMods As New List(Of String) '单项切换选择状态 - Public Sub CheckChanged(sender As MyLocalModItem, e As RouteEventArgs) + Public Sub CheckChanged(sender As MyLocalCompItem, e As RouteEventArgs) If AniControlEnabled <> 0 Then Return '更新选择了的内容 Dim SelectedKey As String = sender.Entry.RawFileName @@ -410,7 +463,7 @@ Install: Private Sub ChangeAllSelected(Value As Boolean) AniControlEnabled += 1 SelectedMods.Clear() - For Each Item As MyLocalModItem In ModItems.Values + For Each Item As MyLocalCompItem In ModItems.Values '#4992,Mod 从过滤器看可能不应在列表中,但因为刚切换状态所以依然保留在列表中,所以应该从列表 UI 判断,而非从过滤器判断 Dim ShouldSelected As Boolean = Value AndAlso PanList.Children.Contains(Item) Item.Checked = ShouldSelected @@ -467,18 +520,18 @@ Install: ''' ''' 检查该 Mod 项是否符合当前筛选的类别。 ''' - Private Function CanPassFilter(CheckingMod As McMod) As Boolean + Private Function CanPassFilter(CheckingMod As LocalCompFile) As Boolean Select Case Filter Case FilterType.All Return True Case FilterType.Enabled - Return CheckingMod.State = McMod.McModState.Fine + Return CheckingMod.State = LocalCompFile.LocalFileStatus.Fine Case FilterType.Disabled - Return CheckingMod.State = McMod.McModState.Disabled + Return CheckingMod.State = LocalCompFile.LocalFileStatus.Disabled Case FilterType.CanUpdate Return CheckingMod.CanUpdate Case FilterType.Unavailable - Return CheckingMod.State = McMod.McModState.Unavailable + Return CheckingMod.State = LocalCompFile.LocalFileStatus.Unavailable Case Else Return False End Select @@ -514,11 +567,11 @@ Install: Private Function GetSortName(Method As SortMethod) As String Select Case Method Case SortMethod.FileName : Return "文件名" - Case SortMethod.ModName : Return "模组名称" + Case SortMethod.ModName : Return "资源名称" Case SortMethod.TagNums : Return "标签数量" Case SortMethod.CreateTime : Return "加入时间" - Case SortMethod.ModFileSize : Return "模组文件大小" - Case Else : Return "模组名称" + Case SortMethod.ModFileSize : Return "文件大小" + Case Else : Return "资源名称" End Select Return "" End Function @@ -544,7 +597,7 @@ Install: If PanList Is Nothing OrElse PanList.Children.Count < 2 Then Exit Sub ' 将子元素转换为可排序的列表 - Dim items = PanList.Children.OfType(Of MyLocalModItem)().ToList() + Dim items = PanList.Children.OfType(Of MyLocalCompItem)().ToList() Dim Method = GetSortMethod(CurrentSortMethod) ' 根据排序类型处理特殊逻辑 @@ -569,30 +622,30 @@ Install: End SyncLock End Sub - Private Function GetSortMethod(Method As SortMethod) As Func(Of McMod, McMod, Integer) + Private Function GetSortMethod(Method As SortMethod) As Func(Of LocalCompFile, LocalCompFile, Integer) Select Case Method Case SortMethod.FileName - Return Function(a As McMod, b As McMod) As Integer + Return Function(a As LocalCompFile, b As LocalCompFile) As Integer Return -StrComp(a.FileName, b.FileName) End Function Case SortMethod.ModName - Return Function(a As McMod, b As McMod) As Integer + Return Function(a As LocalCompFile, b As LocalCompFile) As Integer Return -StrComp(a.Name, b.Name) End Function Case SortMethod.TagNums - Return Function(a As McMod, b As McMod) As Integer + Return Function(a As LocalCompFile, b As LocalCompFile) As Integer Return a.Comp.Tags.Count - b.Comp.Tags.Count End Function Case SortMethod.CreateTime - Return Function(a As McMod, b As McMod) As Integer + Return Function(a As LocalCompFile, b As LocalCompFile) As Integer Return If((New FileInfo(a.Path)).CreationTime > (New FileInfo(b.Path)).CreationTime, 1, -1) End Function Case SortMethod.ModFileSize - Return Function(a As McMod, b As McMod) As Integer + Return Function(a As LocalCompFile, b As LocalCompFile) As Integer Return (New FileInfo(a.Path)).Length - (New FileInfo(b.Path)).Length End Function Case Else - Return Function(a As McMod, b As McMod) As Integer + Return Function(a As LocalCompFile, b As LocalCompFile) As Integer Return -StrComp(a.Name, b.Name) End Function End Select @@ -603,19 +656,19 @@ Install: '启用 / 禁用 Private Sub BtnSelectED_Click(sender As MyIconTextButton, e As RouteEventArgs) Handles BtnSelectEnable.Click, BtnSelectDisable.Click - EDMods(McModLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName)), + EDMods(CurrentLoader.CompResourceListLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName)), Not sender.Equals(BtnSelectDisable)) ChangeAllSelected(False) End Sub - Private Sub EDMods(ModList As IEnumerable(Of McMod), IsEnable As Boolean) + Private Sub EDMods(ModList As IEnumerable(Of LocalCompFile), IsEnable As Boolean) Dim IsSuccessful As Boolean = True For Each ModE In ModList.ToList Dim ModEntity = ModE '仅用于去除迭代变量无法修改的限制 Dim NewPath As String = Nothing - If ModEntity.State = McMod.McModState.Fine AndAlso Not IsEnable Then + If ModEntity.State = LocalCompFile.LocalFileStatus.Fine AndAlso Not IsEnable Then '禁用 NewPath = ModEntity.Path & If(File.Exists(ModEntity.Path & ".old"), ".old", ".disabled") - ElseIf ModEntity.State = McMod.McModState.Disabled AndAlso IsEnable Then + ElseIf ModEntity.State = LocalCompFile.LocalFileStatus.Disabled AndAlso IsEnable Then '启用 NewPath = ModEntity.RawPath Else @@ -640,19 +693,19 @@ Install: FileSystem.Rename(ModEntity.Path, NewPath) Catch ex As FileNotFoundException Log(ex, $"未找到需要重命名的 Mod({If(ModEntity.Path, "null")})", LogLevel.Feedback) - ReloadModList(True) + ReloadCompFileList(True) Return Catch ex As Exception Log(ex, $"重命名 Mod 失败({If(ModEntity.Path, "null")})") IsSuccessful = False End Try '更改 Loader 中的列表 - Dim NewModEntity As New McMod(NewPath) + Dim NewModEntity As New LocalCompFile(NewPath) NewModEntity.FromJson(ModEntity.ToJson) - If McModLoader.Output.Contains(ModEntity) Then - Dim IndexOfLoader As Integer = McModLoader.Output.IndexOf(ModEntity) - McModLoader.Output.RemoveAt(IndexOfLoader) - McModLoader.Output.Insert(IndexOfLoader, NewModEntity) + If CurrentLoader.CompResourceListLoader.Output.Contains(ModEntity) Then + Dim IndexOfLoader As Integer = CurrentLoader.CompResourceListLoader.Output.IndexOf(ModEntity) + CurrentLoader.CompResourceListLoader.Output.RemoveAt(IndexOfLoader) + CurrentLoader.CompResourceListLoader.Output.Insert(IndexOfLoader, NewModEntity) End If If SearchResult IsNot Nothing AndAlso SearchResult.Contains(ModEntity) Then '#4862 Dim IndexOfResult As Integer = SearchResult.IndexOf(ModEntity) @@ -660,9 +713,9 @@ Install: SearchResult.Insert(IndexOfResult, NewModEntity) End If '更改 UI 中的列表 - Dim NewItem As MyLocalModItem = McModListItem(NewModEntity) + Dim NewItem As MyLocalCompItem = BuildLocalCompItem(NewModEntity) ModItems(ModEntity.RawFileName) = NewItem - Dim IndexOfUi As Integer = PanList.Children.IndexOf(PanList.Children.OfType(Of MyLocalModItem).FirstOrDefault(Function(i) i.Entry Is ModEntity)) + Dim IndexOfUi As Integer = PanList.Children.IndexOf(PanList.Children.OfType(Of MyLocalCompItem).FirstOrDefault(Function(i) i.Entry Is ModEntity)) If IndexOfUi = -1 Then Continue For '因为未知原因 Mod 的状态已经切换完了 PanList.Children.RemoveAt(IndexOfUi) PanList.Children.Insert(IndexOfUi, NewItem) @@ -671,25 +724,25 @@ Install: RefreshBars() Else Hint("由于文件被占用,Mod 的状态切换失败,请尝试关闭正在运行的游戏后再试!", HintType.Critical) - ReloadModList(True) + ReloadCompFileList(True) End If LoaderRun(LoaderFolderRunType.UpdateOnly) End Sub '更新 Private Sub BtnSelectUpdate_Click() Handles BtnSelectUpdate.Click - Dim UpdateList As List(Of McMod) = McModLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName) AndAlso m.CanUpdate).ToList() + Dim UpdateList As List(Of LocalCompFile) = CurrentLoader.CompResourceListLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName) AndAlso m.CanUpdate).ToList() If Not UpdateList.Any() Then Return - UpdateMods(UpdateList) + UpdateResource(UpdateList) ChangeAllSelected(False) End Sub ''' ''' 记录正在进行 Mod 更新的 mods 文件夹路径。 ''' Public Shared UpdatingVersions As New List(Of String) - Public Sub UpdateMods(ModList As IEnumerable(Of McMod)) + Public Sub UpdateResource(ModList As IEnumerable(Of LocalCompFile)) '更新前警告 - If Not Setup.Get("HintUpdateMod") OrElse ModList.Count >= 15 Then + If CurrentCompType = CompType.Mod AndAlso ((Not Setup.Get("HintUpdateMod")) OrElse ModList.Count >= 15) Then If MyMsgBox($"新版本 Mod 可能不兼容旧存档或者其他 Mod,这可能导致游戏崩溃,甚至永久损坏存档!{vbCrLf}如果你在游玩整合包,请千万不要自行更新 Mod!{vbCrLf}{vbCrLf}在更新前,请先备份存档,并检查 Mod 的更新日志。{vbCrLf}如果更新后出现问题,你也可以在回收站找回更新前的 Mod。", "Mod 更新警告", "我已了解风险,继续更新", "取消", IsWarn:=True) = 1 Then Setup.Set("HintUpdateMod", True) Else @@ -701,7 +754,7 @@ Install: ModList = ModList.ToList() '防止刷新影响迭代器 Dim FileList As New List(Of NetFile) Dim FileCopyList As New Dictionary(Of String, String) - For Each Entry As McMod In ModList + For Each Entry As LocalCompFile In ModList Dim File As CompFile = Entry.UpdateFile If Not File.Available Then Continue For '确认更新后的文件名 @@ -721,7 +774,7 @@ Install: NewestReplaceName = Join(NewestSegs, "-") End If '添加到下载列表 - Dim TempAddress As String = PathTemp & "DownloadedMods\" & Entry.FileName.Replace(CurrentReplaceName, NewestReplaceName) + Dim TempAddress As String = PathTemp & "DownloadedComp\" & Entry.FileName.Replace(CurrentReplaceName, NewestReplaceName) Dim RealAddress As String = GetPathFromFullPath(Entry.Path) & Entry.FileName.Replace(CurrentReplaceName, NewestReplaceName) FileList.Add(File.ToNetFile(TempAddress)) FileCopyList(TempAddress) = RealAddress @@ -729,21 +782,21 @@ Install: '构造加载器 Dim InstallLoaders As New List(Of LoaderBase) Dim FinishedFileNames As New List(Of String) - InstallLoaders.Add(New LoaderDownload("下载新版 Mod 文件", FileList) With {.ProgressWeight = ModList.Count * 1.5}) '每个 Mod 需要 1.5s - InstallLoaders.Add(New LoaderTask(Of Integer, Integer)("替换旧版 Mod 文件", + InstallLoaders.Add(New LoaderDownload("下载新版资源文件", FileList) With {.ProgressWeight = ModList.Count * 1.5}) '每个 Mod 需要 1.5s + InstallLoaders.Add(New LoaderTask(Of Integer, Integer)("替换旧版资源文件", Sub() Try - For Each Entry As McMod In ModList + For Each Entry As LocalCompFile In ModList If File.Exists(Entry.Path) Then My.Computer.FileSystem.DeleteFile(Entry.Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin) Else - Log($"[Mod] 未找到更新前的 Mod 文件,跳过对它的删除:{Entry.Path}", LogLevel.Debug) + Log($"[CompUpdate] 未找到更新前的资源文件,跳过对它的删除:{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) - Log($"[Mod] 更新后的 Mod 文件已存在,将会把它放入回收站:{Entry.Value}", LogLevel.Debug) + Log($"[Mod] 更新后的资源文件已存在,将会把它放入回收站:{Entry.Value}", LogLevel.Debug) End If If Directory.Exists(GetPathFromFullPath(Entry.Value)) Then File.Move(Entry.Key, Entry.Value) @@ -753,12 +806,12 @@ Install: End If Next Catch ex As OperationCanceledException - Log(ex, "替换旧版 Mod 文件时被主动取消") + Log(ex, "替换旧版资源文件时被主动取消") End Try End Sub)) '结束处理 - Dim Loader As New LoaderCombo(Of IEnumerable(Of McMod))("Mod 更新:" & PageVersionLeft.Version.Name, InstallLoaders) - Dim PathMods As String = PageVersionLeft.Version.PathIndie & "mods\" + Dim Loader As New LoaderCombo(Of IEnumerable(Of LocalCompFile))("资源更新:" & PageVersionLeft.Version.Name, InstallLoaders) + Dim PathMods As String = PageVersionLeft.Version.PathIndie & GetPathNameByCompType(CurrentCompType) & "\" Loader.OnStateChanged = Sub() '结果提示 @@ -766,20 +819,20 @@ Install: Case LoadState.Finished Select Case FinishedFileNames.Count Case 0 '一般是由于 Mod 文件被占用,然后玩家主动取消 - Log($"[Mod] 没有 Mod 被成功更新") + Log($"[CompUpdate] 没有资源被成功更新") Case 1 Hint($"已成功更新 {FinishedFileNames.Single}!", HintType.Finish) Case Else - Hint($"已成功更新 {FinishedFileNames.Count} 个 Mod!", HintType.Finish) + Hint($"已成功更新 {FinishedFileNames.Count} 个资源!", HintType.Finish) End Select Case LoadState.Failed - Hint("Mod 更新失败:" & GetExceptionSummary(Loader.Error), HintType.Critical) + Hint("资源更新失败:" & GetExceptionSummary(Loader.Error), HintType.Critical) Case LoadState.Aborted - Hint("Mod 更新已中止!", HintType.Info) + Hint("资源更新已中止!", HintType.Info) Case Else Exit Sub End Select - Log($"[Mod] 已从正在进行 Mod 更新的文件夹列表移除:{PathMods}") + Log($"[CompUpdate] 已从正在进行资源更新的文件夹列表移除:{PathMods}") UpdatingVersions.Remove(PathMods) '清理缓存 RunInNewThread( @@ -789,41 +842,41 @@ Install: If File.Exists(TempFile) Then File.Delete(TempFile) Next Catch ex As Exception - Log(ex, "清理 Mod 更新缓存失败") + Log(ex, "清理资源更新缓存失败") End Try - End Sub, "Clean Mod Update Cache", ThreadPriority.BelowNormal) + End Sub, "Clean Comp Update Cache", ThreadPriority.BelowNormal) End Sub '启动加载器 - Log($"[Mod] 开始更新 {ModList.Count} 个 Mod:{PathMods}") + Log($"[CompUpdate] 开始更新 {ModList.Count} 个资源:{PathMods}") UpdatingVersions.Add(PathMods) Loader.Start() LoaderTaskbarAdd(Loader) FrmMain.BtnExtraDownload.ShowRefresh() FrmMain.BtnExtraDownload.Ribble() - ReloadModList(True) + ReloadCompFileList(True) Catch ex As Exception - Log(ex, "初始化 Mod 更新失败") + Log(ex, "初始化资源更新失败") End Try End Sub '删除 Private Sub BtnSelectDelete_Click() Handles BtnSelectDelete.Click - DeleteMods(McModLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName))) + DeleteMods(CurrentLoader.CompResourceListLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName))) ChangeAllSelected(False) End Sub - Private Sub DeleteMods(ModList As IEnumerable(Of McMod)) + Private Sub DeleteMods(ModList As IEnumerable(Of LocalCompFile)) Try Dim IsSuccessful As Boolean = True Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown '确认需要删除的文件 ModList = ModList.SelectMany( - Function(Target As McMod) - If Target.State = McMod.McModState.Fine Then + Function(Target As LocalCompFile) + If Target.State = LocalCompFile.LocalFileStatus.Fine Then Return {Target.Path, Target.Path & If(File.Exists(Target.Path & ".old"), ".old", ".disabled")} Else Return {Target.Path, Target.RawPath} End If - End Function).Distinct.Where(Function(m) File.Exists(m)).Select(Function(m) New McMod(m)).ToList() + End Function).Distinct.Where(Function(m) File.Exists(m)).Select(Function(m) New LocalCompFile(m)).ToList() '实际删除文件 For Each ModEntity In ModList '删除 @@ -835,7 +888,7 @@ Install: End If Catch ex As OperationCanceledException Log(ex, "删除 Mod 被主动取消") - ReloadModList(True) + ReloadCompFileList(True) Return Catch ex As Exception Log(ex, $"删除 Mod 失败({ModEntity.Path})", LogLevel.Msgbox) @@ -844,18 +897,18 @@ Install: '取消选中 SelectedMods.Remove(ModEntity.RawFileName) '更改 Loader 和 UI 中的列表 - McModLoader.Output.Remove(ModEntity) + CurrentLoader.CompResourceListLoader.Output.Remove(ModEntity) SearchResult?.Remove(ModEntity) ModItems.Remove(ModEntity.RawFileName) - Dim IndexOfUi As Integer = PanList.Children.IndexOf(PanList.Children.OfType(Of MyLocalModItem).FirstOrDefault(Function(i) i.Entry.Equals(ModEntity))) + Dim IndexOfUi As Integer = PanList.Children.IndexOf(PanList.Children.OfType(Of MyLocalCompItem).FirstOrDefault(Function(i) i.Entry.Equals(ModEntity))) If IndexOfUi >= 0 Then PanList.Children.RemoveAt(IndexOfUi) Next RefreshBars() If Not IsSuccessful Then Hint("由于文件被占用,Mod 删除失败,请尝试关闭正在运行的游戏后再试!", HintType.Critical) - ReloadModList(True) + ReloadCompFileList(True) ElseIf PanList.Children.Count = 0 Then - ReloadModList(True) '删除了全部文件 + ReloadCompFileList(True) '删除了全部文件 Else RefreshBars() End If @@ -876,10 +929,10 @@ Install: End If Catch ex As OperationCanceledException Log(ex, "删除 Mod 被主动取消") - ReloadModList(True) + ReloadCompFileList(True) Catch ex As Exception Log(ex, "删除 Mod 出现未知错误", LogLevel.Feedback) - ReloadModList(True) + ReloadCompFileList(True) End Try LoaderRun(LoaderFolderRunType.UpdateOnly) End Sub @@ -891,15 +944,15 @@ Install: #End Region -#Region "单个 Mod 项" +#Region "单个资源项" '详情 Public Sub Info_Click(sender As Object, e As EventArgs) Try - Dim ModEntry As McMod = CType(If(TypeOf sender Is MyIconButton, sender.Tag, sender), MyLocalModItem).Entry + Dim ModEntry As LocalCompFile = CType(If(TypeOf sender Is MyIconButton, sender.Tag, sender), MyLocalCompItem).Entry '加载失败信息 - If ModEntry.State = McMod.McModState.Unavailable Then + If ModEntry.State = LocalCompFile.LocalFileStatus.Unavailable Then MyMsgBox("无法读取此 Mod 的信息。" & vbCrLf & vbCrLf & "详细的错误信息:" & GetExceptionDetail(ModEntry.FileUnavailableReason), "Mod 读取失败") Return End If @@ -907,9 +960,9 @@ Install: '跳转到 Mod 下载页面 FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail, .Additional = {ModEntry.Comp, New List(Of String), PageVersionLeft.Version.Version.McName, - If(PageVersionLeft.Version.Version.HasForge, CompModLoaderType.Forge, - If(PageVersionLeft.Version.Version.HasNeoForge, CompModLoaderType.NeoForge, - If(PageVersionLeft.Version.Version.HasFabric, CompModLoaderType.Fabric, CompModLoaderType.Any)))}}) + If(PageVersionLeft.Version.Version.HasForge, CompLoaderType.Forge, + If(PageVersionLeft.Version.Version.HasNeoForge, CompLoaderType.NeoForge, + If(PageVersionLeft.Version.Version.HasFabric, CompLoaderType.Fabric, CompLoaderType.Any)))}}) Else '获取信息 Dim ContentLines As New List(Of String) @@ -966,7 +1019,7 @@ Install: Public Sub Open_Click(sender As MyIconButton, e As EventArgs) Try - Dim ListItem As MyLocalModItem = sender.Tag + Dim ListItem As MyLocalCompItem = sender.Tag OpenExplorer("/select,""" & ListItem.Entry.Path & """") Catch ex As Exception @@ -975,13 +1028,13 @@ Install: End Sub '删除 Public Sub Delete_Click(sender As MyIconButton, e As EventArgs) - Dim ListItem As MyLocalModItem = sender.Tag + Dim ListItem As MyLocalCompItem = sender.Tag DeleteMods({ListItem.Entry}) End Sub '启用 / 禁用 Public Sub ED_Click(sender As MyIconButton, e As EventArgs) - Dim ListItem As MyLocalModItem = sender.Tag - EDMods({ListItem.Entry}, ListItem.Entry.State = McMod.McModState.Disabled) + Dim ListItem As MyLocalCompItem = sender.Tag + EDMods({ListItem.Entry}, ListItem.Entry.State = LocalCompFile.LocalFileStatus.Disabled) End Sub #End Region @@ -993,12 +1046,13 @@ Install: Return Not String.IsNullOrWhiteSpace(SearchBox.Text) End Get End Property - Private SearchResult As List(Of McMod) + Private SearchResult As List(Of LocalCompFile) + Public Sub SearchRun() Handles SearchBox.TextChanged If IsSearching Then '构造请求 - Dim QueryList As New List(Of SearchEntry(Of McMod)) - For Each Entry As McMod In McModLoader.Output + Dim QueryList As New List(Of SearchEntry(Of LocalCompFile)) + For Each Entry As LocalCompFile In CurrentLoader.CompResourceListLoader.Output Dim SearchSource As New List(Of KeyValuePair(Of String, Double)) SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Name, 1)) SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.FileName, 1)) @@ -1014,7 +1068,7 @@ Install: If Entry.Comp.Description <> Entry.Description Then SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Comp.Description, 0.4)) SearchSource.Add(New KeyValuePair(Of String, Double)(String.Join("", Entry.Comp.Tags), 0.2)) End If - QueryList.Add(New SearchEntry(Of McMod) With {.Item = Entry, .SearchSource = SearchSource}) + QueryList.Add(New SearchEntry(Of LocalCompFile) With {.Item = Entry, .SearchSource = SearchSource}) Next '进行搜索 SearchResult = Search(QueryList, SearchBox.Text, MaxBlurCount:=6, MinBlurSimilarity:=0.35).Select(Function(r) r.Item).ToList diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionLeft.xaml.vb index fd33edb09..205926e9f 100644 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionLeft.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionLeft.xaml.vb @@ -38,7 +38,7 @@ Public Class PageVersionLeft If FrmVersionOverall Is Nothing Then FrmVersionOverall = New PageVersionOverall Return FrmVersionOverall Case FormMain.PageSubType.VersionMod - If FrmVersionMod Is Nothing Then FrmVersionMod = New PageVersionMod + If FrmVersionMod Is Nothing Then FrmVersionMod = New PageVersionCompResource(CompType.Mod) Return FrmVersionMod Case FormMain.PageSubType.VersionModDisabled If FrmVersionModDisabled Is Nothing Then FrmVersionModDisabled = New PageVersionModDisabled @@ -53,10 +53,10 @@ Public Class PageVersionLeft If FrmVersionScreenshot Is Nothing Then FrmVersionScreenshot = New PageVersionScreenshot Return FrmVersionScreenshot Case FormMain.PageSubType.VersionResourcePack - If FrmVersionResourcePack Is Nothing Then FrmVersionResourcePack = New PageVersionResourcePack + If FrmVersionResourcePack Is Nothing Then FrmVersionResourcePack = New PageVersionCompResource(CompType.ResourcePack) Return FrmVersionResourcePack Case FormMain.PageSubType.VersionShader - If FrmVersionShader Is Nothing Then FrmVersionShader = New PageVersionShader + If FrmVersionShader Is Nothing Then FrmVersionShader = New PageVersionCompResource(CompType.Shader) Return FrmVersionShader Case FormMain.PageSubType.VersionInstall If FrmVersionInstall Is Nothing Then FrmVersionInstall = New PageVersionInstall @@ -105,15 +105,15 @@ Public Class PageVersionLeft Public Sub Refresh(sender As Object, e As EventArgs) '由边栏按钮匿名调用 Select Case Val(sender.Tag) Case FormMain.PageSubType.VersionMod - PageVersionMod.Refresh() + PageVersionCompResource.Refresh(CompType.Mod) Case FormMain.PageSubType.VersionScreenshot PageVersionScreenshot.Refresh() Case FormMain.PageSubType.VersionWorld PageVersionWorld.Refresh() Case FormMain.PageSubType.VersionResourcePack - PageVersionResourcePack.Refresh() + PageVersionCompResource.Refresh(CompType.ResourcePack) Case FormMain.PageSubType.VersionShader - PageVersionShader.Refresh() + PageVersionCompResource.Refresh(CompType.Shader) Case FormMain.PageSubType.VersionInstall DlClientListLoader.Start(IsForceRestart:=True) DlOptiFineListLoader.Start(IsForceRestart:=True) diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionResourcePack.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionResourcePack.xaml deleted file mode 100644 index 08571ebec..000000000 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionResourcePack.xaml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionResourcePack.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionResourcePack.xaml.vb deleted file mode 100644 index 65a246424..000000000 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionResourcePack.xaml.vb +++ /dev/null @@ -1,215 +0,0 @@ -Imports System.IO.Compression -Imports System.Security.Principal - -Public Class PageVersionResourcePack - Implements IRefreshable - Private Sub RefreshSelf() Implements IRefreshable.Refresh - Refresh() - End Sub - Public Shared Sub Refresh() - If FrmVersionResourcePack IsNot Nothing Then FrmVersionResourcePack.Reload() - FrmVersionLeft.ItemResourcePack.Checked = True - Hint("正在刷新……", Log:=False) - End Sub - - Private IsLoad As Boolean = False - Private Sub PageSetupLaunch_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded - - '重复加载部分 - PanBack.ScrollToHome() - ResourcepacksPath = PageVersionLeft.Version.PathIndie + "resourcepacks\" - Directory.CreateDirectory(ResourcepacksPath) - Reload() - - '非重复加载部分 - If IsLoad Then Exit Sub - IsLoad = True - - End Sub - - ''' - ''' 文件和文件夹列表 - ''' - Dim FileList As List(Of String) = New List(Of String) - Dim ResourcepacksPath As String - - ''' - ''' 确保当前页面上的信息已正确显示。 - ''' - Public Sub Reload() - AniControlEnabled += 1 - PanBack.ScrollToHome() - LoadFileList() - AniControlEnabled -= 1 - End Sub - - Private Sub RefreshUI() - PanCard.Title = $"资源包列表 ({FileList.Count})" - If FileList.Count.Equals(0) Then - PanNoWorld.Visibility = Visibility.Visible - PanContent.Visibility = Visibility.Collapsed - PanNoWorld.UpdateLayout() - Else - PanNoWorld.Visibility = Visibility.Collapsed - PanContent.Visibility = Visibility.Visible - PanContent.UpdateLayout() - End If - End Sub - - Private Sub LoadFileList() - Try - Log("[Resourcepack] 刷新资源包文件") - FileList.Clear() - Dim fileRes = Directory.EnumerateFiles(ResourcepacksPath, "*.zip").ToList() - FileList.AddRange(fileRes) - Dim FolderRes = Directory.EnumerateDirectories(ResourcepacksPath).ToList() - FileList.AddRange(FolderRes) - If ModeDebug Then Log($"[Resourcepack] 共发现 {FileList.Count} 个资源包文件({fileRes.Count} 个文件,{FolderRes.Count} 个文件夹)", LogLevel.Debug) - PanList.Children.Clear() - Dim ResCachaPath = PageVersionLeft.Version.PathIndie & "PCL\Cache\resourcepacks\" - If Directory.Exists(ResCachaPath) Then Directory.Delete(ResCachaPath, True) - Directory.CreateDirectory(ResCachaPath) - For Each i In FileList - Dim ResTempIconFile = ResCachaPath & GetHash(i) & ".png" - Dim ResTempDescFile = ResCachaPath & GetHash(i) & ".json" - Dim ResDesc As String = "" - Dim isFile = File.Exists(i) - - '提取资源 - Try - Dim GetResourcepackDesc = - Function(Json As JObject) As String - If Json?("pack")?("description").Type = JTokenType.String Then - Return Json("pack")("description").ToString() - ElseIf Json?("pack")?("description")?("fallback") IsNot Nothing Then - Return Json("pack")("description")("fallback").ToString() - ElseIf Json?("pack")?("description")?("text") IsNot Nothing Then - Return Json("pack")("description")("text").ToString() - End If - Return Nothing - End Function - If isFile Then '文件类型的资源包 - Using Archive As New ZipArchive(New FileStream(i, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - Dim pack = Archive.GetEntry("pack.png") - Dim desc = Archive.GetEntry("pack.mcmeta") - If pack Is Nothing Then - ResTempIconFile = PathImage & "Icons/NoIcon.png" - Else - pack.ExtractToFile(ResTempIconFile) - End If - If desc IsNot Nothing Then - desc.ExtractToFile(ResTempDescFile) - ResDesc = GetResourcepackDesc(GetJson(File.ReadAllText(ResTempDescFile, Encoding.UTF8))) - End If - End Using - Else '文件夹型资源包 - ResTempIconFile = i + "\pack.png" - ResDesc = GetResourcepackDesc(GetJson(File.ReadAllText(i & "\pack.mcmeta", Encoding.UTF8))) - End If - Catch ex As Exception - Log(ex, "[Resourcepack] 提取资源包信息失败!") - ResTempIconFile = PathImage & "Icons/NoIcon.png" - ResDesc = $"引入时间:{ If(isFile, File.GetCreationTime(i), Directory.GetCreationTime(i)).ToString("yyyy'/'MM'/'dd")}" - End Try - - '防止错误 - If String.IsNullOrEmpty(ResDesc) Then ResDesc = $"引入时间:{ If(isFile, File.GetCreationTime(i), Directory.GetCreationTime(i)).ToString("yyyy'/'MM'/'dd")}" - If Not File.Exists(ResTempIconFile) Then ResTempIconFile = PathImage & "Icons/NoIcon.png" - - Dim worldItem As MyListItem = New MyListItem With { - .Title = If(isFile, GetFileNameWithoutExtentionFromPath(i), GetFolderNameFromPath(i)), - .Logo = ResTempIconFile, - .Info = ResDesc, - .Tag = i - } - Dim BtnOpen As MyIconButton = New MyIconButton With { - .Logo = Logo.IconButtonOpen, - .ToolTip = "打开", - .Tag = i - } - AddHandler BtnOpen.Click, AddressOf BtnOpen_Click - Dim BtnDelete As MyIconButton = New MyIconButton With { - .Logo = Logo.IconButtonDelete, - .ToolTip = "删除", - .Tag = i - } - AddHandler BtnDelete.Click, AddressOf BtnDelete_Click - Dim BtnCopy As MyIconButton = New MyIconButton With { - .Logo = Logo.IconButtonCopy, - .ToolTip = "复制", - .Tag = i - } - AddHandler BtnCopy.Click, AddressOf BtnCopy_Click - worldItem.Buttons = {BtnOpen, BtnDelete, BtnCopy} - PanList.Children.Add(worldItem) - Next - RefreshUI() - Catch ex As Exception - Log(ex, "[Resourcepack] 刷新资源包文件失败!", LogLevel.Msgbox) - End Try - End Sub - - Private Function GetPathFromSender(sender As Object) As String - Return sender.Tag - End Function - - Private Sub RemoveItem(Path As String) - Try - For Each i In PanList.Children - If CType(i, MyListItem).Tag.Equals(Path) Then - PanList.Children.Remove(CType(i, MyListItem)) - FileList.Remove(Path) - Exit For - End If - Next - Catch ex As Exception - Log(ex, "未能找到对应 UI") - End Try - RefreshUI() - End Sub - - Private Sub BtnDelete_Click(sender As Object, e As MouseButtonEventArgs) - Path = GetPathFromSender(sender) - RemoveItem(Path) - Try - If File.Exists(Path) Then - My.Computer.FileSystem.DeleteFile(Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin) - Else - My.Computer.FileSystem.DeleteDirectory(Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin) - End If - Hint("已将资源包移至回收站!") - Catch ex As Exception - Log(ex, "删除资源包失败!", LogLevel.Hint) - End Try - End Sub - Private Sub BtnCopy_Click(sender As Object, e As MouseButtonEventArgs) - Try - Dim Path As String = GetPathFromSender(sender) - If File.Exists(Path) Or Directory.Exists(Path) Then - Clipboard.SetFileDropList(New Specialized.StringCollection() From {Path}) - Hint("已复制资源包文件到剪贴板!") - Else - Hint("资源包不存在!") - End If - Catch ex As Exception - Log(ex, "复制失败……", LogLevel.Hint) - End Try - End Sub - - Private Sub BtnOpenFolder_Click(sender As Object, e As MouseButtonEventArgs) - If Not Directory.Exists(ResourcepacksPath) Then Directory.CreateDirectory(ResourcepacksPath) - OpenExplorer("""" & ResourcepacksPath & """") - End Sub - Private Sub BtnOpen_Click(sender As Object, e As MouseButtonEventArgs) - OpenExplorerAndSelect(sender.Tag) - End Sub - Private Sub BtnPaste_Click(sender As Object, e As MouseButtonEventArgs) - Dim count = PasteFileFromClipboard(ResourcepacksPath) - If count > 0 Then - Hint($"已成功粘贴 {count} 个资源包文件(夹)!") - RefreshUI() - Else - Hint("没有资源包文件(夹)可供粘贴!") - End If - End Sub -End Class diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionShader.xaml b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionShader.xaml deleted file mode 100644 index e323cc288..000000000 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionShader.xaml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionShader.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionShader.xaml.vb deleted file mode 100644 index 124f4d2e3..000000000 --- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionShader.xaml.vb +++ /dev/null @@ -1,178 +0,0 @@ -Imports System.Security.Principal - -Public Class PageVersionShader - Implements IRefreshable - Private Sub RefreshSelf() Implements IRefreshable.Refresh - Refresh() - End Sub - Public Shared Sub Refresh() - If FrmVersionShader IsNot Nothing Then FrmVersionShader.Reload() - FrmVersionLeft.ItemShader.Checked = True - Hint("正在刷新……", Log:=False) - End Sub - - Private IsLoad As Boolean = False - Private Sub PageSetupLaunch_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded - - '重复加载部分 - PanBack.ScrollToHome() - ShaderPath = PageVersionLeft.Version.PathIndie + "shaderpacks\" - If Not Directory.Exists(ShaderPath) Then Directory.CreateDirectory(ShaderPath) - Reload() - - '非重复加载部分 - If IsLoad Then Exit Sub - IsLoad = True - - End Sub - - Dim FileList As List(Of String) = New List(Of String) - Dim ShaderPath As String - - ''' - ''' 确保当前页面上的信息已正确显示。 - ''' - Public Sub Reload() - AniControlEnabled += 1 - PanBack.ScrollToHome() - LoadFileList() - AniControlEnabled -= 1 - End Sub - - Private Sub RefreshUI() - PanCard.Title = $"光影包列表 ({FileList.Count})" - If FileList.Count.Equals(0) Then - PanNoWorld.Visibility = Visibility.Visible - PanContent.Visibility = Visibility.Collapsed - PanNoWorld.UpdateLayout() - Else - PanNoWorld.Visibility = Visibility.Collapsed - PanContent.Visibility = Visibility.Visible - PanContent.UpdateLayout() - End If - End Sub - - Private Sub LoadFileList() - Try - Log("[Shader] 刷新光影包文件") - FileList.Clear() - - ' 获取所有 .zip 文件 - Dim zipFiles = Directory.EnumerateFiles(ShaderPath, "*.zip").ToList() - - ' 获取所有文件夹 - Dim folders = Directory.EnumerateDirectories(ShaderPath).ToList() - - ' 合并文件和文件夹列表 - FileList = zipFiles.Concat(folders).ToList() - - If ModeDebug Then Log("[Shader] 共发现 " & FileList.Count & " 个光影包文件", LogLevel.Debug) - - PanList.Children.Clear() - - For Each i In FileList - Dim worldItem As MyListItem = New MyListItem With { - .Title = If(Directory.Exists(i), GetFolderNameFromPath(i), GetFileNameFromPath(i)), - .Info = If(Directory.Exists(i), - $"类型:文件夹 | 创建时间:{Directory.GetCreationTime(i).ToString("yyyy'/'MM'/'dd")}", - $"类型:文件 | 引入时间:{File.GetCreationTime(i).ToString("yyyy'/'MM'/'dd")}"), - .Tag = i - } - - Dim BtnOpen As MyIconButton = New MyIconButton With { - .Logo = Logo.IconButtonOpen, - .ToolTip = "打开", - .Tag = i - } - AddHandler BtnOpen.Click, AddressOf BtnOpen_Click - - Dim BtnDelete As MyIconButton = New MyIconButton With { - .Logo = Logo.IconButtonDelete, - .ToolTip = "删除", - .Tag = i - } - AddHandler BtnDelete.Click, AddressOf BtnDelete_Click - - Dim BtnCopy As MyIconButton = New MyIconButton With { - .Logo = Logo.IconButtonCopy, - .ToolTip = "复制", - .Tag = i - } - AddHandler BtnCopy.Click, AddressOf BtnCopy_Click - - worldItem.Buttons = {BtnOpen, BtnDelete, BtnCopy} - PanList.Children.Add(worldItem) - Next - - RefreshUI() - Catch ex As Exception - Log(ex, "[Shader] 刷新光影包文件失败!", LogLevel.Msgbox) - End Try - End Sub - - Private Function GetPathFromSender(sender As Object) As String - Return sender.Tag - End Function - - Private Sub RemoveItem(Path As String) - Try - For Each i In PanList.Children - If CType(i, MyListItem).Tag.Equals(Path) Then - PanList.Children.Remove(CType(i, MyListItem)) - FileList.Remove(Path) - Exit For - End If - Next - Catch ex As Exception - Log(ex, "未能找到对应 UI") - End Try - RefreshUI() - End Sub - - Private Sub BtnDelete_Click(sender As Object, e As MouseButtonEventArgs) - Path = GetPathFromSender(sender) - RemoveItem(Path) - Try - If Directory.Exists(Path) Then - My.Computer.FileSystem.DeleteDirectory(Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin) - Else - My.Computer.FileSystem.DeleteFile(Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin) - End If - Hint("已将光影包移至回收站!") - Catch ex As Exception - Log(ex, "删除光影包失败!", LogLevel.Hint) - End Try - End Sub - Private Sub BtnCopy_Click(sender As Object, e As MouseButtonEventArgs) - Dim Path As String = GetPathFromSender(sender) - Try - If File.Exists(Path) OrElse Directory.Exists(Path) Then - Clipboard.SetFileDropList(New Specialized.StringCollection() From {Path}) - Hint("已复制光影包文件到剪贴板!") - Else - Hint("光影包不存在!") - End If - Catch ex As Exception - Log(ex, "复制失败……", LogLevel.Hint) - End Try - End Sub - - Private Sub BtnOpenFolder_Click(sender As Object, e As MouseButtonEventArgs) - If Not Directory.Exists(ShaderPath) Then Directory.CreateDirectory(ShaderPath) - OpenExplorer("""" & ShaderPath & """") - End Sub - - Private Sub BtnOpen_Click(sender As Object, e As MouseButtonEventArgs) - OpenExplorerAndSelect(sender.Tag) - End Sub - - Private Sub BtnPaste_Click(sender As Object, e As MouseButtonEventArgs) - Dim count = PasteFileFromClipboard(ShaderPath) - If count > 0 Then - Hint("已成功导入 " & count & " 个光影包文件(夹)!") - RefreshUI() - Else - Hint("没有光影包文件(夹)可供粘贴!") - End If - End Sub -End Class \ No newline at end of file diff --git a/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj b/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj index cd255f3f3..0f6803365 100644 --- a/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj +++ b/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj @@ -181,10 +181,10 @@ - + - - MyLocalModItem.xaml + + MyLocalCompItem.xaml @@ -302,18 +302,12 @@ PageVersionLeft.xaml - - PageVersionMod.xaml + + PageVersionCompResource.xaml PageVersionModDisabled.xaml - - PageVersionShader.xaml - - - PageVersionResourcePack.xaml - PageVersionWorld.xaml @@ -500,7 +494,7 @@ FormMain.xaml Code - + MSBuild:Compile Designer @@ -609,14 +603,6 @@ MSBuild:Compile Designer - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - MSBuild:Compile Designer @@ -733,7 +719,7 @@ Designer MSBuild:Compile - + Designer MSBuild:Compile