PageDownloadInstall.xaml.vb 61 KB

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