ModModpack.vb 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. Public Module ModModpack
  2. '触发整合包安装的外部接口
  3. ''' <summary>
  4. ''' 弹窗要求选择一个整合包文件并进行安装。
  5. ''' </summary>
  6. Public Sub ModpackInstall()
  7. Dim File As String = SelectFile("整合包文件(*.rar;*.zip;*.mrpack)|*.rar;*.zip;*.mrpack", "选择整合包压缩文件") '选择整合包文件
  8. If String.IsNullOrEmpty(File) Then Exit Sub
  9. RunInThread(Sub() ModpackInstall(File))
  10. End Sub
  11. ''' <summary>
  12. ''' 安装一个给定的整合包文件,返回是否安装成功。必须在工作线程执行。
  13. ''' </summary>
  14. Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional ShowHint As Boolean = True, Optional Logo As String = Nothing) As Boolean
  15. Log("[ModPack] 整合包安装请求:" & If(File, "null"))
  16. Dim Archive As Compression.ZipArchive = Nothing
  17. Dim ArchiveBaseFolder As String = ""
  18. Try
  19. '获取整合包种类与关键 Json
  20. Dim PackType As Integer = -1
  21. Try
  22. Archive = New Compression.ZipArchive(New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
  23. '从根目录判断整合包类型
  24. If Archive.GetEntry("mcbbs.packmeta") IsNot Nothing Then PackType = 3 : Exit Try 'MCBBS 整合包(优先于 manifest.json 判断)
  25. If Archive.GetEntry("modrinth.index.json") IsNot Nothing Then PackType = 4 : Exit Try 'Modrinth 整合包
  26. If Archive.GetEntry("manifest.json") IsNot Nothing Then
  27. Dim Json As JObject = GetJson(ReadFile(Archive.GetEntry("manifest.json").Open, Encoding.UTF8))
  28. If Json("addons") Is Nothing Then
  29. PackType = 0 : Exit Try 'CurseForge 整合包
  30. Else
  31. PackType = 3 : Exit Try 'MCBBS 整合包
  32. End If
  33. End If
  34. If Archive.GetEntry("modpack.json") IsNot Nothing Then PackType = 1 : Exit Try 'HMCL 整合包
  35. If Archive.GetEntry("mmc-pack.json") IsNot Nothing Then PackType = 2 : Exit Try 'MMC 整合包
  36. '从一级目录判断整合包类型
  37. For Each Entry In Archive.Entries
  38. Dim FullNames As String() = Entry.FullName.Split("/")
  39. ArchiveBaseFolder = FullNames(0) & "/"
  40. If Entry.FullName.EndsWith("/versions/") AndAlso FullNames.Count = 3 Then PackType = 9 : Exit Try '压缩包
  41. '确定为一级目录下
  42. If FullNames.Count <> 2 Then Continue For
  43. '判断是否为关键文件
  44. If FullNames(1) = "mcbbs.packmeta" Then PackType = 3 : Exit Try 'MCBBS 整合包(优先于 manifest.json 判断)
  45. If FullNames(1) = "modrinth.index.json" Then PackType = 4 : Exit Try 'Modrinth 整合包
  46. If FullNames(1) = "manifest.json" Then
  47. Dim Json As JObject = GetJson(ReadFile(Entry.Open, Encoding.UTF8))
  48. If Json("addons") Is Nothing Then
  49. PackType = 0 : Exit Try 'CurseForge 整合包
  50. Else
  51. PackType = 3 : ArchiveBaseFolder = "overrides/" : Exit Try 'MCBBS 整合包
  52. End If
  53. End If
  54. If FullNames(1) = "modpack.json" Then PackType = 1 : Exit Try 'HMCL 整合包
  55. If FullNames(1) = "mmc-pack.json" Then PackType = 2 : Exit Try 'MMC 整合包
  56. Next
  57. Catch ex As Exception
  58. If GetExceptionDetail(ex, True).Contains("Error.WinIOError") Then
  59. Log(ex, "打开整合包文件失败", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
  60. Return False
  61. ElseIf File.ToLower.EndsWith(".rar") Then
  62. Log(ex, "PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
  63. Return False
  64. Else
  65. Log(ex, "打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
  66. Return False
  67. End If
  68. End Try
  69. '执行对应的安装方法
  70. Select Case PackType
  71. Case 0
  72. Log("[ModPack] 整合包种类:CurseForge")
  73. InstallPackCurseForge(File, Archive, ArchiveBaseFolder, VersionName, Logo)
  74. Case 1
  75. Log("[ModPack] 整合包种类:HMCL")
  76. InstallPackHMCL(File, Archive, ArchiveBaseFolder)
  77. Case 2
  78. Log("[ModPack] 整合包种类:MMC")
  79. InstallPackMMC(File, Archive, ArchiveBaseFolder)
  80. Case 3
  81. Log("[ModPack] 整合包种类:MCBBS")
  82. InstallPackMCBBS(File, Archive, ArchiveBaseFolder)
  83. Case 4
  84. Log("[ModPack] 整合包种类:Modrinth")
  85. InstallPackModrinth(File, Archive, ArchiveBaseFolder, VersionName, Logo)
  86. Case 9
  87. Log("[ModPack] 整合包种类:压缩包")
  88. Archive.Dispose()
  89. Archive = Nothing
  90. InstallPackCompress(File, ArchiveBaseFolder)
  91. Case Else
  92. If ShowHint Then
  93. Hint("未能识别该整合包的种类,无法安装!", HintType.Critical)
  94. Else
  95. Log("[ModPack] 未能识别该整合包的种类,无法安装!")
  96. End If
  97. Return False
  98. End Select
  99. Return True
  100. Catch ex As Exception
  101. Log(ex, "准备安装整合包失败", LogLevel.Feedback)
  102. Return False
  103. Finally
  104. If Archive IsNot Nothing Then Archive.Dispose()
  105. End Try
  106. End Function
  107. '整合包缓存清理
  108. Private IsInstallCacheCleared As Boolean = False
  109. Private IsInstallCacheClearing As Boolean = False
  110. Private Sub UnpackFiles(InstallTemp As String, FileAddress As String)
  111. '清理缓存文件夹
  112. If Not IsInstallCacheCleared Then
  113. IsInstallCacheCleared = True
  114. IsInstallCacheClearing = True
  115. Try
  116. Log("[ModPack] 开始清理整合包安装缓存")
  117. DeleteDirectory(PathTemp & "PackInstall\")
  118. Log("[ModPack] 已清理整合包安装缓存")
  119. Catch ex As Exception
  120. Log(ex, "清理整合包安装缓存失败")
  121. Finally
  122. IsInstallCacheClearing = False
  123. End Try
  124. ElseIf IsInstallCacheClearing Then
  125. '等待另一个整合包安装的清理步骤完成
  126. Do While IsInstallCacheClearing
  127. Thread.Sleep(1)
  128. Loop
  129. End If
  130. '解压文件
  131. Dim RetryCount As Integer = 1
  132. Dim Encode = Encoding.GetEncoding("GB18030")
  133. Try
  134. Retry:
  135. '完全不知道为啥会出现文件正在被另一进程使用的问题,总之多试试
  136. Directory.CreateDirectory(InstallTemp)
  137. DeleteDirectory(InstallTemp)
  138. Compression.ZipFile.ExtractToDirectory(FileAddress, InstallTemp, Encode)
  139. Catch ex As Exception
  140. Log(ex, "第 " & RetryCount & " 次解压尝试失败")
  141. If TypeOf ex Is ArgumentException Then
  142. Encode = Encoding.UTF8
  143. Log("[ModPack] 已切换压缩包解压编码为 UTF8")
  144. End If
  145. If RetryCount < 5 Then
  146. Thread.Sleep(RetryCount * 2000)
  147. RetryCount += 1
  148. GoTo Retry
  149. Else
  150. Throw
  151. End If
  152. End Try
  153. End Sub
  154. #Region "不同类型整合包的安装方法"
  155. 'CurseForge
  156. Private Sub InstallPackCurseForge(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing)
  157. '读取 Json 文件
  158. Dim Json As JObject
  159. Try
  160. Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "manifest.json").Open))
  161. If Json("minecraft") Is Nothing OrElse Json("minecraft")("version") Is Nothing Then Throw New Exception("整合包未提供 Minecraft 版本信息")
  162. Catch ex As Exception
  163. Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
  164. Exit Sub
  165. End Try
  166. '获取版本名
  167. Dim ShowRibble As Boolean = VersionName Is Nothing
  168. If VersionName Is Nothing Then
  169. Dim PackName As String = If(Json("name"), "")
  170. Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
  171. If Validate.Validate(PackName) <> "" Then PackName = ""
  172. VersionName = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
  173. If String.IsNullOrEmpty(VersionName) Then Exit Sub
  174. End If
  175. '获取 Mod API 版本信息
  176. Dim ForgeVersion As String = Nothing
  177. Dim FabricVersion As String = Nothing
  178. For Each Entry In If(Json("minecraft")("modLoaders"), {})
  179. Dim Id As String = If(Entry("id"), "").ToString.ToLower
  180. If Id.StartsWith("forge-") Then
  181. 'Forge 指定
  182. If Id.Contains("recommended") Then
  183. Log("[ModPack] 该整合包版本过老,已不支持进行安装!", LogLevel.Hint)
  184. Exit Sub
  185. End If
  186. Try
  187. Log("[ModPack] 整合包 Forge 版本:" & Id)
  188. ForgeVersion = Id.Split("-")(1)
  189. Exit For
  190. Catch ex As Exception
  191. Log(ex, "读取整合包 Forge 版本失败:" & Id)
  192. End Try
  193. ElseIf Id.StartsWith("fabric-") Then
  194. 'Fabric 指定
  195. Try
  196. Log("[ModPack] 整合包 Fabric 版本:" & Id)
  197. FabricVersion = Id.Split("-")(1)
  198. Exit For
  199. Catch ex As Exception
  200. Log(ex, "读取整合包 Fabric 版本失败:" & Id)
  201. End Try
  202. End If
  203. Next
  204. '解压与配置文件
  205. Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
  206. Dim InstallLoaders As New List(Of LoaderBase)
  207. Dim OverrideHome As String = If(Json("overrides"), "")
  208. If OverrideHome <> "" Then
  209. InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
  210. Sub(Task As LoaderTask(Of String, Integer))
  211. UnpackFiles(InstallTemp, FileAddress)
  212. Task.Progress = 0.5
  213. '复制结果
  214. If Directory.Exists(InstallTemp & ArchiveBaseFolder & OverrideHome) Then
  215. CopyDirectory(InstallTemp & ArchiveBaseFolder & OverrideHome, PathMcFolder & "versions\" & VersionName)
  216. Else
  217. Log("[ModPack] 整合包中未找到 override 目录,已跳过")
  218. End If
  219. Task.Progress = 0.9
  220. '开启版本隔离
  221. WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
  222. End Sub) With {
  223. .ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
  224. End If
  225. '获取 Mod 列表
  226. Dim ModFileList As New List(Of Integer)
  227. For Each ModEntry In If(Json("files"), {})
  228. If ModEntry("projectID") Is Nothing OrElse ModEntry("fileID") Is Nothing Then
  229. Hint("某项 Mod 缺少必要信息,已跳过:" & ModEntry.ToString)
  230. Continue For
  231. End If
  232. If ModEntry("required") IsNot Nothing AndAlso Not ModEntry("required").ToObject(Of Boolean) Then Continue For
  233. ModFileList.Add(ModEntry("fileID"))
  234. Next
  235. If ModFileList.Count > 0 Then
  236. '获取 Mod 下载信息
  237. InstallLoaders.Add(New LoaderTask(Of Integer, JArray)("获取 Mod 下载信息",
  238. Sub(Task As LoaderTask(Of Integer, JArray))
  239. Task.Output = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(ModFileList, ",") & "]}", "application/json"))("data")
  240. '如果文件已被删除,则 API 会跳过那一项
  241. If ModFileList.Count > Task.Output.Count Then Throw New Exception("整合包所需要的部分 Mod 版本已被 Mod 作者删除,因此无法完成整合包安装,请联系整合包作者更新整合包中的 Mod 版本")
  242. End Sub) With {.ProgressWeight = ModFileList.Count / 10}) '每 10 Mod 需要 1s
  243. '构造 NetFile
  244. InstallLoaders.Add(New LoaderTask(Of JArray, List(Of NetFile))("构造 Mod 下载信息",
  245. Sub(Task As LoaderTask(Of JArray, List(Of NetFile)))
  246. Dim FileList As New Dictionary(Of Integer, NetFile)
  247. For Each ModJson In Task.Input
  248. '跳过重复的 Mod(疑似 CurseForge Bug)
  249. If FileList.ContainsKey(ModJson("id").ToObject(Of Integer)) Then Continue For
  250. '建立 CompFile
  251. Dim File As New CompFile(ModJson, CompType.Mod)
  252. If Not File.Available Then Continue For
  253. '根据 modules 和文件名后缀判断是资源包还是 Mod
  254. Dim IsResourcePack As Boolean
  255. If ModJson("modules").Any Then 'modules 可能返回 null(#1006)
  256. Dim ModuleNames = CType(ModJson("modules"), JArray).Select(Function(l) l("name").ToString).ToList
  257. IsResourcePack =
  258. (Not ModuleNames.Contains("META-INF")) AndAlso (Not ModuleNames.Contains("mcmod.info")) AndAlso '不包含 META-INF 或 mcmod.info
  259. ModuleNames.Contains("pack.mcmeta") AndAlso '包含 pack.mcmeta
  260. (Not File.FileName.EndsWith(".jar")) '文件后缀不是 .jar
  261. Else
  262. IsResourcePack = False
  263. End If
  264. '实际的添加
  265. FileList.Add(ModJson("id"),
  266. File.ToNetFile($"{PathMcFolder}versions\{VersionName}\{If(IsResourcePack, "resourcepacks", "mods")}\"))
  267. Task.Progress += 1 / (1 + ModFileList.Count)
  268. Next
  269. Task.Output = FileList.Values.ToList
  270. End Sub) With {.ProgressWeight = ModFileList.Count / 200, .Show = False}) '每 200 Mod 需要 1s
  271. '下载 Mod 文件
  272. InstallLoaders.Add(New LoaderDownload("下载 Mod", New List(Of NetFile)) With {.ProgressWeight = ModFileList.Count * 1.5}) '每个 Mod 需要 1.5s
  273. End If
  274. '构造加载器
  275. Dim Request As New McInstallRequest With {
  276. .TargetVersionName = VersionName,
  277. .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
  278. .MinecraftName = Json("minecraft")("version").ToString,
  279. .ForgeVersion = ForgeVersion,
  280. .FabricVersion = FabricVersion
  281. }
  282. Dim InstallExpectTime As Double = 0
  283. For Each InstallLoader In InstallLoaders
  284. InstallExpectTime += InstallLoader.ProgressWeight
  285. Next
  286. Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
  287. If MergeLoaders Is Nothing Then Exit Sub
  288. Dim MergeExpectTime As Double = 0
  289. For Each MergeLoader In MergeLoaders
  290. MergeExpectTime += MergeLoader.ProgressWeight
  291. Next
  292. '构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
  293. Dim LoadersLib As New List(Of LoaderBase)
  294. LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
  295. LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
  296. '构造总加载器
  297. Dim Loaders As New List(Of LoaderBase)
  298. Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallExpectTime})
  299. Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeExpectTime})
  300. Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
  301. Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
  302. Sub(Task As LoaderTask(Of String, String))
  303. '设置图标
  304. Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
  305. If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
  306. File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
  307. WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
  308. WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
  309. Log("[ModPack] 已设置整合包 Logo:" & Logo)
  310. End If
  311. '删除原始整合包文件
  312. For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
  313. If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
  314. Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
  315. File.Delete(Target)
  316. End If
  317. Next
  318. End Sub) With {.ProgressWeight = 0.1, .Show = False})
  319. '重复任务检查
  320. Dim LoaderName As String = "CurseForge 整合包安装:" & VersionName & " "
  321. SyncLock LoaderTaskbarLock
  322. For i = 0 To LoaderTaskbar.Count - 1
  323. If LoaderTaskbar(i).Name = LoaderName Then
  324. Hint("该整合包正在安装中!", HintType.Critical)
  325. Exit Sub
  326. End If
  327. Next
  328. End SyncLock
  329. '启动
  330. Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
  331. Loader.Start(Request.TargetVersionFolder)
  332. LoaderTaskbarAdd(Loader)
  333. FrmMain.BtnExtraDownload.ShowRefresh()
  334. If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
  335. End Sub
  336. 'Modrinth
  337. Private Sub InstallPackModrinth(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing)
  338. '读取 Json 文件
  339. Dim Json As JObject
  340. Try
  341. Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "modrinth.index.json").Open))
  342. If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("整合包未提供 Minecraft 版本信息")
  343. Catch ex As Exception
  344. Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
  345. Exit Sub
  346. End Try
  347. '获取 Mod API 版本信息
  348. Dim MinecraftVersion As String = Nothing
  349. Dim ForgeVersion As String = Nothing
  350. Dim FabricVersion As String = Nothing
  351. For Each Entry As JProperty In If(Json("dependencies"), {})
  352. Select Case Entry.Name.ToLower
  353. Case "minecraft"
  354. MinecraftVersion = Entry.Value.ToString
  355. Case "forge" 'eg. 14.23.5.2859 / 1.19-41.1.0
  356. ForgeVersion = Entry.Value.ToString
  357. Log("[ModPack] 整合包 Forge 版本:" & ForgeVersion)
  358. Case "fabric-loader" 'eg. 0.14.14
  359. FabricVersion = Entry.Value.ToString
  360. Log("[ModPack] 整合包 Fabric 版本:" & FabricVersion)
  361. Case "quilt-loader" 'eg. 1.0.0
  362. Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
  363. Exit Sub
  364. Case Else
  365. Hint($"无法安装整合包,其中出现了未知的 Mod 加载器 {Entry.Value}!", HintType.Critical)
  366. Exit Sub
  367. End Select
  368. Next
  369. '获取版本名
  370. Dim ShowRibble As Boolean = VersionName Is Nothing
  371. If VersionName Is Nothing Then
  372. Dim PackName As String = If(Json("name"), "")
  373. Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
  374. If Validate.Validate(PackName) <> "" Then PackName = ""
  375. VersionName = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
  376. If String.IsNullOrEmpty(VersionName) Then Exit Sub
  377. End If
  378. '解压和配置文件
  379. Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
  380. Dim InstallLoaders As New List(Of LoaderBase)
  381. InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
  382. Sub(Task As LoaderTask(Of String, Integer))
  383. UnpackFiles(InstallTemp, FileAddress)
  384. Task.Progress = 0.5
  385. '复制 overrides 文件夹和 client-overrides 文件夹
  386. If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then
  387. CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName)
  388. Else
  389. Log("[ModPack] 整合包中未找到 override 目录,已跳过")
  390. End If
  391. Task.Progress = 0.8
  392. If Directory.Exists(InstallTemp & ArchiveBaseFolder & "client-overrides") Then
  393. CopyDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", PathMcFolder & "versions\" & VersionName)
  394. End If
  395. Task.Progress = 0.9
  396. '开启版本隔离
  397. WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
  398. End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
  399. '获取下载文件列表
  400. Dim FileList As New List(Of NetFile)
  401. For Each File In If(Json("files"), {})
  402. '检查是否需要该文件
  403. If File("env") IsNot Nothing Then
  404. Select Case File("env")("client").ToString
  405. Case "optional"
  406. If MyMsgBox("是否要下载整合包中的可选文件 " & GetFileNameFromPath(File("path").ToString) & "?",
  407. "下载可选文件", "是", "否") = 2 Then
  408. Continue For
  409. End If
  410. Case "unsupported"
  411. Continue For
  412. End Select
  413. End If
  414. '添加下载文件
  415. FileList.Add(New NetFile(File("downloads").Select(Function(t) t.ToString).ToArray,
  416. PathMcFolder & "versions\" & VersionName & "\" & File("path").ToString,
  417. New FileChecker(ActualSize:=File("fileSize").ToObject(Of Long), Hash:=File("hashes")("sha1").ToString)))
  418. Next
  419. If FileList.Count > 0 Then
  420. InstallLoaders.Add(New LoaderDownload("下载额外文件", FileList) With {.ProgressWeight = FileList.Count * 1.5}) '每个 Mod 需要 1.5s
  421. End If
  422. '构造加载器
  423. Dim Request As New McInstallRequest With {
  424. .TargetVersionName = VersionName,
  425. .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
  426. .MinecraftName = MinecraftVersion,
  427. .ForgeVersion = ForgeVersion,
  428. .FabricVersion = FabricVersion
  429. }
  430. Dim InstallExpectTime As Double = 0
  431. For Each InstallLoader In InstallLoaders
  432. InstallExpectTime += InstallLoader.ProgressWeight
  433. Next
  434. Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
  435. If MergeLoaders Is Nothing Then Exit Sub
  436. Dim MergeExpectTime As Double = 0
  437. For Each MergeLoader In MergeLoaders
  438. MergeExpectTime += MergeLoader.ProgressWeight
  439. Next
  440. '构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
  441. Dim LoadersLib As New List(Of LoaderBase)
  442. LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
  443. LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
  444. '构造总加载器
  445. Dim Loaders As New List(Of LoaderBase)
  446. Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallExpectTime})
  447. Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeExpectTime})
  448. Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
  449. Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
  450. Sub(Task As LoaderTask(Of String, String))
  451. '设置图标
  452. Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
  453. If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
  454. File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
  455. WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
  456. WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
  457. Log("[ModPack] 已设置整合包 Logo:" & Logo)
  458. End If
  459. '删除原始整合包文件
  460. For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
  461. If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
  462. Log("[ModPack] 根据设置要求删除原始整合包文件:" & Target)
  463. File.Delete(Target)
  464. End If
  465. Next
  466. End Sub) With {.ProgressWeight = 0.1, .Show = False})
  467. '重复任务检查
  468. Dim LoaderName As String = "Modrinth 整合包安装:" & VersionName & " "
  469. SyncLock LoaderTaskbarLock
  470. For i = 0 To LoaderTaskbar.Count - 1
  471. If LoaderTaskbar(i).Name = LoaderName Then
  472. Hint("该整合包正在安装中!", HintType.Critical)
  473. Exit Sub
  474. End If
  475. Next
  476. End SyncLock
  477. '启动
  478. Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
  479. Loader.Start(Request.TargetVersionFolder)
  480. LoaderTaskbarAdd(Loader)
  481. FrmMain.BtnExtraDownload.ShowRefresh()
  482. If ShowRibble Then FrmMain.BtnExtraDownload.Ribble()
  483. End Sub
  484. 'HMCL
  485. Private Sub InstallPackHMCL(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String)
  486. '读取 Json 文件
  487. Dim Json As JObject
  488. Try
  489. Json = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "modpack.json").Open, Encoding.UTF8))
  490. Catch ex As Exception
  491. Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
  492. Exit Sub
  493. End Try
  494. '获取版本名
  495. Dim PackName As String = If(Json("name"), "")
  496. Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
  497. If Validate.Validate(PackName) <> "" Then PackName = ""
  498. Dim VersionName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
  499. If VersionName Is Nothing Then Exit Sub
  500. '解压与配置文件
  501. Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
  502. Dim InstallLoaders As New List(Of LoaderBase)
  503. InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
  504. Sub(Task As LoaderTask(Of String, Integer))
  505. UnpackFiles(InstallTemp, FileAddress)
  506. Task.Progress = 0.5
  507. '复制结果
  508. If Directory.Exists(InstallTemp & ArchiveBaseFolder & "minecraft") Then
  509. CopyDirectory(InstallTemp & ArchiveBaseFolder & "minecraft", PathMcFolder & "versions\" & VersionName)
  510. Else
  511. Log("[ModPack] 整合包中未找到 minecraft override 目录,已跳过")
  512. End If
  513. Task.Progress = 0.9
  514. '开启版本隔离
  515. WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
  516. End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
  517. '构造加载器
  518. If Json("gameVersion") Is Nothing Then
  519. Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
  520. Exit Sub
  521. End If
  522. Dim Request As New McInstallRequest With {
  523. .TargetVersionName = VersionName,
  524. .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
  525. .MinecraftName = Json("gameVersion").ToString
  526. }
  527. Dim InstallExpectTime As Double = 0
  528. For Each InstallLoader In InstallLoaders
  529. InstallExpectTime += InstallLoader.ProgressWeight
  530. Next
  531. Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
  532. If MergeLoaders Is Nothing Then Exit Sub
  533. Dim MergeExpectTime As Double = 0
  534. For Each MergeLoader In MergeLoaders
  535. MergeExpectTime += MergeLoader.ProgressWeight
  536. Next
  537. '构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
  538. Dim LoadersLib As New List(Of LoaderBase)
  539. LoadersLib.Add(New LoaderTask(Of String, String)("重命名版本 Json(副加载器)",
  540. Sub()
  541. Dim RealFileName As String = PathMcFolder & "versions\" & VersionName & "\" & VersionName & ".json"
  542. Dim OldFileName As String = PathMcFolder & "versions\" & VersionName & "\pack.json"
  543. If File.Exists(OldFileName) Then
  544. '修改 id
  545. Dim FileJson = GetJson(ReadFile(OldFileName))
  546. FileJson("id") = VersionName
  547. '替换文件
  548. File.Delete(OldFileName)
  549. WriteFile(RealFileName, FileJson.ToString)
  550. Log("[ModPack] 已重命名版本 Json:" & RealFileName)
  551. End If
  552. End Sub) With {.ProgressWeight = 0.1, .Show = False})
  553. LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
  554. LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
  555. '构造总加载器
  556. Dim Loaders As New List(Of LoaderBase) From {
  557. New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeExpectTime},
  558. New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallExpectTime},
  559. New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8}
  560. }
  561. '重复任务检查
  562. Dim LoaderName As String = "HMCL 整合包安装:" & VersionName & " "
  563. SyncLock LoaderTaskbarLock
  564. For i = 0 To LoaderTaskbar.Count - 1
  565. If LoaderTaskbar(i).Name = LoaderName Then
  566. Hint("该整合包正在安装中!", HintType.Critical)
  567. Exit Sub
  568. End If
  569. Next
  570. End SyncLock
  571. '启动
  572. Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
  573. 'If Archive IsNot Nothing Then Archive.Dispose() '解除占用,以免在加载器中触发 “正由另一进程使用,因此该进程无法访问此文件”
  574. Loader.Start(Request.TargetVersionFolder)
  575. LoaderTaskbarAdd(Loader)
  576. FrmMain.BtnExtraDownload.ShowRefresh()
  577. FrmMain.BtnExtraDownload.Ribble()
  578. End Sub
  579. 'MMC
  580. Private Sub InstallPackMMC(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String)
  581. '读取 Json 文件
  582. Dim PackJson As JObject, PackInstance As String
  583. Try
  584. PackJson = GetJson(ReadFile(Archive.GetEntry(ArchiveBaseFolder & "mmc-pack.json").Open, Encoding.UTF8))
  585. PackInstance = ReadFile(Archive.GetEntry(ArchiveBaseFolder & "instance.cfg").Open, Encoding.UTF8)
  586. Catch ex As Exception
  587. Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
  588. Exit Sub
  589. End Try
  590. '获取版本名
  591. Dim PackName As String = If(RegexSeek(PackInstance, "(?<=\nname\=)[^\n]+"), "")
  592. Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
  593. If Validate.Validate(PackName) <> "" Then PackName = ""
  594. Dim VersionName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
  595. If VersionName Is Nothing Then Exit Sub
  596. '解压与配置文件
  597. Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
  598. Dim InstallLoaders As New List(Of LoaderBase)
  599. InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
  600. Sub(Task As LoaderTask(Of String, Integer))
  601. UnpackFiles(InstallTemp, FileAddress)
  602. Task.Progress = 0.5
  603. '复制结果
  604. If Directory.Exists(InstallTemp & ArchiveBaseFolder & ".minecraft") Then
  605. CopyDirectory(InstallTemp & ArchiveBaseFolder & ".minecraft", PathMcFolder & "versions\" & VersionName)
  606. Else
  607. Log("[ModPack] 整合包中未找到 override .minecraft 目录,已跳过")
  608. End If
  609. Task.Progress = 0.9
  610. '开启版本隔离
  611. WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
  612. End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
  613. '构造版本安装请求
  614. If PackJson("components") Is Nothing Then
  615. Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
  616. Exit Sub
  617. End If
  618. Dim Request As New McInstallRequest With {.TargetVersionName = VersionName, .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\"}
  619. For Each Component In PackJson("components")
  620. Select Case If(Component("uid"), "").ToString
  621. Case "org.lwjgl"
  622. Log("[ModPack] 已跳过 LWJGL 项")
  623. Case "net.minecraft"
  624. Request.MinecraftName = Component("version")
  625. Case "net.minecraftforge"
  626. Request.ForgeVersion = Component("version")
  627. Case "net.fabricmc.fabric-loader"
  628. Request.FabricVersion = Component("version")
  629. Case "org.quiltmc.quilt-loader" 'eg. 1.0.0
  630. Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
  631. Exit Sub
  632. End Select
  633. Next
  634. '构造加载器
  635. Dim InstallExpectTime As Double = 0
  636. For Each InstallLoader In InstallLoaders
  637. InstallExpectTime += InstallLoader.ProgressWeight
  638. Next
  639. Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
  640. If MergeLoaders Is Nothing Then Exit Sub
  641. Dim MergeExpectTime As Double = 0
  642. For Each MergeLoader In MergeLoaders
  643. MergeExpectTime += MergeLoader.ProgressWeight
  644. Next
  645. '构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
  646. Dim LoadersLib As New List(Of LoaderBase)
  647. LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
  648. LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
  649. '构造总加载器
  650. Dim Loaders As New List(Of LoaderBase)
  651. Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeExpectTime})
  652. Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallExpectTime})
  653. Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
  654. '重复任务检查
  655. Dim LoaderName As String = "MMC 整合包安装:" & VersionName & " "
  656. SyncLock LoaderTaskbarLock
  657. For i = 0 To LoaderTaskbar.Count - 1
  658. If LoaderTaskbar(i).Name = LoaderName Then
  659. Hint("该整合包正在安装中!", HintType.Critical)
  660. Exit Sub
  661. End If
  662. Next
  663. End SyncLock
  664. '启动
  665. Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
  666. Loader.Start(Request.TargetVersionFolder)
  667. LoaderTaskbarAdd(Loader)
  668. FrmMain.BtnExtraDownload.ShowRefresh()
  669. FrmMain.BtnExtraDownload.Ribble()
  670. End Sub
  671. 'MCBBS
  672. Private Sub InstallPackMCBBS(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String)
  673. '读取 Json 文件
  674. Dim Json As JObject
  675. Try
  676. Dim Entry = If(Archive.GetEntry(ArchiveBaseFolder & "mcbbs.packmeta"), Archive.GetEntry(ArchiveBaseFolder & "manifest.json"))
  677. Json = GetJson(ReadFile(Entry.Open, Encoding.UTF8))
  678. Catch ex As Exception
  679. Log(ex, "整合包安装信息存在问题", LogLevel.Hint)
  680. Exit Sub
  681. End Try
  682. '获取版本名
  683. Dim PackName As String = If(Json("name"), "")
  684. Dim Validate As New ValidateFolderName(PathMcFolder & "versions")
  685. If Validate.Validate(PackName) <> "" Then PackName = ""
  686. Dim VersionName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
  687. If VersionName Is Nothing Then Exit Sub
  688. '解压与配置文件
  689. Dim InstallTemp As String = PathTemp & "PackInstall\" & RandomInteger(0, 100000) & "\"
  690. Dim InstallLoaders As New List(Of LoaderBase)
  691. InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
  692. Sub(Task As LoaderTask(Of String, Integer))
  693. UnpackFiles(InstallTemp, FileAddress)
  694. Task.Progress = 0.5
  695. '复制结果
  696. If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then
  697. CopyDirectory(InstallTemp & ArchiveBaseFolder & "overrides", PathMcFolder & "versions\" & VersionName)
  698. Else
  699. Log("[ModPack] 整合包中未找到 overrides 目录,已跳过")
  700. End If
  701. Task.Progress = 0.9
  702. '开启版本隔离
  703. WriteIni(PathMcFolder & "versions\" & VersionName & "\PCL\Setup.ini", "VersionArgumentIndie", 1)
  704. End Sub) With {.ProgressWeight = New FileInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
  705. '构造加载器
  706. If Json("addons") Is Nothing Then
  707. Hint("该整合包未提供游戏版本附加信息,无法安装!", HintType.Critical)
  708. Exit Sub
  709. End If
  710. Dim Addons As New Dictionary(Of String, String)
  711. For Each Entry In Json("addons")
  712. Addons.Add(Entry("id"), Entry("version"))
  713. Next
  714. If Not Addons.ContainsKey("game") Then
  715. Hint("该整合包未提供游戏版本信息,无法安装!", HintType.Critical)
  716. Exit Sub
  717. End If
  718. If Addons.ContainsKey("quilt") Then
  719. Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Critical)
  720. Exit Sub
  721. End If
  722. Dim Request As New McInstallRequest With {
  723. .TargetVersionName = VersionName,
  724. .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
  725. .MinecraftName = Addons("game"),
  726. .OptiFineVersion = If(Addons.ContainsKey("optifine"), Addons("optifine"), Nothing),
  727. .ForgeVersion = If(Addons.ContainsKey("forge"), Addons("forge"), Nothing),
  728. .FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
  729. }
  730. Dim InstallExpectTime As Double = 0
  731. For Each InstallLoader In InstallLoaders
  732. InstallExpectTime += InstallLoader.ProgressWeight
  733. Next
  734. Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request, True)
  735. If MergeLoaders Is Nothing Then Exit Sub
  736. Dim MergeExpectTime As Double = 0
  737. For Each MergeLoader In MergeLoaders
  738. MergeExpectTime += MergeLoader.ProgressWeight
  739. Next
  740. '构造 Libraries 加载器(为了使得 Mods 下载结束后再构造,这样才会下载 JumpLoader 文件)
  741. Dim LoadersLib As New List(Of LoaderBase)
  742. LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task As LoaderTask(Of String, List(Of NetFile))) Task.Output = McLibFix(New McVersion(VersionName))) With {.ProgressWeight = 1, .Show = False})
  743. LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
  744. '构造总加载器
  745. Dim Loaders As New List(Of LoaderBase)
  746. Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .Block = False, .ProgressWeight = MergeExpectTime})
  747. Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .ProgressWeight = InstallExpectTime})
  748. Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
  749. '重复任务检查
  750. Dim LoaderName As String = "MCBBS 整合包安装:" & VersionName & " "
  751. SyncLock LoaderTaskbarLock
  752. For i = 0 To LoaderTaskbar.Count - 1
  753. If LoaderTaskbar(i).Name = LoaderName Then
  754. Hint("该整合包正在安装中!", HintType.Critical)
  755. Exit Sub
  756. End If
  757. Next
  758. End SyncLock
  759. '启动
  760. Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
  761. 'If Archive IsNot Nothing Then Archive.Dispose() '解除占用,以免在加载器中触发 “正由另一进程使用,因此该进程无法访问此文件”
  762. Loader.Start(Request.TargetVersionFolder)
  763. LoaderTaskbarAdd(Loader)
  764. FrmMain.BtnExtraDownload.ShowRefresh()
  765. FrmMain.BtnExtraDownload.Ribble()
  766. End Sub
  767. '普通压缩包
  768. Private Sub InstallPackCompress(FileAddress As String, ArchiveBaseFolder As String)
  769. MyMsgBox("请在接下来打开的窗口中选择安装目标文件夹,它必须是一个空文件夹。", "安装提示", "继续", ForceWait:=True)
  770. '获取解压路径
  771. Dim TargetFolder As String = SelectFolder("选择安装目标(必须是一个空文件夹)")
  772. If String.IsNullOrEmpty(TargetFolder) Then Exit Sub
  773. If TargetFolder.Contains("!") OrElse TargetFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Critical) : Exit Sub
  774. If Directory.GetFileSystemEntries(TargetFolder).Length > 0 Then Hint("请选择一个空文件夹作为安装目标!", HintType.Critical) : Exit Sub
  775. '要求显示名称
  776. Dim NewName As String = MyMsgBoxInput("输入显示名称", "输入该文件夹在左边栏列表中显示的名称。", GetFolderNameFromPath(TargetFolder),
  777. New ObjectModel.Collection(Of Validate) From {New ValidateNullOrWhiteSpace, New ValidateLength(1, 30), New ValidateExcept({">", "|"})})
  778. If String.IsNullOrWhiteSpace(NewName) Then Exit Sub
  779. '解压
  780. Hint("正在解压压缩包……")
  781. UnpackFiles(TargetFolder, FileAddress)
  782. '加入文件夹列表
  783. PageSelectLeft.AddFolder(TargetFolder, NewName, False)
  784. Hint("已加入游戏文件夹列表:" & NewName, HintType.Finish)
  785. End Sub
  786. #End Region
  787. End Module