2.13.1.0
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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)];
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -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();
|
||||
|
||||
}
|
||||
Binary file not shown.
+2
-1
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
+2226
-355
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user