Compare commits

..
6 Commits
Author SHA1 Message Date
龙腾猫跃 fd329037e7 2.4.4 2022-12-12 02:34:19 +08:00
龙腾猫跃 5fb5a3b963 2.4.3 2022-11-26 22:39:08 +08:00
龙腾猫跃 5ef1d60e2e 由于联机已被禁用,公开联机部分代码 2022-11-10 20:22:47 +08:00
龙腾猫跃 d091e153a9 删除联机的反馈选项 2022-11-08 19:57:28 +08:00
龙腾猫跃 97c5367108 2.4.2 2022-11-08 19:17:11 +08:00
龙腾猫跃 24cb4599d6 删除联机入口 2022-11-05 21:27:44 +08:00
56 changed files with 3253 additions and 688 deletions

No files matched your search

-3
View File
@@ -3,9 +3,6 @@ contact_links:
- name: 帮助文档反馈
url: https://github.com/LTCatt/PCL2Help/issues
about: 提交 PCL2 帮助系统(更多 → 帮助)相关的反馈
- name: 联机反馈与交流
url: https://shimowendang.com/docs/KrkEVXz1K0frowAJ#anchor-7qQG
about: 加入联机模块官方 QQ 群反馈联机异常,或询问联机功能的使用方式
- name: 提问
url: https://github.com/Hex-Dragon/PCL2/discussions/new?category=%E6%8F%90%E9%97%AE
about: 我不想提交反馈,只是想问一些问题
-3
View File
@@ -349,9 +349,6 @@ ModSetup.vb
PageOtherAbout.*
PageOtherTest.*
PageSetupUI.*
# 公开联机代码可能导致安全风险
Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb
Plain Craft Launcher 2/Pages/PageLink/PageLinkHiPer.xaml.vb
# 开发者工具
ModDevelop.vb
# 不公开底层函数库,以免抄袭
View File
File renamed without changes.
+23 -20
View File
@@ -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">
+5 -6
View File
@@ -15,7 +15,6 @@ Public Class Application
Log(ex, "开发者模式测试出错", LogLevel.Feedback)
End Try
End Sub
#End If
'开始
@@ -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()
@@ -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
+14 -4
View File
@@ -130,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
@@ -287,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),
@@ -302,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),
+18 -22
View File
@@ -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
@@ -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)
@@ -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
+12 -21
View File
@@ -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
'触发颜色动画
+1 -1
View File
@@ -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" />
+42 -7
View File
@@ -10,15 +10,24 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
#If BETA Then
If LastVersion < 268 Then 'Release 2.4.1
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "追加新的联机方式(HiPer 联机模块)"))
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 += 12
BugCount += 30
FeatureCount += 14
BugCount += 33
End If
If LastVersion < 265 Then 'Release 2.3.5
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复部分情况下无法启动路径带有中文的游戏的 Bug"))
@@ -100,8 +109,27 @@ Public Class FormMain
'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
If LastVersion = 266 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 HiPer 联机模块的使用体验"))
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 中文名的显示"))
@@ -109,7 +137,6 @@ Public Class FormMain
BugCount += 22
End If
If LastVersion < 266 Then 'Snapshot 2.4.0
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "追加新的联机方式(HiPer 联机模块)"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "游戏崩溃的弹窗添加了直接查看日志的选项"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在更多分类下添加了新功能投票选项"))
FeatureCount += 3
@@ -1046,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
@@ -1128,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>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

