| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- Public Class MySkin
- '事件
- Public Event Click(sender As Object, e As MouseButtonEventArgs)
- '皮肤储存
- Private _Address As String
- Public Property Address As String
- Get
- Return _Address
- End Get
- Set(value As String)
- _Address = value
- ToolTip = If(_Address = "", "加载中", "点击更换皮肤(右键查看更多选项)")
- End Set
- End Property
- Public Loader As LoaderTask(Of EqualableList(Of String), String)
- '控件动画
- Private Sub PanSkin_MouseEnter(sender As Object, e As MouseEventArgs) Handles Me.MouseEnter
- AniStart(AaOpacity(ShadowSkin, 0.8 - ShadowSkin.Opacity, 200, 100), "Skin Shadow")
- End Sub
- Private Sub PanSkin_MouseLeave(sender As Object, e As MouseEventArgs) Handles Me.MouseLeave
- AniStart(AaOpacity(ShadowSkin, 0.2 - ShadowSkin.Opacity, 200), "Skin Shadow")
- IsSkinMouseDown = False
- AniStart(AaScaleTransform(Me, 1 - CType(Me.RenderTransform, ScaleTransform).ScaleX, 60,, New AniEaseOutFluent), "Skin Scale")
- End Sub
- '点击
- Private IsSkinMouseDown As Boolean = False
- Private Sub PanSkin_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
- IsSkinMouseDown = True
- AniStart(AaScaleTransform(Me, 0.9 - CType(Me.RenderTransform, ScaleTransform).ScaleX, 60,, New AniEaseOutFluent), "Skin Scale")
- End Sub
- Private Sub PanSkin_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
- AniStart(AaScaleTransform(Me, 1 - CType(Me.RenderTransform, ScaleTransform).ScaleX, 60,, New AniEaseOutFluent), "Skin Scale")
- If IsSkinMouseDown Then
- IsSkinMouseDown = False
- RaiseEvent Click(sender, e)
- End If
- End Sub
- '保存皮肤
- Public Sub BtnSkinSave_Click() Handles BtnSkinSave.Click
- Save(Loader)
- End Sub
- Public Shared Sub Save(Loader As LoaderTask(Of EqualableList(Of String), String))
- Dim Address = Loader.Output
- If Not Loader.State = LoadState.Finished Then
- Hint("皮肤正在获取中,请稍候!", HintType.Red)
- If Not Loader.State = LoadState.Loading Then Loader.Start()
- Return
- End If
- Try
- Dim FileAddress As String = SelectSaveFile("选取保存皮肤的位置", GetFileNameFromPath(Address), "皮肤图片文件(*.png)|*.png")
- If FileAddress.Contains("\") Then
- File.Delete(FileAddress)
- If Address.StartsWith(PathImage) Then
- Dim Image As New MyBitmap(Address)
- Image.Save(FileAddress)
- Else
- CopyFile(Address, FileAddress)
- End If
- Hint("皮肤保存成功!", HintType.Green)
- End If
- Catch ex As Exception
- Log(ex, "保存皮肤失败", LogLevel.Hint)
- End Try
- End Sub
- Private Sub BtnSkinSave_Checked(sender As MyMenuItem, e As RoutedEventArgs) Handles BtnSkinSave.Checked
- sender.IsEnabled = Address = ""
- End Sub
- ''' <summary>
- ''' 载入皮肤。
- ''' </summary>
- Public Sub Load()
- Try
- '检查文件存在
- Address = Loader.Output
- If String.IsNullOrEmpty(Address) Then Throw New Exception("皮肤加载器 " & Loader.Name & " 没有输出")
- If Not Address.StartsWith(PathImage) AndAlso Not File.Exists(Address) Then Throw New FileNotFoundException("皮肤文件未找到", Address)
- '加载
- Dim Image As MyBitmap
- Try
- Image = New MyBitmap(Address)
- Catch ex As Exception '#2272
- Log(ex, $"皮肤文件已损坏:{Address}", LogLevel.Hint)
- File.Delete(Address)
- Return
- End Try
- ImgBack.Tag = Address
- '大小检查
- Dim Scale As Integer = Image.Pic.Width / 64
- If Image.Pic.Width < 32 OrElse Image.Pic.Height < 32 Then
- ImgFore.Source = Nothing : ImgBack.Source = Nothing
- Throw New Exception("图片大小不足,长为 " & Image.Pic.Height & ",宽为 " & Image.Pic.Width)
- End If
- '头发层(附加层)
- If Image.Pic.Width >= 64 AndAlso Image.Pic.Height >= 32 Then
- If (Image.Pic.GetPixel(1, 1).A = 0 OrElse '如果图片中有任何透明像素(避免纯色白底)
- Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1).A = 0 OrElse
- Image.Pic.GetPixel(Image.Pic.Width - 2, Image.Pic.Height / 2 - 2).A = 0) OrElse
- (Image.Pic.GetPixel(1, 1) <> Image.Pic.GetPixel(Scale * 41, Scale * 9) AndAlso '或是头部颜色和透明区均不一样
- Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1) <> Image.Pic.GetPixel(Scale * 41, Scale * 9) AndAlso
- Image.Pic.GetPixel(Image.Pic.Width - 2, Image.Pic.Height / 2 - 2) <> Image.Pic.GetPixel(Scale * 41, Scale * 9)) Then
- ImgFore.Source = Image.Clip(Scale * 40, Scale * 8, Scale * 8, Scale * 8)
- Else
- ImgFore.Source = Nothing
- End If
- Else
- ImgFore.Source = Nothing
- End If
- '脸层
- ImgBack.Source = Image.Clip(Scale * 8, Scale * 8, Scale * 8, Scale * 8)
- Log("[Skin] 载入头像成功:" & Loader.Name)
- Catch ex As Exception
- Log(ex, "载入头像失败(" & If(Address, "null") & "," & Loader.Name & ")", LogLevel.Hint)
- End Try
- End Sub
- ''' <summary>
- ''' 清空皮肤。
- ''' </summary>
- Public Sub Clear()
- Address = ""
- ImgFore.Source = Nothing
- ImgBack.Source = Nothing
- End Sub
- '刷新缓存
- Public Sub RefreshClick() Handles BtnSkinRefresh.Click
- RefreshCache(Loader)
- End Sub
- ''' <summary>
- ''' 刷新皮肤缓存。
- ''' </summary>
- Public Shared Sub RefreshCache(Optional sender As LoaderTask(Of EqualableList(Of String), String) = Nothing)
- Dim HasLoaderRunning As Boolean = False
- For Each SkinLoader In PageLaunchLeft.SkinLoaders
- If SkinLoader.State = LoadState.Loading Then
- HasLoaderRunning = True : Exit For
- End If
- Next
- If FrmLaunchLeft IsNot Nothing AndAlso HasLoaderRunning Then
- '由于 Abort 不是实时的,暂时不会释放文件,会导致删除报错,故只能取消执行
- Hint("有正在获取中的皮肤,请稍后再试!", HintType.Blue)
- Else
- RunInThread(
- Sub()
- Try
- Hint("正在刷新头像……")
- '清空缓存
- Log("[Skin] 正在清空皮肤缓存")
- If Directory.Exists(PathTemp & "Cache\Skin") Then DeleteDirectory(PathTemp & "Cache\Skin")
- If Directory.Exists(PathTemp & "Cache\Uuid") Then DeleteDirectory(PathTemp & "Cache\Uuid")
- IniClearCache(PathTemp & "Cache\Skin\IndexMs.ini")
- IniClearCache(PathTemp & "Cache\Skin\IndexNide.ini")
- IniClearCache(PathTemp & "Cache\Skin\IndexAuth.ini")
- IniClearCache(PathTemp & "Cache\Uuid\Mojang.ini")
- '刷新控件
- For Each SkinLoader In If(sender IsNot Nothing, {sender}, {PageLaunchLeft.SkinLegacy, PageLaunchLeft.SkinMs})
- SkinLoader.WaitForExit(IsForceRestart:=True)
- Next
- Hint("已刷新头像!", HintType.Green)
- Catch ex As Exception
- Log(ex, "刷新皮肤缓存失败", LogLevel.Msgbox)
- End Try
- End Sub)
- End If
- End Sub
- ''' <summary>
- ''' 在更换正版皮肤后,刷新正版皮肤。
- ''' </summary>
- ''' <param name="SkinAddress">新的正版皮肤完整地址。</param>
- Public Shared Sub ReloadCache(SkinAddress As String)
- RunInThread(
- Sub()
- Try
- '更新缓存
- WriteIni(PathTemp & "Cache\Skin\IndexMs.ini", Setup.Get("CacheMsV2Uuid"), SkinAddress)
- Log($"[Skin] 已写入皮肤地址缓存 {Setup.Get("CacheMsV2Uuid")} -> {SkinAddress}")
- '刷新控件
- For Each SkinLoader In {PageLaunchLeft.SkinMs, PageLaunchLeft.SkinLegacy}
- SkinLoader.WaitForExit(IsForceRestart:=True)
- Next
- '完成提示
- Hint("更改皮肤成功!", HintType.Green)
- Catch ex As Exception
- Log(ex, "更改正版皮肤后刷新皮肤失败", LogLevel.Feedback)
- End Try
- End Sub)
- End Sub
- '披风
- Public Property HasCape As Boolean
- Get
- Return BtnSkinCape.Visibility = Visibility.Collapsed
- End Get
- Set(value As Boolean)
- If value Then
- BtnSkinCape.Visibility = Visibility.Visible
- Else
- BtnSkinCape.Visibility = Visibility.Collapsed
- End If
- End Set
- End Property
- Private IsChanging As Boolean = False
- Public Sub BtnSkinCape_Click() Handles BtnSkinCape.Click
- '检查条件,获取新披风
- If IsChanging Then
- Hint("正在更改披风中,请稍候!")
- Return
- End If
- If McLoginMsLoader.State = LoadState.Failed Then
- Hint("登录失败,无法更改披风!", HintType.Red)
- Return
- End If
- Hint("正在获取披风列表,请稍候……")
- IsChanging = True
- '开始实际获取
- RunInNewThread(
- Sub()
- Try
- Retry:
- '获取登录信息
- If McLoginMsLoader.State <> LoadState.Finished Then McLoginMsLoader.WaitForExit(PageLoginMsSkin.GetLoginData())
- If McLoginMsLoader.State <> LoadState.Finished Then
- Hint("登录失败,无法更改披风!", HintType.Red)
- Return
- End If
- Dim AccessToken As String = McLoginMsLoader.Output.AccessToken
- Dim Uuid As String = McLoginMsLoader.Output.Uuid
- Dim SkinData As JObject = GetJson(McLoginMsLoader.Output.ProfileJson)
- '获取玩家的所有披风
- Dim SelId As Integer? = Nothing
- RunInUiWait(
- Sub()
- Try
- Dim CapeNames As New Dictionary(Of String, String) From {
- {"Migrator", "迁移者披风"}, {"MapMaker", "Realms 地图制作者披风"}, {"Moderator", "Mojira 管理员披风"},
- {"Translator-Chinese", "Crowdin 中文翻译者披风"}, {"Translator", "Crowdin 翻译者披风"}, {"Cobalt", "Cobalt 披风"},
- {"Vanilla", "原版披风"}, {"Minecon2011", "Minecon 2011 参与者披风"}, {"Minecon2012", "Minecon 2012 参与者披风"},
- {"Minecon2013", "Minecon 2013 参与者披风"}, {"Minecon2015", "Minecon 2015 参与者披风"}, {"Minecon2016", "Minecon 2016 参与者披风"},
- {"Cherry Blossom", "樱花披风"}, {"15th Anniversary", "15 周年纪念披风"}, {"Purple Heart", "紫色心形披风"},
- {"Follower's", "追随者披风"}, {"MCC 15th Year", "MCC 15 周年披风"}, {"Minecraft Experience", "村民救援披风"},
- {"Mojang Office", "Mojang 办公室披风"}, {"Home", "家园披风"}, {"Menace", "入侵披风"}, {"Yearn", "渴望披风"},
- {"Common", "普通披风"}, {"Pan", "薄煎饼披风"}, {"Founder's", "创始人披风"}, {"Copper", "铜披风"}, {"Zombie Horse", "僵尸马披风"}
- }
- Dim SelectionControl As New List(Of IMyRadio) From {New MyRadioBox With {.Text = "无披风"}}
- For Each Cape In SkinData("capes")
- Dim CapeName As String = Cape("alias").ToString
- If CapeNames.ContainsKey(CapeName) Then CapeName = CapeNames(CapeName)
- SelectionControl.Add(New MyRadioBox With {.Text = CapeName, .Checked = Cape("state")?.ToString = "ACTIVE"})
- Next
- SelId = MyMsgBoxSelect(SelectionControl, "选择披风", "确定", "取消")
- Catch ex As Exception
- Log(ex, "获取玩家皮肤列表失败", LogLevel.Feedback)
- End Try
- End Sub)
- If SelId Is Nothing Then Return
- '发送请求
- Dim Result As String = NetRequestByClientRetry("https://api.minecraftservices.com/minecraft/profile/capes/active",
- If(SelId = 0, HttpMethod.Delete, HttpMethod.Put),
- Content:=If(SelId = 0, "", New JObject(New JProperty("capeId", SkinData("capes")(SelId - 1)("id"))).ToString(0)),
- ContentType:="application/json",
- Headers:={{"Authorization", "Bearer " & AccessToken}})
- If Result.Contains("""errorMessage""") Then
- Hint("更改披风失败:" & GetJson(Result)("errorMessage").ToString, HintType.Red)
- Return
- Else
- Hint("更改披风成功!", HintType.Green)
- End If
- Catch ex As Exception
- Log(ex, "更改披风失败", LogLevel.Hint)
- Finally
- IsChanging = False
- End Try
- End Sub, "Cape Change")
- End Sub
- End Class
|