Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd329037e7 | ||
|
|
5fb5a3b963 | ||
|
|
5ef1d60e2e | ||
|
|
d091e153a9 | ||
|
|
97c5367108 | ||
|
|
24cb4599d6 | ||
|
|
ef32179598 | ||
|
|
e9b34ad998 | ||
|
|
2d9a4d9391 | ||
|
|
89f6059ea8 | ||
|
|
1368a902c8 | ||
|
|
0066d1b35e | ||
|
|
dcf0e17890 | ||
|
|
f7c10035e8 | ||
|
|
9876fe3442 | ||
|
|
8175425458 | ||
|
|
cb3b748367 | ||
|
|
f67189919f | ||
|
|
07061dc4a1 | ||
|
|
d7a8c03776 | ||
|
|
c400836de8 | ||
|
|
bbbafa5429 |
No files matched your search
@@ -8,9 +8,9 @@ body:
|
||||
label: "检查项"
|
||||
description: "请逐个检查下列项目,并勾选确认。"
|
||||
options:
|
||||
- label: "**我所启动的游戏不是整合包,且未开启安装 Mod。** 安装 Mod 后的游戏崩溃不是 PCL2 的原因,请 **不要** 提交反馈。你可以在 QQ 群里或者论坛找人求助,但这里并不是你求助的地方。"
|
||||
- label: "**我所启动的游戏不是整合包,且未安装任何 Mod。** 安装 Mod 后的游戏崩溃不是 PCL2 的原因,请 **不要** 提交反馈。你可以在 QQ 群里或者论坛找人求助,但这里并不是你求助的地方。"
|
||||
required: true
|
||||
- label: "**我已尝试使用其他启动器,其他启动器没有出现问题。** 如果其他启动器也存在问题,证明是游戏本身存在问题,并非 PCL2 的问题,请 **不要** 提交反馈。[下载其他启动器](https://www.mcbbs.net/forum.php?mod=forumdisplay&fid=43&filter=typeid&typeid=908)"
|
||||
- label: "**我已尝试使用其他启动器,其他启动器没有出现问题。** 如果其他启动器也存在问题,证明是游戏本身的问题,并非 PCL2 的问题,请 **不要** 提交反馈。[下载其他启动器](https://www.mcbbs.net/forum.php?mod=forumdisplay&fid=43&filter=typeid&typeid=908)"
|
||||
required: true
|
||||
- label: "我已点击 `设置 → 启动器 → 检查更新` 确认了启动器已为最新版,且最新版未修复这个 Bug。[怎样更新?](https://shimo.im/docs/qKPttVvXKqPD8YDC#anchor-oTgb)"
|
||||
required: true
|
||||
@@ -27,7 +27,7 @@ body:
|
||||
id: "yml-3"
|
||||
attributes:
|
||||
label: 错误报告、日志与附件
|
||||
description: "上传 PCL2 提供的错误报告。如果没有,也可以上传 PCL 文件夹中的 Log1~5.txt。"
|
||||
description: "上传 PCL2 提供的错误报告(在崩溃时选择导出错误报告)。如果没有,也可以上传 PCL 文件夹中的 Log1~5.txt。"
|
||||
placeholder: "先点击这个文本框,然后再将文件直接拖拽到文本框中以上传。"
|
||||
validations:
|
||||
required: true
|
||||
@@ -3,9 +3,6 @@ contact_links:
|
||||
- name: 帮助文档反馈
|
||||
url: https://github.com/LTCatt/PCL2Help/issues
|
||||
about: 提交 PCL2 帮助系统(更多 → 帮助)相关的反馈
|
||||
- name: 联机模块反馈
|
||||
url: https://mcer.cn/
|
||||
about: 向联机模块开发者提交反馈
|
||||
- name: 提问
|
||||
url: https://github.com/Hex-Dragon/PCL2/discussions/new?category=%E6%8F%90%E9%97%AE
|
||||
about: 我不想提交反馈,只是想问一些问题
|
||||
@@ -1,7 +1,3 @@
|
||||
|
||||
# Ignore Root .txt File
|
||||
/*.txt
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
@@ -347,16 +343,12 @@ healthchecksdb
|
||||
|
||||
# ------------------------------------------------------------
|
||||
|
||||
*.lnk
|
||||
|
||||
# 包含主题解锁、加密解密等部分的代码
|
||||
ModSecret.vb
|
||||
ModSetup.vb
|
||||
PageOtherAbout.*
|
||||
PageOtherTest.*
|
||||
PageSetupUI.*
|
||||
# 公开联机代码可能导致安全风险
|
||||
PageLink/
|
||||
# 开发者工具
|
||||
ModDevelop.vb
|
||||
# 不公开底层函数库,以免抄袭
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
本文件不是法律文件或开源协议。
|
||||
龙腾猫跃(下文简称为龙猫)承诺在您遵守本文件指引的情况下,不会追究您的法律责任,但裁量您 “是否遵守本文件指引” 的最终权利由龙猫保留。
|
||||
|
||||
1、本存储库中的内容以帮助公共研究为目的而公开。
|
||||
2、在没有附加许可的情况下,龙猫仍然对本存储库的内容保留所有权利,故以下所有允许性表述均无法作出永久性保证。
|
||||
3、不允许以本存储库的内容作为内容主体创建、发布、传播其衍生作品,且您不可以发布本存储库及其相关作品的修改版。
|
||||
4、在满足第 3 款,且在可见位置标注内容来源(即本存储库链接)的前提下,您可以使用或引用本存储库的小部分内容或是其实现思路。
|
||||
5、龙猫可能随时修改本文件,且可能不会提前通知。本文件不是法律文件或开源协议,故本文件的修改不构成与您法律关系的改变。
|
||||
|
||||
——————
|
||||
|
||||
说人话就是,随便你参考这堆代码的思路,乃至复制一两个函数什么的也可以,别太过火就行,顺便记得声明一下这段是从这里来的。
|
||||
不过,你不能把它们直接复制下来然后再小修小补,就说这是你自己的东西。也不能把其中一小部分单独抠出来说是你自己的东西。
|
||||
没有法律顾问,所以这只是明确说明一下,你可以借鉴其中的小部分内容,我也不会且懒得因此找你麻烦。
|
||||
如果有专业人士愿意帮帮忙把这堆东西写得专业一点我也很乐意……
|
||||
@@ -23,7 +23,9 @@
|
||||
<SolidColorBrush x:Key="ColorBrush6">#d5e6fd</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrush7">#e0eafd</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrush8">#eaf2fe</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrush9">#80e0eafd</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushBg0">#96c0f9</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushBg1">#bee0eafd</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushBg2">#50e0eafd</SolidColorBrush>
|
||||
<Color x:Key="ColorObject1">#343d4a</Color>
|
||||
<Color x:Key="ColorObject2">#0b5bcb</Color>
|
||||
<Color x:Key="ColorObject3">#1370f3</Color>
|
||||
@@ -32,7 +34,9 @@
|
||||
<Color x:Key="ColorObject6">#d5e6fd</Color>
|
||||
<Color x:Key="ColorObject7">#e0eafd</Color>
|
||||
<Color x:Key="ColorObject8">#eaf2fe</Color>
|
||||
<Color x:Key="ColorObject9">#40eaf2fe</Color>
|
||||
<Color x:Key="ColorObjectBg0">#96c0f9</Color>
|
||||
<Color x:Key="ColorObjectBg1">#bee0eafd</Color>
|
||||
<Color x:Key="ColorObjectBg2">#50e0eafd</Color>
|
||||
<SolidColorBrush x:Key="ColorBrushGray1">#404040</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushGray2">#737373</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushGray3">#8c8c8c</SolidColorBrush>
|
||||
@@ -53,6 +57,8 @@
|
||||
<SolidColorBrush x:Key="ColorBrushRedLight">#ff4c4c</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushRedDark">#ce2111</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushHalfWhite" Color="#44ffffff" />
|
||||
<SolidColorBrush x:Key="ColorBrushSemiWhite" Color="#bbffffff" />
|
||||
<SolidColorBrush x:Key="ColorBrushWhite" Color="#ffffff" />
|
||||
<SolidColorBrush x:Key="ColorBrushTransparent" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="ColorBrushSemiTransparent">#01eaf2fe</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ColorBrushBackgroundTransparentSidebar" Color="#D2FFFFFF" />
|
||||
@@ -258,7 +264,7 @@
|
||||
<!-- TextBox -->
|
||||
<Style TargetType="local:MyTextBox">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="Background" Value="{StaticResource ColorBrushHalfWhite}" />
|
||||
<Setter Property="Background" Value="{StaticResource ColorBrushBg2}" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="SelectionBrush" Value="{DynamicResource ColorBrush3}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ColorBrush1}" />
|
||||
@@ -274,7 +280,7 @@
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
|
||||
<Setter Property="UndoLimit" Value="15" />
|
||||
<Setter Property="MaxLength" Value="10000" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrush1}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrushBg0}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="TextBox">
|
||||
@@ -283,14 +289,14 @@
|
||||
<RowDefinition MinHeight="28" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Border Margin="{TemplateBinding Padding}" IsHitTestVisible="False" VerticalAlignment="Center" BorderThickness="0">
|
||||
<TextBlock x:Name="labHint" Foreground="{StaticResource ColorBrushGray3}" Margin="7,0,0,0" Padding="{TemplateBinding BorderThickness}" FontSize="{TemplateBinding FontSize}" FontFamily="Resources/#PCL English, Microsoft YaHei UI" />
|
||||
</Border>
|
||||
<Border x:Name="border" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" CornerRadius="3">
|
||||
<ScrollViewer x:Name="PART_ContentHost" Style="{StaticResource ScrollViewerNoMargin}" RenderOptions.ClearTypeHint="Enabled" BorderThickness="0"
|
||||
Margin="5,0,0,0" Cursor="IBeam" />
|
||||
<!-- 由于未知原因,TextView 会有 2,0 的 Margin -->
|
||||
</Border>
|
||||
<Border Margin="{TemplateBinding Padding}" IsHitTestVisible="False" VerticalAlignment="Center" BorderThickness="0">
|
||||
<TextBlock x:Name="labHint" Foreground="{DynamicResource ColorBrush1}" Opacity="0.3" Margin="7,0,0,0" Padding="{TemplateBinding BorderThickness}" FontSize="{TemplateBinding FontSize}" FontFamily="Resources/#PCL English, Microsoft YaHei UI" />
|
||||
</Border>
|
||||
<TextBlock Grid.Row="1" x:Name="labWrong" Height="0" Foreground="{TemplateBinding BorderBrush}" Padding="0,4,0,0" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
@@ -302,8 +308,8 @@
|
||||
<Setter Property="VerticalContentAlignment" Value="Top" />
|
||||
<Setter Property="SelectionBrush" Value="{DynamicResource ColorBrush3}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ColorBrush1}" />
|
||||
<Setter Property="Background" Value="{StaticResource ColorBrushHalfWhite}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrush1}" />
|
||||
<Setter Property="Background" Value="{StaticResource ColorBrushBg2}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrushBg0}" />
|
||||
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||
@@ -317,19 +323,20 @@
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Trigger.Setters>
|
||||
<Setter Property="Foreground" Value="{StaticResource ColorBrushGray4}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource ColorBrushGray4}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource ColorBrushGray5}" />
|
||||
<Setter Property="Background" Value="{StaticResource ColorBrushGray6}" />
|
||||
</Trigger.Setters>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Trigger.Setters>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrush3}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrush4}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ColorBrush7}" />
|
||||
</Trigger.Setters>
|
||||
</Trigger>
|
||||
<Trigger Property="IsFocused" Value="True">
|
||||
<Trigger.Setters>
|
||||
<Setter Property="Background" Value="{DynamicResource ColorBrush9}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrush4}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ColorBrush3}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ColorBrushSemiWhite}" />
|
||||
</Trigger.Setters>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
@@ -348,16 +355,12 @@
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
</DataTemplate>
|
||||
<!--<DataTemplate x:Key="ComboBoxItemTemplateNormal">
|
||||
<local:MyListItem Title="{Binding}" FontSize="13" PaddingRight="40" Height="26" Margin="-1,0,0,0" />
|
||||
</DataTemplate>-->
|
||||
<Style TargetType="local:MyComboBox">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ColorBrush1}" />
|
||||
<Setter Property="Background" Value="{StaticResource ColorBrushHalfWhite}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ColorBrushBg0}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ColorBrushBg2}" />
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
|
||||
<!--<Setter Property="ItemTemplate" Value="{StaticResource ComboBoxItemTemplateNormal}"/>-->
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="MaxDropDownHeight" Value="160" />
|
||||
<Setter Property="Template">
|
||||
|
||||
@@ -15,7 +15,6 @@ Public Class Application
|
||||
Log(ex, "开发者模式测试出错", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
#End If
|
||||
|
||||
'开始
|
||||
@@ -30,7 +29,7 @@ Public Class Application
|
||||
UpdateReplace(e.Args(1), e.Args(2).Trim(""""), e.Args(3).Trim(""""), e.Args(4))
|
||||
Environment.[Exit](Result.Cancel)
|
||||
Exit Sub
|
||||
ElseIf e.Args(0) = "--link" Then
|
||||
ElseIf e.Args(0).StartsWith("--link") Then
|
||||
'稍作等待后切换到联机页面
|
||||
Thread.Sleep(1000)
|
||||
FormMain.IsLinkRestart = True
|
||||
@@ -50,7 +49,7 @@ Public Class Application
|
||||
Directory.CreateDirectory(PathTemp)
|
||||
If Not CheckPermission(PathTemp) Then Throw New Exception("PCL2 没有对 " & PathTemp & " 的访问权限")
|
||||
Catch ex As Exception
|
||||
MyMsgBox("手动设置的缓存文件夹不可用,PCL2 将使用默认缓存文件夹。" & vbCrLf & "错误原因:" & GetString(ex, False), "缓存文件夹不可用")
|
||||
MyMsgBox("手动设置的缓存文件夹不可用,PCL2 将使用默认缓存文件夹。" & vbCrLf & "错误原因:" & GetExceptionDetail(ex), "缓存文件夹不可用")
|
||||
Setup.Set("SystemSystemCache", "")
|
||||
PathTemp = IO.Path.GetTempPath() & "PCL\"
|
||||
End Try
|
||||
@@ -105,7 +104,7 @@ Public Class Application
|
||||
#End If
|
||||
AniControlEnabled += 1
|
||||
Catch ex As Exception
|
||||
MsgBox(GetString(ex, False, True), MsgBoxStyle.Critical, "PCL2 初始化错误")
|
||||
MsgBox(GetExceptionDetail(ex, True), MsgBoxStyle.Critical, "PCL2 初始化错误")
|
||||
FormMain.EndProgramForce(Result.Exception)
|
||||
End Try
|
||||
End Sub
|
||||
@@ -127,13 +126,13 @@ Public Class Application
|
||||
Exit Sub
|
||||
End If
|
||||
IsCritErrored = True
|
||||
Dim ExceptionString As String = GetString(e.Exception, False, True)
|
||||
Dim ExceptionString As String = GetExceptionDetail(e.Exception, True)
|
||||
If ExceptionString.Contains("System.Windows.Threading.Dispatcher.Invoke") OrElse
|
||||
ExceptionString.Contains("MS.Internal.AppModel.ITaskbarList.HrInit") OrElse
|
||||
ExceptionString.Contains(".Net Framework") OrElse ' “自动错误判断” 的结果分析
|
||||
ExceptionString.Contains(".NET Framework") OrElse ' “自动错误判断” 的结果分析
|
||||
ExceptionString.Contains("未能加载文件或程序集") Then
|
||||
OpenWebsite("https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/thank-you/net462-offline-installer")
|
||||
MsgBox("你的 .Net Framework 版本过低或损坏,请在打开的网页中重新下载并安装 .NET Framework 4.6.2 后重试!", MsgBoxStyle.Information, "运行环境错误")
|
||||
MsgBox("你的 .NET Framework 版本过低或损坏,请在打开的网页中重新下载并安装 .NET Framework 4.6.2 后重试!", MsgBoxStyle.Information, "运行环境错误")
|
||||
FormMain.EndProgramForce(Result.Cancel)
|
||||
Else
|
||||
FeedbackInfo()
|
||||
@@ -142,11 +141,9 @@ Public Class Application
|
||||
End Sub
|
||||
|
||||
'动态 DLL 调用
|
||||
Private Shared AssemblyStun As Assembly
|
||||
Private Shared AssemblyNAudio As Assembly
|
||||
Private Shared AssemblyJson As Assembly
|
||||
Private Shared AssemblyDialog As Assembly
|
||||
Private Shared ReadOnly AssemblyStunLock As New Object
|
||||
Private Shared ReadOnly AssemblyNAudioLock As New Object
|
||||
Private Shared ReadOnly AssemblyJsonLock As New Object
|
||||
Private Shared ReadOnly AssemblyDialogLock As New Object
|
||||
@@ -175,14 +172,6 @@ Public Class Application
|
||||
End If
|
||||
Return AssemblyDialog
|
||||
End SyncLock
|
||||
ElseIf args.Name.StartsWith("STUN") Then
|
||||
SyncLock AssemblyStunLock
|
||||
If AssemblyStun Is Nothing Then
|
||||
Log("[Start] 加载 DLL:STUN")
|
||||
AssemblyStun = Assembly.Load(GetResources("STUN"))
|
||||
End If
|
||||
Return AssemblyStun
|
||||
End SyncLock
|
||||
Else
|
||||
Return Nothing
|
||||
End If
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Public Class MyButton
|
||||
|
||||
'声明
|
||||
Public Event Click(sender As Object, e As EventArgs) '自定义事件
|
||||
Public Event Click(sender As Object, e As MouseButtonEventArgs) '自定义事件
|
||||
|
||||
'自定义属性
|
||||
Public Uuid As Integer = GetUuid()
|
||||
@@ -177,7 +177,7 @@
|
||||
}, "MyButton Scale " & Uuid)
|
||||
End Sub
|
||||
Private Sub Button_MouseEnter() Handles Me.MouseEnter
|
||||
AniStart(AaColor(PanFore, BackgroundProperty, If(_ColorType = ColorState.Red, "ColorBrushRedBack", "ColorBrush9"), AnimationColorIn), "MyButton Background " & Uuid)
|
||||
AniStart(AaColor(PanFore, BackgroundProperty, If(_ColorType = ColorState.Red, "ColorBrushRedBack", "ColorBrushBg1"), AnimationColorIn), "MyButton Background " & Uuid)
|
||||
End Sub
|
||||
Private Sub Button_MouseUp() Handles Me.MouseLeftButtonUp
|
||||
If Not IsMouseDown Then Exit Sub
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
Private ReadOnly MainGrid As Grid
|
||||
Private ReadOnly MainChrome As SystemDropShadowChrome
|
||||
Private ReadOnly MainBorder As Border
|
||||
Public Property BorderChild As UIElement
|
||||
Get
|
||||
Return MainBorder.Child
|
||||
End Get
|
||||
Set(value As UIElement)
|
||||
MainBorder.Child = value
|
||||
End Set
|
||||
End Property
|
||||
Public MainTextBlock As TextBlock
|
||||
Public MainSwap As Shapes.Path
|
||||
|
||||
@@ -25,9 +33,9 @@
|
||||
Public Sub New()
|
||||
MainChrome = New SystemDropShadowChrome With {.Margin = New Thickness(-9.5, -9, 0.5, -0.5), .Opacity = 0.1, .CornerRadius = New CornerRadius(6)}
|
||||
MainChrome.SetResourceReference(SystemDropShadowChrome.ColorProperty, "ColorObject1")
|
||||
Children.Add(MainChrome)
|
||||
Children.Insert(0, MainChrome)
|
||||
MainBorder = New Border With {.Background = New SolidColorBrush(Color.FromArgb(205, 255, 255, 255)), .CornerRadius = New CornerRadius(6), .IsHitTestVisible = False}
|
||||
Children.Add(MainBorder)
|
||||
Children.Insert(1, MainBorder)
|
||||
MainGrid = New Grid
|
||||
Children.Add(MainGrid)
|
||||
End Sub
|
||||
@@ -122,7 +130,9 @@
|
||||
Case 6
|
||||
Stack.Children.Add(ForgeDownloadListItem(Data, AddressOf ForgeSave_Click, True))
|
||||
Case 7
|
||||
Stack.Children.Add(McDownloadListItem(Data, AddressOf FrmDownloadInstall.MinecraftSelected, False))
|
||||
Stack.Children.Add(McDownloadListItem(Data, Sub(sender, e) '不能使用 AddressOf,这导致了 #535,原因完全不明,疑似是编译器 Bug
|
||||
FrmDownloadInstall.MinecraftSelected(sender, e)
|
||||
End Sub, False))
|
||||
Case 8
|
||||
Stack.Children.Add(CType(Data, DlCfFile).ToListItem(AddressOf FrmDownloadCfDetail.Save_Click))
|
||||
Case 9
|
||||
@@ -279,9 +289,9 @@
|
||||
End Class
|
||||
Partial Public Module ModAnimation
|
||||
Public Sub AniDispose(Control As MyCard, RemoveFromChildren As Boolean, Optional CallBack As ParameterizedThreadStart = Nothing)
|
||||
If Not Control.IsHitTestVisible Then Exit Sub
|
||||
Control.IsHitTestVisible = False
|
||||
AniStart({
|
||||
If Control.IsHitTestVisible Then
|
||||
Control.IsHitTestVisible = False
|
||||
AniStart({
|
||||
AaScaleTransform(Control, -0.08, 200,, New AniEaseInFluent),
|
||||
AaOpacity(Control, -1, 200,, New AniEaseOutFluent),
|
||||
AaHeight(Control, -Control.ActualHeight, 150, 100, New AniEaseOutFluent),
|
||||
@@ -294,5 +304,13 @@ Partial Public Module ModAnimation
|
||||
If CallBack IsNot Nothing Then CallBack(Control)
|
||||
End Sub,, True)
|
||||
}, "MyCard Dispose " & Control.Uuid)
|
||||
Else
|
||||
If RemoveFromChildren Then
|
||||
CType(Control.Parent, Object).Children.Remove(Control)
|
||||
Else
|
||||
Control.Visibility = Visibility.Collapsed
|
||||
End If
|
||||
If CallBack IsNot Nothing Then CallBack(Control)
|
||||
End If
|
||||
End Sub
|
||||
End Module
|
||||
@@ -5,7 +5,7 @@
|
||||
FocusVisualStyle="{x:Null}"
|
||||
MinWidth="20" x:Name="PanBack" UseLayoutRounding="False" SnapsToDevicePixels="False" MinHeight="20" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True" d:DesignWidth="126.4" d:DesignHeight="44.8">
|
||||
<TextBlock IsHitTestVisible="False" FontSize="13" x:Name="LabText" Padding="0" Margin="26,0,0,0" Text="Checkbox" Foreground="{DynamicResource ColorBrush1}" HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||
<Border IsHitTestVisible="False" x:Name="ShapeBorder" BorderThickness="1.1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="18" Height="18" BorderBrush="{DynamicResource ColorBrush1}" CornerRadius="3" Margin="1,0,0,0" Background="{StaticResource ColorBrushHalfWhite}" />
|
||||
<Border IsHitTestVisible="False" x:Name="ShapeBorder" BorderThickness="1.1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="18" Height="18" BorderBrush="{DynamicResource ColorBrush1}" CornerRadius="3" Margin="1,0,0,0" Background="{StaticResource ColorBrushBg2}" />
|
||||
<Path IsHitTestVisible="False" x:Name="ShapeCheck" HorizontalAlignment="Left" VerticalAlignment="Center" Fill="{Binding BorderBrush, ElementName=ShapeBorder}" Width="12" Height="12" Margin="4,0,0,0" Data="M0,6L1.5,4.5 4.5,7.5 10.5,1.5 12,3 4.5,10.5 0,6z">
|
||||
<Path.RenderTransform>
|
||||
<ScaleTransform CenterX="6" CenterY="6" ScaleX="0" ScaleY="0" />
|
||||
|
||||
@@ -124,13 +124,13 @@
|
||||
Log("[Control] 按下复选框(" & (Not Checked).ToString & "):" & Text)
|
||||
MouseDowned = False
|
||||
SetChecked(Not Checked, True, True)
|
||||
AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushHalfWhite", 100), "MyCheckBox Background " & Uuid)
|
||||
AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushBg2", 100), "MyCheckBox Background " & Uuid)
|
||||
End Sub
|
||||
Private Sub Checkbox_MouseDown() Handles Me.MouseLeftButtonDown
|
||||
If Not AllowMouseDown Then Exit Sub
|
||||
MouseDowned = True
|
||||
Focus()
|
||||
AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrush9", 100), "MyCheckBox Background " & Uuid)
|
||||
AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushBg1", 100), "MyCheckBox Background " & Uuid)
|
||||
If Checked Then
|
||||
AniStart({
|
||||
AaScale(ShapeBorder, 16.5 - ShapeBorder.Width, 1000, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True),
|
||||
@@ -143,7 +143,7 @@
|
||||
Private Sub Checkbox_MouseLeave() Handles Me.MouseLeave
|
||||
If Not MouseDowned Then Exit Sub
|
||||
MouseDowned = False
|
||||
AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushHalfWhite", 100), "MyCheckBox Background " & Uuid)
|
||||
AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushBg2", 100), "MyCheckBox Background " & Uuid)
|
||||
If Checked Then
|
||||
AniStart({
|
||||
AaScale(ShapeBorder, 18 - ShapeBorder.Width, 400, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True),
|
||||
|
||||
@@ -62,44 +62,40 @@
|
||||
'指向动画
|
||||
Public Sub RefreshColor() Handles Me.IsEnabledChanged, Me.MouseEnter, Me.MouseLeave, Me.PreviewMouseLeftButtonDown, Me.PreviewMouseLeftButtonUp, Me.GotKeyboardFocus
|
||||
'判断当前颜色
|
||||
Dim ColorName As String
|
||||
Dim BackName As String
|
||||
Dim ForeColorName As String
|
||||
Dim BackColorName As String
|
||||
Dim Time As Integer
|
||||
If IsEnabled Then
|
||||
If IsEditable AndAlso Template.FindName("PART_EditableTextBox", Me).IsFocused Then
|
||||
ColorName = "ColorBrush4"
|
||||
BackName = "ColorBrush9"
|
||||
Time = 60
|
||||
ElseIf IsMouseDown OrElse IsDropDownOpen Then
|
||||
ColorName = "ColorBrush3"
|
||||
BackName = "ColorBrush9"
|
||||
Time = 60
|
||||
If IsMouseDown OrElse IsDropDownOpen OrElse (IsEditable AndAlso Template.FindName("PART_EditableTextBox", Me).IsFocused) Then
|
||||
ForeColorName = "ColorBrush3"
|
||||
BackColorName = "ColorBrushSemiWhite"
|
||||
Time = 10
|
||||
ElseIf IsMouseOver Then
|
||||
ColorName = "ColorBrush3"
|
||||
BackName = "ColorBrushHalfWhite"
|
||||
Time = 100
|
||||
ForeColorName = "ColorBrush4"
|
||||
BackColorName = "ColorBrush7"
|
||||
Time = 50
|
||||
Else
|
||||
ColorName = "ColorBrush1"
|
||||
BackName = "ColorBrushHalfWhite"
|
||||
Time = 200
|
||||
ForeColorName = "ColorBrushBg0"
|
||||
BackColorName = "ColorBrushBg2"
|
||||
Time = 50
|
||||
End If
|
||||
Else
|
||||
ColorName = "ColorBrushGray4"
|
||||
BackName = "ColorBrushHalfWhite"
|
||||
ForeColorName = "ColorBrushGray5"
|
||||
BackColorName = "ColorBrushGray6"
|
||||
Time = 200
|
||||
End If
|
||||
'触发颜色动画
|
||||
If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
|
||||
'有动画
|
||||
AniStart({
|
||||
AaColor(Me, ForegroundProperty, ColorName, Time),
|
||||
AaColor(Me, BackgroundProperty, BackName, Time)
|
||||
AaColor(Me, ForegroundProperty, ForeColorName, Time),
|
||||
AaColor(Me, BackgroundProperty, BackColorName, Time)
|
||||
}, "MyComboBox Color " & Uuid)
|
||||
Else
|
||||
'无动画
|
||||
AniStop("MyComboBox Color " & Uuid)
|
||||
SetResourceReference(ForegroundProperty, ColorName)
|
||||
SetResourceReference(BackgroundProperty, BackName)
|
||||
SetResourceReference(ForegroundProperty, ForeColorName)
|
||||
SetResourceReference(BackgroundProperty, BackColorName)
|
||||
End If
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
Color
|
||||
White
|
||||
Black
|
||||
Red
|
||||
Custom
|
||||
End Enum
|
||||
Public Property Theme As Themes = Themes.Color
|
||||
@@ -101,6 +102,8 @@
|
||||
AnimList.Add(AaColor(Path, Shape.FillProperty, "ColorBrush2", AnimationColorIn))
|
||||
Case Themes.White
|
||||
AnimList.Add(AaColor(PanBack, BackgroundProperty, New MyColor(50, 255, 255, 255) - PanBack.Background, AnimationColorIn))
|
||||
Case Themes.Red
|
||||
AnimList.Add(AaColor(Path, Shape.FillProperty, New MyColor(255, 76, 76) - Path.Fill, AnimationColorIn))
|
||||
Case Themes.Black
|
||||
AnimList.Add(AaColor(Path, Shape.FillProperty, New MyColor(230, 0, 0, 0) - Path.Fill, AnimationColorIn))
|
||||
Case Themes.Custom
|
||||
@@ -117,6 +120,9 @@
|
||||
Case Themes.White
|
||||
AnimList.Add(AaColor(Path, Shape.FillProperty, "ColorBrush8", AnimationColorOut))
|
||||
AnimList.Add(AaColor(PanBack, BackgroundProperty, New MyColor(0, 255, 255, 255) - PanBack.Background, AnimationColorOut))
|
||||
Case Themes.Red
|
||||
AnimList.Add(AaColor(Path, Shape.FillProperty, New MyColor(160, 255, 76, 76) - Path.Fill, AnimationColorOut))
|
||||
PanBack.Background = New MyColor(0, 255, 255, 255)
|
||||
Case Themes.Black
|
||||
AnimList.Add(AaColor(Path, Shape.FillProperty, New MyColor(160, 0, 0, 0) - Path.Fill, AnimationColorOut))
|
||||
PanBack.Background = New MyColor(0, 255, 255, 255)
|
||||
@@ -135,6 +141,8 @@
|
||||
Path.SetResourceReference(Shape.FillProperty, "ColorBrush5")
|
||||
Case Themes.White
|
||||
Path.SetResourceReference(Shape.FillProperty, "ColorBrush8")
|
||||
Case Themes.Red
|
||||
Path.Fill = New MyColor(160, 255, 76, 76)
|
||||
Case Themes.Black
|
||||
Path.Fill = New MyColor(160, 0, 0, 0)
|
||||
Case Themes.Custom
|
||||
|
||||
@@ -507,27 +507,26 @@
|
||||
|
||||
'触发点击事件
|
||||
Private Sub Button_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonUp
|
||||
If IsMouseDown Then
|
||||
RaiseEvent Click(sender, e)
|
||||
If e.Handled Then Exit Sub
|
||||
'触发自定义事件
|
||||
If Not String.IsNullOrEmpty(EventType) Then
|
||||
ModEvent.TryStartEvent(EventType, EventData)
|
||||
e.Handled = True
|
||||
End If
|
||||
If e.Handled Then Exit Sub
|
||||
'实际的单击处理
|
||||
Select Case Type
|
||||
Case CheckType.Clickable
|
||||
Log("[Control] 按下单击列表项:" & Title)
|
||||
Case CheckType.RadioBox
|
||||
Log("[Control] 按下单选列表项:" & Title)
|
||||
If Not Checked Then SetChecked(True, True, True)
|
||||
Case CheckType.CheckBox
|
||||
Log("[Control] 按下复选列表项(" & (Not Checked).ToString & "):" & Title)
|
||||
SetChecked(Not Checked, True, True)
|
||||
End Select
|
||||
If Not IsMouseDown Then Exit Sub
|
||||
RaiseEvent Click(sender, e)
|
||||
If e.Handled Then Exit Sub
|
||||
'触发自定义事件
|
||||
If Not String.IsNullOrEmpty(EventType) Then
|
||||
ModEvent.TryStartEvent(EventType, EventData)
|
||||
e.Handled = True
|
||||
End If
|
||||
If e.Handled Then Exit Sub
|
||||
'实际的单击处理
|
||||
Select Case Type
|
||||
Case CheckType.Clickable
|
||||
Log("[Control] 按下单击列表项:" & Title)
|
||||
Case CheckType.RadioBox
|
||||
Log("[Control] 按下单选列表项:" & Title)
|
||||
If Not Checked Then SetChecked(True, True, True)
|
||||
Case CheckType.CheckBox
|
||||
Log("[Control] 按下复选列表项(" & (Not Checked).ToString & "):" & Title)
|
||||
SetChecked(Not Checked, True, True)
|
||||
End Select
|
||||
'AniStart({
|
||||
' AaScaleTransform(Me, 1.004 - CType(RenderTransform, ScaleTransform).ScaleX, 150,, New AniEaseOutFluent),
|
||||
' AaScaleTransform(Me, -0.004, 100, 150, New AniEaseInFluent)
|
||||
@@ -603,7 +602,7 @@
|
||||
If IsMouseOver AndAlso IsMouseOverAnimationEnabled Then
|
||||
If ButtonStack IsNot Nothing Then Ani.Add(AaOpacity(ButtonStack, 1 - ButtonStack.Opacity, Time * 0.7, Time * 0.3))
|
||||
Ani.AddRange({
|
||||
AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrush9"), Time),
|
||||
AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrushBg1"), Time),
|
||||
AaOpacity(RectBack, 1 - RectBack.Opacity, Time,, New AniEaseOutFluent)
|
||||
})
|
||||
If IsScaleAnimationEnabled Then
|
||||
@@ -630,7 +629,7 @@
|
||||
If IsMouseOver AndAlso IsMouseOverAnimationEnabled Then
|
||||
If ButtonStack IsNot Nothing Then ButtonStack.Opacity = 1
|
||||
'由于鼠标已经移入,所以直接实例化 RectBack
|
||||
RectBack.Background = Color9
|
||||
RectBack.Background = ColorBg1
|
||||
RectBack.Opacity = 1
|
||||
RectBack.RenderTransform = New ScaleTransform(1, 1)
|
||||
Me.RenderTransform = New ScaleTransform(1, 1)
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<my:MyTextBox x:Name="TextCaption" UseLayoutRounding="False" MaxLength="1000" Width="450" Margin="1" />
|
||||
</Border>
|
||||
<StackPanel Name="PanBtn" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="150,0,22,20" Orientation="Horizontal">
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮1" x:Name="Btn1" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮2" x:Name="Btn2" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮3" x:Name="Btn3" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮1" x:Name="Btn1" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮2" x:Name="Btn2" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮3" x:Name="Btn3" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@@ -109,13 +109,13 @@
|
||||
MyConverter.Result = TextCaption.Text
|
||||
Close()
|
||||
End Sub
|
||||
Private Sub Btn2_Click() Handles Btn2.Click
|
||||
Public Sub Btn2_Click() Handles Btn2.Click
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
MyConverter.IsExited = True
|
||||
MyConverter.Result = Nothing
|
||||
Close()
|
||||
End Sub
|
||||
Private Sub Btn3_Click() Handles Btn3.Click
|
||||
Public Sub Btn3_Click() Handles Btn3.Click
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
MyConverter.IsExited = True
|
||||
MyConverter.Result = Nothing
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
<StackPanel x:Name="PanSelection" Orientation="Vertical" />
|
||||
</my:MyScrollViewer>
|
||||
<StackPanel Name="PanBtn" Grid.Row="3" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="150,0,22,20" Orientation="Horizontal">
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮1" x:Name="Btn1" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" IsEnabled="False" />
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮2" x:Name="Btn2" Margin="15,0,0,0" TextPadding="7" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮3" x:Name="Btn3" TextPadding="7" Margin="15,0,0,0" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮1" x:Name="Btn1" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" IsEnabled="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮2" x:Name="Btn2" Margin="15,0,0,0" TextPadding="7" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮3" x:Name="Btn3" TextPadding="7" Margin="15,0,0,0" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@@ -112,13 +112,13 @@
|
||||
MyConverter.Result = SelectedIndex
|
||||
Close()
|
||||
End Sub
|
||||
Private Sub Btn2_Click() Handles Btn2.Click
|
||||
Public Sub Btn2_Click() Handles Btn2.Click
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
MyConverter.IsExited = True
|
||||
MyConverter.Result = Nothing
|
||||
Close()
|
||||
End Sub
|
||||
Private Sub Btn3_Click() Handles Btn3.Click
|
||||
Public Sub Btn3_Click() Handles Btn3.Click
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
MyConverter.IsExited = True
|
||||
MyConverter.Result = Nothing
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
<TextBlock VerticalAlignment="Top" TextTrimming="None" TextWrapping="Wrap" Name="LabCaption" FontSize="15" Foreground="#FF5C5C5C" FontWeight="Normal" Padding="1" />
|
||||
</my:MyScrollViewer>
|
||||
<StackPanel Name="PanBtn" Grid.Row="3" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="150,0,22,20" Orientation="Horizontal">
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮1" x:Name="Btn1" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮2" x:Name="Btn2" Margin="15,0,0,0" TextPadding="7" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" Text="测试按钮3" x:Name="Btn3" TextPadding="7" Margin="15,0,0,0" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮1" x:Name="Btn1" Margin="15,0,0,0" TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮2" x:Name="Btn2" Margin="15,0,0,0" TextPadding="7" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="测试按钮3" x:Name="Btn3" TextPadding="7" Margin="15,0,0,0" Visibility="Visible" SnapsToDevicePixels="False" Padding="5,0" Opacity="0" UseLayoutRounding="False" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@@ -104,13 +104,13 @@
|
||||
MyConverter.Result = 1
|
||||
Close()
|
||||
End Sub
|
||||
Private Sub Btn2_Click() Handles Btn2.Click
|
||||
Public Sub Btn2_Click() Handles Btn2.Click
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
MyConverter.IsExited = True
|
||||
MyConverter.Result = 2
|
||||
Close()
|
||||
End Sub
|
||||
Private Sub Btn3_Click() Handles Btn3.Click
|
||||
Public Sub Btn3_Click() Handles Btn3.Click
|
||||
If MyConverter.IsExited Then Exit Sub
|
||||
MyConverter.IsExited = True
|
||||
MyConverter.Result = 3
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
LoaderExit '加载环退出动画
|
||||
ContentEnter '内容进入动画
|
||||
ContentStay '内容正常显示
|
||||
ReloadExit '刷新导致的全部退出动画
|
||||
ContentExit '刷新导致的全部退出动画,或页面内容退出(子页面更改)导致的全部退出动画
|
||||
PageExit '切换页面导致的全部退出动画
|
||||
End Enum
|
||||
Private _PageState As PageStates = PageStates.Empty
|
||||
@@ -48,7 +48,8 @@
|
||||
''' <param name="RealLoader">在工作线程执行的加载器。</param>
|
||||
''' <param name="FinishedInvoke">当加载器执行完成,在 UI 线程触发的 UI 初始化事件。</param>
|
||||
Public Sub PageLoaderInit(LoaderUi As MyLoading, PanLoader As FrameworkElement, PanContent As FrameworkElement, PanAlways As FrameworkElement,
|
||||
RealLoader As LoaderBase, FinishedInvoke As Action(Of LoaderBase), Optional InputInvoke As Func(Of Object) = Nothing,
|
||||
RealLoader As LoaderBase,
|
||||
Optional FinishedInvoke As Action(Of LoaderBase) = Nothing, Optional InputInvoke As Func(Of Object) = Nothing,
|
||||
Optional AutoRun As Boolean = True)
|
||||
'初始化参数
|
||||
Me.PanLoader = PanLoader
|
||||
@@ -59,14 +60,16 @@
|
||||
Me.PageLoaderInputInvoke = InputInvoke
|
||||
Me.PageLoaderAutoRun = AutoRun
|
||||
'添加结束 Invoke
|
||||
AddHandler RealLoader.PreviewFinish,
|
||||
Sub()
|
||||
Do While PageState = MyPageRight.PageStates.PageExit OrElse PageState = MyPageRight.PageStates.ReloadExit
|
||||
Thread.Sleep(10) '不在退出动画时执行 UI 线程操作,避免退出动画被重置
|
||||
If FinishedInvoke IsNot Nothing Then
|
||||
AddHandler RealLoader.PreviewFinish,
|
||||
Sub()
|
||||
Do While PageState = MyPageRight.PageStates.PageExit OrElse PageState = MyPageRight.PageStates.ContentExit
|
||||
Thread.Sleep(10) '不在退出动画时执行 UI 线程操作,避免退出动画被重置
|
||||
Loop
|
||||
RunInUiWait(Sub() FinishedInvoke(RealLoader))
|
||||
Thread.Sleep(20) '由于大量初始化控件会导致掉帧,延迟触发 State 改变事件
|
||||
RunInUiWait(Sub() FinishedInvoke(RealLoader))
|
||||
Thread.Sleep(20) '由于大量初始化控件会导致掉帧,延迟触发 State 改变事件
|
||||
End Sub
|
||||
End If
|
||||
AddHandler RealLoader.OnStateChangedUi, Sub(Loader As LoaderBase, NewState As LoadState, OldState As LoadState) RunInUi(Sub() PageLoaderState(Loader, NewState, OldState))
|
||||
'隐藏 UI
|
||||
PanLoader.Visibility = Visibility.Collapsed
|
||||
@@ -82,14 +85,13 @@
|
||||
PageLoader.Start(Input)
|
||||
End If
|
||||
End If
|
||||
If PageLoader.State = LoadState.Finished Then
|
||||
If PageLoader.State = LoadState.Finished AndAlso FinishedInvoke IsNot Nothing Then
|
||||
RunInUiWait(Sub() FinishedInvoke(RealLoader)) '加载器已提前完成,直接触发事件
|
||||
End If
|
||||
'设置加载环
|
||||
PageLoaderUi.State = RealLoader
|
||||
AddHandler PageLoaderUi.Click, Sub() If RealLoader.State = LoadState.Failed Then PageLoaderRestart() '点击重试事件
|
||||
End Sub
|
||||
|
||||
'重试
|
||||
Public Sub PageLoaderRestart(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = True) '由外部调用的重试
|
||||
If Not PageLoaderAutoRun Then Exit Sub
|
||||
@@ -112,32 +114,38 @@
|
||||
''' </summary>
|
||||
Public Sub PageOnEnter()
|
||||
If ModeDebug Then Log("[UI] 已触发 PageOnEnter")
|
||||
RaiseEvent OnPageEnter()
|
||||
|
||||
RaiseEvent PageEnter()
|
||||
Select Case PageState
|
||||
Case PageStates.Empty
|
||||
If PageLoader Is Nothing OrElse PageLoader.State = LoadState.Finished OrElse PageLoader.State = LoadState.Aborted Then
|
||||
If PageLoader Is Nothing OrElse PageLoader.State = LoadState.Finished OrElse PageLoader.State = LoadState.Waiting OrElse PageLoader.State = LoadState.Aborted Then
|
||||
'如果加载器在进入页面时不启动(例如 HiPer 联机),那么在此时就会有 State = Waiting
|
||||
PageState = PageStates.ContentEnter
|
||||
TriggerEnterAnimation(PanAlways, If(PanContent, Child))
|
||||
ElseIf PageLoader.State = LoadState.Loading Then
|
||||
PageState = PageStates.LoaderWait
|
||||
AniStart(AaCode(AddressOf PageOnLoaderWaitFinished, 200), "PageRight PageChange " & PageUuid)
|
||||
ElseIf PageLoader.State = LoadState.Failed Then
|
||||
Else 'PageLoader.State = LoadState.Failed
|
||||
PageState = PageStates.LoaderEnter
|
||||
TriggerEnterAnimation(PanAlways, PanLoader)
|
||||
ElseIf PageLoader.State = LoadState.Waiting Then
|
||||
'由于 “页面加载器 Minecraft Version List 不应在 PageOnEnter 事件出现 Waiting 状态” 的神秘反馈添加的临时修复
|
||||
End If
|
||||
Case PageStates.ContentExit
|
||||
'和上面的一样,但是不管 PanAlways
|
||||
If PageLoader Is Nothing OrElse PageLoader.State = LoadState.Finished OrElse PageLoader.State = LoadState.Waiting OrElse PageLoader.State = LoadState.Aborted Then
|
||||
PageState = PageStates.ContentEnter
|
||||
TriggerEnterAnimation(If(PanContent, Child))
|
||||
ElseIf PageLoader.State = LoadState.Loading Then
|
||||
PageState = PageStates.LoaderWait
|
||||
AniStart(AaCode(AddressOf PageOnLoaderWaitFinished, 200), "PageRight PageChange " & PageUuid)
|
||||
Log("[Anim] 警告:页面加载器 " & PageLoader.Name & " 不应在 PageOnEnter 事件出现 " & GetStringFromEnum(PageLoader.State) & " 状态", LogLevel.Debug)
|
||||
Else
|
||||
Throw New Exception("页面加载器 " & PageLoader.Name & " 不应在 PageOnEnter 事件出现 " & GetStringFromEnum(PageLoader.State) & " 状态。")
|
||||
Else 'PageLoader.State = LoadState.Failed
|
||||
PageState = PageStates.LoaderEnter
|
||||
TriggerEnterAnimation(PanLoader)
|
||||
End If
|
||||
Case PageStates.ContentEnter '重复调用 PageOnEnter,直接忽略
|
||||
Case Else
|
||||
Throw New Exception("在状态为 " & GetStringFromEnum(PageState) & " 时触发了 PageOnEnter 事件。")
|
||||
End Select
|
||||
End Sub
|
||||
Public Event OnPageEnter()
|
||||
Public Event PageEnter()
|
||||
''' <summary>
|
||||
''' 需要切换到其他页面。
|
||||
''' 需要立即切换至 PageExit 或 Empty。
|
||||
@@ -154,7 +162,7 @@
|
||||
Case PageStates.LoaderWait
|
||||
PageState = PageStates.PageExit
|
||||
TriggerExitAnimation(PanAlways)
|
||||
Case PageStates.LoaderExit, PageStates.ReloadExit
|
||||
Case PageStates.LoaderExit, PageStates.ContentExit
|
||||
PageState = PageStates.PageExit
|
||||
If PanAlways IsNot Nothing Then TriggerExitAnimation(PanAlways, If(PanContent, Child))
|
||||
Case PageStates.PageExit, PageStates.Empty
|
||||
@@ -178,6 +186,29 @@
|
||||
If PanAlways IsNot Nothing Then PanAlways.Visibility = Visibility.Collapsed
|
||||
End If
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' PanContent 中的子页面改变,需要让当前内容退出,再显示新的内容。
|
||||
''' 需要在 PageEnter 事件确认要显示的子页面有哪些。
|
||||
''' </summary>
|
||||
Public Sub PageOnContentExit()
|
||||
If ModeDebug Then Log("[UI] 已触发 PageOnContentExit")
|
||||
If PageLoader IsNot Nothing AndAlso PageLoader.State = LoadState.Loading Then
|
||||
Throw New Exception("在调用 PageOnContentExit 时,加载器不能为 Loading 状态")
|
||||
'Loading 的加载器可能触发进一步变化,难以预测会触发子页面的动画还是加载器完成的动画
|
||||
End If
|
||||
Select Case PageState
|
||||
Case PageStates.ContentEnter, PageStates.ContentStay
|
||||
PageState = PageStates.ContentExit
|
||||
TriggerExitAnimation(PanContent)
|
||||
Case PageStates.LoaderExit
|
||||
PageState = PageStates.ContentExit
|
||||
Case PageStates.LoaderEnter, PageStates.LoaderStayForce, PageStates.LoaderStay
|
||||
PageState = PageStates.ContentExit
|
||||
TriggerExitAnimation(PanLoader)
|
||||
Case PageStates.LoaderWait, PageStates.Empty
|
||||
PageOnEnter()
|
||||
End Select
|
||||
End Sub
|
||||
|
||||
'内部触发的事件
|
||||
''' <summary>
|
||||
@@ -205,8 +236,7 @@
|
||||
Select Case PageState
|
||||
Case PageStates.PageExit
|
||||
PageState = PageStates.Empty
|
||||
Case PageStates.ReloadExit
|
||||
PageState = PageStates.Empty
|
||||
Case PageStates.ContentExit
|
||||
PageOnEnter()
|
||||
Case PageStates.LoaderExit
|
||||
PageState = PageStates.ContentEnter
|
||||
@@ -258,20 +288,20 @@
|
||||
Private Sub PageLoaderState(sender As Object, NewState As LoadState, OldState As LoadState)
|
||||
Select Case NewState
|
||||
Case LoadState.Failed, LoadState.Loading
|
||||
If Not OldState = LoadState.Finished Then Exit Sub
|
||||
If ModeDebug Then Log("[UI] 已触发 PageLoaderState (Refresh)")
|
||||
'重新开始运行
|
||||
If OldState = LoadState.Failed OrElse OldState = LoadState.Loading Then Exit Sub
|
||||
If ModeDebug Then Log("[UI] 已触发 PageLoaderState (Start/Refresh)")
|
||||
'(重新)开始运行
|
||||
'需要从部分状态切换到 ReloadExit
|
||||
Select Case PageState
|
||||
Case PageStates.ContentEnter, PageStates.ContentStay
|
||||
PageState = PageStates.ReloadExit
|
||||
PageState = PageStates.ContentExit
|
||||
TriggerExitAnimation(PanContent)
|
||||
Case PageStates.LoaderExit, PageStates.ReloadExit
|
||||
PageState = PageStates.ReloadExit
|
||||
Case PageStates.LoaderExit
|
||||
PageState = PageStates.ContentExit
|
||||
End Select
|
||||
Case LoadState.Finished
|
||||
If Not OldState = LoadState.Loading Then Exit Sub
|
||||
If ModeDebug Then Log("[UI] 已触发 PageLoaderState (Stop)")
|
||||
Case LoadState.Finished, LoadState.Aborted, LoadState.Waiting
|
||||
If Not (OldState = LoadState.Failed OrElse OldState = LoadState.Loading) Then Exit Sub
|
||||
If ModeDebug Then Log("[UI] 已触发 PageLoaderState (Stop/Abort)")
|
||||
'运行结束
|
||||
'需要从 LoaderWait 切换到 ContentEnter,或从 LoaderStay 切换到 LoaderExit
|
||||
Select Case PageState
|
||||
@@ -360,13 +390,14 @@
|
||||
End Function
|
||||
Private Sub GetAllAnimControls(Element As FrameworkElement, ByRef AllControls As List(Of FrameworkElement), IgnoreInvisibility As Boolean)
|
||||
If Not IgnoreInvisibility AndAlso Element.Visibility = Visibility.Collapsed Then Exit Sub
|
||||
If TypeOf Element Is MyCard OrElse TypeOf Element Is MyHint Then
|
||||
If TypeOf Element Is MyCard OrElse TypeOf Element Is MyHint OrElse TypeOf Element Is TextBlock OrElse TypeOf Element Is MyTextButton Then
|
||||
AllControls.Add(Element)
|
||||
ElseIf TypeOf Element Is ContentControl Then
|
||||
GetAllAnimControls(CType(Element, ContentControl).Content, AllControls, IgnoreInvisibility)
|
||||
Dim Content = CType(Element, ContentControl).Content
|
||||
If Content IsNot Nothing AndAlso TypeOf Content Is FrameworkElement Then GetAllAnimControls(Content, AllControls, IgnoreInvisibility)
|
||||
ElseIf TypeOf Element Is Panel Then
|
||||
For Each Element2 As FrameworkElement In CType(Element, Panel).Children
|
||||
GetAllAnimControls(Element2, AllControls, IgnoreInvisibility)
|
||||
For Each Element2 In CType(Element, Panel).Children
|
||||
If TypeOf Element2 Is FrameworkElement Then GetAllAnimControls(Element2, AllControls, IgnoreInvisibility)
|
||||
Next
|
||||
End If
|
||||
End Sub
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
FocusVisualStyle="{x:Null}"
|
||||
MinWidth="20" x:Name="PanBack" UseLayoutRounding="False" SnapsToDevicePixels="False" MinHeight="20" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True">
|
||||
<TextBlock IsHitTestVisible="False" x:Name="LabText" FontSize="13" Padding="0" Margin="26,0,0,0" Text="Radiobox" Foreground="{DynamicResource ColorBrush1}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||||
<Ellipse IsHitTestVisible="False" x:Name="ShapeBorder" StrokeThickness="1.1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="18" Height="18" Stroke="{DynamicResource ColorBrush1}" Margin="1,0,0,0" Fill="{StaticResource ColorBrushHalfWhite}" />
|
||||
<Ellipse IsHitTestVisible="False" x:Name="ShapeDot" HorizontalAlignment="Left" VerticalAlignment="Center" Fill="{Binding Stroke, ElementName=ShapeBorder}" Width="0" Height="0" Margin="10,0,0,0" StrokeThickness="0" />
|
||||
<TextBlock IsHitTestVisible="False" x:Name="LabText" FontSize="13" Padding="0" Margin="26,0,0,0" Text="Radiobox" Foreground="{DynamicResource ColorBrush1}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||||
<Ellipse IsHitTestVisible="False" x:Name="ShapeBorder" StrokeThickness="1.1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="18" Height="18" Stroke="{DynamicResource ColorBrush1}" Margin="1,0,0,0" Fill="{StaticResource ColorBrushBg2}" />
|
||||
<Ellipse IsHitTestVisible="False" x:Name="ShapeDot" HorizontalAlignment="Left" VerticalAlignment="Center" Fill="{Binding Stroke, ElementName=ShapeBorder}" Width="0" Height="0" Margin="10,0,0,0" StrokeThickness="0" />
|
||||
</Grid>
|
||||
@@ -170,12 +170,12 @@
|
||||
MouseDowned = False
|
||||
Log("[Control] 按下单选框:" & Text)
|
||||
SetChecked(True, True, True)
|
||||
AniStart(AaColor(ShapeBorder, Shapes.Ellipse.FillProperty, "ColorBrushHalfWhite", 100), "MyRadioBox Background " & Uuid)
|
||||
AniStart(AaColor(ShapeBorder, Ellipse.FillProperty, "ColorBrushBg2", 100), "MyRadioBox Background " & Uuid)
|
||||
End Sub
|
||||
Private Sub Radiobox_MouseDown() Handles Me.MouseLeftButtonDown
|
||||
MouseDowned = True
|
||||
Focus()
|
||||
AniStart(AaColor(ShapeBorder, Shapes.Ellipse.FillProperty, "ColorBrush9", 100), "MyRadioBox Background " & Uuid)
|
||||
AniStart(AaColor(ShapeBorder, Ellipse.FillProperty, "ColorBrushBg1", 100), "MyRadioBox Background " & Uuid)
|
||||
If Not Checked Then
|
||||
AniStart(AaScale(ShapeBorder, 16.5 - ShapeBorder.Width, 1000, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True), "MyRadioBox Border " & Uuid)
|
||||
End If
|
||||
@@ -183,7 +183,7 @@
|
||||
Private Sub Radiobox_MouseLeave() Handles Me.MouseLeave
|
||||
If Not MouseDowned Then Exit Sub
|
||||
MouseDowned = False
|
||||
AniStart(AaColor(ShapeBorder, Shapes.Ellipse.FillProperty, "ColorBrushHalfWhite", 100), "MyRadioBox Background " & Uuid)
|
||||
AniStart(AaColor(ShapeBorder, Ellipse.FillProperty, "ColorBrushBg2", 100), "MyRadioBox Background " & Uuid)
|
||||
If Not Checked Then
|
||||
AniStart(AaScale(ShapeBorder, 18 - ShapeBorder.Width, 400, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True), "MyRadioBox Border " & Uuid)
|
||||
End If
|
||||
|
||||
@@ -137,12 +137,16 @@
|
||||
|
||||
'点击事件
|
||||
|
||||
Public Event PreviewClick(sender As Object, e As RouteEventArgs)
|
||||
Private IsMouseDown As Boolean = False
|
||||
Private Sub Radiobox_MouseUp() Handles Me.MouseLeftButtonUp
|
||||
If Checked Then Exit Sub
|
||||
If Not IsMouseDown Then Exit Sub
|
||||
Log("[Control] 按下单选按钮:" & Text)
|
||||
IsMouseDown = False
|
||||
Dim e As New RouteEventArgs(True)
|
||||
RaiseEvent PreviewClick(Me, e)
|
||||
If e.Handled Then Exit Sub
|
||||
SetChecked(True, True, True)
|
||||
End Sub
|
||||
Private Sub Radiobox_MouseDown() Handles Me.MouseLeftButtonDown
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="16" d:DesignWidth="162"
|
||||
FocusVisualStyle="{x:Null}"
|
||||
MinHeight="16" UseLayoutRounding="False" SnapsToDevicePixels="False" BorderBrush="{DynamicResource ColorBrush1}" Name="PanBack" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True">
|
||||
MinHeight="16" UseLayoutRounding="False" SnapsToDevicePixels="False" BorderBrush="{DynamicResource ColorBrush4}" Name="PanBack" Background="{StaticResource ColorBrushSemiTransparent}" Focusable="True">
|
||||
<Grid x:Name="PanMain" MinHeight="16" MaxHeight="16" IsHitTestVisible="False">
|
||||
<Line Height="4" Name="LineBack" Stroke="{StaticResource ColorBrushGray5}" StrokeThickness="1.1" X2="10000" Y1="2" Y2="2" HorizontalAlignment="Right" Width="0" SnapsToDevicePixels="True" Margin="0,0,1,0" />
|
||||
<Line Height="4" Name="LineFore" Stroke="{Binding ElementName=PanBack, Path=BorderBrush}" StrokeThickness="1.1" X2="10000" Y1="2" Y2="2" Width="0" HorizontalAlignment="Left" SnapsToDevicePixels="True" Margin="1,0,0,0" />
|
||||
<Ellipse HorizontalAlignment="Left" Width="16" Stroke="{Binding BorderBrush, ElementName=PanBack}" StrokeThickness="1.1" Fill="{StaticResource ColorBrushHalfWhite}" Name="ShapeDot" Height="16" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5">
|
||||
<Line Height="4" Name="LineBack" Stroke="{DynamicResource ColorBrushBg0}" Opacity="0.3" StrokeThickness="1.6" X2="10000" Y1="2" Y2="2" HorizontalAlignment="Right" Width="0" SnapsToDevicePixels="True" Margin="0,0,1,0" />
|
||||
<Line Height="4" Name="LineFore" Stroke="{Binding ElementName=PanBack, Path=BorderBrush}" StrokeThickness="1.6" X2="10000" Y1="2" Y2="2" Width="0" HorizontalAlignment="Left" SnapsToDevicePixels="True" Margin="1,0,0,0" />
|
||||
<Ellipse HorizontalAlignment="Left" Width="10" Height="10"
|
||||
Stroke="{Binding BorderBrush, ElementName=PanBack}" StrokeThickness="1.2"
|
||||
Fill="{DynamicResource ColorBrush4}" Name="ShapeDot" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5">
|
||||
<Ellipse.RenderTransform>
|
||||
<ScaleTransform />
|
||||
</Ellipse.RenderTransform>
|
||||
|
||||
@@ -45,13 +45,13 @@
|
||||
End If
|
||||
|
||||
If IsLoaded AndAlso AniControlEnabled = 0 Then
|
||||
If ActualWidth < 16 Then Exit Property
|
||||
Dim NewWidth As Double = _Value / MaxValue * (ActualWidth - 16)
|
||||
Dim DeltaProcess As Double = Math.Abs(LineFore.Width / (ActualWidth - 16) - _Value / MaxValue)
|
||||
If ActualWidth < ShapeDot.Width Then Exit Property
|
||||
Dim NewWidth As Double = _Value / MaxValue * (ActualWidth - ShapeDot.Width)
|
||||
Dim DeltaProcess As Double = Math.Abs(LineFore.Width / (ActualWidth - ShapeDot.Width) - _Value / MaxValue)
|
||||
Dim Time As Double = (1 - Math.Pow(1 - DeltaProcess, 3)) * 300 + If(ChangeByKey, 100, 0)
|
||||
AniStart({
|
||||
AaWidth(LineFore, Math.Max(0, NewWidth + If(NewWidth < 0.5, 0, 0.5)) - LineFore.Width, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear)),
|
||||
AaWidth(LineBack, Math.Max(0, ActualWidth - 16 - NewWidth + If(ActualWidth - 16 - NewWidth < 0.5, 0, 0.5)) - LineBack.Width, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear)),
|
||||
AaWidth(LineBack, Math.Max(0, ActualWidth - ShapeDot.Width - NewWidth + If(ActualWidth - ShapeDot.Width - NewWidth < 0.5, 0, 0.5)) - LineBack.Width, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear)),
|
||||
AaX(ShapeDot, NewWidth - ShapeDot.Margin.Left, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear))
|
||||
}, "MySlider Progress " & Uuid)
|
||||
Else
|
||||
@@ -67,9 +67,9 @@
|
||||
Private Sub RefreshWidth(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
|
||||
If Not IsNothing(e) Then PanMain.Width = e.NewSize.Width
|
||||
AniStop("MySlider Progress " & Uuid)
|
||||
Dim NewWidth As Double = _Value / MaxValue * (ActualWidth - 16)
|
||||
Dim NewWidth As Double = _Value / MaxValue * (ActualWidth - ShapeDot.Width)
|
||||
LineFore.Width = Math.Max(0, NewWidth + If(NewWidth < 0.5, 0, 0.5))
|
||||
LineBack.Width = Math.Max(0, ActualWidth - 16 - NewWidth + If(ActualWidth - 16 - NewWidth < 0.5, 0, 0.5))
|
||||
LineBack.Width = Math.Max(0, ActualWidth - ShapeDot.Width - NewWidth + If(ActualWidth - ShapeDot.Width - NewWidth < 0.5, 0, 0.5))
|
||||
SetLeft(ShapeDot, NewWidth)
|
||||
End Sub
|
||||
|
||||
@@ -79,9 +79,10 @@
|
||||
Private Sub DragStart(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
|
||||
e.Handled = True '防止 ScrollViewer 失焦问题
|
||||
DragControl = Me
|
||||
RefreshColor()
|
||||
FrmMain.DragDoing()
|
||||
AniStart({
|
||||
AaScaleTransform(ShapeDot, 0.8 - CType(ShapeDot.RenderTransform, ScaleTransform).ScaleX, 75,, New AniEaseOutFluent)
|
||||
AaScaleTransform(ShapeDot, 1.3 - CType(ShapeDot.RenderTransform, ScaleTransform).ScaleX, 40,, New AniEaseOutFluent)
|
||||
}, "MySlider Scale " & Uuid)
|
||||
'更新 Popup
|
||||
If GetHintText IsNot Nothing Then
|
||||
@@ -91,7 +92,7 @@
|
||||
End If
|
||||
End Sub
|
||||
Public Sub DragDoing()
|
||||
Dim Percent As Double = MathRange((Mouse.GetPosition(PanMain).X - 8) / (ActualWidth - 16), 0, 1)
|
||||
Dim Percent As Double = MathRange((Mouse.GetPosition(PanMain).X - ShapeDot.Width / 2) / (ActualWidth - ShapeDot.Width), 0, 1)
|
||||
Dim NewValue As Integer = Percent * MaxValue
|
||||
If Not NewValue = Value Then
|
||||
Value = NewValue
|
||||
@@ -113,28 +114,39 @@
|
||||
Try
|
||||
|
||||
'判断当前颜色
|
||||
Dim ColorName As String
|
||||
Dim ForegroundName As String, DotFillName As String
|
||||
Dim AnimationTime As Integer
|
||||
If IsEnabled Then
|
||||
If IsMouseOver OrElse (Not IsNothing(DragControl) AndAlso DragControl.Equals(Me)) Then
|
||||
ColorName = "ColorBrush3"
|
||||
AnimationTime = 100
|
||||
If Not IsNothing(DragControl) AndAlso DragControl.Equals(Me) Then
|
||||
ForegroundName = "ColorBrush3"
|
||||
DotFillName = "ColorBrush3"
|
||||
AnimationTime = 40
|
||||
ElseIf IsMouseOver Then
|
||||
ForegroundName = "ColorBrush3"
|
||||
DotFillName = "ColorBrush3"
|
||||
AnimationTime = 40
|
||||
Else
|
||||
ColorName = "ColorBrush1"
|
||||
AnimationTime = 200
|
||||
ForegroundName = "ColorBrush4"
|
||||
DotFillName = "ColorBrush4"
|
||||
AnimationTime = 100
|
||||
End If
|
||||
Else
|
||||
ColorName = "ColorBrushGray4"
|
||||
ForegroundName = "ColorBrushGray5"
|
||||
DotFillName = "ColorBrushGray5"
|
||||
AnimationTime = 200
|
||||
End If
|
||||
'触发颜色动画
|
||||
If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
|
||||
'有动画
|
||||
AniStart({AaColor(Me, BorderBrushProperty, ColorName, AnimationTime)}, "MySlider Color " & Uuid)
|
||||
AniStart({
|
||||
AaColor(Me, BorderBrushProperty, ForegroundName, AnimationTime),
|
||||
AaColor(ShapeDot, Ellipse.FillProperty, DotFillName, AnimationTime)
|
||||
}, "MySlider Color " & Uuid)
|
||||
Else
|
||||
'无动画
|
||||
AniStop("MySlider Color " & Uuid)
|
||||
SetResourceReference(BorderBrushProperty, ColorName)
|
||||
SetResourceReference(BorderBrushProperty, ForegroundName)
|
||||
ShapeDot.SetResourceReference(Ellipse.FillProperty, DotFillName)
|
||||
End If
|
||||
|
||||
Catch ex As Exception
|
||||
|
||||
@@ -212,35 +212,26 @@
|
||||
If IsEnabled Then
|
||||
If ValidateResult = "" OrElse Not IsTextChanged Then
|
||||
If IsFocused Then
|
||||
ForeColorName = "ColorBrush4"
|
||||
BackColorName = "ColorBrush9"
|
||||
AnimationTime = 60
|
||||
ElseIf IsMouseOver Then
|
||||
ForeColorName = "ColorBrush3"
|
||||
BackColorName = "ColorBrushHalfWhite"
|
||||
AnimationTime = 100
|
||||
Else
|
||||
ForeColorName = "ColorBrush1"
|
||||
BackColorName = "ColorBrushHalfWhite"
|
||||
AnimationTime = 200
|
||||
BackColorName = "ColorBrushSemiWhite"
|
||||
AnimationTime = 10
|
||||
ElseIf IsMouseOver Then
|
||||
ForeColorName = "ColorBrush4"
|
||||
BackColorName = "ColorBrush7"
|
||||
AnimationTime = 50
|
||||
Else '未选中
|
||||
ForeColorName = "ColorBrushBg0"
|
||||
BackColorName = "ColorBrushBg2"
|
||||
AnimationTime = 50
|
||||
End If
|
||||
Else
|
||||
ForeColorName = "ColorBrushRedLight"
|
||||
BackColorName = "ColorBrushRedBack"
|
||||
AnimationTime = 200
|
||||
'If IsFocused OrElse IsMouseOver Then
|
||||
' ForeColorName = "ColorBrushRedLight"
|
||||
' BackColorName = "ColorBrushRedBack"
|
||||
' AnimationTime = 100
|
||||
'Else
|
||||
' ForeColorName = "ColorBrushRedDark"
|
||||
' BackColorName = "ColorBrushHalfWhite"
|
||||
' AnimationTime = 200
|
||||
'End If
|
||||
End If
|
||||
Else
|
||||
ForeColorName = "ColorBrushGray4"
|
||||
BackColorName = "ColorBrushHalfWhite"
|
||||
ForeColorName = "ColorBrushGray5"
|
||||
BackColorName = "ColorBrushGray6"
|
||||
AnimationTime = 200
|
||||
End If
|
||||
'触发颜色动画
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
<StackPanel x:Name="PanHint" UseLayoutRounding="True" SnapsToDevicePixels="True" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0,0,0,25" IsHitTestVisible="False" Grid.RowSpan="2" />
|
||||
<StackPanel x:Name="PanHint" UseLayoutRounding="True" SnapsToDevicePixels="True" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0,0,0,25" Grid.RowSpan="2" />
|
||||
<StackPanel HorizontalAlignment="Right" VerticalAlignment="Bottom" Grid.Row="1" Margin="15">
|
||||
<local:MyExtraButton x:Name="BtnExtraBack" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="返回顶部" Visibility="Collapsed"
|
||||
Logo="M858.496 188.9024 173.1072 188.9024c-30.2848 0-54.8352-24.5504-54.8352-54.8352L118.272 106.6496c0-30.2848 24.5504-54.8352 54.8352-54.8352l685.3888 0c30.2848 0 54.8352 24.5504 54.8352 54.8352l0 27.4176C913.3312 164.352 888.7808 188.9024 858.496 188.9024L858.496 188.9024zM150.6048 550.8608c0 0 300.0064-240.3584 303.0272-243.328 13.9776-13.5936 31.1808-21.8624 48.8192-24.7552 1.7152-0.3072 3.4304-0.5888 5.1456-0.768 2.7392-0.3072 5.4528-0.3584 8.192-0.3328 2.7392-0.0256 5.4272 0.0256 8.1664 0.3328 1.7408 0.1792 3.4304 0.4864 5.1456 0.768 17.664 2.8928 34.8672 11.1616 48.8192 24.7552 3.0464 2.944 303.0016 243.328 303.0016 243.328 32.384 31.5136 29.6192 63.9744-2.7392 95.5136-32.3328 31.5392-75.648 2.9696-108.0064-28.544l-185.8816-147.1232 0 485.8368c0 30.3104-24.5248 54.8608-54.8352 54.8608l-27.392 0c-30.2848 0-54.8352-24.5504-54.8352-54.8608L447.232 470.7072l-185.8304 147.0976c-32.3584 31.5392-75.6992 60.1344-108.032 28.5696C121.0368 614.8352 118.272 582.3744 150.6048 550.8608L150.6048 550.8608zM150.6048 550.8608" />
|
||||
|
||||
@@ -10,8 +10,33 @@ Public Class FormMain
|
||||
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
||||
'统计更新日志条目
|
||||
#If BETA Then
|
||||
If LastVersion < 272 Then 'Release 2.4.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持在版本设置页导出启动脚本、打开存档文件夹等"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 Mod、整合包下载的版本检查与显示"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修改部分配色,让整体边框变得更淡"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法从下载页安装最新 MC 版本的整合包的 Bug"))
|
||||
If LastVersion <= 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 LiteLoader 的 Bug"))
|
||||
FeatureCount += 13
|
||||
BugCount += 23
|
||||
End If
|
||||
If LastVersion < 268 Then 'Release 2.4.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "暂时关闭了联机功能"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "游戏崩溃的弹窗添加了直接查看日志的选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在更多分类下添加了新功能投票选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "自动安装时支持检查 OptiFine 对 Forge 的具体版本需求"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化自动 Java 选择的准确度"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化 Mod 中文名的显示"))
|
||||
FeatureCount += 14
|
||||
BugCount += 33
|
||||
End If
|
||||
If LastVersion < 265 Then 'Release 2.3.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复部分情况下无法启动路径带有中文的游戏的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复多个可能导致 OptiFine、Forge 安装失败的 Bug"))
|
||||
FeatureCount += 13
|
||||
BugCount += 9
|
||||
End If
|
||||
If LastVersion < 260 Then 'Release 2.3.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "解决了联机人数 ≥3 人时出现的频繁掉线或突发高延迟的问题"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "解决了联机人数 ≥3 人时出现的频繁掉线或突发高延迟的问题"))
|
||||
FeatureCount += 22
|
||||
BugCount += 4
|
||||
End If
|
||||
@@ -26,22 +51,21 @@ Public Class FormMain
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 253 Then 'Release 2.2.13
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(7, "支持在安装菜单中直接安装 OptiFabric"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持调整 Mod 文件名中中文译名的位置"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "崩溃分析优化,支持分析更多 Forge 相关的崩溃"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持在安装菜单中直接安装 OptiFabric"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持调整 Mod 文件名中中文译名的位置"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "崩溃分析优化,支持分析更多 Forge 相关的崩溃"))
|
||||
FeatureCount += 13
|
||||
BugCount += 27
|
||||
End If
|
||||
If LastVersion < 250 Then 'Release 2.2.11
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持将 Mod 文件拖入窗口进行安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持将 Mod 文件拖入窗口进行安装"))
|
||||
If LastVersion = 246 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用中文搜索 Mod 的 Bug"))
|
||||
FeatureCount += 8
|
||||
BugCount += 33
|
||||
End If
|
||||
If LastVersion < 246 Then 'Release 2.2.9
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "Mod 下载支持筛选 Forge Mod 与 Fabric Mod"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "大幅修改联机页面布局(作为联机优化的第二个阶段)"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod、整合包下载的综合优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 下载支持筛选 Forge Mod 与 Fabric Mod"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "Mod、整合包下载的综合优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复使用离线登录进入 Forge 的存档可能导致游戏崩溃"))
|
||||
FeatureCount += 13
|
||||
BugCount += 11
|
||||
@@ -56,100 +80,81 @@ Public Class FormMain
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 236 Then 'Release 2.2.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "网络状态检测支持检测 Windows 防火墙与网络延迟"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "重制右侧页面的切换动画,卡片与提示条将逐个进入退出,并具有独特的位移动画"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "添加 MC 1.18 中要求 Java 17 的检测与提醒"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "优化页面切换、下载的性能"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "允许拖拽按钮的设置第三方登录"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复网络状态检测的结果总为 A 级的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法下载新版本的 Forge 的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "网络状态检测支持检测 Windows 防火墙与网络延迟"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重制右侧页面的切换动画,卡片与提示条将逐个进入退出,并具有独特的位移动画"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 MC 1.18 中要求 Java 17 的检测与提醒"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化页面切换、下载的性能"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "允许拖拽按钮设置第三方登录"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "修复无法下载新版本的 Forge 的 Bug"))
|
||||
FeatureCount += 25
|
||||
BugCount += 22
|
||||
End If
|
||||
If LastVersion < 233 Then 'Release 2.2.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(7, "微软账号支持更换皮肤与披风"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持拖拽整合包文件到 PCL2 进行快捷安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "Mod 下载支持显示对应的 MC 版本与 Mod 加载器,且可以跳转到 MCBBS 介绍页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持安装 1.17 OptiFine + Forge"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "使用 Mojang 账号登录将会显示迁移提醒"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "微软账号支持更换皮肤与披风"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持拖拽整合包文件到 PCL2 进行快捷安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod 下载支持显示对应的 MC 版本与 Mod 加载器,且可以跳转到 MCBBS 介绍页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持安装 1.17 OptiFine + Forge"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "使用 Mojang 账号登录将会显示迁移提醒"))
|
||||
FeatureCount += 12
|
||||
BugCount += 26
|
||||
End If
|
||||
If LastVersion < 231 Then 'Release 2.2.1, Also 229
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(9, "联机功能的早期测试(尚未完成,延迟很高,之后会优化的)"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "添加 1.18 实验性快照 5 的特供下载,且支持列表的联网更新"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "添加 1.18 实验性快照 5 的特供下载,且支持列表的联网更新"))
|
||||
FeatureCount += 11
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 226 Then 'Release 2.1.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持 1.17.1 Forge、Fabric 的安装与启动"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "优化 Forge 下载与安装速度,提高安装稳定性"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "更新内置帮助库,添加数个指南页面与整合包、存档的安装教程"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持将游戏文件夹压缩包作为游戏整合包导入"))
|
||||
FeatureCount += 12
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 224 Then 'Release 2.1.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "界面与动画综合优化,重新制作主题配色"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "添加 1.18 实验性快照的特供下载"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "更新内置帮助库,添加光影、数据包、Mod 等资源的安装教程"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "游戏崩溃分析优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "若设置为自动更新,PCL2 会在关闭时才替换文件"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "追加大量千万████的可能性"))
|
||||
'FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持 1.17 Forge 的安装与启动"))
|
||||
FeatureCount += 33
|
||||
BugCount += 20
|
||||
End If
|
||||
If LastVersion < 217 Then 'Release 2.0.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(7, "可以根据游戏版本自动选择所需的 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "允许在 Java 版本检测不通过时强制指定使用 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "允许为不同版本独立设置 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "Java 选择与搜索的综合优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用 Mod、整合包搜索功能的 Bug"))
|
||||
FeatureCount += 8
|
||||
BugCount += 20
|
||||
End If
|
||||
If LastVersion < 214 Then 'Release 2.0.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "添加一键关闭所有运行中的 Minecraft 的按钮"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "增加对 MC 1.17 需要 Java 16 的检测与说明"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Minecraft 崩溃分析优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法修改部分个性化设置的严重 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复 Windows 7 可能无法登录微软账号的严重 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复网络不稳定时安装整合包极易失败的严重 Bug"))
|
||||
FeatureCount += 10
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 212 Then 'Release 2.0.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(9, "添加帮助页面,且可以自行添加、删除其中的内容"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持安装 MCBBS 格式的整合包"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "自定义主页/帮助页面的 XAML 功能扩展"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "同时安装 OptiFine 与 Forge 时,OptiFine 将作为 Mod 安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "优化 CurseForge 搜索"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化多个报错提示,更加人性化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "适配适用于快照版 MC 的 OptiFine"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复进入 OptiFine 下载页面导致卡死的严重 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法启动部分 OptiFine+Forge 版本的 Bug"))
|
||||
FeatureCount += 20
|
||||
BugCount += 42
|
||||
End If
|
||||
#Else
|
||||
'9:大+
|
||||
'8:中大+
|
||||
'7:中+,大*
|
||||
'6:中小型+,中大*
|
||||
'5:小型+,中*
|
||||
'4:中小*
|
||||
'3:小*
|
||||
'2:极度严重的 Bug
|
||||
'1:严重的 Bug
|
||||
'5: FEAT+
|
||||
'4: IMP+ FEAT*
|
||||
'3:BUG+ IMP* FEAT-
|
||||
'2:BUG* IMP-
|
||||
'1:BUG-
|
||||
If LastVersion < 273 Then 'Snapshot 2.4.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持在版本设置页导出启动脚本、打开存档文件夹等"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修改部分配色,让整体边框变得更淡"))
|
||||
If LastVersion = 271 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法同时开启多个 Minecraft 客户端的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法从下载页安装最新 MC 版本的整合包的 Bug"))
|
||||
FeatureCount += 7
|
||||
BugCount += 8
|
||||
End If
|
||||
If LastVersion < 271 Then 'Snapshot 2.4.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 Mod、整合包下载的版本检查与显示"))
|
||||
If LastVersion <= 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 LiteLoader 的 Bug"))
|
||||
FeatureCount += 6
|
||||
BugCount += 15
|
||||
End If
|
||||
If LastVersion < 269 Then 'Snapshot 2.4.2
|
||||
If LastVersion = 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法下载 CurseForge 整合包的 Bug"))
|
||||
FeatureCount += 2
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 267 Then 'Snapshot 2.4.1
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "暂时关闭了联机功能"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "自动安装时支持检查 OptiFine 对 Forge 的具体版本需求"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化自动 Java 选择的准确度"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化 Mod 中文名的显示"))
|
||||
FeatureCount += 12
|
||||
BugCount += 22
|
||||
End If
|
||||
If LastVersion < 266 Then 'Snapshot 2.4.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "游戏崩溃的弹窗添加了直接查看日志的选项"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在更多分类下添加了新功能投票选项"))
|
||||
FeatureCount += 3
|
||||
BugCount += 11
|
||||
End If
|
||||
If LastVersion < 264 Then 'Snapshot 2.3.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法启动部分 Forge 版本的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复多个可能导致 OptiFine、Forge 安装失败的 Bug"))
|
||||
FeatureCount += 2
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 263 Then 'Snapshot 2.3.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复部分情况下无法启动路径带有中文的游戏的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复多个可能导致 OptiFine、Forge 安装失败的 Bug"))
|
||||
FeatureCount += 11
|
||||
BugCount += 5
|
||||
End If
|
||||
If LastVersion < 262 Then 'Snapshot 2.3.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用 Mod、整合包搜索功能的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "修复无法使用 Mod、整合包搜索功能的 Bug"))
|
||||
BugCount += 1
|
||||
End If
|
||||
If LastVersion < 261 Then 'Snapshot 2.3.2
|
||||
@@ -157,11 +162,10 @@ Public Class FormMain
|
||||
BugCount += 4
|
||||
End If
|
||||
If LastVersion < 259 Then 'Snapshot 2.3.1
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "解决了联机人数 ≥3 人时出现的频繁掉线或突发高延迟的问题"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "解决了联机人数 ≥3 人时出现的频繁掉线或突发高延迟的问题"))
|
||||
FeatureCount += 14
|
||||
End If
|
||||
If LastVersion < 258 Then 'Snapshot 2.3.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复下载部分 Mod、整合包的 Bug"))
|
||||
FeatureCount += 4
|
||||
BugCount += 4
|
||||
End If
|
||||
@@ -171,19 +175,19 @@ Public Class FormMain
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 254 Then 'Snapshot 2.2.13
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持调整 Mod 文件名中中文译名的位置"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持调整 Mod 文件名中中文译名的位置"))
|
||||
FeatureCount += 3
|
||||
BugCount += 17
|
||||
End If
|
||||
If LastVersion < 252 Then 'Snapshot 2.2.12
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(7, "支持在安装菜单中直接安装 OptiFabric"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "崩溃分析优化,支持分析更多 Forge 相关的崩溃"))
|
||||
If LastVersion = 251 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复同时安装 Forge 和 OptiFine 时 OptiFine 无效的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持在安装菜单中直接安装 OptiFabric"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "崩溃分析优化,支持分析更多 Forge 相关的崩溃"))
|
||||
If LastVersion = 251 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复同时安装 Forge 和 OptiFine 时 OptiFine 无效的 Bug"))
|
||||
FeatureCount += 10
|
||||
BugCount += 10
|
||||
End If
|
||||
If LastVersion < 251 Then 'Snapshot 2.2.11
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持将 Mod 文件拖入窗口进行安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持将 Mod 文件拖入窗口进行安装"))
|
||||
FeatureCount += 2
|
||||
BugCount += 16
|
||||
End If
|
||||
@@ -193,14 +197,13 @@ Public Class FormMain
|
||||
BugCount += 17
|
||||
End If
|
||||
If LastVersion < 247 Then 'Snapshot 2.2.9
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "Mod 下载支持筛选 Forge Mod 与 Fabric Mod"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 下载支持筛选 Forge Mod 与 Fabric Mod"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod、整合包下载的综合优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复使用离线登录进入 Forge 的存档可能导致游戏崩溃"))
|
||||
FeatureCount += 8
|
||||
BugCount += 4
|
||||
End If
|
||||
If LastVersion < 245 Then 'Snapshot 2.2.8
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "大幅修改联机页面布局(作为联机优化的第二个阶段)"))
|
||||
FeatureCount += 5
|
||||
BugCount += 7
|
||||
End If
|
||||
@@ -210,116 +213,48 @@ Public Class FormMain
|
||||
End If
|
||||
If LastVersion < 239 Then 'Snapshot 2.2.6
|
||||
If LastVersion >= 235 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复自动更新由于路径错误失败的 Bug"))
|
||||
If LastVersion = 237 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用联机模块的 Bug"))
|
||||
If LastVersion = 237 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "修复无法使用联机模块的 Bug"))
|
||||
FeatureCount += 1
|
||||
BugCount += 1
|
||||
End If
|
||||
If LastVersion < 237 Then 'Snapshot 2.2.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "允许拖拽按钮的设置第三方登录"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "允许拖拽按钮设置第三方登录"))
|
||||
If LastVersion = 235 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复在启动游戏时有可能卡死的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法下载新版本的 Forge 的 Bug"))
|
||||
FeatureCount += 2
|
||||
BugCount += 3
|
||||
End If
|
||||
If LastVersion < 235 Then 'Snapshot 2.2.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "网络状态检测支持检测 Windows 防火墙与网络延迟"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "重制右侧页面的切换动画,卡片与提示条将逐个进入退出,并具有独特的位移动画"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "添加 MC 1.18 中要求 Java 17 的检测与提醒"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "优化页面切换、下载的性能"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复网络状态检测的结果总为 A 级的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "网络状态检测支持检测 Windows 防火墙与网络延迟"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重制右侧页面的切换动画,卡片与提示条将逐个进入退出,并具有独特的位移动画"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 MC 1.18 中要求 Java 17 的检测与提醒"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化页面切换、下载的性能"))
|
||||
FeatureCount += 23
|
||||
BugCount += 19
|
||||
End If
|
||||
If LastVersion < 234 Then 'Snapshot 2.2.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持拖拽整合包文件到 PCL2 进行快捷安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持安装 1.17 OptiFine + Forge"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "Mod 详情页面支持跳转 MCBBS 介绍页"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持拖拽整合包文件到 PCL2 进行快捷安装"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持安装 1.17 OptiFine + Forge"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "Mod 详情页面支持跳转 MCBBS 介绍页"))
|
||||
FeatureCount += 10
|
||||
BugCount += 17
|
||||
End If
|
||||
If LastVersion < 232 Then 'Snapshot 2.2.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(7, "微软账号支持更换皮肤与披风"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持显示 Mod 与整合包对应的 MC 版本与 Mod 加载器名称"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "使用 Mojang 账号登录将会显示迁移提醒"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "微软账号支持更换皮肤与披风"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持显示 Mod 与整合包对应的 MC 版本与 Mod 加载器名称"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "使用 Mojang 账号登录将会显示迁移提醒"))
|
||||
FeatureCount += 2
|
||||
BugCount += 9
|
||||
End If
|
||||
If LastVersion < 230 Then 'Snapshot 2.2.1, Also 228
|
||||
If LastVersion = 227 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "联机功能的小优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "添加 1.18 实验性快照 5 的特供下载,且支持列表的联网更新"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复 Win7 上使用联机功能导致日志文件极大,占用硬盘空间的 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 1.18 实验性快照 5 的特供下载,且支持列表的联网更新"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复 Win7 上 IOI 联机导致日志文件极大,占用硬盘空间的 Bug"))
|
||||
FeatureCount += 12
|
||||
BugCount += 4
|
||||
End If
|
||||
If LastVersion < 227 Then 'Snapshot 2.2.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(9, "新增联机功能的早期测试版本"))
|
||||
FeatureCount += 2
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 225 Then 'Snapshot 2.1.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "支持 1.17.1 Forge、Fabric 的安装与启动"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "优化 Forge 下载与安装速度,提高安装稳定性"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "更新内置帮助库,添加数个指南页面与整合包、存档的安装教程"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持将游戏文件夹压缩包作为游戏整合包导入"))
|
||||
FeatureCount += 12
|
||||
BugCount += 13
|
||||
End If
|
||||
If LastVersion < 223 Then 'Snapshot 2.1.3
|
||||
BugCount += 4
|
||||
End If
|
||||
If LastVersion < 222 Then 'Snapshot 2.1.2
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "更新内置帮助库,添加光影、数据包、Mod 的安装教程"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "游戏崩溃分析优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复登录微软账号启动游戏时报错的 Bug"))
|
||||
FeatureCount += 8
|
||||
BugCount += 11
|
||||
End If
|
||||
If LastVersion < 221 Then 'Snapshot 2.1.1
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "界面与动画综合优化,重新制作主题配色"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "若识别码不变,更新密钥在输入一次后会一直有效"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "若设置为自动更新,PCL2 会在关闭时才替换文件"))
|
||||
FeatureCount += 10
|
||||
BugCount += 5
|
||||
End If
|
||||
If LastVersion < 220 Then 'Snapshot 2.1.0
|
||||
'FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "界面与动画综合优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "追加大量千万████的可能性"))
|
||||
FeatureCount += 15
|
||||
End If
|
||||
If LastVersion < 219 Then 'Snapshot 2.0.5
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用 Mod、整合包搜索功能的 Bug"))
|
||||
BugCount += 2
|
||||
End If
|
||||
If LastVersion < 218 Then 'Snapshot 2.0.4
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "允许为不同版本独立设置 Java"))
|
||||
BugCount += 12
|
||||
End If
|
||||
If LastVersion < 216 Then 'Snapshot 2.0.3
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(7, "可以根据游戏版本自动选择所需的 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "允许在 Java 版本检测不通过时强制指定使用 Java"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "Java 选择与搜索的综合优化"))
|
||||
FeatureCount += 8
|
||||
BugCount += 7
|
||||
End If
|
||||
If LastVersion < 215 Then 'Snapshot 2.0.2
|
||||
If LastVersion = 213 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复账号切换、版本选择下拉框无法展开的严重 Bug"))
|
||||
If LastVersion = 213 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复误判部分客户端需要 Java 16,导致无法启动游戏的严重 Bug"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复 Windows 7 可能无法登录微软账号的严重 Bug"))
|
||||
BugCount += 1
|
||||
End If
|
||||
If LastVersion < 213 Then 'Snapshot 2.0.1
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(6, "添加一键关闭所有运行中的 Minecraft 的按钮"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "增加对 MC 1.17 需要 Java 16 的检测与说明"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Minecraft 崩溃分析优化"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复网络不稳定时安装整合包极易失败的严重 Bug"))
|
||||
FeatureCount += 10
|
||||
BugCount += 12
|
||||
End If
|
||||
If LastVersion < 211 Then 'Snapshot 2.0.0
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "适配适用于快照版 MC 的 OptiFine"))
|
||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复进入 OptiFine 下载页面导致卡死的严重 Bug"))
|
||||
BugCount += 3
|
||||
End If
|
||||
#End If
|
||||
'整理更新日志文本
|
||||
Dim ContentList As New List(Of String)
|
||||
@@ -350,7 +285,10 @@ Public Class FormMain
|
||||
|
||||
'窗口加载
|
||||
Private IsWindowLoadFinished As Boolean = False
|
||||
Public Shared IsLinkRestart As Boolean = False '是否为联机提权后自动重启
|
||||
''' <summary>
|
||||
''' 是否为联机提权后自动重启。
|
||||
''' </summary>
|
||||
Public Shared IsLinkRestart As Boolean = False
|
||||
Public Sub New()
|
||||
ApplicationStartTick = GetTimeTick()
|
||||
'窗体参数初始化
|
||||
@@ -381,7 +319,7 @@ Public Class FormMain
|
||||
PanMainLeft.Child = FrmLaunchLeft
|
||||
PanMainRight.Child = FrmLaunchRight
|
||||
FrmLaunchRight.PageState = MyPageRight.PageStates.ContentStay
|
||||
If IsLinkRestart Then PageChange(PageType.Link)
|
||||
If IsLinkRestart Then PageChange(PageType.Link, PageSubType.LinkIoi)
|
||||
'模式提醒
|
||||
#If DEBUG Then
|
||||
Hint("[开发者模式] PCL 正以开发者模式运行,这可能会造成严重的性能下降,请务必立即向开发者反馈此问题!", HintType.Critical)
|
||||
@@ -458,7 +396,7 @@ Public Class FormMain
|
||||
RunInNewThread(Sub()
|
||||
If Not Setup.Get("SystemEula") Then
|
||||
Reopen:
|
||||
Select Case MyMsgBox("在使用 PCL2 前,请同意 PCL2 的用户协议与免责声明。", "协议授权", "同意", "拒绝", "打开用户协议与免责声明页面")
|
||||
Select Case MyMsgBox("在使用 PCL2 前,请同意 PCL2 的用户协议与免责声明。", "协议授权", "同意", "拒绝", "查看用户协议与免责声明")
|
||||
Case 1
|
||||
Setup.Set("SystemEula", True)
|
||||
Case 2
|
||||
@@ -470,7 +408,6 @@ Reopen:
|
||||
End If
|
||||
Try
|
||||
Thread.Sleep(200)
|
||||
If Setup.Get("LinkAuto") Then PageLinkIoi.InitLoader.Start()
|
||||
DlClientListMojangLoader.Start(1)
|
||||
RunCountSub()
|
||||
ServerLoader.Start(1)
|
||||
@@ -547,9 +484,13 @@ Reopen:
|
||||
"多谢各位的理解啦!", "重新解锁提醒")
|
||||
End If
|
||||
'移动自定义皮肤
|
||||
If LastVersionCode <= 161 AndAlso File.Exists(Path & "PCL\CustomSkin.png") AndAlso Not File.Exists(PathTemp & "CustomSkin.png") Then
|
||||
CopyFile(Path & "PCL\CustomSkin.png", PathTemp & "CustomSkin.png")
|
||||
Log("[Start] 已移动离线自定义皮肤")
|
||||
If LastVersionCode <= 161 AndAlso File.Exists(Path & "PCL\CustomSkin.png") AndAlso Not File.Exists(PathAppdata & "CustomSkin.png") Then
|
||||
CopyFile(Path & "PCL\CustomSkin.png", PathAppdata & "CustomSkin.png")
|
||||
Log("[Start] 已移动离线自定义皮肤 (162)")
|
||||
End If
|
||||
If LastVersionCode <= 263 AndAlso File.Exists(PathTemp & "CustomSkin.png") AndAlso Not File.Exists(PathAppdata & "CustomSkin.png") Then
|
||||
CopyFile(PathTemp & "CustomSkin.png", PathAppdata & "CustomSkin.png")
|
||||
Log("[Start] 已移动离线自定义皮肤 (264)")
|
||||
End If
|
||||
'解除帮助页面的隐藏
|
||||
If LastVersionCode <= 205 Then
|
||||
@@ -621,13 +562,14 @@ Reopen:
|
||||
IsProgramEnded = True
|
||||
AniControlEnabled += 1
|
||||
PageLinkIoi.IoiStop(False)
|
||||
PageLinkHiper.HiperStop(False)
|
||||
If IsUpdateWaitingRestart Then UpdateRestart(False)
|
||||
If ReturnCode = Result.Exception Then
|
||||
If Not IsLogShown Then
|
||||
FeedbackInfo()
|
||||
Log("请在 https://jinshuju.net/f/rP4b6E?x_field_1=crash 提交错误报告,以便于作者解决此问题!")
|
||||
IsLogShown = True
|
||||
ShellAndGetExitCode(Path & "PCL\Log1.txt")
|
||||
ShellOnly(Path & "PCL\Log1.txt")
|
||||
End If
|
||||
Thread.Sleep(500) '防止 PCL 在记事本打开前就被掐掉
|
||||
End If
|
||||
@@ -678,11 +620,25 @@ Reopen:
|
||||
'按键事件
|
||||
Private Sub FormMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||
If e.IsRepeat Then Exit Sub
|
||||
'调用弹窗回车
|
||||
If e.Key = Key.Enter AndAlso PanMsg.Children.Count > 0 Then
|
||||
CType(PanMsg.Children(0), Object).Btn1_Click()
|
||||
Exit Sub
|
||||
'调用弹窗:回车选择第一个,Esc 选择最后一个
|
||||
If PanMsg.Children.Count > 0 Then
|
||||
If e.Key = Key.Enter Then
|
||||
CType(PanMsg.Children(0), Object).Btn1_Click()
|
||||
Exit Sub
|
||||
ElseIf e.Key = Key.Escape Then
|
||||
Dim Msg As Object = PanMsg.Children(0)
|
||||
If Msg.Btn3.Visibility = Visibility.Visible Then
|
||||
Msg.Btn3_Click()
|
||||
ElseIf Msg.Btn2.Visibility = Visibility.Visible Then
|
||||
Msg.Btn2_Click()
|
||||
Else
|
||||
Msg.Btn1_Click()
|
||||
End If
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
'按 ESC 返回上一级
|
||||
If e.Key = Key.Escape Then TriggerPageBack()
|
||||
'更改隐藏版本可见性
|
||||
If e.Key = Key.F11 AndAlso PageCurrent = FormMain.PageType.VersionSelect Then
|
||||
FrmSelectRight.ShowHidden = Not FrmSelectRight.ShowHidden
|
||||
@@ -710,8 +666,6 @@ Reopen:
|
||||
End If
|
||||
'修复按下 Alt 后误认为弹出系统菜单导致的冻结
|
||||
If e.SystemKey = Key.LeftAlt OrElse e.SystemKey = Key.RightAlt Then e.Handled = True
|
||||
'按 ESC 返回上一级
|
||||
If e.Key = Key.Escape Then TriggerPageBack()
|
||||
End Sub
|
||||
Private Sub FormMain_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseDown
|
||||
'鼠标侧键返回上一级
|
||||
@@ -830,7 +784,7 @@ Reopen:
|
||||
'获取并检查目标版本
|
||||
Dim TargetVersion As McVersion = McVersionCurrent
|
||||
If PageCurrent = PageType.VersionSetup Then TargetVersion = PageVersionLeft.Version
|
||||
If PageCurrent = PageType.VersionSelect OrElse TargetVersion Is Nothing OrElse Not TargetVersion.Version.Modable Then
|
||||
If PageCurrent = PageType.VersionSelect OrElse TargetVersion Is Nothing OrElse Not TargetVersion.Modable Then
|
||||
'正在选择版本,或当前版本不能安装 Mod
|
||||
Hint("若要安装 Mod,请先选择一个可以安装 Mod 的版本!")
|
||||
ElseIf Not (PageCurrent = PageType.VersionSetup AndAlso PageCurrentSub = PageSubType.VersionMod) Then
|
||||
@@ -1028,11 +982,11 @@ Install:
|
||||
SetupUI = 1
|
||||
SetupSystem = 2
|
||||
SetupLink = 3
|
||||
LinkCato = 2
|
||||
LinkIoi = 3
|
||||
LinkSetup = 5
|
||||
LinkHelp = 6
|
||||
LinkFeedback = 7
|
||||
LinkHiper = 1
|
||||
LinkIoi = 2
|
||||
LinkSetup = 4
|
||||
LinkHelp = 5
|
||||
LinkFeedback = 6
|
||||
OtherHelp = 0
|
||||
OtherAbout = 1
|
||||
OtherTest = 2
|
||||
@@ -1119,7 +1073,7 @@ Install:
|
||||
''' <summary>
|
||||
''' 上层页面的编号堆栈,用于返回。
|
||||
''' </summary>
|
||||
Private ReadOnly PageStack As New List(Of PageStackData)
|
||||
Public PageStack As New List(Of PageStackData)
|
||||
Public Class PageStackData
|
||||
|
||||
Public Page As PageType
|
||||
@@ -1201,6 +1155,14 @@ Install:
|
||||
If IsChangingPage Then Exit Sub
|
||||
PageChangeActual(Val(sender.Tag))
|
||||
End Sub
|
||||
Private Sub CancelLink(sender As Object, e As RouteEventArgs) Handles BtnTitleSelect2.PreviewClick
|
||||
If MyMsgBox("由于联机提供商要求新联机强制付费,且高度商业化,PCL 将暂时关闭联机功能,不再使用该联机模块。" & vbCrLf &
|
||||
"PCL、HMCL、BakaXL 将合作开发新的跨启动器联机功能,在开发结束后将同步开放,请各位多多理解。",
|
||||
"联机功能已暂时关闭", "查看详情", "确定") = 1 Then
|
||||
OpenWebsite("https://www.bilibili.com/read/cv19845645")
|
||||
End If
|
||||
e.Handled = True
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 通过点击返回按钮或手动触发返回来改变页面。
|
||||
''' </summary>
|
||||
@@ -1270,7 +1232,6 @@ Install:
|
||||
PageChangeAnim(FrmDownloadLeft, FrmDownloadLeft.PageGet(SubType))
|
||||
Case PageType.Link '联机
|
||||
If FrmLinkLeft Is Nothing Then FrmLinkLeft = New PageLinkLeft
|
||||
If FrmLinkIoi Is Nothing Then FrmLinkIoi = New PageLinkIoi
|
||||
PageChangeAnim(FrmLinkLeft, FrmLinkLeft.PageGet(SubType))
|
||||
Case PageType.Setup '设置
|
||||
If FrmSetupLeft Is Nothing Then FrmSetupLeft = New PageSetupLeft
|
||||
@@ -1326,7 +1287,6 @@ Install:
|
||||
AniStart({
|
||||
AaCode(Sub()
|
||||
AniControlEnabled += 1
|
||||
CType(PanMainRight.Child, MyPageRight).PageOnForceExit()
|
||||
'把新页面添加进容器
|
||||
PanMainLeft.Child = PageLeft
|
||||
PageLeft.Opacity = 0
|
||||
|
||||
|
Before Width: | Height: | Size: 434 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 999 B |
|
After Width: | Height: | Size: 912 B |
|
After Width: | Height: | Size: 1001 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 861 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 958 B |
|
After Width: | Height: | Size: 988 B |
|
After Width: | Height: | Size: 947 B |
@@ -777,12 +777,12 @@ Public Module ModAnimation
|
||||
Log("[Animation] 动画线程开始")
|
||||
Do While True
|
||||
'两帧之间的间隔时间
|
||||
Dim DeltaTime As Long = MathRange(GetTimeTick() - AniLastTick, 0, 10000)
|
||||
Dim DeltaTime As Long = MathRange(GetTimeTick() - AniLastTick, 0, 100000)
|
||||
If DeltaTime < 3 Then GoTo Sleeper
|
||||
AniLastTick = GetTimeTick()
|
||||
'记录 FPS
|
||||
If ModeDebug Then
|
||||
If MathRange(AniLastTick - AniFPSTimer, 0, 10000) >= 500 Then
|
||||
If MathRange(AniLastTick - AniFPSTimer, 0, 100000) >= 500 Then
|
||||
AniFPS = AniFPSCounter
|
||||
AniFPSCounter = 0
|
||||
AniFPSTimer = AniLastTick
|
||||
|
||||
@@ -10,12 +10,12 @@ Public Module ModBase
|
||||
#Region "声明"
|
||||
|
||||
'下列版本信息由更新器自动修改
|
||||
Public Const VersionBaseName As String = "2.3.4" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.3.4." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const VersionBaseName As String = "2.4.4" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.4.4." & VersionBranchCode '标准格式的四段式版本号
|
||||
#If BETA Then
|
||||
Public Const VersionCode As Integer = 260 'Release
|
||||
Public Const VersionCode As Integer = 272 'Release
|
||||
#Else
|
||||
Public Const VersionCode As Integer = 263 'Snapshot
|
||||
Public Const VersionCode As Integer = 273 'Snapshot
|
||||
#End If
|
||||
'自动生成的版本信息
|
||||
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
||||
@@ -82,6 +82,10 @@ Public Module ModBase
|
||||
''' 程序的缓存文件夹路径,以“\”结尾。
|
||||
''' </summary>
|
||||
Public PathTemp As String = If(Setup.Get("SystemSystemCache") = "", IO.Path.GetTempPath() & "PCL\", Setup.Get("SystemSystemCache")).ToString.Replace("/", "\").TrimEnd("\") & "\"
|
||||
''' <summary>
|
||||
''' AppData 中的 PCL 文件夹路径,以“\”结尾。
|
||||
''' </summary>
|
||||
Public PathAppdata As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\PCL\"
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -447,6 +451,32 @@ Public Module ModBase
|
||||
|
||||
#Region "数学"
|
||||
|
||||
''' <summary>
|
||||
''' 2~65 进制的转换。
|
||||
''' </summary>
|
||||
Public Function RadixConvert(Input As String, FromRadix As Integer, ToRadix As Integer) As String
|
||||
Const Digits As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+="
|
||||
'零与负数的处理
|
||||
If String.IsNullOrEmpty(Input) Then Return "0"
|
||||
Dim IsNegative As Boolean = Input.StartsWith("-")
|
||||
If IsNegative Then Input = Input.TrimStart("-")
|
||||
'转换为十进制
|
||||
Dim RealNum As Long = 0, Scale As Long = 1
|
||||
For Each Digit In Input.Reverse.Select(Function(l) Digits.IndexOf(l))
|
||||
RealNum += Digit * Scale
|
||||
Scale *= FromRadix
|
||||
Next
|
||||
'转换为指定进制
|
||||
Dim Result = ""
|
||||
While RealNum > 0
|
||||
Dim NewNum As Integer = RealNum Mod ToRadix
|
||||
RealNum = (RealNum - NewNum) / ToRadix
|
||||
Result = Digits(NewNum) & Result
|
||||
End While
|
||||
'负数的结束处理与返回
|
||||
Return If(IsNegative, "-", "") & Result
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 计算二阶贝塞尔曲线。
|
||||
''' </summary>
|
||||
@@ -741,6 +771,8 @@ Public Module ModBase
|
||||
'还原文件路径
|
||||
If Not FromPath.Contains(":\") Then FromPath = Path & FromPath
|
||||
If Not ToPath.Contains(":\") Then ToPath = Path & ToPath
|
||||
'如果复制同一个文件则跳过
|
||||
If FromPath = ToPath Then Exit Sub
|
||||
'读取文件内容
|
||||
Dim FileBytes As Byte()
|
||||
Using ReadStream As New FileStream(FromPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) '支持读取使用中的文件
|
||||
@@ -757,7 +789,7 @@ Public Module ModBase
|
||||
''' 读取文件,如果失败则返回空字符串。
|
||||
''' </summary>
|
||||
''' <param name="FilePath">文件完整或相对路径。</param>
|
||||
Public Function ReadFile(FilePath As String) As String
|
||||
Public Function ReadFile(FilePath As String, Optional Encoding As Encoding = Nothing) As String
|
||||
Try
|
||||
'还原文件路径
|
||||
If Not FilePath.Contains(":\") Then FilePath = Path & FilePath
|
||||
@@ -767,7 +799,7 @@ Public Module ModBase
|
||||
ReDim FileBytes(ReadStream.Length - 1)
|
||||
ReadStream.Read(FileBytes, 0, ReadStream.Length)
|
||||
End Using
|
||||
ReadFile = DecodeBytes(FileBytes)
|
||||
ReadFile = If(Encoding Is Nothing, DecodeBytes(FileBytes), Encoding.GetString(FileBytes))
|
||||
Else
|
||||
Log("[System] 欲读取的文件不存在,已返回空字符串:" & FilePath)
|
||||
Return ""
|
||||
@@ -1039,14 +1071,14 @@ Re:
|
||||
Next
|
||||
Return Result.ToString
|
||||
Catch ex As Exception
|
||||
If Not Retry Then
|
||||
If Retry OrElse TypeOf ex Is FileNotFoundException Then
|
||||
Log(ex, "获取文件 MD5 失败:" & FilePath)
|
||||
Return ""
|
||||
Else
|
||||
Retry = True
|
||||
Log(ex, "获取文件 MD5 可重试失败:" & FilePath, LogLevel.Normal)
|
||||
Thread.Sleep(RandomInteger(200, 500))
|
||||
GoTo Re
|
||||
Else
|
||||
Log(ex, "获取文件 MD5 失败:" & FilePath)
|
||||
Return ""
|
||||
End If
|
||||
End Try
|
||||
End Function
|
||||
@@ -1070,14 +1102,14 @@ Re:
|
||||
Next
|
||||
Return Result.ToString
|
||||
Catch ex As Exception
|
||||
If Not Retry Then
|
||||
If Retry OrElse TypeOf ex Is FileNotFoundException Then
|
||||
Log(ex, "获取文件 SHA256 失败:" & FilePath)
|
||||
Return ""
|
||||
Else
|
||||
Retry = True
|
||||
Log(ex, "获取文件 SHA256 可重试失败:" & FilePath, LogLevel.Normal)
|
||||
Thread.Sleep(RandomInteger(200, 500))
|
||||
GoTo Re
|
||||
Else
|
||||
Log(ex, "获取文件 SHA256 失败:" & FilePath)
|
||||
Return ""
|
||||
End If
|
||||
End Try
|
||||
End Function
|
||||
@@ -1101,14 +1133,14 @@ Re:
|
||||
Next
|
||||
Return Result.ToString
|
||||
Catch ex As Exception
|
||||
If Not Retry Then
|
||||
If Retry OrElse TypeOf ex Is FileNotFoundException Then
|
||||
Log(ex, "获取文件 SHA1 失败:" & FilePath)
|
||||
Return ""
|
||||
Else
|
||||
Retry = True
|
||||
Log(ex, "获取文件 SHA1 可重试失败:" & FilePath, LogLevel.Normal)
|
||||
Thread.Sleep(RandomInteger(200, 500))
|
||||
GoTo Re
|
||||
Else
|
||||
Log(ex, "获取文件 SHA1 失败:" & FilePath)
|
||||
Return ""
|
||||
End If
|
||||
End Try
|
||||
End Function
|
||||
@@ -1175,7 +1207,7 @@ Re:
|
||||
If Hash <> GetAuthMD5(LocalPath) Then Return "文件 MD5 应为 " & Hash & ",实际为 " & GetAuthMD5(LocalPath)
|
||||
ElseIf Hash.Length = 64 Then 'SHA256
|
||||
If Hash <> GetAuthSHA256(LocalPath) Then Return "文件 SHA256 应为 " & Hash & ",实际为 " & GetAuthSHA256(LocalPath)
|
||||
Else 'SHA1
|
||||
Else 'SHA1 (40)
|
||||
If Hash <> GetAuthSHA1(LocalPath) Then Return "文件 SHA1 应为 " & Hash & ",实际为 " & GetAuthSHA1(LocalPath)
|
||||
End If
|
||||
End If
|
||||
@@ -1191,7 +1223,7 @@ Re:
|
||||
Return Nothing
|
||||
Catch ex As Exception
|
||||
Log(ex, "检查文件出错")
|
||||
Return GetString(ex)
|
||||
Return GetExceptionSummary(ex)
|
||||
End Try
|
||||
End Function
|
||||
End Class
|
||||
@@ -1206,7 +1238,7 @@ Re:
|
||||
Directory.CreateDirectory(DestDirectory)
|
||||
If CompressFilePath.EndsWith(".zip") OrElse CompressFilePath.EndsWith(".jar") Then
|
||||
'以 zip 方式解压
|
||||
ZipFile.ExtractToDirectory(CompressFilePath, DestDirectory, If(Encode, Encoding.Default))
|
||||
ZipFile.ExtractToDirectory(CompressFilePath, DestDirectory, If(Encode, Encoding.GetEncoding("GB18030")))
|
||||
Return True
|
||||
ElseIf CompressFilePath.EndsWith(".gz") Then
|
||||
'以 gz 方式解压
|
||||
@@ -1293,59 +1325,99 @@ Re:
|
||||
Public vbRQ As Char = Convert.ToChar(8221)
|
||||
|
||||
''' <summary>
|
||||
''' 提取 Exception 摘要。
|
||||
''' 提取 Exception 的具体描述与堆栈。
|
||||
''' </summary>
|
||||
''' <param name="IsLine">输出是否强制为单行,单行模型下不会输出调用堆栈。</param>
|
||||
Public Function GetString(Ex As Exception, Optional IsLine As Boolean = True, Optional ShowAllTrace As Boolean = False) As String
|
||||
''' <param name="ShowAllTrace">是否必须显示所有堆栈。通常用于判定堆栈信息。</param>
|
||||
Public Function GetExceptionDetail(Ex As Exception, Optional ShowAllTrace As Boolean = False) As String
|
||||
If Ex Is Nothing Then Return "无可用错误信息!"
|
||||
Dim Desc As New List(Of String)
|
||||
|
||||
'自动错误判断
|
||||
Dim RealEx = Ex
|
||||
Do Until RealEx.InnerException Is Nothing
|
||||
RealEx = RealEx.InnerException
|
||||
'获取最底层的异常
|
||||
Dim InnerEx As Exception = Ex
|
||||
Do Until InnerEx.InnerException Is Nothing
|
||||
InnerEx = InnerEx.InnerException
|
||||
Loop
|
||||
If TypeOf RealEx Is TypeLoadException OrElse TypeOf RealEx Is MissingMethodException OrElse TypeOf RealEx Is NotImplementedException OrElse TypeOf RealEx Is TypeInitializationException Then
|
||||
Desc.Add("系统环境存在问题,请尝试重装 .Net Framework 4.6.2 后再试")
|
||||
ElseIf TypeOf RealEx Is UnauthorizedAccessException Then
|
||||
Desc.Add("PCL2 权限不足,请尝试右键 PCL2,选择以管理员身份运行")
|
||||
ElseIf TypeOf RealEx Is OutOfMemoryException Then
|
||||
Desc.Add("电脑运行内存不足,PCL2 无法继续运行")
|
||||
|
||||
'获取各级错误的描述与堆栈信息
|
||||
Dim DescList As New List(Of String)
|
||||
Dim StackList As New List(Of String)
|
||||
Do Until Ex Is Nothing
|
||||
DescList.Add(Ex.Message.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr & vbCr, vbCr).Replace(vbCr, vbCrLf))
|
||||
If Ex.StackTrace IsNot Nothing Then
|
||||
For Each St As String In Ex.StackTrace.Split(vbCrLf)
|
||||
If ShowAllTrace OrElse St.ToLower.Contains("pcl") Then StackList.Add(St.Replace(vbCr, String.Empty).Replace(vbLf, String.Empty))
|
||||
Next
|
||||
End If
|
||||
Ex = Ex.InnerException
|
||||
Loop
|
||||
DescList = DescList.Distinct.ToList
|
||||
Dim Desc As String = Join(DescList, vbCrLf & "→ ")
|
||||
Dim Stack As String = If(StackList.Count > 0, vbCrLf & Join(StackList, vbCrLf), "")
|
||||
|
||||
'常见错误
|
||||
Dim CommonReason As String = Nothing
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL2 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。"
|
||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||
CommonReason = "PCL2 的权限不足。请尝试右键 PCL2,选择以管理员身份运行。"
|
||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||
CommonReason = "你的电脑运行内存不足,导致 PCL2 无法继续运行。请在关闭一部分不需要的程序后再试。"
|
||||
ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
|
||||
CommonReason = "你的网络环境不佳,导致难以连接到服务器。请重试,或尝试使用 VPN。"
|
||||
End If
|
||||
|
||||
If IsLine Then
|
||||
'无内部错误的快速处理
|
||||
If Ex.InnerException Is Nothing Then
|
||||
If Desc.Count = 0 Then
|
||||
Return Ex.Message.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr & vbCr, vbCr).Replace(vbCr, " ")
|
||||
Else
|
||||
Return Desc.First
|
||||
End If
|
||||
End If
|
||||
'构造输出信息
|
||||
Do Until Ex Is Nothing
|
||||
Desc.Add(Ex.Message.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr & vbCr, vbCr).Replace(vbCr, " "))
|
||||
Ex = Ex.InnerException
|
||||
Loop
|
||||
Desc.Reverse() '让最深层错误在最左边
|
||||
GetString = Join(Desc, " → ")
|
||||
'获取错误类型
|
||||
Dim TypeDesc As String = If(InnerEx.GetType.FullName = "System.Exception", "", vbCrLf & "错误类型:" & InnerEx.GetType.FullName)
|
||||
|
||||
'构造输出信息
|
||||
If CommonReason Is Nothing Then
|
||||
Return Desc & Stack & TypeDesc
|
||||
Else
|
||||
Dim Stack As New List(Of String)
|
||||
'逐级追加描述与堆栈
|
||||
Do Until Ex Is Nothing
|
||||
Desc.Add(Ex.Message.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr & vbCr, vbCr).Replace(vbCr, vbCrLf))
|
||||
If Ex.StackTrace IsNot Nothing Then
|
||||
For Each St As String In Ex.StackTrace.Split(vbCrLf)
|
||||
If ShowAllTrace OrElse St.ToLower.Contains("pcl") Then Stack.Add(St.Replace(vbCr, String.Empty).Replace(vbLf, String.Empty))
|
||||
Next
|
||||
End If
|
||||
Ex = Ex.InnerException
|
||||
Loop
|
||||
'构造输出信息
|
||||
Dim TypeName As String = RealEx.GetType.FullName
|
||||
GetString = Join(Desc, vbCrLf & "Caused By: ") & If(Stack.Count > 0, vbCrLf & Join(Stack, vbCrLf), "") & If(TypeName = "System.Exception", "", vbCrLf & "错误类型:" & TypeName)
|
||||
Return DescList.First & vbCrLf & CommonReason & vbCrLf & "————————————" & vbCrLf &
|
||||
"详细错误信息:" & vbCrLf & "→ " & Join(DescList.GetRange(1, DescList.Count - 1), vbCrLf & "→ ") & Stack & TypeDesc
|
||||
End If
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 提取 Exception 描述,汇总到一行。
|
||||
''' </summary>
|
||||
Public Function GetExceptionSummary(Ex As Exception) As String
|
||||
If Ex Is Nothing Then Return "无可用错误信息!"
|
||||
|
||||
'获取最底层的异常
|
||||
Dim InnerEx As Exception = Ex
|
||||
Do Until InnerEx.InnerException Is Nothing
|
||||
InnerEx = InnerEx.InnerException
|
||||
Loop
|
||||
|
||||
'获取各级错误的描述
|
||||
Dim DescList As New List(Of String)
|
||||
Do Until Ex Is Nothing
|
||||
DescList.Add(Ex.Message.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr & vbCr, vbCr).Replace(vbCr, " "))
|
||||
Ex = Ex.InnerException
|
||||
Loop
|
||||
DescList = DescList.Distinct.ToList
|
||||
|
||||
'常见错误
|
||||
Dim Desc As String = Join(DescList, vbCrLf & "→ ")
|
||||
Dim CommonReason As String = Nothing
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL2 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。"
|
||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||
CommonReason = "PCL2 的权限不足。请尝试右键 PCL2,选择以管理员身份运行。"
|
||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||
CommonReason = "你的电脑运行内存不足,导致 PCL2 无法继续运行。请在关闭一部分不需要的程序后再试。"
|
||||
ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
|
||||
CommonReason = "你的网络环境不佳,导致难以连接到服务器。请重试,或尝试使用 VPN。"
|
||||
End If
|
||||
|
||||
'构造输出信息
|
||||
If CommonReason IsNot Nothing Then
|
||||
Return DescList.First & ":" & CommonReason
|
||||
Else
|
||||
DescList.Reverse() '让最深层错误在最左边
|
||||
Return Join(DescList, " → ")
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 返回一个枚举对应的字符串。
|
||||
''' </summary>
|
||||
@@ -1803,28 +1875,36 @@ NextElement:
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 前台运行文件。
|
||||
''' </summary>
|
||||
''' <param name="FileName">文件名。可以为“notepad”等缩写。</param>
|
||||
''' <param name="Arguments">运行参数。</param>
|
||||
Public Sub ShellOnly(FileName As String, Optional Arguments As String = "")
|
||||
Using Program As New Process
|
||||
Program.StartInfo.Arguments = Arguments
|
||||
Program.StartInfo.FileName = FileName
|
||||
Log("[System] 执行外部命令:" & FileName & " " & Arguments)
|
||||
Program.Start()
|
||||
End Using
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 前台运行文件并返回返回值。
|
||||
''' </summary>
|
||||
''' <param name="FileName">文件名。可以为“notepad”等缩写。</param>
|
||||
''' <param name="Arguments">运行参数。</param>
|
||||
''' <param name="WaitForExit">是否等待该程序结束。默认为 False。</param>
|
||||
''' <param name="Timeout">等待该程序结束的最长时间(毫秒)。超时会返回 Result.Timeout。</param>
|
||||
Public Function ShellAndGetExitCode(FileName As String, Optional Arguments As String = "", Optional WaitForExit As Boolean = False, Optional Timeout As Integer = 1000000) As Result
|
||||
Public Function ShellAndGetExitCode(FileName As String, Optional Arguments As String = "", Optional Timeout As Integer = 1000000) As Result
|
||||
Try
|
||||
Using Program As New Process
|
||||
Program.StartInfo.Arguments = Arguments
|
||||
Program.StartInfo.FileName = FileName
|
||||
Log("[System] 执行外部命令并等待返回码:" & FileName & " " & Arguments)
|
||||
Program.Start()
|
||||
If WaitForExit Then
|
||||
If Program.WaitForExit(Timeout) Then
|
||||
Return Program.ExitCode
|
||||
Else
|
||||
Return Result.Timeout
|
||||
End If
|
||||
If Program.WaitForExit(Timeout) Then
|
||||
Return Program.ExitCode
|
||||
Else
|
||||
Return Result.Success
|
||||
Return Result.Timeout
|
||||
End If
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
@@ -1909,6 +1989,18 @@ NextElement:
|
||||
''' 如果当前并非 UI 线程,则会阻断当前线程,直至 UI 线程执行完毕。
|
||||
''' 为防止线程互锁,请仅在开始加载动画、从 UI 获取输入时使用!
|
||||
''' </summary>
|
||||
Public Function RunInUiWait(Of Output)(Action As Func(Of Output)) As Output
|
||||
If RunInUi() Then
|
||||
Return Action()
|
||||
Else
|
||||
Return Application.Current.Dispatcher.Invoke(Action)
|
||||
End If
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 确保在 UI 线程中执行代码。
|
||||
''' 如果当前并非 UI 线程,则会阻断当前线程,直至 UI 线程执行完毕。
|
||||
''' 为防止线程互锁,请仅在开始加载动画、从 UI 获取输入时使用!
|
||||
''' </summary>
|
||||
Public Sub RunInUiWait(Action As Action)
|
||||
If RunInUi() Then
|
||||
Action()
|
||||
@@ -2003,11 +2095,11 @@ NextElement:
|
||||
End Try
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 打开 explorer。
|
||||
''' 打开 explorer。注意参数中的路径要尽量加上双引号!
|
||||
''' </summary>
|
||||
Public Sub OpenExplorer(Argument As String)
|
||||
Try
|
||||
Process.Start("explorer.exe", Argument)
|
||||
ShellOnly("explorer.exe", Argument)
|
||||
Catch ex As Exception
|
||||
Log(ex, "打开资源管理器失败,请尝试关闭安全软件(如 360 安全卫士)", LogLevel.Msgbox)
|
||||
End Try
|
||||
@@ -2251,7 +2343,7 @@ Retry:
|
||||
RunInNewThread(Sub()
|
||||
Dim IsInitSuccess As Boolean = True
|
||||
Try
|
||||
For i = 4 To 1
|
||||
For i = 4 To 1 Step -1
|
||||
If File.Exists(Path & "PCL\Log" & i & ".txt") Then
|
||||
If File.Exists(Path & "PCL\Log" & (i + 1) & ".txt") Then File.Delete(Path & "PCL\Log" & (i + 1) & ".txt")
|
||||
CopyFile(Path & "PCL\Log" & i & ".txt", Path & "PCL\Log" & (i + 1) & ".txt")
|
||||
@@ -2380,10 +2472,10 @@ Retry:
|
||||
IsErrorTriggered = True
|
||||
|
||||
'获取错误信息
|
||||
Dim ExFull As String = Desc & ":" & GetString(Ex, False)
|
||||
Dim ExFull As String = Desc & ":" & GetExceptionDetail(Ex)
|
||||
|
||||
'输出日志
|
||||
Dim AppendText As String = "[" & GetTimeNow() & "] " & Desc & ":" & GetString(Ex, False, True) & vbCrLf '减轻同步锁占用
|
||||
Dim AppendText As String = "[" & GetTimeNow() & "] " & Desc & ":" & GetExceptionDetail(Ex, True) & vbCrLf '减轻同步锁占用
|
||||
If ModeDebug Then
|
||||
SyncLock LogListLock
|
||||
LogList.Append(AppendText)
|
||||
@@ -2401,19 +2493,19 @@ Retry:
|
||||
Case LogLevel.Normal
|
||||
#If DEBUG Then
|
||||
Case LogLevel.Developer
|
||||
Dim ExLine As String = Desc & ":" & GetString(Ex, True)
|
||||
Dim ExLine As String = Desc & ":" & GetExceptionSummary(Ex)
|
||||
Hint("[开发者模式] " & ExLine, HintType.Info, False)
|
||||
Case LogLevel.Debug
|
||||
Dim ExLine As String = Desc & ":" & GetString(Ex, True)
|
||||
Dim ExLine As String = Desc & ":" & GetExceptionSummary(Ex)
|
||||
Hint("[调试模式] " & ExLine, HintType.Info, False)
|
||||
#Else
|
||||
Case LogLevel.Developer
|
||||
Case LogLevel.Debug
|
||||
Dim ExLine As String = Desc & ":" & GetString(Ex, True)
|
||||
Dim ExLine As String = Desc & ":" & GetExceptionSummary(Ex)
|
||||
If ModeDebug Then Hint("[调试模式] " & ExLine, HintType.Info, False)
|
||||
#End If
|
||||
Case LogLevel.Hint
|
||||
Dim ExLine As String = Desc & ":" & GetString(Ex, True)
|
||||
Dim ExLine As String = Desc & ":" & GetExceptionSummary(Ex)
|
||||
Hint(ExLine, HintType.Critical, False)
|
||||
Case LogLevel.Msgbox
|
||||
MyMsgBox(ExFull, Title)
|
||||
@@ -2476,6 +2568,14 @@ Retry:
|
||||
If Not Exp Then Throw New Exception("断言命中")
|
||||
End Sub
|
||||
|
||||
'获取当前的堆栈信息
|
||||
Public Function GetStackTrace() As String
|
||||
Dim Stack As New StackTrace()
|
||||
Return Join(Stack.GetFrames().Skip(1).Select(Function(f) f.GetMethod).
|
||||
Select(Function(f) f.Name & "(" & Join(f.GetParameters.Select(Function(p) p.ToString).ToList, ", ") & ") - " & f.Module.ToString).ToList,
|
||||
vbCrLf).Replace(vbCrLf & vbCrLf, vbCrLf)
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "随机"
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
Me.Input = Input
|
||||
SyncLock LockState
|
||||
State = LoadState.Loading
|
||||
Progress = -1
|
||||
End SyncLock
|
||||
Else
|
||||
Exit Sub
|
||||
@@ -418,7 +419,7 @@
|
||||
Loader.State = LoadState.Waiting
|
||||
Next
|
||||
End If
|
||||
Update()
|
||||
RunInThread(AddressOf Update)
|
||||
End Sub
|
||||
Public Overrides Sub Abort()
|
||||
'改变状态
|
||||
@@ -484,7 +485,6 @@
|
||||
Case LoadState.Finished
|
||||
'检查是否需要重启
|
||||
If Loader.GetType.Name.StartsWith("LoaderTask") Then '类型名后面带有泛型,必须用 StartsWith
|
||||
'UNDONE: 这里的 IgnoreReloadTimeout 导致加载器不会重启,也就是微软登录不会自动重新登录
|
||||
If CType(Loader, Object).ShouldStart(If(Input IsNot Nothing AndAlso Loader.GetType.GenericTypeArguments.First Is Input.GetType, Input, Nothing), IgnoreReloadTimeout:=True) Then
|
||||
If ModeDebug Then Log("[Loader] 由于输入条件变更,重启已完成的加载器 " & Loader.Name)
|
||||
GoTo Restart
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
Imports System.Net
|
||||
|
||||
Public Module ModNet
|
||||
|
||||
Public Const NetDownloadEnd As String = ".PCLDownloading"
|
||||
|
||||
''' <summary>
|
||||
''' 测试 Ping。失败则返回 -1。
|
||||
''' </summary>
|
||||
Public Function Ping(Ip As String, Optional Timeout As Integer = 10000, Optional MakeLog As Boolean = True) As Integer
|
||||
Dim PingResult As NetworkInformation.PingReply
|
||||
Try
|
||||
PingResult = (New NetworkInformation.Ping).Send(Ip)
|
||||
Catch ex As Exception
|
||||
If MakeLog Then Log("[Net] Ping " & Ip & " 失败:" & ex.Message)
|
||||
Return -1
|
||||
End Try
|
||||
If PingResult.Status = NetworkInformation.IPStatus.Success Then
|
||||
If MakeLog Then Log("[Net] Ping " & Ip & " 结束:" & PingResult.RoundtripTime & "ms")
|
||||
Return PingResult.RoundtripTime
|
||||
Else
|
||||
If MakeLog Then Log("[Net] Ping " & Ip & " 失败")
|
||||
Return -1
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 以 WebClient 获取网页源代码。会进行至多 45 秒 3 次的尝试,允许最长 30s 的超时。
|
||||
''' </summary>
|
||||
@@ -77,7 +96,9 @@ Retry:
|
||||
''' </summary>
|
||||
''' <param name="Url">网页的 Url。</param>
|
||||
''' <param name="Encode">网页的编码,通常为 UTF-8。</param>
|
||||
Public Function NetGetCodeByRequestRetry(Url As String, Optional Encode As Encoding = Nothing, Optional Accept As String = "", Optional IsJson As Boolean = False)
|
||||
''' <param name="BackupUrl">如果第一次尝试失败,换用的备用 URL。</param>
|
||||
Public Function NetGetCodeByRequestRetry(Url As String, Optional Encode As Encoding = Nothing, Optional Accept As String = "",
|
||||
Optional IsJson As Boolean = False, Optional BackupUrl As String = Nothing)
|
||||
Dim RetryCount As Integer = 0
|
||||
Dim RetryException As Exception = Nothing
|
||||
Dim StartTime As Long = GetTimeTick()
|
||||
@@ -88,12 +109,12 @@ Retry:
|
||||
Return NetGetCodeRequest(Url, Encode, 10000, IsJson, Accept)
|
||||
Case 1 '慢速重试
|
||||
Thread.Sleep(500)
|
||||
Return NetGetCodeRequest(Url, Encode, 30000, IsJson, Accept)
|
||||
Return NetGetCodeRequest(If(BackupUrl, Url), Encode, 30000, IsJson, Accept)
|
||||
Case Else '快速重试
|
||||
If GetTimeTick() - StartTime > 5500 Then
|
||||
'若前两次加载耗费 5 秒以上,才进行重试
|
||||
Thread.Sleep(500)
|
||||
Return NetGetCodeRequest(Url, Encode, 4000, IsJson, Accept)
|
||||
Return NetGetCodeRequest(If(BackupUrl, Url), Encode, 4000, IsJson, Accept)
|
||||
Else
|
||||
Throw RetryException
|
||||
End If
|
||||
@@ -391,7 +412,7 @@ RequestFinished:
|
||||
Throw
|
||||
Catch ex As WebException
|
||||
If ex.Status = WebExceptionStatus.Timeout Then
|
||||
Throw New TimeoutException("连接服务器超时,请检查你的网络环境是否良好(" & Url & ")", ex)
|
||||
Throw New WebException("连接服务器超时,请检查你的网络环境是否良好(" & Url & ")", ex)
|
||||
Else
|
||||
'获取请求失败的返回
|
||||
Dim Res As String = ""
|
||||
@@ -940,7 +961,7 @@ Capture:
|
||||
Next
|
||||
'是否禁用多线程,以及规定碎片大小
|
||||
Dim TargetUrl As String = GetSource().Url
|
||||
If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") Then Return False
|
||||
If TargetUrl.Contains("pcl2-server") OrElse TargetUrl.Contains("gitcode.net") OrElse TargetUrl.Contains("mcer.cn") Then Return False
|
||||
Dim RealFilePieceLimit = If(TargetUrl.Contains("download.mcbbs.net"), FilePieceLimit * 5, FilePieceLimit)
|
||||
'寻找最大碎片
|
||||
Dim FilePieceMax As NetThread = Threads
|
||||
@@ -1162,10 +1183,10 @@ SourceBreak:
|
||||
Next
|
||||
End SyncLock
|
||||
End SyncLock
|
||||
Dim IsTimeoutString As String = GetString(ex, False).ToLower.Replace(" ", "")
|
||||
Dim IsTimeoutString As String = GetExceptionSummary(ex).ToLower.Replace(" ", "")
|
||||
Dim IsTimeout As Boolean = IsTimeoutString.Contains("由于连接方在一段时间后没有正确答复或连接的主机没有反应") OrElse
|
||||
IsTimeoutString.Contains("超时") OrElse IsTimeoutString.Contains("timeout") OrElse IsTimeoutString.Contains("timedout")
|
||||
Log("[Download] " & LocalName & " " & Info.Uuid & If(IsTimeout, "#:超时(" & (Timeout * 0.001) & "s)", "#:出错," & GetString(ex, False)))
|
||||
Log("[Download] " & LocalName & " " & Info.Uuid & If(IsTimeout, "#:超时(" & (Timeout * 0.001) & "s)", "#:出错," & GetExceptionDetail(ex)))
|
||||
Info.State = NetState.Error
|
||||
''使用该下载源的线程是否没有速度
|
||||
''下载超时也会导致没有速度,容易误判下载失败,所以已弃用此方法
|
||||
@@ -1676,12 +1697,16 @@ Retry:
|
||||
SyncLock LockState
|
||||
If State > LoadState.Loading Then Exit Sub
|
||||
If ExList Is Nothing OrElse ExList.Count = 0 Then ExList = New List(Of Exception) From {New Exception("未知错误!")}
|
||||
[Error] = ExList(0)
|
||||
'寻找第一个不是 404 的下载源
|
||||
Dim UsefulExs = ExList.Where(Function(e) Not e.Message.Contains("(404)")).ToList
|
||||
[Error] = If(UsefulExs.Count > 0, UsefulExs(0), ExList(0))
|
||||
'获取实际失败的文件
|
||||
SyncLock FilesLock
|
||||
For Each File In Files
|
||||
If File.State = NetState.Error Then
|
||||
[Error] = New Exception("文件下载失败:" & File.LocalPath & "(第一下载源:" & File.Sources(0).Url & ")", ExList(0))
|
||||
[Error] = New Exception("文件下载失败:" & File.LocalPath & vbCrLf & Join(
|
||||
File.Sources.Select(Function(s) If(s.Ex Is Nothing, s.Url, s.Ex.Message & "(" & s.Url & ")")).ToList(),
|
||||
vbCrLf), [Error])
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
@@ -1698,7 +1723,7 @@ Retry:
|
||||
'在退出同步锁后再进行日志输出
|
||||
Dim ErrOutput As New List(Of String)
|
||||
For Each Ex As Exception In ExList
|
||||
ErrOutput.Add(GetString(Ex, False))
|
||||
ErrOutput.Add(GetExceptionDetail(Ex))
|
||||
Next
|
||||
Log("[Download] " & Join(ArrayNoDouble(ErrOutput.ToArray), vbCrLf))
|
||||
End Sub
|
||||
|
||||
@@ -49,10 +49,10 @@ End Class
|
||||
Public Class ValidateRegex
|
||||
Inherits Validate
|
||||
Public Property Regex As String
|
||||
Public Property ErrorDescription As String = ""
|
||||
Public Property ErrorDescription As String = "正则检查失败!"
|
||||
Public Sub New()
|
||||
End Sub '用于 XAML 初始化
|
||||
Public Sub New(Regex As String, Optional ErrorDescription As String = "")
|
||||
Public Sub New(Regex As String, Optional ErrorDescription As String = "正则检查失败!")
|
||||
Me.Regex = Regex
|
||||
Me.ErrorDescription = ErrorDescription
|
||||
End Sub
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
SyncLock IsAnalyzeCacheClearedLock
|
||||
If Not IsAnalyzeCacheCleared Then
|
||||
Try
|
||||
DeleteDirectory(PathTemp & "CrashAnalyzer")
|
||||
DeleteDirectory(PathTemp & "CrashAnalyzer\")
|
||||
Catch ex As Exception
|
||||
Log(ex, "清理崩溃分析缓存失败")
|
||||
End Try
|
||||
@@ -88,7 +88,7 @@
|
||||
If FilePath.Contains("crash-") Then
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
|
||||
Else
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, File.ReadAllLines(FilePath, Encoding.UTF8)))
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath, Encoding.UTF8).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取可能的崩溃日志文件失败(" & FilePath & ")")
|
||||
@@ -135,7 +135,7 @@
|
||||
If TargetFile.Name.StartsWith("crash-") Then
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
|
||||
Else
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, File.ReadAllLines(TargetFile.FullName, Encoding.UTF8)))
|
||||
AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName, Encoding.UTF8).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
@@ -153,6 +153,7 @@
|
||||
ExtraLog
|
||||
CrashReport
|
||||
End Enum
|
||||
Private DirectFile As KeyValuePair(Of String, String())? = Nothing '在弹窗中选择直接打开的文件
|
||||
''' <summary>
|
||||
''' 从 AnalyzeRawFiles 中提取实际有用的文本片段存储到 AnalyzeFiles,并整理可用于生成报告的文件。
|
||||
''' 返回找到的用于分析的项目数。
|
||||
@@ -161,18 +162,22 @@
|
||||
Log("[Crash] 步骤 2:准备日志文本")
|
||||
|
||||
'对日志文件进行分类
|
||||
DirectFile = Nothing
|
||||
Dim TotalFiles As New List(Of KeyValuePair(Of AnalyzeFileType, KeyValuePair(Of String, String())))
|
||||
For Each LogFile In AnalyzeRawFiles
|
||||
Dim FileName As String = GetFileNameFromPath(LogFile.Key)
|
||||
Dim TargetType As AnalyzeFileType
|
||||
If FileName.StartsWith("hs_err") Then
|
||||
TargetType = AnalyzeFileType.HsErr
|
||||
DirectFile = LogFile
|
||||
ElseIf FileName.StartsWith("crash-") Then
|
||||
TargetType = AnalyzeFileType.CrashReport
|
||||
DirectFile = LogFile
|
||||
ElseIf FileName = "latest.log" OrElse FileName = "latest log.txt" OrElse
|
||||
FileName = "debug.log" OrElse FileName = "debug log.txt" OrElse FileName = "游戏崩溃前的输出.txt" OrElse
|
||||
FileName = "rawoutput.log" OrElse FileName = "启动器日志.txt" OrElse FileName = "PCL2 启动器日志.txt" OrElse FileName = "log1.txt" Then
|
||||
TargetType = AnalyzeFileType.MinecraftLog
|
||||
If DirectFile Is Nothing Then DirectFile = LogFile
|
||||
ElseIf FileName.EndsWith(".log") OrElse FileName.EndsWith(".txt") Then
|
||||
TargetType = AnalyzeFileType.ExtraLog
|
||||
Else
|
||||
@@ -340,6 +345,7 @@
|
||||
没有可用的分析文件
|
||||
使用32位Java导致JVM无法分配足够多的内存
|
||||
Mod重复安装
|
||||
OptiFine与Forge不兼容
|
||||
Fabric报错
|
||||
Fabric报错并给出解决方案
|
||||
Forge报错
|
||||
@@ -449,8 +455,12 @@ Done:
|
||||
If LogMc.Contains("The driver does not appear to support OpenGL") Then AppendReason(CrashReason.显卡不支持OpenGL)
|
||||
If LogMc.Contains("java.lang.ClassCastException: java.base/jdk") Then AppendReason(CrashReason.使用JDK)
|
||||
If LogMc.Contains("java.lang.ClassCastException: class jdk.") Then AppendReason(CrashReason.使用JDK)
|
||||
If LogMc.Contains("Cannot read field ""ofTelemetry"" because ""net.optifine.Config.gameSettings"" is null") Then AppendReason(CrashReason.OptiFine与Forge不兼容)
|
||||
If LogMc.Contains("TRANSFORMER/net.optifine/net.optifine.reflect.Reflector.<clinit>(Reflector.java") Then AppendReason(CrashReason.OptiFine与Forge不兼容)
|
||||
If LogMc.Contains("Open J9 is not supported") OrElse LogMc.Contains("OpenJ9 is incompatible") OrElse LogMc.Contains(".J9VMInternals.") Then AppendReason(CrashReason.使用OpenJ9)
|
||||
If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本过高)
|
||||
If LogMc.Contains("because module java.base does not export") Then AppendReason(CrashReason.Java版本过高)
|
||||
If LogMc.Contains("java.lang.ClassNotFoundException: jdk.nashorn.api.scripting.NashornScriptEngineFactory") Then AppendReason(CrashReason.Java版本过高)
|
||||
If LogMc.Contains("java.lang.ClassNotFoundException: java.lang.invoke.LambdaMetafactory") Then AppendReason(CrashReason.Java版本过高)
|
||||
If LogMc.Contains("The directories below appear to be extracted jar files. Fix this before you continue.") Then AppendReason(CrashReason.Mod文件被解压)
|
||||
If LogMc.Contains("Extracted mod jars found, loading will NOT continue") Then AppendReason(CrashReason.Mod文件被解压)
|
||||
@@ -460,7 +470,7 @@ Done:
|
||||
If LogMc.Contains("1282: Invalid operation") Then AppendReason(CrashReason.光影或资源包导致OpenGL1282错误)
|
||||
If LogMc.Contains("signer information does not match signer information of other classes in the same package") Then AppendReason(CrashReason.文件或内容校验失败, If(RegexSeek(LogMc, "(?<=class "")[^']+(?=""'s signer information)"), "").TrimEnd(vbCrLf))
|
||||
If LogMc.Contains("An exception was thrown, the game will display an error screen and halt.") Then AppendReason(CrashReason.Forge报错, If(RegexSeek(LogMc, "(?<=the game will display an error screen and halt[\s\S]+?Exception: )[\s\S]+?(?=\n\tat)"), "").TrimEnd(vbCrLf))
|
||||
If LogMc.Contains("A potential solution has been determined:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined:\n)(\t - [^\n]+\n)+"), ""), "(?<=\t)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("A potential solution has been determined:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf))
|
||||
If LogMc.Contains("Maybe try a lower resolution resourcepack?") Then AppendReason(CrashReason.材质过大或显卡配置不足)
|
||||
If LogMc.Contains("java.lang.NoSuchMethodError: net.minecraft.world.server.ChunkManager$ProxyTicketManager.shouldForceTicks(J)Z") AndAlso LogMc.Contains("OptiFine") Then AppendReason(CrashReason.OptiFine导致无法加载世界)
|
||||
If LogMc.Contains("Could not reserve enough space") Then
|
||||
@@ -554,7 +564,7 @@ Done:
|
||||
For Each Stack As String In StackSearchResults
|
||||
'If Not Stack.Contains(".") Then Continue For
|
||||
For Each IgnoreStack In {
|
||||
"java", "sun", "javax", "jdk",
|
||||
"java", "sun", "javax", "jdk", "oolloo",
|
||||
"org.lwjgl", "com.sun", "net.minecraftforge", "com.mojang", "net.minecraft", "cpw.mods", "com.google", "org.apache", "org.spongepowered", "net.fabricmc", "com.mumfrey",
|
||||
"com.electronwill.nightconfig", "it.unimi.dsi",
|
||||
"MojangTricksIntelDriversForPerformance_javaw"}
|
||||
@@ -580,9 +590,9 @@ NextStack:
|
||||
If {"com", "org", "net", "asm", "fml", "mod", "jar", "sun", "lib", "map", "gui", "dev", "nio", "api", "dsi",
|
||||
"core", "init", "mods", "main", "file", "game", "load", "read", "done", "util", "tile", "item", "base",
|
||||
"forge", "setup", "block", "model", "mixin", "event", "unimi",
|
||||
"common", "server", "config", "loader", "launch", "entity", "assist", "client", "modapi", "mojang", "shader", "events", "github",
|
||||
"common", "server", "config", "loader", "launch", "entity", "assist", "client", "modapi", "mojang", "shader", "events", "github", "recipe",
|
||||
"preinit", "preload", "machine", "reflect", "channel", "general", "handler", "content",
|
||||
"fastutil", "optifine", "minecraft", "transformers", "universal", "internal", "multipart", "minecraftforge", "override"
|
||||
"fastutil", "optifine", "minecraft", "transformers", "universal", "internal", "multipart", "minecraftforge", "override", "blockentity"
|
||||
}.Contains(Word.ToLower) Then Continue For
|
||||
PossibleWords.Add(Word.Trim)
|
||||
Next
|
||||
@@ -686,8 +696,19 @@ NextStack:
|
||||
Public Sub Output(IsHandAnalyze As Boolean, Optional ExtraFiles As List(Of String) = Nothing)
|
||||
'弹窗提示
|
||||
FrmMain.ShowWindowToTop()
|
||||
Select Case MyMsgBox(GetAnalyzeResult(IsHandAnalyze), If(IsHandAnalyze, "错误报告分析结果", "Minecraft 出现错误"), "确定", If(IsHandAnalyze, "", "导出错误报告"))
|
||||
Redo:
|
||||
Select Case MyMsgBox(GetAnalyzeResult(IsHandAnalyze), If(IsHandAnalyze, "错误报告分析结果", "Minecraft 出现错误"),
|
||||
"确定", If(IsHandAnalyze OrElse DirectFile Is Nothing, "", "查看日志"), If(IsHandAnalyze, "", "导出错误报告"))
|
||||
Case 2
|
||||
If File.Exists(DirectFile.Value.Key) Then
|
||||
ShellOnly(DirectFile.Value.Key)
|
||||
Else
|
||||
Dim FilePath As String = PathTemp & "Crash.txt"
|
||||
WriteFile(FilePath, Join(DirectFile.Value.Value, vbCrLf))
|
||||
ShellOnly(FilePath)
|
||||
End If
|
||||
GoTo Redo
|
||||
Case 3
|
||||
Dim FileAddress As String = Nothing
|
||||
Try
|
||||
'获取文件路径
|
||||
@@ -720,11 +741,7 @@ NextStack:
|
||||
Log(ex, "导出错误报告失败", LogLevel.Feedback)
|
||||
Exit Sub
|
||||
End Try
|
||||
Try
|
||||
Process.Start("explorer", "/select," & FileAddress)
|
||||
Catch ex As Exception
|
||||
Log(ex, "打开错误报告的存放文件夹失败")
|
||||
End Try
|
||||
OpenExplorer("/select,""" & FileAddress & """")
|
||||
End Select
|
||||
End Sub
|
||||
''' <summary>
|
||||
@@ -754,11 +771,11 @@ NextStack:
|
||||
Case CrashReason.内存不足
|
||||
ResultString = "Minecraft 内存不足,导致其无法继续运行。\n这很可能是由于你为游戏分配的内存不足,或是游戏的配置要求过高。\n\n你可以在启动设置中增加为游戏分配的内存,删除配置要求较高的材质、Mod、光影。\n如果这依然不奏效,请在开始游戏前尽量关闭其他软件,或者……换台电脑?\h"
|
||||
Case CrashReason.使用OpenJ9
|
||||
ResultString = "游戏因为使用 Open J9 而崩溃了。\n请在启动设置的 Java 选择一项中改用非 OpenJ9 的 Java 8,然后再启动游戏。\n如果你没有安装 JRE 8,你可以从网络中下载、安装一个。"
|
||||
ResultString = "游戏因为使用 Open J9 而崩溃了。\n请在启动设置的 Java 选择一项中改用非 OpenJ9 的 Java,然后再启动游戏。"
|
||||
Case CrashReason.使用JDK
|
||||
ResultString = "游戏似乎因为使用 JDK,或 Java 版本过高而崩溃了。\n请在启动设置的 Java 选择一项中改用 JRE 8(Java 8),然后再启动游戏。\n如果你没有安装 JRE 8,你可以从网络中下载、安装一个。"
|
||||
Case CrashReason.Java版本过高
|
||||
ResultString = "游戏似乎因为你所使用的 Java 版本过高而崩溃了。\n请在启动设置的 Java 选择一项中改用 JRE 8(Java 8),然后再启动游戏。\n如果你没有安装 JRE 8,你可以从网络中下载、安装一个。"
|
||||
ResultString = "游戏似乎因为你所使用的 Java 版本过高而崩溃了。\n请在启动设置的 Java 选择一项中改用较低版本的 Java,然后再启动游戏。\n如果没有,可以从网络中下载、安装一个。"
|
||||
Case CrashReason.使用32位Java导致JVM无法分配足够多的内存
|
||||
If Environment.Is64BitOperatingSystem Then
|
||||
ResultString = "你似乎正在使用 32 位 Java,这会导致 Minecraft 无法使用 1GB 以上的内存,进而造成崩溃。\n\n请在启动设置的 Java 选择一项中改用 64 位的 Java 再启动游戏,然后再启动游戏。\n如果你没有安装 64 位的 Java,你可以从网络中下载、安装一个。"
|
||||
@@ -819,6 +836,8 @@ NextStack:
|
||||
Else
|
||||
ResultString = "游戏似乎因为世界中的某些实体出现了问题。\n\n你可以创建一个新世界,并生成各种实体,观察游戏的运行情况:\n - 若正常运行,则是某些实体导致出错,你或许需要删除该世界。\n - 若仍然出错,问题就可能来自其他原因……\h"
|
||||
End If
|
||||
Case CrashReason.OptiFine与Forge不兼容
|
||||
ResultString = "由于 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n\n请前往 OptiFine 官网(https://optifine.net/downloads)查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏。\n经测试,Forge 版本过高或过低都可能导致崩溃。"
|
||||
Case CrashReason.低版本Forge与高版本Java不兼容
|
||||
ResultString = "由于低版本 Forge 与当前 Java 不兼容,导致了游戏崩溃。\n\n请尝试以下解决方案:\n - 更新 Forge 到 36.2.26 或更高版本\n - 换用版本低于 8.0.320 的 Java"
|
||||
Case CrashReason.版本Json中存在多个Forge
|
||||
|
||||
@@ -221,6 +221,7 @@
|
||||
McDownloadClientUpdateHint(Version, Json)
|
||||
IsNewClientVersionHinted = True
|
||||
End If
|
||||
McVersionHighest = Version.Split(".")(1)
|
||||
Setup.Set("ToolUpdateReleaseLast", Version)
|
||||
'解析更新提示(Snapshot)
|
||||
Version = Json("latest")("snapshot")
|
||||
@@ -237,7 +238,9 @@
|
||||
''' </summary>
|
||||
Public DlClientListBmclapiLoader As New LoaderTask(Of Integer, DlClientListResult)("DlClientList Bmclapi", AddressOf DlClientListBmclapiMain)
|
||||
Private Sub DlClientListBmclapiMain(Loader As LoaderTask(Of Integer, DlClientListResult))
|
||||
Dim Json As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json", IsJson:=True)
|
||||
Dim Json As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/mc/game/version_manifest.json",
|
||||
BackupUrl:="https://download.mcbbs.net/mc/game/version_manifest.json",
|
||||
IsJson:=True)
|
||||
Try
|
||||
Dim Versions As JArray = Json("versions")
|
||||
If Versions.Count < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Json.ToString & ")")
|
||||
@@ -331,6 +334,10 @@
|
||||
''' 发布时间,格式为“yyyy/mm/dd”。OptiFine 源无此数据。
|
||||
''' </summary>
|
||||
Public ReleaseTime As String
|
||||
''' <summary>
|
||||
''' 需要的最低 Forge 版本。空字符串为无限制,“28.1.56” 表示版本号,“1161” 表示版本号的最后一位。
|
||||
''' </summary>
|
||||
Public RequiredForgeVersion As String
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
@@ -365,21 +372,23 @@
|
||||
Dim Result As String = NetGetCodeByClient("https://optifine.net/downloads", Encoding.Default)
|
||||
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
||||
'获取所有版本信息
|
||||
Dim ReleaseTime As List(Of String) = RegexSearch(Result, "(?<=Date'>)[^<]+")
|
||||
Dim Forge As List(Of String) = RegexSearch(Result, "(?<=colForge'>)[^<]*")
|
||||
Dim ReleaseTime As List(Of String) = RegexSearch(Result, "(?<=colDate'>)[^<]+")
|
||||
Dim Name As List(Of String) = RegexSearch(Result, "(?<=OptiFine_)[0-9A-Za-z_.]+(?=.jar"")")
|
||||
If Not ReleaseTime.Count = Name.Count Then Throw New Exception("版本与发布时间数据无法对应")
|
||||
If Not Forge.Count = Name.Count Then Throw New Exception("版本与 Forge 兼容数据无法对应")
|
||||
If ReleaseTime.Count < 10 Then Throw New Exception("获取到的版本数量不足(" & Result & ")")
|
||||
'转化为列表输出
|
||||
Dim Versions As New List(Of DlOptiFineListEntry)
|
||||
For i = 0 To ReleaseTime.Count - 1
|
||||
Name(i) = Name(i).Replace("_", " ")
|
||||
Dim Entry As New DlOptiFineListEntry With {
|
||||
.NameDisplay = Name(i).ToString.Replace("HD U ", "").Replace(".0 ", " "),
|
||||
.NameDisplay = Name(i).Replace("HD U ", "").Replace(".0 ", " "),
|
||||
.ReleaseTime = Join({ReleaseTime(i).Split(".")(2), ReleaseTime(i).Split(".")(1), ReleaseTime(i).Split(".")(0)}, "/"),
|
||||
.IsPreview = Name(i).ToString.ToLower.Contains("pre"),
|
||||
.IsPreview = Name(i).ToLower.Contains("pre"),
|
||||
.Inherit = Name(i).ToString.Split(" ")(0),
|
||||
.NameFile = If(Name(i).ToString.ToLower.Contains("pre"), "preview_", "") &
|
||||
"OptiFine_" & Name(i).ToString.Replace(" ", "_") & ".jar"}
|
||||
.NameFile = If(Name(i).ToLower.Contains("pre"), "preview_", "") & "OptiFine_" & Name(i).Replace(" ", "_") & ".jar",
|
||||
.RequiredForgeVersion = Forge(i).Replace("Forge ", "").Replace("#", "")}
|
||||
Entry.NameVersion = Entry.Inherit & "-OptiFine_" & Name(i).ToString.Replace(" ", "_").Replace(Entry.Inherit & "_", "")
|
||||
Versions.Add(Entry)
|
||||
Next
|
||||
@@ -391,7 +400,8 @@
|
||||
''' </summary>
|
||||
Public DlOptiFineListBmclapiLoader As New LoaderTask(Of Integer, DlOptiFineListResult)("DlOptiFineList Bmclapi", AddressOf DlOptiFineListBmclapiMain)
|
||||
Private Sub DlOptiFineListBmclapiMain(Loader As LoaderTask(Of Integer, DlOptiFineListResult))
|
||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/optifine/versionList", IsJson:=True)
|
||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/optifine/versionList",
|
||||
BackupUrl:="https://download.mcbbs.net/optifine/versionList", IsJson:=True)
|
||||
Try
|
||||
Dim Versions As New List(Of DlOptiFineListEntry)
|
||||
For Each Token As JObject In Json
|
||||
@@ -400,7 +410,8 @@
|
||||
.ReleaseTime = "",
|
||||
.IsPreview = Token("patch").ToString.ToLower.Contains("pre"),
|
||||
.Inherit = Token("mcversion").ToString,
|
||||
.NameFile = Token("filename").ToString
|
||||
.NameFile = Token("filename").ToString,
|
||||
.RequiredForgeVersion = If(Token("forge"), "").ToString.Replace("Forge ", "").Replace("#", "")
|
||||
}
|
||||
Entry.NameVersion = Entry.Inherit & "-OptiFine_" & (Token("type").ToString & " " & Token("patch").ToString).Replace(".0 ", " ").Replace(" ", "_").Replace(Entry.Inherit & "_", "")
|
||||
Versions.Add(Entry)
|
||||
@@ -473,7 +484,8 @@
|
||||
''' </summary>
|
||||
Public DlForgeListBmclapiLoader As New LoaderTask(Of Integer, DlForgeListResult)("DlForgeList Bmclapi", AddressOf DlForgeListBmclapiMain)
|
||||
Private Sub DlForgeListBmclapiMain(Loader As LoaderTask(Of Integer, DlForgeListResult))
|
||||
Dim Result As String = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft", Encoding.Default)
|
||||
Dim Result As String = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft", Encoding.Default,
|
||||
BackupUrl:="https://download.mcbbs.net/forge/minecraft")
|
||||
If Result.Length < 200 Then Throw New Exception("获取到的版本列表长度不足(" & Result & ")")
|
||||
'获取所有版本信息
|
||||
Dim Names As List(Of String) = RegexSearch(Result, "[0-9.]+(_pre[0-9]?)?")
|
||||
@@ -598,7 +610,7 @@
|
||||
Try
|
||||
Result = NetGetCodeByDownload("http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_" & Loader.Input & ".html")
|
||||
Catch ex As Exception
|
||||
If GetString(ex).Contains("(404)") Then
|
||||
If GetExceptionSummary(ex).Contains("(404)") Then
|
||||
Throw New Exception("没有可用版本")
|
||||
Else
|
||||
Throw
|
||||
@@ -642,11 +654,14 @@
|
||||
VersionCode = VersionCode.Substring(VersionCode.IndexOf("universal.zip"))
|
||||
MD5 = RegexSeek(VersionCode, "(?<=MD5:</strong> )[^<]+")
|
||||
Category = "universal"
|
||||
Else
|
||||
ElseIf VersionCode.Contains("client.zip") Then
|
||||
'类型为 client.zip,支持范围 182~ (1.3.2 部分 ~)
|
||||
VersionCode = VersionCode.Substring(VersionCode.IndexOf("client.zip"))
|
||||
MD5 = RegexSeek(VersionCode, "(?<=MD5:</strong> )[^<]+")
|
||||
Category = "client"
|
||||
Else
|
||||
'没有任何下载(1.6.4 有一部分这种情况)
|
||||
Continue For
|
||||
End If
|
||||
'添加进列表
|
||||
Versions.Add(New DlForgeVersionEntry With {.Category = Category, .Version = Name, .IsRecommended = IsRecommended, .Hash = MD5.Trim(vbCr, vbLf), .Inherit = Inherit, .ReleaseTime = ReleaseTime, .Branch = Branch})
|
||||
@@ -665,7 +680,8 @@
|
||||
''' Forge 版本列表,BMCLAPI。
|
||||
''' </summary>
|
||||
Public Sub DlForgeVersionBmclapiMain(Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)))
|
||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" & Loader.Input, IsJson:=True)
|
||||
Dim Json As JArray = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/forge/minecraft/" & Loader.Input,
|
||||
BackupUrl:="https://download.mcbbs.net/forge/minecraft/" & Loader.Input, IsJson:=True)
|
||||
Dim Versions As New List(Of DlForgeVersionEntry)
|
||||
Try
|
||||
Dim Recommended As String = McDownloadForgeRecommendedGet(Loader.Input)
|
||||
@@ -757,7 +773,7 @@
|
||||
''' </summary>
|
||||
Public IsLegacy As Boolean
|
||||
''' <summary>
|
||||
''' 发布时间,格式为“yyyy/mm/dd HH:mm:ss”。
|
||||
''' 发布时间,格式为“yyyy/mm/dd HH:mm”。
|
||||
''' </summary>
|
||||
Public ReleaseTime As String
|
||||
''' <summary>
|
||||
@@ -812,7 +828,7 @@
|
||||
.IsPreview = RealEntry("stream").ToString.ToLower = "snapshot",
|
||||
.FileName = "liteloader-installer-" & Pair.Key & If(Pair.Key = "1.8" OrElse Pair.Key = "1.9", ".0", "") & "-00-SNAPSHOT.jar",
|
||||
.MD5 = RealEntry("md5"),
|
||||
.ReleaseTime = GetLocalTime(GetDate(RealEntry("timestamp"))).ToString("yyyy/MM/dd HH:mm:ss"),
|
||||
.ReleaseTime = GetLocalTime(GetDate(RealEntry("timestamp"))).ToString("yyyy/MM/dd HH:mm"),
|
||||
.JsonToken = RealEntry
|
||||
})
|
||||
Next
|
||||
@@ -827,7 +843,8 @@
|
||||
''' </summary>
|
||||
Public DlLiteLoaderListBmclapiLoader As New LoaderTask(Of Integer, DlLiteLoaderListResult)("DlLiteLoaderList Bmclapi", AddressOf DlLiteLoaderListBmclapiMain)
|
||||
Private Sub DlLiteLoaderListBmclapiMain(Loader As LoaderTask(Of Integer, DlLiteLoaderListResult))
|
||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json", IsJson:=True)
|
||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json",
|
||||
BackupUrl:="https://download.mcbbs.net/maven/com/mumfrey/liteloader/versions.json", IsJson:=True)
|
||||
Try
|
||||
Dim Json As JObject = Result("versions")
|
||||
Dim Versions As New List(Of DlLiteLoaderListEntry)
|
||||
@@ -840,7 +857,7 @@
|
||||
.IsPreview = RealEntry("stream").ToString.ToLower = "snapshot",
|
||||
.FileName = "liteloader-installer-" & Pair.Key & If(Pair.Key = "1.8" OrElse Pair.Key = "1.9", ".0", "") & "-00-SNAPSHOT.jar",
|
||||
.MD5 = RealEntry("md5"),
|
||||
.ReleaseTime = GetLocalTime(GetDate(RealEntry("timestamp"))).ToString("yyyy/MM/dd HH:mm:ss"),
|
||||
.ReleaseTime = GetLocalTime(GetDate(RealEntry("timestamp"))).ToString("yyyy/MM/dd HH:mm"),
|
||||
.JsonToken = RealEntry
|
||||
})
|
||||
Next
|
||||
@@ -913,7 +930,8 @@
|
||||
''' </summary>
|
||||
Public DlFabricListBmclapiLoader As New LoaderTask(Of Integer, DlFabricListResult)("DlFabricList Bmclapi", AddressOf DlFabricListBmclapiMain)
|
||||
Private Sub DlFabricListBmclapiMain(Loader As LoaderTask(Of Integer, DlFabricListResult))
|
||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/fabric-meta/v2/versions", IsJson:=True)
|
||||
Dim Result As JObject = NetGetCodeByRequestRetry("https://bmclapi2.bangbang93.com/fabric-meta/v2/versions",
|
||||
BackupUrl:="https://download.mcbbs.net/fabric-meta/v2/versions", IsJson:=True)
|
||||
Try
|
||||
Dim Output = New DlFabricListResult With {.IsOfficial = False, .SourceName = "BMCLAPI", .Value = Result}
|
||||
If Output.Value("game") Is Nothing OrElse Output.Value("loader") Is Nothing OrElse Output.Value("installer") Is Nothing Then Throw New Exception("获取到的列表缺乏必要项")
|
||||
@@ -939,7 +957,7 @@
|
||||
|
||||
#Region "DlCfProject | CurseForge 工程"
|
||||
|
||||
Private DlCfProjectDb As Dictionary(Of String, String) = Nothing
|
||||
Private DlCfProjectDb As Dictionary(Of String, DlCfDbEntry) = Nothing
|
||||
Private DlCfProjectCache As New Dictionary(Of Integer, DlCfProject)
|
||||
|
||||
''' <summary>
|
||||
@@ -988,7 +1006,6 @@
|
||||
|
||||
Public Id As Integer
|
||||
Public Name As String
|
||||
Public McWikiId As Integer = 0
|
||||
Public Description As String
|
||||
Public Website As String
|
||||
Public DateUpdate As Date
|
||||
@@ -1000,22 +1017,19 @@
|
||||
Public IsModPack As Boolean
|
||||
Public FileIndexes As New List(Of Integer)
|
||||
Public Files As List(Of DlCfFile)
|
||||
Private _MCBBS As String
|
||||
Public Property MCBBS As String
|
||||
Private _MCBBS As Integer?
|
||||
Public Property MCBBS As Integer?
|
||||
Get
|
||||
ReleaseCfDatabase()
|
||||
If _MCBBS Is Nothing Then
|
||||
If Website IsNot Nothing Then
|
||||
Dim Keyword As String = Website.TrimEnd("/").Split("/").Last
|
||||
If DlCfProjectDb.ContainsKey(Keyword) Then
|
||||
Dim Result As String() = DlCfProjectDb(Keyword).ToString.Split("|")
|
||||
If Result.Length = 3 Then _MCBBS = Result.Last
|
||||
End If
|
||||
If DlCfProjectDb.ContainsKey(Keyword) Then _MCBBS = DlCfProjectDb(Keyword).MCBBS
|
||||
End If
|
||||
End If
|
||||
Return _MCBBS
|
||||
End Get
|
||||
Set(value As String)
|
||||
Set(value As Integer?)
|
||||
_MCBBS = value
|
||||
End Set
|
||||
End Property
|
||||
@@ -1028,20 +1042,42 @@
|
||||
If Website IsNot Nothing Then
|
||||
Dim Keyword As String = Website.TrimEnd("/").Split("/").Last
|
||||
If DlCfProjectDb.ContainsKey(Keyword) Then
|
||||
Dim Result As String = DlCfProjectDb(Keyword)
|
||||
McWikiId = Result.Split("|")(0)
|
||||
If Not Result.Split("|")(1) = "~" Then '使用原名
|
||||
_ChineseName = Result.Split("|")(1)
|
||||
Dim Result = DlCfProjectDb(Keyword)
|
||||
If Not String.IsNullOrEmpty(Result.ChineseName) Then '使用原名
|
||||
_ChineseName = Result.ChineseName
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Return _ChineseName
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
Set(value As String)
|
||||
_ChineseName = value
|
||||
End Set
|
||||
End Property
|
||||
Private _WikiId As Integer = -1
|
||||
''' <summary>
|
||||
''' MCMOD 的页面 ID。若为 0 则代表没有对应页面。
|
||||
''' </summary>
|
||||
Public Property WikiId As Integer
|
||||
Get
|
||||
ReleaseCfDatabase()
|
||||
If _WikiId = -1 Then
|
||||
If Website IsNot Nothing Then
|
||||
Dim Keyword As String = Website.TrimEnd("/").Split("/").Last
|
||||
If DlCfProjectDb.ContainsKey(Keyword) Then
|
||||
_WikiId = DlCfProjectDb(Keyword).WikiId
|
||||
Else
|
||||
_WikiId = 0
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Return _WikiId
|
||||
End Get
|
||||
Set(value As Integer)
|
||||
_WikiId = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
''' <summary>
|
||||
''' 从 CurseForge 工程 Json 项中初始化实例。若出错会抛出异常。
|
||||
@@ -1055,33 +1091,27 @@
|
||||
DateUpdate = Data("dateModified")
|
||||
DownloadCount = Data("downloadCount")
|
||||
IsModPack = Not Website.Contains("/mc-mods/")
|
||||
'获取常见文件
|
||||
'获取 Mod Loader 列表
|
||||
ModLoaders = New List(Of String)
|
||||
For Each File In If(Data("latestFiles"), {})
|
||||
Dim NewFile As New DlCfFile(File, IsModPack)
|
||||
If Not NewFile.IsAvailable Then Continue For
|
||||
ModLoaders.AddRange(NewFile.ModLoaders)
|
||||
Next
|
||||
'获取游戏版本、Mod Loader
|
||||
ModLoaders = ModLoaders.Distinct.ToList
|
||||
'用一个偷懒的方式让 Forge 排在 Fabric 的前面
|
||||
ModLoaders = ModLoaders.Select(Function(s) s.Replace("Forge", "Aorge")).ToList()
|
||||
ModLoaders.Sort()
|
||||
ModLoaders = ModLoaders.Select(Function(s) s.Replace("Aorge", "Forge")).ToList()
|
||||
'获取游戏版本
|
||||
Dim GameVersions As New List(Of Integer)
|
||||
ModLoaders = New List(Of String)
|
||||
For Each File In If(Data("latestFilesIndexes"), {})
|
||||
Dim Version As String = File("gameVersion")
|
||||
If Not Version.Contains("1.") Then Continue For
|
||||
GameVersions.Add(Version.Split(".")(1).Split("-").First)
|
||||
Select Case If(File("modLoader"), "0").ToString
|
||||
Case 1
|
||||
ModLoaders.Add("Forge")
|
||||
Case 2
|
||||
ModLoaders.Add("Cauldron")
|
||||
Case 3
|
||||
ModLoaders.Add("LiteLoader")
|
||||
Case 4
|
||||
ModLoaders.Add("Fabric")
|
||||
End Select
|
||||
FileIndexes.Add(File("fileId"))
|
||||
Next
|
||||
GameVersions = Sort(GameVersions.Distinct.ToList, AddressOf VersionSortBoolean)
|
||||
ModLoaders = ModLoaders.Distinct.ToList
|
||||
ModLoaders.Sort()
|
||||
If GameVersions.Count = 0 Then
|
||||
GameVersionDesc = ""
|
||||
Else
|
||||
@@ -1098,8 +1128,15 @@
|
||||
Next
|
||||
If StartVersion = EndVersion Then
|
||||
SpaVersions.Add("1." & StartVersion)
|
||||
ElseIf StartVersion >= McVersionHighest Then
|
||||
SpaVersions.Add("1." & EndVersion & "+")
|
||||
ElseIf EndVersion <= 7 Then
|
||||
SpaVersions.Add("1." & StartVersion & "-")
|
||||
Exit For
|
||||
ElseIf StartVersion - EndVersion = 1 Then
|
||||
SpaVersions.Add("1." & StartVersion & ", 1." & EndVersion)
|
||||
Else
|
||||
SpaVersions.Add("1." & StartVersion & "-1." & EndVersion)
|
||||
SpaVersions.Add("1." & StartVersion & "~1." & EndVersion)
|
||||
End If
|
||||
Next
|
||||
GameVersionDesc = "[" & Join(SpaVersions, ", ") & "] "
|
||||
@@ -1176,11 +1213,11 @@
|
||||
Dim NewItem As New MyCfItem With {.Tag = Me}
|
||||
NewItem.LabTitle.Text = ChineseName
|
||||
NewItem.LabInfo.Text = Description.Replace(vbCr, "").Replace(vbLf, "")
|
||||
NewItem.LabLeft.Text = If(ModLoaders.Count > 0 AndAlso ShowLoaderDesc, "[" & Join(ModLoaders, " & ") & "] ", "") &
|
||||
If(ShowVersionDesc, GameVersionDesc, "") &
|
||||
NewItem.LabLeft.Text = (If(ModLoaders.Count > 0 AndAlso ShowLoaderDesc, "[" & Join(ModLoaders, "/") & "] ", "") &
|
||||
If(ShowVersionDesc, GameVersionDesc, "")).Replace("] [", " ") &
|
||||
Join(CategoryDesc, ",") & " (" &
|
||||
GetTimeSpanString(DateUpdate - Date.Now) & "更新" &
|
||||
If(DownloadCount > 0, "," & If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载)", DownloadCount & " 次下载)"), "")
|
||||
GetTimeSpanString(DateUpdate - Date.Now) & "更新," &
|
||||
If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载", DownloadCount & " 次下载") & ")"
|
||||
If Thumb Is Nothing Then
|
||||
NewItem.Logo = "pack://application:,,,/images/Icons/NoIcon.png"
|
||||
Else
|
||||
@@ -1217,8 +1254,15 @@
|
||||
''' CurseForge 工程列表获取事件。
|
||||
''' </summary>
|
||||
Public Sub DlCfProjectSub(Task As LoaderTask(Of DlCfProjectRequest, DlCfProjectResult))
|
||||
Dim RawFilter As String = If(Task.Input.SearchFilter, "")
|
||||
'拒绝 1.13- Quilt(这个版本根本没有 Quilt)
|
||||
If Not Task.Input.IsModPack AndAlso
|
||||
If(Task.Input.ModLoader, 0) = 5 AndAlso VersionSortInteger(If(Task.Input.GameVersion, "1.15"), "1.14") = -1 Then
|
||||
Throw New Exception("Quilt 不支持 Minecraft " & Task.Input.GameVersion)
|
||||
End If
|
||||
|
||||
Dim RawFilter As String = If(Task.Input.SearchFilter, "").Trim
|
||||
Task.Input.SearchFilter = RawFilter
|
||||
RawFilter = RawFilter.ToLower
|
||||
Log("[Download] CurseForge 工程列表搜索原始文本:" & RawFilter)
|
||||
'中文请求关键字处理
|
||||
Dim IsChineseSearch As Boolean = RegexCheck(RawFilter, "[\u4e00-\u9fbb]")
|
||||
@@ -1227,12 +1271,12 @@
|
||||
ReleaseCfDatabase()
|
||||
'构造搜索请求
|
||||
Dim SearchEntries As New List(Of SearchEntry(Of String))
|
||||
For Each Entry In DlCfProjectDb
|
||||
If Entry.Value.ToString.Contains("动态的树") Then Continue For '傻逼 Mod 的附属太多了
|
||||
For Each Entry In DlCfProjectDb.Values
|
||||
If If(Entry.ChineseName, "").Contains("动态的树") Then Continue For '傻逼 Mod 的附属太多了
|
||||
SearchEntries.Add(New SearchEntry(Of String) With {
|
||||
.Item = Entry.Value.ToString.Split("|")(1),
|
||||
.Item = Entry.ChineseName,
|
||||
.SearchSource = New List(Of KeyValuePair(Of String, Double)) From {
|
||||
New KeyValuePair(Of String, Double)(Entry.Value.ToString.Replace(" (", "|").Split("|")(1), 1)
|
||||
New KeyValuePair(Of String, Double)(Entry.ChineseName & Entry.CurseForgeId, 1)
|
||||
}
|
||||
})
|
||||
Next
|
||||
@@ -1242,7 +1286,7 @@
|
||||
Dim SearchResult As String = ""
|
||||
For i = 0 To SearchResults.Count - 1
|
||||
If Not SearchResults(i).AbsoluteRight AndAlso i >= Math.Min(2, SearchResults.Count - 1) Then Exit For '把 3 个结果拼合以提高准确度
|
||||
SearchResult += SearchResults(i).Item.Replace(" (", "|").Split("|").Last.TrimEnd(")") & " "
|
||||
SearchResult += SearchResults(i).Item.Replace(" - ", "§").Split("§").First.Replace(" (", "|").Split("|").Last.TrimEnd(")") & " "
|
||||
Next
|
||||
Log("[Download] CurseForge 工程列表中文搜索原始关键词:" & SearchResult, LogLevel.Developer)
|
||||
'去除常见连接词
|
||||
@@ -1258,14 +1302,25 @@
|
||||
'驼峰英文请求关键字处理
|
||||
Dim SpacedKeywords = RegexReplace(Task.Input.SearchFilter, "$& ", "([A-Z]+|[a-z]+?)(?=[A-Z]+[a-z]+[a-z ]*)")
|
||||
Dim ConnectedKeywords = Task.Input.SearchFilter.Replace(" ", "")
|
||||
Dim AllPossibleKeywords = SpacedKeywords & " " & If(IsChineseSearch, Task.Input.SearchFilter, ConnectedKeywords & " " & RawFilter)
|
||||
Dim AllPossibleKeywords = (SpacedKeywords & " " & If(IsChineseSearch, Task.Input.SearchFilter, ConnectedKeywords & " " & RawFilter)).ToLower
|
||||
'最终处理关键字:分割、去重
|
||||
Dim RightKeywords As New List(Of String)
|
||||
For Each Keyword In AllPossibleKeywords.Split(" ")
|
||||
If Keyword.Trim = "" Then Continue For
|
||||
If Keyword = "forge" OrElse Keyword = "fabric" OrElse Keyword = "for" OrElse Keyword = "mod" Then 'https://github.com/Hex-Dragon/PCL2/issues/208
|
||||
Log("[Download] 已跳过搜索关键词 " & Keyword, LogLevel.Developer)
|
||||
Continue For
|
||||
End If
|
||||
RightKeywords.Add(Keyword)
|
||||
Next
|
||||
Task.Input.SearchFilter = Join(ArrayNoDouble(RightKeywords), " ").ToLower
|
||||
If RawFilter.Length > 0 AndAlso RightKeywords.Count = 0 Then
|
||||
Task.Input.SearchFilter = RawFilter '全都被过滤掉了
|
||||
Else
|
||||
Task.Input.SearchFilter = Join(ArrayNoDouble(RightKeywords), " ").ToLower
|
||||
End If
|
||||
'例外项:OptiForge、OptiFabric(拆词后因为包含 Forge/Fabric 导致无法搜到实际的 Mod)
|
||||
If RawFilter.Replace(" ", "").ToLower.Contains("optiforge") Then Task.Input.SearchFilter = "optiforge"
|
||||
If RawFilter.Replace(" ", "").ToLower.Contains("optifabric") Then Task.Input.SearchFilter = "optifabric"
|
||||
Log("[Download] CurseForge 工程列表搜索最终文本:" & Task.Input.SearchFilter, LogLevel.Developer)
|
||||
'正式获取
|
||||
Dim Url = Task.Input.GetAddress()
|
||||
@@ -1331,16 +1386,42 @@
|
||||
''' </summary>
|
||||
Private Sub ReleaseCfDatabase()
|
||||
If DlCfProjectDb IsNot Nothing Then Exit Sub
|
||||
DlCfProjectDb = New Dictionary(Of String, String)
|
||||
For Each Entry In CType(GetJson(DecodeBytes(GetResources("ModData"))), JObject)
|
||||
Dim Result As String = Entry.Value.ToString
|
||||
If Not Result.Split("|")(1) = "~" Then '处理 *
|
||||
Result = Result.Replace("*", " (" &
|
||||
String.Join(" ", Entry.Key.Split("-").Select(Function(w) w.Substring(0, 1).ToUpper & w.Substring(1, w.Length - 1))) & ")")
|
||||
DlCfProjectDb = New Dictionary(Of String, DlCfDbEntry)
|
||||
For Each Line In DecodeBytes(GetResources("ModData")).Split(vbLf)
|
||||
Dim Entry = New DlCfDbEntry
|
||||
Dim SplitedLine = Line.Split("|")
|
||||
Entry.CurseForgeId = SplitedLine(0)
|
||||
Entry.WikiId = SplitedLine(1)
|
||||
Entry.ChineseName = SplitedLine(2)
|
||||
Entry.MCBBS = If(SplitedLine.Count = 4, SplitedLine(3), Nothing)
|
||||
If Entry.ChineseName.Contains("*") Then '处理 *
|
||||
Entry.ChineseName = Entry.ChineseName.Replace("*", " (" &
|
||||
String.Join(" ", Entry.CurseForgeId.Split("-").Select(Function(w) w.Substring(0, 1).ToUpper & w.Substring(1, w.Length - 1))) & ")")
|
||||
End If
|
||||
DlCfProjectDb.Add(Entry.Key, Result)
|
||||
DlCfProjectDb.Add(Entry.CurseForgeId, Entry)
|
||||
Next
|
||||
End Sub
|
||||
Public Class DlCfDbEntry
|
||||
''' <summary>
|
||||
''' McMod 的 ID。
|
||||
''' </summary>
|
||||
Public WikiId As Integer
|
||||
''' <summary>
|
||||
''' 中文译名。若为 Nothing 或空字符串则使用英文名。
|
||||
''' </summary>
|
||||
Public ChineseName As String
|
||||
''' <summary>
|
||||
''' MCBBS 发布帖编号(例如 195107)。若为 Nothing 则没有发布帖。
|
||||
''' </summary>
|
||||
Public MCBBS As Integer?
|
||||
''' <summary>
|
||||
''' CurseForge ID(例如 advanced-solar-panels)。
|
||||
''' </summary>
|
||||
Public CurseForgeId As String
|
||||
Public Overrides Function ToString() As String
|
||||
Return CurseForgeId & "|" & WikiId & "|" & ChineseName & If(MCBBS Is Nothing, "", "|" & MCBBS)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -1358,6 +1439,7 @@
|
||||
Public DisplayName As String
|
||||
Public [Date] As Date
|
||||
Public GameVersion As String()
|
||||
Public ModLoaders As New List(Of String)
|
||||
Public ReleaseType As Integer
|
||||
Public FileName As String
|
||||
Public DownloadCount As Integer
|
||||
@@ -1407,11 +1489,13 @@
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
'获取游戏版本
|
||||
'获取游戏版本与 Mod 加载器列表
|
||||
Dim Versions As New List(Of String)
|
||||
For Each Version In Data("gameVersions")
|
||||
If Version.ToString.StartsWith("1.") OrElse Version.ToString.Contains("w") Then
|
||||
Versions.Add(Version.ToString.Trim.ToLower)
|
||||
For Each Version In Data("gameVersions").Select(Function(t) t.ToString.Trim.ToLower)
|
||||
If Version.StartsWith("1.") OrElse Version.Contains("w") Then
|
||||
Versions.Add(Version.Replace("-snapshot", " 快照"))
|
||||
ElseIf Version = "forge" OrElse Version = "fabric" OrElse Version = "quilt" OrElse Version = "rift" Then
|
||||
ModLoaders.Add(Version.First.ToString.ToUpper & Version.Substring(1))
|
||||
End If
|
||||
Next
|
||||
If Versions.Count > 1 Then
|
||||
@@ -1419,11 +1503,13 @@
|
||||
If IsModPack Then GameVersion = {GameVersion(0)}
|
||||
ElseIf Versions.Count = 1 Then
|
||||
GameVersion = Versions.ToArray
|
||||
'ElseIf Data("gameVersion").Count = 1 AndAlso Not Data("gameVersion")(0).ToString.Contains("1.") Then
|
||||
' GameVersion = {"1.16.4"}
|
||||
Else
|
||||
GameVersion = {"未知版本"}
|
||||
End If
|
||||
'用一个偷懒的方式让 Forge 排在 Fabric 的前面
|
||||
ModLoaders = ModLoaders.Select(Function(s) s.Replace("Forge", "Aorge")).ToList()
|
||||
ModLoaders.Sort()
|
||||
ModLoaders = ModLoaders.Select(Function(s) s.Replace("Aorge", "Forge")).ToList()
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -1439,10 +1525,14 @@
|
||||
'获取描述信息
|
||||
Dim Info As String = ""
|
||||
If Not IsModPack Then
|
||||
Info += "适用于 " & Join(GameVersion, "、").Replace("-snapshot", " 快照") &
|
||||
If(ModeDebug AndAlso Dependencies.Count > 0, "," & Dependencies.Count & " 个前置,", ",")
|
||||
Info += If(ModLoaders.Count > 0, Join(ModLoaders, "/"), "") &
|
||||
If(GameVersion.Count > 1, If(ModLoaders.Count > 0, " ", "") & Join(GameVersion, "、").Replace("-snapshot", " 快照"), "")
|
||||
If Info <> "" Then Info = "适用于 " & Info & ","
|
||||
Info += If(ModeDebug AndAlso Dependencies.Count > 0, Dependencies.Count & " 个前置 Mod,", "")
|
||||
End If
|
||||
Info += If(DownloadCount > 0, If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载,", DownloadCount & " 次下载,"), "")
|
||||
'If DownloadCount > 0 Then 'DownloadCount 目前的返回内容完全不正确,经常是 0,干脆不显示了
|
||||
' Info += If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载,", DownloadCount & " 次下载,")
|
||||
'End If
|
||||
Info += GetTimeSpanString([Date] - Date.Now) & "更新"
|
||||
Info += If(ReleaseType <> 1, "," & ReleaseTypeString, "")
|
||||
|
||||
@@ -1502,7 +1592,6 @@
|
||||
Json = NetGetCodeByRequestRetry("https://api.curseforge.com/v1/mods/" & ProjectId & "/files?pageSize=999", Accept:="application/json", IsJson:=True)("data")
|
||||
Else
|
||||
'Mod 使用每个版本最新的文件
|
||||
'TODO: 完整 Mod 文件列表支持
|
||||
Json = GetJson(NetRequestRetry("https://api.curseforge.com/v1/mods/files", "POST", "{""fileIds"": [" & Join(TargetProject.FileIndexes, ",") & "]}", "application/json"))("data")
|
||||
End If
|
||||
Dim Files As New Dictionary(Of Integer, DlCfFile)
|
||||
@@ -1630,6 +1719,10 @@ ExitSub:
|
||||
If WaitCycle = 0 Then
|
||||
'启动第一个源
|
||||
LoaderList(0).Key.Start(MainLoader.Input, IsForceRestart)
|
||||
'将其他源标记为未启动,以确保可以切换下载源(#184)
|
||||
For i = 1 To LoaderList.Count - 1
|
||||
LoaderList(i).Key.State = LoadState.Waiting
|
||||
Next
|
||||
End If
|
||||
For i = 0 To LoaderList.Count - 1
|
||||
If WaitCycle = LoaderList(i).Value * 100 Then
|
||||
|
||||
@@ -4,22 +4,73 @@ Public Module ModLaunch
|
||||
|
||||
#Region "开始"
|
||||
|
||||
Public Class McLaunchOptions
|
||||
''' <summary>
|
||||
''' 强制指定在启动后进入的服务器 IP。
|
||||
''' 默认值:Nothing。使用版本设置的值。
|
||||
''' </summary>
|
||||
Public ServerIp As String = Nothing
|
||||
''' <summary>
|
||||
''' 将启动脚本保存到该地址,然后取消启动。这同时会改变启动时的提示等。
|
||||
''' 默认值:Nothing。不保存。
|
||||
''' </summary>
|
||||
Public SaveBatch As String = Nothing
|
||||
''' <summary>
|
||||
''' 强行指定启动的 MC 版本。
|
||||
''' 默认值:Nothing。使用 McVersionCurrent。
|
||||
''' </summary>
|
||||
Public Version As McVersion = Nothing
|
||||
End Class
|
||||
''' <summary>
|
||||
''' 尝试启动 Minecraft。必须在 UI 线程调用。
|
||||
''' 返回是否实际开始了启动(如果没有,则一定弹出了错误提示)。
|
||||
''' </summary>
|
||||
Public Function McLaunchStart(Optional Options As McLaunchOptions = Nothing) As Boolean
|
||||
Options = If(Options, New McLaunchOptions)
|
||||
'预检查
|
||||
If Not RunInUi() Then
|
||||
Throw New Exception("McLaunchStart 必须在 UI 线程调用!")
|
||||
End If
|
||||
If McLaunchLoader.State = LoadState.Loading Then
|
||||
Hint("已有游戏正在启动中!", HintType.Critical)
|
||||
Return False
|
||||
End If
|
||||
'强制切换需要启动的版本
|
||||
If Options.Version IsNot Nothing AndAlso McVersionCurrent <> Options.Version Then
|
||||
McLaunchLog("在启动前切换到版本 " & Options.Version.Name)
|
||||
'检查版本
|
||||
Options.Version.Load()
|
||||
If Options.Version.State = McVersionState.Error Then
|
||||
Hint("无法启动 Minecraft:" & Options.Version.Info, HintType.Critical)
|
||||
Return False
|
||||
End If
|
||||
'切换版本
|
||||
McVersionCurrent = Options.Version
|
||||
Setup.Set("LaunchVersionSelect", McVersionCurrent.Name)
|
||||
FrmLaunchLeft.RefreshButtonsUI()
|
||||
End If
|
||||
FrmMain.AprilGiveup()
|
||||
'禁止进入版本选择页面(否则就可以在启动中切换 McVersionCurrent 了)
|
||||
FrmMain.PageStack = FrmMain.PageStack.Where(Function(p) p.Page <> FormMain.PageType.VersionSelect).ToList
|
||||
'实际启动加载器
|
||||
McLaunchLoader.Start(Options, IsForceRestart:=True)
|
||||
Return True
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 记录启动日志。
|
||||
''' </summary>
|
||||
Public Sub McLaunchLog(Text As String)
|
||||
RunInUi(Sub()
|
||||
FrmLaunchRight.LabLog.Text += vbCrLf & "[" & GetTimeNow() & "] " & Text
|
||||
End Sub)
|
||||
RunInUi(Sub() FrmLaunchRight.LabLog.Text += vbCrLf & "[" & GetTimeNow() & "] " & Text)
|
||||
Log("[Launch] " & Text)
|
||||
End Sub
|
||||
|
||||
'启动状态切换
|
||||
Public McLaunchLoader As New LoaderTask(Of String, Object)("Loader Launch", AddressOf McLaunchStart) With {.OnStateChanged = AddressOf McLaunchState, .ReloadTimeout = 1}
|
||||
Public McLaunchLoader As New LoaderTask(Of McLaunchOptions, Object)("Loader Launch", AddressOf McLaunchStart) With {.OnStateChanged = AddressOf McLaunchState}
|
||||
Public McLaunchLoaderReal As LoaderCombo(Of Object)
|
||||
Public McLaunchProcess As Process
|
||||
Public McLaunchWatcher As Watcher
|
||||
Private Sub McLaunchState(Loader As LoaderTask(Of String, Object))
|
||||
Private Sub McLaunchState(Loader As LoaderTask(Of McLaunchOptions, Object))
|
||||
Select Case McLaunchLoader.State
|
||||
Case LoadState.Finished, LoadState.Failed, LoadState.Waiting, LoadState.Aborted
|
||||
FrmLaunchLeft.PageChangeToLogin()
|
||||
@@ -28,7 +79,13 @@ Public Module ModLaunch
|
||||
FrmLaunchRight.LabLog.Text = ""
|
||||
End Select
|
||||
End Sub
|
||||
Private Sub McLaunchStart(Loader As LoaderTask(Of String, Object))
|
||||
''' <summary>
|
||||
''' 指定启动中断时的提示文本。若不为 Nothing 则会显示为绿色。
|
||||
''' </summary>
|
||||
Private AbortHint As String = Nothing
|
||||
|
||||
'实际的启动方法
|
||||
Private Sub McLaunchStart(Loader As LoaderTask(Of McLaunchOptions, Object))
|
||||
'开始动画
|
||||
RunInUiWait(AddressOf FrmLaunchLeft.PageChangeToLaunching)
|
||||
'预检测(预检测的错误将直接抛出)
|
||||
@@ -48,7 +105,6 @@ Public Module ModLaunch
|
||||
}) With {.ProgressWeight = 2, .Show = False, .Block = False},
|
||||
McLoginLoader,
|
||||
New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground, True)) With {.ProgressWeight = 15, .Show = False, .Block = True},
|
||||
New LoaderTask(Of Integer, String)("提供参数中的服务器 IP", Sub(InnerLoader As LoaderTask(Of Integer, String)) InnerLoader.Output = Loader.Input) With {.ProgressWeight = 0.01, .Show = False},
|
||||
New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
|
||||
New LoaderTask(Of List(Of McLibToken), Integer)("解压文件", AddressOf McLaunchNatives) With {.ProgressWeight = 2},
|
||||
New LoaderTask(Of Integer, Integer)("预启动处理", AddressOf McLaunchPrerun) With {.ProgressWeight = 1},
|
||||
@@ -56,8 +112,10 @@ Public Module ModLaunch
|
||||
New LoaderTask(Of Process, Integer)("等待游戏窗口出现", AddressOf McLaunchWait) With {.ProgressWeight = 1},
|
||||
New LoaderTask(Of Integer, Integer)("结束处理", AddressOf McLaunchEnd) With {.ProgressWeight = 1}
|
||||
}) With {.Show = False}
|
||||
If McLoginLoader.State = LoadState.Finished Then McLoginLoader.State = LoadState.Waiting '要求重启登录主加载器,它会自行决定是否启动副加载器
|
||||
'等待加载器执行并更新 UI
|
||||
McLaunchLoaderReal = LaunchLoader
|
||||
AbortHint = Nothing
|
||||
LaunchLoader.Start()
|
||||
'任务栏进度条
|
||||
LoaderTaskbarAdd(LaunchLoader)
|
||||
@@ -71,7 +129,11 @@ Public Module ModLaunch
|
||||
Case LoadState.Finished
|
||||
Hint(McVersionCurrent.Name & " 启动成功!", HintType.Finish)
|
||||
Case LoadState.Aborted
|
||||
Hint("已取消启动!", HintType.Info)
|
||||
If AbortHint Is Nothing Then
|
||||
Hint("已取消启动!", HintType.Info)
|
||||
Else
|
||||
Hint(AbortHint, HintType.Finish)
|
||||
End If
|
||||
Case LoadState.Failed
|
||||
Throw LaunchLoader.Error
|
||||
Case Else
|
||||
@@ -91,7 +153,7 @@ NextInner:
|
||||
GoTo NextInner
|
||||
Else
|
||||
'没有特殊处理过的错误信息
|
||||
McLaunchLog("错误:" & GetString(ex, False))
|
||||
McLaunchLog("错误:" & GetExceptionDetail(ex))
|
||||
Log(ex, "Minecraft 启动失败", LogLevel.Msgbox, "启动失败")
|
||||
Throw
|
||||
End If
|
||||
@@ -206,12 +268,13 @@ NextInner:
|
||||
Public AccessToken As String = ""
|
||||
Public Uuid As String = ""
|
||||
Public UserName As String = ""
|
||||
Public ProfileJson As String = ""
|
||||
|
||||
Public Sub New()
|
||||
Type = McLoginType.Ms
|
||||
End Sub
|
||||
Public Overrides Function GetHashCode() As Integer
|
||||
Return GetHash(OAuthRefreshToken & AccessToken & Uuid & UserName) Mod Integer.MaxValue
|
||||
Return GetHash(OAuthRefreshToken & AccessToken & Uuid & UserName & ProfileJson) Mod Integer.MaxValue
|
||||
End Function
|
||||
End Class
|
||||
Public Class McLoginLegacy
|
||||
@@ -377,7 +440,7 @@ NextInner:
|
||||
Return LoginData
|
||||
End Function
|
||||
Private Sub McLoginStart(Data As LoaderTask(Of McLoginData, McLoginResult))
|
||||
McLaunchLog("登录线程已启动")
|
||||
McLaunchLog("登录加载已开始")
|
||||
'校验登录信息
|
||||
Dim CheckResult As String = McLoginAble(Data.Input)
|
||||
If Not CheckResult = "" Then Throw New ArgumentException(CheckResult)
|
||||
@@ -389,7 +452,13 @@ NextInner:
|
||||
Case McLoginType.Ms
|
||||
Loader = McLoginMsLoader
|
||||
Case McLoginType.Legacy
|
||||
Loader = McLoginLegacyLoader
|
||||
If PageLinkHiper.HiperState = LoadState.Finished Then
|
||||
'使用 HiPer 内网验证
|
||||
Loader = McLoginHiperLoader
|
||||
Else
|
||||
'默认的离线验证
|
||||
Loader = McLoginLegacyLoader
|
||||
End If
|
||||
Case McLoginType.Nide
|
||||
Loader = McLoginNideLoader
|
||||
Case McLoginType.Auth
|
||||
@@ -399,6 +468,7 @@ NextInner:
|
||||
Loader.WaitForExit(Data.Input, McLoginLoader, Data.IsForceRestarting)
|
||||
Data.Output = CType(Loader, Object).Output
|
||||
RunInUi(Sub() FrmLaunchLeft.RefreshPage(True, False)) '刷新自动填充列表
|
||||
McLaunchLog("登录加载已结束")
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -410,6 +480,7 @@ NextInner:
|
||||
Public McLoginLegacyLoader As New LoaderTask(Of McLoginLegacy, McLoginResult)("Loader Login Legacy", AddressOf McLoginLegacyStart)
|
||||
Public McLoginNideLoader As New LoaderTask(Of McLoginServer, McLoginResult)("Loader Login Nide", AddressOf McLoginServerStart) With {.ReloadTimeout = 60000}
|
||||
Public McLoginAuthLoader As New LoaderTask(Of McLoginServer, McLoginResult)("Loader Login Auth", AddressOf McLoginServerStart) With {.ReloadTimeout = 60000}
|
||||
Public McLoginHiperLoader As New LoaderTask(Of McLoginLegacy, McLoginResult)("Loader Login HiPer", AddressOf McLoginHiperStart) With {.ReloadTimeout = 60000}
|
||||
|
||||
'主加载函数,返回所有需要的登录信息
|
||||
Private Sub McLoginMsStart(Data As LoaderTask(Of McLoginMs, McLoginResult))
|
||||
@@ -419,7 +490,8 @@ NextInner:
|
||||
Data.Progress = 0.05
|
||||
'检查是否已经登录完成
|
||||
If Input.AccessToken <> "" AndAlso Not Data.IsForceRestarting Then
|
||||
Data.Output = New McLoginResult With {.AccessToken = Input.AccessToken, .Name = Input.UserName, .Uuid = Input.Uuid, .Type = "Microsoft", .ClientToken = Input.Uuid}
|
||||
Data.Output = New McLoginResult With
|
||||
{.AccessToken = Input.AccessToken, .Name = Input.UserName, .Uuid = Input.Uuid, .Type = "Microsoft", .ClientToken = Input.Uuid, .ProfileJson = Input.ProfileJson}
|
||||
GoTo SkipLogin
|
||||
End If
|
||||
'尝试登录
|
||||
@@ -456,6 +528,7 @@ Relogin:
|
||||
Setup.Set("CacheMsAccess", AccessToken)
|
||||
Setup.Set("CacheMsUuid", Result(0))
|
||||
Setup.Set("CacheMsName", Result(1))
|
||||
Setup.Set("CacheMsProfileJson", Result(2))
|
||||
Data.Output = New McLoginResult With {.AccessToken = AccessToken, .Name = Result(1), .Uuid = Result(0), .Type = "Microsoft", .ClientToken = Result(0), .ProfileJson = Result(2)}
|
||||
'解锁主题
|
||||
SkipLogin:
|
||||
@@ -480,7 +553,7 @@ SkipLogin:
|
||||
McLoginRequestValidate(Data)
|
||||
GoTo LoginFinish
|
||||
Catch ex As Exception
|
||||
Dim AllMessage = GetString(ex)
|
||||
Dim AllMessage = GetExceptionSummary(ex)
|
||||
McLaunchLog("验证登录失败:" & AllMessage)
|
||||
If (AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout")) AndAlso Not AllMessage.Contains("403") Then
|
||||
McLaunchLog("已触发超时登录失败")
|
||||
@@ -495,7 +568,7 @@ Refresh:
|
||||
McLoginRequestRefresh(Data, NeedRefresh)
|
||||
GoTo LoginFinish
|
||||
Catch ex As Exception
|
||||
McLaunchLog("刷新登录失败:" & GetString(ex))
|
||||
McLaunchLog("刷新登录失败:" & GetExceptionSummary(ex))
|
||||
End Try
|
||||
Data.Progress = If(NeedRefresh, 0.85, 0.45)
|
||||
End If
|
||||
@@ -504,7 +577,7 @@ Refresh:
|
||||
If Data.IsAborted Then Throw New ThreadInterruptedException
|
||||
NeedRefresh = McLoginRequestLogin(Data)
|
||||
Catch ex As Exception
|
||||
McLaunchLog("登录失败:" & GetString(ex))
|
||||
McLaunchLog("登录失败:" & GetExceptionSummary(ex))
|
||||
Throw
|
||||
End Try
|
||||
If NeedRefresh Then
|
||||
@@ -542,43 +615,9 @@ LoginFinish:
|
||||
Data.Progress = 0.1
|
||||
With Data.Output
|
||||
.Name = Input.UserName
|
||||
.Uuid = McLoginLegacyUuid(Input.UserName)
|
||||
.Uuid = McLoginLegacyUuidWithCustomSkin(Input.UserName, Input.SkinType, Input.SkinName)
|
||||
.Type = "Legacy"
|
||||
End With
|
||||
'根据离线皮肤获取实际使用的 Uuid
|
||||
Select Case Input.SkinType
|
||||
Case 0
|
||||
'默认,不需要处理
|
||||
Case 1
|
||||
'Steve
|
||||
Do Until McSkinSex(Data.Output.Uuid) = "Steve"
|
||||
If Data.Output.Uuid.EndsWith("FFFFF") Then Data.Output.Uuid = Mid(Data.Output.Uuid, 1, 32 - 5) & "00000"
|
||||
Data.Output.Uuid = Mid(Data.Output.Uuid, 1, 32 - 5) & (Long.Parse(Right(Data.Output.Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
||||
Loop
|
||||
Case 2
|
||||
'Alex
|
||||
Do Until McSkinSex(Data.Output.Uuid) = "Alex"
|
||||
If Data.Output.Uuid.EndsWith("FFFFF") Then Data.Output.Uuid = Mid(Data.Output.Uuid, 1, 32 - 5) & "00000"
|
||||
Data.Output.Uuid = Mid(Data.Output.Uuid, 1, 32 - 5) & (Long.Parse(Right(Data.Output.Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
||||
Loop
|
||||
Case 3
|
||||
'使用正版用户名
|
||||
Try
|
||||
If Not Input.SkinName = "" Then
|
||||
Log("[Skin] 由于离线皮肤设置,使用正版 UUID:" & Input.SkinName)
|
||||
Data.Output.Uuid = McLoginMojangUuid(Input.SkinName, False)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "离线启动时使用的正版皮肤获取失败")
|
||||
MyMsgBox("由于设置的离线启动时使用的正版皮肤获取失败,游戏将以无皮肤的方式启动。" & vbCrLf & "请检查你的网络是否通畅,或尝试使用 VPN!" & vbCrLf & vbCrLf & "详细的错误信息:" & ex.Message, "皮肤获取失败")
|
||||
End Try
|
||||
Case 4
|
||||
'自定义
|
||||
Do Until McSkinSex(Data.Output.Uuid) = If(Setup.Get("LaunchSkinSlim"), "Alex", "Steve")
|
||||
If Data.Output.Uuid.EndsWith("FFFFF") Then Data.Output.Uuid = Mid(Data.Output.Uuid, 1, 32 - 5) & "00000"
|
||||
Data.Output.Uuid = Mid(Data.Output.Uuid, 1, 32 - 5) & (Long.Parse(Right(Data.Output.Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
||||
Loop
|
||||
End Select
|
||||
'将结果扩展到所有项目中
|
||||
'Data.Output.AccessToken = Setup.Get("CacheMojangAccess") '不能优先使用缓存的 AccessToken,这会导致离线用户名设置失效
|
||||
'If Data.Output.AccessToken.Length < 300 Then
|
||||
@@ -593,6 +632,46 @@ LoginFinish:
|
||||
Names.Insert(0, Input.UserName)
|
||||
Setup.Set("LoginLegacyName", Join(Names.ToArray, "¨"))
|
||||
End Sub
|
||||
Private Sub McLoginHiperStart(Data As LoaderTask(Of McLoginLegacy, McLoginResult))
|
||||
Dim Input As McLoginLegacy = Data.Input
|
||||
McLaunchLog("登录方式:联机离线(" & Input.UserName & ")")
|
||||
Data.Progress = 0.05
|
||||
'尝试登录
|
||||
Try
|
||||
McLaunchLog("登录开始(Login, HiPer)")
|
||||
Dim LoginJson As JObject = GetJson(NetRequestRetry(
|
||||
Url:="http://hiperauth.tech/api/yggdrasil-hiper/authserver/authenticate",
|
||||
Method:="POST",
|
||||
Data:="{""agent"": {""name"": ""Minecraft"",""version"": 1},""username"":""" & Data.Input.UserName & """,""password"":""" &
|
||||
McLoginLegacyUuidWithCustomSkin(Input.UserName, Input.SkinType, Input.SkinName) & """,""requestUser"":true}",
|
||||
ContentType:="application/json; charset=utf-8"))
|
||||
'将登录结果输出
|
||||
Data.Output.AccessToken = LoginJson("accessToken").ToString
|
||||
Data.Output.ClientToken = LoginJson("clientToken").ToString
|
||||
Data.Output.Name = LoginJson("selectedProfile")("name").ToString
|
||||
Data.Output.Uuid = LoginJson("selectedProfile")("id").ToString
|
||||
Data.Output.Type = "Auth"
|
||||
Data.Output.Email = Data.Input.UserName
|
||||
McLaunchLog("登录成功(Login, HiPer)")
|
||||
'保存启动记录
|
||||
Dim Names As New List(Of String)
|
||||
If Not Setup.Get("LoginLegacyName") = "" Then Names.AddRange(Setup.Get("LoginLegacyName").ToString.Split("¨"))
|
||||
Names.Remove(Input.UserName)
|
||||
Names.Insert(0, Input.UserName)
|
||||
Setup.Set("LoginLegacyName", Join(Names.ToArray, "¨"))
|
||||
Catch ex As Exception
|
||||
Dim AllMessage As String = GetExceptionSummary(ex)
|
||||
Log(ex, "登录失败原始错误信息", LogLevel.Normal)
|
||||
Dim ThrowEx As Exception = ex
|
||||
If AllMessage.Contains("403") Then
|
||||
ThrowEx = New Exception("登录尝试过于频繁,导致被系统暂时屏蔽。请不要操作,等待 10 分钟后再试。", ex)
|
||||
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") OrElse AllMessage.Contains("网络请求失败") Then
|
||||
ThrowEx = New Exception("$登录失败:连接登录服务器超时。" & vbCrLf & "请检查 HiPer 联机模块的连接状况是否良好,或选择其他登录方式!")
|
||||
End If
|
||||
McLaunchLog("登录失败:" & GetExceptionSummary(ThrowEx))
|
||||
Throw ThrowEx
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'Server 登录:三种验证方式的请求
|
||||
Private Sub McLoginRequestValidate(ByRef Data As LoaderTask(Of McLoginServer, McLoginResult))
|
||||
@@ -719,7 +798,7 @@ LoginFinish:
|
||||
McLaunchLog("登录成功(Login, " & Data.Input.Token & ")")
|
||||
Return NeedRefresh
|
||||
Catch ex As Exception
|
||||
Dim AllMessage As String = GetString(ex)
|
||||
Dim AllMessage As String = GetExceptionSummary(ex)
|
||||
Log(ex, "登录失败原始错误信息", LogLevel.Normal)
|
||||
If AllMessage.Contains("410") AndAlso AllMessage.Contains("Migrated") Then
|
||||
Throw New Exception("$登录失败:该 Mojang 账号已迁移至微软账号,请在上方的登录方式中选择 微软 并再次尝试登录!")
|
||||
@@ -749,10 +828,8 @@ LoginFinish:
|
||||
If(Data.Input.UserName.Contains("@"), "", " - 登录账号应为邮箱或统一通行证账号,而非游戏角色 ID。" & vbCrLf) &
|
||||
" - 只注册了账号,但没有加入对应服务器。")
|
||||
End Select
|
||||
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") Then
|
||||
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") OrElse AllMessage.Contains("网络请求失败") Then
|
||||
Throw New Exception("$登录失败:连接登录服务器超时。" & vbCrLf & "请检查你的网络状况是否良好,或尝试使用 VPN!")
|
||||
ElseIf AllMessage.Contains("网络请求失败") Then
|
||||
Throw New Exception("$登录失败:连接登录服务器失败。" & vbCrLf & "请检查你的网络状况是否良好,或尝试使用 VPN!")
|
||||
ElseIf ex.Message.StartsWith("$") Then
|
||||
Throw
|
||||
Else
|
||||
@@ -842,7 +919,7 @@ SystemBrowser:
|
||||
Try
|
||||
Result = NetRequestMuity("https://login.live.com/oauth20_token.srf", "POST", Request, "application/x-www-form-urlencoded", 1)
|
||||
Catch ex As Exception
|
||||
If ex.Message.Contains("must sign in again") Then
|
||||
If ex.Message.Contains("must sign in again") OrElse ex.Message.Contains("invalid_grant") Then 'Fix Hex-Dragon/PCL2#269
|
||||
Return {"Relogin", ""}
|
||||
Else
|
||||
Throw
|
||||
@@ -892,7 +969,11 @@ SystemBrowser:
|
||||
Result = NetRequestMuity("https://xsts.auth.xboxlive.com/xsts/authorize", "POST", Request, "application/json", 3)
|
||||
Catch ex As Net.WebException
|
||||
If ex.Message.Contains("2148916233") Then
|
||||
Throw New Exception("$该微软账号尚未购买 Minecraft Java 版或注册 XBox 账户!")
|
||||
If MyMsgBox("该微软账号尚未购买 Minecraft Java 版,或尚未注册 XBox 账户。" & vbCrLf &
|
||||
"如果你确定该账号完成了上述步骤,请先在游戏官网登录一次,然后再在启动器登录。", "登录提示", "打开游戏官网", "取消") = 1 Then
|
||||
OpenWebsite("https://www.minecraft.net/")
|
||||
End If
|
||||
Throw New Exception("$$")
|
||||
ElseIf ex.Message.Contains("2148916238") Then
|
||||
If MyMsgBox("该账号年龄不足,你需要先修改出生日期,然后才能登录。" & vbCrLf &
|
||||
"该账号目前填写的年龄是否在 13 岁以上?", "登录提示", "13 岁以上", "12 岁以下", "我不知道") = 1 Then
|
||||
@@ -924,7 +1005,7 @@ SystemBrowser:
|
||||
Try
|
||||
Result = NetRequestMuity("https://api.minecraftservices.com/authentication/login_with_xbox", "POST", Request, "application/json", 2)
|
||||
Catch ex As Net.WebException
|
||||
Dim Message As String = GetString(ex)
|
||||
Dim Message As String = GetExceptionSummary(ex)
|
||||
If Message.Contains("(429)") Then
|
||||
Log(ex, "微软登录第 5 步汇报 429")
|
||||
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
||||
@@ -948,13 +1029,22 @@ SystemBrowser:
|
||||
Try
|
||||
Result = NetRequestMuity("https://api.minecraftservices.com/minecraft/profile", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
|
||||
Catch ex As Net.WebException
|
||||
Dim Message As String = GetString(ex)
|
||||
Dim Message As String = GetExceptionSummary(ex)
|
||||
If Message.Contains("(429)") Then
|
||||
Log(ex, "微软登录第 6 步汇报 429")
|
||||
Throw New Exception("$登录尝试太过频繁,请等待几分钟后再试!")
|
||||
ElseIf Message.Contains("(404)") Then
|
||||
Log(ex, "微软登录第 6 步汇报 404")
|
||||
Throw New Exception("$你可能没有在购买后去 Minecraft 官网创建游戏档案,或者没有购买 Minecraft。")
|
||||
RunInNewThread(Sub()
|
||||
Select Case MyMsgBox("你可能没有在 Minecraft 官网创建档案,或者没有购买 Minecraft。" & vbCrLf &
|
||||
"如果你已经购买了游戏,请在官网上创建档案后再试。", "登录失败", "创建档案", "购买 Minecraft", "取消")
|
||||
Case 1
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/msaprofile/mygames/editprofile")
|
||||
Case 2
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/store/minecraft-java-bedrock-edition-pc")
|
||||
End Select
|
||||
End Sub, "Login Failed: Create Profile")
|
||||
Throw New Exception("$$")
|
||||
Else
|
||||
Throw
|
||||
End If
|
||||
@@ -965,7 +1055,46 @@ SystemBrowser:
|
||||
Return {UUID, UserName, Result}
|
||||
End Function
|
||||
|
||||
'根据用户名返回对应 Uuid,需要多线程
|
||||
'返回符合离线皮肤设置的 UUID
|
||||
Private Function McLoginLegacyUuidWithCustomSkin(UserName As String, SkinType As Integer, SkinName As String) As String
|
||||
Dim Uuid As String = McLoginLegacyUuid(UserName)
|
||||
'根据离线皮肤获取实际使用的 Uuid
|
||||
Select Case SkinType
|
||||
Case 0
|
||||
'默认,不需要处理
|
||||
Case 1
|
||||
'Steve
|
||||
Do Until McSkinSex(Uuid) = "Steve"
|
||||
If Uuid.EndsWith("FFFFF") Then Uuid = Mid(Uuid, 1, 32 - 5) & "00000"
|
||||
Uuid = Mid(Uuid, 1, 32 - 5) & (Long.Parse(Right(Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
||||
Loop
|
||||
Case 2
|
||||
'Alex
|
||||
Do Until McSkinSex(Uuid) = "Alex"
|
||||
If Uuid.EndsWith("FFFFF") Then Uuid = Mid(Uuid, 1, 32 - 5) & "00000"
|
||||
Uuid = Mid(Uuid, 1, 32 - 5) & (Long.Parse(Right(Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
||||
Loop
|
||||
Case 3
|
||||
'使用正版用户名
|
||||
Try
|
||||
If Not SkinName = "" Then
|
||||
Log("[Skin] 由于离线皮肤设置,使用正版 UUID:" & SkinName)
|
||||
Uuid = McLoginMojangUuid(SkinName, False)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "离线启动时使用的正版皮肤获取失败")
|
||||
MyMsgBox("由于设置的离线启动时使用的正版皮肤获取失败,游戏将以无皮肤的方式启动。" & vbCrLf & "请检查你的网络是否通畅,或尝试使用 VPN!" & vbCrLf & vbCrLf & "详细的错误信息:" & ex.Message, "皮肤获取失败")
|
||||
End Try
|
||||
Case 4
|
||||
'自定义
|
||||
Do Until McSkinSex(Uuid) = If(Setup.Get("LaunchSkinSlim"), "Alex", "Steve")
|
||||
If Uuid.EndsWith("FFFFF") Then Uuid = Mid(Uuid, 1, 32 - 5) & "00000"
|
||||
Uuid = Mid(Uuid, 1, 32 - 5) & (Long.Parse(Right(Uuid, 5), Globalization.NumberStyles.AllowHexSpecifier) + 1).ToString("X")
|
||||
Loop
|
||||
End Select
|
||||
Return Uuid
|
||||
End Function
|
||||
'根据用户名返回对应 UUID,需要多线程
|
||||
Public Function McLoginMojangUuid(Name As String, ThrowOnNotFound As Boolean)
|
||||
If Name.Trim.Length = 0 Then Return StrFill("", "0", 32)
|
||||
'从缓存获取
|
||||
@@ -1014,25 +1143,50 @@ SystemBrowser:
|
||||
ElseIf McVersionCurrent.ReleaseTime.Year >= 2017 Then 'Minecraft 1.12 与 1.11 的分界线正好是 2017 年,太棒了
|
||||
'1.12+:至少 Java 8
|
||||
MinVer = New Version(1, 8, 0, 0)
|
||||
ElseIf McVersionCurrent.ReleaseTime.Year >= 2001 Then '避免某些版本的 1960 癌
|
||||
'1.11-:最高 Java 12
|
||||
ElseIf McVersionCurrent.ReleaseTime <= New Date(2013, 5, 1) AndAlso McVersionCurrent.ReleaseTime.Year >= 2001 Then '避免某些版本的 1960 癌
|
||||
'1.5.2-:最高 Java 12
|
||||
MaxVer = New Version(1, 12, 999, 999)
|
||||
End If
|
||||
|
||||
'OptiFine 检测
|
||||
If McVersionCurrent.Version.HasOptiFine Then
|
||||
If McVersionCurrent.Version.McCodeMain <= 7 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
|
||||
'<1.7:至多 Java 8(Java 9 - 10 未测试)
|
||||
MaxVer = New Version(1, 8, 999, 999)
|
||||
ElseIf McVersionCurrent.Version.McCodeMain >= 8 AndAlso McVersionCurrent.Version.McCodeMain <= 11 Then
|
||||
'1.8 - 1.11:必须恰好 Java 8(Java 9 - 10 未测试)
|
||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 8, 999, 999)
|
||||
End If
|
||||
End If
|
||||
|
||||
'Forge 检测
|
||||
If McVersionCurrent.Version.HasForge Then
|
||||
If McVersionCurrent.Version.McName = "1.7.2" Then
|
||||
'1.7.2:必须 Java 7
|
||||
MinVer = New Version(1, 7, 0, 0) : MaxVer = New Version(1, 7, 999, 999)
|
||||
ElseIf McVersionCurrent.Version.McCodeMain <= 12 AndAlso McVersionCurrent.Version.McCodeMain <> -1 AndAlso VersionSortBoolean("14.23.5.2855", McVersionCurrent.Version.ForgeVersion) Then
|
||||
'1.12,Forge 14.23.5.2855 及更低:Java 8
|
||||
ElseIf McVersionCurrent.Version.McCodeMain <= 12 AndAlso McVersionCurrent.Version.McCodeMain > 0 AndAlso VersionSortBoolean("14.23.5.2855", McVersionCurrent.Version.ForgeVersion) Then
|
||||
'<1.12,Forge 14.23.5.2855 及更低:Java 8
|
||||
MaxVer = New Version(1, 8, 999, 999)
|
||||
ElseIf McVersionCurrent.Version.McCodeMain <= 14 AndAlso McVersionCurrent.Version.McCodeMain <> -1 AndAlso VersionSortBoolean("28.2.23", McVersionCurrent.Version.ForgeVersion) Then
|
||||
ElseIf McVersionCurrent.Version.McCodeMain <= 14 AndAlso McVersionCurrent.Version.McCodeMain > 0 AndAlso VersionSortBoolean("28.2.23", McVersionCurrent.Version.ForgeVersion) Then
|
||||
'1.13 - 1.14,Forge 28.2.23 及更低:Java 8 - 10
|
||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 10, 999, 999)
|
||||
ElseIf McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain <> -1 Then
|
||||
'1.15 - 1.16:Java 8 - 12, 12 - 15未测试
|
||||
ElseIf McVersionCurrent.Version.McCodeMain <= 15 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
|
||||
'1.15:Java 8 - 15
|
||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999)
|
||||
ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305
|
||||
'1.18+:若安装了 OptiFine,最高 Java 18
|
||||
MaxVer = New Version(1, 18, 999, 999)
|
||||
End If
|
||||
End If
|
||||
|
||||
'Fabric 检测
|
||||
If McVersionCurrent.Version.HasFabric Then
|
||||
If McVersionCurrent.Version.McCodeMain >= 15 AndAlso McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain <> -1 Then
|
||||
'1.15 - 1.16:Java 8 - 18
|
||||
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 18, 999, 999)
|
||||
ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 Then
|
||||
'1.18+:Java 17 - 18
|
||||
MinVer = New Version(1, 17, 0, 0) : MaxVer = New Version(1, 18, 999, 999)
|
||||
End If
|
||||
End If
|
||||
|
||||
@@ -1076,6 +1230,31 @@ SystemBrowser:
|
||||
|
||||
Private McLaunchArgument As String
|
||||
|
||||
''' <summary>
|
||||
''' 释放 Java Wrapper 并返回完整文件路径。
|
||||
''' </summary>
|
||||
Public Function ExtractJavaWrapper() As String
|
||||
Dim WrapperPath As String = GetJavaWrapperDir() & "\JavaWrapper.jar"
|
||||
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
||||
Log("[Java] 已释放 Java Wrapper:" & WrapperPath)
|
||||
Return WrapperPath
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
|
||||
''' </summary>
|
||||
Public Function GetJavaWrapperDir() As String
|
||||
Dim WrapperPath As String = PathAppdata.TrimEnd("\")
|
||||
If Encoding.UTF8.GetByteCount(WrapperPath) <> WrapperPath.Length Then
|
||||
Log("[Java] AppData 路径中包含非 ASCII 字符,换用 Temp 目录")
|
||||
WrapperPath = PathTemp.TrimEnd("\")
|
||||
If Encoding.UTF8.GetByteCount(PathTemp) <> PathTemp.Length Then
|
||||
Log("[Java] Temp 路径中包含非 ASCII 字符,换用 C 盘根目录")
|
||||
WrapperPath = "C:\PCL"
|
||||
End If
|
||||
End If
|
||||
Return WrapperPath
|
||||
End Function
|
||||
|
||||
'主方法,合并 Jvm、Game、Replace 三部分的参数数据
|
||||
Private Sub McLaunchArgumentMain(Loader As LoaderTask(Of String, List(Of McLibToken)))
|
||||
McLaunchLog("开始获取 Minecraft 启动参数")
|
||||
@@ -1092,7 +1271,7 @@ SystemBrowser:
|
||||
McLaunchLog("旧版 JVM 参数获取成功:")
|
||||
McLaunchLog(Arguments)
|
||||
End If
|
||||
If McVersionCurrent.JsonObject("minecraftArguments") IsNot Nothing Then
|
||||
If Not String.IsNullOrEmpty(McVersionCurrent.JsonObject("minecraftArguments")) Then '有的版本是空字符串
|
||||
McLaunchLog("获取旧版 Game 参数")
|
||||
Arguments += " " & McLaunchArgumentsGameOld(McVersionCurrent)
|
||||
McLaunchLog("旧版 Game 参数获取成功")
|
||||
@@ -1117,7 +1296,7 @@ SystemBrowser:
|
||||
'全屏
|
||||
If Setup.Get("LaunchArgumentWindowType") = 0 Then Arguments += " --fullscreen"
|
||||
'进服
|
||||
Dim Server As String = If(String.IsNullOrEmpty(Loader.Input), Setup.Get("VersionServerEnter", McVersionCurrent), Loader.Input)
|
||||
Dim Server As String = If(String.IsNullOrEmpty(McLaunchLoader.Input.ServerIp), Setup.Get("VersionServerEnter", McVersionCurrent), McLaunchLoader.Input.ServerIp)
|
||||
If Server.Length > 0 Then
|
||||
If Server.Contains(":") Then
|
||||
'包含端口号
|
||||
@@ -1158,24 +1337,27 @@ SystemBrowser:
|
||||
|
||||
'统一通行证
|
||||
If McLoginLoader.Output.Type = "Nide" Then
|
||||
DataList.Insert(0, "-Dnide8auth.client=true -javaagent:nide8auth.jar=" & Setup.Get("VersionServerNide", Version:=McVersionCurrent))
|
||||
DataList.Insert(0, "-Dnide8auth.client=true -javaagent:""" & PathAppdata & "nide8auth.jar""=" & Setup.Get("VersionServerNide", Version:=McVersionCurrent))
|
||||
End If
|
||||
'Authlib-Injector
|
||||
If McLoginLoader.Output.Type = "Auth" Then
|
||||
Dim Server As String = Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent)
|
||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
||||
DataList.Insert(0, "-javaagent:authlib-injector.jar=" & Server &
|
||||
Dim Server As String = If(McLoginLoader.Input.Type = McLoginType.Legacy,
|
||||
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
||||
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
||||
Try
|
||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
||||
DataList.Insert(0, "-javaagent:""" & PathAppdata & "authlib-injector.jar""=" & Server &
|
||||
" -Dauthlibinjector.side=client" &
|
||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||
Catch ex As Exception
|
||||
Throw New Exception("无法连接到第三方登录服务器(" & If(Server, Nothing) & ")", ex)
|
||||
End Try
|
||||
End If
|
||||
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
Dim WrapperPath As String = PathAppdata & "JavaWrapper.jar"
|
||||
If Not File.Exists(WrapperPath) Then
|
||||
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
||||
McLaunchLog("已自动释放 Java Wrapper")
|
||||
End If
|
||||
DataList.Add("-jar """ & WrapperPath & """")
|
||||
If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
DataList.Insert(0, "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
|
||||
DataList.Add("-jar """ & ExtractJavaWrapper() & """")
|
||||
|
||||
'添加 MainClass
|
||||
If Version.JsonObject("mainClass") Is Nothing Then
|
||||
@@ -1222,21 +1404,28 @@ NextVersion:
|
||||
|
||||
'统一通行证
|
||||
If McLoginLoader.Output.Type = "Nide" Then
|
||||
DataList.Insert(0, "-javaagent:nide8auth.jar=" & Setup.Get("VersionServerNide", Version:=McVersionCurrent))
|
||||
DataList.Insert(0, "-javaagent:""" & PathAppdata & "nide8auth.jar""=" & Setup.Get("VersionServerNide", Version:=McVersionCurrent))
|
||||
End If
|
||||
'Authlib-Injector
|
||||
If McLoginLoader.Output.Type = "Auth" Then
|
||||
Dim Server As String = Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent)
|
||||
Dim Server As String = If(McLoginLoader.Input.Type = McLoginType.Legacy,
|
||||
"http://hiperauth.tech/api/yggdrasil-hiper/", 'HiPer 登录
|
||||
Setup.Get("VersionServerAuthServer", Version:=McVersionCurrent))
|
||||
Try
|
||||
Dim Response As String = NetGetCodeByRequestRetry(Server, Encoding.UTF8)
|
||||
DataList.Insert(0, "-javaagent:authlib-injector.jar=" & Server &
|
||||
DataList.Insert(0, "-javaagent:""" & PathAppdata & "authlib-injector.jar""=" & Server &
|
||||
" -Dauthlibinjector.side=client" &
|
||||
" -Dauthlibinjector.yggdrasil.prefetched=" & Convert.ToBase64String(Encoding.UTF8.GetBytes(Response)))
|
||||
Catch ex As Exception
|
||||
Throw New Exception("无法连接到第三方登录服务器(" & If(Server, Nothing) & ")")
|
||||
Throw New Exception("无法连接到第三方登录服务器(" & If(Server, Nothing) & ")", ex)
|
||||
End Try
|
||||
End If
|
||||
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
DataList.Insert(0, "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
|
||||
DataList.Add("-jar """ & ExtractJavaWrapper() & """")
|
||||
|
||||
'将 "-XXX" 与后面 "XXX" 合并到一起
|
||||
'如果不合并,会导致 Forge 1.17 启动无效,它有两个 --add-exports,进一步导致其中一个在后面被去重
|
||||
Dim DeDuplicateDataList As New List(Of String)
|
||||
@@ -1258,14 +1447,6 @@ NextVersion:
|
||||
'去重
|
||||
Dim Result As String = Join(ArrayNoDouble(DeDuplicateDataList), " ")
|
||||
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
Dim WrapperPath As String = PathAppdata & "JavaWrapper.jar"
|
||||
If Not File.Exists(WrapperPath) Then
|
||||
WriteFile(WrapperPath, GetResources("JavaWrapper"))
|
||||
McLaunchLog("已自动释放 Java Wrapper")
|
||||
End If
|
||||
Result += " -jar """ & WrapperPath & """"
|
||||
|
||||
'添加 MainClass
|
||||
If Version.JsonObject("mainClass") Is Nothing Then
|
||||
Throw New Exception("版本 Json 中没有 mainClass 项!")
|
||||
@@ -1285,9 +1466,6 @@ NextVersion:
|
||||
If Not BasicString.Contains("--height") Then BasicString += " --height ${resolution_height} --width ${resolution_width}"
|
||||
DataList.Add(BasicString)
|
||||
|
||||
'添加 Wrapper 导出参数
|
||||
DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
|
||||
Dim Result As String = Join(DataList, " ")
|
||||
|
||||
'特别改变 OptiFineTweaker
|
||||
@@ -1341,9 +1519,6 @@ NextVersion:
|
||||
GoTo NextVersion
|
||||
End If
|
||||
|
||||
'添加 Wrapper 导出参数
|
||||
DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
|
||||
|
||||
'将 "-XXX" 与后面 "XXX" 合并到一起
|
||||
'如果不进行合并 Impact 会启动无效,它有两个 --tweakclass
|
||||
Dim DeDuplicateDataList As New List(Of String)
|
||||
@@ -1415,7 +1590,7 @@ NextVersion:
|
||||
GameArguments.Add("${assets_index_name}", McAssetsGetIndexName(Version))
|
||||
|
||||
'支持库参数
|
||||
Dim LibList As List(Of McLibToken) = McLibListGet(Version, Not (Version.Version.HasForge AndAlso Version.Version.McCodeMain >= 17))
|
||||
Dim LibList As List(Of McLibToken) = McLibListGet(Version, True)
|
||||
Loader.Output = LibList
|
||||
Dim CpStrings As New List(Of String)
|
||||
Dim OptiFineCp As String = Nothing
|
||||
@@ -1472,7 +1647,7 @@ NextVersion:
|
||||
File.Delete(FilePath)
|
||||
Catch ex As UnauthorizedAccessException
|
||||
McLaunchLog("删除原 dll 访问被拒绝,这通常代表有一个 MC 正在运行,跳过解压:" & FilePath)
|
||||
McLaunchLog("实际的错误信息:" & GetString(ex))
|
||||
McLaunchLog("实际的错误信息:" & GetExceptionSummary(ex))
|
||||
Exit For
|
||||
End Try
|
||||
End If
|
||||
@@ -1492,7 +1667,7 @@ NextVersion:
|
||||
File.Delete(FileName)
|
||||
Catch ex As UnauthorizedAccessException
|
||||
McLaunchLog("删除多余文件访问被拒绝,跳过删除步骤")
|
||||
McLaunchLog("实际的错误信息:" & GetString(ex))
|
||||
McLaunchLog("实际的错误信息:" & GetExceptionSummary(ex))
|
||||
Exit Sub
|
||||
End Try
|
||||
Next
|
||||
@@ -1534,7 +1709,7 @@ NextVersion:
|
||||
'更新文件
|
||||
Dim Profiles As JObject = GetJson(ReadFile(PathMcFolder & "launcher_profiles.json"))
|
||||
Profiles.Merge(ReplaceJson)
|
||||
WriteFile(PathMcFolder & "launcher_profiles.json", Profiles.ToString, Encoding:=Encoding.Default)
|
||||
WriteFile(PathMcFolder & "launcher_profiles.json", Profiles.ToString, Encoding:=Encoding.GetEncoding("GB18030"))
|
||||
McLaunchLog("已更新 launcher_profiles.json")
|
||||
Catch ex As Exception
|
||||
Log(ex, "更新 launcher_profiles.json 失败,将在删除文件后重试")
|
||||
@@ -1565,7 +1740,7 @@ NextVersion:
|
||||
'更新文件
|
||||
Dim Profiles As JObject = GetJson(ReadFile(PathMcFolder & "launcher_profiles.json"))
|
||||
Profiles.Merge(ReplaceJson)
|
||||
WriteFile(PathMcFolder & "launcher_profiles.json", Profiles.ToString, Encoding:=Encoding.Default)
|
||||
WriteFile(PathMcFolder & "launcher_profiles.json", Profiles.ToString, Encoding:=Encoding.GetEncoding("GB18030"))
|
||||
McLaunchLog("已在删除后更新 launcher_profiles.json")
|
||||
Catch exx As Exception
|
||||
Log(exx, "更新 launcher_profiles.json 失败", LogLevel.Feedback)
|
||||
@@ -1619,7 +1794,7 @@ NextVersion:
|
||||
Directory.CreateDirectory(McVersionCurrent.PathIndie & "resourcepacks\")
|
||||
Dim ZipFileAddress As String = McVersionCurrent.PathIndie & "resourcepacks\PCL2 Skin.zip"
|
||||
Dim NewTypeSetup As Boolean = McVersionCurrent.Version.McCodeMain >= 13 OrElse McVersionCurrent.Version.McCodeMain < 6
|
||||
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Setup.Get("LaunchSkinType") = 4 AndAlso File.Exists(PathTemp & "CustomSkin.png") Then
|
||||
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Setup.Get("LaunchSkinType") = 4 AndAlso File.Exists(PathAppdata & "CustomSkin.png") Then
|
||||
Directory.CreateDirectory(PathTemp)
|
||||
Dim MetaFileAddress As String = PathTemp & "pack.mcmeta"
|
||||
Dim PackPicAddress As String = PathTemp & "pack.png"
|
||||
@@ -1659,7 +1834,7 @@ NextVersion:
|
||||
Dim Bit As New MyBitmap(PathImage & "Heads/Logo.png")
|
||||
Bit.Save(PackPicAddress)
|
||||
WriteFile(MetaFileAddress, "{""pack"":{""pack_format"":" & PackFormat & ",""description"":""PCL2 自定义离线皮肤资源包""}}")
|
||||
Dim Skin As New MyBitmap(PathTemp & "CustomSkin.png")
|
||||
Dim Skin As New MyBitmap(PathAppdata & "CustomSkin.png")
|
||||
If (McVersionCurrent.Version.McCodeMain = 6 OrElse McVersionCurrent.Version.McCodeMain = 7) AndAlso Skin.Pic.Height = 64 Then
|
||||
McLaunchLog("该 Minecraft 版本不支持双层皮肤,已进行裁剪")
|
||||
Skin = Skin.Clip(New System.Drawing.Rectangle(0, 0, 64, 32))
|
||||
@@ -1725,6 +1900,30 @@ IgnoreCustomSkin:
|
||||
End Sub
|
||||
Private Sub McLaunchRun(Loader As LoaderTask(Of Integer, Process))
|
||||
|
||||
'输出 bat
|
||||
Try
|
||||
Dim CmdString As String =
|
||||
"@echo off" & vbCrLf &
|
||||
"title 启动 - " & McVersionCurrent.Name & vbCrLf &
|
||||
"echo 游戏正在启动,请稍候。" & vbCrLf &
|
||||
"set APPDATA=""" & PathMcFolder & """" & vbCrLf &
|
||||
"cd /D """ & PathMcFolder & """" & vbCrLf &
|
||||
"""" & McLaunchJavaSelected.PathJava & """ " & McLaunchArgument & vbCrLf &
|
||||
"echo 游戏已退出。" & vbCrLf &
|
||||
"pause"
|
||||
WriteFile(If(McLaunchLoader.Input.SaveBatch, Path & "PCL\LatestLaunch.bat"), CmdString, Encoding:=Encoding.GetEncoding("GB18030"))
|
||||
If McLaunchLoader.Input.SaveBatch IsNot Nothing Then
|
||||
McLaunchLog("导出启动脚本完成,强制结束启动过程")
|
||||
AbortHint = "导出启动脚本成功!"
|
||||
OpenExplorer("/select,""" & McLaunchLoader.Input.SaveBatch & """")
|
||||
Loader.Parent.Abort()
|
||||
Exit Sub '导出脚本完成
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "输出启动脚本失败")
|
||||
If McLaunchLoader.Input.SaveBatch IsNot Nothing Then Throw ex '直接触发启动失败
|
||||
End Try
|
||||
|
||||
'启动信息
|
||||
Dim GameProcess = New Process()
|
||||
Dim StartInfo As New ProcessStartInfo(McLaunchJavaSelected.PathJavaw)
|
||||
@@ -1754,22 +1953,6 @@ IgnoreCustomSkin:
|
||||
Loader.Output = GameProcess
|
||||
McLaunchProcess = GameProcess
|
||||
|
||||
'输出 bat
|
||||
Try
|
||||
Dim CmdString As String =
|
||||
"@echo off" & vbCrLf &
|
||||
"title 启动 - " & McVersionCurrent.Name & vbCrLf &
|
||||
"echo 游戏正在启动,请稍候。" & vbCrLf &
|
||||
"set APPDATA=""" & PathMcFolder & """" & vbCrLf &
|
||||
"cd /D """ & PathMcFolder & """" & vbCrLf &
|
||||
"""" & McLaunchJavaSelected.PathJava & """ " & McLaunchArgument & vbCrLf &
|
||||
"echo 游戏已退出。" & vbCrLf &
|
||||
"pause"
|
||||
WriteFile(Path & "PCL\LatestLaunch.bat", CmdString, Encoding:=Encoding.Default)
|
||||
Catch ex As Exception
|
||||
Log(ex, "输出启动脚本失败")
|
||||
End Try
|
||||
|
||||
'进程优先级处理
|
||||
Try
|
||||
If GameProcess.HasExited Then Exit Try '可能在启动游戏进程的同时刚好取消了启动
|
||||
|
||||
@@ -404,7 +404,6 @@ Wait:
|
||||
Log(ex, "遍历查找 Java 时出错(" & OriginalPath.FullName & ")")
|
||||
End Try
|
||||
End Sub
|
||||
Public PathAppdata As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\PCL\"
|
||||
|
||||
'获取
|
||||
|
||||
@@ -459,9 +458,6 @@ RetryGet:
|
||||
GoTo RetryGet
|
||||
End If
|
||||
|
||||
'若依然未找到适合的 Java,直接返回
|
||||
If AllowedJavaList.Count = 0 Then Return Nothing
|
||||
|
||||
'检查用户指定的 Java
|
||||
Dim UserSetup As String = Setup.Get("LaunchArgumentJavaSelect")
|
||||
If RelatedVersion IsNot Nothing Then
|
||||
@@ -485,16 +481,35 @@ RetryGet:
|
||||
End If
|
||||
Next
|
||||
Log("[Java] 发现用户指定的不兼容 Java:" & UserJava.ToString)
|
||||
If MyMsgBox("你在启动设置中指定了使用下列 Java:" & vbCrLf &
|
||||
" - " & UserJava.ToString & vbCrLf &
|
||||
vbCrLf &
|
||||
"该 Java 可能不兼容当前游戏版本,游戏存在崩溃风险。是否要强制使用该 Java?", "Java 兼容性警告", "取消,让 PCL2 自动选择", "继续") = 2 Then
|
||||
'弹窗要求选择
|
||||
Dim Requirement As String = ""
|
||||
If (MinVersion Is Nothing OrElse MinVersion.Minor = 0) AndAlso (MaxVersion IsNot Nothing AndAlso MaxVersion.Minor < 99) Then
|
||||
Requirement = "最高兼容到 Java " & MaxVersion.Minor & If(MaxVersion.MinorRevision < 99, "." & MaxVersion.MinorRevision & "." & MaxVersion.Revision, "")
|
||||
ElseIf (MinVersion IsNot Nothing AndAlso MinVersion.Minor > 0) AndAlso (MaxVersion Is Nothing OrElse MaxVersion.Minor >= 99) Then
|
||||
Requirement = "至少需要 Java " & MinVersion.Minor & If(MinVersion.MinorRevision > 0 OrElse MinVersion.Revision > 0, "." & MinVersion.MinorRevision & "." & MinVersion.Revision, "")
|
||||
ElseIf (MinVersion IsNot Nothing AndAlso MinVersion.Minor > 0) AndAlso (MaxVersion IsNot Nothing AndAlso MaxVersion.Minor < 99) Then
|
||||
Dim Left As String = MinVersion.Minor & If(MinVersion.MinorRevision > 0 OrElse MinVersion.Revision > 0, "." & MinVersion.MinorRevision & "." & MinVersion.Revision, "")
|
||||
Dim Right As String = MaxVersion.Minor & If(MaxVersion.MinorRevision < 99, "." & MaxVersion.MinorRevision & "." & MaxVersion.Revision, "")
|
||||
Requirement = "需要 Java " & If(Left = Right, Left, Left & " ~ " & Right)
|
||||
End If
|
||||
If Setup.Get("LaunchAdvanceJava") Then
|
||||
'直接跳过弹窗
|
||||
Hint("设置中指定了使用 Java " & UserJava.VersionCode & ",但当前版本" & Requirement & ",这可能会导致游戏崩溃!", HintType.Critical)
|
||||
AllowedJavaList = New List(Of JavaEntry) From {UserJava}
|
||||
ElseIf MyMsgBox("你在启动设置中指定了使用 Java " & UserJava.VersionCode & ",但当前版本" & Requirement & "。" & vbCrLf &
|
||||
"如果强制使用该 Java,可能会导致游戏崩溃。" & vbCrLf &
|
||||
vbCrLf &
|
||||
" - 指定的 Java:" & UserJava.ToString,
|
||||
"Java 兼容性警告", "让 PCL2 自动选择", "强制使用该 Java") = 2 Then
|
||||
'强制使用指定的 Java
|
||||
Log("[Java] 已强制使用用户指定的不兼容 Java")
|
||||
AllowedJavaList = New List(Of JavaEntry) From {UserJava}
|
||||
End If
|
||||
End If
|
||||
|
||||
'若依然未找到适合的 Java,直接返回
|
||||
If AllowedJavaList.Count = 0 Then Return Nothing
|
||||
|
||||
'检查特定的 Java
|
||||
For Each Java In AllowedJavaList
|
||||
If TargetJavaList.Contains(Java) Then
|
||||
@@ -582,8 +597,8 @@ UserPass:
|
||||
If Not Left.IsJre AndAlso Right.IsJre Then Return False
|
||||
'4. Java 大版本
|
||||
If Left.VersionCode <> Right.VersionCode Then
|
||||
' Java 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
Dim Weight = {0, 1, 2, 3, 4, 5, 6, 14, 29, 10, 11, 12, 13, 9, 8, 7, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
|
||||
' Java 7 8 9 10 11 12 13 14 15 16 17 18 19 20...
|
||||
Dim Weight = {0, 1, 2, 3, 4, 5, 6, 14, 29, 10, 11, 12, 13, 9, 8, 7, 15, 30, 29, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
|
||||
Return Weight.ElementAtOrDefault(Left.VersionCode) >= Weight.ElementAtOrDefault(Right.VersionCode)
|
||||
End If
|
||||
'5. 最次级版本号更接近 51
|
||||
@@ -592,7 +607,7 @@ UserPass:
|
||||
|
||||
'缺失
|
||||
''' <summary>
|
||||
''' 提示 Java 缺失并跳转下载。支持 Java 7、8、16。
|
||||
''' 提示 Java 缺失并跳转下载。支持 Java 7、8、16、17。
|
||||
''' </summary>
|
||||
Public Sub JavaMissing(VersionCode As Integer)
|
||||
Select Case VersionCode
|
||||
@@ -613,8 +628,8 @@ UserPass:
|
||||
If Is32BitSystem Then
|
||||
MyMsgBox("该版本的 MC 已不支持 32 位操作系统。你必须增加内存并重装为 64 位系统才能继续。", "系统兼容性提示")
|
||||
Else
|
||||
OpenWebsite("https://www.oracle.com/java/technologies/downloads/#jdk17-windows")
|
||||
MyMsgBox("PCL2 未找到 Java " & VersionCode & "。" & vbCrLf &
|
||||
OpenWebsite("https://www.oracle.com/java/technologies/downloads/#java17")
|
||||
MyMsgBox("PCL2 未找到 Java 17。" & vbCrLf &
|
||||
"请在打开的网页中选择 x64 Installer,下载并安装。" & vbCrLf &
|
||||
"安装后在 PCL2 的 设置 → 启动设置 → 游戏 Java 中通过搜索或导入,确保安装的 Java 已列入 Java 列表。",
|
||||
"未找到 Java")
|
||||
@@ -774,7 +789,7 @@ UserPass:
|
||||
""selectedProfile"": ""PCL2"",
|
||||
""clientToken"": ""23323323323323323323323323323333""
|
||||
}"
|
||||
WriteFile(Folder & "launcher_profiles.json", ResultJson, Encoding:=Encoding.Default)
|
||||
WriteFile(Folder & "launcher_profiles.json", ResultJson, Encoding:=Encoding.GetEncoding("GB18030"))
|
||||
Log("[Minecraft] 已创建 launcher_profiles.json:" & Folder)
|
||||
Catch ex As Exception
|
||||
Log(ex, "创建 launcher_profiles.json 失败(" & Folder & ")", LogLevel.Feedback)
|
||||
@@ -837,7 +852,7 @@ UserPass:
|
||||
''' </summary>
|
||||
Public ReadOnly Property PathIndie As String
|
||||
Get
|
||||
Return GetPathIndie(Version.Modable)
|
||||
Return GetPathIndie(Modable)
|
||||
End Get
|
||||
End Property
|
||||
''' <summary>
|
||||
@@ -917,6 +932,15 @@ UserPass:
|
||||
''' </summary>
|
||||
Public DisplayType As McVersionCardType = McVersionCardType.Auto
|
||||
''' <summary>
|
||||
''' 该版本是否可以安装 Mod。
|
||||
''' </summary>
|
||||
Public ReadOnly Property Modable As Boolean
|
||||
Get
|
||||
Return Version.HasFabric OrElse Version.HasForge OrElse Version.HasLiteLoader OrElse
|
||||
DisplayType = McVersionCardType.API '#223
|
||||
End Get
|
||||
End Property
|
||||
''' <summary>
|
||||
''' 版本信息。
|
||||
''' </summary>
|
||||
Public Property Version As McVersionInfo
|
||||
@@ -1009,7 +1033,7 @@ UserPass:
|
||||
_Version.McName = Regex
|
||||
GoTo VersionSearchFinish
|
||||
End If
|
||||
'TODO: [Quilt 支持] 从 Quilt 版本中获取版本号
|
||||
'FUTURE: [Quilt 支持] 从 Quilt 版本中获取版本号
|
||||
'从 jar 项中获取版本号
|
||||
If JsonObject("jar") IsNot Nothing Then
|
||||
_Version.McName = JsonObject("jar").ToString
|
||||
@@ -1247,7 +1271,7 @@ Recheck:
|
||||
'检查文件夹
|
||||
If Not Directory.Exists(Path) Then
|
||||
State = McVersionState.Error
|
||||
Info = "该文件夹不存在"
|
||||
Info = "未找到版本 " & Name
|
||||
Return False
|
||||
End If
|
||||
'检查权限
|
||||
@@ -1283,7 +1307,7 @@ Recheck:
|
||||
Catch ex As Exception
|
||||
Log(ex, "依赖版本检查出错(" & Name & ")")
|
||||
State = McVersionState.Error
|
||||
Info = "未知错误:" & GetString(ex)
|
||||
Info = "未知错误:" & GetExceptionSummary(ex)
|
||||
Return False
|
||||
End Try
|
||||
|
||||
@@ -1295,7 +1319,6 @@ Recheck:
|
||||
''' </summary>
|
||||
Public Function Load() As McVersion
|
||||
Try
|
||||
Directory.CreateDirectory(Path & "PCL")
|
||||
'检查版本,若出错则跳过数据确定阶段
|
||||
If Not Check() Then GoTo ExitDataLoad
|
||||
#Region "确定版本分类"
|
||||
@@ -1324,7 +1347,7 @@ Recheck:
|
||||
Version.HasLiteLoader = True
|
||||
End If
|
||||
'Fabric、Forge
|
||||
'TODO: [Quilt 支持] 确认这里的玩意儿对不对
|
||||
'FUTURE: [Quilt 支持] 确认这里的玩意儿对不对
|
||||
If RealJson.Contains("net.fabricmc:fabric-loader") OrElse RealJson.Contains("org.quiltmc:quilt-loader") Then
|
||||
State = McVersionState.Fabric
|
||||
Version.FabricVersion = If(RegexSeek(RealJson, "(?<=(net.fabricmc:fabric-loader:)|(org.quiltmc:quilt-loader:))[0-9\.]+(\+build.[0-9]+)?"), "未知版本").Replace("+build", "")
|
||||
@@ -1400,9 +1423,11 @@ ExitDataLoad:
|
||||
'确定版本显示种类
|
||||
DisplayType = ReadIni(Path & "PCL\Setup.ini", "DisplayType", McVersionCardType.Auto)
|
||||
'写入缓存
|
||||
WriteIni(Path & "PCL\Setup.ini", "State", State)
|
||||
WriteIni(Path & "PCL\Setup.ini", "Info", Info)
|
||||
WriteIni(Path & "PCL\Setup.ini", "Logo", Logo)
|
||||
If Directory.Exists(Path) Then
|
||||
WriteIni(Path & "PCL\Setup.ini", "State", State)
|
||||
WriteIni(Path & "PCL\Setup.ini", "Info", Info)
|
||||
WriteIni(Path & "PCL\Setup.ini", "Logo", Logo)
|
||||
End If
|
||||
If State <> McVersionState.Error Then
|
||||
WriteIni(Path & "PCL\Setup.ini", "ReleaseTime", ReleaseTime.ToString("yyyy-MM-dd HH:mm:ss"))
|
||||
WriteIni(Path & "PCL\Setup.ini", "VersionFabric", Version.FabricVersion)
|
||||
@@ -1415,7 +1440,7 @@ ExitDataLoad:
|
||||
WriteIni(Path & "PCL\Setup.ini", "VersionOriginalSub", Version.McCodeSub)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Info = "未知错误:" & GetString(ex)
|
||||
Info = "未知错误:" & GetExceptionSummary(ex)
|
||||
Logo = "pack://application:,,,/images/Blocks/RedstoneBlock.png"
|
||||
State = McVersionState.Error
|
||||
Log(ex, "加载版本失败(" & Name & ")", LogLevel.Feedback)
|
||||
@@ -1430,6 +1455,14 @@ ExitDataLoad:
|
||||
Dim version = TryCast(obj, McVersion)
|
||||
Return version IsNot Nothing AndAlso Path = version.Path
|
||||
End Function
|
||||
Public Shared Operator =(a As McVersion, b As McVersion) As Boolean
|
||||
If a Is Nothing AndAlso b Is Nothing Then Return True
|
||||
If a Is Nothing OrElse b Is Nothing Then Return False
|
||||
Return a.Path = b.Path
|
||||
End Operator
|
||||
Public Shared Operator <>(a As McVersion, b As McVersion) As Boolean
|
||||
Return Not (a = b)
|
||||
End Operator
|
||||
|
||||
End Class
|
||||
Public Enum McVersionState
|
||||
@@ -1511,15 +1544,6 @@ ExitDataLoad:
|
||||
|
||||
'API
|
||||
|
||||
''' <summary>
|
||||
''' 该版本是否可以安装 Mod。
|
||||
''' </summary>
|
||||
Public ReadOnly Property Modable As Boolean
|
||||
Get
|
||||
Return HasFabric OrElse HasForge OrElse HasLiteLoader
|
||||
End Get
|
||||
End Property
|
||||
|
||||
''' <summary>
|
||||
''' 生成对此版本信息的用户友好的描述性字符串。
|
||||
''' </summary>
|
||||
@@ -2312,13 +2336,16 @@ NextVersion:
|
||||
Dim RealVersion As McVersion
|
||||
Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
|
||||
If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
|
||||
'HMCL 项直接使用自身的 Jar
|
||||
'根据 Inherit 获取最深层版本
|
||||
'此外,HMCL 项直接使用自身的 Jar
|
||||
Dim OriginalVersion As McVersion = Version
|
||||
Do Until OriginalVersion.InheritVersion = ""
|
||||
If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
|
||||
OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
|
||||
Loop
|
||||
'1.17+ 的 Forge 不寻找 Inherit
|
||||
If Not (Version.Version.HasForge AndAlso Version.Version.McCodeMain >= 17) Then
|
||||
Do Until OriginalVersion.InheritVersion = ""
|
||||
If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
|
||||
OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
|
||||
Loop
|
||||
End If
|
||||
'需要新建对象,否则后面的 Check 会导致 McVersionCurrent 的 State 变回 Original
|
||||
'复现:启动一个 Snapshot 版本
|
||||
RealVersion = New McVersion(OriginalVersion.Path)
|
||||
@@ -2365,6 +2392,11 @@ NextVersion:
|
||||
'转换为 LibToken
|
||||
For Each Library As JObject In AllLibs.Children
|
||||
|
||||
'清理 null 项(BakaXL 会把没有的项序列化为 null,但会被 Newtonsoft 转换为 JValue,导致 Is Nothing = false;这导致了 #409)
|
||||
For i = Library.Properties.Count - 1 To 0 Step -1
|
||||
If Library.Properties(i).Value.Type = JTokenType.Null Then Library.Remove(Library.Properties(i).Name)
|
||||
Next
|
||||
|
||||
'检查是否需要(Rules)
|
||||
If Not McJsonRuleCheck(Library("rules")) Then Continue For
|
||||
|
||||
@@ -2487,33 +2519,36 @@ NextVersion:
|
||||
|
||||
'统一通行证文件
|
||||
If Setup.Get("VersionServerLogin", Version:=Version) = 3 Then
|
||||
Dim TargetFile = Version.PathIndie & "nide8auth.jar"
|
||||
Dim TargetFile = PathAppdata & "nide8auth.jar"
|
||||
Dim Checker As New FileChecker(MinSize:=173000)
|
||||
If (IsSetupSkip AndAlso File.Exists(TargetFile)) OrElse Checker.Check(TargetFile) IsNot Nothing Then
|
||||
Result.Add(New NetFile({"https://login.mc-user.com:233/index/jar"}, TargetFile, Checker))
|
||||
End If
|
||||
End If
|
||||
'Authlib-Injector 文件
|
||||
If Setup.Get("VersionServerLogin", Version:=Version) = 4 Then
|
||||
Dim TargetFile = Version.PathIndie & "authlib-injector.jar"
|
||||
Dim DownloadInfo As JObject = Nothing
|
||||
'获取下载信息
|
||||
Try
|
||||
Log("[Minecraft] 开始获取 Authlib-Injector 下载信息")
|
||||
DownloadInfo = GetJson(NetGetCodeByDownload({"https://download.mcbbs.net/mirrors/authlib-injector/artifact/latest.json", "https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json"}, IsJson:=True))
|
||||
Catch ex As Exception
|
||||
Log("获取 Authlib-Injector 下载信息失败", LogLevel.Hint)
|
||||
End Try
|
||||
'校验文件
|
||||
If DownloadInfo IsNot Nothing Then
|
||||
Dim Checker As New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)
|
||||
If (IsSetupSkip AndAlso File.Exists(TargetFile)) OrElse Checker.Check(TargetFile) IsNot Nothing Then
|
||||
'开始下载
|
||||
Dim DownloadAddress As String = DownloadInfo("download_url")
|
||||
Log("[Minecraft] Authlib-Injector 需要更新:" & DownloadAddress)
|
||||
Result.Add(New NetFile({
|
||||
DownloadAddress.Replace("bmclapi2.bangbang93.com", "download.mcbbs.net"), DownloadAddress
|
||||
}, TargetFile, New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)))
|
||||
If Setup.Get("VersionServerLogin", Version:=Version) = 4 OrElse
|
||||
(PageLinkHiper.HiperState = LoadState.Finished AndAlso Setup.Get("LoginType") = McLoginType.Legacy) Then 'HiPer 登录转接
|
||||
Dim TargetFile = PathAppdata & "authlib-injector.jar"
|
||||
If Not (IsSetupSkip AndAlso File.Exists(TargetFile)) Then
|
||||
Dim DownloadInfo As JObject = Nothing
|
||||
'获取下载信息
|
||||
Try
|
||||
Log("[Minecraft] 开始获取 Authlib-Injector 下载信息")
|
||||
DownloadInfo = GetJson(NetGetCodeByDownload({"https://download.mcbbs.net/mirrors/authlib-injector/artifact/latest.json", "https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json"}, IsJson:=True))
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取 Authlib-Injector 下载信息失败")
|
||||
End Try
|
||||
'校验文件
|
||||
If DownloadInfo IsNot Nothing Then
|
||||
Dim Checker As New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)
|
||||
If (IsSetupSkip AndAlso File.Exists(TargetFile)) OrElse Checker.Check(TargetFile) IsNot Nothing Then
|
||||
'开始下载
|
||||
Dim DownloadAddress As String = DownloadInfo("download_url")
|
||||
Log("[Minecraft] Authlib-Injector 需要更新:" & DownloadAddress)
|
||||
Result.Add(New NetFile({
|
||||
DownloadAddress.Replace("bmclapi2.bangbang93.com", "download.mcbbs.net"), DownloadAddress
|
||||
}, TargetFile, New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)))
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
@@ -3635,7 +3670,7 @@ VersionFindFail:
|
||||
End If
|
||||
Next
|
||||
Catch ex As Exception
|
||||
Result.Add("检查 Mod 时出错:" & GetString(ex) & vbCrLf & " - " & ModEntity.FileName)
|
||||
Result.Add("检查 Mod 时出错:" & GetExceptionSummary(ex) & vbCrLf & " - " & ModEntity.FileName)
|
||||
Log(ex, "检查 Mod 时出错")
|
||||
End Try
|
||||
Next
|
||||
@@ -3711,8 +3746,8 @@ VersionFindFail:
|
||||
If Left = "未知版本" AndAlso Right = "未知版本" Then Return 0
|
||||
If Left <> "未知版本" AndAlso Right = "未知版本" Then Return -1
|
||||
End If
|
||||
Dim Lefts = RegexSearch(Left.ToLower, "[a-z]+|[0-9]+")
|
||||
Dim Rights = RegexSearch(Right.ToLower, "[a-z]+|[0-9]+")
|
||||
Dim Lefts = RegexSearch(Left.ToLower.Replace("快照", "snapshot"), "[a-z]+|[0-9]+")
|
||||
Dim Rights = RegexSearch(Right.ToLower.Replace("快照", "snapshot"), "[a-z]+|[0-9]+")
|
||||
Dim i As Integer = 0
|
||||
While True
|
||||
'两边均缺失,感觉是一个东西
|
||||
@@ -3805,7 +3840,11 @@ NextEntry:
|
||||
Else
|
||||
Select Case McLoginLoader.Input.Type
|
||||
Case McLoginType.Legacy
|
||||
Raw = Raw.Replace("{login}", "离线")
|
||||
If PageLinkHiper.HiperState = LoadState.Finished Then
|
||||
Raw = Raw.Replace("{login}", "联机离线")
|
||||
Else
|
||||
Raw = Raw.Replace("{login}", "离线")
|
||||
End If
|
||||
Case McLoginType.Mojang
|
||||
Raw = Raw.Replace("{login}", "Mojang 正版")
|
||||
Case McLoginType.Ms
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
''' <summary>
|
||||
''' 安装一个给定的整合包文件,返回是否安装成功。必须在工作线程执行。
|
||||
''' </summary>
|
||||
Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional ShowHint As Boolean = True) As Boolean
|
||||
Public Function ModpackInstall(File As String, Optional VersionName As String = Nothing, Optional ShowHint As Boolean = True, Optional Logo As String = Nothing) As Boolean
|
||||
Log("[ModPack] 整合包安装请求:" & If(File, "null"))
|
||||
Dim Archive As Compression.ZipArchive = Nothing
|
||||
Dim ArchiveBaseFolder As String = ""
|
||||
@@ -54,7 +54,7 @@
|
||||
If FullNames(1) = "mmc-pack.json" Then PackType = 2 : Exit Try 'MMC 整合包
|
||||
Next
|
||||
Catch ex As Exception
|
||||
If GetString(ex, False, True).Contains("Error.WinIOError") Then
|
||||
If GetExceptionDetail(ex, True).Contains("Error.WinIOError") Then
|
||||
Log(ex, "打开整合包文件失败", If(ShowHint, LogLevel.Hint, LogLevel.Normal))
|
||||
Return False
|
||||
ElseIf File.ToLower.EndsWith(".rar") Then
|
||||
@@ -69,7 +69,7 @@
|
||||
Select Case PackType
|
||||
Case 0
|
||||
Log("[ModPack] 整合包种类:CurseForge")
|
||||
InstallPackCurseForge(File, Archive, ArchiveBaseFolder, VersionName)
|
||||
InstallPackCurseForge(File, Archive, ArchiveBaseFolder, VersionName, Logo)
|
||||
Case 1
|
||||
Log("[ModPack] 整合包种类:HMCL")
|
||||
InstallPackHMCL(File, Archive, ArchiveBaseFolder)
|
||||
@@ -126,7 +126,7 @@
|
||||
End If
|
||||
'解压文件
|
||||
Dim RetryCount As Integer = 1
|
||||
Dim Encode = Encoding.Default
|
||||
Dim Encode = Encoding.GetEncoding("GB18030")
|
||||
Try
|
||||
Retry:
|
||||
'完全不知道为啥会出现文件正在被另一进程使用的问题,总之多试试
|
||||
@@ -156,7 +156,7 @@ Retry:
|
||||
''' 获取安装 CurseForge 整合包的加载器,若失败或跳过则返回 Nothing。
|
||||
''' 加载器以安装目标版本文件夹为输入。
|
||||
''' </summary>
|
||||
Private Function InstallPackCurseForgeLoader(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, VersionName As String) As LoaderCombo(Of String)
|
||||
Private Function InstallPackCurseForgeLoader(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, VersionName As String, Optional Logo As String = Nothing) As LoaderCombo(Of String)
|
||||
'读取 Json 文件
|
||||
Dim Json As JObject
|
||||
Try
|
||||
@@ -241,8 +241,12 @@ Retry:
|
||||
For Each ModJson In Task.Input
|
||||
'跳过重复的 Mod(疑似 CurseForge Bug)
|
||||
If FileList.ContainsKey(ModJson("id").ToObject(Of Integer)) Then Continue For
|
||||
'根据 modules 判断是资源包还是 Mod
|
||||
Dim ModuleNames = CType(ModJson("modules"), JArray).Select(Function(l) l("name").ToString).ToList
|
||||
Dim IsResourcePack As Boolean = Not ModuleNames.Contains("META-INF") AndAlso ModuleNames.Contains("pack.mcmeta")
|
||||
'实际的添加
|
||||
FileList.Add(ModJson("id"), New DlCfFile(ModJson, False).GetDownloadFile(PathMcFolder & "versions\" & VersionName & "\mods\", False))
|
||||
FileList.Add(ModJson("id"), New DlCfFile(ModJson, False).GetDownloadFile(
|
||||
PathMcFolder & "versions\" & VersionName & "\" & If(IsResourcePack, "resourcepacks", "mods") & "\", False))
|
||||
Task.Progress += 1 / (1 + ModFileList.Count)
|
||||
Next
|
||||
Task.Output = FileList.Values.ToList
|
||||
@@ -276,6 +280,23 @@ Retry:
|
||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallExpectTime})
|
||||
Loaders.Add(New LoaderCombo(Of String)("游戏安装", MergeLoaders) With {.Show = False, .ProgressWeight = MergeExpectTime})
|
||||
Loaders.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
|
||||
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
||||
Sub(Task As LoaderTask(Of String, String))
|
||||
'设置图标
|
||||
Dim VersionFolder As String = PathMcFolder & "versions\" & VersionName & "\"
|
||||
If Logo IsNot Nothing AndAlso File.Exists(Logo) Then
|
||||
File.Copy(Logo, VersionFolder & "PCL\Logo.png", True)
|
||||
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
||||
WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
|
||||
Log("[Download] 已设置整合包 Logo:" & Logo)
|
||||
End If
|
||||
'删除原始整合包文件
|
||||
Dim Target As String = VersionFolder & "原始整合包.zip"
|
||||
If Not Setup.Get("ToolDownloadKeepModpack") AndAlso File.Exists(Target) Then
|
||||
Log("[Download] 根据设置要求删除原始整合包文件:" & Target)
|
||||
File.Delete(Target)
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
||||
|
||||
'重复任务检查
|
||||
Dim LoaderName As String = "CurseForge 整合包安装:" & VersionName & " "
|
||||
@@ -292,7 +313,7 @@ Retry:
|
||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||
Return Loader
|
||||
End Function
|
||||
Private Sub InstallPackCurseForge(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing)
|
||||
Private Sub InstallPackCurseForge(FileAddress As String, Archive As Compression.ZipArchive, ArchiveBaseFolder As String, Optional VersionName As String = Nothing, Optional Logo As String = Nothing)
|
||||
|
||||
'获取版本名
|
||||
Dim ShowRibble As Boolean = VersionName Is Nothing
|
||||
@@ -314,7 +335,7 @@ Retry:
|
||||
End If
|
||||
|
||||
'启动加载器
|
||||
Dim Loader = InstallPackCurseForgeLoader(FileAddress, Archive, ArchiveBaseFolder, VersionName)
|
||||
Dim Loader = InstallPackCurseForgeLoader(FileAddress, Archive, ArchiveBaseFolder, VersionName, Logo)
|
||||
If Loader Is Nothing Then Exit Sub
|
||||
Loader.Start(PathMcFolder & "versions\" & VersionName & "\")
|
||||
LoaderTaskbarAdd(Loader)
|
||||
|
||||
@@ -94,7 +94,6 @@
|
||||
Do Until State = MinecraftState.Ended OrElse State = MinecraftState.Crashed OrElse Loader.State = LoadState.Aborted
|
||||
TimerWindow()
|
||||
TimerLog()
|
||||
If State = MinecraftState.Loading Then ProgressUpdate()
|
||||
'设置窗口标题
|
||||
For i = 1 To 3
|
||||
If IsWindowFinished AndAlso WindowTitle <> "" AndAlso State = MinecraftState.Running AndAlso Not GameProcess.HasExited Then
|
||||
@@ -151,6 +150,7 @@
|
||||
For Each Str As String In Copyed
|
||||
GameLog(Str)
|
||||
Next
|
||||
If State = MinecraftState.Loading Then ProgressUpdate()
|
||||
'游戏退出检查
|
||||
If GameProcess.HasExited Then
|
||||
WatcherLog("Minecraft 已退出,返回值:" & GameProcess.ExitCode)
|
||||
@@ -167,7 +167,7 @@
|
||||
'返回值不为 0 且未结束
|
||||
WatcherLog("Minecraft 返回值异常,可能已崩溃")
|
||||
Crashed()
|
||||
Else
|
||||
ElseIf State <> MinecraftState.Crashed Then
|
||||
'正常关闭
|
||||
State = MinecraftState.Ended
|
||||
End If
|
||||
@@ -268,8 +268,18 @@
|
||||
WatcherLog("Minecraft 窗口已加载:" & WindowHandle.ToInt64)
|
||||
IsWindowFinished = True
|
||||
'最大化
|
||||
Thread.Sleep(3000) '1.7.10 LiteLoader 不延迟会显示错误
|
||||
If Setup.Get("LaunchArgumentWindowType") = 4 Then ShowWindow(WindowHandle, 3)
|
||||
If Setup.Get("LaunchArgumentWindowType") = 4 Then
|
||||
RunInNewThread(Sub()
|
||||
Try
|
||||
'如果最大化导致屏幕渲染大小不对,那是 MC 的 Bug,不是我的 Bug
|
||||
'……虽然我很想这样说,但总有人反馈,算了
|
||||
Thread.Sleep(1000)
|
||||
ShowWindow(WindowHandle, 3)
|
||||
Catch ex As Exception
|
||||
Log(ex, "最大化 Minecraft 窗口时出现错误")
|
||||
End Try
|
||||
End Sub, "MinecraftWindowMaximize")
|
||||
End If
|
||||
ElseIf Not IsWindowAppeared Then
|
||||
'已找到 FML 窗口
|
||||
WatcherLog("FML 窗口已加载:" & MinecraftWindows.Keys(0).ToInt64)
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
'执行
|
||||
If Type = "打开文件" Then
|
||||
Dim Info As New ProcessStartInfo With {
|
||||
.Arguments = If(Data.Length >= 2, Data(1), ""),
|
||||
.FileName = Location,
|
||||
.WorkingDirectory = WorkingDir
|
||||
}
|
||||
.Arguments = If(Data.Length >= 2, Data(1), ""),
|
||||
.FileName = Location,
|
||||
.WorkingDirectory = WorkingDir
|
||||
}
|
||||
Process.Start(Info)
|
||||
Else '打开帮助
|
||||
PageOtherHelp.EnterHelpPage(Location)
|
||||
@@ -45,28 +45,9 @@
|
||||
End Try
|
||||
End Sub)
|
||||
Case "启动游戏"
|
||||
|
||||
'初始化与前置条件检测
|
||||
If Not (FrmLaunchLeft.BtnLaunch.IsEnabled AndAlso FrmLaunchLeft.BtnLaunch.Visibility = Visibility.Visible AndAlso FrmLaunchLeft.BtnLaunch.IsHitTestVisible) Then
|
||||
Hint("已有游戏正在启动中!", HintType.Critical) : Exit Sub
|
||||
If McLaunchStart(New McLaunchOptions With {.ServerIp = If(Data.Length >= 2, Data(1), Nothing), .Version = New McVersion(Data(0))}) Then
|
||||
Hint("正在启动 " & Data(0) & "……")
|
||||
End If
|
||||
If Not Directory.Exists(PathMcFolder & "versions\" & Data(0)) Then
|
||||
Hint("未在当前 Minecraft 文件夹找到版本 " & Data(0) & "!", HintType.Critical) : Exit Sub
|
||||
End If
|
||||
Dim ButtonVersion As New McVersion(Data(0))
|
||||
ButtonVersion.Load()
|
||||
If ButtonVersion.State = McVersionState.Error Then
|
||||
Hint("无法启动 " & Data(0) & ":" & ButtonVersion.Info, HintType.Critical) : Exit Sub
|
||||
End If
|
||||
|
||||
'实际启动
|
||||
McVersionCurrent = ButtonVersion
|
||||
Setup.Set("LaunchVersionSelect", McVersionCurrent.Name)
|
||||
FrmLaunchLeft.PageLaunchLeft_Loaded()
|
||||
FrmLaunchLeft.RefreshButtonsUI()
|
||||
FrmMain.AprilGiveup()
|
||||
FrmLaunchLeft.LaunchButtonClick(If(Data.Length >= 2, Data(1), ""))
|
||||
FrmMain.PageChange(FormMain.PageType.Launch)
|
||||
|
||||
Case "复制文本"
|
||||
ClipboardSet(Join(Data, "|"))
|
||||
|
||||
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
|
||||
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||
' 方法是按如下所示使用“*”
|
||||
|
||||
<Assembly: AssemblyVersion("2.3.4.0")>
|
||||
<Assembly: AssemblyFileVersion("2.3.4.0")>
|
||||
<Assembly: AssemblyVersion("2.4.4.0")>
|
||||
<Assembly: AssemblyFileVersion("2.4.4.0")>
|
||||
<Assembly: NeutralResourcesLanguage("")>
|
||||
@@ -140,16 +140,6 @@ Namespace My.Resources
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' 查找 System.Byte[] 类型的本地化资源。
|
||||
'''</summary>
|
||||
Friend ReadOnly Property STUN() As Byte()
|
||||
Get
|
||||
Dim obj As Object = ResourceManager.GetObject("STUN", resourceCulture)
|
||||
Return CType(obj,Byte())
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' 查找 System.Byte[] 类型的本地化资源。
|
||||
'''</summary>
|
||||
|
||||
@@ -137,14 +137,11 @@
|
||||
<value>..\Resources\Newtonsoft.Json.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="ModData" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ModData.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>..\Resources\ModData.txt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="NAudio" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\NAudio.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="STUN" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\STUN.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="Transformer" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\transformer.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
Public Module ModDownloadLib
|
||||
|
||||
''' <summary>
|
||||
''' 如果 OptiFine 与 Forge 同时开始安装,就会导致 Forge 安装失败,所以在这里添加一个锁。
|
||||
''' </summary>
|
||||
Private InstallSyncLock As New Object
|
||||
''' <summary>
|
||||
''' 最高的 Minecraft 大版本号,-1 代表尚未获取。
|
||||
''' </summary>
|
||||
Public McVersionHighest As Integer = -1
|
||||
|
||||
#Region "Minecraft 下载"
|
||||
|
||||
''' <summary>
|
||||
@@ -112,7 +121,7 @@ Public Module ModDownloadLib
|
||||
Task.Output = New List(Of NetFile) From {New NetFile(DlSourceLauncherOrMetaGet(JsonAddress), VersionFolder & VersionName & ".json")}
|
||||
End Sub) With {.ProgressWeight = 2, .Show = False})
|
||||
End If
|
||||
Loaders.Add(New LoaderDownload("下载原版 Json 文件", New List(Of NetFile) From {
|
||||
Loaders.Add(New LoaderDownload(McDownloadClientJsonName, New List(Of NetFile) From {
|
||||
New NetFile(DlSourceLauncherOrMetaGet(If(JsonUrl, "")), VersionFolder & VersionName & ".json", New FileChecker(CanUseExistsFile:=False, IsJson:=True))
|
||||
}) With {.ProgressWeight = 3})
|
||||
|
||||
@@ -157,6 +166,7 @@ Public Module ModDownloadLib
|
||||
|
||||
End Function
|
||||
Private Const McDownloadClientLibName As String = "下载原版支持库文件"
|
||||
Private Const McDownloadClientJsonName As String = "下载原版 Json 文件"
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -178,7 +188,7 @@ Public Module ModDownloadLib
|
||||
'建立控件
|
||||
Dim NewItem As New MyListItem With {.Logo = Logo, .SnapsToDevicePixels = True, .Title = Entry("id").ToString, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Entry, .PaddingRight = 60}
|
||||
If Entry("lore") Is Nothing Then
|
||||
NewItem.Info = Entry("releaseTime").Value(Of Date).ToString("yyyy/MM/dd")
|
||||
NewItem.Info = Entry("releaseTime").Value(Of Date).ToString("yyyy/MM/dd HH:mm")
|
||||
Else
|
||||
NewItem.Info = Entry("lore").ToString
|
||||
End If
|
||||
@@ -372,90 +382,95 @@ Public Module ModDownloadLib
|
||||
'选择 Java
|
||||
Dim Java = JavaSelect(New Version(1, 8, 0, 0))
|
||||
If Java Is Nothing Then
|
||||
JavaMissing(8)
|
||||
JavaMissing(17)
|
||||
Throw New Exception("未找到用于安装 OptiFine 的 Java")
|
||||
End If
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer"
|
||||
If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
|
||||
'开始启动
|
||||
Dim Info = New ProcessStartInfo With {
|
||||
.FileName = Java.PathJavaw,
|
||||
.Arguments = "-Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ optifine.Installer",
|
||||
.UseShellExecute = False,
|
||||
.CreateNoWindow = True,
|
||||
.RedirectStandardError = True,
|
||||
.RedirectStandardOutput = True,
|
||||
.WorkingDirectory = BaseMcFolderHome
|
||||
}
|
||||
If Info.EnvironmentVariables.ContainsKey("appdata") Then
|
||||
Info.EnvironmentVariables("appdata") = BaseMcFolderHome
|
||||
Else
|
||||
Info.EnvironmentVariables.Add("appdata", BaseMcFolderHome)
|
||||
End If
|
||||
Log("[Download] 开始安装 OptiFine:" & Target)
|
||||
Dim TotalLength As Integer = 0
|
||||
Dim process As New Process With {.StartInfo = Info}
|
||||
Dim LastResult As String = ""
|
||||
Using outputWaitHandle As New AutoResetEvent(False)
|
||||
Using errorWaitHandle As New AutoResetEvent(False)
|
||||
AddHandler process.OutputDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
outputWaitHandle.[Set]()
|
||||
Else
|
||||
LastResult = e.Data
|
||||
If ModeDebug Then Log("[Installer] " & LastResult)
|
||||
TotalLength += 1
|
||||
Task.Progress += 0.9 / 7000
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 OptiFine 安装器信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 OptiFine 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
AddHandler process.ErrorDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
errorWaitHandle.[Set]()
|
||||
Else
|
||||
LastResult = e.Data
|
||||
If ModeDebug Then Log("[Installer] " & LastResult)
|
||||
TotalLength += 1
|
||||
Task.Progress += 0.9 / 7000
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 OptiFine 安装器错误信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 OptiFine 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
process.Start()
|
||||
process.BeginOutputReadLine()
|
||||
process.BeginErrorReadLine()
|
||||
'等待
|
||||
Do Until process.HasExited
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
'输出
|
||||
outputWaitHandle.WaitOne(10000)
|
||||
errorWaitHandle.WaitOne(10000)
|
||||
process.Dispose()
|
||||
If TotalLength < 1000 Then Throw New Exception("安装器运行出错,末行为 " & LastResult)
|
||||
SyncLock InstallSyncLock
|
||||
Dim Info = New ProcessStartInfo With {
|
||||
.FileName = Java.PathJavaw,
|
||||
.Arguments = Arguments,
|
||||
.UseShellExecute = False,
|
||||
.CreateNoWindow = True,
|
||||
.RedirectStandardError = True,
|
||||
.RedirectStandardOutput = True,
|
||||
.WorkingDirectory = BaseMcFolderHome
|
||||
}
|
||||
If Info.EnvironmentVariables.ContainsKey("appdata") Then
|
||||
Info.EnvironmentVariables("appdata") = BaseMcFolderHome
|
||||
Else
|
||||
Info.EnvironmentVariables.Add("appdata", BaseMcFolderHome)
|
||||
End If
|
||||
Log("[Download] 开始安装 OptiFine:" & Target)
|
||||
Dim TotalLength As Integer = 0
|
||||
Dim process As New Process With {.StartInfo = Info}
|
||||
Dim LastResult As String = ""
|
||||
Using outputWaitHandle As New AutoResetEvent(False)
|
||||
Using errorWaitHandle As New AutoResetEvent(False)
|
||||
AddHandler process.OutputDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
outputWaitHandle.[Set]()
|
||||
Else
|
||||
LastResult = e.Data
|
||||
If ModeDebug Then Log("[Installer] " & LastResult)
|
||||
TotalLength += 1
|
||||
Task.Progress += 0.9 / 7000
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 OptiFine 安装器信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 OptiFine 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
AddHandler process.ErrorDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
errorWaitHandle.[Set]()
|
||||
Else
|
||||
LastResult = e.Data
|
||||
If ModeDebug Then Log("[Installer] " & LastResult)
|
||||
TotalLength += 1
|
||||
Task.Progress += 0.9 / 7000
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 OptiFine 安装器错误信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 OptiFine 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
process.Start()
|
||||
process.BeginOutputReadLine()
|
||||
process.BeginErrorReadLine()
|
||||
'等待
|
||||
Do Until process.HasExited
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
'输出
|
||||
outputWaitHandle.WaitOne(10000)
|
||||
errorWaitHandle.WaitOne(10000)
|
||||
process.Dispose()
|
||||
If TotalLength < 1000 Then Throw New Exception("安装器运行出错,末行为 " & LastResult)
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
End SyncLock
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -511,24 +526,28 @@ Public Module ModDownloadLib
|
||||
Loaders.Add(New LoaderDownload("下载 OptiFine 主文件", New List(Of NetFile)) With {.ProgressWeight = 8})
|
||||
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("等待原版下载",
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
'是否已经存在原版文件
|
||||
If ClientDownloadLoader Is Nothing Then Exit Sub
|
||||
'等待原版文件下载完成
|
||||
For Each Loader In ClientDownloadLoader.GetLoaderList
|
||||
If Loader.Name <> McDownloadClientLibName Then Continue For
|
||||
Loader.WaitForExit()
|
||||
Exit For
|
||||
Next
|
||||
If ClientDownloadLoader Is Nothing Then Exit Sub
|
||||
Dim TargetLoaders As List(Of LoaderBase) =
|
||||
ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
|
||||
Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||
If TargetLoaders.Count > 0 Then Log("[Download] OptiFine 安装正在等待原版文件下载完成")
|
||||
Do While TargetLoaders.Count > 0 AndAlso Not Task.IsAborted
|
||||
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||
Thread.Sleep(50)
|
||||
Loop
|
||||
If Task.IsAborted Then Exit Sub
|
||||
'拷贝原版文件
|
||||
If IsCustomFolder Then
|
||||
Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
|
||||
Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit)
|
||||
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".json", McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
|
||||
End If
|
||||
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".jar", McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
|
||||
End If
|
||||
If Not IsCustomFolder Then Exit Sub
|
||||
Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
|
||||
Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit)
|
||||
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".json",
|
||||
McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
|
||||
End If
|
||||
If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".jar",
|
||||
McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
||||
|
||||
@@ -536,50 +555,50 @@ Public Module ModDownloadLib
|
||||
If IsNewVersion Then
|
||||
Log("[Download] 检测为新版 OptiFine:" & DownloadInfo.Inherit)
|
||||
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("安装 OptiFine(方式 A)",
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Dim BaseMcFolderHome As String = PathTemp & "InstallOptiFine" & RandomInteger(0, 100000)
|
||||
Dim BaseMcFolder As String = BaseMcFolderHome & "\.minecraft\"
|
||||
Try
|
||||
'准备安装环境
|
||||
If Directory.Exists(BaseMcFolder & "versions\" & DownloadInfo.Inherit) Then
|
||||
DeleteDirectory(BaseMcFolder & "versions\" & DownloadInfo.Inherit)
|
||||
End If
|
||||
My.Computer.FileSystem.CreateDirectory(BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\")
|
||||
McFolderLauncherProfilesJsonCreate(BaseMcFolder)
|
||||
CopyFile(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json",
|
||||
BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
|
||||
CopyFile(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar",
|
||||
BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
|
||||
Task.Progress = 0.06
|
||||
'进行安装
|
||||
McDownloadOptiFineInstall(BaseMcFolderHome, Target, Task)
|
||||
Task.Progress = 0.96
|
||||
'复制文件
|
||||
File.Delete(BaseMcFolder & "launcher_profiles.json")
|
||||
My.Computer.FileSystem.CopyDirectory(BaseMcFolder, McFolder, True)
|
||||
Task.Progress = 0.98
|
||||
'清理文件
|
||||
My.Computer.FileSystem.DeleteFile(Target)
|
||||
DeleteDirectory(BaseMcFolderHome)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("安装新版 OptiFine 版本失败", ex)
|
||||
End Try
|
||||
End Sub) With {.ProgressWeight = 8})
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Dim BaseMcFolderHome As String = PathTemp & "InstallOptiFine" & RandomInteger(0, 100000)
|
||||
Dim BaseMcFolder As String = BaseMcFolderHome & "\.minecraft\"
|
||||
Try
|
||||
'准备安装环境
|
||||
If Directory.Exists(BaseMcFolder & "versions\" & DownloadInfo.Inherit) Then
|
||||
DeleteDirectory(BaseMcFolder & "versions\" & DownloadInfo.Inherit)
|
||||
End If
|
||||
My.Computer.FileSystem.CreateDirectory(BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\")
|
||||
McFolderLauncherProfilesJsonCreate(BaseMcFolder)
|
||||
CopyFile(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json",
|
||||
BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
|
||||
CopyFile(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar",
|
||||
BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
|
||||
Task.Progress = 0.06
|
||||
'进行安装
|
||||
McDownloadOptiFineInstall(BaseMcFolderHome, Target, Task)
|
||||
Task.Progress = 0.96
|
||||
'复制文件
|
||||
File.Delete(BaseMcFolder & "launcher_profiles.json")
|
||||
My.Computer.FileSystem.CopyDirectory(BaseMcFolder, McFolder, True)
|
||||
Task.Progress = 0.98
|
||||
'清理文件
|
||||
My.Computer.FileSystem.DeleteFile(Target)
|
||||
DeleteDirectory(BaseMcFolderHome)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("安装新版 OptiFine 版本失败", ex)
|
||||
End Try
|
||||
End Sub) With {.ProgressWeight = 8})
|
||||
Else
|
||||
Log("[Download] 检测为旧版 OptiFine:" & DownloadInfo.Inherit)
|
||||
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("安装 OptiFine(方式 B)",
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Try
|
||||
'新建版本文件夹
|
||||
Directory.CreateDirectory(VersionFolder)
|
||||
Task.Progress = 0.1
|
||||
'复制 Jar 文件
|
||||
If File.Exists(VersionFolder & Id & ".jar") Then File.Delete(VersionFolder & Id & ".jar")
|
||||
CopyFile(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar", VersionFolder & Id & ".jar")
|
||||
Task.Progress = 0.7
|
||||
'建立 Json 文件
|
||||
Dim InheritVersion As New McVersion(McFolder & "versions\" & DownloadInfo.Inherit)
|
||||
Dim Json As String = "{
|
||||
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
Try
|
||||
'新建版本文件夹
|
||||
Directory.CreateDirectory(VersionFolder)
|
||||
Task.Progress = 0.1
|
||||
'复制 Jar 文件
|
||||
If File.Exists(VersionFolder & Id & ".jar") Then File.Delete(VersionFolder & Id & ".jar")
|
||||
CopyFile(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar", VersionFolder & Id & ".jar")
|
||||
Task.Progress = 0.7
|
||||
'建立 Json 文件
|
||||
Dim InheritVersion As New McVersion(McFolder & "versions\" & DownloadInfo.Inherit)
|
||||
Dim Json As String = "{
|
||||
""id"": """ & Id & """,
|
||||
""inheritsFrom"": """ & DownloadInfo.Inherit & """,
|
||||
""time"": """ & If(DownloadInfo.ReleaseTime = "", InheritVersion.ReleaseTime.ToString("yyyy-MM-dd"), DownloadInfo.ReleaseTime.Replace("/", "-")) & "T23:33:33+08:00"",
|
||||
@@ -590,16 +609,16 @@ Public Module ModDownloadLib
|
||||
{""name"": ""net.minecraft:launchwrapper:1.12""}
|
||||
],
|
||||
""mainClass"": ""net.minecraft.launchwrapper.Launch"","
|
||||
Task.Progress = 0.8
|
||||
If InheritVersion.IsOldJson Then
|
||||
'输出旧版 Json 格式
|
||||
Json += "
|
||||
Task.Progress = 0.8
|
||||
If InheritVersion.IsOldJson Then
|
||||
'输出旧版 Json 格式
|
||||
Json += "
|
||||
""minimumLauncherVersion"": 18,
|
||||
""minecraftArguments"": """ & InheritVersion.JsonObject("minecraftArguments").ToString & " --tweakClass optifine.OptiFineTweaker""
|
||||
}"
|
||||
Else
|
||||
'输出新版 Json 格式
|
||||
Json += "
|
||||
Else
|
||||
'输出新版 Json 格式
|
||||
Json += "
|
||||
""minimumLauncherVersion"": ""21"",
|
||||
""arguments"": {
|
||||
""game"": [
|
||||
@@ -608,12 +627,12 @@ Public Module ModDownloadLib
|
||||
]
|
||||
}
|
||||
}"
|
||||
End If
|
||||
WriteFile(VersionFolder & Id & ".json", Json)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("安装旧版 OptiFine 版本失败", ex)
|
||||
End Try
|
||||
End Sub) With {.ProgressWeight = 1})
|
||||
End If
|
||||
WriteFile(VersionFolder & Id & ".json", Json)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("安装旧版 OptiFine 版本失败", ex)
|
||||
End Try
|
||||
End Sub) With {.ProgressWeight = 1})
|
||||
End If
|
||||
|
||||
'下载支持库
|
||||
@@ -669,7 +688,9 @@ Public Module ModDownloadLib
|
||||
'建立控件
|
||||
Dim NewItem As New MyListItem With {
|
||||
.Title = Entry.NameDisplay, .SnapsToDevicePixels = True, .Height = 42, .Type = MyListItem.CheckType.Clickable, .Tag = Entry, .PaddingRight = 60,
|
||||
.Info = If(Entry.IsPreview, "测试版", "正式版") & If(Entry.ReleaseTime = "", "", ",发布于 " & Entry.ReleaseTime),
|
||||
.Info = If(Entry.IsPreview, "测试版", "正式版") &
|
||||
If(Entry.ReleaseTime = "", "", ",发布于 " & Entry.ReleaseTime) &
|
||||
If(Entry.RequiredForgeVersion = "", "", ",推荐 Forge 版本:" & Entry.RequiredForgeVersion),
|
||||
.Logo = "pack://application:,,,/images/Blocks/GrassPath.png"
|
||||
}
|
||||
AddHandler NewItem.Click, OnClick
|
||||
@@ -864,8 +885,8 @@ Public Module ModDownloadLib
|
||||
'构造版本 Json
|
||||
Dim VersionJson As New JObject
|
||||
VersionJson.Add("id", VersionName)
|
||||
VersionJson.Add("time", DateTime.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm:ss", Globalization.CultureInfo.CurrentCulture))
|
||||
VersionJson.Add("releaseTime", DateTime.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm:ss", Globalization.CultureInfo.CurrentCulture))
|
||||
VersionJson.Add("time", Date.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm", Globalization.CultureInfo.CurrentCulture))
|
||||
VersionJson.Add("releaseTime", Date.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm", Globalization.CultureInfo.CurrentCulture))
|
||||
VersionJson.Add("type", "release")
|
||||
VersionJson.Add("arguments", GetJson("{""game"":[""--tweakClass"",""" & DownloadInfo.JsonToken("tweakClass").ToString & """]}"))
|
||||
VersionJson.Add("libraries", DownloadInfo.JsonToken("libraries"))
|
||||
@@ -1078,90 +1099,88 @@ Public Module ModDownloadLib
|
||||
'选择 Java
|
||||
Dim Java = JavaSelect(New Version(1, 8, 0, 60))
|
||||
If Java Is Nothing Then
|
||||
JavaMissing(8)
|
||||
JavaMissing(17)
|
||||
Throw New Exception("未找到用于安装 Forge 的 Java")
|
||||
End If
|
||||
'添加 Java Wrapper 作为主 Jar
|
||||
Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -cp """ & PathTemp & "Cache\forge_installer.jar;" & Target & """ -jar """ & ExtractJavaWrapper() & """ com.bangbang93.ForgeInstaller """ & McFolder
|
||||
If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
|
||||
'开始启动
|
||||
Dim Argument As String = String.Format("-cp ""{0};{1}"" com.bangbang93.ForgeInstaller ""{2}", PathTemp & "Cache\forge_installer.jar", Target, McFolder)
|
||||
Dim Info = New ProcessStartInfo With {
|
||||
.FileName = Java.PathJavaw,
|
||||
.Arguments = Argument,
|
||||
.UseShellExecute = False,
|
||||
.CreateNoWindow = True,
|
||||
.RedirectStandardError = True,
|
||||
.RedirectStandardOutput = True
|
||||
}
|
||||
Log("[Download] 开始安装 Forge:" & Argument)
|
||||
Dim process As New Process With {.StartInfo = Info}
|
||||
Dim LastResults As New Queue(Of String)
|
||||
Using outputWaitHandle As New AutoResetEvent(False)
|
||||
Using errorWaitHandle As New AutoResetEvent(False)
|
||||
AddHandler process.OutputDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
outputWaitHandle.[Set]()
|
||||
Else
|
||||
LastResults.Enqueue(e.Data)
|
||||
If LastResults.Count > 100 Then LastResults.Dequeue()
|
||||
ForgeInjectorLine(e.Data, Task)
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 Forge 安装器信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 Forge 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
AddHandler process.ErrorDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
errorWaitHandle.[Set]()
|
||||
Else
|
||||
LastResults.Enqueue(e.Data)
|
||||
If LastResults.Count > 100 Then LastResults.Dequeue()
|
||||
ForgeInjectorLine(e.Data, Task)
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 Forge 安装器错误信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 Forge 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
process.Start()
|
||||
process.BeginOutputReadLine()
|
||||
process.BeginErrorReadLine()
|
||||
'等待
|
||||
Do Until process.HasExited
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
'输出
|
||||
outputWaitHandle.WaitOne(10000)
|
||||
errorWaitHandle.WaitOne(10000)
|
||||
process.Dispose()
|
||||
If LastResults.Last = "true" Then Exit Sub
|
||||
Log(Join(LastResults, vbCrLf))
|
||||
Throw New Exception("Forge 安装器出错,末行为 " & LastResults.Last)
|
||||
SyncLock InstallSyncLock
|
||||
Dim Info = New ProcessStartInfo With {
|
||||
.FileName = Java.PathJavaw,
|
||||
.Arguments = Arguments,
|
||||
.UseShellExecute = False,
|
||||
.CreateNoWindow = True,
|
||||
.RedirectStandardError = True,
|
||||
.RedirectStandardOutput = True
|
||||
}
|
||||
Log("[Download] 开始安装 Forge:" & Arguments)
|
||||
Dim process As New Process With {.StartInfo = Info}
|
||||
Dim LastResults As New Queue(Of String)
|
||||
Using outputWaitHandle As New AutoResetEvent(False)
|
||||
Using errorWaitHandle As New AutoResetEvent(False)
|
||||
AddHandler process.OutputDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
outputWaitHandle.[Set]()
|
||||
Else
|
||||
LastResults.Enqueue(e.Data)
|
||||
If LastResults.Count > 100 Then LastResults.Dequeue()
|
||||
ForgeInjectorLine(e.Data, Task)
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 Forge 安装器信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 Forge 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
AddHandler process.ErrorDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
errorWaitHandle.[Set]()
|
||||
Else
|
||||
LastResults.Enqueue(e.Data)
|
||||
If LastResults.Count > 100 Then LastResults.Dequeue()
|
||||
ForgeInjectorLine(e.Data, Task)
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取 Forge 安装器错误信息失败")
|
||||
End Try
|
||||
Try
|
||||
If Task.State = LoadState.Aborted AndAlso Not process.HasExited Then
|
||||
Log("[Installer] 由于任务取消,已中止 Forge 安装")
|
||||
process.Kill()
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
process.Start()
|
||||
process.BeginOutputReadLine()
|
||||
process.BeginErrorReadLine()
|
||||
'等待
|
||||
Do Until process.HasExited
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
'输出
|
||||
outputWaitHandle.WaitOne(10000)
|
||||
errorWaitHandle.WaitOne(10000)
|
||||
process.Dispose()
|
||||
If LastResults.Last = "true" Then Exit Sub
|
||||
Log(Join(LastResults, vbCrLf))
|
||||
Throw New Exception("Forge 安装器出错,末行为 " & LastResults.Last)
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
''判断结果
|
||||
'Dim ReturnData As String =
|
||||
'If ModeDebug Then Log("[Download] Forge 安装器 Log:" & vbCrLf & ReturnData & vbCrLf)
|
||||
' If Not ReturnData.TrimEnd(vbCrLf.ToCharArray()).EndsWith("true") Then
|
||||
' Throw New Exception("自动安装过程出错,日志尾部:" & vbCrLf & ReturnData.Substring(Math.Max(0, ReturnData.Length - 1000)))
|
||||
'End If
|
||||
End SyncLock
|
||||
End Sub
|
||||
Private Sub ForgeInjectorLine(Content As String, Task As LoaderTask(Of Boolean, Boolean))
|
||||
If Content.StartsWith(" Data") OrElse Content.StartsWith(" Slim") Then
|
||||
@@ -1319,24 +1338,26 @@ Public Module ModDownloadLib
|
||||
End If
|
||||
#End Region
|
||||
#Region "原版文件"
|
||||
'是否已经存在原版文件
|
||||
If ClientDownloadLoader Is Nothing Then Exit Sub
|
||||
'等待原版文件下载完成
|
||||
For Each Loader In ClientDownloadLoader.GetLoaderList
|
||||
If Loader.Name <> McDownloadClientLibName Then Continue For
|
||||
Loader.WaitForExit()
|
||||
Exit For
|
||||
Next
|
||||
If ClientDownloadLoader Is Nothing Then Exit Sub
|
||||
Dim TargetLoaders As List(Of LoaderBase) =
|
||||
ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName).
|
||||
Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||
If TargetLoaders.Count > 0 Then Log("[Download] Forge 安装正在等待原版文件下载完成")
|
||||
Do While TargetLoaders.Count > 0 AndAlso Not Task.IsAborted
|
||||
TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList
|
||||
Thread.Sleep(50)
|
||||
Loop
|
||||
If Task.IsAborted Then Exit Sub
|
||||
'拷贝原版文件
|
||||
If IsCustomFolder Then
|
||||
Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
|
||||
Directory.CreateDirectory(McFolder & "versions\" & Inherit)
|
||||
If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".json") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".json", McFolder & "versions\" & Inherit & "\" & Inherit & ".json")
|
||||
End If
|
||||
If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".jar") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".jar", McFolder & "versions\" & Inherit & "\" & Inherit & ".jar")
|
||||
End If
|
||||
If Not IsCustomFolder Then Exit Sub
|
||||
Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
|
||||
Directory.CreateDirectory(McFolder & "versions\" & Inherit)
|
||||
If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".json") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".json", McFolder & "versions\" & Inherit & "\" & Inherit & ".json")
|
||||
End If
|
||||
If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".jar") Then
|
||||
CopyFile(ClientDownloadLoader.Input & ClientName & ".jar", McFolder & "versions\" & Inherit & "\" & Inherit & ".jar")
|
||||
End If
|
||||
#End Region
|
||||
End Sub) With {.ProgressWeight = 0.1, .Show = False})
|
||||
@@ -1661,6 +1682,7 @@ Public Module ModDownloadLib
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
|
||||
'下载 Json
|
||||
MinecraftName = MinecraftName.Replace("∞", "infinite") '放在 ID 后面避免影响版本文件夹名称
|
||||
Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("获取 Fabric 主文件下载地址",
|
||||
Sub(Task As LoaderTask(Of String, List(Of NetFile)))
|
||||
'启动依赖版本的下载
|
||||
@@ -1800,7 +1822,7 @@ Public Module ModDownloadLib
|
||||
WriteIni(PathMcFolder & "PCL.ini", "VersionCache", "") '清空缓存(合并安装会先生成文件夹,这会在刷新时误判为可以使用缓存)
|
||||
Hint(Loader.Name & "成功!", HintType.Finish)
|
||||
Case LoadState.Failed
|
||||
Hint(Loader.Name & "失败:" & GetString(Loader.Error), HintType.Critical)
|
||||
Hint(Loader.Name & "失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
|
||||
Case LoadState.Aborted
|
||||
Hint(Loader.Name & "已取消!", HintType.Info)
|
||||
Case LoadState.Loading
|
||||
@@ -1817,7 +1839,7 @@ Public Module ModDownloadLib
|
||||
Case LoadState.Finished
|
||||
Hint(Loader.Name & "成功!", HintType.Finish)
|
||||
Case LoadState.Failed
|
||||
Hint(Loader.Name & "失败:" & GetString(Loader.Error), HintType.Critical)
|
||||
Hint(Loader.Name & "失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
|
||||
Case LoadState.Aborted
|
||||
Hint(Loader.Name & "已取消!", HintType.Info)
|
||||
Case LoadState.Loading
|
||||
@@ -2060,20 +2082,23 @@ Public Module ModDownloadLib
|
||||
#Region "处理 Json 文件"
|
||||
'获取 minecraftArguments
|
||||
Dim AllArguments As String =
|
||||
If(MinecraftJson("minecraftArguments"), " ").ToString &
|
||||
If(OptiFineJson IsNot Nothing, If(OptiFineJson("minecraftArguments"), " ").ToString, " ") &
|
||||
If(ForgeJson IsNot Nothing, If(ForgeJson("minecraftArguments"), " ").ToString, " ") &
|
||||
If(MinecraftJson("minecraftArguments"), " ").ToString & " " &
|
||||
If(OptiFineJson IsNot Nothing, If(OptiFineJson("minecraftArguments"), " ").ToString, " ") & " " &
|
||||
If(ForgeJson IsNot Nothing, If(ForgeJson("minecraftArguments"), " ").ToString, " ") & " " &
|
||||
If(LiteLoaderJson IsNot Nothing, If(LiteLoaderJson("minecraftArguments"), " ").ToString, " ")
|
||||
'分割参数字符串
|
||||
Dim RawArguments As List(Of String) = AllArguments.Split(" ").Where(Function(l) l <> "").Select(Function(l) l.Trim).ToList
|
||||
Dim SplitArguments As New List(Of String)
|
||||
For Each Argument In AllArguments.Split("--")
|
||||
Argument = Argument.Trim
|
||||
If Argument <> "" Then SplitArguments.Add(Argument)
|
||||
For i = 0 To RawArguments.Count - 1
|
||||
If RawArguments(i).StartsWith("-") Then
|
||||
SplitArguments.Add(RawArguments(i))
|
||||
ElseIf SplitArguments.Count > 0 AndAlso SplitArguments.Last.StartsWith("-") AndAlso Not SplitArguments.Last.Contains(" ") Then
|
||||
SplitArguments(SplitArguments.Count - 1) = SplitArguments.Last & " " & RawArguments(i)
|
||||
Else
|
||||
SplitArguments.Add(RawArguments(i))
|
||||
End If
|
||||
Next
|
||||
SplitArguments = ArrayNoDouble(SplitArguments)
|
||||
Dim RealArguments As String = Nothing
|
||||
If SplitArguments.Count > 0 Then
|
||||
RealArguments = "--" & Join(SplitArguments, " --")
|
||||
End If
|
||||
Dim RealArguments As String = Join(ArrayNoDouble(SplitArguments), " ")
|
||||
'合并
|
||||
OutputJson = MinecraftJson
|
||||
If HasOptiFine Then
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#Region "Logo"
|
||||
|
||||
'Public CacheLogo As Boolean = True '是否缓存 Logo:通过下载量确定是否为默认页
|
||||
Private _Logo As String = ""
|
||||
Public Property Logo As String
|
||||
Get
|
||||
@@ -157,7 +156,7 @@ RetryStart:
|
||||
Dim Ani As New List(Of AniData)
|
||||
If IsMouseOver Then
|
||||
Ani.AddRange({
|
||||
AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrush9"), Time),
|
||||
AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrushBg1"), Time),
|
||||
AaOpacity(RectBack, 1 - RectBack.Opacity, Time,, New AniEaseOutFluent)
|
||||
})
|
||||
If IsMouseDown Then
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
PanMain.Children.Add(NewCard)
|
||||
'确定卡片是否展开
|
||||
If Pair.Key = TopVersion Then
|
||||
MyCard.StackInstall(NewStack, 8, Pair.Key)
|
||||
MyCard.StackInstall(NewStack, If(Project.IsModPack, 9, 8), Pair.Key)
|
||||
Else
|
||||
NewCard.IsSwaped = True
|
||||
End If
|
||||
@@ -119,7 +119,7 @@
|
||||
#End Region
|
||||
|
||||
Private IsFirstInit As Boolean = True
|
||||
Public Sub Init() Handles Me.OnPageEnter
|
||||
Public Sub Init() Handles Me.PageEnter
|
||||
AniControlEnabled += 1
|
||||
Project = FrmMain.PageCurrent.Additional
|
||||
PanBack.ScrollToHome()
|
||||
@@ -139,7 +139,7 @@
|
||||
PanIntro.Children.Insert(0, CfItem)
|
||||
|
||||
'决定按钮显示
|
||||
BtnIntroWiki.Visibility = If(Project.McWikiId = 0, Visibility.Collapsed, Visibility.Visible)
|
||||
BtnIntroWiki.Visibility = If(Project.WikiId = 0, Visibility.Collapsed, Visibility.Visible)
|
||||
BtnIntroMCBBS.Visibility = If(Project.MCBBS Is Nothing, Visibility.Collapsed, Visibility.Visible)
|
||||
|
||||
AniControlEnabled -= 1
|
||||
@@ -164,14 +164,20 @@
|
||||
'构造步骤加载器
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
Dim Target As String = PathMcFolder & "versions\" & VersionName & "\原始整合包.zip"
|
||||
Dim LogoFileAddress As String = PathTemp & "CFLogo\" & GetHash(CfItem.Logo) & ".png"
|
||||
Loaders.Add(New LoaderDownload("下载整合包文件", New List(Of NetFile) From {File.GetDownloadFile(Target, True)}) With {.ProgressWeight = 10, .Block = True})
|
||||
Loaders.Add(New LoaderTask(Of Integer, Integer)("准备安装整合包", Sub() ModpackInstall(Target, VersionName)) With {.ProgressWeight = 0.1})
|
||||
Loaders.Add(New LoaderTask(Of Integer, Integer)("准备安装整合包",
|
||||
Sub()
|
||||
If Not ModpackInstall(Target, VersionName, Logo:=If(IO.File.Exists(LogoFileAddress), LogoFileAddress, Nothing)) Then
|
||||
Throw New Exception("整合包安装出现异常!")
|
||||
End If
|
||||
End Sub) With {.ProgressWeight = 0.1})
|
||||
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = Sub(MyLoader)
|
||||
Select Case MyLoader.State
|
||||
Case LoadState.Failed
|
||||
Hint(MyLoader.Name & "失败:" & GetString(MyLoader.Error), HintType.Critical)
|
||||
Hint(MyLoader.Name & "失败:" & GetExceptionSummary(MyLoader.Error), HintType.Critical)
|
||||
Case LoadState.Aborted
|
||||
Hint(MyLoader.Name & "已取消!", HintType.Info)
|
||||
Case LoadState.Loading
|
||||
@@ -189,70 +195,131 @@
|
||||
End Try
|
||||
End Sub
|
||||
'Mod 下载;整合包另存为
|
||||
Public Shared DownloadFolder = Nothing '仅在本次缓存的下载文件夹
|
||||
Public Shared CachedFolder As String = Nothing '仅在本次缓存的下载文件夹
|
||||
Public Sub Save_Click(sender As Object, e As EventArgs)
|
||||
Try
|
||||
Dim Desc As String = If(Project.IsModPack, "整合包", "Mod ")
|
||||
|
||||
'确认默认保存位置
|
||||
Dim DefaultFolder As String = Nothing
|
||||
If Not Project.IsModPack Then
|
||||
DefaultFolder = DownloadFolder
|
||||
If McVersionCurrent IsNot Nothing Then
|
||||
If Not McVersionCurrent.IsLoaded Then McVersionCurrent.Load()
|
||||
If McVersionCurrent.Version.Modable Then
|
||||
Dim File As DlCfFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
|
||||
RunInNewThread(
|
||||
Sub()
|
||||
Try
|
||||
Dim Desc As String = If(Project.IsModPack, "整合包", "Mod ")
|
||||
'确认默认保存位置
|
||||
Dim DefaultFolder As String = Nothing
|
||||
If Not Project.IsModPack Then
|
||||
'获取 Mod 所需的加载器种类
|
||||
Dim AllowForge As Boolean? = Nothing, AllowFabric As Boolean? = Nothing 'FUTURE: Quilt 支持
|
||||
If File.ModLoaders.Count > 0 Then '从文件中获取
|
||||
AllowForge = False : AllowFabric = False
|
||||
For Each LoaderType In File.ModLoaders
|
||||
If LoaderType = "Forge" Then AllowForge = True
|
||||
If LoaderType = "Fabric" Then AllowFabric = True
|
||||
Next
|
||||
ElseIf Project.ModLoaders.Count > 0 Then '从工程中获取
|
||||
AllowForge = False : AllowFabric = False
|
||||
For Each LoaderType In Project.ModLoaders
|
||||
If LoaderType = "Forge" Then AllowForge = True
|
||||
If LoaderType = "Fabric" Then AllowFabric = True
|
||||
Next
|
||||
End If
|
||||
If AllowForge IsNot Nothing AndAlso Not AllowForge AndAlso
|
||||
AllowFabric IsNot Nothing AndAlso Not AllowFabric Then
|
||||
AllowForge = Nothing : AllowFabric = Nothing
|
||||
End If
|
||||
Log("[Download] 允许 Forge:" & If(AllowForge, "未知") & ",允许 Fabric:" & If(AllowFabric, "未知"))
|
||||
'判断某个版本是否符合要求
|
||||
Dim IsVersionSuitable As Func(Of McVersion, Boolean) =
|
||||
Function(Version)
|
||||
If Not Version.IsLoaded Then Version.Load()
|
||||
If Not Version.Modable Then Return False
|
||||
If File.GameVersion.Any(Function(v) v.Contains(".")) AndAlso
|
||||
Not File.GameVersion.Any(Function(v) v.Contains(".") AndAlso v.Split(".")(1) = Version.Version.McCodeMain.ToString) Then Return False
|
||||
If AllowForge Is Nothing OrElse AllowFabric Is Nothing Then Return True
|
||||
If AllowForge AndAlso Version.Version.HasForge Then Return True
|
||||
If AllowFabric AndAlso Version.Version.HasFabric Then Return True
|
||||
Return False
|
||||
End Function
|
||||
'获取 Mod 默认下载位置
|
||||
If CachedFolder IsNot Nothing Then
|
||||
DefaultFolder = CachedFolder
|
||||
Log("[Download] 使用上次下载时的文件夹作为默认下载位置")
|
||||
ElseIf McVersionCurrent IsNot Nothing AndAlso IsVersionSuitable(McVersionCurrent) Then
|
||||
DefaultFolder = McVersionCurrent.PathIndie & "mods\"
|
||||
Directory.CreateDirectory(DefaultFolder)
|
||||
Log("[Download] 使用当前版本的 mods 文件夹作为默认下载位置(" & McVersionCurrent.Name & ")")
|
||||
Else
|
||||
Dim NeedLoad As Boolean = McVersionListLoader.State <> LoadState.Finished
|
||||
If NeedLoad Then
|
||||
Hint("正在查找适合的游戏版本……")
|
||||
LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
|
||||
End If
|
||||
Dim SuitableVersions As New List(Of McVersion)
|
||||
For Each Version As McVersion In McVersionList.Values.SelectMany(Function(l) l)
|
||||
If IsVersionSuitable(Version) Then SuitableVersions.Add(Version)
|
||||
Next
|
||||
If SuitableVersions.Count = 0 Then
|
||||
DefaultFolder = PathMcFolder
|
||||
If NeedLoad Then
|
||||
Hint("当前 MC 文件夹中没有找到适合这个 Mod 的版本!")
|
||||
Else
|
||||
Log("[Download] 由于当前版本不兼容,使用当前的 MC 文件夹作为默认下载位置")
|
||||
End If
|
||||
Else '选择 Mod 数量最多的版本
|
||||
Dim SelectedVersion = SuitableVersions.OrderBy(Function(v)
|
||||
Dim Info As New DirectoryInfo(v.PathIndie & "mods\")
|
||||
Return If(Info.Exists, Info.GetFiles().Length, -1)
|
||||
End Function).LastOrDefault()
|
||||
DefaultFolder = SelectedVersion.PathIndie & "mods\"
|
||||
Directory.CreateDirectory(DefaultFolder)
|
||||
Log("[Download] 使用适合的游戏版本作为默认下载位置(" & SelectedVersion.Name & ")")
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
If String.IsNullOrEmpty(DefaultFolder) Then DefaultFolder = Nothing
|
||||
End If
|
||||
|
||||
'获取基本信息
|
||||
Dim File As DlCfFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
|
||||
Dim ChineseName As String = If(Project.ChineseName = Project.Name, "",
|
||||
Project.ChineseName.Replace(" (", "Å").Split("Å").First.Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":"))
|
||||
Dim FileName As String
|
||||
Select Case Setup.Get("ToolDownloadTranslate")
|
||||
Case 0
|
||||
FileName = If(ChineseName = "", "", "[" & ChineseName & "] ") & File.FileName
|
||||
Case 1
|
||||
FileName = If(ChineseName = "", "", ChineseName & "-") & File.FileName
|
||||
Case 2
|
||||
FileName = File.FileName & If(ChineseName = "", "", "-" & ChineseName)
|
||||
Case Else
|
||||
FileName = File.FileName
|
||||
End Select
|
||||
Dim Target As String
|
||||
If File.FileName.EndsWith(".litemod") Then
|
||||
Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.litemod"), DefaultFolder)
|
||||
Else
|
||||
Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.jar"), DefaultFolder)
|
||||
End If
|
||||
If Not Target.Contains("\") Then Exit Sub
|
||||
Dim LoaderName As String = Desc & "下载:" & File.DisplayName & " "
|
||||
If Target <> DefaultFolder AndAlso Not Project.IsModPack Then DownloadFolder = GetPathFromFullPath(Target)
|
||||
|
||||
'构造步骤加载器
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.GetDownloadFile(Target, True)}) With {.ProgressWeight = 6, .Block = True})
|
||||
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
|
||||
Loader.Start(1)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Catch ex As Exception
|
||||
Log(ex, "保存 CurseForge 文件失败", LogLevel.Feedback)
|
||||
End Try
|
||||
'获取基本信息
|
||||
Dim ChineseName As String = If(Project.ChineseName = Project.Name, "",
|
||||
Project.ChineseName.Replace(" (", "Å").Split("Å").First.Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":"))
|
||||
Dim FileName As String
|
||||
Select Case Setup.Get("ToolDownloadTranslate")
|
||||
Case 0
|
||||
FileName = If(ChineseName = "", "", "[" & ChineseName & "] ") & File.FileName
|
||||
Case 1
|
||||
FileName = If(ChineseName = "", "", ChineseName & "-") & File.FileName
|
||||
Case 2
|
||||
FileName = File.FileName & If(ChineseName = "", "", "-" & ChineseName)
|
||||
Case Else
|
||||
FileName = File.FileName
|
||||
End Select
|
||||
RunInUi(
|
||||
Sub()
|
||||
'弹窗要求选择保存位置
|
||||
Dim Target As String
|
||||
If File.FileName.EndsWith(".litemod") Then
|
||||
Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.litemod"), DefaultFolder)
|
||||
Else
|
||||
Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.jar"), DefaultFolder)
|
||||
End If
|
||||
If Not Target.Contains("\") Then Exit Sub
|
||||
'构造步骤加载器
|
||||
Dim LoaderName As String = Desc & "下载:" & File.DisplayName & " "
|
||||
If Target <> DefaultFolder AndAlso Not Project.IsModPack Then CachedFolder = GetPathFromFullPath(Target)
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.GetDownloadFile(Target, True)}) With {.ProgressWeight = 6, .Block = True})
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
|
||||
Loader.Start(1)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
End Sub)
|
||||
Catch ex As Exception
|
||||
Log(ex, "保存 CurseForge 文件失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub, "Download CFDetail Save")
|
||||
End Sub
|
||||
|
||||
Private Sub BtnIntroCf_Click(sender As Object, e As EventArgs) Handles BtnIntroCf.Click
|
||||
OpenWebsite(Project.Website)
|
||||
End Sub
|
||||
Private Sub BtnIntroWiki_Click(sender As Object, e As EventArgs) Handles BtnIntroWiki.Click
|
||||
OpenWebsite("https://www.mcmod.cn/class/" & Project.McWikiId & ".html")
|
||||
OpenWebsite("https://www.mcmod.cn/class/" & Project.WikiId & ".html")
|
||||
End Sub
|
||||
Private Sub BtnIntroMCBBS_Click(sender As Object, e As EventArgs) Handles BtnIntroMCBBS.Click
|
||||
OpenWebsite("https://www.mcbbs.net/thread-" & Project.MCBBS & "-1-1.html")
|
||||
|
||||
@@ -65,11 +65,11 @@
|
||||
Dim CardInfo As New MyCard With {.Title = "最新版本", .Margin = New Thickness(0, 0, 0, 15), .SwapType = 2}
|
||||
Dim TopestVersions As New List(Of JObject)
|
||||
Dim Release As JObject = Dict("正式版")(0).DeepClone()
|
||||
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").ToString()
|
||||
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").Value(Of Date).ToString("yyyy/MM/dd HH:mm")
|
||||
TopestVersions.Add(Release)
|
||||
If Dict("正式版")(0)("releaseTime").Value(Of Date) < Dict("预览版")(0)("releaseTime").Value(Of Date) Then
|
||||
Dim Snapshot As JObject = Dict("预览版")(0).DeepClone()
|
||||
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").ToString()
|
||||
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").Value(Of Date).ToString("yyyy/MM/dd HH:mm")
|
||||
TopestVersions.Add(Snapshot)
|
||||
End If
|
||||
Dim PanInfo As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = TopestVersions}
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
End Sub
|
||||
|
||||
'页面切换触发
|
||||
Public Sub MinecraftSelected(sender As MyListItem, e As Object)
|
||||
Public Sub MinecraftSelected(sender As MyListItem, e As MouseButtonEventArgs)
|
||||
SelectedMinecraftId = sender.Title
|
||||
SelectedMinecraftJsonUrl = sender.Tag("url").ToString
|
||||
SelectedMinecraftIcon = sender.Logo
|
||||
@@ -536,11 +536,11 @@
|
||||
Dim CardInfo As New MyCard With {.Title = "最新版本", .Margin = New Thickness(0, 15, 0, 15), .SwapType = 2}
|
||||
Dim TopestVersions As New List(Of JObject)
|
||||
Dim Release As JObject = Dict("正式版")(0).DeepClone()
|
||||
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").ToString()
|
||||
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").Value(Of Date).ToString("yyyy/MM/dd HH:mm")
|
||||
TopestVersions.Add(Release)
|
||||
If Dict("正式版")(0)("releaseTime").Value(Of Date) < Dict("预览版")(0)("releaseTime").Value(Of Date) Then
|
||||
Dim Snapshot As JObject = Dict("预览版")(0).DeepClone()
|
||||
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").ToString()
|
||||
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").Value(Of Date).ToString("yyyy/MM/dd HH:mm")
|
||||
TopestVersions.Add(Snapshot)
|
||||
End If
|
||||
Dim PanInfo As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = TopestVersions}
|
||||
@@ -571,17 +571,39 @@
|
||||
''' 获取 OptiFine 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadOptiFineGetError() As String
|
||||
'If Not SelectedMinecraftId.Contains("1.") Then Return "没有可用版本"
|
||||
If LoadOptiFine.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
|
||||
If LoadOptiFine.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadOptiFine.State, Object).Error.Message
|
||||
For Each Version As DlOptiFineListEntry In DlOptiFineListLoader.Output.Value
|
||||
If Version.NameDisplay.StartsWith(SelectedMinecraftId & " ") Then
|
||||
'If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
||||
If SelectedForge IsNot Nothing AndAlso VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then Return "与 Forge 不兼容"
|
||||
'检查 Forge 1.13 - 1.14.3:全部不兼容
|
||||
If SelectedForge IsNot Nothing AndAlso
|
||||
VersionSortInteger(SelectedMinecraftId, "1.13") >= 0 AndAlso VersionSortInteger("1.14.3", SelectedMinecraftId) >= 0 Then
|
||||
Return "与 Forge 不兼容"
|
||||
End If
|
||||
'检查最低 Forge 版本
|
||||
Dim MinimalForgeVersion As String = "9999.9999"
|
||||
For Each OptiFineVersion As DlOptiFineListEntry In DlOptiFineListLoader.Output.Value
|
||||
If Not OptiFineVersion.NameDisplay.StartsWith(SelectedMinecraftId & " ") Then Continue For '不是同一个大版本
|
||||
If SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(OptiFineVersion, SelectedForge) Then
|
||||
Return Nothing
|
||||
Else
|
||||
'设置用于显示的最低 Forge 版本
|
||||
MinimalForgeVersion = If(VersionSortBoolean(MinimalForgeVersion, OptiFineVersion.RequiredForgeVersion),
|
||||
OptiFineVersion.RequiredForgeVersion, MinimalForgeVersion)
|
||||
End If
|
||||
Next
|
||||
Return "没有可用版本"
|
||||
If MinimalForgeVersion = "9999.9999" Then
|
||||
Return "没有可用版本"
|
||||
Else
|
||||
Return "需要 Forge " & If(MinimalForgeVersion.Contains("."), "", "#") & MinimalForgeVersion & " 或更高版本"
|
||||
End If
|
||||
End Function
|
||||
|
||||
'检查某个 OptiFine 是否与某个 Forge 兼容(最低 Forge 版本是否达到需求)
|
||||
Private Function IsOptiFineSuitForForge(OptiFine As DlOptiFineListEntry, Forge As DlForgeVersionEntry)
|
||||
If Forge.Inherit <> OptiFine.Inherit Then Return False '不是同一个大版本
|
||||
Return (OptiFine.RequiredForgeVersion.Contains(".") AndAlso 'XX.X.XXX
|
||||
VersionSortInteger(Forge.Version, OptiFine.RequiredForgeVersion) >= 0) OrElse
|
||||
(Not OptiFine.RequiredForgeVersion.Contains(".") AndAlso '#XXXX
|
||||
VersionSortInteger(Forge.Version.Split(".").Last, OptiFine.RequiredForgeVersion) >= 0)
|
||||
End Function
|
||||
|
||||
'限制展开
|
||||
@@ -595,9 +617,11 @@
|
||||
Private Sub OptiFine_Loaded() Handles LoadOptiFine.StateChanged
|
||||
Try
|
||||
If DlOptiFineListLoader.State <> LoadState.Finished Then Exit Sub
|
||||
|
||||
'获取版本列表
|
||||
Dim Versions As New List(Of DlOptiFineListEntry)
|
||||
For Each Version As DlOptiFineListEntry In DlOptiFineListLoader.Output.Value
|
||||
If SelectedForge IsNot Nothing AndAlso Not IsOptiFineSuitForForge(Version, SelectedForge) Then Continue For
|
||||
If Version.NameDisplay.StartsWith(SelectedMinecraftId & " ") Then Versions.Add(Version)
|
||||
Next
|
||||
If Versions.Count = 0 Then Exit Sub
|
||||
@@ -618,7 +642,9 @@
|
||||
'选择与清除
|
||||
Private Sub OptiFine_Selected(sender As MyListItem, e As EventArgs)
|
||||
SelectedOptiFine = sender.Tag
|
||||
If SelectedForge IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedForge = Nothing
|
||||
OptiFabric_Loaded()
|
||||
Forge_Loaded()
|
||||
CardOptiFine.IsSwaped = True
|
||||
SelectReload()
|
||||
End Sub
|
||||
@@ -627,6 +653,7 @@
|
||||
SelectedOptiFabric = Nothing
|
||||
CardOptiFine.IsSwaped = True
|
||||
e.Handled = True
|
||||
Forge_Loaded()
|
||||
SelectReload()
|
||||
End Sub
|
||||
|
||||
@@ -743,6 +770,7 @@
|
||||
ForgeDownloadListItemPreload(PanForge, Versions, AddressOf Forge_Selected, False)
|
||||
For Each Version In Versions
|
||||
If Version.Category = "universal" OrElse Version.Category = "client" Then Continue For '跳过无法自动安装的版本
|
||||
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, Version) Then Continue For
|
||||
PanForge.Children.Add(ForgeDownloadListItem(Version, AddressOf Forge_Selected, False))
|
||||
Next
|
||||
Catch ex As Exception
|
||||
@@ -754,12 +782,15 @@
|
||||
Private Sub Forge_Selected(sender As MyListItem, e As EventArgs)
|
||||
SelectedForge = sender.Tag
|
||||
CardForge.IsSwaped = True
|
||||
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, SelectedForge) Then SelectedOptiFine = Nothing
|
||||
OptiFine_Loaded()
|
||||
SelectReload()
|
||||
End Sub
|
||||
Private Sub Forge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnForgeClear.MouseLeftButtonUp
|
||||
SelectedForge = Nothing
|
||||
CardForge.IsSwaped = True
|
||||
e.Handled = True
|
||||
OptiFine_Loaded()
|
||||
SelectReload()
|
||||
End Sub
|
||||
|
||||
@@ -774,7 +805,7 @@
|
||||
If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……"
|
||||
If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadFabric.State, Object).Error.Message
|
||||
For Each Version As JObject In DlFabricListLoader.Output.Value("game")
|
||||
If Version("version").ToString = SelectedMinecraftId Then
|
||||
If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite") Then
|
||||
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
||||
'If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
|
||||
Return Nothing
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemHand" IsScaleAnimationEnabled="False" Type="RadioBox" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="手动安装包"
|
||||
LogoScale="1.02" Logo="M292.693 787.627c0 30.72-24.746 55.466-55.466 55.466s-55.467-24.746-55.467-55.466 24.747-55.467 55.467-55.467c30.72-0.853 55.466 24.747 55.466 55.467z M1000.96 241.493c-2.56-5.973-4.267-11.946-6.827-17.92-0.853-6.826-4.266-12.8-8.533-17.92-7.68-9.386-18.773-15.36-31.573-15.36-6.827 0-13.654 1.707-19.627 5.12l-15.36 15.36-17.067 17.067-21.333 21.333L749.227 381.44c-14.507 14.507-38.4 14.507-52.907 0l-54.613-54.613c-14.507-14.507-14.507-38.4 0-52.907l132.266-132.267 14.507-14.506 20.48-20.48 16.213-16.214c3.414-5.973 5.12-11.946 5.12-19.626 0-12.8-5.973-24.747-16.213-32.427-5.973-4.267-11.947-6.827-18.773-7.68-5.12-2.56-10.24-4.267-16.214-5.973-36.693-12.8-76.8-19.627-117.76-19.627-7.68 0-14.506 0-22.186 0.853-188.587 11.947-337.92 168.107-337.92 360.96 0 16.214 0.853 32.427 3.413 48.64L56.32 663.04c-73.387 74.24-73.387 193.707 0 267.093l33.28 33.28c73.387 73.387 193.707 73.387 267.093 0l240.64-241.493c21.334 4.267 42.667 5.973 64 5.973 190.294 0 346.454-146.773 360.107-333.653 0.853-8.533 0.853-17.92 0.853-27.307 0.854-44.373-6.826-86.186-21.333-125.44zM658.773 639.147c-28.16 0-54.613-4.267-79.36-11.094-4.266 7.68-10.24 14.507-16.213 21.334l-258.56 258.56c-43.52 43.52-115.2 43.52-158.72 0l-29.013-29.014c-43.52-44.373-43.52-115.2 0-158.72l212.48-212.48 46.08-46.08c5.973-5.973 12.8-11.093 19.626-15.36-8.533-26.453-12.8-54.613-12.8-83.626v-1.707c0-152.747 123.734-275.627 276.48-275.627 18.774 0 37.547 1.707 55.467 5.974L597.333 207.36c-52.053 52.053-52.053 137.387 0 189.44l29.867 29.867c52.053 52.053 137.387 52.053 189.44 0L930.987 312.32c2.56 16.213 4.266 33.28 4.266 50.347 0 152.746-123.733 276.48-276.48 276.48z" />
|
||||
<TextBlock x:Name="LabHand" Visibility="Collapsed" Text="手动安装包" Margin="13,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<TextBlock x:Name="LabHand" Visibility="Collapsed" Text="▼ 手动安装包" Padding="11,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemClient" Visibility="Collapsed" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="Minecraft"
|
||||
LogoScale="0.98" Logo="M989.7 510.8l-202.3-101c-10.8-5.4-17.7-16.5-17.7-28.6V172.7c0-26.7-16.6-50.6-41.6-59.9L550.5 46.3c-24.2-9-50.8-9-74.9 0.1l-176.9 66.8c-24.9 9.4-41.4 33.2-41.4 59.9v207.1c0 12.1-6.9 23.2-17.7 28.6l-204 101.9C13.9 521.6 0.1 543.8 0.2 568.1l0.5 226c0 23.2 12.6 44.5 32.9 55.8l223.8 124.6 1.2 0.7c18.9 10.5 41.9 10.4 60.8-0.2l2-1.1L497 873.2c9.9-5.7 22.1-5.6 32 0.1l176.7 102.5c18.9 10.7 42 10.8 61 0.3l3-1.7L992.4 851c20.4-11.3 33-32.8 33-56l-0.3-226.9c0-24.3-13.7-46.5-35.4-57.3zM321 192l115.3 46.1c27 10.8 44.7 36.9 44.7 66v163c0 5.9-6.2 9.8-11.6 7.2L339 409.5c-10.9-5.4-17.7-16.5-17.8-28.6L321 192z m-63.7 703.4L82.5 809.6c-10.9-5.4-17.9-16.5-17.9-28.7l-0.4-189.5L217.9 668c24.1 12 39.4 36.7 39.4 63.6v163.8z m64-274.3c-20.1 10.1-43.7 10-63.8 0l-0.2-0.1-149.1-75 149.1-74.4 16.8-8.4c9.2-4.6 20-4.5 29.1 0.3l18.1 9.4 129.8 64.3c5.8 2.9 6 11.1 0.2 14.2l-130 69.7z m141.9 203.8l-141.8 70.6-0.8-163.6c-0.1-27 15.1-51.8 39.2-63.9l108.8-54.5c5.3-2.7 11.6 1.2 11.6 7.1l0.8 175.6c0 12.1-6.9 23.2-17.8 28.7zM385 144l128-48 128 48-103 38.6c-16.1 6-33.8 6-49.9 0L385 144z m320 48l0.6 187.8c0 12.2-6.8 23.3-17.7 28.7l-131.4 65.7c-5.3 2.7-11.6-1.2-11.6-7.2V304.1c0-29.1 17.7-55.2 44.7-66L705 192z m0.7 710.3l-143.8-77.2c-10.4-5.6-16.9-16.4-16.9-28.2v-176c0-5.9 6.3-9.8 11.6-7.2l109.3 54.6c24 12 39.2 36.5 39.3 63.4l0.5 170.6z m-2-280.5l-129.2-70.5c-5.7-3.1-5.5-11.3 0.3-14.2l131-65.3 16.1-8.5c9.1-4.8 19.9-4.9 29.1-0.3l18.7 9.3L916.9 546l-146.2 76.4c-21.1 11-46.2 10.8-67-0.6z m66 279.4l-0.6-169.1c-0.1-27 15.1-51.7 39.3-63.8L961 592v188.7c0 11.9-6.6 22.7-17 28.3l-174.3 92.2z">
|
||||
<!--Logo="M469.333333 213.333333V128a42.666667 42.666667 0 1 1 85.333334 0v85.333333h127.829333C847.722667 213.333333 981.333333 347.029333 981.333333 512.149333v319.936A106.496 106.496 0 0 1 874.730667 938.666667h-85.461334c-48.661333 0-107.221333-29.290667-136.469333-68.266667l-64-85.333333c-6.144-8.170667-23.957333-17.066667-34.24-17.066667h-85.12c-10.282667 0-28.096 8.896-34.24 17.066667l-64 85.333333c-29.226667 38.976-87.808 68.266667-136.469333 68.266667H149.269333A106.496 106.496 0 0 1 42.666667 832.085333V512.149333C42.666667 347.029333 176.277333 213.333333 341.504 213.333333H469.333333z m213.162667 85.333334H341.504A213.333333 213.333333 0 0 0 128 512.149333v319.936c0 11.818667 9.450667 21.248 21.269333 21.248h85.461334c21.802667 0 55.082667-16.64 68.202666-34.133333l64-85.333333c22.272-29.696 65.408-51.2 102.506667-51.2h85.12c37.098667 0 80.213333 21.504 102.506667 51.2l64 85.333333c13.12 17.493333 46.4 34.133333 68.202666 34.133333h85.461334a21.162667 21.162667 0 0 0 21.269333-21.248V512.149333A213.333333 213.333333 0 0 0 682.496 298.666667zM362.666667 469.333333h42.666666a42.666667 42.666667 0 1 1 0 85.333334h-42.666666v42.666666a42.666667 42.666667 0 1 1-85.333334 0v-42.666666h-42.666666a42.666667 42.666667 0 1 1 0-85.333334h42.666666v-42.666666a42.666667 42.666667 0 1 1 85.333334 0v42.666666z m341.333333-21.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m0 213.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m-106.666667-106.666666a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z m213.333334 0a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z">-->
|
||||
|
||||
@@ -51,28 +51,17 @@
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="版本" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="4" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320" HintText="全部 (也可自行输入)">
|
||||
<local:MyComboBoxItem Content="" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="1.19.3" />
|
||||
<local:MyComboBoxItem Content="1.19.2" />
|
||||
<local:MyComboBoxItem Content="1.19.1" />
|
||||
<local:MyComboBoxItem Content="1.19" />
|
||||
<local:MyComboBoxItem Content="1.18.2" />
|
||||
<local:MyComboBoxItem Content="1.18.1" />
|
||||
<local:MyComboBoxItem Content="1.18" />
|
||||
<local:MyComboBoxItem Content="1.17.1" />
|
||||
<local:MyComboBoxItem Content="1.17" />
|
||||
<local:MyComboBoxItem Content="1.16.5" />
|
||||
<local:MyComboBoxItem Content="1.16.4" />
|
||||
<local:MyComboBoxItem Content="1.16.3" />
|
||||
<local:MyComboBoxItem Content="1.16.2" />
|
||||
<local:MyComboBoxItem Content="1.16.1" />
|
||||
<local:MyComboBoxItem Content="1.16" />
|
||||
<local:MyComboBoxItem Content="1.15.2" />
|
||||
<local:MyComboBoxItem Content="1.15" />
|
||||
<local:MyComboBoxItem Content="1.14.4" />
|
||||
<local:MyComboBoxItem Content="1.14" />
|
||||
<local:MyComboBoxItem Content="1.13.2" />
|
||||
<local:MyComboBoxItem Content="1.13" />
|
||||
<local:MyComboBoxItem Content="1.12.2" />
|
||||
<local:MyComboBoxItem Content="1.12" />
|
||||
<local:MyComboBoxItem Content="1.11.2" />
|
||||
<local:MyComboBoxItem Content="1.10.2" />
|
||||
<local:MyComboBoxItem Content="1.9.4" />
|
||||
@@ -83,9 +72,10 @@
|
||||
<local:MyComboBoxItem Content="1.5.2" />
|
||||
</local:MyComboBox>
|
||||
<local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="5" MaxDropDownHeight="320" Margin="10,0,0,0">
|
||||
<local:MyComboBoxItem Content="Forge 或 Fabric" IsSelected="True" Tag="0" />
|
||||
<local:MyComboBoxItem Content="任意 Mod 加载器" IsSelected="True" Tag="0" />
|
||||
<local:MyComboBoxItem Content="Forge" Tag="1" />
|
||||
<local:MyComboBoxItem Content="Fabric" Tag="4" />
|
||||
<local:MyComboBoxItem Content="Quilt" Tag="5" />
|
||||
</local:MyComboBox>
|
||||
</Grid>
|
||||
<Grid Margin="0,4,0,6" Height="35">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
'初始化加载器信息
|
||||
Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
|
||||
PageLoaderInit(Load, PanLoad, CardProjects, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
|
||||
McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
|
||||
End Sub
|
||||
Public Shared Loader As New LoaderTask(Of DlCfProjectRequest, DlCfProjectResult)("DlCfProject Mod", AddressOf DlCfProjectSub, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
|
||||
Private Shared Function LoaderInput() As DlCfProjectRequest
|
||||
|
||||
@@ -47,42 +47,21 @@
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="版本" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="4" IsEditable="True" MaxDropDownHeight="320" HintText="全部 (也可自行输入)">
|
||||
<local:MyComboBoxItem Content="" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="1.19.3" />
|
||||
<local:MyComboBoxItem Content="1.19.2" />
|
||||
<local:MyComboBoxItem Content="1.19.1" />
|
||||
<local:MyComboBoxItem Content="1.19" />
|
||||
<local:MyComboBoxItem Content="1.18.2" />
|
||||
<local:MyComboBoxItem Content="1.18.1" />
|
||||
<local:MyComboBoxItem Content="1.18" />
|
||||
<local:MyComboBoxItem Content="1.17.1" />
|
||||
<local:MyComboBoxItem Content="1.17" />
|
||||
<local:MyComboBoxItem Content="1.16.5" />
|
||||
<local:MyComboBoxItem Content="1.16.4" />
|
||||
<local:MyComboBoxItem Content="1.16.3" />
|
||||
<local:MyComboBoxItem Content="1.16.2" />
|
||||
<local:MyComboBoxItem Content="1.16.1" />
|
||||
<local:MyComboBoxItem Content="1.16" />
|
||||
<local:MyComboBoxItem Content="1.15.2" />
|
||||
<local:MyComboBoxItem Content="1.15.1" />
|
||||
<local:MyComboBoxItem Content="1.15" />
|
||||
<local:MyComboBoxItem Content="1.14.4" />
|
||||
<local:MyComboBoxItem Content="1.14.3" />
|
||||
<local:MyComboBoxItem Content="1.14.2" />
|
||||
<local:MyComboBoxItem Content="1.14.1" />
|
||||
<local:MyComboBoxItem Content="1.14" />
|
||||
<local:MyComboBoxItem Content="1.13.2" />
|
||||
<local:MyComboBoxItem Content="1.13.1" />
|
||||
<local:MyComboBoxItem Content="1.13" />
|
||||
<local:MyComboBoxItem Content="1.12.2" />
|
||||
<local:MyComboBoxItem Content="1.12.1" />
|
||||
<local:MyComboBoxItem Content="1.12" />
|
||||
<local:MyComboBoxItem Content="1.11.2" />
|
||||
<local:MyComboBoxItem Content="1.11" />
|
||||
<local:MyComboBoxItem Content="1.10.2" />
|
||||
<local:MyComboBoxItem Content="1.10" />
|
||||
<local:MyComboBoxItem Content="1.9.4" />
|
||||
<local:MyComboBoxItem Content="1.9" />
|
||||
<local:MyComboBoxItem Content="1.8.9" />
|
||||
<local:MyComboBoxItem Content="1.8" />
|
||||
<local:MyComboBoxItem Content="1.7.10" />
|
||||
<local:MyComboBoxItem Content="1.7.2" />
|
||||
<local:MyComboBoxItem Content="1.6.4" />
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
'初始化加载器信息
|
||||
Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
|
||||
PageLoaderInit(Load, PanLoad, CardProjects, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
|
||||
McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
|
||||
End Sub
|
||||
Public Shared Loader As New LoaderTask(Of DlCfProjectRequest, DlCfProjectResult)("DlCfProject ModPack", AddressOf DlCfProjectSub, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
|
||||
Private Shared Function LoaderInput() As DlCfProjectRequest
|
||||
|
||||
@@ -83,12 +83,21 @@
|
||||
'加载
|
||||
Dim Image As New MyBitmap(Address)
|
||||
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, 2).A = 0) OrElse
|
||||
(Image.Pic.GetPixel(1, 1) <> Image.Pic.GetPixel(41, 9) AndAlso Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1) <> Image.Pic.GetPixel(41, 9) AndAlso Image.Pic.GetPixel(Image.Pic.Width - 2, 2) <> Image.Pic.GetPixel(41, 9)) Then
|
||||
ImgFore.Source = New CroppedBitmap(Image, New Int32Rect(40, 8, 8, 8))
|
||||
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 = New CroppedBitmap(Image, New Int32Rect(Scale * 40, Scale * 8, Scale * 8, Scale * 8))
|
||||
Else
|
||||
ImgFore.Source = Nothing
|
||||
End If
|
||||
@@ -96,13 +105,8 @@
|
||||
ImgFore.Source = Nothing
|
||||
End If
|
||||
'脸层
|
||||
If Image.Pic.Width >= 32 AndAlso Image.Pic.Height >= 32 Then
|
||||
ImgBack.Source = New CroppedBitmap(Image, New Int32Rect(8, 8, 8, 8))
|
||||
Log("[Skin] 载入头像成功:" & Loader.Name)
|
||||
Else
|
||||
ImgBack.Source = Nothing
|
||||
Throw New Exception("图片大小不足,长为 " & Image.Pic.Height & ",宽为 " & Image.Pic.Width)
|
||||
End If
|
||||
ImgBack.Source = New CroppedBitmap(Image, New Int32Rect(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
|
||||
@@ -224,7 +228,10 @@ Retry:
|
||||
RunInUiWait(Sub()
|
||||
Try
|
||||
Dim CapeNames As New Dictionary(Of String, String) From {
|
||||
{"Migrator", "迁移者披风"}, {"MapMaker", "Realms 地图制作者披风"}, {"Moderator", "Mojira 管理员披风"}, {"Translator-Chinese", "Crowdin 中文翻译者披风"}, {"Translator", "Crowdin 翻译者披风"}
|
||||
{"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 参与者披风"}
|
||||
}
|
||||
Dim SelectionControl As New List(Of IMyRadio) From {New MyRadioBox With {.Text = "无披风"}}
|
||||
For Each Cape In SkinData("capes")
|
||||
|
||||
@@ -352,10 +352,10 @@ UnknownType:
|
||||
If ex.GetType.Name = "ThreadInterruptedException" Then
|
||||
Data.Output = ""
|
||||
Exit Sub
|
||||
ElseIf GetString(ex).Contains("429") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("429") Then
|
||||
Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
|
||||
Log("[Minecraft] 获取正版皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
|
||||
ElseIf GetString(ex).Contains("未设置自定义皮肤") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
|
||||
Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
|
||||
Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
|
||||
Else
|
||||
@@ -400,10 +400,10 @@ Finish:
|
||||
If ex.GetType.Name = "ThreadInterruptedException" Then
|
||||
Data.Output = ""
|
||||
Exit Sub
|
||||
ElseIf GetString(ex).Contains("429") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("429") Then
|
||||
Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
|
||||
Log("[Minecraft] 获取正版皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
|
||||
ElseIf GetString(ex).Contains("未设置自定义皮肤") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
|
||||
Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
|
||||
Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
|
||||
Else
|
||||
@@ -470,7 +470,7 @@ UseDefault:
|
||||
If ex.GetType.Name = "ThreadInterruptedException" Then
|
||||
Data.Output = ""
|
||||
Exit Sub
|
||||
ElseIf GetString(ex).Contains("429") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("429") Then
|
||||
Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
|
||||
Log("获取离线登录使用的正版皮肤失败(" & ID & "):获取皮肤太过频繁,请 5 分钟后再试!")
|
||||
Else
|
||||
@@ -479,12 +479,12 @@ UseDefault:
|
||||
End If
|
||||
End Try
|
||||
Case 4 '自定义
|
||||
If Not File.Exists(PathTemp & "CustomSkin.png") Then
|
||||
If Not File.Exists(PathAppdata & "CustomSkin.png") Then
|
||||
Hint("未找到离线皮肤自定义文件,可能它已被删除。PCL2 将使用默认的 Steve 皮肤!")
|
||||
Setup.Set("LaunchSkinType", 1)
|
||||
GoTo UseDefault
|
||||
End If
|
||||
Data.Output = PathTemp & "CustomSkin.png"
|
||||
Data.Output = PathAppdata & "CustomSkin.png"
|
||||
End Select
|
||||
'刷新显示
|
||||
If FrmLoginLegacy IsNot Nothing Then
|
||||
@@ -522,10 +522,10 @@ UseDefault:
|
||||
If ex.GetType.Name = "ThreadInterruptedException" Then
|
||||
Data.Output = ""
|
||||
Exit Sub
|
||||
ElseIf GetString(ex).Contains("429") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("429") Then
|
||||
Data.Output = PathImage & "Skins/Steve.png"
|
||||
Log("[Minecraft] 获取统一通行证皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
|
||||
ElseIf GetString(ex).Contains("未设置自定义皮肤") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
|
||||
Data.Output = PathImage & "Skins/Steve.png"
|
||||
Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
|
||||
Else
|
||||
@@ -570,10 +570,10 @@ Finish:
|
||||
If ex.GetType.Name = "ThreadInterruptedException" Then
|
||||
Data.Output = ""
|
||||
Exit Sub
|
||||
ElseIf GetString(ex).Contains("429") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("429") Then
|
||||
Data.Output = PathImage & "Skins/Steve.png"
|
||||
Log("[Minecraft] 获取 Authlib-Injector 皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
|
||||
ElseIf GetString(ex).Contains("未设置自定义皮肤") Then
|
||||
ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
|
||||
Data.Output = PathImage & "Skins/Steve.png"
|
||||
Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
|
||||
Else
|
||||
@@ -601,26 +601,23 @@ Finish:
|
||||
FrmMain.PageChange(FormMain.PageType.VersionSelect)
|
||||
End Sub
|
||||
'启动按钮
|
||||
Private Sub BtnLaunch_Click() Handles BtnLaunch.Click
|
||||
LaunchButtonClick()
|
||||
End Sub
|
||||
Public Sub LaunchButtonClick(Optional ServerIp As String = "")
|
||||
If BtnLaunch.IsEnabled AndAlso BtnLaunch.Visibility = Visibility.Visible AndAlso BtnLaunch.IsHitTestVisible Then
|
||||
If BtnLaunch.Text = "启动游戏" Then
|
||||
McLaunchLoader.Start(ServerIp)
|
||||
ElseIf BtnLaunch.Text = "下载游戏" Then
|
||||
FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
|
||||
End If
|
||||
'愚人节处理
|
||||
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
|
||||
Public Sub LaunchButtonClick() Handles BtnLaunch.Click
|
||||
If Not BtnLaunch.IsEnabled Then Exit Sub
|
||||
'愚人节处理
|
||||
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
|
||||
@@ -711,7 +708,11 @@ ExitRefresh:
|
||||
'修改登陆方式
|
||||
Select Case Setup.Get("LoginType")
|
||||
Case McLoginType.Legacy
|
||||
LabLaunchingMethod.Text = "离线登录"
|
||||
If PageLinkHiper.HiperState = LoadState.Finished Then
|
||||
LabLaunchingMethod.Text = "联机离线登录"
|
||||
Else
|
||||
LabLaunchingMethod.Text = "离线登录"
|
||||
End If
|
||||
Case McLoginType.Mojang
|
||||
LabLaunchingMethod.Text = "Mojang 正版登录"
|
||||
Case McLoginType.Ms
|
||||
|
||||
@@ -32,12 +32,9 @@
|
||||
''' <summary>
|
||||
''' 获取当前页面的登录信息。
|
||||
''' </summary>
|
||||
Public Shared Function GetLoginData() As McLoginLegacy
|
||||
If FrmLoginLegacy Is Nothing Then
|
||||
Return New McLoginLegacy With {.UserName = "", .SkinType = Setup.Get("LaunchSkinType"), .SkinName = Setup.Get("LaunchSkinID")}
|
||||
Else
|
||||
Return New McLoginLegacy With {.UserName = FrmLoginLegacy.ComboName.Text.Replace("¨", "").Trim, .SkinType = Setup.Get("LaunchSkinType"), .SkinName = Setup.Get("LaunchSkinID")}
|
||||
End If
|
||||
Public Shared Function GetLoginData() As McLoginData
|
||||
Dim UserName As String = If(FrmLoginLegacy Is Nothing, "", FrmLoginLegacy.ComboName.Text.Replace("¨", "").Trim)
|
||||
Return New McLoginLegacy With {.UserName = UserName, .SkinType = Setup.Get("LaunchSkinType"), .SkinName = Setup.Get("LaunchSkinID")}
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 当前页面的登录信息是否有效。
|
||||
|
||||
@@ -72,9 +72,9 @@
|
||||
End Sub
|
||||
Private Sub BtnMojang_Click(sender As Object, e As EventArgs) Handles BtnLink.Click
|
||||
If BtnLink.Content = "购买正版" Then
|
||||
OpenWebsite("https://www.minecraft.net/store/minecraft-java-edition/buy")
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/store/checkout/minecraft-java-bedrock-edition-pc")
|
||||
Else
|
||||
OpenWebsite("https://account.mojang.com/password")
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/password/forgot")
|
||||
End If
|
||||
End Sub
|
||||
Private Sub HintMigration_Click() Handles HintMigration.MouseLeftButtonUp
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
Select Case MyMsgBox("你希望通过哪种途径更改密码?" & vbCrLf & "首次通过个人档案修改密码可能需要验证你的密保问题。", "更改密码", "个人档案", "密保邮箱", "取消")
|
||||
Case 1
|
||||
'个人档案
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/profile/")
|
||||
OpenWebsite("https://www.minecraft.net/zh-hans/msaprofile")
|
||||
Case 2
|
||||
'密保邮箱
|
||||
OpenWebsite("https://account.mojang.com/password")
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
''' </summary>
|
||||
Public Shared Function GetLoginData() As McLoginMs
|
||||
If McLoginMsLoader.State = LoadState.Finished Then
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName"), .AccessToken = Setup.Get("CacheMsAccess"), .Uuid = Setup.Get("CacheMsUuid")}
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName"), .AccessToken = Setup.Get("CacheMsAccess"), .Uuid = Setup.Get("CacheMsUuid"), .ProfileJson = Setup.Get("CacheMsProfileJson")}
|
||||
Else
|
||||
Return New McLoginMs With {.OAuthRefreshToken = Setup.Get("CacheMsOAuthRefresh"), .UserName = Setup.Get("CacheMsName")}
|
||||
End If
|
||||
@@ -51,6 +51,7 @@
|
||||
Private Sub BtnExit_Click() Handles BtnExit.Click
|
||||
Setup.Set("CacheMsOAuthRefresh", "")
|
||||
Setup.Set("CacheMsAccess", "")
|
||||
Setup.Set("CacheMsProfileJson", "")
|
||||
Setup.Set("CacheMsUuid", "")
|
||||
Setup.Set("CacheMsName", "")
|
||||
McLoginMsLoader.Abort()
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<local:MyPageRight
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:PCL" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" x:Class="PageLinkFeedback"
|
||||
d:DesignWidth="800" d:DesignHeight="800">
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel Name="PanMain" Margin="25,25,25,10" Grid.IsSharedSizeScope="True">
|
||||
<local:MyCard Title="关于" Margin="0,0,0,15">
|
||||
<StackPanel Margin="20,40,18,18">
|
||||
<TextBlock TextWrapping="Wrap" Text="多人联机服务由速聚授权提供,PCL2 仅为速聚提供多人联机服务入口,使用中遇到的任何问题由速聚负责处理。你在使用多人联机服务过程中所遇到的任何问题与纠纷(包括其付费业务)均与 PCL2 无关,应与速聚协商解决。"
|
||||
Margin="0,0,0,3" />
|
||||
<TextBlock TextWrapping="Wrap" Text="PCL2 作者并不会从速聚的付费业务中获得任何分成、奖金等报酬,请不要瞎说。"
|
||||
Margin="0,0,0,6" />
|
||||
<local:MyListItem Title="速聚官网" Info="打开速聚的官方网站"
|
||||
Type="Clickable" EventType="打开网页" EventData="https://www.the.bb/zh-CN.html"
|
||||
PaddingRight="20" Logo="pack://application:,,,/images/Blocks/Grass.png" />
|
||||
<local:MyListItem Title="授权协议书" Info="查看速聚与 PCL2 间的授权协议书"
|
||||
Type="Clickable" EventType="打开网页" EventData="https://shimo.im/docs/0l3NVXYzeXhb903R"
|
||||
PaddingRight="20" Logo="pack://application:,,,/images/Blocks/Grass.png" />
|
||||
<local:MyListItem Title="用户协议与隐私政策" Info="查看速聚的用户协议与隐私政策文档"
|
||||
Type="Clickable" EventType="打开网页" EventData="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxMTMyODk3Mg==&action=getalbum&album_id=2585385685407514625&scene=173&from_msgid=2247483720&from_itemidx=1&count=3&nolastread=1#wechat_redirect"
|
||||
PaddingRight="20" Logo="pack://application:,,,/images/Blocks/Grass.png" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="发送反馈" Margin="0,0,0,15">
|
||||
<StackPanel Margin="20,40,18,18">
|
||||
<local:MyListItem Title="联机反馈与交流" Info="加入联机模块官方 QQ 群反馈联机异常,或询问联机功能的使用方式"
|
||||
Type="Clickable" PaddingRight="20" Logo="pack://application:,,,/images/Blocks/RedstoneBlock.png"
|
||||
EventType="打开网页" EventData="https://shimowendang.com/docs/KrkEVXz1K0frowAJ#anchor-7qQG" />
|
||||
<local:MyListItem Title="违法违规举报" Info="投诉、举报联机使用者的各类违法违规行为"
|
||||
Type="Clickable" EventType="打开网页" EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW#anchor-7x6P"
|
||||
PaddingRight="20" Logo="pack://application:,,,/images/Blocks/RedstoneBlock.png" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
</local:MyScrollViewer>
|
||||
</local:MyPageRight>
|
||||
@@ -0,0 +1,2 @@
|
||||
Public Class PageLinkFeedback
|
||||
End Class
|
||||
@@ -0,0 +1,236 @@
|
||||
<local:MyPageRight
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:PCL" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" x:Class="PageLinkHiper"
|
||||
d:DesignWidth="800" d:DesignHeight="800">
|
||||
<Grid>
|
||||
<Grid x:Name="PanLoad">
|
||||
<local:MyCard HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="CardLoad">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="25" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="20" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="18" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="23" />
|
||||
</Grid.RowDefinitions>
|
||||
<local:MyLoading Grid.Column="1" Grid.Row="1" x:Name="Load" Grid.RowSpan="3" Margin="0,0,0,-30" HorizontalAlignment="Center"
|
||||
Text="" TextError="" TextErrorInherit="False" AutoRun="False" IsHitTestVisible="False" />
|
||||
<TextBlock x:Name="LabLoadTitle" Grid.Column="3" Grid.Row="1" Grid.ColumnSpan="2" VerticalAlignment="Center" Text="正在创建联机房间" FontSize="19"
|
||||
Margin="0,0,25,1" Foreground="{Binding Foreground, ElementName=Load}" IsHitTestVisible="False" />
|
||||
<TextBlock x:Name="LabLoadDesc" Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="2" VerticalAlignment="Center" Margin="0,5,10,-5" Text="下载联机模块中……" FontSize="14"
|
||||
LineHeight="19" MaxWidth="400" MaxHeight="220" TextWrapping="Wrap" Foreground="{StaticResource ColorBrushGray3}" IsHitTestVisible="False" />
|
||||
<local:MyIconButton Grid.Column="5" Grid.Row="1" x:Name="BtnLoadCancel" Height="28" Width="28" VerticalAlignment="Top"
|
||||
Theme="Black" Opacity="0.5"
|
||||
ToolTip="取消" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="100"
|
||||
LogoScale="0.72" Logo="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid Height="12" VerticalAlignment="Bottom" Grid.ColumnSpan="100" Grid.RowSpan="100" Margin="0,0,0,-0.6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0*" x:Name="ColumnProgressA" />
|
||||
<ColumnDefinition Width="1*" x:Name="ColumnProgressB" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.Clip>
|
||||
<RectangleGeometry RadiusX="6" RadiusY="6" x:Name="RectProgressClip" />
|
||||
</Grid.Clip>
|
||||
<Rectangle Fill="{Binding Foreground, ElementName=Load}" VerticalAlignment="Bottom" Height="2" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
</Grid>
|
||||
<Grid x:Name="PanContent">
|
||||
<Grid x:Name="PanCert">
|
||||
<local:MyCard HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="25" />
|
||||
<ColumnDefinition Width="Auto" /> <!--Logo-->
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="1*" /> <!--文本区 ↓↓-->
|
||||
<ColumnDefinition Width="Auto" /> <!--按钮 1-->
|
||||
<ColumnDefinition Width="Auto" /> <!--按钮 2-->
|
||||
<ColumnDefinition Width="25" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="21" />
|
||||
<RowDefinition Height="Auto" /> <!--标题栏-->
|
||||
<RowDefinition Height="Auto" /> <!--文本区-->
|
||||
<RowDefinition Height="Auto" /> <!--文本框-->
|
||||
<RowDefinition Height="Auto" /> <!--按钮-->
|
||||
<RowDefinition Height="21" />
|
||||
</Grid.RowDefinitions>
|
||||
<Path Grid.Column="1" Grid.Row="1" Height="25" Width="25"
|
||||
Stretch="Uniform" Fill="{DynamicResource ColorBrush3}"
|
||||
Data="M856.3 291.1c-12-29.6-29.5-56-52.2-78.6-22.6-22.6-49.1-40.2-78.6-52.2-28.5-11.5-58.5-17.4-89.3-17.4s-60.8 5.9-89.3 17.4c-29.6 12-56 29.5-78.6 52.2-22.6 22.6-40.2 49.1-52.2 78.6-11.5 28.5-17.4 58.5-17.4 89.3 0 30.8 5.9 60.8 17.4 89.3 1.5 3.6 3 7.2 4.6 10.7l-238 238c-19 19-30.4 43.4-32.3 68.7-2 26.9 6.9 51.6 25 69.5C191.9 873 214 881 236.9 881c27 0 55.2-11.2 77.1-33l40.4-40.4c12.5-12.5 17.6-30.4 13.2-46.6-3.2-11.7 1.5-25.9 11.8-36.3 10.3-10.3 24.5-15 36.2-11.8 16.3 4.4 34.2-0.7 46.8-13.3l95.1-95.1c25.3 8.9 51.6 13.4 78.6 13.4 30.8 0 60.8-5.9 89.3-17.4 29.6-12 56-29.5 78.6-52.2 22.6-22.6 40.2-49.1 52.2-78.6 11.5-28.5 17.4-58.5 17.4-89.3 0.1-30.7-5.7-60.8-17.3-89.3zM427.2 664.2c-28.7-7.1-60.4 2.5-83 25.1-22.7 22.7-32.2 54.4-25.1 83l-40.3 40.3c-20.7 20.7-51.8 24.5-68 8.4-7.6-7.5-11.3-18.3-10.4-30.4 1-13.4 7.3-26.6 17.8-37l229.2-229.2c6.4 8.4 13.4 16.3 20.9 23.9 12.7 12.7 26.6 23.8 41.6 33.2l-82.7 82.7zM810 450.9c-9.5 23.3-23.3 44.2-41.2 62.1-17.9 17.9-38.7 31.7-62.1 41.2-22.5 9.1-46.2 13.7-70.5 13.7-24.3 0-48-4.6-70.5-13.7-2.5-1.7-5.3-2.8-8.1-3.5-20.1-9.3-38.2-21.9-54-37.7-17.9-17.9-31.7-38.7-41.2-62.1-9.1-22.5-13.7-46.2-13.7-70.5 0-24.3 4.6-48 13.7-70.5 9.5-23.3 23.3-44.2 41.2-62.1 17.9-17.9 38.7-31.7 62.1-41.2 22.5-9.1 46.2-13.7 70.5-13.7s48 4.6 70.5 13.7c23.3 9.5 44.2 23.3 62.1 41.2 17.9 17.9 31.7 38.7 41.2 62.1 9.1 22.5 13.7 46.2 13.7 70.5 0 24.3-4.6 48-13.7 70.5z M551.5 295.7c-22.6 22.6-35.1 52.7-35.1 84.7s12.5 62.1 35.1 84.7c23.4 23.4 54 35 84.7 35 30.7 0 61.4-11.7 84.7-35 22.6-22.6 35.1-52.7 35.1-84.7s-12.5-62.1-35.1-84.7c-46.7-46.7-122.7-46.7-169.4 0z m134.1 134.1c-27.2 27.2-71.5 27.2-98.7 0-13.2-13.2-20.4-30.7-20.4-49.4 0-18.6 7.3-36.2 20.4-49.4 13.6-13.6 31.5-20.4 49.4-20.4s35.7 6.8 49.4 20.4c13.2 13.2 20.4 30.7 20.4 49.4-0.1 18.7-7.3 36.2-20.5 49.4z" />
|
||||
<TextBlock Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="1" x:Name="LabCertTitle"
|
||||
Text="输入索引码" FontSize="20" Foreground="{DynamicResource ColorBrush3}" />
|
||||
<TextBlock Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="2" Margin="0,10,0,6"
|
||||
Text="你需要获取索引码才能使用 HiPer。
如果实在没有索引码,可以在左侧选择 IOI 方式联机。" x:Name="LabCertDesc"
|
||||
FontSize="14" LineHeight="19" MaxWidth="400" TextWrapping="Wrap" Foreground="{StaticResource ColorBrushGray2}" />
|
||||
<local:MyTextBox x:Name="TextCert" Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="3"
|
||||
Margin="0,0,0,12" Width="400" MaxLength="100" Height="28">
|
||||
<local:MyTextBox.ValidateRules>
|
||||
<local:ValidateNullOrWhiteSpace />
|
||||
<local:ValidateRegex Regex="^[^\u4e00-\u9fa5]{6,}$" />
|
||||
</local:MyTextBox.ValidateRules>
|
||||
</local:MyTextBox>
|
||||
<local:MyButton Grid.Column="4" Grid.Row="4" Margin="0,0,15,0" Text="获取索引码" Padding="13,8" EventType="打开网页" EventData="https://shimo.im/docs/KrkEVXz1K0frowAJ" />
|
||||
<local:MyButton x:Name="BtnCertDone" Grid.Column="5" Grid.Row="4" Text="确定" ColorType="Highlight" Padding="13,8" IsEnabled="False" />
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
</Grid>
|
||||
<Grid x:Name="PanSelect" Visibility="Collapsed">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="480" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="120" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="120" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<!--<local:MyHint IsWarn="True" Text="这是错误文本。" x:Name="HintTypeError" Visibility="Collapsed" Grid.ColumnSpan="5" Grid.RowSpan="5" Margin="15,15,15,0" VerticalAlignment="Top" />-->
|
||||
<local:MyCard x:Name="BtnSelectCreate" Grid.Column="1" Grid.Row="1">
|
||||
<Grid Margin="35,0,25,0" IsHitTestVisible="False">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Path Stretch="Uniform" Fill="{DynamicResource ColorBrush3}" Margin="0,25,0,12"
|
||||
Data="M904.479163 416.014006c-41.499044-0.199995-78.198199 20.799521-99.797701 52.698786-4.499896 6.699846-13.299694 9.09979-20.499527 5.399876L398.590818 280.017139c-6.999839-3.499919-10.39976-11.69973-7.999816-19.199557 6.099859-19.199558 9.399783-39.599088 9.399783-60.7986C399.990785 88.721546 308.092902-1.676371 196.795466 0.023589 87.797977 1.72355 0 90.621502 0 200.018982c0 92.597867 62.898551 170.396075 148.196586 193.195549 6.999839 1.899956 11.799728 8.199811 11.799728 15.399646v253.994148c0 7.199834-4.799889 13.399691-11.599733 15.399646C81.198129 697.007533 31.999263 758.806109 31.999263 832.004423c0 88.597959 71.998341 160.296307 160.5963 159.996314 88.09797-0.299993 159.396328-71.798346 159.396328-159.996314v-1.399968c-0.099998-6.099859 3.399922-11.69973 8.799797-14.399668l425.990187-214.495059c6.999839-3.499919 15.499643-1.499965 20.099537 4.79989 21.799498 29.999309 57.198682 49.598857 97.197761 49.598857 66.898459 0 120.997213-54.69874 119.997235-121.797194-1.099975-65.198498-54.498745-118.097279-119.597245-118.297275zM103.797609 296.216766C78.198199 270.517358 63.998526 236.318146 63.998526 200.018982c0-36.299164 14.199673-70.498376 39.799083-96.197784C129.497017 78.12179 163.696229 64.022115 199.995393 64.022115s70.498376 14.099675 96.197784 39.799083c25.699408 25.699408 39.799083 59.798622 39.799083 96.197784 0 15.499643-2.59994 30.499297-7.499828 44.69897-6.599848 19.199558-17.599595 36.699155-32.399253 51.498814-0.899979 0.899979-1.799959 1.699961-2.59994 2.59994-19.499551 18.399576-43.498998 30.499297-69.498399 35.099192-7.79982 1.399968-15.899634 2.099952-23.999447 2.099951-13.799682 0-27.199373-1.999954-39.999079-5.999862-20.999516-6.399853-40.199074-17.899588-56.198705-33.799221z m181.595816 557.887148c-9.99977 42.299026-48.098892 73.898298-93.397848 73.898298-52.898781 0-95.997788-43.099007-95.997789-95.997789 0-41.699039 26.799383-77.298219 63.998526-90.497915 9.99977-3.599917 20.799521-5.499873 31.999263-5.499873s21.999493 1.899956 31.999263 5.499873c22.699477 7.999816 41.499044 24.399438 52.698786 45.398954 7.199834 13.499689 11.29974 28.799337 11.299739 45.098961 0 7.599825-0.899979 14.999654-2.59994 22.099491z m41.299049-108.597498c-20.799521-32.399254-52.998779-56.698694-90.897906-67.498445-6.899841-1.999954-11.799728-8.199811-11.799728-15.399646V412.314091c0-7.699823 5.499873-14.299671 12.9997-15.699638 42.299026-7.899818 79.898159-29.09933 108.297505-59.098638 4.799889-5.099883 12.499712-6.399853 18.69957-3.199927l377.291308 189.995623c11.69973 5.899864 11.69973 22.699477 0 28.599342l-393.990924 198.395429c-7.299832 3.699915-16.199627 1.199972-20.599525-5.799866zM903.979175 592.009952c-19.699546 0-37.099145-10.299763-47.098915-25.699408-5.599871-8.6998-8.899795-19.09956-8.899795-30.299302 0-9.499781 2.399945-18.499574 6.599848-26.399392C863.980096 492.012255 882.579668 480.012532 903.979175 480.012532c30.899288 0 55.99871 25.099422 55.99871 55.99871s-25.099422 55.99871-55.99871 55.99871z" />
|
||||
<TextBlock Grid.Row="1" Text="创建房间" Margin="0,0,0,25" FontSize="20" Foreground="{DynamicResource ColorBrush3}" HorizontalAlignment="Center" />
|
||||
<TextBlock Grid.RowSpan="2" Grid.Column="2" LineHeight="23" FontSize="14" TextWrapping="Wrap" VerticalAlignment="Center" Margin="0,7,0,0"
|
||||
Text="1、打开游戏,在暂停画面选择【对局域网开放】
2、点击这里,并输入游戏显示的端口号
3、将联机码发送给你的朋友" />
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
<local:MyCard x:Name="BtnSelectJoin" Grid.Column="1" Grid.Row="3">
|
||||
<Grid Margin="35,0,25,0" IsHitTestVisible="False">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Path Stretch="Uniform" Fill="{DynamicResource ColorBrush3}" Margin="0,25,0,12"
|
||||
Data="M896 64H544c-17.7 0-32 14.3-32 32s14.3 32 32 32h352c35.3 0 64 28.7 64 64v640c0 35.3-28.7 64-64 64H544c-17.7 0-32 14.3-32 32s14.3 32 32 32h352c70.7 0 128-57.3 128-128V192c0-70.7-57.3-128-128-128z M821.3 488.3L458.9 160.7c-41.2-37.2-106.9-8-106.9 47.5V339c0 4.4-3.6 8-8 8H32c-17.7 0-32 14.3-32 32v266c0 17.7 14.3 32 32 32h312c4.4 0 8 3.6 8 8v130.9c0 55.5 65.8 84.7 106.9 47.5l362.4-327.6c14.1-12.8 14.1-34.8 0-47.5zM64 597V427c0-8.8 7.2-16 16-16h304c17.7 0 32-14.3 32-32V244.9c0-13.9 16.4-21.2 26.7-11.9L746 506.1c3.5 3.2 3.5 8.7 0 11.9L442.7 791c-10.3 9.3-26.7 2-26.7-11.9V645c0-17.7-14.3-32-32-32H80c-8.8 0-16-7.2-16-16z" />
|
||||
<TextBlock Grid.Row="1" Text="加入房间" Margin="0,0,0,25" FontSize="20" Foreground="{DynamicResource ColorBrush3}" HorizontalAlignment="Center" />
|
||||
<TextBlock Grid.RowSpan="2" Grid.Column="2" LineHeight="23" FontSize="14" TextWrapping="Wrap" VerticalAlignment="Center" Margin="0,7,10,0" HorizontalAlignment="Center"
|
||||
Text="点击这里,然后输入朋友发送给你的联机码" />
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
<local:MyCard x:Name="BtnSelectReturn" Grid.Column="1" Grid.Row="5" HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" IsHitTestVisible="False" Margin="15,12">
|
||||
<Path Stretch="Uniform" Fill="{DynamicResource ColorBrush3}" Height="13" Margin="0,0,8,0"
|
||||
Data="M268.70922 566.468085h929.588652c36.312057 0 72.624113-29.049645 72.624114-72.624113 0-36.312057-29.049645-72.624113-72.624114-72.624114H305.021277l297.758865-297.758865c29.049645-29.049645 29.049645-72.624113 0-101.673759-29.049645-29.049645-72.624113-29.049645-101.673759 0L72.624113 450.269504c-14.524823 14.524823-21.787234 36.312057-21.787234 58.09929 0 21.787234 0 43.574468 21.787234 58.099291l428.48227 428.48227c29.049645 29.049645 72.624113 29.049645 101.673759 0 29.049645-29.049645 29.049645-72.624113 0-101.673759l-334.070922-326.808511z" />
|
||||
<TextBlock Text="修改索引码" FontSize="14" Foreground="{DynamicResource ColorBrush3}" />
|
||||
<TextBlock Text="(28F…)" x:Name="LabSelectCode" FontSize="12" Foreground="{DynamicResource ColorBrushGray4}" VerticalAlignment="Bottom" Margin="5,0,0,0.5" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
</Grid>
|
||||
<Grid x:Name="PanFinish" Visibility="Collapsed" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,-50,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<local:MyCard HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,20">
|
||||
<StackPanel Orientation="Horizontal" Margin="3,0">
|
||||
<StackPanel x:Name="BtnFinishQuality" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
|
||||
ToolTip="连接状况" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="100" ToolTipService.VerticalOffset="-35">
|
||||
<Path IsHitTestVisible="False" Height="14" Width="14" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" Margin="12,1,7,0"
|
||||
Data="M512 128c212.064 0 384 171.936 384 384s-173.632 384-384 384C299.936 896 128 724.064 128 512S299.936 128 512 128z m-126.4 575.968c-1.728 40.8 3.52 76.8 36.32 115.2 28.576 8.32 58.816 12.832 90.08 12.832 81.984 0 156.8-30.848 213.408-81.536-77.12 7.2-161.6-5.952-289.216-61.856-11.616 7.52-18.976 12.608-50.592 15.36z m-193.44-202.368c0 123.744 53.536 214.272 135.744 272.16-6.08-25.6-8.352-48.448-4.96-91.68-21.344-17.6-34.944-39.264-34.624-82.08-50.816-42.88-82.88-75.712-96.16-98.4zM544 448c-14.944 0-29.12-3.424-41.728-9.504-10.976 12.96-21.376 26.432-31.2 40.512-4.832 6.912-15.36 23.776-31.616 50.624a95.872 95.872 0 0 1 36.384 106.432c155.52 68.16 302.56 62.048 325.952 11.904 23.36-50.112-35.968-139.776-189.504-228.48A95.68 95.68 0 0 1 544 448z m-160 128a32 32 0 1 0 0 64 32 32 0 0 0 0-64z m-161.92-199.2c-16.576 35.52 16.96 99.68 94.08 163.2a95.936 95.936 0 0 1 59.616-27.648c19.936-35.008 30.72-52.736 42.88-70.08 10.944-15.648 22.528-30.656 38.432-49.44-5.696-12.128-8.96-25.6-9.088-39.872-118.176-30.4-206.88-16.96-225.92 23.84z m415.136-47.84c1.824 7.36 3.296 19.104 2.336 32.416 88.96 48.704 153.76 105.056 192.32 160.704 0-118.656-34.208-176.064-75.52-210.976-49.792-5.92-69.952-4.064-119.136 17.856zM544 320a32 32 0 1 0 0 64 32 32 0 0 0 0-64z m-32-128c-82.016 0-156.8 30.848-213.44 81.6 47.264-4.384 96-0.544 170.304 18.624A95.84 95.84 0 0 1 544 256c21.568 0 41.472 7.104 57.504 19.104 35.968-17.28 62.016-25.824 87.136-29.984A318.528 318.528 0 0 0 512 192z" />
|
||||
<TextBlock x:Name="LabFinishQuality" IsHitTestVisible="False" Text="优秀" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0,12,0" />
|
||||
</StackPanel>
|
||||
<TextBlock Text="|" Opacity="0.3" Margin="0,8.8,0,8" RenderTransformOrigin="0.5,0.5">
|
||||
<TextBlock.RenderTransform>
|
||||
<ScaleTransform ScaleX="1" ScaleY="2.75" CenterX="0.5" CenterY="0.5" />
|
||||
</TextBlock.RenderTransform>
|
||||
</TextBlock>
|
||||
<StackPanel x:Name="BtnFinishPing" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
|
||||
ToolTip="与房主的延迟(点击刷新)" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="100" ToolTipService.VerticalOffset="-35">
|
||||
<Path IsHitTestVisible="False" Height="14" Width="14" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" Margin="12,0,7,0"
|
||||
Data="M512 409.6a102.4 102.4 0 0 0-51.2 190.464V1024h102.4v-423.936A102.4 102.4 0 0 0 512 409.6z M512 0a512 512 0 0 0-263.168 950.272l51.2-87.552a409.6 409.6 0 1 1 420.864 0l51.2 87.552A512 512 0 0 0 512 0z M819.2 512a307.2 307.2 0 1 0-464.896 263.168l51.2-88.064a204.8 204.8 0 1 1 209.92 0l51.2 88.064A307.2 307.2 0 0 0 819.2 512z" />
|
||||
<TextBlock x:Name="LabFinishPing" IsHitTestVisible="False" Text="15ms" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0,12,0" />
|
||||
</StackPanel>
|
||||
<TextBlock Text="|" x:Name="LineFinishPing" Opacity="0.3" Margin="0,8.8,0,8" RenderTransformOrigin="0.5,0.5">
|
||||
<TextBlock.RenderTransform>
|
||||
<ScaleTransform ScaleX="1" ScaleY="2.75" CenterX="0.5" CenterY="0.5" />
|
||||
</TextBlock.RenderTransform>
|
||||
</TextBlock>
|
||||
<StackPanel x:Name="BtnFinishIp" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
|
||||
ToolTip="服务器 IP 地址(点击复制)" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="100" ToolTipService.VerticalOffset="-35">
|
||||
<Path IsHitTestVisible="False" Height="11" Width="11" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" Margin="12,0,7,0"
|
||||
Data="M277.333333 853.333333H192V170.666667h85.333333z m341.333334-597.333333h-170.666667v256h170.666667a128 128 0 0 0 0-256m0-85.333333a213.333333 213.333333 0 0 1 0 426.666666h-170.666667v256h-85.333333V170.666667z" />
|
||||
<TextBlock x:Name="LabFinishIp" IsHitTestVisible="False" Text="6.0.0.1:12345" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0,12,0" />
|
||||
</StackPanel>
|
||||
<TextBlock Text="|" Opacity="0.3" Margin="0,8.8,0,8" RenderTransformOrigin="0.5,0.5">
|
||||
<TextBlock.RenderTransform>
|
||||
<ScaleTransform ScaleX="1" ScaleY="2.75" CenterX="0.5" CenterY="0.5" />
|
||||
</TextBlock.RenderTransform>
|
||||
</TextBlock>
|
||||
<StackPanel Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
|
||||
ToolTip="索引码剩余时间" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="100" ToolTipService.VerticalOffset="-35">
|
||||
<Path IsHitTestVisible="False" Height="13" Width="13" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" Margin="12,0,7,0"
|
||||
Data="M832 64H192c-35.2 0-64 28.8-64 64v192c0 14.532 4.918 27.965 13.158 38.739a63.808 63.808 0 0 0 5.94 6.869L293.49 512 147.098 658.392a63.808 63.808 0 0 0-5.94 6.869C132.918 676.035 128 689.468 128 704v192c0 35.2 28.8 64 64 64h640c35.2 0 64-28.8 64-64V704c0-14.532-4.918-27.965-13.158-38.739a63.808 63.808 0 0 0-5.94-6.869L730.51 512l146.392-146.392a63.808 63.808 0 0 0 5.94-6.869C891.082 347.965 896 334.532 896 320V128c0-35.2-28.8-64-64-64z m-32 244.49L640.098 466.392c-12.534 12.534-18.749 29.086-18.659 45.608-0.09 16.522 6.125 33.074 18.659 45.608L800 718.51V864H224V718.51l158.902-160.902c12.534-12.534 18.749-29.086 18.659-45.608 0.09-16.522-6.125-33.074-18.659-45.608L224 302.49V160h576v148.49z M476.33 457.292c15.631 17.517 42.263 57.543 8.75 100.373L297.608 745.137a31.809 31.809 0 0 0-2.275 2.536C290.757 753.211 288 760.299 288 768c0 17.6 14.4 32 32 32h384.001c17.6 0 32-14.4 32-32 0-7.701-2.757-14.789-7.333-20.327a32.004 32.004 0 0 0-2.275-2.536L545.71 564.454c-16.012-18.851-39.722-58.366-5.07-100.241l58.388-57.487c12.445-12.445 12.445-32.81 0-45.255a31.711 31.711 0 0 0-13.806-8.102A31.712 31.712 0 0 0 576 352H449c-1.287 0-2.553 0.086-3.801 0.235-7.385 0.548-14.612 3.621-20.227 9.236-12.445 12.445-12.445 32.81 0 45.255l51.358 50.566z" />
|
||||
<TextBlock x:Name="LabFinishTime" IsHitTestVisible="False" Text="2:21" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0,12,0" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="25" />
|
||||
<ColumnDefinition Width="Auto" /> <!--Logo-->
|
||||
<ColumnDefinition Width="13" />
|
||||
<ColumnDefinition Width="1*" /> <!--文本区 ↓↓-->
|
||||
<ColumnDefinition Width="Auto" /> <!--按钮 1-->
|
||||
<ColumnDefinition Width="Auto" /> <!--按钮 2-->
|
||||
<ColumnDefinition Width="25" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="21" />
|
||||
<RowDefinition Height="Auto" /> <!--标题栏-->
|
||||
<RowDefinition Height="Auto" /> <!--文本区-->
|
||||
<RowDefinition Height="Auto" /> <!--按钮-->
|
||||
<RowDefinition Height="21" />
|
||||
</Grid.RowDefinitions>
|
||||
<Path Grid.Column="1" Grid.Row="1" Height="25" Width="25"
|
||||
Stretch="Uniform" Fill="{DynamicResource ColorBrush3}"
|
||||
Data="M845 547.45h65.54A400.6 400.6 0 0 0 712.7 201.77l-33.22 56.49C781.6 318.32 845 429.13 845 547.45zM347.72 253.92L316 196.58a401.21 401.21 0 0 0-207 350.87h65.54a335.66 335.66 0 0 1 173.18-293.53zM509.79 882.68a334 334 0 0 1-181.3-53.2L293 884.57a401.13 401.13 0 0 0 419.1 8.91L679 836.93a334.94 334.94 0 0 1-169.21 45.75z M821.51 625.1A108.64 108.64 0 0 0 752.2 650l-67.31-38.86a185.44 185.44 0 0 0 11.22-63.7c0-91.55-66.38-167.9-153.54-183.42V289a109.14 109.14 0 1 0-65.57 0v75c-87.16 15.53-153.54 91.87-153.54 183.42a185.46 185.46 0 0 0 11.22 63.7L267.39 650a109.17 109.17 0 1 0 35.81 55l64.47-37.23a186 186 0 0 0 284.23 0L716.38 705a109.13 109.13 0 1 0 105.13-79.9zM198.07 777.85a43.6 43.6 0 1 1 43.61-43.61 43.66 43.66 0 0 1-43.61 43.61z m311.72-636.53a43.61 43.61 0 1 1-43.61 43.61 43.65 43.65 0 0 1 43.61-43.61z m0 526.91a120.78 120.78 0 1 1 120.78-120.78 120.91 120.91 0 0 1-120.78 120.77z m311.72 109.62a43.6 43.6 0 1 1 43.61-43.61 43.65 43.65 0 0 1-43.61 43.61z" />
|
||||
<TextBlock x:Name="LabFinishTitle" Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="1"
|
||||
Text="已加入 Herobrine 的房间" FontSize="20" Foreground="{DynamicResource ColorBrush3}" />
|
||||
<TextBlock x:Name="LabFinishDesc" Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="2" Margin="0,10,0,12"
|
||||
Text="描述文本。"
|
||||
FontSize="14" LineHeight="19" MaxWidth="400" TextWrapping="Wrap" Foreground="{StaticResource ColorBrushGray2}" />
|
||||
<local:MyButton x:Name="BtnFinishCopy" Grid.Column="4" Grid.Row="3" Margin="0,0,15,0" Text="复制联机码" Padding="13,8" />
|
||||
<local:MyButton x:Name="BtnFinishExit" Grid.Column="5" Grid.Row="3" Text="退出" Padding="13,8" />
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid x:Name="PanAlways" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="15" Opacity="0.5">
|
||||
<local:MyTextButton Text="联机服务由 速聚 授权提供" EventType="打开网页" EventData="https://www.the.bb/zh-CN.html" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</local:MyPageRight>
|
||||
@@ -0,0 +1,952 @@
|
||||
Public Class PageLinkHiper
|
||||
Public Const RequestVersion As Char = "2"
|
||||
|
||||
'记录的启动情况
|
||||
Public Shared IsServerSide As Boolean
|
||||
Private Shared HostIp As String
|
||||
Private Shared HostPort As Integer
|
||||
|
||||
#Region "初始化"
|
||||
|
||||
'加载器初始化
|
||||
Private Sub LoaderInit() Handles Me.Initialized
|
||||
PageLoaderInit(Load, PanLoad, PanContent, PanAlways, InitLoader, AutoRun:=False)
|
||||
'注册自定义的 OnStateChanged
|
||||
AddHandler InitLoader.OnStateChangedUi, AddressOf OnLoadStateChanged
|
||||
End Sub
|
||||
|
||||
Private IsLoad As Boolean = False
|
||||
Private Sub OnLoaded() Handles Me.Loaded
|
||||
If IsLoad Then Exit Sub
|
||||
IsLoad = True
|
||||
'启动监视线程
|
||||
If Not IsWatcherStarted Then RunInNewThread(AddressOf WatcherThread, "Hiper Watcher")
|
||||
'读取索引码
|
||||
Try
|
||||
Dim Time As String = Setup.Get("LinkHiperCertTime")
|
||||
If Time = "" Then
|
||||
Log("[HiPer] 没有缓存凭证")
|
||||
ElseIf Date.Parse(Time) > Date.Now Then
|
||||
TextCert.Text = Setup.Get("LinkHiperCertLast")
|
||||
Log("[HiPer] 缓存凭证尚未过期:" & Time)
|
||||
CurrentSubpage = Subpages.PanSelect
|
||||
Else
|
||||
Log("[HiPer] 缓存凭证已过期:" & Time)
|
||||
LabCertTitle.Text = "输入索引码"
|
||||
LabCertDesc.Text = "你的 HiPer 索引码已经过期,请输入新的索引码。" & vbCrLf & "如果实在没有索引码,可以在左侧选择 IOI 方式联机。"
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取缓存凭证失败")
|
||||
Setup.Set("LinkHiperCertTime", "")
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "加载步骤"
|
||||
|
||||
Public Shared PathHiper As String = PathAppdata & "联机模块\"
|
||||
Public Shared WithEvents InitLoader As New LoaderCombo(Of Integer)("HiPer 初始化", {
|
||||
New LoaderTask(Of Integer, Integer)("网络环境:连通检测", AddressOf InitPingCheck) With {.Block = False, .ProgressWeight = 0.5},
|
||||
New LoaderTask(Of Integer, Integer)("网络环境:IP 检测", AddressOf InitIpCheck) With {.Block = False, .ProgressWeight = 1},
|
||||
New LoaderTask(Of Integer, Integer)("检查网络环境", AddressOf InitCheck) With {.ProgressWeight = 0.5},
|
||||
New LoaderTask(Of Integer, List(Of NetFile))("获取所需文件", AddressOf InitGetFile) With {.ProgressWeight = 4},
|
||||
New LoaderDownload("下载所需文件", New List(Of NetFile)) With {.ProgressWeight = 4},
|
||||
New LoaderTask(Of Integer, Integer)("启动联机模块", AddressOf InitLaunch) With {.ProgressWeight = 7}
|
||||
})
|
||||
|
||||
'检查网络状态
|
||||
Private Shared Sub InitPingCheck(Task As LoaderTask(Of Integer, Integer))
|
||||
PingTime = 0
|
||||
Try
|
||||
Log("[HiPer] 网络检测:连通检测开始")
|
||||
Dim StartTime = Date.Now.Ticks
|
||||
Dim Result As String = NetGetCodeByClient("https://www.baidu.com/duty/", Encoding.UTF8, 20000, "")
|
||||
Dim DuringTime As Integer = (Date.Now.Ticks - StartTime) / 10000
|
||||
If Result.Contains("百度") Then
|
||||
Log("[HiPer] 网络检测:连通检测成功(" & DuringTime & "ms)")
|
||||
PingTime = DuringTime
|
||||
Else
|
||||
Log("[HiPer] 网络检测:连通检测失败(获取的内容有误)")
|
||||
PingTime = -1
|
||||
End If
|
||||
Catch ex As ThreadInterruptedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "连通检测失败")
|
||||
PingTime = -1
|
||||
End Try
|
||||
End Sub
|
||||
Private Shared Sub InitIpCheck()
|
||||
IpCheckStatus = LoadState.Loading
|
||||
Try
|
||||
Log("[HiPer] 网络检测:IP 地址检测开始")
|
||||
Dim IpCheckResult As String = NetRequestOnce("https://ipinfo.io/json", "GET", "", "application/json", 10000)
|
||||
Dim Country As String = GetJson(IpCheckResult)("country")
|
||||
IpIsInChina = Country = "CN"
|
||||
IpCheckStatus = LoadState.Finished
|
||||
Log("[HiPer] 网络检测:IP 地址检测结果:" & Country)
|
||||
Catch ex As ThreadInterruptedException
|
||||
IpCheckStatus = LoadState.Aborted
|
||||
Catch ex As Exception
|
||||
Log(ex, "IP 地址检测失败")
|
||||
IpCheckStatus = LoadState.Failed
|
||||
IpIsInChina = True
|
||||
End Try
|
||||
End Sub
|
||||
Private Shared PingTime As Integer, IpCheckStatus As LoadState = LoadState.Loading, IpIsInChina As Boolean
|
||||
Private Shared Sub InitCheck(Task As LoaderTask(Of Integer, Integer))
|
||||
'检查协议
|
||||
If Not Setup.Get("LinkEula") Then
|
||||
Reopen:
|
||||
Select Case MyMsgBox("PCL2 的联机服务由速聚授权提供。" & vbCrLf & "在使用前,你需要同意速聚的用户服务协议和隐私政策。", "协议授权", "同意", "拒绝", "查看用户服务协议和隐私政策")
|
||||
Case 1
|
||||
Setup.Set("LinkEula", True)
|
||||
Case 2
|
||||
Throw New Exception("$你拒绝了用户服务协议……")
|
||||
Case 3
|
||||
OpenWebsite("https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxMTMyODk3Mg==&action=getalbum&album_id=2585385685407514625&scene=173&from_msgid=2247483720&from_itemidx=1&count=3&nolastread=1#wechat_redirect")
|
||||
GoTo Reopen
|
||||
End Select
|
||||
End If
|
||||
'等待网络环境检查加载器结束
|
||||
SetLoadDesc("正在检查网络环境……", "检查网络环境")
|
||||
Do While Task.State = LoadState.Loading AndAlso Not (PingTime <> 0 AndAlso IpCheckStatus <> LoadState.Loading)
|
||||
Thread.Sleep(50)
|
||||
Loop
|
||||
'获取网络环境检查结果
|
||||
If IpCheckStatus = LoadState.Finished AndAlso Not IpIsInChina Then
|
||||
If MyMsgBox("检测到你的 IP 不在中国,这会导致联机变得非常不稳定。" & vbCrLf &
|
||||
"如果你正开着加速器或者 VPN,请先关闭它们,然后再继续……", "警告", "继续", "取消", IsWarn:=True, ForceWait:=True) = 2 Then
|
||||
Throw New Exception("$请在关闭加速器或者 VPN 后点击重试。")
|
||||
End If
|
||||
Task.Progress = 0.5
|
||||
InitIpCheck() '重新进行检查
|
||||
End If
|
||||
'没有联网
|
||||
If IpCheckStatus = LoadState.Failed AndAlso PingTime = -1 Then
|
||||
Throw New Exception("$PCL2 没法连上网……" & vbCrLf & "如果你改变了网络环境,请重启 PCL2。")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
'获取所需文件
|
||||
Private Shared Sub InitGetFile(Task As LoaderTask(Of Integer, List(Of NetFile)))
|
||||
'初始化
|
||||
SetLoadDesc("正在初始化……", "初始化")
|
||||
Directory.CreateDirectory(PathHiper)
|
||||
WriteFile(PathHiper & "HiPer 联机模块.vbs", "createobject(""wscript.shell"").run """"""" & PathHiper & "HiPer 联机模块.exe"""" v"", 0", Encoding:=Encoding.GetEncoding("GB18030")) '准备启动脚本
|
||||
'获取索引码文件
|
||||
SetLoadDesc("正在获取索引码文件……", "获取索引码文件")
|
||||
Dim Cert As String = RunInUiWait(Function() FrmLinkHiper.TextCert.Text)
|
||||
Log("[Hiper] 联机索引码:" & Cert)
|
||||
If Cert = Setup.Get("LinkHiperCertLast") AndAlso File.Exists(PathHiper & "cert.yml") Then
|
||||
Log("[Hiper] 索引码与上次输入的一致,跳过获取步骤")
|
||||
Else
|
||||
Dim CertRaw As String
|
||||
Try
|
||||
CertRaw = NetRequestOnce("https://cert.mcer.cn/" & Cert & ".yml", "GET", "", "")
|
||||
Catch ex As Exception
|
||||
If GetExceptionSummary(ex).Contains("(404)") Then
|
||||
Throw New CertOutdatedException '索引码无效或已过期
|
||||
ElseIf GetExceptionSummary(ex).Contains("too many requests") Then
|
||||
Throw New Exception("你的尝试太频繁了,请暂时啥都别点,等两分钟后再试……")
|
||||
Else
|
||||
Throw
|
||||
End If
|
||||
End Try
|
||||
If Not CertRaw.Contains("WARNING <<< AUTO SYNC AREA") Then Throw New Exception("获取到的索引码文件内容有误!")
|
||||
WriteFile(PathHiper & "cert.yml", CertRaw)
|
||||
Setup.Set("LinkHiperCertLast", Cert)
|
||||
Setup.Set("LinkHiperCertTime", "")
|
||||
End If
|
||||
Task.Progress = 0.25
|
||||
'获取 CPU 架构
|
||||
SetLoadDesc("正在获取 CPU 架构……", "获取 CPU 架构")
|
||||
Dim Architecture As String
|
||||
Select Case GetType(String).Assembly.GetName().ProcessorArchitecture
|
||||
Case Reflection.ProcessorArchitecture.X86
|
||||
Architecture = "386"
|
||||
Case Reflection.ProcessorArchitecture.Amd64
|
||||
Architecture = "amd64"
|
||||
Case Reflection.ProcessorArchitecture.Arm
|
||||
Architecture = "arm64"
|
||||
Case Else
|
||||
Architecture = "arm64"
|
||||
Log("[Hiper] 当前 CPU 架构为 " & GetStringFromEnum(GetType(String).Assembly.GetName().ProcessorArchitecture) & ",没有最适合的项,这可能会导致联机模块无法启动!", LogLevel.Debug)
|
||||
End Select
|
||||
Log("[Hiper] CPU 架构:" & Architecture)
|
||||
'检查更新:hiper.exe
|
||||
SetLoadDesc("正在检查联机模块本体更新……", "检查联机模块本体更新")
|
||||
Dim RequiredFiles As New List(Of NetFile)
|
||||
Dim Checksums As String = Nothing, ChecksumHiper As String = Nothing
|
||||
If File.Exists(PathHiper & "HiPer 联机模块.exe") Then
|
||||
Try
|
||||
Checksums = NetGetCodeByDownload({
|
||||
"http://mirror.hiper.cn.s2.the.bb/packages.sha1",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/packages.sha1",
|
||||
"https://gitcode.net/to/hiper/-/raw/master/packages.sha1",
|
||||
"https://cert.mcer.cn/mirror/packages.sha1"
|
||||
})
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取联机模块更新信息失败,将会强制启动联机模块", LogLevel.Hint)
|
||||
GoTo FinishHiperFileCheck
|
||||
End Try
|
||||
ChecksumHiper = RegexSeek(Checksums, "[0-9a-f]{40}(?= windows-" & Architecture & "/hiper.exe)")
|
||||
If ChecksumHiper Is Nothing Then
|
||||
Log("[Hiper] 未找到联机模块更新信息,将会强制启动联机模块", LogLevel.Hint)
|
||||
GoTo FinishHiperFileCheck
|
||||
End If
|
||||
Log("[Hiper] hiper.exe 的所需 SHA1:" & ChecksumHiper)
|
||||
If ChecksumHiper = GetAuthSHA1(PathHiper & "HiPer 联机模块.exe") Then
|
||||
Log("[Hiper] hiper.exe 文件校验通过,无需重新下载")
|
||||
GoTo FinishHiperFileCheck
|
||||
End If
|
||||
End If
|
||||
Log("[Hiper] 需要重新下载 hiper.exe")
|
||||
RequiredFiles.Add(New NetFile({"http://mirror.hiper.cn.s2.the.bb/windows-" & Architecture & "/hiper.exe",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/windows-" & Architecture & "/hiper.exe",
|
||||
"https://gitcode.net/to/hiper/-/raw/master/windows-" & Architecture & "/hiper.exe?inline=false",
|
||||
"https://cert.mcer.cn/mirror/windows-" & Architecture & "/hiper.exe"},
|
||||
PathHiper & "HiPer 联机模块.exe",
|
||||
New FileChecker(Hash:=ChecksumHiper, MinSize:=1024 * 200))) 'Hash 的默认值即为 Nothing,所以 Checksum 可以为 Nothing
|
||||
FinishHiperFileCheck:
|
||||
Task.Progress = 0.5
|
||||
'检查更新:wintun.dll
|
||||
Dim ChecksumWintun As String = Nothing
|
||||
If File.Exists(PathHiper & "wintun.dll") Then
|
||||
Try
|
||||
If Checksums Is Nothing Then
|
||||
Checksums = NetGetCodeByDownload({
|
||||
"http://mirror.hiper.cn.s2.the.bb/packages.sha1",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/packages.sha1",
|
||||
"https://gitcode.net/to/hiper/-/raw/master/packages.sha1",
|
||||
"https://cert.mcer.cn/mirror/packages.sha1"
|
||||
})
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取联机模块更新信息失败,将会强制启动联机模块", LogLevel.Hint)
|
||||
GoTo FinishWintunFileCheck
|
||||
End Try
|
||||
ChecksumWintun = RegexSeek(Checksums, "[0-9a-f]{40}(?= windows-" & Architecture & "/wintun.dll)")
|
||||
If ChecksumWintun Is Nothing Then
|
||||
Log("[Hiper] 未找到联机模块更新信息,将会强制启动联机模块", LogLevel.Hint)
|
||||
GoTo FinishWintunFileCheck
|
||||
End If
|
||||
Log("[Hiper] wintun.dll 的所需 SHA1:" & ChecksumWintun)
|
||||
If ChecksumWintun = GetAuthSHA1(PathHiper & "wintun.dll") Then
|
||||
Log("[Hiper] wintun.dll 文件校验通过,无需重新下载")
|
||||
GoTo FinishWintunFileCheck
|
||||
End If
|
||||
End If
|
||||
Log("[Hiper] 需要重新下载 wintun.dll")
|
||||
RequiredFiles.Add(New NetFile({"http://mirror.hiper.cn.s2.the.bb/windows-" & Architecture & "/wintun.dll",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/windows-" & Architecture & "/wintun.dll",
|
||||
"https://gitcode.net/to/hiper/-/raw/master/windows-" & Architecture & "/wintun.dll?inline=false",
|
||||
"https://cert.mcer.cn/mirror/windows-" & Architecture & "/wintun.dll"},
|
||||
PathHiper & "wintun.dll",
|
||||
New FileChecker(Hash:=ChecksumWintun, MinSize:=1024 * 200))) 'Hash 的默认值即为 Nothing,所以 Checksum 可以为 Nothing
|
||||
FinishWintunFileCheck:
|
||||
Task.Progress = 0.75
|
||||
'检查更新:MCB
|
||||
If Not IsServerSide Then
|
||||
SetLoadDesc("正在检查联机模块组件更新……", "检查联机模块组件更新")
|
||||
Dim ChecksumMcb As String = Nothing
|
||||
If File.Exists(PathHiper & "MCB 联机模块.exe") Then
|
||||
Try
|
||||
Checksums = NetGetCodeByDownload({
|
||||
"http://mirror.hiper.cn.s2.the.bb/utils/minecraft-broadcast/packages.sha1",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/utils/minecraft-broadcast/packages.sha1",
|
||||
"https://gitcode.net/to/hiper/-/raw/master/utils/minecraft-broadcast/packages.sha1",
|
||||
"https://cert.mcer.cn/mirror/utils/minecraft-broadcast/packages.sha1"
|
||||
})
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取联机模块组件更新信息失败,将会强制启动联机模块组件", LogLevel.Hint)
|
||||
GoTo FinishMcbFileCheck
|
||||
End Try
|
||||
ChecksumMcb = RegexSeek(Checksums, "[0-9a-f]{40}(?= mcb-windows-" & Architecture & ".exe)")
|
||||
If ChecksumMcb Is Nothing Then
|
||||
Log("[Hiper] 未找到联机模块组件更新信息,将会强制启动联机模块组件", LogLevel.Hint)
|
||||
GoTo FinishMcbFileCheck
|
||||
End If
|
||||
Log("[Hiper] mcb.exe 的所需 SHA1:" & ChecksumMcb)
|
||||
If ChecksumMcb = GetAuthSHA1(PathHiper & "MCB 联机模块.exe") Then
|
||||
Log("[Hiper] mcb.exe 文件校验通过,无需重新下载")
|
||||
GoTo FinishMcbFileCheck
|
||||
End If
|
||||
End If
|
||||
Log("[Hiper] 需要重新下载 mcb.exe")
|
||||
RequiredFiles.Add(New NetFile({
|
||||
"http://mirror.hiper.cn.s2.the.bb/utils/minecraft-broadcast/mcb-windows-" & Architecture & ".exe",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/utils/minecraft-broadcast/mcb-windows-" & Architecture & ".exe",
|
||||
"https://gitcode.net/to/hiper/-/raw/master/utils/minecraft-broadcast/mcb-windows-" & Architecture & ".exe?inline=false",
|
||||
"https://cert.mcer.cn/mirror/utils/minecraft-broadcast/mcb-windows-" & Architecture & ".exe"},
|
||||
PathHiper & "MCB 联机模块.exe",
|
||||
New FileChecker(Hash:=ChecksumMcb, MinSize:=1024 * 200))) 'Hash 的默认值即为 Nothing,所以 Checksum 可以为 Nothing
|
||||
FinishMcbFileCheck:
|
||||
End If
|
||||
'添加 point.yml
|
||||
RequiredFiles.Add(New NetFile({"https://cert.mcer.cn/point.yml"}, PathHiper & "point.yml", New FileChecker(MinSize:=200)))
|
||||
'开始下载
|
||||
SetLoadDesc("正在下载联机模块……", "下载联机模块")
|
||||
Task.Output = RequiredFiles
|
||||
End Sub
|
||||
Public Class CertOutdatedException
|
||||
Inherits Exception
|
||||
End Class
|
||||
'启动联机模块
|
||||
Private Shared Sub InitLaunch(Task As LoaderTask(Of Integer, Integer))
|
||||
'关闭运行中的 HiPer,然后再刷新凭证文件
|
||||
SetLoadDesc("正在关闭运行中的联机模块……", "关闭运行中的联机模块")
|
||||
HiperStop(True)
|
||||
'准备凭证文件
|
||||
SetLoadDesc("正在准备索引码文件……", "准备索引码文件")
|
||||
Dim CertFile As String = ReadFile(PathHiper & "cert.yml")
|
||||
'添加防火墙配置
|
||||
If IsServerSide Then
|
||||
CertFile += ("\n\ninbound:\n port: " & HostPort & "\n proto: tcp\n host: any").Replace("\n", vbCrLf)
|
||||
Else
|
||||
CertFile += ("\n\noutbound:\n port: " & HostPort & "\n proto: tcp\n host: " & HostIp).Replace("\n", vbCrLf)
|
||||
End If
|
||||
CertFile += "\nlogging:\n format: json".Replace("\n", vbCrLf)
|
||||
'更新 point.yml 段
|
||||
Const SyncAreaRegex As String = "(?<=#[ ]*WARNING >>> AUTO SYNC AREA)[\s\S]+?(?=#[ ]*WARNING <<< AUTO SYNC AREA)"
|
||||
CertFile = CertFile.Replace(RegexSeek(CertFile, SyncAreaRegex), RegexSeek(ReadFile(PathHiper & "point.yml"), SyncAreaRegex))
|
||||
WriteFile(PathHiper & "config.yml", CertFile)
|
||||
AllNodes = RegexSearch(CertFile.Replace(vbLf, "cr"), "(?<="")[0-9]+.[0-9]+.[0-9]+.[0-9]+(?=""( )?:( )?cr - "")").Distinct.
|
||||
Where(Function(l) Not (l = "6.6.1.1" OrElse l = "6.6.2.2" OrElse l = "6.6.3.3")).ToList
|
||||
If AllNodes.Count < 2 Then Throw New Exception("$索引码文件格式有误,未找到节点 IP!")
|
||||
Task.Progress = 0.05
|
||||
'尝试启动
|
||||
HiperStart(Task) '启动失败会直接抛出异常
|
||||
Task.Progress = 0.2
|
||||
'检查连接情况
|
||||
SetLoadDesc("正在连接到联机节点 (1/2)……" & If(IpIsInChina, "", vbCrLf & "由于网络不在中国,可能要花费很长时间。"), "检查联机节点")
|
||||
If Not IsServerSide AndAlso HostIp = HiperIp Then Throw New Exception("$还搁这自己连自己?!不是吧?!")
|
||||
Dim PingNodeResults As New List(Of Integer)
|
||||
Dim UnpingedNodes As New List(Of String)(AllNodes)
|
||||
Do Until PingNodeResults.Count >= 2 OrElse Task.IsAborted
|
||||
Dim SelectedNode = RandomOne(UnpingedNodes)
|
||||
Dim PingNode = Ping(SelectedNode, 4000)
|
||||
If PingNode = -1 Then
|
||||
Task.Progress += (If(PingNodeResults.Count = 0, 0.58, 0.88) - Task.Progress) * 0.3
|
||||
Else
|
||||
SetLoadDesc("正在连接到联机节点 (2/2)……" & If(IpIsInChina, "", vbCrLf & "由于网络不在中国,可能要花费很长时间。"), "检查联机节点")
|
||||
Task.Progress = 0.6
|
||||
PingNodeResults.Add(PingNode)
|
||||
UnpingedNodes.Remove(SelectedNode)
|
||||
End If
|
||||
Loop
|
||||
PingNodes = PingNodeResults.Min
|
||||
Task.Progress = 0.9
|
||||
'与房主 Ping 一下看看
|
||||
If Not IsServerSide Then
|
||||
SetLoadDesc("正在连接到房主……", "检查房主")
|
||||
HostPing = -1 '实际上不使用本次 Ping 的结果,因为它真的偏大……
|
||||
Do
|
||||
Dim PingHost = Ping(HostIp, 4000, False)
|
||||
If PingHost = -1 Then
|
||||
Thread.Sleep(500)
|
||||
Else
|
||||
Exit Do
|
||||
End If
|
||||
Loop Until Task.IsAborted
|
||||
'在等待 2 秒后再次触发 Ping,以刷新显示的 Ping
|
||||
RunInNewThread(Sub()
|
||||
Thread.Sleep(2000)
|
||||
TaskPingHost.Start(True, IsForceRestart:=True)
|
||||
End Sub, "HiPer Delayed Ping")
|
||||
End If
|
||||
'刷新完成页面
|
||||
SetLoadDesc("正在加载完成页面……", "加载完成页面")
|
||||
RunInUiWait(AddressOf FrmLinkHiper.WatcherTimer1)
|
||||
End Sub
|
||||
Private Shared PingNodes As Integer, AllNodes As List(Of String)
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "进程管理"
|
||||
|
||||
Private Shared _HiperState As LoadState = LoadState.Waiting
|
||||
Public Shared Property HiperState As LoadState
|
||||
Get
|
||||
Return _HiperState
|
||||
End Get
|
||||
Set(value As LoadState)
|
||||
_HiperState = value
|
||||
RunInUi(Sub() If FrmLinkLeft IsNot Nothing Then CType(FrmLinkLeft.ItemHiper.Buttons(0), MyIconButton).Visibility = If(HiperState = LoadState.Finished OrElse HiperState = LoadState.Loading, Visibility.Visible, Visibility.Collapsed))
|
||||
End Set
|
||||
End Property
|
||||
Public Shared Sub ModuleStopManually() '关闭联机模块按钮
|
||||
HiperExit(False)
|
||||
End Sub
|
||||
|
||||
Private Shared HiperIp As String = Nothing
|
||||
Private Shared HiperProcessId As Integer = -1, McbProcessId As Integer = -1
|
||||
Private Shared HiperCertTime As Date = Date.Now
|
||||
|
||||
''' <summary>
|
||||
''' 若程序正在运行,则结束程序进程,同时初始化状态数据。返回是否关闭了相关进程。
|
||||
''' </summary>
|
||||
Public Shared Function HiperStop(SleepWhenKilled As Boolean) As Boolean
|
||||
HiperStop = False
|
||||
'修改凭证
|
||||
Dim ConfigContent As String = ReadFile(PathHiper & "config.yml")
|
||||
If Not ConfigContent.Contains("enable: false") Then
|
||||
WriteFile(PathHiper & "config.yml", ConfigContent & vbCrLf & "enable: false")
|
||||
End If
|
||||
'关闭所有进程
|
||||
For Each ProcessObject In Process.GetProcesses
|
||||
Dim IsHiper As Boolean = ProcessObject.ProcessName = "HiPer 联机模块"
|
||||
Dim IsMcb As Boolean = ProcessObject.ProcessName = "MCB 联机模块"
|
||||
If Not IsHiper AndAlso Not IsMcb Then Continue For
|
||||
HiperStop = True
|
||||
Try
|
||||
If IsMcb Then
|
||||
ProcessObject.Kill()
|
||||
Log("[HiPer] 已结束进程 PID " & ProcessObject.Id & ":" & ProcessObject.ProcessName)
|
||||
If HiperStop AndAlso SleepWhenKilled Then Thread.Sleep(1000) '等待 1 秒确认进程已退出
|
||||
Else 'IsHiper
|
||||
If SleepWhenKilled Then
|
||||
Thread.Sleep(4000) '等待 4 秒确认进程已退出
|
||||
If Not ProcessObject.HasExited Then
|
||||
ProcessObject.Kill()
|
||||
Log("[HiPer] 已结束进程 PID " & ProcessObject.Id & ":" & ProcessObject.ProcessName)
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "结束进程失败(" & ProcessObject.Id & "," & ProcessObject.ProcessName & ")")
|
||||
End Try
|
||||
Next
|
||||
'初始化
|
||||
HiperState = LoadState.Waiting
|
||||
HiperProcessId = -1 : McbProcessId = -1
|
||||
HiperCertTime = Nothing
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 启动程序,并等待初始化完成后退出运行,同时更新 HiperIp。
|
||||
''' 若启动失败,则会直接抛出异常。
|
||||
''' 若程序正在运行,则会先停止其运行。
|
||||
''' </summary>
|
||||
Public Shared Sub HiperStart(Task As LoaderTask(Of Integer, Integer))
|
||||
Try
|
||||
SetLoadDesc("正在启动联机模块……", "启动联机模块")
|
||||
PossibleFailReason = Nothing
|
||||
'启动 Hiper
|
||||
Log("[Hiper] 启动 Hiper 进程")
|
||||
DeleteDirectory(PathHiper & "logs") '清理日志
|
||||
Dim HiperInfo = New ProcessStartInfo With {
|
||||
.FileName = "wscript",
|
||||
.Arguments = """" & PathHiper & "HiPer 联机模块.vbs""",
|
||||
.Verb = "runas" '需要管理员权限
|
||||
}
|
||||
Dim HiperVbsProcess As New Process() With {.StartInfo = HiperInfo}
|
||||
HiperVbsProcess.Start()
|
||||
'查找真正的 Hiper 进程
|
||||
SetLoadDesc("联机模块正在启动……", "联机模块加载")
|
||||
Do
|
||||
Dim GotProcesses = Process.GetProcesses.
|
||||
Where(Function(l) l.ProcessName = "HiPer 联机模块" AndAlso Math.Abs((l.StartTime - Date.Now).TotalMinutes) < 1)
|
||||
If GotProcesses.Count > 0 Then
|
||||
HiperProcessId = GotProcesses.First.Id
|
||||
Log("[Hiper] 已发现 Hiper 进程,PID:" & HiperProcessId)
|
||||
Exit Do
|
||||
End If
|
||||
Thread.Sleep(50)
|
||||
Loop While Task.State = LoadState.Loading AndAlso Not Task.IsAborted
|
||||
If HiperProcessId = -1 Then Throw New Exception("联机模块未能成功启动!")
|
||||
HiperState = LoadState.Loading
|
||||
Task.Progress = 0.15
|
||||
'抓取日志
|
||||
Dim LogLine As Integer = 0
|
||||
Do
|
||||
Thread.Sleep(100)
|
||||
If Not File.Exists(PathHiper & "logs\hiper.log") Then Continue Do
|
||||
Dim LogLines As String() = ReadFile(PathHiper & "logs\hiper.log").TrimEnd(vbLf).Split(vbLf)
|
||||
For i = LogLine To LogLines.Count - 1
|
||||
HiperLogLine(LogLines(i), Task)
|
||||
Next
|
||||
LogLine = LogLines.Count
|
||||
Loop While HiperState = LoadState.Loading AndAlso Not Task.IsAborted AndAlso Process.GetProcesses.Any(Function(l) l.Id = HiperProcessId)
|
||||
'输出
|
||||
If HiperState = LoadState.Finished Then
|
||||
Log("[Hiper] Hiper 启动完成")
|
||||
ElseIf PossibleFailReason IsNot Nothing AndAlso PossibleFailReason.Contains("索引码已过期") Then
|
||||
Throw New CertOutdatedException()
|
||||
Else
|
||||
Throw New Exception(If(PossibleFailReason, "联机模块因未知原因启动失败!"))
|
||||
End If
|
||||
'启动 MCB
|
||||
Task.Progress = 0.25
|
||||
If Not IsServerSide Then
|
||||
Try
|
||||
Log("[Hiper] 启动 MCB 进程")
|
||||
Dim McbInfo = New ProcessStartInfo With {
|
||||
.FileName = PathHiper & "MCB 联机模块.exe", .WorkingDirectory = PathHiper,
|
||||
.UseShellExecute = False, .CreateNoWindow = True,
|
||||
.RedirectStandardError = True, .RedirectStandardOutput = True,
|
||||
.Arguments = "-addr " & HostIp & ":" & HostPort & " -motd ""PCL2 联机房间"""
|
||||
}
|
||||
Dim McbProcess As New Process() With {.StartInfo = McbInfo}
|
||||
McbProcess.Start()
|
||||
McbProcessId = McbProcess.Id
|
||||
Catch ex As Exception
|
||||
Throw New Exception("联机模块组件启动失败", ex)
|
||||
End Try
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Try
|
||||
HiperStop(True) '由于启动失败停止进程
|
||||
Catch
|
||||
End Try
|
||||
HiperState = LoadState.Failed
|
||||
Throw
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'Hiper 日志
|
||||
Private Shared Sub HiperLogLine(Content As String, Task As LoaderTask(Of Integer, Integer))
|
||||
|
||||
'检查报错
|
||||
Dim ContentTest As String = Content.ToLower
|
||||
Dim ErrorMessage As String = Nothing
|
||||
Dim ContentJson As JObject = Nothing
|
||||
If Content.StartsWith("{""") AndAlso Content.EndsWith("}") Then
|
||||
ContentJson = GetJson(Content)
|
||||
ContentTest = If(ContentJson("error"), ContentJson("msg")).ToString.ToLower
|
||||
ErrorMessage = ContentJson("error")
|
||||
End If
|
||||
If ContentTest.Contains("hiper certificate for this host is expired") Then
|
||||
PossibleFailReason = "$你的索引码已过期,请更换新的索引码!"
|
||||
ElseIf ContentTest.Contains("error creating interface: access is denied") Then
|
||||
PossibleFailReason = "$没有获得管理员权限,无法创建网络通道!"
|
||||
ElseIf ContentTest.Contains("cannot create a file when that file already exists") Then
|
||||
PossibleFailReason = "$请不要重复开启多个联机模块!"
|
||||
ElseIf Content.Contains("failed to load config") Then
|
||||
PossibleFailReason = "$索引码文件内容存在错误!"
|
||||
ElseIf Content.Contains("system cannot find the file specified") Then
|
||||
PossibleFailReason = "$创建网络通道失败!" & vbCrLf & "如果你曾启动过 VPN 软件,请先打开那个软件,然后关掉它,最后再重试。虽然不知道为啥,但这样大概管用……"
|
||||
End If
|
||||
If PossibleFailReason Is Nothing AndAlso ErrorMessage IsNot Nothing Then PossibleFailReason = ErrorMessage
|
||||
|
||||
'检查结束
|
||||
If ContentJson IsNot Nothing Then
|
||||
Dim Message As String = ContentJson("msg")
|
||||
If Message = "HiPer interface is active" Then
|
||||
HiperIp = ContentJson("network").ToString.Split("/").First
|
||||
If IsServerSide Then HostIp = HiperIp
|
||||
Log("[Hiper] Hiper 启动完成,IP:" & HiperIp)
|
||||
HiperState = LoadState.Finished
|
||||
ElseIf Message = "Validity of client certificate" Then
|
||||
Dim VaildTime As String = ContentJson("valid")
|
||||
Date.TryParseExact(VaildTime, "yyyy-MM-dd HH:mm:ss", Globalization.CultureInfo.InvariantCulture, Globalization.DateTimeStyles.None, HiperCertTime)
|
||||
Log("[Hiper] 索引码到期时间:" & HiperCertTime.ToString)
|
||||
Setup.Set("LinkHiperCertTime", HiperCertTime.ToString)
|
||||
End If
|
||||
End If
|
||||
|
||||
'写入日志
|
||||
If ModeDebug OrElse Content.Contains("""error""") Then Log("[Hiper] " & Content)
|
||||
|
||||
End Sub
|
||||
Private Shared PossibleFailReason As String = Nothing
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "监视线程"
|
||||
|
||||
'主 Timer 线程
|
||||
Private IsWatcherStarted As Boolean = False
|
||||
Private Sub WatcherThread()
|
||||
Dim Sec15 As Integer = 0
|
||||
Do While True
|
||||
Try
|
||||
For i = 1 To 5
|
||||
Thread.Sleep(200)
|
||||
If InitLoader.State = LoadState.Loading Then
|
||||
RunInUi(AddressOf UpdateProgress)
|
||||
End If
|
||||
Next
|
||||
Thread.Sleep(1000)
|
||||
Sec15 += 1
|
||||
WatcherTimer1()
|
||||
If Sec15 = 15 Then
|
||||
Sec15 = 0
|
||||
WatcherTimer15()
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "联机模块主时钟出错", LogLevel.Feedback)
|
||||
Thread.Sleep(20000)
|
||||
End Try
|
||||
Loop
|
||||
End Sub
|
||||
|
||||
'每 1 秒执行的 Timer
|
||||
Private Sub WatcherTimer1()
|
||||
If HiperState <> LoadState.Finished Then Exit Sub
|
||||
RunInUi(Sub()
|
||||
'索引码剩余时间
|
||||
Dim Span As TimeSpan = HiperCertTime - Date.Now
|
||||
If Span.TotalDays >= 30 Then
|
||||
LabFinishTime.Text = "> 30 天"
|
||||
ElseIf Span.TotalDays >= 4 Then
|
||||
LabFinishTime.Text = Span.Days & " 天"
|
||||
ElseIf Span.TotalDays >= 1 Then
|
||||
LabFinishTime.Text = Span.Days & " 天" & If(Span.Hours > 0, " " & Span.Hours & " 小时", "")
|
||||
ElseIf Span.TotalMinutes >= 10 Then
|
||||
LabFinishTime.Text = Span.Hours & ":" & Span.Minutes.ToString.PadLeft(2, "0") & "'"
|
||||
Else
|
||||
LabFinishTime.Text = Span.Minutes & "'" & Span.Seconds.ToString.PadLeft(2, "0") & """"
|
||||
End If
|
||||
'提示索引码即将到期
|
||||
If Span.TotalSeconds <= 5 * 60 AndAlso Span.TotalSeconds > 5 * 60 - 1 AndAlso Setup.Get("LinkHiperCertWarn") Then
|
||||
MyMsgBox("你的索引码还有不到 5 分钟就要过期了!" & vbCrLf & "你可以在设置中关闭这个提示……", "索引码即将过期", "我知道了……")
|
||||
ShowWindowToTop(Handle)
|
||||
Beep()
|
||||
End If
|
||||
'检查索引码到期
|
||||
If Span.TotalSeconds < 2 Then
|
||||
LabCertTitle.Text = "索引码已过期"
|
||||
LabCertDesc.Text = "你的 HiPer 索引码已经过期,请输入新的索引码。" & vbCrLf & "如果实在没有索引码,可以在左侧选择 IOI 方式联机。"
|
||||
TextCert.Text = ""
|
||||
HiperExit(True)
|
||||
ShowWindowToTop(Handle)
|
||||
Beep()
|
||||
Exit Sub
|
||||
End If
|
||||
'网络质量
|
||||
Dim QualityScore As Integer = If(IpIsInChina, 0, -2)
|
||||
QualityScore -= Math.Ceiling((Math.Min(PingTime, 600) + Math.Min(PingNodes, 600)) / 80)
|
||||
Select Case QualityScore
|
||||
Case Is >= -1
|
||||
LabFinishQuality.Text = "优秀"
|
||||
Case Is >= -2
|
||||
LabFinishQuality.Text = "优良"
|
||||
Case Is >= -3
|
||||
LabFinishQuality.Text = "良好"
|
||||
Case Is >= -5
|
||||
LabFinishQuality.Text = "一般"
|
||||
Case Is >= -7
|
||||
LabFinishQuality.Text = "较差"
|
||||
Case Else
|
||||
LabFinishQuality.Text = "很差"
|
||||
End Select
|
||||
'Ping
|
||||
If HostPing <> -1 Then
|
||||
If FrmLinkHiper IsNot Nothing AndAlso FrmLinkHiper.LabFinishPing.IsLoaded Then
|
||||
FrmLinkHiper.LabFinishPing.Text = HostPing & "ms"
|
||||
End If
|
||||
End If
|
||||
End Sub)
|
||||
End Sub
|
||||
'每 15 秒执行的 Timer
|
||||
Private Shared HostPing As Integer = -1
|
||||
Private Sub WatcherTimer15()
|
||||
If Not (HiperState = LoadState.Finished OrElse HiperState = LoadState.Loading) Then Exit Sub
|
||||
'检查 HiPer 崩溃
|
||||
Try
|
||||
Process.GetProcessById(HiperProcessId)
|
||||
Catch
|
||||
Dim LogLines = ReadFile(PathHiper & "logs\hiper.log").TrimEnd(vbLf).Split(vbLf)
|
||||
HiperExit(False)
|
||||
MyMsgBox("由于联机模块异常退出,已退出联机房间。" & vbCrLf & vbCrLf &
|
||||
"联机模块最后的日志:" & vbCrLf & Join(LogLines.Skip(LogLines.Count - 3).ToList, vbCrLf), "联机断开")
|
||||
End Try
|
||||
'下面的部分需要完全完成加载
|
||||
If HiperState <> LoadState.Finished Then Exit Sub
|
||||
'检查 MCB 崩溃
|
||||
Try
|
||||
If Not IsServerSide Then Process.GetProcessById(McbProcessId)
|
||||
Catch
|
||||
HiperExit(False)
|
||||
MyMsgBox("由于 MCB 联机模块异常退出,已退出联机房间。", "联机断开")
|
||||
End Try
|
||||
'重新检查 Ping
|
||||
If Not IsServerSide Then
|
||||
Dim PingHostFailedCount As Integer = 0
|
||||
Do
|
||||
TaskPingHost.WaitForExit(True, IsForceRestart:=True)
|
||||
If TaskPingHost.Output = -1 Then
|
||||
PingHostFailedCount += 1
|
||||
Log("[HiPer] Ping 房主失败(第 " & PingHostFailedCount & " 次)")
|
||||
If PingHostFailedCount >= 3 Then
|
||||
HiperExit(False) : MyMsgBox("与房主断开连接,已退出联机房间。", "联机断开") : Exit Sub
|
||||
End If
|
||||
Else
|
||||
If PingHostFailedCount > 0 Then Log("[HiPer] Ping 房主已恢复成功(" & HostPing & "ms)")
|
||||
Exit Do
|
||||
End If
|
||||
Loop While True
|
||||
End If
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "PanCert | 索引码输入页面"
|
||||
|
||||
'检测输入
|
||||
Private Sub TextCert_ValidateChanged(sender As Object, e As EventArgs) Handles TextCert.ValidateChanged
|
||||
BtnCertDone.IsEnabled = TextCert.ValidateResult = ""
|
||||
End Sub
|
||||
Private Sub TextCert_KeyUp(sender As Object, e As KeyEventArgs) Handles TextCert.KeyUp
|
||||
If e.Key = Key.Enter AndAlso BtnCertDone.IsEnabled Then BtnCertDone_Click() '允许回车确认
|
||||
End Sub
|
||||
|
||||
'确认
|
||||
Private Sub BtnCertDone_Click() Handles BtnCertDone.Click
|
||||
CurrentSubpage = Subpages.PanSelect
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "PanSelect | 种类选择页面"
|
||||
|
||||
'返回
|
||||
Private Sub BtnSelectReturn_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnSelectReturn.MouseLeftButtonUp
|
||||
LabCertTitle.Text = "输入索引码"
|
||||
LabCertDesc.Text = "你需要获取索引码才能使用 HiPer。" & vbCrLf & "如果实在没有索引码,可以在左侧选择 IOI 方式联机。"
|
||||
CurrentSubpage = Subpages.PanCert
|
||||
End Sub
|
||||
|
||||
'创建房间
|
||||
Private Sub BtnSelectCreate_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnSelectCreate.MouseLeftButtonUp
|
||||
'获取端口号
|
||||
Dim PortInput As String = MyMsgBoxInput("", New ObjectModel.Collection(Of Validate) From {
|
||||
New ValidateInteger(2, 65535),
|
||||
New ValidateExceptSame({"55555", "55557"}, "端口不能为 %!")
|
||||
}, "在 MC 的暂停画面选择【对局域网开放】", "输入端口号", "确定", "取消")
|
||||
If PortInput Is Nothing Then Exit Sub
|
||||
'开始
|
||||
RoomCreate(Val(PortInput))
|
||||
End Sub
|
||||
Private Sub RoomCreate(Port As Integer)
|
||||
'记录信息
|
||||
HostIp = Nothing : HostPort = Port
|
||||
IsServerSide = True
|
||||
'启动
|
||||
InitLoader.Start(IsForceRestart:=True)
|
||||
End Sub
|
||||
|
||||
'加入房间
|
||||
Private Sub BtnSelectJoin_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnSelectJoin.MouseLeftButtonUp
|
||||
'获取信息
|
||||
Dim Code As String = MyMsgBoxInput("", New ObjectModel.Collection(Of Validate) From {New ValidateLength(8, 99)}, "",
|
||||
"输入联机码", "确定", "取消")
|
||||
If Code Is Nothing Then Exit Sub
|
||||
'记录信息
|
||||
If Not Code.EndsWith(RequestVersion) OrElse Not Code.StartsWith("P") Then GoTo WrongCode
|
||||
Dim Ip As String, Port As Integer
|
||||
Try
|
||||
Dim IpAndPort As Long = RadixConvert(Code.Substring(1, Code.Length - 2).ToUpper, 36, 10)
|
||||
'IpAndPort = HostPort + IpParts(0) * 65536 + IpParts(1) * 65536 * 256 + IpParts(2) * 65536 * 256 * 256 + IpParts(3) * 65536 * 256 * 256 * 256
|
||||
Ip = Math.Floor(IpAndPort / (65536L * 256 * 256 * 256))
|
||||
IpAndPort = IpAndPort Mod (65536L * 256 * 256 * 256)
|
||||
Ip = Math.Floor(IpAndPort / (65536L * 256 * 256)) & "." & Ip
|
||||
IpAndPort = IpAndPort Mod (65536L * 256 * 256)
|
||||
Ip = Math.Floor(IpAndPort / (65536L * 256)) & "." & Ip
|
||||
IpAndPort = IpAndPort Mod (65536L * 256)
|
||||
Ip = Math.Floor(IpAndPort / (65536L)) & "." & Ip
|
||||
Port = IpAndPort Mod 65536
|
||||
Catch
|
||||
GoTo WrongCode
|
||||
End Try
|
||||
'启动
|
||||
RoomJoin(Ip, Port)
|
||||
Exit Sub
|
||||
WrongCode:
|
||||
If Not Code.StartsWith("P") AndAlso Code.Length >= 49 Then Hint("你输入的可能是 IOI 的联机码,请在左侧的联机方式中选择 IOI!", HintType.Critical) : Exit Sub
|
||||
If Code.StartsWith("P") AndAlso Not Code.EndsWith(RequestVersion) Then Hint("你的 PCL2 版本与房主的 PCL2 版本不一致!", HintType.Critical) : Exit Sub
|
||||
Hint("你输入的联机码无效!", HintType.Critical)
|
||||
End Sub
|
||||
Private Sub RoomJoin(Ip As String, Port As Integer)
|
||||
'记录信息
|
||||
HostIp = Ip : HostPort = Port
|
||||
IsServerSide = False
|
||||
'启动
|
||||
InitLoader.Start(IsForceRestart:=True)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "PanLoad | 加载中页面"
|
||||
|
||||
'承接状态切换的 UI 改变
|
||||
Private Sub OnLoadStateChanged(Loader As LoaderBase, NewState As LoadState, OldState As LoadState)
|
||||
Select Case NewState
|
||||
Case LoadState.Loading
|
||||
UpdateProgress(0)
|
||||
If IsServerSide Then
|
||||
LabLoadTitle.Text = "正在创建联机房间"
|
||||
Log("[Hiper] 正在创建联机房间,端口 " & HostPort)
|
||||
Else
|
||||
LabLoadTitle.Text = "正在加入联机房间"
|
||||
Log("[Hiper] 正在加入联机房间,目标 IP " & HostIp & ":" & HostPort)
|
||||
End If
|
||||
LabLoadDesc.Text = "正在初始化……"
|
||||
LoadStep = "准备初始化"
|
||||
Case LoadState.Failed
|
||||
UpdateProgress(1)
|
||||
If IsServerSide Then
|
||||
LabLoadTitle.Text = "创建联机房间失败"
|
||||
Else
|
||||
LabLoadTitle.Text = "加入联机房间失败"
|
||||
End If
|
||||
Dim RealException As Exception = If(Loader.Error.InnerException, Loader.Error)
|
||||
If TypeOf RealException Is CertOutdatedException Then
|
||||
LabCertTitle.Text = "索引码无效"
|
||||
LabCertDesc.Text = "你的 HiPer 索引码无效或者已经过期!" & vbCrLf & "请重新输入索引码。"
|
||||
HiperExit(True)
|
||||
ElseIf RealException.Message.StartsWith("$") Then
|
||||
LabLoadDesc.Text = RealException.Message.TrimStart("$") & vbCrLf &
|
||||
"点击镐子重试,或者点击灰色的 × 取消。"
|
||||
Else
|
||||
LabLoadDesc.Text = LoadStep & "失败:" & GetExceptionSummary(RealException) & vbCrLf &
|
||||
"点击镐子重试,或者点击灰色的 × 取消。"
|
||||
End If
|
||||
Log(Loader.Error, "HiPer 联机尝试失败")
|
||||
Case LoadState.Finished
|
||||
UpdateProgress(1)
|
||||
CurrentSubpage = Subpages.PanFinish
|
||||
BtnFinishPing.Visibility = If(IsServerSide, Visibility.Collapsed, Visibility.Visible)
|
||||
LineFinishPing.Visibility = If(IsServerSide, Visibility.Collapsed, Visibility.Visible)
|
||||
BtnFinishCopy.Visibility = If(IsServerSide, Visibility.Visible, Visibility.Collapsed)
|
||||
If IsServerSide Then
|
||||
LabFinishTitle.Text = "已创建联机房间"
|
||||
LabFinishDesc.Text = "已在端口 " & HostPort & " 创建了联机房间。" & vbCrLf & "点击下方的复制联机码按钮,然后把联机码发给朋友吧!"
|
||||
Else
|
||||
LabFinishTitle.Text = "已加入联机房间"
|
||||
LabFinishDesc.Text = "启动游戏,进入多人游戏页面后稍等片刻,房间就会出现在服务器列表的最下方。" & vbCrLf & "如果提示无效会话,不要退出联机房间,重新启动游戏即可!"
|
||||
End If
|
||||
LabFinishIp.Text = HostIp & ":" & HostPort
|
||||
Log("[Hiper] 已完成连接")
|
||||
End Select
|
||||
End Sub
|
||||
Private Shared LoadStep As String = "准备初始化"
|
||||
Private Shared Sub SetLoadDesc(Intro As String, [Step] As String)
|
||||
Log("[Hiper] 连接步骤:" & Intro)
|
||||
LoadStep = [Step]
|
||||
RunInUiWait(Sub()
|
||||
If FrmLinkHiper Is Nothing OrElse Not FrmLinkHiper.LabLoadDesc.IsLoaded Then Exit Sub
|
||||
FrmLinkHiper.LabLoadDesc.Text = Intro
|
||||
FrmLinkHiper.UpdateProgress()
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
'承接重试
|
||||
Private Sub CardLoad_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles CardLoad.MouseLeftButtonUp
|
||||
If Not InitLoader.State = LoadState.Failed Then Exit Sub
|
||||
InitLoader.Start(IsForceRestart:=True)
|
||||
End Sub
|
||||
|
||||
'取消加载
|
||||
Private Sub CancelLoad() Handles BtnLoadCancel.Click
|
||||
If InitLoader.State = LoadState.Loading Then
|
||||
CurrentSubpage = Subpages.PanSelect
|
||||
InitLoader.Abort()
|
||||
Else
|
||||
InitLoader.State = LoadState.Waiting
|
||||
End If
|
||||
HiperStop(False)
|
||||
End Sub
|
||||
|
||||
'进度改变
|
||||
Private Sub UpdateProgress(Optional Value As Double = -1)
|
||||
If Value = -1 Then Value = InitLoader.Progress
|
||||
Dim DisplayingProgress As Double = ColumnProgressA.Width.Value
|
||||
If Math.Round(Value - DisplayingProgress, 3) = 0 Then Exit Sub
|
||||
If DisplayingProgress > Value Then
|
||||
ColumnProgressA.Width = New GridLength(Value, GridUnitType.Star)
|
||||
ColumnProgressB.Width = New GridLength(1 - Value, GridUnitType.Star)
|
||||
AniStop("Hiper Progress")
|
||||
Else
|
||||
Dim NewProgress As Double = If(Value = 1, 1, (Value - DisplayingProgress) * 0.2 + DisplayingProgress)
|
||||
AniStart({
|
||||
AaGridLengthWidth(ColumnProgressA, NewProgress - ColumnProgressA.Width.Value, 300, Ease:=New AniEaseOutFluent),
|
||||
AaGridLengthWidth(ColumnProgressB, (1 - NewProgress) - ColumnProgressB.Width.Value, 300, Ease:=New AniEaseOutFluent)
|
||||
}, "Hiper Progress")
|
||||
End If
|
||||
End Sub
|
||||
Private Sub CardResized() Handles CardLoad.SizeChanged
|
||||
RectProgressClip.Rect = New Rect(0, 0, CardLoad.ActualWidth, 12)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "PanFinish | 加载完成页面"
|
||||
|
||||
'复制 IP
|
||||
Private Sub BtnFinishIp_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnFinishIp.MouseLeftButtonUp
|
||||
ClipboardSet(LabFinishIp.Text)
|
||||
End Sub
|
||||
|
||||
'退出
|
||||
Private Sub BtnFinishExit_Click(sender As Object, e As EventArgs) Handles BtnFinishExit.Click
|
||||
If IsServerSide AndAlso MyMsgBox("你确定要关闭联机房间吗?", "确认退出", "确定", "取消", IsWarn:=True) = 2 Then Exit Sub
|
||||
HiperExit(False)
|
||||
End Sub
|
||||
|
||||
'复制联机码
|
||||
Private Sub BtnFinishCopy_Click(sender As Object, e As EventArgs) Handles BtnFinishCopy.Click
|
||||
Dim IpParts = HostIp.Split(".").Select(Function(l) Val(l)).ToList
|
||||
Dim IpAndPort As Long = HostPort + IpParts(0) * 65536 + IpParts(1) * 65536 * 256 + IpParts(2) * 65536 * 256 * 256 + IpParts(3) * 65536 * 256 * 256 * 256
|
||||
ClipboardSet("P" & RadixConvert(IpAndPort, 10, 36) & RequestVersion, False)
|
||||
Hint("已复制联机码!", HintType.Finish)
|
||||
End Sub
|
||||
|
||||
'Ping 房主
|
||||
Private Sub BtnFinishPing_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnFinishPing.MouseLeftButtonUp
|
||||
LabFinishPing.Text = "检测中"
|
||||
If TaskPingHost.State = LoadState.Loading Then Exit Sub
|
||||
TaskPingHost.Start(True, IsForceRestart:=True)
|
||||
End Sub
|
||||
Private Shared TaskPingHost As New LoaderTask(Of Boolean, Integer)("HiPer Ping Host",
|
||||
Sub(Task As LoaderTask(Of Boolean, Integer))
|
||||
HostPing = -1
|
||||
HostPing = Ping(HostIp, 5000, Task.Input)
|
||||
End Sub)
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "子页面管理"
|
||||
|
||||
Public Enum Subpages
|
||||
PanCert
|
||||
PanSelect
|
||||
PanFinish
|
||||
End Enum
|
||||
Private _CurrentSubpage As Subpages = Subpages.PanCert
|
||||
Public Property CurrentSubpage As Subpages
|
||||
Get
|
||||
Return _CurrentSubpage
|
||||
End Get
|
||||
Set(value As Subpages)
|
||||
If _CurrentSubpage = value Then Exit Property
|
||||
_CurrentSubpage = value
|
||||
Log("[Hiper] 子页面更改为 " & GetStringFromEnum(value))
|
||||
PageOnContentExit()
|
||||
If value = Subpages.PanSelect Then
|
||||
LabSelectCode.Text = "(" & TextCert.Text.Substring(0, Math.Min(TextCert.Text.Length, 3)) & "…)"
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Private Sub PageLinkHiper_OnPageEnter() Handles Me.PageEnter
|
||||
FrmLinkHiper.PanCert.Visibility = If(CurrentSubpage = Subpages.PanCert, Visibility.Visible, Visibility.Collapsed)
|
||||
FrmLinkHiper.PanSelect.Visibility = If(CurrentSubpage = Subpages.PanSelect, Visibility.Visible, Visibility.Collapsed)
|
||||
FrmLinkHiper.PanFinish.Visibility = If(CurrentSubpage = Subpages.PanFinish, Visibility.Visible, Visibility.Collapsed)
|
||||
End Sub
|
||||
|
||||
Private Shared Sub HiperExit(ExitToCertPage As Boolean)
|
||||
Log("[Hiper] 要求退出 Hiper(当前加载器状态为 " & GetStringFromEnum(InitLoader.State) & ")")
|
||||
HiperStop(False)
|
||||
If InitLoader.State = LoadState.Loading Then InitLoader.Abort()
|
||||
If InitLoader.State = LoadState.Failed Then InitLoader.State = LoadState.Waiting
|
||||
RunInUi(Sub()
|
||||
If FrmLinkHiper Is Nothing OrElse Not FrmLinkHiper.IsLoaded Then Exit Sub
|
||||
FrmLinkHiper.CurrentSubpage = If(ExitToCertPage, Subpages.PanCert, Subpages.PanSelect)
|
||||
FrmLinkHiper.PageOnContentExit()
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
End Class
|
||||
@@ -0,0 +1,50 @@
|
||||
<local:MyPageRight
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:System="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:PCL" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" x:Class="PageLinkIoi"
|
||||
d:DesignWidth="800" d:DesignHeight="800">
|
||||
<Grid>
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel Orientation="Vertical" Margin="25,10">
|
||||
<local:MyCard Margin="0,15,0,0" x:Name="CardUser" Title="已连接的玩家 (0)">
|
||||
<StackPanel Margin="20,37,20,15">
|
||||
<local:MyHint Margin="5,2,5,8" x:Name="LabHint" IsWarn="False" />
|
||||
<StackPanel x:Name="PanUserList" />
|
||||
<Grid Height="35" Margin="5,8,5,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnLeftCreate" Grid.Column="0" MinWidth="140" Text="建立连接" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||
<local:MyButton x:Name="BtnLeftCopy" Grid.Column="1" MinWidth="140" Text="复制联机码" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,15" Title="房间列表" x:Name="CardRoom">
|
||||
<StackPanel Margin="20,37,20,15">
|
||||
<StackPanel x:Name="PanRoom">
|
||||
<!--<local:MyListItem Type="Clickable" PaddingRight="60" Height="40" Title="00ll00" Info="已连接,1100 ms" Logo="pack://application:,,,/images/Blocks/Grass.png">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton ToolTip="刷新" ToolTipService.Placement="Bottom" ToolTipService.HorizontalOffset="-10" ToolTipService.VerticalOffset="5" ToolTipService.ShowDuration="2333333" ToolTipService.InitialShowDelay="200" LogoScale="0.85" Logo="M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z" />
|
||||
<local:MyIconButton ToolTip="断开" ToolTipService.Placement="Bottom" ToolTipService.HorizontalOffset="-10" ToolTipService.VerticalOffset="5" ToolTipService.ShowDuration="2333333" ToolTipService.InitialShowDelay="200" LogoScale="0.85" Logo="F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>-->
|
||||
</StackPanel>
|
||||
<local:MyListItem x:Name="BtnCreate" Type="Clickable" Title="创建房间" Height="34" PaddingLeft="0"
|
||||
Logo="M512.277 954.412c-118.89 0-230.659-46.078-314.73-129.73S67.12 629.666 67.12 511.222s46.327-229.744 130.398-313.427 195.82-129.73 314.73-129.73 230.659 46.078 314.72 129.73S957.397 392.81 957.397 511.183 911.078 740.96 826.97 824.642s-195.8 129.77-314.692 129.77z m0-822.784c-101.972 0-197.809 39.494-269.865 111.222s-111.7 166.997-111.7 268.373 39.653 196.695 111.67 268.335S410.246 890.78 512.248 890.78s197.809-39.484 269.865-111.222 111.7-166.998 111.67-268.374c-0.03-101.375-39.654-196.665-111.67-268.303S614.22 131.628 512.277 131.628z m222.585 347.8H544.073V288.64c-0.76-17.561-15.613-31.18-33.173-30.419-16.495 0.714-29.704 13.924-30.419 30.419v190.787H289.703c-17.56 0.761-31.179 15.614-30.419 33.174 0.715 16.494 13.924 29.703 30.42 30.418H480.48v190.788c0.761 17.56 15.614 31.179 33.174 30.419 16.494-0.715 29.703-13.925 30.418-30.42V543.02h190.788c17.56 0.762 32.413-12.857 33.173-30.418 0.762-17.561-12.858-32.414-30.419-33.174a31.683 31.683 0 0 0-2.753 0z" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
</local:MyScrollViewer>
|
||||
<local:MyCard Opacity="0" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="40,0" SnapsToDevicePixels="True" x:Name="PanLoad" UseAnimation="False">
|
||||
<local:MyLoading Text="正在加载联机模块" Margin="20,20,20,17" x:Name="Load" ShowProgress="True" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</local:MyCard>
|
||||
<Grid x:Name="PanAlways" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="15" Opacity="0.5">
|
||||
<local:MyTextButton Text="联机服务由 速聚 授权提供" EventType="打开网页" EventData="https://www.the.bb/zh-CN.html" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</local:MyPageRight>
|
||||
@@ -0,0 +1,44 @@
|
||||
<local:MyPageLeft x:Class="PageLinkLeft"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:PCL"
|
||||
mc:Ignorable="d" AnimatedControl="{Binding ElementName=PanItem}" MinWidth="150">
|
||||
<StackPanel Orientation="Vertical" x:Name="PanItem" Margin="0,12,0,0">
|
||||
<TextBlock Text="联机方式" Margin="13,6,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemHiper" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="1" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="HiPer"
|
||||
LogoScale="0.85" Logo="M554.496 170.496c141.312 0 256 114.688 256 256s-114.688 256-256 256H402.432c-22.016-1.536-39.424-19.968-39.424-42.496a42.391 42.391 0 0 1 42.496-42.496h149.504c94.208 0 170.496-76.288 170.496-170.496S648.704 256 554.496 256h-256C204.288 256 128 332.288 128 426.496c0 38.4 12.8 73.728 33.792 102.4 5.632 7.168 8.704 15.872 8.704 25.6A42.391 42.391 0 0 1 128 596.992c-11.264 0-20.992-4.096-28.672-11.264l-0.512 0.512c-35.328-44.032-56.32-99.328-56.32-159.744 0-141.312 114.688-256 256-256h256z m64 192h3.072c22.016 1.536 39.424 19.968 39.424 42.496a42.391 42.391 0 0 1-42.496 42.496H469.504c-94.208 0-170.496 76.288-170.496 170.496S375.296 788.48 469.504 788.48h256C819.712 788.48 896 712.192 896 617.984c0-38.4-12.8-73.728-33.792-102.4-5.632-7.168-8.704-15.872-8.704-25.6A42.391 42.391 0 0 1 896 447.488c11.264 0 20.992 4.096 28.672 11.264l0.512-0.512c35.328 44.032 56.32 99.328 56.32 159.744 0 141.312-114.688 256-256 256h-256c-141.312 0-256-114.688-256-256s114.688-256 256-256h148.992z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton ToolTip="关闭联机模块" Loaded="BtnHiperStop_Loaded" Click="BtnHiperStop_Click"
|
||||
ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5" ToolTipService.VerticalOffset="-2" ToolTipService.ShowDuration="2333333" ToolTipService.InitialShowDelay="200" LogoScale="0.7"
|
||||
Logo="M576 512l277.333333 277.333333-64 64-277.333333-277.333333L234.666667 853.333333 170.666667 789.333333l277.333333-277.333333L170.666667 234.666667 234.666667 170.666667l277.333333 277.333333L789.333333 170.666667 853.333333 234.666667 576 512z" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemIoi" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="2" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="IOI"
|
||||
LogoScale="0.85" Logo="M554.496 170.496c141.312 0 256 114.688 256 256s-114.688 256-256 256H402.432c-22.016-1.536-39.424-19.968-39.424-42.496a42.391 42.391 0 0 1 42.496-42.496h149.504c94.208 0 170.496-76.288 170.496-170.496S648.704 256 554.496 256h-256C204.288 256 128 332.288 128 426.496c0 38.4 12.8 73.728 33.792 102.4 5.632 7.168 8.704 15.872 8.704 25.6A42.391 42.391 0 0 1 128 596.992c-11.264 0-20.992-4.096-28.672-11.264l-0.512 0.512c-35.328-44.032-56.32-99.328-56.32-159.744 0-141.312 114.688-256 256-256h256z m64 192h3.072c22.016 1.536 39.424 19.968 39.424 42.496a42.391 42.391 0 0 1-42.496 42.496H469.504c-94.208 0-170.496 76.288-170.496 170.496S375.296 788.48 469.504 788.48h256C819.712 788.48 896 712.192 896 617.984c0-38.4-12.8-73.728-33.792-102.4-5.632-7.168-8.704-15.872-8.704-25.6A42.391 42.391 0 0 1 896 447.488c11.264 0 20.992 4.096 28.672 11.264l0.512-0.512c35.328 44.032 56.32 99.328 56.32 159.744 0 141.312-114.688 256-256 256h-256c-141.312 0-256-114.688-256-256s114.688-256 256-256h148.992z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton ToolTip="关闭联机模块" Loaded="BtnIoiStop_Loaded" Click="BtnIoiStop_Click"
|
||||
ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5" ToolTipService.VerticalOffset="-2" ToolTipService.ShowDuration="2333333" ToolTipService.InitialShowDelay="200" LogoScale="0.7"
|
||||
Logo="M576 512l277.333333 277.333333-64 64-277.333333-277.333333L234.666667 853.333333 170.666667 789.333333l277.333333-277.333333L170.666667 234.666667 234.666667 170.666667l277.333333 277.333333L789.333333 170.666667 853.333333 234.666667 576 512z" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<TextBlock Text="更多选项" Margin="13,18,5,4" Opacity="0.6" FontSize="12" />
|
||||
<local:MyListItem x:Name="ItemSetup" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="设置"
|
||||
LogoScale="0.85" Logo="M940.4 463.7L773.3 174.2c-17.3-30-49.2-48.4-83.8-48.4H340.2c-34.6 0-66.5 18.5-83.8 48.4L89.2 463.7c-17.3 30-17.3 66.9 0 96.8L256.4 850c17.3 30 49.2 48.4 83.8 48.4h349.2c34.6 0 66.5-18.5 83.8-48.4l167.2-289.5c17.3-29.9 17.3-66.8 0-96.8z m-94.6 96.8L725.9 768.1c-17.3 30-49.2 48.4-83.8 48.4H387.5c-34.6 0-66.5-18.5-83.8-48.4L183.9 560.5c-17.3-30-17.3-66.9 0-96.8l119.8-207.5c17.3-30 49.2-48.4 83.8-48.4h254.6c34.6 0 66.5 18.5 83.8 48.4l119.8 207.5c17.3 30 17.3 66.9 0.1 96.8z M522.3 321.2c-2.5-0.1-5-0.2-7.5-0.2-119.9 0-214 110.3-186.3 235 15.8 70.9 71.5 126.6 142.4 142.4 17.5 3.9 34.7 5.4 51.4 4.7 102.1-3.9 183.6-87.9 183.6-191 0.1-103-81.5-187-183.6-190.9z m68.6 269.1c-18.5 18-43 28.9-68.6 30.7l-6 0.3c-30.2 0.4-58.6-11.4-79.7-33-19.5-20.1-30.7-47-30.9-75-0.3-29.6 11.1-57.4 32-78.3 20.6-20.6 48-32 77.2-32 2.5 0 5 0.1 7.5 0.3 26.7 1.8 51.5 13.2 70.5 32.5 19.6 20 30.8 46.9 31.2 74.9 0.2 30.2-11.5 58.6-33.2 79.6z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="5" ToolTip="初始化设置" ToolTipService.Placement="Right" ToolTipService.ShowDuration="2333333" ToolTipService.InitialShowDelay="200" Click="Reset" Logo="M835.072 184.32l-77.824 81.92c-64.512-66.56-153.6-106.496-251.904-106.496-195.584 0-355.328 159.744-355.328 354.304 0 195.584 159.744 354.304 355.328 354.304 147.456 0 304.128-80.896 337.92-245.76 3.072-15.36-9.216-23.552-21.504-23.552l-72.704 0c-15.36 0-28.672 14.336-29.696 24.576 0 2.048 0 3.072-1.024 3.072-32.768 96.256-107.52 119.808-212.992 119.808-128 0-232.448-104.448-232.448-232.448s104.448-231.424 232.448-231.424c64.512 0 121.856 26.624 165.888 69.632l-101.376 100.352c-1.024 0-1.024 1.024-2.048 1.024-20.48 22.528-12.288 37.888 11.264 37.888l256 0c22.528 0 36.864-15.36 36.864-37.888L871.936 193.536C870.912 174.08 857.6 166.912 835.072 184.32z" LogoScale="0.9" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemHelp" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="5" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="常见问题"
|
||||
LogoScale="0.97" Logo="M520.6 620.3c-11.3-0.6-20.1-4-26.9-10.5-6.6-6.3-8.1-11-10.1-20.8-1.9-9.5-1.5-16.7-1-24.9l0.3-5.3c0.5-9.9 3.5-19.6 8.8-28.1 5.7-9 12.5-17.2 20.8-25.1 8.6-8 17.7-15.7 27-22.9 9.4-7.2 18.7-14.8 27.7-22.7 9-7.9 16.2-15.8 22.1-24.3 6.2-9 9.3-18.8 9.3-29.4 1.2-20.3-6.5-37.7-22.8-51.3-16-13.3-37.4-20-63.5-20-13.7 0-26.3 3.3-37.4 10-10.9 6.5-20.2 14.5-27.7 23.8-7.5 9.2-13.5 19-17.9 29.2-4.5 10.6-6.7 19.4-6.7 26.8 0 9.2-3.3 16-10.1 20.8-6.9 4.8-14.6 7.3-22.8 7.3h-1.3c-9-0.3-17-3.3-24.6-9.2-7.3-5.6-11.1-14.6-11.6-27.5-0.6-11.5 1.9-26.1 7.2-43.5 5.4-17.4 14.8-34.4 28.1-50.5 13.4-16.3 31.2-30.4 52.8-41.8 21.6-11.4 49.2-17.2 81.9-17.2 26.4 0 49.6 3.9 69.1 11.7 19.4 7.7 35.4 18.2 47.5 31.1l1.6 1.7c11.8 12.6 20.3 21.7 29.4 44.4 11.6 28.9 7.1 52.1 5.5 58.5-5.8 22.6-12.6 37.7-22.7 50.4-11.7 14.6-24.9 28.2-39.2 40.4-14 11.7-39.2 33.3-39.2 33.3-13.3 11.4-19.4 22.1-18.6 32.9V587c0.5 8.7-2.4 16.1-8.8 22.8-6.2 6.4-14.8 10-26.2 10.5zM519 766.1c-13 0-23.6-4.2-32.2-12.9-8.7-8.7-13-19-13-31.4 0-12.9 4.2-23.5 12.9-32.2 8.7-8.7 19.2-12.9 32.2-12.9 13 0 23.5 4.2 32.2 12.9s12.9 19.2 12.9 32.2c0 12.4-4.2 22.7-12.9 31.4-8.6 8.6-19.2 12.9-32.1 12.9z M515 928.3c-228.1 0-413.7-185.6-413.7-413.7S286.9 100.9 515 100.9s413.7 185.6 413.7 413.7c0.1 228.1-185.5 413.7-413.7 413.7z m0-747.4c-184 0-333.7 149.7-333.7 333.7S331 848.3 515 848.3s333.7-149.7 333.7-333.7S699 180.9 515 180.9z" />
|
||||
<local:MyListItem x:Name="ItemFeedback" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="6" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="关于与反馈"
|
||||
LogoScale="0.9" Logo="M613.717333 64.426667l3.413334 3.242666 331.861333 331.861334a85.333333 85.333333 0 0 1 3.2 117.269333l-3.2 3.413333L573.162667 896H960a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H64a21.333333 21.333333 0 0 1-21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h295.338667L74.069333 610.709333a85.333333 85.333333 0 0 1-3.221333-117.269333l3.2-3.413333 422.4-422.357334a85.333333 85.333333 0 0 1 117.269333-3.221333z m-20.629333 99.882666l-21.418667 321.493334a85.333333 85.333333 0 0 1-74.944 79.04l-4.522666 0.426666-321.493334 21.44 295.552 295.530667 422.4-422.378667L593.066667 164.309333z m-86.442667 13.824L184.533333 500.266667l301.994667-20.117334 20.117333-301.994666z" />
|
||||
</StackPanel>
|
||||
</local:MyPageLeft>
|
||||
@@ -0,0 +1,192 @@
|
||||
Imports NetFwTypeLib
|
||||
|
||||
Public Class PageLinkLeft
|
||||
|
||||
Private IsLoad As Boolean = False
|
||||
Private IsPageSwitched As Boolean = False '如果在 Loaded 前切换到其他页面,会导致触发 Loaded 时再次切换一次
|
||||
Private Sub PageLinkLeft_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
If IsLoad Then Exit Sub
|
||||
IsLoad = True
|
||||
'切换默认页面
|
||||
If IsPageSwitched Then Exit Sub
|
||||
ItemHiper.SetChecked(True, False, False)
|
||||
End Sub
|
||||
Private Sub PageOtherLeft_Unloaded(sender As Object, e As RoutedEventArgs) Handles Me.Unloaded
|
||||
IsPageSwitched = False
|
||||
End Sub
|
||||
|
||||
#Region "Windows 防火墙"
|
||||
|
||||
'为联机模块添加防火墙通行权限的函数库
|
||||
'不加防火墙权限你要我怎么办,这联机根本连都连不上,球球你们别看到防火墙就说是后门了,真的很恼火……
|
||||
|
||||
''' <summary>
|
||||
''' 获取某个文件是否被 Windows 防火墙阻止。
|
||||
''' </summary>
|
||||
Public Shared Function FirewallIsBlock(FilePath As String) As Boolean
|
||||
'获取配置
|
||||
If FirewallPolicy Is Nothing Then
|
||||
Try
|
||||
FirewallPolicy = FirewallPolicyGet()
|
||||
Catch ex As Exception
|
||||
Log(ex, "Windows 防火墙:可能关闭得太死了,根本检测不到,笑死", LogLevel.Normal)
|
||||
Return False
|
||||
End Try
|
||||
End If
|
||||
'检查是否开启
|
||||
If Not FirewallPolicy.CurrentProfile.FirewallEnabled Then
|
||||
Log("[Link] Windows 防火墙:防火墙关闭")
|
||||
Return False
|
||||
End If
|
||||
'检查是否允许例外
|
||||
If FirewallPolicy.CurrentProfile.ExceptionsNotAllowed Then
|
||||
Log("[Link] Windows 防火墙:防火墙开启,不允许例外")
|
||||
Return True
|
||||
End If
|
||||
'检查白名单
|
||||
Dim Target As String = FilePath.Replace(PathTemp.Split("\").First, "").ToLower
|
||||
For Each App As INetFwAuthorizedApplication In FirewallPolicy.CurrentProfile.AuthorizedApplications
|
||||
If ModeDebug Then Log("[Link] 防火墙白名单(" & App.Enabled & "):" & App.ProcessImageFileName)
|
||||
If Not App.Enabled Then Continue For
|
||||
'信标的奇妙盘符 E:0/xxxxx/xxx 导致误判……
|
||||
Dim FileNameTrimmed As String = App.ProcessImageFileName.Replace(App.ProcessImageFileName.Split("\").First, "")
|
||||
If App.ProcessImageFileName.ToLower.Contains(FilePath) Then
|
||||
Log("[Link] Windows 防火墙:开启,已在白名单中(" & FilePath & ")")
|
||||
Return False
|
||||
End If
|
||||
Next
|
||||
Log("[Link] Windows 防火墙:开启,未在白名单中(" & FilePath & ")")
|
||||
Return True
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 添加防火墙通行权限。需要管理员权限。
|
||||
''' </summary>
|
||||
Public Shared Sub FirewallAddAuthorized(DisplayName As String, FilePath As String)
|
||||
Log("[Link] Windows 防火墙:添加通行权限(" & FilePath & ")")
|
||||
'获取配置
|
||||
If FirewallPolicy Is Nothing Then FirewallPolicy = FirewallPolicyGet()
|
||||
'添加项目
|
||||
FirewallPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_DOMAIN).AuthorizedApplications.Add(New FirewallApp(DisplayName, FilePath))
|
||||
FirewallPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD).AuthorizedApplications.Add(New FirewallApp(DisplayName, FilePath))
|
||||
FirewallPolicy.CurrentProfile.AuthorizedApplications.Add(New FirewallApp(DisplayName, FilePath))
|
||||
End Sub
|
||||
Private Class FirewallApp
|
||||
Implements INetFwAuthorizedApplication
|
||||
Public Property Name As String Implements INetFwAuthorizedApplication.Name
|
||||
Public Property ProcessImageFileName As String Implements INetFwAuthorizedApplication.ProcessImageFileName
|
||||
Public Property IpVersion As NET_FW_IP_VERSION_ = NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY Implements INetFwAuthorizedApplication.IpVersion
|
||||
Public Property Scope As NET_FW_SCOPE_ = NET_FW_SCOPE_.NET_FW_SCOPE_ALL Implements INetFwAuthorizedApplication.Scope
|
||||
Public Property RemoteAddresses As String = "*" Implements INetFwAuthorizedApplication.RemoteAddresses
|
||||
Public Property Enabled As Boolean = True Implements INetFwAuthorizedApplication.Enabled
|
||||
Public Sub New(DisplayName As String, FilePath As String)
|
||||
Name = DisplayName
|
||||
ProcessImageFileName = FilePath
|
||||
End Sub
|
||||
End Class
|
||||
'获取防火墙配置
|
||||
Public Shared FirewallPolicy As INetFwPolicy = Nothing
|
||||
Public Shared Function FirewallPolicyGet() As INetFwPolicy
|
||||
Const CLSID_FIREWALL_MANAGER As String = "{304CE942-6E39-40D8-943A-B913C40C9CD4}"
|
||||
Dim objType As Type = Type.GetTypeFromCLSID(New Guid(CLSID_FIREWALL_MANAGER))
|
||||
Return TryCast(Activator.CreateInstance(objType), INetFwMgr).LocalPolicy
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "页面切换"
|
||||
|
||||
''' <summary>
|
||||
''' 当前页面的编号。
|
||||
''' </summary>
|
||||
Public PageID As FormMain.PageSubType = FormMain.PageSubType.LinkHiper
|
||||
|
||||
''' <summary>
|
||||
''' 勾选事件改变页面。
|
||||
''' </summary>
|
||||
Private Sub PageCheck(sender As MyListItem, e As RouteEventArgs) Handles ItemHiper.Check, ItemIoi.Check, ItemSetup.Check, ItemHelp.Check, ItemFeedback.Check
|
||||
'尚未初始化控件属性时,sender.Tag 为 Nothing,会导致切换到页面 0
|
||||
'若使用 IsLoaded,则会导致模拟点击不被执行(模拟点击切换页面时,控件的 IsLoaded 为 False)
|
||||
If sender.Tag IsNot Nothing Then PageChange(Val(sender.Tag))
|
||||
End Sub
|
||||
|
||||
Public Function PageGet(Optional ID As FormMain.PageSubType = -1)
|
||||
If ID = -1 Then ID = PageID
|
||||
Select Case ID
|
||||
Case 0, FormMain.PageSubType.LinkHiper
|
||||
If FrmLinkHiper Is Nothing Then FrmLinkHiper = New PageLinkHiper
|
||||
Return FrmLinkHiper
|
||||
Case FormMain.PageSubType.LinkIoi
|
||||
If FrmLinkIoi Is Nothing Then FrmLinkIoi = New PageLinkIoi
|
||||
Return FrmLinkIoi
|
||||
Case FormMain.PageSubType.LinkSetup
|
||||
If FrmSetupLink Is Nothing Then FrmSetupLink = New PageSetupLink
|
||||
Return FrmSetupLink
|
||||
Case FormMain.PageSubType.LinkHelp
|
||||
If FrmLinkHelp Is Nothing Then FrmLinkHelp = PageOtherHelp.GetHelpPage(PathTemp & "Help\启动器\联机.json")
|
||||
Return FrmLinkHelp
|
||||
Case FormMain.PageSubType.LinkFeedback
|
||||
If FrmLinkFeedback Is Nothing Then FrmLinkFeedback = New PageLinkFeedback
|
||||
Return FrmLinkFeedback
|
||||
Case Else
|
||||
Throw New Exception("未知的更多子页面种类:" & ID)
|
||||
End Select
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 切换现有页面。
|
||||
''' </summary>
|
||||
Public Sub PageChange(ID As FormMain.PageSubType)
|
||||
If PageID = ID Then Exit Sub
|
||||
AniControlEnabled += 1
|
||||
IsPageSwitched = True
|
||||
Try
|
||||
PageChangeRun(PageGet(ID))
|
||||
PageID = ID
|
||||
Catch ex As Exception
|
||||
Log(ex, "切换设置分页面失败(ID " & ID & ")", LogLevel.Feedback)
|
||||
Finally
|
||||
AniControlEnabled -= 1
|
||||
End Try
|
||||
End Sub
|
||||
Private Shared Sub PageChangeRun(Target As MyPageRight)
|
||||
AniStop("FrmMain PageChangeRight") '停止主页面的右页面切换动画,防止它与本动画一起触发多次 PageOnEnter
|
||||
If Target.Parent IsNot Nothing Then Target.SetValue(ContentPresenter.ContentProperty, Nothing)
|
||||
FrmMain.PageRight = Target
|
||||
CType(FrmMain.PanMainRight.Child, MyPageRight).PageOnExit()
|
||||
AniStart({
|
||||
AaCode(Sub()
|
||||
CType(FrmMain.PanMainRight.Child, MyPageRight).PageOnForceExit()
|
||||
FrmMain.PanMainRight.Child = FrmMain.PageRight
|
||||
FrmMain.PageRight.Opacity = 0
|
||||
End Sub, 130),
|
||||
AaCode(Sub()
|
||||
'延迟触发页面通用动画,以使得在 Loaded 事件中加载的控件得以处理
|
||||
FrmMain.PageRight.Opacity = 1
|
||||
FrmMain.PageRight.PageOnEnter()
|
||||
End Sub, 30, True)
|
||||
}, "PageLeft PageChange")
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
Public Sub Reset(sender As Object, e As EventArgs)
|
||||
If MyMsgBox("是否要初始化联机页的所有设置?该操作不可撤销。", "初始化确认",, "取消", IsWarn:=True) = 1 Then
|
||||
If IsNothing(FrmSetupLink) Then FrmSetupLink = New PageSetupLink
|
||||
FrmSetupLink.Reset()
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub BtnHiperStop_Loaded(sender As Object, e As RoutedEventArgs)
|
||||
sender.Visibility = If(PageLinkHiper.HiperState = LoadState.Finished OrElse PageLinkHiper.HiperState = LoadState.Loading, Visibility.Visible, Visibility.Collapsed)
|
||||
End Sub
|
||||
Private Sub BtnHiperStop_Click(sender As Object, e As EventArgs)
|
||||
PageLinkHiper.ModuleStopManually()
|
||||
End Sub
|
||||
Private Sub BtnIoiStop_Loaded(sender As Object, e As RoutedEventArgs)
|
||||
sender.Visibility = If(PageLinkIoi.InitLoader.State = LoadState.Finished, Visibility.Visible, Visibility.Collapsed)
|
||||
End Sub
|
||||
Private Sub BtnIoiStop_Click(sender As Object, e As EventArgs)
|
||||
PageLinkIoi.ModuleStopManually()
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -17,5 +17,7 @@
|
||||
LogoScale="0.97" Logo="M511.488 995.328a128.654222 128.654222 0 0 1-57.116444-13.112889L70.769778 791.808a126.833778 126.833778 0 0 1-70.769778-113.777778V311.608889a126.179556 126.179556 0 0 1 15.36-60.103111V248.604444c1.479111-2.901333 3.356444-5.603556 5.518222-8.021333a127.630222 127.630222 0 0 1 49.891556-42.325333L454.371556 13.368889a128.739556 128.739556 0 0 1 112.981333 0l383.601778 190.407111a126.862222 126.862222 0 0 1 72.049777 113.379556v360.874666a126.805333 126.805333 0 0 1-70.769777 115.939556L568.604444 984.32c-17.92 7.964444-37.461333 11.747556-57.116444 11.008z m42.638222-470.897778v370.204445l360.192-178.545778c14.449778-7.253333 23.552-21.987556 23.438222-38.087111v-335.928889L554.097778 524.430222zM85.248 330.666667v347.335111a42.268444 42.268444 0 0 0 23.438222 38.087111l360.192 178.545778V523.576889L85.248 330.666667zM135.537778 260.835556l375.950222 189.952 137.671111-65.564445L286.435556 188.074667 135.537778 260.864z m245.105778-118.471112l363.576888 197.973334 150.897778-71.480889-365.283555-180.224a42.922667 42.922667 0 0 0-37.518223 0l-111.672888 53.731555z" />
|
||||
<local:MyListItem x:Name="ItemFeedback" IsScaleAnimationEnabled="False" Type="Clickable" Tag="3" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="反馈"
|
||||
LogoScale="0.9" Logo="M613.717333 64.426667l3.413334 3.242666 331.861333 331.861334a85.333333 85.333333 0 0 1 3.2 117.269333l-3.2 3.413333L573.162667 896H960a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H64a21.333333 21.333333 0 0 1-21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h295.338667L74.069333 610.709333a85.333333 85.333333 0 0 1-3.221333-117.269333l3.2-3.413333 422.4-422.357334a85.333333 85.333333 0 0 1 117.269333-3.221333z m-20.629333 99.882666l-21.418667 321.493334a85.333333 85.333333 0 0 1-74.944 79.04l-4.522666 0.426666-321.493334 21.44 295.552 295.530667 422.4-422.378667L593.066667 164.309333z m-86.442667 13.824L184.533333 500.266667l301.994667-20.117334 20.117333-301.994666z" />
|
||||
<local:MyListItem x:Name="ItemVote" IsScaleAnimationEnabled="False" Type="Clickable" Tag="4" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="新功能投票"
|
||||
LogoScale="0.92" Logo="M979 1024H45c-24.9 0-45-20.1-45-45s20.1-45 45-45h934c24.9 0 45 20.1 45 45s-20.1 45-45 45zM135 887C60.6 887 0 826.4 0 752V334c0-74.4 60.6-135 135-135s135 60.6 135 135v418c0 74.4-60.6 135-135 135z m0-598c-24.8 0-45 20.2-45 45v418c0 24.8 20.2 45 45 45s45-20.2 45-45V334c0-24.8-20.2-45-45-45zM512 887c-74.4 0-135-60.6-135-135V532c0-74.4 60.6-135 135-135s135 60.6 135 135v220c0 74.4-60.6 135-135 135z m0-400c-24.8 0-45 20.2-45 45v220c0 24.8 20.2 45 45 45s45-20.2 45-45V532c0-24.8-20.2-45-45-45zM889 887c-74.4 0-135-60.6-135-135V135C754 60.6 814.6 0 889 0s135 60.6 135 135v617c0 74.4-60.6 135-135 135z m0-797c-24.8 0-45 20.2-45 45v617c0 24.8 20.2 45 45 45s45-20.2 45-45V135c0-24.8-20.2-45-45-45z" />
|
||||
</StackPanel>
|
||||
</local:MyPageLeft>
|
||||
@@ -122,9 +122,21 @@
|
||||
FrmOtherHelp.SearchBox.Text = ""
|
||||
End Sub
|
||||
|
||||
'打开反馈
|
||||
'打开网页
|
||||
Public Shared Sub TryFeedback() Handles ItemFeedback.Click
|
||||
If CanFeedback(True) Then Feedback(True, False)
|
||||
If Not CanFeedback(True) Then Exit Sub
|
||||
Select Case MyMsgBox("是否要打开反馈列表网页?" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
|
||||
"反馈提示", "提交新反馈", "查看反馈列表", "取消")
|
||||
Case 1
|
||||
Feedback(True, False)
|
||||
Case 2
|
||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/issues/")
|
||||
End Select
|
||||
End Sub
|
||||
Public Shared Sub TryVote() Handles ItemVote.Click
|
||||
If MyMsgBox("是否要打开新功能投票网页?" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
|
||||
"提醒", "打开", "取消") = 2 Then Exit Sub
|
||||
OpenWebsite("https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8?discussions_q=category%3A%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8+sort%3Adate_created")
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -238,7 +238,7 @@
|
||||
For Each VersionPath In VersionFolder.EnumerateDirectories
|
||||
Dim Version As New McVersion(VersionPath.FullName)
|
||||
Version.Load()
|
||||
If Not Version.Version.Modable Then Continue For
|
||||
If Not Version.Modable Then Continue For
|
||||
'4. 该版本的隔离文件夹下不存在 mods
|
||||
Dim ModIndieFolder As New DirectoryInfo(Version.Path & "mods\")
|
||||
If ModIndieFolder.Exists AndAlso ModIndieFolder.EnumerateFiles.Count > 0 Then Exit Sub
|
||||
|
||||
@@ -211,24 +211,28 @@
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="高级设置" IsSwaped="True" CanSwap="True">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="9" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="LaunchAdvanceJvm" Grid.Column="1" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,在没有确定把握的情况下请不要尝试修改。
你可以通过点击左侧选项卡的初始化按钮来恢复到默认设置。" ToolTipService.ShowDuration="2333333" Text="-XX:+UseG1GC -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignoreInvalidMinecraftCertificates=True -Dfml.ignorePatchDiscrepancies=True -Dlog4j2.formatMsgNoLookups=true" />
|
||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="额外参数" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="LaunchAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。" ToolTipService.ShowDuration="2333333" />
|
||||
</Grid>
|
||||
<local:MyCheckBox Margin="0,10,0,4" Text="关闭文件校验" x:Name="CheckAdvanceAssets" Tag="LaunchAdvanceAssets" Grid.Column="1" ToolTip="在启动 Minecraft 时,不校验 libraries 文件夹、第三方登录库与版本主 jar 文件,不更改 assets 文件夹。
如果你没有修改相关文件,请勿勾选此项。
更推荐在版本设置中关闭特定版本的校验,而不是在这里关闭所有版本的校验。" ToolTipService.ShowDuration="2333333" />
|
||||
</StackPanel>
|
||||
<Grid Margin="25,40,25,15">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="9" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="JVM 参数" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextAdvanceJvm" Grid.Row="0" Grid.ColumnSpan="2" Tag="LaunchAdvanceJvm" Grid.Column="1" ToolTip="启动 Minecraft 时使用的额外 JVM 参数,在没有确定把握的情况下请不要尝试修改。
你可以通过点击左侧选项卡的初始化按钮来恢复到默认设置。" ToolTipService.ShowDuration="2333333" Text="-XX:+UseG1GC -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignoreInvalidMinecraftCertificates=True -Dfml.ignorePatchDiscrepancies=True -Dlog4j2.formatMsgNoLookups=true" />
|
||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="额外参数" Margin="0,0,25,0" />
|
||||
<local:MyTextBox x:Name="TextAdvanceGame" Grid.Row="2" Grid.ColumnSpan="2" Tag="LaunchAdvanceGame" Grid.Column="1" ToolTip="文本框中的内容将会被直接拼合在启动参数的末尾。
例如输入 --demo 则会以试玩模式启动游戏。" ToolTipService.ShowDuration="2333333" />
|
||||
<StackPanel Margin="0,10,0,4" Orientation="Horizontal" Grid.Row="3" Grid.ColumnSpan="2">
|
||||
<local:MyCheckBox Text="忽略 Java 兼容性警告" x:Name="CheckAdvanceJava" Tag="LaunchAdvanceJava" Margin="0,0,60,0"
|
||||
ToolTip="如果在设置中手动选择了与当前版本不兼容的 Java,则自动跳过兼容性警告弹窗,强制使用手动选择的 Java。" ToolTipService.ShowDuration="2333333" />
|
||||
<local:MyCheckBox Text="关闭文件校验" x:Name="CheckAdvanceAssets" Tag="LaunchAdvanceAssets"
|
||||
ToolTip="在启动时不校验 libraries 文件夹、第三方登录库与版本主 jar 文件,不更改 assets 文件夹。
如果你没有修改相关文件,请勿勾选此项。
更推荐在版本设置中关闭特定版本的校验,而不是在这里关闭所有版本的校验。" ToolTipService.ShowDuration="2333333" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
</local:MyScrollViewer>
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
TextAdvanceJvm.Text = Setup.Get("LaunchAdvanceJvm")
|
||||
TextAdvanceGame.Text = Setup.Get("LaunchAdvanceGame")
|
||||
CheckAdvanceAssets.Checked = Setup.Get("LaunchAdvanceAssets")
|
||||
CheckAdvanceJava.Checked = Setup.Get("LaunchAdvanceJava")
|
||||
|
||||
Catch ex As NullReferenceException
|
||||
Log(ex, "启动设置项存在异常,已被自动重置", LogLevel.Msgbox)
|
||||
@@ -74,6 +75,7 @@
|
||||
Setup.Reset("LaunchSkinID")
|
||||
Setup.Reset("LaunchAdvanceJvm")
|
||||
Setup.Reset("LaunchAdvanceGame")
|
||||
Setup.Reset("LaunchAdvanceJava")
|
||||
Setup.Reset("LaunchAdvanceAssets")
|
||||
|
||||
Setup.Reset("LaunchArgumentJavaAll")
|
||||
@@ -102,7 +104,7 @@
|
||||
Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboArgumentIndie.SelectionChanged, ComboArgumentVisibie.SelectionChanged, ComboArgumentWindowType.SelectionChanged, ComboArgumentPriority.SelectionChanged
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
|
||||
End Sub
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceAssets.Change
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckAdvanceAssets.Change, CheckAdvanceJava.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||
End Sub
|
||||
|
||||
@@ -114,8 +116,8 @@
|
||||
'设置文件
|
||||
Try
|
||||
'拷贝文件
|
||||
File.Delete(PathTemp & "CustomSkin.png")
|
||||
CopyFile(SkinInfo.LocalFile, PathTemp & "CustomSkin.png")
|
||||
File.Delete(PathAppdata & "CustomSkin.png")
|
||||
CopyFile(SkinInfo.LocalFile, PathAppdata & "CustomSkin.png")
|
||||
'更新设置
|
||||
Setup.Set("LaunchSkinSlim", SkinInfo.IsSlim)
|
||||
Catch ex As Exception
|
||||
@@ -129,7 +131,7 @@
|
||||
If Not (AniControlEnabled = 0 AndAlso e.RaiseByMouse) Then Exit Sub
|
||||
Try
|
||||
'已有图片则不再选择
|
||||
If File.Exists(PathTemp & "CustomSkin.png") Then Exit Sub
|
||||
If File.Exists(PathAppdata & "CustomSkin.png") Then Exit Sub
|
||||
'没有图片则要求选择
|
||||
Dim SkinInfo As McSkinInfo = McSkinSelect(True)
|
||||
If Not SkinInfo.IsVaild Then
|
||||
@@ -137,8 +139,8 @@
|
||||
Exit Sub
|
||||
End If
|
||||
'拷贝文件
|
||||
File.Delete(PathTemp & "CustomSkin.png")
|
||||
CopyFile(SkinInfo.LocalFile, PathTemp & "CustomSkin.png")
|
||||
File.Delete(PathAppdata & "CustomSkin.png")
|
||||
CopyFile(SkinInfo.LocalFile, PathAppdata & "CustomSkin.png")
|
||||
'更新设置
|
||||
Setup.Set("LaunchSkinSlim", SkinInfo.IsSlim)
|
||||
Catch ex As Exception
|
||||
@@ -151,7 +153,7 @@
|
||||
End Sub
|
||||
Private Sub BtnSkinDelete_Click(sender As Object, e As EventArgs) Handles BtnSkinDelete.Click
|
||||
Try
|
||||
File.Delete(PathTemp & "CustomSkin.png")
|
||||
File.Delete(PathAppdata & "CustomSkin.png")
|
||||
RadioSkinType0.SetChecked(True, True, True)
|
||||
Hint("离线皮肤已清空!", HintType.Finish)
|
||||
Catch ex As Exception
|
||||
@@ -335,7 +337,7 @@
|
||||
Dim RamTarget2 As Double '估计没啥问题了的内存
|
||||
Dim RamTarget3 As Double '放一百万个材质和 Mod 和光影需要的内存
|
||||
If Version IsNot Nothing AndAlso Not Version.IsLoaded Then Version.Load()
|
||||
If Version IsNot Nothing AndAlso Version.Version.Modable Then
|
||||
If Version IsNot Nothing AndAlso Version.Modable Then
|
||||
'可安装 Mod 的版本
|
||||
Dim ModDir As New DirectoryInfo(Version.PathIndie & "mods\")
|
||||
Dim ModCount As Integer = If(ModDir.Exists, ModDir.GetFiles.Length, 0)
|
||||
|
||||
@@ -6,8 +6,14 @@
|
||||
d:DesignWidth="800" d:DesignHeight="800">
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel x:Name="PanMain" Margin="25,10">
|
||||
<local:MyCard Margin="0,20,0,-5" Title="通用设置">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<local:MyCard Margin="0,15" Title="HiPer">
|
||||
<StackPanel Margin="25,40,25,20" Orientation="Vertical">
|
||||
<local:MyCheckBox Text="在索引码还有 5 分钟到期时提醒我" x:Name="CheckHiperCertWarn" Tag="LinkHiperCertWarn" Height="22" />
|
||||
<local:MyButton x:Name="BtnHiperLog" Height="35" MinWidth="140" Text="查看日志" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="IOI">
|
||||
<StackPanel Margin="25,40,25,20">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
@@ -26,8 +32,6 @@
|
||||
</local:MyTextBox.ValidateRules>
|
||||
</local:MyTextBox>
|
||||
</Grid>
|
||||
<local:MyCheckBox Text="打开启动器时启动联机模块" Height="22" x:Name="CheckLinkAuto" Tag="LinkAuto" ToolTipService.ShowDuration="2333333" Margin="0,10,0,4"
|
||||
ToolTip="开启联机模块的人越多,所有使用 PCL2 的玩家的初次连接速度就会越快。因此,启用此项可以为大家作出贡献。 联机模块仅使用少许网络带宽,几乎不使用硬盘与 CPU。" />
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
|
||||
End Sub
|
||||
Public Sub Reload()
|
||||
CheckLinkAuto.Checked = Setup.Get("LinkAuto")
|
||||
TextLinkName.Text = Setup.Get("LinkName")
|
||||
CheckHiperCertWarn.Checked = Setup.Get("LinkHiperCertWarn")
|
||||
End Sub
|
||||
|
||||
'初始化
|
||||
Public Sub Reset()
|
||||
Try
|
||||
Setup.Reset("LinkAuto")
|
||||
Setup.Reset("LinkName")
|
||||
Setup.Reset("LinkHiperCertWarn")
|
||||
|
||||
Log("[Setup] 已初始化联机页设置")
|
||||
Hint("已初始化联机页设置!", HintType.Finish, False)
|
||||
@@ -37,11 +37,19 @@
|
||||
End Sub
|
||||
|
||||
'将控件改变路由到设置改变
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckLinkAuto.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||
End Sub
|
||||
Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextLinkName.ValidatedTextChanged
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Text)
|
||||
End Sub
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckHiperCertWarn.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||
End Sub
|
||||
|
||||
Private Sub BtnHiperLog_Click(sender As Object, e As EventArgs) Handles BtnHiperLog.Click
|
||||
If File.Exists(PageLinkHiper.PathHiper & "logs\hiper.log") Then
|
||||
OpenExplorer("/select,""" & PageLinkHiper.PathHiper & "logs\hiper.log""")
|
||||
Else
|
||||
Hint("没有找到 HiPer 联机模块的日志!")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -23,6 +23,7 @@
|
||||
<RowDefinition Height="27" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="版本列表获取" Margin="0,0,25,0" />
|
||||
<local:MyComboBox x:Name="ComboDownloadVersion" Grid.ColumnSpan="2" Tag="ToolDownloadVersion" Grid.Column="1">
|
||||
@@ -45,7 +46,9 @@
|
||||
<local:MySlider x:Name="SliderDownloadSpeed" Grid.Row="5" Tag="ToolDownloadSpeed" MaxValue="42" Value="42" Grid.Column="1" />
|
||||
<TextBlock VerticalAlignment="Top" Grid.Row="6" HorizontalAlignment="Left" Text="目标文件夹" Margin="0,5,25,5" />
|
||||
<TextBlock Margin="0,5" HorizontalAlignment="Left" Text="请在 启动 → 版本选择 → 文件夹列表 中更改下载目标文件夹。
在某个文件夹或游戏版本上右键,即可选择打开对应文件夹。" Grid.Row="6" Grid.Column="1" VerticalAlignment="Center" />
|
||||
<!--<local:MyCheckBox Text="若版本列表并非从官方源获取,显示版本列表可能过期的提示" Grid.ColumnSpan="2" Grid.Row="3" x:Name="CheckDownloadOutOfDate" Tag="ToolDownloadOutOfDate" Height="22" Margin="0,2,0,8" />-->
|
||||
<local:MyCheckBox Margin="0,2,0,4" Text="安装 CurseForge 整合包时保留原始压缩包" Grid.Row="7" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadKeepModpack" Tag="ToolDownloadKeepModpack"
|
||||
ToolTip="安装 CurseForge 整合包后,在版本文件夹下保留用于安装的 原始整合包.zip 文件" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
SliderDownloadSpeed.Value = Setup.Get("ToolDownloadSpeed")
|
||||
ComboDownloadVersion.SelectedIndex = Setup.Get("ToolDownloadVersion")
|
||||
ComboDownloadTranslate.SelectedIndex = Setup.Get("ToolDownloadTranslate")
|
||||
CheckDownloadKeepModpack.Checked = Setup.Get("ToolDownloadKeepModpack")
|
||||
|
||||
'Minecraft 更新提示
|
||||
CheckUpdateRelease.Checked = Setup.Get("ToolUpdateRelease")
|
||||
@@ -84,6 +85,7 @@
|
||||
Setup.Reset("ToolDownloadSpeed")
|
||||
Setup.Reset("ToolDownloadVersion")
|
||||
Setup.Reset("ToolDownloadTranslate")
|
||||
Setup.Reset("ToolDownloadKeepModpack")
|
||||
Setup.Reset("ToolUpdateRelease")
|
||||
Setup.Reset("ToolUpdateSnapshot")
|
||||
Setup.Reset("ToolHelpChinese")
|
||||
@@ -105,7 +107,7 @@
|
||||
End Sub
|
||||
|
||||
'将控件改变路由到设置改变
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change
|
||||
Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadKeepModpack.Change
|
||||
If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
|
||||
End Sub
|
||||
Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderDebugAnim.Change, SliderDownloadThread.Change, SliderDownloadSpeed.Change
|
||||
@@ -183,7 +185,6 @@
|
||||
Dim Temp As String()
|
||||
Temp = Directory.GetFiles(Path)
|
||||
For Each str As String In Temp
|
||||
If str = PathTemp & "CustomSkin.png" OrElse str = PathTemp & "联机模块.exe" Then Continue For '不删除的文件
|
||||
Try
|
||||
Dim Info As New FileInfo(str)
|
||||
Dim FileActualSize = Math.Ceiling(Info.Length / 4096) * 4096
|
||||
@@ -207,7 +208,7 @@
|
||||
If MyMsgBox("若选择此项,即使在将来出现严重问题时,你也无法获取相关通知。" & vbCrLf &
|
||||
"例如,如果发现某个版本游戏存在严重 Bug,你可能就会因为无法得到通知而导致无法预知的后果。" & vbCrLf & vbCrLf &
|
||||
"一般选择 仅在有重要通知时显示公告 就可以让你尽量不受打扰了。" & vbCrLf &
|
||||
"除非你在制作服务器整合包,或时常手动更新启动器,否则极度不推荐选择此项!", "警告", "继续", "取消") = 2 Then
|
||||
"除非你在制作服务器整合包,或时常手动更新启动器,否则极度不推荐选择此项!", "警告", "我知道我在做什么", "取消", IsWarn:=True) = 2 Then
|
||||
ComboSystemActivity.SelectedItem = e.RemovedItems(0)
|
||||
End If
|
||||
End If
|
||||
@@ -218,7 +219,7 @@
|
||||
If MyMsgBox("若选择此项,即使在启动器将来出现严重问题时,你也无法获取更新并获得修复。" & vbCrLf &
|
||||
"例如,如果官方修改了登录方式,从而导致现有启动器无法登录,你可能就会因为无法更新而无法开始游戏。" & vbCrLf & vbCrLf &
|
||||
"一般选择 仅在有重大漏洞更新时显示提示 就可以让你尽量不受打扰了。" & vbCrLf &
|
||||
"除非你在制作服务器整合包,或时常手动更新启动器,否则极度不推荐选择此项!", "警告", "继续", "取消") = 2 Then
|
||||
"除非你在制作服务器整合包,或时常手动更新启动器,否则极度不推荐选择此项!", "警告", "我知道我在做什么", "取消", IsWarn:=True) = 2 Then
|
||||
ComboSystemUpdate.SelectedItem = e.RemovedItems(0)
|
||||
End If
|
||||
End If
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>
|
||||
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
|
||||
<GradientStop Color="{DynamicResource ColorObject9}" Offset="0"/>
|
||||
<GradientStop Color="{DynamicResource ColorObjectBg1}" Offset="0"/>
|
||||
<GradientStop Color="{DynamicResource ColorObject3}" Offset="0.02"/>
|
||||
<GradientStop Color="{DynamicResource ColorObject3}" Offset="0.98"/>
|
||||
<GradientStop Color="{DynamicResource ColorObject9}" Offset="1"/>
|
||||
<GradientStop Color="{DynamicResource ColorObjectBg1}" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
Card.Children.Clear()
|
||||
Card.Children.Add(GetObjectFromXML("<Path xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" Stretch=""Uniform"" Tag=""Failed"" Data=""F1 M2.5,0 L0,2.5 7.5,10 0,17.5 2.5,20 10,12.5 17.5,20 20,17.5 12.5,10 20,2.5 17.5,0 10,7.5 2.5,0Z"" Height=""15"" Width=""15"" HorizontalAlignment=""Center"" Grid.Column=""0"" Grid.Row=""0"" Fill=""{DynamicResource ColorBrush3}"" Margin=""0,1,0,0"" VerticalAlignment=""Top""/>"))
|
||||
Dim Tb As TextBlock = GetObjectFromXML("<TextBlock xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" TextWrapping=""Wrap"" HorizontalAlignment=""Left"" ToolTipService.ShowDuration=""2333333"" ToolTip=""单击复制错误详情"" Grid.Column=""1"" Grid.Row=""0"" Margin=""0,0,0,5"" />")
|
||||
Tb.Text = GetString(Loader.Error, False)
|
||||
Tb.Text = GetExceptionDetail(Loader.Error)
|
||||
AddHandler Tb.MouseDown, Sub(sender As TextBlock, e As EventArgs)
|
||||
ClipboardSet(sender.Text, False)
|
||||
Hint("已复制错误详情!", HintType.Finish)
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
''' </summary>
|
||||
Public Shared Version As McVersion
|
||||
|
||||
Private Sub PageVersionLeft_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
If Version IsNot Nothing AndAlso Version.Version.Modable Then
|
||||
ItemMod.Visibility = Visibility.Visible
|
||||
ItemModDisabled.Visibility = Visibility.Collapsed
|
||||
Public Sub RefreshModDisabled() Handles Me.Loaded
|
||||
If Version IsNot Nothing AndAlso Version.Modable Then
|
||||
ItemMod.Height = 36
|
||||
ItemModDisabled.Height = 0
|
||||
Else
|
||||
ItemMod.Visibility = Visibility.Collapsed
|
||||
ItemModDisabled.Visibility = Visibility.Visible
|
||||
ItemMod.Height = 0
|
||||
ItemModDisabled.Height = 36
|
||||
End If
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
Case McMod.McModState.Disabled
|
||||
NewPath = ModEntity.Path.Substring(0, ModEntity.Path.Count - ".disabled".Count)
|
||||
Case McMod.McModState.Unavaliable
|
||||
MyMsgBox("无法读取此 Mod 的信息。" & vbCrLf & vbCrLf & "详细的错误信息:" & GetString(ModEntity.FileUnavailableReason, False), "Mod 读取失败")
|
||||
MyMsgBox("无法读取此 Mod 的信息。" & vbCrLf & vbCrLf & "详细的错误信息:" & GetExceptionDetail(ModEntity.FileUnavailableReason), "Mod 读取失败")
|
||||
Exit Sub
|
||||
End Select
|
||||
'重命名
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
d:DesignWidth="800" d:DesignHeight="800" Grid.IsSharedSizeScope="True">
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel x:Name="PanMain" Margin="25,10">
|
||||
<local:MyCard Margin="0,15" Title="个性化" x:Name="PanDisplay">
|
||||
<local:MyCard Margin="0,15" Title="">
|
||||
<Grid Margin="10,7" Name="PanDisplayItem" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="个性化" x:Name="PanDisplay">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<Grid Margin="-7,-3,0,12" Name="PanDisplayItem" />
|
||||
<Grid x:Name="PanDisplayIcon" Margin="0,0,0,11" HorizontalAlignment="Stretch">
|
||||
<Grid x:Name="PanDisplayIcon" HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
<ColumnDefinition />
|
||||
@@ -20,7 +22,7 @@
|
||||
<RowDefinition Height="9" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="版本图标" Margin="0,0,25,0" />
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="图标" Margin="0,0,25,0" />
|
||||
<local:MyComboBox Grid.Column="1" x:Name="ComboDisplayLogo">
|
||||
<local:MyComboBoxItem Content="自动" IsSelected="True" Tag="" />
|
||||
<local:MyComboBoxItem Content="自定义..." x:Name="ItemDisplayLogoCustom" />
|
||||
@@ -36,7 +38,7 @@
|
||||
<local:MyComboBoxItem Content="鸡蛋" Tag="pack://application:,,,/images/Blocks/Egg.png" />
|
||||
<local:MyComboBoxItem Content="布料(Fabric)" Tag="pack://application:,,,/images/Blocks/Fabric.png" />
|
||||
</local:MyComboBox>
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本分类" Margin="0,0,25,0" />
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="分类" Margin="0,0,25,0" />
|
||||
<local:MyComboBox Grid.Column="1" Grid.Row="2" x:Name="ComboDisplayType">
|
||||
<local:MyComboBoxItem Content="自动" IsSelected="True" />
|
||||
<local:MyComboBoxItem Content="从版本列表中隐藏" ToolTip="该版本默认将不会在版本列表中显示。
在版本列表页面按下 F11,即可查看所有隐藏的版本。" ToolTipService.ShowDuration="2333333" />
|
||||
@@ -46,19 +48,19 @@
|
||||
<local:MyComboBoxItem Content="愚人节版本" />
|
||||
</local:MyComboBox>
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,7" Height="35">
|
||||
<Grid Margin="0,15,0,7" Height="35">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnDisplayRename" Text="重命名版本" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnDisplayDesc" Text="更改描述" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="1" />
|
||||
<local:MyButton x:Name="BtnDisplayStar" Text="加入收藏夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="2" />
|
||||
<local:MyButton x:Name="BtnDisplayRename" Text="修改版本名" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnDisplayDesc" Text="修改版本描述" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="1" />
|
||||
<local:MyButton x:Name="BtnDisplayDelete" Text="删除版本" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="2" ColorType="Red" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="管理" x:Name="PanManage">
|
||||
<local:MyCard Margin="0,0,0,15" Title="快捷方式" x:Name="PanFolder">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<Grid Margin="0,2,0,7" Height="35">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -66,9 +68,22 @@
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnManageFolder" Text="打开版本文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnFolderVersion" Text="版本文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnFolderSaves" Text="存档文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="1" />
|
||||
<local:MyButton x:Name="BtnFolderMods" Text="Mod 文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="2" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
<local:MyCard Margin="0,0,0,15" Title="高级管理" x:Name="PanManage">
|
||||
<StackPanel Margin="25,40,25,15">
|
||||
<Grid Margin="0,2,0,7" Height="35">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnManageScript" Text="导出启动脚本" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnManageCheck" Text="补全文件" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="1" ToolTip="校验版本依赖文件是否完整,并重新下载 Assets 索引与缺失、校验失败的文件。
若游戏缺失音效,请尝试此项。" ToolTipService.ShowDuration="2333333" />
|
||||
<local:MyButton x:Name="BtnManageDelete" Text="删除版本" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="2" ColorType="Red" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
'刷新设置项目
|
||||
ComboDisplayType.SelectedIndex = ReadIni(PageVersionLeft.Version.Path & "PCL\Setup.ini", "DisplayType", McVersionCardType.Auto)
|
||||
BtnDisplayStar.Text = If(PageVersionLeft.Version.IsStar, "从收藏夹中移除", "加入收藏夹")
|
||||
BtnFolderMods.Visibility = If(PageVersionLeft.Version.Modable, Visibility.Visible, Visibility.Collapsed)
|
||||
'刷新版本显示
|
||||
PanDisplayItem.Children.Clear()
|
||||
ItemVersion = PageSelectRight.McVersionListItem(PageVersionLeft.Version)
|
||||
@@ -49,7 +49,7 @@
|
||||
AniControlEnabled -= 1
|
||||
End Sub
|
||||
|
||||
#Region "设置临时接口"
|
||||
#Region "卡片:个性化"
|
||||
|
||||
'版本分类
|
||||
Private Sub ComboDisplayType_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ComboDisplayType.SelectionChanged
|
||||
@@ -57,12 +57,17 @@
|
||||
If ComboDisplayType.SelectedIndex <> 1 Then
|
||||
'改为不隐藏
|
||||
Try
|
||||
'若设置分类为可安装 Mod,则显示正常的 Mod 管理页面
|
||||
WriteIni(PageVersionLeft.Version.Path & "PCL\Setup.ini", "DisplayType", ComboDisplayType.SelectedIndex)
|
||||
PageVersionLeft.Version.DisplayType = ReadIni(PageVersionLeft.Version.Path & "PCL\Setup.ini", "DisplayType", McVersionCardType.Auto)
|
||||
FrmVersionLeft.RefreshModDisabled()
|
||||
|
||||
WriteIni(PathMcFolder & "PCL.ini", "VersionCache", "") '要求刷新缓存
|
||||
LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
Catch ex As Exception
|
||||
Log(ex, "修改版本分类失败(" & PageVersionLeft.Version.Name & ")", LogLevel.Feedback)
|
||||
End Try
|
||||
Reload() '更新 “打开 Mod 文件夹” 按钮
|
||||
Else
|
||||
'改为隐藏
|
||||
Try
|
||||
@@ -81,6 +86,7 @@
|
||||
End Try
|
||||
End If
|
||||
End Sub
|
||||
|
||||
'更改描述
|
||||
Private Sub BtnDisplayDesc_Click(sender As Object, e As EventArgs) Handles BtnDisplayDesc.Click
|
||||
Try
|
||||
@@ -94,6 +100,7 @@
|
||||
Log(ex, "版本 " & PageVersionLeft.Version.Name & " 描述更改失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'重命名版本
|
||||
Private Sub BtnDisplayRename_Click(sender As Object, e As EventArgs) Handles BtnDisplayRename.Click
|
||||
Try
|
||||
@@ -167,80 +174,7 @@
|
||||
Log(ex, "重命名版本失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
'收藏夹
|
||||
Private Sub BtnDisplayStar_Click(sender As Object, e As EventArgs) Handles BtnDisplayStar.Click
|
||||
Try
|
||||
WriteIni(PageVersionLeft.Version.Path & "PCL\Setup.ini", "IsStar", Not PageVersionLeft.Version.IsStar)
|
||||
PageVersionLeft.Version = New McVersion(PageVersionLeft.Version.Name).Load()
|
||||
Reload()
|
||||
McVersionListForceRefresh = True
|
||||
LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
Catch ex As Exception
|
||||
Log(ex, "版本 " & PageVersionLeft.Version.Name & " 收藏状态更改失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
'补全文件
|
||||
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
||||
Try
|
||||
'重复任务检查
|
||||
SyncLock LoaderTaskbarLock
|
||||
For i = 0 To LoaderTaskbar.Count - 1
|
||||
If LoaderTaskbar(i).Name = PageVersionLeft.Version.Name & " 文件补全" Then
|
||||
Hint("正在处理中,请稍候!", HintType.Critical)
|
||||
Exit Sub
|
||||
End If
|
||||
Next
|
||||
End SyncLock
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)(PageVersionLeft.Version.Name & " 文件补全", DlClientFix(PageVersionLeft.Version, True, AssetsIndexExistsBehaviour.AlwaysDownload, False))
|
||||
Loader.OnStateChanged = Sub()
|
||||
Select Case Loader.State
|
||||
Case LoadState.Finished
|
||||
Hint(Loader.Name & "成功!", HintType.Finish)
|
||||
Case LoadState.Failed
|
||||
Hint(Loader.Name & "失败:" & GetString(Loader.Error), HintType.Critical)
|
||||
Case LoadState.Aborted
|
||||
Hint(Loader.Name & "已取消!", HintType.Info)
|
||||
End Select
|
||||
End Sub
|
||||
Loader.Start(PageVersionLeft.Version.Name)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Catch ex As Exception
|
||||
Log(ex, "尝试补全文件失败(" & PageVersionLeft.Version.Name & ")", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
'删除版本
|
||||
Private Sub BtnManageDelete_Click(sender As Object, e As EventArgs) Handles BtnManageDelete.Click
|
||||
'修改此代码时,同时修改 PageSelectRight 中的代码
|
||||
Try
|
||||
Dim IsHintIndie As Boolean = PageVersionLeft.Version.State <> McVersionState.Error AndAlso PageVersionLeft.Version.PathIndie <> PathMcFolder
|
||||
Select Case MyMsgBox("你确定要删除版本 " & PageVersionLeft.Version.Name & " 吗?" &
|
||||
If(IsHintIndie, vbCrLf & "由于该版本开启了版本隔离,删除版本时该版本对应的存档、资源包、Mod 等文件也将被一并删除!", ""),
|
||||
"版本删除确认", , "取消",, True)
|
||||
Case 1
|
||||
FileIO.FileSystem.DeleteDirectory(PageVersionLeft.Version.Path, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||
Hint("版本 " & PageVersionLeft.Version.Name & " 已删除到回收站!", HintType.Finish)
|
||||
Case 2
|
||||
' DeleteDirectory(PageVersionLeft.Version.Path)
|
||||
' Hint("版本 " & PageVersionLeft.Version.Name & " 已永久删除!", HintType.Finish)
|
||||
'Case 3
|
||||
Exit Sub
|
||||
End Select
|
||||
LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
FrmMain.PageBack()
|
||||
Catch ex As Exception
|
||||
Log(ex, "删除版本 " & PageVersionLeft.Version.Name & " 失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
'打开版本文件夹
|
||||
Private Sub BtnManageFolder_Click() Handles BtnManageFolder.Click
|
||||
OpenVersionFolder(PageVersionLeft.Version)
|
||||
End Sub
|
||||
Public Shared Sub OpenVersionFolder(Version As McVersion)
|
||||
OpenExplorer("""" & Version.Path & """")
|
||||
End Sub
|
||||
|
||||
'版本图标
|
||||
Private Sub ComboDisplayLogo_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ComboDisplayLogo.SelectionChanged
|
||||
If Not (IsLoad AndAlso AniControlEnabled = 0) Then Exit Sub
|
||||
@@ -276,6 +210,117 @@
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'删除版本
|
||||
Private Sub BtnDisplayDelete_Click(sender As Object, e As EventArgs) Handles BtnDisplayDelete.Click
|
||||
'修改此代码时,同时修改 PageSelectRight 中的代码
|
||||
Try
|
||||
Dim IsHintIndie As Boolean = PageVersionLeft.Version.State <> McVersionState.Error AndAlso PageVersionLeft.Version.PathIndie <> PathMcFolder
|
||||
Select Case MyMsgBox("你确定要删除版本 " & PageVersionLeft.Version.Name & " 吗?" &
|
||||
If(IsHintIndie, vbCrLf & "由于该版本开启了版本隔离,删除版本时该版本对应的存档、资源包、Mod 等文件也将被一并删除!", ""),
|
||||
"版本删除确认", , "取消",, True)
|
||||
Case 1
|
||||
FileIO.FileSystem.DeleteDirectory(PageVersionLeft.Version.Path, FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)
|
||||
Hint("版本 " & PageVersionLeft.Version.Name & " 已删除到回收站!", HintType.Finish)
|
||||
Case 2
|
||||
' DeleteDirectory(PageVersionLeft.Version.Path)
|
||||
' Hint("版本 " & PageVersionLeft.Version.Name & " 已永久删除!", HintType.Finish)
|
||||
'Case 3
|
||||
Exit Sub
|
||||
End Select
|
||||
LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
FrmMain.PageBack()
|
||||
Catch ex As Exception
|
||||
Log(ex, "删除版本 " & PageVersionLeft.Version.Name & " 失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "卡片:快捷方式"
|
||||
|
||||
'版本文件夹
|
||||
Private Sub BtnFolderVersion_Click() Handles BtnFolderVersion.Click
|
||||
OpenVersionFolder(PageVersionLeft.Version)
|
||||
End Sub
|
||||
Public Shared Sub OpenVersionFolder(Version As McVersion)
|
||||
OpenExplorer("""" & Version.Path & """")
|
||||
End Sub
|
||||
|
||||
'存档文件夹
|
||||
Private Sub BtnFolderSaves_Click() Handles BtnFolderSaves.Click
|
||||
Dim FolderPath As String = PageVersionLeft.Version.PathIndie & "saves\"
|
||||
Directory.CreateDirectory(FolderPath)
|
||||
OpenExplorer("""" & FolderPath & """")
|
||||
End Sub
|
||||
|
||||
'Mod 文件夹
|
||||
Private Sub BtnFolderMods_Click() Handles BtnFolderMods.Click
|
||||
Dim FolderPath As String = PageVersionLeft.Version.PathIndie & "mods\"
|
||||
Directory.CreateDirectory(FolderPath)
|
||||
OpenExplorer("""" & FolderPath & """")
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "卡片:管理"
|
||||
|
||||
'导出启动脚本
|
||||
Private Sub BtnManageScript_Click() Handles BtnManageScript.Click
|
||||
Try
|
||||
'弹窗要求指定脚本的保存位置
|
||||
Dim SavePath As String = SelectAs("选择脚本保存位置", "启动 " & PageVersionLeft.Version.Name & ".bat", "批处理文件(*.bat)|*.bat")
|
||||
If SavePath = "" Then Exit Sub
|
||||
'检查中断(等玩家选完弹窗指不定任务就结束了呢……)
|
||||
If McLaunchLoader.State = LoadState.Loading Then
|
||||
Hint("请在当前启动任务结束后再试!", HintType.Critical)
|
||||
Exit Sub
|
||||
End If
|
||||
'生成脚本
|
||||
If McLaunchStart(New McLaunchOptions With {.SaveBatch = SavePath, .Version = PageVersionLeft.Version}) Then
|
||||
If Setup.Get("LoginType") = McLoginType.Legacy Then
|
||||
Hint("正在导出启动脚本……")
|
||||
Else
|
||||
Hint("正在导出启动脚本……(注意,使用脚本启动可能会导致登录失效!)")
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "导出启动脚本失败(" & PageVersionLeft.Version.Name & ")", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'补全文件
|
||||
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
||||
Try
|
||||
'重复任务检查
|
||||
SyncLock LoaderTaskbarLock
|
||||
For i = 0 To LoaderTaskbar.Count - 1
|
||||
If LoaderTaskbar(i).Name = PageVersionLeft.Version.Name & " 文件补全" Then
|
||||
Hint("正在处理中,请稍候!", HintType.Critical)
|
||||
Exit Sub
|
||||
End If
|
||||
Next
|
||||
End SyncLock
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of String)(PageVersionLeft.Version.Name & " 文件补全", DlClientFix(PageVersionLeft.Version, True, AssetsIndexExistsBehaviour.AlwaysDownload, False))
|
||||
Loader.OnStateChanged = Sub()
|
||||
Select Case Loader.State
|
||||
Case LoadState.Finished
|
||||
Hint(Loader.Name & "成功!", HintType.Finish)
|
||||
Case LoadState.Failed
|
||||
Hint(Loader.Name & "失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
|
||||
Case LoadState.Aborted
|
||||
Hint(Loader.Name & "已取消!", HintType.Info)
|
||||
End Select
|
||||
End Sub
|
||||
Loader.Start(PageVersionLeft.Version.Name)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
FrmMain.BtnExtraDownload.Ribble()
|
||||
Catch ex As Exception
|
||||
Log(ex, "尝试补全文件失败(" & PageVersionLeft.Version.Name & ")", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
End Class
|
||||
@@ -275,7 +275,7 @@
|
||||
Dim RamTarget2 As Double '估计没啥问题了的内存
|
||||
Dim RamTarget3 As Double '安装过多附加组件需要的内存
|
||||
If Version IsNot Nothing AndAlso Not Version.IsLoaded Then Version.Load()
|
||||
If Version IsNot Nothing AndAlso Version.Version.Modable Then
|
||||
If Version IsNot Nothing AndAlso Version.Modable Then
|
||||
'可安装 Mod 的版本
|
||||
Dim ModDir As New DirectoryInfo(Version.PathIndie & "mods\")
|
||||
Dim ModCount As Integer = If(ModDir.Exists, ModDir.GetFiles.Length, 0)
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>BasicDesignGuidelineRules.ruleset</CodeAnalysisRuleSet>
|
||||
<DefineConstants>BETA</DefineConstants>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
@@ -152,11 +153,6 @@
|
||||
<HintPath>Resources\Ookii.Dialogs.Wpf.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="STUN, Version=0.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>Resources\STUN.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
@@ -260,6 +256,9 @@
|
||||
<Compile Include="Pages\PageLink\PageLinkFeedback.xaml.vb">
|
||||
<DependentUpon>PageLinkFeedback.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\PageLink\PageLinkHiper.xaml.vb">
|
||||
<DependentUpon>PageLinkHiper.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\PageOther\PageOtherHelpDetail.xaml.vb">
|
||||
<DependentUpon>PageOtherHelpDetail.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -517,6 +516,10 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Pages\PageLink\PageLinkHiper.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Pages\PageOther\PageOtherHelpDetail.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -734,7 +737,6 @@
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Font.ttf" />
|
||||
<None Include="Resources\Help.zip" />
|
||||
<None Include="Resources\ModData.json" />
|
||||
<None Include="Resources\NAudio.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -786,22 +788,22 @@
|
||||
<ItemGroup>
|
||||
<PublishFile Include="NAudio">
|
||||
<Visible>False</Visible>
|
||||
<PublishState>Exclude</PublishState>
|
||||
<IncludeHash>True</IncludeHash>
|
||||
<Group>
|
||||
</Group>
|
||||
<TargetPath>
|
||||
</TargetPath>
|
||||
<PublishState>Exclude</PublishState>
|
||||
<IncludeHash>True</IncludeHash>
|
||||
<FileType>Assembly</FileType>
|
||||
</PublishFile>
|
||||
<PublishFile Include="Newtonsoft.Json">
|
||||
<Visible>False</Visible>
|
||||
<PublishState>Exclude</PublishState>
|
||||
<IncludeHash>True</IncludeHash>
|
||||
<Group>
|
||||
</Group>
|
||||
<TargetPath>
|
||||
</TargetPath>
|
||||
<PublishState>Exclude</PublishState>
|
||||
<IncludeHash>True</IncludeHash>
|
||||
<FileType>Assembly</FileType>
|
||||
</PublishFile>
|
||||
</ItemGroup>
|
||||
@@ -866,12 +868,6 @@
|
||||
<Resource Include="Images\Heads\DoodleHuang.png" />
|
||||
<Resource Include="Images\Heads\wiki.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Heads\noin.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\STUN.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Connected Services\" />
|
||||
</ItemGroup>
|
||||
@@ -901,5 +897,17 @@
|
||||
<ItemGroup>
|
||||
<None Include="Resources\java-wrapper.jar" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\ModData.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Skins\Ari.png" />
|
||||
<Resource Include="Images\Skins\Efe.png" />
|
||||
<Resource Include="Images\Skins\Kai.png" />
|
||||
<Resource Include="Images\Skins\Makena.png" />
|
||||
<Resource Include="Images\Skins\Noor.png" />
|
||||
<Resource Include="Images\Skins\Sunny.png" />
|
||||
<Resource Include="Images\Skins\Zuri.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||
</Project>
|
||||
@@ -1 +0,0 @@
|
||||
{"better-gui-scaling":"4908|更好的界面缩放 (Better GUI Scaling)","jei-lotr":"4481|~","reskillable-psi-compat":"5768|~","mob-origins":"3603|生物起源*","lods-of-emone":"3166|很多钱 (Lods of Emone)","loottweaker":"2304|~","fnars-roguelike-dungeons":"5339|冒险地牢-Fnar版 (Roguelike Dungeons -- Fnar's Edition)","hunterillager":"2735|邪猎者 (HunterIllager)|936480","all-the-tweaks":"6194|~","health-overlay":"1871|更美观的血条*","nyfs-quivers-expanded":"6622|~","zettai-psi":"5769|~","titles":"4909|头衔*","capes":"4482|~","fabric-language-scala":"3167|~","better-storage":"534|更好的储存*","better-default-biomes":"3604|更好的默认生物群系*","make-zoom-zoom":"1440|更快的加载 (MakeZoomZoom)","runelic":"6195|~","auto-feeder-helmet":"1872|自动进食头盔*","projecte":"577|等价交换重制版 (ProjectE)|1109380","rediscovered":"2305|特性重现*|359096","attack-speed-enchantment":"4483|攻击速度附魔*","playerex":"5340|~","pocket-apocalypse-mod":"2737|便携式天灾 (Pocket Apocalypse mod)","kaimyentity":"3605|KAI我的实体 (KAIMyEntity)|1170874","re-chiseled-compat":"7051|~","alexs-cloud-storage":"6196|云存储 (Cloud Storage)","zoomify":"6624|~","fluid-physics":"3168|流体物理*","minecraft-virtual-machines":"1441|Minecraft虚拟机*","psicaster":"5770|~","cc-tweaked-fabric":"1873|~","skiing":"4910|~","kitchen-mod":"2306|厨房 (The Kitchen Mod)|295019","data-attributes":"5341|~","cavern2":"1442|洞穴 II (Cavern II)|782780","minecraft-comes-alive-mca":"100|虚拟人生/凡家物语 (Minecraft Comes Alive)|727273","natures-minerals":"4484|~","compass":"2738|指南针 (compass)|1067220","auto-leveling":"7052|~","tablechair":"3606|桌椅 (TableChair)","golemania":"6625|~","playeranimator":"7487|~","cave-biomes":"4911|~","atomic-bomb-1-16":"4050|枪,炮,原子弹! (Guns, Rockets and Atomic Explosions)","tweakermore":"5771|~","hardcore-buoyance":"5342|~","simple-farming":"1874|简单农业*|988997","visuality":"6197|~","notenoughids":"1443|增加ID上限 (NotEnoughIDs)","legacy-display":"5772|~","balm-fabric":"4485|~","tinkers-evolution":"2739|匠魂进化 (Tinkers' Evolution)|1118159","packed-inventory":"7053|~","apathy-mod":"7488|~","digimobs":"1000|数码宝贝*","tatami":"4912|~","se-sign-shop":"4051|简单经济:牌子商店 (SE: Sign Shop)","zettai-grimoires":"3169|~","baubles-reborn":"2308|饰品栏重置版*","bigger-packets-please":"1875|~","vulkanmod":"6626|~","when-dungeons-arise-fabric":"3607|地牢浮现之时 (When Dungeons Arise)","ecologics":"6198|丰富的生态*","resource-hogs":"4486|资源猪 (Resourse Hogs)|1037377","pchan3-steamship-steamboat-pirates":"274|飞艇与汽船 (SteamShip - SteamBoat and Pirates)","auudio-fabric":"7489|~","storage-boats-mod":"1001|存储船 (Storage Boat Mod)|798267","final-fantasy-12-mod":"4913|~","gregtech-ce-unofficial":"5343|格雷科技社区版:非官方版 (GregTech CE: Unofficial)","avaritia-recipe-generator":"1444|可视化无尽配方编辑器*","thaumic-expansion":"749|神秘膨胀*","crafting-on-a-stick":"7055|~","tinkers-exporter":"2740|匠魂数据导出器*|1071348","sledgehammer":"6627|~","mob-scarecrows":"6199|~","eggtab-forge":"5344|独立刷怪蛋列表 (Egg Tab)","animal-feeding-trough":"3608|动物喂养槽*","mojangster":"4914|加载界面动画 (Mojangster (Animated Loading Screen))","mo-withers":"1002|更多凋灵 (Mo' Withers)","Traincraft":"317|火车工业*","advanced-xray-fabric-edition":"4487|高级透视 (Advanced XRay)","lockyz-extra-dimensions-mod":"1876|更多维度世界 (Lockyz Extra Dimensions)","trapcraft":"1445|陷阱*|260090","the-backrooms":"5773|后室*","pams-brewcraft":"2309|潘马斯酿造工艺 (Pam's Brewcraft)","quilt-loading-screen":"6628|Quilt加载画面*","wiki-zoomer":"3609|~","binnies-mods":"472|宾尼的模组合集 (Binnie's Mods)","anvil-tweaks":"4915|~","always-a-wither-skull":"5345|必得凋灵骷髅头颅 (Always a Wither Skull)","fancymenu-fabric":"4053|~|1367170","farlanders":"2741|更多末影人 (The Farlanders)|425192","mob-properties":"620|怪物属性*","amethyst-imbuement":"6629|~","psi-combat-magic":"1877|~","runorama":"3170|全景截图背景*|910751","easy-shulker-boxes":"7491|~","the-autologin-mod-for-authme-server":"1004|自动登录 (AutoLogin)","trolls-community":"6200|~","creatures-from-the-snow-forge":"5774|雪地里的生物! (Creatures From The Snow!)","asphaltmod":"4916|沥青 (Asphalt Mod)|1012064","dirtcraft":"2310|泥土工艺 (DirtCraft)","anvil-restoration":"5346|铁砧修复*","halogen":"4054|卤素*","vials":"2742|瓶瓶罐罐*","item-stages":"3171|物品阶段*","mod-name-tooltip":"1446|模组名称显示*","dtphc":"1878|动态的树:潘马斯附属 (Dynamic Trees - Pam's Harvestcraft Compat)","water-power":"361|水力科技*|190676","ring-of-attraction-fabric":"4489|吸引戒指 (Ring of Attraction)","g4mespeed":"6201|~","collisions-lib":"5775|~","zetamod":"4055|泽塔 (ZetaForged/Zeta's Mod)","hide-hands":"Line truncated
|
||||
@@ -10,7 +10,6 @@ PCL2 的代码绝大多数其实都是几年前学生时代的产物了……那
|
||||
|
||||
**相关内容:**
|
||||
- [PCL2 功能投票](https://github.com/Hex-Dragon/PCL2/discussions/2):来参加投票吧,开发者会优先处理票数较高的帖子!
|
||||
- [协助编辑权限申请](https://github.com/Hex-Dragon/PCL2/discussions/63):如果感兴趣想帮帮忙的话,可以回复这个帖子来申请加权限!
|
||||
- [程序下载](https://afdian.net/p/0164034c016c11ebafcb52540025c377):下载免费的正式版 PCL2。
|
||||
- [帮助文档库](https://github.com/LTCatt/PCL2Help):PCL2 帮助文档在 GitHub 上的存储库(是的,帮助库在另一个 Repo……)
|
||||
|
||||
@@ -20,4 +19,3 @@ PCL2 的代码绝大多数其实都是几年前学生时代的产物了……那
|
||||
- 别想在这里面找到解密游戏的线索,那部分的代码被我抠掉了(笑)
|
||||
- 哦,对,解锁隐藏主题的相关代码也都被抠掉了,所以别想着用翻源代码这种歪门邪道来绕过解密了.jpg
|
||||
- 源代码库并不是即时更新的,而是在每次 PCL2 发布更新时(手动)同步一次
|
||||
- 源代码仅以帮助公共研究为目的而公开,开发者 **保留所有权利** ,你不能复制粘贴代码到自己的项目
|
||||