PageDownloadInstall.xaml.vb 61 KB

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