+99 -57
View File
@@ -10,12 +10,12 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
Public Const VersionBaseName As String = "2.4.1" '不含分支前缀的显示用版本名
Public Const VersionStandardCode As String = "2.4.1." & 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 = 268 'Release
Public Const VersionCode As Integer = 272 'Release
#Else
Public Const VersionCode As Integer = 267 'Snapshot
Public Const VersionCode As Integer = 273 'Snapshot
#End If
'自动生成的版本信息
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -771,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) '支持读取使用中的文件
@@ -787,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
@@ -797,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 ""
@@ -1221,7 +1223,7 @@ Re:
Return Nothing
Catch ex As Exception
Log(ex, "检查文件出错")
Return GetString(ex)
Return GetExceptionSummary(ex)
End Try
End Function
End Class
@@ -1323,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>
@@ -2430,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)
@@ -2451,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)
+10 -6
View File
@@ -412,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 = ""
@@ -1183,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
''使用该下载源的线程是否没有速度
''下载超时也会导致没有速度,容易误判下载失败,所以已弃用此方法
@@ -1697,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
@@ -1719,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
@@ -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
@@ -771,7 +771,7 @@ Redo:
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版本过高
@@ -221,6 +221,7 @@
McDownloadClientUpdateHint(Version, Json)
IsNewClientVersionHinted = True
End If
McVersionHighest = Version.Split(".")(1)
Setup.Set("ToolUpdateReleaseLast", Version)
'解析更新提示(Snapshot)
Version = Json("latest")("snapshot")
@@ -609,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
@@ -653,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})
@@ -769,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>
@@ -1087,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
@@ -1130,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, ", ") & "] "
@@ -1208,12 +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
@@ -1250,6 +1254,12 @@
''' CurseForge 工程列表获取事件。
''' </summary>
Public Sub DlCfProjectSub(Task As LoaderTask(Of DlCfProjectRequest, DlCfProjectResult))
'拒绝 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
@@ -1276,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)
'去除常见连接词
@@ -1429,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
@@ -1478,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
@@ -1490,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>
@@ -1510,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, "")
@@ -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}
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},
@@ -59,6 +115,7 @@ Public Module ModLaunch
If McLoginLoader.State = LoadState.Finished Then McLoginLoader.State = LoadState.Waiting '要求重启登录主加载器,它会自行决定是否启动副加载器
'等待加载器执行并更新 UI
McLaunchLoaderReal = LaunchLoader
AbortHint = Nothing
LaunchLoader.Start()
'任务栏进度条
LoaderTaskbarAdd(LaunchLoader)
@@ -72,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
@@ -92,7 +153,7 @@ NextInner:
GoTo NextInner
Else
'没有特殊处理过的错误信息
McLaunchLog("错误:" & GetString(ex, False))
McLaunchLog("错误:" & GetExceptionDetail(ex))
Log(ex, "Minecraft 启动失败", LogLevel.Msgbox, "启动失败")
Throw
End If
@@ -492,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("已触发超时登录失败")
@@ -507,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
@@ -516,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
@@ -599,7 +660,7 @@ LoginFinish:
Names.Insert(0, Input.UserName)
Setup.Set("LoginLegacyName", Join(Names.ToArray, "¨"))
Catch ex As Exception
Dim AllMessage As String = GetString(ex)
Dim AllMessage As String = GetExceptionSummary(ex)
Log(ex, "登录失败原始错误信息", LogLevel.Normal)
Dim ThrowEx As Exception = ex
If AllMessage.Contains("403") Then
@@ -607,7 +668,7 @@ LoginFinish:
ElseIf AllMessage.Contains("超时") OrElse AllMessage.Contains("imeout") OrElse AllMessage.Contains("网络请求失败") Then
ThrowEx = New Exception("$登录失败:连接登录服务器超时。" & vbCrLf & "请检查 HiPer 联机模块的连接状况是否良好,或选择其他登录方式!")
End If
McLaunchLog("登录失败:" & GetString(ThrowEx))
McLaunchLog("登录失败:" & GetExceptionSummary(ThrowEx))
Throw ThrowEx
End Try
End Sub
@@ -737,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 账号已迁移至微软账号,请在上方的登录方式中选择 微软 并再次尝试登录!")
@@ -944,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("$登录尝试太过频繁,请等待几分钟后再试!")
@@ -968,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
@@ -1078,19 +1148,30 @@ SystemBrowser:
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 > 0 AndAlso VersionSortBoolean("14.23.5.2855", McVersionCurrent.Version.ForgeVersion) Then
'1.12,Forge 14.23.5.2855 及更低:Java 8
'<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 > 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 > 0 Then
'1.15 - 1.16:Java 8 - 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
@@ -1101,8 +1182,8 @@ SystemBrowser:
'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 - 15
MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999)
'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)
@@ -1150,22 +1231,27 @@ SystemBrowser:
Private McLaunchArgument As String
''' <summary>
''' 释放 Java Wrapper 并返回文件路径。
''' 释放 Java Wrapper 并返回完整文件路径。
''' </summary>
Public Function ExtractJavaWrapper() As String
Dim WrapperPath As String = PathAppdata & "JavaWrapper.jar"
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 & "JavaWrapper.jar"
WrapperPath = PathTemp.TrimEnd("\")
If Encoding.UTF8.GetByteCount(PathTemp) <> PathTemp.Length Then
Log("[Java] Temp 路径中包含非 ASCII 字符,换用 C 盘根目录")
WrapperPath = "C:\PCL\JavaWrapper.jar"
WrapperPath = "C:\PCL"
End If
End If
If Not File.Exists(WrapperPath) OrElse New FileInfo(WrapperPath).Length > 20 * 1024 Then
WriteFile(WrapperPath, GetResources("JavaWrapper"))
Log("[Java] 已自动释放 Java Wrapper:" & WrapperPath)
End If
Return WrapperPath
End Function
@@ -1185,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 参数获取成功")
@@ -1210,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
'包含端口号
@@ -1270,6 +1356,7 @@ SystemBrowser:
'添加 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() & """")
'添加 MainClass
@@ -1336,6 +1423,7 @@ NextVersion:
'添加 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" 合并到一起
@@ -1502,9 +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)) '包含版本 Jar 的条件是不为 1.17+ 的 Forge
Dim LibList As List(Of McLibToken) = McLibListGet(Version, True) '如果在 1.19.x Forge 不包含版本 Jar 会导致 #188
Dim LibList As List(Of McLibToken) = McLibListGet(Version, True)
Loader.Output = LibList
Dim CpStrings As New List(Of String)
Dim OptiFineCp As String = Nothing
@@ -1561,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
@@ -1581,7 +1667,7 @@ NextVersion:
File.Delete(FileName)
Catch ex As UnauthorizedAccessException
McLaunchLog("删除多余文件访问被拒绝,跳过删除步骤")
McLaunchLog("实际的错误信息:" & GetString(ex))
McLaunchLog("实际的错误信息:" & GetExceptionSummary(ex))
Exit Sub
End Try
Next
@@ -1814,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)
@@ -1843,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.GetEncoding("GB18030"))
Catch ex As Exception
Log(ex, "输出启动脚本失败")
End Try
'进程优先级处理
Try
If GameProcess.HasExited Then Exit Try '可能在启动游戏进程的同时刚好取消了启动
@@ -458,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
@@ -495,17 +492,24 @@ RetryGet:
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 MyMsgBox("你在启动设置中指定了使用 Java " & UserJava.VersionCode & ",但当前版本" & Requirement & "。" & vbCrLf &
"如果强制使用该 Java,可能会导致游戏崩溃。" & vbCrLf &
vbCrLf &
" - 指定的 Java:" & UserJava.ToString,
"Java 兼容性警告", "让 PCL2 自动选择", "强制使用该 Java") = 2 Then
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
@@ -1267,7 +1271,7 @@ Recheck:
'检查文件夹
If Not Directory.Exists(Path) Then
State = McVersionState.Error
Info = "该文件夹不存在"
Info = "未找到版本 " & Name
Return False
End If
'检查权限
@@ -1303,7 +1307,7 @@ Recheck:
Catch ex As Exception
Log(ex, "依赖版本检查出错(" & Name & ")")
State = McVersionState.Error
Info = "未知错误:" & GetString(ex)
Info = "未知错误:" & GetExceptionSummary(ex)
Return False
End Try
@@ -1315,7 +1319,6 @@ Recheck:
''' </summary>
Public Function Load() As McVersion
Try
Directory.CreateDirectory(Path & "PCL")
'检查版本,若出错则跳过数据确定阶段
If Not Check() Then GoTo ExitDataLoad
#Region "确定版本分类"
@@ -1420,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)
@@ -1435,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)
@@ -1450,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
@@ -2323,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)
@@ -2376,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
@@ -2508,24 +2529,26 @@ NextVersion:
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"
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)))
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
@@ -3647,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
@@ -3723,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
'两边均缺失,感觉是一个东西
@@ -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)
@@ -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)
+6 -25
View File
@@ -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.4.1.0")>
<Assembly: AssemblyFileVersion("2.4.1.0")>
<Assembly: AssemblyVersion("2.4.4.0")>
<Assembly: AssemblyFileVersion("2.4.4.0")>
<Assembly: NeutralResourcesLanguage("")>
@@ -1,8 +1,15 @@
Imports System.IO.Compression
Public Module ModDownloadLib
'如果 OptiFine 与 Forge 同时开始安装,就会导致 Forge 安装失败
''' <summary>
''' 如果 OptiFine 与 Forge 同时开始安装,就会导致 Forge 安装失败,所以在这里添加一个锁。
''' </summary>
Private InstallSyncLock As New Object
''' <summary>
''' 最高的 Minecraft 大版本号,-1 代表尚未获取。
''' </summary>
Public McVersionHighest As Integer = -1
#Region "Minecraft 下载"
@@ -114,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})
@@ -159,6 +166,7 @@ Public Module ModDownloadLib
End Function
Private Const McDownloadClientLibName As String = "下载原版支持库文件"
Private Const McDownloadClientJsonName As String = "下载原版 Json 文件"
#End Region
@@ -378,7 +386,7 @@ Public Module ModDownloadLib
Throw New Exception("未找到用于安装 OptiFine 的 Java")
End If
'添加 Java Wrapper 作为主 Jar
Dim Arguments = "-Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer"
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
'开始启动
SyncLock InstallSyncLock
@@ -518,27 +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
If Loader.State = LoadState.Loading Then
Log("[Download] OptiFine 安装正在等待原版文件下载完成")
Loader.WaitForExit()
End If
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})
@@ -876,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"))
@@ -1094,7 +1103,7 @@ Public Module ModDownloadLib
Throw New Exception("未找到用于安装 Forge 的 Java")
End If
'添加 Java Wrapper 作为主 Jar
Dim Arguments = "-cp """ & PathTemp & "Cache\forge_installer.jar;" & Target & """ -jar """ & ExtractJavaWrapper() & """ com.bangbang93.ForgeInstaller """ & McFolder
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
'开始启动
SyncLock InstallSyncLock
@@ -1329,27 +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
If Loader.State = LoadState.Loading Then
Log("[Download] Forge 安装正在等待原版文件下载完成")
Loader.WaitForExit()
End If
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})
@@ -1814,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
@@ -1831,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
@@ -2074,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 = If(AllArguments.StartsWith("--"), "--", "") & 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
@@ -164,13 +164,12 @@
'构造步骤加载器
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()
If Not ModpackInstall(Target, VersionName) Then Throw New Exception("整合包安装过程中出现异常!")
If Not Setup.Get("ToolDownloadKeepModpack") Then
Log("[Download] 根据设置要求删除原始整合包文件:" & Target)
IO.File.Delete(Target)
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})
@@ -178,7 +177,7 @@
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
@@ -196,63 +195,124 @@
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.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
@@ -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
@@ -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
@@ -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
@@ -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, IsForceRestart:=True)
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
@@ -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
File diff suppressed because it is too large. Load diff
@@ -18,7 +18,6 @@
<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="新功能投票"
EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8"
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
@@ -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 参数,在没有确定把握的情况下请不要尝试修改。&#xA;你可以通过点击左侧选项卡的初始化按钮来恢复到默认设置。" 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="文本框中的内容将会被直接拼合在启动参数的末尾。&#xA;例如输入 --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 文件夹。&#xA;如果你没有修改相关文件,请勿勾选此项。&#xA;更推荐在版本设置中关闭特定版本的校验,而不是在这里关闭所有版本的校验。" 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 参数,在没有确定把握的情况下请不要尝试修改。&#xA;你可以通过点击左侧选项卡的初始化按钮来恢复到默认设置。" 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="文本框中的内容将会被直接拼合在启动参数的末尾。&#xA;例如输入 --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 文件夹。&#xA;如果你没有修改相关文件,请勿勾选此项。&#xA;更推荐在版本设置中关闭特定版本的校验,而不是在这里关闭所有版本的校验。" 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
@@ -208,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
@@ -219,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)
@@ -7,11 +7,11 @@
Public Sub RefreshModDisabled() Handles Me.Loaded
If Version IsNot Nothing AndAlso Version.Modable Then
ItemMod.Visibility = Visibility.Visible
ItemModDisabled.Visibility = Visibility.Collapsed
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="该版本默认将不会在版本列表中显示。&#xA;在版本列表页面按下 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 索引与缺失、校验失败的文件。&#xa;若游戏缺失音效,请尝试此项。" 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
@@ -67,6 +67,7 @@
Catch ex As Exception
Log(ex, "修改版本分类失败(" & PageVersionLeft.Version.Name & ")", LogLevel.Feedback)
End Try
Reload() '更新 “打开 Mod 文件夹” 按钮
Else
'改为隐藏
Try
@@ -85,6 +86,7 @@
End Try
End If
End Sub
'更改描述
Private Sub BtnDisplayDesc_Click(sender As Object, e As EventArgs) Handles BtnDisplayDesc.Click
Try
@@ -98,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
@@ -171,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
@@ -280,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
@@ -119,6 +119,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleSet>BasicDesignGuidelineRules.ruleset</CodeAnalysisRuleSet>
<DefineConstants>BETA</DefineConstants>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
@@ -867,9 +868,6 @@
<Resource Include="Images\Heads\DoodleHuang.png" />
<Resource Include="Images\Heads\wiki.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Heads\noin.png" />
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
@@ -902,5 +900,14 @@
<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>
Binary file not shown.
Binary file not shown.