PageLaunchLeft.xaml.vb 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. Imports System.Windows.Threading
  2. Public Class PageLaunchLeft
  3. '加载当前版本
  4. Private IsLoad As Boolean = False
  5. Private IsLoadFinished As Boolean = False
  6. Public Sub PageLaunchLeft_Loaded() Handles Me.Loaded
  7. If IsLoad Then RefreshPage(True, False)
  8. AprilPosTrans.X = 0
  9. AprilPosTrans.Y = 0
  10. If IsLoad Then Return
  11. IsLoad = True
  12. AniControlEnabled += 1
  13. '开始按钮
  14. AddHandler McInstanceListLoader.LoadingStateChanged, AddressOf RefreshButtonsUI
  15. AddHandler McFolderListLoader.LoadingStateChanged, AddressOf RefreshButtonsUI
  16. RefreshButtonsUI()
  17. '加载版本
  18. RunInNewThread(
  19. Sub()
  20. '自动整合包安装:准备
  21. Dim PackInstallPath As String = Nothing
  22. If FileUtils.Exists(Paths.Base & "modpack.zip") Then PackInstallPath = Paths.Base & "modpack.zip"
  23. If FileUtils.Exists(Paths.Base & "modpack.mrpack") Then PackInstallPath = Paths.Base & "modpack.mrpack"
  24. If PackInstallPath IsNot Nothing Then
  25. Logger.Warn($"需自动安装整合包:{PackInstallPath}")
  26. PageSelectLeft.CreateMcFolderInCurrentPath()
  27. McFolderListLoader.WaitForExit()
  28. End If
  29. '确认 Minecraft 文件夹存在
  30. If McFolderSelected = "" OrElse Not DirectoryUtils.Exists(McFolderSelected) Then
  31. '无效的文件夹
  32. If McFolderSelected = "" Then
  33. Logger.Info("没有已储存的 Minecraft 文件夹")
  34. Else
  35. Logger.Warn($"Minecraft 文件夹无效,该文件夹已不存在:{McFolderSelected}")
  36. End If
  37. McFolderListLoader.WaitForExit(IsForceRestart:=True)
  38. McFolderSelected = McFolderList.First.Location
  39. End If
  40. If Settings.Get(Of Boolean)("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
  41. '自动整合包安装
  42. If PackInstallPath IsNot Nothing Then
  43. Try
  44. Dim InstallLoader = ModpackInstall(PackInstallPath)
  45. Logger.Info($"自动安装整合包已开始:{PackInstallPath}")
  46. InstallLoader.WaitForExit()
  47. If InstallLoader.State = LoadState.Finished Then
  48. Logger.Info($"自动安装整合包成功,清理安装包:{PackInstallPath}")
  49. FileUtils.Delete(PackInstallPath)
  50. End If
  51. Catch ex As Exception
  52. If ex.IsCanceled Then
  53. Logger.Info($"自动安装整合包已取消:{PackInstallPath}")
  54. Else
  55. Logger.Error(ex, $"自动安装整合包失败:{PackInstallPath}", LogBehavior.Alert)
  56. End If
  57. End Try
  58. End If
  59. '确认 Minecraft 版本存在
  60. Dim Selection As String = ReadIni(McFolderSelected & "PCL.ini", "Version")
  61. Dim Instance As McInstance = If(Selection = "", Nothing, New McInstance(Selection))
  62. If Instance Is Nothing OrElse Not PathUtils.IsParentOf(McFolderSelected, Instance.PathVersion) OrElse Not Instance.Check() Then
  63. '无效的版本
  64. Logger.Info($"当前选择的 Minecraft 版本无效:{If(Instance Is Nothing, "null", Instance.PathVersion)}", If(IsNothing(Instance), LogBehavior.None, LogBehavior.ToastIfDebug))
  65. If Not McInstanceListLoader.State = LoadState.Finished Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
  66. If Not McInstanceList.Any() OrElse McInstanceList.First.Value(0).Logo.Contains("RedstoneBlock") Then
  67. Instance = Nothing
  68. Logger.Info("无可用 Minecraft 版本")
  69. Else
  70. Instance = McInstanceList.First.Value(0)
  71. Logger.Info($"自动选择 Minecraft 版本:{Instance.PathVersion}")
  72. End If
  73. End If
  74. RunInUi(
  75. Sub()
  76. McInstanceSelected = Instance '绕这一圈是为了避免 McVersionCheck 触发第二次版本改变
  77. IsLoadFinished = True
  78. RefreshButtonsUI()
  79. RefreshPage(False, False) '有可能选择的版本变化了,需要重新刷新
  80. If McLoginAble() = "" Then McLoginLoader.Start() '自动登录
  81. '用于自动化测试生成的程序是否可以正常运行
  82. If Environment.CommandLine.Contains("--test") Then
  83. RunInThread(
  84. Sub()
  85. Thread.Sleep(500)
  86. RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.Download))
  87. Thread.Sleep(500)
  88. RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadMod))
  89. Thread.Sleep(500)
  90. RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.Setup))
  91. Thread.Sleep(500)
  92. RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.Other))
  93. Thread.Sleep(500)
  94. RunInUi(Sub() BtnVersion_Click())
  95. Thread.Sleep(500)
  96. RunInUi(Sub() BtnMore_Click())
  97. Thread.Sleep(500)
  98. FormMain.EndProgramForce(123)
  99. End Sub)
  100. End If
  101. End Sub)
  102. End Sub, "Version Check", ThreadPriority.AboveNormal)
  103. '改变页面
  104. Dim LoginType = Settings.Get(Of McLoginType)("LoginType")
  105. If LoginType = McLoginType.Legacy OrElse LoginType = McLoginType.Ms Then CType(FindName("RadioLoginType" & LoginType), MyRadioButton).Checked = True
  106. RefreshPage(False, False)
  107. AniControlEnabled -= 1
  108. End Sub
  109. #Region "切换大页面"
  110. ''' <summary>
  111. ''' 切换至启动中页面。
  112. ''' </summary>
  113. Public Sub PageChangeToLaunching()
  114. '修改登陆方式
  115. Select Case Settings.Get(Of McLoginType)("LoginType")
  116. Case McLoginType.Legacy
  117. LabLaunchingMethod.Text = "离线登录"
  118. Case McLoginType.Ms
  119. LabLaunchingMethod.Text = "正版登录"
  120. Case McLoginType.Nide
  121. LabLaunchingMethod.Text = "统一通行证"
  122. Case McLoginType.Auth
  123. LabLaunchingMethod.Text = "Authlib-Injector"
  124. End Select
  125. '初始化页面
  126. LabLaunchingName.Text = McInstanceSelected.Name
  127. LabLaunchingStage.Text = "初始化"
  128. LabLaunchingTitle.Text = If(CurrentLaunchOptions?.SaveBatch Is Nothing, "正在启动游戏", "正在导出启动脚本")
  129. LabLaunchingProgress.Text = "0.00 %"
  130. LabLaunchingProgress.Opacity = 1
  131. LabLaunchingDownload.Visibility = Visibility.Visible
  132. LabLaunchingProgressLeft.Opacity = 0.6
  133. LabLaunchingDownload.Visibility = Visibility.Visible
  134. LabLaunchingDownload.Text = "0 B/s"
  135. LabLaunchingDownload.Opacity = 0
  136. LabLaunchingDownload.Visibility = Visibility.Collapsed
  137. LabLaunchingDownloadLeft.Opacity = 0
  138. LabLaunchingDownloadLeft.Visibility = Visibility.Collapsed
  139. ProgressLaunchingFinished.Width = New GridLength(0, GridUnitType.Star)
  140. ProgressLaunchingUnfinished.Width = New GridLength(1, GridUnitType.Star)
  141. PanLaunchingHint.Opacity = 0
  142. PanLaunchingHint.Visibility = Visibility.Collapsed
  143. PanLaunchingInfo.Width = Double.NaN '重置宽度改变动画
  144. McLaunchProcess = Nothing
  145. McLaunchWatcher = Nothing
  146. '获取 “你知道吗” 提示
  147. LabLaunchingHint.Text = PageOtherTest.GetRandomHint()
  148. '初始化其他页面
  149. PanInput.IsHitTestVisible = False
  150. PanLaunching.IsHitTestVisible = False
  151. LoadLaunching.State.LoadingState = MyLoading.MyLoadingState.Run
  152. PanLaunching.Visibility = Visibility.Visible
  153. AniStart({
  154. AaOpacity(PanInput, 0, 50), '略作延迟,这样如果预检测失败,不会出现奇怪的弹一下的动画
  155. AaOpacity(PanInput, -PanInput.Opacity, 110, , New AniEaseInFluent, True),
  156. AaScaleTransform(PanInput, 1.2 - CType(PanInput.RenderTransform, ScaleTransform).ScaleX, 160),
  157. AaOpacity(PanLaunching, 1 - PanLaunching.Opacity, 150, 100),
  158. AaScaleTransform(PanLaunching, 1 - CType(PanLaunching.RenderTransform, ScaleTransform).ScaleX, 500, 100, New AniEaseOutBack(AniEasePower.Weak)),
  159. AaCode(Sub() PanLaunching.IsHitTestVisible = True, 150)
  160. }, "Launch State Page")
  161. End Sub
  162. ''' <summary>
  163. ''' 切换至登录页面。
  164. ''' </summary>
  165. Public Sub PageChangeToLogin()
  166. PageGet(PageCurrent).Reload(KeepInput:=False)
  167. PanInput.IsHitTestVisible = False
  168. PanLaunching.IsHitTestVisible = False
  169. LoadLaunching.State.LoadingState = MyLoading.MyLoadingState.Stop
  170. PanInput.Visibility = Visibility.Visible
  171. AniStart({
  172. AaOpacity(PanLaunching, -PanLaunching.Opacity, 150),
  173. AaScaleTransform(PanLaunching, 0.8 - CType(PanLaunching.RenderTransform, ScaleTransform).ScaleX, 150,, New AniEaseOutFluent(AniEasePower.Weak)),
  174. AaOpacity(PanInput, 1 - PanInput.Opacity, 250, 50),
  175. AaScaleTransform(PanInput, 1 - CType(PanInput.RenderTransform, ScaleTransform).ScaleX, 300, 50, New AniEaseOutBack(AniEasePower.Weak)),
  176. AaCode(Sub() PanInput.IsHitTestVisible = True, 200)
  177. }, "Launch State Page", True)
  178. End Sub
  179. #End Region
  180. #Region "切换登录页面"
  181. Private Enum PageType
  182. None
  183. Legacy
  184. Nide
  185. NideSkin
  186. Auth
  187. AuthSkin
  188. Ms
  189. MsSkin
  190. End Enum
  191. ''' <summary>
  192. ''' 当前页面的种类。
  193. ''' </summary>
  194. Private PageCurrent As PageType = PageType.None
  195. Private Function PageGet(Type As PageType)
  196. Select Case Type
  197. Case PageType.Legacy
  198. If IsNothing(FrmLoginLegacy) Then FrmLoginLegacy = New PageLoginLegacy
  199. Return FrmLoginLegacy
  200. Case PageType.Nide
  201. If IsNothing(FrmLoginNide) Then FrmLoginNide = New PageLoginNide
  202. Return FrmLoginNide
  203. Case PageType.NideSkin
  204. If IsNothing(FrmLoginNideSkin) Then FrmLoginNideSkin = New PageLoginNideSkin
  205. Return FrmLoginNideSkin
  206. Case PageType.Auth
  207. If IsNothing(FrmLoginAuth) Then FrmLoginAuth = New PageLoginAuth
  208. Return FrmLoginAuth
  209. Case PageType.AuthSkin
  210. If IsNothing(FrmLoginAuthSkin) Then FrmLoginAuthSkin = New PageLoginAuthSkin
  211. Return FrmLoginAuthSkin
  212. Case PageType.Ms
  213. If IsNothing(FrmLoginMs) Then FrmLoginMs = New PageLoginMs
  214. Return FrmLoginMs
  215. Case PageType.MsSkin
  216. If IsNothing(FrmLoginMsSkin) Then FrmLoginMsSkin = New PageLoginMsSkin
  217. Return FrmLoginMsSkin
  218. Case Else
  219. Throw New ArgumentOutOfRangeException("Type", "即将切换的登录分页编号越界")
  220. End Select
  221. End Function
  222. ''' <summary>
  223. ''' 切换现有登录页面种类,返回新页面的实例。
  224. ''' </summary>
  225. ''' <param name="Type">新页面的种类。</param>
  226. ''' <param name="Anim">是否显示动画。</param>
  227. Private Function PageChange(Type As PageType, Anim As Boolean)
  228. Dim PageNew As Object = FrmLoginMs '初始化一个东西,避免在执行时出现异常导致雪崩
  229. Try
  230. #Region "确定更改的页面实例并实例化"
  231. If PageCurrent = Type Then Return PageNew
  232. PageNew = PageGet(Type)
  233. #End Region
  234. #Region "切换页面"
  235. AniStop("FrmLogin PageChange")
  236. '清除页面关联性
  237. If Not IsNothing(PageNew) AndAlso Not IsNothing(PageNew.Parent) Then PageNew.SetValue(ContentPresenter.ContentProperty, Nothing)
  238. If Anim Then
  239. '动画
  240. Dispatcher.Invoke(
  241. Sub()
  242. '执行动画
  243. AniStart({
  244. AaOpacity(PanLogin, -PanLogin.Opacity, 100,, New AniEaseOutFluent),
  245. AaCode(
  246. Sub()
  247. AniControlEnabled += 1
  248. PanLogin.Children.Clear()
  249. PanLogin.Children.Add(PageNew)
  250. AniControlEnabled -= 1
  251. End Sub, 100),
  252. AaOpacity(PanLogin, 1, 100, 120, New AniEaseInFluent)
  253. }, "FrmLogin PageChange")
  254. End Sub, DispatcherPriority.Render)
  255. Else
  256. '无动画
  257. AniControlEnabled += 1
  258. PanLogin.Children.Clear()
  259. PanLogin.Children.Add(PageNew)
  260. AniControlEnabled -= 1
  261. End If
  262. #End Region
  263. PageCurrent = Type
  264. Return PageNew
  265. Catch ex As Exception
  266. Logger.Error(ex, $"切换登录分页失败({Type})")
  267. Return PageNew
  268. End Try
  269. End Function
  270. ''' <summary>
  271. ''' 确认当前显示的子页面正确,并刷新该页面。
  272. ''' </summary>
  273. Public Sub RefreshPage(KeepInput As Boolean, Anim As Boolean)
  274. '获取页面的可用种类并回写缓存
  275. Dim Type As PageType
  276. Dim LoginPageType As Integer
  277. If McInstanceSelected IsNot Nothing Then
  278. LoginPageType = Settings.Get(Of Integer)("VersionServerLogin", Instance:=McInstanceSelected)
  279. '缓存当前版本的页面种类,下一次打开 McInstanceSelected 为空时才能加载出正确的页面
  280. Settings.Set("LoginPageType", LoginPageType)
  281. Else
  282. LoginPageType = Settings.Get(Of Integer)("LoginPageType")
  283. End If
  284. Select Case LoginPageType
  285. Case 0 '正版或离线
  286. UnknownType:
  287. If RadioLoginType5.Checked Then
  288. If Settings.Get(Of String)("CacheMsV2Access") = "" Then
  289. Type = PageType.Ms
  290. Else
  291. Type = PageType.MsSkin
  292. End If
  293. Settings.Set("LoginType", McLoginType.Ms)
  294. Else
  295. Type = PageType.Legacy
  296. Settings.Set("LoginType", McLoginType.Legacy)
  297. End If
  298. PanType.Visibility = Visibility.Visible
  299. PanTypeOne.Visibility = Visibility.Collapsed
  300. RadioLoginType5.Visibility = Visibility.Visible
  301. RadioLoginType0.Visibility = Visibility.Visible
  302. Case 1 '仅正版
  303. If Settings.Get(Of String)("CacheMsV2Access") = "" Then
  304. Type = PageType.Ms
  305. Else
  306. Type = PageType.MsSkin
  307. End If
  308. Settings.Set("LoginType", McLoginType.Ms)
  309. PanType.Visibility = Visibility.Collapsed
  310. PanTypeOne.Visibility = Visibility.Visible
  311. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonShield)
  312. LabTypeOne.Text = "正版登录"
  313. RadioLoginType5.Visibility = Visibility.Visible
  314. RadioLoginType0.Visibility = Visibility.Collapsed
  315. Case 2 '仅离线
  316. Type = PageType.Legacy
  317. Settings.Set("LoginType", McLoginType.Legacy)
  318. PanType.Visibility = Visibility.Collapsed
  319. PanTypeOne.Visibility = Visibility.Visible
  320. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonOffline)
  321. LabTypeOne.Text = "离线登录"
  322. Case 3 '统一通行证
  323. If Settings.Get(Of String)("CacheNideAccess") = "" Then
  324. Type = PageType.Nide
  325. Else
  326. Type = PageType.NideSkin
  327. End If
  328. Settings.Set("LoginType", McLoginType.Nide)
  329. PanType.Visibility = Visibility.Collapsed
  330. PanTypeOne.Visibility = Visibility.Visible
  331. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonCard)
  332. LabTypeOne.Text = "统一通行证登录"
  333. Case 4 'Authlib-Injector
  334. If Settings.Get(Of String)("CacheAuthAccess") = "" Then
  335. Type = PageType.Auth
  336. Else
  337. Type = PageType.AuthSkin
  338. End If
  339. Settings.Set("LoginType", McLoginType.Auth)
  340. PanType.Visibility = Visibility.Collapsed
  341. PanTypeOne.Visibility = Visibility.Visible
  342. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonCard)
  343. LabTypeOne.Text = If(McInstanceSelected Is Nothing, Settings.Get(Of String)("CacheAuthServerName"), Settings.Get(Of String)("VersionServerAuthName", Instance:=McInstanceSelected))
  344. If LabTypeOne.Text = "" Then LabTypeOne.Text = "第三方登录"
  345. Case Else
  346. Logger.Error($"未知的登录页面:{LoginPageType}", LogBehavior.Toast)
  347. GoTo UnknownType
  348. End Select
  349. '刷新页面
  350. If PageCurrent = Type Then Return
  351. PageChange(Type, Anim).Reload(KeepInput)
  352. Dim Control As MyRadioButton = FindName("RadioLoginType" & Settings.Get(Of McLoginType)("LoginType"))
  353. If Control IsNot Nothing Then Control.Checked = True
  354. End Sub
  355. Private Sub RadioLoginType_Change(sender As Object, raiseByMouse As Boolean) Handles RadioLoginType0.Check, RadioLoginType5.Check
  356. If raiseByMouse Then RefreshPage(True, True)
  357. End Sub
  358. #End Region
  359. #Region "皮肤"
  360. '微软正版皮肤
  361. Public Shared SkinMs As New LoaderTask(Of (String, String), String)("Loader Skin Ms", AddressOf SkinMsLoad, AddressOf SkinMsInput, ThreadPriority.AboveNormal)
  362. Private Shared Function SkinMsInput() As (String, String)
  363. '获取名称
  364. Return (Settings.Get(Of String)("CacheMsV2Name"), Settings.Get(Of String)("CacheMsV2Uuid"))
  365. End Function
  366. Private Shared Sub SkinMsLoad(Data As LoaderTask(Of (String, String), String))
  367. '清空已有皮肤
  368. '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
  369. RunInUi(Sub() If FrmLoginMsSkin IsNot Nothing AndAlso FrmLoginMsSkin.Skin IsNot Nothing Then FrmLoginMsSkin.Skin.Clear())
  370. '获取 Url
  371. Dim UserName As String = Data.Input.Item1
  372. Dim Uuid As String = Data.Input.Item2
  373. If UserName = "" Then
  374. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  375. Logger.Info("获取微软正版皮肤失败,ID 为空")
  376. GoTo Finish
  377. End If
  378. Try
  379. Dim Result As String = McSkinGetAddress(Uuid, "Ms")
  380. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & UserName)
  381. Result = McSkinDownload(Result)
  382. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & UserName)
  383. Data.Output = Result
  384. Catch ex As Exception
  385. If ex.IsCanceled Then
  386. Data.Output = ""
  387. Return
  388. ElseIf ex.GetDisplay(False).Contains("(429)") Then
  389. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  390. Logger.Error($"获取正版皮肤失败({UserName}):获取皮肤太过频繁,请 5 分钟后再试!", LogBehavior.Toast)
  391. ElseIf ex.GetDisplay(False).Contains("未设置自定义皮肤") Then
  392. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  393. Logger.Info("用户未设置自定义皮肤,跳过皮肤加载")
  394. Else
  395. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  396. Logger.Error(ex, $"获取微软正版皮肤失败({UserName})", LogBehavior.Toast)
  397. End If
  398. End Try
  399. Finish:
  400. '刷新显示
  401. If FrmLoginMsSkin IsNot Nothing Then
  402. RunInUi(AddressOf FrmLoginMsSkin.Skin.Load)
  403. ElseIf Not Data.IsCanceled Then '如果已经中断,Input 也被清空,就不会再次刷新
  404. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  405. End If
  406. End Sub
  407. '离线皮肤
  408. Public Shared SkinLegacy As New LoaderTask(Of (String, String), String)("Loader Skin Legacy", AddressOf SkinLegacyLoad, AddressOf SkinLegacyInput, ThreadPriority.AboveNormal)
  409. Private Shared Function SkinLegacyInput() As (String, String)
  410. '根据类型判断输入
  411. Dim Type As Integer = Settings.Get(Of Integer)("LaunchSkinType")
  412. Select Case Type
  413. Case 0
  414. If FrmLoginLegacy?.IsReloaded Then
  415. Return ("0", If(FrmLoginLegacy.ComboName.Text.Trim, ""))
  416. ElseIf Settings.Get(Of String)("LoginLegacyName") = "" Then
  417. Return ("0", "")
  418. Else
  419. Return ("0", If(Settings.Get(Of String)("LoginLegacyName").ToString.BeforeFirst("¨"), ""))
  420. End If
  421. Case 3
  422. Return ("3", Settings.Get(Of String)("LaunchSkinID"))
  423. Case Else
  424. Return (Type.ToString, "")
  425. End Select
  426. End Function
  427. Private Shared Sub SkinLegacyLoad(Data As LoaderTask(Of (String, String), String))
  428. '清空已有皮肤
  429. RunInUi(Sub() If FrmLoginLegacy IsNot Nothing AndAlso FrmLoginLegacy.Skin IsNot Nothing Then FrmLoginLegacy.Skin.Clear())
  430. '获取 Url
  431. Select Case CInt(Data.Input.Item1)
  432. Case 0 '默认
  433. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(Data.Input.Item2)) & ".png"
  434. Case 1 'Steve
  435. UseDefault:
  436. Data.Output = PathImage & "Skins/Steve.png"
  437. Case 2 'Alex
  438. Data.Output = PathImage & "Skins/Alex.png"
  439. Case 3 '正版
  440. Dim ID As String = Data.Input.Item2
  441. Try
  442. If ID.Count < 2 Then
  443. Data.Output = PathImage & "Skins/Steve.png"
  444. Else
  445. Dim Result As String = McLoginMojangUuid(ID, True)
  446. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & ID)
  447. Result = McSkinGetAddress(Result, "Mojang")
  448. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & ID)
  449. Result = McSkinDownload(Result)
  450. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & ID)
  451. Data.Output = Result
  452. End If
  453. Catch ex As Exception
  454. If ex.IsCanceled Then
  455. Data.Output = ""
  456. Return
  457. ElseIf ex.GetDisplay(False).Contains("(429)") Then
  458. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
  459. Logger.Info($"获取离线登录使用的正版皮肤失败({ID}):获取皮肤太过频繁,请 5 分钟后再试!")
  460. Else
  461. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
  462. Logger.Warn(ex, $"获取离线登录使用的正版皮肤失败({ID})")
  463. End If
  464. End Try
  465. Case 4 '自定义
  466. If Not FileUtils.Exists(Paths.AppDataThenName & "CustomSkin.png") Then
  467. Hint("未找到离线皮肤自定义文件,可能它已被删除。PCL 将使用默认的 Steve 皮肤!")
  468. Settings.Set("LaunchSkinType", 1)
  469. GoTo UseDefault
  470. End If
  471. Data.Output = Paths.AppDataThenName & "CustomSkin.png"
  472. End Select
  473. '刷新显示
  474. If FrmLoginLegacy IsNot Nothing Then
  475. RunInUi(AddressOf FrmLoginLegacy.Skin.Load)
  476. ElseIf Not Data.IsCanceled Then '如果已经中断,Input 也被清空,就不会再次刷新
  477. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  478. End If
  479. End Sub
  480. '统一通行证皮肤
  481. Public Shared SkinNide As New LoaderTask(Of (String, String), String)("Loader Skin Nide", AddressOf SkinNideLoad, AddressOf SkinNideInput, ThreadPriority.AboveNormal)
  482. Private Shared Function SkinNideInput() As (String, String)
  483. '获取名称
  484. Return (Settings.Get(Of String)("CacheNideName"), Settings.Get(Of String)("CacheNideUuid"))
  485. End Function
  486. Private Shared Sub SkinNideLoad(Data As LoaderTask(Of (String, String), String))
  487. '清空已有皮肤
  488. '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
  489. RunInUi(Sub() If FrmLoginNideSkin IsNot Nothing AndAlso FrmLoginNideSkin.Skin IsNot Nothing Then FrmLoginNideSkin.Skin.Clear())
  490. '获取 Url
  491. Dim UserName As String = Data.Input.Item1
  492. Dim Uuid As String = Data.Input.Item2
  493. If UserName = "" Then
  494. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  495. Logger.Info("获取统一通行证皮肤失败,ID 为空")
  496. GoTo Finish
  497. End If
  498. Try
  499. Dim Result As String = McSkinGetAddress(Uuid, "Nide")
  500. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & UserName)
  501. Result = McSkinDownload(Result)
  502. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & UserName)
  503. Data.Output = Result
  504. Catch ex As Exception
  505. If ex.IsCanceled Then
  506. Data.Output = ""
  507. Return
  508. ElseIf ex.GetDisplay(False).Contains("(429)") Then
  509. Data.Output = PathImage & "Skins/Steve.png"
  510. Logger.Error($"获取统一通行证皮肤失败({UserName}):获取皮肤太过频繁,请 5 分钟后再试!", LogBehavior.Toast)
  511. ElseIf ex.GetDisplay(False).Contains("未设置自定义皮肤") Then
  512. Data.Output = PathImage & "Skins/Steve.png"
  513. Logger.Info("用户未设置自定义皮肤,跳过皮肤加载")
  514. Else
  515. Data.Output = PathImage & "Skins/Steve.png"
  516. Logger.Error(ex, $"获取统一通行证皮肤失败({UserName})", LogBehavior.Toast)
  517. End If
  518. End Try
  519. Finish:
  520. '刷新显示
  521. If FrmLoginNideSkin IsNot Nothing Then
  522. RunInUi(AddressOf FrmLoginNideSkin.Skin.Load)
  523. ElseIf Not Data.IsCanceled Then '如果已经中断,Input 也被清空,就不会再次刷新
  524. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  525. End If
  526. End Sub
  527. 'Authlib-Injector 皮肤
  528. Public Shared SkinAuth As New LoaderTask(Of (String, String), String)("Loader Skin Auth", AddressOf SkinAuthLoad, AddressOf SkinAuthInput, ThreadPriority.AboveNormal)
  529. Private Shared Function SkinAuthInput() As (String, String)
  530. '获取名称
  531. Return (Settings.Get(Of String)("CacheAuthName"), Settings.Get(Of String)("CacheAuthUuid"))
  532. End Function
  533. Private Shared Sub SkinAuthLoad(Data As LoaderTask(Of (String, String), String))
  534. '清空已有皮肤
  535. '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
  536. RunInUi(Sub() If FrmLoginAuthSkin IsNot Nothing AndAlso FrmLoginAuthSkin.Skin IsNot Nothing Then FrmLoginAuthSkin.Skin.Clear())
  537. '获取 Url
  538. Dim UserName As String = Data.Input.Item1
  539. Dim UUID As String = Data.Input.Item2
  540. If UserName = "" Then
  541. Data.Output = PathImage & "Skins/Steve.png"
  542. Logger.Info("获取 Authlib-Injector 皮肤失败,ID 为空")
  543. GoTo Finish
  544. End If
  545. Try
  546. Dim Result As String = McSkinGetAddress(UUID, "Auth")
  547. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & UserName)
  548. Result = McSkinDownload(Result)
  549. If Data.IsCanceled Then Throw New OperationCanceledException("当前任务已取消:" & UserName)
  550. Data.Output = Result
  551. Catch ex As Exception
  552. If ex.IsCanceled Then
  553. Data.Output = ""
  554. Return
  555. ElseIf ex.GetDisplay(False).Contains("(429)") Then
  556. Data.Output = PathImage & "Skins/Steve.png"
  557. Logger.Error($"获取 Authlib-Injector 皮肤失败({UserName}):获取皮肤太过频繁,请 5 分钟后再试!", LogBehavior.Toast)
  558. ElseIf ex.GetDisplay(False).Contains("未设置自定义皮肤") Then
  559. Data.Output = PathImage & "Skins/Steve.png"
  560. Logger.Info("用户未设置自定义皮肤,跳过皮肤加载")
  561. Else
  562. Data.Output = PathImage & "Skins/Steve.png"
  563. Logger.Error(ex, $"获取 Authlib-Injector 皮肤失败({UserName})", LogBehavior.Toast)
  564. End If
  565. End Try
  566. Finish:
  567. '刷新显示
  568. If FrmLoginAuthSkin IsNot Nothing Then
  569. RunInUi(AddressOf FrmLoginAuthSkin.Skin.Load)
  570. ElseIf Not Data.IsCanceled Then '如果已经中断,Input 也被清空,就不会再次刷新
  571. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  572. End If
  573. End Sub
  574. '全部皮肤加载器
  575. '需要放在其中元素的后面,否则会因为它提前被加载而莫名其妙变成 Nothing
  576. Public Shared SkinLoaders As New List(Of LoaderTask(Of (String, String), String)) From {SkinMs, SkinLegacy, SkinNide, SkinAuth}
  577. #End Region
  578. '版本选择按钮
  579. Private Sub BtnVersion_Click() Handles BtnVersion.Click
  580. If McLaunchLoader.State = LoadState.Loading Then Return
  581. FrmMain.PageChange(FormMain.PageType.InstanceSelect)
  582. End Sub
  583. '启动按钮
  584. Public Sub LaunchButtonClick() Handles BtnLaunch.Click
  585. If McLaunchLoader.State = LoadState.Loading OrElse Not BtnLaunch.IsEnabled OrElse
  586. (FrmMain.PageRight IsNot Nothing AndAlso FrmMain.PageRight.PageState <> MyPageRight.PageStates.ContentStay AndAlso FrmMain.PageRight.PageState <> MyPageRight.PageStates.ContentEnter) Then Return
  587. '愚人节处理
  588. If IsAprilEnabled AndAlso Not IsAprilGiveup Then
  589. ThemeUnlock(12, False, "隐藏主题 滑稽彩 已解锁!")
  590. IsAprilGiveup = True
  591. Settings.Set("AprilYear", Date.Now.Year)
  592. FrmLaunchLeft.AprilScaleTrans.ScaleX = 1
  593. FrmLaunchLeft.AprilScaleTrans.ScaleY = 1
  594. FrmLaunchLeft.AprilPosTrans.X = 0
  595. FrmLaunchLeft.AprilPosTrans.Y = 0
  596. FrmMain.BtnExtraApril.ShowRefresh()
  597. End If
  598. '实际的启动
  599. If BtnLaunch.Text = "启动游戏" Then
  600. McLaunchStart()
  601. ElseIf BtnLaunch.Text = "下载游戏" Then
  602. FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
  603. End If
  604. End Sub
  605. Private BtnLaunchState As Integer = 0
  606. Private BtnLaunchInstance As McInstance = Nothing
  607. Public Sub RefreshButtonsUI() Handles BtnLaunch.Loaded
  608. If Not BtnLaunch.IsLoaded Then Return
  609. '获取当前状态
  610. Dim CurrentState As Integer
  611. If (Not IsLoadFinished) OrElse McInstanceListLoader.State = LoadState.Loading OrElse McFolderListLoader.State = LoadState.Loading Then
  612. CurrentState = 0
  613. Else
  614. If McInstanceSelected Is Nothing Then
  615. If RestrictMcDownload OrElse (Settings.Get(Of Boolean)("UiHiddenPageDownload") AndAlso Not PageSetupUI.HiddenForceShow) Then
  616. CurrentState = 1
  617. Else
  618. CurrentState = 2
  619. End If
  620. Else
  621. CurrentState = 3
  622. End If
  623. End If
  624. '更新状态
  625. If CurrentState = BtnLaunchState AndAlso
  626. If(McInstanceSelected Is Nothing, "", McInstanceSelected.PathVersion) = If(BtnLaunchInstance Is Nothing, "", BtnLaunchInstance.PathVersion) Then GoTo ExitRefresh
  627. BtnLaunchInstance = McInstanceSelected
  628. BtnLaunchState = CurrentState
  629. Select Case CurrentState
  630. Case 0
  631. Logger.Info("启动按钮:正在加载 Minecraft 版本")
  632. FrmLaunchLeft.BtnLaunch.Text = "正在加载"
  633. FrmLaunchLeft.BtnLaunch.IsEnabled = False
  634. FrmLaunchLeft.LabVersion.Text = "正在加载中,请稍候"
  635. FrmLaunchLeft.BtnVersion.IsEnabled = False
  636. FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
  637. Case 1
  638. Logger.Info("启动按钮:无 Minecraft 版本,下载已禁用")
  639. FrmLaunchLeft.BtnLaunch.Text = "启动游戏"
  640. FrmLaunchLeft.BtnLaunch.IsEnabled = False
  641. FrmLaunchLeft.LabVersion.Text = "未找到可用的游戏版本"
  642. FrmLaunchLeft.BtnVersion.IsEnabled = True
  643. FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
  644. Case 2
  645. Logger.Info("启动按钮:无 Minecraft 版本,要求下载")
  646. FrmLaunchLeft.BtnLaunch.Text = "下载游戏"
  647. FrmLaunchLeft.BtnLaunch.IsEnabled = True
  648. FrmLaunchLeft.LabVersion.Text = "未找到可用的游戏版本"
  649. FrmLaunchLeft.BtnVersion.IsEnabled = True
  650. FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
  651. Case 3
  652. Logger.Info($"启动按钮:Minecraft 版本:{McInstanceSelected.PathVersion}")
  653. FrmLaunchLeft.BtnLaunch.Text = "启动游戏"
  654. FrmLaunchLeft.BtnVersion.IsEnabled = True
  655. FrmLaunchLeft.BtnLaunch.IsEnabled = True
  656. FrmLaunchLeft.LabVersion.Text = McInstanceSelected.Name
  657. 'FrmLaunchLeft.BtnMore.Visibility = Visibility.Visible '由功能隐藏设置修改
  658. End Select
  659. ExitRefresh:
  660. '功能隐藏
  661. FrmLaunchLeft.BtnVersion.Visibility = If(Not PageSetupUI.HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenFunctionSelect"), Visibility.Collapsed, Visibility.Visible)
  662. If CurrentState = 3 Then
  663. FrmLaunchLeft.BtnMore.Visibility = FrmLaunchLeft.BtnVersion.Visibility
  664. End If
  665. End Sub
  666. '取消按钮
  667. Public Sub BtnCancel_Click() Handles BtnCancel.Click
  668. If McLaunchLoaderReal IsNot Nothing Then
  669. McLaunchLoaderReal.Cancel()
  670. McLaunchLog("已取消启动")
  671. Try
  672. If McLaunchWatcher IsNot Nothing Then
  673. McLaunchWatcher.Kill()
  674. ElseIf McLaunchProcess IsNot Nothing Then
  675. If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
  676. End If
  677. Catch ex As Exception
  678. Logger.Error(ex, "取消启动结束进程失败", LogBehavior.Toast)
  679. End Try
  680. End If
  681. End Sub
  682. '版本设置按钮
  683. Private Sub BtnMore_Click() Handles BtnMore.Click
  684. If McLaunchLoader.State = LoadState.Loading Then Return
  685. If McInstanceLock.IsLocked(McInstanceSelected) Then
  686. Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
  687. Return
  688. End If
  689. McInstanceSelected.Load()
  690. PageInstanceLeft.Instance = McInstanceSelected
  691. FrmMain.PageChange(FormMain.PageType.InstanceSetup, 0)
  692. End Sub
  693. ''' <summary>
  694. ''' 每 0.1s 执行一次,刷新启动的数据 UI 显示。
  695. ''' </summary>
  696. Public Sub LaunchingRefresh()
  697. Try
  698. If McLaunchLoaderReal.State = LoadState.Canceled Then Return
  699. '阶段状态获取
  700. Dim IsLaunched As Boolean = False '是否已经启动游戏,只是在等待窗口
  701. Try
  702. For Each Loader In McLaunchLoaderReal.GetLoaderList(False)
  703. If Loader.State = LoadState.Loading OrElse Loader.State = LoadState.Waiting Then
  704. LabLaunchingStage.Text = Loader.Name
  705. IsLaunched = Loader.Name = "等待游戏窗口出现" OrElse Loader.Name = "结束处理"
  706. Exit Try
  707. End If
  708. Next
  709. LabLaunchingStage.Text = "已完成"
  710. Catch ex As Exception
  711. Logger.Warn(ex, "获取是否启动完成失败,可能是由于启动状态改变导致集合已修改")
  712. Return
  713. End Try
  714. LabLaunchingTitle.Text = If(IsLaunched OrElse McLaunchLoaderReal.State = LoadState.Finished,
  715. "已启动游戏",
  716. If(CurrentLaunchOptions.SaveBatch Is Nothing, "正在启动游戏", "正在导出启动脚本"))
  717. If AniIsRun("Launch State Page") Then IsLaunched = False '等待页面切换动画完成
  718. '更新进度
  719. Dim ActualProgress = McLaunchLoaderReal.Progress
  720. If ActualProgress >= ShowProgress Then ShowProgress += (ActualProgress - ShowProgress) * 0.1 + 0.0025 '向实际进度靠一点
  721. If ActualProgress <= ShowProgress Then ShowProgress = ActualProgress '原来或处理后变得比实际进度高,直接回退
  722. If IsLaunched Then ShowProgress = 1 '如果已经完成了,就不卖关子了
  723. LabLaunchingProgress.Text = (ShowProgress * 100).ToString("0.00") & " %"
  724. '更新下载速度
  725. Dim HasLaunchDownloader As Boolean = False
  726. Try
  727. If NetManager.Speed = 0 AndAlso LabLaunchingDownload.Visibility = Visibility.Collapsed Then
  728. '可能只是在检查文件,没有实际下载
  729. HasLaunchDownloader = False
  730. Else
  731. For Each Loader In NetManager.Tasks
  732. If Loader.RealParent IsNot Nothing AndAlso Loader.RealParent.Name = "Minecraft 启动" AndAlso Loader.State = LoadState.Loading Then HasLaunchDownloader = True
  733. Next
  734. End If
  735. Catch ex As Exception
  736. Logger.Warn(ex, "获取 Minecraft 启动下载器失败,可能是因为启动被取消")
  737. HasLaunchDownloader = False
  738. End Try
  739. LabLaunchingDownload.Text = StringUtils.FormatByteSize(NetManager.Speed) & "/s"
  740. '进度改变动画
  741. Dim AnimList As New List(Of AniData) From {
  742. AaGridLengthWidth(ProgressLaunchingFinished, ShowProgress - ProgressLaunchingFinished.Width.Value, 130,, New AniEaseOutFluent),
  743. AaGridLengthWidth(ProgressLaunchingUnfinished, 1 - ShowProgress - ProgressLaunchingUnfinished.Width.Value, 130,, New AniEaseOutFluent)
  744. }
  745. If HasLaunchDownloader = (LabLaunchingDownload.Visibility = Visibility.Collapsed) Then 'IsDownloadStateChanged
  746. LabLaunchingDownload.Visibility = Visibility.Visible
  747. LabLaunchingDownloadLeft.Visibility = Visibility.Visible
  748. AnimList.AddRange({
  749. AaOpacity(LabLaunchingDownload, If(HasLaunchDownloader, 1, 0) - LabLaunchingDownload.Opacity, 90),
  750. AaOpacity(LabLaunchingDownloadLeft, If(HasLaunchDownloader, 0.5, 0) - LabLaunchingDownloadLeft.Opacity, 90),
  751. AaCode(
  752. Sub()
  753. If Not HasLaunchDownloader Then
  754. LabLaunchingDownload.Visibility = Visibility.Collapsed
  755. LabLaunchingDownloadLeft.Visibility = Visibility.Collapsed
  756. End If
  757. End Sub, 110)
  758. })
  759. End If
  760. If (Not IsLaunched) = (LabLaunchingProgress.Visibility = Visibility.Collapsed) Then 'IsProgressStateChanged
  761. LabLaunchingProgress.Visibility = Visibility.Visible
  762. LabLaunchingProgressLeft.Visibility = Visibility.Visible
  763. If IsLaunched Then PanLaunchingHint.Visibility = Visibility.Visible
  764. AnimList.AddRange({
  765. AaOpacity(LabLaunchingProgress, If(Not IsLaunched, 1, 0) - LabLaunchingProgress.Opacity, 90),
  766. AaOpacity(LabLaunchingProgressLeft, If(Not IsLaunched, 0.5, 0) - LabLaunchingProgressLeft.Opacity, 90),
  767. AaOpacity(PanLaunchingHint, If(IsLaunched, 1, 0) - PanLaunchingHint.Opacity, 90)
  768. })
  769. End If
  770. AniStart(AnimList, "Launching Progress")
  771. Catch ex As Exception
  772. Logger.Error(ex, "刷新启动信息失败")
  773. End Try
  774. End Sub
  775. Private ShowProgress As Double = 0
  776. '尺寸改变动画
  777. Private IsWidthAnimating As Boolean = False
  778. Private ActualUsedWidth As Double
  779. Private Sub PanLaunchingInfo_SizeChangedW(sender As Object, e As SizeChangedEventArgs) Handles PanLaunchingInfo.SizeChanged
  780. Dim DeltaWidth As Double = e.NewSize.Width - e.PreviousSize.Width
  781. If e.PreviousSize.Width = 0 OrElse IsWidthAnimating OrElse Math.Abs(DeltaWidth) < 1 OrElse PanLaunchingInfo.ActualWidth = 0 Then Return
  782. AniStart({
  783. AaWidth(PanLaunchingInfo, DeltaWidth, 180,, New AniEaseOutFluent),
  784. AaCode(Sub()
  785. IsWidthAnimating = False
  786. PanLaunchingInfo.Width = ActualUsedWidth
  787. End Sub,, True)
  788. }, "Launching Info Width")
  789. IsWidthAnimating = True
  790. ActualUsedWidth = PanLaunchingInfo.Width
  791. PanLaunchingInfo.Width = e.PreviousSize.Width
  792. End Sub
  793. Private IsHeightAnimating As Boolean = False
  794. Private ActualUsedHeight As Double
  795. Private Sub PanLaunchingInfo_SizeChangedH(sender As Object, e As SizeChangedEventArgs) Handles PanLaunchingInfo.SizeChanged
  796. Dim DeltaHeight As Double = e.NewSize.Height - e.PreviousSize.Height
  797. If e.PreviousSize.Height = 0 OrElse IsHeightAnimating OrElse Math.Abs(DeltaHeight) < 1 OrElse PanLaunchingInfo.ActualHeight = 0 Then Return
  798. AniStart({
  799. AaHeight(PanLaunchingInfo, DeltaHeight, 180,, New AniEaseOutFluent),
  800. AaCode(Sub()
  801. IsHeightAnimating = False
  802. PanLaunchingInfo.Height = ActualUsedHeight
  803. End Sub,, True)
  804. }, "Launching Info Height")
  805. IsHeightAnimating = True
  806. ActualUsedHeight = PanLaunchingInfo.Height
  807. PanLaunchingInfo.Height = e.PreviousSize.Height
  808. End Sub
  809. End Class