PageDownloadInstall.xaml.vb 49 KB

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