2.14.0.0
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
<local:MyPageRight
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:PCL" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:PCL" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" x:Class="PageDownloadInstall"
|
||||
PanScroll="PanBack">
|
||||
<Grid>
|
||||
@@ -14,19 +14,96 @@
|
||||
</StackPanel.RenderTransform>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" x:Name="PanSelect" Visibility="Collapsed" Opacity="0" IsHitTestVisible="False" Margin="0,0,0,45">
|
||||
<StackPanel.Resources>
|
||||
<Style x:Key="ModifyCompareIcon" TargetType="{x:Type local:MyImage}">
|
||||
<Setter Property="Width" Value="18" />
|
||||
<Setter Property="Height" Value="18" />
|
||||
<Setter Property="RenderOptions.BitmapScalingMode" Value="Linear" />
|
||||
</Style>
|
||||
<Style x:Key="ModifyCompareText" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BasedOnTextBlock}">
|
||||
<Setter Property="Margin" Value="7,0,0,0" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style x:Key="ModifyCompareArrow" TargetType="{x:Type Path}">
|
||||
<Setter Property="Data" Value="M3,3 L7,7 3,11 M9,3 L13,7 9,11" />
|
||||
<Setter Property="Margin" Value="10,0,18,0" />
|
||||
<Setter Property="Height" Value="14" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Stroke" Value="{DynamicResource ColorBrushGray2}" />
|
||||
<Setter Property="StrokeThickness" Value="1.4" />
|
||||
<Setter Property="StrokeStartLineCap" Value="Round" />
|
||||
<Setter Property="StrokeEndLineCap" Value="Round" />
|
||||
<Setter Property="StrokeLineJoin" Value="Round" />
|
||||
</Style>
|
||||
<sys:String x:Key="ModifyRestoreLogo">M9.83,3.17 A1.18,1.18 0 0 1 9.83,4.83 L6.85,7.82 H14.5 A6.68,6.68 0 0 1 14.5,21.18 H11 A1.18,1.18 0 0 1 11,18.82 H14.5 A4.32,4.32 0 0 0 14.5,10.18 H6.85 L9.83,13.17 A1.18,1.18 0 0 1 8.17,14.83 L3.17,9.83 A1.18,1.18 0 0 1 3.17,8.17 L8.17,3.17 A1.18,1.18 0 0 1 9.83,3.17 Z</sys:String>
|
||||
<sys:String x:Key="ModifyClearLogo">F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z</sys:String>
|
||||
<Style x:Key="ModifyRestoreButton" TargetType="{x:Type local:MyIconButton}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Setter Property="Height" Value="30" />
|
||||
<Setter Property="Width" Value="30" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="Margin" Value="0,5,32,0" />
|
||||
<Setter Property="ToolTip" Value="撤销更改" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
</Style>
|
||||
<Style x:Key="ModifyClearButton" TargetType="{x:Type local:MyIconButton}">
|
||||
<Setter Property="Height" Value="30" />
|
||||
<Setter Property="Width" Value="30" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="Margin" Value="0,5,32,0" />
|
||||
<Setter Property="ToolTip" Value="取消安装" />
|
||||
</Style>
|
||||
</StackPanel.Resources>
|
||||
<StackPanel.RenderTransform>
|
||||
<TranslateTransform X="40" />
|
||||
</StackPanel.RenderTransform>
|
||||
<local:MyCard Margin="0,15,0,15" UseAnimation="False" Height="62">
|
||||
<local:MyCard x:Name="CardSelectName" Margin="0,15,0,15" MinHeight="62">
|
||||
<local:MyIconButton HorizontalAlignment="Left" Theme="Black" Opacity="0.6" x:Name="BtnBack" Margin="13,0,0,0" Height="26" Width="26"
|
||||
LogoScale="0.87" Logo="M1097 584 250 584 562 896C591 925 591 972 562 1001 533 1030 487 1030 458 1001L21 565C6 550-0 531 0 511L0 511 0 511C-0 492 6 472 21 457L458 21C487-7 533-7 562 21 591 50 591 97 562 126L250 438 1097 438C1137 438 1170 471 1170 511 1170 551 1137 584 1097 584L1097 584Z" />
|
||||
<local:MyImage x:Name="ImgLogo" Margin="52,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" Height="32" RenderOptions.BitmapScalingMode="HighQuality" />
|
||||
<local:MyTextBox Margin="93,0,16,0" Padding="-1,0" MinHeight="30" FontSize="15" VerticalAlignment="Center" x:Name="TextSelectName" MaxLength="70" HasBackground="False" />
|
||||
<local:MyImage x:Name="ImgLogo" Margin="52,15,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Height="32" RenderOptions.BitmapScalingMode="HighQuality" />
|
||||
<local:MyTextBox Margin="93,16,16,0" Padding="-1,0" MinHeight="30" FontSize="15" VerticalAlignment="Top" x:Name="TextSelectName" MaxLength="70" HasBackground="False" ShowValidateResult="False" />
|
||||
<TextBlock x:Name="LabSelectName" Visibility="Collapsed" Height="21" Margin="56,47,42,11" Padding="0,4,0,0" VerticalAlignment="Top" FontSize="12.5" Foreground="{DynamicResource ColorBrushGray3}" TextTrimming="CharacterEllipsis" />
|
||||
<local:MyIconButton x:Name="BtnOriginalNameRestore" Style="{StaticResource ModifyRestoreButton}" Margin="0,16,6,0"
|
||||
Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyHint x:Name="HintSelectName" Theme="Red" Visibility="Collapsed" />
|
||||
<local:MyHint Text="如果不安装 Fabric API,大多数 Mod 都会无法使用!" Margin="0,10,0,0" x:Name="HintFabricAPI" Theme="Red" />
|
||||
<local:MyHint Text="必须安装 OptiFabric 才能正常使用 OptiFine!" Margin="0,10,0,0" x:Name="HintOptiFabric" Theme="Red" />
|
||||
<local:MyHint Text="安装结束后,请在 Mod 下载中搜索 OptiFabric Origins 并下载,否则 OptiFine 会无法使用!" Margin="0,10,0,0" x:Name="HintOptiFabricOld" Theme="Yellow" />
|
||||
<local:MyHint Text="OptiFine 与一部分 Mod 的兼容性不佳,请谨慎安装。" Margin="0,10,0,0" x:Name="HintModOptiFine" Theme="Yellow" />
|
||||
<local:MyCard Title="Minecraft" Height="40" Margin="0,12,0,0" x:Name="CardMinecraft" Visibility="Collapsed">
|
||||
<Grid x:Name="PanMinecraftInfo" Height="18" Margin="132,11,35,0" VerticalAlignment="Top">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" /><ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyImage x:Name="ImgMinecraft" Height="18" Width="18" Margin="0,0,7,0" RenderOptions.BitmapScalingMode="Linear" />
|
||||
<TextBlock x:Name="LabMinecraftVersion" Grid.Column="1" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
|
||||
</Grid>
|
||||
<Grid x:Name="PanMinecraftCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage x:Name="ImgMinecraftOld" Style="{StaticResource ModifyCompareIcon}" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabMinecraftOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage x:Name="ImgMinecraftNew" Style="{StaticResource ModifyCompareIcon}" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabMinecraftNew" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<Grid Height="40" VerticalAlignment="Top" Background="Transparent" Cursor="Hand">
|
||||
<Path HorizontalAlignment="Right" Margin="0,0,16,0" Stretch="Uniform" Height="6" Width="10" Fill="{StaticResource ColorBrush1}" RenderTransformOrigin="0.5,0.5">
|
||||
<Path.Data>M2,4 l-2,2 10,10 10,-10 -2,-2 -8,8 -8,-8 z</Path.Data>
|
||||
<Path.RenderTransform><RotateTransform Angle="270" /></Path.RenderTransform>
|
||||
</Path>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnMinecraftRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="Forge" Height="40" Margin="0,12,0,0" x:Name="CardForge" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanForge" />
|
||||
<Grid x:Name="PanForgeInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||
@@ -37,13 +114,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgForge" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Anvil.png" />
|
||||
<local:MyImage x:Name="ImgForge" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Anvil.png" />
|
||||
<TextBlock x:Name="LabForge" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnForgeClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnForgeClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanForgeCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Anvil.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabForgeOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Anvil.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnForgeClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnForgeRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="NeoForge" Height="40" Margin="0,12,0,0" x:Name="CardNeoForge" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanNeoForge" />
|
||||
@@ -55,13 +144,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgNeoForge" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/NeoForge.png" />
|
||||
<local:MyImage x:Name="ImgNeoForge" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/NeoForge.png" />
|
||||
<TextBlock x:Name="LabNeoForge" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnNeoForgeClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnNeoForgeClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanNeoForgeCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/NeoForge.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabNeoForgeOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/NeoForge.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnNeoForgeClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnNeoForgeRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="Fabric" Height="40" Margin="0,12,0,0" x:Name="CardFabric" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabric" />
|
||||
@@ -73,13 +174,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgFabric" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Fabric.png" />
|
||||
<local:MyImage x:Name="ImgFabric" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Fabric.png" />
|
||||
<TextBlock x:Name="LabFabric" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnFabricClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnFabricClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanFabricCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Fabric.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabFabricOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Fabric.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnFabricClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnFabricRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="Fabric API" Height="40" Margin="0,12,0,0" x:Name="CardFabricApi" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabricApi" />
|
||||
@@ -91,13 +204,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgFabricApi" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Fabric.png" />
|
||||
<local:MyImage x:Name="ImgFabricApi" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Fabric.png" />
|
||||
<TextBlock x:Name="LabFabricApi" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnFabricApiClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnFabricApiClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanFabricApiCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Fabric.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabFabricApiOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Fabric.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnFabricApiClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnFabricApiRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="OptiFine" Height="40" Margin="0,12,0,0" x:Name="CardOptiFine" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top">
|
||||
@@ -111,13 +236,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgOptiFine" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/GrassPath.png" />
|
||||
<local:MyImage x:Name="ImgOptiFine" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/GrassPath.png" />
|
||||
<TextBlock x:Name="LabOptiFine" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnOptiFineClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnOptiFineClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanOptiFineCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/GrassPath.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabOptiFineOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/GrassPath.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnOptiFineClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnOptiFineRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="OptiFabric" Height="40" Margin="0,12,0,0" x:Name="CardOptiFabric" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanOptiFabric" />
|
||||
@@ -129,13 +266,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgOptiFabric" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="HighQuality" Source="pack://application:,,,/images/Blocks/OptiFabric.png" />
|
||||
<local:MyImage x:Name="ImgOptiFabric" Margin="0,0,7,0" SnapsToDevicePixels="True" Height="18" RenderOptions.BitmapScalingMode="HighQuality" Source="pack://application:,,,/images/Blocks/OptiFabric.png" />
|
||||
<TextBlock x:Name="LabOptiFabric" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnOptiFabricClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnOptiFabricClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanOptiFabricCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/OptiFabric.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabOptiFabricOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/OptiFabric.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnOptiFabricClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnOptiFabricRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
<local:MyCard Title="LiteLoader" Height="40" Margin="0,12,0,0" x:Name="CardLiteLoader" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
||||
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanLiteLoader" />
|
||||
@@ -147,13 +296,25 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="ImgLiteLoader" Margin="-1,0,6,0" SnapsToDevicePixels="True" Height="20" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Egg.png" />
|
||||
<local:MyImage x:Name="ImgLiteLoader" Margin="-1,0,6,0" SnapsToDevicePixels="True" Height="20" RenderOptions.BitmapScalingMode="Linear" Source="pack://application:,,,/images/Blocks/Egg.png" />
|
||||
<TextBlock x:Name="LabLiteLoader" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||
</Grid>
|
||||
<Grid x:Name="BtnLiteLoaderClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
||||
<Path x:Name="BtnLiteLoaderClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
|
||||
<Grid x:Name="PanLiteLoaderCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<DockPanel>
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Egg.png" DockPanel.Dock="Left" />
|
||||
<TextBlock x:Name="LabLiteLoaderOld" Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
<Path Grid.Column="1" Style="{StaticResource ModifyCompareArrow}" />
|
||||
<DockPanel Grid.Column="2">
|
||||
<local:MyImage Style="{StaticResource ModifyCompareIcon}" Source="pack://application:,,,/images/Blocks/Egg.png" DockPanel.Dock="Left" />
|
||||
<TextBlock Style="{StaticResource ModifyCompareText}" />
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<local:MyIconButton x:Name="BtnLiteLoaderClear" Style="{StaticResource ModifyClearButton}" Theme="Black" LogoScale="0.5" Logo="{StaticResource ModifyClearLogo}" />
|
||||
<local:MyIconButton x:Name="BtnLiteLoaderRestore" Style="{StaticResource ModifyRestoreButton}" Theme="Black" LogoScale="0.55" Logo="{StaticResource ModifyRestoreLogo}" />
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@@ -163,7 +324,7 @@
|
||||
LogoScale="0.95" Logo="M955 610h-59c-15 0-29 13-29 29v196c0 15-13 29-29 29h-649c-15 0-29-13-29-29v-196c0-15-13-29-29-29h-59c-15 0-29 13-29 29V905c0 43 35 78 78 78h787c43 0 78-35 78-78V640c0-15-13-29-29-29zM492 740c11 11 29 11 41 0l265-265c11-11 11-29 0-41l-41-41c-11-11-29-11-41 0l-110 110c-11 11-33 3-33-13V68C571 53 555 39 541 39h-59c-15 0-29 13-29 29v417c0 17-21 25-33 13l-110-110c-11-11-29-11-41 0L226 433c-11 11-11 29 0 41L492 740z" />
|
||||
</Grid>
|
||||
<local:MyCard HorizontalAlignment="Center" VerticalAlignment="Center" Margin="40,0" SnapsToDevicePixels="True" x:Name="PanLoad" UseAnimation="False">
|
||||
<local:MyLoading Text="正在获取版本列表" Margin="20,20,20,17" x:Name="LoadMinecraft" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
<local:MyLoading Text="正在加载" Margin="20,20,20,17" x:Name="LoadMinecraft" HorizontalAlignment="Center" VerticalAlignment="Center" ShowProgress="True" />
|
||||
<local:MyLoading Visibility="Collapsed" x:Name="LoadOptiFine" HasAnimation="False" />
|
||||
<local:MyLoading Visibility="Collapsed" x:Name="LoadForge" HasAnimation="False" />
|
||||
<local:MyLoading Visibility="Collapsed" x:Name="LoadNeoForge" HasAnimation="False" />
|
||||
@@ -196,4 +357,4 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
-->
|
||||
-->
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
Public Class PageDownloadInstall
|
||||
|
||||
Private Sub LoaderInit() Handles Me.Initialized
|
||||
Public Sub ControlInit()
|
||||
DisabledPageAnimControls.Add(BtnStart)
|
||||
LoadOptiFine.State = DlOptiFineListLoader
|
||||
LoadLiteLoader.State = DlLiteLoaderListLoader
|
||||
LoadFabric.State = DlFabricListLoader
|
||||
LoadFabricApi.State = DlFabricApiLoader
|
||||
LoadNeoForge.State = DlNeoForgeListLoader
|
||||
LoadOptiFabric.State = DlOptiFabricLoader
|
||||
|
||||
McDownloadForgeRecommendedRefresh()
|
||||
End Sub
|
||||
|
||||
Public Overridable Sub LoaderInit() Handles Me.Initialized
|
||||
ControlInit()
|
||||
PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, DlClientListLoader, AddressOf LoadMinecraft_OnFinish)
|
||||
End Sub
|
||||
|
||||
Private IsLoad As Boolean = False
|
||||
Private Sub Init() Handles Me.Loaded
|
||||
Public Overridable Sub Init() Handles Me.Loaded
|
||||
If IsLoad Then
|
||||
IsSelectNameEdited = False
|
||||
ExitSelectPage()
|
||||
If DlClientListLoader.State = LoadState.Finished Then TrySelectWaitingVersion()
|
||||
End If
|
||||
IsLoad = True
|
||||
PanBack.ScrollToHome()
|
||||
DlOptiFineListLoader.Start()
|
||||
DlLiteLoaderListLoader.Start()
|
||||
@@ -17,35 +35,19 @@ Public Class PageDownloadInstall
|
||||
TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {New ValidateFolderName(McFolderSelected & "versions")}
|
||||
TextSelectName.Validate()
|
||||
ReloadSelected()
|
||||
|
||||
'非重复加载部分
|
||||
If IsLoad Then Return
|
||||
IsLoad = True
|
||||
|
||||
McDownloadForgeRecommendedRefresh()
|
||||
|
||||
LoadOptiFine.State = DlOptiFineListLoader
|
||||
LoadLiteLoader.State = DlLiteLoaderListLoader
|
||||
LoadFabric.State = DlFabricListLoader
|
||||
LoadFabricApi.State = DlFabricApiLoader
|
||||
LoadNeoForge.State = DlNeoForgeListLoader
|
||||
LoadOptiFabric.State = DlOptiFabricLoader
|
||||
End Sub
|
||||
|
||||
#Region "页面切换"
|
||||
|
||||
'页面切换动画
|
||||
Public IsInSelectPage As Boolean = False
|
||||
Private IsFirstLoaded As Boolean = False
|
||||
Private Sub EnterSelectPage()
|
||||
If IsInSelectPage Then Return
|
||||
|
||||
''' <summary>
|
||||
''' 选择页面 UI 初始化。
|
||||
''' </summary>
|
||||
Public Sub PrepareSelectPage()
|
||||
IsInSelectPage = True
|
||||
|
||||
PanInner.Margin = New Thickness(25, 10, 25, 40)
|
||||
|
||||
AutoSelectedFabricApi = False
|
||||
AutoSelectedOptiFabric = False
|
||||
IsSelectNameEdited = False
|
||||
PanSelect.Visibility = Visibility.Visible
|
||||
PanSelect.IsHitTestVisible = True
|
||||
PanMinecraft.IsHitTestVisible = False
|
||||
@@ -54,13 +56,9 @@ Public Class PageDownloadInstall
|
||||
|
||||
DisabledPageAnimControls.Remove(BtnStart)
|
||||
BtnStart.Show = True
|
||||
CardOptiFine.IsSwapped = True
|
||||
CardLiteLoader.IsSwapped = True
|
||||
CardForge.IsSwapped = True
|
||||
CardNeoForge.IsSwapped = True
|
||||
CardFabric.IsSwapped = True
|
||||
CardFabricApi.IsSwapped = True
|
||||
CardOptiFabric.IsSwapped = True
|
||||
For Each Card In {CardOptiFine, CardLiteLoader, CardForge, CardNeoForge, CardFabric, CardFabricApi, CardOptiFabric}
|
||||
Card.IsSwapped = True
|
||||
Next
|
||||
|
||||
'如果在选择页面按了刷新键,选择页的东西可能会由于动画被隐藏,但不会由于加载结束而再次显示,因此这里需要手动恢复
|
||||
For Each Control In GetAllAnimControls(PanSelect)
|
||||
@@ -69,9 +67,16 @@ Public Class PageDownloadInstall
|
||||
Control.RenderTransform = New TranslateTransform
|
||||
End If
|
||||
Next
|
||||
End Sub
|
||||
|
||||
Private Sub EnterSelectPage()
|
||||
If IsInSelectPage Then Return
|
||||
AutoSelectedFabricApi = False
|
||||
AutoSelectedOptiFabric = False
|
||||
PrepareSelectPage()
|
||||
|
||||
'启动 Forge 加载
|
||||
If McVersion.IsFormatFit(VanillaName) Then
|
||||
If McVersion.IsStandardFormat(VanillaName) Then
|
||||
Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("DlForgeVersion " & VanillaName, AddressOf DlForgeVersionMain)
|
||||
LoadForge.State = ForgeLoader
|
||||
ForgeLoader.Start(VanillaName)
|
||||
@@ -87,35 +92,27 @@ Public Class PageDownloadInstall
|
||||
AaCode(
|
||||
Sub()
|
||||
PanBack.ScrollToHome()
|
||||
TextSelectName.Validate()
|
||||
OptiFine_Loaded()
|
||||
LiteLoader_Loaded()
|
||||
Forge_Loaded()
|
||||
NeoForge_Loaded()
|
||||
Fabric_Loaded()
|
||||
FabricApi_Loaded()
|
||||
OptiFabric_Loaded()
|
||||
ReloadSelected()
|
||||
ReloadComponentLists()
|
||||
PanMinecraft.Visibility = Visibility.Collapsed
|
||||
End Sub, After:=True),
|
||||
AaOpacity(PanSelect, 1 - PanSelect.Opacity, 70, 100),
|
||||
AaTranslateX(PanSelect, -CType(PanSelect.RenderTransform, TranslateTransform).X, 160, 100, Ease:=New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
||||
AaCode(
|
||||
Sub()
|
||||
PanBack.IsHitTestVisible = True
|
||||
'初始化 Binding
|
||||
If IsFirstLoaded Then Return
|
||||
IsFirstLoaded = True
|
||||
BtnOptiFineClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFine.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
BtnLiteLoaderClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardLiteLoader.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
BtnForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardForge.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
BtnNeoForgeClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardNeoForge.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
BtnFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabric.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
BtnFabricApiClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardFabricApi.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
BtnOptiFabricClearInner.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = CardOptiFabric.MainTextBlock, .Mode = BindingMode.OneWay})
|
||||
End Sub,, True)
|
||||
AaCode(Sub() PanBack.IsHitTestVisible = True,, True)
|
||||
}, "FrmDownloadInstall SelectPageSwitch", True)
|
||||
End Sub
|
||||
|
||||
Public Sub ReloadComponentLists()
|
||||
TextSelectName.Validate()
|
||||
OptiFine_Loaded()
|
||||
LiteLoader_Loaded()
|
||||
Forge_Loaded()
|
||||
NeoForge_Loaded()
|
||||
Fabric_Loaded()
|
||||
FabricApi_Loaded()
|
||||
OptiFabric_Loaded()
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
|
||||
Public Sub ExitSelectPage() Handles BtnBack.Click
|
||||
If Not IsInSelectPage Then Return
|
||||
IsInSelectPage = False
|
||||
@@ -144,10 +141,11 @@ Public Class PageDownloadInstall
|
||||
End Sub,, True)
|
||||
}, "FrmDownloadInstall SelectPageSwitch")
|
||||
End Sub
|
||||
Public Sub MinecraftSelected(sender As MyListItem, e As MouseButtonEventArgs)
|
||||
Public Overridable Sub MinecraftSelected(sender As MyListItem, e As MouseButtonEventArgs)
|
||||
VanillaName = sender.Title
|
||||
VanillaData = sender.Tag
|
||||
VanillaIcon = sender.Logo
|
||||
LabMinecraftVersion.Text = VanillaName
|
||||
EnterSelectPage()
|
||||
End Sub
|
||||
|
||||
@@ -156,9 +154,9 @@ Public Class PageDownloadInstall
|
||||
#Region "选择"
|
||||
|
||||
'Minecraft
|
||||
Private VanillaName As String
|
||||
Private VanillaData As JObject
|
||||
Private VanillaIcon As String
|
||||
Public VanillaName As String
|
||||
Public VanillaData As JObject
|
||||
Public VanillaIcon As String
|
||||
Private ReadOnly Property VanillaDrop As Integer
|
||||
Get
|
||||
Return McVersion.VersionToDrop(VanillaName)
|
||||
@@ -166,24 +164,25 @@ Public Class PageDownloadInstall
|
||||
End Property
|
||||
|
||||
'附加组件
|
||||
Private SelectedOptiFine As DlOptiFineListEntry = Nothing
|
||||
Private SelectedLiteLoader As DlLiteLoaderListEntry = Nothing
|
||||
Private SelectedForge As DlForgeVersionEntry = Nothing
|
||||
Private SelectedNeoForge As DlNeoForgeListEntry = Nothing
|
||||
Private SelectedFabric As String = Nothing
|
||||
Private SelectedFabricApi As ResourceVersion = Nothing
|
||||
Private SelectedOptiFabric As ResourceVersion = Nothing
|
||||
Public SelectedOptiFine As DlOptiFineListEntry = Nothing
|
||||
Public SelectedLiteLoader As DlLiteLoaderListEntry = Nothing
|
||||
Public SelectedForge As DlForgeVersionEntry = Nothing
|
||||
Public SelectedNeoForge As DlNeoForgeListEntry = Nothing
|
||||
Public SelectedFabric As String = Nothing
|
||||
Public SelectedFabricApi As ResourceVersion = Nothing
|
||||
Public SelectedOptiFabric As ResourceVersion = Nothing
|
||||
|
||||
''' <summary>
|
||||
''' 重载已选择的项目的显示。
|
||||
''' </summary>
|
||||
Private Sub ReloadSelected() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardNeoForge.Swap, LoadNeoForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
|
||||
Public Overridable Sub ReloadSelected() Handles CardOptiFine.Swap, LoadOptiFine.StateChanged, CardForge.Swap, LoadForge.StateChanged, CardNeoForge.Swap, LoadNeoForge.StateChanged, CardFabric.Swap, LoadFabric.StateChanged, CardFabricApi.Swap, LoadFabricApi.StateChanged, CardOptiFabric.Swap, LoadOptiFabric.StateChanged, CardLiteLoader.Swap, LoadLiteLoader.StateChanged
|
||||
Static Ongoing As Boolean = False '#3742 中,LoadOptiFineGetError 会初始化 LoadOptiFine,触发事件 LoadOptiFine.StateChanged,导致再次调用 SelectReload
|
||||
If VanillaName Is Nothing OrElse Ongoing Then Return
|
||||
Ongoing = True
|
||||
'主预览
|
||||
SelectNameUpdate()
|
||||
ImgLogo.Source = GetSelectLogo()
|
||||
ImgMinecraft.Source = VanillaIcon
|
||||
'OptiFine
|
||||
Dim OptiFineError As String = LoadOptiFineGetError()
|
||||
CardOptiFine.MainSwap.Visibility = If(OptiFineError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||
@@ -222,7 +221,7 @@ Public Class PageDownloadInstall
|
||||
End If
|
||||
End If
|
||||
'Forge
|
||||
If Not McVersion.IsFormatFit(VanillaName) Then
|
||||
If Not McVersion.IsStandardFormat(VanillaName) Then
|
||||
CardForge.Visibility = Visibility.Collapsed
|
||||
Else
|
||||
CardForge.Visibility = Visibility.Visible
|
||||
@@ -356,7 +355,7 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 清空已选择的项目。
|
||||
''' </summary>
|
||||
Private Sub ClearSelected()
|
||||
Public Sub ClearSelected()
|
||||
VanillaName = Nothing
|
||||
VanillaData = Nothing
|
||||
VanillaIcon = Nothing
|
||||
@@ -367,7 +366,10 @@ Public Class PageDownloadInstall
|
||||
SelectedFabric = Nothing
|
||||
SelectedFabricApi = Nothing
|
||||
SelectedOptiFabric = Nothing
|
||||
IsSelectNameEdited = False
|
||||
For Each ClearButton In {BtnOptiFineClear, BtnLiteLoaderClear, BtnForgeClear, BtnNeoForgeClear,
|
||||
BtnFabricClear, BtnFabricApiClear, BtnOptiFabricClear}
|
||||
ClearButton.Visibility = Visibility.Collapsed
|
||||
Next
|
||||
End Sub
|
||||
'信息栏动画
|
||||
Private Sub SetPanelVisibility(Panel As Grid, IsVisible As Boolean)
|
||||
@@ -389,7 +391,7 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取版本图标。
|
||||
''' </summary>
|
||||
Private Function GetSelectLogo() As String
|
||||
Public Overridable Function GetSelectLogo() As String
|
||||
If SelectedFabric IsNot Nothing Then
|
||||
Return "pack://application:,,,/images/Blocks/Fabric.png"
|
||||
ElseIf SelectedForge IsNot Nothing Then
|
||||
@@ -409,7 +411,7 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取默认版本名。
|
||||
''' </summary>
|
||||
Private Function GetSelectName() As String
|
||||
Public Function GetSelectName() As String
|
||||
Dim Name As String = VanillaName
|
||||
If SelectedFabric IsNot Nothing Then Name += "-Fabric " & SelectedFabric.BeforeFirst("+")
|
||||
If SelectedForge IsNot Nothing Then Name += "-Forge_" & SelectedForge.VersionName
|
||||
@@ -418,36 +420,39 @@ Public Class PageDownloadInstall
|
||||
If SelectedOptiFine IsNot Nothing Then Name += "-OptiFine_" & SelectedOptiFine.DisplayName.Replace(VanillaName & " ", "").Replace(" ", "_")
|
||||
Return Name
|
||||
End Function
|
||||
Private IsSelectNameEdited As Boolean = False
|
||||
Private IsSelectNameChanging As Boolean = False
|
||||
Public IsSelectNameEdited As Boolean = False
|
||||
Private Sub SelectNameUpdate()
|
||||
If IsSelectNameEdited OrElse IsSelectNameChanging Then Return
|
||||
IsSelectNameChanging = True
|
||||
If IsSelectNameEdited Then Return
|
||||
TextSelectName.Text = GetSelectName()
|
||||
IsSelectNameChanging = False
|
||||
IsSelectNameEdited = False
|
||||
End Sub
|
||||
Private Sub TextSelectName_TextChanged(sender As Object, e As TextChangedEventArgs) Handles TextSelectName.TextChanged
|
||||
If IsSelectNameChanging Then Return
|
||||
IsSelectNameEdited = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub TextSelectName_ValidateChanged(sender As Object, e As EventArgs) Handles TextSelectName.ValidateChanged
|
||||
BtnStart.IsEnabled = TextSelectName.IsValidated
|
||||
HintSelectName.Text = TextSelectName.ValidateResult
|
||||
HintSelectName.Visibility = If(TextSelectName.IsValidated, Visibility.Collapsed, Visibility.Visible)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "加载器"
|
||||
Public MinecraftVersions As JArray
|
||||
Private Sub LoadMinecraft_OnFinish()
|
||||
MinecraftVersions = CType(DlClientListLoader.Output.Value("versions").DeepClone(), JArray)
|
||||
ShowMinecraftVersionList()
|
||||
TrySelectWaitingVersion() '自动选择版本
|
||||
End Sub
|
||||
|
||||
'结果数据化
|
||||
Private Sub LoadMinecraft_OnFinish()
|
||||
Public Overridable Sub ShowMinecraftVersionList()
|
||||
ExitSelectPage() '返回
|
||||
Try
|
||||
Dim Dict As New Dictionary(Of String, List(Of JObject)) From {
|
||||
{"正式版", New List(Of JObject)}, {"预览版", New List(Of JObject)}, {"远古版", New List(Of JObject)}, {"愚人节版", New List(Of JObject)}
|
||||
}
|
||||
Dim Versions As JArray = DlClientListLoader.Output.Value("versions")
|
||||
For Each Version As JObject In Versions
|
||||
For Each Version As JObject In MinecraftVersions
|
||||
'确定分类
|
||||
Dim Type As String = Version("type")
|
||||
Select Case Type
|
||||
@@ -498,7 +503,7 @@ Public Class PageDownloadInstall
|
||||
'清空当前
|
||||
PanMinecraft.Children.Clear()
|
||||
'添加最新版本
|
||||
Dim CardInfo As New MyCard With {.Title = "最新版本", .Margin = New Thickness(0, 15, 0, 15), .SwapType = 2}
|
||||
Dim CardInfo As New MyCard With {.Title = "最新版本", .Margin = New Thickness(0, 15, 0, 15)}
|
||||
Dim PinnedVersions As New List(Of JObject)
|
||||
Dim Release As JObject = Dict("正式版")(0).DeepClone()
|
||||
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
|
||||
@@ -508,36 +513,41 @@ Public Class PageDownloadInstall
|
||||
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
|
||||
PinnedVersions.Add(Snapshot)
|
||||
End If
|
||||
Dim PanInfo As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = PinnedVersions}
|
||||
MyCard.StackInstall(PanInfo, 7)
|
||||
Dim PanInfo As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0)}
|
||||
CardInfo.Children.Add(PanInfo)
|
||||
CardInfo.SwapControl = PanInfo
|
||||
CardInfo.SetContentBuilder(PinnedVersions, '使用 Lambda 转发点击事件,避免 #535
|
||||
Function(Version) McDownloadListItem(Version, Sub(sender, e) MinecraftSelected(sender, e), False))
|
||||
CardInfo.BuildContent()
|
||||
PanMinecraft.Children.Insert(0, CardInfo)
|
||||
'添加其他版本
|
||||
For Each Pair As KeyValuePair(Of String, List(Of JObject)) In Dict
|
||||
If Not Pair.Value.Any() Then Continue For
|
||||
'增加卡片
|
||||
Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15), .SwapType = 7}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
|
||||
Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15)}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0)}
|
||||
NewCard.Children.Add(NewStack)
|
||||
NewCard.SwapControl = NewStack
|
||||
NewCard.SetContentBuilder(Pair.Value,
|
||||
Function(Version) McDownloadListItem(Version, Sub(sender, e) MinecraftSelected(sender, e), False))
|
||||
NewCard.IsSwapped = True
|
||||
PanMinecraft.Children.Add(NewCard)
|
||||
Next
|
||||
'自动选择版本
|
||||
If VersionWaitingSelect Is Nothing Then Exit Try
|
||||
Logger.Info($"自动选择 MC 版本:{VersionWaitingSelect}")
|
||||
For Each Version As JObject In Versions
|
||||
If Version("id").ToString <> VersionWaitingSelect Then Continue For
|
||||
Dim Item = McDownloadListItem(Version, Sub()
|
||||
End Sub, False).Init()
|
||||
MinecraftSelected(Item, Nothing)
|
||||
VersionWaitingSelect = Nothing
|
||||
Return
|
||||
Next
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "可视化安装版本列表出错")
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub TrySelectWaitingVersion()
|
||||
If VersionWaitingSelect Is Nothing Then Return
|
||||
For Each Version As JObject In MinecraftVersions
|
||||
If Version("id").ToString <> VersionWaitingSelect Then Continue For
|
||||
Logger.Info($"自动选择 MC 版本:{VersionWaitingSelect}")
|
||||
MinecraftSelected(McDownloadListItem(Version, Nothing, False).Init(), Nothing)
|
||||
VersionWaitingSelect = Nothing
|
||||
Return
|
||||
Next
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 当 MC 版本列表加载完时,立即自动选择的版本。用于外部调用。
|
||||
''' </summary>
|
||||
@@ -550,16 +560,16 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取 OptiFine 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadOptiFineGetError() As String
|
||||
Public Function LoadOptiFineGetError() As String
|
||||
If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
|
||||
'检查 Forge 1.13 - 1.14.3:全部不兼容
|
||||
If SelectedForge IsNot Nothing AndAlso
|
||||
CompareVersion(VanillaName, "1.13") >= 0 AndAlso CompareVersion("1.14.3", VanillaName) >= 0 Then
|
||||
McUtils.CompareVersionGE(VanillaName, "1.13") AndAlso McUtils.CompareVersionGE("1.14.3", VanillaName) Then
|
||||
Return "与 Forge 不兼容"
|
||||
End If
|
||||
'检查 Fabric 1.20.5+:全部不兼容
|
||||
If SelectedFabric IsNot Nothing AndAlso
|
||||
CompareVersion(VanillaName, "1.20.4") > 0 Then
|
||||
McUtils.CompareVersion(VanillaName, "1.20.4") > 0 Then
|
||||
Return "与 Fabric 不兼容"
|
||||
End If
|
||||
'检查 Loader
|
||||
@@ -584,12 +594,12 @@ Public Class PageDownloadInstall
|
||||
End Function
|
||||
|
||||
'检查某个 OptiFine 是否与某个 Forge 兼容
|
||||
Private Function IsOptiFineSuitForForge(OptiFine As DlOptiFineListEntry, Forge As DlForgeVersionEntry)
|
||||
Public Shared Function IsOptiFineSuitForForge(OptiFine As DlOptiFineListEntry, Forge As DlForgeVersionEntry) As Boolean
|
||||
If Forge.Inherit <> OptiFine.Inherit Then Return False '不是同一个大版本
|
||||
If OptiFine.RequiredForgeVersion Is Nothing Then Return False '不兼容 Forge
|
||||
If String.IsNullOrWhiteSpace(OptiFine.RequiredForgeVersion) Then Return True '#4183
|
||||
If OptiFine.RequiredForgeVersion.Contains(".") Then 'XX.X.XXX
|
||||
Return CompareVersion(Forge.Version.ToString, OptiFine.RequiredForgeVersion) = 0
|
||||
Return McUtils.CompareVersion(Forge.Version.ToString, OptiFine.RequiredForgeVersion) = 0
|
||||
Else 'XXXX
|
||||
Return Forge.Version.Revision = OptiFine.RequiredForgeVersion
|
||||
End If
|
||||
@@ -619,7 +629,7 @@ Public Class PageDownloadInstall
|
||||
Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
|
||||
If Not Left.IsPreview AndAlso Right.IsPreview Then Return True
|
||||
If Left.IsPreview AndAlso Not Right.IsPreview Then Return False
|
||||
Return CompareVersionGE(Left.DisplayName, Right.DisplayName)
|
||||
Return McUtils.CompareVersionGE(Left.DisplayName, Right.DisplayName)
|
||||
End Function)
|
||||
'可视化
|
||||
PanOptiFine.Children.Clear()
|
||||
@@ -641,12 +651,12 @@ Public Class PageDownloadInstall
|
||||
CardOptiFine.IsSwapped = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub OptiFine_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFineClear.MouseLeftButtonUp
|
||||
Private Sub OptiFine_Clear(sender As Object, e As EventArgs) Handles BtnOptiFineClear.Click
|
||||
SelectedOptiFine = Nothing
|
||||
SelectedOptiFabric = Nothing
|
||||
BtnOptiFabricClear.Visibility = Visibility.Collapsed
|
||||
AutoSelectedOptiFabric = False
|
||||
CardOptiFine.IsSwapped = True
|
||||
e.Handled = True
|
||||
Forge_Loaded()
|
||||
NeoForge_Loaded()
|
||||
ReloadSelected()
|
||||
@@ -659,7 +669,7 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取 LiteLoader 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadLiteLoaderGetError() As String
|
||||
Public Function LoadLiteLoaderGetError() As String
|
||||
'检查 Loader
|
||||
If GetLoaderError(LoadLiteLoader) IsNot Nothing Then Return GetLoaderError(LoadLiteLoader)
|
||||
'检查版本
|
||||
@@ -699,10 +709,9 @@ Public Class PageDownloadInstall
|
||||
CardLiteLoader.IsSwapped = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub LiteLoader_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnLiteLoaderClear.MouseLeftButtonUp
|
||||
Private Sub LiteLoader_Clear(sender As Object, e As EventArgs) Handles BtnLiteLoaderClear.Click
|
||||
SelectedLiteLoader = Nothing
|
||||
CardLiteLoader.IsSwapped = True
|
||||
e.Handled = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
|
||||
@@ -713,8 +722,8 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取 Forge 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadForgeGetError() As String
|
||||
If CompareVersionGE("1.5.1", VanillaName) AndAlso CompareVersionGE(VanillaName, "1.1") Then Return "无"
|
||||
Public Function LoadForgeGetError() As String
|
||||
If McUtils.CompareVersionGE("1.5.1", VanillaName) AndAlso McUtils.CompareVersionGE(VanillaName, "1.1") Then Return "无"
|
||||
'检查 Loader
|
||||
If GetLoaderError(LoadForge) IsNot Nothing Then Return GetLoaderError(LoadForge)
|
||||
Dim Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = LoadForge.State
|
||||
@@ -725,7 +734,7 @@ Public Class PageDownloadInstall
|
||||
If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
|
||||
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
||||
If SelectedOptiFine IsNot Nothing AndAlso
|
||||
CompareVersionGE(VanillaName, "1.13") AndAlso CompareVersionGE("1.14.3", VanillaName) Then
|
||||
McUtils.CompareVersionGE(VanillaName, "1.13") AndAlso McUtils.CompareVersionGE("1.14.3", VanillaName) Then
|
||||
Return "与 OptiFine 不兼容" '1.13 ~ 1.14.3 OptiFine 检查
|
||||
End If
|
||||
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, Version) Then Continue For
|
||||
@@ -775,10 +784,9 @@ Public Class PageDownloadInstall
|
||||
OptiFine_Loaded()
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub Forge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnForgeClear.MouseLeftButtonUp
|
||||
Private Sub Forge_Clear(sender As Object, e As EventArgs) Handles BtnForgeClear.Click
|
||||
SelectedForge = Nothing
|
||||
CardForge.IsSwapped = True
|
||||
e.Handled = True
|
||||
OptiFine_Loaded()
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
@@ -790,7 +798,7 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取 NeoForge 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadNeoForgeGetError() As String
|
||||
Public Function LoadNeoForgeGetError() As String
|
||||
If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
|
||||
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
||||
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
||||
@@ -832,10 +840,9 @@ Public Class PageDownloadInstall
|
||||
OptiFine_Loaded()
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub NeoForge_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnNeoForgeClear.MouseLeftButtonUp
|
||||
Private Sub NeoForge_Clear(sender As Object, e As EventArgs) Handles BtnNeoForgeClear.Click
|
||||
SelectedNeoForge = Nothing
|
||||
CardNeoForge.IsSwapped = True
|
||||
e.Handled = True
|
||||
OptiFine_Loaded()
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
@@ -847,9 +854,9 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取 Fabric 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadFabricGetError() As String
|
||||
Public Function LoadFabricGetError() As String
|
||||
'检查 OptiFine 1.20.5+:没有 OptiFabric 故全部不兼容
|
||||
If SelectedOptiFine IsNot Nothing AndAlso CompareVersionGE(VanillaName, "1.20.5") Then Return "与 OptiFine 不兼容"
|
||||
If SelectedOptiFine IsNot Nothing AndAlso McUtils.CompareVersionGE(VanillaName, "1.20.5") Then Return "与 OptiFine 不兼容"
|
||||
'检查 Loader
|
||||
If GetLoaderError(LoadFabric) IsNot Nothing Then Return GetLoaderError(LoadFabric)
|
||||
'检查版本
|
||||
@@ -879,9 +886,10 @@ Public Class PageDownloadInstall
|
||||
If Not Versions.Any() Then Return
|
||||
'可视化
|
||||
PanFabric.Children.Clear()
|
||||
PanFabric.Tag = Versions
|
||||
CardFabric.SwapControl = PanFabric
|
||||
CardFabric.SwapType = 12
|
||||
CardFabric.SetContentBuilder(Versions.OfType(Of JObject),
|
||||
Function(Version) FabricDownloadListItem(Version, AddressOf Fabric_Selected))
|
||||
If Not CardFabric.IsSwapped Then CardFabric.BuildContent()
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "可视化 Fabric 安装版本列表出错")
|
||||
End Try
|
||||
@@ -895,14 +903,15 @@ Public Class PageDownloadInstall
|
||||
CardFabric.IsSwapped = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub Fabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricClear.MouseLeftButtonUp
|
||||
Private Sub Fabric_Clear(sender As Object, e As EventArgs) Handles BtnFabricClear.Click
|
||||
SelectedFabric = Nothing
|
||||
SelectedFabricApi = Nothing
|
||||
BtnFabricApiClear.Visibility = Visibility.Collapsed
|
||||
AutoSelectedFabricApi = False
|
||||
SelectedOptiFabric = Nothing
|
||||
BtnOptiFabricClear.Visibility = Visibility.Collapsed
|
||||
AutoSelectedOptiFabric = False
|
||||
CardFabric.IsSwapped = True
|
||||
e.Handled = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
|
||||
@@ -911,14 +920,14 @@ Public Class PageDownloadInstall
|
||||
#Region "Fabric API 列表"
|
||||
|
||||
''' <summary>
|
||||
''' 判断某 Fabric API 是否适配当前选择的原版版本。
|
||||
''' 判断某 Fabric API 是否适配指定的原版版本。
|
||||
''' </summary>
|
||||
Public Function IsFabricApiCompatible(FabricApi As ResourceVersion) As Boolean
|
||||
Public Shared Function IsFabricApiCompatible(FabricApi As ResourceVersion, MinecraftVersion As String) As Boolean
|
||||
Dim FabricApiName = FabricApi.Display
|
||||
Try
|
||||
If FabricApiName Is Nothing OrElse VanillaName Is Nothing Then Return False
|
||||
If FabricApiName Is Nothing OrElse MinecraftVersion Is Nothing Then Return False
|
||||
FabricApiName = FabricApiName.Lower
|
||||
Dim TargetName = VanillaName.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3").Lower
|
||||
Dim TargetName = MinecraftVersion.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3").Lower
|
||||
If FabricApiName.StartsWithF("[" & TargetName & "]") Then Return True
|
||||
If Not FabricApiName.Contains("/") OrElse Not FabricApiName.Contains("]") Then Return False
|
||||
'直接的判断(例如 1.18.1/22w03a)
|
||||
@@ -946,7 +955,7 @@ Public Class PageDownloadInstall
|
||||
End While
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, $"判断 Fabric API 版本适配性出错({FabricApiName}, {VanillaName})")
|
||||
Logger.Warn(ex, $"判断 Fabric API 版本适配性出错({FabricApiName}, {MinecraftVersion})")
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
@@ -954,12 +963,12 @@ Public Class PageDownloadInstall
|
||||
''' <summary>
|
||||
''' 获取 FabricApi 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadFabricApiGetError() As String
|
||||
Public Function LoadFabricApiGetError() As String
|
||||
'检查 Loader
|
||||
If GetLoaderError(LoadFabricApi) IsNot Nothing Then Return GetLoaderError(LoadFabricApi)
|
||||
If DlFabricApiLoader.Output Is Nothing Then Return If(SelectedFabric Is Nothing, "需要安装 Fabric", "获取中……")
|
||||
'检查版本
|
||||
If DlFabricApiLoader.Output.Any(Function(f) IsFabricApiCompatible(f)) Then
|
||||
If DlFabricApiLoader.Output.Any(Function(f) IsFabricApiCompatible(f, VanillaName)) Then
|
||||
Return If(SelectedFabric Is Nothing, "需要安装 Fabric", Nothing)
|
||||
Else
|
||||
Return "无"
|
||||
@@ -971,7 +980,7 @@ Public Class PageDownloadInstall
|
||||
If LoadFabricApiGetError() IsNot Nothing Then e.Handled = True
|
||||
End Sub
|
||||
|
||||
Private AutoSelectedFabricApi As Boolean = False
|
||||
Public AutoSelectedFabricApi As Boolean = False
|
||||
''' <summary>
|
||||
''' 尝试重新可视化 FabricApi 版本列表。
|
||||
''' </summary>
|
||||
@@ -982,7 +991,7 @@ Public Class PageDownloadInstall
|
||||
'获取版本列表
|
||||
Dim Versions As New List(Of ResourceVersion)
|
||||
For Each Version In DlFabricApiLoader.Output
|
||||
If IsFabricApiCompatible(Version) Then
|
||||
If IsFabricApiCompatible(Version, VanillaName) Then
|
||||
If Not Version.Display.StartsWithF("[") Then
|
||||
Logger.Warn($"已特判修改 Fabric API 显示名:{Version.Display}")
|
||||
Version.Display = "[" & VanillaName & "] " & Version.Display
|
||||
@@ -995,7 +1004,6 @@ Public Class PageDownloadInstall
|
||||
'可视化
|
||||
PanFabricApi.Children.Clear()
|
||||
For Each Version In Versions
|
||||
If Not IsFabricApiCompatible(Version) Then Continue For
|
||||
PanFabricApi.Children.Add(FabricApiDownloadListItem(Version, AddressOf FabricApi_Selected))
|
||||
Next
|
||||
'自动选择 Fabric API
|
||||
@@ -1016,10 +1024,9 @@ Public Class PageDownloadInstall
|
||||
CardFabricApi.IsSwapped = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub FabricApi_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnFabricApiClear.MouseLeftButtonUp
|
||||
Private Sub FabricApi_Clear(sender As Object, e As EventArgs) Handles BtnFabricApiClear.Click
|
||||
SelectedFabricApi = Nothing
|
||||
CardFabricApi.IsSwapped = True
|
||||
e.Handled = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
|
||||
@@ -1028,23 +1035,23 @@ Public Class PageDownloadInstall
|
||||
#Region "OptiFabric 列表"
|
||||
|
||||
''' <summary>
|
||||
''' 判断某 OptiFabric 是否适配当前选择的原版版本。
|
||||
''' 判断某 OptiFabric 是否适配指定的原版版本。
|
||||
''' </summary>
|
||||
Private Function IsOptiFabricCompatible(ModFile As ResourceVersion) As Boolean
|
||||
Public Shared Function IsOptiFabricCompatible(ModFile As ResourceVersion, MinecraftVersion As String) As Boolean
|
||||
Try
|
||||
If VanillaName Is Nothing Then Return False
|
||||
Return ModFile.GameVersions.Contains(VanillaName)
|
||||
If MinecraftVersion Is Nothing Then Return False
|
||||
Return ModFile.GameVersions.Contains(MinecraftVersion)
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, $"判断 OptiFabric 版本适配性出错({VanillaName})")
|
||||
Logger.Warn(ex, $"判断 OptiFabric 版本适配性出错({MinecraftVersion})")
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private AutoSelectedOptiFabric As Boolean = False
|
||||
Public AutoSelectedOptiFabric As Boolean = False
|
||||
''' <summary>
|
||||
''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function LoadOptiFabricGetError() As String
|
||||
Public Function LoadOptiFabricGetError() As String
|
||||
If VanillaDrop >= 140 AndAlso VanillaDrop <= 150 Then Return "不兼容老版本 Fabric,请手动下载 OptiFabric Origins"
|
||||
'检查 Loader
|
||||
If GetLoaderError(LoadOptiFabric) IsNot Nothing Then Return GetLoaderError(LoadOptiFabric)
|
||||
@@ -1056,7 +1063,7 @@ Public Class PageDownloadInstall
|
||||
Return "获取中……"
|
||||
End If
|
||||
For Each Version In DlOptiFabricLoader.Output
|
||||
If Not IsOptiFabricCompatible(Version) Then Continue For '2135#
|
||||
If Not IsOptiFabricCompatible(Version, VanillaName) Then Continue For '2135#
|
||||
If SelectedFabric Is Nothing AndAlso SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine 与 Fabric"
|
||||
If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
|
||||
If SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine"
|
||||
@@ -1080,7 +1087,7 @@ Public Class PageDownloadInstall
|
||||
'获取版本列表
|
||||
Dim Versions As New List(Of ResourceVersion)
|
||||
For Each Version In DlOptiFabricLoader.Output
|
||||
If IsOptiFabricCompatible(Version) Then Versions.Add(Version)
|
||||
If IsOptiFabricCompatible(Version, VanillaName) Then Versions.Add(Version)
|
||||
Next
|
||||
If Not Versions.Any() Then Return
|
||||
'排序
|
||||
@@ -1088,7 +1095,6 @@ Public Class PageDownloadInstall
|
||||
'可视化
|
||||
PanOptiFabric.Children.Clear()
|
||||
For Each Version In Versions
|
||||
If Not IsOptiFabricCompatible(Version) Then Continue For
|
||||
PanOptiFabric.Children.Add(OptiFabricDownloadListItem(Version, AddressOf OptiFabric_Selected))
|
||||
Next
|
||||
'自动选择 OptiFabric
|
||||
@@ -1108,10 +1114,9 @@ Public Class PageDownloadInstall
|
||||
CardOptiFabric.IsSwapped = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
Private Sub OptiFabric_Clear(sender As Object, e As MouseButtonEventArgs) Handles BtnOptiFabricClear.MouseLeftButtonUp
|
||||
Private Sub OptiFabric_Clear(sender As Object, e As EventArgs) Handles BtnOptiFabricClear.Click
|
||||
SelectedOptiFabric = Nothing
|
||||
CardOptiFabric.IsSwapped = True
|
||||
e.Handled = True
|
||||
ReloadSelected()
|
||||
End Sub
|
||||
|
||||
@@ -1119,10 +1124,42 @@ Public Class PageDownloadInstall
|
||||
|
||||
#Region "安装"
|
||||
|
||||
''' <summary>
|
||||
''' 获取当前选择的组件信息。
|
||||
''' </summary>
|
||||
Public Function GetSelectedComponents() As McComponents
|
||||
Return New McComponents(
|
||||
minecraftVersion:=VanillaName,
|
||||
optiFineEntry:=If(SelectedOptiFine Is Nothing, Nothing, JObject.FromObject(SelectedOptiFine)),
|
||||
forgeVersion:=SelectedForge?.VersionName,
|
||||
neoForgeVersion:=SelectedNeoForge?.VersionName,
|
||||
fabricVersion:=SelectedFabric,
|
||||
fabricApiVersion:=If(SelectedFabricApi?.Version, If(SelectedFabricApi?.Id, SelectedFabricApi?.Display)),
|
||||
optiFabricVersion:=If(SelectedOptiFabric?.Version, If(SelectedOptiFabric?.Id, SelectedOptiFabric?.Display)),
|
||||
liteLoaderVersion:=SelectedLiteLoader?.JsonToken?("version").ToString())
|
||||
End Function
|
||||
|
||||
Private Sub TextSelectName_KeyDown(sender As Object, e As KeyEventArgs) Handles TextSelectName.KeyDown
|
||||
If e.Key = Key.Enter AndAlso IsInSelectPage AndAlso BtnStart.IsEnabled Then BtnStart_Click()
|
||||
End Sub
|
||||
Private Sub BtnStart_Click() Handles BtnStart.Click
|
||||
'提交安装申请
|
||||
Dim InstanceName As String = TextSelectName.Text
|
||||
Dim Request As New McInstallRequest With {
|
||||
.NewInstanceName = InstanceName,
|
||||
.InstanceFolder = $"{McFolderSelected}versions\{InstanceName}\",
|
||||
.Components = GetSelectedComponents(),
|
||||
.MinecraftJson = VanillaData("url").ToString,
|
||||
.ForgeEntry = SelectedForge,
|
||||
.NeoForgeEntry = SelectedNeoForge,
|
||||
.FabricApi = SelectedFabricApi,
|
||||
.OptiFabric = SelectedOptiFabric,
|
||||
.LiteLoaderEntry = SelectedLiteLoader
|
||||
}
|
||||
StartInstall(Request)
|
||||
End Sub
|
||||
|
||||
Public Overridable Sub StartInstall(Request As McInstallRequest)
|
||||
'确认版本隔离
|
||||
If (SelectedForge IsNot Nothing OrElse SelectedNeoForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) AndAlso
|
||||
(Settings.Get(Of Integer)("LaunchArgumentIndieV2") = 0 OrElse Settings.Get(Of Integer)("LaunchArgumentIndieV2") = 2) Then
|
||||
@@ -1132,22 +1169,7 @@ Public Class PageDownloadInstall
|
||||
Return
|
||||
End If
|
||||
End If
|
||||
'提交安装申请
|
||||
Dim InstanceName As String = TextSelectName.Text
|
||||
Dim Request As New McInstallRequest With {
|
||||
.NewInstanceName = InstanceName,
|
||||
.VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
|
||||
.MinecraftJson = VanillaData("url").ToString,
|
||||
.MinecraftName = VanillaName,
|
||||
.OptiFineEntry = SelectedOptiFine,
|
||||
.ForgeEntry = SelectedForge,
|
||||
.NeoForgeEntry = SelectedNeoForge,
|
||||
.FabricVersion = SelectedFabric,
|
||||
.FabricApi = SelectedFabricApi,
|
||||
.OptiFabric = SelectedOptiFabric,
|
||||
.LiteLoaderEntry = SelectedLiteLoader
|
||||
}
|
||||
If Not McInstall(Request) Then Return
|
||||
If Not McInstallStart(Request) Then Return
|
||||
'返回,这样在再次进入安装页面时这个版本就会显示文件夹已重复
|
||||
ExitSelectPage()
|
||||
End Sub
|
||||
|
||||
@@ -0,0 +1,727 @@
|
||||
''' <summary>
|
||||
''' 版本修改页:完整还原已安装组件后,复用安装页的选择交互。
|
||||
''' </summary>
|
||||
Public Class PageDownloadModify
|
||||
Inherits PageDownloadInstall
|
||||
|
||||
Private InitLoader As LoaderTask(Of McInstance, Object)
|
||||
Private ForgeVersionLoader As LoaderTask(Of String, List(Of DlForgeVersionEntry))
|
||||
Private InitialTarget As McComponents '进入时的组件快照
|
||||
''' <summary>
|
||||
''' 原版的版本号是否可靠(不是通过 json 模糊分析)。
|
||||
''' </summary>
|
||||
Private IsVanillaVersionReliable As Boolean
|
||||
Private OriginalName As String
|
||||
Private CustomLogo As String
|
||||
''' <summary>
|
||||
''' 开始修改 MC 版本时,记录当前选择的组件,以在修改 MC 版本后尝试自动选中相同组件。
|
||||
''' </summary>
|
||||
Private ReadOnly PendingComponents As New Dictionary(Of MyLoading, String)
|
||||
Private IsRestoringComponents As Boolean
|
||||
|
||||
Public Overrides Sub LoaderInit() '父级 Handles Me.Initialized
|
||||
ControlInit()
|
||||
InitLoader = New LoaderTask(Of McInstance, Object)("初始化版本修改", AddressOf LoadInstance)
|
||||
PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, InitLoader, AddressOf LoadInstanceFinished, Function() PageInstanceLeft.Instance)
|
||||
End Sub
|
||||
Public Overrides Sub Init() '父级 Handles Me.Loaded
|
||||
PanBack.ScrollToHome()
|
||||
Static IsLoad As Boolean = False
|
||||
If IsLoad Then PageLoaderRestart()
|
||||
IsLoad = True
|
||||
End Sub
|
||||
Private Sub PageUnloaded() Handles Me.Unloaded
|
||||
InitLoader.Cancel()
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 读取或初始化版本的安装清单。
|
||||
''' </summary>
|
||||
Private Sub LoadInstance(Task As LoaderTask(Of McInstance, Object))
|
||||
|
||||
'旧状态清理
|
||||
RunInUiWait(
|
||||
Sub()
|
||||
AniStop("FrmDownloadInstall SelectPageSwitch")
|
||||
IsSelectNameEdited = False
|
||||
ClearSelected()
|
||||
PendingComponents.Clear()
|
||||
InitialTarget = Nothing
|
||||
IsInSelectPage = False
|
||||
PanAllBack.IsHitTestVisible = False
|
||||
End Sub)
|
||||
Task.Input.Config.DiscardCache()
|
||||
|
||||
'获取 Components
|
||||
Dim Manifest = Configs.McInstallManifest.Get(Task.Input.Config)
|
||||
If Manifest IsNot Nothing AndAlso Manifest.SchemaVersion > Versions.McInstallManifestVersion Then
|
||||
Logger.Warn($"安装清单由更新版本的 PCL 创建(清单版本:{Manifest.SchemaVersion},当前版本:{Versions.McInstallManifestVersion})")
|
||||
Throw New Exception($"更新 PCL 后才能修改它!点击【设置 → 其他 → 检查更新】以更新。")
|
||||
End If
|
||||
If Manifest IsNot Nothing Then
|
||||
Dim LatestManifest = Manifest.RefreshModComponents(Task.Input.PathIndie)
|
||||
If LatestManifest IsNot Manifest Then
|
||||
Manifest = LatestManifest
|
||||
Configs.McInstallManifest.Set(Manifest, Task.Input.Config)
|
||||
Task.Input.Config.Save()
|
||||
End If
|
||||
End If
|
||||
Dim Components As McComponents
|
||||
Dim OptiFineVersion As String = Nothing
|
||||
If Manifest IsNot Nothing Then
|
||||
'有清单:从清单读取
|
||||
Components = Manifest.Components
|
||||
If Components Is Nothing Then Throw New Exception("安装清单缺少组件信息,无法还原已安装组件。")
|
||||
IsVanillaVersionReliable = True
|
||||
Else
|
||||
'无清单:通过版本 JSON 获取
|
||||
Dim VersionInfo = New McInstance(Task.Input.PathVersion).Version
|
||||
If VersionInfo.VanillaName = "Unknown" Then Throw New Exception("无法确定 Minecraft 版本,无法修改")
|
||||
Dim UnknownLoaders = VersionInfo.ModLoaderVersions.
|
||||
Where(Function(Loader) String.IsNullOrWhiteSpace(Loader.Value) OrElse Loader.Value = "未知版本").
|
||||
Select(Function(Loader) Loader.Key.ToString()).ToList()
|
||||
If UnknownLoaders.Any() Then Throw New Exception($"无法确定 {UnknownLoaders.Join("、")} 的版本,无法修改")
|
||||
Components = New McComponents(VersionInfo.VanillaName, VersionInfo.ModLoaderVersions)
|
||||
OptiFineVersion = VersionInfo.OptiFine
|
||||
IsVanillaVersionReliable = VersionInfo.Reliable
|
||||
End If
|
||||
Dim MinecraftVersion = Components.MinecraftVersion
|
||||
If String.IsNullOrWhiteSpace(MinecraftVersion) Then Throw New Exception("无法确定当前 Minecraft 版本,请检查版本文件")
|
||||
'等待子列表加载器完成获取
|
||||
Dim LoaderList As New Dictionary(Of String, LoaderBase) From {
|
||||
{"Minecraft", DlClientListLoader}, {"OptiFine", DlOptiFineListLoader}, {"LiteLoader", DlLiteLoaderListLoader},
|
||||
{"NeoForge", DlNeoForgeListLoader}, {"Fabric", DlFabricListLoader}, {"Fabric API", DlFabricApiLoader}, {"OptiFabric", DlOptiFabricLoader}}
|
||||
Dim ForgeLoader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = Nothing
|
||||
If McVersion.IsStandardFormat(MinecraftVersion) Then
|
||||
ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("DlForgeVersion " & MinecraftVersion, AddressOf DlForgeVersionMain)
|
||||
LoaderList.Add("Forge", ForgeLoader)
|
||||
End If
|
||||
For Each Loader In LoaderList.Values
|
||||
Loader.Start(If(Loader Is ForgeLoader, MinecraftVersion, Nothing), Task.IsForceRestarting)
|
||||
Next
|
||||
Do
|
||||
If Task.IsCanceled Then Return
|
||||
For Each Pair In LoaderList
|
||||
Dim Loader = Pair.Value
|
||||
If Loader.State = LoadState.Failed Then
|
||||
If Loader Is ForgeLoader AndAlso Loader.Error.Message = "无" Then Continue For 'Forge 无版本时不报错
|
||||
Throw New Exception($"获取 {Pair.Key} 版本列表失败,请稍后再试,或使用 VPN 改善网络环境", Loader.Error)
|
||||
ElseIf Loader.State = LoadState.Canceled Then
|
||||
Throw New Exception($"获取 {Pair.Key} 版本列表被中断,请稍后再试,或使用 VPN 改善网络环境")
|
||||
End If
|
||||
Next
|
||||
If LoaderList.Values.All(Function(Loader) Loader.State = LoadState.Finished OrElse Loader.State = LoadState.Failed) Then Exit Do
|
||||
Task.Progress = 0.7 * LoaderList.Values.Average(Function(Loader) Loader.Progress)
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
If Task.IsCanceled Then Return
|
||||
Task.Progress = 0.7
|
||||
'Minecraft
|
||||
MinecraftVersions = CType(DlClientListLoader.Output.Value("versions").DeepClone(), JArray)
|
||||
VanillaData = MinecraftVersions.OfType(Of JObject).FirstOrDefault(
|
||||
Function(v) v("id").ToString.Replace("∞", "infinite") = MinecraftVersion.Replace("∞", "infinite"))
|
||||
If VanillaData Is Nothing Then Throw New Exception($"Minecraft 列表中没有已安装的 {MinecraftVersion}")
|
||||
VanillaData("id") = MinecraftVersion
|
||||
'OptiFine
|
||||
If Manifest IsNot Nothing Then
|
||||
SelectedOptiFine = Components.OptiFineEntry?.ToObject(Of DlOptiFineListEntry)()
|
||||
If SelectedOptiFine IsNot Nothing AndAlso Not DlOptiFineListLoader.Output.Value.Any(Function(v) v.FileName = SelectedOptiFine.FileName) Then
|
||||
'如果 OptiFine 是 pre 版,可能只在 BMCLAPI 下有,官方源删了。如果是这种缺失数据的情况,换用 BMCLAPI 源作为输出
|
||||
If DlOptiFineListBmclapiLoader.State <> LoadState.Finished Then DlOptiFineListBmclapiLoader.WaitForExit()
|
||||
DlOptiFineListLoader.Output = DlOptiFineListBmclapiLoader.Output
|
||||
End If
|
||||
ElseIf OptiFineVersion IsNot Nothing AndAlso OptiFineVersion <> "未知版本" Then
|
||||
SelectedOptiFine = DlOptiFineListLoader.Output.Value.FirstOrDefault(
|
||||
Function(v) v.Inherit = MinecraftVersion AndAlso
|
||||
v.InstanceName.AfterLast("-OptiFine_").Replace("HD_U_", "") = OptiFineVersion.Replace("HD_U_", ""))
|
||||
If SelectedOptiFine Is Nothing Then Throw New Exception($"OptiFine 列表中没有已安装的 {OptiFineVersion}")
|
||||
End If
|
||||
'Forge
|
||||
If Components.ModLoaderVersions.ContainsKey(ModLoaders.Forge) Then
|
||||
SelectedForge = ForgeLoader?.Output?.FirstOrDefault(
|
||||
Function(v) v.Inherit = MinecraftVersion AndAlso v.VersionName = Components.ModLoaderVersions(ModLoaders.Forge) AndAlso
|
||||
v.Category <> "universal" AndAlso v.Category <> "client" AndAlso (SelectedOptiFine Is Nothing OrElse IsOptiFineSuitForForge(SelectedOptiFine, v)))
|
||||
If SelectedForge Is Nothing Then Throw New Exception($"Forge 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.Forge)}")
|
||||
End If
|
||||
'NeoForge
|
||||
If Components.ModLoaderVersions.ContainsKey(ModLoaders.NeoForge) Then
|
||||
SelectedNeoForge = DlNeoForgeListLoader.Output.Value.FirstOrDefault(
|
||||
Function(v) v.Inherit = MinecraftVersion AndAlso v.VersionName = Components.ModLoaderVersions(ModLoaders.NeoForge))
|
||||
If SelectedNeoForge Is Nothing Then Throw New Exception($"NeoForge 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.NeoForge)}")
|
||||
End If
|
||||
'Fabric
|
||||
If Components.ModLoaderVersions.ContainsKey(ModLoaders.Fabric) Then
|
||||
Dim FabricEntry = DlFabricListLoader.Output.Value("loader").OfType(Of JObject).FirstOrDefault(
|
||||
Function(v) v("version").ToString = Components.ModLoaderVersions(ModLoaders.Fabric),
|
||||
Function(v) v("version").ToString.Replace("+build", "") = Components.ModLoaderVersions(ModLoaders.Fabric))
|
||||
If FabricEntry Is Nothing OrElse Not DlFabricListLoader.Output.Value("game").OfType(Of JObject).
|
||||
Any(Function(v) v("version").ToString = MinecraftVersion.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3")) Then
|
||||
Throw New Exception($"Fabric 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.Fabric)}")
|
||||
End If
|
||||
SelectedFabric = FabricEntry("version").ToString
|
||||
End If
|
||||
'LiteLoader
|
||||
If Components.ModLoaderVersions.ContainsKey(ModLoaders.LiteLoader) Then
|
||||
SelectedLiteLoader = DlLiteLoaderListLoader.Output.Value.FirstOrDefault(
|
||||
Function(v) v.Inherit = MinecraftVersion AndAlso v.JsonToken("version").ToString = Components.ModLoaderVersions(ModLoaders.LiteLoader))
|
||||
If SelectedLiteLoader Is Nothing Then Throw New Exception($"LiteLoader 列表中没有已安装的 {Components.ModLoaderVersions(ModLoaders.LiteLoader)}")
|
||||
End If
|
||||
'Fabric API
|
||||
If Components.FabricApiVersion IsNot Nothing Then
|
||||
SelectedFabricApi = DlFabricApiLoader.Output.FirstOrDefault(
|
||||
Function(v) (v.Version = Components.FabricApiVersion OrElse v.Id = Components.FabricApiVersion OrElse
|
||||
v.Display = Components.FabricApiVersion) AndAlso IsFabricApiCompatible(v, MinecraftVersion))
|
||||
If SelectedFabricApi Is Nothing Then Throw New Exception($"Fabric API 列表中没有已安装的 {Components.FabricApiVersion}")
|
||||
End If
|
||||
'OptiFabric
|
||||
If Components.OptiFabricVersion IsNot Nothing Then
|
||||
SelectedOptiFabric = DlOptiFabricLoader.Output.FirstOrDefault(
|
||||
Function(v) (v.Version = Components.OptiFabricVersion OrElse v.Id = Components.OptiFabricVersion OrElse
|
||||
v.Display = Components.OptiFabricVersion) AndAlso IsOptiFabricCompatible(v, MinecraftVersion))
|
||||
If SelectedOptiFabric Is Nothing Then Throw New Exception($"OptiFabric 列表中没有已安装的 {Components.OptiFabricVersion}")
|
||||
End If
|
||||
|
||||
'扫描尚未识别的 Mod 组件
|
||||
Dim ManagedFiles As New List(Of McInstallManifest.ManagedFile)
|
||||
If Manifest IsNot Nothing Then ManagedFiles.AddRange(Manifest.ManagedFiles)
|
||||
|
||||
#Region "从 mods 文件夹中获取以 Mod 形式安装的组件信息"
|
||||
|
||||
'获取 mods 文件夹下的 jar 文件与 SHA1
|
||||
Dim Mods As New Lazy(Of List(Of (File As FileInfo, Sha1 As String)))(
|
||||
Function()
|
||||
Dim ModsFolder = Task.Input.PathIndie & "mods\"
|
||||
Dim Files = DirectoryUtils.EnumerateFiles(ModsFolder, searchPattern:="*.jar").ToList()
|
||||
If SelectedLiteLoader IsNot Nothing Then 'LiteLoader 的 OptiFine 安装目录
|
||||
Files.AddRange(DirectoryUtils.EnumerateFiles(Path.Combine(ModsFolder, MinecraftVersion), searchPattern:="*.jar"))
|
||||
End If
|
||||
Dim Entries As New List(Of (File As FileInfo, Sha1 As String))
|
||||
For Each FilePath In Files
|
||||
If Task.IsCanceled Then Return Entries
|
||||
Dim File = FileUtils.GetInfo(FilePath)
|
||||
Entries.Add((File, New LocalResourceFile(File).ModrinthHash))
|
||||
Task.Progress = 0.7 + 0.28 * Entries.Count / Files.Count
|
||||
Next
|
||||
Return Entries
|
||||
End Function)
|
||||
'Fabric API
|
||||
If SelectedFabric IsNot Nothing AndAlso SelectedFabricApi Is Nothing Then
|
||||
Dim FabricApiList = DlFabricApiLoader.Output.Where(Function(v) IsFabricApiCompatible(v, MinecraftVersion)).ToList()
|
||||
Dim Matches As New List(Of (File As FileInfo, Sha1 As String, Version As ResourceVersion))
|
||||
For Each Entry In Mods.Value
|
||||
Dim Match = FabricApiList.FirstOrDefault(Function(v) v.Hash = Entry.Sha1)
|
||||
If Match Is Nothing Then Continue For
|
||||
Matches.Add((Entry.File, Entry.Sha1, Match))
|
||||
Next
|
||||
Dim SelectedFile = SelectMod("Fabric API", Matches)
|
||||
If SelectedFile IsNot Nothing Then
|
||||
SelectedFabricApi = SelectedFile.Value.Version
|
||||
ManagedFiles.Add(New McInstallManifest.ManagedFile("mods/" & SelectedFile.Value.File.Name.Lower(), SelectedFile.Value.Sha1, SelectedFile.Value.File.LastWriteTimeUtc, "FabricApi"))
|
||||
End If
|
||||
End If
|
||||
If Task.IsCanceled Then Return
|
||||
'OptiFabric
|
||||
If SelectedFabric IsNot Nothing AndAlso SelectedOptiFabric Is Nothing Then
|
||||
Dim OptiFabricList = DlOptiFabricLoader.Output.Where(Function(v) IsOptiFabricCompatible(v, MinecraftVersion)).ToList()
|
||||
Dim HasMd5 = OptiFabricList.Any(Function(v) If(v.Hash, "").Length = 32) 'CurseForge 的 OptiFabric 信息可能提供 SHA1 或 MD5
|
||||
Dim Matches As New List(Of (File As FileInfo, Sha1 As String, Version As ResourceVersion))
|
||||
For Each Entry In Mods.Value
|
||||
Dim Match = OptiFabricList.FirstOrDefault(Function(v) v.Hash = Entry.Sha1)
|
||||
If Match Is Nothing AndAlso HasMd5 Then
|
||||
Dim Md5 = CryptographyUtils.ComputeFileHash(Entry.File.FullName, CryptographyUtils.HashMethod.Md5)
|
||||
Match = OptiFabricList.FirstOrDefault(Function(v) v.Hash = Md5)
|
||||
End If
|
||||
If Match Is Nothing Then Continue For
|
||||
Matches.Add((Entry.File, Entry.Sha1, Match))
|
||||
Next
|
||||
Dim SelectedFile = SelectMod("OptiFabric", Matches)
|
||||
If SelectedFile IsNot Nothing Then
|
||||
SelectedOptiFabric = SelectedFile.Value.Version
|
||||
ManagedFiles.Add(New McInstallManifest.ManagedFile("mods/" & SelectedFile.Value.File.Name.Lower(), SelectedFile.Value.Sha1, SelectedFile.Value.File.LastWriteTimeUtc, "OptiFabric"))
|
||||
End If
|
||||
End If
|
||||
If Task.IsCanceled Then Return
|
||||
'OptiFine
|
||||
Dim OptiFineFiles As New List(Of (File As FileInfo, Sha1 As String, OriginalName As String))
|
||||
If SelectedOptiFine Is Nothing AndAlso (SelectedForge IsNot Nothing OrElse SelectedLiteLoader IsNot Nothing OrElse SelectedFabric IsNot Nothing) Then 'OptiFine 只在有 Mod 加载器时才看在不在 mods 文件夹中
|
||||
Static OptiFineHashes As JObject = FileUtils.ReadAsJson("Minecraft\OptiFineHashes.json", type:=GetType(Resource)) 'JSON 内容:{"SHA1": "原始文件名", ...}
|
||||
OptiFineFiles = Mods.Value.
|
||||
Select(Function(Entry) (Entry.File, Entry.Sha1, OriginalName:=OptiFineHashes(Entry.Sha1)?.ToString())). '用本地文件的 SHA1 匹配下载时的原始文件名,再根据原始文件名取得下载源信息
|
||||
Where(Function(Entry) Entry.OriginalName IsNot Nothing).ToList()
|
||||
Dim Matches As New List(Of (File As FileInfo, Sha1 As String, Version As DlOptiFineListEntry))
|
||||
For Each Entry In OptiFineFiles '遍历 hash 匹配到了的本地文件
|
||||
Dim Match = DlOptiFineListLoader.Output.Value.FirstOrDefault(
|
||||
Function(v) v.Inherit = MinecraftVersion AndAlso v.FileName = Entry.OriginalName AndAlso (SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(v, SelectedForge)))
|
||||
If Match Is Nothing Then
|
||||
Hint($"无法从 OptiFine 列表还原 {Entry.File.Name} 对应的 {Entry.OriginalName},将跳过该文件。")
|
||||
Continue For
|
||||
End If
|
||||
Matches.Add((Entry.File, Entry.Sha1, Match))
|
||||
Next
|
||||
Dim SelectedFile = SelectMod("OptiFine", Matches)
|
||||
If SelectedFile IsNot Nothing Then
|
||||
SelectedOptiFine = SelectedFile.Value.Version
|
||||
Dim RelativePath = PathUtils.RemoveExtendedPrefix(SelectedFile.Value.File.FullName).Substring(Task.Input.PathIndie.Length).Replace("\", "/").Lower()
|
||||
ManagedFiles.Add(New McInstallManifest.ManagedFile(RelativePath, SelectedFile.Value.Sha1, SelectedFile.Value.File.LastWriteTimeUtc, "OptiFine"))
|
||||
End If
|
||||
End If
|
||||
If Task.IsCanceled Then Return
|
||||
|
||||
#End Region
|
||||
|
||||
'保存 Manifest
|
||||
If IsVanillaVersionReliable Then
|
||||
Components = New McComponents(MinecraftVersion, Components.ModLoaderVersions,
|
||||
If(SelectedOptiFine Is Nothing, Nothing, JObject.FromObject(SelectedOptiFine)),
|
||||
If(SelectedFabricApi?.Version, If(SelectedFabricApi?.Id, SelectedFabricApi?.Display)),
|
||||
If(SelectedOptiFabric?.Version, If(SelectedOptiFabric?.Id, SelectedOptiFabric?.Display)))
|
||||
If Manifest Is Nothing OrElse Not Components.IsEquivalentTo(Manifest.Components) OrElse Not ManagedFiles.SequenceEqual(Manifest.ManagedFiles) Then
|
||||
Configs.McInstallManifest.Set(New McInstallManifest(Versions.McInstallManifestVersion, Components, Date.UtcNow, ManagedFiles), Task.Input.Config)
|
||||
Task.Input.Config.Save()
|
||||
Logger.Info($"已为 {Task.Input.Name} 更新安装清单")
|
||||
End If
|
||||
End If
|
||||
If Task.IsCanceled Then Return
|
||||
ForgeVersionLoader = ForgeLoader
|
||||
End Sub
|
||||
Private Function SelectMod(Of T)(ComponentName As String, Matches As List(Of (File As FileInfo, Sha1 As String, Version As T))) As (File As FileInfo, Sha1 As String, Version As T)?
|
||||
If Matches.Count = 0 Then Return Nothing
|
||||
If Matches.Count = 1 Then Return Matches(0)
|
||||
Dim Choice As Integer? = Nothing
|
||||
RunInUiWait(Sub() Choice = MyMsgBoxSelect(Matches.Select(Function(Entry) CType(New MyRadioBox With {.Text = Entry.File.Name}, IMyRadio)), $"选择当前使用的 {ComponentName}"))
|
||||
If Not Choice.HasValue Then Throw New Exception($"发现了多个 {ComponentName}")
|
||||
Return Matches(Choice.Value)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 初始化修改页
|
||||
''' </summary>
|
||||
Private Sub LoadInstanceFinished(Task As LoaderTask(Of McInstance, Object))
|
||||
'还原原版信息
|
||||
OriginalName = Task.Input.Name
|
||||
CustomLogo = Nothing
|
||||
If ReadIni(Task.Input.PathVersion & "PCL\Setup.ini", "LogoCustom", False) Then
|
||||
CustomLogo = If(Task.Input.Logo.EndsWithF("PCL\Logo.png"), Task.Input.PathVersion & "PCL\Logo.png", Task.Input.Logo)
|
||||
End If
|
||||
Dim Item = McDownloadListItem(VanillaData, Nothing, False).Init()
|
||||
VanillaName = Item.Title
|
||||
VanillaIcon = Item.Logo
|
||||
LabMinecraftVersion.Text = VanillaName
|
||||
TextSelectName.Text = OriginalName
|
||||
IsSelectNameEdited = Not String.Equals(OriginalName, GetSelectName(), StringComparison.Ordinal)
|
||||
TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {
|
||||
New ValidateFolderName(McFolderSelected & "versions", IgnoreList:=New List(Of String) From {OriginalName})}
|
||||
'修改页 UI
|
||||
CardMinecraft.Visibility = Visibility.Visible
|
||||
BtnBack.Visibility = Visibility.Collapsed
|
||||
ImgLogo.Margin = New Thickness(15, 15, 0, 0)
|
||||
TextSelectName.Margin = New Thickness(56, 16, 16, 0)
|
||||
LabSelectName.Text = $"原名 : {OriginalName}"
|
||||
UpdateOriginalNameVisibility()
|
||||
BtnStart.Text = "开始修改"
|
||||
BtnStart.Logo = FrmInstanceLeft.ItemModify.Logo
|
||||
AutoSelectedFabricApi = SelectedFabric IsNot Nothing
|
||||
AutoSelectedOptiFabric = SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing
|
||||
If ForgeVersionLoader IsNot Nothing Then LoadForge.State = ForgeVersionLoader
|
||||
PrepareSelectPage()
|
||||
ReloadComponentLists()
|
||||
'进入动画
|
||||
PanMinecraft.Visibility = Visibility.Collapsed
|
||||
PanMinecraft.Opacity = 0
|
||||
PanMinecraft.RenderTransform = New TranslateTransform(-50, 0)
|
||||
PanSelect.Opacity = 1
|
||||
PanSelect.RenderTransform = New TranslateTransform
|
||||
PanBack.IsHitTestVisible = True
|
||||
PanAllBack.IsHitTestVisible = True
|
||||
InitialTarget = GetSelectedComponents()
|
||||
'设置原始数据
|
||||
BtnMinecraftRestore.Tag = VanillaData
|
||||
BtnOptiFineRestore.Tag = SelectedOptiFine
|
||||
BtnForgeRestore.Tag = SelectedForge
|
||||
BtnNeoForgeRestore.Tag = SelectedNeoForge
|
||||
BtnFabricRestore.Tag = SelectedFabric
|
||||
BtnFabricApiRestore.Tag = SelectedFabricApi
|
||||
BtnOptiFabricRestore.Tag = SelectedOptiFabric
|
||||
BtnLiteLoaderRestore.Tag = SelectedLiteLoader
|
||||
ImgMinecraftOld.Source = VanillaIcon
|
||||
LabMinecraftOld.Text = LabMinecraftVersion.Text
|
||||
LabOptiFineOld.Text = If(SelectedOptiFine Is Nothing, "无", LabOptiFine.Text)
|
||||
LabForgeOld.Text = If(SelectedForge Is Nothing, "无", LabForge.Text)
|
||||
LabNeoForgeOld.Text = If(SelectedNeoForge Is Nothing, "无", LabNeoForge.Text)
|
||||
LabFabricOld.Text = If(SelectedFabric Is Nothing, "无", LabFabric.Text)
|
||||
LabLiteLoaderOld.Text = If(SelectedLiteLoader Is Nothing, "无", LabLiteLoader.Text)
|
||||
LabFabricApiOld.Text = If(SelectedFabricApi Is Nothing, "无", LabFabricApi.Text)
|
||||
LabOptiFabricOld.Text = If(SelectedOptiFabric Is Nothing, "无", LabOptiFabric.Text)
|
||||
RefreshComparisons()
|
||||
End Sub
|
||||
|
||||
Public Overrides Function GetSelectLogo() As String
|
||||
Return If(CustomLogo, MyBase.GetSelectLogo())
|
||||
End Function
|
||||
|
||||
Public Overrides Sub ShowMinecraftVersionList()
|
||||
If IsInSelectPage Then
|
||||
'把当前已选择的组件记录到 PendingComponents
|
||||
Dim Components = GetSelectedComponents()
|
||||
For Each Component In {
|
||||
(Loader:=LoadOptiFine, Version:=Components.OptiFineVersion),
|
||||
(Loader:=LoadFabricApi, Version:=Components.FabricApiVersion),
|
||||
(Loader:=LoadOptiFabric, Version:=Components.OptiFabricVersion),
|
||||
(Loader:=LoadForge, Version:=SelectedForge?.VersionName),
|
||||
(Loader:=LoadNeoForge, Version:=SelectedNeoForge?.VersionName),
|
||||
(Loader:=LoadFabric, Version:=SelectedFabric),
|
||||
(Loader:=LoadLiteLoader, Version:=SelectedLiteLoader?.JsonToken?("version").ToString())}
|
||||
'保留尚未加载完成的组件选择
|
||||
If Component.Version IsNot Nothing Then PendingComponents(Component.Loader) = Component.Version
|
||||
Next
|
||||
End If
|
||||
MyBase.ShowMinecraftVersionList()
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub ReloadSelected()
|
||||
If IsRestoringComponents Then Return
|
||||
If IsInSelectPage AndAlso VanillaName IsNot Nothing AndAlso PendingComponents.Any() Then
|
||||
IsRestoringComponents = True
|
||||
Try
|
||||
Dim HasProcessed As Boolean = False
|
||||
'优先恢复 Mod 加载器,再匹配兼容的附加组件
|
||||
For Each LoadingComponent In {LoadFabric, LoadForge, LoadNeoForge, LoadLiteLoader, LoadOptiFine, LoadFabricApi, LoadOptiFabric}
|
||||
Dim Version As String = Nothing
|
||||
If Not PendingComponents.TryGetValue(LoadingComponent, Version) Then Continue For
|
||||
If Not LoadingComponent.State.IsLoader Then Continue For
|
||||
Dim Loader = DirectCast(LoadingComponent.State, LoaderBase)
|
||||
'检查前置组件
|
||||
If LoadingComponent Is LoadOptiFine Then
|
||||
If {LoadFabric, LoadForge, LoadNeoForge, LoadLiteLoader}.Any(Function(Component) PendingComponents.ContainsKey(Component)) Then Continue For
|
||||
ElseIf LoadingComponent Is LoadFabricApi Then
|
||||
If PendingComponents.ContainsKey(LoadFabric) Then Continue For
|
||||
ElseIf LoadingComponent Is LoadForge Then
|
||||
If Not McVersion.IsStandardFormat(VanillaName) Then
|
||||
PendingComponents.Remove(LoadingComponent)
|
||||
Continue For
|
||||
End If
|
||||
If DirectCast(Loader, LoaderTask(Of String, List(Of DlForgeVersionEntry))).Input <> VanillaName Then Continue For
|
||||
If Loader.State = LoadState.Failed AndAlso Loader.Error.Message = "无" Then
|
||||
PendingComponents.Remove(LoadingComponent)
|
||||
Continue For
|
||||
End If
|
||||
ElseIf LoadingComponent Is LoadOptiFabric Then
|
||||
If PendingComponents.ContainsKey(LoadFabric) OrElse PendingComponents.ContainsKey(LoadOptiFine) Then Continue For
|
||||
End If
|
||||
If Loader.State <> LoadState.Finished Then Continue For
|
||||
'移除已处理的组件
|
||||
PendingComponents.Remove(LoadingComponent)
|
||||
HasProcessed = True
|
||||
'匹配目标 MC 版本下兼容的组件
|
||||
If LoadingComponent Is LoadFabric Then
|
||||
If SelectedFabric Is Nothing AndAlso LoadFabricGetError() Is Nothing Then
|
||||
Dim Versions = DlFabricListLoader.Output.Value("loader").OfType(Of JObject)
|
||||
SelectedFabric = If(Versions.FirstOrDefault(Function(v) v("version").ToString = Version), Versions.FirstOrDefault())?("version").ToString()
|
||||
End If
|
||||
ElseIf LoadingComponent Is LoadOptiFine Then
|
||||
If SelectedOptiFine Is Nothing AndAlso LoadOptiFineGetError() Is Nothing Then
|
||||
Dim Versions = DlOptiFineListLoader.Output.Value.Where(Function(v) v.Inherit = VanillaName AndAlso
|
||||
(SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(v, SelectedForge)))
|
||||
SelectedOptiFine = If(Versions.FirstOrDefault(Function(v) v.InstanceName.AfterLast("-OptiFine_") = Version),
|
||||
Versions.OrderBy(Function(v) v.IsPreview).
|
||||
ThenByDescending(Function(v) v.DisplayName, Comparer(Of String).Create(AddressOf McUtils.CompareVersion)).FirstOrDefault())
|
||||
End If
|
||||
ElseIf LoadingComponent Is LoadForge Then
|
||||
If SelectedForge Is Nothing AndAlso LoadForgeGetError() Is Nothing Then
|
||||
Dim Versions = DirectCast(Loader, LoaderTask(Of String, List(Of DlForgeVersionEntry))).Output.Where(
|
||||
Function(v) v.Inherit = VanillaName AndAlso
|
||||
v.Category <> "universal" AndAlso v.Category <> "client" AndAlso
|
||||
(SelectedOptiFine Is Nothing OrElse IsOptiFineSuitForForge(SelectedOptiFine, v)))
|
||||
SelectedForge = If(Versions.FirstOrDefault(Function(v) v.VersionName = Version), Versions.OrderByDescending(Function(v) v).FirstOrDefault())
|
||||
End If
|
||||
ElseIf LoadingComponent Is LoadNeoForge Then
|
||||
If SelectedNeoForge Is Nothing AndAlso LoadNeoForgeGetError() Is Nothing Then
|
||||
Dim Versions = DlNeoForgeListLoader.Output.Value.Where(Function(v) v.Inherit = VanillaName)
|
||||
SelectedNeoForge = If(Versions.FirstOrDefault(Function(v) v.VersionName = Version), Versions.FirstOrDefault())
|
||||
End If
|
||||
ElseIf LoadingComponent Is LoadLiteLoader Then
|
||||
If SelectedLiteLoader Is Nothing AndAlso LoadLiteLoaderGetError() Is Nothing Then
|
||||
Dim Versions = DlLiteLoaderListLoader.Output.Value.Where(Function(v) v.Inherit = VanillaName)
|
||||
SelectedLiteLoader = If(Versions.FirstOrDefault(Function(v) v.JsonToken("version").ToString = Version), Versions.FirstOrDefault())
|
||||
End If
|
||||
ElseIf LoadingComponent Is LoadFabricApi Then
|
||||
If SelectedFabricApi Is Nothing AndAlso LoadFabricApiGetError() Is Nothing Then
|
||||
Dim Versions = DlFabricApiLoader.Output.Where(Function(v) IsFabricApiCompatible(v, VanillaName))
|
||||
SelectedFabricApi = If(Versions.FirstOrDefault(Function(v) v.Version = Version OrElse v.Id = Version OrElse v.Display = Version),
|
||||
Versions.OrderByDescending(Function(v) v.ReleaseDate).FirstOrDefault())
|
||||
End If
|
||||
If SelectedFabricApi IsNot Nothing Then AutoSelectedFabricApi = True
|
||||
ElseIf LoadingComponent Is LoadOptiFabric Then
|
||||
If SelectedOptiFabric Is Nothing AndAlso LoadOptiFabricGetError() Is Nothing Then
|
||||
Dim Versions = DlOptiFabricLoader.Output.Where(Function(v) IsOptiFabricCompatible(v, VanillaName))
|
||||
SelectedOptiFabric = If(Versions.FirstOrDefault(Function(v) v.Version = Version OrElse v.Id = Version OrElse v.Display = Version),
|
||||
Versions.OrderByDescending(Function(v) v.ReleaseDate).FirstOrDefault())
|
||||
End If
|
||||
If SelectedOptiFabric IsNot Nothing Then AutoSelectedOptiFabric = True
|
||||
End If
|
||||
Next
|
||||
'更新组件列表
|
||||
If HasProcessed Then ReloadComponentLists()
|
||||
Finally
|
||||
IsRestoringComponents = False
|
||||
End Try
|
||||
End If
|
||||
'刷新当前选择与原始版本的对比
|
||||
MyBase.ReloadSelected()
|
||||
If InitialTarget IsNot Nothing Then RefreshComparisons()
|
||||
End Sub
|
||||
|
||||
Private Sub RefreshComparisons()
|
||||
Dim Current = GetSelectedComponents()
|
||||
ImgMinecraftNew.Source = VanillaIcon
|
||||
'Minecraft
|
||||
Dim IsMinecraftUnchanged = InitialTarget.MinecraftVersion = Current.MinecraftVersion
|
||||
ShowComparison(PanMinecraftCompare, PanMinecraftInfo, InitialTarget.MinecraftVersion, Current.MinecraftVersion,
|
||||
LabMinecraftVersion.Text, BtnMinecraftRestore, True)
|
||||
'OptiFine
|
||||
Dim OriginalOptiFine = TryCast(BtnOptiFineRestore.Tag, DlOptiFineListEntry)
|
||||
ShowComparison(PanOptiFineCompare, PanOptiFineInfo, InitialTarget.OptiFineVersion, Current.OptiFineVersion,
|
||||
LabOptiFine.Text, BtnOptiFineRestore, InitialTarget.OptiFineEntry Is Nothing OrElse
|
||||
IsMinecraftUnchanged AndAlso CardOptiFine.MainSwap.Visibility = Visibility.Visible AndAlso OriginalOptiFine IsNot Nothing AndAlso
|
||||
(SelectedForge Is Nothing OrElse IsOptiFineSuitForForge(OriginalOptiFine, SelectedForge)), BtnOptiFineClear)
|
||||
'Fabric API
|
||||
ShowComparison(PanFabricApiCompare, PanFabricApiInfo, InitialTarget.FabricApiVersion, Current.FabricApiVersion,
|
||||
LabFabricApi.Text, BtnFabricApiRestore, InitialTarget.FabricApiVersion Is Nothing OrElse
|
||||
IsMinecraftUnchanged AndAlso SelectedFabric IsNot Nothing AndAlso CardFabricApi.MainSwap.Visibility = Visibility.Visible, BtnFabricApiClear)
|
||||
'OptiFabric
|
||||
ShowComparison(PanOptiFabricCompare, PanOptiFabricInfo, InitialTarget.OptiFabricVersion, Current.OptiFabricVersion,
|
||||
LabOptiFabric.Text, BtnOptiFabricRestore, InitialTarget.OptiFabricVersion Is Nothing OrElse
|
||||
IsMinecraftUnchanged AndAlso SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing AndAlso CardOptiFabric.MainSwap.Visibility = Visibility.Visible, BtnOptiFabricClear)
|
||||
'Mod Loader
|
||||
For Each Loader In {
|
||||
(Kind:=ModLoaders.Forge, Card:=CardForge, ComparePanel:=PanForgeCompare, CurrentPanel:=PanForgeInfo, Label:=LabForge, RestoreButton:=BtnForgeRestore, ClearButton:=BtnForgeClear),
|
||||
(Kind:=ModLoaders.NeoForge, Card:=CardNeoForge, ComparePanel:=PanNeoForgeCompare, CurrentPanel:=PanNeoForgeInfo, Label:=LabNeoForge, RestoreButton:=BtnNeoForgeRestore, ClearButton:=BtnNeoForgeClear),
|
||||
(Kind:=ModLoaders.Fabric, Card:=CardFabric, ComparePanel:=PanFabricCompare, CurrentPanel:=PanFabricInfo, Label:=LabFabric, RestoreButton:=BtnFabricRestore, ClearButton:=BtnFabricClear),
|
||||
(Kind:=ModLoaders.LiteLoader, Card:=CardLiteLoader, ComparePanel:=PanLiteLoaderCompare, CurrentPanel:=PanLiteLoaderInfo, Label:=LabLiteLoader, RestoreButton:=BtnLiteLoaderRestore, ClearButton:=BtnLiteLoaderClear)}
|
||||
Dim OldVersion As String = Nothing, NewVersion As String = Nothing
|
||||
InitialTarget.ModLoaderVersions.TryGetValue(Loader.Kind, OldVersion)
|
||||
Current.ModLoaderVersions.TryGetValue(Loader.Kind, NewVersion)
|
||||
Dim CanRestore = OldVersion Is Nothing OrElse IsMinecraftUnchanged AndAlso
|
||||
Loader.Card.MainSwap.Visibility = Visibility.Visible AndAlso Loader.RestoreButton.Tag IsNot Nothing
|
||||
If Loader.Kind = ModLoaders.Forge AndAlso OldVersion IsNot Nothing AndAlso CanRestore Then
|
||||
CanRestore = SelectedOptiFine Is Nothing OrElse IsOptiFineSuitForForge(SelectedOptiFine, DirectCast(Loader.RestoreButton.Tag, DlForgeVersionEntry))
|
||||
End If
|
||||
If Loader.Kind = ModLoaders.Fabric AndAlso OldVersion IsNot Nothing Then
|
||||
Dim TargetVersion = VanillaName.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3")
|
||||
CanRestore = CardFabric.Visibility = Visibility.Visible AndAlso CardFabric.MainSwap.Visibility = Visibility.Visible AndAlso
|
||||
DlFabricListLoader.Output.Value("loader").OfType(Of JObject).Any(Function(v) v("version").ToString = OldVersion) AndAlso
|
||||
DlFabricListLoader.Output.Value("game").OfType(Of JObject).Any(Function(v) v("version").ToString = TargetVersion)
|
||||
End If
|
||||
ShowComparison(Loader.ComparePanel, Loader.CurrentPanel, OldVersion, NewVersion, Loader.Label.Text,
|
||||
Loader.RestoreButton, CanRestore, Loader.ClearButton)
|
||||
Next
|
||||
UpdateStartButton()
|
||||
End Sub
|
||||
|
||||
Private Sub ShowComparison(ComparePanel As Grid, CurrentPanel As FrameworkElement, OldVersion As String, NewVersion As String, NewText As String,
|
||||
RestoreButton As MyIconButton, CanRestore As Boolean, Optional ClearButton As FrameworkElement = Nothing)
|
||||
'获取不可安装的原因
|
||||
Dim UnavailableReason As String = Nothing
|
||||
If NewVersion Is Nothing Then
|
||||
If RestoreButton Is BtnOptiFineRestore Then
|
||||
UnavailableReason = LoadOptiFineGetError()
|
||||
ElseIf RestoreButton Is BtnForgeRestore Then
|
||||
UnavailableReason = If(McVersion.IsStandardFormat(VanillaName), LoadForgeGetError(), "无")
|
||||
ElseIf RestoreButton Is BtnNeoForgeRestore Then
|
||||
UnavailableReason = If(CardNeoForge.Visibility = Visibility.Collapsed, "无", LoadNeoForgeGetError())
|
||||
ElseIf RestoreButton Is BtnFabricRestore Then
|
||||
UnavailableReason = If(CardFabric.Visibility = Visibility.Collapsed, "无", LoadFabricGetError())
|
||||
ElseIf RestoreButton Is BtnLiteLoaderRestore Then
|
||||
UnavailableReason = If(CardLiteLoader.Visibility = Visibility.Collapsed, "无", LoadLiteLoaderGetError())
|
||||
ElseIf RestoreButton Is BtnFabricApiRestore Then
|
||||
UnavailableReason = LoadFabricApiGetError()
|
||||
ElseIf RestoreButton Is BtnOptiFabricRestore Then
|
||||
UnavailableReason = LoadOptiFabricGetError()
|
||||
End If
|
||||
NewText = If(UnavailableReason, "可以添加")
|
||||
End If
|
||||
'修改对比
|
||||
Dim IsPending = NewVersion Is Nothing AndAlso (NewText = "获取中……" OrElse NewText.StartsWithF("获取失败:"))
|
||||
Dim IsChanged = OldVersion <> NewVersion AndAlso Not IsPending
|
||||
CanRestore = IsChanged AndAlso OldVersion IsNot Nothing AndAlso CanRestore
|
||||
ComparePanel.Visibility = If(IsChanged, Visibility.Visible, Visibility.Collapsed)
|
||||
CurrentPanel.Visibility = If(IsChanged, Visibility.Collapsed, Visibility.Visible)
|
||||
'还原与取消安装按钮
|
||||
RestoreButton.Visibility = If(CanRestore, Visibility.Visible, Visibility.Collapsed)
|
||||
If ClearButton IsNot Nothing Then ClearButton.ToolTip = If(OldVersion Is Nothing, "取消安装", "移除")
|
||||
Dim HasClearButton = ClearButton IsNot Nothing AndAlso ClearButton.Visibility = Visibility.Visible
|
||||
RestoreButton.Margin = New Thickness(0, 5, If(CanRestore AndAlso HasClearButton, 60, 32), 0)
|
||||
ComparePanel.Margin = New Thickness(ComparePanel.Margin.Left, ComparePanel.Margin.Top,
|
||||
If(CanRestore AndAlso HasClearButton, 110, 80), ComparePanel.Margin.Bottom)
|
||||
If Not IsChanged Then Return
|
||||
'显示修改前已安装组件的对比卡片
|
||||
If OldVersion IsNot Nothing Then
|
||||
Dim Card = CType(ComparePanel.Parent, MyCard)
|
||||
If Card.Visibility = Visibility.Collapsed Then
|
||||
Card.IsSwapped = True
|
||||
If Card.MainSwap IsNot Nothing Then Card.MainSwap.Visibility = Visibility.Collapsed
|
||||
Card.Visibility = Visibility.Visible
|
||||
End If
|
||||
End If
|
||||
Dim OldSide = CType(ComparePanel.Children(0), DockPanel)
|
||||
Dim NewSide = CType(ComparePanel.Children(2), DockPanel)
|
||||
OldSide.Children(0).Visibility = If(OldVersion Is Nothing, Visibility.Collapsed, Visibility.Visible)
|
||||
CType(OldSide.Children(1), TextBlock).Margin = If(OldVersion Is Nothing, New Thickness(0), New Thickness(7, 0, 0, 0))
|
||||
NewSide.Children(0).Visibility = If(NewVersion Is Nothing, Visibility.Collapsed, Visibility.Visible)
|
||||
Dim NewLabel = CType(NewSide.Children(1), TextBlock)
|
||||
NewLabel.Margin = If(NewVersion Is Nothing, New Thickness(0), New Thickness(7, 0, 0, 0))
|
||||
NewLabel.Text = If(NewVersion Is Nothing, "移除", NewText)
|
||||
If NewVersion Is Nothing AndAlso UnavailableReason IsNot Nothing Then
|
||||
NewLabel.Inlines.Add(New Run($"({If(UnavailableReason = "无", "无可用版本", UnavailableReason)})") With {.Foreground = ColorGray4})
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub RestoreComponent(sender As Object, e As EventArgs) Handles BtnMinecraftRestore.Click, BtnOptiFineRestore.Click, BtnForgeRestore.Click,
|
||||
BtnNeoForgeRestore.Click, BtnFabricRestore.Click, BtnFabricApiRestore.Click, BtnOptiFabricRestore.Click, BtnLiteLoaderRestore.Click
|
||||
Dim Button = DirectCast(sender, MyIconButton)
|
||||
'恢复初始选择
|
||||
If Button Is BtnMinecraftRestore Then
|
||||
IsRestoringComponents = True
|
||||
Try
|
||||
PendingComponents.Clear()
|
||||
MinecraftSelected(McDownloadListItem(DirectCast(Button.Tag, JObject), Nothing, False).Init(), Nothing)
|
||||
If ForgeVersionLoader IsNot Nothing Then LoadForge.State = ForgeVersionLoader
|
||||
'恢复初始的组件
|
||||
SelectedOptiFine = TryCast(BtnOptiFineRestore.Tag, DlOptiFineListEntry)
|
||||
SelectedForge = TryCast(BtnForgeRestore.Tag, DlForgeVersionEntry)
|
||||
SelectedNeoForge = TryCast(BtnNeoForgeRestore.Tag, DlNeoForgeListEntry)
|
||||
SelectedFabric = TryCast(BtnFabricRestore.Tag, String)
|
||||
SelectedLiteLoader = TryCast(BtnLiteLoaderRestore.Tag, DlLiteLoaderListEntry)
|
||||
SelectedFabricApi = TryCast(BtnFabricApiRestore.Tag, ResourceVersion)
|
||||
SelectedOptiFabric = TryCast(BtnOptiFabricRestore.Tag, ResourceVersion)
|
||||
AutoSelectedFabricApi = SelectedFabric IsNot Nothing
|
||||
AutoSelectedOptiFabric = SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing
|
||||
Finally
|
||||
IsRestoringComponents = False
|
||||
End Try
|
||||
ReloadComponentLists()
|
||||
Return
|
||||
ElseIf Button Is BtnOptiFineRestore Then
|
||||
SelectedOptiFine = TryCast(Button.Tag, DlOptiFineListEntry)
|
||||
AutoSelectedOptiFabric = SelectedOptiFine IsNot Nothing AndAlso SelectedFabric IsNot Nothing
|
||||
If SelectedOptiFine Is Nothing Then SelectedOptiFabric = Nothing
|
||||
ElseIf Button Is BtnForgeRestore Then
|
||||
SelectedForge = TryCast(Button.Tag, DlForgeVersionEntry)
|
||||
ElseIf Button Is BtnNeoForgeRestore Then
|
||||
SelectedNeoForge = TryCast(Button.Tag, DlNeoForgeListEntry)
|
||||
ElseIf Button Is BtnFabricRestore Then
|
||||
SelectedFabric = TryCast(Button.Tag, String)
|
||||
AutoSelectedFabricApi = SelectedFabric IsNot Nothing
|
||||
AutoSelectedOptiFabric = SelectedFabric IsNot Nothing AndAlso SelectedOptiFine IsNot Nothing
|
||||
If SelectedFabric Is Nothing Then
|
||||
SelectedFabricApi = Nothing
|
||||
SelectedOptiFabric = Nothing
|
||||
End If
|
||||
ElseIf Button Is BtnFabricApiRestore Then
|
||||
SelectedFabricApi = TryCast(Button.Tag, ResourceVersion)
|
||||
AutoSelectedFabricApi = True
|
||||
ElseIf Button Is BtnOptiFabricRestore Then
|
||||
SelectedOptiFabric = TryCast(Button.Tag, ResourceVersion)
|
||||
AutoSelectedOptiFabric = True
|
||||
ElseIf Button Is BtnLiteLoaderRestore Then
|
||||
SelectedLiteLoader = TryCast(Button.Tag, DlLiteLoaderListEntry)
|
||||
End If
|
||||
DirectCast(Button.Parent, MyCard).IsSwapped = True
|
||||
'刷新组件
|
||||
ReloadComponentLists()
|
||||
End Sub
|
||||
|
||||
Private Sub CardMinecraft_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles CardMinecraft.MouseLeftButtonUp
|
||||
ShowMinecraftVersionList()
|
||||
e.Handled = True
|
||||
End Sub
|
||||
|
||||
Private Sub UpdateStartButton() Handles TextSelectName.TextChanged, TextSelectName.ValidateChanged
|
||||
BtnStart.IsEnabled = TextSelectName.IsValidated AndAlso InitialTarget IsNot Nothing AndAlso
|
||||
Not PendingComponents.Any() AndAlso
|
||||
(Not IsVanillaVersionReliable OrElse Not InitialTarget.IsEquivalentTo(GetSelectedComponents()) OrElse
|
||||
Not String.Equals(TextSelectName.Text, OriginalName, StringComparison.Ordinal))
|
||||
End Sub
|
||||
|
||||
Private Sub UpdateOriginalNameVisibility() Handles TextSelectName.TextChanged
|
||||
Dim IsNameChanged = Not String.Equals(TextSelectName.Text, OriginalName, StringComparison.Ordinal)
|
||||
Dim NewVisibility = If(IsNameChanged, Visibility.Visible, Visibility.Collapsed)
|
||||
If LabSelectName.Visibility = NewVisibility Then Return
|
||||
LabSelectName.Visibility = NewVisibility
|
||||
BtnOriginalNameRestore.Visibility = NewVisibility
|
||||
Dim RightMargin = If(IsNameChanged, 40, 16)
|
||||
If IsInSelectPage AndAlso AniControlEnabled = 0 Then
|
||||
AniStart(AaDouble(Sub(Delta) TextSelectName.Margin = New Thickness(56, 16, TextSelectName.Margin.Right + Delta, 0),
|
||||
RightMargin - TextSelectName.Margin.Right, 150,, New AniEaseOutFluent), "DownloadModify Name Margin")
|
||||
Else
|
||||
AniStop("DownloadModify Name Margin")
|
||||
TextSelectName.Margin = New Thickness(56, 16, RightMargin, 0)
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub BtnOriginalNameRestore_Click(sender As Object, e As EventArgs) Handles BtnOriginalNameRestore.Click
|
||||
TextSelectName.Text = OriginalName
|
||||
IsSelectNameEdited = Not String.Equals(OriginalName, GetSelectName(), StringComparison.Ordinal)
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub StartInstall(Request As McInstallRequest)
|
||||
UpdateStartButton()
|
||||
If Not BtnStart.IsEnabled Then Return
|
||||
Dim TargetInstance = InitLoader.Input
|
||||
Dim Target = Request.Components
|
||||
Dim InstanceName = Request.NewInstanceName
|
||||
Dim IsNameChanged = Not String.Equals(InstanceName, TargetInstance.Name, StringComparison.Ordinal)
|
||||
Request.NewInstanceName = If(IsNameChanged, InstanceName, Nothing)
|
||||
Request.InstanceFolder = TargetInstance.PathVersion
|
||||
'警告
|
||||
Dim Warnings As New List(Of String)
|
||||
If (SelectedForge IsNot Nothing OrElse SelectedNeoForge IsNot Nothing OrElse SelectedFabric IsNot Nothing) AndAlso
|
||||
Not PathUtils.IsSame(TargetInstance.PathIndie, TargetInstance.PathVersion) Then
|
||||
Warnings.Add("该版本尚未开启版本隔离,可能与别的 MC 版本共用同一个 Mod 和存档文件夹。" & vbCrLf &
|
||||
"修改版本后,已有的 Mod、存档等需要手动迁移到新的游戏目录。")
|
||||
End If
|
||||
Dim IsMinecraftVersionChanged = InitialTarget.MinecraftVersion <> Target.MinecraftVersion
|
||||
If Not IsVanillaVersionReliable AndAlso Not IsMinecraftVersionChanged Then
|
||||
Warnings.Add($"PCL 未能精准识别该版本,请确认它是不是 Minecraft {InitialTarget.MinecraftVersion},如果不正确,请取消并选择正确的版本!")
|
||||
End If
|
||||
If Not Configs.HintModifyInstanceWarning.Get() Then
|
||||
Warnings.Add("如果该版本安装了 PCL 不兼容的加载器,或经过第三方修改,这些改动将会丢失!")
|
||||
End If
|
||||
Dim IsModLoaderChanged As Boolean = False
|
||||
For Each Loader In InitialTarget.ModLoaderVersions.Keys.Union(Target.ModLoaderVersions.Keys)
|
||||
Dim CurrentVersion As String = Nothing, TargetVersion As String = Nothing
|
||||
Dim HasCurrent = InitialTarget.ModLoaderVersions.TryGetValue(Loader, CurrentVersion)
|
||||
Dim HasTarget = Target.ModLoaderVersions.TryGetValue(Loader, TargetVersion)
|
||||
If HasCurrent <> HasTarget OrElse CurrentVersion <> TargetVersion Then
|
||||
IsModLoaderChanged = True
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
If (IsModLoaderChanged OrElse IsMinecraftVersionChanged) AndAlso InitialTarget.ModLoaderVersions.Any Then
|
||||
Warnings.Add("现有的 Mod、资源包等在修改后可能会不兼容!")
|
||||
End If
|
||||
If Warnings.Any() Then
|
||||
If MyMsgBox("请注意:" & vbCrLf & "• " & Warnings.Join(vbCrLf & "• "), "修改确认", "开始修改", "取消", IsWarn:=True) <> 1 Then Return
|
||||
End If
|
||||
If Not Configs.HintModifyInstanceWarning.Get() Then Configs.HintModifyInstanceWarning.Set(True)
|
||||
'开始修改
|
||||
If IsVanillaVersionReliable AndAlso InitialTarget.IsEquivalentTo(Target) Then
|
||||
'仅重命名
|
||||
Try
|
||||
Dim OldPath = TargetInstance.PathVersion
|
||||
Dim RenamedInstance = TargetInstance.Rename(InstanceName)
|
||||
If PageInstanceLeft.Instance IsNot Nothing AndAlso PathUtils.IsSame(PageInstanceLeft.Instance.PathVersion, OldPath) Then PageInstanceLeft.Instance = RenamedInstance
|
||||
If McInstanceSelected IsNot Nothing AndAlso PathUtils.IsSame(McInstanceSelected.PathVersion, OldPath) Then McInstanceSelected = RenamedInstance
|
||||
PageInstanceLeft.ReloadCurrentJava()
|
||||
Hint("重命名成功!", HintType.Green)
|
||||
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
FrmMain.PageBack()
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "重命名版本失败", LogBehavior.Alert)
|
||||
End Try
|
||||
Else
|
||||
'实际修改
|
||||
If McModificationStart(Request, TargetInstance) Then FrmMain.PageBack()
|
||||
End If
|
||||
End Sub
|
||||
End Class
|
||||
@@ -64,10 +64,10 @@ Public Class PageDownloadResourceDetail
|
||||
If IsXSpecial Then Return 1
|
||||
If IsYSpecial Then Return -1
|
||||
'比较版本号
|
||||
Dim VersionCodeSort = -CompareVersion(x.Replace(x.BeforeFirst(" ") & " ", ""), y.Replace(y.BeforeFirst(" ") & " ", ""))
|
||||
Dim VersionCodeSort = -McUtils.CompareVersion(x.Replace(x.BeforeFirst(" ") & " ", ""), y.Replace(y.BeforeFirst(" ") & " ", ""))
|
||||
If VersionCodeSort <> 0 Then Return VersionCodeSort
|
||||
'比较全部
|
||||
Return -CompareVersion(x, y)
|
||||
Return -McUtils.CompareVersion(x, y)
|
||||
End Function
|
||||
Public Sub New(Optional Topmost As String = "")
|
||||
Me.Topmost = If(Topmost, "")
|
||||
@@ -98,7 +98,7 @@ Public Class PageDownloadResourceDetail
|
||||
Dim UpdateFilters =
|
||||
Sub()
|
||||
Filters = Results.SelectMany(Function(v) v.GameVersions).Select(Function(v) GetGroupedVersionName(v, GroupedDrop, GroupedOld)).
|
||||
Distinct.OrderByDescending(Function(s) s, New VersionComparer).ToList
|
||||
Distinct.OrderByDescending(Function(s) s, Comparer(Of String).Create(Function(x, y) McUtils.CompareVersion(x, y))).ToList
|
||||
End Sub
|
||||
|
||||
'确定分组方式
|
||||
@@ -174,7 +174,7 @@ GroupDone:
|
||||
Dim Loaders As New List(Of String)
|
||||
If Project.ModLoaders.Flags.Count > 1 AndAlso '工程至少有两个加载器
|
||||
Version.ResourceType = ResourceTypes.Mod AndAlso '是 Mod
|
||||
McVersion.IsFormatFit(VerName) Then '不是 “快照版本” 之类的
|
||||
McVersion.IsStandardFormat(VerName) Then '不是 “快照版本” 之类的
|
||||
Loaders.AddRange(Version.ModLoaders.Flags.Select(Function(f) f.ToString & " "))
|
||||
End If
|
||||
If Not Loaders.Any() Then Loaders.Add("") '保底加一个空的,确保它在一张卡片里
|
||||
@@ -206,16 +206,17 @@ GroupDone:
|
||||
If Not Pair.Value.Any() Then Continue For
|
||||
If Pair.Key = TargetCardName.Replace("(所选版本)", "") Then Continue For
|
||||
'增加卡片
|
||||
Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15), .SwapType = If(TargetResourceType = ResourceTypes.ModPack, 9, 8)} '9 是安装,8 是另存为
|
||||
Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15)}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
|
||||
NewCard.Children.Add(NewStack)
|
||||
NewCard.SwapControl = NewStack
|
||||
NewCard.SetContentBuilder(AddressOf InitializeStackResourceVersions)
|
||||
PanResults.Children.Add(NewCard)
|
||||
'确定卡片是否默认展开
|
||||
If Pair.Key = TargetCardName OrElse
|
||||
(FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
|
||||
CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
|
||||
MyCard.StackInstall(NewStack, If(TargetResourceType = ResourceTypes.ModPack, 9, 8), Pair.Key) '9 是安装,8 是另存为
|
||||
NewCard.BuildContent()
|
||||
Else
|
||||
NewCard.IsSwapped = True
|
||||
End If
|
||||
@@ -240,13 +241,53 @@ GroupDone:
|
||||
Logger.Error(ex, "可视化工程下载列表出错")
|
||||
End Try
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 根据卡片中的 StackPanel.Tag 将资源版本列表数据实例化为 UI。
|
||||
''' </summary>
|
||||
Private Sub InitializeStackResourceVersions(Stack As StackPanel)
|
||||
Dim Versions = CType(Stack.Tag, List(Of ResourceVersion)).SortByComparison(Function(a, b) a.ReleaseDate > b.ReleaseDate)
|
||||
Dim HasDuplicates = Versions.DistinctBy(Function(a) a.Display).Count <> Versions.Count
|
||||
Dim Dependences As List(Of String)
|
||||
'获取并添加前置信息
|
||||
If TargetResourceType = ResourceTypes.ModPack Then
|
||||
Dependences = New List(Of String) '整合包的前置信息会显示其中包含的一大堆 Mod,不是真正意义的前置
|
||||
Else
|
||||
Dependences = Versions.SelectMany(Function(f) f.Dependencies).Distinct.Ordered.ToList()
|
||||
End If
|
||||
If Dependences.Any() Then
|
||||
Dependences = Dependences.Where(
|
||||
Function(d)
|
||||
If Not ResourceProject.Cache.ContainsKey(d) Then Logger.Warn($"未找到 ID {d} 的前置信息")
|
||||
Return ResourceProject.Cache.ContainsKey(d)
|
||||
End Function).ToList
|
||||
'添加开头间隔
|
||||
Stack.Children.Add(New TextBlock With {.Text = "前置资源", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 2, 0, 5)})
|
||||
'添加前置列表
|
||||
For Each Dep In Dependences
|
||||
Dim Item = ResourceProject.Cache(Dep).ToResourceItem(False, False)
|
||||
Stack.Children.Add(Item)
|
||||
Next
|
||||
'添加结尾间隔
|
||||
Stack.Children.Add(New TextBlock With {.Text = "版本列表", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 12, 0, 5)})
|
||||
End If
|
||||
'实例化每个元素
|
||||
For Each Version In Versions
|
||||
If TargetResourceType = ResourceTypes.ModPack Then
|
||||
Stack.Children.Add(Version.ToListItem(AddressOf Install_Click, AddressOf Save_Click, IsBadDisplay:=HasDuplicates))
|
||||
Else
|
||||
Stack.Children.Add(Version.ToListItem(AddressOf Save_Click, IsBadDisplay:=HasDuplicates))
|
||||
End If
|
||||
Next
|
||||
Stack.Children.Add(New FrameworkElement With {.Height = 18})
|
||||
Stack.Tag = Nothing
|
||||
End Sub
|
||||
Private Function GetGroupedVersionName(Name As String, GroupedByDrop As Boolean, FoldOld As Boolean) As String
|
||||
Dim Drop = McVersion.VersionToDrop(Name)
|
||||
If Name Is Nothing Then
|
||||
Return "其他"
|
||||
ElseIf Name.Contains("w") OrElse Drop = 209 Then
|
||||
Return "快照版"
|
||||
ElseIf Not McVersion.IsFormatFit(Name) OrElse (FoldOld AndAlso Drop < 120) Then
|
||||
ElseIf Not McVersion.IsStandardFormat(Name) OrElse (FoldOld AndAlso Drop < 120) Then
|
||||
Return "远古版"
|
||||
ElseIf GroupedByDrop Then
|
||||
Return McVersion.DropToVersion(Drop)
|
||||
@@ -469,19 +510,23 @@ GroupDone:
|
||||
'弹窗要求选择保存位置
|
||||
Dim Target As String
|
||||
Dim Ext As String = If(File.ResourceType = ResourceTypes.Mod,
|
||||
If(File.FileName.EndsWithF(".litemod"), "litemod", "jar"),
|
||||
If(File.FileName.EndsWithF(".mrpack"), "mrpack", "zip"))
|
||||
If(PathUtils.GetExtension(File.FileName) = "litemod", "litemod", "jar"),
|
||||
If(PathUtils.GetExtension(File.FileName) = "mrpack", "mrpack", "zip"))
|
||||
Target = Dialogs.SaveFile("选择保存位置", FileName, DefaultFolder, {(Ext, Desc & "文件")})
|
||||
If Target Is Nothing Then Return
|
||||
'构造步骤加载器
|
||||
Dim LoaderName As String = Desc & "下载:" & PathUtils.GetFileNameWithoutExtension(Target) & " "
|
||||
If Target <> DefaultFolder Then CachedFolder(File.ResourceType) = PathUtils.RemoveLastPart(Target)
|
||||
If Not PathUtils.IsSame(PathUtils.RemoveLastPart(Target), DefaultFolder) Then CachedFolder(File.ResourceType) = PathUtils.RemoveLastPart(Target)
|
||||
Dim Loaders As New List(Of LoaderBase)
|
||||
Loaders.Add(New LoaderDownload("下载文件", {
|
||||
File.ToNetFile(Target, If(TargetResourceType = ResourceTypes.Any, ResourceVersion.DownloadReason.Dependency, ResourceVersion.DownloadReason.Standalone))
|
||||
}) With {.ProgressWeight = 6, .Block = True})
|
||||
'启动
|
||||
Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged = AddressOf LoaderStateChangedHintOnly}
|
||||
Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged =
|
||||
Sub(MyLoader)
|
||||
LoaderStateChangedHintOnly(MyLoader)
|
||||
If MyLoader.State = LoadState.Finished AndAlso File.ResourceType = ResourceTypes.ModPack Then OpenExplorer(Target)
|
||||
End Sub}
|
||||
Loader.Start(1)
|
||||
LoaderTaskbarAdd(Loader)
|
||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||
@@ -510,29 +555,4 @@ GroupDone:
|
||||
PageLoaderRestart(IsForceRestart:=True)
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 预载包含大量 ProjectVersion 的卡片,添加必要的元素和前置列表。
|
||||
''' </summary>
|
||||
Public Shared Sub ResourceFilesCardPreload(Stack As StackPanel, Files As List(Of ResourceVersion))
|
||||
'获取卡片对应的前置 ID
|
||||
'如果为整合包就不会有 Dependencies 信息,所以不用管
|
||||
Dim Deps As List(Of String) = Files.SelectMany(Function(f) f.Dependencies).Distinct.ToList()
|
||||
Deps.Sort()
|
||||
If Not Deps.Any() Then Return
|
||||
Deps = Deps.Where(
|
||||
Function(dep)
|
||||
If Not ResourceProject.Cache.ContainsKey(dep) Then Logger.Warn($"未找到 ID {dep} 的前置信息")
|
||||
Return ResourceProject.Cache.ContainsKey(dep)
|
||||
End Function).ToList
|
||||
'添加开头间隔
|
||||
Stack.Children.Add(New TextBlock With {.Text = "前置资源", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 2, 0, 5)})
|
||||
'添加前置列表
|
||||
For Each Dep In Deps
|
||||
Dim Item = ResourceProject.Cache(Dep).ToResourceItem(False, False)
|
||||
Stack.Children.Add(Item)
|
||||
Next
|
||||
'添加结尾间隔
|
||||
Stack.Children.Add(New TextBlock With {.Text = "版本列表", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 12, 0, 5)})
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
@@ -90,11 +90,11 @@ Public Class PageResource
|
||||
Next
|
||||
Return ComboSearchLoader.Items(0)
|
||||
End Function
|
||||
If TargetInstance.Version.HasForge Then
|
||||
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then
|
||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("Forge")
|
||||
ElseIf TargetInstance.Version.HasFabric Then
|
||||
ElseIf TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then
|
||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("Fabric")
|
||||
ElseIf TargetInstance.Version.HasNeoForge Then
|
||||
ElseIf TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then
|
||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
|
||||
End If
|
||||
TargetInstance = Nothing
|
||||
|
||||
@@ -335,7 +335,7 @@ Public Class MyLocalModItem
|
||||
BtnUpdate.Visibility = Visibility.Collapsed
|
||||
End If
|
||||
'标题与描述
|
||||
Dim DescFileName As String = Entry.File.Name.BeforeLast(".")
|
||||
Dim DescFileName As String = PathUtils.GetFileNameWithoutExtension(Entry.EnabledName)
|
||||
Dim NewDescription As String
|
||||
If Settings.Get(Of Integer)("ToolModLocalNameStyle") = 1 Then
|
||||
'标题显示文件名,详情显示译名
|
||||
|
||||
@@ -65,10 +65,10 @@
|
||||
<local:MyCheckBox Margin="30,0,0,0">
|
||||
<local:MyCheckBox.Tag>
|
||||
<local:ExportOption
|
||||
Title="OptiFine 设置"
|
||||
Rules="optionsof.txt|optionsshaders.txt"
|
||||
DefaultChecked="True"
|
||||
RequireOptiFine="True" />
|
||||
Title="OptiFine 设置"
|
||||
Rules="optionsof.txt|optionsshaders.txt"
|
||||
DefaultChecked="True"
|
||||
RequireOptiFine="True" />
|
||||
</local:MyCheckBox.Tag>
|
||||
</local:MyCheckBox>
|
||||
<local:MyCheckBox x:Name="CheckOptionsMod">
|
||||
|
||||
@@ -22,14 +22,14 @@ Public Class PageInstanceExport
|
||||
End Sub
|
||||
Private Sub PageInstanceExport_Loaded() Handles Me.Loaded
|
||||
AniControlEnabled += 1
|
||||
If CurrentInstance <> PageInstanceLeft.Instance.PathVersion Then RefreshAll() '切换到了另一个版本,重置页面
|
||||
If Not PathUtils.IsSame(CurrentInstance, PageInstanceLeft.Instance.PathVersion) Then RefreshAll() '切换到了另一个版本,重置页面
|
||||
CustomEventService.SetEventData(BtnAdvancedHelp,
|
||||
If(BuildType = BuildTypes.Release, "指南/整合包制作 - Public.json", "指南/整合包制作 - Snapshot.json"))
|
||||
AniControlEnabled -= 1
|
||||
End Sub
|
||||
Public Sub RefreshAll() Implements IRefreshable.Refresh
|
||||
Logger.Info("刷新导出页面")
|
||||
HintOptiFine.Visibility = If(PageInstanceLeft.Instance.Version.HasOptiFine, Visibility.Visible, Visibility.Collapsed)
|
||||
HintOptiFine.Visibility = If(PageInstanceLeft.Instance.Version.HasOptiFine AndAlso Not PageInstanceLeft.Instance.Version.OptiFineAsMod, Visibility.Visible, Visibility.Collapsed)
|
||||
CurrentInstance = PageInstanceLeft.Instance.PathVersion
|
||||
TextExportName.Text = ""
|
||||
TextExportName.HintText = PageInstanceLeft.Instance.Name
|
||||
@@ -114,7 +114,7 @@ Public Class PageInstanceExport
|
||||
'确认选项是否应该被显示
|
||||
Dim IsVisible =
|
||||
Function(TargetOption As ExportOption) As Boolean
|
||||
'检查需要 OptiFine 或 Mod 加载器
|
||||
'检查需要 OptiFine(例如光影)或 Mod 加载器(例如 mods/)
|
||||
If TargetOption.RequireOptiFine AndAlso Not PageInstanceLeft.Instance.Version.HasOptiFine Then Return False
|
||||
If TargetOption.RequireModLoader AndAlso Not PageInstanceLeft.Instance.Modable Then Return False
|
||||
If TargetOption.RequireModLoaderOrOptiFine AndAlso Not PageInstanceLeft.Instance.Version.HasOptiFine AndAlso Not PageInstanceLeft.Instance.Modable Then Return False
|
||||
@@ -257,9 +257,9 @@ Public Class PageInstanceExport
|
||||
For Each ShaderPackCheckBox In PanOptionsShaderPacks.Children.OfType(Of MyCheckBox)()
|
||||
If Not ShaderPackCheckBox.Checked Then Continue For
|
||||
Dim ShaderPackOption = GetExportOption(ShaderPackCheckBox)
|
||||
Dim SettingFileName = ShaderPackOption.Rules.TrimEnd("/") & ".txt"
|
||||
If Not FileUtils.Exists(Path.Combine(PageInstanceLeft.Instance.PathIndie, SettingFileName)) Then Continue For
|
||||
Rules.Add(StringUtils.LikePatternEscape($"shaderpacks/{SettingFileName}"))
|
||||
Dim SettingsFile = $"shaderpacks/{ShaderPackOption.Title}.txt"
|
||||
If Not FileUtils.Exists(Path.Combine(PageInstanceLeft.Instance.PathIndie, SettingsFile)) Then Continue For
|
||||
Rules.Add(StringUtils.LikePatternEscape(SettingsFile))
|
||||
Next
|
||||
End If
|
||||
|
||||
@@ -457,11 +457,11 @@ Public Class PageInstanceExport
|
||||
'缓存所需参数
|
||||
Dim CacheFolder = RequestTaskTempFolder()
|
||||
Dim OverridesFolder = CacheFolder & "modpack\overrides\"
|
||||
Dim McVersion = PageInstanceLeft.Instance
|
||||
Dim TargetInstance = PageInstanceLeft.Instance
|
||||
Dim IncludeJava As Boolean =
|
||||
(RulesOverrides Is Nothing AndAlso CheckOptionsJava.Visibility = Visibility.Visible AndAlso CheckOptionsJava.Checked) OrElse
|
||||
(RulesOverrides IsNot Nothing AndAlso CheckOptionsJava.Checked AndAlso Settings.Get(Of Integer)("VersionArgumentJavaV2", McVersion) = 2)
|
||||
Dim PathIndie As String = McVersion.PathIndie
|
||||
(RulesOverrides IsNot Nothing AndAlso CheckOptionsJava.Checked AndAlso Settings.Get(Of Integer)("VersionArgumentJavaV2", TargetInstance) = 2)
|
||||
Dim PathIndie As String = TargetInstance.PathIndie
|
||||
Dim CheckHostedAssets As Boolean = Not CheckAdvancedInclude.Checked
|
||||
Dim ModrinthUploadMode As Boolean = CheckAdvancedModrinth.Checked
|
||||
Dim IncludePCL As Boolean = CheckOptionsPcl.Checked
|
||||
@@ -498,7 +498,7 @@ Public Class PageInstanceExport
|
||||
'文件夹:进一步搜索
|
||||
For Each SubFolder In Folder.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
|
||||
'跳过部分又没用文件又多的文件夹,加快搜索
|
||||
If {"assets", "versions", "libraries"}.Contains(SubFolder.Name) AndAlso PathIndie = PathUtils.RemoveExtendedPrefix(Folder.FullName) Then Continue For
|
||||
If {"assets", "versions", "libraries"}.Contains(SubFolder.Name) AndAlso PathUtils.IsSame(PathIndie, Folder.FullName) Then Continue For
|
||||
If {"structureCacheV1", ".fabric", ".git", "avatar-cache", "cosmetic-cache"}.Contains(SubFolder.Name) Then Continue For
|
||||
SearchFolder(SubFolder)
|
||||
Next
|
||||
@@ -536,10 +536,10 @@ Public Class PageInstanceExport
|
||||
Loader.Progress = 0.85
|
||||
'复制 Java
|
||||
If IncludeJava Then
|
||||
Dim JavaToExport = SelectOrDownloadJava(McVersion, False, Loader.CreateCancellationToken, Loader.CreateSyncProgressProvider(0.85, 0.93))
|
||||
Dim JavaToExport = SelectOrDownloadJava(TargetInstance, False, Loader.CreateCancellationToken, Loader.CreateSyncProgressProvider(0.85, 0.93))
|
||||
If JavaToExport Is Nothing Then Throw New FileNotFoundException("版本文件夹中没有找到可导出的 Java。")
|
||||
Dim JavaFolder = PathUtils.RemoveLastPart(JavaToExport.Folder)
|
||||
Dim DestFolder As String = Path.Combine(OverridesFolder, JavaFolder.AfterFirst(McVersion.PathVersion, True))
|
||||
Dim DestFolder As String = Path.Combine(OverridesFolder, JavaFolder.AfterFirst(TargetInstance.PathVersion, True))
|
||||
DirectoryUtils.Copy(JavaFolder, DestFolder)
|
||||
Logger.Info($"已复制版本文件夹中的 Java:{JavaFolder} → {DestFolder}")
|
||||
End If
|
||||
@@ -563,7 +563,7 @@ Public Class PageInstanceExport
|
||||
Next
|
||||
Loader.Progress = 0.97
|
||||
'复制 PCL 版本设置
|
||||
If DirectoryUtils.Exists(McVersion.PathVersion & "PCL\") Then DirectoryUtils.Copy(McVersion.PathVersion & "PCL\", OverridesFolder & "PCL\")
|
||||
If DirectoryUtils.Exists(TargetInstance.PathVersion & "PCL\") Then DirectoryUtils.Copy(TargetInstance.PathVersion & "PCL\", OverridesFolder & "PCL\")
|
||||
WriteIni(OverridesFolder & "PCL\Setup.ini", "IsStar", False)
|
||||
'复制 PCL 本体(正式版)
|
||||
If BuildType = BuildTypes.Release AndAlso IncludePCL Then FileUtils.Copy(PathExe, CacheFolder & "Plain Craft Launcher.exe")
|
||||
@@ -686,16 +686,16 @@ Public Class PageInstanceExport
|
||||
Next
|
||||
Loader.Progress = 0.2
|
||||
'导出最终 JSON 文件
|
||||
Dim Dependencies As New JObject From {{"minecraft", McVersion.Version.VanillaName}}
|
||||
If McVersion.Version.HasForge Then Dependencies.Add("forge", McVersion.Version.Forge)
|
||||
If McVersion.Version.HasFabric Then Dependencies.Add("fabric-loader", McVersion.Version.Fabric)
|
||||
If McVersion.Version.HasNeoForge Then Dependencies.Add("neoforge", McVersion.Version.NeoForge)
|
||||
Dim Dependencies As New JObject From {{"minecraft", TargetInstance.Version.VanillaName}}
|
||||
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then Dependencies.Add("forge", TargetInstance.Version.ModLoaderVersions(ModLoaders.Forge))
|
||||
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then Dependencies.Add("fabric-loader", TargetInstance.Version.ModLoaderVersions(ModLoaders.Fabric))
|
||||
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then Dependencies.Add("neoforge", TargetInstance.Version.ModLoaderVersions(ModLoaders.NeoForge))
|
||||
Dim ResultJson As New JObject From {
|
||||
{"game", "minecraft"},
|
||||
{"formatVersion", 1},
|
||||
{"versionId", PackVersion},
|
||||
{"name", PackName},
|
||||
{"summary", McVersion.Info},
|
||||
{"summary", TargetInstance.Info},
|
||||
{"files", Files},
|
||||
{"dependencies", Dependencies}
|
||||
}
|
||||
|
||||
@@ -13,21 +13,29 @@
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemMod" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="2" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
||||
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" >
|
||||
<local:MyListItem x:Name="ItemModify" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="2" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="修改" LogoScale="0.95"
|
||||
Logo="F1 M652.624 145.904c62.256-62.272 163.2-62.272 225.472 0 62.272 62.256 62.272 163.2 0 225.472L477.808 771.664a28.8 28.8 0 0 1-10.816 6.8L242.4 857.376c-47.04 16.544-92.32-28.736-75.776-75.776l78.896-224.592c1.44-4.08 3.76-7.776 6.816-10.816L652.624 145.904z M828.604 195.396a89.44 89.44 0 0 0-126.488 0L308.48 589.032 241.68 781.12 433.768 714.32 828.604 321.884a89.44 89.44 0 0 0 0-126.488z M606.256 194.816a35 35 0 0 1 49.504 0l173.728 173.728a35 35 0 0 1-49.504 49.504L606.256 244.32a35 35 0 0 1 0-49.504z M261.984 539.104a35 35 0 0 1 49.504 0l173.728 173.728a35 35 0 0 1-49.504 49.504L261.984 588.608a35 35 0 0 1 0-49.504z" >
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="2" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemModDisabled" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="3" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
||||
<local:MyListItem x:Name="ItemMod" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="3" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
||||
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" >
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="3" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
<local:MyListItem x:Name="ItemModDisabled" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
||||
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" />
|
||||
<local:MyListItem x:Name="ItemExport" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="导出"
|
||||
<local:MyListItem x:Name="ItemExport" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="5" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="导出"
|
||||
Logo="M511 995a128 128 0 0 1-57-13L70 791a126 126 0 0 1-70-113V311a126 126 0 0 1 15-60V248c1-2 3-5 5-8a127 127 0 0 1 49-42L454 13a128 128 0 0 1 112 0l383 190a126 126 0 0 1 72 113v360a126 126 0 0 1-70 115L568 984c-17 7-37 11-57 11z m42-470v370l360-178c14-7 23-21 23-38v-335L554 524zM85 330v347a42 42 0 0 0 23 38l360 178V523L85 330zM135 260l375 189 137-65L286 188 135 260z m245-118l363 197 150-71-365-180a42 42 0 0 0-37 0l-111 53z">
|
||||
<local:MyListItem.Buttons>
|
||||
<x:Array Type="{x:Type local:MyIconButton}">
|
||||
<local:MyIconButton Tag="4" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||
<local:MyIconButton Tag="5" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||
</x:Array>
|
||||
</local:MyListItem.Buttons>
|
||||
</local:MyListItem>
|
||||
|
||||
@@ -6,6 +6,10 @@ Public Class PageInstanceLeft
|
||||
''' </summary>
|
||||
Public Shared Instance As McInstance = Nothing
|
||||
|
||||
Private Sub PageInstanceLeft_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||
PageSetupUI.HiddenRefresh()
|
||||
End Sub
|
||||
|
||||
Public Sub RefreshModDisabled() Handles Me.Loaded
|
||||
If Instance IsNot Nothing AndAlso Instance.Modable Then
|
||||
ItemMod.Visibility = Visibility.Visible
|
||||
@@ -26,7 +30,7 @@ Public Class PageInstanceLeft
|
||||
''' <summary>
|
||||
''' 勾选事件改变页面。
|
||||
''' </summary>
|
||||
Private Sub PageCheck(sender As FrameworkElement, e As RouteEventArgs) Handles ItemOverall.Check, ItemMod.Check, ItemModDisabled.Check, ItemSetup.Check, ItemExport.Check
|
||||
Private Sub PageCheck(sender As FrameworkElement, e As RouteEventArgs) Handles ItemOverall.Check, ItemMod.Check, ItemModDisabled.Check, ItemSetup.Check, ItemModify.Check, ItemExport.Check
|
||||
'尚未初始化控件属性时,sender.Tag 为 Nothing,会导致切换到页面 0
|
||||
'若使用 IsLoaded,则会导致模拟点击不被执行(模拟点击切换页面时,控件的 IsLoaded 为 False)
|
||||
If sender.Tag IsNot Nothing Then PageChange(Val(sender.Tag))
|
||||
@@ -45,11 +49,14 @@ Public Class PageInstanceLeft
|
||||
If FrmInstanceModDisabled Is Nothing Then FrmInstanceModDisabled = New PageInstanceModDisabled
|
||||
Return FrmInstanceModDisabled
|
||||
Case FormMain.PageSubType.InstanceSetup
|
||||
If IsNothing(FrmInstanceSetup) Then FrmInstanceSetup = New PageInstanceSetup
|
||||
If FrmInstanceSetup Is Nothing Then FrmInstanceSetup = New PageInstanceSetup
|
||||
Return FrmInstanceSetup
|
||||
Case FormMain.PageSubType.InstanceExport
|
||||
If FrmInstanceExport Is Nothing Then FrmInstanceExport = New PageInstanceExport
|
||||
Return FrmInstanceExport
|
||||
Case FormMain.PageSubType.InstanceModify
|
||||
If FrmDownloadModify Is Nothing Then FrmDownloadModify = New PageDownloadModify
|
||||
Return FrmDownloadModify
|
||||
Case Else
|
||||
Throw New Exception("未知的版本设置子页面种类:" & ID)
|
||||
End Select
|
||||
@@ -60,6 +67,10 @@ Public Class PageInstanceLeft
|
||||
''' </summary>
|
||||
Public Sub PageChange(ID As FormMain.PageSubType)
|
||||
If PageID = ID Then Return
|
||||
If Instance IsNot Nothing AndAlso McInstanceLock.IsLocked(Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再切换页面!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
AniControlEnabled += 1
|
||||
Try
|
||||
PageChangeRun(PageGet(ID))
|
||||
@@ -98,13 +109,20 @@ Public Class PageInstanceLeft
|
||||
Refresh(FrmMain.PageCurrentSub)
|
||||
End Sub
|
||||
Public Sub Refresh(SubType As FormMain.PageSubType)
|
||||
If Instance IsNot Nothing AndAlso McInstanceLock.IsLocked(Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再刷新!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
Select Case SubType
|
||||
Case FormMain.PageSubType.InstanceMod
|
||||
PageInstanceMod.Refresh()
|
||||
ItemMod.Checked = True
|
||||
Case FormMain.PageSubType.InstanceExport
|
||||
If FrmInstanceExport IsNot Nothing Then FrmInstanceExport.RefreshAll()
|
||||
FrmInstanceExport?.RefreshAll()
|
||||
ItemExport.Checked = True
|
||||
Case FormMain.PageSubType.InstanceModify
|
||||
FrmDownloadModify?.PageLoaderRestart()
|
||||
ItemModify.Checked = True
|
||||
End Select
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ Public Class PageInstanceMod
|
||||
''' 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。
|
||||
''' </summary>
|
||||
Public Shared Function InstallMods(FilePathList As IEnumerable(Of String)) As Boolean
|
||||
Dim Extension As String = FilePathList.First.AfterLast(".").Lower
|
||||
Dim Extension As String = PathUtils.GetExtension(FilePathList.First)
|
||||
'检查文件扩展名
|
||||
If Not {"jar", "litemod", "disabled", "old"}.Any(Function(t) t = Extension) Then Return False
|
||||
Logger.Info("文件为 jar/litemod 格式,尝试作为 Mod 安装")
|
||||
@@ -307,15 +307,15 @@ Public Class PageInstanceMod
|
||||
Install:
|
||||
Try
|
||||
For Each ModFile In FilePathList
|
||||
Dim NewFileName = PathUtils.GetLastPart(ModFile).Replace(".disabled", "").Replace(".old", "")
|
||||
Dim NewFileName = (New LocalResourceFile(ModFile)).EnabledName
|
||||
If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
|
||||
NewFileName = Instance.PathIndie & "mods\" & NewFileName
|
||||
If ModFile = NewFileName Then Continue For '防止安装相同文件导致文件被删除
|
||||
If PathUtils.IsSame(ModFile, NewFileName) Then Continue For '防止安装相同文件导致文件被删除
|
||||
FileUtils.Delete(NewFileName, True)
|
||||
FileUtils.Copy(ModFile, NewFileName)
|
||||
Next
|
||||
If FilePathList.IsSingle Then
|
||||
Hint($"已安装 {PathUtils.GetLastPart(FilePathList.First).Replace(".disabled", "").Replace(".old", "")}!", HintType.Green)
|
||||
Hint($"已安装 {(New LocalResourceFile(FilePathList.First)).EnabledName}!", HintType.Green)
|
||||
Else
|
||||
Hint($"已安装 {FilePathList.Count} 个 Mod!", HintType.Green)
|
||||
End If
|
||||
@@ -553,8 +553,8 @@ Install:
|
||||
Dim File As ResourceVersion = Entry.UpdateFile
|
||||
If Not File.DownloadAvailable Then Continue For
|
||||
'确认更新后的文件名
|
||||
Dim CurrentReplaceName = Entry.ProjectVersion.FileName.Replace(".jar", "").Replace(".old", "").Replace(".disabled", "")
|
||||
Dim NewestReplaceName = Entry.UpdateFile.FileName.Replace(".jar", "").Replace(".old", "").Replace(".disabled", "")
|
||||
Dim CurrentReplaceName = PathUtils.GetFileNameWithoutExtension(Entry.ProjectVersion.FileName)
|
||||
Dim NewestReplaceName = PathUtils.GetFileNameWithoutExtension(Entry.UpdateFile.FileName)
|
||||
Dim CurrentSegs = CurrentReplaceName.Split("-"c).ToList()
|
||||
Dim NewestSegs = NewestReplaceName.Split("-"c).ToList()
|
||||
Dim Shortened As Boolean = False
|
||||
|
||||
@@ -104,51 +104,21 @@ Public Class PageInstanceOverall
|
||||
'重命名版本
|
||||
Private Sub BtnDisplayRename_Click(sender As Object, e As EventArgs) Handles BtnDisplayRename.Click
|
||||
Try
|
||||
If McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再重命名!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
'确认输入的新名称
|
||||
Dim OldName As String = PageInstanceLeft.Instance.Name
|
||||
Dim OldPath As String = PageInstanceLeft.Instance.PathVersion
|
||||
'修改此部分的同时修改快速安装的版本名检测*
|
||||
Dim NewName As String = MyMsgBoxInput("重命名版本", "", OldName, New ObjectModel.Collection(Of Validate) From {
|
||||
New ValidateFolderName(McFolderSelected & "versions", IgnoreList:=New List(Of String) From {OldName})
|
||||
})
|
||||
If String.IsNullOrWhiteSpace(NewName) Then Return
|
||||
Dim NewPath As String = McFolderSelected & "versions\" & NewName & "\"
|
||||
'重新读取版本 JSON 信息,避免 JsonObject 中已被合并的项被重新存储
|
||||
Dim JsonObject As JObject
|
||||
Dim OldJsonPath As String = PageInstanceLeft.Instance.GetJsonPath()
|
||||
Try
|
||||
JsonObject = FileUtils.ReadAsJson(OldJsonPath)
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, "在重命名读取 JSON 时失败")
|
||||
JsonObject = PageInstanceLeft.Instance.JsonObject
|
||||
End Try
|
||||
'重命名主文件夹
|
||||
DirectoryUtils.Move(OldPath, NewPath)
|
||||
'清理 ini 缓存
|
||||
PageInstanceLeft.Instance.ResetSettingsCache()
|
||||
'重命名 jar 文件与 natives 文件夹
|
||||
'不能进行遍历重命名,否则在版本名很短的时候容易误伤其他文件(#6443)
|
||||
If DirectoryUtils.Exists($"{NewPath}{OldName}-natives") Then DirectoryUtils.Move($"{NewPath}{OldName}-natives", $"{NewPath}{NewName}-natives")
|
||||
If FileUtils.Exists($"{NewPath}{OldName}.jar") Then FileUtils.Move($"{NewPath}{OldName}.jar", $"{NewPath}{NewName}.jar")
|
||||
'替换版本设置文件中的路径
|
||||
If FileUtils.Exists(NewPath & "PCL\Setup.ini") Then
|
||||
FileUtils.Write(NewPath & "PCL\Setup.ini", FileUtils.ReadAsString(NewPath & "PCL\Setup.ini").Replace(OldPath, NewPath))
|
||||
End If
|
||||
'更改已选中的版本
|
||||
If ReadIni(McFolderSelected & "PCL.ini", "Version") = OldName Then
|
||||
WriteIni(McFolderSelected & "PCL.ini", "Version", NewName)
|
||||
End If
|
||||
'更新版本 Json
|
||||
Try
|
||||
JsonObject("id") = NewName
|
||||
FileUtils.Delete(NewPath & PathUtils.GetLastPart(OldJsonPath))
|
||||
FileUtils.Write(NewPath & NewName & ".json", JsonObject.ToString)
|
||||
Catch ex As Exception
|
||||
Logger.Warn(ex, "重命名版本 json 失败")
|
||||
End Try
|
||||
Dim NewInstance = PageInstanceLeft.Instance.Rename(NewName)
|
||||
'刷新与提示
|
||||
Hint("重命名成功!", HintType.Green)
|
||||
PageInstanceLeft.Instance = New McInstance(NewName).Load()
|
||||
PageInstanceLeft.Instance = NewInstance
|
||||
If Not IsNothing(McInstanceSelected) AndAlso McInstanceSelected.Equals(PageInstanceLeft.Instance) Then WriteIni(McFolderSelected & "PCL.ini", "Version", NewName)
|
||||
Reload()
|
||||
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
@@ -267,6 +237,10 @@ Public Class PageInstanceOverall
|
||||
'补全文件
|
||||
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
||||
Try
|
||||
If McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再补全文件!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
'忽略文件检查提示
|
||||
If ShouldIgnoreFileCheck(PageInstanceLeft.Instance) Then
|
||||
Hint("请先关闭 [版本设置 → 设置 → 高级启动选项 → 关闭文件校验],然后再尝试补全文件!", HintType.Blue)
|
||||
@@ -304,8 +278,12 @@ Public Class PageInstanceOverall
|
||||
'修改此代码时,同时修改 PageSelectRight 中的代码
|
||||
Private Sub BtnManageDelete_Click(sender As Object, e As EventArgs) Handles BtnManageDelete.Click
|
||||
Try
|
||||
If McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再删除!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
|
||||
Dim IsHintIndie As Boolean = PageInstanceLeft.Instance.State <> McInstanceState.Error AndAlso PageInstanceLeft.Instance.PathIndie <> McFolderSelected
|
||||
Dim IsHintIndie As Boolean = PageInstanceLeft.Instance.State <> McInstance.McInstanceState.Error AndAlso PageInstanceLeft.Instance.PathIndie <> McFolderSelected
|
||||
Dim SavesFolder = DirectoryUtils.GetInfo(PageInstanceLeft.Instance.PathIndie & "saves\")
|
||||
Dim SaveEntries = If(IsHintIndie AndAlso SavesFolder.Exists, SavesFolder.EnumerateDirectories.OrderByDescending(Function(Save) Save.LastWriteTime).Select(Function(Save) $"{Save.Name}(上次修改:{StringUtils.FormatTimeSpan(Save.LastWriteTime - Date.Now, False)})").ToList, New List(Of String))
|
||||
Select Case MyMsgBox($"你确定要{If(IsShiftPressed, "永久", "")}删除版本 {PageInstanceLeft.Instance.Name} 吗?" &
|
||||
|
||||
@@ -499,7 +499,7 @@ PreFin:
|
||||
ComboArgumentJavaSelect.Items.Add(JavaItem)
|
||||
Dim Buttons As New List(Of MyIconButton)
|
||||
'从列表中移除按钮
|
||||
Dim IsOfficial As Boolean = JavaEntry.Folder.StartsWithF($"{Paths.AppData}.minecraft\runtime\")
|
||||
Dim IsOfficial As Boolean = PathUtils.IsParentOf($"{Paths.AppData}.minecraft\runtime\", JavaEntry.Folder)
|
||||
Dim DeleteButton As New MyIconButton With {.Logo = Logo.IconButtonStop, .Height = 24, .Width = 24}
|
||||
DeleteButton.IsEnabled = Not IsOfficial
|
||||
DeleteButton.ToolTip = If(DeleteButton.IsEnabled, "从列表中移除", "无法移除官方 Java")
|
||||
|
||||
@@ -65,7 +65,7 @@ Public Class PageLaunchLeft
|
||||
'确认 Minecraft 版本存在
|
||||
Dim Selection As String = ReadIni(McFolderSelected & "PCL.ini", "Version")
|
||||
Dim Instance As McInstance = If(Selection = "", Nothing, New McInstance(Selection))
|
||||
If Instance Is Nothing OrElse Not Instance.PathVersion.StartsWithF(McFolderSelected) OrElse Not Instance.Check() Then
|
||||
If Instance Is Nothing OrElse Not PathUtils.IsParentOf(McFolderSelected, Instance.PathVersion) OrElse Not Instance.Check() Then
|
||||
'无效的版本
|
||||
Logger.Info($"当前选择的 Minecraft 版本无效:{If(Instance Is Nothing, "null", Instance.PathVersion)}", If(IsNothing(Instance), LogBehavior.None, LogBehavior.ToastIfDebug))
|
||||
If Not McInstanceListLoader.State = LoadState.Finished Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
|
||||
@@ -691,12 +691,28 @@ ExitRefresh:
|
||||
End If
|
||||
End Sub
|
||||
'取消按钮
|
||||
Private Sub BtnCancel_Click() Handles BtnCancel.Click
|
||||
McLaunchCancel()
|
||||
Public Sub BtnCancel_Click() Handles BtnCancel.Click
|
||||
If McLaunchLoaderReal IsNot Nothing Then
|
||||
McLaunchLoaderReal.Cancel()
|
||||
McLaunchLog("已取消启动")
|
||||
Try
|
||||
If McLaunchWatcher IsNot Nothing Then
|
||||
McLaunchWatcher.Kill()
|
||||
ElseIf McLaunchProcess IsNot Nothing Then
|
||||
If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "取消启动结束进程失败", LogBehavior.Toast)
|
||||
End Try
|
||||
End If
|
||||
End Sub
|
||||
'版本设置按钮
|
||||
Private Sub BtnMore_Click() Handles BtnMore.Click
|
||||
If McLaunchLoader.State = LoadState.Loading Then Return
|
||||
If McInstanceLock.IsLocked(McInstanceSelected) Then
|
||||
Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
McInstanceSelected.Load()
|
||||
PageInstanceLeft.Instance = McInstanceSelected
|
||||
FrmMain.PageChange(FormMain.PageType.InstanceSetup, 0)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:behaviors="clr-namespace:PCL.Controls.Behaviors"
|
||||
xmlns:local="clr-namespace:PCL" PanScroll="PanBack">
|
||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||
<StackPanel Name="PanMain" Margin="25,25,25,10" Grid.IsSharedSizeScope="True">
|
||||
@@ -11,8 +12,10 @@
|
||||
<StackPanel x:Name="PanCustom">
|
||||
</StackPanel>
|
||||
<local:MyCard Margin="0,0,0,15" Title="启动日志" x:Name="PanLog">
|
||||
<TextBlock x:Name="LabLog" Margin="20,38,20,18" TextTrimming="None" TextWrapping="Wrap" />
|
||||
<local:MyTextBox x:Name="LabLog" Margin="15,34,15,13" Padding="0,4" IsReadOnly="True" IsUndoEnabled="False"
|
||||
AcceptsReturn="True" TextWrapping="Wrap" BorderThickness="0" HasBackground="False"
|
||||
VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" />
|
||||
</local:MyCard>
|
||||
</StackPanel>
|
||||
</local:MyScrollViewer>
|
||||
</local:MyPageRight>
|
||||
</local:MyPageRight>
|
||||
|
||||
@@ -101,19 +101,34 @@ Public Class PageLaunchRight
|
||||
Url = "https://pcl.wyc-w.top/index.xaml"
|
||||
Case 15
|
||||
Logger.Info("主页预设:Minecraft 芝士站")
|
||||
Url = "https://www.xxag.top/mkss"
|
||||
Url = "https://mkss-services.awaeric.xyz"
|
||||
Case 16
|
||||
Logger.Info("主页预设:整合包推荐引擎")
|
||||
Url = "https://qawsedrftgyhujiko.fun/pcl2/Custom.xaml"
|
||||
Case 17
|
||||
Logger.Info("Bangumi 番剧主页")
|
||||
Url = "https://bangumi.p.kaphia.qzz.io"
|
||||
Logger.Info("主页预设:Bangumi 番剧主页")
|
||||
Url = "https://bangumi.p.kaphia.top"
|
||||
Case 18
|
||||
Logger.Info("Bilibili 热门")
|
||||
Url = "https://bilibili.p.kaphia.qzz.io"
|
||||
Logger.Info("主页预设:Bilibili 热门")
|
||||
Url = "https://bilibili.p.kaphia.top"
|
||||
Case 19
|
||||
Logger.Info("Music 云音乐热门")
|
||||
Url = "https://cloudmusic.p.kaphia.qzz.io"
|
||||
Logger.Info("主页预设:Music 云音乐热门")
|
||||
Url = "https://cloudmusic.p.kaphia.top"
|
||||
Case 20
|
||||
Logger.Info("主页预设:模组推荐")
|
||||
Url = "https://g-fish.dpdns.org/download/ModPage.xaml"
|
||||
Case 21
|
||||
Logger.Info("主页预设:每日游戏推荐")
|
||||
Url = "https://pcl.xn--9iq209asnop94b.top/download/GamePage.xaml"
|
||||
Case 22
|
||||
Logger.Info("主页预设:Wallpaper 每日壁纸")
|
||||
Url = "https://wallpaper.p.kaphia.top"
|
||||
Case 23
|
||||
Logger.Info("主页预设:Weather 天气预报")
|
||||
Url = "https://weather-p.kaphia.top/{variable:PCLDailyWeatherPage:choose}.xaml"
|
||||
Case 24
|
||||
Logger.Info("主页预设:新一代狗屁王大杂烩主页")
|
||||
Url = "https://end.g-fish.dpdns.org/Custom.xaml"
|
||||
End Select
|
||||
End Select
|
||||
'联网下载
|
||||
|
||||
@@ -45,7 +45,7 @@ Public Class PageLoginLegacy
|
||||
If LoginData.UserName.Trim = "" Then Return "玩家名不能为空!"
|
||||
If LoginData.UserName.Contains("""") Then Return "玩家名不能包含英文引号!"
|
||||
If McInstanceSelected IsNot Nothing AndAlso
|
||||
McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.Version.Vanilla >= New Version(20, 0, 3) AndAlso
|
||||
McInstanceSelected.Version.Valid AndAlso McInstanceSelected.Version.Vanilla >= New Version(20, 0, 3) AndAlso
|
||||
LoginData.UserName.Trim.Length > 16 Then
|
||||
Return "自 1.20.3 起,玩家名至多只能包含 16 个字符!"
|
||||
End If
|
||||
|
||||
@@ -358,8 +358,9 @@ Public Class PageLinkMain
|
||||
'复制邀请码
|
||||
Private Sub Copy() Handles BtnFinishCopy.Click
|
||||
Dim CodeText As String = $"在 PCL 启动器中输入邀请码【{GetInviteCode()}】,即可加入联机房间!"
|
||||
ClipboardSet(CodeText, SuccessHint:="已复制邀请码!")
|
||||
ClipboardSet(CodeText, False)
|
||||
Settings.Set("LinkLastAutoJoinInviteCode", CodeText)
|
||||
Hint("已复制邀请码!", HintType.Green)
|
||||
End Sub
|
||||
Private Function GetInviteCode() As String
|
||||
Return $"{NetworkName}-{NetworkSecret}-{INVITE_CODE_VERSION.ToString.PadLeft(2, "0"c)}{ _
|
||||
@@ -368,7 +369,8 @@ Public Class PageLinkMain
|
||||
|
||||
'复制 IP
|
||||
Private Sub BtnFinishIp_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnFinishIp.MouseLeftButtonUp
|
||||
ClipboardSet(ClientAddress, SuccessHint:="已复制服务器地址!")
|
||||
ClipboardSet(ClientAddress, False)
|
||||
Hint("已复制服务器地址!", HintType.Green)
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,12 +48,13 @@ Public Class PageOtherHelp
|
||||
If Item.Types.Contains(Type) Then TypeItems.Add(Item)
|
||||
Next
|
||||
'增加卡片
|
||||
Dim NewCard As New MyCard With {.Title = Type, .Margin = New Thickness(0, 0, 0, 15), .SwapType = 11}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = TypeItems}
|
||||
Dim NewCard As New MyCard With {.Title = Type, .Margin = New Thickness(0, 0, 0, 15)}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0)}
|
||||
NewCard.Children.Add(NewStack)
|
||||
NewCard.SwapControl = NewStack
|
||||
NewCard.SetContentBuilder(TypeItems, Function(Entry) Entry.ToListItem)
|
||||
If Type = "指南" Then
|
||||
MyCard.StackInstall(NewStack, 11, "指南")
|
||||
NewCard.BuildContent()
|
||||
Else
|
||||
NewCard.IsSwapped = True
|
||||
End If
|
||||
|
||||
@@ -64,7 +64,7 @@ Public Class PageSelectLeft
|
||||
</ContextMenu>
|
||||
)
|
||||
End Select
|
||||
If (Folder.Type = McFolder.Types.Vanilla OrElse Folder.Type = McFolder.Types.RenamedVanilla) AndAlso Folder.Location = Paths.Base & ".minecraft\" AndAlso McFolderList.IsSingle Then CType(ContMenu.FindName("Delete"), MyMenuItem).Header = "清空"
|
||||
If (Folder.Type = McFolder.Types.Vanilla OrElse Folder.Type = McFolder.Types.RenamedVanilla) AndAlso PathUtils.IsSame(Folder.Location, Paths.Base & ".minecraft\") AndAlso McFolderList.IsSingle Then CType(ContMenu.FindName("Delete"), MyMenuItem).Header = "清空"
|
||||
'注册事件
|
||||
If Not Folder.Type = McFolder.Types.Vanilla Then CType(ContMenu.FindName("Remove"), MyMenuItem).AddHandler(MyMenuItem.ClickEvent, New RoutedEventHandler(AddressOf FrmSelectLeft.Remove_Click))
|
||||
CType(ContMenu.FindName("Open"), MyMenuItem).AddHandler(MyMenuItem.ClickEvent, New RoutedEventHandler(AddressOf FrmSelectLeft.Open_Click))
|
||||
@@ -116,7 +116,7 @@ Public Class PageSelectLeft
|
||||
|
||||
'确认勾选状态
|
||||
For i = 0 To McFolderList.Count - 1
|
||||
If McFolderList(i).Location = McFolderSelected Then
|
||||
If PathUtils.IsSame(McFolderList(i).Location, McFolderSelected) Then
|
||||
CType(FrmSelectLeft.PanList.Children(i + 1), MyListItem).Checked = True '去掉第一个标题
|
||||
Return
|
||||
End If
|
||||
@@ -139,9 +139,9 @@ Public Class PageSelectLeft
|
||||
'添加文件夹
|
||||
Public Sub Add_Click()
|
||||
Dim NewFolder As String = ""
|
||||
'检查是否有下载任务
|
||||
If HasDownloadingTask() Then
|
||||
Hint("在下载任务进行时,无法添加游戏文件夹!", HintType.Red)
|
||||
'下载或版本修改期间禁止更改游戏文件夹
|
||||
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||
Hint("请在其他任务完成后,再添加游戏文件夹!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
Try
|
||||
@@ -150,8 +150,11 @@ Public Class PageSelectLeft
|
||||
If NewFolder Is Nothing Then Return
|
||||
If NewFolder.Contains("!") OrElse NewFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Red) : Return
|
||||
'要求输入显示名称
|
||||
Dim SplitedNames As String() = NewFolder.TrimEnd("\").Split("\")
|
||||
Dim DefaultName As String = If(SplitedNames.Last = ".minecraft", If(SplitedNames.Count >= 3, SplitedNames(SplitedNames.Count - 2), ""), SplitedNames.Last)
|
||||
Dim DefaultName = PathUtils.GetLastPart(NewFolder)
|
||||
If DefaultName = ".minecraft" Then
|
||||
Dim ParentFolder = PathUtils.RemoveLastPart(NewFolder)
|
||||
DefaultName = If(ParentFolder.EndsWithF(":"), "", PathUtils.GetLastPart(ParentFolder))
|
||||
End If
|
||||
If DefaultName.Length > 40 Then DefaultName = DefaultName.Substring(0, 39)
|
||||
Dim NewName As String = MyMsgBoxInput("输入显示名称", "输入该文件夹在左边栏列表中显示的名称。", DefaultName,
|
||||
New ObjectModel.Collection(Of Validate) From {New ValidateNullOrWhiteSpace, New ValidateLength(1, 30), New ValidateExcept({">", "|"})})
|
||||
@@ -169,7 +172,7 @@ Public Class PageSelectLeft
|
||||
RunInThread(
|
||||
Sub()
|
||||
Try
|
||||
If Not FolderPath.EndsWithF("\") Then FolderPath &= "\"
|
||||
FolderPath = PathUtils.AddSlashSuffix(FolderPath)
|
||||
'检查文件夹权限
|
||||
If Not CheckPermission(FolderPath) Then
|
||||
If ShowHint Then
|
||||
@@ -195,7 +198,7 @@ Public Class PageSelectLeft
|
||||
For i = 0 To Folders.Count - 1
|
||||
Dim Folder As String = Folders(i)
|
||||
If Folder = "" Then Continue For
|
||||
If Folder.Split(">")(1) = FolderPath Then
|
||||
If PathUtils.IsSame(Folder.Split(">")(1), FolderPath) Then
|
||||
IsAdded = True
|
||||
If Folder.Split(">")(0) = DisplayName Then
|
||||
If ShowHint Then Hint("此文件夹已在列表中!", HintType.Blue)
|
||||
@@ -246,9 +249,9 @@ Public Class PageSelectLeft
|
||||
|
||||
'创建文件夹
|
||||
Public Sub Create_Click()
|
||||
'检查是否有下载任务
|
||||
If HasDownloadingTask() Then
|
||||
Hint("在下载任务进行时,无法创建游戏文件夹!", HintType.Red)
|
||||
'下载或版本修改期间禁止更改游戏文件夹
|
||||
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||
Hint("请在其他任务完成后,再创建游戏文件夹!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
CreateMcFolderInCurrentPath()
|
||||
@@ -270,6 +273,10 @@ Public Class PageSelectLeft
|
||||
Dim Target As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||
'若为 “移除”,则提醒是否删除 PCL 的配置文件
|
||||
If Target.Type = McFolder.Types.Custom Then
|
||||
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||
Hint("请在其他任务完成后,再移除游戏文件夹!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
Select Case MyMsgBox("是否需要清理 PCL 在该文件夹中的配置文件?" & vbCrLf & "这包括各个版本的独立设置(如自定义图标、第三方登录配置)等,对游戏本身没有影响。", "配置文件清理", "删除", "保留", "取消")
|
||||
Case 1
|
||||
'删除配置文件
|
||||
@@ -292,6 +299,10 @@ Public Class PageSelectLeft
|
||||
End Try
|
||||
End Sub
|
||||
Public Sub Delete_Click(sender As Object, e As RoutedEventArgs)
|
||||
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||
Hint("请在其他任务完成后,再删除游戏文件夹!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
Dim Target As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||
Dim DeleteText As String = If((Target.Type = McFolder.Types.Vanilla OrElse Target.Type = McFolder.Types.RenamedVanilla) AndAlso Target.Location = Paths.Base & ".minecraft\" AndAlso McFolderList.IsSingle, "清空", "删除")
|
||||
If MyMsgBox("你确定要" & DeleteText & "这个文件夹吗?" & vbCrLf &
|
||||
@@ -328,7 +339,7 @@ Public Class PageSelectLeft
|
||||
Dim DeletedName As String = Nothing
|
||||
Dim Folders = Settings.Get(Of String)("LaunchFolders").Split("|"c, True).ToList
|
||||
For Each Folder In Folders.ToList
|
||||
If Not Folder.EndsWithF(Target.Location) Then Continue For
|
||||
If Not Folder.Contains(">") OrElse Not PathUtils.IsSame(Folder.AfterFirst(">"), Target.Location) Then Continue For
|
||||
DeletedName = Folder.BeforeFirst(">")
|
||||
Folders.Remove(Folder)
|
||||
Exit For
|
||||
@@ -349,7 +360,7 @@ Public Class PageSelectLeft
|
||||
End Sub
|
||||
Public Shared Sub RefreshCurrent(Folder As String)
|
||||
WriteIni(Folder & "PCL.ini", "InstanceCache", "") '删除缓存以强制要求下一次加载时更新列表
|
||||
If Folder = McFolderSelected Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
If PathUtils.IsSame(Folder, McFolderSelected) Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
End Sub
|
||||
Public Sub Rename_Click(sender As Object, e As RoutedEventArgs)
|
||||
Dim Folder As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||
@@ -365,7 +376,7 @@ Public Class PageSelectLeft
|
||||
For i = 0 To Folders.Count - 1
|
||||
Dim FolderCurrent As String = Folders(i)
|
||||
If FolderCurrent = "" Then Continue For
|
||||
If FolderCurrent.Split(">")(1) = Folder.Location Then
|
||||
If PathUtils.IsSame(FolderCurrent.Split(">")(1), Folder.Location) Then
|
||||
IsAdded = True
|
||||
If FolderCurrent.Split(">")(0) = NewName Then
|
||||
'名称未修改
|
||||
@@ -390,9 +401,9 @@ Public Class PageSelectLeft
|
||||
'点击选项
|
||||
Public Sub Folder_Change(sender As MyListItem, e As RouteEventArgs)
|
||||
If Not e.RaiseByMouse OrElse Not sender.Checked Then Return
|
||||
'检查是否有下载任务
|
||||
If HasDownloadingTask(True) Then
|
||||
Hint("在下载任务进行时,无法切换游戏文件夹!", HintType.Red)
|
||||
'下载或版本修改期间禁止更改游戏文件夹
|
||||
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask(True) Then
|
||||
Hint("请在其他任务完成后,再切换游戏文件夹!", HintType.Red)
|
||||
e.Handled = True
|
||||
Return
|
||||
End If
|
||||
|
||||
@@ -30,6 +30,8 @@ Public Class PageSelectRight
|
||||
For Each Card As KeyValuePair(Of McInstanceCardType, List(Of McInstance)) In McInstanceList.ToArray
|
||||
'确认是否为隐藏版本显示状态
|
||||
If Card.Key = McInstanceCardType.Hidden Xor ShowHidden Then Continue For
|
||||
Dim Instances = Card.Value.Where(Function(Instance) Not McInstanceLock.IsLocked(Instance)).ToList
|
||||
If Not Instances.Any Then Continue For
|
||||
#Region "确认卡片名称"
|
||||
Dim CardName As String = ""
|
||||
Select Case Card.Key
|
||||
@@ -40,11 +42,11 @@ Public Class PageSelectRight
|
||||
Dim IsNeoForgeExists As Boolean = False
|
||||
Dim IsFabricExists As Boolean = False
|
||||
Dim IsLiteExists As Boolean = False
|
||||
For Each Instance As McInstance In Card.Value
|
||||
If Instance.Version.HasFabric Then IsFabricExists = True
|
||||
If Instance.Version.HasLiteLoader Then IsLiteExists = True
|
||||
If Instance.Version.HasForge Then IsForgeExists = True
|
||||
If Instance.Version.HasNeoForge Then IsNeoForgeExists = True
|
||||
For Each Instance As McInstance In Instances
|
||||
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then IsFabricExists = True
|
||||
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) Then IsLiteExists = True
|
||||
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then IsForgeExists = True
|
||||
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then IsNeoForgeExists = True
|
||||
Next
|
||||
If If(IsLiteExists, 1, 0) + If(IsForgeExists, 1, 0) + If(IsFabricExists, 1, 0) + If(IsNeoForgeExists, 1, 0) > 1 Then
|
||||
CardName = "可安装 Mod"
|
||||
@@ -72,17 +74,18 @@ Public Class PageSelectRight
|
||||
End Select
|
||||
#End Region
|
||||
'建立控件
|
||||
Dim CardTitle As String = CardName & If(CardName = "收藏夹", "", " (" & Card.Value.Count & ")")
|
||||
Dim NewCard As New MyCard With {.Title = CardTitle, .Margin = New Thickness(0, 0, 0, 15), .SwapType = 0}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Card.Value}
|
||||
Dim CardTitle As String = CardName & If(CardName = "收藏夹", "", " (" & Instances.Count & ")")
|
||||
Dim NewCard As New MyCard With {.Title = CardTitle, .Margin = New Thickness(0, 0, 0, 15)}
|
||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0)}
|
||||
NewCard.Children.Add(NewStack)
|
||||
NewCard.SwapControl = NewStack
|
||||
NewCard.SetContentBuilder(Instances, Function(Instance) Instance.ToListItem(AddressOf McInstanceListContent))
|
||||
PanMain.Children.Add(NewCard)
|
||||
'确定卡片是否展开
|
||||
If Card.Key = McInstanceCardType.Rubbish OrElse Card.Key = McInstanceCardType.Error OrElse Card.Key = McInstanceCardType.Fool Then
|
||||
NewCard.IsSwapped = True
|
||||
Else
|
||||
MyCard.StackInstall(NewStack, 0, CardTitle)
|
||||
NewCard.BuildContent()
|
||||
End If
|
||||
Next
|
||||
|
||||
@@ -128,15 +131,16 @@ Public Class PageSelectRight
|
||||
BtnStar.LogoScale = 1.1
|
||||
BtnStar.Logo = Logo.IconButtonLikeLine
|
||||
End If
|
||||
AddHandler BtnStar.Click, Sub()
|
||||
WriteIni(Instance.PathVersion & "PCL\Setup.ini", "IsStar", Not Instance.IsStar)
|
||||
McInstanceListForceRefresh = True
|
||||
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
End Sub
|
||||
AddHandler BtnStar.Click,
|
||||
Sub()
|
||||
WriteIni(Instance.PathVersion & "PCL\Setup.ini", "IsStar", Not Instance.IsStar)
|
||||
McInstanceListForceRefresh = True
|
||||
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||
End Sub
|
||||
Dim BtnDel As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonDelete}
|
||||
BtnDel.ToolTip = "删除"
|
||||
AddHandler BtnDel.Click, Sub() DeleteInstance(sender, Instance)
|
||||
If Instance.State <> McInstanceState.Error Then
|
||||
If Instance.State <> McInstance.McInstanceState.Error Then
|
||||
Dim BtnCont As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonSetup}
|
||||
BtnCont.ToolTip = "设置"
|
||||
AddHandler BtnCont.Click,
|
||||
@@ -166,6 +170,10 @@ Public Class PageSelectRight
|
||||
'点击选项
|
||||
Public Shared Sub Item_Click(sender As MyListItem, e As EventArgs)
|
||||
Dim Instance As McInstance = sender.Tag
|
||||
If McInstanceLock.IsLocked(Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再选择!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
If New McInstance(Instance.PathVersion).Check Then
|
||||
'正常版本
|
||||
McInstanceSelected = Instance
|
||||
@@ -183,8 +191,12 @@ Public Class PageSelectRight
|
||||
'修改此代码时,同时修改 PageInstanceOverall 中的代码
|
||||
Public Shared Sub DeleteInstance(Item As MyListItem, Instance As McInstance)
|
||||
Try
|
||||
If McInstanceLock.IsLocked(Instance) Then
|
||||
Hint("该版本正在被修改,请稍后再删除!", HintType.Red)
|
||||
Return
|
||||
End If
|
||||
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
|
||||
Dim IsHintIndie As Boolean = Instance.State <> McInstanceState.Error AndAlso Instance.PathIndie <> McFolderSelected
|
||||
Dim IsHintIndie As Boolean = Instance.State <> McInstance.McInstanceState.Error AndAlso Instance.PathIndie <> McFolderSelected
|
||||
Dim SavesFolder = DirectoryUtils.GetInfo(Instance.PathIndie & "saves\")
|
||||
Dim SaveEntries = If(IsHintIndie AndAlso SavesFolder.Exists, SavesFolder.EnumerateDirectories.OrderByDescending(Function(Save) Save.LastWriteTime).Select(Function(Save) $"{Save.Name}(上次修改:{StringUtils.FormatTimeSpan(Save.LastWriteTime - Date.Now, False)})").ToList, New List(Of String))
|
||||
Select Case MyMsgBox($"你确定要{If(IsShiftPressed, "永久", "")}删除版本 {Instance.Name} 吗?" &
|
||||
@@ -207,7 +219,7 @@ Public Class PageSelectRight
|
||||
Dim Card As MyCard = Parent.Parent
|
||||
Card.Title = Card.Title.Replace(Parent.Children.Count - 1, Parent.Children.Count - 2) '有一个占位符
|
||||
Parent.Children.Remove(Item)
|
||||
If McInstanceSelected IsNot Nothing AndAlso Instance.PathVersion = McInstanceSelected.PathVersion Then
|
||||
If McInstanceSelected IsNot Nothing AndAlso PathUtils.IsSame(Instance.PathVersion, McInstanceSelected.PathVersion) Then
|
||||
'删除当前版本就更改选择
|
||||
McInstanceSelected = MyVirtualizingElement.TryInit(Parent.Children(0)).Tag
|
||||
End If
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="9" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="9" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="默认版本隔离" Margin="0,0,25,0" />
|
||||
<local:MyComboBox local:SettingService.Key="LaunchArgumentIndieV2" x:Name="ComboArgumentIndieV2"
|
||||
@@ -106,9 +104,6 @@
|
||||
</local:MyTextBox.ValidateRules>
|
||||
</local:MyTextBox>
|
||||
</Grid>
|
||||
<local:MyCheckBox Margin="0,8,0,4" Text="在正版登录时验证 SSL 证书" Grid.Row="12" Height="22" Grid.ColumnSpan="2"
|
||||
x:Name="CheckDownloadCert" local:SettingService.Key="ToolDownloadCert"
|
||||
ToolTip="开启验证可以提高安全性,但可能会导致正版登录失败(见 #3018)。
若登录因为 “未能为 SSL/TLS 安全通道建立信任关系” 失败,请考虑关闭此选项。" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
@@ -291,6 +286,7 @@
|
||||
<local:MyCheckBox Height="28" Text="禁用 Java Launch Wrapper" local:SettingService.Key="LaunchAdvanceDisableJLW" ToolTip="是否使用 Java Launch Wrapper 修复 Java 18- 在中文路径下可能无法正常启动的问题。
详见:https://github.com/00ll00/java_launch_wrapper" />
|
||||
<local:MyCheckBox Height="28" Text="禁用 LWJGL Unsafe Agent" local:SettingService.Key="LaunchAdvanceDisableLUA" ToolTip="是否使用 LWJGL Unsafe Agent 修复 LWJGL 3.4.1 的一个性能问题。
详见:https://github.com/HMCL-dev/lwjgl-unsafe-agent" />
|
||||
<local:MyCheckBox Height="28" Text="使用高性能显卡" local:SettingService.Key="LaunchAdvanceGraphicCard" ToolTip="自动在 Windows 设置 → 系统 → 屏幕 → 显示卡 中将 PCL 和 Java 改为使用高性能显卡。
如果同时有集成显卡和独立显卡,这能确保 MC 使用独立显卡进行渲染,以大幅提高帧率。" />
|
||||
<local:MyCheckBox Height="28" Text="在正版登录时验证 SSL 证书" local:SettingService.Key="ToolDownloadCert" ToolTip="开启验证可以提高安全性,但可能会导致正版登录失败(见 #3018)。
若登录因为 “未能为 SSL/TLS 安全通道建立信任关系” 失败,请考虑关闭此选项。" />
|
||||
</StackPanel>
|
||||
<local:MyHint Text="版本独立设置中还有更多高级选项可供调整。" Margin="0,5,0,10" Theme="Blue" Grid.Row="11" Grid.ColumnSpan="2"
|
||||
CanClose="True" RelativeSetup="HintMoreAdvancedSetup" />
|
||||
|
||||
@@ -396,7 +396,7 @@ PreFin:
|
||||
AddHandler DownButton.Click, Sub() MoveJavaInList(JavaEntry, 1)
|
||||
Buttons.Add(DownButton)
|
||||
'从列表中移除按钮
|
||||
Dim IsOfficial As Boolean = JavaEntry.Folder.StartsWithF($"{Paths.AppData}.minecraft\runtime\")
|
||||
Dim IsOfficial As Boolean = PathUtils.IsParentOf($"{Paths.AppData}.minecraft\runtime\", JavaEntry.Folder)
|
||||
Dim DeleteButton As New MyIconButton With {.Logo = Logo.IconButtonStop, .Height = 24, .Width = 24}
|
||||
DeleteButton.IsEnabled = Not IsOfficial
|
||||
DeleteButton.ToolTip = If(DeleteButton.IsEnabled, "从列表中移除", "无法移除官方 Java")
|
||||
|
||||
@@ -235,18 +235,16 @@
|
||||
<local:MyHint Margin="0,15,0,-4" Text="内容见 ModSetup" Theme="Blue" x:Name="HintCustom" />
|
||||
<local:MyHint Margin="0,15,0,6" Text="请谨慎使用陌生人提供的主页,恶意代码可能会造成损害!" Theme="Yellow" x:Name="HintCustomWarn"
|
||||
CanClose="True" RelativeSetup="HintCustomWarn" />
|
||||
<Grid Height="35" x:Name="PanCustomLocal" Visibility="Collapsed" Margin="0,10,0,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:MyButton x:Name="BtnCustomRefresh" Grid.Column="0" Height="32" MinWidth="140" Text="刷新主页" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight" />
|
||||
<local:MyButton x:Name="BtnCustomFile" Grid.Column="1" Height="32" MinWidth="140" Text="生成教学文件" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnCustomTutorial" Grid.Column="2" Height="32" MinWidth="140" Text="查看教程" Padding="13,0" Margin="0,0,20,0" />
|
||||
<local:MyButton x:Name="BtnCustomOpen" Grid.Column="3" Height="32" MinWidth="140" Text="打开主页文件夹" Padding="13,0" Margin="0,0,20,0" />
|
||||
</Grid>
|
||||
<WrapPanel x:Name="PanCustomLocal" Visibility="Collapsed" Margin="0,0,0,5">
|
||||
<local:MyButton x:Name="BtnCustomRefresh" Text="刷新主页"
|
||||
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||
<local:MyButton x:Name="BtnCustomFile" Text="生成教学文件"
|
||||
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnCustomTutorial" Text="查看教程"
|
||||
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||
<local:MyButton x:Name="BtnCustomFolder" Text="打开主页文件夹"
|
||||
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||
</WrapPanel>
|
||||
<Grid x:Name="PanCustomNet" Visibility="Collapsed" Margin="0,10,0,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||
@@ -288,6 +286,11 @@
|
||||
<local:MyComboBoxItem local:SettingService.Value="17" Content="Bangumi 番剧主页(作者:wzyaeu)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="18" Content="Bilibili 热门(作者:wzyaeu)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="19" Content="Music 云音乐热门(作者:wzyaeu)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="20" Content="模组推荐(作者:llsgllsg)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="21" Content="每日游戏推荐(作者:llsgllsg)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="22" Content="Wallpaper 每日壁纸(作者:wzyaeu)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="23" Content="Weather 天气预报(作者:wzyaeu)" />
|
||||
<local:MyComboBoxItem local:SettingService.Value="24" Content="新一代狗屁王大杂烩主页(作者:llsgllsg)" />
|
||||
</local:MyComboBox>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
@@ -334,6 +337,7 @@
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="3" Text="版本管理" x:Name="CheckHiddenFunctionSelect" local:SettingService.Key="UiHiddenFunctionSelect" ToolTip="隐藏启动按钮下方的版本选择与版本设置入口。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="4" Text="Mod 更新" x:Name="CheckHiddenFunctionModUpdate" local:SettingService.Key="UiHiddenFunctionModUpdate" ToolTip="禁止在 Mod 管理页面更新 Mod。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="5" Text="功能隐藏" x:Name="CheckHiddenFunctionHidden" local:SettingService.Key="UiHiddenFunctionHidden" ToolTip="仅隐藏本选项卡,设置的禁用内容依然有效。
可以在保留个性化设置页面的情况下避免隐藏设置被修改。" />
|
||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="6" Text="版本修改" x:Name="CheckHiddenFunctionModify" local:SettingService.Key="UiHiddenFunctionInstanceModify" ToolTip="隐藏版本设置中的版本修改功能。" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:MyCard>
|
||||
|
||||
@@ -306,19 +306,6 @@ Refresh:
|
||||
"你可以在生成教学文件后直接刷新主页,对照着进行修改,更有助于理解。" & vbCrLf &
|
||||
"直接将主页文件拖进 PCL 窗口也可以快捷加载。", "主页自定义教程")
|
||||
End Sub
|
||||
Private Sub BtnCustomOpen_Click(sender As Object, e As EventArgs) Handles BtnCustomOpen.Click
|
||||
Try
|
||||
Dim CustomPath As String = Paths.Base & "PCL\Custom.xaml"
|
||||
If FileUtils.Exists(CustomPath) Then
|
||||
OpenExplorer(CustomPath)
|
||||
Else
|
||||
OpenExplorer(Paths.Base & "PCL\")
|
||||
Hint("未找到 Custom.xaml,已打开 PCL 文件夹。", HintType.Blue)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex, "打开主页文件失败")
|
||||
End Try
|
||||
End Sub
|
||||
Public Shared Sub OnMainPageTypeChanged()
|
||||
If FrmSetupUI Is Nothing Then Return
|
||||
Select Case CInt(Settings.Get(Of Integer)("UiCustomType"))
|
||||
@@ -354,6 +341,14 @@ Refresh:
|
||||
End Select
|
||||
FrmSetupUI.CardCustom.TriggerForceResize()
|
||||
End Sub
|
||||
Private Sub BtnCustomFolder_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnCustomFolder.Click
|
||||
Dim CustomPath As String = Paths.Base & "PCL\Custom.xaml"
|
||||
If FileUtils.Exists(CustomPath) Then
|
||||
OpenExplorer(CustomPath)
|
||||
Else
|
||||
OpenExplorer(Paths.Base & "PCL\")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
'主题
|
||||
Private Sub LabLauncherTheme5Unlock_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles LabLauncherTheme5Unlock.MouseLeftButtonUp
|
||||
@@ -458,6 +453,10 @@ Refresh:
|
||||
If FrmSetupUI IsNot Nothing Then
|
||||
FrmSetupUI.CardSwitch.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenFunctionHidden"), Visibility.Collapsed, Visibility.Visible)
|
||||
End If
|
||||
'版本设置子页面
|
||||
If FrmInstanceLeft IsNot Nothing Then
|
||||
FrmInstanceLeft.ItemModify.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenFunctionInstanceModify"), Visibility.Collapsed, Visibility.Visible)
|
||||
End If
|
||||
'设置子页面
|
||||
If FrmSetupLeft IsNot Nothing Then
|
||||
FrmSetupLeft.ItemLaunch.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenSetupLaunch"), Visibility.Collapsed, Visibility.Visible)
|
||||
|
||||
@@ -158,6 +158,7 @@ Public Class Settings
|
||||
New Setting("UiHiddenPageOther", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
New Setting("UiHiddenFunctionSelect", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
New Setting("UiHiddenFunctionModUpdate", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
New Setting("UiHiddenFunctionInstanceModify", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
New Setting("UiHiddenFunctionHidden", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
New Setting("UiHiddenSetupLaunch", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
New Setting("UiHiddenSetupUi", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||
|
||||
@@ -93,7 +93,8 @@ Public Class PageSpeedLeft
|
||||
Tb.Text = Loader.Error.GetDisplay(True)
|
||||
AddHandler Tb.MouseLeftButtonDown,
|
||||
Sub(sender As TextBlock, e As EventArgs)
|
||||
ClipboardSet(sender.Text, SuccessHint:="已复制错误详情!")
|
||||
ClipboardSet(sender.Text, False)
|
||||
Hint("已复制错误详情!", HintType.Green)
|
||||
End Sub
|
||||
Card.Children.Add(Tb)
|
||||
#End Region
|
||||
|
||||
Reference in New Issue
Block a user