| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- Public Class PageLaunchLeft
- '加载当前版本
- Private IsLoad As Boolean = False
- Private IsLoadFinished As Boolean = False
- Public Sub PageLaunchLeft_Loaded() Handles Me.Loaded
- If IsLoad Then RefreshPage(True, False)
- AprilPosTrans.X = 0
- AprilPosTrans.Y = 0
- If IsLoad Then Return
- IsLoad = True
- AniControlEnabled += 1
- '开始按钮
- AddHandler McInstanceListLoader.LoadingStateChanged, AddressOf RefreshButtonsUI
- AddHandler McFolderListLoader.LoadingStateChanged, AddressOf RefreshButtonsUI
- RefreshButtonsUI()
- '加载版本
- RunInNewThread(
- Sub()
- '自动整合包安装:准备
- Dim PackInstallPath As String = Nothing
- If File.Exists(Path & "modpack.zip") Then PackInstallPath = Path & "modpack.zip"
- If File.Exists(Path & "modpack.mrpack") Then PackInstallPath = Path & "modpack.mrpack"
- If PackInstallPath IsNot Nothing Then
- Log("[Launch] 需自动安装整合包:" & PackInstallPath, LogLevel.Debug)
- Setup.Set("LaunchFolderSelect", "$.minecraft\")
- If Not Directory.Exists(Path & ".minecraft\") Then
- Directory.CreateDirectory(Path & ".minecraft\")
- Directory.CreateDirectory(Path & ".minecraft\versions\")
- McFolderLauncherProfilesJsonCreate(Path & ".minecraft\")
- End If
- PageSelectLeft.AddFolder(Path & ".minecraft\", GetFolderNameFromPath(Path), False)
- McFolderListLoader.WaitForExit()
- End If
- '确认 Minecraft 文件夹存在
- McFolderSelected = Setup.Get("LaunchFolderSelect").ToString.Replace("$", Path)
- If McFolderSelected = "" OrElse Not Directory.Exists(McFolderSelected) Then
- '无效的文件夹
- If McFolderSelected = "" Then
- Log("[Launch] 没有已储存的 Minecraft 文件夹")
- Else
- Log("[Launch] Minecraft 文件夹无效,该文件夹已不存在:" & McFolderSelected, LogLevel.Debug)
- End If
- McFolderListLoader.WaitForExit(IsForceRestart:=True)
- Setup.Set("LaunchFolderSelect", McFolderList(0).Location.Replace(Path, "$"))
- End If
- Log("[Launch] Minecraft 文件夹:" & McFolderSelected)
- If Setup.Get("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
- '自动整合包安装
- If PackInstallPath IsNot Nothing Then
- Try
- Dim InstallLoader = ModpackInstall(PackInstallPath)
- Log("[Launch] 自动安装整合包已开始:" & PackInstallPath)
- InstallLoader.WaitForExit()
- If InstallLoader.State = LoadState.Finished Then
- Log("[Launch] 自动安装整合包成功,清理安装包:" & PackInstallPath)
- If File.Exists(PackInstallPath) Then File.Delete(PackInstallPath)
- End If
- Catch ex As CancelledException
- Log(ex, "自动安装整合包被用户取消:" & PackInstallPath)
- Catch ex As Exception
- Log(ex, "自动安装整合包失败:" & PackInstallPath, LogLevel.Msgbox)
- End Try
- End If
- '确认 Minecraft 版本存在
- Dim Selection As String = Setup.Get("LaunchVersionSelect")
- Dim Instance As McInstance = If(Selection = "", Nothing, New McInstance(Selection))
- If Instance Is Nothing OrElse Not Instance.PathVersion.StartsWithF(McFolderSelected) OrElse Not Instance.Check() Then
- '无效的版本
- Log("[Launch] 当前选择的 Minecraft 版本无效:" & If(Instance Is Nothing, "null", Instance.PathVersion), If(IsNothing(Instance), LogLevel.Normal, LogLevel.Debug))
- If Not McInstanceListLoader.State = LoadState.Finished Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
- If Not McInstanceList.Any() OrElse McInstanceList.First.Value(0).Logo.Contains("RedstoneBlock") Then
- Instance = Nothing
- Setup.Set("LaunchVersionSelect", "")
- Log("[Launch] 无可用 Minecraft 版本")
- Else
- Instance = McInstanceList.First.Value(0)
- Setup.Set("LaunchVersionSelect", Instance.Name)
- Log("[Launch] 自动选择 Minecraft 版本:" & Instance.PathVersion)
- End If
- End If
- RunInUi(
- Sub()
- McInstanceSelected = Instance '绕这一圈是为了避免 McVersionCheck 触发第二次版本改变
- IsLoadFinished = True
- RefreshButtonsUI()
- RefreshPage(False, False) '有可能选择的版本变化了,需要重新刷新
- If McLoginAble() = "" Then McLoginLoader.Start() '自动登录
- End Sub)
- End Sub, "Version Check", ThreadPriority.AboveNormal)
- '改变页面
- Dim LoginType As McLoginType = Setup.Get("LoginType")
- If LoginType = McLoginType.Legacy OrElse LoginType = McLoginType.Ms Then CType(FindName("RadioLoginType" & LoginType), MyRadioButton).Checked = True
- RefreshPage(False, False)
- AniControlEnabled -= 1
- End Sub
- #Region "切换大页面"
- ''' <summary>
- ''' 切换至启动中页面。
- ''' </summary>
- Public Sub PageChangeToLaunching()
- '修改登陆方式
- Select Case Setup.Get("LoginType")
- Case McLoginType.Legacy
- LabLaunchingMethod.Text = "离线登录"
- Case McLoginType.Ms
- LabLaunchingMethod.Text = "正版登录"
- Case McLoginType.Nide
- LabLaunchingMethod.Text = "统一通行证"
- Case McLoginType.Auth
- LabLaunchingMethod.Text = "Authlib-Injector"
- End Select
- '初始化页面
- LabLaunchingName.Text = McInstanceSelected.Name
- LabLaunchingStage.Text = "初始化"
- LabLaunchingTitle.Text = If(CurrentLaunchOptions?.SaveBatch Is Nothing, "正在启动游戏", "正在导出启动脚本")
- LabLaunchingProgress.Text = "0.00 %"
- LabLaunchingProgress.Opacity = 1
- LabLaunchingDownload.Visibility = Visibility.Visible
- LabLaunchingProgressLeft.Opacity = 0.6
- LabLaunchingDownload.Visibility = Visibility.Visible
- LabLaunchingDownload.Text = "0 B/s"
- LabLaunchingDownload.Opacity = 0
- LabLaunchingDownload.Visibility = Visibility.Collapsed
- LabLaunchingDownloadLeft.Opacity = 0
- LabLaunchingDownloadLeft.Visibility = Visibility.Collapsed
- ProgressLaunchingFinished.Width = New GridLength(0, GridUnitType.Star)
- ProgressLaunchingUnfinished.Width = New GridLength(1, GridUnitType.Star)
- PanLaunchingHint.Opacity = 0
- PanLaunchingHint.Visibility = Visibility.Collapsed
- PanLaunchingInfo.Width = Double.NaN '重置宽度改变动画
- McLaunchProcess = Nothing
- McLaunchWatcher = Nothing
- '获取 “你知道吗” 提示
- LabLaunchingHint.Text = PageOtherTest.GetRandomHint()
- '初始化其他页面
- PanInput.IsHitTestVisible = False
- PanLaunching.IsHitTestVisible = False
- LoadLaunching.State.LoadingState = MyLoading.MyLoadingState.Run
- PanLaunching.Visibility = Visibility.Visible
- AniStart({
- AaOpacity(PanInput, 0, 50), '略作延迟,这样如果预检测失败,不会出现奇怪的弹一下的动画
- AaOpacity(PanInput, -PanInput.Opacity, 110, , New AniEaseInFluent, True),
- AaScaleTransform(PanInput, 1.2 - CType(PanInput.RenderTransform, ScaleTransform).ScaleX, 160),
- AaOpacity(PanLaunching, 1 - PanLaunching.Opacity, 150, 100),
- AaScaleTransform(PanLaunching, 1 - CType(PanLaunching.RenderTransform, ScaleTransform).ScaleX, 500, 100, New AniEaseOutBack(AniEasePower.Weak)),
- AaCode(Sub() PanLaunching.IsHitTestVisible = True, 150)
- }, "Launch State Page")
- End Sub
- ''' <summary>
- ''' 切换至登录页面。
- ''' </summary>
- Public Sub PageChangeToLogin()
- PageGet(PageCurrent).Reload(KeepInput:=False)
- PanInput.IsHitTestVisible = False
- PanLaunching.IsHitTestVisible = False
- LoadLaunching.State.LoadingState = MyLoading.MyLoadingState.Stop
- PanInput.Visibility = Visibility.Visible
- AniStart({
- AaOpacity(PanLaunching, -PanLaunching.Opacity, 150),
- AaScaleTransform(PanLaunching, 0.8 - CType(PanLaunching.RenderTransform, ScaleTransform).ScaleX, 150,, New AniEaseOutFluent(AniEasePower.Weak)),
- AaOpacity(PanInput, 1 - PanInput.Opacity, 250, 50),
- AaScaleTransform(PanInput, 1 - CType(PanInput.RenderTransform, ScaleTransform).ScaleX, 300, 50, New AniEaseOutBack(AniEasePower.Weak)),
- AaCode(Sub() PanInput.IsHitTestVisible = True, 200)
- }, "Launch State Page", True)
- End Sub
- #End Region
- #Region "切换登录页面"
- Private Enum PageType
- None
- Legacy
- Nide
- NideSkin
- Auth
- AuthSkin
- Ms
- MsSkin
- End Enum
- ''' <summary>
- ''' 当前页面的种类。
- ''' </summary>
- Private PageCurrent As PageType = PageType.None
- Private Function PageGet(Type As PageType)
- Select Case Type
- Case PageType.Legacy
- If IsNothing(FrmLoginLegacy) Then FrmLoginLegacy = New PageLoginLegacy
- Return FrmLoginLegacy
- Case PageType.Nide
- If IsNothing(FrmLoginNide) Then FrmLoginNide = New PageLoginNide
- Return FrmLoginNide
- Case PageType.NideSkin
- If IsNothing(FrmLoginNideSkin) Then FrmLoginNideSkin = New PageLoginNideSkin
- Return FrmLoginNideSkin
- Case PageType.Auth
- If IsNothing(FrmLoginAuth) Then FrmLoginAuth = New PageLoginAuth
- Return FrmLoginAuth
- Case PageType.AuthSkin
- If IsNothing(FrmLoginAuthSkin) Then FrmLoginAuthSkin = New PageLoginAuthSkin
- Return FrmLoginAuthSkin
- Case PageType.Ms
- If IsNothing(FrmLoginMs) Then FrmLoginMs = New PageLoginMs
- Return FrmLoginMs
- Case PageType.MsSkin
- If IsNothing(FrmLoginMsSkin) Then FrmLoginMsSkin = New PageLoginMsSkin
- Return FrmLoginMsSkin
- Case Else
- Throw New ArgumentOutOfRangeException("Type", "即将切换的登录分页编号越界")
- End Select
- End Function
- ''' <summary>
- ''' 切换现有登录页面种类,返回新页面的实例。
- ''' </summary>
- ''' <param name="Type">新页面的种类。</param>
- ''' <param name="Anim">是否显示动画。</param>
- Private Function PageChange(Type As PageType, Anim As Boolean)
- Dim PageNew As Object = FrmLoginMs '初始化一个东西,避免在执行时出现异常导致雪崩
- Try
- #Region "确定更改的页面实例并实例化"
- If PageCurrent = Type Then Return PageNew
- PageNew = PageGet(Type)
- #End Region
- #Region "切换页面"
- AniStop("FrmLogin PageChange")
- '清除页面关联性
- If Not IsNothing(PageNew) AndAlso Not IsNothing(PageNew.Parent) Then PageNew.SetValue(ContentPresenter.ContentProperty, Nothing)
- If Anim Then
- '动画
- Dispatcher.Invoke(
- Sub()
- '执行动画
- AniStart({
- AaOpacity(PanLogin, -PanLogin.Opacity, 100,, New AniEaseOutFluent),
- AaCode(
- Sub()
- AniControlEnabled += 1
- PanLogin.Children.Clear()
- PanLogin.Children.Add(PageNew)
- AniControlEnabled -= 1
- End Sub, 100),
- AaOpacity(PanLogin, 1, 100, 120, New AniEaseInFluent)
- }, "FrmLogin PageChange")
- End Sub, Threading.DispatcherPriority.Render)
- Else
- '无动画
- AniControlEnabled += 1
- PanLogin.Children.Clear()
- PanLogin.Children.Add(PageNew)
- AniControlEnabled -= 1
- End If
- #End Region
- PageCurrent = Type
- Return PageNew
- Catch ex As Exception
- Log(ex, "切换登录分页失败(" & GetStringFromEnum(CType(Type, [Enum])) & ")", LogLevel.Feedback)
- Return PageNew
- End Try
- End Function
- ''' <summary>
- ''' 确认当前显示的子页面正确,并刷新该页面。
- ''' </summary>
- Public Sub RefreshPage(KeepInput As Boolean, Anim As Boolean)
- '获取页面的可用种类并回写缓存
- Dim Type As PageType
- Dim LoginPageType As Integer
- If McInstanceSelected IsNot Nothing Then
- LoginPageType = Setup.Get("VersionServerLogin", Instance:=McInstanceSelected)
- '缓存当前版本的页面种类,下一次打开 McInstanceSelected 为空时才能加载出正确的页面
- Setup.Set("LoginPageType", LoginPageType)
- Else
- LoginPageType = Setup.Get("LoginPageType")
- End If
- Select Case LoginPageType
- Case 0 '正版或离线
- UnknownType:
- If RadioLoginType5.Checked Then
- If Setup.Get("CacheMsV2Access") = "" Then
- Type = PageType.Ms
- Else
- Type = PageType.MsSkin
- End If
- Setup.Set("LoginType", McLoginType.Ms)
- Else
- Type = PageType.Legacy
- Setup.Set("LoginType", McLoginType.Legacy)
- End If
- PanType.Visibility = Visibility.Visible
- PanTypeOne.Visibility = Visibility.Collapsed
- RadioLoginType5.Visibility = Visibility.Visible
- RadioLoginType0.Visibility = Visibility.Visible
- Case 1 '仅正版
- If Setup.Get("CacheMsV2Access") = "" Then
- Type = PageType.Ms
- Else
- Type = PageType.MsSkin
- End If
- Setup.Set("LoginType", McLoginType.Ms)
- PanType.Visibility = Visibility.Collapsed
- PanTypeOne.Visibility = Visibility.Visible
- PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonShield)
- LabTypeOne.Text = "正版登录"
- RadioLoginType5.Visibility = Visibility.Visible
- RadioLoginType0.Visibility = Visibility.Collapsed
- Case 2 '仅离线
- Type = PageType.Legacy
- Setup.Set("LoginType", McLoginType.Legacy)
- PanType.Visibility = Visibility.Collapsed
- PanTypeOne.Visibility = Visibility.Visible
- PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonOffline)
- LabTypeOne.Text = "离线登录"
- Case 3 '统一通行证
- If Setup.Get("CacheNideAccess") = "" Then
- Type = PageType.Nide
- Else
- Type = PageType.NideSkin
- End If
- Setup.Set("LoginType", McLoginType.Nide)
- PanType.Visibility = Visibility.Collapsed
- PanTypeOne.Visibility = Visibility.Visible
- PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonCard)
- LabTypeOne.Text = "统一通行证登录"
- Case 4 'Authlib-Injector
- If Setup.Get("CacheAuthAccess") = "" Then
- Type = PageType.Auth
- Else
- Type = PageType.AuthSkin
- End If
- Setup.Set("LoginType", McLoginType.Auth)
- PanType.Visibility = Visibility.Collapsed
- PanTypeOne.Visibility = Visibility.Visible
- PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonCard)
- LabTypeOne.Text = If(McInstanceSelected Is Nothing, Setup.Get("CacheAuthServerName"), Setup.Get("VersionServerAuthName", Instance:=McInstanceSelected))
- If LabTypeOne.Text = "" Then LabTypeOne.Text = "第三方登录"
- Case Else
- Log("[Control] 未知的登录页面:" & LoginPageType, LogLevel.Hint)
- GoTo UnknownType
- End Select
- '刷新页面
- If PageCurrent = Type Then Return
- PageChange(Type, Anim).Reload(KeepInput)
- Dim Control As MyRadioButton = FindName("RadioLoginType" & Setup.Get("LoginType"))
- If Control IsNot Nothing Then Control.Checked = True
- End Sub
- Private Sub RadioLoginType_Change(sender As Object, raiseByMouse As Boolean) Handles RadioLoginType0.Check, RadioLoginType5.Check
- If raiseByMouse Then RefreshPage(True, True)
- End Sub
- #End Region
- #Region "皮肤"
- '微软正版皮肤
- Public Shared SkinMs As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Ms", AddressOf SkinMsLoad, AddressOf SkinMsInput, ThreadPriority.AboveNormal)
- Private Shared Function SkinMsInput() As EqualableList(Of String)
- '获取名称
- Return New EqualableList(Of String) From {Setup.Get("CacheMsV2Name"), Setup.Get("CacheMsV2Uuid")}
- End Function
- Private Shared Sub SkinMsLoad(Data As LoaderTask(Of EqualableList(Of String), String))
- '清空已有皮肤
- '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
- RunInUi(Sub() If FrmLoginMsSkin IsNot Nothing AndAlso FrmLoginMsSkin.Skin IsNot Nothing Then FrmLoginMsSkin.Skin.Clear())
- '获取 Url
- Dim UserName As String = Data.Input(0)
- Dim Uuid As String = Data.Input(1)
- If UserName = "" Then
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
- Log("[Minecraft] 获取微软正版皮肤失败,ID 为空")
- GoTo Finish
- End If
- Try
- Dim Result As String = McSkinGetAddress(Uuid, "Ms")
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
- Result = McSkinDownload(Result)
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
- Data.Output = Result
- Catch ex As ThreadInterruptedException
- Data.Output = ""
- Return
- Catch ex As Exception
- If ex.GetBrief.Contains("(429)") Then
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
- Log("[Minecraft] 获取正版皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
- ElseIf ex.GetBrief.Contains("未设置自定义皮肤") Then
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
- Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
- Else
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
- Log(ex, "获取微软正版皮肤失败(" & UserName & ")", LogLevel.Hint)
- End If
- End Try
- Finish:
- '刷新显示
- If FrmLoginMsSkin IsNot Nothing Then
- RunInUi(AddressOf FrmLoginMsSkin.Skin.Load)
- ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
- Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
- End If
- End Sub
- '离线皮肤
- Public Shared SkinLegacy As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Legacy", AddressOf SkinLegacyLoad, AddressOf SkinLegacyInput, ThreadPriority.AboveNormal)
- Private Shared Function SkinLegacyInput() As EqualableList(Of String)
- '根据类型判断输入
- Dim Type As Integer = Setup.Get("LaunchSkinType")
- Select Case Type
- Case 0
- If FrmLoginLegacy IsNot Nothing AndAlso FrmLoginLegacy.IsReloaded Then
- Return New EqualableList(Of String) From {0, If(FrmLoginLegacy.ComboName.Text.Trim, "")}
- ElseIf Setup.Get("LoginLegacyName") = "" Then
- Return New EqualableList(Of String) From {0, ""}
- Else
- Return New EqualableList(Of String) From {0, If(Setup.Get("LoginLegacyName").ToString.BeforeFirst("¨"), "")}
- End If
- Case 3
- Return New EqualableList(Of String) From {3, Setup.Get("LaunchSkinID")}
- Case Else
- Return New EqualableList(Of String) From {Type}
- End Select
- End Function
- Private Shared Sub SkinLegacyLoad(Data As LoaderTask(Of EqualableList(Of String), String))
- '清空已有皮肤
- RunInUi(Sub() If FrmLoginLegacy IsNot Nothing AndAlso FrmLoginLegacy.Skin IsNot Nothing Then FrmLoginLegacy.Skin.Clear())
- '获取 Url
- Select Case Data.Input(0)
- Case 0 '默认
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(Data.Input(1))) & ".png"
- Case 1 'Steve
- UseDefault:
- Data.Output = PathImage & "Skins/Steve.png"
- Case 2 'Alex
- Data.Output = PathImage & "Skins/Alex.png"
- Case 3 '正版
- Dim ID As String = Data.Input(1)
- Try
- If ID.Count < 2 Then
- Data.Output = PathImage & "Skins/Steve.png"
- Else
- Dim Result As String = McLoginMojangUuid(ID, True)
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & ID)
- Result = McSkinGetAddress(Result, "Mojang")
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & ID)
- Result = McSkinDownload(Result)
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & ID)
- Data.Output = Result
- End If
- Catch ex As ThreadInterruptedException
- Data.Output = ""
- Return
- Catch ex As Exception
- If ex.GetBrief.Contains("(429)") Then
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
- Log("获取离线登录使用的正版皮肤失败(" & ID & "):获取皮肤太过频繁,请 5 分钟后再试!")
- Else
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
- Log(ex, "获取离线登录使用的正版皮肤失败(" & ID & ")")
- End If
- End Try
- Case 4 '自定义
- If Not File.Exists(PathAppdata & "CustomSkin.png") Then
- Hint("未找到离线皮肤自定义文件,可能它已被删除。PCL 将使用默认的 Steve 皮肤!")
- Setup.Set("LaunchSkinType", 1)
- GoTo UseDefault
- End If
- Data.Output = PathAppdata & "CustomSkin.png"
- End Select
- '刷新显示
- If FrmLoginLegacy IsNot Nothing Then
- RunInUi(AddressOf FrmLoginLegacy.Skin.Load)
- ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
- Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
- End If
- End Sub
- '统一通行证皮肤
- Public Shared SkinNide As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Nide", AddressOf SkinNideLoad, AddressOf SkinNideInput, ThreadPriority.AboveNormal)
- Private Shared Function SkinNideInput() As EqualableList(Of String)
- '获取名称
- Return New EqualableList(Of String) From {Setup.Get("CacheNideName"), Setup.Get("CacheNideUuid")}
- End Function
- Private Shared Sub SkinNideLoad(Data As LoaderTask(Of EqualableList(Of String), String))
- '清空已有皮肤
- '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
- RunInUi(Sub() If FrmLoginNideSkin IsNot Nothing AndAlso FrmLoginNideSkin.Skin IsNot Nothing Then FrmLoginNideSkin.Skin.Clear())
- '获取 Url
- Dim UserName As String = Data.Input(0)
- Dim Uuid As String = Data.Input(1)
- If UserName = "" Then
- Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
- Log("[Minecraft] 获取统一通行证皮肤失败,ID 为空")
- GoTo Finish
- End If
- Try
- Dim Result As String = McSkinGetAddress(Uuid, "Nide")
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
- Result = McSkinDownload(Result)
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
- Data.Output = Result
- Catch ex As ThreadInterruptedException
- Data.Output = ""
- Return
- Catch ex As Exception
- If ex.GetBrief.Contains("(429)") Then
- Data.Output = PathImage & "Skins/Steve.png"
- Log("[Minecraft] 获取统一通行证皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
- ElseIf ex.GetBrief.Contains("未设置自定义皮肤") Then
- Data.Output = PathImage & "Skins/Steve.png"
- Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
- Else
- Data.Output = PathImage & "Skins/Steve.png"
- Log(ex, "获取统一通行证皮肤失败(" & UserName & ")", LogLevel.Hint)
- End If
- End Try
- Finish:
- '刷新显示
- If FrmLoginNideSkin IsNot Nothing Then
- RunInUi(AddressOf FrmLoginNideSkin.Skin.Load)
- ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
- Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
- End If
- End Sub
- 'Authlib-Injector 皮肤
- Public Shared SkinAuth As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Auth", AddressOf SkinAuthLoad, AddressOf SkinAuthInput, ThreadPriority.AboveNormal)
- Private Shared Function SkinAuthInput() As EqualableList(Of String)
- '获取名称
- Return New EqualableList(Of String) From {Setup.Get("CacheAuthName"), Setup.Get("CacheAuthUuid")}
- End Function
- Private Shared Sub SkinAuthLoad(Data As LoaderTask(Of EqualableList(Of String), String))
- '清空已有皮肤
- '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
- RunInUi(Sub() If FrmLoginAuthSkin IsNot Nothing AndAlso FrmLoginAuthSkin.Skin IsNot Nothing Then FrmLoginAuthSkin.Skin.Clear())
- '获取 Url
- Dim UserName As String = Data.Input(0)
- Dim UUID As String = Data.Input(1)
- If UserName = "" Then
- Data.Output = PathImage & "Skins/Steve.png"
- Log("[Minecraft] 获取 Authlib-Injector 皮肤失败,ID 为空")
- GoTo Finish
- End If
- Try
- Dim Result As String = McSkinGetAddress(UUID, "Auth")
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
- Result = McSkinDownload(Result)
- If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
- Data.Output = Result
- Catch ex As ThreadInterruptedException
- Data.Output = ""
- Return
- Catch ex As Exception
- If ex.GetBrief.Contains("(429)") Then
- Data.Output = PathImage & "Skins/Steve.png"
- Log("[Minecraft] 获取 Authlib-Injector 皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
- ElseIf ex.GetBrief.Contains("未设置自定义皮肤") Then
- Data.Output = PathImage & "Skins/Steve.png"
- Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
- Else
- Data.Output = PathImage & "Skins/Steve.png"
- Log(ex, "获取 Authlib-Injector 皮肤失败(" & UserName & ")", LogLevel.Hint)
- End If
- End Try
- Finish:
- '刷新显示
- If FrmLoginAuthSkin IsNot Nothing Then
- RunInUi(AddressOf FrmLoginAuthSkin.Skin.Load)
- ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
- Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
- End If
- End Sub
- '全部皮肤加载器
- '需要放在其中元素的后面,否则会因为它提前被加载而莫名其妙变成 Nothing
- Public Shared SkinLoaders As New List(Of LoaderTask(Of EqualableList(Of String), String)) From {SkinMs, SkinLegacy, SkinNide, SkinAuth}
- #End Region
- '版本选择按钮
- Private Sub BtnVersion_Click(sender As Object, e As EventArgs) Handles BtnVersion.Click
- If McLaunchLoader.State = LoadState.Loading Then Return
- FrmMain.PageChange(FormMain.PageType.InstanceSelect)
- End Sub
- '启动按钮
- Public Sub LaunchButtonClick() Handles BtnLaunch.Click
- If McLaunchLoader.State = LoadState.Loading OrElse Not BtnLaunch.IsEnabled OrElse
- (FrmMain.PageRight IsNot Nothing AndAlso FrmMain.PageRight.PageState <> MyPageRight.PageStates.ContentStay AndAlso FrmMain.PageRight.PageState <> MyPageRight.PageStates.ContentEnter) Then Return
- '愚人节处理
- If IsAprilEnabled AndAlso Not IsAprilGiveup Then
- ThemeUnlock(12, False, "隐藏主题 滑稽彩 已解锁!")
- IsAprilGiveup = True
- FrmLaunchLeft.AprilScaleTrans.ScaleX = 1
- FrmLaunchLeft.AprilScaleTrans.ScaleY = 1
- FrmLaunchLeft.AprilPosTrans.X = 0
- FrmLaunchLeft.AprilPosTrans.Y = 0
- FrmMain.BtnExtraApril.ShowRefresh()
- End If
- '实际的启动
- If BtnLaunch.Text = "启动游戏" Then
- McLaunchStart()
- ElseIf BtnLaunch.Text = "下载游戏" Then
- FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
- End If
- End Sub
- Private BtnLaunchState As Integer = 0
- Private BtnLaunchInstance As McInstance = Nothing
- Public Sub RefreshButtonsUI() Handles BtnLaunch.Loaded
- If Not BtnLaunch.IsLoaded Then Return
- '获取当前状态
- Dim CurrentState As Integer
- If (Not IsLoadFinished) OrElse McInstanceListLoader.State = LoadState.Loading OrElse McFolderListLoader.State = LoadState.Loading Then
- CurrentState = 0
- Else
- If McInstanceSelected Is Nothing Then
- If Setup.Get("UiHiddenPageDownload") AndAlso Not PageSetupUI.HiddenForceShow Then
- CurrentState = 1
- Else
- CurrentState = 2
- End If
- Else
- CurrentState = 3
- End If
- End If
- '更新状态
- If CurrentState = BtnLaunchState AndAlso
- If(McInstanceSelected Is Nothing, "", McInstanceSelected.PathVersion) = If(BtnLaunchInstance Is Nothing, "", BtnLaunchInstance.PathVersion) Then GoTo ExitRefresh
- BtnLaunchInstance = McInstanceSelected
- BtnLaunchState = CurrentState
- Select Case CurrentState
- Case 0
- Log("[Minecraft] 启动按钮:正在加载 Minecraft 版本")
- FrmLaunchLeft.BtnLaunch.Text = "正在加载"
- FrmLaunchLeft.BtnLaunch.IsEnabled = False
- FrmLaunchLeft.LabVersion.Text = "正在加载中,请稍候"
- FrmLaunchLeft.BtnVersion.IsEnabled = False
- FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
- Case 1
- Log("[Minecraft] 启动按钮:无 Minecraft 版本,下载已禁用")
- FrmLaunchLeft.BtnLaunch.Text = "启动游戏"
- FrmLaunchLeft.BtnLaunch.IsEnabled = False
- FrmLaunchLeft.LabVersion.Text = "未找到可用的游戏版本"
- FrmLaunchLeft.BtnVersion.IsEnabled = True
- FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
- Case 2
- Log("[Minecraft] 启动按钮:无 Minecraft 版本,要求下载")
- FrmLaunchLeft.BtnLaunch.Text = "下载游戏"
- FrmLaunchLeft.BtnLaunch.IsEnabled = True
- FrmLaunchLeft.LabVersion.Text = "未找到可用的游戏版本"
- FrmLaunchLeft.BtnVersion.IsEnabled = True
- FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
- Case 3
- Log("[Minecraft] 启动按钮:Minecraft 版本:" & McInstanceSelected.PathVersion)
- FrmLaunchLeft.BtnLaunch.Text = "启动游戏"
- FrmLaunchLeft.BtnVersion.IsEnabled = True
- FrmLaunchLeft.BtnLaunch.IsEnabled = True
- FrmLaunchLeft.LabVersion.Text = McInstanceSelected.Name
- 'FrmLaunchLeft.BtnMore.Visibility = Visibility.Visible '由功能隐藏设置修改
- End Select
- ExitRefresh:
- '功能隐藏
- FrmLaunchLeft.BtnVersion.Visibility = If(Not PageSetupUI.HiddenForceShow AndAlso Setup.Get("UiHiddenFunctionSelect"), Visibility.Collapsed, Visibility.Visible)
- If CurrentState = 3 Then
- FrmLaunchLeft.BtnMore.Visibility = FrmLaunchLeft.BtnVersion.Visibility
- End If
- End Sub
- '取消按钮
- Private Sub BtnCancel_Click() Handles BtnCancel.Click
- If McLaunchLoaderReal IsNot Nothing Then
- McLaunchLoaderReal.Abort()
- McLaunchLog("已取消启动")
- Try
- If McLaunchWatcher IsNot Nothing Then
- McLaunchWatcher.Kill()
- ElseIf McLaunchProcess IsNot Nothing Then
- If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
- End If
- Catch ex As Exception
- Log(ex, "取消启动结束进程失败", LogLevel.Hint)
- End Try
- End If
- End Sub
- '版本设置按钮
- Private Sub BtnMore_Click(sender As Object, e As EventArgs) Handles BtnMore.Click
- If McLaunchLoader.State = LoadState.Loading Then Return
- McInstanceSelected.Load()
- PageInstanceLeft.Instance = McInstanceSelected
- FrmMain.PageChange(FormMain.PageType.InstanceSetup, 0)
- End Sub
- ''' <summary>
- ''' 每 0.1s 执行一次,刷新启动的数据 UI 显示。
- ''' </summary>
- Public Sub LaunchingRefresh()
- Try
- If McLaunchLoaderReal.State = LoadState.Aborted Then Return
- '阶段状态获取
- Dim IsLaunched As Boolean = False '是否已经启动游戏,只是在等待窗口
- Try
- For Each Loader In McLaunchLoaderReal.GetLoaderList(False)
- If Loader.State = LoadState.Loading OrElse Loader.State = LoadState.Waiting Then
- LabLaunchingStage.Text = Loader.Name
- IsLaunched = Loader.Name = "等待游戏窗口出现" OrElse Loader.Name = "结束处理"
- Exit Try
- End If
- Next
- LabLaunchingStage.Text = "已完成"
- Catch ex As Exception
- Log(ex, "获取是否启动完成失败,可能是由于启动状态改变导致集合已修改")
- Return
- End Try
- LabLaunchingTitle.Text = If(IsLaunched OrElse McLaunchLoaderReal.State = LoadState.Finished,
- "已启动游戏",
- If(CurrentLaunchOptions.SaveBatch Is Nothing, "正在启动游戏", "正在导出启动脚本"))
- If AniIsRun("Launch State Page") Then IsLaunched = False '等待页面切换动画完成
- '更新进度
- Dim ActualProgress = McLaunchLoaderReal.Progress
- If ActualProgress >= ShowProgress Then ShowProgress += (ActualProgress - ShowProgress) * 0.1 + 0.0025 '向实际进度靠一点
- If ActualProgress <= ShowProgress Then ShowProgress = ActualProgress '原来或处理后变得比实际进度高,直接回退
- If IsLaunched Then ShowProgress = 1 '如果已经完成了,就不卖关子了
- LabLaunchingProgress.Text = (ShowProgress * 100).ToString("0.00") & " %"
- '更新下载速度
- Dim HasLaunchDownloader As Boolean = False
- Try
- If NetManager.Speed = 0 AndAlso LabLaunchingDownload.Visibility = Visibility.Collapsed Then
- '可能只是在检查文件,没有实际下载
- HasLaunchDownloader = False
- Else
- For Each Loader In NetManager.Tasks
- If Loader.RealParent IsNot Nothing AndAlso Loader.RealParent.Name = "Minecraft 启动" AndAlso Loader.State = LoadState.Loading Then HasLaunchDownloader = True
- Next
- End If
- Catch ex As Exception
- Log(ex, "获取 Minecraft 启动下载器失败,可能是因为启动被取消")
- HasLaunchDownloader = False
- End Try
- LabLaunchingDownload.Text = GetString(NetManager.Speed) & "/s"
- '进度改变动画
- Dim AnimList As New List(Of AniData) From {
- AaGridLengthWidth(ProgressLaunchingFinished, ShowProgress - ProgressLaunchingFinished.Width.Value, 130,, New AniEaseOutFluent),
- AaGridLengthWidth(ProgressLaunchingUnfinished, 1 - ShowProgress - ProgressLaunchingUnfinished.Width.Value, 130,, New AniEaseOutFluent)
- }
- If HasLaunchDownloader = (LabLaunchingDownload.Visibility = Visibility.Collapsed) Then 'IsDownloadStateChanged
- LabLaunchingDownload.Visibility = Visibility.Visible
- LabLaunchingDownloadLeft.Visibility = Visibility.Visible
- AnimList.AddRange({
- AaOpacity(LabLaunchingDownload, If(HasLaunchDownloader, 1, 0) - LabLaunchingDownload.Opacity, 90),
- AaOpacity(LabLaunchingDownloadLeft, If(HasLaunchDownloader, 0.5, 0) - LabLaunchingDownloadLeft.Opacity, 90),
- AaCode(
- Sub()
- If Not HasLaunchDownloader Then
- LabLaunchingDownload.Visibility = Visibility.Collapsed
- LabLaunchingDownloadLeft.Visibility = Visibility.Collapsed
- End If
- End Sub, 110)
- })
- End If
- If (Not IsLaunched) = (LabLaunchingProgress.Visibility = Visibility.Collapsed) Then 'IsProgressStateChanged
- LabLaunchingProgress.Visibility = Visibility.Visible
- LabLaunchingProgressLeft.Visibility = Visibility.Visible
- If IsLaunched Then PanLaunchingHint.Visibility = Visibility.Visible
- AnimList.AddRange({
- AaOpacity(LabLaunchingProgress, If(Not IsLaunched, 1, 0) - LabLaunchingProgress.Opacity, 90),
- AaOpacity(LabLaunchingProgressLeft, If(Not IsLaunched, 0.5, 0) - LabLaunchingProgressLeft.Opacity, 90),
- AaOpacity(PanLaunchingHint, If(IsLaunched, 1, 0) - PanLaunchingHint.Opacity, 90)
- })
- End If
- AniStart(AnimList, "Launching Progress")
- Catch ex As Exception
- Log(ex, "刷新启动信息失败", LogLevel.Feedback)
- End Try
- End Sub
- Private ShowProgress As Double = 0
- '尺寸改变动画
- Private IsWidthAnimating As Boolean = False
- Private ActualUsedWidth As Double
- Private Sub PanLaunchingInfo_SizeChangedW(sender As Object, e As SizeChangedEventArgs) Handles PanLaunchingInfo.SizeChanged
- Dim DeltaWidth As Double = e.NewSize.Width - e.PreviousSize.Width
- If e.PreviousSize.Width = 0 OrElse IsWidthAnimating OrElse Math.Abs(DeltaWidth) < 1 OrElse PanLaunchingInfo.ActualWidth = 0 Then Return
- AniStart({
- AaWidth(PanLaunchingInfo, DeltaWidth, 180,, New AniEaseOutFluent),
- AaCode(Sub()
- IsWidthAnimating = False
- PanLaunchingInfo.Width = ActualUsedWidth
- End Sub,, True)
- }, "Launching Info Width")
- IsWidthAnimating = True
- ActualUsedWidth = PanLaunchingInfo.Width
- PanLaunchingInfo.Width = e.PreviousSize.Width
- End Sub
- Private IsHeightAnimating As Boolean = False
- Private ActualUsedHeight As Double
- Private Sub PanLaunchingInfo_SizeChangedH(sender As Object, e As SizeChangedEventArgs) Handles PanLaunchingInfo.SizeChanged
- Dim DeltaHeight As Double = e.NewSize.Height - e.PreviousSize.Height
- If e.PreviousSize.Height = 0 OrElse IsHeightAnimating OrElse Math.Abs(DeltaHeight) < 1 OrElse PanLaunchingInfo.ActualHeight = 0 Then Return
- AniStart({
- AaHeight(PanLaunchingInfo, DeltaHeight, 180,, New AniEaseOutFluent),
- AaCode(Sub()
- IsHeightAnimating = False
- PanLaunchingInfo.Height = ActualUsedHeight
- End Sub,, True)
- }, "Launching Info Height")
- IsHeightAnimating = True
- ActualUsedHeight = PanLaunchingInfo.Height
- PanLaunchingInfo.Height = e.PreviousSize.Height
- End Sub
- End Class
|