PageDownloadInstall.xaml.vb 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. Public Class PageDownloadInstall
  2. Private Sub LoaderInit() Handles Me.Initialized
  3. DisabledPageAnimControls.Add(BtnStart)
  4. PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, DlClientListLoader, AddressOf LoadMinecraft_OnFinish)
  5. End Sub
  6. Private IsLoad As Boolean = False
  7. Private Sub Init() Handles Me.Loaded
  8. PanBack.ScrollToHome()
  9. DlOptiFineListLoader.Start()
  10. DlLiteLoaderListLoader.Start()
  11. DlFabricListLoader.Start()
  12. DlNeoForgeListLoader.Start()
  13. '重载预览
  14. TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {New ValidateFolderName(PathMcFolder & "versions")}
  15. TextSelectName.Validate()
  16. SelectReload()
  17. '非重复加载部分
  18. If IsLoad Then Exit Sub
  19. IsLoad = True
  20. McDownloadForgeRecommendedRefresh()
  21. LoadOptiFine.State = DlOptiFineListLoader
  22. LoadLiteLoader.State = DlLiteLoaderListLoader
  23. LoadFabric.State = DlFabricListLoader
  24. LoadFabricApi.State = DlFabricApiLoader
  25. LoadNeoForge.State = DlNeoForgeListLoader
  26. LoadOptiFabric.State = DlOptiFabricLoader
  27. End Sub
  28. #Region "页面切换"
  29. '页面切换动画
  30. Public IsInSelectPage As Boolean = False
  31. Private IsFirstLoaded As Boolean = False
  32. Private Sub EnterSelectPage()
  33. If IsInSelectPage Then Exit Sub
  34. IsInSelectPage = True
  35. PanInner.Margin = New Thickness(25, 10, 25, 40)
  36. AutoSelectedFabricApi = False
  37. AutoSelectedOptiFabric = False
  38. IsSelectNameEdited = False
  39. PanSelect.Visibility = Visibility.Visible
  40. PanSelect.IsHitTestVisible = True
  41. PanMinecraft.IsHitTestVisible = False
  42. PanBack.IsHitTestVisible = False
  43. PanBack.ScrollToHome()
  44. DisabledPageAnimControls.Remove(BtnStart)
  45. BtnStart.Show = True
  46. CardOptiFine.IsSwaped = True
  47. CardLiteLoader.IsSwaped = True
  48. CardForge.IsSwaped = True
  49. CardNeoForge.IsSwaped = True
  50. CardFabric.IsSwaped = True
  51. CardFabricApi.IsSwaped = True
  52. CardOptiFabric.IsSwaped = True
  53. If Not Setup.Get("HintInstallBack") Then
  54. Setup.Set("HintInstallBack", True)
  55. Hint("点击 Minecraft 项即可返回游戏主版本选择页面!")
  56. End If
  57. '如果在选择页面按了刷新键,选择页的东西可能会由于动画被隐藏,但不会由于加载结束而再次显示,因此这里需要手动恢复
  58. For Each Control In GetAllAnimControls(PanSelect)
  59. Control.Opacity = 1
  60. If Control.RenderTransform Is Nothing OrElse TypeOf Control.RenderTransform Is TranslateTransform Then
  61. Control.RenderTransform = New TranslateTransform
  62. End If
  63. Next
  64. '启动 Forge 加载
  65. If SelectedMinecraftId.StartsWith("1.") Then
  66. Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("DlForgeVersion " & SelectedMinecraftId, AddressOf DlForgeVersionMain)
  67. LoadForge.State = ForgeLoader
  68. ForgeLoader.Start(SelectedMinecraftId)
  69. End If
  70. '启动 Fabric API、OptiFabric 加载
  71. DlFabricApiLoader.Start()
  72. DlOptiFabricLoader.Start()
  73. AniStart({
  74. AaOpacity(PanMinecraft, -PanMinecraft.Opacity, 90, 10),
  75. AaTranslateX(PanMinecraft, -50 - CType(PanMinecraft.RenderTransform, TranslateTransform).X, 100, 10),
  76. AaCode(
  77. Sub()
  78. PanBack.ScrollToHome()
  79. TextSelectName.Validate()
  80. OptiFine_Loaded()
  81. LiteLoader_Loaded()
  82. Forge_Loaded()
  83. NeoForge_Loaded()
  84. Fabric_Loaded()
  85. FabricApi_Loaded()
  86. OptiFabric_Loaded()
  87. SelectReload()
  88. End Sub, After:=True),
  89. AaOpacity(PanSelect, 1 - PanSelect.Opacity, 90, 100),
  90. AaTranslateX(PanSelect, -CType(PanSelect.RenderTransform, TranslateTransform).X, 200, 100, Ease:=New AniEaseOutFluent(AniEasePower.ExtraStrong)),
  91. AaCode(
  92. Sub()
  93. PanMinecraft.Visibility = Visibility.Collapsed
  94. PanBack.IsHitTestVisible = True
  95. '初始化 Binding
  96. If IsFirstLoaded Then Exit Sub
  97. IsFirstLoaded = True
  98. BtnOptiFineClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFine.MainTextBlock, .Mode = BindingMode.OneWay})
  99. BtnLiteLoaderClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardLiteLoader.MainTextBlock, .Mode = BindingMode.OneWay})
  100. BtnForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardForge.MainTextBlock, .Mode = BindingMode.OneWay})
  101. BtnNeoForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardNeoForge.MainTextBlock, .Mode = BindingMode.OneWay})
  102. BtnFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabric.MainTextBlock, .Mode = BindingMode.OneWay})
  103. BtnFabricApiClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabricApi.MainTextBlock, .Mode = BindingMode.OneWay})
  104. BtnOptiFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFabric.MainTextBlock, .Mode = BindingMode.OneWay})
  105. End Sub,, True)
  106. }, "FrmDownloadInstall SelectPageSwitch", True)
  107. End Sub
  108. Public Sub ExitSelectPage() Handles BtnBack.Click
  109. If Not IsInSelectPage Then Exit Sub
  110. IsInSelectPage = False
  111. PanInner.Margin = New Thickness(25, 10, 25, 25)
  112. DisabledPageAnimControls.Add(BtnStart)
  113. BtnStart.Show = False
  114. SelectClear() '清除已选择项
  115. PanMinecraft.Visibility = Visibility.Visible
  116. PanSelect.IsHitTestVisible = False
  117. PanMinecraft.IsHitTestVisible = True
  118. PanBack.IsHitTestVisible = False
  119. PanBack.ScrollToHome()
  120. AniStart({
  121. AaOpacity(PanSelect, -PanSelect.Opacity, 90, 10),
  122. AaTranslateX(PanSelect, 50 - CType(PanSelect.RenderTransform, TranslateTransform).X, 100, 10),
  123. AaCode(Sub() PanBack.ScrollToHome(), After:=True),
  124. AaOpacity(PanMinecraft, 1 - PanMinecraft.Opacity, 90, 100),
  125. AaTranslateX(PanMinecraft, -CType(PanMinecraft.RenderTransform, TranslateTransform).X, 200, 100, Ease:=New AniEaseOutFluent(AniEasePower.ExtraStrong)),
  126. AaCode(
  127. Sub()
  128. PanSelect.Visibility = Visibility.Collapsed
  129. PanBack.IsHitTestVisible = True
  130. End Sub,, True)
  131. }, "FrmDownloadInstall SelectPageSwitch")
  132. End Sub
  133. Public Sub MinecraftSelected(sender As MyListItem, e As MouseButtonEventArgs)
  134. SelectedMinecraftId = sender.Title
  135. SelectedMinecraftJsonUrl = sender.Tag("url").ToString
  136. SelectedMinecraftIcon = sender.Logo
  137. EnterSelectPage()
  138. End Sub
  139. #End Region
  140. #Region "选择"
  141. 'Minecraft
  142. Private SelectedMinecraftId As String
  143. Private SelectedMinecraftJsonUrl As String
  144. Private SelectedMinecraftIcon As String
  145. 'OptiFine
  146. Private SelectedOptiFine As DlOptiFineListEntry = Nothing
  147. Private Sub SetOptiFineInfoShow(IsShow As String)
  148. If PanOptiFineInfo.Tag = IsShow Then Exit Sub
  149. PanOptiFineInfo.Tag = IsShow
  150. If IsShow = "True" Then
  151. '显示信息栏
  152. AniStart({
  153. AaTranslateY(PanOptiFineInfo, -CType(PanOptiFineInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  154. AaOpacity(PanOptiFineInfo, 1 - PanOptiFineInfo.Opacity, 100, 90)
  155. }, "SetOptiFineInfoShow")
  156. Else
  157. '隐藏信息栏
  158. AniStart({
  159. AaTranslateY(PanOptiFineInfo, 6 - CType(PanOptiFineInfo.RenderTransform, TranslateTransform).Y, 200),
  160. AaOpacity(PanOptiFineInfo, -PanOptiFineInfo.Opacity, 100)
  161. }, "SetOptiFineInfoShow")
  162. End If
  163. End Sub
  164. 'LiteLoader
  165. Private SelectedLiteLoader As DlLiteLoaderListEntry = Nothing
  166. Private Sub SetLiteLoaderInfoShow(IsShow As String)
  167. If PanLiteLoaderInfo.Tag = IsShow Then Exit Sub
  168. PanLiteLoaderInfo.Tag = IsShow
  169. If IsShow = "True" Then
  170. '显示信息栏
  171. AniStart({
  172. AaTranslateY(PanLiteLoaderInfo, -CType(PanLiteLoaderInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  173. AaOpacity(PanLiteLoaderInfo, 1 - PanLiteLoaderInfo.Opacity, 100, 90)
  174. }, "SetLiteLoaderInfoShow")
  175. Else
  176. '隐藏信息栏
  177. AniStart({
  178. AaTranslateY(PanLiteLoaderInfo, 6 - CType(PanLiteLoaderInfo.RenderTransform, TranslateTransform).Y, 200),
  179. AaOpacity(PanLiteLoaderInfo, -PanLiteLoaderInfo.Opacity, 100)
  180. }, "SetLiteLoaderInfoShow")
  181. End If
  182. End Sub
  183. 'Forge
  184. Private SelectedForge As DlForgeVersionEntry = Nothing
  185. Private Sub SetForgeInfoShow(IsShow As String)
  186. If PanForgeInfo.Tag = IsShow Then Exit Sub
  187. PanForgeInfo.Tag = IsShow
  188. If IsShow = "True" Then
  189. '显示信息栏
  190. AniStart({
  191. AaTranslateY(PanForgeInfo, -CType(PanForgeInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  192. AaOpacity(PanForgeInfo, 1 - PanForgeInfo.Opacity, 100, 90)
  193. }, "SetForgeInfoShow")
  194. Else
  195. '隐藏信息栏
  196. AniStart({
  197. AaTranslateY(PanForgeInfo, 6 - CType(PanForgeInfo.RenderTransform, TranslateTransform).Y, 200),
  198. AaOpacity(PanForgeInfo, -PanForgeInfo.Opacity, 100)
  199. }, "SetForgeInfoShow")
  200. End If
  201. End Sub
  202. 'NeoForge
  203. Private SelectedNeoForge As DlNeoForgeListEntry = Nothing
  204. Private Sub SetNeoForgeInfoShow(IsShow As String)
  205. If PanNeoForgeInfo.Tag = IsShow Then Exit Sub
  206. PanNeoForgeInfo.Tag = IsShow
  207. If IsShow = "True" Then
  208. '显示信息栏
  209. AniStart({
  210. AaTranslateY(PanNeoForgeInfo, -CType(PanNeoForgeInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  211. AaOpacity(PanNeoForgeInfo, 1 - PanNeoForgeInfo.Opacity, 100, 90)
  212. }, "SetNeoForgeInfoShow")
  213. Else
  214. '隐藏信息栏
  215. AniStart({
  216. AaTranslateY(PanNeoForgeInfo, 6 - CType(PanNeoForgeInfo.RenderTransform, TranslateTransform).Y, 200),
  217. AaOpacity(PanNeoForgeInfo, -PanNeoForgeInfo.Opacity, 100)
  218. }, "SetNeoForgeInfoShow")
  219. End If
  220. End Sub
  221. 'Fabric
  222. Private SelectedFabric As String = Nothing
  223. Private Sub SetFabricInfoShow(IsShow As String)
  224. If PanFabricInfo.Tag = IsShow Then Exit Sub
  225. PanFabricInfo.Tag = IsShow
  226. If IsShow = "True" Then
  227. '显示信息栏
  228. AniStart({
  229. AaTranslateY(PanFabricInfo, -CType(PanFabricInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  230. AaOpacity(PanFabricInfo, 1 - PanFabricInfo.Opacity, 100, 90)
  231. }, "SetFabricInfoShow")
  232. Else
  233. '隐藏信息栏
  234. AniStart({
  235. AaTranslateY(PanFabricInfo, 6 - CType(PanFabricInfo.RenderTransform, TranslateTransform).Y, 200),
  236. AaOpacity(PanFabricInfo, -PanFabricInfo.Opacity, 100)
  237. }, "SetFabricInfoShow")
  238. End If
  239. End Sub
  240. 'FabricApi
  241. Private SelectedFabricApi As CompFile = Nothing
  242. Private Sub SetFabricApiInfoShow(IsShow As String)
  243. If PanFabricApiInfo.Tag = IsShow Then Exit Sub
  244. PanFabricApiInfo.Tag = IsShow
  245. If IsShow = "True" Then
  246. '显示信息栏
  247. AniStart({
  248. AaTranslateY(PanFabricApiInfo, -CType(PanFabricApiInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  249. AaOpacity(PanFabricApiInfo, 1 - PanFabricApiInfo.Opacity, 100, 90)
  250. }, "SetFabricApiInfoShow")
  251. Else
  252. '隐藏信息栏
  253. AniStart({
  254. AaTranslateY(PanFabricApiInfo, 6 - CType(PanFabricApiInfo.RenderTransform, TranslateTransform).Y, 200),
  255. AaOpacity(PanFabricApiInfo, -PanFabricApiInfo.Opacity, 100)
  256. }, "SetFabricApiInfoShow")
  257. End If
  258. End Sub
  259. 'OptiFabric
  260. Private SelectedOptiFabric As CompFile = Nothing
  261. Private Sub SetOptiFabricInfoShow(IsShow As String)
  262. If PanOptiFabricInfo.Tag = IsShow Then Exit Sub
  263. PanOptiFabricInfo.Tag = IsShow
  264. If IsShow = "True" Then
  265. '显示信息栏
  266. AniStart({
  267. AaTranslateY(PanOptiFabricInfo, -CType(PanOptiFabricInfo.RenderTransform, TranslateTransform).Y, 270, 100, Ease:=New AniEaseOutBack),
  268. AaOpacity(PanOptiFabricInfo, 1 - PanOptiFabricInfo.Opacity, 100, 90)
  269. }, "SetOptiFabricInfoShow")
  270. Else
  271. '隐藏信息栏
  272. AniStart({
  273. AaTranslateY(PanOptiFabricInfo, 6 - CType(PanOptiFabricInfo.RenderTransform, TranslateTransform).Y, 200),
  274. AaOpacity(PanOptiFabricInfo, -PanOptiFabricInfo.Opacity, 100)
  275. }, "SetOptiFabricInfoShow")
  276. End If
  277. End Sub
  278. Private IsReloading As Boolean = False '#3742 中,LoadOptiFineGetError 会初始化 LoadOptiFine,触发事件 LoadOptiFine.StateChanged,导致再次调用 SelectReload
  279. ''' <summary>
  280. ''' 重载已选择的项目的显示。
  281. ''' </summary>
  282. Private Sub SelectReload() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardNeoForge.Swap, LoadNeoForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
  283. If SelectedMinecraftId Is Nothing OrElse IsReloading Then Exit Sub
  284. IsReloading = True
  285. '主预览
  286. SelectNameUpdate()
  287. ImgLogo.Source = GetSelectLogo()
  288. 'OptiFine
  289. Dim OptiFineError As String = LoadOptiFineGetError()
  290. CardOptiFine.MainSwap.Visibility = If(OptiFineError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  291. If OptiFineError IsNot Nothing Then CardOptiFine.IsSwaped = True '例如在同时展开卡片时选择了不兼容项则强制折叠
  292. SetOptiFineInfoShow(CardOptiFine.IsSwaped)
  293. If SelectedOptiFine Is Nothing Then
  294. BtnOptiFineClear.Visibility = Visibility.Collapsed
  295. ImgOptiFine.Visibility = Visibility.Collapsed
  296. LabOptiFine.Text = If(OptiFineError, "可以添加")
  297. LabOptiFine.Foreground = ColorGray4
  298. Else
  299. BtnOptiFineClear.Visibility = Visibility.Visible
  300. ImgOptiFine.Visibility = Visibility.Visible
  301. LabOptiFine.Text = SelectedOptiFine.NameDisplay.Replace(SelectedMinecraftId & " ", "")
  302. LabOptiFine.Foreground = ColorGray1
  303. End If
  304. 'LiteLoader
  305. If Not SelectedMinecraftId.Contains("1.") OrElse Val(SelectedMinecraftId.Split(".")(1)) > 12 Then
  306. CardLiteLoader.Visibility = Visibility.Collapsed
  307. Else
  308. CardLiteLoader.Visibility = Visibility.Visible
  309. Dim LiteLoaderError As String = LoadLiteLoaderGetError()
  310. CardLiteLoader.MainSwap.Visibility = If(LiteLoaderError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  311. If LiteLoaderError IsNot Nothing Then CardLiteLoader.IsSwaped = True '例如在同时展开卡片时选择了不兼容项则强制折叠
  312. SetLiteLoaderInfoShow(CardLiteLoader.IsSwaped)
  313. If SelectedLiteLoader Is Nothing Then
  314. BtnLiteLoaderClear.Visibility = Visibility.Collapsed
  315. ImgLiteLoader.Visibility = Visibility.Collapsed
  316. LabLiteLoader.Text = If(LiteLoaderError, "可以添加")
  317. LabLiteLoader.Foreground = ColorGray4
  318. Else
  319. BtnLiteLoaderClear.Visibility = Visibility.Visible
  320. ImgLiteLoader.Visibility = Visibility.Visible
  321. LabLiteLoader.Text = SelectedLiteLoader.Inherit
  322. LabLiteLoader.Foreground = ColorGray1
  323. End If
  324. End If
  325. 'Forge
  326. Dim ForgeError As String = LoadForgeGetError()
  327. CardForge.MainSwap.Visibility = If(ForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  328. If ForgeError IsNot Nothing Then CardForge.IsSwaped = True
  329. SetForgeInfoShow(CardForge.IsSwaped)
  330. If SelectedForge Is Nothing Then
  331. BtnForgeClear.Visibility = Visibility.Collapsed
  332. ImgForge.Visibility = Visibility.Collapsed
  333. LabForge.Text = If(ForgeError, "可以添加")
  334. LabForge.Foreground = ColorGray4
  335. Else
  336. BtnForgeClear.Visibility = Visibility.Visible
  337. ImgForge.Visibility = Visibility.Visible
  338. LabForge.Text = SelectedForge.VersionName
  339. LabForge.Foreground = ColorGray1
  340. End If
  341. 'NeoForge
  342. If Not SelectedMinecraftId.Contains("1.") OrElse Val(SelectedMinecraftId.Split(".")(1)) <= 19 Then
  343. CardNeoForge.Visibility = Visibility.Collapsed
  344. Else
  345. CardNeoForge.Visibility = Visibility.Visible
  346. Dim NeoForgeError As String = LoadNeoForgeGetError()
  347. CardNeoForge.MainSwap.Visibility = If(NeoForgeError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  348. If NeoForgeError IsNot Nothing Then CardNeoForge.IsSwaped = True
  349. SetNeoForgeInfoShow(CardNeoForge.IsSwaped)
  350. If SelectedNeoForge Is Nothing Then
  351. BtnNeoForgeClear.Visibility = Visibility.Collapsed
  352. ImgNeoForge.Visibility = Visibility.Collapsed
  353. LabNeoForge.Text = If(NeoForgeError, "可以添加")
  354. LabNeoForge.Foreground = ColorGray4
  355. Else
  356. BtnNeoForgeClear.Visibility = Visibility.Visible
  357. ImgNeoForge.Visibility = Visibility.Visible
  358. LabNeoForge.Text = SelectedNeoForge.VersionName
  359. LabNeoForge.Foreground = ColorGray1
  360. End If
  361. End If
  362. 'Fabric
  363. If SelectedMinecraftId.Contains("1.") AndAlso Val(SelectedMinecraftId.Split(".")(1)) <= 13 Then
  364. CardFabric.Visibility = Visibility.Collapsed
  365. Else
  366. CardFabric.Visibility = Visibility.Visible
  367. Dim FabricError As String = LoadFabricGetError()
  368. CardFabric.MainSwap.Visibility = If(FabricError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  369. If FabricError IsNot Nothing Then CardFabric.IsSwaped = True
  370. SetFabricInfoShow(CardFabric.IsSwaped)
  371. If SelectedFabric Is Nothing Then
  372. BtnFabricClear.Visibility = Visibility.Collapsed
  373. ImgFabric.Visibility = Visibility.Collapsed
  374. LabFabric.Text = If(FabricError, "可以添加")
  375. LabFabric.Foreground = ColorGray4
  376. Else
  377. BtnFabricClear.Visibility = Visibility.Visible
  378. ImgFabric.Visibility = Visibility.Visible
  379. LabFabric.Text = SelectedFabric.Replace("+build", "")
  380. LabFabric.Foreground = ColorGray1
  381. End If
  382. End If
  383. 'FabricApi
  384. If SelectedFabric Is Nothing Then
  385. CardFabricApi.Visibility = Visibility.Collapsed
  386. Else
  387. CardFabricApi.Visibility = Visibility.Visible
  388. Dim FabricApiError As String = LoadFabricApiGetError()
  389. CardFabricApi.MainSwap.Visibility = If(FabricApiError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  390. If FabricApiError IsNot Nothing OrElse SelectedFabric Is Nothing Then CardFabricApi.IsSwaped = True
  391. SetFabricApiInfoShow(CardFabricApi.IsSwaped)
  392. If SelectedFabricApi Is Nothing Then
  393. BtnFabricApiClear.Visibility = Visibility.Collapsed
  394. ImgFabricApi.Visibility = Visibility.Collapsed
  395. LabFabricApi.Text = If(FabricApiError, "可以添加")
  396. LabFabricApi.Foreground = ColorGray4
  397. Else
  398. BtnFabricApiClear.Visibility = Visibility.Visible
  399. ImgFabricApi.Visibility = Visibility.Visible
  400. LabFabricApi.Text = SelectedFabricApi.DisplayName.Split("]")(1).Replace("Fabric API ", "").Replace(" build ", ".").Split("+").First.Trim
  401. LabFabricApi.Foreground = ColorGray1
  402. End If
  403. End If
  404. 'OptiFabric
  405. If SelectedFabric Is Nothing OrElse SelectedOptiFine Is Nothing Then
  406. CardOptiFabric.Visibility = Visibility.Collapsed
  407. Else
  408. CardOptiFabric.Visibility = Visibility.Visible
  409. Dim OptiFabricError As String = LoadOptiFabricGetError()
  410. CardOptiFabric.MainSwap.Visibility = If(OptiFabricError Is Nothing, Visibility.Visible, Visibility.Collapsed)
  411. If OptiFabricError IsNot Nothing OrElse SelectedFabric Is Nothing Then CardOptiFabric.IsSwaped = True
  412. SetOptiFabricInfoShow(CardOptiFabric.IsSwaped)
  413. If SelectedOptiFabric Is Nothing Then
  414. BtnOptiFabricClear.Visibility = Visibility.Collapsed
  415. ImgOptiFabric.Visibility = Visibility.Collapsed
  416. LabOptiFabric.Text = If(OptiFabricError, "可以添加")
  417. LabOptiFabric.Foreground = ColorGray4
  418. Else
  419. BtnOptiFabricClear.Visibility = Visibility.Visible
  420. ImgOptiFabric.Visibility = Visibility.Visible
  421. LabOptiFabric.Text = SelectedOptiFabric.DisplayName.ToLower.Replace("optifabric-", "").Replace(".jar", "").Trim.TrimStart("v")
  422. LabOptiFabric.Foreground = ColorGray1
  423. End If
  424. End If
  425. '主警告
  426. If SelectedFabric IsNot Nothing AndAlso SelectedFabricApi Is Nothing Then
  427. HintFabricAPI.Visibility = Visibility.Visible
  428. Else
  429. HintFabricAPI.Visibility = Visibility.Collapsed
  430. End If
  431. If SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing AndAlso SelectedOptiFabric Is Nothing Then
  432. If SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15") Then
  433. HintOptiFabric.Visibility = Visibility.Collapsed
  434. HintOptiFabricOld.Visibility = Visibility.Visible
  435. Else
  436. HintOptiFabric.Visibility = Visibility.Visible
  437. HintOptiFabricOld.Visibility = Visibility.Collapsed
  438. End If
  439. Else
  440. HintOptiFabric.Visibility = Visibility.Collapsed
  441. HintOptiFabricOld.Visibility = Visibility.Collapsed
  442. End If
  443. If SelectedMinecraftId.Contains("1.") AndAlso Val(SelectedMinecraftId.Split(".")(1)) >= 16 AndAlso SelectedOptiFine IsNot Nothing AndAlso
  444. (SelectedForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) Then
  445. HintModOptiFine.Visibility = Visibility.Visible
  446. Else
  447. HintModOptiFine.Visibility = Visibility.Collapsed
  448. End If
  449. '结束
  450. IsReloading = False
  451. End Sub
  452. ''' <summary>
  453. ''' 清空已选择的项目。
  454. ''' </summary>
  455. Private Sub SelectClear()
  456. SelectedMinecraftId = Nothing
  457. SelectedMinecraftJsonUrl = Nothing
  458. SelectedMinecraftIcon = Nothing
  459. SelectedOptiFine = Nothing
  460. SelectedLiteLoader = Nothing
  461. SelectedForge = Nothing
  462. SelectedNeoForge = Nothing
  463. SelectedFabric = Nothing
  464. SelectedFabricApi = Nothing
  465. SelectedOptiFabric = Nothing
  466. End Sub
  467. ''' <summary>
  468. ''' 获取版本图标。
  469. ''' </summary>
  470. Private Function GetSelectLogo() As String
  471. If SelectedFabric IsNot Nothing Then
  472. Return "pack://application:,,,/images/Blocks/Fabric.png"
  473. ElseIf SelectedForge IsNot Nothing Then
  474. Return "pack://application:,,,/images/Blocks/Anvil.png"
  475. ElseIf SelectedNeoForge IsNot Nothing Then
  476. Return "pack://application:,,,/images/Blocks/NeoForge.png"
  477. ElseIf SelectedLiteLoader IsNot Nothing Then
  478. Return "pack://application:,,,/images/Blocks/Egg.png"
  479. ElseIf SelectedOptiFine IsNot Nothing Then
  480. Return "pack://application:,,,/images/Blocks/GrassPath.png"
  481. Else
  482. Return SelectedMinecraftIcon
  483. End If
  484. End Function
  485. '版本名处理
  486. ''' <summary>
  487. ''' 获取默认版本名。
  488. ''' </summary>
  489. Private Function GetSelectName() As String
  490. Dim Name As String = SelectedMinecraftId
  491. If SelectedFabric IsNot Nothing Then
  492. Name += "-Fabric " & SelectedFabric.Replace("+build", "")
  493. End If
  494. If SelectedForge IsNot Nothing Then
  495. Name += "-Forge_" & SelectedForge.VersionName
  496. End If
  497. If SelectedNeoForge IsNot Nothing Then
  498. Name += "-NeoForge_" & SelectedNeoForge.VersionName
  499. End If
  500. If SelectedLiteLoader IsNot Nothing Then
  501. Name += "-LiteLoader"
  502. End If
  503. If SelectedOptiFine IsNot Nothing Then
  504. Name += "-OptiFine_" & SelectedOptiFine.NameDisplay.Replace(SelectedMinecraftId & " ", "").Replace(" ", "_")
  505. End If
  506. Return Name
  507. End Function
  508. Private IsSelectNameEdited As Boolean = False
  509. Private IsSelectNameChanging As Boolean = False
  510. Private Sub SelectNameUpdate()
  511. If IsSelectNameEdited OrElse IsSelectNameChanging Then Exit Sub
  512. IsSelectNameChanging = True
  513. TextSelectName.Text = GetSelectName()
  514. IsSelectNameChanging = False
  515. End Sub
  516. Private Sub TextSelectName_TextChanged(sender As Object, e As TextChangedEventArgs) Handles TextSelectName.TextChanged
  517. If IsSelectNameChanging Then Exit Sub
  518. IsSelectNameEdited = True
  519. SelectReload()
  520. End Sub
  521. Private Sub TextSelectName_ValidateChanged(sender As Object, e As EventArgs) Handles TextSelectName.ValidateChanged
  522. BtnStart.IsEnabled = TextSelectName.IsValidated
  523. End Sub
  524. #End Region
  525. #Region "加载器"
  526. '结果数据化
  527. Private Sub LoadMinecraft_OnFinish()
  528. ExitSelectPage() '返回
  529. Try
  530. Dim Dict As New Dictionary(Of String, List(Of JObject)) From {
  531. {"正式版", New List(Of JObject)}, {"预览版", New List(Of JObject)}, {"远古版", New List(Of JObject)}, {"愚人节版", New List(Of JObject)}
  532. }
  533. Dim Versions As JArray = DlClientListLoader.Output.Value("versions")
  534. For Each Version As JObject In Versions
  535. '确定分类
  536. Dim Type As String = Version("type")
  537. Select Case Type
  538. Case "release"
  539. Type = "正式版"
  540. Case "snapshot"
  541. Type = "预览版"
  542. 'Mojang 误分类
  543. If Version("id").ToString.StartsWith("1.") AndAlso
  544. Not Version("id").ToString.ToLower.Contains("combat") AndAlso
  545. Not Version("id").ToString.ToLower.Contains("rc") AndAlso
  546. Not Version("id").ToString.ToLower.Contains("experimental") AndAlso
  547. Not Version("id").ToString.ToLower.Contains("pre") Then
  548. Type = "正式版"
  549. Version("type") = "release"
  550. End If
  551. '愚人节版本
  552. Select Case Version("id").ToString.ToLower
  553. Case "20w14infinite", "20w14∞"
  554. Type = "愚人节版"
  555. Version("id") = "20w14∞"
  556. Version("type") = "special"
  557. Version.Add("lore", GetMcFoolName(Version("id")))
  558. Case "3d shareware v1.34", "1.rv-pre1", "15w14a", "2.0", "22w13oneblockatatime", "23w13a_or_b", "24w14potato"
  559. Type = "愚人节版"
  560. Version("type") = "special"
  561. Version.Add("lore", GetMcFoolName(Version("id")))
  562. Case Else '4/1 自动视作愚人节版
  563. Dim ReleaseDate = Version("releaseTime").Value(Of Date).ToUniversalTime().AddHours(2)
  564. If ReleaseDate.Month = 4 AndAlso ReleaseDate.Day = 1 Then
  565. Type = "愚人节版"
  566. Version("type") = "special"
  567. End If
  568. End Select
  569. Case "special"
  570. '已被处理的愚人节版
  571. Type = "愚人节版"
  572. Case Else
  573. Type = "远古版"
  574. End Select
  575. '加入辞典
  576. Dict(Type).Add(Version)
  577. Next
  578. '排序
  579. For Each Pair In Dict.ToList
  580. Dict(Pair.Key) = Pair.Value.OrderByDescending(Function(j) j("releaseTime").Value(Of Date)).ToList
  581. Next
  582. '清空当前
  583. PanMinecraft.Children.Clear()
  584. '添加最新版本
  585. Dim CardInfo As New MyCard With {.Title = "最新版本", .Margin = New Thickness(0, 15, 0, 15), .SwapType = 2}
  586. Dim TopestVersions As New List(Of JObject)
  587. Dim Release As JObject = Dict("正式版")(0).DeepClone()
  588. Release("lore") = "最新正式版,发布于 " & Release("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
  589. TopestVersions.Add(Release)
  590. If Dict("正式版")(0)("releaseTime").Value(Of Date) < Dict("预览版")(0)("releaseTime").Value(Of Date) Then
  591. Dim Snapshot As JObject = Dict("预览版")(0).DeepClone()
  592. Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
  593. TopestVersions.Add(Snapshot)
  594. End If
  595. Dim PanInfo As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = TopestVersions}
  596. MyCard.StackInstall(PanInfo, 7)
  597. CardInfo.Children.Add(PanInfo)
  598. PanMinecraft.Children.Insert(0, CardInfo)
  599. '添加其他版本
  600. For Each Pair As KeyValuePair(Of String, List(Of JObject)) In Dict
  601. If Not Pair.Value.Any() Then Continue For
  602. '增加卡片
  603. Dim NewCard As New MyCard With {.Title = Pair.Key & " (" & Pair.Value.Count & ")", .Margin = New Thickness(0, 0, 0, 15), .SwapType = 7}
  604. 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}
  605. NewCard.Children.Add(NewStack)
  606. NewCard.SwapControl = NewStack
  607. NewCard.IsSwaped = True
  608. PanMinecraft.Children.Add(NewCard)
  609. Next
  610. '自动选择版本
  611. If McVersionWaitingForSelect Is Nothing Then Exit Try
  612. Log("[Download] 自动选择 MC 版本:" & McVersionWaitingForSelect)
  613. For Each Version As JObject In Versions
  614. If Version("id").ToString <> McVersionWaitingForSelect Then Continue For
  615. Dim Item = McDownloadListItem(Version, Sub()
  616. End Sub, False)
  617. MinecraftSelected(Item, Nothing)
  618. Next
  619. Catch ex As Exception
  620. Log(ex, "可视化安装版本列表出错", LogLevel.Feedback)
  621. End Try
  622. End Sub
  623. ''' <summary>
  624. ''' 当 MC 版本列表加载完时,立即自动选择的版本。用于外部调用。
  625. ''' </summary>
  626. Public Shared McVersionWaitingForSelect As String = Nothing
  627. #End Region
  628. #Region "OptiFine 列表"
  629. ''' <summary>
  630. ''' 获取 OptiFine 的加载异常信息。若正常则返回 Nothing。
  631. ''' </summary>
  632. Private Function LoadOptiFineGetError() As String
  633. If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
  634. If LoadOptiFine Is Nothing OrElse LoadOptiFine.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
  635. If LoadOptiFine.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFine.State, Object).Error.Message
  636. '检查 Forge 1.13 - 1.14.3:全部不兼容
  637. If SelectedForge IsNot Nothing AndAlso
  638. VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
  639. Return "与 Forge 不兼容"
  640. End If
  641. '检查 Forge 版本
  642. Dim HasAny As Boolean = False
  643. Dim HasRequiredVersion As Boolean = False
  644. For Each OptiFineVersion As DlOptiFineListEntry In DlOptiFineListLoader.Output.Value
  645. If Not OptiFineVersion.NameDisplay.StartsWith(SelectedMinecraftId & " ") Then Continue For '不是同一个大版本
  646. HasAny = True
  647. If SelectedForge Is Nothing Then Return Nothing '未选择 Forge
  648. If IsOptiFineSuitForForge(OptiFineVersion, SelectedForge) Then Return Nothing '该版本可用
  649. If OptiFineVersion.RequiredForgeVersion IsNot Nothing Then HasRequiredVersion = True
  650. Next
  651. If Not HasAny Then
  652. Return "不可用"
  653. ElseIf HasRequiredVersion Then
  654. Return "仅兼容特定版本的 Forge"
  655. Else
  656. Return "与 Forge 不兼容"
  657. End If
  658. End Function
  659. '检查某个 OptiFine 是否与某个 Forge 兼容
  660. Private Function IsOptiFineSuitForForge(OptiFine As DlOptiFineListEntry, Forge As DlForgeVersionEntry)
  661. If Forge.Inherit <> OptiFine.Inherit Then Return False '不是同一个大版本
  662. If OptiFine.RequiredForgeVersion Is Nothing Then Return False '不兼容 Forge
  663. If String.IsNullOrWhiteSpace(OptiFine.RequiredForgeVersion) Then Return True '#4183
  664. If OptiFine.RequiredForgeVersion.Contains(".") Then 'XX.X.XXX
  665. Return VersionSortInteger(Forge.Version.ToString, OptiFine.RequiredForgeVersion) = 0
  666. Else 'XXXX
  667. Return Forge.Version.Revision = OptiFine.RequiredForgeVersion
  668. End If
  669. End Function
  670. '限制展开
  671. Private Sub CardOptiFine_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardOptiFine.PreviewSwap
  672. If LoadOptiFineGetError() IsNot Nothing Then e.Handled = True
  673. End Sub
  674. ''' <summary>
  675. ''' 尝试重新可视化 OptiFine 版本列表。
  676. ''' </summary>
  677. Private Sub OptiFine_Loaded() Handles LoadOptiFine.StateChanged
  678. Try
  679. If DlOptiFineListLoader.State <> LoadState.Finished Then Exit Sub
  680. '获取版本列表
  681. Dim Versions As New List(Of DlOptiFineListEntry)
  682. For Each Version As DlOptiFineListEntry In DlOptiFineListLoader.Output.Value
  683. If SelectedForge IsNot Nothing AndAlso Not IsOptiFineSuitForForge(Version, SelectedForge) Then Continue For
  684. If Version.NameDisplay.StartsWith(SelectedMinecraftId & " ") Then Versions.Add(Version)
  685. Next
  686. If Not Versions.Any() Then Exit Sub
  687. '排序
  688. Versions = Versions.Sort(
  689. Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
  690. If Not Left.IsPreview AndAlso Right.IsPreview Then Return True
  691. If Left.IsPreview AndAlso Not Right.IsPreview Then Return False
  692. Return VersionSortBoolean(Left.NameDisplay, Right.NameDisplay)
  693. End Function)
  694. '可视化
  695. PanOptiFine.Children.Clear()
  696. For Each Version In Versions
  697. PanOptiFine.Children.Add(OptiFineDownloadListItem(Version, AddressOf OptiFine_Selected, False))
  698. Next
  699. Catch ex As Exception
  700. Log(ex, "可视化 OptiFine 安装版本列表出错", LogLevel.Feedback)
  701. End Try
  702. End Sub
  703. '选择与清除
  704. Private Sub OptiFine_Selected(sender As MyListItem, e As EventArgs)
  705. SelectedOptiFine = sender.Tag
  706. If SelectedForge IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedForge = Nothing
  707. OptiFabric_Loaded()
  708. Forge_Loaded()
  709. NeoForge_Loaded()
  710. CardOptiFine.IsSwaped = True
  711. SelectReload()
  712. End Sub
  713. Private Sub OptiFine_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFineClear.MouseLeftButtonUp
  714. SelectedOptiFine = Nothing
  715. SelectedOptiFabric = Nothing
  716. AutoSelectedOptiFabric = False
  717. CardOptiFine.IsSwaped = True
  718. e.Handled = True
  719. Forge_Loaded()
  720. NeoForge_Loaded()
  721. SelectReload()
  722. End Sub
  723. #End Region
  724. #Region "LiteLoader 列表"
  725. ''' <summary>
  726. ''' 获取 LiteLoader 的加载异常信息。若正常则返回 Nothing。
  727. ''' </summary>
  728. Private Function LoadLiteLoaderGetError() As String
  729. If Not SelectedMinecraftId.Contains("1.") OrElse Val(SelectedMinecraftId.Split(".")(1)) > 12 Then Return "不可用"
  730. If LoadLiteLoader Is Nothing OrElse LoadLiteLoader.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
  731. If LoadLiteLoader.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadLiteLoader.State, Object).Error.Message
  732. For Each Version As DlLiteLoaderListEntry In DlLiteLoaderListLoader.Output.Value
  733. If Version.Inherit = SelectedMinecraftId Then Return Nothing
  734. Next
  735. Return "不可用"
  736. End Function
  737. '限制展开
  738. Private Sub CardLiteLoader_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardLiteLoader.PreviewSwap
  739. If LoadLiteLoaderGetError() IsNot Nothing Then e.Handled = True
  740. End Sub
  741. ''' <summary>
  742. ''' 尝试重新可视化 LiteLoader 版本列表。
  743. ''' </summary>
  744. Private Sub LiteLoader_Loaded() Handles LoadLiteLoader.StateChanged
  745. Try
  746. If DlLiteLoaderListLoader.State <> LoadState.Finished Then Exit Sub
  747. '获取版本列表
  748. Dim Versions As New List(Of DlLiteLoaderListEntry)
  749. For Each Version As DlLiteLoaderListEntry In DlLiteLoaderListLoader.Output.Value
  750. If Version.Inherit = SelectedMinecraftId Then Versions.Add(Version)
  751. Next
  752. If Not Versions.Any() Then Exit Sub
  753. '可视化
  754. PanLiteLoader.Children.Clear()
  755. For Each Version In Versions
  756. PanLiteLoader.Children.Add(LiteLoaderDownloadListItem(Version, AddressOf LiteLoader_Selected, False))
  757. Next
  758. Catch ex As Exception
  759. Log(ex, "可视化 LiteLoader 安装版本列表出错", LogLevel.Feedback)
  760. End Try
  761. End Sub
  762. '选择与清除
  763. Private Sub LiteLoader_Selected(sender As MyListItem, e As EventArgs)
  764. SelectedLiteLoader = sender.Tag
  765. CardLiteLoader.IsSwaped = True
  766. SelectReload()
  767. End Sub
  768. Private Sub LiteLoader_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnLiteLoaderClear.MouseLeftButtonUp
  769. SelectedLiteLoader = Nothing
  770. CardLiteLoader.IsSwaped = True
  771. e.Handled = True
  772. SelectReload()
  773. End Sub
  774. #End Region
  775. #Region "Forge 列表"
  776. ''' <summary>
  777. ''' 获取 Forge 的加载异常信息。若正常则返回 Nothing。
  778. ''' </summary>
  779. Private Function LoadForgeGetError() As String
  780. If Not SelectedMinecraftId.StartsWith("1.") Then Return "不可用"
  781. If Not LoadForge.State.IsLoader Then Return "加载中……"
  782. Dim Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = LoadForge.State
  783. If SelectedMinecraftId <> Loader.Input Then Return "加载中……"
  784. If Loader.State = LoadState.Loading Then Return "加载中……"
  785. If Loader.State = LoadState.Failed Then
  786. Dim ErrorMessage As String = Loader.Error.Message
  787. If ErrorMessage.Contains("不可用") Then
  788. Return "不可用"
  789. Else
  790. Return "获取版本列表失败:" & ErrorMessage
  791. End If
  792. End If
  793. If Loader.State <> LoadState.Finished Then Return "获取版本列表失败:未知错误,状态为 " & GetStringFromEnum(Loader.State)
  794. Dim NotSuitForOptiFine As Boolean = False
  795. For Each Version In Loader.Output
  796. If Version.Category = "universal" OrElse Version.Category = "client" Then Continue For '跳过无法自动安装的版本
  797. If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
  798. If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
  799. If SelectedOptiFine IsNot Nothing AndAlso
  800. VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
  801. Return "与 OptiFine 不兼容" '1.13 ~ 1.14.3 OptiFine 检查
  802. End If
  803. If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, Version) Then
  804. NotSuitForOptiFine = True '与 OptiFine 不兼容
  805. Continue For
  806. End If
  807. Return Nothing
  808. Next
  809. Return If(NotSuitForOptiFine, "与 OptiFine 不兼容", "该版本不支持自动安装")
  810. End Function
  811. '限制展开
  812. Private Sub CardForge_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardForge.PreviewSwap
  813. If LoadForgeGetError() IsNot Nothing Then e.Handled = True
  814. End Sub
  815. ''' <summary>
  816. ''' 尝试重新可视化 Forge 版本列表。
  817. ''' </summary>
  818. Private Sub Forge_Loaded() Handles LoadForge.StateChanged
  819. Try
  820. If Not LoadForge.State.IsLoader Then Exit Sub
  821. Dim Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = LoadForge.State
  822. If SelectedMinecraftId <> Loader.Input Then Exit Sub
  823. If Loader.State <> LoadState.Finished Then Exit Sub
  824. '获取要显示的版本
  825. Dim Versions = Loader.Output.ToList '复制数组,以免 Output 在实例化后变空
  826. If Not Loader.Output.Any() Then Exit Sub
  827. PanForge.Children.Clear()
  828. Versions = Versions.Where(
  829. Function(v)
  830. If v.Category = "universal" OrElse v.Category = "client" Then Return False '跳过无法自动安装的版本
  831. If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, v) Then Return False
  832. Return True
  833. End Function).OrderByDescending(Function(v) v.Version).ToList()
  834. ForgeDownloadListItemPreload(PanForge, Versions, AddressOf Forge_Selected, False)
  835. For Each Version In Versions
  836. PanForge.Children.Add(ForgeDownloadListItem(Version, AddressOf Forge_Selected, False))
  837. Next
  838. Catch ex As Exception
  839. Log(ex, "可视化 Forge 安装版本列表出错", LogLevel.Feedback)
  840. End Try
  841. End Sub
  842. '选择与清除
  843. Private Sub Forge_Selected(sender As MyListItem, e As EventArgs)
  844. SelectedForge = sender.Tag
  845. CardForge.IsSwaped = True
  846. If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedOptiFine = Nothing
  847. OptiFine_Loaded()
  848. SelectReload()
  849. End Sub
  850. Private Sub Forge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnForgeClear.MouseLeftButtonUp
  851. SelectedForge = Nothing
  852. CardForge.IsSwaped = True
  853. e.Handled = True
  854. OptiFine_Loaded()
  855. SelectReload()
  856. End Sub
  857. #End Region
  858. #Region "NeoForge 列表"
  859. ''' <summary>
  860. ''' 获取 NeoForge 的加载异常信息。若正常则返回 Nothing。
  861. ''' </summary>
  862. Private Function LoadNeoForgeGetError() As String
  863. If Not SelectedMinecraftId.StartsWith("1.") Then Return "不可用"
  864. If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
  865. If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
  866. If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
  867. If LoadNeoForge Is Nothing OrElse LoadNeoForge.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
  868. If LoadNeoForge.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadNeoForge.State, Object).Error.Message
  869. If DlNeoForgeListLoader.Output.Value.Any(Function(v) v.Inherit = SelectedMinecraftId) Then
  870. Return Nothing
  871. Else
  872. Return "不可用"
  873. End If
  874. End Function
  875. '限制展开
  876. Private Sub CardNeoForge_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardNeoForge.PreviewSwap
  877. If LoadNeoForgeGetError() IsNot Nothing Then e.Handled = True
  878. End Sub
  879. ''' <summary>
  880. ''' 尝试重新可视化 NeoForge 版本列表。
  881. ''' </summary>
  882. Private Sub NeoForge_Loaded() Handles LoadNeoForge.StateChanged
  883. Try
  884. '获取版本列表
  885. If DlNeoForgeListLoader.State <> LoadState.Finished Then Exit Sub
  886. Dim Versions = DlNeoForgeListLoader.Output.Value.Where(Function(v) v.Inherit = SelectedMinecraftId).ToList
  887. If Not Versions.Any() Then Exit Sub
  888. '可视化
  889. PanNeoForge.Children.Clear()
  890. NeoForgeDownloadListItemPreload(PanNeoForge, Versions, AddressOf NeoForge_Selected, False)
  891. For Each Version In Versions
  892. PanNeoForge.Children.Add(NeoForgeDownloadListItem(Version, AddressOf NeoForge_Selected, False))
  893. Next
  894. Catch ex As Exception
  895. Log(ex, "可视化 NeoForge 安装版本列表出错", LogLevel.Feedback)
  896. End Try
  897. End Sub
  898. '选择与清除
  899. Private Sub NeoForge_Selected(sender As MyListItem, e As EventArgs)
  900. SelectedNeoForge = sender.Tag
  901. CardNeoForge.IsSwaped = True
  902. OptiFine_Loaded()
  903. SelectReload()
  904. End Sub
  905. Private Sub NeoForge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnNeoForgeClear.MouseLeftButtonUp
  906. SelectedNeoForge = Nothing
  907. CardNeoForge.IsSwaped = True
  908. e.Handled = True
  909. OptiFine_Loaded()
  910. SelectReload()
  911. End Sub
  912. #End Region
  913. #Region "Fabric 列表"
  914. ''' <summary>
  915. ''' 获取 Fabric 的加载异常信息。若正常则返回 Nothing。
  916. ''' </summary>
  917. Private Function LoadFabricGetError() As String
  918. If LoadFabric Is Nothing OrElse LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
  919. If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadFabric.State, Object).Error.Message
  920. For Each Version As JObject In DlFabricListLoader.Output.Value("game")
  921. If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3") Then
  922. If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
  923. If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
  924. Return Nothing
  925. End If
  926. Next
  927. Return "不可用"
  928. End Function
  929. '限制展开
  930. Private Sub CardFabric_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardFabric.PreviewSwap
  931. If LoadFabricGetError() IsNot Nothing Then e.Handled = True
  932. End Sub
  933. ''' <summary>
  934. ''' 尝试重新可视化 Fabric 版本列表。
  935. ''' </summary>
  936. Private Sub Fabric_Loaded() Handles LoadFabric.StateChanged
  937. Try
  938. If DlFabricListLoader.State <> LoadState.Finished Then Exit Sub
  939. '获取版本列表
  940. Dim Versions As JArray = DlFabricListLoader.Output.Value("loader")
  941. If Not Versions.Any() Then Exit Sub
  942. '可视化
  943. PanFabric.Children.Clear()
  944. PanFabric.Tag = Versions
  945. CardFabric.SwapControl = PanFabric
  946. CardFabric.SwapType = 12
  947. Catch ex As Exception
  948. Log(ex, "可视化 Fabric 安装版本列表出错", LogLevel.Feedback)
  949. End Try
  950. End Sub
  951. '选择与清除
  952. Public Sub Fabric_Selected(sender As MyListItem, e As EventArgs)
  953. SelectedFabric = sender.Tag("version").ToString
  954. FabricApi_Loaded()
  955. OptiFabric_Loaded()
  956. CardFabric.IsSwaped = True
  957. SelectReload()
  958. End Sub
  959. Private Sub Fabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricClear.MouseLeftButtonUp
  960. SelectedFabric = Nothing
  961. SelectedFabricApi = Nothing
  962. AutoSelectedFabricApi = False
  963. SelectedOptiFabric = Nothing
  964. AutoSelectedOptiFabric = False
  965. CardFabric.IsSwaped = True
  966. e.Handled = True
  967. SelectReload()
  968. End Sub
  969. #End Region
  970. #Region "Fabric API 列表"
  971. ''' <summary>
  972. ''' 从显示名判断该 API 是否与某版本适配。
  973. ''' </summary>
  974. Public Shared Function IsSuitableFabricApi(DisplayName As String, MinecraftVersion As String) As Boolean
  975. Try
  976. If DisplayName Is Nothing OrElse MinecraftVersion Is Nothing Then Return False
  977. DisplayName = DisplayName.ToLower : MinecraftVersion = MinecraftVersion.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3").ToLower
  978. If DisplayName.StartsWith("[" & MinecraftVersion & "]") Then Return True
  979. If Not DisplayName.Contains("/") OrElse Not DisplayName.Contains("]") Then Return False
  980. '直接的判断(例如 1.18.1/22w03a)
  981. For Each Part As String In DisplayName.BeforeFirst("]").TrimStart("[").Split("/")
  982. If Part = MinecraftVersion Then Return True
  983. Next
  984. '将版本名分割语素(例如 1.16.4/5)
  985. Dim Lefts = RegexSearch(DisplayName.BeforeFirst("]"), "[a-z/]+|[0-9/]+")
  986. Dim Rights = RegexSearch(MinecraftVersion.BeforeFirst("]"), "[a-z/]+|[0-9/]+")
  987. '对每段进行判断
  988. Dim i As Integer = 0
  989. While True
  990. '两边均缺失,感觉是一个东西
  991. If Lefts.Count - 1 < i AndAlso Rights.Count - 1 < i Then Return True
  992. '确定两边是否一致
  993. Dim LeftValue As String = If(Lefts.Count - 1 < i, "-1", Lefts(i))
  994. Dim RightValue As String = If(Rights.Count - 1 < i, "-1", Rights(i))
  995. If Not LeftValue.Contains("/") Then
  996. If LeftValue <> RightValue Then Return False
  997. Else
  998. '左边存在斜杠
  999. If Not LeftValue.Contains(RightValue) Then Return False
  1000. End If
  1001. i += 1
  1002. End While
  1003. Return True
  1004. Catch ex As Exception
  1005. Log(ex, "判断 Fabric API 版本适配性出错(" & DisplayName & ", " & MinecraftVersion & ")")
  1006. Return False
  1007. End Try
  1008. End Function
  1009. ''' <summary>
  1010. ''' 获取 FabricApi 的加载异常信息。若正常则返回 Nothing。
  1011. ''' </summary>
  1012. Private Function LoadFabricApiGetError() As String
  1013. If LoadFabricApi Is Nothing OrElse LoadFabricApi.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
  1014. If LoadFabricApi.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadFabricApi.State, Object).Error.Message
  1015. If DlFabricApiLoader.Output Is Nothing Then
  1016. If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
  1017. Return "加载中……"
  1018. End If
  1019. For Each Version In DlFabricApiLoader.Output
  1020. If Not IsSuitableFabricApi(Version.DisplayName, SelectedMinecraftId) Then Continue For
  1021. If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
  1022. Return Nothing
  1023. Next
  1024. Return "不可用"
  1025. End Function
  1026. '限制展开
  1027. Private Sub CardFabricApi_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardFabricApi.PreviewSwap
  1028. If LoadFabricApiGetError() IsNot Nothing Then e.Handled = True
  1029. End Sub
  1030. Private AutoSelectedFabricApi As Boolean = False
  1031. ''' <summary>
  1032. ''' 尝试重新可视化 FabricApi 版本列表。
  1033. ''' </summary>
  1034. Private Sub FabricApi_Loaded() Handles LoadFabricApi.StateChanged
  1035. Try
  1036. If DlFabricApiLoader.State <> LoadState.Finished Then Exit Sub
  1037. If SelectedMinecraftId Is Nothing OrElse SelectedFabric Is Nothing Then Exit Sub
  1038. '获取版本列表
  1039. Dim Versions As New List(Of CompFile)
  1040. For Each Version In DlFabricApiLoader.Output
  1041. If IsSuitableFabricApi(Version.DisplayName, SelectedMinecraftId) Then
  1042. If Not Version.DisplayName.StartsWith("[") Then
  1043. Log("[Download] 已特判修改 Fabric API 显示名:" & Version.DisplayName, LogLevel.Debug)
  1044. Version.DisplayName = "[" & SelectedMinecraftId & "] " & Version.DisplayName
  1045. End If
  1046. Versions.Add(Version)
  1047. End If
  1048. Next
  1049. If Not Versions.Any() Then Exit Sub
  1050. Versions = Versions.OrderByDescending(Function(v) v.ReleaseDate).ToList
  1051. '可视化
  1052. PanFabricApi.Children.Clear()
  1053. For Each Version In Versions
  1054. If Not IsSuitableFabricApi(Version.DisplayName, SelectedMinecraftId) Then Continue For
  1055. PanFabricApi.Children.Add(FabricApiDownloadListItem(Version, AddressOf FabricApi_Selected))
  1056. Next
  1057. '自动选择 Fabric API
  1058. If Not AutoSelectedFabricApi Then
  1059. AutoSelectedFabricApi = True
  1060. Log($"[Download] 已自动选择 Fabric API:{CType(PanFabricApi.Children(0), MyListItem).Title}")
  1061. FabricApi_Selected(PanFabricApi.Children(0), Nothing)
  1062. End If
  1063. Catch ex As Exception
  1064. Log(ex, "可视化 Fabric API 安装版本列表出错", LogLevel.Feedback)
  1065. End Try
  1066. End Sub
  1067. '选择与清除
  1068. Private Sub FabricApi_Selected(sender As MyListItem, e As EventArgs)
  1069. SelectedFabricApi = sender.Tag
  1070. CardFabricApi.IsSwaped = True
  1071. SelectReload()
  1072. End Sub
  1073. Private Sub FabricApi_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricApiClear.MouseLeftButtonUp
  1074. SelectedFabricApi = Nothing
  1075. CardFabricApi.IsSwaped = True
  1076. e.Handled = True
  1077. SelectReload()
  1078. End Sub
  1079. #End Region
  1080. #Region "OptiFabric 列表"
  1081. ''' <summary>
  1082. ''' 从显示名判断该 Mod 是否与某版本适配。
  1083. ''' </summary>
  1084. Private Function IsSuitableOptiFabric(ModFile As CompFile, MinecraftVersion As String) As Boolean
  1085. Try
  1086. If MinecraftVersion Is Nothing Then Return False
  1087. Return ModFile.GameVersions.Contains(MinecraftVersion)
  1088. Catch ex As Exception
  1089. Log(ex, "判断 OptiFabric 版本适配性出错(" & MinecraftVersion & ")")
  1090. Return False
  1091. End Try
  1092. End Function
  1093. Private AutoSelectedOptiFabric As Boolean = False
  1094. ''' <summary>
  1095. ''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
  1096. ''' </summary>
  1097. Private Function LoadOptiFabricGetError() As String
  1098. If SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15") Then Return "不兼容老版本 Fabric,请手动下载 OptiFabric Origins"
  1099. If LoadOptiFabric Is Nothing OrElse LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "加载中……"
  1100. If LoadOptiFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFabric.State, Object).Error.Message
  1101. If DlOptiFabricLoader.Output Is Nothing Then
  1102. If SelectedFabric Is Nothing AndAlso SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine 与 Fabric"
  1103. If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
  1104. If SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine"
  1105. Return "加载中……"
  1106. End If
  1107. For Each Version In DlOptiFabricLoader.Output
  1108. If Not IsSuitableOptiFabric(Version, SelectedMinecraftId) Then Continue For '2135#
  1109. If SelectedFabric Is Nothing AndAlso SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine 与 Fabric"
  1110. If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
  1111. If SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine"
  1112. Return Nothing '通过检查
  1113. Next
  1114. Return "不可用"
  1115. End Function
  1116. '限制展开
  1117. Private Sub CardOptiFabric_PreviewSwap(sender As Object, e As RouteEventArgs) Handles CardOptiFabric.PreviewSwap
  1118. If LoadOptiFabricGetError() IsNot Nothing Then e.Handled = True
  1119. End Sub
  1120. ''' <summary>
  1121. ''' 尝试重新可视化 OptiFabric 版本列表。
  1122. ''' </summary>
  1123. Private Sub OptiFabric_Loaded() Handles LoadOptiFabric.StateChanged
  1124. Try
  1125. If DlOptiFabricLoader.State <> LoadState.Finished Then Exit Sub
  1126. If SelectedMinecraftId Is Nothing OrElse SelectedFabric Is Nothing OrElse SelectedOptiFine Is Nothing Then Exit Sub
  1127. '获取版本列表
  1128. Dim Versions As New List(Of CompFile)
  1129. For Each Version In DlOptiFabricLoader.Output
  1130. If IsSuitableOptiFabric(Version, SelectedMinecraftId) Then Versions.Add(Version)
  1131. Next
  1132. If Not Versions.Any() Then Exit Sub
  1133. '排序
  1134. Versions = Versions.OrderByDescending(Function(v) v.ReleaseDate).ToList
  1135. '可视化
  1136. PanOptiFabric.Children.Clear()
  1137. For Each Version In Versions
  1138. If Not IsSuitableOptiFabric(Version, SelectedMinecraftId) Then Continue For
  1139. PanOptiFabric.Children.Add(OptiFabricDownloadListItem(Version, AddressOf OptiFabric_Selected))
  1140. Next
  1141. '自动选择 OptiFabric
  1142. If Not AutoSelectedOptiFabric AndAlso
  1143. Not (SelectedMinecraftId.StartsWith("1.14") OrElse SelectedMinecraftId.StartsWith("1.15")) Then '1.14~15 不自动选择
  1144. AutoSelectedOptiFabric = True
  1145. Log($"[Download] 已自动选择 OptiFabric:{CType(PanOptiFabric.Children(0), MyListItem).Title}")
  1146. OptiFabric_Selected(PanOptiFabric.Children(0), Nothing)
  1147. End If
  1148. Catch ex As Exception
  1149. Log(ex, "可视化 OptiFabric 安装版本列表出错", LogLevel.Feedback)
  1150. End Try
  1151. End Sub
  1152. '选择与清除
  1153. Private Sub OptiFabric_Selected(sender As MyListItem, e As EventArgs)
  1154. SelectedOptiFabric = sender.Tag
  1155. CardOptiFabric.IsSwaped = True
  1156. SelectReload()
  1157. End Sub
  1158. Private Sub OptiFabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFabricClear.MouseLeftButtonUp
  1159. SelectedOptiFabric = Nothing
  1160. CardOptiFabric.IsSwaped = True
  1161. e.Handled = True
  1162. SelectReload()
  1163. End Sub
  1164. #End Region
  1165. #Region "安装"
  1166. Private Sub TextSelectName_KeyDown(sender As Object, e As KeyEventArgs) Handles TextSelectName.KeyDown
  1167. If e.Key = Key.Enter AndAlso BtnStart.IsEnabled Then BtnStart_Click()
  1168. End Sub
  1169. Private Sub BtnStart_Click() Handles BtnStart.Click
  1170. '确认版本隔离
  1171. If (SelectedForge IsNot Nothing OrElse SelectedNeoForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) AndAlso
  1172. (Setup.Get("LaunchArgumentIndieV2") = 0 OrElse Setup.Get("LaunchArgumentIndieV2") = 2) Then
  1173. If MyMsgBox("你尚未开启版本隔离,这会导致多个版本共用同一个 Mod 文件夹。" & vbCrLf &
  1174. "因此游戏可能会因为读取到与当前版本不符的 Mod 而崩溃。" & vbCrLf &
  1175. "推荐在开始下载前,在 设置 → 启动选项 → 版本隔离 中开启版本隔离!", "版本隔离提示", "取消下载", "继续") = 1 Then
  1176. Exit Sub
  1177. End If
  1178. End If
  1179. '提交安装申请
  1180. Dim VersionName As String = TextSelectName.Text
  1181. Dim Request As New McInstallRequest With {
  1182. .TargetVersionName = VersionName,
  1183. .TargetVersionFolder = $"{PathMcFolder}versions\{VersionName}\",
  1184. .MinecraftJson = SelectedMinecraftJsonUrl,
  1185. .MinecraftName = SelectedMinecraftId,
  1186. .OptiFineEntry = SelectedOptiFine,
  1187. .ForgeEntry = SelectedForge,
  1188. .NeoForgeEntry = SelectedNeoForge,
  1189. .FabricVersion = SelectedFabric,
  1190. .FabricApi = SelectedFabricApi,
  1191. .OptiFabric = SelectedOptiFabric,
  1192. .LiteLoaderEntry = SelectedLiteLoader
  1193. }
  1194. If Not McInstall(Request) Then Exit Sub
  1195. '返回,这样在再次进入安装页面时这个版本就会显示文件夹已重复
  1196. ExitSelectPage()
  1197. End Sub
  1198. #End Region
  1199. End Class