PageDownloadInstall.xaml.vb 63 KB

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