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
|
||||
|
||||
Reference in New Issue
Block a user