PageDownloadInstall.xaml.vb 63 KB

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