PageDownloadInstall.xaml.vb 61 KB

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