Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
216b91f784 | ||
|
|
6b9a50df91 | ||
|
|
e4b0489a22 | ||
|
|
5ef81e490a | ||
|
|
ade6e04c6e | ||
|
|
9dcb799fb0 | ||
|
|
073546ba19 | ||
|
|
f8584954b8 | ||
|
|
a91d5e0079 | ||
|
|
5dcbd570a8 | ||
|
|
87a89e877d | ||
|
|
bc4ed0797f | ||
|
|
b4a8193bae | ||
|
|
0a3258974a | ||
|
|
d69ef35547 | ||
|
|
1ca8b78388 |
Vendored
+34
@@ -0,0 +1,34 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[ValidateSet('Debug', 'Release', 'Snapshot')]
|
||||||
|
[string]$Configuration = 'Debug'
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$solution = Join-Path $PSScriptRoot '..\Plain Craft Launcher 2.sln'
|
||||||
|
$solution = [IO.Path]::GetFullPath($solution)
|
||||||
|
|
||||||
|
$msbuild = (Get-Command msbuild.exe -ErrorAction SilentlyContinue).Source
|
||||||
|
if (-not $msbuild) {
|
||||||
|
$vswhere = @(
|
||||||
|
(Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'),
|
||||||
|
(Join-Path $env:ProgramFiles 'Microsoft Visual Studio\Installer\vswhere.exe')
|
||||||
|
) | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||||
|
|
||||||
|
if ($vswhere) {
|
||||||
|
$installationPath = & $vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath
|
||||||
|
if ($installationPath) {
|
||||||
|
$candidate = Join-Path $installationPath 'MSBuild\Current\Bin\MSBuild.exe'
|
||||||
|
if (Test-Path $candidate) { $msbuild = $candidate }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $msbuild) {
|
||||||
|
throw 'MSBuild was not found. Install Visual Studio Build Tools with the .NET desktop build tools and .NET Framework 4.8 targeting pack.'
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "MSBuild: $msbuild"
|
||||||
|
Write-Host "Configuration: $Configuration"
|
||||||
|
& $msbuild $solution /t:Build "/p:Configuration=$Configuration" "/p:Platform=Any CPU" /m /v:minimal
|
||||||
|
exit $LASTEXITCODE
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"ms-dotnettools.csharp",
|
||||||
|
"ms-dotnettools.csdevkit"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"dotnet.defaultSolution": "Plain Craft Launcher 2.sln"
|
||||||
|
}
|
||||||
Vendored
+39
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build PCL-ISE (Debug)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "powershell.exe",
|
||||||
|
"args": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-File",
|
||||||
|
"${workspaceFolder}\\.vscode\\build.ps1",
|
||||||
|
"-Configuration",
|
||||||
|
"Debug"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build PCL-ISE (Release)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "powershell.exe",
|
||||||
|
"args": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-File",
|
||||||
|
"${workspaceFolder}\\.vscode\\build.ps1",
|
||||||
|
"-Configuration",
|
||||||
|
"Release"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+1
-1
Submodule MeloongCore updated: 811438aa3c...98157d65c7
+9
-1
@@ -1,13 +1,21 @@
|
|||||||
namespace PCLCS;
|
namespace PCLCS;
|
||||||
public static class Configs {
|
public static class Configs {
|
||||||
|
|
||||||
/// <summary>当前 Java 相关配置的版本。0 代表尚未从老的 Settings 系统中迁移。</summary>
|
public static readonly DynamicConfigEntry<McInstallManifest> McInstallManifest = new("MinecraftInstallManifest", null);
|
||||||
|
|
||||||
|
// Java
|
||||||
|
|
||||||
|
/// <summary> 当前 Java 相关配置的版本。0 代表尚未从老的 Settings 系统中迁移。</summary>
|
||||||
public static readonly ConfigEntry<int> JavaConfigVersion = new("JavaConfigVersion", 0);
|
public static readonly ConfigEntry<int> JavaConfigVersion = new("JavaConfigVersion", 0);
|
||||||
public static readonly ConfigEntry<ConcurrentList<Java>> JavaList = new("JavaList", []);
|
public static readonly ConfigEntry<ConcurrentList<Java>> JavaList = new("JavaList", []);
|
||||||
public static readonly ConfigEntry<List<string>> JavaRemovedList = new("JavaRemovedList", []);
|
public static readonly ConfigEntry<List<string>> JavaRemovedList = new("JavaRemovedList", []);
|
||||||
public static readonly DynamicConfigEntry<bool> JavaMigrated = new("InstanceMigratedJava", false);
|
public static readonly DynamicConfigEntry<bool> JavaMigrated = new("InstanceMigratedJava", false);
|
||||||
public static readonly DynamicConfigEntry<Java> JavaForced = new("InstanceForcedJava", null);
|
public static readonly DynamicConfigEntry<Java> JavaForced = new("InstanceForcedJava", null);
|
||||||
|
|
||||||
|
// 提示
|
||||||
|
|
||||||
|
public static readonly ConfigEntry<bool> HintModifyInstanceWarning = new("HintModifyInstanceWarning", false);
|
||||||
|
|
||||||
static Configs() {
|
static Configs() {
|
||||||
/// 当 JavaForced 获取到一个不在 JavaList 中的值时,将其重置为 null。
|
/// 当 JavaForced 获取到一个不在 JavaList 中的值时,将其重置为 null。
|
||||||
JavaForced.PreviewGet += (args, provider) => {
|
JavaForced.PreviewGet += (args, provider) => {
|
||||||
|
|||||||
+6
-2
@@ -68,13 +68,17 @@ public static class Versions {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 版本管理中 Mod 信息缓存的版本号。
|
/// 版本管理中 Mod 信息缓存的版本号。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int LocalModCacheVersion = 19;
|
public const int LocalModCacheVersion = 21;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minecraft 本地实例信息缓存的版本号。
|
/// Minecraft 本地实例信息缓存的版本号。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int McInstanceCacheVersion = 38;
|
public const int McInstanceCacheVersion = 39;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Java 相关配置的版本号。
|
/// Java 相关配置的版本号。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int JavaConfigVersion = 1;
|
public const int JavaConfigVersion = 1;
|
||||||
|
/// <summary>
|
||||||
|
/// Minecraft 安装清单的版本号。
|
||||||
|
/// </summary>
|
||||||
|
public const int McInstallManifestVersion = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -87,9 +87,9 @@ namespace PCLCS;
|
|||||||
|
|
||||||
// 相同检查
|
// 相同检查
|
||||||
public bool Equals(Java? other)
|
public bool Equals(Java? other)
|
||||||
=> other is not null && string.Equals(Folder, other.Folder, StringComparison.OrdinalIgnoreCase);
|
=> other is not null && PathUtils.IsSame(Folder, other.Folder);
|
||||||
public override bool Equals(object? obj) => obj is Java other && Equals(other);
|
public override bool Equals(object? obj) => obj is Java other && Equals(other);
|
||||||
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Folder);
|
public override int GetHashCode() => StringComparer.CurrentCultureIgnoreCase.GetHashCode(PathUtils.ForCompare(Folder));
|
||||||
|
|
||||||
/// <summary>用户友好的描述文本。</summary>
|
/// <summary>用户友好的描述文本。</summary>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@@ -211,7 +211,7 @@ public static class JavaUtils {
|
|||||||
}
|
}
|
||||||
// 结果
|
// 结果
|
||||||
var hasReparsePoint = HasReparsePoint(FileUtils.GetInfo(Path.Combine(targetFolder, "java.exe")));
|
var hasReparsePoint = HasReparsePoint(FileUtils.GetInfo(Path.Combine(targetFolder, "java.exe")));
|
||||||
var isSpecialPath = targetFolder.Contains("java8path_target_") || targetFolder.Contains("javapath_target_") || targetFolder.Contains("javatmp") || targetFolder.Contains("system32");
|
var isSpecialPath = targetFolder.ContainsIgnoreCase("java8path_target_") || targetFolder.ContainsIgnoreCase("javapath_target_") || targetFolder.ContainsIgnoreCase("javatmp") || targetFolder.ContainsIgnoreCase("system32");
|
||||||
results.Add((targetFolder, hasReparsePoint, isSpecialPath));
|
results.Add((targetFolder, hasReparsePoint, isSpecialPath));
|
||||||
}
|
}
|
||||||
} catch (UnauthorizedAccessException) {
|
} catch (UnauthorizedAccessException) {
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace PCLCS;
|
||||||
|
|
||||||
|
public static class McUtils {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 比较两个版本名;左侧较新返回正数,相同返回 0,右侧较新返回负数。
|
||||||
|
/// 无法比较两个预发布版的大小。
|
||||||
|
/// 支持的格式:未知版本, 26.1-snapshot-1,1.13.2, 1.7.10-pre4, 1.8_pre, 1.14 Pre-Release 2, 1.14.4 C6
|
||||||
|
/// </summary>
|
||||||
|
public static int CompareVersion(string left, string right) {
|
||||||
|
if (left == right) return 0;
|
||||||
|
if (left == "未知版本" || right == "未知版本") return left == "未知版本" ? 1 : -1;
|
||||||
|
left = left.Lower();
|
||||||
|
right = right.Lower();
|
||||||
|
var leftParts = left.Replace("快照", "snapshot").Replace("预览版", "pre").RegexSearch("[a-z]+|[0-9]+").ToList();
|
||||||
|
var rightParts = right.Replace("快照", "snapshot").Replace("预览版", "pre").RegexSearch("[a-z]+|[0-9]+").ToList();
|
||||||
|
for (int i = 0; ; i++) {
|
||||||
|
if (i >= leftParts.Count && i >= rightParts.Count) return string.Compare(left, right, StringComparison.Ordinal); // 两边均缺失,感觉是一个东西
|
||||||
|
string leftValue = i < leftParts.Count ? leftParts[i] : "0";
|
||||||
|
string rightValue = i < rightParts.Count ? rightParts[i] : "0";
|
||||||
|
if (leftValue == rightValue) continue;
|
||||||
|
int leftNumber = leftValue switch {
|
||||||
|
"rc" => -1,
|
||||||
|
"pre" => -2,
|
||||||
|
"snapshot" => -3,
|
||||||
|
"experimental" => -4,
|
||||||
|
_ => int.TryParse(leftValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out int leftResult) ? leftResult : 0
|
||||||
|
};
|
||||||
|
int rightNumber = rightValue switch {
|
||||||
|
"rc" => -1,
|
||||||
|
"pre" => -2,
|
||||||
|
"snapshot" => -3,
|
||||||
|
"experimental" => -4,
|
||||||
|
_ => int.TryParse(rightValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out int rightResult) ? rightResult : 0
|
||||||
|
};
|
||||||
|
if (leftNumber == 0 && rightNumber == 0) return string.Compare(leftValue, rightValue, StringComparison.Ordinal);
|
||||||
|
if (leftNumber != rightNumber) return leftNumber.CompareTo(rightNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 比较两个版本名;左侧不旧于右侧返回 True。
|
||||||
|
/// </summary>
|
||||||
|
public static bool CompareVersionGE(string left, string right) => CompareVersion(left, right) >= 0;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
namespace PCLCS;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MC 版本安装清单及 PCL 管理文件清单。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="SchemaVersion"> 清单格式版本;无版本的旧清单为 0。</param>
|
||||||
|
/// <param name="Components"> 安装目标及受管理组件版本。</param>
|
||||||
|
/// <param name="LastModifiedUtc"> 最后修改时间(UTC)。</param>
|
||||||
|
/// <param name="ManagedFiles"> 受管理文件;没有文件时为空列表。</param>
|
||||||
|
public record McInstallManifest(int SchemaVersion, McComponents Components, DateTime LastModifiedUtc, IReadOnlyList<McInstallManifest.ManagedFile> ManagedFiles) {
|
||||||
|
/// <summary>
|
||||||
|
/// 清理以 Mod 形式安装的、已删除或修改的组件的记录,并更新清单。
|
||||||
|
/// </summary>
|
||||||
|
public McInstallManifest RefreshModComponents(string gameFolder) {
|
||||||
|
List<ManagedFile> invalidFiles = [];
|
||||||
|
foreach (ManagedFile entry in ManagedFiles) {
|
||||||
|
if (entry.Component is null) continue; // 不检查非组件文件
|
||||||
|
FileInfo file = new(Path.Combine(gameFolder, entry.RelativePath));
|
||||||
|
if (!file.Exists || file.LastWriteTimeUtc != entry.LastWriteTimeUtc.ToUniversalTime()) invalidFiles.Add(entry);
|
||||||
|
}
|
||||||
|
if (!invalidFiles.Any()) return this;
|
||||||
|
return this with {
|
||||||
|
Components = Components with {
|
||||||
|
OptiFineEntry = invalidFiles.Any(file => file.Component == "OptiFine") ? null : Components.OptiFineEntry,
|
||||||
|
FabricApiVersion = invalidFiles.Any(file => file.Component == "FabricApi") ? null : Components.FabricApiVersion,
|
||||||
|
OptiFabricVersion = invalidFiles.Any(file => file.Component == "OptiFabric") ? null : Components.OptiFabricVersion
|
||||||
|
},
|
||||||
|
ManagedFiles = ManagedFiles.Where(file => !invalidFiles.Contains(file)).ToList(),
|
||||||
|
LastModifiedUtc = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 由 PCL 管理并记录的版本内文件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RelativePath"> 相对于游戏目录的文件路径。确保路径为全小写且可比较。</param>
|
||||||
|
/// <param name="Sha1"> 小写的 SHA1。</param>
|
||||||
|
/// <param name="LastWriteTimeUtc"> 目标文件的最后修改时间(UTC)。</param>
|
||||||
|
/// <param name="Component"> 安装器组件名;为空时表示文件由整合包管理。</param>
|
||||||
|
public record ManagedFile(string RelativePath, string Sha1, DateTime LastWriteTimeUtc,
|
||||||
|
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? Component = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="MinecraftVersion"> 目标 Minecraft 版本。</param>
|
||||||
|
/// <param name="ModLoaderVersions"> 目标中各个 Mod Loader 的版本;原版为空字典。</param>
|
||||||
|
/// <param name="OptiFineEntry"> OptiFine 条目信息,不安装时为 <see langword="null"/>。</param>
|
||||||
|
/// <param name="FabricApiVersion"> 由 PCL 管理的 Fabric API 版本;不安装时为 <see langword="null"/>。</param>
|
||||||
|
/// <param name="OptiFabricVersion"> 由 PCL 管理的 OptiFabric 版本;不安装时为 <see langword="null"/>。</param>
|
||||||
|
[method: JsonConstructor]
|
||||||
|
public record McComponents(string MinecraftVersion, Dictionary<ModLoaders, string> ModLoaderVersions,
|
||||||
|
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] JObject? OptiFineEntry = null,
|
||||||
|
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? FabricApiVersion = null,
|
||||||
|
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? OptiFabricVersion = null) {
|
||||||
|
[JsonIgnore]
|
||||||
|
public string? OptiFineVersion => OptiFineEntry?["InstanceName"]?.Value<string>()?.AfterLast("-OptiFine_");
|
||||||
|
public McComponents(string minecraftVersion, JObject? optiFineEntry, string? forgeVersion,
|
||||||
|
string? neoForgeVersion, string? fabricVersion, string? fabricApiVersion, string? optiFabricVersion, string? liteLoaderVersion)
|
||||||
|
: this(minecraftVersion, [], optiFineEntry, fabricApiVersion, optiFabricVersion) {
|
||||||
|
if (forgeVersion is not null) ModLoaderVersions[ModLoaders.Forge] = forgeVersion;
|
||||||
|
if (neoForgeVersion is not null) ModLoaderVersions[ModLoaders.NeoForge] = neoForgeVersion;
|
||||||
|
if (fabricVersion is not null) ModLoaderVersions[ModLoaders.Fabric] = fabricVersion;
|
||||||
|
if (liteLoaderVersion is not null) ModLoaderVersions[ModLoaders.LiteLoader] = liteLoaderVersion;
|
||||||
|
}
|
||||||
|
public bool IsEquivalentTo(McComponents other) =>
|
||||||
|
MinecraftVersion == other.MinecraftVersion &&
|
||||||
|
OptiFineVersion == other.OptiFineVersion &&
|
||||||
|
FabricApiVersion == other.FabricApiVersion &&
|
||||||
|
OptiFabricVersion == other.OptiFabricVersion &&
|
||||||
|
ModLoaderVersions.Count == other.ModLoaderVersions.Count &&
|
||||||
|
ModLoaderVersions.All(entry => other.ModLoaderVersions.TryGetValue(entry.Key, out string? version) && version == entry.Value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,295 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace PCLCS;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minecraft 版本号和组件信息
|
||||||
|
/// </summary>
|
||||||
|
public sealed class McVersion {
|
||||||
|
/// <summary>
|
||||||
|
/// 原版版本名,如 26.1、26.1-snapshot-1、1.12.2、16w01a。
|
||||||
|
/// </summary>
|
||||||
|
public string VanillaName {
|
||||||
|
get => _vanillaName;
|
||||||
|
set {
|
||||||
|
_vanillaName = value ?? "Unknown";
|
||||||
|
Vanilla = NameToVersion(_vanillaName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private string _vanillaName = "Unknown";
|
||||||
|
/// <summary>
|
||||||
|
/// 可比较的三段式原版版本号。
|
||||||
|
/// 旧格式会将次版本号移到主版本号,例如 1.20.1 会转换为 20.0.1,若没有版本号,例如旧快照,则为 9999.0.0。
|
||||||
|
/// </summary>
|
||||||
|
public Version Vanilla = new(9999, 0, 0);
|
||||||
|
/// <summary> 原版版本号是否可靠(不是通过猜测获取)。</summary>
|
||||||
|
public bool Reliable;
|
||||||
|
/// <summary> 原版版本号是否有效。</summary>
|
||||||
|
public bool Valid => Vanilla.Major < 1000;
|
||||||
|
/// <summary> 可供比较的原版 Drop 序数,例如 26.3.2 为 263,1.21.5 为 210;若没有版本号,例如旧快照,则直接指定为 209。</summary>
|
||||||
|
public int Drop => Valid ? Vanilla.Major * 10 + Vanilla.Minor : 209;
|
||||||
|
/// <summary> 已安装的 Mod Loader,可能有多个。未安装时为 <see cref="ModLoaders.None"/>。</summary>
|
||||||
|
public ModLoaders ModLoaders => ModLoaderVersions.Keys.Aggregate(ModLoaders.None, (result, loader) => result | loader);
|
||||||
|
/// <summary> 已安装的各个 Mod Loader 及其版本;无法确定精确版本时为“未知版本”。</summary>
|
||||||
|
public Dictionary<ModLoaders, string> ModLoaderVersions { get; } = [];
|
||||||
|
/// <summary> OptiFine 版本名,如 C8、C9_pre10;未识别到时为 null。</summary>
|
||||||
|
public string? OptiFine;
|
||||||
|
/// <summary> OptiFine 是否以 Mod 形式安装。</summary>
|
||||||
|
public bool OptiFineAsMod;
|
||||||
|
/// <summary> 版本的发布时间。</summary>
|
||||||
|
public DateTime ReleaseTime = new(1970, 1, 1, 15, 0, 0);
|
||||||
|
/// <summary> 是否为愚人节版本。</summary>
|
||||||
|
public bool IsFool;
|
||||||
|
/// <summary> 是否为快照、预发布版、发布候选或实验性版本。</summary>
|
||||||
|
public bool IsSnapshot;
|
||||||
|
/// <summary> 是否识别到已安装的 OptiFine。</summary>
|
||||||
|
public bool HasOptiFine => OptiFine is not null;
|
||||||
|
/// <summary>
|
||||||
|
/// 可供比较的 OptiFine 版本序数。
|
||||||
|
/// </summary>
|
||||||
|
public int OptiFineCode {
|
||||||
|
get {
|
||||||
|
if (OptiFine is null or "未知版本" || OptiFine.Length == 0) return 0;
|
||||||
|
// 字母编号,如 G2 中的 G(7)
|
||||||
|
int result = char.ToUpperInvariant(OptiFine[0]) - 'A' + 1;
|
||||||
|
// 末尾数字,如 C5 beta4 中的 5
|
||||||
|
result = result * 100 + (int.TryParse(OptiFine.Substring(1).RegexSeek(@"\d+"), out int mainVersion) ? mainVersion : 0);
|
||||||
|
// 测试标记(正式版为 99,Pre[x] 为 50+x,Beta[x] 为 x)
|
||||||
|
result *= 100;
|
||||||
|
string? preview = OptiFine.RegexSeek(@"(?i)(pre|beta)\d*");
|
||||||
|
if (preview is null) return result + 99;
|
||||||
|
int sequence = int.TryParse(preview.RegexSeek(@"\d+"), out int value) ? value : 1; // 为 pre 或 beta 结尾,视作 1
|
||||||
|
return result + (preview.StartsWithF("pre", true) ? 50 : 0) + sequence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 可供比较的类 Forge 版本序数。
|
||||||
|
/// </summary>
|
||||||
|
public int ForgelikeCode {
|
||||||
|
get {
|
||||||
|
if (!ModLoaderVersions.TryGetValue(ModLoaders.Forge, out string? version)) {
|
||||||
|
ModLoaderVersions.TryGetValue(ModLoaders.NeoForge, out version);
|
||||||
|
}
|
||||||
|
if (version is null or "未知版本") return 0;
|
||||||
|
// 提取所有数字段,以兼容 beta、alpha 和 snapshot 等非数字后缀。
|
||||||
|
int[] segments = version.RegexSearch(@"\d+")
|
||||||
|
.Select(segment => int.TryParse(segment, out int value) ? value : 0).ToArray();
|
||||||
|
return segments.Length switch {
|
||||||
|
>= 4 => segments[0] * 1000000 + segments[1] * 10000 + segments[3],
|
||||||
|
3 => segments[0] * 1000000 + segments[1] * 10000 + segments[2],
|
||||||
|
2 => segments[0] * 1000000 + segments[1] * 10000,
|
||||||
|
1 => segments[0] * 1000000,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建默认 Minecraft 版本。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vanillaName">原版版本名。</param>
|
||||||
|
/// <param name="reliable">版本名是否来自可靠依据。</param>
|
||||||
|
public McVersion(string vanillaName, bool reliable = true) {
|
||||||
|
Reliable = reliable;
|
||||||
|
VanillaName = vanillaName;
|
||||||
|
IsFool = IsFoolName(VanillaName);
|
||||||
|
IsSnapshot = IsSnapshotName(VanillaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过 Components 创建 Minecraft 版本信息。
|
||||||
|
/// </summary>
|
||||||
|
public McVersion(McComponents components) : this(components.MinecraftVersion) {
|
||||||
|
OptiFine = components.OptiFineVersion?.AfterLast("HD_").AfterFirst("_");
|
||||||
|
foreach (var loader in components.ModLoaderVersions) ModLoaderVersions[loader.Key] = loader.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过 JSON 识别 Minecraft 版本和已安装组件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instanceName">实例文件夹名。</param>
|
||||||
|
/// <param name="json">展开的版本 JSON。</param>
|
||||||
|
/// <param name="jarVersionJson">版本 JAR 中的 version.json。</param>
|
||||||
|
public McVersion(string instanceName, JObject json, JObject? jarVersionJson = null) {
|
||||||
|
string jsonText = json.ToString(Formatting.None);
|
||||||
|
DateTime releaseTime = new(1970, 1, 1, 15, 0, 0); // 未知版本也可能显示为 1970 年
|
||||||
|
try {
|
||||||
|
if (json["releaseTime"] is JToken releaseTimeToken) releaseTime = releaseTimeToken.ToObject<DateTime>();
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
bool reliable = true;
|
||||||
|
// 获取游戏版本
|
||||||
|
string vanillaName = (GetVanillaName(instanceName, json, jarVersionJson, releaseTime, ref reliable) ?? "Unknown").Replace("_unobfuscated", "").Replace(" Unobfuscated", "");
|
||||||
|
Reliable = reliable;
|
||||||
|
VanillaName = vanillaName;
|
||||||
|
ReleaseTime = releaseTime;
|
||||||
|
// 确定版本分类
|
||||||
|
string jsonType = json.Value<string>("type") ?? "";
|
||||||
|
// OptiFine
|
||||||
|
OptiFine = jsonText.ContainsIgnoreCase("optifine") ? jsonText.RegexSeek(@"(?<=HD_U_)[^\"":/]+") ?? "未知版本": null;
|
||||||
|
// 愚人节与快照版本
|
||||||
|
DateTime fixedReleaseTime = releaseTime.ToUniversalTime().AddHours(2);
|
||||||
|
IsFool = jsonType == "fool" || IsFoolName(vanillaName) || (fixedReleaseTime.Month == 4 && fixedReleaseTime.Day == 1 && jsonType == "snapshot");
|
||||||
|
IsSnapshot = IsSnapshotName(vanillaName) || instanceName.ContainsIgnoreCase("combat") || jsonType is "snapshot" or "pending" or "fool";
|
||||||
|
if (!Reliable) Logger.Info($"无法完全确认 MC 版本号的版本:{VanillaName}");
|
||||||
|
// LiteLoader
|
||||||
|
if (jsonText.ContainsIgnoreCase("liteloader")) {
|
||||||
|
ModLoaderVersions[ModLoaders.LiteLoader] = jsonText.RegexSeek(@"(?<=com\.mumfrey:liteloader:)[^\"":/]+") ?? "未知版本";
|
||||||
|
}
|
||||||
|
// Fabric、Forge、NeoForge
|
||||||
|
if (jsonText.ContainsIgnoreCase("net.fabricmc:fabric-loader") || jsonText.ContainsIgnoreCase("org.quiltmc:quilt-loader")) {
|
||||||
|
ModLoaderVersions[ModLoaders.Fabric] = jsonText.RegexSeek(@"(?<=(net\.fabricmc:fabric-loader:|org\.quiltmc:quilt-loader:))[0-9\.]+(\+build.[0-9]+)?")?
|
||||||
|
.Replace("+build", "") ?? "未知版本";
|
||||||
|
} else if (jsonText.ContainsIgnoreCase("net.neoforge")) {
|
||||||
|
// 1.20.1 JSON 范例:"--fml.forgeVersion", "47.1.99"
|
||||||
|
// 1.20.2+ JSON 范例:"--fml.neoForgeVersion", "20.6.119-beta"
|
||||||
|
ModLoaderVersions[ModLoaders.NeoForge] = FindArgumentValue(json, "--fml.neoForgeVersion") ?? FindArgumentValue(json, "--fml.forgeVersion") ?? "未知版本";
|
||||||
|
} else if (jsonText.ContainsIgnoreCase("minecraftforge")) {
|
||||||
|
ModLoaderVersions[ModLoaders.Forge] = jsonText.RegexSeek(@"(?<=forge:[0-9\.]+(?:_pre[0-9]*)?-)[0-9\.]+")
|
||||||
|
?? jsonText.RegexSeek(@"(?<=net\.minecraftforge:minecraftforge:)[0-9\.]+")
|
||||||
|
?? jsonText.RegexSeek(@"(?<=net\.minecraftforge:fmlloader:[0-9\.]+-)[0-9\.]+") ?? "未知版本";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? GetVanillaName(string instanceName, JObject json, JObject? jarVersionJson, DateTime releaseTime, ref bool reliable) {
|
||||||
|
// 获取发布时间并判断是否为老版本
|
||||||
|
if (releaseTime.Year is > 2000 and < 2013) return "Old";
|
||||||
|
// 实验性快照
|
||||||
|
if (json.Value<string>("type") == "pending") return "pending";
|
||||||
|
// 从 PCL 下载的版本信息中获取版本号
|
||||||
|
if (json["clientVersion"] is JToken clientVersion) return clientVersion.ToString();
|
||||||
|
// 从 HMCL 下载的版本信息中获取版本号
|
||||||
|
if (json["patches"] is JArray patches) {
|
||||||
|
JToken? gameVersion = patches.OfType<JObject>().FirstOrDefault(patch => patch.Value<string>("id") == "game")?["version"];
|
||||||
|
if (gameVersion is not null) return gameVersion.ToString();
|
||||||
|
}
|
||||||
|
// 从 Forge / NeoForge Arguments 中获取版本号
|
||||||
|
if (FindArgumentValue(json, "--fml.mcVersion") is { Length: > 0 } fmlVersion) return fmlVersion;
|
||||||
|
// 从继承版本中获取版本号
|
||||||
|
string inherit = json["inheritsFrom"]?.ToString() ?? "";
|
||||||
|
if (inherit.Length > 0) {
|
||||||
|
string jar = json["jar"]?.ToString() ?? ""; // LiteLoader 优先使用 Jar
|
||||||
|
return jar.Length > 0 ? jar : inherit;
|
||||||
|
}
|
||||||
|
// 从下载地址中获取版本号
|
||||||
|
string? download = json["downloads"]?.ToString(Formatting.None).RegexSeek(@"(?<=launcher.mojang.com/mc/game/)[^/]*");
|
||||||
|
if (download is not null) return download;
|
||||||
|
// 从 Forge/OptiFine/Fabric 版本中获取版本号
|
||||||
|
string librariesText = json["libraries"]!.ToString();
|
||||||
|
string[] libraryPatterns = [
|
||||||
|
@"(?<=net.minecraftforge:forge:)[0-9]{1,2}.[0-9+.]+",
|
||||||
|
@"(?<=net.minecraftforge:fmlloader:)[0-9]{1,2}.[0-9+.]+",
|
||||||
|
@"(?<=optifine:OptiFine:)[0-9]{1,2}.[0-9+.]+",
|
||||||
|
@"(?<=((fabricmc)|(quiltmc)):intermediary:)[^\""]*"
|
||||||
|
];
|
||||||
|
foreach (string pattern in libraryPatterns) {
|
||||||
|
if (librariesText.RegexSeek(pattern) is string match) return match;
|
||||||
|
}
|
||||||
|
// 从 jar 项中获取版本号
|
||||||
|
if (json["jar"] is JToken jarToken) return jarToken.ToString();
|
||||||
|
// 从 jar 文件的 version.json 中获取版本号
|
||||||
|
if (jarVersionJson?["name"] is JToken jarNameToken && jarNameToken.ToString() is { Length: < 32 } jarName) { // 因为 wiki 说这玩意儿可能是个 hash,虽然我没发现
|
||||||
|
Logger.Info($"从版本 jar 中的 version.json 获取到版本号:{jarName}");
|
||||||
|
return jarName;
|
||||||
|
}
|
||||||
|
string VersionPattern = @"(([1-9][0-9]w[0-9]{2}[a-g])|((1|[2-9][0-9])\.[0-9]+(\.[0-9]+)?(-(pre|rc|snapshot-?)[1-9]*| Pre-Release( [1-9])?)?))(_unobfuscated)?";
|
||||||
|
// 从 JSON 的 ID 中获取
|
||||||
|
if (json["id"]!.ToString().RegexSeek(VersionPattern, RegexOptions.IgnoreCase) is string idMatch) return idMatch;
|
||||||
|
// 非准确的版本判断警告
|
||||||
|
Logger.Info($"无法完全确认 MC 版本号的版本:{instanceName}");
|
||||||
|
reliable = false;
|
||||||
|
// 从文件夹名中获取
|
||||||
|
if (instanceName.RegexSeek(VersionPattern, RegexOptions.IgnoreCase) is string folderMatch) return folderMatch;
|
||||||
|
// 从 JSON 出现的版本号中获取
|
||||||
|
JObject withoutLibraries = (JObject) json.DeepClone();
|
||||||
|
withoutLibraries.Remove("libraries");
|
||||||
|
return withoutLibraries.ToString(Formatting.None).RegexSeek(VersionPattern, RegexOptions.IgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsFoolName(string name) {
|
||||||
|
name = name.Lower();
|
||||||
|
return name.StartsWithF("2.0") || name is "15w14a" or "1.rv-pre1" or
|
||||||
|
"3d shareware v1.34" or "20w14∞" or "22w13oneblockatatime" or "23w13a_or_b" or
|
||||||
|
"24w14potato" or "25w14craftmine" or "26w14a" || name.StartsWithF("20w14inf");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSnapshotName(string name) =>
|
||||||
|
new[] { "w", "snapshot", "rc", "pre", "experimental", "-" }.Any(name.ContainsIgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取 arguments 中指定参数的字符串值。
|
||||||
|
/// </summary>
|
||||||
|
private static string? FindArgumentValue(JObject json, string name) {
|
||||||
|
JArray? arguments = json["arguments"]?["game"] as JArray;
|
||||||
|
if (arguments is null) return null;
|
||||||
|
for (int i = 0; i + 1 < arguments.Count; i++) {
|
||||||
|
if (arguments[i]?.ToString() == name) return arguments[i + 1]?.ToString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断版本字符串是否符合 Minecraft 原版格式,例如 1.x、26.x。
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsStandardFormat(string? version) {
|
||||||
|
if (version is null) return false;
|
||||||
|
if (Regex.IsMatch(version, @"^1\.\d")) return true;
|
||||||
|
return double.TryParse(version.RegexSeek(@"^[2-9]\d\.\d+"), NumberStyles.Float,
|
||||||
|
CultureInfo.InvariantCulture, out double value) && value >= 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将版本名转换为 Drop 序数;无法转换时返回 209。
|
||||||
|
/// </summary>
|
||||||
|
public static int VersionToDrop(string? vanillaName) {
|
||||||
|
if (vanillaName is null) return 209;
|
||||||
|
Version version = NameToVersion(vanillaName);
|
||||||
|
return version.Major >= 1000 ? 209 : version.Major * 10 + version.Minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将 Drop 序数转换为版本字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string DropToVersion(int drop) {
|
||||||
|
if (drop >= 250) return $"{drop / 10}.{drop % 10}";
|
||||||
|
if (drop != 209) return $"1.{drop / 10}";
|
||||||
|
Logger.Warn(new Exception("尝试将旧快照版 Drop 序数转换为版本字符串,这不应该发生!"));
|
||||||
|
return "1.20";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将版本名转换为可比较的三段式原版版本号。
|
||||||
|
/// 对老版本格式,例如 1.20.3,会被转换为 20.0.3。
|
||||||
|
/// 对愚人节版本,返回其基于的正式版版本号。
|
||||||
|
/// 若没有版本号,例如旧快照,则为 9999.0.0。
|
||||||
|
/// </summary>
|
||||||
|
public static Version NameToVersion(string? name) {
|
||||||
|
if (name is null) return new Version(9999, 0, 0);
|
||||||
|
name = name.Lower().Replace("_unobfuscated", "").Replace(" unobfuscated", "");
|
||||||
|
// 愚人节版本
|
||||||
|
if (name.StartsWithF("2.0")) return NameToVersion("1.5.1");
|
||||||
|
if (name == "15w14a") return NameToVersion("1.8.3");
|
||||||
|
if (name.ContainsIgnoreCase(".rv-pre")) return NameToVersion("1.9.2");
|
||||||
|
if (name.ContainsIgnoreCase("shareware")) return NameToVersion("1.13.2");
|
||||||
|
if (name.StartsWithF("20w14") && name != "20w14a") return NameToVersion("1.15.2");
|
||||||
|
if (name.ContainsIgnoreCase("oneblockatatime")) return NameToVersion("1.18.2");
|
||||||
|
if (name.ContainsIgnoreCase("23w13a") && name != "20w13a") return NameToVersion("1.19.4");
|
||||||
|
if (name == "24w14potato") return NameToVersion("1.20.4");
|
||||||
|
if (name == "25w14craftmine") return NameToVersion("1.21.4");
|
||||||
|
if (name == "26w14a") return NameToVersion("26.1.1");
|
||||||
|
// 其余版本
|
||||||
|
static int ParseSegment(string[] segments, int index) {
|
||||||
|
if (index >= segments.Length) return 0;
|
||||||
|
// 只读取该段开头连续的数字,忽略其后的预览版标记。
|
||||||
|
return int.TryParse(segments[index].RegexSeek(@"^\d+"), out int value) ? value : 0;
|
||||||
|
}
|
||||||
|
string[] segments = name.Split([' ', '_', '-', '.'], StringSplitOptions.None);
|
||||||
|
if (name.StartsWithF("1.")) {
|
||||||
|
return new Version(ParseSegment(segments, 1), 0, ParseSegment(segments, 2));
|
||||||
|
} else if (name.RegexCheck(@"^[2-9][0-9]\.")) {
|
||||||
|
return new Version(ParseSegment(segments, 0), ParseSegment(segments, 1), ParseSegment(segments, 2));
|
||||||
|
} else {
|
||||||
|
return new Version(9999, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,423 @@
|
|||||||
|
{
|
||||||
|
"f3a3c9d792bdb48595405d52c02cc7baf1db4ecb": "OptiFine_1.7.2_HD_U_E3.jar",
|
||||||
|
"657169c421ce280f80c73b05ab71ad582d2b37fd": "OptiFine_1.7.2_HD_U_E4.jar",
|
||||||
|
"99f20d449912cd860b409e4679c54dd8da43d55e": "OptiFine_1.7.2_HD_U_E7.jar",
|
||||||
|
"8253f6ed418a2a61a612cc9e69fd1fea1d11fa7d": "OptiFine_1.7.2_HD_U_E8.jar",
|
||||||
|
"379e52fc02cd75562d201b0c505269b6109b2136": "OptiFine_1.7.2_HD_U_F3.jar",
|
||||||
|
"fb04b91e47b5eaa172d2b76c843e488dba8f909b": "OptiFine_1.7.2_HD_U_F7.jar",
|
||||||
|
"b4b6c2c99f5734e4267030a47f2eaad2796eb2a7": "OptiFine_1.7.10_HD_U_D3.jar",
|
||||||
|
"a0b533bc97b24fe771f5b08536c6339d04f92bae": "OptiFine_1.7.10_HD_U_D4.jar",
|
||||||
|
"5e9327dd05a1e762c23c3c0227445d90f193922f": "OptiFine_1.7.10_HD_U_D6.jar",
|
||||||
|
"7a7d2adf21038d241dd375faa7316fb2c74d34d3": "OptiFine_1.7.10_HD_U_D7.jar",
|
||||||
|
"2345677be44dd56a0ae5b90e747a590c3cc00ff8": "OptiFine_1.7.10_HD_U_D8.jar",
|
||||||
|
"23f133173428aee712eb11f200b461e3114bde31": "OptiFine_1.7.10_HD_U_E3.jar",
|
||||||
|
"2130d7266224da6a7325051e37444f7e7c19277c": "OptiFine_1.7.10_HD_U_E7.jar",
|
||||||
|
"55c9c475ecd0f62cc1776ce52be04c5937112936": "OptiFine_1.8.0_HD_U_H5.jar",
|
||||||
|
"bb2c2997cdc66cfb3c311a3dc065752a4845c1a8": "OptiFine_1.8.0_HD_U_H6.jar",
|
||||||
|
"692b0b7e878c3416f21b4347fab4516f3cc86dfc": "OptiFine_1.8.0_HD_U_H7.jar",
|
||||||
|
"5464962b66b9b0dacb3d787e6a71d2365ae50bca": "OptiFine_1.8.0_HD_U_H8.jar",
|
||||||
|
"b7718b03111bec04036fd3352ce374eea273171c": "OptiFine_1.8.0_HD_U_I3.jar",
|
||||||
|
"0d1dcf64b4d104a71e8f65a1362a163ed81a9030": "OptiFine_1.8.0_HD_U_I7.jar",
|
||||||
|
"e5e5eb03748af0fa160b502a28359c0144e254d2": "OptiFine_1.8.8_HD_U_H5.jar",
|
||||||
|
"9294bc4562a143c35ece03a6b3d3a000109def5f": "OptiFine_1.8.8_HD_U_H6.jar",
|
||||||
|
"1c06c011904ab22952a96f73d4b575a5c265d207": "OptiFine_1.8.8_HD_U_H7.jar",
|
||||||
|
"3984e4dd222bb62cb7e28e4d3092029cc7534fd1": "OptiFine_1.8.8_HD_U_H8.jar",
|
||||||
|
"0dc33a9761ceac19ca0bbb1ea6813c0160d43aa1": "OptiFine_1.8.8_HD_U_I3.jar",
|
||||||
|
"30cbf4d61052cbfb736a78117da333df23c129a3": "OptiFine_1.8.8_HD_U_I7.jar",
|
||||||
|
"d8240cfa7387b994fdf2a64bdc8a8860857adc18": "OptiFine_1.8.9_HD_U_H5.jar",
|
||||||
|
"2636689b31810896cf80493f6fc4d8c1783048ea": "OptiFine_1.8.9_HD_U_H6.jar",
|
||||||
|
"e4544c9210bc056abffa1986a33c4e72623d4f31": "OptiFine_1.8.9_HD_U_H7.jar",
|
||||||
|
"4b73738913453bcbca969d3e77f05ae0cf5b8a7e": "OptiFine_1.8.9_HD_U_H8.jar",
|
||||||
|
"d5cd8b902077075bbf1d865cfd5b3362a6863ace": "OptiFine_1.8.9_HD_U_I3.jar",
|
||||||
|
"58bec8f8766918dcad2b8412f1fbb6f30cc9319f": "OptiFine_1.8.9_HD_U_I7.jar",
|
||||||
|
"dcab4849a24ccad5a6a3496c67bc5a88411d2a35": "OptiFine_1.8.9_HD_U_L5.jar",
|
||||||
|
"d362d58a28f5373b141b9e426e8e160638bfafcd": "OptiFine_1.8.9_HD_U_M5.jar",
|
||||||
|
"1f9dcc9735e94ebb5195c4014300ea462eb12878": "preview_OptiFine_1.8.9_HD_U_L6_pre1.jar",
|
||||||
|
"6e0b3b86e51c2647c98e277475ee7e68f32a0d0e": "preview_OptiFine_1.8.9_HD_U_M5_pre2.jar",
|
||||||
|
"7287fcd1a415ab87eca5e89457cc3507aa3fa579": "preview_OptiFine_1.8.9_HD_U_M6_pre1.jar",
|
||||||
|
"0bb792be16ec78d8b62586cc4856950befb3391b": "preview_OptiFine_1.8.9_HD_U_M6_pre2.jar",
|
||||||
|
"fd87c53197312614c34669feb7608f74a30da712": "OptiFine_1.9.0_HD_U_B1.jar",
|
||||||
|
"f99941037f3633926ffebb3eda67f296a701c019": "OptiFine_1.9.0_HD_U_B2.jar",
|
||||||
|
"34c47106cda1371ecf13e61aed4c1b53a3a53163": "OptiFine_1.9.0_HD_U_B3.jar",
|
||||||
|
"ebc7258e13344097588c73a0b48457083069e1df": "OptiFine_1.9.0_HD_U_B5.jar",
|
||||||
|
"999df92e8904f9268e549135edbec322d332ef62": "OptiFine_1.9.0_HD_U_D7.jar",
|
||||||
|
"0fe031e95f9c01481c9376d9a1df68f9e9857db8": "OptiFine_1.9.0_HD_U_D8.jar",
|
||||||
|
"f4bc2eb5e039e842eb07181ea564eba487513228": "OptiFine_1.9.0_HD_U_E3.jar",
|
||||||
|
"78870a94ec3c4db8aebc4c29d4d39bdda2bf05da": "OptiFine_1.9.0_HD_U_E7.jar",
|
||||||
|
"d3d55bb37e76d1932cb3ad9dde4b9127993f856d": "OptiFine_1.9.0_HD_U_H5.jar",
|
||||||
|
"b5faec3b84f42dd396512a3ce7c1b57c0b972b70": "OptiFine_1.9.0_HD_U_I5.jar",
|
||||||
|
"92742ecac143b1d28c215ca145bd9775a01c5085": "preview_OptiFine_1.9.0_HD_U_I5_pre1.jar",
|
||||||
|
"c87029938376017deba9108322bcb8424d64e92c": "OptiFine_1.9.2_HD_U_B1.jar",
|
||||||
|
"d3e5e1fa480e66603ca037d74966a95d25968d51": "OptiFine_1.9.2_HD_U_B2.jar",
|
||||||
|
"fbd545f921d098235a28f87cda55a0504e831954": "OptiFine_1.9.2_HD_U_B3.jar",
|
||||||
|
"1ae8e6daeeccb6ee48618e8ccdc0b6276d47944f": "OptiFine_1.9.2_HD_U_D7.jar",
|
||||||
|
"3350c829b29d170e9ac19809a3ae45cb099277b5": "OptiFine_1.9.2_HD_U_D8.jar",
|
||||||
|
"c032b2ae0b6087077efef8ae89b612e0d4ea81b7": "OptiFine_1.9.2_HD_U_E3.jar",
|
||||||
|
"3d8cbc19bcad9e9ecc98f607e10f65673a09b482": "OptiFine_1.9.4_HD_U_B4.jar",
|
||||||
|
"b6b9e66b34ddcda5294b016602fb17d741ff6f54": "OptiFine_1.9.4_HD_U_B5.jar",
|
||||||
|
"060ddd5a0b7b7ac5586de04ae53cf923ae5c7290": "OptiFine_1.9.4_HD_U_B6.jar",
|
||||||
|
"2c39611a89dc583cdb403f402c2efd2bd8c6da63": "OptiFine_1.9.4_HD_U_D7.jar",
|
||||||
|
"4b26926208de270225eb9d3af24a4ff3841238f5": "OptiFine_1.9.4_HD_U_D8.jar",
|
||||||
|
"012f82fce41aee5e6e56e551d450a07b2b361646": "OptiFine_1.9.4_HD_U_E3.jar",
|
||||||
|
"cf9c075fa71dab34cdf1c376a76bd08295c69ce6": "OptiFine_1.9.4_HD_U_E7.jar",
|
||||||
|
"b3a76b92e0e9594f6fa135f1156b9cc13712db20": "OptiFine_1.9.4_HD_U_H5.jar",
|
||||||
|
"68a206db0d425dd85f6eba33e52122b01e844c46": "OptiFine_1.9.4_HD_U_I5.jar",
|
||||||
|
"2e48d20605340cfad844a6587d3848e328fd4399": "preview_OptiFine_1.9.4_HD_U_I5_pre1.jar",
|
||||||
|
"d7a1e5f40e28fa3283b82bf3af7d3f433b91df08": "OptiFine_1.10_HD_U_B6.jar",
|
||||||
|
"717a02b21136e022cdb4d7d6ec6a4125f4ed2312": "OptiFine_1.10_HD_U_B7.jar",
|
||||||
|
"0b5d1719592a57cf414643c5b56f4bb3c23a5b94": "OptiFine_1.10_HD_U_C1.jar",
|
||||||
|
"236747126edcf0c97fc6a20fa7f6491accbf0108": "OptiFine_1.10_HD_U_D7.jar",
|
||||||
|
"c5fd78710e821f06f871994032e951065c15c40d": "OptiFine_1.10_HD_U_D8.jar",
|
||||||
|
"1bea8b0bae04ca4b25c6824a6f23a5442d5aa926": "OptiFine_1.10_HD_U_E3.jar",
|
||||||
|
"7a7195348ea583458b657573b5fcc72e4adc8308": "OptiFine_1.10_HD_U_E7.jar",
|
||||||
|
"3bcc46f718711cd6fe3db49de4cc810b75420de8": "OptiFine_1.10_HD_U_H5.jar",
|
||||||
|
"a0070afe9c1c0ced4bcfcda85359e07917d569bd": "OptiFine_1.10_HD_U_I5.jar",
|
||||||
|
"f9a36eb0246ad6ba303e670082be2c2515c50dcd": "preview_OptiFine_1.10_HD_U_I5_pre1.jar",
|
||||||
|
"3ea5dae651b6d64900562d1cde5070ebd9db2936": "OptiFine_1.10.2_HD_U_C1.jar",
|
||||||
|
"41968442e8d1e30e9a32e7a5594caca22312d9d6": "OptiFine_1.10.2_HD_U_C2.jar",
|
||||||
|
"9c8bc96d3125199e96f5dbfda685ea5dd92c253e": "OptiFine_1.10.2_HD_U_C3.jar",
|
||||||
|
"7ec4ccc213b482936baaffb9f1937f7147796893": "OptiFine_1.10.2_HD_U_D1.jar",
|
||||||
|
"3ee5aecc8e11567fb46de0b94e23cf1428f4c9fc": "OptiFine_1.10.2_HD_U_D2.jar",
|
||||||
|
"98059ed7e93d0fc058203569ccfe965b022fb18f": "OptiFine_1.10.2_HD_U_D3.jar",
|
||||||
|
"c3165d0a0207d72e18f4533e7aa5ca30e96819a9": "OptiFine_1.10.2_HD_U_D4.jar",
|
||||||
|
"347359aef422d64711b470f4cf0803cb072da0fa": "OptiFine_1.10.2_HD_U_D6.jar",
|
||||||
|
"4ddf7c45e00839031f5793451541bca002f9257f": "OptiFine_1.10.2_HD_U_D7.jar",
|
||||||
|
"5c3685e279c664a818c41ca213b2bc9bfc4340b0": "OptiFine_1.10.2_HD_U_D8.jar",
|
||||||
|
"129581af3d7d73b506b42d822cb2d3fce68c8e2e": "OptiFine_1.10.2_HD_U_E3.jar",
|
||||||
|
"f052d269109154d851cc7a8e766c78802a76e9b2": "OptiFine_1.10.2_HD_U_E7.jar",
|
||||||
|
"f285cfe6753c5d987e4cb0940da05e9513334d98": "OptiFine_1.10.2_HD_U_H5.jar",
|
||||||
|
"12fd8dd33150f9e4436f23bac08265305f949e20": "OptiFine_1.10.2_HD_U_I5.jar",
|
||||||
|
"adac69b25bb95242422a635965c7f17503c694be": "preview_OptiFine_1.10.2_HD_U_I5_pre1.jar",
|
||||||
|
"06031e4c828b66facefdfa32cd29c585909d9e45": "OptiFine_1.11_HD_U_B1.jar",
|
||||||
|
"449aef14cee17cf1c79d4bad73b69107202d3c1c": "OptiFine_1.11_HD_U_B2.jar",
|
||||||
|
"7663e1ee572c742e96a71a355f0775baf7cbc6ef": "OptiFine_1.11_HD_U_B3.jar",
|
||||||
|
"bde9d34f84a030734c7b9d09eda700c7c828eb96": "OptiFine_1.11_HD_U_B5.jar",
|
||||||
|
"579cfb75b86f3404c5f6e8f694c51b09b7c9b261": "OptiFine_1.11_HD_U_B6.jar",
|
||||||
|
"350af22b31dbc27d1b928e7144582fd361deb193": "OptiFine_1.11_HD_U_B7.jar",
|
||||||
|
"236161183cc5cd5faf84dd27824cc3eaa107ed5f": "OptiFine_1.11_HD_U_B8.jar",
|
||||||
|
"9ca32d42c7e5ad9de9665ffee9ddd41dddd33b66": "OptiFine_1.11_HD_U_C3.jar",
|
||||||
|
"2e45de9e9fb385f24c6eecb1a64537de78778105": "OptiFine_1.11_HD_U_C7.jar",
|
||||||
|
"32df58fec7148e75b599b18691f80e69b7f9cd1b": "OptiFine_1.11_HD_U_F5.jar",
|
||||||
|
"71057cb7a3d0971c3b56e1fbbc333304a72e1352": "OptiFine_1.11_HD_U_G5.jar",
|
||||||
|
"c2ee1e1019ab26bee56447f4df8a2639d2029925": "preview_OptiFine_1.11_HD_U_G5_pre1.jar",
|
||||||
|
"083a002215e2174c0d40af20d2f3844ea349a354": "OptiFine_1.11.2_HD_U_B5.jar",
|
||||||
|
"eb92ce00048faa95b184d121fa667074532fb9db": "OptiFine_1.11.2_HD_U_B6.jar",
|
||||||
|
"7449a2db44e86303d588b526dc73127c16b0e94f": "OptiFine_1.11.2_HD_U_B7.jar",
|
||||||
|
"3e1006c935fe27d83459e77d336460ac5b5c81b4": "OptiFine_1.11.2_HD_U_B8.jar",
|
||||||
|
"049e7e134e8c7364ab61810d84289394e17921de": "OptiFine_1.11.2_HD_U_B9.jar",
|
||||||
|
"4871f2edf7ded30c374aa770e9ea4adcc0b786d0": "OptiFine_1.11.2_HD_U_C1.jar",
|
||||||
|
"e7a54d9e203a1b951f8373ab6dcdedb348e536b1": "OptiFine_1.11.2_HD_U_C2.jar",
|
||||||
|
"8d7fd0facc2299f3dad9dc7c19cc13f72a780343": "OptiFine_1.11.2_HD_U_C3.jar",
|
||||||
|
"20db26eaafb1c4ebd99e1dc2fffe4a62456bf60e": "OptiFine_1.11.2_HD_U_C7.jar",
|
||||||
|
"e4efcf05086389fe18d6fe62eb8ab7512a07323c": "OptiFine_1.11.2_HD_U_F5.jar",
|
||||||
|
"65c425ab628d1748b489dee8619271402428509e": "OptiFine_1.11.2_HD_U_G5.jar",
|
||||||
|
"f253807a4689e44da030acd5c2187d2184885e87": "preview_OptiFine_1.11.2_HD_U_G5_pre1.jar",
|
||||||
|
"1fdacab6f3b0df1f46142acf9c427db2a653d680": "OptiFine_1.12_HD_U_C2.jar",
|
||||||
|
"a62a02c8437a0dccaf2ea89ab8392fd40dc92eb1": "OptiFine_1.12_HD_U_C3.jar",
|
||||||
|
"36d6f6f64048f68dd248a4d3c43a6f5e51fbb9c5": "OptiFine_1.12_HD_U_C4.jar",
|
||||||
|
"fd8e0e3ba43568e5ca0ce31c87373806d269b7e5": "OptiFine_1.12_HD_U_C5.jar",
|
||||||
|
"25ba634e5105e6d1e615dad0046905b68313cc9f": "OptiFine_1.12_HD_U_C7.jar",
|
||||||
|
"b9cd2775fc49bf009f82d3ce36235b1e702d46bb": "OptiFine_1.12_HD_U_F5.jar",
|
||||||
|
"3b8369d33c3257cb247c22b13a41b7db0924e948": "OptiFine_1.12_HD_U_G5.jar",
|
||||||
|
"aeee885ccf821c34d86537184389873d8c312ae1": "preview_OptiFine_1.12_HD_U_G5_pre1.jar",
|
||||||
|
"c754771bf6a7371a7084459505c244cbec61a7cf": "OptiFine_1.12.1_HD_U_C5.jar",
|
||||||
|
"4362a9d38542b5f4ba07782fc4d07949f4fede08": "OptiFine_1.12.1_HD_U_C6.jar",
|
||||||
|
"38785968beeb796cde55f91995c6cf8bfbc3b062": "OptiFine_1.12.1_HD_U_C7.jar",
|
||||||
|
"e6f9e6b573119c052062192695fed4ef388db9c1": "OptiFine_1.12.1_HD_U_F5.jar",
|
||||||
|
"3c9cd74810cad75de5091633a1e0c7d3d76ea09c": "OptiFine_1.12.1_HD_U_G5.jar",
|
||||||
|
"aaaaff3ae13a0cdffa2475632cf6303b9f86e0b0": "preview_OptiFine_1.12.1_HD_U_G5_pre1.jar",
|
||||||
|
"a9d21f084a485bc12fce8c9bea1660c6d4b08855": "OptiFine_1.12.2_HD_U_C5.jar",
|
||||||
|
"2159a0a754828d63446fca7b6f8fa57b710c6048": "OptiFine_1.12.2_HD_U_C6.jar",
|
||||||
|
"8ed8009fc82b43909190882927f335d5250a0e19": "OptiFine_1.12.2_HD_U_C7.jar",
|
||||||
|
"a55768a83db4ad0599f68d9bf3fa8041e2ae3852": "OptiFine_1.12.2_HD_U_C8.jar",
|
||||||
|
"e0236d21a2a164f2af1cfff8f9f325f53c9125f2": "OptiFine_1.12.2_HD_U_C9.jar",
|
||||||
|
"b91a0d82c24eef95be0af92993b14e94b842f166": "OptiFine_1.12.2_HD_U_D1.jar",
|
||||||
|
"04c28238506dc3561addb6efb87c9878d5b82ffe": "OptiFine_1.12.2_HD_U_D2.jar",
|
||||||
|
"b784000951d41f54d67685a0a275d9f61f810514": "OptiFine_1.12.2_HD_U_D3.jar",
|
||||||
|
"343f814410401ebdbb3314deb17c27cbab67bfac": "OptiFine_1.12.2_HD_U_E1.jar",
|
||||||
|
"5c87706b6d14061fed248506d8e3f95b7824ad18": "OptiFine_1.12.2_HD_U_E2.jar",
|
||||||
|
"e805d4be5c2a3343488c573145606e90bb13816d": "OptiFine_1.12.2_HD_U_E3.jar",
|
||||||
|
"0e8d45666e80829c9ab74527628dace9187fbfb5": "OptiFine_1.12.2_HD_U_F4.jar",
|
||||||
|
"84ada0f48bcfb16c37c49283627597bb74d935f6": "OptiFine_1.12.2_HD_U_F5.jar",
|
||||||
|
"ca3aea3a09ce215906c346fe190907fe0347b0c4": "OptiFine_1.12.2_HD_U_G5.jar",
|
||||||
|
"23a8be042f354ec97c99672906c3e61fdf54ca2c": "preview_OptiFine_1.12.2_HD_U_F6_pre1.jar",
|
||||||
|
"b71f993a364c7945081cc6cde9a20d29b4e43f1f": "preview_OptiFine_1.12.2_HD_U_G5_pre1.jar",
|
||||||
|
"ab2118b1ed23444d6decf081e0295e4c679af6c2": "preview_OptiFine_1.12.2_HD_U_G6_pre1.jar",
|
||||||
|
"25498de48dd9b7ed2ba5b83464950ad132e61c1f": "preview_OptiFine_1.14_HD_U_F1_pre6.jar",
|
||||||
|
"396ce7f0e22aae3543134baabd61ad547334c0aa": "OptiFine_1.14.2_HD_U_F1.jar",
|
||||||
|
"c8c6da3e2ae32d020d9001d4489aad702680f50f": "preview_OptiFine_1.14.2_HD_U_F1_pre15.jar",
|
||||||
|
"52420ef34128a8b15d7c8f5ed8f7ebc94b708efd": "OptiFine_1.14.3_HD_U_F1.jar",
|
||||||
|
"887d648f26f7ba17ea34c0c2dcff4096f7a226b1": "OptiFine_1.14.3_HD_U_F2.jar",
|
||||||
|
"ad8a8f60931f48e2873238d1460268bb4111f6c9": "OptiFine_1.14.4_HD_U_F2.jar",
|
||||||
|
"c9710081fb7012ddb56838ac54653ac2258a2404": "OptiFine_1.14.4_HD_U_F3.jar",
|
||||||
|
"c09f4d1ad66df8e3039334023422f1bc8cc211b8": "OptiFine_1.14.4_HD_U_F4.jar",
|
||||||
|
"3408258990309de773cc5a8ab71cb4137718a82b": "OptiFine_1.14.4_HD_U_F5.jar",
|
||||||
|
"117c01a5431244a8b6a3ac393374dac9624f9be6": "OptiFine_1.14.4_HD_U_G5.jar",
|
||||||
|
"ac602fe6a39d2fb4cadfe08e87af0b0daa2d8ac9": "preview_OptiFine_1.14.4_HD_U_G5_pre1.jar",
|
||||||
|
"630a32be9b711b5a479507159d5d2598189fed33": "OptiFine_1.15.2_HD_U_G6.jar",
|
||||||
|
"8339858b33056ec8975f6c0c9e1694a11f0d209a": "preview_OptiFine_1.15.2_HD_U_G1_pre1.jar",
|
||||||
|
"6cdf96d972b5f70c4575ff875a031c4931985686": "preview_OptiFine_1.15.2_HD_U_G1_pre10.jar",
|
||||||
|
"489d2284f2d50bd7c7cf4c216a766503d37e1f3c": "preview_OptiFine_1.15.2_HD_U_G1_pre12.jar",
|
||||||
|
"c66d412c4cb46c6f2c76c224dc45a62d30ee8b43": "preview_OptiFine_1.15.2_HD_U_G1_pre13.jar",
|
||||||
|
"582eb1d6470cc133db563bd1c2c8bc2068215806": "preview_OptiFine_1.15.2_HD_U_G1_pre18.jar",
|
||||||
|
"64d738862683c54a22e1856b2c13379599ca79ce": "preview_OptiFine_1.15.2_HD_U_G1_pre19.jar",
|
||||||
|
"3da9d466c847c50a73dc634dabc6a57f3b24e2f7": "preview_OptiFine_1.15.2_HD_U_G1_pre2.jar",
|
||||||
|
"e6583246a85dba26a478dd4925c298bb5b3f277a": "preview_OptiFine_1.15.2_HD_U_G1_pre20.jar",
|
||||||
|
"84c5d50e26aaa02733fa15a8c13ab845fbdea97f": "preview_OptiFine_1.15.2_HD_U_G1_pre21.jar",
|
||||||
|
"c55e449386eeca34df5b428d85927242fc841438": "preview_OptiFine_1.15.2_HD_U_G1_pre22.jar",
|
||||||
|
"459e17c77059671ef5daa9ab794400e8ae25095d": "preview_OptiFine_1.15.2_HD_U_G1_pre23.jar",
|
||||||
|
"2c6e4f61b1ceea92b76e0be40bc672e5b6d58efe": "preview_OptiFine_1.15.2_HD_U_G1_pre24.jar",
|
||||||
|
"4ea53e3d202239c5ffa2affa809e36998194f1bc": "preview_OptiFine_1.15.2_HD_U_G1_pre26.jar",
|
||||||
|
"29861ba50021b08200ef33f77c776f9f5b7135f7": "preview_OptiFine_1.15.2_HD_U_G1_pre27.jar",
|
||||||
|
"454dc0e03dab9d30a2ccce5823b7a0b309f5c859": "preview_OptiFine_1.15.2_HD_U_G1_pre28.jar",
|
||||||
|
"3c3623d75dc47722149edfb93fdca121c32e8987": "preview_OptiFine_1.15.2_HD_U_G1_pre29.jar",
|
||||||
|
"942e23fa0169c693fb1b645fae4db9217c6b5916": "preview_OptiFine_1.15.2_HD_U_G1_pre3.jar",
|
||||||
|
"bdbd92e5252c0afc0f22d6d5840f96762e5d01ea": "preview_OptiFine_1.15.2_HD_U_G1_pre30.jar",
|
||||||
|
"5daa9461c5762bdd647665f49d2e0ef0eb348910": "preview_OptiFine_1.15.2_HD_U_G1_pre4.jar",
|
||||||
|
"0029ab50050d19f4009f0a7d708982dde736f022": "preview_OptiFine_1.15.2_HD_U_G1_pre5.jar",
|
||||||
|
"646b279927cab6036e8f295efd5bda268acd85cf": "preview_OptiFine_1.15.2_HD_U_G1_pre7.jar",
|
||||||
|
"f11e79a7bc91a5fd985cb756445fc88e8c2dd31b": "preview_OptiFine_1.15.2_HD_U_G1_pre9.jar",
|
||||||
|
"1e9869b63a89a8ab81a58e1473dd2c2291fbd943": "preview_OptiFine_1.15.2_HD_U_G6_pre5.jar",
|
||||||
|
"87533b8ac0dfeb11241041f197f8f95c0ffa8c08": "OptiFine_1.16.1_HD_U_G2.jar",
|
||||||
|
"3e610c9bd89ae2a54cc06de6dfb1b00cd45e9895": "preview_OptiFine_1.16.1_HD_U_G2_pre1.jar",
|
||||||
|
"df817e1ab0e577be1dfb6c20a9b628d3d725c780": "preview_OptiFine_1.16.1_HD_U_G2_pre10.jar",
|
||||||
|
"dbca331e7abbe64d6aa360e6a93beec2935d24e3": "preview_OptiFine_1.16.1_HD_U_G2_pre11.jar",
|
||||||
|
"6fef880338cabe32443557762ca43fb36fe01f7c": "preview_OptiFine_1.16.1_HD_U_G2_pre12.jar",
|
||||||
|
"ea7bea6511f3b20aa672544d28dbc6d1a2ee8b41": "preview_OptiFine_1.16.1_HD_U_G2_pre13.jar",
|
||||||
|
"efdc788f59e1c1bcde3b64430322d8990ce7c7d6": "preview_OptiFine_1.16.1_HD_U_G2_pre14.jar",
|
||||||
|
"388100110b4dc8ef28eaa2f3a4ae2f33a8beb5ae": "preview_OptiFine_1.16.1_HD_U_G2_pre15.jar",
|
||||||
|
"63f5f097ce2e678d69767981b09b133ab8eac4f5": "preview_OptiFine_1.16.1_HD_U_G2_pre16.jar",
|
||||||
|
"c56031c3f6e5dcad536115e9f6a1fb5710b72391": "preview_OptiFine_1.16.1_HD_U_G2_pre2.jar",
|
||||||
|
"da269cdb109b6441ebed179a8d9f974590006cbb": "preview_OptiFine_1.16.1_HD_U_G2_pre3.jar",
|
||||||
|
"ad9b5d4e0bdd5697d4f6a6b9c30a64977bb8834e": "preview_OptiFine_1.16.1_HD_U_G2_pre4.jar",
|
||||||
|
"f6d5ea6cedff1f80bed298f9b456de2448b1f268": "preview_OptiFine_1.16.1_HD_U_G2_pre5.jar",
|
||||||
|
"f57a4269d404d4025de4d864b88510504e785e19": "preview_OptiFine_1.16.1_HD_U_G2_pre6.jar",
|
||||||
|
"28b46592e2f510a246a8bf62a2b12e808094167c": "preview_OptiFine_1.16.1_HD_U_G2_pre7.jar",
|
||||||
|
"26207daec6acc66250116e4f73295c9a031b491a": "preview_OptiFine_1.16.1_HD_U_G2_pre8.jar",
|
||||||
|
"6902e902866b765ff8e31716980c2067d491e004": "preview_OptiFine_1.16.1_HD_U_G2_pre9.jar",
|
||||||
|
"dde4274c696063496323731ad7b58e0f6d7265af": "OptiFine_1.16.2_HD_U_G3.jar",
|
||||||
|
"5b5627a814e8c95aa7ac27fa4cf2cc0b8bd4519b": "OptiFine_1.16.2_HD_U_G5.jar",
|
||||||
|
"5dafc10061020c519ba4abe4982a7dc80eae30f6": "preview_OptiFine_1.16.2_HD_U_G3_pre1.jar",
|
||||||
|
"0c0d9828984da34f9d5967027c244bb2c83a4396": "preview_OptiFine_1.16.2_HD_U_G3_pre2.jar",
|
||||||
|
"7c791e4348808132b8c7b59e6350ae2ee25a1918": "preview_OptiFine_1.16.2_HD_U_G3_pre3.jar",
|
||||||
|
"9a30a2cbc81095d38b4dc17e7d30a4b84e10e235": "preview_OptiFine_1.16.2_HD_U_G3_pre4.jar",
|
||||||
|
"ec1a4ce97e29c9ee2ac259d98e35bc386035a66d": "preview_OptiFine_1.16.2_HD_U_G3_pre5.jar",
|
||||||
|
"e03b0cdfbbcf01b1371b3e1090dee64e60a759d8": "preview_OptiFine_1.16.2_HD_U_G3_pre6.jar",
|
||||||
|
"40ae5fbb4e3724d6e5525d2688445c09ecfe5d39": "preview_OptiFine_1.16.2_HD_U_G3_pre7.jar",
|
||||||
|
"dc83d55f74722e1e6f503817e00e5ba2e6cb4abb": "OptiFine_1.16.3_HD_U_G3.jar",
|
||||||
|
"89d9472ee507946caa227e226524e5260ed944db": "OptiFine_1.16.3_HD_U_G4.jar",
|
||||||
|
"6a8f57ca84628da47b011e608ff449cde7ec13ed": "OptiFine_1.16.3_HD_U_G5.jar",
|
||||||
|
"f53bad69adaac9e523577dcb1c65b158802f3dee": "preview_OptiFine_1.16.3_HD_U_G3_pre2.jar",
|
||||||
|
"5b970eeae2ba07316b3e3a53da1d71de87c9f9f2": "preview_OptiFine_1.16.3_HD_U_G4_pre1.jar",
|
||||||
|
"599d9de6b656077b03fbebc9478924c548a6e9e0": "OptiFine_1.16.4_HD_U_G5.jar",
|
||||||
|
"7cce72db1f77c6178b549fa430e241eadb318f69": "OptiFine_1.16.4_HD_U_G6.jar",
|
||||||
|
"f49c042fa099907eafcbe22d7035d84f8b5715f1": "OptiFine_1.16.4_HD_U_G7.jar",
|
||||||
|
"f0b1eb59acdae57e10bb928046ee26012ef220ad": "preview_OptiFine_1.16.4_HD_U_G6_pre12.jar",
|
||||||
|
"ded7894eebda787b7bd5013aa8c66577f2ba03fc": "preview_OptiFine_1.16.4_HD_U_G7_pre1.jar",
|
||||||
|
"57cfcec3dd99b9f0950d0d6305bc95ecd8563212": "OptiFine_1.16.5_HD_U_G6.jar",
|
||||||
|
"706fb33784045d69e7ac5730426d813a39511dcd": "OptiFine_1.16.5_HD_U_G7.jar",
|
||||||
|
"137363842c5bfdebb72356a4079faeef3157eb3c": "OptiFine_1.16.5_HD_U_G8.jar",
|
||||||
|
"ad0f1577ce02a703185e46ee9e24fdeb65479fd5": "preview_OptiFine_1.16.5_HD_U_G7_pre10.jar",
|
||||||
|
"11770876367980da546c68bc95c4f794582907f2": "preview_OptiFine_1.16.5_HD_U_G7_pre11.jar",
|
||||||
|
"c5b32d2bad3bd54c31ddb29869a55fe44409cfe2": "preview_OptiFine_1.16.5_HD_U_G7_pre2.jar",
|
||||||
|
"9fc9cc09e72a3060d577f62f3535820056b0c2d4": "preview_OptiFine_1.16.5_HD_U_G7_pre4.jar",
|
||||||
|
"577fae32b60ac8d1b91e3fa645dc004d4a9e513e": "preview_OptiFine_1.16.5_HD_U_G7_pre5.jar",
|
||||||
|
"4bccf7f371ac83523796b4706569cc5077c46aea": "preview_OptiFine_1.16.5_HD_U_G7_pre6.jar",
|
||||||
|
"97b8d413a909354e2e0f42943cf292941dfe4c38": "preview_OptiFine_1.16.5_HD_U_G7_pre7.jar",
|
||||||
|
"9c48a804ee990e526000c7061bde9aa6f75d62a6": "preview_OptiFine_1.16.5_HD_U_G7_pre8.jar",
|
||||||
|
"9a9b69a52a4514f5d25c9f47127a822e93458fa3": "preview_OptiFine_1.16.5_HD_U_G7_pre9.jar",
|
||||||
|
"d16a450ec4205d02319480799008d8177ba05d69": "preview_OptiFine_1.16.5_HD_U_G8_pre1.jar",
|
||||||
|
"539c215aa0e8b8f696b325e89f3f9a3658ab32c8": "preview_OptiFine_1.16.5_HD_U_G8_pre10.jar",
|
||||||
|
"311ed81a27d24047b6ade33f46ac21c962897016": "preview_OptiFine_1.16.5_HD_U_G8_pre11.jar",
|
||||||
|
"4bc50f85809a299d30c3e3e73cfd87cad61cf7e6": "preview_OptiFine_1.16.5_HD_U_G8_pre12.jar",
|
||||||
|
"7de1b8e9f7cd6d7ca941d90121e50206aba80c68": "preview_OptiFine_1.16.5_HD_U_G8_pre13.jar",
|
||||||
|
"a4e021a75aab7ed1eb83ff7b45182d497aa930f2": "preview_OptiFine_1.16.5_HD_U_G8_pre14.jar",
|
||||||
|
"0ddcc4f47e10b2d671ebbf9147eb16cf8f1bb92a": "preview_OptiFine_1.16.5_HD_U_G8_pre2.jar",
|
||||||
|
"b8600be4fde6f8cc3c28173cc9bde6923956ff42": "preview_OptiFine_1.16.5_HD_U_G8_pre3.jar",
|
||||||
|
"d46b10098309929d9a6583323f059e65ba40a5e5": "preview_OptiFine_1.16.5_HD_U_G8_pre4.jar",
|
||||||
|
"e835424b36fdae3d5f46c6bf096852848127f1e7": "preview_OptiFine_1.16.5_HD_U_G8_pre5.jar",
|
||||||
|
"5a84983221331597f58e9636d41f1fb0c9e3de61": "preview_OptiFine_1.16.5_HD_U_G8_pre6.jar",
|
||||||
|
"d03ce2209d787539e5e51f80a7cbffc69a49ce9f": "preview_OptiFine_1.16.5_HD_U_G8_pre7.jar",
|
||||||
|
"1c646dc058aa32898917589858d900407883ba3f": "preview_OptiFine_1.16.5_HD_U_G8_pre8.jar",
|
||||||
|
"9bf369aa609e5612247473326dc298e6e6c9fecf": "preview_OptiFine_1.16.5_HD_U_G8_pre9.jar",
|
||||||
|
"b88b05278fbbf400cb5ec0cc26e0c5b7306e0c1e": "preview_OptiFine_1.17_HD_U_G9_pre16.jar",
|
||||||
|
"a6beac3091d17a4ba420116c75c89faeaee48539": "preview_OptiFine_1.17_HD_U_G9_pre17.jar",
|
||||||
|
"2839c5e74f64500561ee3e8605c51d9f06727c22": "preview_OptiFine_1.17_HD_U_G9_pre18.jar",
|
||||||
|
"455243ff55177189fff140ba7f4c4777cc977ef6": "preview_OptiFine_1.17_HD_U_G9_pre19.jar",
|
||||||
|
"bcc390e34bd529a86e6ae0e25d50417f46ba482f": "preview_OptiFine_1.17_HD_U_G9_pre20.jar",
|
||||||
|
"d30c23d745df54fd6ea2374e9c0b4392f0a78199": "preview_OptiFine_1.17_HD_U_G9_pre21.jar",
|
||||||
|
"075e7f8473b6785c3c6bbeeb41a3728f6ff3c3ba": "preview_OptiFine_1.17_HD_U_G9_pre22.jar",
|
||||||
|
"2ffaee36c717ae918cc93661df739740636900c9": "preview_OptiFine_1.17_HD_U_G9_pre23.jar",
|
||||||
|
"4385493e7ce4c6f4a3945f1d96246bce0b151c7e": "preview_OptiFine_1.17_HD_U_G9_pre24.jar",
|
||||||
|
"bcc33e67f134861eb30b1f0b9a829183c8afdebf": "preview_OptiFine_1.17_HD_U_G9_pre25.jar",
|
||||||
|
"6a8e34605cc828091027d9f011b804d916808af4": "preview_OptiFine_1.17_HD_U_G9_pre26.jar",
|
||||||
|
"4714bdceaefc15e0af9d5c72de8c05cf3051d760": "OptiFine_1.17.1_HD_U_G9.jar",
|
||||||
|
"cc64084e73d6423baf7ccbdd9f3760dd56f2fce5": "OptiFine_1.17.1_HD_U_H1.jar",
|
||||||
|
"1ee73bd882385a7abb9896b9469586741a6850a8": "preview_OptiFine_1.17.1_HD_U_G9_pre26.jar",
|
||||||
|
"537c1fbee9ebe25b49a8e6fb93db162d217f1c83": "preview_OptiFine_1.17.1_HD_U_G9_pre27.jar",
|
||||||
|
"68e1124f4b0376773d8d581da78f9bb6fc76486e": "preview_OptiFine_1.17.1_HD_U_G9_pre28.jar",
|
||||||
|
"3f80a562b39439831491c650c65ecb762e70d5f7": "preview_OptiFine_1.17.1_HD_U_G9_pre29.jar",
|
||||||
|
"9751c69568a61ce5b2a602b4dcf77c1cea57c709": "preview_OptiFine_1.17.1_HD_U_G9_pre30.jar",
|
||||||
|
"162fa1b4a0d5b89dad6030b5fd5903a3f24d39c7": "preview_OptiFine_1.17.1_HD_U_G9_pre31.jar",
|
||||||
|
"c4f3a33d892948927cecfaa60b284217325557c5": "preview_OptiFine_1.17.1_HD_U_G9_pre32.jar",
|
||||||
|
"12dbbc8ccd8dc02806768fb3fbe4a2d8c7c11301": "preview_OptiFine_1.17.1_HD_U_G9_pre33.jar",
|
||||||
|
"f74d1dfcb24c43e633076c63dd4492b29fca14b3": "preview_OptiFine_1.17.1_HD_U_G9_pre34.jar",
|
||||||
|
"42e55681fb106475ef13d5c5ef7113fb631392d4": "preview_OptiFine_1.17.1_HD_U_G9_pre35.jar",
|
||||||
|
"245ddb68349f5f81d067f4d9402d62db3d439d50": "preview_OptiFine_1.17.1_HD_U_H1_pre1.jar",
|
||||||
|
"0ac033f5ba4089311af55172281e73df143b9ac4": "preview_OptiFine_1.17.1_HD_U_H1_pre2.jar",
|
||||||
|
"68a3727bcdb0eac0986ff4e883d93fef406eb1c3": "preview_OptiFine_1.17.1_HD_U_H1_pre3.jar",
|
||||||
|
"a6534877558f0438bda604dc43093d61c6de88ae": "preview_OptiFine_1.17.1_HD_U_H1_pre4.jar",
|
||||||
|
"3e18db17b8695feb0a188ecdcb81b561d9d7030c": "preview_OptiFine_1.17.1_HD_U_H1_pre5.jar",
|
||||||
|
"c2e0c4391a671cd06931f7b6e965085c04c58762": "preview_OptiFine_1.17.1_HD_U_H1_pre6.jar",
|
||||||
|
"1ffb7325df5bf01b1d99bbbed8006a477b861394": "preview_OptiFine_1.17.1_HD_U_H1_pre7.jar",
|
||||||
|
"f2fa727e67b4795ddea3cc37cc5ced42e9c3b0c5": "preview_OptiFine_1.17.1_HD_U_H1_pre8.jar",
|
||||||
|
"aee167aff9937a068d514c85e3f8c766db99ed43": "preview_OptiFine_1.17.1_HD_U_H1_pre9.jar",
|
||||||
|
"59709e09632c80ab80ffcc4b5bf380d073bf467f": "preview_OptiFine_1.17.1_HD_U_H2_pre1.jar",
|
||||||
|
"52629bc5319ec203edd42de1776cb8d67a0e6b1b": "OptiFine_1.18_HD_U_H3.jar",
|
||||||
|
"e5077b4be03956118613162b5dbcf90406b27747": "preview_OptiFine_1.18_HD_U_H3_pre7.jar",
|
||||||
|
"326c160481cc849bccb821939992c101a8fe163b": "OptiFine_1.18.1_HD_U_H4.jar",
|
||||||
|
"1679654fdf49fd1216b090d51d3d8ec906094619": "OptiFine_1.18.1_HD_U_H5.jar",
|
||||||
|
"c86534ee821a78efc741c9cb407eec76625e1bab": "OptiFine_1.18.1_HD_U_H6.jar",
|
||||||
|
"34c98382131efa1394cff06528238dc44d255794": "preview_OptiFine_1.18.1_HD_U_H4_pre1.jar",
|
||||||
|
"d6cd0a2d0243ecad107220bff639eb46277762ea": "preview_OptiFine_1.18.1_HD_U_H5_pre1.jar",
|
||||||
|
"e24d766864f9238b94be5b3ad65608d7eb521fad": "preview_OptiFine_1.18.1_HD_U_H5_pre2.jar",
|
||||||
|
"bc1b87a6379acf5a5dca2a56196080ace49e4864": "preview_OptiFine_1.18.1_HD_U_H5_pre3.jar",
|
||||||
|
"555a6b8e420bd63a04d9f338d61f3333b4ccf5d9": "preview_OptiFine_1.18.1_HD_U_H5_pre4.jar",
|
||||||
|
"1d02694393f10992cbbd11a802568b0890b4dc81": "preview_OptiFine_1.18.1_HD_U_H5_pre5.jar",
|
||||||
|
"e3a22adc6931dcd7513f26afa1adecd62a35641b": "preview_OptiFine_1.18.1_HD_U_H5_pre6.jar",
|
||||||
|
"445a8cb8a1d565d8a1fabc0ba984c5936edbf561": "OptiFine_1.18.2_HD_U_H6.jar",
|
||||||
|
"8d83d4d5e325887e000a462029d2bf7a6e77eebc": "OptiFine_1.18.2_HD_U_H7.jar",
|
||||||
|
"2a461188167c1da6b1cfd520d85a656f45c74d70": "OptiFine_1.18.2_HD_U_H9.jar",
|
||||||
|
"e591777f272df533b62260a6dbe0e6cde62066f6": "preview_OptiFine_1.18.2_HD_U_H6_pre1.jar",
|
||||||
|
"f7c727c99e7f58ef9b86cc96fb894f628391016c": "preview_OptiFine_1.18.2_HD_U_H7_pre1.jar",
|
||||||
|
"cb51529f94e0eff5b9da92c8f70b1d498662a115": "preview_OptiFine_1.18.2_HD_U_H7_pre2.jar",
|
||||||
|
"ceea3c6612d2ec36c6ef1ca4a9355a141df9089f": "preview_OptiFine_1.18.2_HD_U_H7_pre3.jar",
|
||||||
|
"596c3a399889c3e2ef1d8fee994e8cf5a91e457e": "preview_OptiFine_1.18.2_HD_U_H8_pre1.jar",
|
||||||
|
"85f545aeb9d232ae970b0efa24e833f9c5d0fe33": "preview_OptiFine_1.18.2_HD_U_H9_pre1.jar",
|
||||||
|
"b9bbabb8f31f2b04ca1a1a8645df1be701f705bd": "preview_OptiFine_1.18.2_HD_U_H9_pre2.jar",
|
||||||
|
"c2bf213b4f60b6a29e402e3eaf219a4c85a5d1e6": "preview_OptiFine_1.18.2_HD_U_H9_pre3.jar",
|
||||||
|
"64c8c35313d25a64a8a8677cb851a2c83556ddc8": "OptiFine_1.19_HD_U_H8.jar",
|
||||||
|
"c668eaf9b6ce4e64f26a29fb27e830229ab4bef3": "OptiFine_1.19_HD_U_H9.jar",
|
||||||
|
"cda9130e0d36f0d6e06950ab393a8929b502a440": "preview_OptiFine_1.19_HD_U_H8_pre1.jar",
|
||||||
|
"cd1ae81f544672df776dc4426269771d2e82d0b2": "preview_OptiFine_1.19_HD_U_H8_pre10.jar",
|
||||||
|
"cb3ad2a9b4c23675ca569058f55dd174eed67a38": "preview_OptiFine_1.19_HD_U_H8_pre2.jar",
|
||||||
|
"2f7139ea0888ed18006e3a39b7475e88a3fd545d": "preview_OptiFine_1.19_HD_U_H8_pre3.jar",
|
||||||
|
"85cd70bb714e65935abf351811889a47a648bb96": "preview_OptiFine_1.19_HD_U_H8_pre4.jar",
|
||||||
|
"c65cbae4c1cfb5b9a5a573e4b83424df2d81b172": "preview_OptiFine_1.19_HD_U_H8_pre5.jar",
|
||||||
|
"10cd57890ebf449f5c258cff1c60d8dcefcc6cf6": "preview_OptiFine_1.19_HD_U_H8_pre6.jar",
|
||||||
|
"eb03e60c2fa9904a47eec1ef4a2c8804ee6cc0b8": "preview_OptiFine_1.19_HD_U_H8_pre7.jar",
|
||||||
|
"40d0b514168161fdefc91594f0d3f774f831d7de": "preview_OptiFine_1.19_HD_U_H8_pre8.jar",
|
||||||
|
"8e5bedd1c1a3641caad0743c4629db51c11f8feb": "preview_OptiFine_1.19_HD_U_H9_pre1.jar",
|
||||||
|
"7745216a810f0d617ed17a520fda44e12456492f": "preview_OptiFine_1.19_HD_U_H9_pre2.jar",
|
||||||
|
"6d6ed920eb99836e76549a7803af85881fcdee34": "preview_OptiFine_1.19_HD_U_H9_pre3.jar",
|
||||||
|
"7604e63ca74876b4e8ea9c3a36dbe80111c776b1": "preview_OptiFine_1.19_HD_U_H9_pre4.jar",
|
||||||
|
"b42dcce86c88ad4bcfa52a9d297afa800477aa78": "OptiFine_1.19.1_HD_U_H9.jar",
|
||||||
|
"648427a02940b3c53b3678cd5df1ff6997bd1e6c": "preview_OptiFine_1.19.1_HD_U_H9_pre1.jar",
|
||||||
|
"7cc221a6df6831b62c3b676b5f958e82a4487fd8": "OptiFine_1.19.2_HD_U_H9.jar",
|
||||||
|
"f304c56c7ab9119ce4269f2b019cd4668f48376d": "OptiFine_1.19.2_HD_U_I1.jar",
|
||||||
|
"708c1ecc148a0bd7d341e8f5e005e670903650f7": "OptiFine_1.19.2_HD_U_I2.jar",
|
||||||
|
"e0e924990bd12cc499fc89439f0b2c50b6e147fa": "preview_OptiFine_1.19.2_HD_U_I1_pre1.jar",
|
||||||
|
"465b229481c0a285195a168bf6581549a5cd7373": "preview_OptiFine_1.19.2_HD_U_I1_pre2.jar",
|
||||||
|
"af4398d0ce0628bcc0204e61c157e3c8951b9ad5": "preview_OptiFine_1.19.2_HD_U_I1_pre3.jar",
|
||||||
|
"35ef18f953bbea9a4cba6e14d0731d56f888114f": "preview_OptiFine_1.19.2_HD_U_I1_pre4.jar",
|
||||||
|
"b24d8725a8d06e1c190d1d2b3bc51c899f74b36d": "OptiFine_1.19.3_HD_U_I3.jar",
|
||||||
|
"f5ce615d9886e377079fd13cc4700a51d5a9c7b6": "preview_OptiFine_1.19.3_HD_U_I2_pre1.jar",
|
||||||
|
"10e6d97ea2c97cf0575a7c587fb11e1ddb73aa71": "preview_OptiFine_1.19.3_HD_U_I2_pre2.jar",
|
||||||
|
"89718cd608225d7c23f7e180d011daa4a47ce6bd": "preview_OptiFine_1.19.3_HD_U_I2_pre3.jar",
|
||||||
|
"204baf0fd59432054aebd2f83c83fe15fdd3e611": "preview_OptiFine_1.19.3_HD_U_I2_pre4.jar",
|
||||||
|
"90a52b3adc94a1b9a70f03f4c4ea14dfdf3424d8": "preview_OptiFine_1.19.3_HD_U_I2_pre5.jar",
|
||||||
|
"050d787936cc239ea8db0aa250d2ed72a44fa71d": "OptiFine_1.19.4_HD_U_I3.jar",
|
||||||
|
"253e9d29c6826c134fbdeea074d1d91c3410225c": "OptiFine_1.19.4_HD_U_I4.jar",
|
||||||
|
"068b998d6c5db5b3bb7ad6a0a7d0c6aefc4dc191": "preview_OptiFine_1.19.4_HD_U_I3_pre3.jar",
|
||||||
|
"a8b9156811c4745dbd612ebbb1df6f93d2fa734a": "preview_OptiFine_1.19.4_HD_U_I3_pre4.jar",
|
||||||
|
"6f2793e6236a27c06a74e8a1876ea6b29be038a7": "preview_OptiFine_1.19.4_HD_U_I3_pre5.jar",
|
||||||
|
"9ad82ef9f32fb5a0e7e7e0c7e8906c9f319a9705": "preview_OptiFine_1.19.4_HD_U_I3_pre6.jar",
|
||||||
|
"cf02ee8b5cf6922fbc28d6ffc8183949fff55d49": "preview_OptiFine_1.19.4_HD_U_I3_pre7.jar",
|
||||||
|
"702e0e9987209f66a5b4f825e7ac658fd49dd4b1": "preview_OptiFine_1.19.4_HD_U_I3_pre8.jar",
|
||||||
|
"04c8eaeadf24c42929500812a8f3f5fe634f0d1f": "preview_OptiFine_1.19.4_HD_U_I3_pre9.jar",
|
||||||
|
"968784e051c2c44f10a4ab448c979572977969c0": "preview_OptiFine_1.19.4_HD_U_I4_pre1.jar",
|
||||||
|
"abe4b1dbda7d95eb47953ef8aa11ed8ed1d8e238": "preview_OptiFine_1.20_HD_U_I5_pre3.jar",
|
||||||
|
"6612ce97d846018126f91cdbae23f0eff6bd2bab": "preview_OptiFine_1.20_HD_U_I5_pre4.jar",
|
||||||
|
"f37d62b6a071f6cd3d6bdfa378b56f7f5b9ec7c6": "preview_OptiFine_1.20_HD_U_I5_pre5.jar",
|
||||||
|
"c44bd276edd10fa910d929a4e7f6b8c7ffe6c23f": "OptiFine_1.20.1_HD_U_I5.jar",
|
||||||
|
"227914ab1037762eae44a2e66a568b87d7a02365": "OptiFine_1.20.1_HD_U_I6.jar",
|
||||||
|
"7484cf60bd8e019c40fa448daa294bd31f52962b": "preview_OptiFine_1.20.1_HD_U_I5_pre4.jar",
|
||||||
|
"953b1b4f15f56329bc4ade851846ef004ebbd5d0": "preview_OptiFine_1.20.1_HD_U_I5_pre5.jar",
|
||||||
|
"ebbdb3076f8291d7f8e10cbec3b1d3c49a0a701d": "preview_OptiFine_1.20.1_HD_U_I5_pre6.jar",
|
||||||
|
"b831d59eeb63122893f87a62ec3e5b3f1cc5586a": "preview_OptiFine_1.20.1_HD_U_I5_pre7.jar",
|
||||||
|
"dc93d991b07b2c5c6d2cd50a553599900c256264": "preview_OptiFine_1.20.1_HD_U_I5_pre8.jar",
|
||||||
|
"040a73427541170bccf162c04f4129b3909b8da1": "preview_OptiFine_1.20.1_HD_U_I5_pre9.jar",
|
||||||
|
"9f5fd75ede7770ad35383443b0a203f026cef5db": "preview_OptiFine_1.20.1_HD_U_I6_pre1.jar",
|
||||||
|
"85d5566b440036b926c5dd306108e48e7fb9b6e8": "preview_OptiFine_1.20.1_HD_U_I6_pre2.jar",
|
||||||
|
"d09c110358117336472414720bf961a581690dc5": "preview_OptiFine_1.20.1_HD_U_I6_pre3.jar",
|
||||||
|
"3365577f5161f9a1bbfefb15675bb5ece27600e4": "preview_OptiFine_1.20.1_HD_U_I6_pre4.jar",
|
||||||
|
"f317c701ae8c533fc34809dbce914bcced4e9a03": "preview_OptiFine_1.20.1_HD_U_I6_pre5.jar",
|
||||||
|
"445b32b14a2c2802d5a0832a708712d2fabafbc2": "preview_OptiFine_1.20.1_HD_U_I6_pre6.jar",
|
||||||
|
"9ea6b1389e88b81797f54b9d8d1e870d3fe8532c": "preview_OptiFine_1.20.2_HD_U_I7_pre1.jar",
|
||||||
|
"f2475e8d5746477d1d2972cd5aae62a5d9c04264": "OptiFine_1.20.4_HD_U_I7.jar",
|
||||||
|
"fec28a2fa152744bc2b47b3c5db3217974aa57ee": "preview_OptiFine_1.20.4_HD_U_I7_pre2.jar",
|
||||||
|
"4068365a57f4b154f4ebbc670894dc9038cf3819": "preview_OptiFine_1.20.4_HD_U_I7_pre3.jar",
|
||||||
|
"2481e0bed7610bfdfe26dea5a6bd8f01537c4ea8": "preview_OptiFine_1.20.4_HD_U_I7_pre4.jar",
|
||||||
|
"150990ba068cfb55bbf9e525c5ab84db0b8903e1": "preview_OptiFine_1.20.4_HD_U_I7_pre5.jar",
|
||||||
|
"fcf0f0f278d1901e4341d5ec8022bede03572430": "preview_OptiFine_1.20.4_HD_U_I7_pre6.jar",
|
||||||
|
"1c3395efa928758505b808291162a2514523b399": "preview_OptiFine_1.20.4_HD_U_I7_pre7.jar",
|
||||||
|
"4bcfec24e5d917ee96e0de6ef095bfc08782217b": "preview_OptiFine_1.20.4_HD_U_I8_pre1.jar",
|
||||||
|
"c931df21309800f1d1ece59b318e6b3e39c98176": "preview_OptiFine_1.20.4_HD_U_I8_pre2.jar",
|
||||||
|
"83f5ad147536405d86bf4ee47a7f7970e1fa8329": "preview_OptiFine_1.20.4_HD_U_I8_pre3.jar",
|
||||||
|
"7c6669319db18c9622d896da2a061479be88acf5": "preview_OptiFine_1.20.4_HD_U_I8_pre4.jar",
|
||||||
|
"bda7bbdd5e2d8c73148372e8c3b34d7c2485a4e8": "preview_OptiFine_1.20.6_HD_U_J1_pre18.jar",
|
||||||
|
"24a20f949a719480523669669a4e5e7339df6186": "OptiFine_1.21.1_HD_U_J1.jar",
|
||||||
|
"6bc74af8f733864539404a3f087aeb6f0cadc6b1": "preview_OptiFine_1.21.1_HD_U_J1_pre10.jar",
|
||||||
|
"4813a6cde6b0f5b20223d486ba7adf0816236a77": "preview_OptiFine_1.21.1_HD_U_J1_pre11.jar",
|
||||||
|
"c99ea98d8537f99b7470f1bcfa81c7ce405fd97e": "preview_OptiFine_1.21.1_HD_U_J1_pre12.jar",
|
||||||
|
"f2f55e6d61a4b90bdaa31eb520f5af78f8a1833b": "preview_OptiFine_1.21.1_HD_U_J1_pre13.jar",
|
||||||
|
"53a15b75ea9d20b644b0d3e9c7280ba172ade053": "preview_OptiFine_1.21.1_HD_U_J1_pre14.jar",
|
||||||
|
"da5575e1138fc2a4c28779cfc5e7d260253ccbdb": "preview_OptiFine_1.21.1_HD_U_J1_pre15.jar",
|
||||||
|
"0930876341beadf7014f57e9ebdd44be445dacbe": "OptiFine_1.21.3_HD_U_J2.jar",
|
||||||
|
"350f63ec3e59d21227f803d4078883884e482660": "preview_OptiFine_1.21.3_HD_U_J2_pre10.jar",
|
||||||
|
"2c48a4210acd25082c220f9601f17d1cc7769098": "preview_OptiFine_1.21.3_HD_U_J2_pre11.jar",
|
||||||
|
"8f0a097b1f7c9d065396bac9230eab62412a8b54": "preview_OptiFine_1.21.3_HD_U_J2_pre12.jar",
|
||||||
|
"f97df5638fcda7f4380d9284b329569d4e1554aa": "preview_OptiFine_1.21.3_HD_U_J2_pre8.jar",
|
||||||
|
"77df50552deea51687592b60c6d24561ee11aa74": "preview_OptiFine_1.21.3_HD_U_J2_pre9.jar",
|
||||||
|
"bcc6a7a140320566a985b1499a59fcb085255d14": "OptiFine_1.21.4_HD_U_J3.jar",
|
||||||
|
"e7bff4575b7311e11d7111506e855b4ad910481f": "preview_OptiFine_1.21.4_HD_U_J3_pre10.jar",
|
||||||
|
"52b2b6defdb8d1c189afb42125079f1b76ff72e2": "preview_OptiFine_1.21.4_HD_U_J3_pre11.jar",
|
||||||
|
"708f70aa5f70919a40d02ba75fc30d2d60c8e7cd": "preview_OptiFine_1.21.4_HD_U_J3_pre12.jar",
|
||||||
|
"86b796325d03d4571809a155c54cf6cba7c7482b": "preview_OptiFine_1.21.4_HD_U_J3_pre13.jar",
|
||||||
|
"618719a6a69eb674ea50c82cffe3d4e3c2f67abf": "preview_OptiFine_1.21.4_HD_U_J3_pre14.jar",
|
||||||
|
"98dd84b0581fcf7a27aa96238acb615b5b719825": "preview_OptiFine_1.21.4_HD_U_J3_pre15.jar",
|
||||||
|
"5c8573ae921082a069a9e7269500178f0c580c97": "preview_OptiFine_1.21.4_HD_U_J3_pre4.jar",
|
||||||
|
"17d51e1bfc94dde95368ab91aa0bb56e89c706bf": "preview_OptiFine_1.21.4_HD_U_J3_pre5.jar",
|
||||||
|
"1a4311606ac94d682800714793ea887c3276b18d": "preview_OptiFine_1.21.4_HD_U_J3_pre6.jar",
|
||||||
|
"12bf1a1b5607b5c62405a8c6ab4e1bd02bef2c8d": "preview_OptiFine_1.21.4_HD_U_J3_pre7.jar",
|
||||||
|
"f1f56403dc575fd975a000bfb133060285cacd6f": "preview_OptiFine_1.21.4_HD_U_J3_pre8.jar",
|
||||||
|
"9584de0e8204f5c855b60741d58af967dfc599a8": "preview_OptiFine_1.21.4_HD_U_J3_pre9.jar",
|
||||||
|
"0b97631e166ace9346744de33b7772df7bf5fbeb": "preview_OptiFine_1.21.4_HD_U_J4_pre1.jar",
|
||||||
|
"a776ec6c072529d4b731e0e6929a8aee56d04e76": "preview_OptiFine_1.21.4_HD_U_J4_pre2.jar",
|
||||||
|
"2a3fdfcbfc9c572b22c7d15c6129b8ea58ea1712": "preview_OptiFine_1.21.8_HD_U_J6_pre13.jar",
|
||||||
|
"ba7ca56c9b33d2fc7f7d22e20ce2765e4d257299": "preview_OptiFine_1.21.8_HD_U_J6_pre14.jar",
|
||||||
|
"097d3acd315b0682a4565ab9cbb4cdc1cc17d81f": "preview_OptiFine_1.21.8_HD_U_J6_pre15.jar",
|
||||||
|
"d7effca0de34c9442f06776848679a684f1f166a": "preview_OptiFine_1.21.8_HD_U_J6_pre16.jar",
|
||||||
|
"696ed52cdfd0ac2eafab8e98575d146b400de530": "preview_OptiFine_1.21.10_HD_U_J7_pre10.jar",
|
||||||
|
"be7bc81f0c9ce15316f76a059b0a690f62c03a5d": "preview_OptiFine_1.21.10_HD_U_J7_pre11.jar",
|
||||||
|
"731e698abe94bbd90cda628f80b4ce6ac5af8188": "preview_OptiFine_1.21.10_HD_U_J7_pre6.jar",
|
||||||
|
"63f189a4b7ff5b53e5bc56391f5274eab8555def": "preview_OptiFine_1.21.10_HD_U_J7_pre7.jar",
|
||||||
|
"7ccfc0085ccdef3f4ec21918a059ddd05171711a": "preview_OptiFine_1.21.10_HD_U_J7_pre8.jar",
|
||||||
|
"aad53ad3346944a12ed088ffbba98cf9eccc474c": "preview_OptiFine_1.21.10_HD_U_J7_pre9.jar",
|
||||||
|
"2800efeb56565f23494d372e7edac29333113e11": "OptiFine_1.21.11_HD_U_J8.jar",
|
||||||
|
"cee35b83c75da33dc07ffbb344386cae5cdc5c5b": "OptiFine_1.21.11_HD_U_J9.jar",
|
||||||
|
"687046282c370e690ec4b4aa6d90a6b42ada3ee1": "preview_OptiFine_1.21.11_HD_U_J8_pre10.jar",
|
||||||
|
"c09b05637610072bc33023d1c901e2726b7d16ce": "preview_OptiFine_1.21.11_HD_U_J8_pre11.jar",
|
||||||
|
"88682b40f08f462c4daae8e6b25ea99b1ed5cd14": "preview_OptiFine_1.21.11_HD_U_J8_pre12.jar",
|
||||||
|
"1c69de725c249d487df676470c71a7c05ece943c": "preview_OptiFine_1.21.11_HD_U_J8_pre3.jar",
|
||||||
|
"921b68e014539d75b77a47ca2117fc9e09ace4ed": "preview_OptiFine_1.21.11_HD_U_J8_pre4.jar",
|
||||||
|
"2fee496a35eeebf39fbb43017b12d752f5c37dee": "preview_OptiFine_1.21.11_HD_U_J8_pre5.jar",
|
||||||
|
"e5b5da810d43c02dccedfd99f83ae8ad63e49966": "preview_OptiFine_1.21.11_HD_U_J8_pre6.jar",
|
||||||
|
"8309638bab4d99258354b4d13c3cd82ff7c9645b": "preview_OptiFine_1.21.11_HD_U_J8_pre7.jar",
|
||||||
|
"b3d208ec7b5015842fcc77b3399b04b24e0b54cb": "preview_OptiFine_1.21.11_HD_U_J8_pre8.jar",
|
||||||
|
"c4ac7401bb5f668e4e92121501d1537cdbe7343c": "preview_OptiFine_1.21.11_HD_U_J8_pre9.jar",
|
||||||
|
"fd96031b5fc4c41ad71581eea53eb122022fff5b": "preview_OptiFine_1.21.11_HD_U_J9_pre1.jar",
|
||||||
|
"a159a217aba02cd7897394a51bd346c3b658b9f9": "preview_OptiFine_1.21.11_HD_U_J9_pre2.jar",
|
||||||
|
"2a784437076b539ea1a3c1a37ec98ff21bc3952c": "preview_OptiFine_1.21.11_HD_U_J9_pre3.jar",
|
||||||
|
"ee32ce4b406e290a0e99685afd09dc44cad03ddd": "preview_OptiFine_1.21.11_HD_U_J9_pre4.jar"
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
<Using Include="System.Collections.Generic" />
|
<Using Include="System.Collections.Generic" />
|
||||||
<Using Include="System.Collections.Concurrent" />
|
<Using Include="System.Collections.Concurrent" />
|
||||||
<Using Include="System.Text" />
|
<Using Include="System.Text" />
|
||||||
|
<Using Include="System.Text.RegularExpressions" />
|
||||||
<Using Include="System.Net" />
|
<Using Include="System.Net" />
|
||||||
<Using Include="System.Runtime.CompilerServices" />
|
<Using Include="System.Runtime.CompilerServices" />
|
||||||
<Using Include="System.Runtime.InteropServices" />
|
<Using Include="System.Runtime.InteropServices" />
|
||||||
@@ -58,6 +59,7 @@
|
|||||||
<EmbeddedResource Include="Launch\JavaWrapper.jar" LogicalName="Launch\JavaWrapper.jar" />
|
<EmbeddedResource Include="Launch\JavaWrapper.jar" LogicalName="Launch\JavaWrapper.jar" />
|
||||||
<EmbeddedResource Include="Launch\LwjglUnsafeAgent.jar" LogicalName="Launch\LwjglUnsafeAgent.jar" />
|
<EmbeddedResource Include="Launch\LwjglUnsafeAgent.jar" LogicalName="Launch\LwjglUnsafeAgent.jar" />
|
||||||
<EmbeddedResource Include="Resource\WikiEntries.txt" LogicalName="Resource\WikiEntries.txt" />
|
<EmbeddedResource Include="Resource\WikiEntries.txt" LogicalName="Resource\WikiEntries.txt" />
|
||||||
|
<EmbeddedResource Include="Minecraft\OptiFineHashes.json" LogicalName="Minecraft\OptiFineHashes.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.VisualBasic" />
|
<Reference Include="Microsoft.VisualBasic" />
|
||||||
|
|||||||
+3106
-476
File diff suppressed because one or more lines are too long
@@ -9,7 +9,10 @@ Public Class Application
|
|||||||
'核心初始化
|
'核心初始化
|
||||||
MeloongCore.Main.Init("PCL")
|
MeloongCore.Main.Init("PCL")
|
||||||
MeloongCore.Wpf.Main.Init()
|
MeloongCore.Wpf.Main.Init()
|
||||||
Logger.Instance = New PclLogger With {.logFolder = Paths.BaseThenName, .MinLevel = If(ModeDebug, LogLevel.Trace, LogLevel.Info)}
|
If Not (e.Args.Contains("--update") OrElse e.Args.Contains("--gpu") OrElse e.Args.Contains("--memory")) Then '若是通过命令行调用,则不检查单例、不轮换日志(#9137)
|
||||||
|
WaitingMutex(e)
|
||||||
|
Logger.Instance = New PclLogger With {.logFolder = Paths.BaseThenName, .MinLevel = If(ModeDebug, LogLevel.Trace, LogLevel.Info)}
|
||||||
|
End If
|
||||||
'提升主线程优先级
|
'提升主线程优先级
|
||||||
Thread.CurrentThread.Priority = ThreadPriority.Highest
|
Thread.CurrentThread.Priority = ThreadPriority.Highest
|
||||||
'执行开发版测试
|
'执行开发版测试
|
||||||
@@ -47,7 +50,7 @@ Public Class Application
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Environment.Exit(ProcessReturnValues.Fail)
|
Environment.Exit(ProcessReturnValues.Fail)
|
||||||
End Try
|
End Try
|
||||||
ElseIf e.Args(0).StartsWithF("--memory") Then
|
ElseIf e.Args(0) = "--memory" Then
|
||||||
'内存优化
|
'内存优化
|
||||||
Dim Ram = My.Computer.Info.AvailablePhysicalMemory
|
Dim Ram = My.Computer.Info.AvailablePhysicalMemory
|
||||||
Try
|
Try
|
||||||
@@ -70,7 +73,7 @@ Public Class Application
|
|||||||
CheckPermissionWithException(Paths.Base & "PCL\")
|
CheckPermissionWithException(Paths.Base & "PCL\")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
MsgBox($"PCL 没有对当前文件夹的权限({Paths.Base}PCL\),请尝试:" & vbCrLf &
|
MsgBox($"PCL 没有对当前文件夹的权限({Paths.Base}PCL\),请尝试:" & vbCrLf &
|
||||||
"1. 将 PCL 移动到其他文件夹" & If(Paths.Base.StartsWithF("C:", True), ",例如 C 盘和桌面以外的其他位置。", "。") & vbCrLf &
|
"1. 将 PCL 移动到其他文件夹" & If(PathUtils.GetDiskName(Paths.Base) = "C"c, ",例如 C 盘和桌面以外的其他位置。", "。") & vbCrLf &
|
||||||
"2. 删除当前目录中的 PCL 文件夹,然后再试。" & vbCrLf &
|
"2. 删除当前目录中的 PCL 文件夹,然后再试。" & vbCrLf &
|
||||||
"3. 右键 PCL 选择属性,打开 兼容性 中的 以管理员身份运行此程序。",
|
"3. 右键 PCL 选择属性,打开 兼容性 中的 以管理员身份运行此程序。",
|
||||||
MsgBoxStyle.Critical, "运行环境错误")
|
MsgBoxStyle.Critical, "运行环境错误")
|
||||||
@@ -81,7 +84,7 @@ RetryCacheCheck:
|
|||||||
DirectoryUtils.Create(PathTemp)
|
DirectoryUtils.Create(PathTemp)
|
||||||
CheckPermissionWithException(PathTemp)
|
CheckPermissionWithException(PathTemp)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
If PathTemp = Path.GetTempPath() & "PCL\" Then
|
If PathUtils.IsSame(PathTemp, Path.GetTempPath() & "PCL\") Then
|
||||||
MyMsgBox("PCL 无法访问缓存文件夹,可能导致程序出错或无法正常使用!" & vbCrLf & vbCrLf & "错误原因:" & ex.GetDisplay(True), "缓存文件夹不可用")
|
MyMsgBox("PCL 无法访问缓存文件夹,可能导致程序出错或无法正常使用!" & vbCrLf & vbCrLf & "错误原因:" & ex.GetDisplay(True), "缓存文件夹不可用")
|
||||||
Else
|
Else
|
||||||
MyMsgBox("手动设置的缓存文件夹不可用,PCL 将使用默认缓存文件夹。" & vbCrLf & vbCrLf & "错误原因:" & ex.GetDisplay(True), "缓存文件夹不可用")
|
MyMsgBox("手动设置的缓存文件夹不可用,PCL 将使用默认缓存文件夹。" & vbCrLf & vbCrLf & "错误原因:" & ex.GetDisplay(True), "缓存文件夹不可用")
|
||||||
@@ -92,8 +95,6 @@ RetryCacheCheck:
|
|||||||
End Try
|
End Try
|
||||||
DirectoryUtils.Create(PathTemp & "Cache\")
|
DirectoryUtils.Create(PathTemp & "Cache\")
|
||||||
DirectoryUtils.Create(Paths.AppDataThenName)
|
DirectoryUtils.Create(Paths.AppDataThenName)
|
||||||
'要求单例
|
|
||||||
WaitingMutex(e)
|
|
||||||
'设置 ToolTipService 默认值
|
'设置 ToolTipService 默认值
|
||||||
ToolTipService.InitialShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(100))
|
ToolTipService.InitialShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(100))
|
||||||
'设置网络配置默认值
|
'设置网络配置默认值
|
||||||
@@ -231,7 +232,7 @@ RetryCacheCheck:
|
|||||||
End Function
|
End Function
|
||||||
End Sub
|
End Sub
|
||||||
Private Shared Sub ExtractLibwebp() '这个方法会调用 ModBase,进而调用 MeloongCore,所以不能放在 New 里
|
Private Shared Sub ExtractLibwebp() '这个方法会调用 ModBase,进而调用 MeloongCore,所以不能放在 New 里
|
||||||
SetDllDirectory(PathPure.Value.TrimEnd("\"c))
|
SetDllDirectory(PathUtils.RemoveSlashSuffix(PathPure.Value))
|
||||||
Try
|
Try
|
||||||
ExtractResources(PathPure.Value & "libwebp.dll", "libwebp64")
|
ExtractResources(PathPure.Value & "libwebp.dll", "libwebp64")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ Namespace Controls.Behaviors
|
|||||||
|
|
||||||
Private Shared Sub AddCommandBindingsToTextBox(tb As TextBox)
|
Private Shared Sub AddCommandBindingsToTextBox(tb As TextBox)
|
||||||
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyTextBox))
|
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyTextBox))
|
||||||
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutTextBox))
|
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutTextBox, AddressOf CanEditTextBox))
|
||||||
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteTextBox))
|
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteTextBox, AddressOf CanEditTextBox))
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Shared Sub AddCommandBindingsToRichTextBox(rtb As RichTextBox)
|
Private Shared Sub AddCommandBindingsToRichTextBox(rtb As RichTextBox)
|
||||||
@@ -58,42 +58,61 @@ Namespace Controls.Behaviors
|
|||||||
dg.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyDataGrid))
|
dg.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyDataGrid))
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub SetClipboardText(text As String)
|
||||||
|
Forms.Clipboard.SetDataObject(text, False, retryTimes:=10, retryDelay:=100) '实际的复制
|
||||||
|
Try
|
||||||
|
System.Windows.Clipboard.Flush() '将数据持久化到系统剪贴板,避免应用程序退出后数据丢失
|
||||||
|
Catch ex As Exception '持久化失败不抛出异常
|
||||||
|
Logger.Warn(ex, $"剪贴板持久化失败(错误码:0x{ex.HResult:X8})")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
|
||||||
Private Shared Sub OnCopyTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
Private Shared Sub OnCopyTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
Dim tb = TryCast(sender, TextBox)
|
Dim tb = TryCast(sender, TextBox)
|
||||||
If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
|
If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
|
||||||
|
|
||||||
Try
|
Try
|
||||||
Forms.Clipboard.Clear()
|
SetClipboardText(tb.SelectedText)
|
||||||
Forms.Clipboard.SetDataObject(tb.SelectedText, True)
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "复制失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"复制失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private Shared Sub CanEditTextBox(sender As Object, e As CanExecuteRoutedEventArgs)
|
||||||
|
Dim tb = TryCast(sender, TextBox)
|
||||||
|
e.CanExecute = tb IsNot Nothing AndAlso Not tb.IsReadOnly AndAlso
|
||||||
|
(e.Command IsNot ApplicationCommands.Cut OrElse tb.SelectionLength > 0)
|
||||||
|
e.Handled = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
Private Shared Sub OnCutTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
Private Shared Sub OnCutTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
Dim tb = TryCast(sender, TextBox)
|
Dim tb = TryCast(sender, TextBox)
|
||||||
If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
|
e.Handled = True
|
||||||
|
If tb Is Nothing OrElse tb.IsReadOnly OrElse tb.SelectionLength <= 0 Then Return
|
||||||
|
|
||||||
Try
|
Try
|
||||||
Forms.Clipboard.Clear()
|
SetClipboardText(tb.SelectedText)
|
||||||
Forms.Clipboard.SetDataObject(tb.SelectedText, True)
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "剪切失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"剪切失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
|
Return
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
tb.SelectedText = String.Empty
|
tb.SelectedText = String.Empty
|
||||||
e.Handled = True
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Shared Sub OnPasteTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
Private Shared Sub OnPasteTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
Dim tb = TryCast(sender, TextBox)
|
Dim tb = TryCast(sender, TextBox)
|
||||||
If tb Is Nothing Then Return
|
e.Handled = True
|
||||||
|
If tb Is Nothing OrElse tb.IsReadOnly Then Return
|
||||||
|
|
||||||
Try
|
Try
|
||||||
If Forms.Clipboard.ContainsText() Then
|
Dim pasteText = Retrier.Attempt(func:=
|
||||||
Dim pasteText = Forms.Clipboard.GetText()
|
Function(Attempt) As String
|
||||||
|
Return If(Forms.Clipboard.ContainsText(), Forms.Clipboard.GetText(), Nothing)
|
||||||
|
End Function, maxAttempts:=10, delay:=Function() TimeSpan.FromMilliseconds(100))
|
||||||
|
If pasteText IsNot Nothing Then
|
||||||
|
|
||||||
'将换行符替换为空格(#7825)
|
'将换行符替换为空格(#7825)
|
||||||
If Not tb.AcceptsReturn Then pasteText = pasteText.ReplaceLineEndings(" ", mergeMultiple:=True)
|
If Not tb.AcceptsReturn Then pasteText = pasteText.ReplaceLineEndings(" ", mergeMultiple:=True)
|
||||||
@@ -105,10 +124,8 @@ Namespace Controls.Behaviors
|
|||||||
tb.SelectionLength = 0
|
tb.SelectionLength = 0
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "粘贴失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"粘贴失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
e.Handled = True
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Shared Sub OnCopyRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
Private Shared Sub OnCopyRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
@@ -119,10 +136,9 @@ Namespace Controls.Behaviors
|
|||||||
If String.IsNullOrEmpty(textRange.Text) Then Return
|
If String.IsNullOrEmpty(textRange.Text) Then Return
|
||||||
|
|
||||||
Try
|
Try
|
||||||
Forms.Clipboard.Clear()
|
SetClipboardText(textRange.Text)
|
||||||
Forms.Clipboard.SetDataObject(textRange.Text, True)
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "复制失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"复制失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
@@ -134,16 +150,16 @@ Namespace Controls.Behaviors
|
|||||||
|
|
||||||
Dim selection = New TextRange(rtb.Selection.Start, rtb.Selection.End)
|
Dim selection = New TextRange(rtb.Selection.Start, rtb.Selection.End)
|
||||||
If String.IsNullOrEmpty(selection.Text) Then Return
|
If String.IsNullOrEmpty(selection.Text) Then Return
|
||||||
|
e.Handled = True
|
||||||
|
|
||||||
Try
|
Try
|
||||||
Forms.Clipboard.Clear()
|
SetClipboardText(selection.Text)
|
||||||
Forms.Clipboard.SetDataObject(selection.Text, True)
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "剪切失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"剪切失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
|
Return
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
selection.Text = String.Empty
|
selection.Text = String.Empty
|
||||||
e.Handled = True
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Shared Sub OnPasteRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
Private Shared Sub OnPasteRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
|
||||||
@@ -151,9 +167,11 @@ Namespace Controls.Behaviors
|
|||||||
If rtb Is Nothing Then Return
|
If rtb Is Nothing Then Return
|
||||||
|
|
||||||
Try
|
Try
|
||||||
If Not Forms.Clipboard.ContainsText() Then Return
|
Dim pasteText = Retrier.Attempt(func:=
|
||||||
|
Function(Attempt) As String
|
||||||
Dim pasteText = Forms.Clipboard.GetText()
|
Return If(Forms.Clipboard.ContainsText(), Forms.Clipboard.GetText(), Nothing)
|
||||||
|
End Function, maxAttempts:=2, delay:=Function() TimeSpan.FromMilliseconds(200))
|
||||||
|
If pasteText Is Nothing Then Return
|
||||||
Dim selection = rtb.Selection
|
Dim selection = rtb.Selection
|
||||||
|
|
||||||
selection.Text = pasteText
|
selection.Text = pasteText
|
||||||
@@ -162,7 +180,7 @@ Namespace Controls.Behaviors
|
|||||||
rtb.CaretPosition = caretPos
|
rtb.CaretPosition = caretPos
|
||||||
rtb.Selection.Select(caretPos, caretPos)
|
rtb.Selection.Select(caretPos, caretPos)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "粘贴失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"粘贴失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
@@ -187,10 +205,9 @@ Namespace Controls.Behaviors
|
|||||||
Dim sbStr = sb.ToString().TrimEnd(ControlChars.Cr, ControlChars.Lf)
|
Dim sbStr = sb.ToString().TrimEnd(ControlChars.Cr, ControlChars.Lf)
|
||||||
|
|
||||||
Try
|
Try
|
||||||
Forms.Clipboard.Clear()
|
SetClipboardText(sbStr)
|
||||||
Forms.Clipboard.SetDataObject(sbStr, True)
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, "复制失败,请稍后再试", LogBehavior.Toast)
|
Logger.Warn(ex, $"复制失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
|
|||||||
@@ -102,73 +102,36 @@ Public Class MyCard
|
|||||||
RunInUi(Sub() UseAnimation = RawUseAnimation, True)
|
RunInUi(Sub() UseAnimation = RawUseAnimation, True)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub StackInstall()
|
|
||||||
StackInstall(SwapControl, SwapType, Title)
|
'填充
|
||||||
TriggerForceResize()
|
Private ContentBuilder As Action(Of Panel)
|
||||||
|
Public Sub SetContentBuilder(Builder As Action(Of Panel))
|
||||||
|
ContentBuilder = Builder
|
||||||
End Sub
|
End Sub
|
||||||
Public Shared Sub StackInstall(ByRef Stack As StackPanel, Type As Integer, Optional CardTitle As String = "")
|
Public Sub SetContentBuilder(Of T)(Items As IEnumerable(Of T), ItemBuilder As Func(Of T, UIElement))
|
||||||
'这一部分的代码是好几年前留下的究极屎坑,当时还不知道该咋正确调用这种方法,就写了这么一坨屎
|
SetContentBuilder(
|
||||||
'但是现在……反正勉强能用……懒得改了就这样吧.jpg
|
Sub(Stack)
|
||||||
'别骂了别骂了.jpg
|
For Each Item In Items
|
||||||
If Stack.Tag Is Nothing Then Return
|
Stack.Children.Add(ItemBuilder(Item))
|
||||||
'排序
|
Next
|
||||||
Dim HasDuplicates As Boolean = False
|
Stack.Children.Add(New FrameworkElement With {.Height = 18})
|
||||||
Select Case Type
|
End Sub)
|
||||||
Case 3
|
End Sub
|
||||||
Stack.Tag = CType(Stack.Tag, List(Of DlOptiFineListEntry)).SortByComparison(Function(a, b) CompareVersionGE(a.DisplayName, b.DisplayName))
|
''' <summary>
|
||||||
Case 4, 10
|
''' 使用 ContentBuilder 生成卡片内容。
|
||||||
Stack.Tag = CType(Stack.Tag, List(Of DlLiteLoaderListEntry)).SortByComparison(Function(a, b) CompareVersionGE(a.Inherit, b.Inherit))
|
''' </summary>
|
||||||
Case 6
|
Public Sub BuildContent()
|
||||||
Stack.Tag = CType(Stack.Tag, List(Of DlForgeVersionEntry)).OrderByDescending(Function(a) a).ToList
|
If ContentBuilder Is Nothing Then Return
|
||||||
Case 8, 9
|
Dim Stack = TryCast(SwapControl, Panel)
|
||||||
Stack.Tag = CType(Stack.Tag, List(Of ResourceVersion)).SortByComparison(Function(a, b) a.ReleaseDate > b.ReleaseDate)
|
If Stack Is Nothing Then Return
|
||||||
HasDuplicates =
|
Try
|
||||||
CType(Stack.Tag, List(Of ResourceVersion)).DistinctBy(Function(a) a.Display).Count <>
|
ContentBuilder(Stack)
|
||||||
CType(Stack.Tag, List(Of ResourceVersion)).Count
|
ContentBuilder = Nothing
|
||||||
End Select
|
Catch
|
||||||
'控件转换
|
Stack.Children.Clear()
|
||||||
Select Case Type
|
Throw
|
||||||
Case 6
|
End Try
|
||||||
ForgeDownloadListItemPreload(Stack, Stack.Tag, AddressOf ForgeSave_Click, True)
|
TriggerForceResize()
|
||||||
Case 8
|
|
||||||
PageDownloadResourceDetail.ResourceFilesCardPreload(Stack, Stack.Tag)
|
|
||||||
End Select
|
|
||||||
'实现控件虚拟化
|
|
||||||
For Each Data As Object In Stack.Tag
|
|
||||||
Select Case Type
|
|
||||||
Case 0
|
|
||||||
Stack.Children.Add(CType(Data, McInstance).ToListItem(AddressOf PageSelectRight.McInstanceListContent))
|
|
||||||
Case 2
|
|
||||||
Stack.Children.Add(McDownloadListItem(Data, AddressOf McDownloadMenuSave, True))
|
|
||||||
Case 3
|
|
||||||
Stack.Children.Add(OptiFineDownloadListItem(Data, AddressOf OptiFineSave_Click, True))
|
|
||||||
Case 6
|
|
||||||
Stack.Children.Add(ForgeDownloadListItem(Data, AddressOf ForgeSave_Click, True))
|
|
||||||
Case 7
|
|
||||||
'不能使用 AddressOf,这导致了 #535,原因完全不明,疑似是编译器 Bug
|
|
||||||
Stack.Children.Add(McDownloadListItem(Data, Sub(sender, e) FrmDownloadInstall.MinecraftSelected(sender, e), False))
|
|
||||||
Case 8
|
|
||||||
'若存在重复的版本名,则显示文件名而非版本名(#1344)
|
|
||||||
Stack.Children.Add(CType(Data, ResourceVersion).ToListItem(
|
|
||||||
AddressOf FrmDownloadResourceDetail.Save_Click, IsBadDisplay:=HasDuplicates))
|
|
||||||
Case 9
|
|
||||||
'若存在重复的版本名,则显示文件名而非版本名(#1344)
|
|
||||||
Stack.Children.Add(CType(Data, ResourceVersion).ToListItem(
|
|
||||||
AddressOf FrmDownloadResourceDetail.Install_Click, AddressOf FrmDownloadResourceDetail.Save_Click, IsBadDisplay:=HasDuplicates))
|
|
||||||
Case 10
|
|
||||||
Stack.Children.Add(LiteLoaderDownloadListItem(Data, AddressOf LiteLoaderSave_Click, True))
|
|
||||||
Case 11
|
|
||||||
Stack.Children.Add(CType(Data, HelpEntry).ToListItem)
|
|
||||||
Case 12
|
|
||||||
Stack.Children.Add(FabricDownloadListItem(CType(Data, JObject), AddressOf FrmDownloadInstall.Fabric_Selected))
|
|
||||||
Case 13
|
|
||||||
Stack.Children.Add(NeoForgeDownloadListItem(Data, AddressOf NeoForgeSave_Click, True))
|
|
||||||
Case Else
|
|
||||||
Logger.Error($"未知的虚拟化种类:{Type}")
|
|
||||||
End Select
|
|
||||||
Next
|
|
||||||
Stack.Children.Add(New FrameworkElement With {.Height = 18}) '下边距,同时适应折叠
|
|
||||||
Stack.Tag = Nothing
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'动画
|
'动画
|
||||||
@@ -278,10 +241,6 @@ Public Class MyCard
|
|||||||
Public SwapControl As FrameworkElement
|
Public SwapControl As FrameworkElement
|
||||||
Public Property CanSwap As Boolean = False
|
Public Property CanSwap As Boolean = False
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 被折叠的种类,用于控件虚拟化。
|
|
||||||
''' </summary>
|
|
||||||
Public Property SwapType As Integer
|
|
||||||
''' <summary>
|
|
||||||
''' 是否已被折叠。
|
''' 是否已被折叠。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Property IsSwapped As Boolean
|
Public Property IsSwapped As Boolean
|
||||||
@@ -293,7 +252,7 @@ Public Class MyCard
|
|||||||
_IsSwapped = value
|
_IsSwapped = value
|
||||||
If SwapControl Is Nothing Then Return
|
If SwapControl Is Nothing Then Return
|
||||||
'展开
|
'展开
|
||||||
If Not IsSwapped AndAlso TypeOf SwapControl Is StackPanel Then StackInstall(SwapControl, SwapType, Title)
|
If Not IsSwapped Then BuildContent()
|
||||||
'若尚未加载,会在 Loaded 事件中触发无动画的折叠,不需要在这里进行
|
'若尚未加载,会在 Loaded 事件中触发无动画的折叠,不需要在这里进行
|
||||||
If Not IsLoaded Then Return
|
If Not IsLoaded Then Return
|
||||||
'更新样式
|
'更新样式
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Public Class MyImage
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, $"加载图片失败({value})")
|
Logger.Warn(ex, $"加载图片失败({value})")
|
||||||
Try
|
Try
|
||||||
If value.StartsWithF(PathTemp) Then FileUtils.Delete(value)
|
If value.StartsWithF(PathTemp, True) Then FileUtils.Delete(value)
|
||||||
Catch
|
Catch
|
||||||
End Try
|
End Try
|
||||||
End Try
|
End Try
|
||||||
|
|||||||
@@ -508,7 +508,8 @@ Public Class MyListItem
|
|||||||
RaiseEvent Click(sender, e)
|
RaiseEvent Click(sender, e)
|
||||||
If e.Handled Then Return
|
If e.Handled Then Return
|
||||||
'触发自定义事件
|
'触发自定义事件
|
||||||
If CustomEventService.GetEventType(sender) <> CustomEvent.EventType.None Then
|
If CustomEventService.GetEventType(sender) <> CustomEvent.EventType.None OrElse
|
||||||
|
CustomEventService.GetEvents(sender).Events.Count > 0 Then
|
||||||
RaiseCustomEvent()
|
RaiseCustomEvent()
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ Public Class FormMain
|
|||||||
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
|
||||||
'统计更新日志条目
|
'统计更新日志条目
|
||||||
If BuildType = BuildTypes.Release Then
|
If BuildType = BuildTypes.Release Then
|
||||||
|
If LastVersion < 413 Then 'Release 2.99.0.0
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "删除:为遵守相关法律法规,PCL 暂时不再提供 MC 下载功能,非常抱歉 qwq……"))
|
||||||
|
End If
|
||||||
|
If LastVersion < 411 Then 'Release 2.14.0.0
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "新增:允许修改、添加、移除、更新已安装版本的各个组件,可从版本设置中进入"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:启动游戏时允许按 Esc 取消"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:允许复制主页的启动日志中的内容"))
|
||||||
|
FeatureCount += 19
|
||||||
|
BugCount += 26
|
||||||
|
End If
|
||||||
If LastVersion < 408 Then 'Release 2.13.1.1
|
If LastVersion < 408 Then 'Release 2.13.1.1
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:版本设置中,添加打开截图文件夹的快捷方式"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:版本设置中,添加打开截图文件夹的快捷方式"))
|
||||||
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:导出整合包时,可以勾选导出光影设置文件"))
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:导出整合包时,可以勾选导出光影设置文件"))
|
||||||
@@ -93,6 +103,16 @@ Public Class FormMain
|
|||||||
'3:BUG+ IMP* FEAT-
|
'3:BUG+ IMP* FEAT-
|
||||||
'2:BUG* IMP-
|
'2:BUG* IMP-
|
||||||
'1:BUG-
|
'1:BUG-
|
||||||
|
If LastVersion < 414 Then 'Snapshot 2.99.0.0
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "删除:为遵守相关法律法规,PCL 暂时不再提供 MC 下载功能,非常抱歉 qwq……"))
|
||||||
|
End If
|
||||||
|
If LastVersion < 412 Then 'Snapshot 2.14.0.0
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "新增:允许修改、添加、移除、更新已安装版本的各个组件,可从版本设置中进入"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:启动游戏时允许按 Esc 取消"))
|
||||||
|
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:允许复制主页的启动日志中的内容"))
|
||||||
|
FeatureCount += 19
|
||||||
|
BugCount += 26
|
||||||
|
End If
|
||||||
If LastVersion < 410 Then 'Snapshot 2.13.1.1
|
If LastVersion < 410 Then 'Snapshot 2.13.1.1
|
||||||
If LastVersion = 409 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:更新 Mod 时可能更新成另一个 Mod 加载器的版本"))
|
If LastVersion = 409 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:更新 Mod 时可能更新成另一个 Mod 加载器的版本"))
|
||||||
FeatureCount += 2
|
FeatureCount += 2
|
||||||
@@ -786,7 +806,7 @@ Public Class FormMain
|
|||||||
If PanMsg.Children.Any Then
|
If PanMsg.Children.Any Then
|
||||||
If e.Key = Key.Enter Then
|
If e.Key = Key.Enter Then
|
||||||
CType(PanMsg.Children(0), Object).Btn1_Click()
|
CType(PanMsg.Children(0), Object).Btn1_Click()
|
||||||
ElseIf e.Key = Key.Escape OrElse (e.Key = Key.W AndAlso Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) Then
|
ElseIf e.Key = Key.Escape Then
|
||||||
Dim Msg As Object = PanMsg.Children(0)
|
Dim Msg As Object = PanMsg.Children(0)
|
||||||
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
|
||||||
Msg.Btn3_Click()
|
Msg.Btn3_Click()
|
||||||
@@ -803,13 +823,13 @@ Public Class FormMain
|
|||||||
' 在没有弹窗时:继续检查……
|
' 在没有弹窗时:继续检查……
|
||||||
'==========================
|
'==========================
|
||||||
|
|
||||||
'按 ESC:启动中则取消启动,否则返回上一级
|
'按 ESC 取消启动,或返回上一级
|
||||||
If e.Key = Key.Escape Then
|
If e.Key = Key.Escape Then
|
||||||
If McLaunchLoader.State = LoadState.Loading Then
|
If PageCurrent = FormMain.PageType.Launch AndAlso McLaunchLoader.State = LoadState.Loading Then
|
||||||
McLaunchCancel()
|
FrmLaunchLeft.BtnCancel_Click()
|
||||||
Else
|
Return
|
||||||
TriggerPageBack()
|
|
||||||
End If
|
End If
|
||||||
|
TriggerPageBack()
|
||||||
End If
|
End If
|
||||||
'更改隐藏版本可见性
|
'更改隐藏版本可见性
|
||||||
If e.Key = Key.F11 AndAlso PageCurrent = FormMain.PageType.InstanceSelect Then
|
If e.Key = Key.F11 AndAlso PageCurrent = FormMain.PageType.InstanceSelect Then
|
||||||
@@ -834,11 +854,6 @@ Public Class FormMain
|
|||||||
If TypeOf PageRight Is IRefreshable Then CType(PageRight, IRefreshable).Refresh()
|
If TypeOf PageRight Is IRefreshable Then CType(PageRight, IRefreshable).Refresh()
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
'Ctrl + w 关闭程序
|
|
||||||
If e.Key = Key.W AndAlso Keyboard.Modifiers.HasFlag(ModifierKeys.Control) Then
|
|
||||||
EndProgram(True)
|
|
||||||
Return
|
|
||||||
End If
|
|
||||||
'调用启动游戏
|
'调用启动游戏
|
||||||
If e.Key = Key.Enter AndAlso PageCurrent = FormMain.PageType.Launch Then
|
If e.Key = Key.Enter AndAlso PageCurrent = FormMain.PageType.Launch Then
|
||||||
If IsAprilEnabled AndAlso Not IsAprilGiveup Then
|
If IsAprilEnabled AndAlso Not IsAprilGiveup Then
|
||||||
@@ -1026,14 +1041,14 @@ Public Class FormMain
|
|||||||
If FilePathList.Count > 1 Then
|
If FilePathList.Count > 1 Then
|
||||||
'必须要求全部为 jar 文件
|
'必须要求全部为 jar 文件
|
||||||
For Each File In PathList
|
For Each File In PathList
|
||||||
If Not {"jar", "litemod", "disabled", "old"}.Contains(File.AfterLast(".").Lower) Then
|
If Not {"jar", "litemod", "disabled", "old"}.Contains(PathUtils.GetExtension(File)) Then
|
||||||
Hint("一次请只拖入一个文件!", HintType.Red)
|
Hint("一次请只拖入一个文件!", HintType.Red)
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
'主页
|
'主页
|
||||||
Dim Extension As String = FilePath.AfterLast(".").Lower
|
Dim Extension As String = PathUtils.GetExtension(FilePath)
|
||||||
If Extension = "xaml" Then
|
If Extension = "xaml" Then
|
||||||
Logger.Info("文件后缀为 XAML,作为主页加载")
|
Logger.Info("文件后缀为 XAML,作为主页加载")
|
||||||
If FileUtils.Exists(Paths.Base & "PCL\Custom.xaml") Then
|
If FileUtils.Exists(Paths.Base & "PCL\Custom.xaml") Then
|
||||||
@@ -1054,20 +1069,24 @@ Public Class FormMain
|
|||||||
If PageInstanceMod.InstallMods(PathList) Then Return
|
If PageInstanceMod.InstallMods(PathList) Then Return
|
||||||
'安装整合包
|
'安装整合包
|
||||||
If {"zip", "rar", "mrpack"}.Any(Function(t) t = Extension) Then '部分压缩包是 zip 格式但后缀为 rar,总之试一试
|
If {"zip", "rar", "mrpack"}.Any(Function(t) t = Extension) Then '部分压缩包是 zip 格式但后缀为 rar,总之试一试
|
||||||
Logger.Info("文件为压缩包,尝试作为整合包安装")
|
Hint("正在读取压缩包……")
|
||||||
Hint("检测到压缩包拖入,正在准备安装……")
|
|
||||||
Try
|
Try
|
||||||
|
Logger.Info("文件为压缩包,尝试作为整合包安装")
|
||||||
ModpackInstall(FilePath)
|
ModpackInstall(FilePath)
|
||||||
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.TaskManager))
|
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.TaskManager))
|
||||||
Return
|
Return
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
If RestrictMcDownload AndAlso ex.Message = "为遵守相关法律法规,PCL 暂时不再提供 MC 下载功能,非常抱歉 qwq……" Then
|
||||||
|
Hint(ex.Message, HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
If ex.IsCanceled Then Return
|
If ex.IsCanceled Then Return
|
||||||
'安装失败,继续往后尝试
|
'安装失败,继续往后尝试
|
||||||
End Try
|
End Try
|
||||||
End If
|
End If
|
||||||
'RAR 处理
|
'RAR 处理
|
||||||
If Extension = "rar" Then
|
If Extension = "rar" Then
|
||||||
Hint("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试!")
|
Hint("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试!", HintType.Red)
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
'错误报告分析
|
'错误报告分析
|
||||||
@@ -1083,7 +1102,7 @@ Public Class FormMain
|
|||||||
Logger.Error(ex, "自主错误报告分析失败")
|
Logger.Error(ex, "自主错误报告分析失败")
|
||||||
End Try
|
End Try
|
||||||
'未知操作
|
'未知操作
|
||||||
Hint("PCL 无法确定应当执行的文件拖拽操作……")
|
Hint("PCL 无法确定适合的操作……", HintType.Red)
|
||||||
End Sub, "文件拖拽")
|
End Sub, "文件拖拽")
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -1225,9 +1244,10 @@ Public Class FormMain
|
|||||||
OtherTest = 2
|
OtherTest = 2
|
||||||
InstanceOverall = 0
|
InstanceOverall = 0
|
||||||
InstanceSetup = 1
|
InstanceSetup = 1
|
||||||
InstanceMod = 2
|
InstanceModify = 2
|
||||||
InstanceModDisabled = 3
|
InstanceMod = 3
|
||||||
InstanceExport = 4
|
InstanceModDisabled = 4
|
||||||
|
InstanceExport = 5
|
||||||
End Enum
|
End Enum
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取次级页面的名称。若并非次级页面则返回空字符串,故可以以此判断是否为次级页面。
|
''' 获取次级页面的名称。若并非次级页面则返回空字符串,故可以以此判断是否为次级页面。
|
||||||
@@ -1392,6 +1412,10 @@ Public Class FormMain
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub PageChangeActual(Stack As PageStackData, Optional SubType As PageSubType = -1)
|
Private Sub PageChangeActual(Stack As PageStackData, Optional SubType As PageSubType = -1)
|
||||||
If PageCurrent = Stack AndAlso (PageCurrentSub = SubType OrElse SubType = -1) Then Return
|
If PageCurrent = Stack AndAlso (PageCurrentSub = SubType OrElse SubType = -1) Then Return
|
||||||
|
If Stack.Page = PageType.InstanceSetup AndAlso PageInstanceLeft.Instance IsNot Nothing AndAlso McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||||
|
Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
AniControlEnabled += 1
|
AniControlEnabled += 1
|
||||||
Try
|
Try
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ Public Module ModBase
|
|||||||
|
|
||||||
#Region "声明"
|
#Region "声明"
|
||||||
|
|
||||||
'下列版本信息由更新器自动修改
|
'PCL-ISE 版本规则:主版本.次版本.修订版本;内部 VersionCode 继续用于更新兼容判断。
|
||||||
Public Const VersionBaseName As String = "2.13.1.1" '显示用版本名
|
Public Const ProductName As String = "Plain Craft Launcher (PCL) InfstarMC Edition"
|
||||||
|
Public Const ProductShortName As String = "PCL-ISE"
|
||||||
|
Public Const VersionBaseName As String = "0.1.0" '显示用版本名
|
||||||
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
||||||
#If RELEASE Then
|
#If RELEASE Then
|
||||||
Public Const VersionCode As Integer = 408 '正式版
|
Public Const VersionCode As Integer = 413 '正式版
|
||||||
#Else
|
#Else
|
||||||
Public Const VersionCode As Integer = 410 '快照版
|
Public Const VersionCode As Integer = 414 '快照版
|
||||||
#End If
|
#End If
|
||||||
|
|
||||||
'版本信息
|
'版本信息
|
||||||
@@ -47,7 +49,7 @@ Public Module ModBase
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 程序的缓存文件夹路径,以 \ 结尾。
|
''' 程序的缓存文件夹路径,以 \ 结尾。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public PathTemp As String = If(Settings.Get(Of String)("SystemSystemCache") = "", Path.GetTempPath() & "PCL\", Settings.Get(Of String)("SystemSystemCache")).ToString.Replace("/", "\").TrimEnd("\") & "\"
|
Public PathTemp As String = PathUtils.AddSlashSuffix(If(Settings.Get(Of String)("SystemSystemCache") = "", Path.GetTempPath() & "PCL\", Settings.Get(Of String)("SystemSystemCache")).Replace("/", "\"))
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 当前程序的语言。
|
''' 当前程序的语言。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -75,7 +77,7 @@ Public Module ModBase
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 系统盘盘符,以 \ 结尾。例如 “C:\”。
|
''' 系统盘盘符,以 \ 结尾。例如 “C:\”。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public OsDrive As String = Environment.GetLogicalDrives().Where(Function(p) Directory.Exists(p)).First.Upper.First & ":\" '#3799
|
Public OsDrive As String = Environment.GetLogicalDrives().First(Function(p) Directory.Exists(p)) '#3799
|
||||||
|
|
||||||
Public ReadOnly Property ModeDebug As Boolean
|
Public ReadOnly Property ModeDebug As Boolean
|
||||||
Get
|
Get
|
||||||
@@ -576,7 +578,7 @@ Public Module ModBase
|
|||||||
Try
|
Try
|
||||||
If String.IsNullOrEmpty(Folder) Then Return False
|
If String.IsNullOrEmpty(Folder) Then Return False
|
||||||
Folder = PathUtils.AddSlashSuffix(Folder)
|
Folder = PathUtils.AddSlashSuffix(Folder)
|
||||||
If Folder.EndsWithF(":\System Volume Information\") OrElse Folder.EndsWithF(":\$RECYCLE.BIN\") Then Return False
|
If Folder.EndsWithF(":\System Volume Information\", True) OrElse Folder.EndsWithF(":\$RECYCLE.BIN\", True) Then Return False
|
||||||
If Not DirectoryUtils.Exists(Folder) Then Return False
|
If Not DirectoryUtils.Exists(Folder) Then Return False
|
||||||
Dim TestFilePath As String = $"{Folder}CheckPermission{GetUuid()}.txt"
|
Dim TestFilePath As String = $"{Folder}CheckPermission{GetUuid()}.txt"
|
||||||
FileUtils.Write(TestFilePath, "临时文件,用于检测该文件夹的权限是否正常。")
|
FileUtils.Write(TestFilePath, "临时文件,用于检测该文件夹的权限是否正常。")
|
||||||
@@ -593,7 +595,7 @@ Public Module ModBase
|
|||||||
Public Sub CheckPermissionWithException(Folder As String)
|
Public Sub CheckPermissionWithException(Folder As String)
|
||||||
If String.IsNullOrWhiteSpace(Folder) Then Throw New ArgumentNullException("文件夹名不能为空!")
|
If String.IsNullOrWhiteSpace(Folder) Then Throw New ArgumentNullException("文件夹名不能为空!")
|
||||||
Folder = PathUtils.AddSlashSuffix(Folder)
|
Folder = PathUtils.AddSlashSuffix(Folder)
|
||||||
If Folder.EndsWithF(":\System Volume Information\") OrElse Folder.EndsWithF(":\$RECYCLE.BIN\") Then Throw New UnauthorizedAccessException("没有对系统文件夹的权限!")
|
If Folder.EndsWithF(":\System Volume Information\", True) OrElse Folder.EndsWithF(":\$RECYCLE.BIN\", True) Then Throw New UnauthorizedAccessException("没有对系统文件夹的权限!")
|
||||||
If Not DirectoryUtils.Exists(Folder) Then Throw New DirectoryNotFoundException("文件夹不存在!")
|
If Not DirectoryUtils.Exists(Folder) Then Throw New DirectoryNotFoundException("文件夹不存在!")
|
||||||
Dim TestFilePath As String = $"{Folder}CheckPermission{GetUuid()}.txt"
|
Dim TestFilePath As String = $"{Folder}CheckPermission{GetUuid()}.txt"
|
||||||
FileUtils.Write(TestFilePath, "临时文件,用于检测该文件夹的权限是否正常。")
|
FileUtils.Write(TestFilePath, "临时文件,用于检测该文件夹的权限是否正常。")
|
||||||
@@ -788,7 +790,7 @@ Public Module ModBase
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
|
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public PathPure As Lazy(Of String) = New Lazy(Of String)(
|
Public PathPure As New Lazy(Of String)(
|
||||||
Function()
|
Function()
|
||||||
If Paths.Base.IsAsciiOnly() Then
|
If Paths.Base.IsAsciiOnly() Then
|
||||||
Return Paths.Base & "PCL\"
|
Return Paths.Base & "PCL\"
|
||||||
@@ -845,6 +847,12 @@ Public Module ModBase
|
|||||||
Return (Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000
|
Return (Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000
|
||||||
End Function
|
End Function
|
||||||
''' <summary>
|
''' <summary>
|
||||||
|
''' 获取十进制 Unix 时间戳。
|
||||||
|
''' </summary>
|
||||||
|
Public Function ToUnixTimestampUtc(Time As Date) As Long
|
||||||
|
Return (Time.ToUniversalTime().Ticks - 621355968000000000) / 10000000
|
||||||
|
End Function
|
||||||
|
''' <summary>
|
||||||
''' 时间戳转化为日期。
|
''' 时间戳转化为日期。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Function GetDate(timeStamp As Integer) As Date
|
Public Function GetDate(timeStamp As Integer) As Date
|
||||||
@@ -1021,20 +1029,22 @@ Public Module ModBase
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 设置剪贴板。将在另一线程运行,且不会抛出异常。
|
''' 设置剪贴板。将在另一线程运行,且不会抛出异常。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub ClipboardSet(Text As String, Optional ShowSuccessHint As Boolean = True, Optional SuccessHint As String = "")
|
Public Sub ClipboardSet(Text As String, Optional ShowSuccessHint As Boolean = True)
|
||||||
RunInThread(
|
RunInThread(
|
||||||
Sub()
|
Sub()
|
||||||
RunInUi(
|
Try
|
||||||
Sub()
|
Retrier.Attempt(delay:=Function(Attempt) TimeSpan.FromMilliseconds(200), maxAttempts:=4, isRetryAllowed:=Function(ex) True, action:=
|
||||||
Try
|
Sub()
|
||||||
My.Computer.Clipboard.Clear()
|
RunInUiWait(
|
||||||
If Not String.IsNullOrEmpty(Text) Then My.Computer.Clipboard.SetText(Text)
|
Sub()
|
||||||
If ShowSuccessHint Then Hint(If(String.IsNullOrEmpty(SuccessHint), "已成功复制!", SuccessHint), HintType.Green)
|
My.Computer.Clipboard.Clear()
|
||||||
Catch ex As Exception
|
If Not String.IsNullOrEmpty(Text) Then My.Computer.Clipboard.SetText(Text)
|
||||||
Logger.Error(ex, behavior:=LogBehavior.None)
|
End Sub)
|
||||||
Hint("复制失败,可能由于剪贴板被其他程序占用!", HintType.Red)
|
End Sub)
|
||||||
End Try
|
If ShowSuccessHint Then Hint("已成功复制!", HintType.Green)
|
||||||
End Sub)
|
Catch ex As Exception
|
||||||
|
Logger.Error(ex, "可能由于剪贴板被其他程序占用,文本复制失败", LogBehavior.Toast)
|
||||||
|
End Try
|
||||||
End Sub)
|
End Sub)
|
||||||
End Sub
|
End Sub
|
||||||
''' <summary>
|
''' <summary>
|
||||||
|
|||||||
@@ -1396,7 +1396,7 @@ FinishExCatch:
|
|||||||
Public Overrides Sub Start(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = False)
|
Public Overrides Sub Start(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = False)
|
||||||
If Input IsNot Nothing Then Files = New ConcurrentQueue(Of NetFile)(CType(Input, IEnumerable(Of NetFile)))
|
If Input IsNot Nothing Then Files = New ConcurrentQueue(Of NetFile)(CType(Input, IEnumerable(Of NetFile)))
|
||||||
'去重
|
'去重
|
||||||
Files = New ConcurrentQueue(Of NetFile)(Files.DistinctBy(Function(a) a.LocalPath))
|
Files = New ConcurrentQueue(Of NetFile)(Files.DistinctBy(Function(a) PathUtils.ForCompare(a.LocalPath).Lower()))
|
||||||
'设置剩余文件数
|
'设置剩余文件数
|
||||||
SyncLock FileRemainLock
|
SyncLock FileRemainLock
|
||||||
FileRemain += Files.Where(Function(f) f.State <> NetState.Finished).Count
|
FileRemain += Files.Where(Function(f) f.State <> NetState.Finished).Count
|
||||||
@@ -1421,7 +1421,7 @@ FinishExCatch:
|
|||||||
Next
|
Next
|
||||||
If Not File.HasAvailableSource() Then Throw New ArgumentException("输入的下载链接不正确!")
|
If Not File.HasAvailableSource() Then Throw New ArgumentException("输入的下载链接不正确!")
|
||||||
File.LocalPath = File.LocalPath.Replace("/", "\")
|
File.LocalPath = File.LocalPath.Replace("/", "\")
|
||||||
If Not File.LocalPath.Lower.Contains(":\") Then Throw New ArgumentException("输入的本地文件地址不正确:" & File.LocalPath)
|
If Not File.LocalPath.Contains(":\") Then Throw New ArgumentException("输入的本地文件地址不正确:" & File.LocalPath)
|
||||||
If File.LocalPath.EndsWithF("\") Then Throw New ArgumentException("请输入含文件名的完整文件路径:" & File.LocalPath)
|
If File.LocalPath.EndsWithF("\") Then Throw New ArgumentException("请输入含文件名的完整文件路径:" & File.LocalPath)
|
||||||
DirectoryUtils.Create(PathUtils.RemoveLastPart(File.LocalPath)) '创建目标文件夹
|
DirectoryUtils.Create(PathUtils.RemoveLastPart(File.LocalPath)) '创建目标文件夹
|
||||||
Next
|
Next
|
||||||
@@ -1519,7 +1519,7 @@ FinishExCatch:
|
|||||||
Select(Function(FolderName) (FolderName, File.LocalPath.IndexOfF(FolderName, True))).
|
Select(Function(FolderName) (FolderName, File.LocalPath.IndexOfF(FolderName, True))).
|
||||||
Where(Function(kv) kv.Item2 >= 0).ToList
|
Where(Function(kv) kv.Item2 >= 0).ToList
|
||||||
If Not TypeIndexes.Any Then
|
If Not TypeIndexes.Any Then
|
||||||
If File.LocalName.EndsWithF(".jar") Then
|
If PathUtils.GetExtension(File.LocalName) = "jar" Then
|
||||||
TypeIndexes.Add(("\versions\", 1)) '总是对 jar 进行版本文件检查,以包括另存为 jar 的情况
|
TypeIndexes.Add(("\versions\", 1)) '总是对 jar 进行版本文件检查,以包括另存为 jar 的情况
|
||||||
Else
|
Else
|
||||||
Return Nothing
|
Return Nothing
|
||||||
@@ -1547,7 +1547,7 @@ FinishExCatch:
|
|||||||
Case "versions\"
|
Case "versions\"
|
||||||
'版本 jar 或 json:查找 MC 文件夹下的各个版本文件夹
|
'版本 jar 或 json:查找 MC 文件夹下的各个版本文件夹
|
||||||
For Each VersionFolder In VersionFolders
|
For Each VersionFolder In VersionFolders
|
||||||
For Each Candidate In DirectoryUtils.EnumerateFiles(VersionFolder, searchPattern:="*." & PathUtils.GetLastPart(File.LocalPath).AfterLast(".").Lower)
|
For Each Candidate In DirectoryUtils.EnumerateFiles(VersionFolder, searchPattern:="*." & PathUtils.GetExtension(File.LocalPath))
|
||||||
If CheckCandidate(Candidate, File.Check) Then Return Candidate
|
If CheckCandidate(Candidate, File.Check) Then Return Candidate
|
||||||
Next
|
Next
|
||||||
Next
|
Next
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ Public Class ValidateFolderPath
|
|||||||
Public Overrides Function Validate(Str As String) As String
|
Public Overrides Function Validate(Str As String) As String
|
||||||
'去除尾部斜线,统一为 \
|
'去除尾部斜线,统一为 \
|
||||||
Str = Str.Replace("/", "\")
|
Str = Str.Replace("/", "\")
|
||||||
If Not Str.TrimEnd("\").EndsWithF(":") Then Str = Str.TrimEnd("\")
|
If Not PathUtils.RemoveSlashSuffix(Str).EndsWithF(":") Then Str = PathUtils.RemoveSlashSuffix(Str)
|
||||||
'检查是否为空
|
'检查是否为空
|
||||||
Dim LengthCheck As String = New ValidateNullOrWhiteSpace().Validate(Str)
|
Dim LengthCheck As String = New ValidateNullOrWhiteSpace().Validate(Str)
|
||||||
If LengthCheck <> "" Then Return LengthCheck
|
If LengthCheck <> "" Then Return LengthCheck
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ Public Class CrashAnalyzer
|
|||||||
'尝试视作压缩包解压
|
'尝试视作压缩包解压
|
||||||
Try
|
Try
|
||||||
Dim Info = FileUtils.GetInfo(FilePath)
|
Dim Info = FileUtils.GetInfo(FilePath)
|
||||||
If Info.Exists AndAlso Info.Length > 0 AndAlso Not FilePath.EndsWithF(".jar", True) Then
|
If Info.Exists AndAlso Info.Length > 0 AndAlso Not PathUtils.GetExtension(FilePath) = "jar" Then
|
||||||
FileUtils.ExtractToDirectory(FilePath, TempFolder & "Temp\")
|
FileUtils.ExtractToDirectory(FilePath, TempFolder & "Temp\")
|
||||||
Logger.Info($"已解压导入的日志文件:{FilePath}")
|
Logger.Info($"已解压导入的日志文件:{FilePath}")
|
||||||
GoTo Extracted
|
GoTo Extracted
|
||||||
@@ -163,9 +163,9 @@ Extracted:
|
|||||||
Else
|
Else
|
||||||
TargetType = AnalyzeFileType.ExtraLogFile
|
TargetType = AnalyzeFileType.ExtraLogFile
|
||||||
End If
|
End If
|
||||||
ElseIf MatchName.EndsWithF(".log", True) Then
|
ElseIf PathUtils.GetExtension(MatchName) = "log" Then
|
||||||
TargetType = AnalyzeFileType.ExtraLogFile
|
TargetType = AnalyzeFileType.ExtraLogFile
|
||||||
ElseIf MatchName.EndsWithF(".txt", True) Then
|
ElseIf PathUtils.GetExtension(MatchName) = "txt" Then
|
||||||
TargetType = AnalyzeFileType.ExtraReportFile
|
TargetType = AnalyzeFileType.ExtraReportFile
|
||||||
Else
|
Else
|
||||||
Logger.Info($"{MatchName} 分类为 Ignore")
|
Logger.Info($"{MatchName} 分类为 Ignore")
|
||||||
|
|||||||
@@ -242,8 +242,6 @@ Public Module ModDownload
|
|||||||
DlPreferMojang = DeltaTime < 4000
|
DlPreferMojang = DeltaTime < 4000
|
||||||
Logger.Info($"Mojang 官方源加载耗时:{DeltaTime}ms,{If(DlPreferMojang, "可优先使用官方源", "不优先使用官方源")}")
|
Logger.Info($"Mojang 官方源加载耗时:{DeltaTime}ms,{If(DlPreferMojang, "可优先使用官方源", "不优先使用官方源")}")
|
||||||
End If
|
End If
|
||||||
'添加 PCL 特供项
|
|
||||||
If FileUtils.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(FileUtils.ReadAsJson(PathTemp & "Cache\download.json"))
|
|
||||||
'返回
|
'返回
|
||||||
Loader.Output = New DlClientListResult With {.IsOfficial = True, .SourceName = "Mojang 官方源", .Value = Json}
|
Loader.Output = New DlClientListResult With {.IsOfficial = True, .SourceName = "Mojang 官方源", .Value = Json}
|
||||||
'MC 更新提示
|
'MC 更新提示
|
||||||
@@ -438,7 +436,7 @@ Public Module ModDownload
|
|||||||
.FileName = If(Name(i).ContainsIgnoreCase("pre"), "preview_", "") & "OptiFine_" & Name(i).Replace(" ", "_") & ".jar",
|
.FileName = If(Name(i).ContainsIgnoreCase("pre"), "preview_", "") & "OptiFine_" & Name(i).Replace(" ", "_") & ".jar",
|
||||||
.RequiredForgeVersion = Forge(i).Replace("Forge ", "").Replace("#", "")}
|
.RequiredForgeVersion = Forge(i).Replace("Forge ", "").Replace("#", "")}
|
||||||
If Entry.RequiredForgeVersion.Contains("N/A") Then Entry.RequiredForgeVersion = Nothing
|
If Entry.RequiredForgeVersion.Contains("N/A") Then Entry.RequiredForgeVersion = Nothing
|
||||||
Entry.InstanceName = Entry.Inherit & "-OptiFine_" & Name(i).ToString.Replace(" ", "_").Replace(Entry.Inherit & "_", "")
|
Entry.InstanceName = Entry.Inherit & "-OptiFine_" & Name(i).AfterFirst(" ").Replace(" ", "_")
|
||||||
Versions.Add(Entry)
|
Versions.Add(Entry)
|
||||||
Next
|
Next
|
||||||
Loader.Output = New DlOptiFineListResult With {.IsOfficial = True, .SourceName = "OptiFine 官方源", .Value = Versions}
|
Loader.Output = New DlOptiFineListResult With {.IsOfficial = True, .SourceName = "OptiFine 官方源", .Value = Versions}
|
||||||
@@ -581,7 +579,7 @@ Public Module ModDownload
|
|||||||
If Version <> other.Version Then
|
If Version <> other.Version Then
|
||||||
Return Version.CompareTo(other.Version)
|
Return Version.CompareTo(other.Version)
|
||||||
Else
|
Else
|
||||||
Return CompareVersion(VersionName, other.VersionName)
|
Return McUtils.CompareVersion(VersionName, other.VersionName)
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Public Module ModJava
|
|||||||
'强制选择的 Java
|
'强制选择的 Java
|
||||||
Dim SelectedJavaSetting = Settings.Get(Of String)("LaunchArgumentJavaSelect")
|
Dim SelectedJavaSetting = Settings.Get(Of String)("LaunchArgumentJavaSelect")
|
||||||
Dim SelectedJava = If(SelectedJavaSetting.StartsWithF("{"), SelectedJavaSetting.DeserializeJson(Of JObject)()("Path").ToString, "")
|
Dim SelectedJava = If(SelectedJavaSetting.StartsWithF("{"), SelectedJavaSetting.DeserializeJson(Of JObject)()("Path").ToString, "")
|
||||||
Dim Match = OldJavaList.FirstOrDefault(Function(j) j.Folder.Equals(SelectedJava, StringComparison.OrdinalIgnoreCase))
|
Dim Match = OldJavaList.FirstOrDefault(Function(j) PathUtils.IsSame(j.Folder, SelectedJava))
|
||||||
If Match IsNot Nothing Then
|
If Match IsNot Nothing Then
|
||||||
OldJavaList.Remove(Match)
|
OldJavaList.Remove(Match)
|
||||||
OldJavaList.Insert(0, Match)
|
OldJavaList.Insert(0, Match)
|
||||||
@@ -78,7 +78,7 @@ Public Module ModJava
|
|||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
'不再移除它
|
'不再移除它
|
||||||
Configs.JavaRemovedList.Edit(Sub(ByRef List) List.RemoveIf(Function(f) f.Equals(NewJava.Folder, StringComparison.OrdinalIgnoreCase)))
|
Configs.JavaRemovedList.Edit(Sub(ByRef List) List.RemoveIf(Function(f) PathUtils.IsSame(f, NewJava.Folder)))
|
||||||
'加入列表顶部
|
'加入列表顶部
|
||||||
Configs.JavaList.Edit(
|
Configs.JavaList.Edit(
|
||||||
Sub(ByRef List)
|
Sub(ByRef List)
|
||||||
@@ -150,16 +150,16 @@ Public Module ModJava
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'原版 26-:通过版本号判断
|
'原版 26-:通过版本号判断
|
||||||
If (Not Instance.Version.Vaild AndAlso Instance.ReleaseTime >= New Date(2024, 4, 2)) OrElse
|
If (Not Instance.Version.Valid AndAlso Instance.ReleaseTime >= New Date(2024, 4, 2)) OrElse
|
||||||
(Instance.Version.Vaild AndAlso Instance.Version.Vanilla >= New Version(20, 0, 5)) Then
|
(Instance.Version.Valid AndAlso Instance.Version.Vanilla >= New Version(20, 0, 5)) Then
|
||||||
'1.20.5+(24w14a+):至少 Java 21
|
'1.20.5+(24w14a+):至少 Java 21
|
||||||
AddConstraint(ValueRange(Of Version).AtLeast(New Version(21, 0)))
|
AddConstraint(ValueRange(Of Version).AtLeast(New Version(21, 0)))
|
||||||
ElseIf (Not Instance.Version.Vaild AndAlso Instance.ReleaseTime >= New Date(2021, 11, 16)) OrElse
|
ElseIf (Not Instance.Version.Valid AndAlso Instance.ReleaseTime >= New Date(2021, 11, 16)) OrElse
|
||||||
(Instance.Version.Vaild AndAlso Instance.Version.Vanilla.Major >= 18) Then
|
(Instance.Version.Valid AndAlso Instance.Version.Vanilla.Major >= 18) Then
|
||||||
'1.18 pre2+:至少 Java 17
|
'1.18 pre2+:至少 Java 17
|
||||||
AddConstraint(ValueRange(Of Version).AtLeast(New Version(17, 0)))
|
AddConstraint(ValueRange(Of Version).AtLeast(New Version(17, 0)))
|
||||||
ElseIf (Not Instance.Version.Vaild AndAlso Instance.ReleaseTime >= New Date(2021, 5, 11)) OrElse
|
ElseIf (Not Instance.Version.Valid AndAlso Instance.ReleaseTime >= New Date(2021, 5, 11)) OrElse
|
||||||
(Instance.Version.Vaild AndAlso Instance.Version.Vanilla.Major >= 17) Then
|
(Instance.Version.Valid AndAlso Instance.Version.Vanilla.Major >= 17) Then
|
||||||
'1.17+ (21w19a+):至少 Java 16
|
'1.17+ (21w19a+):至少 Java 16
|
||||||
AddConstraint(ValueRange(Of Version).AtLeast(New Version(16, 0)))
|
AddConstraint(ValueRange(Of Version).AtLeast(New Version(16, 0)))
|
||||||
ElseIf Instance.ReleaseTime.Year >= 2017 Then 'Minecraft 1.12 与 1.11 的分界线正好是 2017 年,太棒了
|
ElseIf Instance.ReleaseTime.Year >= 2017 Then 'Minecraft 1.12 与 1.11 的分界线正好是 2017 年,太棒了
|
||||||
@@ -185,7 +185,7 @@ Public Module ModJava
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
'OptiFine 检测
|
'OptiFine 检测
|
||||||
If Instance.Version.HasOptiFine AndAlso Instance.Version.Vaild Then '不管非标准版本
|
If Instance.Version.HasOptiFine AndAlso Instance.Version.Valid Then '不管非标准版本
|
||||||
If Instance.Version.Vanilla.Major < 7 Then
|
If Instance.Version.Vanilla.Major < 7 Then
|
||||||
'<1.7:至多 Java 8
|
'<1.7:至多 Java 8
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
|
||||||
@@ -199,11 +199,11 @@ Public Module ModJava
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
'Forge 检测(部分测试结果见 #8432)
|
'Forge 检测(部分测试结果见 #8432)
|
||||||
If Instance.Version.HasForge Then
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then
|
||||||
If Instance.Version.Vanilla >= New Version(6, 0, 1) AndAlso Instance.Version.Vanilla <= New Version(7, 0, 2) Then
|
If Instance.Version.Vanilla >= New Version(6, 0, 1) AndAlso Instance.Version.Vanilla <= New Version(7, 0, 2) Then
|
||||||
'1.6.1 - 1.7.2:必须 Java 7
|
'1.6.1 - 1.7.2:必须 Java 7
|
||||||
AddConstraint(ValueRange(Of Version).ClosedOpen(New Version(7, 0), New Version(8, 0)))
|
AddConstraint(ValueRange(Of Version).ClosedOpen(New Version(7, 0), New Version(8, 0)))
|
||||||
ElseIf Instance.Version.Vanilla.Major <= 12 OrElse Not Instance.Version.Vaild Then '非标准版本
|
ElseIf Instance.Version.Vanilla.Major <= 12 OrElse Not Instance.Version.Valid Then '非标准版本
|
||||||
'<=1.12:Java 8
|
'<=1.12:Java 8
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
|
||||||
ElseIf Instance.Version.Vanilla.Major <= 14 Then
|
ElseIf Instance.Version.Vanilla.Major <= 14 Then
|
||||||
@@ -212,38 +212,38 @@ Public Module ModJava
|
|||||||
ElseIf Instance.Version.Vanilla.Major = 15 Then
|
ElseIf Instance.Version.Vanilla.Major = 15 Then
|
||||||
'1.15:Java 8 - 15
|
'1.15:Java 8 - 15
|
||||||
AddConstraint(ValueRange(Of Version).ClosedOpen(New Version(8, 0), New Version(16, 0)))
|
AddConstraint(ValueRange(Of Version).ClosedOpen(New Version(8, 0), New Version(16, 0)))
|
||||||
ElseIf CompareVersionGE(Instance.Version.Forge, "34.0.0") AndAlso CompareVersionGE("36.2.25", Instance.Version.Forge) Then
|
ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "34.0.0") AndAlso McUtils.CompareVersionGE("36.2.25", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
|
||||||
'1.16.3~5,Forge 34.0.0 ~ 36.2.25:最高 Java 8u320
|
'1.16.3~5,Forge 34.0.0 ~ 36.2.25:最高 Java 8u320
|
||||||
AddConstraint(ValueRange(Of Version).AtMost(New Version(8, 0, 320)))
|
AddConstraint(ValueRange(Of Version).AtMost(New Version(8, 0, 320)))
|
||||||
ElseIf CompareVersionGE(Instance.Version.Forge, "36.2.26") AndAlso CompareVersionGE("36.999999.999999", Instance.Version.Forge) Then
|
ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "36.2.26") AndAlso McUtils.CompareVersionGE("36.999999.999999", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
|
||||||
'1.16.5,Forge 36.2.26+,<37.0.0:最高 Java 23
|
'1.16.5,Forge 36.2.26+,<37.0.0:最高 Java 23
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(24, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(24, 0)))
|
||||||
ElseIf CompareVersionGE(Instance.Version.Forge, "37.0.0") AndAlso CompareVersionGE("37.0.79", Instance.Version.Forge) Then
|
ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "37.0.0") AndAlso McUtils.CompareVersionGE("37.0.79", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
|
||||||
'1.17.1,Forge 37.0.0 ~ 37.0.79:最高 Java 16
|
'1.17.1,Forge 37.0.0 ~ 37.0.79:最高 Java 16
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(17, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(17, 0)))
|
||||||
ElseIf Instance.Version.Vanilla.Major = 18 AndAlso Instance.Version.HasOptiFine Then '#305
|
ElseIf Instance.Version.Vanilla.Major = 18 AndAlso Instance.Version.HasOptiFine Then '#305
|
||||||
'1.18:若安装了 OptiFine,最高 Java 18
|
'1.18:若安装了 OptiFine,最高 Java 18
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(19, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(19, 0)))
|
||||||
ElseIf CompareVersionGE(Instance.Version.Forge, "45.0.21") AndAlso CompareVersionGE("45.0.65", Instance.Version.Forge) Then
|
ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "45.0.21") AndAlso McUtils.CompareVersionGE("45.0.65", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
|
||||||
'1.19.4,Forge 45.0.21 ~ 45.0.65:最高 Java 19
|
'1.19.4,Forge 45.0.21 ~ 45.0.65:最高 Java 19
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(20, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(20, 0)))
|
||||||
ElseIf CompareVersionGE(Instance.Version.Forge, "45.0.66") AndAlso CompareVersionGE("47.4.8", Instance.Version.Forge) Then
|
ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "45.0.66") AndAlso McUtils.CompareVersionGE("47.4.8", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
|
||||||
'1.19.4~1.20.1,Forge 45.0.66 ~ 47.4.8:最高 Java 21
|
'1.19.4~1.20.1,Forge 45.0.66 ~ 47.4.8:最高 Java 21
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(22, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(22, 0)))
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'NeoForge 检测
|
'NeoForge 检测
|
||||||
If Instance.Version.HasNeoForge Then
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then
|
||||||
If Instance.Version.Vanilla = New Version(20, 0, 1) OrElse
|
If Instance.Version.Vanilla = New Version(20, 0, 1) OrElse
|
||||||
(CompareVersionGE("20.2.62-beta", Instance.Version.NeoForge) AndAlso Not Instance.Version.NeoForge.Contains("25w14craftmine")) Then
|
(McUtils.CompareVersionGE("20.2.62-beta", Instance.Version.ModLoaderVersions(ModLoaders.NeoForge)) AndAlso Not Instance.Version.ModLoaderVersions(ModLoaders.NeoForge).Contains("25w14craftmine")) Then
|
||||||
'1.20.1,以及 1.20.2 的 20.2.62-beta 之前:最高 Java 21
|
'1.20.1,以及 1.20.2 的 20.2.62-beta 之前:最高 Java 21
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(22, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(22, 0)))
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'Fabric 检测
|
'Fabric 检测
|
||||||
If Instance.Version.HasFabric AndAlso Instance.Version.Vaild Then '不管非标准版本
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) AndAlso Instance.Version.Valid Then '不管非标准版本
|
||||||
If Instance.Version.Vanilla.Major >= 15 AndAlso Instance.Version.Vanilla.Major <= 16 Then
|
If Instance.Version.Vanilla.Major >= 15 AndAlso Instance.Version.Vanilla.Major <= 16 Then
|
||||||
'1.15 - 1.16:Java 8+
|
'1.15 - 1.16:Java 8+
|
||||||
AddConstraint(ValueRange(Of Version).AtLeast(New Version(8, 0)))
|
AddConstraint(ValueRange(Of Version).AtLeast(New Version(8, 0)))
|
||||||
@@ -251,15 +251,14 @@ Public Module ModJava
|
|||||||
'1.18+:Java 17+
|
'1.18+:Java 17+
|
||||||
AddConstraint(ValueRange(Of Version).AtLeast(New Version(17, 0)))
|
AddConstraint(ValueRange(Of Version).AtLeast(New Version(17, 0)))
|
||||||
End If
|
End If
|
||||||
If Instance.Version.Fabric <> "未知版本" AndAlso
|
If Instance.Version.ModLoaderVersions(ModLoaders.Fabric) <> "未知版本" AndAlso McUtils.CompareVersion(Instance.Version.ModLoaderVersions(ModLoaders.Fabric), "0.17.0") < 0 Then
|
||||||
CompareVersion(Instance.Version.Fabric, "0.17.0") < 0 Then
|
|
||||||
'Fabric Loader 0.16.x 及更早版本的 Mixin/ASM 不兼容 Java 25
|
'Fabric Loader 0.16.x 及更早版本的 Mixin/ASM 不兼容 Java 25
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(25, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(25, 0)))
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'LiteLoader 检测
|
'LiteLoader 检测
|
||||||
If Instance.Version.HasLiteLoader AndAlso Instance.Version.Vaild Then '不管非标准版本
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) AndAlso Instance.Version.Valid Then '不管非标准版本
|
||||||
'最高 Java 8
|
'最高 Java 8
|
||||||
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
|
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
|
||||||
End If
|
End If
|
||||||
@@ -411,9 +410,9 @@ Public Module ModJava
|
|||||||
Dim Components = DownloadListWorker.LastResult
|
Dim Components = DownloadListWorker.LastResult
|
||||||
|
|
||||||
'确定要下载的目标 Java
|
'确定要下载的目标 Java
|
||||||
Dim JavaToDownload As JavaDownloadInfo = If(
|
Dim JavaToDownload As JavaDownloadInfo = Components.FirstOrDefault(
|
||||||
Components.FirstOrDefault(Function(Comp) Comp.Java("version")("name").ToString = RecommendedComponent), '优先选择指定的 Component
|
Function(Comp) Comp.Java("version")("name").ToString = RecommendedComponent, '优先选择指定的 Component
|
||||||
Components.FirstOrDefault(Function(Comp) Range.Contains(Comp.JavaVersion)))
|
Function(Comp) Range.Contains(Comp.JavaVersion))
|
||||||
If JavaToDownload Is Nothing Then
|
If JavaToDownload Is Nothing Then
|
||||||
Logger.Warn($"Mojang 提供的 Java 列表中没有合适的 Java,无法自动下载")
|
Logger.Warn($"Mojang 提供的 Java 列表中没有合适的 Java,无法自动下载")
|
||||||
'提示需要手动下载 Java
|
'提示需要手动下载 Java
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Public Module ModLaunch
|
|||||||
End Try
|
End Try
|
||||||
'检查版本
|
'检查版本
|
||||||
CurrentLaunchOptions.Instance.Load()
|
CurrentLaunchOptions.Instance.Load()
|
||||||
If CurrentLaunchOptions.Instance.State = McInstanceState.Error Then
|
If CurrentLaunchOptions.Instance.State = McInstance.McInstanceState.Error Then
|
||||||
Hint($"无法启动 {CurrentLaunchOptions.Instance.Name}:{CurrentLaunchOptions.Instance.Info}", HintType.Red)
|
Hint($"无法启动 {CurrentLaunchOptions.Instance.Name}:{CurrentLaunchOptions.Instance.Info}", HintType.Red)
|
||||||
Return False
|
Return False
|
||||||
End If
|
End If
|
||||||
@@ -57,6 +57,10 @@ Public Module ModLaunch
|
|||||||
FrmLaunchLeft.RefreshButtonsUI()
|
FrmLaunchLeft.RefreshButtonsUI()
|
||||||
FrmLaunchLeft.RefreshPage(False, False)
|
FrmLaunchLeft.RefreshPage(False, False)
|
||||||
End If
|
End If
|
||||||
|
If McInstanceSelected IsNot Nothing AndAlso McInstanceLock.IsLocked(McInstanceSelected) Then
|
||||||
|
Hint($"版本 {McInstanceSelected.Name} 正在被修改,请稍后再启动!", HintType.Red)
|
||||||
|
Return False
|
||||||
|
End If
|
||||||
FrmMain.AprilGiveup()
|
FrmMain.AprilGiveup()
|
||||||
'禁止进入版本选择页面(否则就可以在启动中切换 McInstanceSelected 了)
|
'禁止进入版本选择页面(否则就可以在启动中切换 McInstanceSelected 了)
|
||||||
FrmMain.PageStack = FrmMain.PageStack.Where(Function(p) p.Page <> FormMain.PageType.InstanceSelect).ToList
|
FrmMain.PageStack = FrmMain.PageStack.Where(Function(p) p.Page <> FormMain.PageType.InstanceSelect).ToList
|
||||||
@@ -70,7 +74,12 @@ Public Module ModLaunch
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub McLaunchLog(Text As String, Optional Level As LogLevel = LogLevel.Info)
|
Public Sub McLaunchLog(Text As String, Optional Level As LogLevel = LogLevel.Info)
|
||||||
Text = FilterUserName(FilterAccessToken(Text, "*"), "*")
|
Text = FilterUserName(FilterAccessToken(Text, "*"), "*")
|
||||||
If ModeDebug Then RunInUi(Sub() FrmLaunchRight.LabLog.Text += $"{vbCrLf}[{Date.Now:HH':'mm':'ss'.'fff}] {Text}")
|
If ModeDebug Then
|
||||||
|
RunInUi(
|
||||||
|
Sub()
|
||||||
|
FrmLaunchRight.LabLog.AppendText($"[{Date.Now:HH':'mm':'ss'.'fff}] {Text}{vbCrLf}")
|
||||||
|
End Sub)
|
||||||
|
End If
|
||||||
Logger.Log(Text, Level)
|
Logger.Log(Text, Level)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -196,25 +205,6 @@ NextInner:
|
|||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
''' <summary>
|
|
||||||
''' 取消正在进行的游戏启动。
|
|
||||||
''' </summary>
|
|
||||||
Public Sub McLaunchCancel()
|
|
||||||
If McLaunchLoaderReal IsNot Nothing Then
|
|
||||||
McLaunchLoaderReal.Cancel()
|
|
||||||
McLaunchLog("已取消启动")
|
|
||||||
Try
|
|
||||||
If McLaunchWatcher IsNot Nothing Then
|
|
||||||
McLaunchWatcher.Kill()
|
|
||||||
ElseIf McLaunchProcess IsNot Nothing Then
|
|
||||||
If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
|
|
||||||
End If
|
|
||||||
Catch ex As Exception
|
|
||||||
Logger.Error(ex, "取消启动结束进程失败", LogBehavior.Toast)
|
|
||||||
End Try
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
#Region "内存优化"
|
#Region "内存优化"
|
||||||
@@ -249,7 +239,7 @@ NextInner:
|
|||||||
'检查版本
|
'检查版本
|
||||||
If McInstanceSelected Is Nothing Then Throw New Exception("未选择 Minecraft 版本!")
|
If McInstanceSelected Is Nothing Then Throw New Exception("未选择 Minecraft 版本!")
|
||||||
McInstanceSelected.Load()
|
McInstanceSelected.Load()
|
||||||
If McInstanceSelected.State = McInstanceState.Error Then Throw New Exception("Minecraft 存在问题:" & McInstanceSelected.Info)
|
If McInstanceSelected.State = McInstance.McInstanceState.Error Then Throw New Exception("Minecraft 存在问题:" & McInstanceSelected.Info)
|
||||||
'检查输入信息
|
'检查输入信息
|
||||||
Dim CheckResult As String = ""
|
Dim CheckResult As String = ""
|
||||||
RunInUiWait(Sub() CheckResult = McLoginAble(McLoginInput()))
|
RunInUiWait(Sub() CheckResult = McLoginAble(McLoginInput()))
|
||||||
@@ -557,7 +547,7 @@ NextInner:
|
|||||||
'检查是否已经登录完成
|
'检查是否已经登录完成
|
||||||
Dim ExpiresAt = Settings.Get(Of Long)("CacheMsV2Expires")
|
Dim ExpiresAt = Settings.Get(Of Long)("CacheMsV2Expires")
|
||||||
If Not Data.IsForceRestarting AndAlso '不要求强行重启
|
If Not Data.IsForceRestarting AndAlso '不要求强行重启
|
||||||
ExpiresAt > 0 AndAlso ExpiresAt > GetUnixTimestampUtc() AndAlso 'AccessToken 尚未过期
|
ExpiresAt > 0 AndAlso ExpiresAt > ToUnixTimestampUtc(Date.UtcNow) AndAlso 'AccessToken 尚未过期
|
||||||
Input.UserName = Settings.Get(Of String)("CacheMsV2Name") Then
|
Input.UserName = Settings.Get(Of String)("CacheMsV2Name") Then
|
||||||
Data.Output = New McLoginResult With {
|
Data.Output = New McLoginResult With {
|
||||||
.Name = Input.UserName, .Type = "Microsoft",
|
.Name = Input.UserName, .Type = "Microsoft",
|
||||||
@@ -1052,7 +1042,7 @@ Retry:
|
|||||||
Dim ResultJson As JObject = Result.DeserializeJson()
|
Dim ResultJson As JObject = Result.DeserializeJson()
|
||||||
Return (
|
Return (
|
||||||
ResultJson("access_token").ToString,
|
ResultJson("access_token").ToString,
|
||||||
ResultJson("expires_in").ToObject(Of Integer) + GetUnixTimestampUtc() - 1200) '提前 20 分钟视作过期
|
ResultJson("expires_in").ToObject(Of Integer) + GetUnixTimestampUtc() - 3600) '提前 1 小时视作过期
|
||||||
End Function
|
End Function
|
||||||
'微软登录步骤 5:验证微软账号是否持有 MC,这也会刷新 XGP
|
'微软登录步骤 5:验证微软账号是否持有 MC,这也会刷新 XGP
|
||||||
Private Sub MsLoginStep5(AccessToken As String)
|
Private Sub MsLoginStep5(AccessToken As String)
|
||||||
@@ -1382,16 +1372,11 @@ NextInstance:
|
|||||||
'Log4j 漏洞防御参数
|
'Log4j 漏洞防御参数
|
||||||
Args.Add("-Dlog4j2.formatMsgNoLookups=true")
|
Args.Add("-Dlog4j2.formatMsgNoLookups=true")
|
||||||
|
|
||||||
'编码(#4700、#5892、#5909、#6934、#8950)
|
'编码(#4700、#5892、#5909、#6934、#8950、#9241)
|
||||||
Dim EncodingName As String
|
Dim UseCompatEncoding = McLaunchJavaSelected.Version.Major >= 18
|
||||||
Select Case McLaunchJavaSelected.Version.Major
|
Dim EncodingName = If(UseCompatEncoding,
|
||||||
Case Is >= 21 'Java 21+ 会固定使用 UTF-8
|
McLaunchJavaSelected.NativeEncodingName, 'Java 18+ 会添加 COMPAT,因此 Java 会回退到 native.encoding
|
||||||
EncodingName = "UTF-8"
|
McLaunchJavaSelected.FileEncodingName) 'Java 17- 直接使用 file.encoding
|
||||||
Case Is >= 18 'Java 18~20 时,启动 MC 时会添加 COMPAT 参数,因此 Java 会回退到 native.encoding
|
|
||||||
EncodingName = McLaunchJavaSelected.NativeEncodingName
|
|
||||||
Case Else 'Java 17- 时,直接使用 file.encoding
|
|
||||||
EncodingName = McLaunchJavaSelected.FileEncodingName
|
|
||||||
End Select
|
|
||||||
Try
|
Try
|
||||||
McLaunchEncoding = Encoding.GetEncoding(If(EncodingName.Equals("GBK", StringComparison.OrdinalIgnoreCase), "GB18030", EncodingName))
|
McLaunchEncoding = Encoding.GetEncoding(If(EncodingName.Equals("GBK", StringComparison.OrdinalIgnoreCase), "GB18030", EncodingName))
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -1405,7 +1390,7 @@ NextInstance:
|
|||||||
Dim StderrArgName = If(McLaunchJavaSelected.Version.Major < 19, "sun.stderr.encoding", "stderr.encoding")
|
Dim StderrArgName = If(McLaunchJavaSelected.Version.Major < 19, "sun.stderr.encoding", "stderr.encoding")
|
||||||
If Not Args.Any(Function(a) a.StartsWithF($"-D{StdoutArgName}=")) Then Args.Add($"-D{StdoutArgName}={LaunchEncodingName}")
|
If Not Args.Any(Function(a) a.StartsWithF($"-D{StdoutArgName}=")) Then Args.Add($"-D{StdoutArgName}={LaunchEncodingName}")
|
||||||
If Not Args.Any(Function(a) a.StartsWithF($"-D{StderrArgName}=")) Then Args.Add($"-D{StderrArgName}={LaunchEncodingName}")
|
If Not Args.Any(Function(a) a.StartsWithF($"-D{StderrArgName}=")) Then Args.Add($"-D{StderrArgName}={LaunchEncodingName}")
|
||||||
If McLaunchJavaSelected.Version.Major >= 18 AndAlso McLaunchJavaSelected.Version.Major < 21 Then Args.Add("-Dfile.encoding=COMPAT") '使用 COMPAT 防止部分 Mod 配置文件不兼容 UTF-8
|
If UseCompatEncoding AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dfile.encoding=")) Then Args.Add("-Dfile.encoding=COMPAT") '防止老版本 MC 与部分 Mod 不兼容 UTF-8
|
||||||
|
|
||||||
'为 JLW 添加 -jar,它必须放在最后
|
'为 JLW 添加 -jar,它必须放在最后
|
||||||
If UseJLW Then
|
If UseJLW Then
|
||||||
@@ -1465,7 +1450,8 @@ NextInstance:
|
|||||||
Arg &= " " & CustomArg
|
Arg &= " " & CustomArg
|
||||||
|
|
||||||
'把 OptiFineForgeTweaker 放在参数的末尾
|
'把 OptiFineForgeTweaker 放在参数的末尾
|
||||||
If (McInstanceSelected.Version.HasForge OrElse McInstanceSelected.Version.HasLiteLoader) AndAlso McInstanceSelected.Version.HasOptiFine Then
|
If (McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Forge) OrElse McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader)) AndAlso
|
||||||
|
McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.OptiFineAsMod Then
|
||||||
If Arg.Contains("--tweakClass optifine.OptiFineForgeTweaker") Then
|
If Arg.Contains("--tweakClass optifine.OptiFineForgeTweaker") Then
|
||||||
McLaunchLog("发现正确的 OptiFineForge TweakClass,目前的游戏参数:" & Arg)
|
McLaunchLog("发现正确的 OptiFineForge TweakClass,目前的游戏参数:" & Arg)
|
||||||
Arg = Arg.Replace(" --tweakClass optifine.OptiFineForgeTweaker", "") & " --tweakClass optifine.OptiFineForgeTweaker"
|
Arg = Arg.Replace(" --tweakClass optifine.OptiFineForgeTweaker", "") & " --tweakClass optifine.OptiFineForgeTweaker"
|
||||||
@@ -1520,10 +1506,10 @@ NextInstance:
|
|||||||
Private Iterator Function McLaunchArgumentsReplace(Arguments As List(Of String)) As IEnumerable(Of (Key As String, Value As String))
|
Private Iterator Function McLaunchArgumentsReplace(Arguments As List(Of String)) As IEnumerable(Of (Key As String, Value As String))
|
||||||
'基础参数
|
'基础参数
|
||||||
Yield ("${classpath_separator}", ";")
|
Yield ("${classpath_separator}", ";")
|
||||||
Yield ("${natives_directory}", GetNativesFolder().TrimEnd("\"c))
|
Yield ("${natives_directory}", PathUtils.RemoveSlashSuffix(GetNativesFolder()))
|
||||||
Yield ("${library_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
|
Yield ("${library_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
|
||||||
Yield ("${libraries_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
|
Yield ("${libraries_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
|
||||||
Yield ("${pure_directory}", PathPure.Value.TrimEnd("\"c)) '由 PCL 添加,这会允许在分割参数并去重后再替换路径,防止路径中的特殊字符影响参数分割和去重
|
Yield ("${pure_directory}", PathUtils.RemoveSlashSuffix(PathPure.Value)) '由 PCL 添加,这会允许在分割参数并去重后再替换路径,防止路径中的特殊字符影响参数分割和去重
|
||||||
Yield ("${launcher_name}", "PCL")
|
Yield ("${launcher_name}", "PCL")
|
||||||
Yield ("${launcher_version}", VersionCode)
|
Yield ("${launcher_version}", VersionCode)
|
||||||
Yield ("${version_name}", McInstanceSelected.Name)
|
Yield ("${version_name}", McInstanceSelected.Name)
|
||||||
@@ -1568,9 +1554,8 @@ NextInstance:
|
|||||||
Case Else
|
Case Else
|
||||||
TargetSize = New Size(854, 480)
|
TargetSize = New Size(854, 480)
|
||||||
End Select
|
End Select
|
||||||
If McInstanceSelected.Version.Vanilla.Major <= 12 AndAlso
|
If McInstanceSelected.Version.Vanilla.Major <= 12 AndAlso McLaunchJavaSelected.Version >= New Version(8, 0, 200) AndAlso McLaunchJavaSelected.Version <= New Version(8, 0, 321) AndAlso
|
||||||
McLaunchJavaSelected.Version >= New Version(8, 0, 200) AndAlso McLaunchJavaSelected.Version <= New Version(8, 0, 321) AndAlso
|
Not McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then '修复 1.12.2- 下 JRE 8u200~321 下窗口大小为设置大小的 DPI% 倍(#3463)
|
||||||
Not McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.HasForge Then '修复 1.12.2- 下 JRE 8u200~321 下窗口大小为设置大小的 DPI% 倍(#3463)
|
|
||||||
McLaunchLog($"已应用窗口大小过大修复(Java 版本:{McLaunchJavaSelected.Version})")
|
McLaunchLog($"已应用窗口大小过大修复(Java 版本:{McLaunchJavaSelected.Version})")
|
||||||
TargetSize.Width /= DPI / 96
|
TargetSize.Width /= DPI / 96
|
||||||
TargetSize.Height /= DPI / 96
|
TargetSize.Height /= DPI / 96
|
||||||
@@ -1694,7 +1679,7 @@ NextInstance:
|
|||||||
End Try
|
End Try
|
||||||
For Each Entry In Zip.Entries
|
For Each Entry In Zip.Entries
|
||||||
Dim FileName As String = Entry.FullName
|
Dim FileName As String = Entry.FullName
|
||||||
If FileName.EndsWithF(".dll", True) Then
|
If PathUtils.GetExtension(FileName) = "dll" Then
|
||||||
'实际解压文件的步骤
|
'实际解压文件的步骤
|
||||||
Dim FilePath As String = Target & FileName
|
Dim FilePath As String = Target & FileName
|
||||||
ExistFiles.Add(FilePath)
|
ExistFiles.Add(FilePath)
|
||||||
@@ -1738,8 +1723,9 @@ NextInstance:
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 Natives 文件夹路径,以 \ 结尾。
|
''' 获取 Natives 文件夹路径,以 \ 结尾。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function GetNativesFolder() As String
|
Public Function GetNativesFolder(Optional Instance As McInstance = Nothing) As String
|
||||||
Dim Result As String = PathUtils.AddSlashSuffix(PathUtils.ToShortPath(McInstanceSelected.PathVersion)) & McInstanceSelected.Name & "-natives\"
|
If Instance Is Nothing Then Instance = McInstanceSelected
|
||||||
|
Dim Result As String = PathUtils.AddSlashSuffix(PathUtils.ToShortPath(Instance.PathVersion)) & Instance.Name & "-natives\"
|
||||||
If Not (IsGBKEncoding OrElse Result.IsAsciiOnly()) Then
|
If Not (IsGBKEncoding OrElse Result.IsAsciiOnly()) Then
|
||||||
Result = Paths.AppData & ".minecraft\bin\natives\"
|
Result = Paths.AppData & ".minecraft\bin\natives\"
|
||||||
If Not Result.IsAsciiOnly() Then
|
If Not Result.IsAsciiOnly() Then
|
||||||
@@ -1865,7 +1851,7 @@ NextInstance:
|
|||||||
Dim CurrentLang As String = ReadIni(SetupFileAddress, "lang", "none")
|
Dim CurrentLang As String = ReadIni(SetupFileAddress, "lang", "none")
|
||||||
Dim RequiredLang As String = If(CurrentLang = "none" OrElse Not DirectoryUtils.Exists(McInstanceSelected.PathIndie & "saves"), '#3844,整合包可能已经自带了 options.txt
|
Dim RequiredLang As String = If(CurrentLang = "none" OrElse Not DirectoryUtils.Exists(McInstanceSelected.PathIndie & "saves"), '#3844,整合包可能已经自带了 options.txt
|
||||||
If(Settings.Get(Of Boolean)("ToolHelpChinese"), "zh_cn", "en_us"), CurrentLang.Lower)
|
If(Settings.Get(Of Boolean)("ToolHelpChinese"), "zh_cn", "en_us"), CurrentLang.Lower)
|
||||||
If Not McInstanceSelected.Version.Vaild OrElse McInstanceSelected.Version.Vanilla.Major <= 10 Then
|
If Not McInstanceSelected.Version.Valid OrElse McInstanceSelected.Version.Vanilla.Major <= 10 Then
|
||||||
'将最后两位改为大写,前面的部分保留
|
'将最后两位改为大写,前面的部分保留
|
||||||
RequiredLang = RequiredLang.Substring(0, RequiredLang.Length - 2) & RequiredLang.Substring(RequiredLang.Length - 2).Upper
|
RequiredLang = RequiredLang.Substring(0, RequiredLang.Length - 2) & RequiredLang.Substring(RequiredLang.Length - 2).Upper
|
||||||
End If
|
End If
|
||||||
@@ -1908,53 +1894,40 @@ NextInstance:
|
|||||||
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Settings.Get(Of Integer)("LaunchSkinType") = 4 AndAlso FileUtils.Exists(Paths.AppDataThenName & "CustomSkin.png") Then
|
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Settings.Get(Of Integer)("LaunchSkinType") = 4 AndAlso FileUtils.Exists(Paths.AppDataThenName & "CustomSkin.png") Then
|
||||||
Dim MetaFileAddress As String = PathTemp & "pack.mcmeta"
|
Dim MetaFileAddress As String = PathTemp & "pack.mcmeta"
|
||||||
Dim PackPicAddress As String = PathTemp & "pack.png"
|
Dim PackPicAddress As String = PathTemp & "pack.png"
|
||||||
Dim PackFormat As Integer
|
If McInstanceSelected.Version.Vanilla.Major < 6 Then
|
||||||
Select Case McInstanceSelected.Version.Vanilla.Major
|
McLaunchLog("Minecraft 版本过老,尚不支持自定义离线皮肤")
|
||||||
Case 0, 1, 2, 3, 4, 5
|
GoTo IgnoreCustomSkin
|
||||||
'更早的版本没有资源包
|
End If
|
||||||
McLaunchLog("Minecraft 版本过老,尚不支持自定义离线皮肤")
|
Dim PackVersionJToken As JToken = McInstanceSelected.JsonVersion?("pack_version")
|
||||||
GoTo IgnoreCustomSkin
|
If TypeOf PackVersionJToken Is JObject Then PackVersionJToken = DirectCast(PackVersionJToken, JObject)("resource") '从 1.17 开始,可以从 pack_version.resource 获取资源包版本
|
||||||
Case 6, 7, 8
|
Dim PackVersion As Integer = Val(PackVersionJToken?.ToString)
|
||||||
PackFormat = 1
|
If PackVersion <= 0 Then '没有对应字段的老版本 MC,或兜底
|
||||||
Case 9, 10
|
Select Case McInstanceSelected.Version.Vanilla.Major
|
||||||
PackFormat = 2
|
Case 6, 7, 8
|
||||||
Case 11, 12
|
PackVersion = 1
|
||||||
PackFormat = 3
|
Case 9, 10
|
||||||
Case 13, 14
|
PackVersion = 2
|
||||||
PackFormat = 4
|
Case 11, 12
|
||||||
Case 15
|
PackVersion = 3
|
||||||
PackFormat = 5
|
Case 13, 14
|
||||||
Case 16
|
PackVersion = 4
|
||||||
PackFormat = 6
|
Case 15
|
||||||
Case 17
|
PackVersion = 5
|
||||||
PackFormat = 7
|
Case 16
|
||||||
Case 18
|
PackVersion = If(McInstanceSelected.Version.Vanilla.Build <= 1, 5, 6)
|
||||||
If McInstanceSelected.Version.Vanilla.Minor <= 2 Then
|
Case 17
|
||||||
PackFormat = 8
|
PackVersion = 7
|
||||||
Else
|
Case 18
|
||||||
PackFormat = 9
|
PackVersion = 8
|
||||||
End If
|
Case Else '旧版快照可能没有可用的资源包格式声明
|
||||||
Case 19
|
PackVersion = 17
|
||||||
If McInstanceSelected.Version.Vanilla.Minor <= 3 Then
|
End Select
|
||||||
PackFormat = 9
|
End If
|
||||||
Else
|
McLaunchLog($"正在构建自定义皮肤资源包,版本号 {PackVersion},MC 版本 {McInstanceSelected.Version.Vanilla}")
|
||||||
PackFormat = 12
|
|
||||||
End If
|
|
||||||
Case 20
|
|
||||||
If McInstanceSelected.Version.Vanilla.Minor <= 1 Then
|
|
||||||
PackFormat = 15
|
|
||||||
Else
|
|
||||||
PackFormat = 17
|
|
||||||
End If
|
|
||||||
Case Else '快照版是 9999
|
|
||||||
PackFormat = 17
|
|
||||||
'https://zh.minecraft.wiki/w/数据包#数据包版本
|
|
||||||
End Select
|
|
||||||
McLaunchLog("正在构建自定义皮肤资源包,格式为:" & PackFormat)
|
|
||||||
'准备文件
|
'准备文件
|
||||||
Dim Bit As New MyBitmap(PathImage & "Heads/Logo.png")
|
Dim Bit As New MyBitmap(PathImage & "Heads/Logo.png")
|
||||||
Bit.Save(PackPicAddress)
|
Bit.Save(PackPicAddress)
|
||||||
FileUtils.Write(MetaFileAddress, "{""pack"":{""pack_format"":" & PackFormat & ",""description"":""PCL 自定义离线皮肤资源包""}}")
|
FileUtils.Write(MetaFileAddress, "{""pack"":{""pack_format"":" & PackVersion & ",""description"":""PCL 自定义离线皮肤资源包""}}")
|
||||||
Dim Skin As New MyBitmap(Paths.AppDataThenName & "CustomSkin.png")
|
Dim Skin As New MyBitmap(Paths.AppDataThenName & "CustomSkin.png")
|
||||||
If (McInstanceSelected.Version.Vanilla.Major = 6 OrElse McInstanceSelected.Version.Vanilla.Major = 7) AndAlso Skin.Pic.Height = 64 Then
|
If (McInstanceSelected.Version.Vanilla.Major = 6 OrElse McInstanceSelected.Version.Vanilla.Major = 7) AndAlso Skin.Pic.Height = 64 Then
|
||||||
McLaunchLog("该 Minecraft 版本不支持双层皮肤,已进行裁剪")
|
McLaunchLog("该 Minecraft 版本不支持双层皮肤,已进行裁剪")
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,10 @@ Public Module ModModpack
|
|||||||
''' 弹窗要求选择一个整合包文件并进行安装。
|
''' 弹窗要求选择一个整合包文件并进行安装。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub ModpackInstall()
|
Public Sub ModpackInstall()
|
||||||
|
If RestrictMcDownload Then
|
||||||
|
Hint("为遵守相关法律法规,PCL 暂时不再提供 MC 下载功能,非常抱歉 qwq……", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
Dim File As String = Dialogs.SelectFile("选择整合包压缩文件", False, filter:={({"rar", "zip", "mrpack"}, "整合包文件")}).FirstOrDefault() '选择整合包文件
|
Dim File As String = Dialogs.SelectFile("选择整合包压缩文件", False, filter:={({"rar", "zip", "mrpack"}, "整合包文件")}).FirstOrDefault() '选择整合包文件
|
||||||
If String.IsNullOrEmpty(File) Then Return
|
If String.IsNullOrEmpty(File) Then Return
|
||||||
RunInThread(
|
RunInThread(
|
||||||
@@ -74,13 +78,14 @@ Public Module ModModpack
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
If ex.GetDisplay(True).Contains("Error.WinIOError") Then
|
If ex.GetDisplay(True).Contains("Error.WinIOError") Then
|
||||||
Throw New Exception("打开整合包文件失败", ex)
|
Throw New Exception("打开整合包文件失败", ex)
|
||||||
ElseIf File.EndsWithF(".rar", True) Then
|
ElseIf PathUtils.GetExtension(File) = "rar" Then
|
||||||
Throw New Exception("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", ex)
|
Throw New Exception("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", ex)
|
||||||
Else
|
Else
|
||||||
Throw New Exception("打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", ex)
|
Throw New Exception("打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", ex)
|
||||||
End If
|
End If
|
||||||
End Try
|
End Try
|
||||||
'执行对应的安装方法
|
'执行对应的安装方法
|
||||||
|
If RestrictMcDownload Then Throw New Exception("为遵守相关法律法规,PCL 暂时不再提供 MC 下载功能,非常抱歉 qwq……")
|
||||||
Select Case PackType
|
Select Case PackType
|
||||||
Case 0
|
Case 0
|
||||||
Logger.Info("整合包种类:CurseForge")
|
Logger.Info("整合包种类:CurseForge")
|
||||||
@@ -119,8 +124,8 @@ Public Module ModModpack
|
|||||||
''' 对路径末尾是否为 \ 没有要求。
|
''' 对路径末尾是否为 \ 没有要求。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub CopyOverrideDirectory(OverridesFolder As String, VersionFolder As String, Loader As LoaderBase)
|
Private Sub CopyOverrideDirectory(OverridesFolder As String, VersionFolder As String, Loader As LoaderBase)
|
||||||
If Not OverridesFolder.EndsWithF("\") Then OverridesFolder += "\"
|
OverridesFolder = PathUtils.AddSlashSuffix(OverridesFolder)
|
||||||
If Not VersionFolder.EndsWithF("\") Then VersionFolder += "\"
|
VersionFolder = PathUtils.AddSlashSuffix(VersionFolder)
|
||||||
'复制文件
|
'复制文件
|
||||||
If DirectoryUtils.Exists(OverridesFolder) Then
|
If DirectoryUtils.Exists(OverridesFolder) Then
|
||||||
Logger.Info($"处理整合包覆写文件夹:{OverridesFolder} → {VersionFolder}")
|
Logger.Info($"处理整合包覆写文件夹:{OverridesFolder} → {VersionFolder}")
|
||||||
@@ -174,25 +179,25 @@ Public Module ModModpack
|
|||||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||||
End If
|
End If
|
||||||
|
Dim VersionFolder As String = PathUtils.AddSlashSuffix(Path.Combine(McFolderSelected, "versions", InstanceName) & "\")
|
||||||
|
|
||||||
'获取 Mod API 版本信息
|
'获取 Mod API 版本信息
|
||||||
Dim TargetVersion As New McVersion
|
Dim TargetVersion As New McVersion(Json("minecraft")("version").ToString)
|
||||||
TargetVersion.VanillaName = Json("minecraft")("version").ToString
|
|
||||||
For Each Entry In If(Json("minecraft")("modLoaders"), {})
|
For Each Entry In If(Json("minecraft")("modLoaders"), {})
|
||||||
Dim Id As String = If(Entry("id"), "").ToString.Lower
|
Dim Id As String = If(Entry("id"), "").ToString.Lower
|
||||||
If Id.StartsWithF("forge-") Then
|
If Id.StartsWithF("forge-") Then
|
||||||
'Forge 指定
|
'Forge 指定
|
||||||
If Id.Contains("recommended") Then Throw New Exception("该整合包版本过老,已不支持进行安装!")
|
If Id.Contains("recommended") Then Throw New Exception("该整合包版本过老,已不支持进行安装!")
|
||||||
Logger.Info($"整合包 Forge 版本:{Id}")
|
Logger.Info($"整合包 Forge 版本:{Id}")
|
||||||
TargetVersion.Forge = Id.Replace("forge-", "")
|
TargetVersion.ModLoaderVersions(ModLoaders.Forge) = Id.Replace("forge-", "")
|
||||||
ElseIf Id.StartsWithF("neoforge-") Then
|
ElseIf Id.StartsWithF("neoforge-") Then
|
||||||
'NeoForge 指定
|
'NeoForge 指定
|
||||||
Logger.Info($"整合包 NeoForge 版本:{Id}")
|
Logger.Info($"整合包 NeoForge 版本:{Id}")
|
||||||
TargetVersion.NeoForge = Id.Replace("neoforge-", "")
|
TargetVersion.ModLoaderVersions(ModLoaders.NeoForge) = Id.Replace("neoforge-", "")
|
||||||
ElseIf Id.StartsWithF("fabric-") Then
|
ElseIf Id.StartsWithF("fabric-") Then
|
||||||
'Fabric 指定
|
'Fabric 指定
|
||||||
Logger.Info($"整合包 Fabric 版本:{Id}")
|
Logger.Info($"整合包 Fabric 版本:{Id}")
|
||||||
TargetVersion.Fabric = Id.Replace("fabric-", "")
|
TargetVersion.ModLoaderVersions(ModLoaders.Fabric) = Id.Replace("fabric-", "")
|
||||||
Else
|
Else
|
||||||
NotifyIncompatibleLoader(Id)
|
NotifyIncompatibleLoader(Id)
|
||||||
End If
|
End If
|
||||||
@@ -202,12 +207,12 @@ Public Module ModModpack
|
|||||||
Dim InstallLoaders As New List(Of LoaderBase)
|
Dim InstallLoaders As New List(Of LoaderBase)
|
||||||
Dim OverrideHome As String = If(Json("overrides"), "")
|
Dim OverrideHome As String = If(Json("overrides"), "")
|
||||||
If OverrideHome <> "" Then
|
If OverrideHome <> "" Then
|
||||||
|
Dim OverridesFolder As String = InstallTemp & ArchiveBaseFolder & If(OverrideHome = "." OrElse OverrideHome = "./", "", OverrideHome) '#5613
|
||||||
|
If Not PathUtils.IsParentOf(InstallTemp, OverridesFolder) Then Throw New Exception("整合包的 overrides 路径超出了解压目录,请向整合包作者反馈此问题!")
|
||||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||||
Sub(Task As LoaderTask(Of String, Integer))
|
Sub(Task As LoaderTask(Of String, Integer))
|
||||||
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
|
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
|
||||||
CopyOverrideDirectory(
|
CopyOverrideDirectory(OverridesFolder, VersionFolder, Task)
|
||||||
InstallTemp & ArchiveBaseFolder & If(OverrideHome = "." OrElse OverrideHome = "./", "", OverrideHome), '#5613
|
|
||||||
$"{McFolderSelected}versions\{InstanceName}", Task)
|
|
||||||
End Sub) With {
|
End Sub) With {
|
||||||
.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||||
End If
|
End If
|
||||||
@@ -293,7 +298,7 @@ Public Module ModModpack
|
|||||||
Dim File = ResourceVersion.FromPlatformJson(ModJson, Type)
|
Dim File = ResourceVersion.FromPlatformJson(ModJson, Type)
|
||||||
If Not File.DownloadAvailable Then Continue For
|
If Not File.DownloadAvailable Then Continue For
|
||||||
'实际的添加
|
'实际的添加
|
||||||
FileList.Add(Id, File.ToNetFile($"{McFolderSelected}versions\{InstanceName}\{TargetFolder}\",
|
FileList.Add(Id, File.ToNetFile(PathUtils.AddSlashSuffix(Path.Combine(VersionFolder, TargetFolder)),
|
||||||
ResourceVersion.DownloadReason.ModPack, TargetVersion.VanillaName, TargetVersion.ModLoaders))
|
ResourceVersion.DownloadReason.ModPack, TargetVersion.VanillaName, TargetVersion.ModLoaders))
|
||||||
Task.Progress += 1 / (1 + ModList.Count)
|
Task.Progress += 1 / (1 + ModList.Count)
|
||||||
Next
|
Next
|
||||||
@@ -307,15 +312,9 @@ Public Module ModModpack
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
'构造加载器
|
'构造加载器
|
||||||
Dim Request As New McInstallRequest With {
|
Dim Target As New McComponents(TargetVersion.VanillaName, TargetVersion.ModLoaderVersions)
|
||||||
.NewInstanceName = InstanceName,
|
Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
|
||||||
.VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
|
.NewInstanceName = InstanceName, .InstanceFolder = VersionFolder, .Components = Target})
|
||||||
.MinecraftName = TargetVersion.VanillaName,
|
|
||||||
.ForgeVersion = TargetVersion.Forge,
|
|
||||||
.NeoForgeVersion = TargetVersion.NeoForge,
|
|
||||||
.FabricVersion = TargetVersion.Fabric
|
|
||||||
}
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
|
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
@@ -323,7 +322,6 @@ Public Module ModModpack
|
|||||||
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
||||||
Sub(Task As LoaderTask(Of String, String))
|
Sub(Task As LoaderTask(Of String, String))
|
||||||
'设置图标
|
'设置图标
|
||||||
Dim VersionFolder As String = $"{McFolderSelected}versions\{InstanceName}\"
|
|
||||||
If Logo IsNot Nothing AndAlso FileUtils.Exists(Logo) Then
|
If Logo IsNot Nothing AndAlso FileUtils.Exists(Logo) Then
|
||||||
FileUtils.Copy(Logo, VersionFolder & "PCL\Logo.png")
|
FileUtils.Copy(Logo, VersionFolder & "PCL\Logo.png")
|
||||||
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
||||||
@@ -337,10 +335,10 @@ Public Module ModModpack
|
|||||||
FileUtils.Delete(MapFile)
|
FileUtils.Delete(MapFile)
|
||||||
Next
|
Next
|
||||||
'删除原始整合包文件
|
'删除原始整合包文件
|
||||||
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
For Each FileToDelete As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
||||||
If FileUtils.Exists(Target) Then
|
If FileUtils.Exists(FileToDelete) Then
|
||||||
Logger.Info($"删除原始整合包文件:{Target}")
|
Logger.Info($"删除原始整合包文件:{FileToDelete}")
|
||||||
FileUtils.Delete(Target)
|
FileUtils.Delete(FileToDelete)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
If FileUtils.Exists(FileAddress) AndAlso PathUtils.GetFileNameWithoutExtension(FileAddress) = "modpack" Then
|
If FileUtils.Exists(FileAddress) AndAlso PathUtils.GetFileNameWithoutExtension(FileAddress) = "modpack" Then
|
||||||
@@ -358,7 +356,7 @@ Public Module ModModpack
|
|||||||
|
|
||||||
'启动
|
'启动
|
||||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||||
Loader.Start(Request.VersionFolder)
|
Loader.Start(VersionFolder)
|
||||||
LoaderTaskbarAdd(Loader)
|
LoaderTaskbarAdd(Loader)
|
||||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||||
Return Loader
|
Return Loader
|
||||||
@@ -376,20 +374,21 @@ Public Module ModModpack
|
|||||||
End Try
|
End Try
|
||||||
If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("Modrinth 整合包未提供 Minecraft 版本信息")
|
If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("Modrinth 整合包未提供 Minecraft 版本信息")
|
||||||
'获取 Mod API 版本信息
|
'获取 Mod API 版本信息
|
||||||
Dim TargetVersion As New McVersion
|
'TODO: 改为使用类似 InstallPackMMC 中,一个版本名一个字典的方式来存储它,不要用 Unknown
|
||||||
|
Dim TargetVersion As New McVersion("Unknown")
|
||||||
For Each Entry As JProperty In If(Json("dependencies"), {})
|
For Each Entry As JProperty In If(Json("dependencies"), {})
|
||||||
Select Case Entry.Name.Lower
|
Select Case Entry.Name.Lower
|
||||||
Case "minecraft"
|
Case "minecraft"
|
||||||
TargetVersion.VanillaName = Entry.Value.ToString
|
TargetVersion.VanillaName = Entry.Value.ToString
|
||||||
Case "forge" 'eg. 14.23.5.2859 / 1.19-41.1.0
|
Case "forge" 'eg. 14.23.5.2859 / 1.19-41.1.0
|
||||||
TargetVersion.Forge = Entry.Value.ToString
|
TargetVersion.ModLoaderVersions(ModLoaders.Forge) = Entry.Value.ToString
|
||||||
Logger.Info($"整合包 Forge 版本:{TargetVersion.Forge}")
|
Logger.Info($"整合包 Forge 版本:{TargetVersion.ModLoaderVersions(ModLoaders.Forge)}")
|
||||||
Case "neoforge", "neo-forge" 'eg. 20.6.98-beta
|
Case "neoforge", "neo-forge" 'eg. 20.6.98-beta
|
||||||
TargetVersion.NeoForge = Entry.Value.ToString
|
TargetVersion.ModLoaderVersions(ModLoaders.NeoForge) = Entry.Value.ToString
|
||||||
Logger.Info($"整合包 NeoForge 版本:{TargetVersion.NeoForge}")
|
Logger.Info($"整合包 NeoForge 版本:{TargetVersion.ModLoaderVersions(ModLoaders.NeoForge)}")
|
||||||
Case "fabric-loader" 'eg. 0.14.14
|
Case "fabric-loader" 'eg. 0.14.14
|
||||||
TargetVersion.Fabric = Entry.Value.ToString
|
TargetVersion.ModLoaderVersions(ModLoaders.Fabric) = Entry.Value.ToString
|
||||||
Logger.Info($"整合包 Fabric 版本:{TargetVersion.Fabric}")
|
Logger.Info($"整合包 Fabric 版本:{TargetVersion.ModLoaderVersions(ModLoaders.Fabric)}")
|
||||||
Case Else
|
Case Else
|
||||||
NotifyIncompatibleLoader(Entry.Name)
|
NotifyIncompatibleLoader(Entry.Name)
|
||||||
End Select
|
End Select
|
||||||
@@ -402,18 +401,15 @@ Public Module ModModpack
|
|||||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||||
End If
|
End If
|
||||||
|
Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
|
||||||
'解压
|
'解压
|
||||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||||
Dim InstallLoaders As New List(Of LoaderBase)
|
Dim InstallLoaders As New List(Of LoaderBase)
|
||||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||||
Sub(Task As LoaderTask(Of String, Integer))
|
Sub(Task As LoaderTask(Of String, Integer))
|
||||||
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.5))
|
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.5))
|
||||||
CopyOverrideDirectory(
|
CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "overrides", VersionFolder, Task)
|
||||||
InstallTemp & ArchiveBaseFolder & "overrides",
|
CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", VersionFolder, Task)
|
||||||
McFolderSelected & "versions\" & InstanceName, Task)
|
|
||||||
CopyOverrideDirectory(
|
|
||||||
InstallTemp & ArchiveBaseFolder & "client-overrides",
|
|
||||||
McFolderSelected & "versions\" & InstanceName, Task)
|
|
||||||
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||||
'获取下载文件列表
|
'获取下载文件列表
|
||||||
Dim FileList As New List(Of NetFile)
|
Dim FileList As New List(Of NetFile)
|
||||||
@@ -436,8 +432,8 @@ Public Module ModModpack
|
|||||||
Urls = ResourceVersion.ParseModrinthTrackArguments(Urls,
|
Urls = ResourceVersion.ParseModrinthTrackArguments(Urls,
|
||||||
ResourceVersion.DownloadReason.ModPack, TargetVersion.VanillaName, TargetVersion.ModLoaders).ToList 'Modrinth 来源追踪信息
|
ResourceVersion.DownloadReason.ModPack, TargetVersion.VanillaName, TargetVersion.ModLoaders).ToList 'Modrinth 来源追踪信息
|
||||||
Urls = Urls.Distinct.ToList()
|
Urls = Urls.Distinct.ToList()
|
||||||
Dim TargetPath As String = Path.Combine(McFolderSelected, "versions", InstanceName, File("path").ToString().TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
|
Dim TargetPath As String = Path.Combine(VersionFolder, File("path").ToString().TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
|
||||||
If Not PathUtils.IsParentOf($"{McFolderSelected}versions\{InstanceName}\", TargetPath) Then
|
If Not PathUtils.IsParentOf(VersionFolder, TargetPath) Then
|
||||||
MyMsgBox($"整合包的文件路径超出了版本文件夹,请向整合包作者反馈此问题!{vbCrLf}目标:{Path.GetFullPath(TargetPath)}{vbCrLf}错误的文件:{TargetPath}", "文件路径校验失败", IsWarn:=True)
|
MyMsgBox($"整合包的文件路径超出了版本文件夹,请向整合包作者反馈此问题!{vbCrLf}目标:{Path.GetFullPath(TargetPath)}{vbCrLf}错误的文件:{TargetPath}", "文件路径校验失败", IsWarn:=True)
|
||||||
Throw New OperationCanceledException
|
Throw New OperationCanceledException
|
||||||
End If
|
End If
|
||||||
@@ -449,15 +445,10 @@ Public Module ModModpack
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
'构造加载器
|
'构造加载器
|
||||||
Dim Request As New McInstallRequest With {
|
Dim Target As New McComponents(TargetVersion.VanillaName, TargetVersion.ModLoaderVersions)
|
||||||
.NewInstanceName = InstanceName,
|
Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
|
||||||
.VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
|
.NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
|
||||||
.MinecraftName = TargetVersion.VanillaName,
|
.Components = Target})
|
||||||
.ForgeVersion = TargetVersion.Forge,
|
|
||||||
.NeoForgeVersion = TargetVersion.NeoForge,
|
|
||||||
.FabricVersion = TargetVersion.Fabric
|
|
||||||
}
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
|
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
@@ -465,7 +456,6 @@ Public Module ModModpack
|
|||||||
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
|
||||||
Sub(Task As LoaderTask(Of String, String))
|
Sub(Task As LoaderTask(Of String, String))
|
||||||
'设置图标
|
'设置图标
|
||||||
Dim VersionFolder As String = $"{McFolderSelected}versions\{InstanceName}\"
|
|
||||||
If Logo IsNot Nothing AndAlso FileUtils.Exists(Logo) Then
|
If Logo IsNot Nothing AndAlso FileUtils.Exists(Logo) Then
|
||||||
FileUtils.Copy(Logo, VersionFolder & "PCL\Logo.png")
|
FileUtils.Copy(Logo, VersionFolder & "PCL\Logo.png")
|
||||||
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
|
||||||
@@ -473,10 +463,10 @@ Public Module ModModpack
|
|||||||
Logger.Info($"已设置整合包 Logo:{Logo}")
|
Logger.Info($"已设置整合包 Logo:{Logo}")
|
||||||
End If
|
End If
|
||||||
'删除原始整合包文件
|
'删除原始整合包文件
|
||||||
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
For Each FileToDelete As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
|
||||||
If FileUtils.Exists(Target) Then
|
If FileUtils.Exists(FileToDelete) Then
|
||||||
Logger.Info($"删除原始整合包文件:{Target}")
|
Logger.Info($"删除原始整合包文件:{FileToDelete}")
|
||||||
FileUtils.Delete(Target)
|
FileUtils.Delete(FileToDelete)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
If FileUtils.Exists(FileAddress) AndAlso PathUtils.GetFileNameWithoutExtension(FileAddress) = "modpack" Then
|
If FileUtils.Exists(FileAddress) AndAlso PathUtils.GetFileNameWithoutExtension(FileAddress) = "modpack" Then
|
||||||
@@ -494,7 +484,7 @@ Public Module ModModpack
|
|||||||
|
|
||||||
'启动
|
'启动
|
||||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||||
Loader.Start(Request.VersionFolder)
|
Loader.Start(VersionFolder)
|
||||||
LoaderTaskbarAdd(Loader)
|
LoaderTaskbarAdd(Loader)
|
||||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||||
Return Loader
|
Return Loader
|
||||||
@@ -515,24 +505,21 @@ Public Module ModModpack
|
|||||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||||
|
Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
|
||||||
'解压
|
'解压
|
||||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||||
Dim InstallLoaders As New List(Of LoaderBase)
|
Dim InstallLoaders As New List(Of LoaderBase)
|
||||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||||
Sub(Task As LoaderTask(Of String, Integer))
|
Sub(Task As LoaderTask(Of String, Integer))
|
||||||
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
|
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
|
||||||
CopyOverrideDirectory(
|
CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "minecraft", VersionFolder, Task)
|
||||||
InstallTemp & ArchiveBaseFolder & "minecraft",
|
|
||||||
McFolderSelected & "versions\" & InstanceName, Task)
|
|
||||||
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||||
'构造游戏本体安装加载器
|
'构造游戏本体安装加载器
|
||||||
If Json("gameVersion") Is Nothing Then Throw New Exception("该 HMCL 整合包未提供游戏版本信息,无法安装!")
|
If Json("gameVersion") Is Nothing Then Throw New Exception("该 HMCL 整合包未提供游戏版本信息,无法安装!")
|
||||||
Dim Request As New McInstallRequest With {
|
Dim Target As New McComponents(Json("gameVersion").ToString, New Dictionary(Of ModLoaders, String))
|
||||||
.NewInstanceName = InstanceName,
|
Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
|
||||||
.VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
|
.NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
|
||||||
.MinecraftName = Json("gameVersion").ToString
|
.Components = Target})
|
||||||
}
|
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
|
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase) From {
|
Dim Loaders As New List(Of LoaderBase) From {
|
||||||
New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)},
|
New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)},
|
||||||
@@ -546,7 +533,7 @@ Public Module ModModpack
|
|||||||
End If
|
End If
|
||||||
'启动
|
'启动
|
||||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||||
Loader.Start(Request.VersionFolder)
|
Loader.Start(VersionFolder)
|
||||||
LoaderTaskbarAdd(Loader)
|
LoaderTaskbarAdd(Loader)
|
||||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||||
Return Loader
|
Return Loader
|
||||||
@@ -568,16 +555,22 @@ Public Module ModModpack
|
|||||||
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
|
||||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||||
|
Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
|
||||||
'解压
|
'解压
|
||||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||||
Dim SetupFile As String = $"{McFolderSelected}versions\{InstanceName}\PCL\Setup.ini"
|
Dim SetupFile As String = VersionFolder & "PCL\Setup.ini"
|
||||||
Dim InstallLoaders As New List(Of LoaderBase)
|
Dim InstallLoaders As New List(Of LoaderBase)
|
||||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||||
Sub(Task As LoaderTask(Of String, Integer))
|
Sub(Task As LoaderTask(Of String, Integer))
|
||||||
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.55))
|
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.55))
|
||||||
CopyOverrideDirectory(
|
'Prism 优先使用 minecraft/ 而非 .minecraft/(#9272)
|
||||||
InstallTemp & ArchiveBaseFolder & ".minecraft",
|
Dim MmcGameRoot As String
|
||||||
McFolderSelected & "versions\" & InstanceName, Task)
|
If DirectoryUtils.Exists(InstallTemp & ArchiveBaseFolder & ".minecraft") AndAlso Not DirectoryUtils.Exists(InstallTemp & ArchiveBaseFolder & "minecraft") Then
|
||||||
|
MmcGameRoot = InstallTemp & ArchiveBaseFolder & ".minecraft"
|
||||||
|
Else
|
||||||
|
MmcGameRoot = InstallTemp & ArchiveBaseFolder & "minecraft"
|
||||||
|
End If
|
||||||
|
CopyOverrideDirectory(MmcGameRoot, VersionFolder, Task)
|
||||||
'读取 MMC 设置文件(#2655)
|
'读取 MMC 设置文件(#2655)
|
||||||
Try
|
Try
|
||||||
Dim MmcSetupFile As String = InstallTemp & ArchiveBaseFolder & "instance.cfg"
|
Dim MmcSetupFile As String = InstallTemp & ArchiveBaseFolder & "instance.cfg"
|
||||||
@@ -611,7 +604,7 @@ Public Module ModModpack
|
|||||||
If Logo <> "" AndAlso FileUtils.Exists($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png") Then
|
If Logo <> "" AndAlso FileUtils.Exists($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png") Then
|
||||||
WriteIni(SetupFile, "LogoCustom", True)
|
WriteIni(SetupFile, "LogoCustom", True)
|
||||||
WriteIni(SetupFile, "Logo", "PCL\Logo.png")
|
WriteIni(SetupFile, "Logo", "PCL\Logo.png")
|
||||||
FileUtils.Copy($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png", $"{McFolderSelected}versions\{InstanceName}\PCL\Logo.png")
|
FileUtils.Copy($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png", VersionFolder & "PCL\Logo.png")
|
||||||
Logger.Info($"迁移 MultiMC 版本独立设置:版本图标({Logo}.png)")
|
Logger.Info($"迁移 MultiMC 版本独立设置:版本图标({Logo}.png)")
|
||||||
End If
|
End If
|
||||||
'JVM 参数
|
'JVM 参数
|
||||||
@@ -633,19 +626,20 @@ Public Module ModModpack
|
|||||||
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
|
||||||
'构造版本安装请求
|
'构造版本安装请求
|
||||||
If PackJson("components") Is Nothing Then Throw New Exception("该 MMC 整合包未提供游戏版本信息,无法安装!")
|
If PackJson("components") Is Nothing Then Throw New Exception("该 MMC 整合包未提供游戏版本信息,无法安装!")
|
||||||
Dim Request As New McInstallRequest With {.NewInstanceName = InstanceName, .VersionFolder = $"{McFolderSelected}versions\{InstanceName}\"}
|
Dim MinecraftVersion As String = Nothing
|
||||||
|
Dim ModLoaderVersions As New Dictionary(Of ModLoaders, String)
|
||||||
For Each Component As JObject In PackJson("components")
|
For Each Component As JObject In PackJson("components")
|
||||||
If Not Component.ContainsKey("uid") Then Continue For
|
If Not Component.ContainsKey("uid") Then Continue For
|
||||||
Dim UID As String = Component("uid").ToString
|
Dim UID As String = Component("uid").ToString
|
||||||
Select Case UID
|
Select Case UID
|
||||||
Case "net.minecraft"
|
Case "net.minecraft"
|
||||||
Request.MinecraftName = Component("version")
|
MinecraftVersion = Component("version")
|
||||||
Case "net.minecraftforge"
|
Case "net.minecraftforge"
|
||||||
Request.ForgeVersion = Component("version")
|
ModLoaderVersions(ModLoaders.Forge) = Component("version")
|
||||||
Case "net.neoforged"
|
Case "net.neoforged"
|
||||||
Request.NeoForgeVersion = Component("version")
|
ModLoaderVersions(ModLoaders.NeoForge) = Component("version")
|
||||||
Case "net.fabricmc.fabric-loader"
|
Case "net.fabricmc.fabric-loader"
|
||||||
Request.FabricVersion = Component("version")
|
ModLoaderVersions(ModLoaders.Fabric) = Component("version")
|
||||||
Case Else
|
Case Else
|
||||||
If UID.StartsWithF("org.lwjgl") Then '#8210
|
If UID.StartsWithF("org.lwjgl") Then '#8210
|
||||||
Logger.Info($"已跳过 LWJGL 项:{UID}")
|
Logger.Info($"已跳过 LWJGL 项:{UID}")
|
||||||
@@ -655,7 +649,10 @@ Public Module ModModpack
|
|||||||
End Select
|
End Select
|
||||||
Next
|
Next
|
||||||
'构造加载器
|
'构造加载器
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
|
Dim Target As New McComponents(MinecraftVersion, ModLoaderVersions)
|
||||||
|
Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
|
||||||
|
.NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
|
||||||
|
.Components = Target})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
@@ -670,7 +667,7 @@ Public Module ModModpack
|
|||||||
|
|
||||||
'启动
|
'启动
|
||||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||||
Loader.Start(Request.VersionFolder)
|
Loader.Start(VersionFolder)
|
||||||
LoaderTaskbarAdd(Loader)
|
LoaderTaskbarAdd(Loader)
|
||||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||||
Return Loader
|
Return Loader
|
||||||
@@ -695,16 +692,15 @@ Public Module ModModpack
|
|||||||
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
|
||||||
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
|
||||||
End If
|
End If
|
||||||
|
Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
|
||||||
'解压
|
'解压
|
||||||
Dim InstallTemp As String = RequestTaskTempFolder()
|
Dim InstallTemp As String = RequestTaskTempFolder()
|
||||||
Dim SetupFile As String = $"{McFolderSelected}versions\{InstanceName}\PCL\Setup.ini"
|
Dim SetupFile As String = VersionFolder & "PCL\Setup.ini"
|
||||||
Dim InstallLoaders As New List(Of LoaderBase)
|
Dim InstallLoaders As New List(Of LoaderBase)
|
||||||
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
|
||||||
Sub(Task As LoaderTask(Of String, Integer))
|
Sub(Task As LoaderTask(Of String, Integer))
|
||||||
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
|
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
|
||||||
CopyOverrideDirectory(
|
CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "overrides", VersionFolder, Task)
|
||||||
InstallTemp & ArchiveBaseFolder & "overrides",
|
|
||||||
McFolderSelected & "versions\" & InstanceName, Task)
|
|
||||||
'JVM 参数
|
'JVM 参数
|
||||||
If Json("launchInfo") IsNot Nothing Then
|
If Json("launchInfo") IsNot Nothing Then
|
||||||
Dim LaunchInfo As JObject = Json("launchInfo")
|
Dim LaunchInfo As JObject = Json("launchInfo")
|
||||||
@@ -723,16 +719,26 @@ Public Module ModModpack
|
|||||||
Hint("PCL 不支持安装 Quilt 整合包!", HintType.Red)
|
Hint("PCL 不支持安装 Quilt 整合包!", HintType.Red)
|
||||||
Throw New OperationCanceledException
|
Throw New OperationCanceledException
|
||||||
End If
|
End If
|
||||||
Dim Request As New McInstallRequest With {
|
Dim ModLoaderVersions As New Dictionary(Of ModLoaders, String)
|
||||||
.NewInstanceName = InstanceName,
|
If Addons.ContainsKey("forge") Then ModLoaderVersions(ModLoaders.Forge) = Addons("forge")
|
||||||
.VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
|
If Addons.ContainsKey("neoforge") Then ModLoaderVersions(ModLoaders.NeoForge) = Addons("neoforge")
|
||||||
.MinecraftName = Addons("game"),
|
If Addons.ContainsKey("fabric") Then ModLoaderVersions(ModLoaders.Fabric) = Addons("fabric")
|
||||||
.OptiFineVersion = If(Addons.ContainsKey("optifine"), Addons("optifine"), Nothing),
|
Dim OptiFineEntry As JObject = Nothing
|
||||||
.ForgeVersion = If(Addons.ContainsKey("forge"), Addons("forge"), Nothing),
|
If Addons.ContainsKey("optifine") Then
|
||||||
.NeoForgeVersion = If(Addons.ContainsKey("neoforge"), Addons("neoforge"), Nothing),
|
Dim MinecraftVersion = Addons("game")
|
||||||
.FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
|
If MinecraftVersion.EndsWithF(".0") Then MinecraftVersion = MinecraftVersion.Substring(0, MinecraftVersion.Length - 2)
|
||||||
}
|
Dim OptiFineFileSuffix = "_HD_" & Addons("optifine").AfterLast("HD_") & ".jar"
|
||||||
Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
|
'从镜像源拉取 OptiFine 列表
|
||||||
|
If DlOptiFineListBmclapiLoader.State <> LoadState.Finished Then DlOptiFineListBmclapiLoader.WaitForExit()
|
||||||
|
Dim Entry = DlOptiFineListBmclapiLoader.Output.Value.FirstOrDefault(
|
||||||
|
Function(v) v.Inherit = MinecraftVersion AndAlso v.FileName.EndsWithF(OptiFineFileSuffix))
|
||||||
|
If Entry Is Nothing Then Throw New Exception($"OptiFine 列表中没有整合包所需的 OptiFine {Addons("optifine")}(Minecraft {Addons("game")})")
|
||||||
|
OptiFineEntry = JObject.FromObject(Entry)
|
||||||
|
End If
|
||||||
|
Dim Target As New McComponents(Addons("game"), ModLoaderVersions, OptiFineEntry)
|
||||||
|
Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
|
||||||
|
.NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
|
||||||
|
.Components = Target})
|
||||||
'构造总加载器
|
'构造总加载器
|
||||||
Dim Loaders As New List(Of LoaderBase)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
|
||||||
@@ -748,7 +754,7 @@ Public Module ModModpack
|
|||||||
'启动
|
'启动
|
||||||
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
|
||||||
'If Archive IsNot Nothing Then Archive.Dispose() '解除占用,以免在加载器中触发 “正由另一进程使用,因此该进程无法访问此文件”
|
'If Archive IsNot Nothing Then Archive.Dispose() '解除占用,以免在加载器中触发 “正由另一进程使用,因此该进程无法访问此文件”
|
||||||
Loader.Start(Request.VersionFolder)
|
Loader.Start(VersionFolder)
|
||||||
LoaderTaskbarAdd(Loader)
|
LoaderTaskbarAdd(Loader)
|
||||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||||
Return Loader
|
Return Loader
|
||||||
|
|||||||
@@ -319,13 +319,16 @@ Public Module ModWatcher
|
|||||||
GetClassName(hwnd, str, str.Capacity)
|
GetClassName(hwnd, str, str.Capacity)
|
||||||
Dim ClassName As String = str.ToString
|
Dim ClassName As String = str.ToString
|
||||||
If Not (ClassName = "GLFW30" OrElse ClassName = "SDL_app" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Return
|
If Not (ClassName = "GLFW30" OrElse ClassName = "SDL_app" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Return
|
||||||
|
'SDL 会先创建隐藏窗口,待初始化完成后才显示(#9073)
|
||||||
|
If ClassName = "SDL_app" AndAlso Not IsWindowVisible(hwnd) Then Return
|
||||||
'获取窗口标题名
|
'获取窗口标题名
|
||||||
str = New StringBuilder(512)
|
str = New StringBuilder(512)
|
||||||
GetWindowText(hwnd, str, str.Capacity)
|
GetWindowText(hwnd, str, str.Capacity)
|
||||||
Dim WindowText As String = str.ToString
|
Dim WindowText As String = str.ToString
|
||||||
'有的 Mod 可以修改窗口标题,所以不能检测是否为 Minecraft 打头,这并不准确
|
'有的 Mod 可以修改窗口标题,所以不能检测是否为 Minecraft 打头,这并不准确
|
||||||
'部分版本会搞个 GLFW message window 出来所以得反选
|
'部分版本会搞个 GLFW message window,高版本还有个 Hidden Utility Window,都要反选
|
||||||
If Not (WindowText.StartsWithF("FML") OrElse (WindowText <> "PopupMessageWindow") AndAlso Not WindowText.StartsWithF("GLFW")) Then Return
|
If String.IsNullOrWhiteSpace(WindowText) OrElse WindowText = "SDL_app" OrElse WindowText = "PopupMessageWindow" OrElse
|
||||||
|
WindowText.StartsWithF("GLFW") OrElse WindowText.EndsWithF("Hidden Utility Window") Then Return
|
||||||
'获取窗口关联的进程
|
'获取窗口关联的进程
|
||||||
Dim ProcessId As Integer
|
Dim ProcessId As Integer
|
||||||
GetWindowThreadProcessId(hwnd, ProcessId)
|
GetWindowThreadProcessId(hwnd, ProcessId)
|
||||||
@@ -346,6 +349,7 @@ Public Module ModWatcher
|
|||||||
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (hWnd As Integer, str As StringBuilder, maxCount As Integer) As Integer
|
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (hWnd As Integer, str As StringBuilder, maxCount As Integer) As Integer
|
||||||
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (hWnd As Integer, str As String) As Boolean
|
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (hWnd As Integer, str As String) As Boolean
|
||||||
Private Declare Function ShowWindow Lib "user32" (hWnd As IntPtr, cmdWindow As UInteger) As Boolean
|
Private Declare Function ShowWindow Lib "user32" (hWnd As IntPtr, cmdWindow As UInteger) As Boolean
|
||||||
|
Private Declare Function IsWindowVisible Lib "user32" (hWnd As IntPtr) As Boolean
|
||||||
Private Declare Function GetWindowThreadProcessId Lib "user32" (hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
|
Private Declare Function GetWindowThreadProcessId Lib "user32" (hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
|
||||||
|
|
||||||
'崩溃处理
|
'崩溃处理
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#Region "附加属性"
|
#Region "附加属性"
|
||||||
|
|
||||||
|
Imports PCL.FormMain
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 用于在 XAML 中初始化列表对象。
|
''' 用于在 XAML 中初始化列表对象。
|
||||||
''' 附加属性无法在 XAML 中为每个对象初始化独立的列表对象,因此需要一个包装类,然后在 XAML 中显式初始化。
|
''' 附加属性无法在 XAML 中为每个对象初始化独立的列表对象,因此需要一个包装类,然后在 XAML 中显式初始化。
|
||||||
@@ -272,9 +275,23 @@ Public Class CustomEvent
|
|||||||
Hint(Arg0.Replace("\n", vbCrLf), If(Args.Length = 1, HintType.Blue, EnumUtils.FromString(Of HintType)(Arg1)))
|
Hint(Arg0.Replace("\n", vbCrLf), If(Args.Length = 1, HintType.Blue, EnumUtils.FromString(Of HintType)(Arg1)))
|
||||||
|
|
||||||
Case EventType.切换页面
|
Case EventType.切换页面
|
||||||
RunInUi(Sub() FrmMain.PageChange(
|
RunInUi(
|
||||||
EnumUtils.FromString(Of FormMain.PageType)(Arg0),
|
Sub()
|
||||||
If(Args.Length = 1, FormMain.PageSubType.Default, EnumUtils.FromString(Of FormMain.PageSubType)(Arg1))))
|
Dim TargetPage = EnumUtils.FromString(Of PageType)(Arg0)
|
||||||
|
If TargetPage = PageType.InstanceSetup Then
|
||||||
|
If McInstanceSelected Is Nothing Then
|
||||||
|
Hint("请先选择一个 Minecraft 版本!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
If McInstanceLock.IsLocked(McInstanceSelected) Then
|
||||||
|
Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
PageInstanceLeft.Instance = McInstanceSelected
|
||||||
|
End If
|
||||||
|
FrmMain.PageChange(TargetPage,
|
||||||
|
If(Args.Length = 1, PageSubType.Default, EnumUtils.FromString(Of PageSubType)(Arg1)))
|
||||||
|
End Sub)
|
||||||
|
|
||||||
Case EventType.导入整合包, EventType.安装整合包
|
Case EventType.导入整合包, EventType.安装整合包
|
||||||
RunInUi(Sub() ModpackInstall())
|
RunInUi(Sub() ModpackInstall())
|
||||||
@@ -295,7 +312,7 @@ Public Class CustomEvent
|
|||||||
Case 2
|
Case 2
|
||||||
PageOtherTest.StartCustomDownload(Arg0, Arg1)
|
PageOtherTest.StartCustomDownload(Arg0, Arg1)
|
||||||
Case Else
|
Case Else
|
||||||
PageOtherTest.StartCustomDownload(Arg0, Arg(1), Args(2))
|
PageOtherTest.StartCustomDownload(Arg0, Args(1), Args(2))
|
||||||
End Select
|
End Select
|
||||||
Catch
|
Catch
|
||||||
PageOtherTest.StartCustomDownload(Arg0, "未知")
|
PageOtherTest.StartCustomDownload(Arg0, "未知")
|
||||||
@@ -304,16 +321,16 @@ Public Class CustomEvent
|
|||||||
|
|
||||||
Case EventType.修改设置, EventType.写入设置
|
Case EventType.修改设置, EventType.写入设置
|
||||||
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 UiLauncherTransparent|400")
|
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 UiLauncherTransparent|400")
|
||||||
Settings.SetSafe(Arg0, Arg1, Instance:=McInstanceSelected)
|
Settings.SetSafe(Arg0, Args(1), Instance:=McInstanceSelected)
|
||||||
If Args.Length = 2 Then Hint($"已写入设置:{Arg0} → {Arg1}", HintType.Green)
|
If Args.Length = 2 Then Hint($"已写入设置:{Arg0} → {Args(1)}", HintType.Green)
|
||||||
|
|
||||||
Case EventType.修改变量, EventType.写入变量
|
Case EventType.修改变量, EventType.写入变量
|
||||||
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 VariableName|SomeValue")
|
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 VariableName|SomeValue")
|
||||||
Try
|
Try
|
||||||
RegistryUtils.Write($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{Arg0}", Arg1)
|
RegistryUtils.Write($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{Arg0}", Args(1))
|
||||||
If Args.Length = 2 Then Hint($"已写入变量:{Arg0} → {Arg1}", HintType.Green)
|
If Args.Length = 2 Then Hint($"已写入变量:{Arg0} → {Args(1)}", HintType.Green)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, $"写入变量失败:{Arg0} → {Arg1}", LogBehavior.Toast)
|
Logger.Warn(ex, $"写入变量失败:{Arg0} → {Args(1)}", LogBehavior.Toast)
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
Case EventType.加入房间
|
Case EventType.加入房间
|
||||||
@@ -353,7 +370,7 @@ Public Class CustomEvent
|
|||||||
Dim RawFileName As String
|
Dim RawFileName As String
|
||||||
Try
|
Try
|
||||||
RawFileName = PathUtils.GetLastPart(RelativeUrl)
|
RawFileName = PathUtils.GetLastPart(RelativeUrl)
|
||||||
If Not RawFileName.EndsWithF(".json", True) Then Throw New Exception("未指向 .json 后缀的文件")
|
If Not PathUtils.GetExtension(RawFileName) = "json" Then Throw New Exception("未指向 .json 后缀的文件")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Throw New Exception("联网帮助页面须指向一个帮助 JSON 文件,并在同路径下包含相应 XAML 文件!" & vbCrLf &
|
Throw New Exception("联网帮助页面须指向一个帮助 JSON 文件,并在同路径下包含相应 XAML 文件!" & vbCrLf &
|
||||||
"例如:" & vbCrLf &
|
"例如:" & vbCrLf &
|
||||||
|
|||||||
@@ -414,6 +414,7 @@ EndHint:
|
|||||||
Public FrmInstanceModDisabled As PageInstanceModDisabled
|
Public FrmInstanceModDisabled As PageInstanceModDisabled
|
||||||
Public FrmInstanceSetup As PageInstanceSetup
|
Public FrmInstanceSetup As PageInstanceSetup
|
||||||
Public FrmInstanceExport As PageInstanceExport
|
Public FrmInstanceExport As PageInstanceExport
|
||||||
|
Public FrmDownloadModify As PageDownloadModify
|
||||||
|
|
||||||
'资源信息分页声明
|
'资源信息分页声明
|
||||||
Public FrmDownloadResourceDetail As PageDownloadResourceDetail
|
Public FrmDownloadResourceDetail As PageDownloadResourceDetail
|
||||||
@@ -510,7 +511,7 @@ EndHint:
|
|||||||
EventData = If(JsonData("EventData"), "")
|
EventData = If(JsonData("EventData"), "")
|
||||||
IsEvent = True
|
IsEvent = True
|
||||||
Else
|
Else
|
||||||
Dim XamlAddress As String = FilePath.Lower.Replace(".json", ".xaml")
|
Dim XamlAddress As String = Path.ChangeExtension(FilePath, ".xaml")
|
||||||
If FileUtils.Exists(XamlAddress) Then
|
If FileUtils.Exists(XamlAddress) Then
|
||||||
XamlContent = FileUtils.ReadAsString(XamlAddress)
|
XamlContent = FileUtils.ReadAsString(XamlAddress)
|
||||||
IsEvent = False
|
IsEvent = False
|
||||||
@@ -596,9 +597,9 @@ EndHint:
|
|||||||
'读取自带文件
|
'读取自带文件
|
||||||
For Each File In DirectoryUtils.EnumerateFiles(PathTemp & "Help", True)
|
For Each File In DirectoryUtils.EnumerateFiles(PathTemp & "Help", True)
|
||||||
'跳过非 json 文件与以 . 开头的文件夹
|
'跳过非 json 文件与以 . 开头的文件夹
|
||||||
If PathUtils.RemoveLastPart(File).Replace(PathTemp & "Help", "").Contains("\.") OrElse PathUtils.GetExtension(File) <> "json" Then Continue For
|
If PathUtils.RemoveLastPart(File).Substring((PathTemp & "Help").Length).Contains("\.") OrElse PathUtils.GetExtension(File) <> "json" Then Continue For
|
||||||
'检查忽略列表
|
'检查忽略列表
|
||||||
Dim RealPath As String = File.Replace(PathTemp & "Help\", "")
|
Dim RealPath As String = File.Substring((PathTemp & "Help\").Length)
|
||||||
For Each Ignore In IgnoreList
|
For Each Ignore In IgnoreList
|
||||||
If RealPath.RegexCheck(Ignore) Then
|
If RealPath.RegexCheck(Ignore) Then
|
||||||
Logger.Trace($"已忽略 {RealPath}:{Ignore}")
|
Logger.Trace($"已忽略 {RealPath}:{Ignore}")
|
||||||
@@ -857,10 +858,10 @@ NextFile:
|
|||||||
Else
|
Else
|
||||||
Text = Text.Replace("{version}", Replacer(McInstanceSelected.Version.VanillaName))
|
Text = Text.Replace("{version}", Replacer(McInstanceSelected.Version.VanillaName))
|
||||||
End If
|
End If
|
||||||
Text = Text.Replace("{forge}", Replacer(If(McInstanceSelected.Version.HasForge, McInstanceSelected.Version.Forge, "")))
|
Text = Text.Replace("{forge}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Forge), McInstanceSelected.Version.ModLoaderVersions(ModLoaders.Forge), "")))
|
||||||
Text = Text.Replace("{fabric}", Replacer(If(McInstanceSelected.Version.HasFabric, McInstanceSelected.Version.Fabric, "")))
|
Text = Text.Replace("{fabric}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Fabric), McInstanceSelected.Version.ModLoaderVersions(ModLoaders.Fabric), "")))
|
||||||
Text = Text.Replace("{neoforge}", Replacer(If(McInstanceSelected.Version.HasNeoForge, McInstanceSelected.Version.NeoForge, "")))
|
Text = Text.Replace("{neoforge}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge), McInstanceSelected.Version.ModLoaderVersions(ModLoaders.NeoForge), "")))
|
||||||
Text = Text.Replace("{liteloader}", Replacer(If(McInstanceSelected.Version.HasLiteLoader, "true", "")))
|
Text = Text.Replace("{liteloader}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader), "true", "")))
|
||||||
Else
|
Else
|
||||||
Text = Text.Replace("{version_path}", Replacer(Nothing)) : Text = Text.Replace("{verpath}", Replacer(Nothing))
|
Text = Text.Replace("{version_path}", Replacer(Nothing)) : Text = Text.Replace("{verpath}", Replacer(Nothing))
|
||||||
Text = Text.Replace("{version_indie}", Replacer(Nothing)) : Text = Text.Replace("{verindie}", Replacer(Nothing))
|
Text = Text.Replace("{version_indie}", Replacer(Nothing)) : Text = Text.Replace("{verindie}", Replacer(Nothing))
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ Public Module ModMusic
|
|||||||
Hint("由于音频设备变更,音乐播放功能在重启 PCL 后才能恢复!", HintType.Red)
|
Hint("由于音频设备变更,音乐播放功能在重启 PCL 后才能恢复!", HintType.Red)
|
||||||
Thread.Sleep(1000000000)
|
Thread.Sleep(1000000000)
|
||||||
End If
|
End If
|
||||||
If Not (MusicCurrent.EndsWithF(".wav", True) OrElse MusicCurrent.EndsWithF(".mp3", True) OrElse MusicCurrent.EndsWithF(".flac", True)) OrElse
|
If Not ({"wav", "mp3", "flac"}.Contains(PathUtils.GetExtension(MusicCurrent))) OrElse
|
||||||
ex.Message.Contains("0xC00D36C4") Then '#5096:不支持给定的 URL 的字节流类型。 (异常来自 HRESULT:0xC00D36C4)
|
ex.Message.Contains("0xC00D36C4") Then '#5096:不支持给定的 URL 的字节流类型。 (异常来自 HRESULT:0xC00D36C4)
|
||||||
Hint("播放音乐失败(" & PathUtils.GetLastPart(MusicCurrent) & "):PCL 可能不支持此音乐格式,请将格式转换为 .wav、.mp3 或 .flac 后再试", HintType.Red)
|
Hint("播放音乐失败(" & PathUtils.GetLastPart(MusicCurrent) & "):PCL 可能不支持此音乐格式,请将格式转换为 .wav、.mp3 或 .flac 后再试", HintType.Red)
|
||||||
Else
|
Else
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Friend Module ModSecret
|
|||||||
|
|
||||||
#Region "网络鉴权"
|
#Region "网络鉴权"
|
||||||
|
|
||||||
|
Public Const RestrictMcDownload As Boolean = True
|
||||||
Friend Function SecretCdnSign(UrlWithMark As String) As String
|
Friend Function SecretCdnSign(UrlWithMark As String) As String
|
||||||
If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
|
If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
|
||||||
Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
|
Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Public Class LocalResourceFile
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 假若该资源未被禁用时,文件的文件名。
|
''' 假若该资源未被禁用时,文件的文件名。包含 .jar/.litemod 等后缀。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public ReadOnly Property EnabledName As String
|
Public ReadOnly Property EnabledName As String
|
||||||
Get
|
Get
|
||||||
@@ -57,7 +57,7 @@ Public Class LocalResourceFile
|
|||||||
Public Property Display As String
|
Public Property Display As String
|
||||||
Get
|
Get
|
||||||
If _Display Is Nothing Then _Display = ProjectVersion?.Display
|
If _Display Is Nothing Then _Display = ProjectVersion?.Display
|
||||||
If _Display Is Nothing Then _Display = PathUtils.GetFileNameWithoutExtension(File.FullName)
|
If _Display Is Nothing Then _Display = PathUtils.GetFileNameWithoutExtension(EnabledName)
|
||||||
Return _Display
|
Return _Display
|
||||||
End Get
|
End Get
|
||||||
Set(value As String)
|
Set(value As String)
|
||||||
@@ -238,7 +238,7 @@ Public Class LocalResourceFile
|
|||||||
Private _CurseForgeHash As UInteger?
|
Private _CurseForgeHash As UInteger?
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取用于 Modrinth 信息获取的 Hash 值(SHA1)。
|
''' 获取用于 Modrinth 信息获取的 Hash 值(SHA1)。固定为小写。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public ReadOnly Property ModrinthHash As String
|
Public ReadOnly Property ModrinthHash As String
|
||||||
Get
|
Get
|
||||||
@@ -269,7 +269,7 @@ Public Class LocalResourceFile
|
|||||||
End Function
|
End Function
|
||||||
Public Overrides Function Equals(obj As Object) As Boolean
|
Public Overrides Function Equals(obj As Object) As Boolean
|
||||||
Dim Target = TryCast(obj, LocalResourceFile)
|
Dim Target = TryCast(obj, LocalResourceFile)
|
||||||
Return Target IsNot Nothing AndAlso File.FullName = Target.File.FullName
|
Return Target IsNot Nothing AndAlso PathUtils.IsSame(File.FullName, Target.File.FullName)
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -24,11 +24,10 @@ Public Module LocalResourceLoaders
|
|||||||
'获取 Mod 文件夹下的可用文件列表
|
'获取 Mod 文件夹下的可用文件列表
|
||||||
Dim ModFileList As New List(Of String)
|
Dim ModFileList As New List(Of String)
|
||||||
If DirectoryUtils.Exists(Loader.Input) Then
|
If DirectoryUtils.Exists(Loader.Input) Then
|
||||||
Dim RawName As String = Loader.Input.Lower
|
|
||||||
For Each File In DirectoryUtils.EnumerateFiles(Loader.Input, True)
|
For Each File In DirectoryUtils.EnumerateFiles(Loader.Input, True)
|
||||||
If File.BeforeLast("\").Lower & "\" <> RawName Then
|
If Not PathUtils.IsSame(PathUtils.RemoveLastPart(File), Loader.Input) Then
|
||||||
'仅当 Forge 1.13- 且文件夹名与版本号相同时,才加载该子文件夹下的 Mod
|
'仅当 Forge 1.13- 且文件夹名与版本号相同时,才加载该子文件夹下的 Mod
|
||||||
If Not (PageInstanceLeft.Instance IsNot Nothing AndAlso PageInstanceLeft.Instance.Version.HasForge AndAlso
|
If Not (PageInstanceLeft.Instance IsNot Nothing AndAlso PageInstanceLeft.Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) AndAlso
|
||||||
PageInstanceLeft.Instance.Version.Vanilla.Major < 13 AndAlso
|
PageInstanceLeft.Instance.Version.Vanilla.Major < 13 AndAlso
|
||||||
PathUtils.GetLastPart(PathUtils.RemoveLastPart(File)) = $"1.{PageInstanceLeft.Instance.Version.Vanilla.Major}.{PageInstanceLeft.Instance.Version.Vanilla.Build}") Then
|
PathUtils.GetLastPart(PathUtils.RemoveLastPart(File)) = $"1.{PageInstanceLeft.Instance.Version.Vanilla.Major}.{PageInstanceLeft.Instance.Version.Vanilla.Build}") Then
|
||||||
Continue For
|
Continue For
|
||||||
@@ -36,12 +35,9 @@ Public Module LocalResourceLoaders
|
|||||||
End If
|
End If
|
||||||
Static IsModFile As Func(Of String, Boolean) =
|
Static IsModFile As Func(Of String, Boolean) =
|
||||||
Function(FullName As String)
|
Function(FullName As String)
|
||||||
If FullName Is Nothing OrElse Not FullName.Contains(".") Then Return False
|
If FullName Is Nothing Then Return False
|
||||||
FullName = FullName.Lower
|
If {"disabled", "old"}.Contains(PathUtils.GetExtension(FullName)) Then FullName = PathUtils.GetFileNameWithoutExtension(FullName)
|
||||||
If FullName.EndsWithF(".jar", True) OrElse FullName.EndsWithF(".zip", True) OrElse FullName.EndsWithF(".litemod", True) OrElse
|
Return {"jar", "zip", "litemod"}.Contains(PathUtils.GetExtension(FullName))
|
||||||
FullName.EndsWithF(".jar.disabled", True) OrElse FullName.EndsWithF(".zip.disabled", True) OrElse FullName.EndsWithF(".litemod.disabled", True) OrElse
|
|
||||||
FullName.EndsWithF(".jar.old", True) OrElse FullName.EndsWithF(".zip.old", True) OrElse FullName.EndsWithF(".litemod.old", True) Then Return True
|
|
||||||
Return False
|
|
||||||
End Function
|
End Function
|
||||||
If IsModFile(File) Then ModFileList.Add(File)
|
If IsModFile(File) Then ModFileList.Add(File)
|
||||||
Next
|
Next
|
||||||
@@ -271,7 +267,7 @@ Public Module LocalResourceLoaders
|
|||||||
Dim EntryVersion As String = Entry("gameVersion")
|
Dim EntryVersion As String = Entry("gameVersion")
|
||||||
Return EntryVersion IsNot Nothing AndAlso EntryVersion = VanillaVersion
|
Return EntryVersion IsNot Nothing AndAlso EntryVersion = VanillaVersion
|
||||||
End Function).
|
End Function).
|
||||||
MaxByAll(Function(Entry) Entry("gameVersion").ToString, New VersionComparer) '只保留最新的 MC 版本
|
MaxByAll(Function(Entry) Entry("gameVersion").ToString, Comparer(Of String).Create(Function(x, y) McUtils.CompareVersion(x, y))) '只保留最新的 MC 版本
|
||||||
For Each Entry In LatestFiles
|
For Each Entry In LatestFiles
|
||||||
Dim FileId = Entry("fileId").ToObject(Of Integer)
|
Dim FileId = Entry("fileId").ToObject(Of Integer)
|
||||||
If Not UpdateFileIds.ContainsKey(FileId) Then UpdateFileIds(FileId) = New List(Of LocalResourceFile)
|
If Not UpdateFileIds.ContainsKey(FileId) Then UpdateFileIds(FileId) = New List(Of LocalResourceFile)
|
||||||
|
|||||||
@@ -184,11 +184,11 @@ Public Class ResourceProject
|
|||||||
If Not NewFile.DownloadAvailable Then Continue For
|
If Not NewFile.DownloadAvailable Then Continue For
|
||||||
ModLoaders = ModLoaders Or NewFile.ModLoaders
|
ModLoaders = ModLoaders Or NewFile.ModLoaders
|
||||||
Dim GameVersions = File("gameVersions").ToObject(Of List(Of String))
|
Dim GameVersions = File("gameVersions").ToObject(Of List(Of String))
|
||||||
If Not GameVersions.Any(Function(v) McVersion.IsFormatFit(v)) Then Continue For
|
If Not GameVersions.Any(Function(v) McVersion.IsStandardFormat(v)) Then Continue For
|
||||||
Files.Add(New KeyValuePair(Of Integer, List(Of String))(File("id"), GameVersions))
|
Files.Add(New KeyValuePair(Of Integer, List(Of String))(File("id"), GameVersions))
|
||||||
Next
|
Next
|
||||||
For Each File In If(Data("latestFilesIndexes"), New JArray) '这俩玩意儿包含的文件不一样,见 #3599
|
For Each File In If(Data("latestFilesIndexes"), New JArray) '这俩玩意儿包含的文件不一样,见 #3599
|
||||||
If Not McVersion.IsFormatFit(File("gameVersion")) Then Continue For
|
If Not McVersion.IsStandardFormat(File("gameVersion")) Then Continue For
|
||||||
Files.Add(New KeyValuePair(Of Integer, List(Of String))(File("fileId"), {File("gameVersion").ToString}.ToList))
|
Files.Add(New KeyValuePair(Of Integer, List(Of String))(File("fileId"), {File("gameVersion").ToString}.ToList))
|
||||||
Next
|
Next
|
||||||
CurseForgeFileIds = Files.Select(Function(f) f.Key).Distinct.ToList
|
CurseForgeFileIds = Files.Select(Function(f) f.Key).Distinct.ToList
|
||||||
|
|||||||
@@ -99,12 +99,12 @@ Public Class ResourceSearcher
|
|||||||
Dim Address As String = $"https://api.modrinth.com/v2/search?limit={RESULT_PAGE_SIZE}&index=relevance"
|
Dim Address As String = $"https://api.modrinth.com/v2/search?limit={RESULT_PAGE_SIZE}&index=relevance"
|
||||||
If Not String.IsNullOrEmpty(SearchText) Then Address += "&query=" & StringUtils.UrlEscape(SearchText)
|
If Not String.IsNullOrEmpty(SearchText) Then Address += "&query=" & StringUtils.UrlEscape(SearchText)
|
||||||
If Storage.ModrinthOffset > 0 Then Address += "&offset=" & Storage.ModrinthOffset
|
If Storage.ModrinthOffset > 0 Then Address += "&offset=" & Storage.ModrinthOffset
|
||||||
'facets=[["categories:'game-mechanics'"],["categories:'forge',categories:'fabric'"],["versions:1.19.3"],["project_type:mod"]]
|
'facets=[["categories:'game-mechanics'"],["categories:forge","categories:fabric"],["versions:1.19.3"],["project_type:mod"]]
|
||||||
Dim Facets As New List(Of String)
|
Dim Facets As New List(Of String)
|
||||||
Facets.Add($"[""project_type:{Type.ToString.Lower}""]")
|
Facets.Add($"[""project_type:{Type.ToString.Lower}""]")
|
||||||
If Not String.IsNullOrEmpty(Tag) Then Facets.Add($"[""categories:'{Tag.AfterLast("/")}'""]")
|
If Not String.IsNullOrEmpty(Tag) Then Facets.Add($"[""categories:'{Tag.AfterLast("/")}'""]")
|
||||||
If ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter Then
|
If ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter Then
|
||||||
Facets.Add($"[""categories:'{ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join("',categories:'")}'""]")
|
Facets.Add($"[""categories:{ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join(""",""categories:")}""]")
|
||||||
End If
|
End If
|
||||||
If Not String.IsNullOrEmpty(GameVersion) Then Facets.Add($"[""versions:'{GameVersion}'""]")
|
If Not String.IsNullOrEmpty(GameVersion) Then Facets.Add($"[""versions:'{GameVersion}'""]")
|
||||||
Address += "&facets=[" & String.Join(",", Facets) & "]"
|
Address += "&facets=[" & String.Join(",", Facets) & "]"
|
||||||
@@ -378,21 +378,19 @@ NextPage:
|
|||||||
If Request.Type <> ResourceTypes.Any AndAlso Not Project.Types.HasFlagF(Request.Type) Then Continue For
|
If Request.Type <> ResourceTypes.Any AndAlso Not Project.Types.HasFlagF(Request.Type) Then Continue For
|
||||||
If Not String.IsNullOrEmpty(Request.Tag) AndAlso
|
If Not String.IsNullOrEmpty(Request.Tag) AndAlso
|
||||||
Not JsonEntry("categories").Any(Function(c) c.ToString = Request.Tag.AfterLast("/")) Then Continue For 'Project.Tags 已经转换成中文了,只能从 json 判
|
Not JsonEntry("categories").Any(Function(c) c.ToString = Request.Tag.AfterLast("/")) Then Continue For 'Project.Tags 已经转换成中文了,只能从 json 判
|
||||||
|
If Request.ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter AndAlso
|
||||||
|
Not Project.ModLoaders.Flags.Intersect(Request.ModLoaders.Flags).Any() Then Continue For
|
||||||
|
If Not String.IsNullOrEmpty(Request.GameVersion) AndAlso
|
||||||
|
Not Project.UnsafeGameVersions.Any(Function(d) d = Request.GameVersion) Then Continue For
|
||||||
ProjectList.Add(Project)
|
ProjectList.Add(Project)
|
||||||
Next
|
Next
|
||||||
Dim Facets As New List(Of String)
|
If ProjectList.Any AndAlso Request.ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter AndAlso
|
||||||
If Request.ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter Then
|
Not String.IsNullOrEmpty(Request.GameVersion) Then
|
||||||
Facets.Add($"[""categories:'{Request.ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join("'"",""categories:'")}'""]")
|
Dim ProjectIds = ProjectList.Select(Function(p) p.Id).Join(""",""project_id:")
|
||||||
End If
|
Dim Loaders = Request.ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join(""",""categories:")
|
||||||
If Not String.IsNullOrEmpty(Request.GameVersion) Then Facets.Add($"[""versions:'{Request.GameVersion}'""]")
|
Dim FilterUrl = $"https://api.modrinth.com/v2/search?limit={ProjectList.Count}&facets=" &
|
||||||
If ProjectList.Any AndAlso Facets.Any Then
|
$"[[""project_id:{ProjectIds}""],[""categories:{Loaders}""],[""versions:{Request.GameVersion}""]]"
|
||||||
Facets.Add("[""project_id:" & ProjectList.Select(Function(p) p.Id).Join(""",""project_id:") & """]")
|
Dim MatchedIds = DlModRequest(FilterUrl)("hits").Select(Function(h) h("project_id").ToString).ToList
|
||||||
Dim FilterUrl As String = $"https://api.modrinth.com/v2/search?limit={Math.Min(ProjectList.Count, 100)}&facets=[" & String.Join(",", Facets) & "]"
|
|
||||||
Logger.Info($"开始 Modrinth 直接获取筛选:{FilterUrl}")
|
|
||||||
Dim MatchedIds As New List(Of String)
|
|
||||||
For Each JsonEntry As JObject In DlModRequest(FilterUrl)("hits")
|
|
||||||
MatchedIds.Add(JsonEntry("project_id").ToString)
|
|
||||||
Next
|
|
||||||
ProjectList.KeepIf(Function(p) MatchedIds.Contains(p.Id))
|
ProjectList.KeepIf(Function(p) MatchedIds.Contains(p.Id))
|
||||||
End If
|
End If
|
||||||
'更新结果
|
'更新结果
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Public Class ResourceVersion
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public DownloadUrls As List(Of String)
|
Public DownloadUrls As List(Of String)
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 对应文件的 SHA1 或 MD5。
|
''' 对应文件的 SHA1 或 MD5。固定为小写。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Hash As String = Nothing
|
Public Hash As String = Nothing
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -127,8 +127,9 @@ Public Class ResourceVersion
|
|||||||
.DownloadCount = Data("downloadCount")
|
.DownloadCount = Data("downloadCount")
|
||||||
.FileName = Data("fileName")
|
.FileName = Data("fileName")
|
||||||
.Size = Data("fileLength")
|
.Size = Data("fileLength")
|
||||||
.Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 1)?("value")
|
If .Size = 0 Then .Size = -1 'CurseForge 可能错误地返回 0 尺寸(#9104)
|
||||||
If .Hash Is Nothing Then .Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 2)?("value")
|
.Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 1)?("value")?.ToString().Lower()
|
||||||
|
If .Hash Is Nothing Then .Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 2)?("value")?.ToString().Lower()
|
||||||
'DownloadAddress
|
'DownloadAddress
|
||||||
Dim Url = Data("downloadUrl").ToString
|
Dim Url = Data("downloadUrl").ToString
|
||||||
If Url = "" Then Url = $"https://edge.forgecdn.net/files/{CInt(.Id.ToString.Substring(0, 4))}/{CInt(.Id.ToString.Substring(4))}/{ .FileName}"
|
If Url = "" Then Url = $"https://edge.forgecdn.net/files/{CInt(.Id.ToString.Substring(0, 4))}/{CInt(.Id.ToString.Substring(4))}/{ .FileName}"
|
||||||
@@ -145,13 +146,13 @@ Public Class ResourceVersion
|
|||||||
'GameVersions
|
'GameVersions
|
||||||
Dim RawVersions As List(Of String) = Data("gameVersions").Select(Function(t) t.ToString.Trim.Lower).ToList
|
Dim RawVersions As List(Of String) = Data("gameVersions").Select(Function(t) t.ToString.Trim.Lower).ToList
|
||||||
.GameVersions = RawVersions.
|
.GameVersions = RawVersions.
|
||||||
Where(Function(v) McVersion.IsFormatFit(v)).
|
Where(Function(v) McVersion.IsStandardFormat(v)).
|
||||||
Select(Function(v) v.Replace("-snapshot", " 预览版")).
|
Select(Function(v) v.Replace("-snapshot", " 预览版")).
|
||||||
Distinct.ToList
|
Distinct.ToList
|
||||||
If .GameVersions.IsSingle Then
|
If .GameVersions.IsSingle Then
|
||||||
.GameVersions = .GameVersions.ToList
|
.GameVersions = .GameVersions.ToList
|
||||||
ElseIf .GameVersions.Count > 1 Then
|
ElseIf .GameVersions.Count > 1 Then
|
||||||
.GameVersions = .GameVersions.SortByComparison(AddressOf CompareVersionGE).ToList
|
.GameVersions = .GameVersions.SortByComparison(AddressOf McUtils.CompareVersionGE).ToList
|
||||||
If .ResourceType = ResourceTypes.ModPack Then .GameVersions = { .GameVersions(0)}.ToList '整合包理应只 “支持” 一个版本
|
If .ResourceType = ResourceTypes.ModPack Then .GameVersions = { .GameVersions(0)}.ToList '整合包理应只 “支持” 一个版本
|
||||||
Else
|
Else
|
||||||
.GameVersions = New List(Of String) From {"未知版本"}
|
.GameVersions = New List(Of String) From {"未知版本"}
|
||||||
@@ -176,7 +177,7 @@ Public Class ResourceVersion
|
|||||||
.FileName = File("filename")
|
.FileName = File("filename")
|
||||||
.DownloadUrls = New List(Of String) From {File("url"), DlSourceModGet(File("url"))}.Distinct.ToList '同时添加了镜像源
|
.DownloadUrls = New List(Of String) From {File("url"), DlSourceModGet(File("url"))}.Distinct.ToList '同时添加了镜像源
|
||||||
.Size = File("size")
|
.Size = File("size")
|
||||||
.Hash = File("hashes")("sha1")
|
.Hash = File("hashes")("sha1")?.ToString.Lower()
|
||||||
End If
|
End If
|
||||||
'类别与 Loaders
|
'类别与 Loaders
|
||||||
'结果可能混杂着 Mod、数据包和服务端插件
|
'结果可能混杂着 Mod、数据包和服务端插件
|
||||||
@@ -208,7 +209,7 @@ Public Class ResourceVersion
|
|||||||
If .GameVersions.IsSingle Then
|
If .GameVersions.IsSingle Then
|
||||||
'无需处理
|
'无需处理
|
||||||
ElseIf .GameVersions.Count > 1 Then
|
ElseIf .GameVersions.Count > 1 Then
|
||||||
.GameVersions = .GameVersions.SortByComparison(AddressOf CompareVersionGE).ToList
|
.GameVersions = .GameVersions.SortByComparison(AddressOf McUtils.CompareVersionGE).ToList
|
||||||
If .ResourceType = ResourceTypes.ModPack Then .GameVersions = New List(Of String) From { .GameVersions(0)} '整合包理应只 “支持” 一个版本
|
If .ResourceType = ResourceTypes.ModPack Then .GameVersions = New List(Of String) From { .GameVersions(0)} '整合包理应只 “支持” 一个版本
|
||||||
ElseIf RawVersions.Any(Function(v) v.RegexCheck("[0-9]{2}w[0-9]{2}[a-z]")) Then
|
ElseIf RawVersions.Any(Function(v) v.RegexCheck("[0-9]{2}w[0-9]{2}[a-z]")) Then
|
||||||
.GameVersions = RawVersions.Where(Function(v) v.RegexCheck("[0-9]{2}w[0-9]{2}[a-z]")).ToList
|
.GameVersions = RawVersions.Where(Function(v) v.RegexCheck("[0-9]{2}w[0-9]{2}[a-z]")).ToList
|
||||||
@@ -355,7 +356,7 @@ Public Class ResourceVersion
|
|||||||
.Info =
|
.Info =
|
||||||
Iterator Function()
|
Iterator Function()
|
||||||
If ModLoaders <> ModLoaders.None Then Yield ModLoaders.Flags.Join("、"c)
|
If ModLoaders <> ModLoaders.None Then Yield ModLoaders.Flags.Join("、"c)
|
||||||
If .Title <> FileName.BeforeLast(".") Then Yield FileName.BeforeLast(".")
|
If .Title <> PathUtils.GetFileNameWithoutExtension(FileName) Then Yield PathUtils.GetFileNameWithoutExtension(FileName)
|
||||||
If Dependencies.Any Then Yield $"{Dependencies.Count} 项前置"
|
If Dependencies.Any Then Yield $"{Dependencies.Count} 项前置"
|
||||||
If GameVersions.All(Function(v) Not v.Contains(".") OrElse {"w", "snapshot", "rc", "pre", "experimental", "-"}.Any(Function(s) v.ContainsIgnoreCase(s))) Then Yield $"游戏版本 {GameVersions.Join("、"c)}"
|
If GameVersions.All(Function(v) Not v.Contains(".") OrElse {"w", "snapshot", "rc", "pre", "experimental", "-"}.Any(Function(s) v.ContainsIgnoreCase(s))) Then Yield $"游戏版本 {GameVersions.Join("、"c)}"
|
||||||
If DownloadCount > 0 Then Yield $"下载 {If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万", DownloadCount.ToString() + " ")}次" 'CurseForge 的下载次数经常错误地返回 0
|
If DownloadCount > 0 Then Yield $"下载 {If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万", DownloadCount.ToString() + " ")}次" 'CurseForge 的下载次数经常错误地返回 0
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ Imports System.Runtime.InteropServices
|
|||||||
|
|
||||||
'查看程序集特性的值
|
'查看程序集特性的值
|
||||||
|
|
||||||
<Assembly: AssemblyTitle("Plain Craft Launcher 启动器")>
|
<Assembly: AssemblyTitle("Plain Craft Launcher (PCL) InfstarMC Edition")>
|
||||||
<Assembly: AssemblyDescription("Minecraft 启动器")>
|
<Assembly: AssemblyDescription("InfstarMC 基于 PCL 独立进行的第三方 Minecraft 启动器")>
|
||||||
<Assembly: AssemblyCompany("")>
|
<Assembly: AssemblyCompany("InfstarMC")>
|
||||||
<Assembly: AssemblyProduct("Plain Craft Launcher")>
|
<Assembly: AssemblyProduct("Plain Craft Launcher (PCL) InfstarMC Edition")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 成都瓜皮龙科技有限公司")>
|
<Assembly: AssemblyCopyright("Copyright © 成都瓜皮龙科技有限公司")>
|
||||||
<Assembly: AssemblyConfiguration("PCL2 Config Mark")>
|
<Assembly: AssemblyConfiguration("PCL2 Config Mark")>
|
||||||
<Assembly: ComVisible(False)>
|
<Assembly: ComVisible(False)>
|
||||||
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||||
' 方法是按如下所示使用“*”
|
' 方法是按如下所示使用“*”
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2.13.1.1")>
|
<Assembly: AssemblyVersion("0.1.0")>
|
||||||
<Assembly: AssemblyFileVersion("2.13.1.1")>
|
<Assembly: AssemblyFileVersion("0.1.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("")>
|
<Assembly: NeutralResourcesLanguage("")>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
<local:MyPageRight
|
<local:MyPageRight
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
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"
|
mc:Ignorable="d" x:Class="PageDownloadInstall"
|
||||||
PanScroll="PanBack">
|
PanScroll="PanBack">
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -14,19 +14,96 @@
|
|||||||
</StackPanel.RenderTransform>
|
</StackPanel.RenderTransform>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="1" x:Name="PanSelect" Visibility="Collapsed" Opacity="0" IsHitTestVisible="False" Margin="0,0,0,45">
|
<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>
|
<StackPanel.RenderTransform>
|
||||||
<TranslateTransform X="40" />
|
<TranslateTransform X="40" />
|
||||||
</StackPanel.RenderTransform>
|
</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"
|
<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" />
|
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:MyImage x:Name="ImgLogo" Margin="52,15,0,0" VerticalAlignment="Top" 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: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: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="如果不安装 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="必须安装 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="安装结束后,请在 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: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">
|
<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" />
|
<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">
|
<Grid x:Name="PanForgeInfo" Height="18" Margin="132,11,15,0" VerticalAlignment="Top" Tag="True">
|
||||||
@@ -37,13 +114,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabForge" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnForgeClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanForgeCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnForgeClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
||||||
<local:MyCard Title="NeoForge" Height="40" Margin="0,12,0,0" x:Name="CardNeoForge" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
<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" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanNeoForge" />
|
||||||
@@ -55,13 +144,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabNeoForge" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnNeoForgeClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanNeoForgeCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnNeoForgeClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
||||||
<local:MyCard Title="Fabric" Height="40" Margin="0,12,0,0" x:Name="CardFabric" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
<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" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabric" />
|
||||||
@@ -73,13 +174,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabFabric" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnFabricClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanFabricCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnFabricClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
||||||
<local:MyCard Title="Fabric API" Height="40" Margin="0,12,0,0" x:Name="CardFabricApi" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
<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" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabricApi" />
|
||||||
@@ -91,13 +204,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabFabricApi" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnFabricApiClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanFabricApiCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnFabricApiClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
||||||
<local:MyCard Title="OptiFine" Height="40" Margin="0,12,0,0" x:Name="CardOptiFine" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
<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">
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top">
|
||||||
@@ -111,13 +236,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabOptiFine" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnOptiFineClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanOptiFineCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnOptiFineClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
||||||
<local:MyCard Title="OptiFabric" Height="40" Margin="0,12,0,0" x:Name="CardOptiFabric" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
<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" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanOptiFabric" />
|
||||||
@@ -129,13 +266,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabOptiFabric" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnOptiFabricClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanOptiFabricCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnOptiFabricClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
||||||
<local:MyCard Title="LiteLoader" Height="40" Margin="0,12,0,0" x:Name="CardLiteLoader" IsSwapped="True" CanSwap="True" SwapLogoRight="True">
|
<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" />
|
<StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanLiteLoader" />
|
||||||
@@ -147,13 +296,25 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="1*" />
|
<ColumnDefinition Width="1*" />
|
||||||
</Grid.ColumnDefinitions>
|
</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" />
|
<TextBlock x:Name="LabLiteLoader" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Grid.Column="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid x:Name="BtnLiteLoaderClear" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,32,0" Background="{StaticResource ColorBrushSemiTransparent}">
|
<Grid x:Name="PanLiteLoaderCompare" Height="18" Margin="132,11,80,0" VerticalAlignment="Top" Visibility="Collapsed" IsHitTestVisible="False">
|
||||||
<Path x:Name="BtnLiteLoaderClearInner" Height="10" Width="10" Stretch="Uniform" Fill="{StaticResource ColorBrushGray1}" HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Grid.ColumnDefinitions>
|
||||||
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" />
|
<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>
|
</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>
|
</local:MyCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</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" />
|
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>
|
</Grid>
|
||||||
<local:MyCard HorizontalAlignment="Center" VerticalAlignment="Center" Margin="40,0" SnapsToDevicePixels="True" x:Name="PanLoad" UseAnimation="False">
|
<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="LoadOptiFine" HasAnimation="False" />
|
||||||
<local:MyLoading Visibility="Collapsed" x:Name="LoadForge" HasAnimation="False" />
|
<local:MyLoading Visibility="Collapsed" x:Name="LoadForge" HasAnimation="False" />
|
||||||
<local:MyLoading Visibility="Collapsed" x:Name="LoadNeoForge" HasAnimation="False" />
|
<local:MyLoading Visibility="Collapsed" x:Name="LoadNeoForge" HasAnimation="False" />
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
Public Class PageDownloadInstall
|
Public Class PageDownloadInstall
|
||||||
|
|
||||||
Private Sub LoaderInit() Handles Me.Initialized
|
Public Sub ControlInit()
|
||||||
DisabledPageAnimControls.Add(BtnStart)
|
DisabledPageAnimControls.Add(BtnStart)
|
||||||
PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, DlClientListLoader, AddressOf LoadMinecraft_OnFinish)
|
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()
|
||||||
|
If RestrictMcDownload Then
|
||||||
|
PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, New LoaderTask(Of String, DlClientListResult)("关闭下载", Sub() Throw New Exception("为遵守相关法律法规,PCL 暂时不再提供 MC 下载功能,非常抱歉 qwq……")), AddressOf LoadMinecraft_OnFinish)
|
||||||
|
Else
|
||||||
|
PageLoaderInit(LoadMinecraft, PanLoad, PanAllBack, Nothing, DlClientListLoader, AddressOf LoadMinecraft_OnFinish)
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private IsLoad As Boolean = False
|
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()
|
PanBack.ScrollToHome()
|
||||||
DlOptiFineListLoader.Start()
|
DlOptiFineListLoader.Start()
|
||||||
DlLiteLoaderListLoader.Start()
|
DlLiteLoaderListLoader.Start()
|
||||||
@@ -17,35 +39,19 @@ Public Class PageDownloadInstall
|
|||||||
TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {New ValidateFolderName(McFolderSelected & "versions")}
|
TextSelectName.ValidateRules = New ObjectModel.Collection(Of Validate) From {New ValidateFolderName(McFolderSelected & "versions")}
|
||||||
TextSelectName.Validate()
|
TextSelectName.Validate()
|
||||||
ReloadSelected()
|
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
|
End Sub
|
||||||
|
|
||||||
#Region "页面切换"
|
#Region "页面切换"
|
||||||
|
|
||||||
'页面切换动画
|
'页面切换动画
|
||||||
Public IsInSelectPage As Boolean = False
|
Public IsInSelectPage As Boolean = False
|
||||||
Private IsFirstLoaded As Boolean = False
|
|
||||||
Private Sub EnterSelectPage()
|
''' <summary>
|
||||||
If IsInSelectPage Then Return
|
''' 选择页面 UI 初始化。
|
||||||
|
''' </summary>
|
||||||
|
Public Sub PrepareSelectPage()
|
||||||
IsInSelectPage = True
|
IsInSelectPage = True
|
||||||
|
|
||||||
PanInner.Margin = New Thickness(25, 10, 25, 40)
|
PanInner.Margin = New Thickness(25, 10, 25, 40)
|
||||||
|
|
||||||
AutoSelectedFabricApi = False
|
|
||||||
AutoSelectedOptiFabric = False
|
|
||||||
IsSelectNameEdited = False
|
|
||||||
PanSelect.Visibility = Visibility.Visible
|
PanSelect.Visibility = Visibility.Visible
|
||||||
PanSelect.IsHitTestVisible = True
|
PanSelect.IsHitTestVisible = True
|
||||||
PanMinecraft.IsHitTestVisible = False
|
PanMinecraft.IsHitTestVisible = False
|
||||||
@@ -54,13 +60,9 @@ Public Class PageDownloadInstall
|
|||||||
|
|
||||||
DisabledPageAnimControls.Remove(BtnStart)
|
DisabledPageAnimControls.Remove(BtnStart)
|
||||||
BtnStart.Show = True
|
BtnStart.Show = True
|
||||||
CardOptiFine.IsSwapped = True
|
For Each Card In {CardOptiFine, CardLiteLoader, CardForge, CardNeoForge, CardFabric, CardFabricApi, CardOptiFabric}
|
||||||
CardLiteLoader.IsSwapped = True
|
Card.IsSwapped = True
|
||||||
CardForge.IsSwapped = True
|
Next
|
||||||
CardNeoForge.IsSwapped = True
|
|
||||||
CardFabric.IsSwapped = True
|
|
||||||
CardFabricApi.IsSwapped = True
|
|
||||||
CardOptiFabric.IsSwapped = True
|
|
||||||
|
|
||||||
'如果在选择页面按了刷新键,选择页的东西可能会由于动画被隐藏,但不会由于加载结束而再次显示,因此这里需要手动恢复
|
'如果在选择页面按了刷新键,选择页的东西可能会由于动画被隐藏,但不会由于加载结束而再次显示,因此这里需要手动恢复
|
||||||
For Each Control In GetAllAnimControls(PanSelect)
|
For Each Control In GetAllAnimControls(PanSelect)
|
||||||
@@ -69,9 +71,16 @@ Public Class PageDownloadInstall
|
|||||||
Control.RenderTransform = New TranslateTransform
|
Control.RenderTransform = New TranslateTransform
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub EnterSelectPage()
|
||||||
|
If IsInSelectPage Then Return
|
||||||
|
AutoSelectedFabricApi = False
|
||||||
|
AutoSelectedOptiFabric = False
|
||||||
|
PrepareSelectPage()
|
||||||
|
|
||||||
'启动 Forge 加载
|
'启动 Forge 加载
|
||||||
If McVersion.IsFormatFit(VanillaName) Then
|
If McVersion.IsStandardFormat(VanillaName) Then
|
||||||
Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("DlForgeVersion " & VanillaName, AddressOf DlForgeVersionMain)
|
Dim ForgeLoader = New LoaderTask(Of String, List(Of DlForgeVersionEntry))("DlForgeVersion " & VanillaName, AddressOf DlForgeVersionMain)
|
||||||
LoadForge.State = ForgeLoader
|
LoadForge.State = ForgeLoader
|
||||||
ForgeLoader.Start(VanillaName)
|
ForgeLoader.Start(VanillaName)
|
||||||
@@ -87,35 +96,27 @@ Public Class PageDownloadInstall
|
|||||||
AaCode(
|
AaCode(
|
||||||
Sub()
|
Sub()
|
||||||
PanBack.ScrollToHome()
|
PanBack.ScrollToHome()
|
||||||
TextSelectName.Validate()
|
ReloadComponentLists()
|
||||||
OptiFine_Loaded()
|
|
||||||
LiteLoader_Loaded()
|
|
||||||
Forge_Loaded()
|
|
||||||
NeoForge_Loaded()
|
|
||||||
Fabric_Loaded()
|
|
||||||
FabricApi_Loaded()
|
|
||||||
OptiFabric_Loaded()
|
|
||||||
ReloadSelected()
|
|
||||||
PanMinecraft.Visibility = Visibility.Collapsed
|
PanMinecraft.Visibility = Visibility.Collapsed
|
||||||
End Sub, After:=True),
|
End Sub, After:=True),
|
||||||
AaOpacity(PanSelect, 1 - PanSelect.Opacity, 70, 100),
|
AaOpacity(PanSelect, 1 - PanSelect.Opacity, 70, 100),
|
||||||
AaTranslateX(PanSelect, -CType(PanSelect.RenderTransform, TranslateTransform).X, 160, 100, Ease:=New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
AaTranslateX(PanSelect, -CType(PanSelect.RenderTransform, TranslateTransform).X, 160, 100, Ease:=New AniEaseOutFluent(AniEasePower.ExtraStrong)),
|
||||||
AaCode(
|
AaCode(Sub() PanBack.IsHitTestVisible = True,, True)
|
||||||
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)
|
|
||||||
}, "FrmDownloadInstall SelectPageSwitch", True)
|
}, "FrmDownloadInstall SelectPageSwitch", True)
|
||||||
End Sub
|
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
|
Public Sub ExitSelectPage() Handles BtnBack.Click
|
||||||
If Not IsInSelectPage Then Return
|
If Not IsInSelectPage Then Return
|
||||||
IsInSelectPage = False
|
IsInSelectPage = False
|
||||||
@@ -144,10 +145,11 @@ Public Class PageDownloadInstall
|
|||||||
End Sub,, True)
|
End Sub,, True)
|
||||||
}, "FrmDownloadInstall SelectPageSwitch")
|
}, "FrmDownloadInstall SelectPageSwitch")
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub MinecraftSelected(sender As MyListItem, e As MouseButtonEventArgs)
|
Public Overridable Sub MinecraftSelected(sender As MyListItem, e As MouseButtonEventArgs)
|
||||||
VanillaName = sender.Title
|
VanillaName = sender.Title
|
||||||
VanillaData = sender.Tag
|
VanillaData = sender.Tag
|
||||||
VanillaIcon = sender.Logo
|
VanillaIcon = sender.Logo
|
||||||
|
LabMinecraftVersion.Text = VanillaName
|
||||||
EnterSelectPage()
|
EnterSelectPage()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -156,9 +158,9 @@ Public Class PageDownloadInstall
|
|||||||
#Region "选择"
|
#Region "选择"
|
||||||
|
|
||||||
'Minecraft
|
'Minecraft
|
||||||
Private VanillaName As String
|
Public VanillaName As String
|
||||||
Private VanillaData As JObject
|
Public VanillaData As JObject
|
||||||
Private VanillaIcon As String
|
Public VanillaIcon As String
|
||||||
Private ReadOnly Property VanillaDrop As Integer
|
Private ReadOnly Property VanillaDrop As Integer
|
||||||
Get
|
Get
|
||||||
Return McVersion.VersionToDrop(VanillaName)
|
Return McVersion.VersionToDrop(VanillaName)
|
||||||
@@ -166,24 +168,25 @@ Public Class PageDownloadInstall
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'附加组件
|
'附加组件
|
||||||
Private SelectedOptiFine As DlOptiFineListEntry = Nothing
|
Public SelectedOptiFine As DlOptiFineListEntry = Nothing
|
||||||
Private SelectedLiteLoader As DlLiteLoaderListEntry = Nothing
|
Public SelectedLiteLoader As DlLiteLoaderListEntry = Nothing
|
||||||
Private SelectedForge As DlForgeVersionEntry = Nothing
|
Public SelectedForge As DlForgeVersionEntry = Nothing
|
||||||
Private SelectedNeoForge As DlNeoForgeListEntry = Nothing
|
Public SelectedNeoForge As DlNeoForgeListEntry = Nothing
|
||||||
Private SelectedFabric As String = Nothing
|
Public SelectedFabric As String = Nothing
|
||||||
Private SelectedFabricApi As ResourceVersion = Nothing
|
Public SelectedFabricApi As ResourceVersion = Nothing
|
||||||
Private SelectedOptiFabric As ResourceVersion = Nothing
|
Public SelectedOptiFabric As ResourceVersion = Nothing
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 重载已选择的项目的显示。
|
''' 重载已选择的项目的显示。
|
||||||
''' </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
|
Static Ongoing As Boolean = False '#3742 中,LoadOptiFineGetError 会初始化 LoadOptiFine,触发事件 LoadOptiFine.StateChanged,导致再次调用 SelectReload
|
||||||
If VanillaName Is Nothing OrElse Ongoing Then Return
|
If VanillaName Is Nothing OrElse Ongoing Then Return
|
||||||
Ongoing = True
|
Ongoing = True
|
||||||
'主预览
|
'主预览
|
||||||
SelectNameUpdate()
|
SelectNameUpdate()
|
||||||
ImgLogo.Source = GetSelectLogo()
|
ImgLogo.Source = GetSelectLogo()
|
||||||
|
ImgMinecraft.Source = VanillaIcon
|
||||||
'OptiFine
|
'OptiFine
|
||||||
Dim OptiFineError As String = LoadOptiFineGetError()
|
Dim OptiFineError As String = LoadOptiFineGetError()
|
||||||
CardOptiFine.MainSwap.Visibility = If(OptiFineError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
CardOptiFine.MainSwap.Visibility = If(OptiFineError Is Nothing, Visibility.Visible, Visibility.Collapsed)
|
||||||
@@ -222,7 +225,7 @@ Public Class PageDownloadInstall
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
'Forge
|
'Forge
|
||||||
If Not McVersion.IsFormatFit(VanillaName) Then
|
If Not McVersion.IsStandardFormat(VanillaName) Then
|
||||||
CardForge.Visibility = Visibility.Collapsed
|
CardForge.Visibility = Visibility.Collapsed
|
||||||
Else
|
Else
|
||||||
CardForge.Visibility = Visibility.Visible
|
CardForge.Visibility = Visibility.Visible
|
||||||
@@ -356,7 +359,7 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 清空已选择的项目。
|
''' 清空已选择的项目。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub ClearSelected()
|
Public Sub ClearSelected()
|
||||||
VanillaName = Nothing
|
VanillaName = Nothing
|
||||||
VanillaData = Nothing
|
VanillaData = Nothing
|
||||||
VanillaIcon = Nothing
|
VanillaIcon = Nothing
|
||||||
@@ -367,7 +370,10 @@ Public Class PageDownloadInstall
|
|||||||
SelectedFabric = Nothing
|
SelectedFabric = Nothing
|
||||||
SelectedFabricApi = Nothing
|
SelectedFabricApi = Nothing
|
||||||
SelectedOptiFabric = Nothing
|
SelectedOptiFabric = Nothing
|
||||||
IsSelectNameEdited = False
|
For Each ClearButton In {BtnOptiFineClear, BtnLiteLoaderClear, BtnForgeClear, BtnNeoForgeClear,
|
||||||
|
BtnFabricClear, BtnFabricApiClear, BtnOptiFabricClear}
|
||||||
|
ClearButton.Visibility = Visibility.Collapsed
|
||||||
|
Next
|
||||||
End Sub
|
End Sub
|
||||||
'信息栏动画
|
'信息栏动画
|
||||||
Private Sub SetPanelVisibility(Panel As Grid, IsVisible As Boolean)
|
Private Sub SetPanelVisibility(Panel As Grid, IsVisible As Boolean)
|
||||||
@@ -389,7 +395,7 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取版本图标。
|
''' 获取版本图标。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function GetSelectLogo() As String
|
Public Overridable Function GetSelectLogo() As String
|
||||||
If SelectedFabric IsNot Nothing Then
|
If SelectedFabric IsNot Nothing Then
|
||||||
Return "pack://application:,,,/images/Blocks/Fabric.png"
|
Return "pack://application:,,,/images/Blocks/Fabric.png"
|
||||||
ElseIf SelectedForge IsNot Nothing Then
|
ElseIf SelectedForge IsNot Nothing Then
|
||||||
@@ -409,7 +415,7 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取默认版本名。
|
''' 获取默认版本名。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function GetSelectName() As String
|
Public Function GetSelectName() As String
|
||||||
Dim Name As String = VanillaName
|
Dim Name As String = VanillaName
|
||||||
If SelectedFabric IsNot Nothing Then Name += "-Fabric " & SelectedFabric.BeforeFirst("+")
|
If SelectedFabric IsNot Nothing Then Name += "-Fabric " & SelectedFabric.BeforeFirst("+")
|
||||||
If SelectedForge IsNot Nothing Then Name += "-Forge_" & SelectedForge.VersionName
|
If SelectedForge IsNot Nothing Then Name += "-Forge_" & SelectedForge.VersionName
|
||||||
@@ -418,36 +424,39 @@ Public Class PageDownloadInstall
|
|||||||
If SelectedOptiFine IsNot Nothing Then Name += "-OptiFine_" & SelectedOptiFine.DisplayName.Replace(VanillaName & " ", "").Replace(" ", "_")
|
If SelectedOptiFine IsNot Nothing Then Name += "-OptiFine_" & SelectedOptiFine.DisplayName.Replace(VanillaName & " ", "").Replace(" ", "_")
|
||||||
Return Name
|
Return Name
|
||||||
End Function
|
End Function
|
||||||
Private IsSelectNameEdited As Boolean = False
|
Public IsSelectNameEdited As Boolean = False
|
||||||
Private IsSelectNameChanging As Boolean = False
|
|
||||||
Private Sub SelectNameUpdate()
|
Private Sub SelectNameUpdate()
|
||||||
If IsSelectNameEdited OrElse IsSelectNameChanging Then Return
|
If IsSelectNameEdited Then Return
|
||||||
IsSelectNameChanging = True
|
|
||||||
TextSelectName.Text = GetSelectName()
|
TextSelectName.Text = GetSelectName()
|
||||||
IsSelectNameChanging = False
|
IsSelectNameEdited = False
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub TextSelectName_TextChanged(sender As Object, e As TextChangedEventArgs) Handles TextSelectName.TextChanged
|
Private Sub TextSelectName_TextChanged(sender As Object, e As TextChangedEventArgs) Handles TextSelectName.TextChanged
|
||||||
If IsSelectNameChanging Then Return
|
|
||||||
IsSelectNameEdited = True
|
IsSelectNameEdited = True
|
||||||
ReloadSelected()
|
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub TextSelectName_ValidateChanged(sender As Object, e As EventArgs) Handles TextSelectName.ValidateChanged
|
Private Sub TextSelectName_ValidateChanged(sender As Object, e As EventArgs) Handles TextSelectName.ValidateChanged
|
||||||
BtnStart.IsEnabled = TextSelectName.IsValidated
|
BtnStart.IsEnabled = TextSelectName.IsValidated
|
||||||
|
HintSelectName.Text = TextSelectName.ValidateResult
|
||||||
|
HintSelectName.Visibility = If(TextSelectName.IsValidated, Visibility.Collapsed, Visibility.Visible)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|
||||||
#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() '返回
|
ExitSelectPage() '返回
|
||||||
Try
|
Try
|
||||||
Dim Dict As New Dictionary(Of String, List(Of JObject)) From {
|
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)}
|
{"正式版", 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 MinecraftVersions
|
||||||
For Each Version As JObject In Versions
|
|
||||||
'确定分类
|
'确定分类
|
||||||
Dim Type As String = Version("type")
|
Dim Type As String = Version("type")
|
||||||
Select Case Type
|
Select Case Type
|
||||||
@@ -498,7 +507,7 @@ Public Class PageDownloadInstall
|
|||||||
'清空当前
|
'清空当前
|
||||||
PanMinecraft.Children.Clear()
|
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 PinnedVersions As New List(Of JObject)
|
||||||
Dim Release As JObject = Dict("正式版")(0).DeepClone()
|
Dim Release As JObject = Dict("正式版")(0).DeepClone()
|
||||||
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
|
Release("lore") = "最新正式版,发布于 " & Release("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
|
||||||
@@ -508,36 +517,41 @@ Public Class PageDownloadInstall
|
|||||||
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
|
Snapshot("lore") = "最新预览版,发布于 " & Snapshot("releaseTime").Value(Of Date).ToString("yyyy'/'MM'/'dd HH':'mm")
|
||||||
PinnedVersions.Add(Snapshot)
|
PinnedVersions.Add(Snapshot)
|
||||||
End If
|
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}
|
Dim PanInfo As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0)}
|
||||||
MyCard.StackInstall(PanInfo, 7)
|
|
||||||
CardInfo.Children.Add(PanInfo)
|
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)
|
PanMinecraft.Children.Insert(0, CardInfo)
|
||||||
'添加其他版本
|
'添加其他版本
|
||||||
For Each Pair As KeyValuePair(Of String, List(Of JObject)) In Dict
|
For Each Pair As KeyValuePair(Of String, List(Of JObject)) In Dict
|
||||||
If Not Pair.Value.Any() Then Continue For
|
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 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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
|
NewCard.SetContentBuilder(Pair.Value,
|
||||||
|
Function(Version) McDownloadListItem(Version, Sub(sender, e) MinecraftSelected(sender, e), False))
|
||||||
NewCard.IsSwapped = True
|
NewCard.IsSwapped = True
|
||||||
PanMinecraft.Children.Add(NewCard)
|
PanMinecraft.Children.Add(NewCard)
|
||||||
Next
|
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
|
Catch ex As Exception
|
||||||
Logger.Error(ex, "可视化安装版本列表出错")
|
Logger.Error(ex, "可视化安装版本列表出错")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
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>
|
''' <summary>
|
||||||
''' 当 MC 版本列表加载完时,立即自动选择的版本。用于外部调用。
|
''' 当 MC 版本列表加载完时,立即自动选择的版本。用于外部调用。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -550,16 +564,16 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 OptiFine 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 OptiFine 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadOptiFineGetError() As String
|
Public Function LoadOptiFineGetError() As String
|
||||||
If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
|
If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
|
||||||
'检查 Forge 1.13 - 1.14.3:全部不兼容
|
'检查 Forge 1.13 - 1.14.3:全部不兼容
|
||||||
If SelectedForge IsNot Nothing AndAlso
|
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 不兼容"
|
Return "与 Forge 不兼容"
|
||||||
End If
|
End If
|
||||||
'检查 Fabric 1.20.5+:全部不兼容
|
'检查 Fabric 1.20.5+:全部不兼容
|
||||||
If SelectedFabric IsNot Nothing AndAlso
|
If SelectedFabric IsNot Nothing AndAlso
|
||||||
CompareVersion(VanillaName, "1.20.4") > 0 Then
|
McUtils.CompareVersion(VanillaName, "1.20.4") > 0 Then
|
||||||
Return "与 Fabric 不兼容"
|
Return "与 Fabric 不兼容"
|
||||||
End If
|
End If
|
||||||
'检查 Loader
|
'检查 Loader
|
||||||
@@ -584,12 +598,12 @@ Public Class PageDownloadInstall
|
|||||||
End Function
|
End Function
|
||||||
|
|
||||||
'检查某个 OptiFine 是否与某个 Forge 兼容
|
'检查某个 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 Forge.Inherit <> OptiFine.Inherit Then Return False '不是同一个大版本
|
||||||
If OptiFine.RequiredForgeVersion Is Nothing Then Return False '不兼容 Forge
|
If OptiFine.RequiredForgeVersion Is Nothing Then Return False '不兼容 Forge
|
||||||
If String.IsNullOrWhiteSpace(OptiFine.RequiredForgeVersion) Then Return True '#4183
|
If String.IsNullOrWhiteSpace(OptiFine.RequiredForgeVersion) Then Return True '#4183
|
||||||
If OptiFine.RequiredForgeVersion.Contains(".") Then 'XX.X.XXX
|
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
|
Else 'XXXX
|
||||||
Return Forge.Version.Revision = OptiFine.RequiredForgeVersion
|
Return Forge.Version.Revision = OptiFine.RequiredForgeVersion
|
||||||
End If
|
End If
|
||||||
@@ -619,7 +633,7 @@ Public Class PageDownloadInstall
|
|||||||
Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
|
Function(Left As DlOptiFineListEntry, Right As DlOptiFineListEntry) As Boolean
|
||||||
If Not Left.IsPreview AndAlso Right.IsPreview Then Return True
|
If Not Left.IsPreview AndAlso Right.IsPreview Then Return True
|
||||||
If Left.IsPreview AndAlso Not Right.IsPreview Then Return False
|
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)
|
End Function)
|
||||||
'可视化
|
'可视化
|
||||||
PanOptiFine.Children.Clear()
|
PanOptiFine.Children.Clear()
|
||||||
@@ -641,12 +655,12 @@ Public Class PageDownloadInstall
|
|||||||
CardOptiFine.IsSwapped = True
|
CardOptiFine.IsSwapped = True
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedOptiFine = Nothing
|
||||||
SelectedOptiFabric = Nothing
|
SelectedOptiFabric = Nothing
|
||||||
|
BtnOptiFabricClear.Visibility = Visibility.Collapsed
|
||||||
AutoSelectedOptiFabric = False
|
AutoSelectedOptiFabric = False
|
||||||
CardOptiFine.IsSwapped = True
|
CardOptiFine.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
Forge_Loaded()
|
Forge_Loaded()
|
||||||
NeoForge_Loaded()
|
NeoForge_Loaded()
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
@@ -659,7 +673,7 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 LiteLoader 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 LiteLoader 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadLiteLoaderGetError() As String
|
Public Function LoadLiteLoaderGetError() As String
|
||||||
'检查 Loader
|
'检查 Loader
|
||||||
If GetLoaderError(LoadLiteLoader) IsNot Nothing Then Return GetLoaderError(LoadLiteLoader)
|
If GetLoaderError(LoadLiteLoader) IsNot Nothing Then Return GetLoaderError(LoadLiteLoader)
|
||||||
'检查版本
|
'检查版本
|
||||||
@@ -699,10 +713,9 @@ Public Class PageDownloadInstall
|
|||||||
CardLiteLoader.IsSwapped = True
|
CardLiteLoader.IsSwapped = True
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedLiteLoader = Nothing
|
||||||
CardLiteLoader.IsSwapped = True
|
CardLiteLoader.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -713,8 +726,8 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 Forge 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 Forge 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadForgeGetError() As String
|
Public Function LoadForgeGetError() As String
|
||||||
If CompareVersionGE("1.5.1", VanillaName) AndAlso CompareVersionGE(VanillaName, "1.1") Then Return "无"
|
If McUtils.CompareVersionGE("1.5.1", VanillaName) AndAlso McUtils.CompareVersionGE(VanillaName, "1.1") Then Return "无"
|
||||||
'检查 Loader
|
'检查 Loader
|
||||||
If GetLoaderError(LoadForge) IsNot Nothing Then Return GetLoaderError(LoadForge)
|
If GetLoaderError(LoadForge) IsNot Nothing Then Return GetLoaderError(LoadForge)
|
||||||
Dim Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = LoadForge.State
|
Dim Loader As LoaderTask(Of String, List(Of DlForgeVersionEntry)) = LoadForge.State
|
||||||
@@ -725,7 +738,7 @@ Public Class PageDownloadInstall
|
|||||||
If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
|
If SelectedNeoForge IsNot Nothing Then Return "与 NeoForge 不兼容"
|
||||||
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
||||||
If SelectedOptiFine IsNot Nothing AndAlso
|
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 检查
|
Return "与 OptiFine 不兼容" '1.13 ~ 1.14.3 OptiFine 检查
|
||||||
End If
|
End If
|
||||||
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, Version) Then Continue For
|
If SelectedOptiFine IsNot Nothing AndAlso Not IsOptiFineSuitForForge(SelectedOptiFine, Version) Then Continue For
|
||||||
@@ -775,10 +788,9 @@ Public Class PageDownloadInstall
|
|||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedForge = Nothing
|
||||||
CardForge.IsSwapped = True
|
CardForge.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -790,7 +802,7 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 NeoForge 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 NeoForge 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadNeoForgeGetError() As String
|
Public Function LoadNeoForgeGetError() As String
|
||||||
If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
|
If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容"
|
||||||
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容"
|
||||||
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
If SelectedFabric IsNot Nothing Then Return "与 Fabric 不兼容"
|
||||||
@@ -832,10 +844,9 @@ Public Class PageDownloadInstall
|
|||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedNeoForge = Nothing
|
||||||
CardNeoForge.IsSwapped = True
|
CardNeoForge.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
OptiFine_Loaded()
|
OptiFine_Loaded()
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -847,9 +858,9 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 Fabric 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 Fabric 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadFabricGetError() As String
|
Public Function LoadFabricGetError() As String
|
||||||
'检查 OptiFine 1.20.5+:没有 OptiFabric 故全部不兼容
|
'检查 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
|
'检查 Loader
|
||||||
If GetLoaderError(LoadFabric) IsNot Nothing Then Return GetLoaderError(LoadFabric)
|
If GetLoaderError(LoadFabric) IsNot Nothing Then Return GetLoaderError(LoadFabric)
|
||||||
'检查版本
|
'检查版本
|
||||||
@@ -879,9 +890,10 @@ Public Class PageDownloadInstall
|
|||||||
If Not Versions.Any() Then Return
|
If Not Versions.Any() Then Return
|
||||||
'可视化
|
'可视化
|
||||||
PanFabric.Children.Clear()
|
PanFabric.Children.Clear()
|
||||||
PanFabric.Tag = Versions
|
|
||||||
CardFabric.SwapControl = PanFabric
|
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
|
Catch ex As Exception
|
||||||
Logger.Error(ex, "可视化 Fabric 安装版本列表出错")
|
Logger.Error(ex, "可视化 Fabric 安装版本列表出错")
|
||||||
End Try
|
End Try
|
||||||
@@ -895,14 +907,15 @@ Public Class PageDownloadInstall
|
|||||||
CardFabric.IsSwapped = True
|
CardFabric.IsSwapped = True
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedFabric = Nothing
|
||||||
SelectedFabricApi = Nothing
|
SelectedFabricApi = Nothing
|
||||||
|
BtnFabricApiClear.Visibility = Visibility.Collapsed
|
||||||
AutoSelectedFabricApi = False
|
AutoSelectedFabricApi = False
|
||||||
SelectedOptiFabric = Nothing
|
SelectedOptiFabric = Nothing
|
||||||
|
BtnOptiFabricClear.Visibility = Visibility.Collapsed
|
||||||
AutoSelectedOptiFabric = False
|
AutoSelectedOptiFabric = False
|
||||||
CardFabric.IsSwapped = True
|
CardFabric.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -911,14 +924,14 @@ Public Class PageDownloadInstall
|
|||||||
#Region "Fabric API 列表"
|
#Region "Fabric API 列表"
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 判断某 Fabric API 是否适配当前选择的原版版本。
|
''' 判断某 Fabric API 是否适配指定的原版版本。
|
||||||
''' </summary>
|
''' </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
|
Dim FabricApiName = FabricApi.Display
|
||||||
Try
|
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
|
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 FabricApiName.StartsWithF("[" & TargetName & "]") Then Return True
|
||||||
If Not FabricApiName.Contains("/") OrElse Not FabricApiName.Contains("]") Then Return False
|
If Not FabricApiName.Contains("/") OrElse Not FabricApiName.Contains("]") Then Return False
|
||||||
'直接的判断(例如 1.18.1/22w03a)
|
'直接的判断(例如 1.18.1/22w03a)
|
||||||
@@ -946,7 +959,7 @@ Public Class PageDownloadInstall
|
|||||||
End While
|
End While
|
||||||
Return True
|
Return True
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, $"判断 Fabric API 版本适配性出错({FabricApiName}, {VanillaName})")
|
Logger.Warn(ex, $"判断 Fabric API 版本适配性出错({FabricApiName}, {MinecraftVersion})")
|
||||||
Return False
|
Return False
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
@@ -954,12 +967,12 @@ Public Class PageDownloadInstall
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 FabricApi 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 FabricApi 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadFabricApiGetError() As String
|
Public Function LoadFabricApiGetError() As String
|
||||||
'检查 Loader
|
'检查 Loader
|
||||||
If GetLoaderError(LoadFabricApi) IsNot Nothing Then Return GetLoaderError(LoadFabricApi)
|
If GetLoaderError(LoadFabricApi) IsNot Nothing Then Return GetLoaderError(LoadFabricApi)
|
||||||
If DlFabricApiLoader.Output Is Nothing Then Return If(SelectedFabric Is Nothing, "需要安装 Fabric", "获取中……")
|
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)
|
Return If(SelectedFabric Is Nothing, "需要安装 Fabric", Nothing)
|
||||||
Else
|
Else
|
||||||
Return "无"
|
Return "无"
|
||||||
@@ -971,7 +984,7 @@ Public Class PageDownloadInstall
|
|||||||
If LoadFabricApiGetError() IsNot Nothing Then e.Handled = True
|
If LoadFabricApiGetError() IsNot Nothing Then e.Handled = True
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private AutoSelectedFabricApi As Boolean = False
|
Public AutoSelectedFabricApi As Boolean = False
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 尝试重新可视化 FabricApi 版本列表。
|
''' 尝试重新可视化 FabricApi 版本列表。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
@@ -982,7 +995,7 @@ Public Class PageDownloadInstall
|
|||||||
'获取版本列表
|
'获取版本列表
|
||||||
Dim Versions As New List(Of ResourceVersion)
|
Dim Versions As New List(Of ResourceVersion)
|
||||||
For Each Version In DlFabricApiLoader.Output
|
For Each Version In DlFabricApiLoader.Output
|
||||||
If IsFabricApiCompatible(Version) Then
|
If IsFabricApiCompatible(Version, VanillaName) Then
|
||||||
If Not Version.Display.StartsWithF("[") Then
|
If Not Version.Display.StartsWithF("[") Then
|
||||||
Logger.Warn($"已特判修改 Fabric API 显示名:{Version.Display}")
|
Logger.Warn($"已特判修改 Fabric API 显示名:{Version.Display}")
|
||||||
Version.Display = "[" & VanillaName & "] " & Version.Display
|
Version.Display = "[" & VanillaName & "] " & Version.Display
|
||||||
@@ -995,7 +1008,6 @@ Public Class PageDownloadInstall
|
|||||||
'可视化
|
'可视化
|
||||||
PanFabricApi.Children.Clear()
|
PanFabricApi.Children.Clear()
|
||||||
For Each Version In Versions
|
For Each Version In Versions
|
||||||
If Not IsFabricApiCompatible(Version) Then Continue For
|
|
||||||
PanFabricApi.Children.Add(FabricApiDownloadListItem(Version, AddressOf FabricApi_Selected))
|
PanFabricApi.Children.Add(FabricApiDownloadListItem(Version, AddressOf FabricApi_Selected))
|
||||||
Next
|
Next
|
||||||
'自动选择 Fabric API
|
'自动选择 Fabric API
|
||||||
@@ -1016,10 +1028,9 @@ Public Class PageDownloadInstall
|
|||||||
CardFabricApi.IsSwapped = True
|
CardFabricApi.IsSwapped = True
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedFabricApi = Nothing
|
||||||
CardFabricApi.IsSwapped = True
|
CardFabricApi.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -1028,23 +1039,23 @@ Public Class PageDownloadInstall
|
|||||||
#Region "OptiFabric 列表"
|
#Region "OptiFabric 列表"
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 判断某 OptiFabric 是否适配当前选择的原版版本。
|
''' 判断某 OptiFabric 是否适配指定的原版版本。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function IsOptiFabricCompatible(ModFile As ResourceVersion) As Boolean
|
Public Shared Function IsOptiFabricCompatible(ModFile As ResourceVersion, MinecraftVersion As String) As Boolean
|
||||||
Try
|
Try
|
||||||
If VanillaName Is Nothing Then Return False
|
If MinecraftVersion Is Nothing Then Return False
|
||||||
Return ModFile.GameVersions.Contains(VanillaName)
|
Return ModFile.GameVersions.Contains(MinecraftVersion)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Warn(ex, $"判断 OptiFabric 版本适配性出错({VanillaName})")
|
Logger.Warn(ex, $"判断 OptiFabric 版本适配性出错({MinecraftVersion})")
|
||||||
Return False
|
Return False
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private AutoSelectedOptiFabric As Boolean = False
|
Public AutoSelectedOptiFabric As Boolean = False
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
|
''' 获取 OptiFabric 的加载异常信息。若正常则返回 Nothing。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Function LoadOptiFabricGetError() As String
|
Public Function LoadOptiFabricGetError() As String
|
||||||
If VanillaDrop >= 140 AndAlso VanillaDrop <= 150 Then Return "不兼容老版本 Fabric,请手动下载 OptiFabric Origins"
|
If VanillaDrop >= 140 AndAlso VanillaDrop <= 150 Then Return "不兼容老版本 Fabric,请手动下载 OptiFabric Origins"
|
||||||
'检查 Loader
|
'检查 Loader
|
||||||
If GetLoaderError(LoadOptiFabric) IsNot Nothing Then Return GetLoaderError(LoadOptiFabric)
|
If GetLoaderError(LoadOptiFabric) IsNot Nothing Then Return GetLoaderError(LoadOptiFabric)
|
||||||
@@ -1056,7 +1067,7 @@ Public Class PageDownloadInstall
|
|||||||
Return "获取中……"
|
Return "获取中……"
|
||||||
End If
|
End If
|
||||||
For Each Version In DlOptiFabricLoader.Output
|
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 AndAlso SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine 与 Fabric"
|
||||||
If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
|
If SelectedFabric Is Nothing Then Return "需要安装 Fabric"
|
||||||
If SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine"
|
If SelectedOptiFine Is Nothing Then Return "需要安装 OptiFine"
|
||||||
@@ -1080,7 +1091,7 @@ Public Class PageDownloadInstall
|
|||||||
'获取版本列表
|
'获取版本列表
|
||||||
Dim Versions As New List(Of ResourceVersion)
|
Dim Versions As New List(Of ResourceVersion)
|
||||||
For Each Version In DlOptiFabricLoader.Output
|
For Each Version In DlOptiFabricLoader.Output
|
||||||
If IsOptiFabricCompatible(Version) Then Versions.Add(Version)
|
If IsOptiFabricCompatible(Version, VanillaName) Then Versions.Add(Version)
|
||||||
Next
|
Next
|
||||||
If Not Versions.Any() Then Return
|
If Not Versions.Any() Then Return
|
||||||
'排序
|
'排序
|
||||||
@@ -1088,7 +1099,6 @@ Public Class PageDownloadInstall
|
|||||||
'可视化
|
'可视化
|
||||||
PanOptiFabric.Children.Clear()
|
PanOptiFabric.Children.Clear()
|
||||||
For Each Version In Versions
|
For Each Version In Versions
|
||||||
If Not IsOptiFabricCompatible(Version) Then Continue For
|
|
||||||
PanOptiFabric.Children.Add(OptiFabricDownloadListItem(Version, AddressOf OptiFabric_Selected))
|
PanOptiFabric.Children.Add(OptiFabricDownloadListItem(Version, AddressOf OptiFabric_Selected))
|
||||||
Next
|
Next
|
||||||
'自动选择 OptiFabric
|
'自动选择 OptiFabric
|
||||||
@@ -1108,10 +1118,9 @@ Public Class PageDownloadInstall
|
|||||||
CardOptiFabric.IsSwapped = True
|
CardOptiFabric.IsSwapped = True
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
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
|
SelectedOptiFabric = Nothing
|
||||||
CardOptiFabric.IsSwapped = True
|
CardOptiFabric.IsSwapped = True
|
||||||
e.Handled = True
|
|
||||||
ReloadSelected()
|
ReloadSelected()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
@@ -1119,10 +1128,42 @@ Public Class PageDownloadInstall
|
|||||||
|
|
||||||
#Region "安装"
|
#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
|
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()
|
If e.Key = Key.Enter AndAlso IsInSelectPage AndAlso BtnStart.IsEnabled Then BtnStart_Click()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BtnStart_Click() Handles BtnStart.Click
|
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
|
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
|
(Settings.Get(Of Integer)("LaunchArgumentIndieV2") = 0 OrElse Settings.Get(Of Integer)("LaunchArgumentIndieV2") = 2) Then
|
||||||
@@ -1132,22 +1173,7 @@ Public Class PageDownloadInstall
|
|||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
'提交安装申请
|
If Not McInstallStart(Request) Then Return
|
||||||
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
|
|
||||||
'返回,这样在再次进入安装页面时这个版本就会显示文件夹已重复
|
'返回,这样在再次进入安装页面时这个版本就会显示文件夹已重复
|
||||||
ExitSelectPage()
|
ExitSelectPage()
|
||||||
End Sub
|
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 = If(RestrictMcDownload, Visibility.Collapsed, 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 IsXSpecial Then Return 1
|
||||||
If IsYSpecial 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
|
If VersionCodeSort <> 0 Then Return VersionCodeSort
|
||||||
'比较全部
|
'比较全部
|
||||||
Return -CompareVersion(x, y)
|
Return -McUtils.CompareVersion(x, y)
|
||||||
End Function
|
End Function
|
||||||
Public Sub New(Optional Topmost As String = "")
|
Public Sub New(Optional Topmost As String = "")
|
||||||
Me.Topmost = If(Topmost, "")
|
Me.Topmost = If(Topmost, "")
|
||||||
@@ -98,7 +98,7 @@ Public Class PageDownloadResourceDetail
|
|||||||
Dim UpdateFilters =
|
Dim UpdateFilters =
|
||||||
Sub()
|
Sub()
|
||||||
Filters = Results.SelectMany(Function(v) v.GameVersions).Select(Function(v) GetGroupedVersionName(v, GroupedDrop, GroupedOld)).
|
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
|
End Sub
|
||||||
|
|
||||||
'确定分组方式
|
'确定分组方式
|
||||||
@@ -174,7 +174,7 @@ GroupDone:
|
|||||||
Dim Loaders As New List(Of String)
|
Dim Loaders As New List(Of String)
|
||||||
If Project.ModLoaders.Flags.Count > 1 AndAlso '工程至少有两个加载器
|
If Project.ModLoaders.Flags.Count > 1 AndAlso '工程至少有两个加载器
|
||||||
Version.ResourceType = ResourceTypes.Mod AndAlso '是 Mod
|
Version.ResourceType = ResourceTypes.Mod AndAlso '是 Mod
|
||||||
McVersion.IsFormatFit(VerName) Then '不是 “快照版本” 之类的
|
McVersion.IsStandardFormat(VerName) Then '不是 “快照版本” 之类的
|
||||||
Loaders.AddRange(Version.ModLoaders.Flags.Select(Function(f) f.ToString & " "))
|
Loaders.AddRange(Version.ModLoaders.Flags.Select(Function(f) f.ToString & " "))
|
||||||
End If
|
End If
|
||||||
If Not Loaders.Any() Then Loaders.Add("") '保底加一个空的,确保它在一张卡片里
|
If Not Loaders.Any() Then Loaders.Add("") '保底加一个空的,确保它在一张卡片里
|
||||||
@@ -206,16 +206,17 @@ GroupDone:
|
|||||||
If Not Pair.Value.Any() Then Continue For
|
If Not Pair.Value.Any() Then Continue For
|
||||||
If Pair.Key = TargetCardName.Replace("(所选版本)", "") 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}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
|
NewCard.SetContentBuilder(AddressOf InitializeStackResourceVersions)
|
||||||
PanResults.Children.Add(NewCard)
|
PanResults.Children.Add(NewCard)
|
||||||
'确定卡片是否默认展开
|
'确定卡片是否默认展开
|
||||||
If Pair.Key = TargetCardName OrElse
|
If Pair.Key = TargetCardName OrElse
|
||||||
(FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
|
(FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
|
||||||
CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
|
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
|
Else
|
||||||
NewCard.IsSwapped = True
|
NewCard.IsSwapped = True
|
||||||
End If
|
End If
|
||||||
@@ -240,13 +241,53 @@ GroupDone:
|
|||||||
Logger.Error(ex, "可视化工程下载列表出错")
|
Logger.Error(ex, "可视化工程下载列表出错")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
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 Not RestrictMcDownload AndAlso 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
|
Private Function GetGroupedVersionName(Name As String, GroupedByDrop As Boolean, FoldOld As Boolean) As String
|
||||||
Dim Drop = McVersion.VersionToDrop(Name)
|
Dim Drop = McVersion.VersionToDrop(Name)
|
||||||
If Name Is Nothing Then
|
If Name Is Nothing Then
|
||||||
Return "其他"
|
Return "其他"
|
||||||
ElseIf Name.Contains("w") OrElse Drop = 209 Then
|
ElseIf Name.Contains("w") OrElse Drop = 209 Then
|
||||||
Return "快照版"
|
Return "快照版"
|
||||||
ElseIf Not McVersion.IsFormatFit(Name) OrElse (FoldOld AndAlso Drop < 120) Then
|
ElseIf Not McVersion.IsStandardFormat(Name) OrElse (FoldOld AndAlso Drop < 120) Then
|
||||||
Return "远古版"
|
Return "远古版"
|
||||||
ElseIf GroupedByDrop Then
|
ElseIf GroupedByDrop Then
|
||||||
Return McVersion.DropToVersion(Drop)
|
Return McVersion.DropToVersion(Drop)
|
||||||
@@ -469,19 +510,23 @@ GroupDone:
|
|||||||
'弹窗要求选择保存位置
|
'弹窗要求选择保存位置
|
||||||
Dim Target As String
|
Dim Target As String
|
||||||
Dim Ext As String = If(File.ResourceType = ResourceTypes.Mod,
|
Dim Ext As String = If(File.ResourceType = ResourceTypes.Mod,
|
||||||
If(File.FileName.EndsWithF(".litemod"), "litemod", "jar"),
|
If(PathUtils.GetExtension(File.FileName) = "litemod", "litemod", "jar"),
|
||||||
If(File.FileName.EndsWithF(".mrpack"), "mrpack", "zip"))
|
If(PathUtils.GetExtension(File.FileName) = "mrpack", "mrpack", "zip"))
|
||||||
Target = Dialogs.SaveFile("选择保存位置", FileName, DefaultFolder, {(Ext, Desc & "文件")})
|
Target = Dialogs.SaveFile("选择保存位置", FileName, DefaultFolder, {(Ext, Desc & "文件")})
|
||||||
If Target Is Nothing Then Return
|
If Target Is Nothing Then Return
|
||||||
'构造步骤加载器
|
'构造步骤加载器
|
||||||
Dim LoaderName As String = Desc & "下载:" & PathUtils.GetFileNameWithoutExtension(Target) & " "
|
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)
|
Dim Loaders As New List(Of LoaderBase)
|
||||||
Loaders.Add(New LoaderDownload("下载文件", {
|
Loaders.Add(New LoaderDownload("下载文件", {
|
||||||
File.ToNetFile(Target, If(TargetResourceType = ResourceTypes.Any, ResourceVersion.DownloadReason.Dependency, ResourceVersion.DownloadReason.Standalone))
|
File.ToNetFile(Target, If(TargetResourceType = ResourceTypes.Any, ResourceVersion.DownloadReason.Dependency, ResourceVersion.DownloadReason.Standalone))
|
||||||
}) With {.ProgressWeight = 6, .Block = True})
|
}) 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)
|
Loader.Start(1)
|
||||||
LoaderTaskbarAdd(Loader)
|
LoaderTaskbarAdd(Loader)
|
||||||
FrmMain.BtnExtraDownload.ShowRefresh()
|
FrmMain.BtnExtraDownload.ShowRefresh()
|
||||||
@@ -510,29 +555,4 @@ GroupDone:
|
|||||||
PageLoaderRestart(IsForceRestart:=True)
|
PageLoaderRestart(IsForceRestart:=True)
|
||||||
End Sub
|
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
|
End Class
|
||||||
|
|||||||
@@ -90,11 +90,11 @@ Public Class PageResource
|
|||||||
Next
|
Next
|
||||||
Return ComboSearchLoader.Items(0)
|
Return ComboSearchLoader.Items(0)
|
||||||
End Function
|
End Function
|
||||||
If TargetInstance.Version.HasForge Then
|
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then
|
||||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("Forge")
|
ComboSearchLoader.SelectedItem = GetTargetItemByName("Forge")
|
||||||
ElseIf TargetInstance.Version.HasFabric Then
|
ElseIf TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then
|
||||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("Fabric")
|
ComboSearchLoader.SelectedItem = GetTargetItemByName("Fabric")
|
||||||
ElseIf TargetInstance.Version.HasNeoForge Then
|
ElseIf TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then
|
||||||
ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
|
ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
|
||||||
End If
|
End If
|
||||||
TargetInstance = Nothing
|
TargetInstance = Nothing
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ Public Class MyLocalModItem
|
|||||||
BtnUpdate.Visibility = Visibility.Collapsed
|
BtnUpdate.Visibility = Visibility.Collapsed
|
||||||
End If
|
End If
|
||||||
'标题与描述
|
'标题与描述
|
||||||
Dim DescFileName As String = Entry.File.Name.BeforeLast(".")
|
Dim DescFileName As String = PathUtils.GetFileNameWithoutExtension(Entry.EnabledName)
|
||||||
Dim NewDescription As String
|
Dim NewDescription As String
|
||||||
If Settings.Get(Of Integer)("ToolModLocalNameStyle") = 1 Then
|
If Settings.Get(Of Integer)("ToolModLocalNameStyle") = 1 Then
|
||||||
'标题显示文件名,详情显示译名
|
'标题显示文件名,详情显示译名
|
||||||
|
|||||||
@@ -65,10 +65,10 @@
|
|||||||
<local:MyCheckBox Margin="30,0,0,0">
|
<local:MyCheckBox Margin="30,0,0,0">
|
||||||
<local:MyCheckBox.Tag>
|
<local:MyCheckBox.Tag>
|
||||||
<local:ExportOption
|
<local:ExportOption
|
||||||
Title="OptiFine 设置"
|
Title="OptiFine 设置"
|
||||||
Rules="optionsof.txt|optionsshaders.txt"
|
Rules="optionsof.txt|optionsshaders.txt"
|
||||||
DefaultChecked="True"
|
DefaultChecked="True"
|
||||||
RequireOptiFine="True" />
|
RequireOptiFine="True" />
|
||||||
</local:MyCheckBox.Tag>
|
</local:MyCheckBox.Tag>
|
||||||
</local:MyCheckBox>
|
</local:MyCheckBox>
|
||||||
<local:MyCheckBox x:Name="CheckOptionsMod">
|
<local:MyCheckBox x:Name="CheckOptionsMod">
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ Public Class PageInstanceExport
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub PageInstanceExport_Loaded() Handles Me.Loaded
|
Private Sub PageInstanceExport_Loaded() Handles Me.Loaded
|
||||||
AniControlEnabled += 1
|
AniControlEnabled += 1
|
||||||
If CurrentInstance <> PageInstanceLeft.Instance.PathVersion Then RefreshAll() '切换到了另一个版本,重置页面
|
If Not PathUtils.IsSame(CurrentInstance, PageInstanceLeft.Instance.PathVersion) Then RefreshAll() '切换到了另一个版本,重置页面
|
||||||
CustomEventService.SetEventData(BtnAdvancedHelp,
|
CustomEventService.SetEventData(BtnAdvancedHelp,
|
||||||
If(BuildType = BuildTypes.Release, "指南/整合包制作 - Public.json", "指南/整合包制作 - Snapshot.json"))
|
If(BuildType = BuildTypes.Release, "指南/整合包制作 - Public.json", "指南/整合包制作 - Snapshot.json"))
|
||||||
AniControlEnabled -= 1
|
AniControlEnabled -= 1
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub RefreshAll() Implements IRefreshable.Refresh
|
Public Sub RefreshAll() Implements IRefreshable.Refresh
|
||||||
Logger.Info("刷新导出页面")
|
Logger.Info("刷新导出页面")
|
||||||
HintOptiFine.Visibility = If(PageInstanceLeft.Instance.Version.HasOptiFine, Visibility.Visible, Visibility.Collapsed)
|
HintOptiFine.Visibility = If(PageInstanceLeft.Instance.Version.HasOptiFine AndAlso Not PageInstanceLeft.Instance.Version.OptiFineAsMod, Visibility.Visible, Visibility.Collapsed)
|
||||||
CurrentInstance = PageInstanceLeft.Instance.PathVersion
|
CurrentInstance = PageInstanceLeft.Instance.PathVersion
|
||||||
TextExportName.Text = ""
|
TextExportName.Text = ""
|
||||||
TextExportName.HintText = PageInstanceLeft.Instance.Name
|
TextExportName.HintText = PageInstanceLeft.Instance.Name
|
||||||
@@ -114,7 +114,7 @@ Public Class PageInstanceExport
|
|||||||
'确认选项是否应该被显示
|
'确认选项是否应该被显示
|
||||||
Dim IsVisible =
|
Dim IsVisible =
|
||||||
Function(TargetOption As ExportOption) As Boolean
|
Function(TargetOption As ExportOption) As Boolean
|
||||||
'检查需要 OptiFine 或 Mod 加载器
|
'检查需要 OptiFine(例如光影)或 Mod 加载器(例如 mods/)
|
||||||
If TargetOption.RequireOptiFine AndAlso Not PageInstanceLeft.Instance.Version.HasOptiFine Then Return False
|
If TargetOption.RequireOptiFine AndAlso Not PageInstanceLeft.Instance.Version.HasOptiFine Then Return False
|
||||||
If TargetOption.RequireModLoader AndAlso Not PageInstanceLeft.Instance.Modable Then Return False
|
If TargetOption.RequireModLoader AndAlso Not PageInstanceLeft.Instance.Modable Then Return False
|
||||||
If TargetOption.RequireModLoaderOrOptiFine AndAlso Not PageInstanceLeft.Instance.Version.HasOptiFine AndAlso Not PageInstanceLeft.Instance.Modable Then Return False
|
If TargetOption.RequireModLoaderOrOptiFine AndAlso Not PageInstanceLeft.Instance.Version.HasOptiFine AndAlso Not PageInstanceLeft.Instance.Modable Then Return False
|
||||||
@@ -257,9 +257,9 @@ Public Class PageInstanceExport
|
|||||||
For Each ShaderPackCheckBox In PanOptionsShaderPacks.Children.OfType(Of MyCheckBox)()
|
For Each ShaderPackCheckBox In PanOptionsShaderPacks.Children.OfType(Of MyCheckBox)()
|
||||||
If Not ShaderPackCheckBox.Checked Then Continue For
|
If Not ShaderPackCheckBox.Checked Then Continue For
|
||||||
Dim ShaderPackOption = GetExportOption(ShaderPackCheckBox)
|
Dim ShaderPackOption = GetExportOption(ShaderPackCheckBox)
|
||||||
Dim SettingFileName = ShaderPackOption.Rules.TrimEnd("/") & ".txt"
|
Dim SettingsFile = $"shaderpacks/{ShaderPackOption.Title}.txt"
|
||||||
If Not FileUtils.Exists(Path.Combine(PageInstanceLeft.Instance.PathIndie, SettingFileName)) Then Continue For
|
If Not FileUtils.Exists(Path.Combine(PageInstanceLeft.Instance.PathIndie, SettingsFile)) Then Continue For
|
||||||
Rules.Add(StringUtils.LikePatternEscape($"shaderpacks/{SettingFileName}"))
|
Rules.Add(StringUtils.LikePatternEscape(SettingsFile))
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
|
|
||||||
@@ -457,11 +457,11 @@ Public Class PageInstanceExport
|
|||||||
'缓存所需参数
|
'缓存所需参数
|
||||||
Dim CacheFolder = RequestTaskTempFolder()
|
Dim CacheFolder = RequestTaskTempFolder()
|
||||||
Dim OverridesFolder = CacheFolder & "modpack\overrides\"
|
Dim OverridesFolder = CacheFolder & "modpack\overrides\"
|
||||||
Dim McVersion = PageInstanceLeft.Instance
|
Dim TargetInstance = PageInstanceLeft.Instance
|
||||||
Dim IncludeJava As Boolean =
|
Dim IncludeJava As Boolean =
|
||||||
(RulesOverrides Is Nothing AndAlso CheckOptionsJava.Visibility = Visibility.Visible AndAlso CheckOptionsJava.Checked) OrElse
|
(RulesOverrides Is Nothing AndAlso CheckOptionsJava.Visibility = Visibility.Visible AndAlso CheckOptionsJava.Checked) OrElse
|
||||||
(RulesOverrides IsNot Nothing AndAlso CheckOptionsJava.Checked AndAlso Settings.Get(Of Integer)("VersionArgumentJavaV2", McVersion) = 2)
|
(RulesOverrides IsNot Nothing AndAlso CheckOptionsJava.Checked AndAlso Settings.Get(Of Integer)("VersionArgumentJavaV2", TargetInstance) = 2)
|
||||||
Dim PathIndie As String = McVersion.PathIndie
|
Dim PathIndie As String = TargetInstance.PathIndie
|
||||||
Dim CheckHostedAssets As Boolean = Not CheckAdvancedInclude.Checked
|
Dim CheckHostedAssets As Boolean = Not CheckAdvancedInclude.Checked
|
||||||
Dim ModrinthUploadMode As Boolean = CheckAdvancedModrinth.Checked
|
Dim ModrinthUploadMode As Boolean = CheckAdvancedModrinth.Checked
|
||||||
Dim IncludePCL As Boolean = CheckOptionsPcl.Checked
|
Dim IncludePCL As Boolean = CheckOptionsPcl.Checked
|
||||||
@@ -498,7 +498,7 @@ Public Class PageInstanceExport
|
|||||||
'文件夹:进一步搜索
|
'文件夹:进一步搜索
|
||||||
For Each SubFolder In Folder.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
|
For Each SubFolder In Folder.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
|
||||||
'跳过部分又没用文件又多的文件夹,加快搜索
|
'跳过部分又没用文件又多的文件夹,加快搜索
|
||||||
If {"assets", "versions", "libraries"}.Contains(SubFolder.Name) AndAlso PathIndie = PathUtils.RemoveExtendedPrefix(Folder.FullName) Then Continue For
|
If {"assets", "versions", "libraries"}.Contains(SubFolder.Name) AndAlso PathUtils.IsSame(PathIndie, Folder.FullName) Then Continue For
|
||||||
If {"structureCacheV1", ".fabric", ".git", "avatar-cache", "cosmetic-cache"}.Contains(SubFolder.Name) Then Continue For
|
If {"structureCacheV1", ".fabric", ".git", "avatar-cache", "cosmetic-cache"}.Contains(SubFolder.Name) Then Continue For
|
||||||
SearchFolder(SubFolder)
|
SearchFolder(SubFolder)
|
||||||
Next
|
Next
|
||||||
@@ -536,10 +536,10 @@ Public Class PageInstanceExport
|
|||||||
Loader.Progress = 0.85
|
Loader.Progress = 0.85
|
||||||
'复制 Java
|
'复制 Java
|
||||||
If IncludeJava Then
|
If IncludeJava Then
|
||||||
Dim JavaToExport = SelectOrDownloadJava(McVersion, False, Loader.CreateCancellationToken, Loader.CreateSyncProgressProvider(0.85, 0.93))
|
Dim JavaToExport = SelectOrDownloadJava(TargetInstance, False, Loader.CreateCancellationToken, Loader.CreateSyncProgressProvider(0.85, 0.93))
|
||||||
If JavaToExport Is Nothing Then Throw New FileNotFoundException("版本文件夹中没有找到可导出的 Java。")
|
If JavaToExport Is Nothing Then Throw New FileNotFoundException("版本文件夹中没有找到可导出的 Java。")
|
||||||
Dim JavaFolder = PathUtils.RemoveLastPart(JavaToExport.Folder)
|
Dim JavaFolder = PathUtils.RemoveLastPart(JavaToExport.Folder)
|
||||||
Dim DestFolder As String = Path.Combine(OverridesFolder, JavaFolder.AfterFirst(McVersion.PathVersion, True))
|
Dim DestFolder As String = Path.Combine(OverridesFolder, JavaFolder.AfterFirst(TargetInstance.PathVersion, True))
|
||||||
DirectoryUtils.Copy(JavaFolder, DestFolder)
|
DirectoryUtils.Copy(JavaFolder, DestFolder)
|
||||||
Logger.Info($"已复制版本文件夹中的 Java:{JavaFolder} → {DestFolder}")
|
Logger.Info($"已复制版本文件夹中的 Java:{JavaFolder} → {DestFolder}")
|
||||||
End If
|
End If
|
||||||
@@ -563,7 +563,7 @@ Public Class PageInstanceExport
|
|||||||
Next
|
Next
|
||||||
Loader.Progress = 0.97
|
Loader.Progress = 0.97
|
||||||
'复制 PCL 版本设置
|
'复制 PCL 版本设置
|
||||||
If DirectoryUtils.Exists(McVersion.PathVersion & "PCL\") Then DirectoryUtils.Copy(McVersion.PathVersion & "PCL\", OverridesFolder & "PCL\")
|
If DirectoryUtils.Exists(TargetInstance.PathVersion & "PCL\") Then DirectoryUtils.Copy(TargetInstance.PathVersion & "PCL\", OverridesFolder & "PCL\")
|
||||||
WriteIni(OverridesFolder & "PCL\Setup.ini", "IsStar", False)
|
WriteIni(OverridesFolder & "PCL\Setup.ini", "IsStar", False)
|
||||||
'复制 PCL 本体(正式版)
|
'复制 PCL 本体(正式版)
|
||||||
If BuildType = BuildTypes.Release AndAlso IncludePCL Then FileUtils.Copy(PathExe, CacheFolder & "Plain Craft Launcher.exe")
|
If BuildType = BuildTypes.Release AndAlso IncludePCL Then FileUtils.Copy(PathExe, CacheFolder & "Plain Craft Launcher.exe")
|
||||||
@@ -686,16 +686,16 @@ Public Class PageInstanceExport
|
|||||||
Next
|
Next
|
||||||
Loader.Progress = 0.2
|
Loader.Progress = 0.2
|
||||||
'导出最终 JSON 文件
|
'导出最终 JSON 文件
|
||||||
Dim Dependencies As New JObject From {{"minecraft", McVersion.Version.VanillaName}}
|
Dim Dependencies As New JObject From {{"minecraft", TargetInstance.Version.VanillaName}}
|
||||||
If McVersion.Version.HasForge Then Dependencies.Add("forge", McVersion.Version.Forge)
|
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then Dependencies.Add("forge", TargetInstance.Version.ModLoaderVersions(ModLoaders.Forge))
|
||||||
If McVersion.Version.HasFabric Then Dependencies.Add("fabric-loader", McVersion.Version.Fabric)
|
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then Dependencies.Add("fabric-loader", TargetInstance.Version.ModLoaderVersions(ModLoaders.Fabric))
|
||||||
If McVersion.Version.HasNeoForge Then Dependencies.Add("neoforge", McVersion.Version.NeoForge)
|
If TargetInstance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then Dependencies.Add("neoforge", TargetInstance.Version.ModLoaderVersions(ModLoaders.NeoForge))
|
||||||
Dim ResultJson As New JObject From {
|
Dim ResultJson As New JObject From {
|
||||||
{"game", "minecraft"},
|
{"game", "minecraft"},
|
||||||
{"formatVersion", 1},
|
{"formatVersion", 1},
|
||||||
{"versionId", PackVersion},
|
{"versionId", PackVersion},
|
||||||
{"name", PackName},
|
{"name", PackName},
|
||||||
{"summary", McVersion.Info},
|
{"summary", TargetInstance.Info},
|
||||||
{"files", Files},
|
{"files", Files},
|
||||||
{"dependencies", Dependencies}
|
{"dependencies", Dependencies}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,29 @@
|
|||||||
</x:Array>
|
</x:Array>
|
||||||
</local:MyListItem.Buttons>
|
</local:MyListItem.Buttons>
|
||||||
</local:MyListItem>
|
</local:MyListItem>
|
||||||
<local:MyListItem x:Name="ItemMod" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="2" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
<local:MyListItem x:Name="ItemModify" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="2" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="修改" LogoScale="0.95"
|
||||||
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" >
|
Logo="F1 M652.624 145.904c62.256-62.272 163.2-62.272 225.472 0 62.272 62.256 62.272 163.2 0 225.472L477.808 771.664a28.8 28.8 0 0 1-10.816 6.8L242.4 857.376c-47.04 16.544-92.32-28.736-75.776-75.776l78.896-224.592c1.44-4.08 3.76-7.776 6.816-10.816L652.624 145.904z M828.604 195.396a89.44 89.44 0 0 0-126.488 0L308.48 589.032 241.68 781.12 433.768 714.32 828.604 321.884a89.44 89.44 0 0 0 0-126.488z M606.256 194.816a35 35 0 0 1 49.504 0l173.728 173.728a35 35 0 0 1-49.504 49.504L606.256 244.32a35 35 0 0 1 0-49.504z M261.984 539.104a35 35 0 0 1 49.504 0l173.728 173.728a35 35 0 0 1-49.504 49.504L261.984 588.608a35 35 0 0 1 0-49.504z" >
|
||||||
<local:MyListItem.Buttons>
|
<local:MyListItem.Buttons>
|
||||||
<x:Array Type="{x:Type local:MyIconButton}">
|
<x:Array Type="{x:Type local:MyIconButton}">
|
||||||
<local:MyIconButton Tag="2" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
<local:MyIconButton Tag="2" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||||
</x:Array>
|
</x:Array>
|
||||||
</local:MyListItem.Buttons>
|
</local:MyListItem.Buttons>
|
||||||
</local:MyListItem>
|
</local:MyListItem>
|
||||||
<local:MyListItem x:Name="ItemModDisabled" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="3" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
<local:MyListItem x:Name="ItemMod" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="3" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
||||||
|
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" >
|
||||||
|
<local:MyListItem.Buttons>
|
||||||
|
<x:Array Type="{x:Type local:MyIconButton}">
|
||||||
|
<local:MyIconButton Tag="3" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||||
|
</x:Array>
|
||||||
|
</local:MyListItem.Buttons>
|
||||||
|
</local:MyListItem>
|
||||||
|
<local:MyListItem x:Name="ItemModDisabled" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="Mod 管理"
|
||||||
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" />
|
Logo="M789.504 912.896h-195.072a35.328 35.328 0 0 1-34.816-35.328v-77.312a39.936 39.936 0 0 0-40.448-39.936H481.28a40.448 40.448 0 0 0-40.448 39.936v77.312a34.816 34.816 0 0 1-34.816 35.328H204.8a41.984 41.984 0 0 1-40.448-42.496v-200.192a35.328 35.328 0 0 1 35.328-35.328h72.704a39.936 39.936 0 0 0 39.936-39.936v-37.888a39.936 39.936 0 0 0-39.936-40.448H199.68a35.328 35.328 0 0 1-35.328-35.328V287.744A41.984 41.984 0 0 1 204.8 245.76h176.64v-32.768a102.4 102.4 0 0 1 102.4-102.4h33.792a102.4 102.4 0 0 1 102.4 102.4v32.768h170.496a41.984 41.984 0 0 1 41.984 41.984V460.8h28.672a102.4 102.4 0 0 1 102.4 102.4v33.792a102.4 102.4 0 0 1-102.4 102.4h-28.672V870.4a41.984 41.984 0 0 1-43.008 42.496z m-159.744-70.144h131.584V665.6a34.304 34.304 0 0 1 34.816-34.816h64a31.744 31.744 0 0 0 31.744-31.744V563.2a31.744 31.744 0 0 0-31.744-31.744h-64a34.816 34.816 0 0 1-34.816-35.328V316.416h-177.152a35.328 35.328 0 0 1-35.328-35.328V212.992a31.744 31.744 0 0 0-31.744-31.744h-33.792a31.744 31.744 0 0 0-31.744 31.744v68.096a35.328 35.328 0 0 1-34.816 35.328H234.496v130.048h37.888a110.592 110.592 0 0 1 110.08 110.592v37.888a110.592 110.592 0 0 1-110.08 110.592h-37.888v137.216h136.192v-42.496a110.592 110.592 0 0 1 110.592-110.08h37.888a110.592 110.592 0 0 1 110.592 110.08z" />
|
||||||
<local:MyListItem x:Name="ItemExport" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="4" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="导出"
|
<local:MyListItem x:Name="ItemExport" IsScaleAnimationEnabled="False" Type="RadioBox" Tag="5" MinPaddingRight="35" Height="36" VerticalAlignment="Top" Title="导出"
|
||||||
Logo="M511 995a128 128 0 0 1-57-13L70 791a126 126 0 0 1-70-113V311a126 126 0 0 1 15-60V248c1-2 3-5 5-8a127 127 0 0 1 49-42L454 13a128 128 0 0 1 112 0l383 190a126 126 0 0 1 72 113v360a126 126 0 0 1-70 115L568 984c-17 7-37 11-57 11z m42-470v370l360-178c14-7 23-21 23-38v-335L554 524zM85 330v347a42 42 0 0 0 23 38l360 178V523L85 330zM135 260l375 189 137-65L286 188 135 260z m245-118l363 197 150-71-365-180a42 42 0 0 0-37 0l-111 53z">
|
Logo="M511 995a128 128 0 0 1-57-13L70 791a126 126 0 0 1-70-113V311a126 126 0 0 1 15-60V248c1-2 3-5 5-8a127 127 0 0 1 49-42L454 13a128 128 0 0 1 112 0l383 190a126 126 0 0 1 72 113v360a126 126 0 0 1-70 115L568 984c-17 7-37 11-57 11z m42-470v370l360-178c14-7 23-21 23-38v-335L554 524zM85 330v347a42 42 0 0 0 23 38l360 178V523L85 330zM135 260l375 189 137-65L286 188 135 260z m245-118l363 197 150-71-365-180a42 42 0 0 0-37 0l-111 53z">
|
||||||
<local:MyListItem.Buttons>
|
<local:MyListItem.Buttons>
|
||||||
<x:Array Type="{x:Type local:MyIconButton}">
|
<x:Array Type="{x:Type local:MyIconButton}">
|
||||||
<local:MyIconButton Tag="4" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
<local:MyIconButton Tag="5" ToolTip="刷新" Click="Refresh_Click" LogoScale="0.85" Logo="M512.0 838.3c-80.2 0-153.4-29.3-210.2-77.4l75.5-75.5c11.5-11.5 25.8-22.0 25.8-37.0a27.2 27.2 0 0 0-27.1-27.1H104.0c-27.1 0-27.1 23.9-27.1 27.1v271.9a27.1 27.1 0 0 0 27.1 27.1c15.0 0 27.8-16.6 42.5-31.2l77.9-77.9c76.6 67.7 177.1 108.9 287.4 108.9 221.7 0 404.5-166.0 431.2-380.6h-109.8c-25.9 154.2-159.7 271.9-321.3 271.9zM919.9 76.6c-15.0 0-27.8 16.6-42.5 31.3L799.5 185.8c-76.5-67.7-177.1-108.9-287.4-108.9-221.8 0-404.5 166.1-431.3 380.6H190.6c25.9-154.2 159.7-271.9 321.4-271.9 80.2 0 153.4 29.3 210.1 77.4l-75.5 75.5c-11.6 11.5-25.8 22.0-25.8 37.1a27.2 27.2 0 0 0 27.1 27.1h271.9c27.1 0 27.1-23.9 27.1-27.1V103.8a27.1 27.1 0 0 0-27.1-27.1z" />
|
||||||
</x:Array>
|
</x:Array>
|
||||||
</local:MyListItem.Buttons>
|
</local:MyListItem.Buttons>
|
||||||
</local:MyListItem>
|
</local:MyListItem>
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ Public Class PageInstanceLeft
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Shared Instance As McInstance = Nothing
|
Public Shared Instance As McInstance = Nothing
|
||||||
|
|
||||||
|
Private Sub PageInstanceLeft_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
|
||||||
|
PageSetupUI.HiddenRefresh()
|
||||||
|
End Sub
|
||||||
|
|
||||||
Public Sub RefreshModDisabled() Handles Me.Loaded
|
Public Sub RefreshModDisabled() Handles Me.Loaded
|
||||||
If Instance IsNot Nothing AndAlso Instance.Modable Then
|
If Instance IsNot Nothing AndAlso Instance.Modable Then
|
||||||
ItemMod.Visibility = Visibility.Visible
|
ItemMod.Visibility = Visibility.Visible
|
||||||
@@ -26,7 +30,7 @@ Public Class PageInstanceLeft
|
|||||||
''' <summary>
|
''' <summary>
|
||||||
''' 勾选事件改变页面。
|
''' 勾选事件改变页面。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Private Sub PageCheck(sender As FrameworkElement, e As RouteEventArgs) Handles ItemOverall.Check, ItemMod.Check, ItemModDisabled.Check, ItemSetup.Check, ItemExport.Check
|
Private Sub PageCheck(sender As FrameworkElement, e As RouteEventArgs) Handles ItemOverall.Check, ItemMod.Check, ItemModDisabled.Check, ItemSetup.Check, ItemModify.Check, ItemExport.Check
|
||||||
'尚未初始化控件属性时,sender.Tag 为 Nothing,会导致切换到页面 0
|
'尚未初始化控件属性时,sender.Tag 为 Nothing,会导致切换到页面 0
|
||||||
'若使用 IsLoaded,则会导致模拟点击不被执行(模拟点击切换页面时,控件的 IsLoaded 为 False)
|
'若使用 IsLoaded,则会导致模拟点击不被执行(模拟点击切换页面时,控件的 IsLoaded 为 False)
|
||||||
If sender.Tag IsNot Nothing Then PageChange(Val(sender.Tag))
|
If sender.Tag IsNot Nothing Then PageChange(Val(sender.Tag))
|
||||||
@@ -45,11 +49,14 @@ Public Class PageInstanceLeft
|
|||||||
If FrmInstanceModDisabled Is Nothing Then FrmInstanceModDisabled = New PageInstanceModDisabled
|
If FrmInstanceModDisabled Is Nothing Then FrmInstanceModDisabled = New PageInstanceModDisabled
|
||||||
Return FrmInstanceModDisabled
|
Return FrmInstanceModDisabled
|
||||||
Case FormMain.PageSubType.InstanceSetup
|
Case FormMain.PageSubType.InstanceSetup
|
||||||
If IsNothing(FrmInstanceSetup) Then FrmInstanceSetup = New PageInstanceSetup
|
If FrmInstanceSetup Is Nothing Then FrmInstanceSetup = New PageInstanceSetup
|
||||||
Return FrmInstanceSetup
|
Return FrmInstanceSetup
|
||||||
Case FormMain.PageSubType.InstanceExport
|
Case FormMain.PageSubType.InstanceExport
|
||||||
If FrmInstanceExport Is Nothing Then FrmInstanceExport = New PageInstanceExport
|
If FrmInstanceExport Is Nothing Then FrmInstanceExport = New PageInstanceExport
|
||||||
Return FrmInstanceExport
|
Return FrmInstanceExport
|
||||||
|
Case FormMain.PageSubType.InstanceModify
|
||||||
|
If FrmDownloadModify Is Nothing Then FrmDownloadModify = New PageDownloadModify
|
||||||
|
Return FrmDownloadModify
|
||||||
Case Else
|
Case Else
|
||||||
Throw New Exception("未知的版本设置子页面种类:" & ID)
|
Throw New Exception("未知的版本设置子页面种类:" & ID)
|
||||||
End Select
|
End Select
|
||||||
@@ -60,6 +67,10 @@ Public Class PageInstanceLeft
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Sub PageChange(ID As FormMain.PageSubType)
|
Public Sub PageChange(ID As FormMain.PageSubType)
|
||||||
If PageID = ID Then Return
|
If PageID = ID Then Return
|
||||||
|
If Instance IsNot Nothing AndAlso McInstanceLock.IsLocked(Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再切换页面!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
AniControlEnabled += 1
|
AniControlEnabled += 1
|
||||||
Try
|
Try
|
||||||
PageChangeRun(PageGet(ID))
|
PageChangeRun(PageGet(ID))
|
||||||
@@ -98,13 +109,20 @@ Public Class PageInstanceLeft
|
|||||||
Refresh(FrmMain.PageCurrentSub)
|
Refresh(FrmMain.PageCurrentSub)
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub Refresh(SubType As FormMain.PageSubType)
|
Public Sub Refresh(SubType As FormMain.PageSubType)
|
||||||
|
If Instance IsNot Nothing AndAlso McInstanceLock.IsLocked(Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再刷新!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
Select Case SubType
|
Select Case SubType
|
||||||
Case FormMain.PageSubType.InstanceMod
|
Case FormMain.PageSubType.InstanceMod
|
||||||
PageInstanceMod.Refresh()
|
PageInstanceMod.Refresh()
|
||||||
ItemMod.Checked = True
|
ItemMod.Checked = True
|
||||||
Case FormMain.PageSubType.InstanceExport
|
Case FormMain.PageSubType.InstanceExport
|
||||||
If FrmInstanceExport IsNot Nothing Then FrmInstanceExport.RefreshAll()
|
FrmInstanceExport?.RefreshAll()
|
||||||
ItemExport.Checked = True
|
ItemExport.Checked = True
|
||||||
|
Case FormMain.PageSubType.InstanceModify
|
||||||
|
FrmDownloadModify?.PageLoaderRestart()
|
||||||
|
ItemModify.Checked = True
|
||||||
End Select
|
End Select
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ Public Class PageInstanceMod
|
|||||||
''' 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。
|
''' 返回输入的文件是否为一个 Mod 文件,仅用于判断拖拽行为。
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Shared Function InstallMods(FilePathList As IEnumerable(Of String)) As Boolean
|
Public Shared Function InstallMods(FilePathList As IEnumerable(Of String)) As Boolean
|
||||||
Dim Extension As String = FilePathList.First.AfterLast(".").Lower
|
Dim Extension As String = PathUtils.GetExtension(FilePathList.First)
|
||||||
'检查文件扩展名
|
'检查文件扩展名
|
||||||
If Not {"jar", "litemod", "disabled", "old"}.Any(Function(t) t = Extension) Then Return False
|
If Not {"jar", "litemod", "disabled", "old"}.Any(Function(t) t = Extension) Then Return False
|
||||||
Logger.Info("文件为 jar/litemod 格式,尝试作为 Mod 安装")
|
Logger.Info("文件为 jar/litemod 格式,尝试作为 Mod 安装")
|
||||||
@@ -307,15 +307,15 @@ Public Class PageInstanceMod
|
|||||||
Install:
|
Install:
|
||||||
Try
|
Try
|
||||||
For Each ModFile In FilePathList
|
For Each ModFile In FilePathList
|
||||||
Dim NewFileName = PathUtils.GetLastPart(ModFile).Replace(".disabled", "").Replace(".old", "")
|
Dim NewFileName = (New LocalResourceFile(ModFile)).EnabledName
|
||||||
If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
|
If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
|
||||||
NewFileName = Instance.PathIndie & "mods\" & NewFileName
|
NewFileName = Instance.PathIndie & "mods\" & NewFileName
|
||||||
If ModFile = NewFileName Then Continue For '防止安装相同文件导致文件被删除
|
If PathUtils.IsSame(ModFile, NewFileName) Then Continue For '防止安装相同文件导致文件被删除
|
||||||
FileUtils.Delete(NewFileName, True)
|
FileUtils.Delete(NewFileName, True)
|
||||||
FileUtils.Copy(ModFile, NewFileName)
|
FileUtils.Copy(ModFile, NewFileName)
|
||||||
Next
|
Next
|
||||||
If FilePathList.IsSingle Then
|
If FilePathList.IsSingle Then
|
||||||
Hint($"已安装 {PathUtils.GetLastPart(FilePathList.First).Replace(".disabled", "").Replace(".old", "")}!", HintType.Green)
|
Hint($"已安装 {(New LocalResourceFile(FilePathList.First)).EnabledName}!", HintType.Green)
|
||||||
Else
|
Else
|
||||||
Hint($"已安装 {FilePathList.Count} 个 Mod!", HintType.Green)
|
Hint($"已安装 {FilePathList.Count} 个 Mod!", HintType.Green)
|
||||||
End If
|
End If
|
||||||
@@ -553,8 +553,8 @@ Install:
|
|||||||
Dim File As ResourceVersion = Entry.UpdateFile
|
Dim File As ResourceVersion = Entry.UpdateFile
|
||||||
If Not File.DownloadAvailable Then Continue For
|
If Not File.DownloadAvailable Then Continue For
|
||||||
'确认更新后的文件名
|
'确认更新后的文件名
|
||||||
Dim CurrentReplaceName = Entry.ProjectVersion.FileName.Replace(".jar", "").Replace(".old", "").Replace(".disabled", "")
|
Dim CurrentReplaceName = PathUtils.GetFileNameWithoutExtension(Entry.ProjectVersion.FileName)
|
||||||
Dim NewestReplaceName = Entry.UpdateFile.FileName.Replace(".jar", "").Replace(".old", "").Replace(".disabled", "")
|
Dim NewestReplaceName = PathUtils.GetFileNameWithoutExtension(Entry.UpdateFile.FileName)
|
||||||
Dim CurrentSegs = CurrentReplaceName.Split("-"c).ToList()
|
Dim CurrentSegs = CurrentReplaceName.Split("-"c).ToList()
|
||||||
Dim NewestSegs = NewestReplaceName.Split("-"c).ToList()
|
Dim NewestSegs = NewestReplaceName.Split("-"c).ToList()
|
||||||
Dim Shortened As Boolean = False
|
Dim Shortened As Boolean = False
|
||||||
|
|||||||
@@ -104,51 +104,21 @@ Public Class PageInstanceOverall
|
|||||||
'重命名版本
|
'重命名版本
|
||||||
Private Sub BtnDisplayRename_Click(sender As Object, e As EventArgs) Handles BtnDisplayRename.Click
|
Private Sub BtnDisplayRename_Click(sender As Object, e As EventArgs) Handles BtnDisplayRename.Click
|
||||||
Try
|
Try
|
||||||
|
If McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再重命名!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
'确认输入的新名称
|
'确认输入的新名称
|
||||||
Dim OldName As String = PageInstanceLeft.Instance.Name
|
Dim OldName As String = PageInstanceLeft.Instance.Name
|
||||||
Dim OldPath As String = PageInstanceLeft.Instance.PathVersion
|
|
||||||
'修改此部分的同时修改快速安装的版本名检测*
|
'修改此部分的同时修改快速安装的版本名检测*
|
||||||
Dim NewName As String = MyMsgBoxInput("重命名版本", "", OldName, New ObjectModel.Collection(Of Validate) From {
|
Dim NewName As String = MyMsgBoxInput("重命名版本", "", OldName, New ObjectModel.Collection(Of Validate) From {
|
||||||
New ValidateFolderName(McFolderSelected & "versions", IgnoreList:=New List(Of String) From {OldName})
|
New ValidateFolderName(McFolderSelected & "versions", IgnoreList:=New List(Of String) From {OldName})
|
||||||
})
|
})
|
||||||
If String.IsNullOrWhiteSpace(NewName) Then Return
|
If String.IsNullOrWhiteSpace(NewName) Then Return
|
||||||
Dim NewPath As String = McFolderSelected & "versions\" & NewName & "\"
|
Dim NewInstance = PageInstanceLeft.Instance.Rename(NewName)
|
||||||
'重新读取版本 JSON 信息,避免 JsonObject 中已被合并的项被重新存储
|
|
||||||
Dim JsonObject As JObject
|
|
||||||
Dim OldJsonPath As String = PageInstanceLeft.Instance.GetJsonPath()
|
|
||||||
Try
|
|
||||||
JsonObject = FileUtils.ReadAsJson(OldJsonPath)
|
|
||||||
Catch ex As Exception
|
|
||||||
Logger.Warn(ex, "在重命名读取 JSON 时失败")
|
|
||||||
JsonObject = PageInstanceLeft.Instance.JsonObject
|
|
||||||
End Try
|
|
||||||
'重命名主文件夹
|
|
||||||
DirectoryUtils.Move(OldPath, NewPath)
|
|
||||||
'清理 ini 缓存
|
|
||||||
PageInstanceLeft.Instance.ResetSettingsCache()
|
|
||||||
'重命名 jar 文件与 natives 文件夹
|
|
||||||
'不能进行遍历重命名,否则在版本名很短的时候容易误伤其他文件(#6443)
|
|
||||||
If DirectoryUtils.Exists($"{NewPath}{OldName}-natives") Then DirectoryUtils.Move($"{NewPath}{OldName}-natives", $"{NewPath}{NewName}-natives")
|
|
||||||
If FileUtils.Exists($"{NewPath}{OldName}.jar") Then FileUtils.Move($"{NewPath}{OldName}.jar", $"{NewPath}{NewName}.jar")
|
|
||||||
'替换版本设置文件中的路径
|
|
||||||
If FileUtils.Exists(NewPath & "PCL\Setup.ini") Then
|
|
||||||
FileUtils.Write(NewPath & "PCL\Setup.ini", FileUtils.ReadAsString(NewPath & "PCL\Setup.ini").Replace(OldPath, NewPath))
|
|
||||||
End If
|
|
||||||
'更改已选中的版本
|
|
||||||
If ReadIni(McFolderSelected & "PCL.ini", "Version") = OldName Then
|
|
||||||
WriteIni(McFolderSelected & "PCL.ini", "Version", NewName)
|
|
||||||
End If
|
|
||||||
'更新版本 Json
|
|
||||||
Try
|
|
||||||
JsonObject("id") = NewName
|
|
||||||
FileUtils.Delete(NewPath & PathUtils.GetLastPart(OldJsonPath))
|
|
||||||
FileUtils.Write(NewPath & NewName & ".json", JsonObject.ToString)
|
|
||||||
Catch ex As Exception
|
|
||||||
Logger.Warn(ex, "重命名版本 json 失败")
|
|
||||||
End Try
|
|
||||||
'刷新与提示
|
'刷新与提示
|
||||||
Hint("重命名成功!", HintType.Green)
|
Hint("重命名成功!", HintType.Green)
|
||||||
PageInstanceLeft.Instance = New McInstance(NewName).Load()
|
PageInstanceLeft.Instance = NewInstance
|
||||||
If Not IsNothing(McInstanceSelected) AndAlso McInstanceSelected.Equals(PageInstanceLeft.Instance) Then WriteIni(McFolderSelected & "PCL.ini", "Version", NewName)
|
If Not IsNothing(McInstanceSelected) AndAlso McInstanceSelected.Equals(PageInstanceLeft.Instance) Then WriteIni(McFolderSelected & "PCL.ini", "Version", NewName)
|
||||||
Reload()
|
Reload()
|
||||||
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||||
@@ -267,6 +237,10 @@ Public Class PageInstanceOverall
|
|||||||
'补全文件
|
'补全文件
|
||||||
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
|
||||||
Try
|
Try
|
||||||
|
If McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再补全文件!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
'忽略文件检查提示
|
'忽略文件检查提示
|
||||||
If ShouldIgnoreFileCheck(PageInstanceLeft.Instance) Then
|
If ShouldIgnoreFileCheck(PageInstanceLeft.Instance) Then
|
||||||
Hint("请先关闭 [版本设置 → 设置 → 高级启动选项 → 关闭文件校验],然后再尝试补全文件!", HintType.Blue)
|
Hint("请先关闭 [版本设置 → 设置 → 高级启动选项 → 关闭文件校验],然后再尝试补全文件!", HintType.Blue)
|
||||||
@@ -304,8 +278,12 @@ Public Class PageInstanceOverall
|
|||||||
'修改此代码时,同时修改 PageSelectRight 中的代码
|
'修改此代码时,同时修改 PageSelectRight 中的代码
|
||||||
Private Sub BtnManageDelete_Click(sender As Object, e As EventArgs) Handles BtnManageDelete.Click
|
Private Sub BtnManageDelete_Click(sender As Object, e As EventArgs) Handles BtnManageDelete.Click
|
||||||
Try
|
Try
|
||||||
|
If McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再删除!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
|
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
|
||||||
Dim IsHintIndie As Boolean = PageInstanceLeft.Instance.State <> McInstanceState.Error AndAlso PageInstanceLeft.Instance.PathIndie <> McFolderSelected
|
Dim IsHintIndie As Boolean = PageInstanceLeft.Instance.State <> McInstance.McInstanceState.Error AndAlso PageInstanceLeft.Instance.PathIndie <> McFolderSelected
|
||||||
Dim SavesFolder = DirectoryUtils.GetInfo(PageInstanceLeft.Instance.PathIndie & "saves\")
|
Dim SavesFolder = DirectoryUtils.GetInfo(PageInstanceLeft.Instance.PathIndie & "saves\")
|
||||||
Dim SaveEntries = If(IsHintIndie AndAlso SavesFolder.Exists, SavesFolder.EnumerateDirectories.OrderByDescending(Function(Save) Save.LastWriteTime).Select(Function(Save) $"{Save.Name}(上次修改:{StringUtils.FormatTimeSpan(Save.LastWriteTime - Date.Now, False)})").ToList, New List(Of String))
|
Dim SaveEntries = If(IsHintIndie AndAlso SavesFolder.Exists, SavesFolder.EnumerateDirectories.OrderByDescending(Function(Save) Save.LastWriteTime).Select(Function(Save) $"{Save.Name}(上次修改:{StringUtils.FormatTimeSpan(Save.LastWriteTime - Date.Now, False)})").ToList, New List(Of String))
|
||||||
Select Case MyMsgBox($"你确定要{If(IsShiftPressed, "永久", "")}删除版本 {PageInstanceLeft.Instance.Name} 吗?" &
|
Select Case MyMsgBox($"你确定要{If(IsShiftPressed, "永久", "")}删除版本 {PageInstanceLeft.Instance.Name} 吗?" &
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ PreFin:
|
|||||||
ComboArgumentJavaSelect.Items.Add(JavaItem)
|
ComboArgumentJavaSelect.Items.Add(JavaItem)
|
||||||
Dim Buttons As New List(Of MyIconButton)
|
Dim Buttons As New List(Of MyIconButton)
|
||||||
'从列表中移除按钮
|
'从列表中移除按钮
|
||||||
Dim IsOfficial As Boolean = JavaEntry.Folder.StartsWithF($"{Paths.AppData}.minecraft\runtime\")
|
Dim IsOfficial As Boolean = PathUtils.IsParentOf($"{Paths.AppData}.minecraft\runtime\", JavaEntry.Folder)
|
||||||
Dim DeleteButton As New MyIconButton With {.Logo = Logo.IconButtonStop, .Height = 24, .Width = 24}
|
Dim DeleteButton As New MyIconButton With {.Logo = Logo.IconButtonStop, .Height = 24, .Width = 24}
|
||||||
DeleteButton.IsEnabled = Not IsOfficial
|
DeleteButton.IsEnabled = Not IsOfficial
|
||||||
DeleteButton.ToolTip = If(DeleteButton.IsEnabled, "从列表中移除", "无法移除官方 Java")
|
DeleteButton.ToolTip = If(DeleteButton.IsEnabled, "从列表中移除", "无法移除官方 Java")
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ Retry:
|
|||||||
{"Cherry Blossom", "樱花披风"}, {"15th Anniversary", "15 周年纪念披风"}, {"Purple Heart", "紫色心形披风"},
|
{"Cherry Blossom", "樱花披风"}, {"15th Anniversary", "15 周年纪念披风"}, {"Purple Heart", "紫色心形披风"},
|
||||||
{"Follower's", "追随者披风"}, {"MCC 15th Year", "MCC 15 周年披风"}, {"Minecraft Experience", "村民救援披风"},
|
{"Follower's", "追随者披风"}, {"MCC 15th Year", "MCC 15 周年披风"}, {"Minecraft Experience", "村民救援披风"},
|
||||||
{"Mojang Office", "Mojang 办公室披风"}, {"Home", "家园披风"}, {"Menace", "入侵披风"}, {"Yearn", "渴望披风"},
|
{"Mojang Office", "Mojang 办公室披风"}, {"Home", "家园披风"}, {"Menace", "入侵披风"}, {"Yearn", "渴望披风"},
|
||||||
{"Common", "普通披风"}, {"Pan", "薄煎饼披风"}, {"Founder's", "创始人披风"}, {"Copper", "铜披风"}, {"Zombie Horse", "僵尸马披风"}, {"Builder", "建造者披风"}, {"Crafter", "工匠披风"}
|
{"Common", "普通披风"}, {"Pan", "薄煎饼披风"}, {"Founder's", "创始人披风"}, {"Copper", "铜披风"}, {"Zombie Horse", "僵尸马披风"}, {"Builder", "建造者披风"}, {"Crafter", "工匠披风"},
|
||||||
|
{"Aurora", "极光披风"}
|
||||||
}
|
}
|
||||||
Dim SelectionControl As New List(Of IMyRadio) From {
|
Dim SelectionControl As New List(Of IMyRadio) From {
|
||||||
New MyRadioBox With {.Text = "无披风", .Checked = Not SkinData("capes").Any(Function(c) c("state")?.ToString = "ACTIVE")}}
|
New MyRadioBox With {.Text = "无披风", .Checked = Not SkinData("capes").Any(Function(c) c("state")?.ToString = "ACTIVE")}}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ Public Class PageLaunchLeft
|
|||||||
'确认 Minecraft 版本存在
|
'确认 Minecraft 版本存在
|
||||||
Dim Selection As String = ReadIni(McFolderSelected & "PCL.ini", "Version")
|
Dim Selection As String = ReadIni(McFolderSelected & "PCL.ini", "Version")
|
||||||
Dim Instance As McInstance = If(Selection = "", Nothing, New McInstance(Selection))
|
Dim Instance As McInstance = If(Selection = "", Nothing, New McInstance(Selection))
|
||||||
If Instance Is Nothing OrElse Not Instance.PathVersion.StartsWithF(McFolderSelected) OrElse Not Instance.Check() Then
|
If Instance Is Nothing OrElse Not PathUtils.IsParentOf(McFolderSelected, Instance.PathVersion) OrElse Not Instance.Check() Then
|
||||||
'无效的版本
|
'无效的版本
|
||||||
Logger.Info($"当前选择的 Minecraft 版本无效:{If(Instance Is Nothing, "null", Instance.PathVersion)}", If(IsNothing(Instance), LogBehavior.None, LogBehavior.ToastIfDebug))
|
Logger.Info($"当前选择的 Minecraft 版本无效:{If(Instance Is Nothing, "null", Instance.PathVersion)}", If(IsNothing(Instance), LogBehavior.None, LogBehavior.ToastIfDebug))
|
||||||
If Not McInstanceListLoader.State = LoadState.Finished Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
|
If Not McInstanceListLoader.State = LoadState.Finished Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
|
||||||
@@ -691,12 +691,28 @@ ExitRefresh:
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
'取消按钮
|
'取消按钮
|
||||||
Private Sub BtnCancel_Click() Handles BtnCancel.Click
|
Public Sub BtnCancel_Click() Handles BtnCancel.Click
|
||||||
McLaunchCancel()
|
If McLaunchLoaderReal IsNot Nothing Then
|
||||||
|
McLaunchLoaderReal.Cancel()
|
||||||
|
McLaunchLog("已取消启动")
|
||||||
|
Try
|
||||||
|
If McLaunchWatcher IsNot Nothing Then
|
||||||
|
McLaunchWatcher.Kill()
|
||||||
|
ElseIf McLaunchProcess IsNot Nothing Then
|
||||||
|
If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
Logger.Error(ex, "取消启动结束进程失败", LogBehavior.Toast)
|
||||||
|
End Try
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
'版本设置按钮
|
'版本设置按钮
|
||||||
Private Sub BtnMore_Click() Handles BtnMore.Click
|
Private Sub BtnMore_Click() Handles BtnMore.Click
|
||||||
If McLaunchLoader.State = LoadState.Loading Then Return
|
If McLaunchLoader.State = LoadState.Loading Then Return
|
||||||
|
If McInstanceLock.IsLocked(McInstanceSelected) Then
|
||||||
|
Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
McInstanceSelected.Load()
|
McInstanceSelected.Load()
|
||||||
PageInstanceLeft.Instance = McInstanceSelected
|
PageInstanceLeft.Instance = McInstanceSelected
|
||||||
FrmMain.PageChange(FormMain.PageType.InstanceSetup, 0)
|
FrmMain.PageChange(FormMain.PageType.InstanceSetup, 0)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:behaviors="clr-namespace:PCL.Controls.Behaviors"
|
||||||
xmlns:local="clr-namespace:PCL" PanScroll="PanBack">
|
xmlns:local="clr-namespace:PCL" PanScroll="PanBack">
|
||||||
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
<local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
|
||||||
<StackPanel Name="PanMain" Margin="25,25,25,10" Grid.IsSharedSizeScope="True">
|
<StackPanel Name="PanMain" Margin="25,25,25,10" Grid.IsSharedSizeScope="True">
|
||||||
@@ -11,7 +12,9 @@
|
|||||||
<StackPanel x:Name="PanCustom">
|
<StackPanel x:Name="PanCustom">
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="启动日志" x:Name="PanLog">
|
<local:MyCard Margin="0,0,0,15" Title="启动日志" x:Name="PanLog">
|
||||||
<TextBlock x:Name="LabLog" Margin="20,38,20,18" TextTrimming="None" TextWrapping="Wrap" />
|
<local:MyTextBox x:Name="LabLog" Margin="15,34,15,13" Padding="0,4" IsReadOnly="True" IsUndoEnabled="False"
|
||||||
|
AcceptsReturn="True" TextWrapping="Wrap" BorderThickness="0" HasBackground="False"
|
||||||
|
VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" />
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyScrollViewer>
|
</local:MyScrollViewer>
|
||||||
|
|||||||
@@ -101,23 +101,40 @@ Public Class PageLaunchRight
|
|||||||
Url = "https://pcl.wyc-w.top/index.xaml"
|
Url = "https://pcl.wyc-w.top/index.xaml"
|
||||||
Case 15
|
Case 15
|
||||||
Logger.Info("主页预设:Minecraft 芝士站")
|
Logger.Info("主页预设:Minecraft 芝士站")
|
||||||
Url = "https://www.xxag.top/mkss"
|
Url = "https://mkss-services.awaeric.xyz"
|
||||||
Case 16
|
Case 16
|
||||||
Logger.Info("主页预设:整合包推荐引擎")
|
Logger.Info("主页预设:整合包推荐引擎")
|
||||||
Url = "https://qawsedrftgyhujiko.fun/pcl2/Custom.xaml"
|
Url = "https://qawsedrftgyhujiko.fun/pcl2/Custom.xaml"
|
||||||
Case 17
|
Case 17
|
||||||
Logger.Info("Bangumi 番剧主页")
|
Logger.Info("主页预设:Bangumi 番剧主页")
|
||||||
Url = "https://bangumi.p.kaphia.qzz.io"
|
Url = "https://bangumi.p.kaphia.top"
|
||||||
Case 18
|
Case 18
|
||||||
Logger.Info("Bilibili 热门")
|
Logger.Info("主页预设:Bilibili 热门")
|
||||||
Url = "https://bilibili.p.kaphia.qzz.io"
|
Url = "https://bilibili.p.kaphia.top"
|
||||||
Case 19
|
Case 19
|
||||||
Logger.Info("Music 云音乐热门")
|
Logger.Info("主页预设:Music 云音乐热门")
|
||||||
Url = "https://cloudmusic.p.kaphia.qzz.io"
|
Url = "https://cloudmusic.p.kaphia.top"
|
||||||
|
Case 20
|
||||||
|
Logger.Info("主页预设:模组推荐")
|
||||||
|
Url = "https://g-fish.dpdns.org/download/ModPage.xaml"
|
||||||
|
Case 21
|
||||||
|
Logger.Info("主页预设:每日游戏推荐")
|
||||||
|
Url = "https://pcl.xn--9iq209asnop94b.top/download/GamePage.xaml"
|
||||||
|
Case 22
|
||||||
|
Logger.Info("主页预设:Wallpaper 每日壁纸")
|
||||||
|
Url = "https://wallpaper.p.kaphia.top"
|
||||||
|
Case 23
|
||||||
|
Logger.Info("主页预设:Weather 天气预报")
|
||||||
|
Url = "https://weather-p.kaphia.top/{variable:PCLDailyWeatherPage:choose}.xaml"
|
||||||
|
Case 24
|
||||||
|
Logger.Info("主页预设:新一代狗屁王大杂烩主页")
|
||||||
|
Url = "https://end.g-fish.dpdns.org/Custom.xaml"
|
||||||
End Select
|
End Select
|
||||||
End Select
|
End Select
|
||||||
'联网下载
|
'联网下载
|
||||||
If Not String.IsNullOrWhiteSpace(Url) Then
|
If Not String.IsNullOrWhiteSpace(Url) Then
|
||||||
|
'替换自定义变量与设置
|
||||||
|
Url = ArgumentReplace(Url, AddressOf WebUtility.HtmlEncode)
|
||||||
If Url = Settings.Get(Of String)("CacheSavedPageUrl") AndAlso FileUtils.Exists(PathTemp & "Cache\Custom.xaml") Then
|
If Url = Settings.Get(Of String)("CacheSavedPageUrl") AndAlso FileUtils.Exists(PathTemp & "Cache\Custom.xaml") Then
|
||||||
'缓存可用
|
'缓存可用
|
||||||
Logger.Info("主页自定义数据来源:联网缓存文件")
|
Logger.Info("主页自定义数据来源:联网缓存文件")
|
||||||
@@ -145,8 +162,6 @@ Public Class PageLaunchRight
|
|||||||
Dim Address As String = Task.Input.Address '#3721 中连续触发两次导致内容变化
|
Dim Address As String = Task.Input.Address '#3721 中连续触发两次导致内容变化
|
||||||
Dim ShouldRefresh As Boolean = Task.Input.ShouldRefresh
|
Dim ShouldRefresh As Boolean = Task.Input.ShouldRefresh
|
||||||
Try
|
Try
|
||||||
'替换自定义变量与设置
|
|
||||||
Address = ArgumentReplace(Address, AddressOf WebUtility.HtmlEncode)
|
|
||||||
'获取版本校验地址
|
'获取版本校验地址
|
||||||
Dim VersionAddress As String
|
Dim VersionAddress As String
|
||||||
If Address.Contains(".xaml") Then
|
If Address.Contains(".xaml") Then
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Public Class PageLoginLegacy
|
|||||||
If LoginData.UserName.Trim = "" Then Return "玩家名不能为空!"
|
If LoginData.UserName.Trim = "" Then Return "玩家名不能为空!"
|
||||||
If LoginData.UserName.Contains("""") Then Return "玩家名不能包含英文引号!"
|
If LoginData.UserName.Contains("""") Then Return "玩家名不能包含英文引号!"
|
||||||
If McInstanceSelected IsNot Nothing AndAlso
|
If McInstanceSelected IsNot Nothing AndAlso
|
||||||
McInstanceSelected.Version.Vaild AndAlso McInstanceSelected.Version.Vanilla >= New Version(20, 0, 3) AndAlso
|
McInstanceSelected.Version.Valid AndAlso McInstanceSelected.Version.Vanilla >= New Version(20, 0, 3) AndAlso
|
||||||
LoginData.UserName.Trim.Length > 16 Then
|
LoginData.UserName.Trim.Length > 16 Then
|
||||||
Return "自 1.20.3 起,玩家名至多只能包含 16 个字符!"
|
Return "自 1.20.3 起,玩家名至多只能包含 16 个字符!"
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -358,8 +358,9 @@ Public Class PageLinkMain
|
|||||||
'复制邀请码
|
'复制邀请码
|
||||||
Private Sub Copy() Handles BtnFinishCopy.Click
|
Private Sub Copy() Handles BtnFinishCopy.Click
|
||||||
Dim CodeText As String = $"在 PCL 启动器中输入邀请码【{GetInviteCode()}】,即可加入联机房间!"
|
Dim CodeText As String = $"在 PCL 启动器中输入邀请码【{GetInviteCode()}】,即可加入联机房间!"
|
||||||
ClipboardSet(CodeText, SuccessHint:="已复制邀请码!")
|
ClipboardSet(CodeText, False)
|
||||||
Settings.Set("LinkLastAutoJoinInviteCode", CodeText)
|
Settings.Set("LinkLastAutoJoinInviteCode", CodeText)
|
||||||
|
Hint("已复制邀请码!", HintType.Green)
|
||||||
End Sub
|
End Sub
|
||||||
Private Function GetInviteCode() As String
|
Private Function GetInviteCode() As String
|
||||||
Return $"{NetworkName}-{NetworkSecret}-{INVITE_CODE_VERSION.ToString.PadLeft(2, "0"c)}{ _
|
Return $"{NetworkName}-{NetworkSecret}-{INVITE_CODE_VERSION.ToString.PadLeft(2, "0"c)}{ _
|
||||||
@@ -368,7 +369,8 @@ Public Class PageLinkMain
|
|||||||
|
|
||||||
'复制 IP
|
'复制 IP
|
||||||
Private Sub BtnFinishIp_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnFinishIp.MouseLeftButtonUp
|
Private Sub BtnFinishIp_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnFinishIp.MouseLeftButtonUp
|
||||||
ClipboardSet(ClientAddress, SuccessHint:="已复制服务器地址!")
|
ClipboardSet(ClientAddress, False)
|
||||||
|
Hint("已复制服务器地址!", HintType.Green)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
<RowDefinition Height="45" />
|
<RowDefinition Height="45" />
|
||||||
<RowDefinition Height="45" />
|
<RowDefinition Height="45" />
|
||||||
<RowDefinition Height="45" />
|
<RowDefinition Height="45" />
|
||||||
|
<RowDefinition Height="45" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="40" />
|
<ColumnDefinition Width="40" />
|
||||||
@@ -20,7 +21,8 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<local:MyListItem IsHitTestVisible="False" Title="龙腾猫跃" Margin="-5,0,15,0" Info="Plain Craft Launcher 的开发者!" Grid.Row="0" Grid.Column="1" />
|
<local:MyListItem IsHitTestVisible="False" Title="龙腾猫跃" Margin="-5,0,15,0" Info="Plain Craft Launcher 的开发者!" Grid.Row="0" Grid.Column="1" />
|
||||||
<local:MyListItem IsHitTestVisible="False" Title="HerobrineXia" Margin="-5,0,15,0" Info="Plain Craft Launcher 的协力开发者!" Grid.Row="1" Grid.Column="1" />
|
<local:MyListItem IsHitTestVisible="False" Title="HerobrineXia" Margin="-5,0,15,0" Info="Plain Craft Launcher 的协力开发者!" Grid.Row="1" Grid.Column="1" />
|
||||||
<local:MyListItem IsHitTestVisible="False" Title="Plain Craft Launcher 2" Margin="-5,0,15,0" Info="当前版本:%VERSION%(%VERSIONCODE%.%BRANCH%)" Grid.Row="2" Grid.Column="1" x:Name="ItemAboutPcl" />
|
<local:MyListItem IsHitTestVisible="False" Title="Coldsmile_7" Margin="-5,0,15,0" Info="Plain Craft Launcher (PCL) InfstarMC Edition 的开发者!" Grid.Row="2" Grid.Column="1" />
|
||||||
|
<local:MyListItem IsHitTestVisible="False" Title="Plain Craft Launcher (PCL) InfstarMC Edition" Margin="-5,0,15,0" Info="当前版本:%VERSION%(%VERSIONCODE%.%BRANCH%)" Grid.Row="3" Grid.Column="1" x:Name="ItemAboutPcl" />
|
||||||
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/LTCat.jpg" Grid.Row="0" Margin="3">
|
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/LTCat.jpg" Grid.Row="0" Margin="3">
|
||||||
<Image.Clip>
|
<Image.Clip>
|
||||||
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
@@ -36,10 +38,16 @@
|
|||||||
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
</Image.Clip>
|
</Image.Clip>
|
||||||
</Image>
|
</Image>
|
||||||
|
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/Logo.png" Grid.Row="3" Margin="3">
|
||||||
|
<Image.Clip>
|
||||||
|
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
|
||||||
|
</Image.Clip>
|
||||||
|
</Image>
|
||||||
<local:MyButton Text="赞助 PCL !" Grid.Column="2" Grid.Row="0" Height="35" ColorType="Highlight"
|
<local:MyButton Text="赞助 PCL !" Grid.Column="2" Grid.Row="0" Height="35" ColorType="Highlight"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://meloong.com/afd/a/LTCat" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://meloong.com/afd/a/LTCat" />
|
||||||
<local:MyButton Text="检查更新" Grid.Column="2" Grid.Row="2" Height="35"
|
<local:MyButton Text="项目仓库" Grid.Column="2" Grid.Row="2" Height="35"
|
||||||
x:Name="BtnAboutUpdate" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://git.infstar.cn/InfStarMC/PCL-ISE" />
|
||||||
|
<local:MyButton Text="检查更新" Grid.Column="2" Grid.Row="3" Height="35" x:Name="BtnAboutUpdate" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
<local:MyCard Margin="0,0,0,15" Title="特别鸣谢">
|
<local:MyCard Margin="0,0,0,15" Title="特别鸣谢">
|
||||||
@@ -131,388 +139,391 @@
|
|||||||
<local:MyCard Margin="0,0,0,15" Title="赞助者">
|
<local:MyCard Margin="0,0,0,15" Title="赞助者">
|
||||||
<StackPanel Margin="25,40,19,20">
|
<StackPanel Margin="25,40,19,20">
|
||||||
<TextBlock HorizontalAlignment="Left" Text="以下是近期的高级赞助者们!感谢大家对 PCL 的支持!!!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
<TextBlock HorizontalAlignment="Left" Text="以下是近期的高级赞助者们!感谢大家对 PCL 的支持!!!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
|
||||||
<WrapPanel Margin="0,0,0,10">
<TextBlock Margin="0,1.5,6,0" Text="L" />
|
<WrapPanel Margin="0,0,0,10">
<TextBlock Margin="0,1.5,6,0" Text="J" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Z" />
|
<TextBlock Margin="0,1.5,6,0" Text="R" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="N" />
|
<TextBlock Margin="0,1.5,6,0" Text="D" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="P." />
|
<TextBlock Margin="0,1.5,6,0" Text="hj" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="...:" />
|
<TextBlock Margin="0,1.5,6,0" Text="乖" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="妖" />
|
<TextBlock Margin="0,1.5,6,0" Text="吕" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="FL" />
|
<TextBlock Margin="0,1.5,6,0" Text="宇" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="萧" />
|
<TextBlock Margin="0,1.5,6,0" Text="FF" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="乔" />
|
<TextBlock Margin="0,1.5,6,0" Text="金" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="cc" />
|
<TextBlock Margin="0,1.5,6,0" Text="夏" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="!" />
|
<TextBlock Margin="0,1.5,6,0" Text="鸿" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="一" />
|
<TextBlock Margin="0,1.5,6,0" Text="ツ" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="韆" />
|
<TextBlock Margin="0,1.5,6,0" Text="枫" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="莫" />
|
<TextBlock Margin="0,1.5,6,0" Text="SF" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="无" />
|
<TextBlock Margin="0,1.5,6,0" Text="kll" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="澍" />
|
<TextBlock Margin="0,1.5,6,0" Text="02" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ttt" />
|
<TextBlock Margin="0,1.5,6,0" Text="YY" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="88" />
|
<TextBlock Margin="0,1.5,6,0" Text="……" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="33" />
|
<TextBlock Margin="0,1.5,6,0" Text="shy" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="kk" />
|
<TextBlock Margin="0,1.5,6,0" Text="lost" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="jjb" />
|
<TextBlock Margin="0,1.5,6,0" Text="A仔" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="狮." />
|
<TextBlock Margin="0,1.5,6,0" Text="111" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="+1" />
|
<TextBlock Margin="0,1.5,6,0" Text="afaf" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Iirs" />
|
<TextBlock Margin="0,1.5,6,0" Text="pen" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Lio" />
|
<TextBlock Margin="0,1.5,6,0" Text="lulu" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="lrw" />
|
<TextBlock Margin="0,1.5,6,0" Text="xyty" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="LLL" />
|
<TextBlock Margin="0,1.5,6,0" Text="排骨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Sht" />
|
<TextBlock Margin="0,1.5,6,0" Text="踏雾" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Nul" />
|
<TextBlock Margin="0,1.5,6,0" Text="Zsol" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="250" />
|
<TextBlock Margin="0,1.5,6,0" Text="景仪" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Life" />
|
<TextBlock Margin="0,1.5,6,0" Text="可可" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="kile" />
|
<TextBlock Margin="0,1.5,6,0" Text="白夜" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="pbc" />
|
<TextBlock Margin="0,1.5,6,0" Text="汤圆" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Aya" />
|
<TextBlock Margin="0,1.5,6,0" Text="星月" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="mjp" />
|
<TextBlock Margin="0,1.5,6,0" Text="皓月" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="azzt" />
|
<TextBlock Margin="0,1.5,6,0" Text="老建" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小小" />
|
<TextBlock Margin="0,1.5,6,0" Text="阿琼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="冒子" />
|
<TextBlock Margin="0,1.5,6,0" Text="晓月" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="王道" />
|
<TextBlock Margin="0,1.5,6,0" Text="朝雨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鸡人" />
|
<TextBlock Margin="0,1.5,6,0" Text="迟雨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="喵根" />
|
<TextBlock Margin="0,1.5,6,0" Text="折纸" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="折花" />
|
<TextBlock Margin="0,1.5,6,0" Text="张某" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="归墟" />
|
<TextBlock Margin="0,1.5,6,0" Text="残月" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="墨渊" />
|
<TextBlock Margin="0,1.5,6,0" Text="缘分" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="键来" />
|
<TextBlock Margin="0,1.5,6,0" Text="静态" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="睚眦" />
|
<TextBlock Margin="0,1.5,6,0" Text="铭熙" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="而后" />
|
<TextBlock Margin="0,1.5,6,0" Text="酒狐" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="南安" />
|
<TextBlock Margin="0,1.5,6,0" Text="誌異" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="曰久" />
|
<TextBlock Margin="0,1.5,6,0" Text="灵喵" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小翼" />
|
<TextBlock Margin="0,1.5,6,0" Text="曦宇" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鲤逐" />
|
<TextBlock Margin="0,1.5,6,0" Text="木辛" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="陌天" />
|
<TextBlock Margin="0,1.5,6,0" Text="轻梦" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="eqw" />
|
<TextBlock Margin="0,1.5,6,0" Text="熊猫" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="缘泠" />
|
<TextBlock Margin="0,1.5,6,0" Text="鱼柳" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="烨落" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="安安" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="寒叙" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="诶嘿" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="月月" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="凌迟" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="泰吉" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="楚渡" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="将夜" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="滴雨" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="无萤" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="秋水" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="团子" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="川儿" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="冥曌" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="红中" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小云" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="诗人" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="狐狸" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="游阙" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="悠真" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="天雨" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="章凤" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="空空" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="去衣" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="老抽" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="七海" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="品茗" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="白桦" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="狐斋" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="猫神" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="乙总" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="屺野" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="极光" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="哈哈" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小洛" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="璃辰" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="茉莉" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="旅人" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="航卡" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="班总" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小圆" />
|
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="梨子" />
|
<TextBlock Margin="0,1.5,6,0" Text="梨子" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="风?" />
|
<TextBlock Margin="0,1.5,6,0" Text="小本" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="瓜瓜" />
|
<TextBlock Margin="0,1.5,6,0" Text="起媛" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="阳光" />
|
<TextBlock Margin="0,1.5,6,0" Text="夏天" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="菜菜" />
|
<TextBlock Margin="0,1.5,6,0" Text="泪痕" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="副连" />
|
<TextBlock Margin="0,1.5,6,0" Text="南北" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="如舟" />
|
<TextBlock Margin="0,1.5,6,0" Text="灰鱼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="bow" />
|
<TextBlock Margin="0,1.5,6,0" Text="灰尘" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Byet" />
|
<TextBlock Margin="0,1.5,6,0" Text="骗铭" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Kian" />
|
<TextBlock Margin="0,1.5,6,0" Text="青轴" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ZDD" />
|
<TextBlock Margin="0,1.5,6,0" Text="谷雨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Um1" />
|
<TextBlock Margin="0,1.5,6,0" Text="呈祥" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="2514" />
|
<TextBlock Margin="0,1.5,6,0" Text="猫玖" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="4440" />
|
<TextBlock Margin="0,1.5,6,0" Text="枕月" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Fu_jc" />
|
<TextBlock Margin="0,1.5,6,0" Text="刘革" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="LEVA" />
|
<TextBlock Margin="0,1.5,6,0" Text="折花" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ZNLL" />
|
<TextBlock Margin="0,1.5,6,0" Text="应星" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="joker" />
|
<TextBlock Margin="0,1.5,6,0" Text="没有" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="花园" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="华烬" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="啥猫" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="阿伯" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="妄想" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="树叶" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="拾玖" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="让人" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="晓光" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="懿尘" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="尾巴" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="枯骨" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="鹤升" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="遊泠" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="裕茗" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="沁园" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="尹伊" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="枫音" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="古色" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="傻鱼" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="幻灭" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="小琪" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="小寒" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="星狗" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="玄米" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="菜狗" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="ZWL" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="1234" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text=" 清空" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="7104" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="2333" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="5-DF" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="qqes" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="Patxi" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="Sage" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="R301" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="RXZY" />
|
<TextBlock Margin="0,1.5,6,0" Text="RXZY" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="白成y" />
|
<TextBlock Margin="0,1.5,6,0" Text="Siwill" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="mww" />
|
<TextBlock Margin="0,1.5,6,0" Text="kassa" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Rofni" />
|
<TextBlock Margin="0,1.5,6,0" Text="ssdsb" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="mzqc" />
|
<TextBlock Margin="0,1.5,6,0" Text="Ztdzz" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="jason" />
|
<TextBlock Margin="0,1.5,6,0" Text="xiboa" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="youzi" />
|
<TextBlock Margin="0,1.5,6,0" Text="ZERO" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="xxlzta" />
|
<TextBlock Margin="0,1.5,6,0" Text="pr1nk" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="end_x" />
|
<TextBlock Margin="0,1.5,6,0" Text="BBUH" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="QWYJ" />
|
<TextBlock Margin="0,1.5,6,0" Text="ALISA" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="qwqw" />
|
<TextBlock Margin="0,1.5,6,0" Text="89623" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Angel" />
|
<TextBlock Margin="0,1.5,6,0" Text="IDXLZ" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="15041" />
|
<TextBlock Margin="0,1.5,6,0" Text="翎羽絮" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="晓空er" />
|
<TextBlock Margin="0,1.5,6,0" Text="硫酸梅" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="kaoyu" />
|
<TextBlock Margin="0,1.5,6,0" Text="死鱼梦" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="肥富帅" />
|
<TextBlock Margin="0,1.5,6,0" Text="秦始皇" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小王子" />
|
<TextBlock Margin="0,1.5,6,0" Text="春忆雪" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="狐狸涩" />
|
<TextBlock Margin="0,1.5,6,0" Text="冷空气" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="大涡流" />
|
<TextBlock Margin="0,1.5,6,0" Text="天崇域" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="无名氏" />
|
<TextBlock Margin="0,1.5,6,0" Text="白与沧" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="紫风狐" />
|
<TextBlock Margin="0,1.5,6,0" Text="柳蕴訫" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="杨巨焕" />
|
<TextBlock Margin="0,1.5,6,0" Text="苟子丶" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="范桂圆" />
|
<TextBlock Margin="0,1.5,6,0" Text="午時夢" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="芸芸云" />
|
<TextBlock Margin="0,1.5,6,0" Text="清水石" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="快夏波" />
|
<TextBlock Margin="0,1.5,6,0" Text="鹿鹤云" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="陈知远" />
|
<TextBlock Margin="0,1.5,6,0" Text="洛沫兀" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="梦华书" />
|
<TextBlock Margin="0,1.5,6,0" Text="。。。" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="樱咲夜" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="星期天" />
|
<TextBlock Margin="0,1.5,6,0" Text="星期天" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="铸日者" />
|
<TextBlock Margin="0,1.5,6,0" Text="制花人" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="晴云雯" />
|
<TextBlock Margin="0,1.5,6,0" Text="aleMk" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="叶龙辉" />
|
<TextBlock Margin="0,1.5,6,0" Text="张炜国" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小零蚀" />
|
<TextBlock Margin="0,1.5,6,0" Text="咦嘻嘻" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="唐墨白" />
|
<TextBlock Margin="0,1.5,6,0" Text="拟态虫" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="香子兰" />
|
<TextBlock Margin="0,1.5,6,0" Text="蜥蜴拔" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="胡萝北" />
|
<TextBlock Margin="0,1.5,6,0" Text="鬼画符" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="乐永昶" />
|
<TextBlock Margin="0,1.5,6,0" Text="孙无为" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="lingke" />
|
<TextBlock Margin="0,1.5,6,0" Text="浅陌菌" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="东雪莲" />
|
<TextBlock Margin="0,1.5,6,0" Text="黯域星" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="殷疯子" />
|
<TextBlock Margin="0,1.5,6,0" Text="愿不惑" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="伊文斯" />
|
<TextBlock Margin="0,1.5,6,0" Text="三色堇" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="丁乙恒" />
|
<TextBlock Margin="0,1.5,6,0" Text="訫卜變" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="朔望月" />
|
<TextBlock Margin="0,1.5,6,0" Text="周家逸" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="V0rt3x" />
|
<TextBlock Margin="0,1.5,6,0" Text="水芃叁" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="提灯狼" />
|
<TextBlock Margin="0,1.5,6,0" Text="无限旡" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="王孟清" />
|
<TextBlock Margin="0,1.5,6,0" Text="Enrico" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="牛排鸭" />
|
<TextBlock Margin="0,1.5,6,0" Text="???" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="王靖淳" />
|
<TextBlock Margin="0,1.5,6,0" Text="小南新" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="嘿嘿地" />
|
<TextBlock Margin="0,1.5,6,0" Text="星千织" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鹿露璐" />
|
<TextBlock Margin="0,1.5,6,0" Text="CX330" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="琪露诺" />
|
<TextBlock Margin="0,1.5,6,0" Text="林空月" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="亚波人" />
|
<TextBlock Margin="0,1.5,6,0" Text="花开丶" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="卿天岚" />
|
<TextBlock Margin="0,1.5,6,0" Text="琉璃子" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="哈士奇" />
|
<TextBlock Margin="0,1.5,6,0" Text="冰冰冰" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="江溪渺" />
|
<TextBlock Margin="0,1.5,6,0" Text="老花眼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="浮千傀" />
|
<TextBlock Margin="0,1.5,6,0" Text="哈贝吧" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="恰啦啦" />
|
<TextBlock Margin="0,1.5,6,0" Text="蘑菇头" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="梦痕丿" />
|
<TextBlock Margin="0,1.5,6,0" Text="小黄刀" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="三叶铭" />
|
<TextBlock Margin="0,1.5,6,0" Text="大破林" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="卿姬昉" />
|
<TextBlock Margin="0,1.5,6,0" Text="倾伏离" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="疯一回" />
|
<TextBlock Margin="0,1.5,6,0" Text="豆角君" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="李困困" />
|
<TextBlock Margin="0,1.5,6,0" Text="灵玄机" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="厄尔萨" />
|
<TextBlock Margin="0,1.5,6,0" Text="Sherry" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="伏拉夫" />
|
<TextBlock Margin="0,1.5,6,0" Text="lizi756" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="α-蒎烯" />
|
<TextBlock Margin="0,1.5,6,0" Text="letitbe" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="你的JK" />
|
<TextBlock Margin="0,1.5,6,0" Text="Ikorito" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="jiujinh" />
|
<TextBlock Margin="0,1.5,6,0" Text="MCDD" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="慕qwq" />
|
<TextBlock Margin="0,1.5,6,0" Text="nihility" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Twicat" />
|
<TextBlock Margin="0,1.5,6,0" Text="小宇Bo" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="stenac" />
|
<TextBlock Margin="0,1.5,6,0" Text="2789th" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="JOKER" />
|
<TextBlock Margin="0,1.5,6,0" Text="S1NKO" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="半日谣." />
|
<TextBlock Margin="0,1.5,6,0" Text="Rimlue" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="EX星辞" />
|
<TextBlock Margin="0,1.5,6,0" Text="FMDQI" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Tefrish" />
|
<TextBlock Margin="0,1.5,6,0" Text="Aevrud" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Triple9" />
|
<TextBlock Margin="0,1.5,6,0" Text="Larry76" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="gediao" />
|
<TextBlock Margin="0,1.5,6,0" Text="Miantu" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Zen1th" />
|
<TextBlock Margin="0,1.5,6,0" Text="Nature." />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="CH南宫" />
|
<TextBlock Margin="0,1.5,6,0" Text="Autism." />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="qiumin" />
|
<TextBlock Margin="0,1.5,6,0" Text="MXUER" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="cui白烁" />
|
<TextBlock Margin="0,1.5,6,0" Text="suifeng" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="anyayu" />
|
<TextBlock Margin="0,1.5,6,0" Text="Yangeh" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="SISENG" />
|
<TextBlock Margin="0,1.5,6,0" Text="Anmisu" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ro-suto" />
|
<TextBlock Margin="0,1.5,6,0" Text="TinkerZ" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="GAGUA" />
|
<TextBlock Margin="0,1.5,6,0" Text="LaoGou" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Yi_xuan" />
|
<TextBlock Margin="0,1.5,6,0" Text="lkhkykk" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="MC芬达" />
|
<TextBlock Margin="0,1.5,6,0" Text="N/Azais" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="shallow" />
|
<TextBlock Margin="0,1.5,6,0" Text="KISSHIP" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ETL蓝夢" />
|
<TextBlock Margin="0,1.5,6,0" Text="Vanessa" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="𝕳轩辕氏" />
|
<TextBlock Margin="0,1.5,6,0" Text="lanyuan" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="谜茶360" />
|
<TextBlock Margin="0,1.5,6,0" Text="BBBKKK" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="颜沐Jun" />
|
<TextBlock Margin="0,1.5,6,0" Text="mchim1" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="CS2七松" />
|
<TextBlock Margin="0,1.5,6,0" Text="MANBA" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Eventful" />
|
<TextBlock Margin="0,1.5,6,0" Text="Tairitsu_" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Molioos" />
|
<TextBlock Margin="0,1.5,6,0" Text="宇陌୧⍤⃝🇨🇳" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="logicum" />
|
<TextBlock Margin="0,1.5,6,0" Text="我不在线" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Mr_loba" />
|
<TextBlock Margin="0,1.5,6,0" Text="南吕十三" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="一叶知秋" />
|
<TextBlock Margin="0,1.5,6,0" Text="Parapha" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="我妻狗卷" />
|
<TextBlock Margin="0,1.5,6,0" Text="开始学习" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="御神凌霜" />
|
<TextBlock Margin="0,1.5,6,0" Text="对方和你" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="狼烟居士" />
|
<TextBlock Margin="0,1.5,6,0" Text="雪辰千叶" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="千风伶羽" />
|
<TextBlock Margin="0,1.5,6,0" Text="残风尘缘" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="mumiao" />
|
<TextBlock Margin="0,1.5,6,0" Text="黄粱一梦" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="欧刃赛卌" />
|
<TextBlock Margin="0,1.5,6,0" Text="腊肉清蒸" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="蓝白幻影" />
|
<TextBlock Margin="0,1.5,6,0" Text="画下花夏" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鸭梨山大" />
|
<TextBlock Margin="0,1.5,6,0" Text="蛮列后备" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="一条鱼瓯" />
|
<TextBlock Margin="0,1.5,6,0" Text="魔法少年" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="苇渚泊舟" />
|
<TextBlock Margin="0,1.5,6,0" Text="戒者有八" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="花开富贵" />
|
<TextBlock Margin="0,1.5,6,0" Text="躺平如尸" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="多肉藕片" />
|
<TextBlock Margin="0,1.5,6,0" Text="萝卜奶酪" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="浮屠阿仙" />
|
<TextBlock Margin="0,1.5,6,0" Text="Erinneys" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="繁星萤火" />
|
<TextBlock Margin="0,1.5,6,0" Text="病名為愛" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="沐风沐雨" />
|
<TextBlock Margin="0,1.5,6,0" Text="伊卡洛斯" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="金槍羽翼" />
|
<TextBlock Margin="0,1.5,6,0" Text="云鹰肥将" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="龘羅孖倆" />
|
<TextBlock Margin="0,1.5,6,0" Text="爱莉信徒" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鸽子王雷" />
|
<TextBlock Margin="0,1.5,6,0" Text="user晚曦" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="红莲焚霞" />
|
<TextBlock Margin="0,1.5,6,0" Text="欣某在此" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="老凌野少" />
|
<TextBlock Margin="0,1.5,6,0" Text="繁星末路" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="孤酒青魇" />
|
<TextBlock Margin="0,1.5,6,0" Text="鲸鱼橘子" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="天空奇己" />
|
<TextBlock Margin="0,1.5,6,0" Text="坠入幻想" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="霜月秋阳" />
|
<TextBlock Margin="0,1.5,6,0" Text="卑微老万" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="啃瓜咸鱼" />
|
<TextBlock Margin="0,1.5,6,0" Text="乌云踏雪" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="淡墨染星" />
|
<TextBlock Margin="0,1.5,6,0" Text="公积金卡" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="2k2k114" />
|
<TextBlock Margin="0,1.5,6,0" Text="各务原念" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="肉蛋葱鸡" />
|
<TextBlock Margin="0,1.5,6,0" Text="风间琉璃" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="傻鹅二号" />
|
<TextBlock Margin="0,1.5,6,0" Text="杨枝甘露" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="动漫阿宅" />
|
<TextBlock Margin="0,1.5,6,0" Text="晚安晚安" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="只若初见" />
|
<TextBlock Margin="0,1.5,6,0" Text="牛奶曲奇" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Sakuzyo" />
|
<TextBlock Margin="0,1.5,6,0" Text="魔法空间" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="1415145" />
|
<TextBlock Margin="0,1.5,6,0" Text="一路向北" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="消失的喵" />
|
<TextBlock Margin="0,1.5,6,0" Text="百里无焉" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="春山如笑" />
|
<TextBlock Margin="0,1.5,6,0" Text="皮蛋肥猫" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="幻天阿绝" />
|
<TextBlock Margin="0,1.5,6,0" Text="身披坚甲" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="忘道蜂枫" />
|
<TextBlock Margin="0,1.5,6,0" Text="近则不逊" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="深海无渊" />
|
<TextBlock Margin="0,1.5,6,0" Text="卡白小洛" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="心软的神" />
|
<TextBlock Margin="0,1.5,6,0" Text="即墨非墨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="砂锅豆腐" />
|
<TextBlock Margin="0,1.5,6,0" Text="准备冒险" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="好人好逝" />
|
<TextBlock Margin="0,1.5,6,0" Text="喰梦优音" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="登峰破晓" />
|
<TextBlock Margin="0,1.5,6,0" Text="雨夜色中" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="东隅未殁" />
|
<TextBlock Margin="0,1.5,6,0" Text="沃特拉奇" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="星花银影" />
|
<TextBlock Margin="0,1.5,6,0" Text="闲鱼教授" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="往事如昔" />
|
<TextBlock Margin="0,1.5,6,0" Text="北川暮雨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="林克之空" />
|
<TextBlock Margin="0,1.5,6,0" Text="生根发芽" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="0X00001" />
|
<TextBlock Margin="0,1.5,6,0" Text="暮霭凝缘" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="MuMAA" />
|
<TextBlock Margin="0,1.5,6,0" Text="孤灯裹尘" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="溯枫qwq" />
|
<TextBlock Margin="0,1.5,6,0" Text="日薪月亿" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Tacenda" />
|
<TextBlock Margin="0,1.5,6,0" Text="北默千鹤" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="sky fung" />
|
<TextBlock Margin="0,1.5,6,0" Text="咸鱼一条" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="👁👄👃" />
|
<TextBlock Margin="0,1.5,6,0" Text="禾辞共振" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="秋慕owo" />
|
<TextBlock Margin="0,1.5,6,0" Text="雨宫冰莲" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="船长Yuki" />
|
<TextBlock Margin="0,1.5,6,0" Text="BG4LHO" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="HIMEKO" />
|
<TextBlock Margin="0,1.5,6,0" Text="没啥想法" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="是小61呀" />
|
<TextBlock Margin="0,1.5,6,0" Text="古色沉竹" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="47号虾球" />
|
<TextBlock Margin="0,1.5,6,0" Text="W污狮W" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Alancnel" />
|
<TextBlock Margin="0,1.5,6,0" Text="jinyucao" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Muertesl" />
|
<TextBlock Margin="0,1.5,6,0" Text="MESGRZ" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="猫幺Suro" />
|
<TextBlock Margin="0,1.5,6,0" Text="qiewang" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="i'g'd'y'f's" />
|
<TextBlock Margin="0,1.5,6,0" Text="bao9898" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="xiaochen" />
|
<TextBlock Margin="0,1.5,6,0" Text="幻沫_123" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ㅤSIMV9r" />
|
<TextBlock Margin="0,1.5,6,0" Text="Yuting.Li" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="alpHabet" />
|
<TextBlock Margin="0,1.5,6,0" Text="Zaaaako" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Charlotte" />
|
<TextBlock Margin="0,1.5,6,0" Text="Tianqiao" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="paperfish" />
|
<TextBlock Margin="0,1.5,6,0" Text="EMILIIIIA" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="stealtoup" />
|
<TextBlock Margin="0,1.5,6,0" Text="阿尔法.@" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="bingyan0" />
|
<TextBlock Margin="0,1.5,6,0" Text="neymarjr" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="MselQAQ" />
|
<TextBlock Margin="0,1.5,6,0" Text="AsUWish" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="UZQueen" />
|
<TextBlock Margin="0,1.5,6,0" Text="waxberry" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="hihospital" />
|
<TextBlock Margin="0,1.5,6,0" Text="彼岸的***" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="cutegirl3k" />
|
<TextBlock Margin="0,1.5,6,0" Text="liminalily" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Prifo_lone" />
|
<TextBlock Margin="0,1.5,6,0" Text="sansisthe" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="有....暗星!" />
|
<TextBlock Margin="0,1.5,6,0" Text="RickyZhu" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Hitsser 1.0" />
|
<TextBlock Margin="0,1.5,6,0" Text="TenKings" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="一只憨火龙" />
|
<TextBlock Margin="0,1.5,6,0" Text="yvnchvan" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="异色收集癖" />
|
<TextBlock Margin="0,1.5,6,0" Text="喵呜派zzz" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="DsxiaKsxia" />
|
<TextBlock Margin="0,1.5,6,0" Text="Mz小狐仙" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Plainsman" />
|
<TextBlock Margin="0,1.5,6,0" Text="huangwu" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="湛蓝一四七" />
|
<TextBlock Margin="0,1.5,6,0" Text="玖月Yiyue" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="凛果与百橙" />
|
<TextBlock Margin="0,1.5,6,0" Text="石头WAW" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="叶落才知秋" />
|
<TextBlock Margin="0,1.5,6,0" Text="YiYi_Sama" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="好喝的氦三" />
|
<TextBlock Margin="0,1.5,6,0" Text="theancato" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="星河奈叶风" />
|
<TextBlock Margin="0,1.5,6,0" Text="Feng_mee" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="魔法且河豚" />
|
<TextBlock Margin="0,1.5,6,0" Text="_東森浮星_" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="魏小泓泓泓" />
|
<TextBlock Margin="0,1.5,6,0" Text="dark 寿司s" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="阴冷潮湿酱" />
|
<TextBlock Margin="0,1.5,6,0" Text="zhouuohz" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="一只白色缨" />
|
<TextBlock Margin="0,1.5,6,0" Text="躺床上发霉" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="结局的椰子" />
|
<TextBlock Margin="0,1.5,6,0" Text="装睡的少爷" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="三玖二拾柒" />
|
<TextBlock Margin="0,1.5,6,0" Text="无想的贤者" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="旭旭大魔王" />
|
<TextBlock Margin="0,1.5,6,0" Text="我不是陌行" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="离人如飘萍" />
|
<TextBlock Margin="0,1.5,6,0" Text="海绵体宝宝" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="秋葉逐殘夏" />
|
<TextBlock Margin="0,1.5,6,0" Text="猫不吃咸鱼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="水星有海吗" />
|
<TextBlock Margin="0,1.5,6,0" Text="别太失望啦" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="吃饱爱睡觉" />
|
<TextBlock Margin="0,1.5,6,0" Text="土豆粉底液" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="ac纯萌新cy" />
|
<TextBlock Margin="0,1.5,6,0" Text="沈默已陌鑫" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="岁月suiyue" />
|
<TextBlock Margin="0,1.5,6,0" Text="向神明祈祷" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="陌然MajorC" />
|
<TextBlock Margin="0,1.5,6,0" Text="Zurkey106" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="-Pareidolia." />
|
<TextBlock Margin="0,1.5,6,0" Text="stargolven" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="蛙蛙大王Kzr" />
|
<TextBlock Margin="0,1.5,6,0" Text="拒绝过阿姨" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Aurorawalk" />
|
<TextBlock Margin="0,1.5,6,0" Text="拟态深埋箱" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Yhcmdbfwz" />
|
<TextBlock Margin="0,1.5,6,0" Text="凤凰院凶真" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Ayers赜蠹嬭" />
|
<TextBlock Margin="0,1.5,6,0" Text="时间&轮盘" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="We1J1uSh1" />
|
<TextBlock Margin="0,1.5,6,0" Text="无心于刹那" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="xinghen233" />
|
<TextBlock Margin="0,1.5,6,0" Text="粗心忘带头" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="kingkongair" />
|
<TextBlock Margin="0,1.5,6,0" Text="提线的人偶" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="最后一只斑鸠" />
|
<TextBlock Margin="0,1.5,6,0" Text="非慕所不敬" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="随便写的名字" />
|
<TextBlock Margin="0,1.5,6,0" Text="天生会炸鱼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="芥末味青豌豆" />
|
<TextBlock Margin="0,1.5,6,0" Text="世界第一矮" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鹅给金华额度" />
|
<TextBlock Margin="0,1.5,6,0" Text="雷焰不虚误" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="LisaPatorsed" />
|
<TextBlock Margin="0,1.5,6,0" Text="一株腐竹吖" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="鸡屁股配大蒜" />
|
<TextBlock Margin="0,1.5,6,0" Text="七曜不打针" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="我真没想开摆" />
|
<TextBlock Margin="0,1.5,6,0" Text="Ferrum000" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="我不想取名字" />
|
<TextBlock Margin="0,1.5,6,0" Text="小白pandk" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="平安京的封兽" />
|
<TextBlock Margin="0,1.5,6,0" Text="LapalceXIII" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="被压力的鸭梨" />
|
<TextBlock Margin="0,1.5,6,0" Text="charlesmin" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小田love白子" />
|
<TextBlock Margin="0,1.5,6,0" Text="DeepSleep" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Sasha_Xiong" />
|
<TextBlock Margin="0,1.5,6,0" Text="rishaoshan" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="赤狸_crisnow" />
|
<TextBlock Margin="0,1.5,6,0" Text="LJJ有擎天柱" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="dorod月gour" />
|
<TextBlock Margin="0,1.5,6,0" Text="builder天识" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Name0emaN" />
|
<TextBlock Margin="0,1.5,6,0" Text="Cathan猫皁" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="happypickles" />
|
<TextBlock Margin="0,1.5,6,0" Text="猫熊NICEST" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="无中生有为dd" />
|
<TextBlock Margin="0,1.5,6,0" Text="heaven伯特" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="polarisdream" />
|
<TextBlock Margin="0,1.5,6,0" Text="礼央子sama" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="YHKooooooy" />
|
<TextBlock Margin="0,1.5,6,0" Text="蠢萌der小白" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Sakura2403ly" />
|
<TextBlock Margin="0,1.5,6,0" Text="Dying Bone" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Flying Potato" />
|
<TextBlock Margin="0,1.5,6,0" Text="DaisyCrown" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="陈昊骏泥碳GR" />
|
<TextBlock Margin="0,1.5,6,0" Text="2127864647" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="funnyzhuling" />
|
<TextBlock Margin="0,1.5,6,0" Text="Z123456789" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Turbo_Zhang" />
|
<TextBlock Margin="0,1.5,6,0" Text="MOMOHAN" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="SUBLawrence" />
|
<TextBlock Margin="0,1.5,6,0" Text="舸沫_Official" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Epsilon-9新人" />
|
<TextBlock Margin="0,1.5,6,0" Text="ξKō Hei-seiξ" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="TheDovebach" />
|
<TextBlock Margin="0,1.5,6,0" Text="CookieNeko" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="wobushi_furry" />
|
<TextBlock Margin="0,1.5,6,0" Text="伊吹风子大人" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="FTC夏日的余晖" />
|
<TextBlock Margin="0,1.5,6,0" Text="バベルの悪霊" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Isshiki Satoshi" />
|
<TextBlock Margin="0,1.5,6,0" Text="沉默的玄晓羲" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Srive_Schegler" />
|
<TextBlock Margin="0,1.5,6,0" Text="为什么水无鱼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="1080p安全卫士" />
|
<TextBlock Margin="0,1.5,6,0" Text="无敌猫猫刺客" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="开心上学玩游戏" />
|
<TextBlock Margin="0,1.5,6,0" Text="久恋丿如初漾" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="重生之发财传奇" />
|
<TextBlock Margin="0,1.5,6,0" Text="肥宅不是胖子" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="某科学的小狐狸" />
|
<TextBlock Margin="0,1.5,6,0" Text="路边的小野寺" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="爱喝可乐的猫猫" />
|
<TextBlock Margin="0,1.5,6,0" Text="要一个手抓饼" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Vsinger-洛天依" />
|
<TextBlock Margin="0,1.5,6,0" Text="从未擦肩而过" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="芙利莲最も強い" />
|
<TextBlock Margin="0,1.5,6,0" Text="瓜皮的大甘蔗" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="洋葱香菜炒蛋子" />
|
<TextBlock Margin="0,1.5,6,0" Text="LI_JIACHENG" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="不开心,不快乐" />
|
<TextBlock Margin="0,1.5,6,0" Text="mouyangjun" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="忧郁的破产鼠鼠" />
|
<TextBlock Margin="0,1.5,6,0" Text="我no想取名字" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="我的世界爱好者" />
|
<TextBlock Margin="0,1.5,6,0" Text="机电2516汪帅" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="半透明的小透明" />
|
<TextBlock Margin="0,1.5,6,0" Text="QueNanNNN" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="到处闲逛的咸鱼" />
|
<TextBlock Margin="0,1.5,6,0" Text="huamozhuke" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="什么落寒都不是" />
|
<TextBlock Margin="0,1.5,6,0" Text="Titanic Rising" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="没什么名字好取" />
|
<TextBlock Margin="0,1.5,6,0" Text="Skymunchrex" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Wanderer5147" />
|
<TextBlock Margin="0,1.5,6,0" Text="☆百☆岁☆枭☆" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="取个名字耗阳寿" />
|
<TextBlock Margin="0,1.5,6,0" Text="CarbonDHeat" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="北熊何时与狼行" />
|
<TextBlock Margin="0,1.5,6,0" Text="不爱fa电的小安" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="向着有风的地方" />
|
<TextBlock Margin="0,1.5,6,0" Text="是enderman噢" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="AAA神秘人批发" />
|
<TextBlock Margin="0,1.5,6,0" Text="无敌兵王陈亚蒙" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Bangbang2025" />
|
<TextBlock Margin="0,1.5,6,0" Text="申鹤红绳牵我魂" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="贝吉蒙Begimon" />
|
<TextBlock Margin="0,1.5,6,0" Text="背不完的郭同学" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="取个名字真难0.0" />
|
<TextBlock Margin="0,1.5,6,0" Text="追随自己的星星" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="NoTuring_Steve" />
|
<TextBlock Margin="0,1.5,6,0" Text="帅道无上大宗师" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="VividerCafe2379" />
|
<TextBlock Margin="0,1.5,6,0" Text="LucidZuowang" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="冰冰watermelon" />
|
<TextBlock Margin="0,1.5,6,0" Text="AAA.果粒橙批发" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="DOODOODOOD" />
|
<TextBlock Margin="0,1.5,6,0" Text="Omega•Epsilon" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="怕做苦力的苦力怕" />
|
<TextBlock Margin="0,1.5,6,0" Text="Ries1ing_嗷菲兽" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="小句号就是小句号" />
|
<TextBlock Margin="0,1.5,6,0" Text="Understand You" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="弹跳爆炸小鱼珠🐟" />
|
<TextBlock Margin="0,1.5,6,0" Text="AAADasAbi9527" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="Xanadu Silk Fable" />
|
<TextBlock Margin="0,1.5,6,0" Text="筱筱雨吖_Official" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="看我的都得白内障了" />
|
<TextBlock Margin="0,1.5,6,0" Text="DecadeMagenta" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="【点击请输入文本】" />
|
<TextBlock Margin="0,1.5,6,0" Text="0223YUKIUKOORI" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="AAA难办批发商乌鸦" />
|
<TextBlock Margin="0,1.5,6,0" Text="☆Etritz__㯊龝.ET☆" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="zhuanzhuanzhaun!" />
|
<TextBlock Margin="0,1.5,6,0" Text="NineTailed123213" />
|
||||||
<TextBlock Margin="0,1.5,6,0" Text="你上课记得记得你先忙" />
|
<TextBlock Margin="0,1.5,6,0" Text="于电子星海寻极星间" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="``Aurora. (极光)" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="来自少女前线的刀客塔" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text=" 此恨绵绵无绝期" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="3425789779@qq.com" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="AdeleineSummy的粉丝" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="有趣的灵魂肘击无趣的肉体" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="我是pipikeng我喂自己袋盐" />
|
||||||
|
<TextBlock Margin="0,1.5,6,0" Text="人族人亚族人属智人种晚期智人亚种" />
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<Grid Height="35">
|
<Grid Height="35">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -534,13 +545,13 @@
|
|||||||
<TextBlock Text="隐私声明与个人信息保护政策" TextWrapping="Wrap" Margin="0,10,0,4" FontWeight="Bold" />
|
<TextBlock Text="隐私声明与个人信息保护政策" TextWrapping="Wrap" Margin="0,10,0,4" FontWeight="Bold" />
|
||||||
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="PCL 没有收集个人信息,所以这里其实啥都不用写……
留个这个其实只是为了让你知道 PCL 没有收集个人信息,诶嘿。" TextWrapping="Wrap" />
|
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="PCL 没有收集个人信息,所以这里其实啥都不用写……
留个这个其实只是为了让你知道 PCL 没有收集个人信息,诶嘿。" TextWrapping="Wrap" />
|
||||||
<TextBlock Text="其他信息" TextWrapping="Wrap" Margin="0,10,0,4" FontWeight="Bold" />
|
<TextBlock Text="其他信息" TextWrapping="Wrap" Margin="0,10,0,4" FontWeight="Bold" />
|
||||||
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="Copyright © 成都瓜皮龙科技有限公司 计算机软件著作权登记号:2020SR0875133 违法违规行为举报投诉邮箱:admin@meloong.com 非 MINECRAFT 官方产品。未经 MOJANG 或 MICROSOFT 批准,也不与 MOJANG 或 MICROSOFT 关联。" TextWrapping="Wrap" />
|
<TextBlock Margin="0,0,0,2" LineHeight="17" Text="Copyright © 成都瓜皮龙科技有限公司 计算机软件著作权登记号:2020SR0875133 本软件是 InfstarMC 基于 Plain Craft Launcher (PCL) 独立进行的第三方二次开发版本,不代表 PCL 官方。 非 MINECRAFT 官方产品。未经 MOJANG 或 MICROSOFT 批准,也不与 MOJANG 或 MICROSOFT 关联。" TextWrapping="Wrap" />
|
||||||
<StackPanel Orientation="Horizontal" Height="35" HorizontalAlignment="Left" Margin="0,12,0,0">
|
<StackPanel Orientation="Horizontal" Height="35" HorizontalAlignment="Left" Margin="0,12,0,0">
|
||||||
<local:MyButton Text="用户协议与免责声明" Width="170" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight"
|
<local:MyButton Text="用户协议与免责声明" Width="170" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW#anchor-RnU9" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW#anchor-RnU9" />
|
||||||
<local:MyButton Text="PCL 分发有限许可" Width="170" Padding="13,0" Margin="0,0,20,0"
|
<local:MyButton Text="PCL 分发有限许可" Width="170" Padding="13,0" Margin="0,0,20,0"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW#anchor-X0bo" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW#anchor-X0bo" />
|
||||||
<local:MyButton Text="开源代码" Width="140" Padding="13,0" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/Hex-Dragon/PCL2" />
|
<local:MyButton Text="开源代码" Width="140" Padding="13,0" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://git.infstar.cn/InfStarMC/PCL-ISE" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
@@ -599,14 +610,14 @@
|
|||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://opensource.org/licenses/MIT" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://opensource.org/licenses/MIT" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="NAudio" TextWrapping="Wrap" FontWeight="Bold" />
|
<TextBlock Grid.Row="6" Grid.Column="0" Text="NAudio" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
<TextBlock Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2015 Mark Heath (mark.heath@gmail.com)
Licensed under the MIT License." TextWrapping="Wrap" />
|
<TextBlock Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2015 Mark Heath (mark.heath@gmail.com)
Licensed under the Microsoft Public License (Ms-PL)." TextWrapping="Wrap" />
|
||||||
<local:MyButton Grid.Row="7" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="7" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/naudio/NAudio" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/naudio/NAudio" />
|
||||||
<local:MyButton Grid.Row="7" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="7" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/naudio/NAudio/blob/master/license.txt" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/naudio/NAudio/blob/f98664ba3d5966a736dd5cf45329e542be5fece8/license.txt" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Ookii.Dialogs" TextWrapping="Wrap" FontWeight="Bold" />
|
<TextBlock Grid.Row="8" Grid.Column="0" Text="Ookii.Dialogs" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
<TextBlock Grid.Row="8" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2009 Sven Groot (Ookii.org)" TextWrapping="Wrap" />
|
<TextBlock Grid.Row="8" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2009 Sven Groot (Ookii.org)
Licensed under the BSD 3-Clause License." TextWrapping="Wrap" />
|
||||||
<local:MyButton Grid.Row="9" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="9" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.ookii.org/Software/Dialogs/" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.ookii.org/Software/Dialogs/" />
|
||||||
<local:MyButton Grid.Row="9" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="9" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
@@ -628,29 +639,36 @@
|
|||||||
|
|
||||||
<TextBlock Grid.Row="14" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
|
<TextBlock Grid.Row="14" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
<TextBlock Grid.Row="14" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
|
<TextBlock Grid.Row="14" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
|
||||||
<local:MyButton Grid.Row="15" Grid.Column="2" MinWidth="140" Text="查看原网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="15" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.iconfont.cn/" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.iconfont.cn/" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="16" Grid.Column="0" Text="EasyTier" TextWrapping="Wrap" FontWeight="Bold" />
|
<!--<TextBlock Grid.Row="16" Grid.Column="0" Text="EasyTier" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
<TextBlock Grid.Row="16" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2024-present Easytier Programme within The Commons Conservancy
Licensed under the GNU Lesser General Public License." TextWrapping="Wrap" />
|
<TextBlock Grid.Row="16" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2024-present Easytier Programme within The Commons Conservancy
Licensed under the GNU Lesser General Public License." TextWrapping="Wrap" />
|
||||||
<local:MyButton Grid.Row="17" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="17" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://easytier.cn/" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://easytier.cn/" />
|
||||||
<local:MyButton Grid.Row="17" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="17" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/EasyTier/EasyTier/blob/main/LICENSE" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/EasyTier/EasyTier/blob/main/LICENSE" />-->
|
||||||
|
|
||||||
<TextBlock Grid.Row="18" Grid.Column="0" Text="ThrottleDebounce" TextWrapping="Wrap" FontWeight="Bold" />
|
<TextBlock Grid.Row="16" Grid.Column="0" Text="ThrottleDebounce" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
<TextBlock Grid.Row="18" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2026 Ben Hutchison
Licensed under the Apache License, Version 2.0." TextWrapping="Wrap" />
|
<TextBlock Grid.Row="16" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2026 Ben Hutchison
Licensed under the Apache License, Version 2.0." TextWrapping="Wrap" />
|
||||||
<local:MyButton Grid.Row="19" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="17" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/Aldaviva/ThrottleDebounce" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/Aldaviva/ThrottleDebounce" />
|
||||||
<local:MyButton Grid.Row="19" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="17" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://licenses.nuget.org/Apache-2.0" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://licenses.nuget.org/Apache-2.0" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="20" Grid.Column="0" Text="CacheCow" TextWrapping="Wrap" FontWeight="Bold" />
|
<TextBlock Grid.Row="18" Grid.Column="0" Text="CacheCow" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
<TextBlock Grid.Row="20" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © Ali Kheyrollahi
Licensed under the MIT License." TextWrapping="Wrap" />
|
<TextBlock Grid.Row="18" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © Ali Kheyrollahi
Licensed under the MIT License." TextWrapping="Wrap" />
|
||||||
<local:MyButton Grid.Row="21" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="19" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/aliostad/CacheCow" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/aliostad/CacheCow" />
|
||||||
<local:MyButton Grid.Row="21" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
<local:MyButton Grid.Row="19" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://licenses.nuget.org/MIT" />
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://licenses.nuget.org/MIT" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="20" Grid.Column="0" Text="Transformer Discovery Service" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
|
<TextBlock Grid.Row="20" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2020 huangyuhui <huanghongxun2008@126.com> and contributors
Licensed under the GNU General Public License, Version 3 or later, with additional terms.
本组件作为独立组件分发,可依 GPL 复制、修改及再分发。" TextWrapping="Wrap" />
|
||||||
|
<local:MyButton Grid.Row="21" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/HMCL-dev/HMCL/tree/main/minecraft/libraries/HMCLTransformerDiscoveryService" />
|
||||||
|
<local:MyButton Grid.Row="21" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
|
||||||
|
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/HMCL-dev/HMCL/blob/main/LICENSE" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -48,12 +48,13 @@ Public Class PageOtherHelp
|
|||||||
If Item.Types.Contains(Type) Then TypeItems.Add(Item)
|
If Item.Types.Contains(Type) Then TypeItems.Add(Item)
|
||||||
Next
|
Next
|
||||||
'增加卡片
|
'增加卡片
|
||||||
Dim NewCard As New MyCard With {.Title = Type, .Margin = New Thickness(0, 0, 0, 15), .SwapType = 11}
|
Dim NewCard As New MyCard With {.Title = Type, .Margin = New Thickness(0, 0, 0, 15)}
|
||||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = TypeItems}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
|
NewCard.SetContentBuilder(TypeItems, Function(Entry) Entry.ToListItem)
|
||||||
If Type = "指南" Then
|
If Type = "指南" Then
|
||||||
MyCard.StackInstall(NewStack, 11, "指南")
|
NewCard.BuildContent()
|
||||||
Else
|
Else
|
||||||
NewCard.IsSwapped = True
|
NewCard.IsSwapped = True
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Public Class PageSelectLeft
|
|||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
)
|
)
|
||||||
End Select
|
End Select
|
||||||
If (Folder.Type = McFolder.Types.Vanilla OrElse Folder.Type = McFolder.Types.RenamedVanilla) AndAlso Folder.Location = Paths.Base & ".minecraft\" AndAlso McFolderList.IsSingle Then CType(ContMenu.FindName("Delete"), MyMenuItem).Header = "清空"
|
If (Folder.Type = McFolder.Types.Vanilla OrElse Folder.Type = McFolder.Types.RenamedVanilla) AndAlso PathUtils.IsSame(Folder.Location, Paths.Base & ".minecraft\") AndAlso McFolderList.IsSingle Then CType(ContMenu.FindName("Delete"), MyMenuItem).Header = "清空"
|
||||||
'注册事件
|
'注册事件
|
||||||
If Not Folder.Type = McFolder.Types.Vanilla Then CType(ContMenu.FindName("Remove"), MyMenuItem).AddHandler(MyMenuItem.ClickEvent, New RoutedEventHandler(AddressOf FrmSelectLeft.Remove_Click))
|
If Not Folder.Type = McFolder.Types.Vanilla Then CType(ContMenu.FindName("Remove"), MyMenuItem).AddHandler(MyMenuItem.ClickEvent, New RoutedEventHandler(AddressOf FrmSelectLeft.Remove_Click))
|
||||||
CType(ContMenu.FindName("Open"), MyMenuItem).AddHandler(MyMenuItem.ClickEvent, New RoutedEventHandler(AddressOf FrmSelectLeft.Open_Click))
|
CType(ContMenu.FindName("Open"), MyMenuItem).AddHandler(MyMenuItem.ClickEvent, New RoutedEventHandler(AddressOf FrmSelectLeft.Open_Click))
|
||||||
@@ -116,7 +116,7 @@ Public Class PageSelectLeft
|
|||||||
|
|
||||||
'确认勾选状态
|
'确认勾选状态
|
||||||
For i = 0 To McFolderList.Count - 1
|
For i = 0 To McFolderList.Count - 1
|
||||||
If McFolderList(i).Location = McFolderSelected Then
|
If PathUtils.IsSame(McFolderList(i).Location, McFolderSelected) Then
|
||||||
CType(FrmSelectLeft.PanList.Children(i + 1), MyListItem).Checked = True '去掉第一个标题
|
CType(FrmSelectLeft.PanList.Children(i + 1), MyListItem).Checked = True '去掉第一个标题
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
@@ -139,9 +139,9 @@ Public Class PageSelectLeft
|
|||||||
'添加文件夹
|
'添加文件夹
|
||||||
Public Sub Add_Click()
|
Public Sub Add_Click()
|
||||||
Dim NewFolder As String = ""
|
Dim NewFolder As String = ""
|
||||||
'检查是否有下载任务
|
'下载或版本修改期间禁止更改游戏文件夹
|
||||||
If HasDownloadingTask() Then
|
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||||
Hint("在下载任务进行时,无法添加游戏文件夹!", HintType.Red)
|
Hint("请在其他任务完成后,再添加游戏文件夹!", HintType.Red)
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
Try
|
Try
|
||||||
@@ -150,8 +150,11 @@ Public Class PageSelectLeft
|
|||||||
If NewFolder Is Nothing Then Return
|
If NewFolder Is Nothing Then Return
|
||||||
If NewFolder.Contains("!") OrElse NewFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Red) : Return
|
If NewFolder.Contains("!") OrElse NewFolder.Contains(";") Then Hint("Minecraft 文件夹路径中不能含有感叹号或分号!", HintType.Red) : Return
|
||||||
'要求输入显示名称
|
'要求输入显示名称
|
||||||
Dim SplitedNames As String() = NewFolder.TrimEnd("\").Split("\")
|
Dim DefaultName = PathUtils.GetLastPart(NewFolder)
|
||||||
Dim DefaultName As String = If(SplitedNames.Last = ".minecraft", If(SplitedNames.Count >= 3, SplitedNames(SplitedNames.Count - 2), ""), SplitedNames.Last)
|
If DefaultName = ".minecraft" Then
|
||||||
|
Dim ParentFolder = PathUtils.RemoveLastPart(NewFolder)
|
||||||
|
DefaultName = If(ParentFolder.EndsWithF(":"), "", PathUtils.GetLastPart(ParentFolder))
|
||||||
|
End If
|
||||||
If DefaultName.Length > 40 Then DefaultName = DefaultName.Substring(0, 39)
|
If DefaultName.Length > 40 Then DefaultName = DefaultName.Substring(0, 39)
|
||||||
Dim NewName As String = MyMsgBoxInput("输入显示名称", "输入该文件夹在左边栏列表中显示的名称。", DefaultName,
|
Dim NewName As String = MyMsgBoxInput("输入显示名称", "输入该文件夹在左边栏列表中显示的名称。", DefaultName,
|
||||||
New ObjectModel.Collection(Of Validate) From {New ValidateNullOrWhiteSpace, New ValidateLength(1, 30), New ValidateExcept({">", "|"})})
|
New ObjectModel.Collection(Of Validate) From {New ValidateNullOrWhiteSpace, New ValidateLength(1, 30), New ValidateExcept({">", "|"})})
|
||||||
@@ -169,7 +172,7 @@ Public Class PageSelectLeft
|
|||||||
RunInThread(
|
RunInThread(
|
||||||
Sub()
|
Sub()
|
||||||
Try
|
Try
|
||||||
If Not FolderPath.EndsWithF("\") Then FolderPath &= "\"
|
FolderPath = PathUtils.AddSlashSuffix(FolderPath)
|
||||||
'检查文件夹权限
|
'检查文件夹权限
|
||||||
If Not CheckPermission(FolderPath) Then
|
If Not CheckPermission(FolderPath) Then
|
||||||
If ShowHint Then
|
If ShowHint Then
|
||||||
@@ -195,7 +198,7 @@ Public Class PageSelectLeft
|
|||||||
For i = 0 To Folders.Count - 1
|
For i = 0 To Folders.Count - 1
|
||||||
Dim Folder As String = Folders(i)
|
Dim Folder As String = Folders(i)
|
||||||
If Folder = "" Then Continue For
|
If Folder = "" Then Continue For
|
||||||
If Folder.Split(">")(1) = FolderPath Then
|
If PathUtils.IsSame(Folder.Split(">")(1), FolderPath) Then
|
||||||
IsAdded = True
|
IsAdded = True
|
||||||
If Folder.Split(">")(0) = DisplayName Then
|
If Folder.Split(">")(0) = DisplayName Then
|
||||||
If ShowHint Then Hint("此文件夹已在列表中!", HintType.Blue)
|
If ShowHint Then Hint("此文件夹已在列表中!", HintType.Blue)
|
||||||
@@ -246,9 +249,9 @@ Public Class PageSelectLeft
|
|||||||
|
|
||||||
'创建文件夹
|
'创建文件夹
|
||||||
Public Sub Create_Click()
|
Public Sub Create_Click()
|
||||||
'检查是否有下载任务
|
'下载或版本修改期间禁止更改游戏文件夹
|
||||||
If HasDownloadingTask() Then
|
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||||
Hint("在下载任务进行时,无法创建游戏文件夹!", HintType.Red)
|
Hint("请在其他任务完成后,再创建游戏文件夹!", HintType.Red)
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
CreateMcFolderInCurrentPath()
|
CreateMcFolderInCurrentPath()
|
||||||
@@ -270,6 +273,10 @@ Public Class PageSelectLeft
|
|||||||
Dim Target As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
Dim Target As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||||
'若为 “移除”,则提醒是否删除 PCL 的配置文件
|
'若为 “移除”,则提醒是否删除 PCL 的配置文件
|
||||||
If Target.Type = McFolder.Types.Custom Then
|
If Target.Type = McFolder.Types.Custom Then
|
||||||
|
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||||
|
Hint("请在其他任务完成后,再移除游戏文件夹!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
Select Case MyMsgBox("是否需要清理 PCL 在该文件夹中的配置文件?" & vbCrLf & "这包括各个版本的独立设置(如自定义图标、第三方登录配置)等,对游戏本身没有影响。", "配置文件清理", "删除", "保留", "取消")
|
Select Case MyMsgBox("是否需要清理 PCL 在该文件夹中的配置文件?" & vbCrLf & "这包括各个版本的独立设置(如自定义图标、第三方登录配置)等,对游戏本身没有影响。", "配置文件清理", "删除", "保留", "取消")
|
||||||
Case 1
|
Case 1
|
||||||
'删除配置文件
|
'删除配置文件
|
||||||
@@ -292,6 +299,10 @@ Public Class PageSelectLeft
|
|||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub Delete_Click(sender As Object, e As RoutedEventArgs)
|
Public Sub Delete_Click(sender As Object, e As RoutedEventArgs)
|
||||||
|
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask() Then
|
||||||
|
Hint("请在其他任务完成后,再删除游戏文件夹!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
Dim Target As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
Dim Target As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||||
Dim DeleteText As String = If((Target.Type = McFolder.Types.Vanilla OrElse Target.Type = McFolder.Types.RenamedVanilla) AndAlso Target.Location = Paths.Base & ".minecraft\" AndAlso McFolderList.IsSingle, "清空", "删除")
|
Dim DeleteText As String = If((Target.Type = McFolder.Types.Vanilla OrElse Target.Type = McFolder.Types.RenamedVanilla) AndAlso Target.Location = Paths.Base & ".minecraft\" AndAlso McFolderList.IsSingle, "清空", "删除")
|
||||||
If MyMsgBox("你确定要" & DeleteText & "这个文件夹吗?" & vbCrLf &
|
If MyMsgBox("你确定要" & DeleteText & "这个文件夹吗?" & vbCrLf &
|
||||||
@@ -328,7 +339,7 @@ Public Class PageSelectLeft
|
|||||||
Dim DeletedName As String = Nothing
|
Dim DeletedName As String = Nothing
|
||||||
Dim Folders = Settings.Get(Of String)("LaunchFolders").Split("|"c, True).ToList
|
Dim Folders = Settings.Get(Of String)("LaunchFolders").Split("|"c, True).ToList
|
||||||
For Each Folder In Folders.ToList
|
For Each Folder In Folders.ToList
|
||||||
If Not Folder.EndsWithF(Target.Location) Then Continue For
|
If Not Folder.Contains(">") OrElse Not PathUtils.IsSame(Folder.AfterFirst(">"), Target.Location) Then Continue For
|
||||||
DeletedName = Folder.BeforeFirst(">")
|
DeletedName = Folder.BeforeFirst(">")
|
||||||
Folders.Remove(Folder)
|
Folders.Remove(Folder)
|
||||||
Exit For
|
Exit For
|
||||||
@@ -349,7 +360,7 @@ Public Class PageSelectLeft
|
|||||||
End Sub
|
End Sub
|
||||||
Public Shared Sub RefreshCurrent(Folder As String)
|
Public Shared Sub RefreshCurrent(Folder As String)
|
||||||
WriteIni(Folder & "PCL.ini", "InstanceCache", "") '删除缓存以强制要求下一次加载时更新列表
|
WriteIni(Folder & "PCL.ini", "InstanceCache", "") '删除缓存以强制要求下一次加载时更新列表
|
||||||
If Folder = McFolderSelected Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
If PathUtils.IsSame(Folder, McFolderSelected) Then LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub Rename_Click(sender As Object, e As RoutedEventArgs)
|
Public Sub Rename_Click(sender As Object, e As RoutedEventArgs)
|
||||||
Dim Folder As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
Dim Folder As McFolder = CType(CType(CType(sender.Parent, ContextMenu).Parent, Primitives.Popup).PlacementTarget, MyListItem).Tag
|
||||||
@@ -365,7 +376,7 @@ Public Class PageSelectLeft
|
|||||||
For i = 0 To Folders.Count - 1
|
For i = 0 To Folders.Count - 1
|
||||||
Dim FolderCurrent As String = Folders(i)
|
Dim FolderCurrent As String = Folders(i)
|
||||||
If FolderCurrent = "" Then Continue For
|
If FolderCurrent = "" Then Continue For
|
||||||
If FolderCurrent.Split(">")(1) = Folder.Location Then
|
If PathUtils.IsSame(FolderCurrent.Split(">")(1), Folder.Location) Then
|
||||||
IsAdded = True
|
IsAdded = True
|
||||||
If FolderCurrent.Split(">")(0) = NewName Then
|
If FolderCurrent.Split(">")(0) = NewName Then
|
||||||
'名称未修改
|
'名称未修改
|
||||||
@@ -390,9 +401,9 @@ Public Class PageSelectLeft
|
|||||||
'点击选项
|
'点击选项
|
||||||
Public Sub Folder_Change(sender As MyListItem, e As RouteEventArgs)
|
Public Sub Folder_Change(sender As MyListItem, e As RouteEventArgs)
|
||||||
If Not e.RaiseByMouse OrElse Not sender.Checked Then Return
|
If Not e.RaiseByMouse OrElse Not sender.Checked Then Return
|
||||||
'检查是否有下载任务
|
'下载或版本修改期间禁止更改游戏文件夹
|
||||||
If HasDownloadingTask(True) Then
|
If McInstanceLock.IsAnyLocked OrElse HasDownloadingTask(True) Then
|
||||||
Hint("在下载任务进行时,无法切换游戏文件夹!", HintType.Red)
|
Hint("请在其他任务完成后,再切换游戏文件夹!", HintType.Red)
|
||||||
e.Handled = True
|
e.Handled = True
|
||||||
Return
|
Return
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ Public Class PageSelectRight
|
|||||||
For Each Card As KeyValuePair(Of McInstanceCardType, List(Of McInstance)) In McInstanceList.ToArray
|
For Each Card As KeyValuePair(Of McInstanceCardType, List(Of McInstance)) In McInstanceList.ToArray
|
||||||
'确认是否为隐藏版本显示状态
|
'确认是否为隐藏版本显示状态
|
||||||
If Card.Key = McInstanceCardType.Hidden Xor ShowHidden Then Continue For
|
If Card.Key = McInstanceCardType.Hidden Xor ShowHidden Then Continue For
|
||||||
|
Dim Instances = Card.Value.Where(Function(Instance) Not McInstanceLock.IsLocked(Instance)).ToList
|
||||||
|
If Not Instances.Any Then Continue For
|
||||||
#Region "确认卡片名称"
|
#Region "确认卡片名称"
|
||||||
Dim CardName As String = ""
|
Dim CardName As String = ""
|
||||||
Select Case Card.Key
|
Select Case Card.Key
|
||||||
@@ -40,11 +42,11 @@ Public Class PageSelectRight
|
|||||||
Dim IsNeoForgeExists As Boolean = False
|
Dim IsNeoForgeExists As Boolean = False
|
||||||
Dim IsFabricExists As Boolean = False
|
Dim IsFabricExists As Boolean = False
|
||||||
Dim IsLiteExists As Boolean = False
|
Dim IsLiteExists As Boolean = False
|
||||||
For Each Instance As McInstance In Card.Value
|
For Each Instance As McInstance In Instances
|
||||||
If Instance.Version.HasFabric Then IsFabricExists = True
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then IsFabricExists = True
|
||||||
If Instance.Version.HasLiteLoader Then IsLiteExists = True
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) Then IsLiteExists = True
|
||||||
If Instance.Version.HasForge Then IsForgeExists = True
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then IsForgeExists = True
|
||||||
If Instance.Version.HasNeoForge Then IsNeoForgeExists = True
|
If Instance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then IsNeoForgeExists = True
|
||||||
Next
|
Next
|
||||||
If If(IsLiteExists, 1, 0) + If(IsForgeExists, 1, 0) + If(IsFabricExists, 1, 0) + If(IsNeoForgeExists, 1, 0) > 1 Then
|
If If(IsLiteExists, 1, 0) + If(IsForgeExists, 1, 0) + If(IsFabricExists, 1, 0) + If(IsNeoForgeExists, 1, 0) > 1 Then
|
||||||
CardName = "可安装 Mod"
|
CardName = "可安装 Mod"
|
||||||
@@ -72,17 +74,18 @@ Public Class PageSelectRight
|
|||||||
End Select
|
End Select
|
||||||
#End Region
|
#End Region
|
||||||
'建立控件
|
'建立控件
|
||||||
Dim CardTitle As String = CardName & If(CardName = "收藏夹", "", " (" & Card.Value.Count & ")")
|
Dim CardTitle As String = CardName & If(CardName = "收藏夹", "", " (" & Instances.Count & ")")
|
||||||
Dim NewCard As New MyCard With {.Title = CardTitle, .Margin = New Thickness(0, 0, 0, 15), .SwapType = 0}
|
Dim NewCard As New MyCard With {.Title = CardTitle, .Margin = New Thickness(0, 0, 0, 15)}
|
||||||
Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Card.Value}
|
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.Children.Add(NewStack)
|
||||||
NewCard.SwapControl = NewStack
|
NewCard.SwapControl = NewStack
|
||||||
|
NewCard.SetContentBuilder(Instances, Function(Instance) Instance.ToListItem(AddressOf McInstanceListContent))
|
||||||
PanMain.Children.Add(NewCard)
|
PanMain.Children.Add(NewCard)
|
||||||
'确定卡片是否展开
|
'确定卡片是否展开
|
||||||
If Card.Key = McInstanceCardType.Rubbish OrElse Card.Key = McInstanceCardType.Error OrElse Card.Key = McInstanceCardType.Fool Then
|
If Card.Key = McInstanceCardType.Rubbish OrElse Card.Key = McInstanceCardType.Error OrElse Card.Key = McInstanceCardType.Fool Then
|
||||||
NewCard.IsSwapped = True
|
NewCard.IsSwapped = True
|
||||||
Else
|
Else
|
||||||
MyCard.StackInstall(NewStack, 0, CardTitle)
|
NewCard.BuildContent()
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
|
|
||||||
@@ -128,15 +131,16 @@ Public Class PageSelectRight
|
|||||||
BtnStar.LogoScale = 1.1
|
BtnStar.LogoScale = 1.1
|
||||||
BtnStar.Logo = Logo.IconButtonLikeLine
|
BtnStar.Logo = Logo.IconButtonLikeLine
|
||||||
End If
|
End If
|
||||||
AddHandler BtnStar.Click, Sub()
|
AddHandler BtnStar.Click,
|
||||||
WriteIni(Instance.PathVersion & "PCL\Setup.ini", "IsStar", Not Instance.IsStar)
|
Sub()
|
||||||
McInstanceListForceRefresh = True
|
WriteIni(Instance.PathVersion & "PCL\Setup.ini", "IsStar", Not Instance.IsStar)
|
||||||
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
McInstanceListForceRefresh = True
|
||||||
End Sub
|
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
|
||||||
|
End Sub
|
||||||
Dim BtnDel As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonDelete}
|
Dim BtnDel As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonDelete}
|
||||||
BtnDel.ToolTip = "删除"
|
BtnDel.ToolTip = "删除"
|
||||||
AddHandler BtnDel.Click, Sub() DeleteInstance(sender, Instance)
|
AddHandler BtnDel.Click, Sub() DeleteInstance(sender, Instance)
|
||||||
If Instance.State <> McInstanceState.Error Then
|
If Instance.State <> McInstance.McInstanceState.Error Then
|
||||||
Dim BtnCont As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonSetup}
|
Dim BtnCont As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonSetup}
|
||||||
BtnCont.ToolTip = "设置"
|
BtnCont.ToolTip = "设置"
|
||||||
AddHandler BtnCont.Click,
|
AddHandler BtnCont.Click,
|
||||||
@@ -166,6 +170,10 @@ Public Class PageSelectRight
|
|||||||
'点击选项
|
'点击选项
|
||||||
Public Shared Sub Item_Click(sender As MyListItem, e As EventArgs)
|
Public Shared Sub Item_Click(sender As MyListItem, e As EventArgs)
|
||||||
Dim Instance As McInstance = sender.Tag
|
Dim Instance As McInstance = sender.Tag
|
||||||
|
If McInstanceLock.IsLocked(Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再选择!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
If New McInstance(Instance.PathVersion).Check Then
|
If New McInstance(Instance.PathVersion).Check Then
|
||||||
'正常版本
|
'正常版本
|
||||||
McInstanceSelected = Instance
|
McInstanceSelected = Instance
|
||||||
@@ -183,8 +191,12 @@ Public Class PageSelectRight
|
|||||||
'修改此代码时,同时修改 PageInstanceOverall 中的代码
|
'修改此代码时,同时修改 PageInstanceOverall 中的代码
|
||||||
Public Shared Sub DeleteInstance(Item As MyListItem, Instance As McInstance)
|
Public Shared Sub DeleteInstance(Item As MyListItem, Instance As McInstance)
|
||||||
Try
|
Try
|
||||||
|
If McInstanceLock.IsLocked(Instance) Then
|
||||||
|
Hint("该版本正在被修改,请稍后再删除!", HintType.Red)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
|
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
|
||||||
Dim IsHintIndie As Boolean = Instance.State <> McInstanceState.Error AndAlso Instance.PathIndie <> McFolderSelected
|
Dim IsHintIndie As Boolean = Instance.State <> McInstance.McInstanceState.Error AndAlso Instance.PathIndie <> McFolderSelected
|
||||||
Dim SavesFolder = DirectoryUtils.GetInfo(Instance.PathIndie & "saves\")
|
Dim SavesFolder = DirectoryUtils.GetInfo(Instance.PathIndie & "saves\")
|
||||||
Dim SaveEntries = If(IsHintIndie AndAlso SavesFolder.Exists, SavesFolder.EnumerateDirectories.OrderByDescending(Function(Save) Save.LastWriteTime).Select(Function(Save) $"{Save.Name}(上次修改:{StringUtils.FormatTimeSpan(Save.LastWriteTime - Date.Now, False)})").ToList, New List(Of String))
|
Dim SaveEntries = If(IsHintIndie AndAlso SavesFolder.Exists, SavesFolder.EnumerateDirectories.OrderByDescending(Function(Save) Save.LastWriteTime).Select(Function(Save) $"{Save.Name}(上次修改:{StringUtils.FormatTimeSpan(Save.LastWriteTime - Date.Now, False)})").ToList, New List(Of String))
|
||||||
Select Case MyMsgBox($"你确定要{If(IsShiftPressed, "永久", "")}删除版本 {Instance.Name} 吗?" &
|
Select Case MyMsgBox($"你确定要{If(IsShiftPressed, "永久", "")}删除版本 {Instance.Name} 吗?" &
|
||||||
@@ -207,7 +219,7 @@ Public Class PageSelectRight
|
|||||||
Dim Card As MyCard = Parent.Parent
|
Dim Card As MyCard = Parent.Parent
|
||||||
Card.Title = Card.Title.Replace(Parent.Children.Count - 1, Parent.Children.Count - 2) '有一个占位符
|
Card.Title = Card.Title.Replace(Parent.Children.Count - 1, Parent.Children.Count - 2) '有一个占位符
|
||||||
Parent.Children.Remove(Item)
|
Parent.Children.Remove(Item)
|
||||||
If McInstanceSelected IsNot Nothing AndAlso Instance.PathVersion = McInstanceSelected.PathVersion Then
|
If McInstanceSelected IsNot Nothing AndAlso PathUtils.IsSame(Instance.PathVersion, McInstanceSelected.PathVersion) Then
|
||||||
'删除当前版本就更改选择
|
'删除当前版本就更改选择
|
||||||
McInstanceSelected = MyVirtualizingElement.TryInit(Parent.Children(0)).Tag
|
McInstanceSelected = MyVirtualizingElement.TryInit(Parent.Children(0)).Tag
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -27,8 +27,6 @@
|
|||||||
<RowDefinition Height="28" />
|
<RowDefinition Height="28" />
|
||||||
<RowDefinition Height="9" />
|
<RowDefinition Height="9" />
|
||||||
<RowDefinition Height="28" />
|
<RowDefinition Height="28" />
|
||||||
<RowDefinition Height="9" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="默认版本隔离" Margin="0,0,25,0" />
|
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="默认版本隔离" Margin="0,0,25,0" />
|
||||||
<local:MyComboBox local:SettingService.Key="LaunchArgumentIndieV2" x:Name="ComboArgumentIndieV2"
|
<local:MyComboBox local:SettingService.Key="LaunchArgumentIndieV2" x:Name="ComboArgumentIndieV2"
|
||||||
@@ -106,9 +104,6 @@
|
|||||||
</local:MyTextBox.ValidateRules>
|
</local:MyTextBox.ValidateRules>
|
||||||
</local:MyTextBox>
|
</local:MyTextBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
<local:MyCheckBox Margin="0,8,0,4" Text="在正版登录时验证 SSL 证书" Grid.Row="12" Height="22" Grid.ColumnSpan="2"
|
|
||||||
x:Name="CheckDownloadCert" local:SettingService.Key="ToolDownloadCert"
|
|
||||||
ToolTip="开启验证可以提高安全性,但可能会导致正版登录失败(见 #3018)。
若登录因为 “未能为 SSL/TLS 安全通道建立信任关系” 失败,请考虑关闭此选项。" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
@@ -291,6 +286,7 @@
|
|||||||
<local:MyCheckBox Height="28" Text="禁用 Java Launch Wrapper" local:SettingService.Key="LaunchAdvanceDisableJLW" ToolTip="是否使用 Java Launch Wrapper 修复 Java 18- 在中文路径下可能无法正常启动的问题。
详见:https://github.com/00ll00/java_launch_wrapper" />
|
<local:MyCheckBox Height="28" Text="禁用 Java Launch Wrapper" local:SettingService.Key="LaunchAdvanceDisableJLW" ToolTip="是否使用 Java Launch Wrapper 修复 Java 18- 在中文路径下可能无法正常启动的问题。
详见:https://github.com/00ll00/java_launch_wrapper" />
|
||||||
<local:MyCheckBox Height="28" Text="禁用 LWJGL Unsafe Agent" local:SettingService.Key="LaunchAdvanceDisableLUA" ToolTip="是否使用 LWJGL Unsafe Agent 修复 LWJGL 3.4.1 的一个性能问题。
详见:https://github.com/HMCL-dev/lwjgl-unsafe-agent" />
|
<local:MyCheckBox Height="28" Text="禁用 LWJGL Unsafe Agent" local:SettingService.Key="LaunchAdvanceDisableLUA" ToolTip="是否使用 LWJGL Unsafe Agent 修复 LWJGL 3.4.1 的一个性能问题。
详见:https://github.com/HMCL-dev/lwjgl-unsafe-agent" />
|
||||||
<local:MyCheckBox Height="28" Text="使用高性能显卡" local:SettingService.Key="LaunchAdvanceGraphicCard" ToolTip="自动在 Windows 设置 → 系统 → 屏幕 → 显示卡 中将 PCL 和 Java 改为使用高性能显卡。
如果同时有集成显卡和独立显卡,这能确保 MC 使用独立显卡进行渲染,以大幅提高帧率。" />
|
<local:MyCheckBox Height="28" Text="使用高性能显卡" local:SettingService.Key="LaunchAdvanceGraphicCard" ToolTip="自动在 Windows 设置 → 系统 → 屏幕 → 显示卡 中将 PCL 和 Java 改为使用高性能显卡。
如果同时有集成显卡和独立显卡,这能确保 MC 使用独立显卡进行渲染,以大幅提高帧率。" />
|
||||||
|
<local:MyCheckBox Height="28" Text="在正版登录时验证 SSL 证书" local:SettingService.Key="ToolDownloadCert" ToolTip="开启验证可以提高安全性,但可能会导致正版登录失败(见 #3018)。
若登录因为 “未能为 SSL/TLS 安全通道建立信任关系” 失败,请考虑关闭此选项。" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<local:MyHint Text="版本独立设置中还有更多高级选项可供调整。" Margin="0,5,0,10" Theme="Blue" Grid.Row="11" Grid.ColumnSpan="2"
|
<local:MyHint Text="版本独立设置中还有更多高级选项可供调整。" Margin="0,5,0,10" Theme="Blue" Grid.Row="11" Grid.ColumnSpan="2"
|
||||||
CanClose="True" RelativeSetup="HintMoreAdvancedSetup" />
|
CanClose="True" RelativeSetup="HintMoreAdvancedSetup" />
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ PreFin:
|
|||||||
AddHandler DownButton.Click, Sub() MoveJavaInList(JavaEntry, 1)
|
AddHandler DownButton.Click, Sub() MoveJavaInList(JavaEntry, 1)
|
||||||
Buttons.Add(DownButton)
|
Buttons.Add(DownButton)
|
||||||
'从列表中移除按钮
|
'从列表中移除按钮
|
||||||
Dim IsOfficial As Boolean = JavaEntry.Folder.StartsWithF($"{Paths.AppData}.minecraft\runtime\")
|
Dim IsOfficial As Boolean = PathUtils.IsParentOf($"{Paths.AppData}.minecraft\runtime\", JavaEntry.Folder)
|
||||||
Dim DeleteButton As New MyIconButton With {.Logo = Logo.IconButtonStop, .Height = 24, .Width = 24}
|
Dim DeleteButton As New MyIconButton With {.Logo = Logo.IconButtonStop, .Height = 24, .Width = 24}
|
||||||
DeleteButton.IsEnabled = Not IsOfficial
|
DeleteButton.IsEnabled = Not IsOfficial
|
||||||
DeleteButton.ToolTip = If(DeleteButton.IsEnabled, "从列表中移除", "无法移除官方 Java")
|
DeleteButton.ToolTip = If(DeleteButton.IsEnabled, "从列表中移除", "无法移除官方 Java")
|
||||||
|
|||||||
@@ -235,18 +235,16 @@
|
|||||||
<local:MyHint Margin="0,15,0,-4" Text="内容见 ModSetup" Theme="Blue" x:Name="HintCustom" />
|
<local:MyHint Margin="0,15,0,-4" Text="内容见 ModSetup" Theme="Blue" x:Name="HintCustom" />
|
||||||
<local:MyHint Margin="0,15,0,6" Text="请谨慎使用陌生人提供的主页,恶意代码可能会造成损害!" Theme="Yellow" x:Name="HintCustomWarn"
|
<local:MyHint Margin="0,15,0,6" Text="请谨慎使用陌生人提供的主页,恶意代码可能会造成损害!" Theme="Yellow" x:Name="HintCustomWarn"
|
||||||
CanClose="True" RelativeSetup="HintCustomWarn" />
|
CanClose="True" RelativeSetup="HintCustomWarn" />
|
||||||
<Grid Height="35" x:Name="PanCustomLocal" Visibility="Collapsed" Margin="0,10,0,5">
|
<WrapPanel x:Name="PanCustomLocal" Visibility="Collapsed" Margin="0,0,0,5">
|
||||||
<Grid.ColumnDefinitions>
|
<local:MyButton x:Name="BtnCustomRefresh" Text="刷新主页"
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<local:MyButton x:Name="BtnCustomFile" Text="生成教学文件"
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
|
<local:MyButton x:Name="BtnCustomTutorial" Text="查看教程"
|
||||||
</Grid.ColumnDefinitions>
|
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||||
<local:MyButton x:Name="BtnCustomRefresh" Grid.Column="0" Height="32" MinWidth="140" Text="刷新主页" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight" />
|
<local:MyButton x:Name="BtnCustomFolder" Text="打开主页文件夹"
|
||||||
<local:MyButton x:Name="BtnCustomFile" Grid.Column="1" Height="32" MinWidth="140" Text="生成教学文件" Padding="13,0" Margin="0,0,20,0" />
|
MinWidth="140" Height="35" Padding="13,0" Margin="0,10,20,0" HorizontalAlignment="Left" />
|
||||||
<local:MyButton x:Name="BtnCustomTutorial" Grid.Column="2" Height="32" MinWidth="140" Text="查看教程" Padding="13,0" Margin="0,0,20,0" />
|
</WrapPanel>
|
||||||
<local:MyButton x:Name="BtnCustomOpen" Grid.Column="3" Height="32" MinWidth="140" Text="打开主页文件夹" Padding="13,0" Margin="0,0,20,0" />
|
|
||||||
</Grid>
|
|
||||||
<Grid x:Name="PanCustomNet" Visibility="Collapsed" Margin="0,10,0,5">
|
<Grid x:Name="PanCustomNet" Visibility="Collapsed" Margin="0,10,0,5">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
|
||||||
@@ -288,6 +286,11 @@
|
|||||||
<local:MyComboBoxItem local:SettingService.Value="17" Content="Bangumi 番剧主页(作者:wzyaeu)" />
|
<local:MyComboBoxItem local:SettingService.Value="17" Content="Bangumi 番剧主页(作者:wzyaeu)" />
|
||||||
<local:MyComboBoxItem local:SettingService.Value="18" Content="Bilibili 热门(作者:wzyaeu)" />
|
<local:MyComboBoxItem local:SettingService.Value="18" Content="Bilibili 热门(作者:wzyaeu)" />
|
||||||
<local:MyComboBoxItem local:SettingService.Value="19" Content="Music 云音乐热门(作者:wzyaeu)" />
|
<local:MyComboBoxItem local:SettingService.Value="19" Content="Music 云音乐热门(作者:wzyaeu)" />
|
||||||
|
<local:MyComboBoxItem local:SettingService.Value="20" Content="模组推荐(作者:llsgllsg)" />
|
||||||
|
<local:MyComboBoxItem local:SettingService.Value="21" Content="每日游戏推荐(作者:llsgllsg)" />
|
||||||
|
<local:MyComboBoxItem local:SettingService.Value="22" Content="Wallpaper 每日壁纸(作者:wzyaeu)" />
|
||||||
|
<local:MyComboBoxItem local:SettingService.Value="23" Content="Weather 天气预报(作者:wzyaeu)" />
|
||||||
|
<local:MyComboBoxItem local:SettingService.Value="24" Content="新一代狗屁王大杂烩主页(作者:llsgllsg)" />
|
||||||
</local:MyComboBox>
|
</local:MyComboBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@@ -334,6 +337,7 @@
|
|||||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="3" Text="版本管理" x:Name="CheckHiddenFunctionSelect" local:SettingService.Key="UiHiddenFunctionSelect" ToolTip="隐藏启动按钮下方的版本选择与版本设置入口。" />
|
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="3" Text="版本管理" x:Name="CheckHiddenFunctionSelect" local:SettingService.Key="UiHiddenFunctionSelect" ToolTip="隐藏启动按钮下方的版本选择与版本设置入口。" />
|
||||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="4" Text="Mod 更新" x:Name="CheckHiddenFunctionModUpdate" local:SettingService.Key="UiHiddenFunctionModUpdate" ToolTip="禁止在 Mod 管理页面更新 Mod。" />
|
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="4" Text="Mod 更新" x:Name="CheckHiddenFunctionModUpdate" local:SettingService.Key="UiHiddenFunctionModUpdate" ToolTip="禁止在 Mod 管理页面更新 Mod。" />
|
||||||
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="5" Text="功能隐藏" x:Name="CheckHiddenFunctionHidden" local:SettingService.Key="UiHiddenFunctionHidden" ToolTip="仅隐藏本选项卡,设置的禁用内容依然有效。
可以在保留个性化设置页面的情况下避免隐藏设置被修改。" />
|
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="5" Text="功能隐藏" x:Name="CheckHiddenFunctionHidden" local:SettingService.Key="UiHiddenFunctionHidden" ToolTip="仅隐藏本选项卡,设置的禁用内容依然有效。
可以在保留个性化设置页面的情况下避免隐藏设置被修改。" />
|
||||||
|
<local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="6" Text="版本修改" x:Name="CheckHiddenFunctionModify" local:SettingService.Key="UiHiddenFunctionInstanceModify" ToolTip="隐藏版本设置中的版本修改功能。" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:MyCard>
|
</local:MyCard>
|
||||||
|
|||||||
@@ -306,19 +306,6 @@ Refresh:
|
|||||||
"你可以在生成教学文件后直接刷新主页,对照着进行修改,更有助于理解。" & vbCrLf &
|
"你可以在生成教学文件后直接刷新主页,对照着进行修改,更有助于理解。" & vbCrLf &
|
||||||
"直接将主页文件拖进 PCL 窗口也可以快捷加载。", "主页自定义教程")
|
"直接将主页文件拖进 PCL 窗口也可以快捷加载。", "主页自定义教程")
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BtnCustomOpen_Click(sender As Object, e As EventArgs) Handles BtnCustomOpen.Click
|
|
||||||
Try
|
|
||||||
Dim CustomPath As String = Paths.Base & "PCL\Custom.xaml"
|
|
||||||
If FileUtils.Exists(CustomPath) Then
|
|
||||||
OpenExplorer(CustomPath)
|
|
||||||
Else
|
|
||||||
OpenExplorer(Paths.Base & "PCL\")
|
|
||||||
Hint("未找到 Custom.xaml,已打开 PCL 文件夹。", HintType.Blue)
|
|
||||||
End If
|
|
||||||
Catch ex As Exception
|
|
||||||
Logger.Error(ex, "打开主页文件失败")
|
|
||||||
End Try
|
|
||||||
End Sub
|
|
||||||
Public Shared Sub OnMainPageTypeChanged()
|
Public Shared Sub OnMainPageTypeChanged()
|
||||||
If FrmSetupUI Is Nothing Then Return
|
If FrmSetupUI Is Nothing Then Return
|
||||||
Select Case CInt(Settings.Get(Of Integer)("UiCustomType"))
|
Select Case CInt(Settings.Get(Of Integer)("UiCustomType"))
|
||||||
@@ -354,6 +341,14 @@ Refresh:
|
|||||||
End Select
|
End Select
|
||||||
FrmSetupUI.CardCustom.TriggerForceResize()
|
FrmSetupUI.CardCustom.TriggerForceResize()
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub BtnCustomFolder_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnCustomFolder.Click
|
||||||
|
Dim CustomPath As String = Paths.Base & "PCL\Custom.xaml"
|
||||||
|
If FileUtils.Exists(CustomPath) Then
|
||||||
|
OpenExplorer(CustomPath)
|
||||||
|
Else
|
||||||
|
OpenExplorer(Paths.Base & "PCL\")
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
'主题
|
'主题
|
||||||
Private Sub LabLauncherTheme5Unlock_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles LabLauncherTheme5Unlock.MouseLeftButtonUp
|
Private Sub LabLauncherTheme5Unlock_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles LabLauncherTheme5Unlock.MouseLeftButtonUp
|
||||||
@@ -458,6 +453,10 @@ Refresh:
|
|||||||
If FrmSetupUI IsNot Nothing Then
|
If FrmSetupUI IsNot Nothing Then
|
||||||
FrmSetupUI.CardSwitch.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenFunctionHidden"), Visibility.Collapsed, Visibility.Visible)
|
FrmSetupUI.CardSwitch.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenFunctionHidden"), Visibility.Collapsed, Visibility.Visible)
|
||||||
End If
|
End If
|
||||||
|
'版本设置子页面
|
||||||
|
If FrmInstanceLeft IsNot Nothing Then
|
||||||
|
FrmInstanceLeft.ItemModify.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenFunctionInstanceModify"), Visibility.Collapsed, Visibility.Visible)
|
||||||
|
End If
|
||||||
'设置子页面
|
'设置子页面
|
||||||
If FrmSetupLeft IsNot Nothing Then
|
If FrmSetupLeft IsNot Nothing Then
|
||||||
FrmSetupLeft.ItemLaunch.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenSetupLaunch"), Visibility.Collapsed, Visibility.Visible)
|
FrmSetupLeft.ItemLaunch.Visibility = If(Not HiddenForceShow AndAlso Settings.Get(Of Boolean)("UiHiddenSetupLaunch"), Visibility.Collapsed, Visibility.Visible)
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ Public Class Settings
|
|||||||
New Setting("UiHiddenPageOther", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
New Setting("UiHiddenPageOther", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
New Setting("UiHiddenFunctionSelect", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
New Setting("UiHiddenFunctionSelect", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
New Setting("UiHiddenFunctionModUpdate", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
New Setting("UiHiddenFunctionModUpdate", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
|
New Setting("UiHiddenFunctionInstanceModify", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
New Setting("UiHiddenFunctionHidden", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
New Setting("UiHiddenFunctionHidden", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
New Setting("UiHiddenSetupLaunch", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
New Setting("UiHiddenSetupLaunch", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
New Setting("UiHiddenSetupUi", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
New Setting("UiHiddenSetupUi", False, OnChanged:=AddressOf PageSetupUI.HiddenRefresh),
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ Public Class PageSpeedLeft
|
|||||||
Tb.Text = Loader.Error.GetDisplay(True)
|
Tb.Text = Loader.Error.GetDisplay(True)
|
||||||
AddHandler Tb.MouseLeftButtonDown,
|
AddHandler Tb.MouseLeftButtonDown,
|
||||||
Sub(sender As TextBlock, e As EventArgs)
|
Sub(sender As TextBlock, e As EventArgs)
|
||||||
ClipboardSet(sender.Text, SuccessHint:="已复制错误详情!")
|
ClipboardSet(sender.Text, False)
|
||||||
|
Hint("已复制错误详情!", HintType.Green)
|
||||||
End Sub
|
End Sub
|
||||||
Card.Children.Add(Tb)
|
Card.Children.Add(Tb)
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -282,6 +282,7 @@
|
|||||||
<Compile Include="Pages\PageDownload\PageDownloadInstall.xaml.vb">
|
<Compile Include="Pages\PageDownload\PageDownloadInstall.xaml.vb">
|
||||||
<DependentUpon>PageDownloadInstall.xaml</DependentUpon>
|
<DependentUpon>PageDownloadInstall.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Pages\PageDownload\PageDownloadModify.vb" />
|
||||||
<Compile Include="Pages\PageDownload\Resource\PageDownloadCompDetail.xaml.vb">
|
<Compile Include="Pages\PageDownload\Resource\PageDownloadCompDetail.xaml.vb">
|
||||||
<DependentUpon>PageDownloadCompDetail.xaml</DependentUpon>
|
<DependentUpon>PageDownloadCompDetail.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user