PageDownloadCompDetail.xaml.vb 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. Public Class PageDownloadCompDetail
  2. Private CompItem As MyCompItem = Nothing
  3. #Region "加载器"
  4. Private CompFileLoader As New LoaderTask(Of Integer, List(Of CompFile))(
  5. "Comp File",
  6. Sub(Task)
  7. LoadTargetFromAdditional()
  8. Dim Result = CompFilesGet(Project.Id, Project.FromCurseForge)
  9. If Task.IsAborted Then Return
  10. Task.Output = Result
  11. End Sub)
  12. '初始化加载器信息
  13. Private Sub PageDownloadCompDetail_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
  14. LoadTargetFromAdditional()
  15. PageLoaderInit(Load, PanLoad, PanMain, CardIntro, CompFileLoader, AddressOf Load_OnFinish)
  16. End Sub
  17. Public Sub LoadTargetFromAdditional() Handles Me.Loaded
  18. Project = FrmMain.PageCurrent.Additional(0)
  19. TargetInstance = FrmMain.PageCurrent.Additional(2)
  20. TargetLoader = FrmMain.PageCurrent.Additional(3)
  21. PageType = FrmMain.PageCurrent.Additional(4)
  22. End Sub
  23. Private Project As CompProject
  24. Private TargetInstance As String, TargetLoader As CompModLoaderType
  25. ''' <summary>
  26. ''' 当前页面应展示的内容类别。可能为 Any。
  27. ''' </summary>
  28. Private PageType As CompType
  29. '自动重试
  30. Private Sub Load_State(sender As Object, state As MyLoading.MyLoadingState, oldState As MyLoading.MyLoadingState) Handles Load.StateChanged
  31. Select Case CompFileLoader.State
  32. Case LoadState.Failed
  33. Dim ErrorMessage As String = ""
  34. If CompFileLoader.Error IsNot Nothing Then ErrorMessage = CompFileLoader.Error.Message
  35. If ErrorMessage.Contains("不是有效的 json 文件") Then
  36. Log("[Comp] 下载的文件 json 列表损坏,已自动重试", LogLevel.Debug)
  37. PageLoaderRestart()
  38. End If
  39. End Select
  40. End Sub
  41. '结果 UI 化
  42. Private Class CardSorter
  43. Implements IComparer(Of String)
  44. Public Topmost As String = ""
  45. Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
  46. '相同
  47. If x = y Then Return 0
  48. '置顶
  49. If x = Topmost Then Return -1
  50. If y = Topmost Then Return 1
  51. '特殊版本
  52. Dim IsXSpecial As Boolean = Not x.Contains(".")
  53. Dim IsYSpecial As Boolean = Not y.Contains(".")
  54. If IsXSpecial AndAlso IsYSpecial Then Return x.CompareTo(y)
  55. If IsXSpecial Then Return 1
  56. If IsYSpecial Then Return -1
  57. '比较版本号
  58. Dim VersionCodeSort = -CompareVersion(x.Replace(x.BeforeFirst(" ") & " ", ""), y.Replace(y.BeforeFirst(" ") & " ", ""))
  59. If VersionCodeSort <> 0 Then Return VersionCodeSort
  60. '比较全部
  61. Return -CompareVersion(x, y)
  62. End Function
  63. Public Sub New(Optional Topmost As String = "")
  64. Me.Topmost = If(Topmost, "")
  65. End Sub
  66. End Class
  67. Private VersionFilter As String
  68. Private GroupedDrop As Boolean '是否按 Drop 筛选(1.21 / 1.20 / 1.19 / ...)而非小版本号(1.21.1 / 1.21 / 1.20.4 / ...)
  69. Private GroupedOld As Boolean '是否折叠远古版本为一个选项
  70. '筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
  71. Private Function GetResults() As List(Of CompFile)
  72. Dim Results As List(Of CompFile) = CompFileLoader.Output
  73. Select Case PageType
  74. Case CompType.Any
  75. Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
  76. Case CompType.Shader, CompType.ResourcePack
  77. '不筛选光影和资源包,否则原版光影会因为是资源包格式而被过滤(#6473)
  78. Case Else
  79. Results = Results.Where(Function(r) r.Type = PageType).ToList
  80. End Select
  81. Return Results
  82. End Function
  83. Private Sub Load_OnFinish()
  84. Dim Results = GetResults()
  85. '初始化筛选器
  86. Dim Filters As List(Of String) = Nothing
  87. Dim UpdateFilters =
  88. Sub()
  89. Filters = Results.SelectMany(Function(v) v.GameVersions).Select(Function(v) GetGroupedVersionName(v, GroupedDrop, GroupedOld)).
  90. Distinct.OrderByDescending(Function(s) s, New VersionComparer).ToList
  91. End Sub
  92. '确定分组方式
  93. GroupedDrop = False : GroupedOld = False
  94. UpdateFilters()
  95. If Filters.Count < 9 Then GoTo GroupDone
  96. GroupedDrop = True : GroupedOld = False
  97. UpdateFilters()
  98. If Filters.Count < 9 Then GoTo GroupDone
  99. GroupedDrop = False : GroupedOld = True
  100. UpdateFilters()
  101. If Filters.Count < 9 Then GoTo GroupDone
  102. GroupedDrop = True : GroupedOld = True
  103. UpdateFilters()
  104. GroupDone:
  105. 'UI 化筛选器
  106. PanFilter.Children.Clear()
  107. If Filters.Count < 2 Then
  108. CardFilter.Visibility = Visibility.Collapsed
  109. VersionFilter = Nothing
  110. Else
  111. CardFilter.Visibility = Visibility.Visible
  112. Filters.Insert(0, "全部")
  113. '转化为按钮
  114. For Each Version As String In Filters
  115. Dim NewButton As New MyRadioButton With {
  116. .Text = Version, .Margin = New Thickness(2, 0, 2, 0), .ColorType = MyRadioButton.ColorState.Highlight}
  117. NewButton.LabText.Margin = New Thickness(-2, 0, 10, 0)
  118. AddHandler NewButton.Check,
  119. Sub(sender As MyRadioButton, raiseByMouse As Boolean)
  120. VersionFilter = If(sender.Text = "全部", Nothing, sender.Text)
  121. UpdateFilterResult()
  122. End Sub
  123. PanFilter.Children.Add(NewButton)
  124. Next
  125. '自动选择
  126. Dim ToCheck As MyRadioButton = Nothing
  127. If TargetInstance <> "" Then
  128. Dim TargetFile = Results.FirstOrDefault(Function(v) v.GameVersions.Contains(TargetInstance))
  129. If TargetFile IsNot Nothing Then
  130. Dim TargetGroup = GetGroupedVersionName(TargetInstance, GroupedDrop, GroupedOld)
  131. For Each Button As MyRadioButton In PanFilter.Children
  132. If Button.Text <> TargetGroup Then Continue For
  133. ToCheck = Button
  134. Exit For
  135. Next
  136. End If
  137. End If
  138. If ToCheck Is Nothing Then ToCheck = PanFilter.Children(0)
  139. ToCheck.Checked = True
  140. End If
  141. '更新筛选结果(文件列表 UI 化)
  142. UpdateFilterResult()
  143. End Sub
  144. Private Sub UpdateFilterResult()
  145. Dim Results = GetResults()
  146. Dim TargetCardName As String = If(TargetInstance <> "" OrElse TargetLoader <> CompModLoaderType.Any,
  147. $"{If(TargetLoader <> CompModLoaderType.Any, TargetLoader.ToString & " ", "")}{TargetInstance}(所选版本)", "")
  148. '归类到卡片下
  149. Dim Dict As New SortedDictionary(Of String, List(Of CompFile))(New CardSorter(TargetCardName))
  150. Dict.Add("其他", New List(Of CompFile))
  151. Dim SupportedLoaders As New List(Of Integer)([Enum].GetValues(GetType(CompModLoaderType)))
  152. For Each Version As CompFile In Results
  153. For Each GameVersion In Version.GameVersions
  154. '检查是否符合版本筛选器
  155. If VersionFilter IsNot Nothing AndAlso
  156. GetGroupedVersionName(GameVersion, GroupedDrop, GroupedOld) <> VersionFilter Then Continue For
  157. '决定添加到哪个卡片
  158. Dim VerName As String = GetGroupedVersionName(GameVersion, False, False)
  159. '遍历加入的加载器列表
  160. Dim Loaders As New List(Of String)
  161. If Project.ModLoaders.Count > 1 AndAlso '工程至少有两个加载器
  162. Version.Type = CompType.Mod AndAlso '是 Mod
  163. McVersion.IsFormatFit(VerName) Then '不是 “快照版本” 之类的
  164. For Each Loader In Version.ModLoaders
  165. If Loader = CompModLoaderType.Quilt AndAlso Setup.Get("ToolDownloadIgnoreQuilt") Then Continue For
  166. If SupportedLoaders.Contains(Loader) Then Loaders.Add(Loader.ToString & " ")
  167. Next
  168. End If
  169. If Not Loaders.Any() Then Loaders.Add("") '保底加一个空的,确保它在一张卡片里
  170. '实际添加
  171. For Each Loader In Loaders
  172. Dim TargetCard As String = Loader & VerName
  173. If Not Dict.ContainsKey(TargetCard) Then Dict.Add(TargetCard, New List(Of CompFile))
  174. If Not Dict(TargetCard).Contains(Version) Then Dict(TargetCard).Add(Version)
  175. Next
  176. Next
  177. Next
  178. '添加筛选的版本的卡片
  179. If TargetCardName <> "" AndAlso (VersionFilter Is Nothing OrElse GetGroupedVersionName(TargetInstance, GroupedDrop, GroupedOld).StartsWithF(VersionFilter)) Then
  180. Dict.Add(TargetCardName, New List(Of CompFile))
  181. For Each Version As CompFile In Results
  182. If Version.GameVersions.Contains(TargetInstance) AndAlso
  183. (TargetLoader = CompModLoaderType.Any OrElse Version.ModLoaders.Contains(TargetLoader)) Then
  184. '检查是否符合版本筛选器
  185. If VersionFilter IsNot Nothing AndAlso
  186. Not Version.GameVersions.Any(Function(v) GetGroupedVersionName(v, GroupedDrop, GroupedOld) = VersionFilter) Then Continue For
  187. If Not Dict(TargetCardName).Contains(Version) Then Dict(TargetCardName).Add(Version)
  188. End If
  189. Next
  190. End If
  191. '转化为 UI
  192. Try
  193. PanResults.Children.Clear()
  194. For Each Pair As KeyValuePair(Of String, List(Of CompFile)) In Dict
  195. If Not Pair.Value.Any() Then Continue For
  196. If Pair.Key = TargetCardName.Replace("(所选版本)", "") Then Continue For
  197. '增加卡片
  198. Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15), .SwapType = If(PageType = CompType.ModPack, 9, 8)} '9 是安装,8 是另存为
  199. Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
  200. NewCard.Children.Add(NewStack)
  201. NewCard.SwapControl = NewStack
  202. PanResults.Children.Add(NewCard)
  203. '确定卡片是否展开
  204. If Pair.Key = TargetCardName OrElse
  205. (FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
  206. CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
  207. MyCard.StackInstall(NewStack, If(PageType = CompType.ModPack, 9, 8), Pair.Key) '9 是安装,8 是另存为
  208. Else
  209. NewCard.IsSwapped = True
  210. End If
  211. '增加提示
  212. If Pair.Key = "其他" Then
  213. NewStack.Children.Add(New MyHint With {.Text = "由于版本信息更新缓慢,可能无法识别刚更新的 MC 版本。几天后即可正常识别。", .Theme = MyHint.Themes.Yellow, .Margin = New Thickness(5, 0, 0, 8)})
  214. End If
  215. Next
  216. '如果只有一张卡片,展开第一张卡片
  217. If PanResults.Children.Count = 1 Then
  218. CType(PanResults.Children(0), MyCard).IsSwapped = False
  219. End If
  220. Catch ex As Exception
  221. Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
  222. End Try
  223. End Sub
  224. Private Function GetGroupedVersionName(Name As String, GroupedByDrop As Boolean, FoldOld As Boolean) As String
  225. If Name Is Nothing Then
  226. Return "其他"
  227. ElseIf Name.Contains("w") Then
  228. Return "快照版"
  229. ElseIf Not McVersion.IsFormatFit(Name) OrElse (FoldOld AndAlso McVersion.VersionToDrop(Name, True) < 120) Then
  230. Return "远古版"
  231. ElseIf GroupedByDrop Then
  232. Return McVersion.DropToVersion(McVersion.VersionToDrop(Name, True))
  233. Else
  234. Return Name
  235. End If
  236. End Function
  237. #End Region
  238. Private IsFirstInit As Boolean = True
  239. Public Sub Init() Handles Me.PageEnter
  240. AniControlEnabled += 1
  241. Project = FrmMain.PageCurrent.Additional(0)
  242. PanBack.ScrollToHome()
  243. '重启加载器
  244. If IsFirstInit Then
  245. '在 Me.Initialized 已经初始化了加载器,不再重复初始化
  246. IsFirstInit = False
  247. Else
  248. PageLoaderRestart(IsForceRestart:=True)
  249. End If
  250. '放置当前工程
  251. If CompItem IsNot Nothing Then PanIntro.Children.Remove(CompItem)
  252. CompItem = Project.ToCompItem(True, True).Init()
  253. CompItem.CanInteraction = False
  254. CompItem.Margin = New Thickness(-7, -7, 0, 8)
  255. PanIntro.Children.Insert(0, CompItem)
  256. '决定按钮显示
  257. BtnIntroWeb.Text = If(Project.FromCurseForge, "转到 CurseForge", "转到 Modrinth")
  258. BtnIntroWiki.Visibility = If(Project.WikiId = 0, Visibility.Collapsed, Visibility.Visible)
  259. AniControlEnabled -= 1
  260. End Sub
  261. '整合包安装
  262. Public Sub Install_Click(sender As MyListItem, e As EventArgs)
  263. Try
  264. '获取基本信息
  265. Dim File As CompFile = sender.Tag
  266. Dim LoaderName As String = $"{If(Project.FromCurseForge, "CurseForge", "Modrinth")} 整合包下载:{Project.TranslatedName} "
  267. '获取版本名
  268. Dim PackName As String = Project.TranslatedName.Replace(".zip", "").Replace(".rar", "").Replace(".mrpack", "").Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":")
  269. Dim Validate As New ValidateFolderName(McFolderSelected & "versions")
  270. If Validate.Validate(PackName) <> "" Then PackName = ""
  271. Dim InstanceName As String = MyMsgBoxInput("输入版本名称", "", PackName, New ObjectModel.Collection(Of Validate) From {Validate})
  272. If String.IsNullOrEmpty(InstanceName) Then Return
  273. '构造步骤加载器
  274. Dim Loaders As New List(Of LoaderBase)
  275. Dim Target As String = $"{McFolderSelected}versions\{InstanceName}\原始整合包.{If(Project.FromCurseForge, "zip", "mrpack")}"
  276. Dim LogoFileAddress As String = CompItem.PathLogo.ActualSource
  277. Loaders.Add(New LoaderDownload("下载整合包文件", New List(Of NetFile) From {File.ToNetFile(Target)}) With {.ProgressWeight = 10, .Block = True})
  278. Loaders.Add(New LoaderTask(Of Integer, Integer)("准备安装整合包",
  279. Sub() ModpackInstall(Target, InstanceName, If(IO.File.Exists(LogoFileAddress), LogoFileAddress, Nothing))) With {.ProgressWeight = 0.1})
  280. '启动
  281. Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged =
  282. Sub(MyLoader)
  283. Select Case MyLoader.State
  284. Case LoadState.Failed
  285. Hint(MyLoader.Name & "失败:" & MyLoader.Error.GetBrief(), HintType.Red)
  286. Case LoadState.Aborted
  287. Hint(MyLoader.Name & "已取消!", HintType.Blue)
  288. Case LoadState.Loading
  289. Return '不重新加载版本列表
  290. End Select
  291. McInstallFailedClearFolder(MyLoader)
  292. End Sub}
  293. Loader.Start(McFolderSelected & "versions\" & InstanceName & "\")
  294. LoaderTaskbarAdd(Loader)
  295. FrmMain.BtnExtraDownload.ShowRefresh()
  296. FrmMain.BtnExtraDownload.Ribble()
  297. Catch ex As Exception
  298. Log(ex, "下载资源整合包失败", LogLevel.Feedback)
  299. End Try
  300. End Sub
  301. '资源下载;整合包另存为
  302. Public Shared CachedFolder As New Dictionary(Of CompType, String) '仅在本次缓存的下载文件夹
  303. Public Sub Save_Click(sender As Object, e As EventArgs)
  304. Dim File As CompFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
  305. RunInNewThread(
  306. Sub()
  307. Try
  308. Dim Desc As String = Nothing
  309. Select Case File.Type
  310. Case CompType.ModPack : Desc = "整合包"
  311. Case CompType.Mod : Desc = "Mod "
  312. Case CompType.ResourcePack : Desc = "资源包"
  313. Case CompType.Shader : Desc = "光影包"
  314. Case CompType.DataPack : Desc = "数据包"
  315. End Select
  316. '确认默认保存位置
  317. Dim DefaultFolder As String = Nothing
  318. If File.Type <> CompType.ModPack Then
  319. Dim SubFolder As String = Nothing
  320. Select Case File.Type
  321. Case CompType.Mod : SubFolder = "mods\"
  322. Case CompType.ResourcePack : SubFolder = "resourcepacks\"
  323. Case CompType.Shader : SubFolder = "shaderpacks\"
  324. Case CompType.DataPack : SubFolder = "" '导航到版本根目录
  325. End Select
  326. Dim IsInstanceSuitable As Func(Of McInstance, Boolean) = Nothing
  327. '获取资源所需的加载器
  328. Dim AllowedLoaders As New List(Of CompModLoaderType)
  329. If File.ModLoaders.Any Then
  330. AllowedLoaders = File.ModLoaders
  331. ElseIf Project.ModLoaders.Any Then
  332. AllowedLoaders = Project.ModLoaders
  333. End If
  334. Log($"[Comp] {Desc}要求的加载器种类:" & If(AllowedLoaders.Any(), AllowedLoaders.Join(" / "), "无要求"))
  335. '判断某个版本是否符合资源要求
  336. IsInstanceSuitable =
  337. Function(Instance As McInstance)
  338. If Not Instance.IsLoaded Then Instance.Load()
  339. '只对 Mod 和数据包进行版本检测
  340. If File.Type = CompType.Mod OrElse File.Type = CompType.DataPack Then
  341. If File.GameVersions.Any(Function(v) v.Contains(".")) AndAlso
  342. Not File.GameVersions.Any(Function(v) v.Contains(".") AndAlso v = Instance.Version.VanillaName) Then Return False
  343. End If
  344. '加载器
  345. If Not AllowedLoaders.Any() Then Return True '无要求
  346. If AllowedLoaders.Contains(CompModLoaderType.Forge) AndAlso Instance.Version.HasForge Then Return True
  347. If AllowedLoaders.Contains(CompModLoaderType.Fabric) AndAlso Instance.Version.HasFabric Then Return True
  348. If AllowedLoaders.Contains(CompModLoaderType.NeoForge) AndAlso Instance.Version.HasNeoForge Then Return True
  349. If AllowedLoaders.Contains(CompModLoaderType.LiteLoader) AndAlso Instance.Version.HasLiteLoader Then Return True
  350. Return False
  351. End Function
  352. '获取常规资源默认下载位置
  353. If CachedFolder.ContainsKey(File.Type) Then
  354. DefaultFolder = CachedFolder(File.Type)
  355. Log($"[Comp] 使用上次下载时的文件夹作为默认下载位置:{DefaultFolder}")
  356. ElseIf McInstanceSelected IsNot Nothing AndAlso IsInstanceSuitable(McInstanceSelected) Then
  357. DefaultFolder = $"{McInstanceSelected.PathIndie}{SubFolder}"
  358. Directory.CreateDirectory(DefaultFolder)
  359. Log($"[Comp] 使用当前版本作为默认下载位置:{DefaultFolder}")
  360. Else
  361. '查找所有可能的版本
  362. Dim NeedLoad As Boolean = McInstanceListLoader.State <> LoadState.Finished
  363. If NeedLoad Then
  364. Hint("正在查找适合的游戏版本……")
  365. LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
  366. End If
  367. Dim SuitableInstanceList = McInstanceList.Values.SelectMany(Function(l) l).Where(Function(v) IsInstanceSuitable(v)).
  368. Select(Function(v) New DirectoryInfo($"{v.PathIndie}{SubFolder}"))
  369. If SuitableInstanceList.Any Then
  370. Dim SelectedInstance = SuitableInstanceList.
  371. OrderByDescending(Function(Dir) If(Dir.Exists, Dir.LastWriteTimeUtc, Date.MinValue)). '先按文件夹更改时间降序
  372. ThenByDescending(Function(Dir) If(Dir.Exists, Dir.GetFiles().Length, -1)). '再按文件夹中的文件数量降序
  373. First()
  374. DefaultFolder = SelectedInstance.FullName
  375. Directory.CreateDirectory(DefaultFolder)
  376. Log($"[Comp] 使用适合的游戏版本作为默认下载位置:{DefaultFolder}")
  377. Else
  378. DefaultFolder = McFolderSelected
  379. If NeedLoad Then
  380. Hint($"当前 MC 文件夹中没有找到合适的版本!")
  381. Else
  382. Log("[Comp] 由于当前版本不兼容,使用当前的 MC 文件夹作为默认下载位置")
  383. End If
  384. End If
  385. End If
  386. End If
  387. '获取基本信息
  388. Dim FileName As String
  389. If Project.TranslatedName = Project.RawName Then
  390. FileName = File.FileName
  391. Else
  392. Dim ChineseName As String = Project.TranslatedName.BeforeFirst(" (").BeforeFirst(" - ").
  393. Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":")
  394. Select Case Setup.Get("ToolDownloadTranslateV2")
  395. Case 0
  396. FileName = $"【{ChineseName}】{File.FileName}"
  397. Case 1
  398. FileName = $"[{ChineseName}] {File.FileName}"
  399. Case 2
  400. FileName = $"{ChineseName}-{File.FileName}"
  401. Case 3
  402. FileName = $"{File.FileName}-{ChineseName}"
  403. Case Else
  404. FileName = File.FileName
  405. End Select
  406. End If
  407. If File.Type = CompType.Mod Then FileName = FileName.Replace("~", "-") '~ 会导致 Mixin 加载失败
  408. RunInUi(
  409. Sub()
  410. '弹窗要求选择保存位置
  411. Dim Target As String
  412. Target = SelectSaveFile("选择保存位置", FileName,
  413. Desc & "文件|" &
  414. If(File.Type = CompType.Mod,
  415. If(File.FileName.EndsWith(".litemod"), "*.litemod", "*.jar"),
  416. If(File.FileName.EndsWith(".mrpack"), "*.mrpack", "*.zip")), DefaultFolder)
  417. If Not Target.Contains("\") Then Return
  418. '构造步骤加载器
  419. Dim LoaderName As String = Desc & "下载:" & IO.Path.GetFileNameWithoutExtension(Target) & " "
  420. If Target <> DefaultFolder Then CachedFolder(File.Type) = GetPathFromFullPath(Target)
  421. Dim Loaders As New List(Of LoaderBase)
  422. Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.ToNetFile(Target)}) With {.ProgressWeight = 6, .Block = True})
  423. '启动
  424. Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged = AddressOf LoaderStateChangedHintOnly}
  425. Loader.Start(1)
  426. LoaderTaskbarAdd(Loader)
  427. FrmMain.BtnExtraDownload.ShowRefresh()
  428. FrmMain.BtnExtraDownload.Ribble()
  429. End Sub)
  430. Catch ex As Exception
  431. Log(ex, "保存资源文件失败", LogLevel.Feedback)
  432. End Try
  433. End Sub, "Download CompDetail Save")
  434. End Sub
  435. Private Sub BtnIntroWeb_Click(sender As Object, e As EventArgs) Handles BtnIntroWeb.Click
  436. OpenWebsite(Project.Website)
  437. End Sub
  438. Private Sub BtnIntroWiki_Click(sender As Object, e As EventArgs) Handles BtnIntroWiki.Click
  439. OpenWebsite("https://www.mcmod.cn/class/" & Project.WikiId & ".html")
  440. End Sub
  441. Private Sub BtnIntroCopy_Click(sender As Object, e As EventArgs) Handles BtnIntroCopy.Click
  442. ClipboardSet(CompItem.LabTitle.Text & CompItem.LabTitleRaw.Text)
  443. End Sub
  444. End Class