This commit is contained in:
LTCat
2026-08-02 01:00:16 +08:00
parent c7ccdd65dc
commit 7fb6e5d68e
61 changed files with 3291 additions and 1165 deletions
+246
View File
@@ -0,0 +1,246 @@
# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行
root = true
# c# 文件
[*.cs]
#### Core EditorConfig 选项 ####
# 缩进和间距
indent_size = 4
indent_style = space
tab_width = 4
# 新行首选项
end_of_line = crlf
insert_final_newline = false
#### .NET 代码操作 ####
# 类型成员
dotnet_hide_advanced_members = false
dotnet_member_insertion_location = with_other_members_of_the_same_kind
dotnet_property_generation_behavior = prefer_throwing_properties
# 符号搜索
dotnet_search_reference_assemblies = true
#### .NET 编码约定 ####
# 组织 Using
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
file_header_template = unset
# this. 和 Me. 首选项
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# 语言关键字与 bcl 类型首选项
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# 括号首选项
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
# 修饰符首选项
dotnet_style_require_accessibility_modifiers = for_non_interface_members
# 表达式级首选项
dotnet_prefer_system_hash_code = true
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true
dotnet_style_explicit_tuple_names = true
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true
dotnet_style_object_initializer = true
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:suggestion
dotnet_style_prefer_collection_expression = when_types_loosely_match
dotnet_style_prefer_compound_assignment = true
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_inferred_anonymous_type_member_names = true
dotnet_style_prefer_inferred_tuple_names = true
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_simplified_boolean_expressions = true
dotnet_style_prefer_simplified_interpolation = true
# 字段首选项
dotnet_style_readonly_field = true
# 参数首选项
dotnet_code_quality_unused_parameters = all
# 禁止显示首选项
dotnet_remove_unnecessary_suppression_exclusions = none
# 新行首选项
dotnet_style_allow_multiple_blank_lines_experimental = true
dotnet_style_allow_statement_immediately_after_block_experimental = true
#### c# 编码约定 ####
# var 首选项
csharp_style_var_elsewhere = false
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = false
# Expression-bodied 成员
csharp_style_expression_bodied_accessors = true
csharp_style_expression_bodied_constructors = false
csharp_style_expression_bodied_indexers = true
csharp_style_expression_bodied_lambdas = true
csharp_style_expression_bodied_local_functions = false
csharp_style_expression_bodied_methods = false
csharp_style_expression_bodied_operators = false
csharp_style_expression_bodied_properties = true
# 模式匹配首选项
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_extended_property_pattern = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true:suggestion
csharp_style_prefer_switch_expression = true
# Null 检查首选项
csharp_style_conditional_delegate_call = true
# 修饰符首选项
csharp_prefer_static_anonymous_function = true
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
csharp_style_prefer_readonly_struct = true
csharp_style_prefer_readonly_struct_member = true
# 代码块首选项
csharp_prefer_braces = true
csharp_prefer_simple_using_statement = true
csharp_prefer_system_threading_lock = true
csharp_style_namespace_declarations = file_scoped:suggestion
csharp_style_prefer_method_group_conversion = true
csharp_style_prefer_primary_constructors = true
csharp_style_prefer_top_level_statements = true
# 表达式级首选项
csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
csharp_style_prefer_implicitly_typed_lambda_expression = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_range_operator = true
csharp_style_prefer_tuple_swap = true
csharp_style_prefer_unbound_generic_type_in_nameof = true
csharp_style_prefer_utf8_string_literals = true
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
# "using" 指令首选项
csharp_using_directive_placement = outside_namespace
# 新行首选项
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
#### C# 格式规则 ####
# 新行首选项
csharp_new_line_before_catch = false
csharp_new_line_before_else = false
csharp_new_line_before_finally = false
csharp_new_line_before_members_in_anonymous_types = false
csharp_new_line_before_members_in_object_initializers = false
csharp_new_line_before_open_brace = none
csharp_new_line_between_query_expression_clauses = false
# 缩进首选项
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = false
csharp_indent_labels = flush_left
csharp_indent_switch_labels = false
# 空格键首选项
csharp_space_after_cast = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = ignore
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# 包装首选项
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### 命名样式 ####
# 命名规则
dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
# 符号规范
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.类型.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.类型.required_modifiers =
dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.非字段成员.required_modifiers =
# 命名样式
dotnet_naming_style.帕斯卡拼写法.required_prefix =
dotnet_naming_style.帕斯卡拼写法.required_suffix =
dotnet_naming_style.帕斯卡拼写法.word_separator =
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
dotnet_naming_style.以_i_开始.required_prefix = I
dotnet_naming_style.以_i_开始.required_suffix =
dotnet_naming_style.以_i_开始.word_separator =
dotnet_naming_style.以_i_开始.capitalization = pascal_case
+15 -6
View File
@@ -2,10 +2,19 @@ namespace PCLCS;
public static class Configs {
/// <summary>当前 Java 相关配置的版本。0 代表尚未从老的 Settings 系统中迁移。</summary>
public static readonly ConfigEntry<int> JavaConfigVersion = new(nameof(JavaConfigVersion), 0);
public static readonly ConfigEntry<ConcurrentList<Java>> JavaList = new(nameof(JavaList), []);
public static readonly ConfigEntry<List<string>> JavaRemovedList = new(nameof(JavaRemovedList), []);
public static readonly ConfigEntry<bool> InstanceMigratedJava = new(nameof(InstanceMigratedJava), false);
public static readonly ConfigEntry<Java> InstanceForcedJava = new(nameof(InstanceForcedJava), null);
public static readonly ConfigEntry<int> JavaConfigVersion = new("JavaConfigVersion", 0);
public static readonly ConfigEntry<ConcurrentList<Java>> JavaList = new("JavaList", []);
public static readonly ConfigEntry<List<string>> JavaRemovedList = new("JavaRemovedList", []);
public static readonly DynamicConfigEntry<bool> JavaMigrated = new("InstanceMigratedJava", false);
public static readonly DynamicConfigEntry<Java> JavaForced = new("InstanceForcedJava", null);
}
static Configs() {
/// 当 JavaForced 获取到一个不在 JavaList 中的值时,将其重置为 null。
JavaForced.PreviewGet += (args, provider) => {
if (args.Value is not null && !JavaList.Get()!.Contains(args.Value)) {
args.Value = null;
JavaForced.Reset(provider);
}
};
}
}
+5 -4
View File
@@ -17,10 +17,12 @@ public enum ResourceTypes {
DataPack = 16,
/// <summary>服务端插件。</summary>
Plugin = 32,
/// <summary>地图。</summary>
Map = 64,
/// <summary>同时包含数据包以及 Mod。</summary>
ModOrDataPack = Mod | DataPack,
/// <summary>允许任意种类,或种类未知。</summary>
Any = Mod | ModPack | ResourcePack | Shader | DataPack | Plugin,
Any = Mod | ModPack | ResourcePack | Shader | DataPack | Plugin | Map,
}
/// <summary>
@@ -42,9 +44,8 @@ public enum ModLoaders {
Forge = 1,
LiteLoader = 2,
Fabric = 4,
Quilt = 8,
NeoForge = 16,
All = Forge | LiteLoader | Fabric | Quilt | NeoForge,
All = Forge | LiteLoader | Fabric | NeoForge,
}
/// <summary>
@@ -67,7 +68,7 @@ public static class Versions {
/// <summary>
/// 版本管理中 Mod 信息缓存的版本号。
/// </summary>
public const int LocalModCacheVersion = 17;
public const int LocalModCacheVersion = 18;
/// <summary>
/// Minecraft 本地实例信息缓存的版本号。
/// </summary>
+64 -30
View File
@@ -19,6 +19,13 @@ namespace PCLCS;
/// <para/> 若为 null,则还需要调用 <see cref="CheckAsync"/> 以获取版本号。
/// </summary>
public Version? Version = version;
/// <summary>Java 的默认字符编码。</summary>
[JsonIgnore] public string? FileEncodingName;
/// <summary>
/// Java 根据系统环境确定的本地字符编码,仅 Java 17+ 可用。
/// <para/>若系统开启了 UTF-8,部分 Java 会错误地返回 JDK,因此不能使用 <see cref="Encoding.Default"/>。
/// </summary>
[JsonIgnore] public string? NativeEncodingName;
/// <summary>
/// 检查该 Java 是否存在问题,并获取其版本号。
@@ -31,12 +38,12 @@ namespace PCLCS;
if (!FileUtils.Exists(JavaExePath)) throw new FileNotFoundException("未找到 java.exe 文件", JavaExePath);
// 运行 -version
output = (await TaskUtils.RunProgramAsync(JavaExePath, "-version", 15000, cancellationToken: cancellationToken).NoCapture()).Output.Lower();
output = (await TaskUtils.RunProgramAsync(JavaExePath, "-XshowSettings:properties -version", 15000, cancellationToken: cancellationToken).NoCapture()).Output.Lower();
if (output == "") throw new InvalidOperationException("尝试运行该 Java 失败");
Logger.Trace($"Java 检查输出:{JavaExePath}{Environment.NewLine}{output}");
if (output.Contains("/lib/ext exists")) throw new InvalidOperationException("无法运行该 Java,请在删除 Java 文件夹中的 /lib/ext 文件夹后再试");
if (output.Contains("a fatal error") || output.Contains("error: ")) throw new InvalidOperationException("无法运行该 Java,该 Java 或系统存在问题");
// 获取版本号
var versionString = (output.RegexSeek(@"(?<=version "")[^""]+") ?? output.RegexSeek("(?<=openjdk )[0-9]+"))?.Replace("_", ".").Replace("+", ".").BeforeFirst("-");
if (string.IsNullOrEmpty(versionString)) throw new InvalidOperationException($"未找到该 Java 的版本号{(output.Length < 500 ? $"\n原始输出为:\n{output}" : "")}");
@@ -46,7 +53,16 @@ namespace PCLCS;
Version = new Version(segments.Take(4).Join("."));
if (Version.Major is <= 4 or >= 100) throw new InvalidOperationException($"分析详细信息失败,获取的版本为 {Version}{(output.Length < 500 ? $"\n原始输出为:\n{output}" : "")}");
// 获取 Java 的相关属性
if (!output.Contains("64-bit")) throw new InvalidOperationException("该 Java 为 32 位版本,请安装 64 位的 Java");
string? GetProperty(string name) {
string prefix = name + " = ";
string? line = output.Split('\n').Select(l => l.Trim()).FirstOrDefault(l => l.StartsWithF(prefix));
return line?[prefix.Length..].Trim();
}
FileEncodingName = GetProperty("file.encoding");
NativeEncodingName = GetProperty("native.encoding") ?? FileEncodingName; // 旧版本没有 native.encoding
Logger.Info($"检查 Java 成功:{this}");
available = true;
} catch (Exception ex) {
@@ -59,6 +75,12 @@ namespace PCLCS;
}
return available!.Value;
}
public void InvalidateChecked() {
isChecked = 0;
available = null;
}
[JsonIgnore] private int isChecked = 0;
/// <summary>若已进行过检查,表示该检查是否成功。若未检查,则为 null。</summary>
[JsonIgnore] internal bool? available = null;
@@ -95,8 +117,8 @@ public static class JavaUtils {
javas = await JavaUtils.CheckAllAsync(javas, cancellationToken, progress).NoCapture();
javas.Sort((left, right) => {
// 优先使用带完整 Java 的文件夹列表中的 Java
var isLeftInCandidateFolder = JavaUtils.CandidateFolders.Any(folder => PathUtils.IsParentOf(folder, left.Folder));
var isRightInCandidateFolder = JavaUtils.CandidateFolders.Any(folder => PathUtils.IsParentOf(folder, right.Folder));
var isLeftInCandidateFolder = JavaUtils.CandidateFolders.Value.Any(folder => PathUtils.IsParentOf(folder, left.Folder));
var isRightInCandidateFolder = JavaUtils.CandidateFolders.Value.Any(folder => PathUtils.IsParentOf(folder, right.Folder));
if (isLeftInCandidateFolder != isRightInCandidateFolder) return isLeftInCandidateFolder ? -1 : 1;
// 其次优先使用主版本号接近 21 的 Java
var leftDistance = left.Version is null ? int.MaxValue : Math.Abs(left.Version.Major - 21);
@@ -111,36 +133,47 @@ public static class JavaUtils {
/// <summary>
/// 存在完整 Java 的文件夹列表。
/// </summary>
internal static readonly List<string> CandidateFolders = [
Paths.AppData + @".minecraft\runtime\", // 这也是 PCL 下载 Java 的路径
Paths.AppData + @".hmcl\java\",
Paths.AppData + @"ATLauncher\runtimes\minecraft\",
Paths.AppData + @"ModrinthApp\meta\java_versions\",
Paths.AppData + @"PrismLauncher\java\",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\curseforge\minecraft\Install\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\.jdks\",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\.sdkman\candidates\java\",
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\.ftba\bin\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Packages\Microsoft.4297127D64EC6_8wekyb3d8bbwe\LocalCache\Local\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Minecraft Launcher\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Minecraft\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Curse\Minecraft\Install\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Java\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Eclipse Adoptium\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Amazon Corretto\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Zulu\",
..DirectoryUtils.EnumerateDirectories(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Microsoft\", searchPattern: "jdk-*"),
// 环境变量
..(Environment.GetEnvironmentVariable("JDK_HOME") + ";" + Environment.GetEnvironmentVariable("JAVA_HOME")).
Split(";", true).Select(path => path.Trim(' ', '"'))
];
internal static readonly Lazy<List<string>> CandidateFolders = new(() => {
List<string> folders = [
Paths.AppData + @".minecraft\runtime\", // 这也是 PCL 下载 Java 的路径
Paths.AppData + @".hmcl\java\",
Paths.AppData + @"ATLauncher\runtimes\minecraft\",
Paths.AppData + @"ModrinthApp\meta\java_versions\",
Paths.AppData + @"PrismLauncher\java\",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\curseforge\minecraft\Install\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\.jdks\",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\.sdkman\candidates\java\",
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\.ftba\bin\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Packages\Microsoft.4297127D64EC6_8wekyb3d8bbwe\LocalCache\Local\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Minecraft Launcher\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Minecraft\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Curse\Minecraft\Install\runtime\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Java\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Eclipse Adoptium\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Amazon Corretto\",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Zulu\",
..DirectoryUtils.EnumerateDirectories(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Microsoft\", searchPattern: "jdk-*"),
// 环境变量
..(Environment.GetEnvironmentVariable("JDK_HOME") + ";" + Environment.GetEnvironmentVariable("JAVA_HOME")).
Split(";", true).Select(path => path.Trim(' ', '"'))
];
return folders.Select(f => {
try {
return PathUtils.ForCompare(f);
} catch (Exception ex) {
Logger.Warn(ex, $"Java 候选文件夹路径无效({f})");
return null;
}
}).Where(f => f is not null).Cast<string>().ToList();
});
/// <summary>
/// 从常见文件夹和环境变量中搜索 Java,并将搜索结果写入设置。
/// </summary>
public static async Task RefreshListAsync(CancellationToken c = default, ProgressProvider? p = null) {
// 搜索
List<Java> javaList = await SearchFoldersAsync(true, CandidateFolders, c, p?.SplitTo(0.5)).NoCapture();
List<Java> javaList = await SearchFoldersAsync(true, CandidateFolders.Value, c, p?.SplitTo(0.5)).NoCapture();
// 将新发现的 Java 排在最前,原有列表保留既有顺序排在后面
var oldJavaList = Configs.JavaList.Get()!;
oldJavaList = await JavaUtils.CheckAllAsync(oldJavaList, c, p?.SplitTo(0.9)).NoCapture(); // 检查原有列表中的 Java
@@ -169,6 +202,7 @@ public static class JavaUtils {
string targetFolder = PathUtils.AddSlashSuffix(PathUtils.ForCompare(PathUtils.RemoveLastPart(file)));
// 判断文件夹是否包含重解析点(例如符号链接)
static bool HasReparsePoint(FileSystemInfo info) {
if (PathUtils.IsParentOf(Paths.AppData + @".minecraft\runtime\", info.FullName)) return false; // 不筛查 PCL 的下载路径(#8928)
do {
if (info.Attributes.HasFlag(FileAttributes.ReparsePoint)) return true;
info = info is FileInfo fileInfo ? fileInfo.Directory : ((DirectoryInfo) info).Parent;
@@ -194,14 +228,14 @@ public static class JavaUtils {
if (results.All(r => r.HasReparsePoint)) {
Logger.Warn("找到的所有 Java 都包含重解析点,保留全部结果");
} else if (results.Any(r => r.HasReparsePoint)) {
Logger.Info($"找到以下的 Java 包含重解析点,将它们从列表中排除:{results.Where(r => r.HasReparsePoint).Select(r => r.Folder).Join('、')}");
Logger.Warn($"找到的以下 Java 包含重解析点,将它们从列表中排除:{results.Where(r => r.HasReparsePoint).Select(r => r.Folder).Join('、')}");
results = [..results.Where(r => !r.HasReparsePoint)];
}
// 筛除特殊路径
if (results.All(r => r.IsSpecialPath)) {
Logger.Warn("找到的所有 Java 都包含特殊路径,保留全部结果");
} else if (results.Any(r => r.IsSpecialPath)) {
Logger.Info($"找到以下的 Java 包含特殊路径,将它们从列表中排除:{results.Where(r => r.IsSpecialPath).Select(r => r.Folder).Join('、')}");
Logger.Warn($"找到的以下 Java 包含特殊路径,将它们从列表中排除:{results.Where(r => r.IsSpecialPath).Select(r => r.Folder).Join('、')}");
results = [..results.Where(r => !r.IsSpecialPath)];
}
+30
View File
@@ -0,0 +1,30 @@
namespace PCLCS;
public static class LaunchUtils {
/// <summary>
/// 释放补丁文件并返回完整文件路径。
/// </summary>
/// <param name="patchFilePath">补丁文件路径
/// <param name="outputDirectory">补丁文件的释放目录。</param>
public static string ExtractPatch(string patchFilePath, string outputDirectory) {
Logger.Info($"选定的资源 {patchFilePath} 输出路径:{outputDirectory}");
lock (ExtractPatchLock) { // 避免 OptiFine 和 Forge 安装时同时释放导致冲突
try {
FileUtils.ExtractResources(patchFilePath, Path.Combine(outputDirectory, PathUtils.GetLastPart(patchFilePath)), typeof(LaunchUtils));
} catch (Exception ex) {
if (!FileUtils.Exists(outputDirectory)) throw new FileNotFoundException($"释放 {patchFilePath} 失败", ex);
Logger.Warn(ex, $"{patchFilePath} 文件重新释放失败,将尝试更换文件名重新生成");
patchFilePath = Path.Combine(outputDirectory, $"{PathUtils.GetFileNameWithoutExtension(patchFilePath)}2.{PathUtils.GetExtension(patchFilePath)}");
try {
FileUtils.ExtractResources(patchFilePath, Path.Combine(outputDirectory, PathUtils.GetLastPart(patchFilePath)), typeof(LaunchUtils));
} catch (Exception ex2) {
throw new FileNotFoundException($"释放 {patchFilePath} 最终尝试失败", ex2);
}
}
}
return Path.Combine(outputDirectory, PathUtils.GetLastPart(patchFilePath));
}
private static readonly object ExtractPatchLock = new();
}
+2 -1
View File
@@ -55,7 +55,8 @@
<!-- 内嵌的资源 -->
<ItemGroup>
<None Remove="Resource\WikiEntries.txt" />
<EmbeddedResource Include="Launch\JavaWrapper.jar" LogicalName="Launch\JavaWrapper.jar" />
<EmbeddedResource Include="Launch\LwjglUnsafeAgent.jar" LogicalName="Launch\LwjglUnsafeAgent.jar" />
<EmbeddedResource Include="Resource\WikiEntries.txt" LogicalName="Resource\WikiEntries.txt" />
</ItemGroup>
<ItemGroup>
-2
View File
@@ -9,7 +9,6 @@ public static class Resource {
1 => ModLoaders.Forge,
3 => ModLoaders.LiteLoader,
4 => ModLoaders.Fabric,
5 => ModLoaders.Quilt,
6 => ModLoaders.NeoForge,
_ => ModLoaders.None,
};
@@ -24,7 +23,6 @@ public static class Resource {
ModLoaders.Forge => 1,
ModLoaders.LiteLoader => 3,
ModLoaders.Fabric => 4,
ModLoaders.Quilt => 5,
ModLoaders.NeoForge => 6,
_ => 0,
};
File diff suppressed because one or more lines are too long
-31
View File
@@ -132,37 +132,6 @@
<Setter Property="FontFamily" Value="Resources/#PCL English, Microsoft YaHei UI" />
</Style>
<!-- ToolTip -->
<Style TargetType="ToolTip">
<EventSetter Event="Opened" Handler="OnTooltipOpened" />
<EventSetter Event="Closed" Handler="OnTooltipClosed" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="{DynamicResource ColorBrush1}" BorderThickness="1.5" CornerRadius="4" MaxWidth="500" Background="#E5FFFFFF" Margin="0,0,4,4" SnapsToDevicePixels="True">
<Border.Effect>
<DropShadowEffect Opacity="0.3" BlurRadius="4" ShadowDepth="2" Color="{DynamicResource ColorObject1}" />
</Border.Effect>
<TextBlock Text="{TemplateBinding ContentControl.Content}" TextWrapping="Wrap" Foreground="{DynamicResource ColorBrush1}" Margin="7,5" FontSize="12"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExtendTextToolTip" TargetType="ToolTip">
<EventSetter Event="Opened" Handler="OnTooltipOpened" />
<EventSetter Event="Closed" Handler="OnTooltipClosed" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="{DynamicResource ColorBrush1}" BorderThickness="1" CornerRadius="3" Background="White" Margin="0,0,4,4" SnapsToDevicePixels="True">
<TextBlock Text="{TemplateBinding ContentControl.Content}" TextWrapping="Wrap" Foreground="{DynamicResource ColorBrush1}" Margin="7,5" FontSize="12"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ScrollViewer -->
<Style x:Key="MyThumb" TargetType="Thumb">
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
+4 -17
View File
@@ -1,6 +1,5 @@
Imports System.Reflection
Imports System.Windows.Threading
Imports Microsoft.Win32
Public Class Application
@@ -23,9 +22,7 @@ Public Class Application
End If
'检查 .NET Framework 版本
Try
Using ndpKey As RegistryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\")
If ndpKey?.GetValue("Release") IsNot Nothing AndAlso CInt(ndpKey.GetValue("Release")) < 528040 Then OldEnvironmentAssert()
End Using
If CInt(RegistryUtils.TryRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", "Release", 999999)) < 528040 Then OldEnvironmentAssert()
Catch ex As Exception
Logger.Warn(ex, "检查 .NET Framework 版本失败")
End Try
@@ -218,7 +215,7 @@ RetryCacheCheck:
'动态 DLL 加载
Private Sub New() '这里必须尽早调用,且不能使用任何库,否则加载 MeloongCore 就会导致崩溃
Static Prefixes As String() = {"NAudio", "Newtonsoft.Json", "Ookii.Dialogs.Wpf", "Imazen.WebP", "CacheCow.Common", "CacheCow.Client.FileStore", "CacheCow.Client", "ThrottleDebounce", "System.Net.Http.Formatting", "PCLCS", "MeloongCore.Wpf", "MeloongCore"}
Static Prefixes As String() = {"NAudio", "Newtonsoft.Json", "Ookii.Dialogs.Wpf", "Imazen.WebP", "CacheCow.Common", "CacheCow.Client.FileStore", "CacheCow.Client", "ThrottleDebounce", "System.Net.Http.Formatting", "Microsoft.Win32.Registry", "PCLCS", "MeloongCore.Wpf", "MeloongCore"}
Static LoadedAssemblies As New ConcurrentDictionary(Of String, Lazy(Of Assembly))(StringComparer.Ordinal) '缓存
AddHandler AppDomain.CurrentDomain.AssemblyResolve,
Function(sender As Object, Args As ResolveEventArgs) As Assembly
@@ -234,17 +231,15 @@ RetryCacheCheck:
End Function
End Sub
Private Shared Sub ExtractLibwebp() '这个方法会调用 ModBase,进而调用 MeloongCore,所以不能放在 New 里
SetDllDirectory(PathPure.TrimEnd("\"c))
SetDllDirectory(PathPure.Value.TrimEnd("\"c))
Try
ExtractResources(PathPure & "libwebp.dll", "libwebp64")
ExtractResources(PathPure.Value & "libwebp.dll", "libwebp64")
Catch ex As Exception
Logger.Warn(ex, "写入 libwebp.dll 失败") '防止同时加载多个图片时,同时写入文件导致文件占用,进而导致崩溃
End Try
End Sub
Private Declare Function SetDllDirectory Lib "kernel32" Alias "SetDllDirectoryA" (lpPathName As String) As Boolean
'切换窗口
'控件模板事件
Private Sub MyIconButton_Click(sender As Object, e As EventArgs)
Select Case Settings.Get(Of McLoginType)("LoginType")
@@ -290,12 +285,4 @@ RetryCacheCheck:
End Select
End Sub
Public Shared ShowingTooltips As New List(Of ToolTip)
Private Sub OnTooltipOpened(sender As ToolTip, e As RoutedEventArgs)
ShowingTooltips.Add(sender)
End Sub
Private Sub OnTooltipClosed(sender As ToolTip, e As RoutedEventArgs)
ShowingTooltips.Remove(sender)
End Sub
End Class
@@ -76,8 +76,7 @@ Public Class MyLoading
If Ex Is Nothing Then
LabText.Text = "未知错误"
Else
Ex = Ex.RootException()
LabText.Text = If(Ex.IsBadNetwork(), "网络环境不佳,请稍后再试,或使用 VPN 改善网络环境", Ex.Message)
LabText.Text = Ex.GetDisplay(False)
End If
Else
LabText.Text = TextError
@@ -18,9 +18,6 @@ Public Class MyScrollViewer
End If
e.Handled = True
PerformVerticalOffsetDelta(-e.Delta)
'关闭 Tooltip (#2552)
'通过 IsOpen 关闭 Tooltip 而不是降低 Border 不透明度 (#5744)
Application.ShowingTooltips.ForEach(Sub(tooltip) tooltip.IsOpen = False)
End Sub
Public Sub PerformVerticalOffsetDelta(Delta As Double)
AniStart(
+2 -2
View File
@@ -169,8 +169,8 @@
<StackPanel HorizontalAlignment="Right" VerticalAlignment="Bottom" Grid.Row="1" Margin="15">
<local:MyExtraButton x:Name="BtnExtraBack" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="返回顶部" Visibility="Collapsed"
Logo="M858.496 188.9024 173.1072 188.9024c-30.2848 0-54.8352-24.5504-54.8352-54.8352L118.272 106.6496c0-30.2848 24.5504-54.8352 54.8352-54.8352l685.3888 0c30.2848 0 54.8352 24.5504 54.8352 54.8352l0 27.4176C913.3312 164.352 888.7808 188.9024 858.496 188.9024L858.496 188.9024zM150.6048 550.8608c0 0 300.0064-240.3584 303.0272-243.328 13.9776-13.5936 31.1808-21.8624 48.8192-24.7552 1.7152-0.3072 3.4304-0.5888 5.1456-0.768 2.7392-0.3072 5.4528-0.3584 8.192-0.3328 2.7392-0.0256 5.4272 0.0256 8.1664 0.3328 1.7408 0.1792 3.4304 0.4864 5.1456 0.768 17.664 2.8928 34.8672 11.1616 48.8192 24.7552 3.0464 2.944 303.0016 243.328 303.0016 243.328 32.384 31.5136 29.6192 63.9744-2.7392 95.5136-32.3328 31.5392-75.648 2.9696-108.0064-28.544l-185.8816-147.1232 0 485.8368c0 30.3104-24.5248 54.8608-54.8352 54.8608l-27.392 0c-30.2848 0-54.8352-24.5504-54.8352-54.8608L447.232 470.7072l-185.8304 147.0976c-32.3584 31.5392-75.6992 60.1344-108.032 28.5696C121.0368 614.8352 118.272 582.3744 150.6048 550.8608L150.6048 550.8608zM150.6048 550.8608" />
<local:MyExtraButton x:Name="BtnExtraDownload" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="下载管理" Visibility="Collapsed"
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" />
<local:MyExtraButton x:Name="BtnExtraDownload" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="任务管理" Visibility="Collapsed"
LogoScale="1.1" Logo="M484.693 225.28 314.027 389.12l-68.267-68.267c-13.653-13.653-40.96-13.653-47.787 0-13.653 13.654-13.653 34.134 0 47.787l95.574 95.573c13.653 13.654 34.133 13.654 47.786 0L532.48 273.067c13.653-13.654 13.653-34.134 0-47.787s-34.133-13.653-47.787 0M819.2 341.333H614.4c-20.48 0-34.133 13.654-34.133 34.134S593.92 409.6 614.4 409.6h204.8c20.48 0 34.133-13.653 34.133-34.133s-13.653-34.134-34.133-34.134m0 341.334H614.4c-20.48 0-34.133 13.653-34.133 34.133s13.653 34.133 34.133 34.133h204.8c20.48 0 34.133-13.653 34.133-34.133s-13.653-34.133-34.133-34.133m-477.867-102.4c-75.093 0-136.533 61.44-136.533 136.533s61.44 136.533 136.533 136.533 136.534-61.44 136.534-136.533-61.44-136.533-136.534-136.533m0 204.8c-40.96 0-68.266-27.307-68.266-68.267s27.306-68.267 68.266-68.267S409.6 675.84 409.6 716.8s-27.307 68.267-68.267 68.267" />
<local:MyExtraButton x:Name="BtnExtraApril" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="投降" Visibility="Collapsed"
Logo="M124.96 32c-28.64 0-60.064 23.2-60.064 51.904v856.192c0 28.576 30.688 51.904 59.296 51.904s60.064-23.328 60.064-51.904V83.904C184.256 55.2 153.536 32 124.96 32z m616.352 71.264c-168.416 0-168.416-69.024-336.8-69.024-97.216 0-172.256 45.344-172.256 45.344l-0.736 516.736s75.776-45.28 172.96-45.28c168.416 0 168.416 69.024 336.8 69.024 105.344 0 211.168-55.328 211.168-55.328V48.064c0.032 0-105.792 55.2-211.136 55.2z m0 0" />
<local:MyExtraButton x:Name="BtnExtraShutdown" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="关闭 Minecraft" Visibility="Collapsed"
+25 -12
View File
@@ -11,6 +11,12 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
If BuildType = BuildTypes.Release Then
If LastVersion < 408 Then 'Release 2.13.1.0
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:版本设置中,添加打开截图文件夹的快捷方式"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:导出整合包时,可以勾选导出光影设置文件"))
FeatureCount += 21
BugCount += 22
End If
If LastVersion < 406 Then 'Release 2.13.0.1
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "新增:重做 Java 管理与相关设置,允许调整 Java 优先级、指定 Java 版本范围等"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:导出整合包时允许自动导出版本文件夹中的 Java"))
@@ -87,6 +93,12 @@ Public Class FormMain
'3:BUG+ IMP* FEAT-
'2:BUG* IMP-
'1:BUG-
If LastVersion < 409 Then 'Snapshot 2.13.1.0
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:版本设置中,添加打开截图文件夹的快捷方式"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:导出整合包时,可以勾选导出光影设置文件"))
FeatureCount += 21
BugCount += 22
End If
If LastVersion < 407 Then 'Snapshot 2.13.0.1
If LastVersion = 405 Then
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:使用部分主页预设时崩溃"))
@@ -150,7 +162,7 @@ Public Class FormMain
If LastVersion < 385 Then 'Snapshot 2.12.5
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法下载 NeoForge 26.1"))
If LastVersion = 384 Then
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:下载可能失败,提示下载管理刷新线程出错"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:下载可能失败,提示任务管理刷新线程出错"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法保存选择的 Minecraft 文件夹"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:使用中文搜索 Mod 时,部分结果会忽略筛选条件"))
End If
@@ -1029,6 +1041,7 @@ Public Class FormMain
Logger.Info("文件为压缩包,尝试作为整合包安装")
Try
ModpackInstall(FilePath)
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.TaskManager))
Return
Catch ex As Exception
If ex.IsCanceled Then Return
@@ -1157,9 +1170,9 @@ Public Class FormMain
''' </summary>
InstanceSelect = 5
''' <summary>
''' 下载管理。这是一个副页面。
''' 任务管理。这是一个副页面。
''' </summary>
DownloadManager = 6
TaskManager = 6
''' <summary>
''' 版本设置。这是一个副页面。
''' </summary>
@@ -1206,8 +1219,8 @@ Public Class FormMain
Select Case Stack.Page
Case PageType.InstanceSelect
Return "版本选择"
Case PageType.DownloadManager
Return "下载管理"
Case PageType.TaskManager
Return "任务管理"
Case PageType.InstanceSetup
Return "版本设置 - " & If(PageInstanceLeft.Instance Is Nothing, "未知版本", PageInstanceLeft.Instance.Name)
Case PageType.ResourceDetail
@@ -1429,7 +1442,7 @@ Public Class FormMain
If FrmSelectLeft Is Nothing Then FrmSelectLeft = New PageSelectLeft
If FrmSelectRight Is Nothing Then FrmSelectRight = New PageSelectRight
PageChangeAnim(FrmSelectLeft, FrmSelectRight)
Case PageType.DownloadManager '下载管理
Case PageType.TaskManager '任务管理
If FrmSpeedLeft Is Nothing Then FrmSpeedLeft = New PageSpeedLeft
If FrmSpeedRight Is Nothing Then FrmSpeedRight = New PageSpeedRight
PageChangeAnim(FrmSpeedLeft, FrmSpeedRight)
@@ -1449,7 +1462,7 @@ Public Class FormMain
BtnExtraApril.ShowRefresh()
#End Region
Logger.Info($"切换主要页面:{Stack}, {SubType}")
Logger.Info($"切换主要页面:{Stack.Page}, {SubType}")
Catch ex As Exception
Logger.Error(ex, $"切换主要页面失败(ID {PageCurrent.Page})")
Finally
@@ -1461,8 +1474,8 @@ Public Class FormMain
AniStop("PageLeft PageChange") '停止左边栏变更导致的右页面切换动画,防止它与本动画一起触发多次 PageOnEnter
AniControlEnabled += 1
'清除新页面关联性
If Not IsNothing(TargetLeft.Parent) Then TargetLeft.SetValue(ContentPresenter.ContentProperty, Nothing)
If Not IsNothing(TargetRight) AndAlso Not IsNothing(TargetRight.Parent) Then TargetRight.SetValue(ContentPresenter.ContentProperty, Nothing)
If TargetLeft.Parent IsNot Nothing Then TargetLeft.SetValue(ContentPresenter.ContentProperty, Nothing)
If TargetRight IsNot Nothing AndAlso TargetRight.Parent IsNot Nothing Then TargetRight.SetValue(ContentPresenter.ContentProperty, Nothing)
PageLeft = TargetLeft
PageRight = TargetRight
'触发页面通用动画
@@ -1603,12 +1616,12 @@ Public Class FormMain
MusicControlNext()
End Sub
'下载管理
'任务管理
Private Sub BtnExtraDownload_Click(sender As Object, e As EventArgs) Handles BtnExtraDownload.Click
PageChange(PageType.DownloadManager)
PageChange(PageType.TaskManager)
End Sub
Private Function BtnExtraDownload_ShowCheck() As Boolean
Return HasDownloadingTask() AndAlso Not PageCurrent = PageType.DownloadManager
Return HasDownloadingTask() AndAlso Not PageCurrent = PageType.TaskManager
End Function
'投降
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -79,7 +79,7 @@ Public Module ModAnimation
''' 已经执行的动画长度。如果为负数则为延迟。
''' </summary>
''' <remarks></remarks>
Public TimeFinished As Integer
Public TimeFinished As Double
''' <summary>
''' 已经完成的百分比。
''' </summary>
@@ -853,9 +853,8 @@ Sleeper:
''' <summary>
''' 动画定时器事件。
''' </summary>
Public Sub AniTimer(DeltaTick As Integer)
Public Sub AniTimer(DeltaTick As Double)
Try
If DeltaTick / AniSpeed > 100 Then Logger.Info($"两个动画帧间隔 {DeltaTick} ms")
Dim i As Integer = -1
'循环每个动画组
@@ -1034,6 +1033,7 @@ NextAni:
End If
Case AniType.Code
Ani.TimeFinished = Ani.TimeTotal
CType(Ani.Value, ThreadStart)()
Case AniType.ScaleTransform
+9 -58
View File
@@ -6,12 +6,12 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
Public Const VersionBaseName As String = "2.13.0.1" '显示用版本名
Public Const VersionBaseName As String = "2.13.1.0" '显示用版本名
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
#If RELEASE Then
Public Const VersionCode As Integer = 406 '正式版
Public Const VersionCode As Integer = 408 '正式版
#Else
Public Const VersionCode As Integer = 407 '快照版
Public Const VersionCode As Integer = 409 '快照版
#End If
'版本信息
@@ -465,57 +465,7 @@ Public Module ModBase
#Region "文件"
'=============================
' 注册表
'=============================
''' <summary>
''' 读取注册表键。如果失败则返回默认值。
''' </summary>
Public Function ReadReg(Key As String, Optional DefaultValue As String = "") As String
Try
Return If(My.Computer.Registry.CurrentUser.OpenSubKey("Software\" & RegFolder, False)?.GetValue(Key), DefaultValue)
Catch ex As Exception
Logger.Error(ex, $"读取注册表出错:{Key}", LogBehavior.Toast)
Return DefaultValue
End Try
End Function
''' <summary>
''' 写入注册表键。
''' </summary>
Public Sub WriteReg(Key As String, Value As String, Optional ThrowException As Boolean = False)
Try
Dim SubKey As Microsoft.Win32.RegistryKey = My.Computer.Registry.CurrentUser.OpenSubKey("Software\" & RegFolder, True)
If SubKey Is Nothing Then SubKey = My.Computer.Registry.CurrentUser.CreateSubKey("Software\" & RegFolder) '如果不存在就创建
SubKey.SetValue(Key, Value)
Catch ex As Exception
Logger.Warn(ex, $"写入注册表出错:{Key}", If(ThrowException, LogBehavior.Toast, LogBehavior.ToastIfDebug))
If ThrowException Then Throw
End Try
End Sub
''' <summary>
''' 是否存在某个注册表键。
''' </summary>
Public Function HasReg(Key As String) As Boolean
Return ReadReg(Key, Nothing) IsNot Nothing
End Function
''' <summary>
''' 删除注册表键。
''' </summary>
Public Sub DeleteReg(Key As String, Optional ThrowException As Boolean = False)
Try
Dim SubKey As Microsoft.Win32.RegistryKey = My.Computer.Registry.CurrentUser.OpenSubKey("Software\" & RegFolder, True)
If SubKey?.GetValue(Key) Is Nothing Then Return
SubKey.DeleteValue(Key)
Catch ex As Exception
Logger.Warn(ex, $"删除注册表出错:{Key}", If(ThrowException, LogBehavior.Toast, LogBehavior.ToastIfDebug))
If ThrowException Then Throw
End Try
End Sub
'=============================
' ini
'=============================
'ini
Private ReadOnly IniCache As New ConcurrentDictionary(Of String, ConcurrentDictionary(Of String, String))
''' <summary>
@@ -617,7 +567,8 @@ Public Module ModBase
End Try
End Sub
'文件校验
'权限检查
''' <summary>
''' 检查是否拥有某一文件夹的 I/O 权限。如果文件夹不存在,会返回 False。
''' </summary>
@@ -837,8 +788,8 @@ Public Module ModBase
''' <summary>
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
''' </summary>
Public PathPure As String = GetPureASCIIDir()
Private Function GetPureASCIIDir() As String
Public PathPure As Lazy(Of String) = New Lazy(Of String)(
Function()
If Paths.Base.IsAsciiOnly() Then
Return Paths.Base & "PCL\"
ElseIf Paths.AppDataThenName.IsAsciiOnly() Then
@@ -848,7 +799,7 @@ Public Module ModBase
Else
Return OsDrive & "ProgramData\PCL\"
End If
End Function
End Function)
''' <summary>
''' 指示接取到这个异常的函数进行重试。
@@ -288,7 +288,7 @@ Retry:
Catch ex As TimeoutException
Throw New WebException($"连接服务器超时,请稍后再试,或使用 VPN 改善网络环境({Method}, {Url},IP:{HostIp})", WebExceptionStatus.Timeout)
Catch ex As Exception
ex.ThrowIfCanceled()
If TypeOf ex IsNot TaskCanceledException Then ex.ThrowIfCanceled() 'GetResultWithTimeout 会抛出 TaskCanceledException
RecordIPReliability(HostIp, -1)
If ex.IsBadNetwork Then
Throw New WebException($"网络请求失败,请稍后再试,或使用 VPN 改善网络环境({Method}, {Url},IP:{HostIp})", WebExceptionStatus.Timeout)
@@ -1423,8 +1423,8 @@ Retry:
End Get
Set(value As Integer)
_FailCount = value
If State = LoadState.Loading AndAlso value >= Math.Min(10000, Math.Max(FileRemain * 5.5, NetTaskThreadLimit * 5.5 + 3)) Then
Logger.Warn($"由于同加载器中失败次数过多引发强制失败:连续失败了 {value} 次")
If State = LoadState.Loading AndAlso value >= Math.Min(10000, Math.Max(FileRemain * 8, NetTaskThreadLimit * 8 + 3)) Then
Logger.Error($"由于同加载器中失败次数过多引发强制失败:连续失败了 {value} 次", LogBehavior.ToastIfDebug)
On Error Resume Next
Dim ExList As New List(Of Exception)
For Each File In Files
@@ -1917,7 +1917,7 @@ FinishExCatch:
End Class
''' <summary>
''' 是否有正在进行中、需要在下载管理页面显示的下载任务?
''' 是否有正在进行中、需要在任务管理页面显示的下载任务?
''' </summary>
Public Function HasDownloadingTask(Optional IgnoreCustomDownload As Boolean = False) As Boolean
Return LoaderTaskbar.Any(
@@ -260,16 +260,16 @@ Public Class ValidateFolderName
Inherits Validate
Public Property Folder As String
Public Property UseMinecraftCharCheck As Boolean = True
Public Property IgnoreCase As Boolean = True
Private ReadOnly PathIgnore As IEnumerable(Of String)
Private ReadOnly IgnoreList As List(Of String)
Public Sub New()
End Sub
Public Sub New(Folder As String, Optional UseMinecraftCharCheck As Boolean = True, Optional IgnoreCase As Boolean = True)
Public Sub New(Folder As String, Optional UseMinecraftCharCheck As Boolean = True, Optional IgnoreList As List(Of String) = Nothing)
Me.Folder = Folder
Me.IgnoreCase = IgnoreCase
Me.UseMinecraftCharCheck = UseMinecraftCharCheck
On Error Resume Next
PathIgnore = DirectoryUtils.EnumerateDirectories(Folder)
Me.IgnoreList = IgnoreList
End Sub
Public Overrides Function Validate(Str As String) As String
Try
@@ -291,15 +291,17 @@ Public Class ValidateFolderName
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件夹名不可为 %!", True).Validate(Str)
If InvalidStrCheck <> "" Then Return InvalidStrCheck
'检查 NTFS 8.3 文件名(#4505)
If Str.RegexCheck(".{2,}~\d") Then Return "文件夹名不可包含这一特殊格式!"
If Str.RegexCheck(".{2,}~\d") Then Return "文件夹名不能包含这一特殊格式!"
'检查文件夹重名
Dim Arr As New List(Of String)
Dim folderName As String
If PathIgnore IsNot Nothing Then
For Each FolderPath In PathIgnore
Arr.Add(PathUtils.GetLastPart(FolderPath))
folderName = PathUtils.GetLastPart(FolderPath)
If IgnoreList Is Nothing OrElse Not IgnoreList.Contains(folderName, StringComparer.OrdinalIgnoreCase) Then Arr.Add(folderName)
Next
End If
Dim SameNameCheck = New ValidateExceptSame(Arr, "不可与现有文件夹重名!", IgnoreCase).Validate(Str)
Dim SameNameCheck = New ValidateExceptSame(Arr, "不可与现有文件夹重名!", True).Validate(Str)
If Not SameNameCheck = "" Then Return SameNameCheck
Return ""
Catch ex As Exception
@@ -387,6 +389,9 @@ Public Class ValidateFolderPath
'检查长度
LengthCheck = New ValidateLength(1, 254).Validate(Str)
If LengthCheck <> "" Then Return LengthCheck
'检查 NTFS 8.3 文件名(#4505)
Dim Match = Str.RegexSeek(".{2,}~\d")
If Match IsNot Nothing Then Return $"文件夹名不能包含 {Match} 这一特殊格式!"
'检查开头
If Str.StartsWithF("\\Mac\") Then GoTo Fin
For Each Drive In Environment.GetLogicalDrives().Where(Function(p) DirectoryUtils.Exists(p))
@@ -413,8 +418,6 @@ Fin:
'检查特殊字符串
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件夹名不可为 %!").Validate(SubStr)
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
'检查 NTFS 8.3 文件名(#4505)
If SubStr.RegexCheck(".{2,}~\d") Then Return "文件夹名不可包含这一特殊格式!"
Next
Return ""
End Function
@@ -514,7 +514,6 @@ Done:
If LogMc.Contains("signer information does not match signer information of other classes in the same package") Then AppendReason(CrashReason.文件或内容校验失败, If(LogMc.RegexSeek("(?<=class "")[^']+(?=""'s signer information)"), "").TrimEnd(vbCrLf))
If LogMc.Contains("Maybe try a lower resolution resourcepack?") Then AppendReason(CrashReason.材质过大或显卡配置不足)
If LogMc.Contains("java.lang.NoSuchMethodError: net.minecraft.world.server.ChunkManager$ProxyTicketManager.shouldForceTicks(J)Z") AndAlso LogMc.Contains("OptiFine") Then AppendReason(CrashReason.OptiFine导致无法加载世界)
If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
If LogMc.Contains("com.electronwill.nightconfig.core.io.ParsingException: Not enough data available") AndAlso Not CrashReasons.ContainsKey(CrashReason.Mod配置文件导致游戏崩溃) Then AppendReason(CrashReason.NightConfig的Bug)
If LogMc.Contains("Cannot find launch target fmlclient, unable to launch") Then AppendReason(CrashReason.Forge安装不完整)
If LogMc.Contains("Invalid paths argument, contained no existing paths") AndAlso LogMc.Contains("libraries\net\minecraftforge\fmlcore") Then AppendReason(CrashReason.Forge安装不完整)
@@ -522,7 +521,9 @@ Done:
If LogMc.Contains("has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to") Then AppendReason(CrashReason.Mod需要Java11)
If LogMc.Contains("java.lang.RuntimeException: java.lang.NoSuchMethodException: no such method: sun.misc.Unsafe.defineAnonymousClass(Class,byte[],Object[])Class/invokeVirtual") Then AppendReason(CrashReason.Mod需要Java11)
If LogMc.Contains("java.lang.IllegalArgumentException: The requested compatibility level JAVA_11 could not be set. Level is not supported by the active JRE or ASM version") Then AppendReason(CrashReason.Mod需要Java11)
If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
If LogMc.Contains("Unsupported major.minor version") Then AppendReason(CrashReason.Java版本不兼容)
If LogMc.Contains("Level is not supported by the active JRE or ASM version") Then AppendReason(CrashReason.Java版本不兼容)
If LogMc.Contains("Invalid maximum heap size") Then AppendReason(CrashReason.使用32位Java导致JVM无法分配足够多的内存)
If LogMc.Contains("Could not reserve enough space") Then
If LogMc.Contains("for 1048576KB object heap") Then
@@ -543,8 +544,8 @@ Done:
End If
If LogMc.Contains("Missing or unsupported mandatory dependencies:") Then
AppendReason(CrashReason.Mod缺少前置或MC版本错误,
LogMc.RegexSearch("(?<=Missing or unsupported mandatory dependencies:)([\n\r]+\t(.*))+", RegularExpressions.RegexOptions.IgnoreCase).
Select(Function(s) s.Trim((vbCrLf & vbTab & " ").ToCharArray)).Distinct().ToList())
LogMc.RegexSearch("(?<=Missing or unsupported mandatory dependencies:)([\n\r]+\t(.*))+", RegularExpressions.RegexOptions.IgnoreCase).
Select(Function(s) s.Trim((vbCrLf & vbTab & " ").ToCharArray)).Distinct().ToList())
End If
End If
@@ -65,7 +65,7 @@ Public Module ModDownload
#Region "下载资源文件"
If ShouldIgnoreFileCheck(Instance) Then
Logger.Info("已跳过所有 Assets 检查")
Logger.Warn("设置要求跳过所有 Assets 检查,文件可能不是最新的", LogBehavior.None)
Else
Dim LoadersAssets As New List(Of LoaderBase)
'获取资源文件索引地址
@@ -78,13 +78,23 @@ Public Module ModDownload
If IndexFile Is Nothing Then
Task.Output = New List(Of NetFile)
Logger.Warn($"未找到版本 {Instance.Name} 的合适的资源索引下载地址,游戏 assets 可能缺失")
ElseIf DownloadAssetIndexInBackground Then
Return
End If
Dim IndexBackgroundFile = PathTemp & "Cache\" & IndexFile.LocalName & "_background"
If FileUtils.Exists(IndexBackgroundFile) AndAlso
FileUtils.GetInfo(IndexBackgroundFile).LastWriteTime.Date > FileUtils.GetInfo(IndexFile.LocalPath).LastWriteTime.Date Then
Logger.Info($"发现后台更新的资源索引缓存文件:{IndexBackgroundFile}")
FileUtils.Move(IndexBackgroundFile, IndexFile.LocalPath)
End If
If DownloadAssetIndexInBackground Then
'允许后台更新索引
If IndexFile.Check.Check(IndexFile.LocalPath) Is Nothing Then
Task.Output = New List(Of NetFile)
Else
Task.Output = New List(Of NetFile) From {IndexFile}
End If
Else '强制要求重新下载
Else
'强制要求重新下载
RealAddressMain = IndexFile.LocalPath
TempAddressMain = PathTemp & "Cache\" & IndexFile.LocalName
IndexFile.LocalPath = TempAddressMain
@@ -114,28 +124,24 @@ Public Module ModDownload
Dim LoadersAssetsUpdate As New List(Of LoaderBase)
LoadersAssetsUpdate.Add(New LoaderTask(Of String, List(Of NetFile))("后台分析资源文件索引地址",
Sub(Task As LoaderTask(Of String, List(Of NetFile)))
Dim BackAssetsFile As NetFile = DlClientAssetIndexGet(Instance)
If BackAssetsFile Is Nothing Then
Dim IndexFile As NetFile = DlClientAssetIndexGet(Instance)
If IndexFile Is Nothing Then
Logger.Warn($"未找到版本 {Instance.Name} 的合适的资源索引下载地址,游戏 assets 可能缺失")
Task.Cancel()
Throw New OperationCanceledException
End If
RealAddressBg = BackAssetsFile.LocalPath
TempAddressBg = PathTemp & "Cache\" & BackAssetsFile.LocalName & "_background"
BackAssetsFile.LocalPath = TempAddressBg
Task.Output = New List(Of NetFile) From {BackAssetsFile}
RealAddressBg = IndexFile.LocalPath
TempAddressBg = PathTemp & "Cache\" & IndexFile.LocalName & "_background"
IndexFile.LocalPath = TempAddressBg
Task.Output = New List(Of NetFile) From {IndexFile}
'检查是否需要更新:每天只更新一次
If FileUtils.Exists(RealAddressBg) AndAlso Math.Abs((FileUtils.GetInfo(RealAddressBg).LastWriteTime.Date - Now.Date).TotalDays) < 1 Then
Logger.Info("无需更新资源文件索引,取消")
Dim LastUpdate As Date = FileUtils.GetInfo(RealAddressBg).LastWriteTime.Date
If FileUtils.Exists(RealAddressBg) AndAlso Math.Abs((LastUpdate - Now.Date).TotalDays) < 1 Then
Logger.Info($"无需更新资源文件索引,上次更新于 {LastUpdate}")
Task.Cancel()
End If
End Sub))
LoadersAssetsUpdate.Add(New LoaderDownload("后台下载资源文件索引", New List(Of NetFile)))
LoadersAssetsUpdate.Add(New LoaderTask(Of List(Of NetFile), String)("后台复制资源文件索引",
Sub(Task As LoaderTask(Of List(Of NetFile), String))
FileUtils.Move(TempAddressBg, RealAddressBg)
McLaunchLog("后台更新资源文件索引成功:" & TempAddressBg)
End Sub))
Dim Updater As New LoaderCombo(Of String)("后台更新资源文件索引", LoadersAssetsUpdate)
Logger.Info("开始后台检查资源文件索引")
Updater.Start()
@@ -1193,15 +1199,15 @@ Public Module ModDownload
Urls.Add((Url, If(Url.Contains("modrinth"), 20, 10)))
Urls.Add((Url, 30))
End If
Dim Exs As String = ""
Dim Errors As New List(Of Exception)
For Each Source In Urls
Try
Return NetRequestByClient(Source.Url, Method, Content, ContentType, Timeout:=Source.Timeout * 1000, Encoding:=Encoding.UTF8, RequireJson:=True).DeserializeJson()
Catch ex As Exception
Exs += ex.Message + vbCrLf
Errors.Add(ex)
End Try
Next
Throw New Exception(Exs)
Throw New AggregateException(Errors)
End Function
#End Region
@@ -101,11 +101,12 @@ Public Module ModJava
End Sub
''' <summary>
''' 手动触发搜索 Java。
''' 手动触发搜索 Java,强制检查所有 Java。
''' </summary>
Public Sub ManuallySearchJava(Optional CancellationToken As CancellationToken = Nothing)
RunInThread(
Sub()
Configs.JavaList.Get().ForAll(Sub(java) java.InvalidateChecked()) '重置已检查的状态
JavaListRefreshWorker.Start(cancellationToken:=CancellationToken)
JavaListRefreshWorker.WaitIfRunningAsync(cancellationToken:=CancellationToken).Run() 'worker 开始/结束时会自动重载 UI
If Configs.JavaList.Get().Any Then
@@ -142,7 +143,10 @@ Public Module ModJava
Dim AddConstraint =
Sub(Constraint As ValueRange(Of Version))
JavaRange = JavaRange?.Intersect(Constraint)
If JavaRange.IsEmpty Then Logger.Warn($"Java 版本要求冲突(当前追加的要求为 {Constraint},版本为 {Instance.VersionDisplayName})")
If JavaRange.IsEmpty Then
Logger.Warn($"Java 版本要求冲突,若启动失败请在版本设置手动指定 Java:当前追加的要求为 {Constraint},游戏版本为 {Instance.VersionDisplayName}", LogBehavior.Toast)
JavaRange = Constraint
End If
End Sub
'原版 26-:通过版本号判断
@@ -294,7 +298,7 @@ Public Module ModJava
Case 3 '=============================== 强制指定特定 Java ===============================
Dim ChosenJava = Configs.InstanceForcedJava.Get(Instance.Config)
Dim ChosenJava = Configs.JavaForced.Get(Instance.Config)
Logger.Info($"版本设置中强制指定的 Java:{Instance.PathVersion} → {ChosenJava}")
If ChosenJava Is Nothing Then
If TryFixOrHint Then
@@ -305,7 +309,7 @@ Public Module ModJava
p?.Skip() : Return Nothing '<==== 设置中未指定 Java
End If
If Not Configs.JavaList.Get().Contains(ChosenJava) Then
Configs.InstanceForcedJava.Reset(Instance.Config)
Configs.JavaForced.Reset(Instance.Config)
UpdateJavaLists()
If TryFixOrHint Then
SwitchToInstanceSetup(Instance)
@@ -314,7 +318,7 @@ Public Module ModJava
p?.Skip() : Return Nothing '<==== 设置中指定的 Java 不在列表中
End If
If Not ChosenJava.CheckAsync(c).Run() Then
Configs.InstanceForcedJava.Reset(Instance.Config)
Configs.JavaForced.Reset(Instance.Config)
UpdateJavaLists()
If TryFixOrHint Then
SwitchToInstanceSetup(Instance)
@@ -365,9 +369,41 @@ Public Module ModJava
'电脑中没有合适的 Java,获取 Mojang 提供的 Java 下载列表
Logger.Warn($"电脑中没有合适的 Java,开始获取 Mojang 提供的 Java 下载列表")
Dim Components = DownloadJavaList()
c.ThrowIfCancellationRequested()
p?.Set(0.4)
Static DownloadListWorker As New RedoableWorker(Of List(Of JavaDownloadInfo))(
Function(cancellationToken)
'下载 Mojang 提供的 Java 列表
Dim IndexFileStr As String = NetRequestByLoader(DlVersionListOrder(
{"https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"},
{"https://bmclapi2.bangbang93.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"}
), IsJson:=True)
cancellationToken?.ThrowIfCancellationRequested()
'解析 Java 列表
Dim Results = New List(Of JavaDownloadInfo)
For Each Prop As JProperty In IndexFileStr.DeserializeJson(Of JObject)()("windows-x64")
cancellationToken?.ThrowIfCancellationRequested()
If Prop.Name = "minecraft-java-exe" Then Continue For '不是完整 Java
Try
Dim Entry = Prop.Value.FirstOrDefault
If Entry Is Nothing Then Continue For
Dim JavaName = Entry("version")("name").ToString '可能的名称格式:"12"、"8u51-cacert462b08"、"17.0.8.1"、"17.0.1.12.1"、"21.0.7"
If JavaName.Contains(".") Then
Dim Parts As String() = JavaName.Split(".")
Results.Add(New JavaDownloadInfo With {.ComponentName = Prop.Name, .Java = Entry, .JavaVersion = New Version(Val(Parts(0)), Val(Parts(1)), If(Parts.Length >= 3, Val(Parts(2)), 0), If(Parts.Length >= 4, Val(Parts(3)), 0))})
ElseIf JavaName.StartsWithF("8u51-") Then
Results.Add(New JavaDownloadInfo With {.ComponentName = Prop.Name, .Java = Entry, .JavaVersion = New Version(8, 0, 51, 0)})
Else
Results.Add(New JavaDownloadInfo With {.ComponentName = Prop.Name, .Java = Entry, .JavaVersion = New Version(Val(JavaName.BeforeFirstOfAny({"u", "."})), 0, 0, 0)})
End If
Catch ex As Exception
Logger.Warn(ex, $"解析 Mojang 提供的 Java 列表项失败,已跳过({Prop.Name})")
End Try
Next
Return Results
End Function)
If Not DownloadListWorker.HasSucceeded Then DownloadListWorker.Start(c, p?.SplitTo(0.4))
DownloadListWorker.WaitIfRunning(cancellationToken:=c)
p?.Set(0.4, skiped:=True)
Dim Components = DownloadListWorker.LastResult
'确定要下载的目标 Java
Dim JavaToDownload As JavaDownloadInfo = If(
@@ -443,7 +479,7 @@ Public Module ModJava
''' 从老版本 PCL 迁移版本独立的 Java 设置。
''' </summary>
Private Sub MigrateInstanceJavaSettings(Instance As McInstance, Optional c As CancellationToken = Nothing, Optional p As ProgressProvider = Nothing)
If Configs.InstanceMigratedJava.Get(Instance.Config) Then p?.Skip() : Return
If Configs.JavaMigrated.Get(Instance.Config) Then p?.Skip() : Return
If FrmInstanceSetup IsNot Nothing Then RunInUiWait(Sub() FrmInstanceSetup.ComboArgumentJava.IsEnabled = False)
Try
Logger.Info($"正在尝试迁移版本独立的 Java 设置({Instance.Name})")
@@ -462,10 +498,10 @@ Public Module ModJava
Configs.JavaList.Edit(Sub(ByRef List) List.Add(ForcedJava)) '加入列表底部
Logger.Info($"已将强制指定的 Java 加入 Java 列表底部:{ForcedJava}")
End If
Configs.InstanceForcedJava.Set(ForcedJava, Instance.Config)
Configs.JavaForced.Set(ForcedJava, Instance.Config)
Settings.Set("VersionArgumentJavaV2", 3, Instance)
UpdateJavaLists()
Configs.InstanceMigratedJava.Set(True, Instance.Config) '完成
Configs.JavaMigrated.Set(True, Instance.Config) '完成
p?.Finish() : Return
NoForcedJava:
Dim JavaFound = JavaUtils.SearchFoldersAsync(True, {Instance.PathVersion}, c, p?.SplitTo(1)).Run()
@@ -478,7 +514,7 @@ NoForcedJava:
Logger.Info("没有需要迁移的内容,自动选择 Java")
Settings.Set("VersionArgumentJavaV2", 0, Instance)
End If
Configs.InstanceMigratedJava.Set(True, Instance.Config) '完成
Configs.JavaMigrated.Set(True, Instance.Config) '完成
Finally
If FrmInstanceSetup IsNot Nothing Then RunInUiWait(
Sub()
@@ -499,44 +535,6 @@ NoForcedJava:
Public Property JavaVersion As Version
End Class
''' <summary>
''' 下载 Mojang 提供的 Java 列表。
''' <para/> 若本次打开程序已经下载过,则会直接返回缓存的结果。
''' </summary>
Private Function DownloadJavaList() As List(Of JavaDownloadInfo)
'TODO: 写一个更简单的 Lazy,允许重置缓存
Static Components As New Lazy(Of List(Of JavaDownloadInfo))(
Function()
'下载 Mojang 提供的 Java 列表
Dim IndexFileStr As String = NetRequestByLoader(DlVersionListOrder(
{"https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"},
{"https://bmclapi2.bangbang93.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"}
), IsJson:=True)
'解析 Java 列表
Dim Results = New List(Of JavaDownloadInfo)
For Each Prop As JProperty In IndexFileStr.DeserializeJson(Of JObject)()("windows-x64")
If Prop.Name = "minecraft-java-exe" Then Continue For '不是完整 Java
Try
Dim Entry = Prop.Value.FirstOrDefault
If Entry Is Nothing Then Continue For
Dim JavaName = Entry("version")("name").ToString '可能的名称格式:"12"、"8u51-cacert462b08"、"17.0.8.1"、"17.0.1.12.1"、"21.0.7"
If JavaName.Contains(".") Then
Dim Parts As String() = JavaName.Split(".")
Results.Add(New JavaDownloadInfo With {.ComponentName = Prop.Name, .Java = Entry, .JavaVersion = New Version(Val(Parts(0)), Val(Parts(1)), If(Parts.Length >= 3, Val(Parts(2)), 0), If(Parts.Length >= 4, Val(Parts(3)), 0))})
ElseIf JavaName.StartsWithF("8u51-") Then
Results.Add(New JavaDownloadInfo With {.ComponentName = Prop.Name, .Java = Entry, .JavaVersion = New Version(8, 0, 51, 0)})
Else
Results.Add(New JavaDownloadInfo With {.ComponentName = Prop.Name, .Java = Entry, .JavaVersion = New Version(Val(JavaName.BeforeFirstOfAny({"u", "."})), 0, 0, 0)})
End If
Catch ex As Exception
Logger.Warn(ex, $"解析 Mojang 提供的 Java 列表项失败,已跳过({Prop.Name})")
End Try
Next
Return Results
End Function)
Return Components.Value
End Function
''' <summary>
''' 构建下载指定 Java 的加载器。
''' </summary>
@@ -463,7 +463,8 @@ NextInner:
End Function
'登录主模块加载器
Public McLoginLoader As New LoaderTask(Of McLoginData, McLoginResult)("登录", AddressOf McLoginStart, AddressOf McLoginInput, ThreadPriority.BelowNormal) With {.ReloadTimeout = 1, .ProgressWeight = 15, .Block = False}
Public McLoginLoader As New LoaderTask(Of McLoginData, McLoginResult)("登录", AddressOf McLoginStart, AddressOf McLoginInput, ThreadPriority.BelowNormal) With
{.ReloadTimeout = 1, .ProgressWeight = 15, .Block = False}
Public Function McLoginInput() As McLoginData
Dim LoginData As McLoginData = Nothing
Dim LoginType = Settings.Get(Of McLoginType)("LoginType")
@@ -1175,6 +1176,7 @@ Retry:
#Region "启动参数"
Private McLaunchArgument As String
Private McLaunchEncoding As Encoding
'主方法
Private Sub McLaunchArgumentMain(Loader As LoaderTask(Of String, Integer))
@@ -1296,8 +1298,8 @@ NextInstance:
'LUA
Dim UseLUA As Boolean =
Not Settings.Get(Of Boolean)("LaunchAdvanceDisableLUA") AndAlso Not Settings.Get(Of Boolean)("VersionAdvanceDisableLUA", McInstanceSelected) AndAlso
McLibListGet(McInstanceSelected, False).Any(Function(e) e.OriginalName = "org.lwjgl:lwjgl:3.4.1")
If UseLUA Then Args.Add($"-javaagent:""{ExtractPatch("LUA")}""")
McLibListGet(McInstanceSelected, False).Select(Function(e) e.OriginalName).Contains("org.lwjgl:lwjgl:3.4.1")
If UseLUA Then Args.Add($"-javaagent:""{LaunchUtils.ExtractPatch("Launch\LwjglUnsafeAgent.jar", PathPure.Value)}""")
McLaunchLog("使用 LUA:" & UseLUA)
#Region "内存管理"
@@ -1361,14 +1363,34 @@ NextInstance:
'Log4j 漏洞防御参数
Args.Add("-Dlog4j2.formatMsgNoLookups=true")
'编码(#4700、#5892、#5909)
If McLaunchJavaSelected.Version.Major > 8 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dstdout.encoding=")) Then Args.Add("-Dstdout.encoding=UTF-8")
If McLaunchJavaSelected.Version.Major > 8 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dstderr.encoding=")) Then Args.Add("-Dstderr.encoding=UTF-8")
If McLaunchJavaSelected.Version.Major >= 18 AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dfile.encoding=")) Then Args.Add("-Dfile.encoding=COMPAT") 'Dfile.encoding 需要放在 Dstdout.encoding 后面(#6934)
'编码(#4700、#5892、#5909、#6934、#8950)
Dim EncodingName As String
Select Case McLaunchJavaSelected.Version.Major
Case Is >= 21 'Java 21+ 会固定使用 UTF-8
EncodingName = "UTF-8"
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
McLaunchEncoding = Encoding.GetEncoding(If(EncodingName.Equals("GBK", StringComparison.OrdinalIgnoreCase), "GB18030", EncodingName))
Catch ex As Exception
Dim FallbackEncoding = Encoding.GetEncoding(Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage) '老版本 Java 的编码选择行为
McLaunchLog($"无法识别 Java 编码 {If(EncodingName, "Nothing")},已回退为 {FallbackEncoding.WebName}", LogLevel.Warn)
McLaunchEncoding = FallbackEncoding
End Try
McLaunchLog($"使用编码:{McLaunchEncoding.WebName}")
Dim LaunchEncodingName = If(McLaunchEncoding.CodePage = 54936, "GBK", McLaunchEncoding.WebName)
Dim StdoutArgName = If(McLaunchJavaSelected.Version.Major < 19, "sun.stdout.encoding", "stdout.encoding") '老版本 Java 应该设置 sun.std
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{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
'为 JLW 添加 -jar,它必须放在最后
If UseJLW Then
Args.Add("-jar") : Args.Add(ExtractPatch("JavaWrapper"))
Args.Add("-jar") : Args.Add(LaunchUtils.ExtractPatch("Launch\JavaWrapper.jar", PathPure.Value))
End If
'再次去重并输出
@@ -1482,7 +1504,7 @@ NextInstance:
Yield ("${natives_directory}", GetNativesFolder().TrimEnd("\"c))
Yield ("${library_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
Yield ("${libraries_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
Yield ("${pure_directory}", PathPure.TrimEnd("\"c)) '由 PCL 添加,这会允许在分割参数并去重后再替换路径,防止路径中的特殊字符影响参数分割和去重
Yield ("${pure_directory}", PathPure.Value.TrimEnd("\"c)) '由 PCL 添加,这会允许在分割参数并去重后再替换路径,防止路径中的特殊字符影响参数分割和去重
Yield ("${launcher_name}", "PCL")
Yield ("${launcher_version}", VersionCode)
Yield ("${version_name}", McInstanceSelected.Name)
@@ -1997,7 +2019,7 @@ IgnoreCustomSkin:
'输出 bat
Try
Dim CmdString As String =
$"{If(McLaunchJavaSelected.Version.Major > 8, "chcp 65001>nul" & vbCrLf, "")}" &
$"chcp {If(McLaunchEncoding.CodePage = 54936 AndAlso IsGBKEncoding, 936, McLaunchEncoding.CodePage)}>nul" & vbCrLf &
"@echo off" & vbCrLf &
$"title 启动 - {McInstanceSelected.Name}" & vbCrLf &
"echo 游戏正在启动,请稍候。" & vbCrLf &
@@ -2010,7 +2032,7 @@ IgnoreCustomSkin:
FileUtils.Write(
filePath:=If(CurrentLaunchOptions.SaveBatch, Paths.Base & "PCL\LatestLaunch.bat"),
text:=FilterAccessToken(CmdString, "F").Replace("%", "%%"),
encoding:=If(McLaunchJavaSelected.Version.Major > 8, Encoding.UTF8, Encoding.Default))
encoding:=McLaunchEncoding)
If CurrentLaunchOptions.SaveBatch IsNot Nothing Then
McLaunchLog("导出启动脚本完成,强制结束启动过程")
CanceledHint = "导出启动脚本成功!"
@@ -2092,6 +2114,8 @@ IgnoreCustomSkin:
'设置其他参数
StartInfo.WorkingDirectory = McInstanceSelected.PathIndie
StartInfo.UseShellExecute = False
StartInfo.StandardOutputEncoding = McLaunchEncoding
StartInfo.StandardErrorEncoding = McLaunchEncoding
StartInfo.RedirectStandardOutput = True
StartInfo.RedirectStandardError = True
StartInfo.CreateNoWindow = True
@@ -484,7 +484,7 @@ VersionSearchFinish:
Return JsonPath
End Function
''' <summary>
''' 该版本的 Json 文本。
''' 该版本的 Json 文本。会抛出异常。
''' </summary>
Public Property JsonText As String
Get
@@ -2073,7 +2073,7 @@ OnLoaded:
'统一通行证文件
If Settings.Get(Of Integer)("VersionServerLogin", Instance:=Instance) = 3 Then
Dim TargetFile As String = PathPure & "nide8auth.jar"
Dim TargetFile As String = PathPure.Value & "nide8auth.jar"
Try
'测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
Logger.Info("开始获取统一通行证下载信息")
@@ -2093,7 +2093,7 @@ OnLoaded:
'Authlib-Injector 文件
If Settings.Get(Of Integer)("VersionServerLogin", Instance:=Instance) = 4 Then
Dim TargetFile = PathPure & "authlib-injector.jar"
Dim TargetFile = PathPure.Value & "authlib-injector.jar"
Try
Logger.Info("开始获取 Authlib-Injector 下载信息")
Dim DownloadInfo As JObject = NetRequestByClientRetry(
@@ -109,29 +109,10 @@ Public Module ModModpack
End Try
End Function
Private Sub ExtractModpackFiles(InstallTemp As String, FileAddress As String, Loader As LoaderBase, ProgressIncrement As Double)
'解压文件
Dim RetryCount As Integer = 1
Dim InitialProgress = Loader.Progress
Retry:
Try
Loader.Progress = InitialProgress
DirectoryUtils.Delete(InstallTemp)
Dim RawProgress As Double = Loader.Progress
FileUtils.ExtractToDirectory(FileAddress, InstallTemp, progressHandler:=Sub(Percentage) Loader.Progress = RawProgress + Percentage * ProgressIncrement)
Catch ex As Exception
Logger.Warn(ex, $"第 {RetryCount} 次解压尝试失败")
'完全不知道为啥会出现文件正在被另一进程使用的问题,总之加个重试
If RetryCount < 5 Then
Thread.Sleep(RetryCount * 2000)
If Loader IsNot Nothing AndAlso Loader.LoadingState <> MyLoading.MyLoadingState.Run Then Return
RetryCount += 1
GoTo Retry
Else
Throw New Exception("解压整合包文件失败", ex)
End If
End Try
Loader.Progress = InitialProgress + ProgressIncrement
Private Sub ExtractModpackFiles(InstallTemp As String, FileAddress As String, Optional c As CancellationToken = Nothing, Optional p As ProgressProvider = Nothing)
DirectoryUtils.Delete(InstallTemp)
c.ThrowIfCancellationRequested()
FileUtils.ExtractToDirectory(FileAddress, InstallTemp, c, p)
End Sub
''' <summary>
''' 从整合包的 override 目录复制文件,同时设置 PCL 的配置文件与版本隔离。
@@ -213,7 +194,6 @@ Retry:
Logger.Info($"整合包 Fabric 版本:{Id}")
TargetVersion.Fabric = Id.Replace("fabric-", "")
Else
'ElseIf Id.StartsWithF("quilt-") Then
NotifyIncompatibleLoader(Id)
End If
Next
@@ -224,7 +204,7 @@ Retry:
If OverrideHome <> "" Then
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
CopyOverrideDirectory(
InstallTemp & ArchiveBaseFolder & If(OverrideHome = "." OrElse OverrideHome = "./", "", OverrideHome), '#5613
$"{McFolderSelected}versions\{InstanceName}", Task)
@@ -296,13 +276,15 @@ Retry:
Dim TargetFolder As String, Type As ResourceTypes
If ModJson("modules").Any Then 'modules 可能返回 null(#1006)
Dim ModuleNames = CType(ModJson("modules"), JArray).Select(Function(l) l("name").ToString).ToList
If ModuleNames.Contains("META-INF") OrElse ModuleNames.Contains("mcmod.info") OrElse
ModJson?("FileName")?.ToString.EndsWithF(".jar", True) Then
If ModuleNames.Contains("META-INF") OrElse ModuleNames.Contains("mcmod.info") OrElse ModuleNames.Contains("fabric.mod.json") OrElse
ModJson?("FileName")?.ToString.EndsWithF(".jar", True) Then
TargetFolder = "mods" : Type = ResourceTypes.Mod
ElseIf ModuleNames.Contains("pack.mcmeta") Then
TargetFolder = "resourcepacks" : Type = ResourceTypes.ResourcePack
Else
ElseIf ModuleNames.Contains("shaders") Then
TargetFolder = "shaderpacks" : Type = ResourceTypes.Shader
Else
TargetFolder = "saves" : Type = ResourceTypes.Map
End If
Else
TargetFolder = "mods" : Type = ResourceTypes.Mod
@@ -348,6 +330,12 @@ Retry:
WriteIni(VersionFolder & "PCL\Setup.ini", "LogoCustom", "True")
Logger.Info($"已设置整合包 Logo:{Logo}")
End If
'解压地图文件
Dim SaveFolder As String = $"{VersionFolder}saves\"
For Each MapFile In DirectoryUtils.EnumerateFiles(SaveFolder, searchPattern:="*.zip")
FileUtils.ExtractToDirectory(MapFile, SaveFolder, Task.CreateCancellationToken())
FileUtils.Delete(MapFile)
Next
'删除原始整合包文件
For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
If FileUtils.Exists(Target) Then
@@ -373,7 +361,6 @@ Retry:
Loader.Start(Request.VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
Return Loader
End Function
@@ -404,7 +391,6 @@ Retry:
TargetVersion.Fabric = Entry.Value.ToString
Logger.Info($"整合包 Fabric 版本:{TargetVersion.Fabric}")
Case Else
'Case "quilt-loader" 'eg. 1.0.0
NotifyIncompatibleLoader(Entry.Name)
End Select
Next
@@ -421,7 +407,7 @@ Retry:
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.5)
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.5))
CopyOverrideDirectory(
InstallTemp & ArchiveBaseFolder & "overrides",
McFolderSelected & "versions\" & InstanceName, Task)
@@ -456,7 +442,7 @@ Retry:
Throw New OperationCanceledException
End If
FileList.Add(New NetFile(Urls, TargetPath,
New FileChecker With {.ActualSize = File("fileSize").ToObject(Of Long), .Hash = File("hashes")("sha1").ToString}, True))
New FileChecker With {.Hash = File("hashes")("sha1").ToString}, True)) 'Modrinth 整合包不应校验文件大小(他们官方自己说的)
Next
If FileList.Any Then
InstallLoaders.Add(New LoaderDownload("下载额外文件", FileList) With {.ProgressWeight = FileList.Count * 1.5}) '每个 Mod 需要 1.5s
@@ -511,7 +497,6 @@ Retry:
Loader.Start(Request.VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
Return Loader
End Function
@@ -535,7 +520,7 @@ Retry:
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
CopyOverrideDirectory(
InstallTemp & ArchiveBaseFolder & "minecraft",
McFolderSelected & "versions\" & InstanceName, Task)
@@ -564,7 +549,6 @@ Retry:
Loader.Start(Request.VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
Return Loader
End Function
@@ -590,7 +574,7 @@ Retry:
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.55)
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.55))
CopyOverrideDirectory(
InstallTemp & ArchiveBaseFolder & ".minecraft",
McFolderSelected & "versions\" & InstanceName, Task)
@@ -662,7 +646,6 @@ Retry:
Request.NeoForgeVersion = Component("version")
Case "net.fabricmc.fabric-loader"
Request.FabricVersion = Component("version")
'Case "org.quiltmc.quilt-loader" 'eg. 1.0.0
Case Else
If UID.StartsWithF("org.lwjgl") Then '#8210
Logger.Info($"已跳过 LWJGL 项:{UID}")
@@ -690,7 +673,6 @@ Retry:
Loader.Start(Request.VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
Return Loader
End Function
@@ -719,7 +701,7 @@ Retry:
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task, 0.6)
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
CopyOverrideDirectory(
InstallTemp & ArchiveBaseFolder & "overrides",
McFolderSelected & "versions\" & InstanceName, Task)
@@ -738,7 +720,7 @@ Retry:
Next
If Not Addons.ContainsKey("game") Then Throw New Exception("该 MCBBS 整合包未提供游戏版本信息,无法安装!")
If Addons.ContainsKey("quilt") Then
Hint("PCL 暂不支持安装需要 Quilt 的整合包!", HintType.Red)
Hint("PCL 不支持安装 Quilt 整合包!", HintType.Red)
Throw New OperationCanceledException
End If
Dim Request As New McInstallRequest With {
@@ -769,7 +751,6 @@ Retry:
Loader.Start(Request.VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.DownloadManager))
Return Loader
End Function
@@ -784,7 +765,7 @@ Retry:
Dim Loader As New LoaderCombo(Of String)("解压压缩包", {
New LoaderTask(Of String, Integer)("解压压缩包",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(TargetFolder, FileAddress, Task, 0.9)
ExtractModpackFiles(TargetFolder, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.9))
OpenExplorer(TargetFolder)
Thread.Sleep(400) '避免文件争用
'查找解压后的 exe 文件
@@ -860,7 +841,7 @@ Retry:
Dim Loader As New LoaderCombo(Of String)("解压压缩包", {
New LoaderTask(Of String, Integer)("解压压缩包",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(TargetFolder, FileAddress, Task, 0.95)
ExtractModpackFiles(TargetFolder, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.95))
'加入文件夹列表
PageSelectLeft.AddFolder(TargetFolder & ArchiveBaseFolder, PathUtils.GetLastPart(TargetFolder), False)
Thread.Sleep(400) '避免文件争用
@@ -8,7 +8,8 @@ Public Module ModWatcher
Dim IsRunning As Boolean = False
Dim TriggerLauncherShutdown As Boolean = True
For Each Watcher In McWatcherList
If Watcher.State = Watcher.MinecraftState.Loading OrElse Watcher.State = Watcher.MinecraftState.Running Then
If Watcher.State = Watcher.MinecraftState.Loading OrElse Watcher.State = Watcher.MinecraftState.Running OrElse
(Watcher.State = Watcher.MinecraftState.Crashed AndAlso Not Watcher.GameProcess.HasExited) Then
IsRunning = True
Exit For
ElseIf Watcher.State = Watcher.MinecraftState.Crashed OrElse Watcher.State = Watcher.MinecraftState.Canceled Then
@@ -91,7 +92,9 @@ Public Module ModWatcher
RunInNewThread(
Sub()
Try
Do Until State = MinecraftState.Ended OrElse State = MinecraftState.Crashed OrElse State = MinecraftState.Canceled OrElse Loader.State = LoadState.Canceled
Do Until State = MinecraftState.Ended OrElse State = MinecraftState.Canceled OrElse
(Loader.State = LoadState.Canceled AndAlso State <> MinecraftState.Crashed) OrElse
(State = MinecraftState.Crashed AndAlso GameProcess.HasExited)
TimerWindow()
TimerLog()
'设置窗口标题
@@ -103,6 +106,7 @@ Public Module ModWatcher
Thread.Sleep(64)
Next
Loop
If State = MinecraftState.Crashed Then WatcherStateChanged()
WatcherLog("Minecraft 日志监控已退出")
Catch ex As Exception
Logger.Error(ex, "Minecraft 日志监控主循环出错")
@@ -314,7 +318,7 @@ Public Module ModWatcher
Dim str As New StringBuilder(512)
GetClassName(hwnd, str, str.Capacity)
Dim ClassName As String = str.ToString
If Not (ClassName = "GLFW30" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Return
If Not (ClassName = "GLFW30" OrElse ClassName = "SDL_app" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Return
'获取窗口标题名
str = New StringBuilder(512)
GetWindowText(hwnd, str, str.Capacity)
+28 -22
View File
@@ -178,6 +178,8 @@ Public Class CustomEvent
Logger.Info($"执行自定义事件:{Type}, {Arg}")
If Arg Is Nothing Then Arg = ""
Dim Args As String() = Arg.Split("|")
Dim Arg0 As String = Arg.BeforeFirst("|")
Dim Arg1 As String = Arg.AfterFirst("|")
Try
Select Case Type
Case EventType.打开网页
@@ -194,16 +196,16 @@ Public Class CustomEvent
Sub()
Try
'确认实际路径
Dim ActualPaths = GetAbsoluteUrls(Args(0), Type)
Dim ActualPaths = GetAbsoluteUrls(Arg0, Type)
Dim Location = ActualPaths(0), WorkingDir = ActualPaths(1)
Logger.Info($"打开类自定义事件实际路径:{Location},工作目录:{WorkingDir}")
'执行
If Type = EventType.打开帮助 Then
PageOtherHelp.EnterHelpPage(Location)
Else
If Not EventSafetyConfirm("即将执行:" & Location & If(Args.Length >= 2, " " & Args(1), "")) Then Return
If Not EventSafetyConfirm("即将执行:" & Location & If(Args.Length >= 2, " " & Arg1, "")) Then Return
Dim Info As New ProcessStartInfo With {
.Arguments = If(Args.Length >= 2, Args(1), ""),
.Arguments = If(Args.Length >= 2, Arg1, ""),
.FileName = Location,
.WorkingDirectory = WorkingDir
}
@@ -215,19 +217,19 @@ Public Class CustomEvent
End Sub)
Case EventType.启动游戏
If Args(0) = "\current" Then
If Arg0 = "\current" Then
If McInstanceSelected Is Nothing Then
Hint("请先选择一个 Minecraft 版本!", HintType.Red)
Return
Else
Args(0) = McInstanceSelected.Name
Arg0 = McInstanceSelected.Name
End If
End If
RunInUi(
Sub()
If McLaunchStart(New McLaunchOptions With
{.ServerIp = If(Args.Length >= 2, Args(1), Nothing), .Instance = New McInstance(Args(0))}) Then
Hint($"正在启动 {Args(0)}……")
{.ServerIp = If(Args.Length >= 2, Args(1), Nothing), .Instance = New McInstance(Arg0)}) Then
Hint($"正在启动 {Arg0}……")
End If
End Sub)
@@ -264,51 +266,55 @@ Public Class CustomEvent
Case EventType.弹出窗口
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 弹窗标题|弹窗内容")
MyMsgBox(Args(1).Replace("\n", vbCrLf), Args(0).Replace("\n", vbCrLf), If(Args.Length > 2, Args(2), "确定"))
MyMsgBox(Arg1.BeforeLast("|").Replace("\n", vbCrLf), Arg0.Replace("\n", vbCrLf), If(Args.Length > 2, Arg1.AfterLast("|"), "确定"))
Case EventType.弹出提示
Hint(Args(0).Replace("\n", vbCrLf), If(Args.Length = 1, HintType.Blue, EnumUtils.FromString(Of HintType)(Args(1))))
Hint(Arg0.Replace("\n", vbCrLf), If(Args.Length = 1, HintType.Blue, EnumUtils.FromString(Of HintType)(Arg1)))
Case EventType.切换页面
RunInUi(Sub() FrmMain.PageChange(
EnumUtils.FromString(Of FormMain.PageType)(Args(0)),
If(Args.Length = 1, FormMain.PageSubType.Default, EnumUtils.FromString(Of FormMain.PageSubType)(Args(1)))))
EnumUtils.FromString(Of FormMain.PageType)(Arg0),
If(Args.Length = 1, FormMain.PageSubType.Default, EnumUtils.FromString(Of FormMain.PageSubType)(Arg1))))
Case EventType.导入整合包, EventType.安装整合包
RunInUi(Sub() ModpackInstall())
Case EventType.下载文件
Args(0) = Args(0).Replace("\", "/")
If Not (Args(0).StartsWithF("http://", True) OrElse Args(0).StartsWithF("https://", True)) Then
Arg0 = Arg0.Replace("\", "/")
If Not (Arg0.StartsWithF("http://", True) OrElse Arg0.StartsWithF("https://", True)) Then
MyMsgBox("EventData 必须为以 http:// 或 https:// 开头的网址。" & vbCrLf & "PCL 不支持其他乱七八糟的下载协议。", "事件执行失败")
Return
End If
If Not EventSafetyConfirm("即将从该网址下载文件:" & vbCrLf & Args(0)) Then Return
If Not EventSafetyConfirm("即将从该网址下载文件:" & vbCrLf & Arg0) Then Return
RunInUi(
Sub()
Try
Select Case Args.Length
Case 1
PageOtherTest.StartCustomDownload(Args(0), PathUtils.GetLastPart(Args(0)))
PageOtherTest.StartCustomDownload(Arg0, PathUtils.GetLastPart(Arg0))
Case 2
PageOtherTest.StartCustomDownload(Args(0), Args(1))
PageOtherTest.StartCustomDownload(Arg0, Arg1)
Case Else
PageOtherTest.StartCustomDownload(Args(0), Args(1), Args(2))
PageOtherTest.StartCustomDownload(Arg0, Arg(1), Args(2))
End Select
Catch
PageOtherTest.StartCustomDownload(Args(0), "未知")
PageOtherTest.StartCustomDownload(Arg0, "未知")
End Try
End Sub)
Case EventType.修改设置, EventType.写入设置
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 UiLauncherTransparent|400")
Settings.SetSafe(Args(0), Args(1), Instance:=McInstanceSelected)
If Args.Length = 2 Then Hint($"已写入设置:{Args(0)} → {Args(1)}", HintType.Green)
Settings.SetSafe(Arg0, Arg1, Instance:=McInstanceSelected)
If Args.Length = 2 Then Hint($"已写入设置:{Arg0} → {Arg1}", HintType.Green)
Case EventType.修改变量, EventType.写入变量
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 VariableName|SomeValue")
WriteReg("CustomEvent" & Args(0), Args(1))
If Args.Length = 2 Then Hint($"已写入变量:{Args(0)} → {Args(1)}", HintType.Green)
Try
RegistryUtils.Write($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{Arg0}", Arg1)
If Args.Length = 2 Then Hint($"已写入变量:{Arg0} → {Arg1}", HintType.Green)
Catch ex As Exception
Logger.Warn(ex, $"写入变量失败:{Arg0} → {Arg1}", LogBehavior.Toast)
End Try
Case EventType.加入房间
RunInUi(
+17 -19
View File
@@ -799,26 +799,16 @@ NextFile:
''' 如果失败,则抛出异常。
''' </summary>
Public Sub SetGPUPreference(Executeable As String)
Const REG_KEY As String = "Software\Microsoft\DirectX\UserGpuPreferences"
Const REG_KEY As String = "HKEY_CURRENT_USER\Software\Microsoft\DirectX\UserGpuPreferences"
Const REG_VALUE As String = "GpuPreference=2;"
'查看现有设置
Using ReadOnlyKey = My.Computer.Registry.CurrentUser.OpenSubKey(REG_KEY, False)
If ReadOnlyKey IsNot Nothing Then
If REG_VALUE = ReadOnlyKey.GetValue(Executeable)?.ToString() Then
Logger.Info($"无需调整显卡设置:{Executeable}")
Return
End If
Else
'创建父级键
Logger.Info($"需要创建显卡设置的父级键")
My.Computer.Registry.CurrentUser.CreateSubKey(REG_KEY)
End If
End Using
If RegistryUtils.Read(REG_KEY, Executeable).result?.ToString() = REG_VALUE Then
Logger.Info($"无需调整显卡设置:{Executeable}")
Return
End If
'写入新设置
Using WriteKey = My.Computer.Registry.CurrentUser.OpenSubKey(REG_KEY, True)
WriteKey.SetValue(Executeable, REG_VALUE)
Logger.Info($"已调整显卡设置:{Executeable}")
End Using
RegistryUtils.Write(REG_KEY, Executeable, REG_VALUE)
Logger.Info($"已调整显卡设置:{Executeable}")
End Sub
''' <summary>
@@ -867,11 +857,19 @@ NextFile:
Else
Text = Text.Replace("{version}", Replacer(McInstanceSelected.Version.VanillaName))
End If
Text = Text.Replace("{forge}", Replacer(If(McInstanceSelected.Version.HasForge, McInstanceSelected.Version.Forge, "")))
Text = Text.Replace("{fabric}", Replacer(If(McInstanceSelected.Version.HasFabric, McInstanceSelected.Version.Fabric, "")))
Text = Text.Replace("{neoforge}", Replacer(If(McInstanceSelected.Version.HasNeoForge, McInstanceSelected.Version.NeoForge, "")))
Text = Text.Replace("{liteloader}", Replacer(If(McInstanceSelected.Version.HasLiteLoader, "true", "")))
Else
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("{name}", Replacer(Nothing))
Text = Text.Replace("{version}", Replacer(Nothing))
Text = Text.Replace("{forge}", Replacer(Nothing))
Text = Text.Replace("{fabric}", Replacer(Nothing))
Text = Text.Replace("{neoforge}", Replacer(Nothing))
Text = Text.Replace("{liteloader}", Replacer(Nothing))
End If
'登录信息
If McLoginLoader.State = LoadState.Finished Then
@@ -896,8 +894,8 @@ NextFile:
Text = Text.RegexReplace("\{hint\}", Function() Replacer(PageOtherTest.GetRandomHint()))
Text = Text.RegexReplace("\{cave\}", Function() Replacer(PageOtherTest.GetRandomCave()))
Text = Text.RegexReplace("\{setup:([a-zA-Z0-9]+)\}", Function(m) Replacer(Settings.GetSafe(m.Groups(1).Value, McInstanceSelected)))
Text = Text.RegexReplace("\{varible:([^:\}]+)(?::([^\}]+))?\}", Function(m) Replacer(ReadReg("CustomEvent" & m.Groups(1).Value, m.Groups(2).Value)))
Text = Text.RegexReplace("\{variable:([^:\}]+)(?::([^\}]+))?\}", Function(m) Replacer(ReadReg("CustomEvent" & m.Groups(1).Value, m.Groups(2).Value)))
Text = Text.RegexReplace("\{varible:([^:\}]+)(?::([^\}]+))?\}", Function(m) Replacer(RegistryUtils.TryRead($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{m.Groups(1).Value}", m.Groups(2).Value)))
Text = Text.RegexReplace("\{variable:([^:\}]+)(?::([^\}]+))?\}", Function(m) Replacer(RegistryUtils.TryRead($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{m.Groups(1).Value}", m.Groups(2).Value)))
Return Text
End Function
@@ -502,7 +502,6 @@ Public Class ResourceProject
'获取 Mod 加载器描述
Dim ModLoaderDescriptionFull As String, ModLoaderDescriptionPart As String
Dim ModLoadersForDesc = ModLoaders.Flags().ToList()
If Settings.Get(Of Boolean)("ToolDownloadIgnoreQuilt") Then ModLoadersForDesc.Remove(ModLoaders.Quilt)
Select Case ModLoadersForDesc.Count
Case 0
If ModLoadersForDesc.IsSingle Then
@@ -519,8 +518,7 @@ Public Class ResourceProject
Dim NewestDrop As Integer = If(Drops.Any, Drops.First, 9999)
If ModLoadersForDesc.Contains(ModLoaders.Forge) AndAlso
(NewestDrop < 140 OrElse ModLoadersForDesc.Contains(ModLoaders.Fabric)) AndAlso
(NewestDrop < 200 OrElse ModLoadersForDesc.Contains(ModLoaders.NeoForge)) AndAlso
(NewestDrop < 140 OrElse ModLoadersForDesc.Contains(ModLoaders.Quilt) OrElse Settings.Get(Of Boolean)("ToolDownloadIgnoreQuilt")) Then
(NewestDrop < 200 OrElse ModLoadersForDesc.Contains(ModLoaders.NeoForge)) Then
ModLoaderDescriptionFull = "任意"
ModLoaderDescriptionPart = ""
Else
@@ -179,11 +179,6 @@ Public Class ResourceSearcher
End If
End If
'拒绝 1.13- Quilt(这个版本根本没有 Quilt)
If Request.ModLoaders = ModLoaders.Quilt AndAlso CompareVersion(If(Request.GameVersion, "1.15"), "1.14") = -1 Then
Throw New Exception("Quilt 不支持 Minecraft " & Request.GameVersion)
End If
#End Region
#Region "中文搜索"
@@ -348,7 +348,7 @@ Public Class ResourceVersion
.Height = 42
.Type = MyListItem.CheckType.Clickable
.Tag = Me
.Title = If(IsBadDisplay, FileName, Display)
.Title = If(IsBadDisplay, FileName, Display).BeforeLastOfAny({".zip", ".jar", ".mrpack", ".litemod"}, True)
.Logo = $"{PathImage}ReleaseTypes/{ReleaseType}.png"
AddHandler .Click, ClickHandler
'描述
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
' 方法是按如下所示使用“*”
<Assembly: AssemblyVersion("2.13.0.1")>
<Assembly: AssemblyFileVersion("2.13.0.1")>
<Assembly: AssemblyVersion("2.13.1.0")>
<Assembly: AssemblyFileVersion("2.13.1.0")>
<Assembly: NeutralResourcesLanguage("")>
+5 -25
View File
@@ -139,47 +139,27 @@ Namespace My.Resources
Return CType(obj,Byte())
End Get
End Property
'''<summary>
''' 查找 System.Byte[] 类型的本地化资源。
'''</summary>
Friend ReadOnly Property JavaWrapper() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("JavaWrapper", resourceCulture)
Return CType(obj,Byte())
End Get
End Property
'''<summary>
''' 查找 System.Byte[] 类型的本地化资源。
'''</summary>
Friend ReadOnly Property libwebp64() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("libwebp64", resourceCulture)
Return CType(obj,Byte())
Return CType(obj, Byte())
End Get
End Property
'''<summary>
''' 查找 System.Byte[] 类型的本地化资源。
'''</summary>
Friend ReadOnly Property LUA() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("LUA", resourceCulture)
Return CType(obj,Byte())
End Get
End Property
'''<summary>
''' 查找 System.Byte[] 类型的本地化资源。
'''</summary>
Friend ReadOnly Property MeloongCore() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("MeloongCore", resourceCulture)
Return CType(obj,Byte())
Return CType(obj, Byte())
End Get
End Property
'''<summary>
''' 查找 System.Byte[] 类型的本地化资源。
'''</summary>
@@ -142,21 +142,18 @@
<data name="Imazen.WebP" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Imazen.WebP.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="JavaWrapper" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\java-wrapper.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="libwebp64" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\libwebp64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="LUA" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\lwjgl-unsafe-agent.jar;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="MeloongCore" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\PCLCS\bin\MeloongCore.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="MeloongCore.Wpf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\PCLCS\bin\MeloongCore.Wpf.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="Microsoft.Win32.Registry" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\PCLCS\bin\Microsoft.Win32.Registry.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="NAudio" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\NAudio.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
@@ -368,7 +368,7 @@ pause"
'添加 Java Wrapper 作为主 Jar
Dim Arguments As String
If UseJavaWrapper AndAlso Not Settings.Get(Of Boolean)("LaunchAdvanceDisableJLW") Then
Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.TrimEnd("\")}"" -Duser.home=""{BaseMcFolderHome.TrimEnd("\")}"" -cp ""{Target}"" -jar ""{ExtractPatch("JavaWrapper")}"" optifine.Installer"
Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.Value.TrimEnd("\")}"" -Duser.home=""{BaseMcFolderHome.TrimEnd("\")}"" -cp ""{Target}"" -jar ""{LaunchUtils.ExtractPatch("Launch\JavaWrapper.jar", PathPure.Value)}"" optifine.Installer"
Else
Arguments = $"-Duser.home=""{BaseMcFolderHome.TrimEnd("\")}"" -cp ""{Target}"" optifine.Installer"
End If
@@ -939,7 +939,7 @@ Retry:
'添加 Java Wrapper 作为主 Jar
Dim Arguments As String
If UseJavaWrapper AndAlso Not Settings.Get(Of Boolean)("LaunchAdvanceDisableJLW") Then
Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.TrimEnd("\")}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{ExtractPatch("JavaWrapper")}"" com.bangbang93.ForgeInstaller ""{McFolder}"
Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.Value.TrimEnd("\")}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{LaunchUtils.ExtractPatch("Launch\JavaWrapper.jar", PathPure.Value)}"" com.bangbang93.ForgeInstaller ""{McFolder}"
Else
Arguments = $"-cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" com.bangbang93.ForgeInstaller ""{McFolder}"
End If
@@ -2160,39 +2160,4 @@ Retry:
''' </summary>
Private VanillaSyncLock As New Object
''' <summary>
''' 释放补丁文件并返回完整文件路径。
''' </summary>
''' <param name="Patch">"LUA" 或 "JavaWrapper"。</param>
Public Function ExtractPatch(Patch As String) As String
Dim PatchPath As String = $"{PathPure}{Patch}.jar"
Logger.Info($"选定的 {Patch} 路径:{PatchPath}")
Static Lock As New Object
SyncLock Lock '避免 OptiFine 和 Forge 安装时同时释放导致冲突
Try
ExtractResources(PatchPath, Patch)
Catch ex As Exception
If FileUtils.Exists(PatchPath) Then
'因为未知原因可能变为只读文件(#4243)
Logger.Warn(ex, $"{Patch} 文件释放失败,但文件已存在,将在删除后尝试重新生成")
Try
FileUtils.Delete(PatchPath)
ExtractResources(PatchPath, Patch)
Catch ex2 As Exception
Logger.Warn(ex2, $"{Patch} 文件重新释放失败,将尝试更换文件名重新生成")
PatchPath = $"{PathPure}{Patch}2.jar"
Try
ExtractResources(PatchPath, Patch)
Catch ex3 As Exception
Throw New FileNotFoundException($"释放 {Patch} 最终尝试失败", ex3)
End Try
End Try
Else
Throw New FileNotFoundException($"释放 {Patch} 失败", ex)
End If
End Try
End SyncLock
Return PatchPath
End Function
End Module
@@ -1120,7 +1120,7 @@ Public Class PageDownloadInstall
#Region "安装"
Private Sub TextSelectName_KeyDown(sender As Object, e As KeyEventArgs) Handles TextSelectName.KeyDown
If e.Key = Key.Enter AndAlso BtnStart.IsEnabled Then BtnStart_Click()
If e.Key = Key.Enter AndAlso IsInSelectPage AndAlso BtnStart.IsEnabled Then BtnStart_Click()
End Sub
Private Sub BtnStart_Click() Handles BtnStart.Click
'确认版本隔离
@@ -175,10 +175,7 @@ GroupDone:
If Project.ModLoaders.Flags.Count > 1 AndAlso '工程至少有两个加载器
Version.ResourceType = ResourceTypes.Mod AndAlso '是 Mod
McVersion.IsFormatFit(VerName) Then '不是 “快照版本” 之类的
For Each Loader In Version.ModLoaders.Flags
If Loader = ModLoaders.Quilt AndAlso Settings.Get(Of Boolean)("ToolDownloadIgnoreQuilt") Then Continue For
Loaders.Add(Loader.ToString & " ")
Next
Loaders.AddRange(Version.ModLoaders.Flags.Select(Function(f) f.ToString & " "))
End If
If Not Loaders.Any() Then Loaders.Add("") '保底加一个空的,确保它在一张卡片里
'实际添加
@@ -329,7 +326,7 @@ GroupDone:
Loader.Start(McFolderSelected & "versions\" & InstanceName & "\")
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
FrmMain.BtnExtraDownload.Ribble()
FrmMain.PageChange(FormMain.PageType.TaskManager)
Catch ex As Exception
Logger.Error(ex, "下载资源整合包失败")
@@ -34,6 +34,7 @@
<TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
<local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" IsTextSearchEnabled="False">
<local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
<local:MyComboBoxItem Content="26.2" />
<local:MyComboBoxItem Content="26.1" />
<local:MyComboBoxItem Content="1.21.11" />
<local:MyComboBoxItem Content="1.21.8" />
@@ -51,7 +52,6 @@
<local:MyComboBoxItem Content="Forge" Tag="1" />
<local:MyComboBoxItem Content="NeoForge" Tag="16" />
<local:MyComboBoxItem Content="Fabric" Tag="4" />
<local:MyComboBoxItem Content="Quilt" Tag="8" />
<local:MyComboBoxItem Content="LiteLoader" Tag="2" />
</local:MyComboBox>
<TextBlock VerticalAlignment="Center" Grid.Column="4" Grid.Row="2" HorizontalAlignment="Left" Text="类型" Margin="0,0,18,0" />
@@ -181,6 +181,18 @@
RequireModLoaderOrOptiFine="True" />
</local:MyCheckBox.Tag>
</local:MyCheckBox>
<StackPanel Margin="30,0,0,0"
Visibility="{Binding Checked, ElementName=CheckOptionsShaderPacks, Converter={StaticResource BooleanToVisibilityConverter}}">
<local:MyCheckBox x:Name="CheckOptionsShaderPackSettings">
<local:MyCheckBox.Tag>
<local:ExportOption
Title="光影包设置"
Description="已选光影包的自定义设置"
ShowRules="shaderpacks/*.txt"
DefaultChecked="True" />
</local:MyCheckBox.Tag>
</local:MyCheckBox>
</StackPanel>
<StackPanel Margin="30,0,0,0" x:Name="PanOptionsShaderPacks"
Visibility="{Binding Checked, ElementName=CheckOptionsShaderPacks, Converter={StaticResource BooleanToVisibilityConverter}}">
</StackPanel>
@@ -299,4 +311,4 @@
x:Name="BtnExport" Text="开始导出"
LogoScale="1.1" 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" />
</Grid>
</local:MyPageRight>
</local:MyPageRight>
@@ -76,6 +76,7 @@ Public Class PageInstanceExport
If Not SubFolder.EnumerateFileSystemInfos().Any() Then Continue For
Dim NewCheckBox As New MyCheckBox With {. _
Tag = New ExportOption With {.Title = SubFolder.Name, .DefaultChecked = True, .Rules = StringUtils.LikePatternEscape($"{Folder}/{SubFolder.Name}/")}}
If AcceptCompressedFile Then GetExportOption(NewCheckBox).Description = "文件夹"
If Panel Is PanOptionsSaves Then GetExportOption(NewCheckBox).Description = SubFolder.LastWriteTime.ToString("yyyy'/'MM'/'dd HH':'mm")
Panel.Children.Add(NewCheckBox)
Next
@@ -249,9 +250,22 @@ Public Class PageInstanceExport
For Each CheckBox In GetAllOptions(False)
If Not CheckBox.Checked Then Continue For
Dim TargetOption = GetExportOption(CheckBox)
If TargetOption.Rules Is Nothing Then Continue For
Dim Rules = If(TargetOption.Rules?.Split("|"c).ToList(), New List(Of String))
'动态 Rules
If CheckBox Is CheckOptionsShaderPackSettings Then '光影包设置:只导出勾选的光影包的设置
For Each ShaderPackCheckBox In PanOptionsShaderPacks.Children.OfType(Of MyCheckBox)()
If Not ShaderPackCheckBox.Checked Then Continue For
Dim ShaderPackOption = GetExportOption(ShaderPackCheckBox)
Dim SettingFileName = ShaderPackOption.Rules.TrimEnd("/") & ".txt"
If Not FileUtils.Exists(Path.Combine(PageInstanceLeft.Instance.PathIndie, SettingFileName)) Then Continue For
Rules.Add(StringUtils.LikePatternEscape($"shaderpacks/{SettingFileName}"))
Next
End If
If Not Rules.Any() Then Continue For
Yield $"# {TargetOption.Title}"
For Each Rule In TargetOption.Rules.Split("|"c)
For Each Rule In Rules
Yield Rule
Next
Yield ""
@@ -412,7 +426,7 @@ Public Class PageInstanceExport
Dim LoaderName As String = $"导出整合包:" & PackName
For Each OngoingLoader In LoaderTaskbar
If OngoingLoader.Name <> LoaderName Then Continue For
FrmMain.PageChange(FormMain.PageType.DownloadManager)
FrmMain.PageChange(FormMain.PageType.TaskManager)
Return
Next
@@ -608,7 +622,7 @@ Public Class PageInstanceExport
Try
If ModrinthUploadMode Then Return 'Modrinth 上传模式下,不从 CurseForge 获取信息
Dim CurseForgeHashes = Loader.Input.Select(Function(m) m.CurseForgeHash)
Dim CurseForgeRaw As JContainer = DlModRequest("https://api.curseforge.com/v1/fingerprints/432/", HttpMethod.Post,
Dim CurseForgeRaw As JContainer = DlModRequest("https://api.curseforge.com/v1/fingerprints/432", HttpMethod.Post,
$"{{""fingerprints"": [{CurseForgeHashes.Join(",")}]}}", "application/json")("data")("exactMatches")
For Each ResultJson As JObject In CurseForgeRaw
If Not ResultJson.ContainsKey("file") Then Continue For
@@ -712,7 +726,7 @@ Public Class PageInstanceExport
LoaderTaskbarAdd(MainLoader)
FrmMain.BtnExtraDownload.ShowRefresh()
FrmMain.BtnExtraDownload.Ribble()
FrmMain.PageChange(FormMain.PageType.DownloadManager)
FrmMain.PageChange(FormMain.PageType.TaskManager)
End Sub
#End Region
@@ -309,7 +309,10 @@ Install:
For Each ModFile In FilePathList
Dim NewFileName = PathUtils.GetLastPart(ModFile).Replace(".disabled", "").Replace(".old", "")
If Not NewFileName.Contains(".") Then NewFileName += ".jar" '#4227
FileUtils.Copy(ModFile, Instance.PathIndie & "mods\" & NewFileName)
NewFileName = Instance.PathIndie & "mods\" & NewFileName
If ModFile = NewFileName Then Continue For '防止安装相同文件导致文件被删除
FileUtils.Delete(NewFileName, True)
FileUtils.Copy(ModFile, NewFileName)
Next
If FilePathList.IsSingle Then
Hint($"已安装 {PathUtils.GetLastPart(FilePathList.First).Replace(".disabled", "").Replace(".old", "")}!", HintType.Green)
@@ -62,18 +62,12 @@
</StackPanel>
</local:MyCard>
<local:MyCard Margin="0,0,0,15" Title="快捷方式" x:Name="PanFolder">
<StackPanel Margin="25,40,25,15">
<Grid Margin="0,2,0,7" Height="35">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
</Grid.ColumnDefinitions>
<local:MyButton x:Name="BtnFolderVersion" Text="版本文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
<local:MyButton x:Name="BtnFolderSaves" Text="存档文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="1" />
<local:MyButton x:Name="BtnFolderMods" Text="Mod 文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" Grid.Column="2" />
</Grid>
</StackPanel>
<WrapPanel Margin="25,30,25,20">
<local:MyButton x:Name="BtnFolderVersion" Text="版本文件夹" MinWidth="140" Padding="13,0" Margin="0,13,20,0" Height="35" />
<local:MyButton x:Name="BtnFolderSaves" Text="存档文件夹" MinWidth="140" Padding="13,0" Margin="0,13,20,0" Height="35"/>
<local:MyButton x:Name="BtnFolderMods" Text="Mod 文件夹" MinWidth="140" Padding="13,0" Margin="0,13,20,0" Height="35"/>
<local:MyButton x:Name="BtnFolderScreen" Text="截图文件夹" MinWidth="140" Padding="13,0" Margin="0,13,20,0" Height="35" />
</WrapPanel>
</local:MyCard>
<local:MyCard Margin="0,0,0,15" Title="高级管理" x:Name="PanManage">
<StackPanel Margin="25,40,25,15">
@@ -109,7 +109,8 @@ Public Class PageInstanceOverall
Dim OldPath As String = PageInstanceLeft.Instance.PathVersion
'修改此部分的同时修改快速安装的版本名检测*
Dim NewName As String = MyMsgBoxInput("重命名版本", "", OldName, New ObjectModel.Collection(Of Validate) From {
New ValidateFolderName(McFolderSelected & "versions", IgnoreCase:=False)})
New ValidateFolderName(McFolderSelected & "versions", IgnoreList:=New List(Of String) From {OldName})
})
If String.IsNullOrWhiteSpace(NewName) Then Return
Dim NewPath As String = McFolderSelected & "versions\" & NewName & "\"
'重新读取版本 JSON 信息,避免 JsonObject 中已被合并的项被重新存储
@@ -157,7 +158,7 @@ Public Class PageInstanceOverall
End Sub
'版本图标
Private Sub ComboDisplayLogo_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ComboDisplayLogo.SelectionChanged
Private Sub ComboDisplayLogo_SelectionChanged() Handles ItemDisplayLogoCustom.PreviewMouseLeftButtonUp, ComboDisplayLogo.SelectionChanged
If Not (IsLoad AndAlso AniControlEnabled = 0) Then Return
'选择 自定义 时修改图片
Try
@@ -228,6 +229,13 @@ Public Class PageInstanceOverall
OpenExplorer(Folder)
End Sub
'截图文件夹
Private Sub BtnFolderScreen_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnFolderScreen.Click
Dim Folder As String = PageInstanceLeft.Instance.PathIndie & "screenshots\"
DirectoryUtils.Create(Folder)
OpenExplorer(Folder)
End Sub
#End Region
#Region "卡片:管理"
@@ -298,8 +306,11 @@ Public Class PageInstanceOverall
Try
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
Dim IsHintIndie As Boolean = PageInstanceLeft.Instance.State <> McInstanceState.Error AndAlso PageInstanceLeft.Instance.PathIndie <> McFolderSelected
Dim SavesFolder = DirectoryUtils.GetInfo(PageInstanceLeft.Instance.PathIndie & "saves\")
Dim SaveEntries = If(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} 吗?" &
If(IsHintIndie, vbCrLf & "由于该版本开启了版本隔离,删除版本时该版本对应的存档、资源包、Mod 等文件也将被一并删除!", ""),
If(IsHintIndie, vbCrLf & "该版本对应的存档、资源包、Mod 等文件也将被一并删除!" &
If(SaveEntries.Any, vbCrLf & vbCrLf & "这会删除以下存档:" & vbCrLf & "· " & SaveEntries.Join(vbCrLf & "· "), ""), ""),
"版本删除确认", , "取消",, IsHintIndie OrElse IsShiftPressed)
Case 1
PageInstanceLeft.Instance.ResetSettingsCache()
@@ -83,7 +83,7 @@ Public Class PageInstanceSetup
Settings.Reset("VersionServerLogin", Instance:=PageInstanceLeft.Instance)
Settings.Reset("VersionArgumentIndieV2", Instance:=PageInstanceLeft.Instance)
Settings.Reset("VersionAdvanceAssets", Instance:=PageInstanceLeft.Instance)
Configs.InstanceForcedJava.Reset(PageInstanceLeft.Instance.Config)
Configs.JavaForced.Reset(PageInstanceLeft.Instance.Config)
JavaListRefreshWorker.Start()
Logger.Info("已初始化版本独立设置")
@@ -474,7 +474,7 @@ PreFin:
'========================================== 显示结果 ==========================================
BtnArgumentJavaSearch.IsEnabled = True
ComboArgumentJavaSelect.IsEnabled = True
Dim SelectedJava As Java = Configs.InstanceForcedJava.Get(PageInstanceLeft.Instance.Config)
Dim SelectedJava As Java = Configs.JavaForced.Get(PageInstanceLeft.Instance.Config)
'更新下拉框文本
If Not Configs.JavaList.Get().Any() Then
LabArgumentJava.Text = "未找到 Java,点击以导入已有的 Java"
@@ -492,7 +492,7 @@ PreFin:
AddHandler JavaItem.MouseLeftButtonUp, Sub(sender As Object, e As MouseButtonEventArgs) e.Handled = True
AddHandler JavaItem.Click,
Sub()
Configs.InstanceForcedJava.Set(JavaEntry, PageInstanceLeft.Instance.Config)
Configs.JavaForced.Set(JavaEntry, PageInstanceLeft.Instance.Config)
UpdateJavaList()
ComboArgumentJavaSelect.IsDropDownOpen = False
End Sub
@@ -108,6 +108,12 @@ Public Class PageLaunchRight
Case 17
Logger.Info("Bangumi 番剧主页")
Url = "https://bangumi.p.kaphia.qzz.io"
Case 18
Logger.Info("Bilibili 热门")
Url = "https://bilibili.p.kaphia.qzz.io"
Case 19
Logger.Info("Music 云音乐热门")
Url = "https://cloudmusic.p.kaphia.qzz.io"
End Select
End Select
'联网下载
@@ -21,7 +21,7 @@
<TextBlock Name="TextEmail" Text="加载中" Margin="8,4,8,0" FontSize="12" HorizontalAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="{DynamicResource ColorBrushGray3}" />
</StackPanel>
<local:MyIconButton ToolTip="更换角色" Grid.Row="1" Height="14" Opacity="0" x:Name="BtnEdit" ToolTipService.InitialShowDelay="50" Grid.Column="0" HorizontalAlignment="Center" Logo="F1 M 53.2929,21.2929L 54.7071,22.7071C 56.4645,24.4645 56.4645,27.3137 54.7071,29.0711L 52.2323,31.5459L 44.4541,23.7677L 46.9289,21.2929C 48.6863,19.5355 51.5355,19.5355 53.2929,21.2929 Z M 31.7262,52.052L 23.948,44.2738L 43.0399,25.182L 50.818,32.9601L 31.7262,52.052 Z M 23.2409,47.1023L 28.8977,52.7591L 21.0463,54.9537L 23.2409,47.1023 Z" Margin="8,0,0,0" VerticalAlignment="Center" />
<local:MyIconButton ToolTip="退出登录" Grid.Row="1" Height="14" Opacity="0" x:Name="BtnExit" ToolTipService.InitialShowDelay="50" Grid.Column="2" HorizontalAlignment="Center" Logo="F1 M 51.0071,19.0027L 51.0071,27.0038L 48.0067,27.0038L 48.0067,22.0031L 25.0035,22.0031L 25.0035,54.0075L 48.0067,54.0075L 48.0067,49.0068L 51.0071,49.0068L 51.0071,57.008L 22.1698,57.008L 22.0031,19.0027L 51.0071,19.0027 Z M 30.0042,35.0049L 45.2563,35.0049L 37.005,28.0039L 47.0066,28.0039L 58.5082,38.0053L 47.0066,48.0067L 37.005,48.0067L 45.2563,41.0057L 30.0042,41.0057L 30.0042,35.0049 Z" Margin="0,0,8,0" VerticalAlignment="Center" />
<local:MyIconButton ToolTip="切换账号" Grid.Row="1" Height="14" Opacity="0" x:Name="BtnExit" ToolTipService.InitialShowDelay="50" Grid.Column="2" HorizontalAlignment="Center" Logo="M512 0A512 512 0 1 0 1024 512 512 512 0 0 0 512 0z m0 941.407086A429.407086 429.407086 0 1 1 941.407086 512 429.407086 429.407086 0 0 1 512 941.407086z m235.139657-368.64H264.045714a43.505371 43.505371 0 0 0-31.246628 72.060343l159.305143 166.765714a41.281829 41.281829 0 1 0 59.626057-56.788114l-94.997943-99.474286H747.227429a41.311086 41.311086 0 1 0 0-82.622172zM262.670629 450.940343H745.764571a43.505371 43.505371 0 0 0 31.246629-72.352914l-159.305143-166.765715a41.281829 41.281829 0 1 0-59.713828 57.022172l94.968685 99.474285H262.670629a41.281829 41.281829 0 0 0 0 82.563658z" Margin="0,0,8,0" VerticalAlignment="Center" />
</Grid>
<local:MySkin HorizontalAlignment="Center" VerticalAlignment="Top" x:Name="Skin" HasCape="False" />
</Grid>
@@ -18,7 +18,7 @@ Public Class PageLoginMs
ComboAccounts.Items.Add(Item)
Next
Catch ex As Exception
Logger.Error(ex, $"微软登录信息出错,登录信息已被重置({Settings.Get(Of String)("LoginMsJson")})", LogBehavior.Toast)
Logger.Error(ex, $"微软登录信息出错,登录信息已被重置", LogBehavior.Toast)
Settings.Set("LoginMsJson", "{}")
End Try
'如果不保留输入,刷新列表后自动选择第一项
@@ -28,6 +28,8 @@
<Separator />
<local:MyMenuItem Click="BtnSkinCape_Click" Header="修改披风"/>
<local:MyMenuItem Click="BtnSkinCapeRefresh_Click" Header="刷新披风列表"/>
<local:MyMenuItem Header="使用 CDKEY 兑换奖励"
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.minecraft.net/zh-hans/redeem" />
</ContextMenu>
</local:MyIconButton.ContextMenu>
</local:MyIconButton>
@@ -36,8 +38,10 @@
LogoScale="1.1" Logo="M462.336 924.891429L73.142857 950.857143l25.965714-389.193143 467.017143-467.017143a73.398857 73.398857 0 0 1 103.789715 0l259.437714 259.437714a73.398857 73.398857 0 0 1 0 103.789715l-467.017143 467.017143z m155.684571-778.349715L202.861714 561.664l259.474286 259.474286L877.458286 405.942857 618.057143 146.541714zM151.003429 873.033143l233.508571-25.965714-207.579429-207.579429-25.965714 233.545143z m544.841142-492.982857l51.894858 51.894857-233.508572 233.508571-51.931428-51.894857 233.545142-233.508571z">
<local:MyIconButton.ContextMenu>
<ContextMenu Closed="HidePanel" HorizontalOffset="10" VerticalOffset="18">
<local:MyMenuItem Header="修改密码" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://account.live.com/password/Change" />
<local:MyMenuItem Header="修改玩家名" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.minecraft.net/zh-hans/msaprofile/mygames/editprofile" />
<local:MyMenuItem Header="修改密码"
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://account.live.com/password/Change" />
<local:MyMenuItem Header="修改玩家名"
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.minecraft.net/zh-hans/msaprofile/mygames/editprofile" />
</ContextMenu>
</local:MyIconButton.ContextMenu>
</local:MyIconButton>
@@ -22,7 +22,7 @@
</StackPanel>
<local:MyIconButton ToolTip="更改密码" Grid.Row="1" Height="14" Opacity="0" x:Name="BtnEdit" ToolTipService.InitialShowDelay="50" Grid.Column="0" HorizontalAlignment="Center" Logo="F1 M 53.2929,21.2929L 54.7071,22.7071C 56.4645,24.4645 56.4645,27.3137 54.7071,29.0711L 52.2323,31.5459L 44.4541,23.7677L 46.9289,21.2929C 48.6863,19.5355 51.5355,19.5355 53.2929,21.2929 Z M 31.7262,52.052L 23.948,44.2738L 43.0399,25.182L 50.818,32.9601L 31.7262,52.052 Z M 23.2409,47.1023L 28.8977,52.7591L 21.0463,54.9537L 23.2409,47.1023 Z" Margin="8,0,0,0" VerticalAlignment="Center"
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://login.mc-user.com:233/account/changepw" />
<local:MyIconButton ToolTip="退出登录" Grid.Row="1" Height="14" Opacity="0" x:Name="BtnExit" ToolTipService.InitialShowDelay="50" Grid.Column="2" HorizontalAlignment="Center" Logo="F1 M 51.0071,19.0027L 51.0071,27.0038L 48.0067,27.0038L 48.0067,22.0031L 25.0035,22.0031L 25.0035,54.0075L 48.0067,54.0075L 48.0067,49.0068L 51.0071,49.0068L 51.0071,57.008L 22.1698,57.008L 22.0031,19.0027L 51.0071,19.0027 Z M 30.0042,35.0049L 45.2563,35.0049L 37.005,28.0039L 47.0066,28.0039L 58.5082,38.0053L 47.0066,48.0067L 37.005,48.0067L 45.2563,41.0057L 30.0042,41.0057L 30.0042,35.0049 Z" Margin="0,0,8,0" VerticalAlignment="Center" />
<local:MyIconButton ToolTip="切换账号" Grid.Row="1" Height="14" Opacity="0" x:Name="BtnExit" ToolTipService.InitialShowDelay="50" Grid.Column="2" HorizontalAlignment="Center" Logo="M512 0A512 512 0 1 0 1024 512 512 512 0 0 0 512 0z m0 941.407086A429.407086 429.407086 0 1 1 941.407086 512 429.407086 429.407086 0 0 1 512 941.407086z m235.139657-368.64H264.045714a43.505371 43.505371 0 0 0-31.246628 72.060343l159.305143 166.765714a41.281829 41.281829 0 1 0 59.626057-56.788114l-94.997943-99.474286H747.227429a41.311086 41.311086 0 1 0 0-82.622172zM262.670629 450.940343H745.764571a43.505371 43.505371 0 0 0 31.246629-72.352914l-159.305143-166.765715a41.281829 41.281829 0 1 0-59.713828 57.022172l94.968685 99.474285H262.670629a41.281829 41.281829 0 0 0 0 82.563658z" Margin="0,0,8,0" VerticalAlignment="Center" />
</Grid>
<local:MySkin HorizontalAlignment="Center" VerticalAlignment="Top" x:Name="Skin" HasCape="False" />
</Grid>
@@ -487,8 +487,8 @@ Public Class PageLinkMain
If FileUtils.Exists(PathEasyTier & "EasyTier.zip") Then
'解压
Dim ExtractPath As String = RequestTaskTempFolder()
FileUtils.ExtractToDirectory(PathEasyTier & "EasyTier.zip", ExtractPath,
progressHandler:=Sub(Percentage) Task.Progress = Percentage * 0.05)
'FileUtils.ExtractToDirectory(PathEasyTier & "EasyTier.zip", ExtractPath,
' progressHandler:=Sub(Percentage) Task.Progress = Percentage * 0.05)
DirectoryUtils.Copy(DirectoryUtils.EnumerateDirectories(ExtractPath, True).First, PathEasyTier)
'重命名
FileUtils.Move(PathEasyTier & "easytier-core.exe", PathEasyTier & "联机模块.exe")
@@ -11,6 +11,7 @@
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="45" />
<RowDefinition Height="45" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
@@ -18,21 +19,27 @@
<ColumnDefinition Width="150" />
</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="Plain Craft Launcher 2" Margin="-5,0,15,0" Info="当前版本:%VERSION%(%VERSIONCODE%.%BRANCH%)" Grid.Row="1" Grid.Column="1" x:Name="ItemAboutPcl" />
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/Logo.png" Grid.Row="1" Margin="3">
<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" />
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/LTCat.jpg" Grid.Row="0" Margin="3">
<Image.Clip>
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
</Image.Clip>
</Image>
<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/HerobrineXia.png" Grid.Row="1" Margin="3">
<Image.Clip>
<EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
</Image.Clip>
</Image>
<Image Source="/Plain Craft Launcher 2;component/Images/Heads/Logo.png" Grid.Row="2" 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:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://meloong.com/afd/a/LTCat" />
<local:MyButton Text="查看源代码" Grid.Column="2" Grid.Row="1" Height="35"
local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/Hex-Dragon/PCL2" />
<local:MyButton Text="检查更新" Grid.Column="2" Grid.Row="2" Height="35"
x:Name="BtnAboutUpdate" />
</Grid>
</local:MyCard>
<local:MyCard Margin="0,0,0,15" Title="特别鸣谢">
@@ -124,335 +131,329 @@
<local:MyCard Margin="0,0,0,15" Title="赞助者">
<StackPanel Margin="25,40,19,20">
<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="." />
<TextBlock Margin="0,1.5,6,0" Text="7" />
<TextBlock Margin="0,1.5,6,0" Text="ln" />
<TextBlock Margin="0,1.5,6,0" Text="sc" />
<TextBlock Margin="0,1.5,6,0" Text="龙" />
<TextBlock Margin="0,1.5,6,0" Text="人" />
<TextBlock Margin="0,1.5,6,0" Text="溈" />
<TextBlock Margin="0,1.5,6,0" Text="域" />
<TextBlock Margin="0,1.5,6,0" Text="菌" />
<TextBlock Margin="0,1.5,6,0" Text="。" />
<TextBlock Margin="0,1.5,6,0" Text="東" />
<TextBlock Margin="0,1.5,6,0" Text="喆" />
<TextBlock Margin="0,1.5,6,0" Text="辞" />
<TextBlock Margin="0,1.5,6,0" Text="溯" />
<WrapPanel Margin="0,0,0,10"> <TextBlock Margin="0,1.5,6,0" Text="L" />
<TextBlock Margin="0,1.5,6,0" Text="Z" />
<TextBlock Margin="0,1.5,6,0" Text="N" />
<TextBlock Margin="0,1.5,6,0" Text="...:" />
<TextBlock Margin="0,1.5,6,0" Text="妖" />
<TextBlock Margin="0,1.5,6,0" Text="萧" />
<TextBlock Margin="0,1.5,6,0" Text="乔" />
<TextBlock Margin="0,1.5,6,0" Text="liy" />
<TextBlock Margin="0,1.5,6,0" Text="xu" />
<TextBlock Margin="0,1.5,6,0" Text="lor" />
<TextBlock Margin="0,1.5,6,0" Text="💢" />
<TextBlock Margin="0,1.5,6,0" Text="ikii" />
<TextBlock Margin="0,1.5,6,0" Text="ym" />
<TextBlock Margin="0,1.5,6,0" Text="tstt" />
<TextBlock Margin="0,1.5,6,0" Text="hjk" />
<TextBlock Margin="0,1.5,6,0" Text="s11" />
<TextBlock Margin="0,1.5,6,0" Text="gxx" />
<TextBlock Margin="0,1.5,6,0" Text="Lhy" />
<TextBlock Margin="0,1.5,6,0" Text="jojo" />
<TextBlock Margin="0,1.5,6,0" Text="沙轻" />
<TextBlock Margin="0,1.5,6,0" Text="阳阳" />
<TextBlock Margin="0,1.5,6,0" Text="画卿" />
<TextBlock Margin="0,1.5,6,0" Text="幽灵" />
<TextBlock Margin="0,1.5,6,0" Text="御衡" />
<TextBlock Margin="0,1.5,6,0" Text="语墨" />
<TextBlock Margin="0,1.5,6,0" Text="若希" />
<TextBlock Margin="0,1.5,6,0" Text="少帅" />
<TextBlock Margin="0,1.5,6,0" Text="小怂" />
<TextBlock Margin="0,1.5,6,0" Text="叶虚" />
<TextBlock Margin="0,1.5,6,0" Text="伍十" />
<TextBlock Margin="0,1.5,6,0" Text="计计" />
<TextBlock Margin="0,1.5,6,0" Text="雪雪" />
<TextBlock Margin="0,1.5,6,0" Text="李镜" />
<TextBlock Margin="0,1.5,6,0" Text="迪勒" />
<TextBlock Margin="0,1.5,6,0" Text="。。" />
<TextBlock Margin="0,1.5,6,0" Text="优优" />
<TextBlock Margin="0,1.5,6,0" Text="青烬" />
<TextBlock Margin="0,1.5,6,0" Text="苏籁" />
<TextBlock Margin="0,1.5,6,0" Text="阿江" />
<TextBlock Margin="0,1.5,6,0" Text="绵绵" />
<TextBlock Margin="0,1.5,6,0" Text="萧白" />
<TextBlock Margin="0,1.5,6,0" Text="枫灵" />
<TextBlock Margin="0,1.5,6,0" Text="豆腐" />
<TextBlock Margin="0,1.5,6,0" Text="无聊" />
<TextBlock Margin="0,1.5,6,0" Text="闻序" />
<TextBlock Margin="0,1.5,6,0" Text="风鸢" />
<TextBlock Margin="0,1.5,6,0" Text="殉情" />
<TextBlock Margin="0,1.5,6,0" Text="朱磊" />
<TextBlock Margin="0,1.5,6,0" Text="先森" />
<TextBlock Margin="0,1.5,6,0" Text="文博" />
<TextBlock Margin="0,1.5,6,0" Text="月白" />
<TextBlock Margin="0,1.5,6,0" Text="角慕" />
<TextBlock Margin="0,1.5,6,0" Text="楽天" />
<TextBlock Margin="0,1.5,6,0" Text="九杳" />
<TextBlock Margin="0,1.5,6,0" Text="昨易" />
<TextBlock Margin="0,1.5,6,0" Text="W.H" />
<TextBlock Margin="0,1.5,6,0" Text="嘟嘟" />
<TextBlock Margin="0,1.5,6,0" Text="断疆" />
<TextBlock Margin="0,1.5,6,0" Text="麋鹿" />
<TextBlock Margin="0,1.5,6,0" Text="云心" />
<TextBlock Margin="0,1.5,6,0" Text="睚眦" />
<TextBlock Margin="0,1.5,6,0" Text="诡奇" />
<TextBlock Margin="0,1.5,6,0" Text="咲狐" />
<TextBlock Margin="0,1.5,6,0" Text="白云" />
<TextBlock Margin="0,1.5,6,0" Text="泽闻" />
<TextBlock Margin="0,1.5,6,0" Text="逍遥" />
<TextBlock Margin="0,1.5,6,0" Text="木鱼" />
<TextBlock Margin="0,1.5,6,0" Text="凌月" />
<TextBlock Margin="0,1.5,6,0" Text="梓昕" />
<TextBlock Margin="0,1.5,6,0" Text="白菜" />
<TextBlock Margin="0,1.5,6,0" Text="云上" />
<TextBlock Margin="0,1.5,6,0" Text="老赵" />
<TextBlock Margin="0,1.5,6,0" Text="拾岳" />
<TextBlock Margin="0,1.5,6,0" Text="济川" />
<TextBlock Margin="0,1.5,6,0" Text="樾安" />
<TextBlock Margin="0,1.5,6,0" Text="蜜狳" />
<TextBlock Margin="0,1.5,6,0" Text="七月" />
<TextBlock Margin="0,1.5,6,0" Text="北瓜" />
<TextBlock Margin="0,1.5,6,0" Text="昔涟" />
<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="ttt" />
<TextBlock Margin="0,1.5,6,0" Text="88" />
<TextBlock Margin="0,1.5,6,0" Text="33" />
<TextBlock Margin="0,1.5,6,0" Text="kk" />
<TextBlock Margin="0,1.5,6,0" Text="jjb" />
<TextBlock Margin="0,1.5,6,0" Text="+1" />
<TextBlock Margin="0,1.5,6,0" Text="Iirs" />
<TextBlock Margin="0,1.5,6,0" Text="Lio" />
<TextBlock Margin="0,1.5,6,0" Text="lrw" />
<TextBlock Margin="0,1.5,6,0" Text="LLL" />
<TextBlock Margin="0,1.5,6,0" Text="Sht" />
<TextBlock Margin="0,1.5,6,0" Text="Nul" />
<TextBlock Margin="0,1.5,6,0" Text="250" />
<TextBlock Margin="0,1.5,6,0" Text="kile" />
<TextBlock Margin="0,1.5,6,0" Text="pbc" />
<TextBlock Margin="0,1.5,6,0" Text="Aya" />
<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="王道" />
<TextBlock Margin="0,1.5,6,0" Text="鸡人" />
<TextBlock Margin="0,1.5,6,0" Text="喵根" />
<TextBlock Margin="0,1.5,6,0" Text="归墟" />
<TextBlock Margin="0,1.5,6,0" Text="键来" />
<TextBlock Margin="0,1.5,6,0" Text="而后" />
<TextBlock Margin="0,1.5,6,0" Text="南安" />
<TextBlock Margin="0,1.5,6,0" Text="ryan" />
<TextBlock Margin="0,1.5,6,0" Text="xx_α" />
<TextBlock Margin="0,1.5,6,0" Text="欸·柚" />
<TextBlock Margin="0,1.5,6,0" Text="liutd" />
<TextBlock Margin="0,1.5,6,0" Text="KIO3" />
<TextBlock Margin="0,1.5,6,0" Text=" 无悔" />
<TextBlock Margin="0,1.5,6,0" Text="曰久" />
<TextBlock Margin="0,1.5,6,0" Text="小翼" />
<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="Byet" />
<TextBlock Margin="0,1.5,6,0" Text="ZDD" />
<TextBlock Margin="0,1.5,6,0" Text="Um1" />
<TextBlock Margin="0,1.5,6,0" Text="2514" />
<TextBlock Margin="0,1.5,6,0" Text="4440" />
<TextBlock Margin="0,1.5,6,0" Text="Dr.松" />
<TextBlock Margin="0,1.5,6,0" Text="LiMu" />
<TextBlock Margin="0,1.5,6,0" Text="KING" />
<TextBlock Margin="0,1.5,6,0" Text="ᝰᧁꫀꪑⅈꪀⅈ💫" />
<TextBlock Margin="0,1.5,6,0" Text="ming" />
<TextBlock Margin="0,1.5,6,0" Text="CIYE_" />
<TextBlock Margin="0,1.5,6,0" Text="祇–仆" />
<TextBlock Margin="0,1.5,6,0" Text="Pluto" />
<TextBlock Margin="0,1.5,6,0" Text="LYX_7" />
<TextBlock Margin="0,1.5,6,0" Text="刘666" />
<TextBlock Margin="0,1.5,6,0" Text="Dong" />
<TextBlock Margin="0,1.5,6,0" Text="Lecen" />
<TextBlock Margin="0,1.5,6,0" Text="Hikari" />
<TextBlock Margin="0,1.5,6,0" Text="Vertin" />
<TextBlock Margin="0,1.5,6,0" Text="35035" />
<TextBlock Margin="0,1.5,6,0" Text="Dye乄" />
<TextBlock Margin="0,1.5,6,0" Text="白椰菜" />
<TextBlock Margin="0,1.5,6,0" Text="小白龙" />
<TextBlock Margin="0,1.5,6,0" Text="TeRiRi" />
<TextBlock Margin="0,1.5,6,0" Text="索菲亚" />
<TextBlock Margin="0,1.5,6,0" Text="穷哥们" />
<TextBlock Margin="0,1.5,6,0" Text="华华子" />
<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="LEVA" />
<TextBlock Margin="0,1.5,6,0" Text="ZNLL" />
<TextBlock Margin="0,1.5,6,0" Text="joker" />
<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="Rofni" />
<TextBlock Margin="0,1.5,6,0" Text="mzqc" />
<TextBlock Margin="0,1.5,6,0" Text="jason" />
<TextBlock Margin="0,1.5,6,0" Text="xxlzta" />
<TextBlock Margin="0,1.5,6,0" Text="end_x" />
<TextBlock Margin="0,1.5,6,0" Text="QWYJ" />
<TextBlock Margin="0,1.5,6,0" Text="qwqw" />
<TextBlock Margin="0,1.5,6,0" Text="Angel" />
<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="小王子" />
<TextBlock Margin="0,1.5,6,0" Text="狐狸涩" />
<TextBlock Margin="0,1.5,6,0" Text="大涡流" />
<TextBlock Margin="0,1.5,6,0" Text="无名氏" />
<TextBlock Margin="0,1.5,6,0" Text="power" />
<TextBlock Margin="0,1.5,6,0" Text="苏清绾" />
<TextBlock Margin="0,1.5,6,0" Text="四月初" />
<TextBlock Margin="0,1.5,6,0" Text="雪落骆" />
<TextBlock Margin="0,1.5,6,0" Text="秋天爽" />
<TextBlock Margin="0,1.5,6,0" Text="茏三颜" />
<TextBlock Margin="0,1.5,6,0" Text="月落蝶" />
<TextBlock Margin="0,1.5,6,0" Text="蒲咩咩" />
<TextBlock Margin="0,1.5,6,0" Text="糖不哭" />
<TextBlock Margin="0,1.5,6,0" Text="风雨颜" />
<TextBlock Margin="0,1.5,6,0" Text="花江湖" />
<TextBlock Margin="0,1.5,6,0" Text="大馒头" />
<TextBlock Margin="0,1.5,6,0" Text="啊哈哈" />
<TextBlock Margin="0,1.5,6,0" Text="云与海" />
<TextBlock Margin="0,1.5,6,0" Text="V0rtex" />
<TextBlock Margin="0,1.5,6,0" Text="杨子普" />
<TextBlock Margin="0,1.5,6,0" Text="大阿科" />
<TextBlock Margin="0,1.5,6,0" Text="夷希微" />
<TextBlock Margin="0,1.5,6,0" Text="吃不饱" />
<TextBlock Margin="0,1.5,6,0" Text="爱熙熙" />
<TextBlock Margin="0,1.5,6,0" Text="丁老王" />
<TextBlock Margin="0,1.5,6,0" Text="吕雪源" />
<TextBlock Margin="0,1.5,6,0" Text="赵亦勋" />
<TextBlock Margin="0,1.5,6,0" Text="为南西" />
<TextBlock Margin="0,1.5,6,0" Text="下午觉" />
<TextBlock Margin="0,1.5,6,0" Text="李寒衣" />
<TextBlock Margin="0,1.5,6,0" Text="水不湿" />
<TextBlock Margin="0,1.5,6,0" Text="椛芷茈" />
<TextBlock Margin="0,1.5,6,0" Text="李察维" />
<TextBlock Margin="0,1.5,6,0" Text="十六夜" />
<TextBlock Margin="0,1.5,6,0" Text="皮小风" />
<TextBlock Margin="0,1.5,6,0" Text="紫风狐" />
<TextBlock Margin="0,1.5,6,0" Text="范桂圆" />
<TextBlock Margin="0,1.5,6,0" Text="芸芸云" />
<TextBlock Margin="0,1.5,6,0" Text="快夏波" />
<TextBlock Margin="0,1.5,6,0" Text="陈知远" />
<TextBlock Margin="0,1.5,6,0" Text="TaLula" />
<TextBlock Margin="0,1.5,6,0" Text="N线🧵" />
<TextBlock Margin="0,1.5,6,0" Text="秋辞白." />
<TextBlock Margin="0,1.5,6,0" Text="Keil_v5" />
<TextBlock Margin="0,1.5,6,0" Text="laimati" />
<TextBlock Margin="0,1.5,6,0" Text="TraSok" />
<TextBlock Margin="0,1.5,6,0" Text="CH2N8" />
<TextBlock Margin="0,1.5,6,0" Text="Ls-盛望" />
<TextBlock Margin="0,1.5,6,0" Text="FiLin12" />
<TextBlock Margin="0,1.5,6,0" Text="cz_awa" />
<TextBlock Margin="0,1.5,6,0" Text="SYMYR" />
<TextBlock Margin="0,1.5,6,0" Text="524950" />
<TextBlock Margin="0,1.5,6,0" Text="Trigger" />
<TextBlock Margin="0,1.5,6,0" Text="梦华书" />
<TextBlock Margin="0,1.5,6,0" Text="星期天" />
<TextBlock Margin="0,1.5,6,0" Text="铸日者" />
<TextBlock Margin="0,1.5,6,0" Text="晴云雯" />
<TextBlock Margin="0,1.5,6,0" Text="叶龙辉" />
<TextBlock Margin="0,1.5,6,0" Text="小零蚀" />
<TextBlock Margin="0,1.5,6,0" Text="唐墨白" />
<TextBlock Margin="0,1.5,6,0" Text="香子兰" />
<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="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="嘿嘿地" />
<TextBlock Margin="0,1.5,6,0" Text="鹿露璐" />
<TextBlock Margin="0,1.5,6,0" Text="琪露诺" />
<TextBlock Margin="0,1.5,6,0" Text="亚波人" />
<TextBlock Margin="0,1.5,6,0" Text="卿天岚" />
<TextBlock Margin="0,1.5,6,0" Text="哈士奇" />
<TextBlock Margin="0,1.5,6,0" Text="江溪渺" />
<TextBlock Margin="0,1.5,6,0" Text="浮千傀" />
<TextBlock Margin="0,1.5,6,0" Text="恰啦啦" />
<TextBlock Margin="0,1.5,6,0" Text="梦痕丿" />
<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="Twicat" />
<TextBlock Margin="0,1.5,6,0" Text="stenac" />
<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="Triple9" />
<TextBlock Margin="0,1.5,6,0" Text="gediao" />
<TextBlock Margin="0,1.5,6,0" Text="Zen1th" />
<TextBlock Margin="0,1.5,6,0" Text="CH南宫" />
<TextBlock Margin="0,1.5,6,0" Text="bajie79" />
<TextBlock Margin="0,1.5,6,0" Text="_xundu" />
<TextBlock Margin="0,1.5,6,0" Text="TSLOLY" />
<TextBlock Margin="0,1.5,6,0" Text="ncg303" />
<TextBlock Margin="0,1.5,6,0" Text="cqg36k" />
<TextBlock Margin="0,1.5,6,0" Text="YueYue" />
<TextBlock Margin="0,1.5,6,0" Text="火羽白S" />
<TextBlock Margin="0,1.5,6,0" Text="AMumi" />
<TextBlock Margin="0,1.5,6,0" Text="qiumin" />
<TextBlock Margin="0,1.5,6,0" Text="cui白烁" />
<TextBlock Margin="0,1.5,6,0" Text="anyayu" />
<TextBlock Margin="0,1.5,6,0" Text="SISENG" />
<TextBlock Margin="0,1.5,6,0" Text="ro-suto" />
<TextBlock Margin="0,1.5,6,0" Text="GAGUA" />
<TextBlock Margin="0,1.5,6,0" Text="shijie02" />
<TextBlock Margin="0,1.5,6,0" Text="LULULU" />
<TextBlock Margin="0,1.5,6,0" Text="iso3824" />
<TextBlock Margin="0,1.5,6,0" Text="Yununy" />
<TextBlock Margin="0,1.5,6,0" Text="pnd6ou" />
<TextBlock Margin="0,1.5,6,0" Text="Liuaovo" />
<TextBlock Margin="0,1.5,6,0" Text="Akashi7" />
<TextBlock Margin="0,1.5,6,0" Text="softtype" />
<TextBlock Margin="0,1.5,6,0" Text="dumpyy" />
<TextBlock Margin="0,1.5,6,0" Text="LO_WSY" />
<TextBlock Margin="0,1.5,6,0" Text="Mirtium" />
<TextBlock Margin="0,1.5,6,0" Text="adccadc" />
<TextBlock Margin="0,1.5,6,0" Text="Bug虫爷" />
<TextBlock Margin="0,1.5,6,0" Text="DylanPL" />
<TextBlock Margin="0,1.5,6,0" Text="moxuan" />
<TextBlock Margin="0,1.5,6,0" Text="elyruirui" />
<TextBlock Margin="0,1.5,6,0" Text="井上青叶" />
<TextBlock Margin="0,1.5,6,0" Text="懒人ROY" />
<TextBlock Margin="0,1.5,6,0" Text="殇殇月月" />
<TextBlock Margin="0,1.5,6,0" Text="日隅汐音" />
<TextBlock Margin="0,1.5,6,0" Text="小猫渔民" />
<TextBlock Margin="0,1.5,6,0" Text="凤辞时笙" />
<TextBlock Margin="0,1.5,6,0" Text="清苍星海" />
<TextBlock Margin="0,1.5,6,0" Text="芒果挺忙" />
<TextBlock Margin="0,1.5,6,0" Text="只鱼二三" />
<TextBlock Margin="0,1.5,6,0" Text="エンソウ" />
<TextBlock Margin="0,1.5,6,0" Text="高露威姿" />
<TextBlock Margin="0,1.5,6,0" Text="雪本柚子" />
<TextBlock Margin="0,1.5,6,0" Text="萌新求带" />
<TextBlock Margin="0,1.5,6,0" Text="顾炎武月" />
<TextBlock Margin="0,1.5,6,0" Text="刻记牛杂" />
<TextBlock Margin="0,1.5,6,0" Text="小飞小飞" />
<TextBlock Margin="0,1.5,6,0" Text="纯真雪豹" />
<TextBlock Margin="0,1.5,6,0" Text="罗兹瓦尔" />
<TextBlock Margin="0,1.5,6,0" Text="安静的雨" />
<TextBlock Margin="0,1.5,6,0" Text="北牧辰曦" />
<TextBlock Margin="0,1.5,6,0" Text="下次一定" />
<TextBlock Margin="0,1.5,6,0" Text="飞天土钩" />
<TextBlock Margin="0,1.5,6,0" Text="曲线生活" />
<TextBlock Margin="0,1.5,6,0" Text="管那么多" />
<TextBlock Margin="0,1.5,6,0" Text="我叫杨戬" />
<TextBlock Margin="0,1.5,6,0" Text="乐风昭苏" />
<TextBlock Margin="0,1.5,6,0" Text="丨离凡丨" />
<TextBlock Margin="0,1.5,6,0" Text="如图建系" />
<TextBlock Margin="0,1.5,6,0" Text="酒筵辞夕" />
<TextBlock Margin="0,1.5,6,0" Text="踏马的淦" />
<TextBlock Margin="0,1.5,6,0" Text="夜殇羽镰" />
<TextBlock Margin="0,1.5,6,0" Text="星尘墨韵" />
<TextBlock Margin="0,1.5,6,0" Text="聆听冰风" />
<TextBlock Margin="0,1.5,6,0" Text="Yi_xuan" />
<TextBlock Margin="0,1.5,6,0" Text="MC芬达" />
<TextBlock Margin="0,1.5,6,0" Text="shallow" />
<TextBlock Margin="0,1.5,6,0" Text="𝕳轩辕氏" />
<TextBlock Margin="0,1.5,6,0" Text="谜茶360" />
<TextBlock Margin="0,1.5,6,0" Text="Eventful" />
<TextBlock Margin="0,1.5,6,0" Text="Molioos" />
<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="狼烟居士" />
<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="Kang_XL" />
<TextBlock Margin="0,1.5,6,0" Text="Crispykit" />
<TextBlock Margin="0,1.5,6,0" Text="vorinshe" />
<TextBlock Margin="0,1.5,6,0" Text="凉曦luke" />
<TextBlock Margin="0,1.5,6,0" Text="Eiluosha" />
<TextBlock Margin="0,1.5,6,0" Text="GKD小哥" />
<TextBlock Margin="0,1.5,6,0" Text="苇渚泊舟" />
<TextBlock Margin="0,1.5,6,0" Text="花开富贵" />
<TextBlock Margin="0,1.5,6,0" Text="多肉藕片" />
<TextBlock Margin="0,1.5,6,0" Text="浮屠阿仙" />
<TextBlock Margin="0,1.5,6,0" Text="繁星萤火" />
<TextBlock Margin="0,1.5,6,0" Text="沐风沐雨" />
<TextBlock Margin="0,1.5,6,0" Text="金槍羽翼" />
<TextBlock Margin="0,1.5,6,0" Text="龘羅孖倆" />
<TextBlock Margin="0,1.5,6,0" Text="鸽子王雷" />
<TextBlock Margin="0,1.5,6,0" Text="红莲焚霞" />
<TextBlock Margin="0,1.5,6,0" Text="老凌野少" />
<TextBlock Margin="0,1.5,6,0" Text="孤酒青魇" />
<TextBlock Margin="0,1.5,6,0" Text="天空奇己" />
<TextBlock Margin="0,1.5,6,0" Text="霜月秋阳" />
<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="Sakuzyo" />
<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="MuMAA" />
<TextBlock Margin="0,1.5,6,0" Text="溯枫qwq" />
<TextBlock Margin="0,1.5,6,0" Text="Tacenda" />
<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="秋慕owo" />
<TextBlock Margin="0,1.5,6,0" Text="船长Yuki" />
<TextBlock Margin="0,1.5,6,0" Text="是小61呀" />
<TextBlock Margin="0,1.5,6,0" Text="Disbelief" />
<TextBlock Margin="0,1.5,6,0" Text="Manatsu" />
<TextBlock Margin="0,1.5,6,0" Text="Ace_墨尘" />
<TextBlock Margin="0,1.5,6,0" Text="Murousa" />
<TextBlock Margin="0,1.5,6,0" Text="mulberry" />
<TextBlock Margin="0,1.5,6,0" Text="lyh20218" />
<TextBlock Margin="0,1.5,6,0" Text="HIK4RI39" />
<TextBlock Margin="0,1.5,6,0" Text="Gwen_jin" />
<TextBlock Margin="0,1.5,6,0" Text="EthanCAi" />
<TextBlock Margin="0,1.5,6,0" Text="Maplefor" />
<TextBlock Margin="0,1.5,6,0" Text="Dryadove" />
<TextBlock Margin="0,1.5,6,0" Text="Xiaomo_y" />
<TextBlock Margin="0,1.5,6,0" Text="DWS3333" />
<TextBlock Margin="0,1.5,6,0" Text="EnochHcx" />
<TextBlock Margin="0,1.5,6,0" Text="47号虾球" />
<TextBlock Margin="0,1.5,6,0" Text="Alancnel" />
<TextBlock Margin="0,1.5,6,0" Text="Muertesl" />
<TextBlock Margin="0,1.5,6,0" Text="猫幺Suro" />
<TextBlock Margin="0,1.5,6,0" Text="i&apos;g&apos;d&apos;y&apos;f&apos;s" />
<TextBlock Margin="0,1.5,6,0" Text="xiaochen" />
<TextBlock Margin="0,1.5,6,0" Text="ㅤSIMV9r" />
<TextBlock Margin="0,1.5,6,0" Text="alpHabet" />
<TextBlock Margin="0,1.5,6,0" Text="Charlotte" />
<TextBlock Margin="0,1.5,6,0" Text="paperfish" />
<TextBlock Margin="0,1.5,6,0" Text="stealtoup" />
<TextBlock Margin="0,1.5,6,0" Text="bingyan0" />
<TextBlock Margin="0,1.5,6,0" Text="MselQAQ" />
<TextBlock Margin="0,1.5,6,0" Text="UZQueen" />
<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="Com_XDN" />
<TextBlock Margin="0,1.5,6,0" Text="SEIGLE404" />
<TextBlock Margin="0,1.5,6,0" Text="Kevin2022" />
<TextBlock Margin="0,1.5,6,0" Text="梓晨Otaku" />
<TextBlock Margin="0,1.5,6,0" Text="凌点工作室" />
<TextBlock Margin="0,1.5,6,0" Text="千秋万载猹" />
<TextBlock Margin="0,1.5,6,0" Text="超级大月光" />
<TextBlock Margin="0,1.5,6,0" Text="精酿糯米酒" />
<TextBlock Margin="0,1.5,6,0" Text="不「成」器" />
<TextBlock Margin="0,1.5,6,0" Text="无常之客星" />
<TextBlock Margin="0,1.5,6,0" Text="第一年冬天" />
<TextBlock Margin="0,1.5,6,0" Text="大王上早八" />
<TextBlock Margin="0,1.5,6,0" Text="爱吃小笼包" />
<TextBlock Margin="0,1.5,6,0" Text="红楼彡揽月" />
<TextBlock Margin="0,1.5,6,0" Text="画海听竹者" />
<TextBlock Margin="0,1.5,6,0" Text="白哥咯咯咯" />
<TextBlock Margin="0,1.5,6,0" Text="懒得喷喷喷" />
<TextBlock Margin="0,1.5,6,0" Text="估计不会玩" />
<TextBlock Margin="0,1.5,6,0" Text="伊南宁门特" />
<TextBlock Margin="0,1.5,6,0" Text="秋山有希子" />
<TextBlock Margin="0,1.5,6,0" Text="氧化氧化氧" />
<TextBlock Margin="0,1.5,6,0" Text="傻悠不知道" />
<TextBlock Margin="0,1.5,6,0" Text="不爱吃灼芋" />
<TextBlock Margin="0,1.5,6,0" Text="山枕檀痕涴" />
<TextBlock Margin="0,1.5,6,0" Text="你是妖怪叭" />
<TextBlock Margin="0,1.5,6,0" Text="不知名玩家" />
<TextBlock Margin="0,1.5,6,0" Text="Prifo_lone" />
<TextBlock Margin="0,1.5,6,0" Text="有....暗星!" />
<TextBlock Margin="0,1.5,6,0" Text="Hitsser 1.0" />
<TextBlock Margin="0,1.5,6,0" Text="一只憨火龙" />
<TextBlock Margin="0,1.5,6,0" Text="异色收集癖" />
<TextBlock Margin="0,1.5,6,0" Text="DsxiaKsxia" />
<TextBlock Margin="0,1.5,6,0" Text="Plainsman" />
<TextBlock Margin="0,1.5,6,0" Text="湛蓝一四七" />
<TextBlock Margin="0,1.5,6,0" Text="翰墨续丹青" />
<TextBlock Margin="0,1.5,6,0" Text="凛果与百橙" />
<TextBlock Margin="0,1.5,6,0" Text="Touma000" />
<TextBlock Margin="0,1.5,6,0" Text="回忆de天空" />
<TextBlock Margin="0,1.5,6,0" Text="Yunlimeng" />
<TextBlock Margin="0,1.5,6,0" Text="GODxianyu" />
<TextBlock Margin="0,1.5,6,0" Text="叶落才知秋" />
<TextBlock Margin="0,1.5,6,0" Text="好喝的氦三" />
<TextBlock Margin="0,1.5,6,0" Text="星河奈叶风" />
<TextBlock Margin="0,1.5,6,0" Text="魔法且河豚" />
<TextBlock Margin="0,1.5,6,0" Text="魏小泓泓泓" />
<TextBlock Margin="0,1.5,6,0" Text="阴冷潮湿酱" />
<TextBlock Margin="0,1.5,6,0" Text="一只白色缨" />
<TextBlock Margin="0,1.5,6,0" Text="结局的椰子" />
<TextBlock Margin="0,1.5,6,0" Text="三玖二拾柒" />
<TextBlock Margin="0,1.5,6,0" Text="旭旭大魔王" />
<TextBlock Margin="0,1.5,6,0" Text="离人如飘萍" />
<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="岁月suiyue" />
<TextBlock Margin="0,1.5,6,0" Text="陌然MajorC" />
<TextBlock Margin="0,1.5,6,0" Text="-Pareidolia." />
<TextBlock Margin="0,1.5,6,0" Text="蛙蛙大王Kzr" />
<TextBlock Margin="0,1.5,6,0" Text="Yhcmdbfwz" />
<TextBlock Margin="0,1.5,6,0" Text="Equilibrium" />
<TextBlock Margin="0,1.5,6,0" Text="陌泽陌泽MZ" />
<TextBlock Margin="0,1.5,6,0" Text="咖啡R3borN" />
<TextBlock Margin="0,1.5,6,0" Text="1234567890" />
<TextBlock Margin="0,1.5,6,0" Text="GUGUGAGA" />
<TextBlock Margin="0,1.5,6,0" Text="2366445223" />
<TextBlock Margin="0,1.5,6,0" Text="arrovartsk77" />
<TextBlock Margin="0,1.5,6,0" Text="Elegytairitsu" />
<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="We1J1uSh1" />
<TextBlock Margin="0,1.5,6,0" Text="xinghen233" />
<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="DLurker7840" />
<TextBlock Margin="0,1.5,6,0" Text="Don_Quixote" />
<TextBlock Margin="0,1.5,6,0" Text="随便写的名字" />
<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="被压力的鸭梨" />
<TextBlock Margin="0,1.5,6,0" Text="小田love白子" />
<TextBlock Margin="0,1.5,6,0" Text="Sasha_Xiong" />
<TextBlock Margin="0,1.5,6,0" Text="赤狸_crisnow" />
<TextBlock Margin="0,1.5,6,0" Text="Name0emaN" />
<TextBlock Margin="0,1.5,6,0" Text="happypickles" />
<TextBlock Margin="0,1.5,6,0" Text="无中生有为dd" />
<TextBlock Margin="0,1.5,6,0" Text="polarisdream" />
<TextBlock Margin="0,1.5,6,0" Text="YHKooooooy" />
<TextBlock Margin="0,1.5,6,0" Text="Sakura2403ly" />
<TextBlock Margin="0,1.5,6,0" Text="Flying Potato" />
<TextBlock Margin="0,1.5,6,0" Text="陈昊骏泥碳GR" />
<TextBlock Margin="0,1.5,6,0" Text="funnyzhuling" />
<TextBlock Margin="0,1.5,6,0" Text="AYGY暗夜古韵" />
<TextBlock Margin="0,1.5,6,0" Text="Kecdl_Chacha" />
<TextBlock Margin="0,1.5,6,0" Text="对方正在输入 ..." />
<TextBlock Margin="0,1.5,6,0" Text="Chihaya-Anon" />
<TextBlock Margin="0,1.5,6,0" Text="虚域染指亦起舞" />
<TextBlock Margin="0,1.5,6,0" Text="半人半灵的麻薯" />
<TextBlock Margin="0,1.5,6,0" Text="霜雪焉能见太阳" />
<TextBlock Margin="0,1.5,6,0" Text="章鱼哥的琪露诺" />
<TextBlock Margin="0,1.5,6,0" Text="Turbo_Zhang" />
<TextBlock Margin="0,1.5,6,0" Text="SUBLawrence" />
<TextBlock Margin="0,1.5,6,0" Text="Epsilon-9新人" />
<TextBlock Margin="0,1.5,6,0" Text="TheDovebach" />
<TextBlock Margin="0,1.5,6,0" Text="wobushi_furry" />
<TextBlock Margin="0,1.5,6,0" Text="FTC夏日的余晖" />
<TextBlock Margin="0,1.5,6,0" Text="Isshiki Satoshi" />
<TextBlock Margin="0,1.5,6,0" Text="Srive_Schegler" />
<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="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="我的世界爱好者" />
<TextBlock Margin="0,1.5,6,0" Text="半透明的小透明" />
<TextBlock Margin="0,1.5,6,0" Text="到处闲逛的咸鱼" />
<TextBlock Margin="0,1.5,6,0" Text="什么落寒都不是" />
<TextBlock Margin="0,1.5,6,0" Text="没什么名字好取" />
<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="AAA神秘人批发" />
<TextBlock Margin="0,1.5,6,0" Text="Bangbang2025" />
<TextBlock Margin="0,1.5,6,0" Text="贝吉蒙Begimon" />
<TextBlock Margin="0,1.5,6,0" Text="Kozume_Kenma" />
<TextBlock Margin="0,1.5,6,0" Text="Taskmgr-MEMZ" />
<TextBlock Margin="0,1.5,6,0" Text="漫天星火为谁舞?" />
<TextBlock Margin="0,1.5,6,0" Text="常凱申(刘小胖)" />
<TextBlock Margin="0,1.5,6,0" Text="赚够三千万就瘦瘦" />
<TextBlock Margin="0,1.5,6,0" Text="大道五十天衍四九" />
<TextBlock Margin="0,1.5,6,0" Text="爱停电用户_查尔德" />
<TextBlock Margin="0,1.5,6,0" Text="狸猫曾在学校烤面包" />
<TextBlock Margin="0,1.5,6,0" Text="(´o̴̶̷̤ㅂo̴̶̷̤`)" />
<TextBlock Margin="0,1.5,6,0" Text="克洛伊.冯.爱因兹贝伦" />
<TextBlock Margin="0,1.5,6,0" Text="(*^ワ^*)^_^$$" />
<TextBlock Margin="0,1.5,6,0" Text="GongzhuHuanerAwA" />
<TextBlock Margin="0,1.5,6,0" Text="幽兰黛尔【Druandal】" />
<TextBlock Margin="0,1.5,6,0" Text="codm我要玩一辈子cx-9" />
<TextBlock Margin="0,1.5,6,0" Text="取个名字真难0.0" />
<TextBlock Margin="0,1.5,6,0" Text="NoTuring_Steve" />
<TextBlock Margin="0,1.5,6,0" Text="冰冰watermelon" />
<TextBlock Margin="0,1.5,6,0" Text="DOODOODOOD" />
<TextBlock Margin="0,1.5,6,0" Text="小句号就是小句号" />
<TextBlock Margin="0,1.5,6,0" Text="弹跳爆炸小鱼珠🐟" />
<TextBlock Margin="0,1.5,6,0" Text="Xanadu Silk Fable" />
<TextBlock Margin="0,1.5,6,0" Text="看我的都得白内障了" />
<TextBlock Margin="0,1.5,6,0" Text="【点击请输入文本】" />
<TextBlock Margin="0,1.5,6,0" Text="AAA难办批发商乌鸦" />
<TextBlock Margin="0,1.5,6,0" Text="zhuanzhuanzhaun!" />
<TextBlock Margin="0,1.5,6,0" Text="你上课记得记得你先忙" />
</WrapPanel>
<Grid Height="35">
<Grid.ColumnDefinitions>
@@ -27,5 +27,8 @@ Public Class PageOtherAbout
Private Sub BtnDonateOutput_Click(sender As Object, e As EventArgs) Handles BtnDonateOutput.Click
GeneratePotatoCode()
End Sub
Private Sub BtnAboutUpdate_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnAboutUpdate.Click
UpdateCheckByButton()
End Sub
End Class
@@ -185,8 +185,11 @@ Public Class PageSelectRight
Try
Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
Dim IsHintIndie As Boolean = Instance.State <> McInstanceState.Error AndAlso Instance.PathIndie <> McFolderSelected
Dim SavesFolder = DirectoryUtils.GetInfo(Instance.PathIndie & "saves\")
Dim SaveEntries = If(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} 吗?" &
If(IsHintIndie, vbCrLf & "由于该版本开启了版本隔离,删除版本时该版本对应的存档、资源包、Mod 等文件也将被一并删除!", ""),
If(IsHintIndie, vbCrLf & "该版本对应的存档、资源包、Mod 等文件也将被一并删除!", "") &
If(SaveEntries.Any, vbCrLf & vbCrLf & "这会删除以下存档:" & vbCrLf & "· " & SaveEntries.Join(vbCrLf & "· "), ""),
"版本删除确认", , "取消",, True)
Case 1
Instance.ResetSettingsCache()
@@ -64,7 +64,6 @@
<RowDefinition Height="7" />
<RowDefinition Height="28" />
<RowDefinition Height="7" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="来源" Margin="0,0,25,0" />
<local:MyComboBox x:Name="ComboDownloadMod" Grid.Row="0" Grid.ColumnSpan="2" local:SettingService.Key="ToolDownloadMod" Grid.Column="1">
@@ -87,8 +86,6 @@
<local:MyComboBoxItem Content="标题显示译名,详情显示文件名" IsSelected="True" />
<local:MyComboBoxItem Content="标题显示文件名,详情显示译名" />
</local:MyComboBox>
<local:MyCheckBox Margin="0,2,0,4" Text="在显示 Mod 加载器时忽略 Quilt" Grid.Row="6" Height="22" Grid.ColumnSpan="2"
x:Name="CheckDownloadIgnoreQuilt" local:SettingService.Key="ToolDownloadIgnoreQuilt" />
</Grid>
</StackPanel>
</local:MyCard>
@@ -284,6 +284,8 @@
<local:MyComboBoxItem local:SettingService.Value="15" Content="Minecraft 芝士站(作者:awaEric233)" />
<local:MyComboBoxItem local:SettingService.Value="16" Content="整合包推荐引擎(作者:CHMYGZ)" />
<local:MyComboBoxItem local:SettingService.Value="17" Content="Bangumi 番剧主页(作者:wzyaeu)" />
<local:MyComboBoxItem local:SettingService.Value="18" Content="Bilibili 热门(作者:wzyaeu)" />
<local:MyComboBoxItem local:SettingService.Value="19" Content="Music 云音乐热门(作者:wzyaeu)" />
</local:MyComboBox>
</Grid>
</StackPanel>
@@ -120,7 +120,6 @@ Public Class Settings
New Setting("ToolDownloadVersion", 1, Source:=Sources.Registry),
New Setting("ToolDownloadTranslate", 0, Source:=Sources.Registry),
New Setting("ToolDownloadTranslateV2", 1, Source:=Sources.Registry),
New Setting("ToolDownloadIgnoreQuilt", True, Source:=Sources.Registry),
New Setting("ToolDownloadCert", False, Source:=Sources.Registry, OnChanged:=AddressOf ModNet.ShouldValidateSslCertificateOnLogin),
New Setting("ToolDownloadMod", 2, Source:=Sources.Registry),
New Setting("ToolModLocalNameStyle", 0, Source:=Sources.Registry),
@@ -261,7 +260,11 @@ Public Class Settings
Case Sources.Normal
WriteIni("Setup", Key, Value)
Case Sources.Registry
WriteReg(Key, Value)
Try
RegistryUtils.Write($"HKEY_CURRENT_USER\Software\{RegFolder}", Key, Value)
Catch ex As Exception
Logger.Warn(ex, $"写入注册表失败({Key} → {Value})", LogBehavior.Toast)
End Try
Case Sources.Instance
If Instance Is Nothing Then Throw New Exception($"保存版本独立设置 {Key} 时未提供目标版本")
WriteIni(Instance.PathVersion & "PCL\Setup.ini", Key, Value)
@@ -327,7 +330,7 @@ Public Class Settings
Case Sources.Normal
GotValue = ReadIni("Setup", Key, DefaultValue)
Case Sources.Registry
GotValue = ReadReg(Key, DefaultValue)
GotValue = RegistryUtils.TryRead($"HKEY_CURRENT_USER\Software\{RegFolder}", Key, DefaultValue)
Case Sources.Instance
If Instance Is Nothing Then
Throw New Exception($"读取版本设置 {Key} 时未提供目标版本")
@@ -386,7 +389,11 @@ Public Class Settings
Case Sources.Normal
DeleteIniKey("Setup", Key)
Case Sources.Registry
DeleteReg(Key)
Try
RegistryUtils.Delete($"HKEY_CURRENT_USER\Software\{RegFolder}", Key)
Catch ex As Exception
Logger.Warn(ex, $"删除注册表失败({Key})", LogBehavior.Toast)
End Try
Case Sources.Instance
If Instance Is Nothing Then Throw New Exception($"重置版本设置 {Key} 时未提供目标版本")
DeleteIniKey(Instance.PathVersion & "PCL\Setup.ini", Key)
@@ -414,7 +421,12 @@ Public Class Settings
Case Sources.Normal
Return HasIniKey("Setup", Key)
Case Sources.Registry
Return HasReg(Key)
Try
Return RegistryUtils.Has($"HKEY_CURRENT_USER\Software\{RegFolder}", Key)
Catch ex As Exception
Logger.Warn(ex, $"判断注册表 {Key} 是否存在时出错")
Return False
End Try
Case Else 'Source.Instance
If Instance Is Nothing Then Throw New Exception($"判断版本设置 {Key} 是否存在时未提供目标版本")
Return HasIniKey(Instance.PathVersion & "PCL\Setup.ini", Key)
@@ -32,7 +32,7 @@ Public Class PageSpeedLeft
'定时器任务
Private ReadOnly RightCards As New Dictionary(Of String, MyCard)
Private Sub Watcher()
If Not FrmMain.PageCurrent = FormMain.PageType.DownloadManager Then Return
If Not FrmMain.PageCurrent = FormMain.PageType.TaskManager Then Return
Try
#Region "更新左边栏"
@@ -55,7 +55,7 @@ Public Class PageSpeedLeft
#End Region
Catch ex As Exception
Logger.Error(ex, "下载管理左栏监视出错")
Logger.Error(ex, "任务管理左栏监视出错")
End Try
If FrmSpeedRight Is Nothing OrElse FrmSpeedRight.PanMain Is Nothing Then Return
Try
@@ -63,7 +63,7 @@ Public Class PageSpeedLeft
TaskRefresh(Loader)
Next
Catch ex As Exception
Logger.Error(ex, "下载管理右栏监视出错")
Logger.Error(ex, "任务管理右栏监视出错")
End Try
End Sub
Public Sub TaskRefresh(Loader As LoaderBase)
@@ -106,7 +106,7 @@ Public Class PageSpeedLeft
#Region "进度不同,更新卡片"
Try
If Card.Children.Count < LoaderList.Count * 2 Then
Logger.Warn($"刷新下载管理卡片 {Loader.Name} 失败:卡片中仅有 {Card.Children.Count} 个子项,要求至少有 {LoaderList.Count * 2} 个子项")
Logger.Warn($"刷新任务管理卡片 {Loader.Name} 失败:卡片中仅有 {Card.Children.Count} 个子项,要求至少有 {LoaderList.Count * 2} 个子项")
Exit Try
End If
Dim Row As Integer = 0
@@ -133,12 +133,12 @@ Public Class PageSpeedLeft
Row += 1
Next
Catch ex As Exception
Logger.Error(ex, $"刷新下载管理卡片 {Loader.Name} 失败")
Logger.Error(ex, $"刷新任务管理卡片 {Loader.Name} 失败")
End Try
#End Region
End Select
Catch ex As Exception
Logger.Error(ex, $"更新下载管理显示失败({Loader.State})")
Logger.Error(ex, $"更新任务管理显示失败({Loader.State})")
End Try
ElseIf Not (Loader.State = LoadState.Canceled OrElse Loader.State = LoadState.Finished) Then
Try
@@ -177,23 +177,23 @@ Public Class PageSpeedLeft
Try
Card = GetObjectFromXML(CardXAML)
Catch ex As Exception
Logger.Warn(ex, "新建下载管理卡片失败")
Logger.Warn(ex, "新建任务管理卡片失败")
Logger.Info($"出错的卡片内容:{vbCrLf}{CardXAML}")
Throw
End Try
FrmSpeedRight.PanMain.Children.Insert(0, Card)
RightCards.Add(Loader.Name, Card)
Logger.Info($"新建下载管理卡片:{Loader.Name}")
Logger.Info($"新建任务管理卡片:{Loader.Name}")
'添加取消按钮
Dim Cancel As New MyIconButton With {.Name = "BtnCancel", .Logo = "F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z", .Height = 20, .Margin = New Thickness(0, 10, 10, 0), .LogoScale = 1.1, .HorizontalAlignment = HorizontalAlignment.Right, .VerticalAlignment = VerticalAlignment.Top}
Card.Children.Add(Cancel)
AddHandler Cancel.Click,
Sub(sender As MyIconButton, e As EventArgs)
AniDispose(sender, False)
AniDispose(Card, True, Sub() If FrmSpeedRight.PanMain.Children.Count = 0 AndAlso FrmMain.PageCurrent = FormMain.PageType.DownloadManager Then FrmMain.PageBack())
AniDispose(Card, True, Sub() If FrmSpeedRight.PanMain.Children.Count = 0 AndAlso FrmMain.PageCurrent = FormMain.PageType.TaskManager Then FrmMain.PageBack())
RightCards.Remove(Loader.Name)
LoaderTaskbar.Remove(Loader)
Logger.Info($"关闭下载管理卡片:{Loader.Name},且移出任务列表")
Logger.Info($"关闭任务管理卡片:{Loader.Name},且移出任务列表")
RunInThread(Sub() Loader.Cancel())
End Sub
'如果已经失败,再刷新一次,修改成失败的控件
@@ -203,11 +203,11 @@ Public Class PageSpeedLeft
End If
#End Region
Catch ex As Exception
Logger.Error(ex, "添加下载管理卡片失败")
Logger.Error(ex, "添加任务管理卡片失败")
End Try
End If
Catch ex As Exception
Logger.Error(ex, "刷新下载管理显示失败")
Logger.Error(ex, "刷新任务管理显示失败")
End Try
End Sub
Public Sub TaskRemove(Loader As Object)
@@ -218,7 +218,7 @@ Public Class PageSpeedLeft
Dim Card As Grid = RightCards(Loader.Name)
FrmSpeedRight.PanMain.Children.Remove(Card)
RightCards.Remove(Loader.Name)
Logger.Info($"移除下载管理卡片:{Loader.Name}")
Logger.Info($"移除任务管理卡片:{Loader.Name}")
End Sub)
End If
End Sub
@@ -227,7 +227,7 @@ Public Class PageSpeedLeft
''' 若没有任务,尝试返回主页。
''' </summary>
Private Sub TryReturnToHome()
If FrmSpeedRight.PanMain.Children.Count = 0 AndAlso FrmMain.PageCurrent = FormMain.PageType.DownloadManager Then
If FrmSpeedRight.PanMain.Children.Count = 0 AndAlso FrmMain.PageCurrent = FormMain.PageType.TaskManager Then
FrmMain.PageBack()
End If
End Sub
@@ -939,9 +939,14 @@
<LogicalName>MeloongCore.Wpf.dll</LogicalName>
<Link>Resources\MeloongCore.Wpf.dll</Link>
</None>
<None Include="..\PCLCS\bin\Microsoft.Win32.Registry.dll">
<LogicalName>Microsoft.Win32.Registry.dll</LogicalName>
<Link>Resources\Microsoft.Win32.Registry.dll</Link>
</None>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Heads\ChongQing.png" />
<Resource Include="Images\Heads\HerobrineXia.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />