From ade6e04c6eab65e945b0fc51faae1ba8e714245c Mon Sep 17 00:00:00 2001
From: LTCat <1043137532@qq.com>
Date: Sat, 17 Oct 2026 03:39:13 +0800
Subject: [PATCH] 2.14.0.0
---
MeloongCore | 2 +-
PCLCS/Configs.cs | 12 +-
PCLCS/Constants.cs | 8 +-
PCLCS/Java.cs | 6 +-
PCLCS/Minecraft/MCUtils.cs | 47 +
PCLCS/Minecraft/McInstallManifest.cs | 71 +
PCLCS/Minecraft/McVersion.cs | 295 ++
PCLCS/Minecraft/OptifineHashes.json | 423 ++
PCLCS/PCLCS.csproj | 2 +
PCLCS/Resource/WikiEntries.txt | 3582 ++++++++++++++---
Plain Craft Launcher 2/Application.xaml.vb | 15 +-
.../Behaviors/ClipboardInterceptor.vb | 77 +-
Plain Craft Launcher 2/Controls/MyCard.vb | 103 +-
Plain Craft Launcher 2/Controls/MyImage.vb | 2 +-
Plain Craft Launcher 2/FormMain.xaml.vb | 54 +-
.../Modules/Base/ModBase.vb | 48 +-
Plain Craft Launcher 2/Modules/Base/ModNet.vb | 8 +-
.../Modules/Base/ModValidate.vb | 2 +-
.../Modules/Minecraft/ModCrash.vb | 6 +-
.../Modules/Minecraft/ModDownload.vb | 6 +-
.../Modules/Minecraft/ModJava.vb | 49 +-
.../Modules/Minecraft/ModLaunch.vb | 151 +-
.../Modules/Minecraft/ModMinecraft.vb | 766 +---
.../Modules/Minecraft/ModModpack.vb | 189 +-
.../Modules/Minecraft/ModWatcher.vb | 3 +
Plain Craft Launcher 2/Modules/ModEvent.vb | 37 +-
Plain Craft Launcher 2/Modules/ModMain.vb | 15 +-
Plain Craft Launcher 2/Modules/ModMusic.vb | 2 +-
.../Modules/Resource/LocalResourceFile.vb | 8 +-
.../Modules/Resource/LocalResourceLoaders.vb | 16 +-
.../Modules/Resource/ResourceProject.vb | 4 +-
.../Modules/Resource/ResourceSearcher.vb | 28 +-
.../Modules/Resource/ResourceVersion.vb | 17 +-
.../My Project/AssemblyInfo.vb | 4 +-
.../Pages/PageDownload/ModDownloadLib.vb | 870 ++--
.../PageDownload/PageDownloadInstall.xaml | 229 +-
.../PageDownload/PageDownloadInstall.xaml.vb | 346 +-
.../Pages/PageDownload/PageDownloadModify.vb | 727 ++++
.../Resource/PageDownloadCompDetail.xaml.vb | 92 +-
.../Resource/PageResource.xaml.vb | 6 +-
.../Pages/PageInstance/MyLocalModItem.xaml.vb | 2 +-
.../PageInstance/PageInstanceExport.xaml | 8 +-
.../PageInstance/PageInstanceExport.xaml.vb | 36 +-
.../Pages/PageInstance/PageInstanceLeft.xaml | 18 +-
.../PageInstance/PageInstanceLeft.xaml.vb | 24 +-
.../PageInstance/PageInstanceMod.xaml.vb | 12 +-
.../PageInstance/PageInstanceOverall.xaml.vb | 52 +-
.../PageInstance/PageInstanceSetup.xaml.vb | 2 +-
.../Pages/PageLaunch/PageLaunchLeft.xaml.vb | 22 +-
.../Pages/PageLaunch/PageLaunchRight.xaml | 7 +-
.../Pages/PageLaunch/PageLaunchRight.xaml.vb | 29 +-
.../Pages/PageLaunch/PageLoginLegacy.xaml.vb | 2 +-
.../Pages/PageLink/PageLinkMain.xaml.vb | 6 +-
.../Pages/PageOther/PageOtherAbout.xaml | 918 +++--
.../Pages/PageOther/PageOtherHelp.xaml.vb | 7 +-
.../Pages/PageSelectLeft.xaml.vb | 47 +-
.../Pages/PageSelectRight.xaml.vb | 46 +-
.../Pages/PageSetup/PageSetupLaunch.xaml | 6 +-
.../Pages/PageSetup/PageSetupLaunch.xaml.vb | 2 +-
.../Pages/PageSetup/PageSetupUI.xaml | 28 +-
.../Pages/PageSetup/PageSetupUI.xaml.vb | 25 +-
.../Pages/PageSetup/Settings.vb | 1 +
.../Pages/PageSpeedLeft.xaml.vb | 3 +-
.../Plain Craft Launcher 2.vbproj | 1 +
Plain Craft Launcher 2/Resources/Help.zip | Bin 78240 -> 78235 bytes
65 files changed, 6989 insertions(+), 2643 deletions(-)
create mode 100644 PCLCS/Minecraft/MCUtils.cs
create mode 100644 PCLCS/Minecraft/McInstallManifest.cs
create mode 100644 PCLCS/Minecraft/McVersion.cs
create mode 100644 PCLCS/Minecraft/OptifineHashes.json
create mode 100644 Plain Craft Launcher 2/Pages/PageDownload/PageDownloadModify.vb
diff --git a/MeloongCore b/MeloongCore
index 811438a..c774ae4 160000
--- a/MeloongCore
+++ b/MeloongCore
@@ -1 +1 @@
-Subproject commit 811438aa3c7c0437c7e60e85b516cc593dcf6cb1
+Subproject commit c774ae4c85fd94e0eaa171db21e78a65870df19b
diff --git a/PCLCS/Configs.cs b/PCLCS/Configs.cs
index 55aaf7b..3de9d93 100644
--- a/PCLCS/Configs.cs
+++ b/PCLCS/Configs.cs
@@ -1,13 +1,21 @@
namespace PCLCS;
public static class Configs {
- /// 当前 Java 相关配置的版本。0 代表尚未从老的 Settings 系统中迁移。
+ public static readonly DynamicConfigEntry McInstallManifest = new("MinecraftInstallManifest", null);
+
+ // Java
+
+ /// 当前 Java 相关配置的版本。0 代表尚未从老的 Settings 系统中迁移。
public static readonly ConfigEntry JavaConfigVersion = new("JavaConfigVersion", 0);
public static readonly ConfigEntry> JavaList = new("JavaList", []);
public static readonly ConfigEntry> JavaRemovedList = new("JavaRemovedList", []);
public static readonly DynamicConfigEntry JavaMigrated = new("InstanceMigratedJava", false);
public static readonly DynamicConfigEntry JavaForced = new("InstanceForcedJava", null);
+ // 提示
+
+ public static readonly ConfigEntry HintModifyInstanceWarning = new("HintModifyInstanceWarning", false);
+
static Configs() {
/// 当 JavaForced 获取到一个不在 JavaList 中的值时,将其重置为 null。
JavaForced.PreviewGet += (args, provider) => {
@@ -17,4 +25,4 @@ public static class Configs {
}
};
}
-}
\ No newline at end of file
+}
diff --git a/PCLCS/Constants.cs b/PCLCS/Constants.cs
index 2e1b7fd..314810e 100644
--- a/PCLCS/Constants.cs
+++ b/PCLCS/Constants.cs
@@ -68,13 +68,17 @@ public static class Versions {
///
/// 版本管理中 Mod 信息缓存的版本号。
///
- public const int LocalModCacheVersion = 19;
+ public const int LocalModCacheVersion = 21;
///
/// Minecraft 本地实例信息缓存的版本号。
///
- public const int McInstanceCacheVersion = 38;
+ public const int McInstanceCacheVersion = 39;
///
/// Java 相关配置的版本号。
///
public const int JavaConfigVersion = 1;
+ ///
+ /// Minecraft 安装清单的版本号。
+ ///
+ public const int McInstallManifestVersion = 1;
}
diff --git a/PCLCS/Java.cs b/PCLCS/Java.cs
index 8c88fd3..57d3eef 100644
--- a/PCLCS/Java.cs
+++ b/PCLCS/Java.cs
@@ -87,9 +87,9 @@ namespace PCLCS;
// 相同检查
public bool Equals(Java? other)
- => other is not null && string.Equals(Folder, other.Folder, StringComparison.OrdinalIgnoreCase);
+ => other is not null && PathUtils.IsSame(Folder, other.Folder);
public override bool Equals(object? obj) => obj is Java other && Equals(other);
- public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Folder);
+ public override int GetHashCode() => StringComparer.CurrentCultureIgnoreCase.GetHashCode(PathUtils.ForCompare(Folder));
/// 用户友好的描述文本。
public override string ToString()
@@ -211,7 +211,7 @@ public static class JavaUtils {
}
// 结果
var hasReparsePoint = HasReparsePoint(FileUtils.GetInfo(Path.Combine(targetFolder, "java.exe")));
- var isSpecialPath = targetFolder.Contains("java8path_target_") || targetFolder.Contains("javapath_target_") || targetFolder.Contains("javatmp") || targetFolder.Contains("system32");
+ var isSpecialPath = targetFolder.ContainsIgnoreCase("java8path_target_") || targetFolder.ContainsIgnoreCase("javapath_target_") || targetFolder.ContainsIgnoreCase("javatmp") || targetFolder.ContainsIgnoreCase("system32");
results.Add((targetFolder, hasReparsePoint, isSpecialPath));
}
} catch (UnauthorizedAccessException) {
diff --git a/PCLCS/Minecraft/MCUtils.cs b/PCLCS/Minecraft/MCUtils.cs
new file mode 100644
index 0000000..641c9a3
--- /dev/null
+++ b/PCLCS/Minecraft/MCUtils.cs
@@ -0,0 +1,47 @@
+using System.Globalization;
+
+namespace PCLCS;
+
+public static class McUtils {
+
+ ///
+ /// 比较两个版本名;左侧较新返回正数,相同返回 0,右侧较新返回负数。
+ /// 无法比较两个预发布版的大小。
+ /// 支持的格式:未知版本, 26.1-snapshot-1,1.13.2, 1.7.10-pre4, 1.8_pre, 1.14 Pre-Release 2, 1.14.4 C6
+ ///
+ public static int CompareVersion(string left, string right) {
+ if (left == right) return 0;
+ if (left == "未知版本" || right == "未知版本") return left == "未知版本" ? 1 : -1;
+ left = left.Lower();
+ right = right.Lower();
+ var leftParts = left.Replace("快照", "snapshot").Replace("预览版", "pre").RegexSearch("[a-z]+|[0-9]+").ToList();
+ var rightParts = right.Replace("快照", "snapshot").Replace("预览版", "pre").RegexSearch("[a-z]+|[0-9]+").ToList();
+ for (int i = 0; ; i++) {
+ if (i >= leftParts.Count && i >= rightParts.Count) return string.Compare(left, right, StringComparison.Ordinal); // 两边均缺失,感觉是一个东西
+ string leftValue = i < leftParts.Count ? leftParts[i] : "0";
+ string rightValue = i < rightParts.Count ? rightParts[i] : "0";
+ if (leftValue == rightValue) continue;
+ int leftNumber = leftValue switch {
+ "rc" => -1,
+ "pre" => -2,
+ "snapshot" => -3,
+ "experimental" => -4,
+ _ => int.TryParse(leftValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out int leftResult) ? leftResult : 0
+ };
+ int rightNumber = rightValue switch {
+ "rc" => -1,
+ "pre" => -2,
+ "snapshot" => -3,
+ "experimental" => -4,
+ _ => int.TryParse(rightValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out int rightResult) ? rightResult : 0
+ };
+ if (leftNumber == 0 && rightNumber == 0) return string.Compare(leftValue, rightValue, StringComparison.Ordinal);
+ if (leftNumber != rightNumber) return leftNumber.CompareTo(rightNumber);
+ }
+ }
+ ///
+ /// 比较两个版本名;左侧不旧于右侧返回 True。
+ ///
+ public static bool CompareVersionGE(string left, string right) => CompareVersion(left, right) >= 0;
+
+}
diff --git a/PCLCS/Minecraft/McInstallManifest.cs b/PCLCS/Minecraft/McInstallManifest.cs
new file mode 100644
index 0000000..09eefdc
--- /dev/null
+++ b/PCLCS/Minecraft/McInstallManifest.cs
@@ -0,0 +1,71 @@
+namespace PCLCS;
+
+///
+/// MC 版本安装清单及 PCL 管理文件清单。
+///
+/// 清单格式版本;无版本的旧清单为 0。
+/// 安装目标及受管理组件版本。
+/// 最后修改时间(UTC)。
+/// 受管理文件;没有文件时为空列表。
+public record McInstallManifest(int SchemaVersion, McComponents Components, DateTime LastModifiedUtc, IReadOnlyList ManagedFiles) {
+ ///
+ /// 清理以 Mod 形式安装的、已删除或修改的组件的记录,并更新清单。
+ ///
+ public McInstallManifest RefreshModComponents(string gameFolder) {
+ List invalidFiles = [];
+ foreach (ManagedFile entry in ManagedFiles) {
+ if (entry.Component is null) continue; // 不检查非组件文件
+ FileInfo file = new(Path.Combine(gameFolder, entry.RelativePath));
+ if (!file.Exists || file.LastWriteTimeUtc != entry.LastWriteTimeUtc.ToUniversalTime()) invalidFiles.Add(entry);
+ }
+ if (!invalidFiles.Any()) return this;
+ return this with {
+ Components = Components with {
+ OptiFineEntry = invalidFiles.Any(file => file.Component == "OptiFine") ? null : Components.OptiFineEntry,
+ FabricApiVersion = invalidFiles.Any(file => file.Component == "FabricApi") ? null : Components.FabricApiVersion,
+ OptiFabricVersion = invalidFiles.Any(file => file.Component == "OptiFabric") ? null : Components.OptiFabricVersion
+ },
+ ManagedFiles = ManagedFiles.Where(file => !invalidFiles.Contains(file)).ToList(),
+ LastModifiedUtc = DateTime.UtcNow
+ };
+ }
+
+ ///
+ /// 由 PCL 管理并记录的版本内文件。
+ ///
+ /// 相对于游戏目录的文件路径。确保路径为全小写且可比较。
+ /// 小写的 SHA1。
+ /// 目标文件的最后修改时间(UTC)。
+ /// 安装器组件名;为空时表示文件由整合包管理。
+ public record ManagedFile(string RelativePath, string Sha1, DateTime LastWriteTimeUtc,
+ [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? Component = null);
+}
+
+/// 目标 Minecraft 版本。
+/// 目标中各个 Mod Loader 的版本;原版为空字典。
+/// OptiFine 条目信息,不安装时为 。
+/// 由 PCL 管理的 Fabric API 版本;不安装时为 。
+/// 由 PCL 管理的 OptiFabric 版本;不安装时为 。
+[method: JsonConstructor]
+public record McComponents(string MinecraftVersion, Dictionary ModLoaderVersions,
+ [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] JObject? OptiFineEntry = null,
+ [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? FabricApiVersion = null,
+ [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? OptiFabricVersion = null) {
+ [JsonIgnore]
+ public string? OptiFineVersion => OptiFineEntry?["InstanceName"]?.Value()?.AfterLast("-OptiFine_");
+ public McComponents(string minecraftVersion, JObject? optiFineEntry, string? forgeVersion,
+ string? neoForgeVersion, string? fabricVersion, string? fabricApiVersion, string? optiFabricVersion, string? liteLoaderVersion)
+ : this(minecraftVersion, [], optiFineEntry, fabricApiVersion, optiFabricVersion) {
+ if (forgeVersion is not null) ModLoaderVersions[ModLoaders.Forge] = forgeVersion;
+ if (neoForgeVersion is not null) ModLoaderVersions[ModLoaders.NeoForge] = neoForgeVersion;
+ if (fabricVersion is not null) ModLoaderVersions[ModLoaders.Fabric] = fabricVersion;
+ if (liteLoaderVersion is not null) ModLoaderVersions[ModLoaders.LiteLoader] = liteLoaderVersion;
+ }
+ public bool IsEquivalentTo(McComponents other) =>
+ MinecraftVersion == other.MinecraftVersion &&
+ OptiFineVersion == other.OptiFineVersion &&
+ FabricApiVersion == other.FabricApiVersion &&
+ OptiFabricVersion == other.OptiFabricVersion &&
+ ModLoaderVersions.Count == other.ModLoaderVersions.Count &&
+ ModLoaderVersions.All(entry => other.ModLoaderVersions.TryGetValue(entry.Key, out string? version) && version == entry.Value);
+}
diff --git a/PCLCS/Minecraft/McVersion.cs b/PCLCS/Minecraft/McVersion.cs
new file mode 100644
index 0000000..2e5a5e8
--- /dev/null
+++ b/PCLCS/Minecraft/McVersion.cs
@@ -0,0 +1,295 @@
+using System.Globalization;
+
+namespace PCLCS;
+
+///
+/// Minecraft 版本号和组件信息
+///
+public sealed class McVersion {
+ ///
+ /// 原版版本名,如 26.1、26.1-snapshot-1、1.12.2、16w01a。
+ ///
+ public string VanillaName {
+ get => _vanillaName;
+ set {
+ _vanillaName = value ?? "Unknown";
+ Vanilla = NameToVersion(_vanillaName);
+ }
+ }
+ private string _vanillaName = "Unknown";
+ ///
+ /// 可比较的三段式原版版本号。
+ /// 旧格式会将次版本号移到主版本号,例如 1.20.1 会转换为 20.0.1,若没有版本号,例如旧快照,则为 9999.0.0。
+ ///
+ public Version Vanilla = new(9999, 0, 0);
+ /// 原版版本号是否可靠(不是通过猜测获取)。
+ public bool Reliable;
+ /// 原版版本号是否有效。
+ public bool Valid => Vanilla.Major < 1000;
+ /// 可供比较的原版 Drop 序数,例如 26.3.2 为 263,1.21.5 为 210;若没有版本号,例如旧快照,则直接指定为 209。
+ public int Drop => Valid ? Vanilla.Major * 10 + Vanilla.Minor : 209;
+ /// 已安装的 Mod Loader,可能有多个。未安装时为 。
+ public ModLoaders ModLoaders => ModLoaderVersions.Keys.Aggregate(ModLoaders.None, (result, loader) => result | loader);
+ /// 已安装的各个 Mod Loader 及其版本;无法确定精确版本时为“未知版本”。
+ public Dictionary ModLoaderVersions { get; } = [];
+ /// OptiFine 版本名,如 C8、C9_pre10;未识别到时为 null。
+ public string? OptiFine;
+ /// OptiFine 是否以 Mod 形式安装。
+ public bool OptiFineAsMod;
+ /// 版本的发布时间。
+ public DateTime ReleaseTime = new(1970, 1, 1, 15, 0, 0);
+ /// 是否为愚人节版本。
+ public bool IsFool;
+ /// 是否为快照、预发布版、发布候选或实验性版本。
+ public bool IsSnapshot;
+ /// 是否识别到已安装的 OptiFine。
+ public bool HasOptiFine => OptiFine is not null;
+ ///
+ /// 可供比较的 OptiFine 版本序数。
+ ///
+ public int OptiFineCode {
+ get {
+ if (OptiFine is null or "未知版本" || OptiFine.Length == 0) return 0;
+ // 字母编号,如 G2 中的 G(7)
+ int result = char.ToUpperInvariant(OptiFine[0]) - 'A' + 1;
+ // 末尾数字,如 C5 beta4 中的 5
+ result = result * 100 + (int.TryParse(OptiFine.Substring(1).RegexSeek(@"\d+"), out int mainVersion) ? mainVersion : 0);
+ // 测试标记(正式版为 99,Pre[x] 为 50+x,Beta[x] 为 x)
+ result *= 100;
+ string? preview = OptiFine.RegexSeek(@"(?i)(pre|beta)\d*");
+ if (preview is null) return result + 99;
+ int sequence = int.TryParse(preview.RegexSeek(@"\d+"), out int value) ? value : 1; // 为 pre 或 beta 结尾,视作 1
+ return result + (preview.StartsWithF("pre", true) ? 50 : 0) + sequence;
+ }
+ }
+ ///
+ /// 可供比较的类 Forge 版本序数。
+ ///
+ public int ForgelikeCode {
+ get {
+ if (!ModLoaderVersions.TryGetValue(ModLoaders.Forge, out string? version)) {
+ ModLoaderVersions.TryGetValue(ModLoaders.NeoForge, out version);
+ }
+ if (version is null or "未知版本") return 0;
+ // 提取所有数字段,以兼容 beta、alpha 和 snapshot 等非数字后缀。
+ int[] segments = version.RegexSearch(@"\d+")
+ .Select(segment => int.TryParse(segment, out int value) ? value : 0).ToArray();
+ return segments.Length switch {
+ >= 4 => segments[0] * 1000000 + segments[1] * 10000 + segments[3],
+ 3 => segments[0] * 1000000 + segments[1] * 10000 + segments[2],
+ 2 => segments[0] * 1000000 + segments[1] * 10000,
+ 1 => segments[0] * 1000000,
+ _ => 0
+ };
+ }
+ }
+
+ ///
+ /// 创建默认 Minecraft 版本。
+ ///
+ /// 原版版本名。
+ /// 版本名是否来自可靠依据。
+ public McVersion(string vanillaName, bool reliable = true) {
+ Reliable = reliable;
+ VanillaName = vanillaName;
+ IsFool = IsFoolName(VanillaName);
+ IsSnapshot = IsSnapshotName(VanillaName);
+ }
+
+ ///
+ /// 通过 Components 创建 Minecraft 版本信息。
+ ///
+ public McVersion(McComponents components) : this(components.MinecraftVersion) {
+ OptiFine = components.OptiFineVersion?.AfterLast("HD_").AfterFirst("_");
+ foreach (var loader in components.ModLoaderVersions) ModLoaderVersions[loader.Key] = loader.Value;
+ }
+
+ ///
+ /// 通过 JSON 识别 Minecraft 版本和已安装组件。
+ ///
+ /// 实例文件夹名。
+ /// 展开的版本 JSON。
+ /// 版本 JAR 中的 version.json。
+ public McVersion(string instanceName, JObject json, JObject? jarVersionJson = null) {
+ string jsonText = json.ToString(Formatting.None);
+ DateTime releaseTime = new(1970, 1, 1, 15, 0, 0); // 未知版本也可能显示为 1970 年
+ try {
+ if (json["releaseTime"] is JToken releaseTimeToken) releaseTime = releaseTimeToken.ToObject();
+ } catch {
+ }
+ bool reliable = true;
+ // 获取游戏版本
+ string vanillaName = (GetVanillaName(instanceName, json, jarVersionJson, releaseTime, ref reliable) ?? "Unknown").Replace("_unobfuscated", "").Replace(" Unobfuscated", "");
+ Reliable = reliable;
+ VanillaName = vanillaName;
+ ReleaseTime = releaseTime;
+ // 确定版本分类
+ string jsonType = json.Value("type") ?? "";
+ // OptiFine
+ OptiFine = jsonText.ContainsIgnoreCase("optifine") ? jsonText.RegexSeek(@"(?<=HD_U_)[^\"":/]+") ?? "未知版本": null;
+ // 愚人节与快照版本
+ DateTime fixedReleaseTime = releaseTime.ToUniversalTime().AddHours(2);
+ IsFool = jsonType == "fool" || IsFoolName(vanillaName) || (fixedReleaseTime.Month == 4 && fixedReleaseTime.Day == 1 && jsonType == "snapshot");
+ IsSnapshot = IsSnapshotName(vanillaName) || instanceName.ContainsIgnoreCase("combat") || jsonType is "snapshot" or "pending" or "fool";
+ if (!Reliable) Logger.Info($"无法完全确认 MC 版本号的版本:{VanillaName}");
+ // LiteLoader
+ if (jsonText.ContainsIgnoreCase("liteloader")) {
+ ModLoaderVersions[ModLoaders.LiteLoader] = jsonText.RegexSeek(@"(?<=com\.mumfrey:liteloader:)[^\"":/]+") ?? "未知版本";
+ }
+ // Fabric、Forge、NeoForge
+ if (jsonText.ContainsIgnoreCase("net.fabricmc:fabric-loader") || jsonText.ContainsIgnoreCase("org.quiltmc:quilt-loader")) {
+ ModLoaderVersions[ModLoaders.Fabric] = jsonText.RegexSeek(@"(?<=(net\.fabricmc:fabric-loader:|org\.quiltmc:quilt-loader:))[0-9\.]+(\+build.[0-9]+)?")?
+ .Replace("+build", "") ?? "未知版本";
+ } else if (jsonText.ContainsIgnoreCase("net.neoforge")) {
+ // 1.20.1 JSON 范例:"--fml.forgeVersion", "47.1.99"
+ // 1.20.2+ JSON 范例:"--fml.neoForgeVersion", "20.6.119-beta"
+ ModLoaderVersions[ModLoaders.NeoForge] = FindArgumentValue(json, "--fml.neoForgeVersion") ?? FindArgumentValue(json, "--fml.forgeVersion") ?? "未知版本";
+ } else if (jsonText.ContainsIgnoreCase("minecraftforge")) {
+ ModLoaderVersions[ModLoaders.Forge] = jsonText.RegexSeek(@"(?<=forge:[0-9\.]+(?:_pre[0-9]*)?-)[0-9\.]+")
+ ?? jsonText.RegexSeek(@"(?<=net\.minecraftforge:minecraftforge:)[0-9\.]+")
+ ?? jsonText.RegexSeek(@"(?<=net\.minecraftforge:fmlloader:[0-9\.]+-)[0-9\.]+") ?? "未知版本";
+ }
+ }
+
+ private static string? GetVanillaName(string instanceName, JObject json, JObject? jarVersionJson, DateTime releaseTime, ref bool reliable) {
+ // 获取发布时间并判断是否为老版本
+ if (releaseTime.Year is > 2000 and < 2013) return "Old";
+ // 实验性快照
+ if (json.Value("type") == "pending") return "pending";
+ // 从 PCL 下载的版本信息中获取版本号
+ if (json["clientVersion"] is JToken clientVersion) return clientVersion.ToString();
+ // 从 HMCL 下载的版本信息中获取版本号
+ if (json["patches"] is JArray patches) {
+ JToken? gameVersion = patches.OfType().FirstOrDefault(patch => patch.Value("id") == "game")?["version"];
+ if (gameVersion is not null) return gameVersion.ToString();
+ }
+ // 从 Forge / NeoForge Arguments 中获取版本号
+ if (FindArgumentValue(json, "--fml.mcVersion") is { Length: > 0 } fmlVersion) return fmlVersion;
+ // 从继承版本中获取版本号
+ string inherit = json["inheritsFrom"]?.ToString() ?? "";
+ if (inherit.Length > 0) {
+ string jar = json["jar"]?.ToString() ?? ""; // LiteLoader 优先使用 Jar
+ return jar.Length > 0 ? jar : inherit;
+ }
+ // 从下载地址中获取版本号
+ string? download = json["downloads"]?.ToString(Formatting.None).RegexSeek(@"(?<=launcher.mojang.com/mc/game/)[^/]*");
+ if (download is not null) return download;
+ // 从 Forge/OptiFine/Fabric 版本中获取版本号
+ string librariesText = json["libraries"]!.ToString();
+ string[] libraryPatterns = [
+ @"(?<=net.minecraftforge:forge:)[0-9]{1,2}.[0-9+.]+",
+ @"(?<=net.minecraftforge:fmlloader:)[0-9]{1,2}.[0-9+.]+",
+ @"(?<=optifine:OptiFine:)[0-9]{1,2}.[0-9+.]+",
+ @"(?<=((fabricmc)|(quiltmc)):intermediary:)[^\""]*"
+ ];
+ foreach (string pattern in libraryPatterns) {
+ if (librariesText.RegexSeek(pattern) is string match) return match;
+ }
+ // 从 jar 项中获取版本号
+ if (json["jar"] is JToken jarToken) return jarToken.ToString();
+ // 从 jar 文件的 version.json 中获取版本号
+ if (jarVersionJson?["name"] is JToken jarNameToken && jarNameToken.ToString() is { Length: < 32 } jarName) { // 因为 wiki 说这玩意儿可能是个 hash,虽然我没发现
+ Logger.Info($"从版本 jar 中的 version.json 获取到版本号:{jarName}");
+ return jarName;
+ }
+ string VersionPattern = @"(([1-9][0-9]w[0-9]{2}[a-g])|((1|[2-9][0-9])\.[0-9]+(\.[0-9]+)?(-(pre|rc|snapshot-?)[1-9]*| Pre-Release( [1-9])?)?))(_unobfuscated)?";
+ // 从 JSON 的 ID 中获取
+ if (json["id"]!.ToString().RegexSeek(VersionPattern, RegexOptions.IgnoreCase) is string idMatch) return idMatch;
+ // 非准确的版本判断警告
+ Logger.Info($"无法完全确认 MC 版本号的版本:{instanceName}");
+ reliable = false;
+ // 从文件夹名中获取
+ if (instanceName.RegexSeek(VersionPattern, RegexOptions.IgnoreCase) is string folderMatch) return folderMatch;
+ // 从 JSON 出现的版本号中获取
+ JObject withoutLibraries = (JObject) json.DeepClone();
+ withoutLibraries.Remove("libraries");
+ return withoutLibraries.ToString(Formatting.None).RegexSeek(VersionPattern, RegexOptions.IgnoreCase);
+ }
+
+ private static bool IsFoolName(string name) {
+ name = name.Lower();
+ return name.StartsWithF("2.0") || name is "15w14a" or "1.rv-pre1" or
+ "3d shareware v1.34" or "20w14∞" or "22w13oneblockatatime" or "23w13a_or_b" or
+ "24w14potato" or "25w14craftmine" or "26w14a" || name.StartsWithF("20w14inf");
+ }
+
+ private static bool IsSnapshotName(string name) =>
+ new[] { "w", "snapshot", "rc", "pre", "experimental", "-" }.Any(name.ContainsIgnoreCase);
+
+ ///
+ /// 读取 arguments 中指定参数的字符串值。
+ ///
+ private static string? FindArgumentValue(JObject json, string name) {
+ JArray? arguments = json["arguments"]?["game"] as JArray;
+ if (arguments is null) return null;
+ for (int i = 0; i + 1 < arguments.Count; i++) {
+ if (arguments[i]?.ToString() == name) return arguments[i + 1]?.ToString();
+ }
+ return null;
+ }
+
+ ///
+ /// 判断版本字符串是否符合 Minecraft 原版格式,例如 1.x、26.x。
+ ///
+ public static bool IsStandardFormat(string? version) {
+ if (version is null) return false;
+ if (Regex.IsMatch(version, @"^1\.\d")) return true;
+ return double.TryParse(version.RegexSeek(@"^[2-9]\d\.\d+"), NumberStyles.Float,
+ CultureInfo.InvariantCulture, out double value) && value >= 26;
+ }
+
+ ///
+ /// 将版本名转换为 Drop 序数;无法转换时返回 209。
+ ///
+ public static int VersionToDrop(string? vanillaName) {
+ if (vanillaName is null) return 209;
+ Version version = NameToVersion(vanillaName);
+ return version.Major >= 1000 ? 209 : version.Major * 10 + version.Minor;
+ }
+
+ ///
+ /// 将 Drop 序数转换为版本字符串。
+ ///
+ public static string DropToVersion(int drop) {
+ if (drop >= 250) return $"{drop / 10}.{drop % 10}";
+ if (drop != 209) return $"1.{drop / 10}";
+ Logger.Warn(new Exception("尝试将旧快照版 Drop 序数转换为版本字符串,这不应该发生!"));
+ return "1.20";
+ }
+
+ ///
+ /// 将版本名转换为可比较的三段式原版版本号。
+ /// 对老版本格式,例如 1.20.3,会被转换为 20.0.3。
+ /// 对愚人节版本,返回其基于的正式版版本号。
+ /// 若没有版本号,例如旧快照,则为 9999.0.0。
+ ///
+ public static Version NameToVersion(string? name) {
+ if (name is null) return new Version(9999, 0, 0);
+ name = name.Lower().Replace("_unobfuscated", "").Replace(" unobfuscated", "");
+ // 愚人节版本
+ if (name.StartsWithF("2.0")) return NameToVersion("1.5.1");
+ if (name == "15w14a") return NameToVersion("1.8.3");
+ if (name.ContainsIgnoreCase(".rv-pre")) return NameToVersion("1.9.2");
+ if (name.ContainsIgnoreCase("shareware")) return NameToVersion("1.13.2");
+ if (name.StartsWithF("20w14") && name != "20w14a") return NameToVersion("1.15.2");
+ if (name.ContainsIgnoreCase("oneblockatatime")) return NameToVersion("1.18.2");
+ if (name.ContainsIgnoreCase("23w13a") && name != "20w13a") return NameToVersion("1.19.4");
+ if (name == "24w14potato") return NameToVersion("1.20.4");
+ if (name == "25w14craftmine") return NameToVersion("1.21.4");
+ if (name == "26w14a") return NameToVersion("26.1.1");
+ // 其余版本
+ static int ParseSegment(string[] segments, int index) {
+ if (index >= segments.Length) return 0;
+ // 只读取该段开头连续的数字,忽略其后的预览版标记。
+ return int.TryParse(segments[index].RegexSeek(@"^\d+"), out int value) ? value : 0;
+ }
+ string[] segments = name.Split([' ', '_', '-', '.'], StringSplitOptions.None);
+ if (name.StartsWithF("1.")) {
+ return new Version(ParseSegment(segments, 1), 0, ParseSegment(segments, 2));
+ } else if (name.RegexCheck(@"^[2-9][0-9]\.")) {
+ return new Version(ParseSegment(segments, 0), ParseSegment(segments, 1), ParseSegment(segments, 2));
+ } else {
+ return new Version(9999, 0, 0);
+ }
+ }
+}
diff --git a/PCLCS/Minecraft/OptifineHashes.json b/PCLCS/Minecraft/OptifineHashes.json
new file mode 100644
index 0000000..2284b0b
--- /dev/null
+++ b/PCLCS/Minecraft/OptifineHashes.json
@@ -0,0 +1,423 @@
+{
+ "f3a3c9d792bdb48595405d52c02cc7baf1db4ecb": "OptiFine_1.7.2_HD_U_E3.jar",
+ "657169c421ce280f80c73b05ab71ad582d2b37fd": "OptiFine_1.7.2_HD_U_E4.jar",
+ "99f20d449912cd860b409e4679c54dd8da43d55e": "OptiFine_1.7.2_HD_U_E7.jar",
+ "8253f6ed418a2a61a612cc9e69fd1fea1d11fa7d": "OptiFine_1.7.2_HD_U_E8.jar",
+ "379e52fc02cd75562d201b0c505269b6109b2136": "OptiFine_1.7.2_HD_U_F3.jar",
+ "fb04b91e47b5eaa172d2b76c843e488dba8f909b": "OptiFine_1.7.2_HD_U_F7.jar",
+ "b4b6c2c99f5734e4267030a47f2eaad2796eb2a7": "OptiFine_1.7.10_HD_U_D3.jar",
+ "a0b533bc97b24fe771f5b08536c6339d04f92bae": "OptiFine_1.7.10_HD_U_D4.jar",
+ "5e9327dd05a1e762c23c3c0227445d90f193922f": "OptiFine_1.7.10_HD_U_D6.jar",
+ "7a7d2adf21038d241dd375faa7316fb2c74d34d3": "OptiFine_1.7.10_HD_U_D7.jar",
+ "2345677be44dd56a0ae5b90e747a590c3cc00ff8": "OptiFine_1.7.10_HD_U_D8.jar",
+ "23f133173428aee712eb11f200b461e3114bde31": "OptiFine_1.7.10_HD_U_E3.jar",
+ "2130d7266224da6a7325051e37444f7e7c19277c": "OptiFine_1.7.10_HD_U_E7.jar",
+ "55c9c475ecd0f62cc1776ce52be04c5937112936": "OptiFine_1.8.0_HD_U_H5.jar",
+ "bb2c2997cdc66cfb3c311a3dc065752a4845c1a8": "OptiFine_1.8.0_HD_U_H6.jar",
+ "692b0b7e878c3416f21b4347fab4516f3cc86dfc": "OptiFine_1.8.0_HD_U_H7.jar",
+ "5464962b66b9b0dacb3d787e6a71d2365ae50bca": "OptiFine_1.8.0_HD_U_H8.jar",
+ "b7718b03111bec04036fd3352ce374eea273171c": "OptiFine_1.8.0_HD_U_I3.jar",
+ "0d1dcf64b4d104a71e8f65a1362a163ed81a9030": "OptiFine_1.8.0_HD_U_I7.jar",
+ "e5e5eb03748af0fa160b502a28359c0144e254d2": "OptiFine_1.8.8_HD_U_H5.jar",
+ "9294bc4562a143c35ece03a6b3d3a000109def5f": "OptiFine_1.8.8_HD_U_H6.jar",
+ "1c06c011904ab22952a96f73d4b575a5c265d207": "OptiFine_1.8.8_HD_U_H7.jar",
+ "3984e4dd222bb62cb7e28e4d3092029cc7534fd1": "OptiFine_1.8.8_HD_U_H8.jar",
+ "0dc33a9761ceac19ca0bbb1ea6813c0160d43aa1": "OptiFine_1.8.8_HD_U_I3.jar",
+ "30cbf4d61052cbfb736a78117da333df23c129a3": "OptiFine_1.8.8_HD_U_I7.jar",
+ "d8240cfa7387b994fdf2a64bdc8a8860857adc18": "OptiFine_1.8.9_HD_U_H5.jar",
+ "2636689b31810896cf80493f6fc4d8c1783048ea": "OptiFine_1.8.9_HD_U_H6.jar",
+ "e4544c9210bc056abffa1986a33c4e72623d4f31": "OptiFine_1.8.9_HD_U_H7.jar",
+ "4b73738913453bcbca969d3e77f05ae0cf5b8a7e": "OptiFine_1.8.9_HD_U_H8.jar",
+ "d5cd8b902077075bbf1d865cfd5b3362a6863ace": "OptiFine_1.8.9_HD_U_I3.jar",
+ "58bec8f8766918dcad2b8412f1fbb6f30cc9319f": "OptiFine_1.8.9_HD_U_I7.jar",
+ "dcab4849a24ccad5a6a3496c67bc5a88411d2a35": "OptiFine_1.8.9_HD_U_L5.jar",
+ "d362d58a28f5373b141b9e426e8e160638bfafcd": "OptiFine_1.8.9_HD_U_M5.jar",
+ "1f9dcc9735e94ebb5195c4014300ea462eb12878": "preview_OptiFine_1.8.9_HD_U_L6_pre1.jar",
+ "6e0b3b86e51c2647c98e277475ee7e68f32a0d0e": "preview_OptiFine_1.8.9_HD_U_M5_pre2.jar",
+ "7287fcd1a415ab87eca5e89457cc3507aa3fa579": "preview_OptiFine_1.8.9_HD_U_M6_pre1.jar",
+ "0bb792be16ec78d8b62586cc4856950befb3391b": "preview_OptiFine_1.8.9_HD_U_M6_pre2.jar",
+ "fd87c53197312614c34669feb7608f74a30da712": "OptiFine_1.9.0_HD_U_B1.jar",
+ "f99941037f3633926ffebb3eda67f296a701c019": "OptiFine_1.9.0_HD_U_B2.jar",
+ "34c47106cda1371ecf13e61aed4c1b53a3a53163": "OptiFine_1.9.0_HD_U_B3.jar",
+ "ebc7258e13344097588c73a0b48457083069e1df": "OptiFine_1.9.0_HD_U_B5.jar",
+ "999df92e8904f9268e549135edbec322d332ef62": "OptiFine_1.9.0_HD_U_D7.jar",
+ "0fe031e95f9c01481c9376d9a1df68f9e9857db8": "OptiFine_1.9.0_HD_U_D8.jar",
+ "f4bc2eb5e039e842eb07181ea564eba487513228": "OptiFine_1.9.0_HD_U_E3.jar",
+ "78870a94ec3c4db8aebc4c29d4d39bdda2bf05da": "OptiFine_1.9.0_HD_U_E7.jar",
+ "d3d55bb37e76d1932cb3ad9dde4b9127993f856d": "OptiFine_1.9.0_HD_U_H5.jar",
+ "b5faec3b84f42dd396512a3ce7c1b57c0b972b70": "OptiFine_1.9.0_HD_U_I5.jar",
+ "92742ecac143b1d28c215ca145bd9775a01c5085": "preview_OptiFine_1.9.0_HD_U_I5_pre1.jar",
+ "c87029938376017deba9108322bcb8424d64e92c": "OptiFine_1.9.2_HD_U_B1.jar",
+ "d3e5e1fa480e66603ca037d74966a95d25968d51": "OptiFine_1.9.2_HD_U_B2.jar",
+ "fbd545f921d098235a28f87cda55a0504e831954": "OptiFine_1.9.2_HD_U_B3.jar",
+ "1ae8e6daeeccb6ee48618e8ccdc0b6276d47944f": "OptiFine_1.9.2_HD_U_D7.jar",
+ "3350c829b29d170e9ac19809a3ae45cb099277b5": "OptiFine_1.9.2_HD_U_D8.jar",
+ "c032b2ae0b6087077efef8ae89b612e0d4ea81b7": "OptiFine_1.9.2_HD_U_E3.jar",
+ "3d8cbc19bcad9e9ecc98f607e10f65673a09b482": "OptiFine_1.9.4_HD_U_B4.jar",
+ "b6b9e66b34ddcda5294b016602fb17d741ff6f54": "OptiFine_1.9.4_HD_U_B5.jar",
+ "060ddd5a0b7b7ac5586de04ae53cf923ae5c7290": "OptiFine_1.9.4_HD_U_B6.jar",
+ "2c39611a89dc583cdb403f402c2efd2bd8c6da63": "OptiFine_1.9.4_HD_U_D7.jar",
+ "4b26926208de270225eb9d3af24a4ff3841238f5": "OptiFine_1.9.4_HD_U_D8.jar",
+ "012f82fce41aee5e6e56e551d450a07b2b361646": "OptiFine_1.9.4_HD_U_E3.jar",
+ "cf9c075fa71dab34cdf1c376a76bd08295c69ce6": "OptiFine_1.9.4_HD_U_E7.jar",
+ "b3a76b92e0e9594f6fa135f1156b9cc13712db20": "OptiFine_1.9.4_HD_U_H5.jar",
+ "68a206db0d425dd85f6eba33e52122b01e844c46": "OptiFine_1.9.4_HD_U_I5.jar",
+ "2e48d20605340cfad844a6587d3848e328fd4399": "preview_OptiFine_1.9.4_HD_U_I5_pre1.jar",
+ "d7a1e5f40e28fa3283b82bf3af7d3f433b91df08": "OptiFine_1.10_HD_U_B6.jar",
+ "717a02b21136e022cdb4d7d6ec6a4125f4ed2312": "OptiFine_1.10_HD_U_B7.jar",
+ "0b5d1719592a57cf414643c5b56f4bb3c23a5b94": "OptiFine_1.10_HD_U_C1.jar",
+ "236747126edcf0c97fc6a20fa7f6491accbf0108": "OptiFine_1.10_HD_U_D7.jar",
+ "c5fd78710e821f06f871994032e951065c15c40d": "OptiFine_1.10_HD_U_D8.jar",
+ "1bea8b0bae04ca4b25c6824a6f23a5442d5aa926": "OptiFine_1.10_HD_U_E3.jar",
+ "7a7195348ea583458b657573b5fcc72e4adc8308": "OptiFine_1.10_HD_U_E7.jar",
+ "3bcc46f718711cd6fe3db49de4cc810b75420de8": "OptiFine_1.10_HD_U_H5.jar",
+ "a0070afe9c1c0ced4bcfcda85359e07917d569bd": "OptiFine_1.10_HD_U_I5.jar",
+ "f9a36eb0246ad6ba303e670082be2c2515c50dcd": "preview_OptiFine_1.10_HD_U_I5_pre1.jar",
+ "3ea5dae651b6d64900562d1cde5070ebd9db2936": "OptiFine_1.10.2_HD_U_C1.jar",
+ "41968442e8d1e30e9a32e7a5594caca22312d9d6": "OptiFine_1.10.2_HD_U_C2.jar",
+ "9c8bc96d3125199e96f5dbfda685ea5dd92c253e": "OptiFine_1.10.2_HD_U_C3.jar",
+ "7ec4ccc213b482936baaffb9f1937f7147796893": "OptiFine_1.10.2_HD_U_D1.jar",
+ "3ee5aecc8e11567fb46de0b94e23cf1428f4c9fc": "OptiFine_1.10.2_HD_U_D2.jar",
+ "98059ed7e93d0fc058203569ccfe965b022fb18f": "OptiFine_1.10.2_HD_U_D3.jar",
+ "c3165d0a0207d72e18f4533e7aa5ca30e96819a9": "OptiFine_1.10.2_HD_U_D4.jar",
+ "347359aef422d64711b470f4cf0803cb072da0fa": "OptiFine_1.10.2_HD_U_D6.jar",
+ "4ddf7c45e00839031f5793451541bca002f9257f": "OptiFine_1.10.2_HD_U_D7.jar",
+ "5c3685e279c664a818c41ca213b2bc9bfc4340b0": "OptiFine_1.10.2_HD_U_D8.jar",
+ "129581af3d7d73b506b42d822cb2d3fce68c8e2e": "OptiFine_1.10.2_HD_U_E3.jar",
+ "f052d269109154d851cc7a8e766c78802a76e9b2": "OptiFine_1.10.2_HD_U_E7.jar",
+ "f285cfe6753c5d987e4cb0940da05e9513334d98": "OptiFine_1.10.2_HD_U_H5.jar",
+ "12fd8dd33150f9e4436f23bac08265305f949e20": "OptiFine_1.10.2_HD_U_I5.jar",
+ "adac69b25bb95242422a635965c7f17503c694be": "preview_OptiFine_1.10.2_HD_U_I5_pre1.jar",
+ "06031e4c828b66facefdfa32cd29c585909d9e45": "OptiFine_1.11_HD_U_B1.jar",
+ "449aef14cee17cf1c79d4bad73b69107202d3c1c": "OptiFine_1.11_HD_U_B2.jar",
+ "7663e1ee572c742e96a71a355f0775baf7cbc6ef": "OptiFine_1.11_HD_U_B3.jar",
+ "bde9d34f84a030734c7b9d09eda700c7c828eb96": "OptiFine_1.11_HD_U_B5.jar",
+ "579cfb75b86f3404c5f6e8f694c51b09b7c9b261": "OptiFine_1.11_HD_U_B6.jar",
+ "350af22b31dbc27d1b928e7144582fd361deb193": "OptiFine_1.11_HD_U_B7.jar",
+ "236161183cc5cd5faf84dd27824cc3eaa107ed5f": "OptiFine_1.11_HD_U_B8.jar",
+ "9ca32d42c7e5ad9de9665ffee9ddd41dddd33b66": "OptiFine_1.11_HD_U_C3.jar",
+ "2e45de9e9fb385f24c6eecb1a64537de78778105": "OptiFine_1.11_HD_U_C7.jar",
+ "32df58fec7148e75b599b18691f80e69b7f9cd1b": "OptiFine_1.11_HD_U_F5.jar",
+ "71057cb7a3d0971c3b56e1fbbc333304a72e1352": "OptiFine_1.11_HD_U_G5.jar",
+ "c2ee1e1019ab26bee56447f4df8a2639d2029925": "preview_OptiFine_1.11_HD_U_G5_pre1.jar",
+ "083a002215e2174c0d40af20d2f3844ea349a354": "OptiFine_1.11.2_HD_U_B5.jar",
+ "eb92ce00048faa95b184d121fa667074532fb9db": "OptiFine_1.11.2_HD_U_B6.jar",
+ "7449a2db44e86303d588b526dc73127c16b0e94f": "OptiFine_1.11.2_HD_U_B7.jar",
+ "3e1006c935fe27d83459e77d336460ac5b5c81b4": "OptiFine_1.11.2_HD_U_B8.jar",
+ "049e7e134e8c7364ab61810d84289394e17921de": "OptiFine_1.11.2_HD_U_B9.jar",
+ "4871f2edf7ded30c374aa770e9ea4adcc0b786d0": "OptiFine_1.11.2_HD_U_C1.jar",
+ "e7a54d9e203a1b951f8373ab6dcdedb348e536b1": "OptiFine_1.11.2_HD_U_C2.jar",
+ "8d7fd0facc2299f3dad9dc7c19cc13f72a780343": "OptiFine_1.11.2_HD_U_C3.jar",
+ "20db26eaafb1c4ebd99e1dc2fffe4a62456bf60e": "OptiFine_1.11.2_HD_U_C7.jar",
+ "e4efcf05086389fe18d6fe62eb8ab7512a07323c": "OptiFine_1.11.2_HD_U_F5.jar",
+ "65c425ab628d1748b489dee8619271402428509e": "OptiFine_1.11.2_HD_U_G5.jar",
+ "f253807a4689e44da030acd5c2187d2184885e87": "preview_OptiFine_1.11.2_HD_U_G5_pre1.jar",
+ "1fdacab6f3b0df1f46142acf9c427db2a653d680": "OptiFine_1.12_HD_U_C2.jar",
+ "a62a02c8437a0dccaf2ea89ab8392fd40dc92eb1": "OptiFine_1.12_HD_U_C3.jar",
+ "36d6f6f64048f68dd248a4d3c43a6f5e51fbb9c5": "OptiFine_1.12_HD_U_C4.jar",
+ "fd8e0e3ba43568e5ca0ce31c87373806d269b7e5": "OptiFine_1.12_HD_U_C5.jar",
+ "25ba634e5105e6d1e615dad0046905b68313cc9f": "OptiFine_1.12_HD_U_C7.jar",
+ "b9cd2775fc49bf009f82d3ce36235b1e702d46bb": "OptiFine_1.12_HD_U_F5.jar",
+ "3b8369d33c3257cb247c22b13a41b7db0924e948": "OptiFine_1.12_HD_U_G5.jar",
+ "aeee885ccf821c34d86537184389873d8c312ae1": "preview_OptiFine_1.12_HD_U_G5_pre1.jar",
+ "c754771bf6a7371a7084459505c244cbec61a7cf": "OptiFine_1.12.1_HD_U_C5.jar",
+ "4362a9d38542b5f4ba07782fc4d07949f4fede08": "OptiFine_1.12.1_HD_U_C6.jar",
+ "38785968beeb796cde55f91995c6cf8bfbc3b062": "OptiFine_1.12.1_HD_U_C7.jar",
+ "e6f9e6b573119c052062192695fed4ef388db9c1": "OptiFine_1.12.1_HD_U_F5.jar",
+ "3c9cd74810cad75de5091633a1e0c7d3d76ea09c": "OptiFine_1.12.1_HD_U_G5.jar",
+ "aaaaff3ae13a0cdffa2475632cf6303b9f86e0b0": "preview_OptiFine_1.12.1_HD_U_G5_pre1.jar",
+ "a9d21f084a485bc12fce8c9bea1660c6d4b08855": "OptiFine_1.12.2_HD_U_C5.jar",
+ "2159a0a754828d63446fca7b6f8fa57b710c6048": "OptiFine_1.12.2_HD_U_C6.jar",
+ "8ed8009fc82b43909190882927f335d5250a0e19": "OptiFine_1.12.2_HD_U_C7.jar",
+ "a55768a83db4ad0599f68d9bf3fa8041e2ae3852": "OptiFine_1.12.2_HD_U_C8.jar",
+ "e0236d21a2a164f2af1cfff8f9f325f53c9125f2": "OptiFine_1.12.2_HD_U_C9.jar",
+ "b91a0d82c24eef95be0af92993b14e94b842f166": "OptiFine_1.12.2_HD_U_D1.jar",
+ "04c28238506dc3561addb6efb87c9878d5b82ffe": "OptiFine_1.12.2_HD_U_D2.jar",
+ "b784000951d41f54d67685a0a275d9f61f810514": "OptiFine_1.12.2_HD_U_D3.jar",
+ "343f814410401ebdbb3314deb17c27cbab67bfac": "OptiFine_1.12.2_HD_U_E1.jar",
+ "5c87706b6d14061fed248506d8e3f95b7824ad18": "OptiFine_1.12.2_HD_U_E2.jar",
+ "e805d4be5c2a3343488c573145606e90bb13816d": "OptiFine_1.12.2_HD_U_E3.jar",
+ "0e8d45666e80829c9ab74527628dace9187fbfb5": "OptiFine_1.12.2_HD_U_F4.jar",
+ "84ada0f48bcfb16c37c49283627597bb74d935f6": "OptiFine_1.12.2_HD_U_F5.jar",
+ "ca3aea3a09ce215906c346fe190907fe0347b0c4": "OptiFine_1.12.2_HD_U_G5.jar",
+ "23a8be042f354ec97c99672906c3e61fdf54ca2c": "preview_OptiFine_1.12.2_HD_U_F6_pre1.jar",
+ "b71f993a364c7945081cc6cde9a20d29b4e43f1f": "preview_OptiFine_1.12.2_HD_U_G5_pre1.jar",
+ "ab2118b1ed23444d6decf081e0295e4c679af6c2": "preview_OptiFine_1.12.2_HD_U_G6_pre1.jar",
+ "25498de48dd9b7ed2ba5b83464950ad132e61c1f": "preview_OptiFine_1.14_HD_U_F1_pre6.jar",
+ "396ce7f0e22aae3543134baabd61ad547334c0aa": "OptiFine_1.14.2_HD_U_F1.jar",
+ "c8c6da3e2ae32d020d9001d4489aad702680f50f": "preview_OptiFine_1.14.2_HD_U_F1_pre15.jar",
+ "52420ef34128a8b15d7c8f5ed8f7ebc94b708efd": "OptiFine_1.14.3_HD_U_F1.jar",
+ "887d648f26f7ba17ea34c0c2dcff4096f7a226b1": "OptiFine_1.14.3_HD_U_F2.jar",
+ "ad8a8f60931f48e2873238d1460268bb4111f6c9": "OptiFine_1.14.4_HD_U_F2.jar",
+ "c9710081fb7012ddb56838ac54653ac2258a2404": "OptiFine_1.14.4_HD_U_F3.jar",
+ "c09f4d1ad66df8e3039334023422f1bc8cc211b8": "OptiFine_1.14.4_HD_U_F4.jar",
+ "3408258990309de773cc5a8ab71cb4137718a82b": "OptiFine_1.14.4_HD_U_F5.jar",
+ "117c01a5431244a8b6a3ac393374dac9624f9be6": "OptiFine_1.14.4_HD_U_G5.jar",
+ "ac602fe6a39d2fb4cadfe08e87af0b0daa2d8ac9": "preview_OptiFine_1.14.4_HD_U_G5_pre1.jar",
+ "630a32be9b711b5a479507159d5d2598189fed33": "OptiFine_1.15.2_HD_U_G6.jar",
+ "8339858b33056ec8975f6c0c9e1694a11f0d209a": "preview_OptiFine_1.15.2_HD_U_G1_pre1.jar",
+ "6cdf96d972b5f70c4575ff875a031c4931985686": "preview_OptiFine_1.15.2_HD_U_G1_pre10.jar",
+ "489d2284f2d50bd7c7cf4c216a766503d37e1f3c": "preview_OptiFine_1.15.2_HD_U_G1_pre12.jar",
+ "c66d412c4cb46c6f2c76c224dc45a62d30ee8b43": "preview_OptiFine_1.15.2_HD_U_G1_pre13.jar",
+ "582eb1d6470cc133db563bd1c2c8bc2068215806": "preview_OptiFine_1.15.2_HD_U_G1_pre18.jar",
+ "64d738862683c54a22e1856b2c13379599ca79ce": "preview_OptiFine_1.15.2_HD_U_G1_pre19.jar",
+ "3da9d466c847c50a73dc634dabc6a57f3b24e2f7": "preview_OptiFine_1.15.2_HD_U_G1_pre2.jar",
+ "e6583246a85dba26a478dd4925c298bb5b3f277a": "preview_OptiFine_1.15.2_HD_U_G1_pre20.jar",
+ "84c5d50e26aaa02733fa15a8c13ab845fbdea97f": "preview_OptiFine_1.15.2_HD_U_G1_pre21.jar",
+ "c55e449386eeca34df5b428d85927242fc841438": "preview_OptiFine_1.15.2_HD_U_G1_pre22.jar",
+ "459e17c77059671ef5daa9ab794400e8ae25095d": "preview_OptiFine_1.15.2_HD_U_G1_pre23.jar",
+ "2c6e4f61b1ceea92b76e0be40bc672e5b6d58efe": "preview_OptiFine_1.15.2_HD_U_G1_pre24.jar",
+ "4ea53e3d202239c5ffa2affa809e36998194f1bc": "preview_OptiFine_1.15.2_HD_U_G1_pre26.jar",
+ "29861ba50021b08200ef33f77c776f9f5b7135f7": "preview_OptiFine_1.15.2_HD_U_G1_pre27.jar",
+ "454dc0e03dab9d30a2ccce5823b7a0b309f5c859": "preview_OptiFine_1.15.2_HD_U_G1_pre28.jar",
+ "3c3623d75dc47722149edfb93fdca121c32e8987": "preview_OptiFine_1.15.2_HD_U_G1_pre29.jar",
+ "942e23fa0169c693fb1b645fae4db9217c6b5916": "preview_OptiFine_1.15.2_HD_U_G1_pre3.jar",
+ "bdbd92e5252c0afc0f22d6d5840f96762e5d01ea": "preview_OptiFine_1.15.2_HD_U_G1_pre30.jar",
+ "5daa9461c5762bdd647665f49d2e0ef0eb348910": "preview_OptiFine_1.15.2_HD_U_G1_pre4.jar",
+ "0029ab50050d19f4009f0a7d708982dde736f022": "preview_OptiFine_1.15.2_HD_U_G1_pre5.jar",
+ "646b279927cab6036e8f295efd5bda268acd85cf": "preview_OptiFine_1.15.2_HD_U_G1_pre7.jar",
+ "f11e79a7bc91a5fd985cb756445fc88e8c2dd31b": "preview_OptiFine_1.15.2_HD_U_G1_pre9.jar",
+ "1e9869b63a89a8ab81a58e1473dd2c2291fbd943": "preview_OptiFine_1.15.2_HD_U_G6_pre5.jar",
+ "87533b8ac0dfeb11241041f197f8f95c0ffa8c08": "OptiFine_1.16.1_HD_U_G2.jar",
+ "3e610c9bd89ae2a54cc06de6dfb1b00cd45e9895": "preview_OptiFine_1.16.1_HD_U_G2_pre1.jar",
+ "df817e1ab0e577be1dfb6c20a9b628d3d725c780": "preview_OptiFine_1.16.1_HD_U_G2_pre10.jar",
+ "dbca331e7abbe64d6aa360e6a93beec2935d24e3": "preview_OptiFine_1.16.1_HD_U_G2_pre11.jar",
+ "6fef880338cabe32443557762ca43fb36fe01f7c": "preview_OptiFine_1.16.1_HD_U_G2_pre12.jar",
+ "ea7bea6511f3b20aa672544d28dbc6d1a2ee8b41": "preview_OptiFine_1.16.1_HD_U_G2_pre13.jar",
+ "efdc788f59e1c1bcde3b64430322d8990ce7c7d6": "preview_OptiFine_1.16.1_HD_U_G2_pre14.jar",
+ "388100110b4dc8ef28eaa2f3a4ae2f33a8beb5ae": "preview_OptiFine_1.16.1_HD_U_G2_pre15.jar",
+ "63f5f097ce2e678d69767981b09b133ab8eac4f5": "preview_OptiFine_1.16.1_HD_U_G2_pre16.jar",
+ "c56031c3f6e5dcad536115e9f6a1fb5710b72391": "preview_OptiFine_1.16.1_HD_U_G2_pre2.jar",
+ "da269cdb109b6441ebed179a8d9f974590006cbb": "preview_OptiFine_1.16.1_HD_U_G2_pre3.jar",
+ "ad9b5d4e0bdd5697d4f6a6b9c30a64977bb8834e": "preview_OptiFine_1.16.1_HD_U_G2_pre4.jar",
+ "f6d5ea6cedff1f80bed298f9b456de2448b1f268": "preview_OptiFine_1.16.1_HD_U_G2_pre5.jar",
+ "f57a4269d404d4025de4d864b88510504e785e19": "preview_OptiFine_1.16.1_HD_U_G2_pre6.jar",
+ "28b46592e2f510a246a8bf62a2b12e808094167c": "preview_OptiFine_1.16.1_HD_U_G2_pre7.jar",
+ "26207daec6acc66250116e4f73295c9a031b491a": "preview_OptiFine_1.16.1_HD_U_G2_pre8.jar",
+ "6902e902866b765ff8e31716980c2067d491e004": "preview_OptiFine_1.16.1_HD_U_G2_pre9.jar",
+ "dde4274c696063496323731ad7b58e0f6d7265af": "OptiFine_1.16.2_HD_U_G3.jar",
+ "5b5627a814e8c95aa7ac27fa4cf2cc0b8bd4519b": "OptiFine_1.16.2_HD_U_G5.jar",
+ "5dafc10061020c519ba4abe4982a7dc80eae30f6": "preview_OptiFine_1.16.2_HD_U_G3_pre1.jar",
+ "0c0d9828984da34f9d5967027c244bb2c83a4396": "preview_OptiFine_1.16.2_HD_U_G3_pre2.jar",
+ "7c791e4348808132b8c7b59e6350ae2ee25a1918": "preview_OptiFine_1.16.2_HD_U_G3_pre3.jar",
+ "9a30a2cbc81095d38b4dc17e7d30a4b84e10e235": "preview_OptiFine_1.16.2_HD_U_G3_pre4.jar",
+ "ec1a4ce97e29c9ee2ac259d98e35bc386035a66d": "preview_OptiFine_1.16.2_HD_U_G3_pre5.jar",
+ "e03b0cdfbbcf01b1371b3e1090dee64e60a759d8": "preview_OptiFine_1.16.2_HD_U_G3_pre6.jar",
+ "40ae5fbb4e3724d6e5525d2688445c09ecfe5d39": "preview_OptiFine_1.16.2_HD_U_G3_pre7.jar",
+ "dc83d55f74722e1e6f503817e00e5ba2e6cb4abb": "OptiFine_1.16.3_HD_U_G3.jar",
+ "89d9472ee507946caa227e226524e5260ed944db": "OptiFine_1.16.3_HD_U_G4.jar",
+ "6a8f57ca84628da47b011e608ff449cde7ec13ed": "OptiFine_1.16.3_HD_U_G5.jar",
+ "f53bad69adaac9e523577dcb1c65b158802f3dee": "preview_OptiFine_1.16.3_HD_U_G3_pre2.jar",
+ "5b970eeae2ba07316b3e3a53da1d71de87c9f9f2": "preview_OptiFine_1.16.3_HD_U_G4_pre1.jar",
+ "599d9de6b656077b03fbebc9478924c548a6e9e0": "OptiFine_1.16.4_HD_U_G5.jar",
+ "7cce72db1f77c6178b549fa430e241eadb318f69": "OptiFine_1.16.4_HD_U_G6.jar",
+ "f49c042fa099907eafcbe22d7035d84f8b5715f1": "OptiFine_1.16.4_HD_U_G7.jar",
+ "f0b1eb59acdae57e10bb928046ee26012ef220ad": "preview_OptiFine_1.16.4_HD_U_G6_pre12.jar",
+ "ded7894eebda787b7bd5013aa8c66577f2ba03fc": "preview_OptiFine_1.16.4_HD_U_G7_pre1.jar",
+ "57cfcec3dd99b9f0950d0d6305bc95ecd8563212": "OptiFine_1.16.5_HD_U_G6.jar",
+ "706fb33784045d69e7ac5730426d813a39511dcd": "OptiFine_1.16.5_HD_U_G7.jar",
+ "137363842c5bfdebb72356a4079faeef3157eb3c": "OptiFine_1.16.5_HD_U_G8.jar",
+ "ad0f1577ce02a703185e46ee9e24fdeb65479fd5": "preview_OptiFine_1.16.5_HD_U_G7_pre10.jar",
+ "11770876367980da546c68bc95c4f794582907f2": "preview_OptiFine_1.16.5_HD_U_G7_pre11.jar",
+ "c5b32d2bad3bd54c31ddb29869a55fe44409cfe2": "preview_OptiFine_1.16.5_HD_U_G7_pre2.jar",
+ "9fc9cc09e72a3060d577f62f3535820056b0c2d4": "preview_OptiFine_1.16.5_HD_U_G7_pre4.jar",
+ "577fae32b60ac8d1b91e3fa645dc004d4a9e513e": "preview_OptiFine_1.16.5_HD_U_G7_pre5.jar",
+ "4bccf7f371ac83523796b4706569cc5077c46aea": "preview_OptiFine_1.16.5_HD_U_G7_pre6.jar",
+ "97b8d413a909354e2e0f42943cf292941dfe4c38": "preview_OptiFine_1.16.5_HD_U_G7_pre7.jar",
+ "9c48a804ee990e526000c7061bde9aa6f75d62a6": "preview_OptiFine_1.16.5_HD_U_G7_pre8.jar",
+ "9a9b69a52a4514f5d25c9f47127a822e93458fa3": "preview_OptiFine_1.16.5_HD_U_G7_pre9.jar",
+ "d16a450ec4205d02319480799008d8177ba05d69": "preview_OptiFine_1.16.5_HD_U_G8_pre1.jar",
+ "539c215aa0e8b8f696b325e89f3f9a3658ab32c8": "preview_OptiFine_1.16.5_HD_U_G8_pre10.jar",
+ "311ed81a27d24047b6ade33f46ac21c962897016": "preview_OptiFine_1.16.5_HD_U_G8_pre11.jar",
+ "4bc50f85809a299d30c3e3e73cfd87cad61cf7e6": "preview_OptiFine_1.16.5_HD_U_G8_pre12.jar",
+ "7de1b8e9f7cd6d7ca941d90121e50206aba80c68": "preview_OptiFine_1.16.5_HD_U_G8_pre13.jar",
+ "a4e021a75aab7ed1eb83ff7b45182d497aa930f2": "preview_OptiFine_1.16.5_HD_U_G8_pre14.jar",
+ "0ddcc4f47e10b2d671ebbf9147eb16cf8f1bb92a": "preview_OptiFine_1.16.5_HD_U_G8_pre2.jar",
+ "b8600be4fde6f8cc3c28173cc9bde6923956ff42": "preview_OptiFine_1.16.5_HD_U_G8_pre3.jar",
+ "d46b10098309929d9a6583323f059e65ba40a5e5": "preview_OptiFine_1.16.5_HD_U_G8_pre4.jar",
+ "e835424b36fdae3d5f46c6bf096852848127f1e7": "preview_OptiFine_1.16.5_HD_U_G8_pre5.jar",
+ "5a84983221331597f58e9636d41f1fb0c9e3de61": "preview_OptiFine_1.16.5_HD_U_G8_pre6.jar",
+ "d03ce2209d787539e5e51f80a7cbffc69a49ce9f": "preview_OptiFine_1.16.5_HD_U_G8_pre7.jar",
+ "1c646dc058aa32898917589858d900407883ba3f": "preview_OptiFine_1.16.5_HD_U_G8_pre8.jar",
+ "9bf369aa609e5612247473326dc298e6e6c9fecf": "preview_OptiFine_1.16.5_HD_U_G8_pre9.jar",
+ "b88b05278fbbf400cb5ec0cc26e0c5b7306e0c1e": "preview_OptiFine_1.17_HD_U_G9_pre16.jar",
+ "a6beac3091d17a4ba420116c75c89faeaee48539": "preview_OptiFine_1.17_HD_U_G9_pre17.jar",
+ "2839c5e74f64500561ee3e8605c51d9f06727c22": "preview_OptiFine_1.17_HD_U_G9_pre18.jar",
+ "455243ff55177189fff140ba7f4c4777cc977ef6": "preview_OptiFine_1.17_HD_U_G9_pre19.jar",
+ "bcc390e34bd529a86e6ae0e25d50417f46ba482f": "preview_OptiFine_1.17_HD_U_G9_pre20.jar",
+ "d30c23d745df54fd6ea2374e9c0b4392f0a78199": "preview_OptiFine_1.17_HD_U_G9_pre21.jar",
+ "075e7f8473b6785c3c6bbeeb41a3728f6ff3c3ba": "preview_OptiFine_1.17_HD_U_G9_pre22.jar",
+ "2ffaee36c717ae918cc93661df739740636900c9": "preview_OptiFine_1.17_HD_U_G9_pre23.jar",
+ "4385493e7ce4c6f4a3945f1d96246bce0b151c7e": "preview_OptiFine_1.17_HD_U_G9_pre24.jar",
+ "bcc33e67f134861eb30b1f0b9a829183c8afdebf": "preview_OptiFine_1.17_HD_U_G9_pre25.jar",
+ "6a8e34605cc828091027d9f011b804d916808af4": "preview_OptiFine_1.17_HD_U_G9_pre26.jar",
+ "4714bdceaefc15e0af9d5c72de8c05cf3051d760": "OptiFine_1.17.1_HD_U_G9.jar",
+ "cc64084e73d6423baf7ccbdd9f3760dd56f2fce5": "OptiFine_1.17.1_HD_U_H1.jar",
+ "1ee73bd882385a7abb9896b9469586741a6850a8": "preview_OptiFine_1.17.1_HD_U_G9_pre26.jar",
+ "537c1fbee9ebe25b49a8e6fb93db162d217f1c83": "preview_OptiFine_1.17.1_HD_U_G9_pre27.jar",
+ "68e1124f4b0376773d8d581da78f9bb6fc76486e": "preview_OptiFine_1.17.1_HD_U_G9_pre28.jar",
+ "3f80a562b39439831491c650c65ecb762e70d5f7": "preview_OptiFine_1.17.1_HD_U_G9_pre29.jar",
+ "9751c69568a61ce5b2a602b4dcf77c1cea57c709": "preview_OptiFine_1.17.1_HD_U_G9_pre30.jar",
+ "162fa1b4a0d5b89dad6030b5fd5903a3f24d39c7": "preview_OptiFine_1.17.1_HD_U_G9_pre31.jar",
+ "c4f3a33d892948927cecfaa60b284217325557c5": "preview_OptiFine_1.17.1_HD_U_G9_pre32.jar",
+ "12dbbc8ccd8dc02806768fb3fbe4a2d8c7c11301": "preview_OptiFine_1.17.1_HD_U_G9_pre33.jar",
+ "f74d1dfcb24c43e633076c63dd4492b29fca14b3": "preview_OptiFine_1.17.1_HD_U_G9_pre34.jar",
+ "42e55681fb106475ef13d5c5ef7113fb631392d4": "preview_OptiFine_1.17.1_HD_U_G9_pre35.jar",
+ "245ddb68349f5f81d067f4d9402d62db3d439d50": "preview_OptiFine_1.17.1_HD_U_H1_pre1.jar",
+ "0ac033f5ba4089311af55172281e73df143b9ac4": "preview_OptiFine_1.17.1_HD_U_H1_pre2.jar",
+ "68a3727bcdb0eac0986ff4e883d93fef406eb1c3": "preview_OptiFine_1.17.1_HD_U_H1_pre3.jar",
+ "a6534877558f0438bda604dc43093d61c6de88ae": "preview_OptiFine_1.17.1_HD_U_H1_pre4.jar",
+ "3e18db17b8695feb0a188ecdcb81b561d9d7030c": "preview_OptiFine_1.17.1_HD_U_H1_pre5.jar",
+ "c2e0c4391a671cd06931f7b6e965085c04c58762": "preview_OptiFine_1.17.1_HD_U_H1_pre6.jar",
+ "1ffb7325df5bf01b1d99bbbed8006a477b861394": "preview_OptiFine_1.17.1_HD_U_H1_pre7.jar",
+ "f2fa727e67b4795ddea3cc37cc5ced42e9c3b0c5": "preview_OptiFine_1.17.1_HD_U_H1_pre8.jar",
+ "aee167aff9937a068d514c85e3f8c766db99ed43": "preview_OptiFine_1.17.1_HD_U_H1_pre9.jar",
+ "59709e09632c80ab80ffcc4b5bf380d073bf467f": "preview_OptiFine_1.17.1_HD_U_H2_pre1.jar",
+ "52629bc5319ec203edd42de1776cb8d67a0e6b1b": "OptiFine_1.18_HD_U_H3.jar",
+ "e5077b4be03956118613162b5dbcf90406b27747": "preview_OptiFine_1.18_HD_U_H3_pre7.jar",
+ "326c160481cc849bccb821939992c101a8fe163b": "OptiFine_1.18.1_HD_U_H4.jar",
+ "1679654fdf49fd1216b090d51d3d8ec906094619": "OptiFine_1.18.1_HD_U_H5.jar",
+ "c86534ee821a78efc741c9cb407eec76625e1bab": "OptiFine_1.18.1_HD_U_H6.jar",
+ "34c98382131efa1394cff06528238dc44d255794": "preview_OptiFine_1.18.1_HD_U_H4_pre1.jar",
+ "d6cd0a2d0243ecad107220bff639eb46277762ea": "preview_OptiFine_1.18.1_HD_U_H5_pre1.jar",
+ "e24d766864f9238b94be5b3ad65608d7eb521fad": "preview_OptiFine_1.18.1_HD_U_H5_pre2.jar",
+ "bc1b87a6379acf5a5dca2a56196080ace49e4864": "preview_OptiFine_1.18.1_HD_U_H5_pre3.jar",
+ "555a6b8e420bd63a04d9f338d61f3333b4ccf5d9": "preview_OptiFine_1.18.1_HD_U_H5_pre4.jar",
+ "1d02694393f10992cbbd11a802568b0890b4dc81": "preview_OptiFine_1.18.1_HD_U_H5_pre5.jar",
+ "e3a22adc6931dcd7513f26afa1adecd62a35641b": "preview_OptiFine_1.18.1_HD_U_H5_pre6.jar",
+ "445a8cb8a1d565d8a1fabc0ba984c5936edbf561": "OptiFine_1.18.2_HD_U_H6.jar",
+ "8d83d4d5e325887e000a462029d2bf7a6e77eebc": "OptiFine_1.18.2_HD_U_H7.jar",
+ "2a461188167c1da6b1cfd520d85a656f45c74d70": "OptiFine_1.18.2_HD_U_H9.jar",
+ "e591777f272df533b62260a6dbe0e6cde62066f6": "preview_OptiFine_1.18.2_HD_U_H6_pre1.jar",
+ "f7c727c99e7f58ef9b86cc96fb894f628391016c": "preview_OptiFine_1.18.2_HD_U_H7_pre1.jar",
+ "cb51529f94e0eff5b9da92c8f70b1d498662a115": "preview_OptiFine_1.18.2_HD_U_H7_pre2.jar",
+ "ceea3c6612d2ec36c6ef1ca4a9355a141df9089f": "preview_OptiFine_1.18.2_HD_U_H7_pre3.jar",
+ "596c3a399889c3e2ef1d8fee994e8cf5a91e457e": "preview_OptiFine_1.18.2_HD_U_H8_pre1.jar",
+ "85f545aeb9d232ae970b0efa24e833f9c5d0fe33": "preview_OptiFine_1.18.2_HD_U_H9_pre1.jar",
+ "b9bbabb8f31f2b04ca1a1a8645df1be701f705bd": "preview_OptiFine_1.18.2_HD_U_H9_pre2.jar",
+ "c2bf213b4f60b6a29e402e3eaf219a4c85a5d1e6": "preview_OptiFine_1.18.2_HD_U_H9_pre3.jar",
+ "64c8c35313d25a64a8a8677cb851a2c83556ddc8": "OptiFine_1.19_HD_U_H8.jar",
+ "c668eaf9b6ce4e64f26a29fb27e830229ab4bef3": "OptiFine_1.19_HD_U_H9.jar",
+ "cda9130e0d36f0d6e06950ab393a8929b502a440": "preview_OptiFine_1.19_HD_U_H8_pre1.jar",
+ "cd1ae81f544672df776dc4426269771d2e82d0b2": "preview_OptiFine_1.19_HD_U_H8_pre10.jar",
+ "cb3ad2a9b4c23675ca569058f55dd174eed67a38": "preview_OptiFine_1.19_HD_U_H8_pre2.jar",
+ "2f7139ea0888ed18006e3a39b7475e88a3fd545d": "preview_OptiFine_1.19_HD_U_H8_pre3.jar",
+ "85cd70bb714e65935abf351811889a47a648bb96": "preview_OptiFine_1.19_HD_U_H8_pre4.jar",
+ "c65cbae4c1cfb5b9a5a573e4b83424df2d81b172": "preview_OptiFine_1.19_HD_U_H8_pre5.jar",
+ "10cd57890ebf449f5c258cff1c60d8dcefcc6cf6": "preview_OptiFine_1.19_HD_U_H8_pre6.jar",
+ "eb03e60c2fa9904a47eec1ef4a2c8804ee6cc0b8": "preview_OptiFine_1.19_HD_U_H8_pre7.jar",
+ "40d0b514168161fdefc91594f0d3f774f831d7de": "preview_OptiFine_1.19_HD_U_H8_pre8.jar",
+ "8e5bedd1c1a3641caad0743c4629db51c11f8feb": "preview_OptiFine_1.19_HD_U_H9_pre1.jar",
+ "7745216a810f0d617ed17a520fda44e12456492f": "preview_OptiFine_1.19_HD_U_H9_pre2.jar",
+ "6d6ed920eb99836e76549a7803af85881fcdee34": "preview_OptiFine_1.19_HD_U_H9_pre3.jar",
+ "7604e63ca74876b4e8ea9c3a36dbe80111c776b1": "preview_OptiFine_1.19_HD_U_H9_pre4.jar",
+ "b42dcce86c88ad4bcfa52a9d297afa800477aa78": "OptiFine_1.19.1_HD_U_H9.jar",
+ "648427a02940b3c53b3678cd5df1ff6997bd1e6c": "preview_OptiFine_1.19.1_HD_U_H9_pre1.jar",
+ "7cc221a6df6831b62c3b676b5f958e82a4487fd8": "OptiFine_1.19.2_HD_U_H9.jar",
+ "f304c56c7ab9119ce4269f2b019cd4668f48376d": "OptiFine_1.19.2_HD_U_I1.jar",
+ "708c1ecc148a0bd7d341e8f5e005e670903650f7": "OptiFine_1.19.2_HD_U_I2.jar",
+ "e0e924990bd12cc499fc89439f0b2c50b6e147fa": "preview_OptiFine_1.19.2_HD_U_I1_pre1.jar",
+ "465b229481c0a285195a168bf6581549a5cd7373": "preview_OptiFine_1.19.2_HD_U_I1_pre2.jar",
+ "af4398d0ce0628bcc0204e61c157e3c8951b9ad5": "preview_OptiFine_1.19.2_HD_U_I1_pre3.jar",
+ "35ef18f953bbea9a4cba6e14d0731d56f888114f": "preview_OptiFine_1.19.2_HD_U_I1_pre4.jar",
+ "b24d8725a8d06e1c190d1d2b3bc51c899f74b36d": "OptiFine_1.19.3_HD_U_I3.jar",
+ "f5ce615d9886e377079fd13cc4700a51d5a9c7b6": "preview_OptiFine_1.19.3_HD_U_I2_pre1.jar",
+ "10e6d97ea2c97cf0575a7c587fb11e1ddb73aa71": "preview_OptiFine_1.19.3_HD_U_I2_pre2.jar",
+ "89718cd608225d7c23f7e180d011daa4a47ce6bd": "preview_OptiFine_1.19.3_HD_U_I2_pre3.jar",
+ "204baf0fd59432054aebd2f83c83fe15fdd3e611": "preview_OptiFine_1.19.3_HD_U_I2_pre4.jar",
+ "90a52b3adc94a1b9a70f03f4c4ea14dfdf3424d8": "preview_OptiFine_1.19.3_HD_U_I2_pre5.jar",
+ "050d787936cc239ea8db0aa250d2ed72a44fa71d": "OptiFine_1.19.4_HD_U_I3.jar",
+ "253e9d29c6826c134fbdeea074d1d91c3410225c": "OptiFine_1.19.4_HD_U_I4.jar",
+ "068b998d6c5db5b3bb7ad6a0a7d0c6aefc4dc191": "preview_OptiFine_1.19.4_HD_U_I3_pre3.jar",
+ "a8b9156811c4745dbd612ebbb1df6f93d2fa734a": "preview_OptiFine_1.19.4_HD_U_I3_pre4.jar",
+ "6f2793e6236a27c06a74e8a1876ea6b29be038a7": "preview_OptiFine_1.19.4_HD_U_I3_pre5.jar",
+ "9ad82ef9f32fb5a0e7e7e0c7e8906c9f319a9705": "preview_OptiFine_1.19.4_HD_U_I3_pre6.jar",
+ "cf02ee8b5cf6922fbc28d6ffc8183949fff55d49": "preview_OptiFine_1.19.4_HD_U_I3_pre7.jar",
+ "702e0e9987209f66a5b4f825e7ac658fd49dd4b1": "preview_OptiFine_1.19.4_HD_U_I3_pre8.jar",
+ "04c8eaeadf24c42929500812a8f3f5fe634f0d1f": "preview_OptiFine_1.19.4_HD_U_I3_pre9.jar",
+ "968784e051c2c44f10a4ab448c979572977969c0": "preview_OptiFine_1.19.4_HD_U_I4_pre1.jar",
+ "abe4b1dbda7d95eb47953ef8aa11ed8ed1d8e238": "preview_OptiFine_1.20_HD_U_I5_pre3.jar",
+ "6612ce97d846018126f91cdbae23f0eff6bd2bab": "preview_OptiFine_1.20_HD_U_I5_pre4.jar",
+ "f37d62b6a071f6cd3d6bdfa378b56f7f5b9ec7c6": "preview_OptiFine_1.20_HD_U_I5_pre5.jar",
+ "c44bd276edd10fa910d929a4e7f6b8c7ffe6c23f": "OptiFine_1.20.1_HD_U_I5.jar",
+ "227914ab1037762eae44a2e66a568b87d7a02365": "OptiFine_1.20.1_HD_U_I6.jar",
+ "7484cf60bd8e019c40fa448daa294bd31f52962b": "preview_OptiFine_1.20.1_HD_U_I5_pre4.jar",
+ "953b1b4f15f56329bc4ade851846ef004ebbd5d0": "preview_OptiFine_1.20.1_HD_U_I5_pre5.jar",
+ "ebbdb3076f8291d7f8e10cbec3b1d3c49a0a701d": "preview_OptiFine_1.20.1_HD_U_I5_pre6.jar",
+ "b831d59eeb63122893f87a62ec3e5b3f1cc5586a": "preview_OptiFine_1.20.1_HD_U_I5_pre7.jar",
+ "dc93d991b07b2c5c6d2cd50a553599900c256264": "preview_OptiFine_1.20.1_HD_U_I5_pre8.jar",
+ "040a73427541170bccf162c04f4129b3909b8da1": "preview_OptiFine_1.20.1_HD_U_I5_pre9.jar",
+ "9f5fd75ede7770ad35383443b0a203f026cef5db": "preview_OptiFine_1.20.1_HD_U_I6_pre1.jar",
+ "85d5566b440036b926c5dd306108e48e7fb9b6e8": "preview_OptiFine_1.20.1_HD_U_I6_pre2.jar",
+ "d09c110358117336472414720bf961a581690dc5": "preview_OptiFine_1.20.1_HD_U_I6_pre3.jar",
+ "3365577f5161f9a1bbfefb15675bb5ece27600e4": "preview_OptiFine_1.20.1_HD_U_I6_pre4.jar",
+ "f317c701ae8c533fc34809dbce914bcced4e9a03": "preview_OptiFine_1.20.1_HD_U_I6_pre5.jar",
+ "445b32b14a2c2802d5a0832a708712d2fabafbc2": "preview_OptiFine_1.20.1_HD_U_I6_pre6.jar",
+ "9ea6b1389e88b81797f54b9d8d1e870d3fe8532c": "preview_OptiFine_1.20.2_HD_U_I7_pre1.jar",
+ "f2475e8d5746477d1d2972cd5aae62a5d9c04264": "OptiFine_1.20.4_HD_U_I7.jar",
+ "fec28a2fa152744bc2b47b3c5db3217974aa57ee": "preview_OptiFine_1.20.4_HD_U_I7_pre2.jar",
+ "4068365a57f4b154f4ebbc670894dc9038cf3819": "preview_OptiFine_1.20.4_HD_U_I7_pre3.jar",
+ "2481e0bed7610bfdfe26dea5a6bd8f01537c4ea8": "preview_OptiFine_1.20.4_HD_U_I7_pre4.jar",
+ "150990ba068cfb55bbf9e525c5ab84db0b8903e1": "preview_OptiFine_1.20.4_HD_U_I7_pre5.jar",
+ "fcf0f0f278d1901e4341d5ec8022bede03572430": "preview_OptiFine_1.20.4_HD_U_I7_pre6.jar",
+ "1c3395efa928758505b808291162a2514523b399": "preview_OptiFine_1.20.4_HD_U_I7_pre7.jar",
+ "4bcfec24e5d917ee96e0de6ef095bfc08782217b": "preview_OptiFine_1.20.4_HD_U_I8_pre1.jar",
+ "c931df21309800f1d1ece59b318e6b3e39c98176": "preview_OptiFine_1.20.4_HD_U_I8_pre2.jar",
+ "83f5ad147536405d86bf4ee47a7f7970e1fa8329": "preview_OptiFine_1.20.4_HD_U_I8_pre3.jar",
+ "7c6669319db18c9622d896da2a061479be88acf5": "preview_OptiFine_1.20.4_HD_U_I8_pre4.jar",
+ "bda7bbdd5e2d8c73148372e8c3b34d7c2485a4e8": "preview_OptiFine_1.20.6_HD_U_J1_pre18.jar",
+ "24a20f949a719480523669669a4e5e7339df6186": "OptiFine_1.21.1_HD_U_J1.jar",
+ "6bc74af8f733864539404a3f087aeb6f0cadc6b1": "preview_OptiFine_1.21.1_HD_U_J1_pre10.jar",
+ "4813a6cde6b0f5b20223d486ba7adf0816236a77": "preview_OptiFine_1.21.1_HD_U_J1_pre11.jar",
+ "c99ea98d8537f99b7470f1bcfa81c7ce405fd97e": "preview_OptiFine_1.21.1_HD_U_J1_pre12.jar",
+ "f2f55e6d61a4b90bdaa31eb520f5af78f8a1833b": "preview_OptiFine_1.21.1_HD_U_J1_pre13.jar",
+ "53a15b75ea9d20b644b0d3e9c7280ba172ade053": "preview_OptiFine_1.21.1_HD_U_J1_pre14.jar",
+ "da5575e1138fc2a4c28779cfc5e7d260253ccbdb": "preview_OptiFine_1.21.1_HD_U_J1_pre15.jar",
+ "0930876341beadf7014f57e9ebdd44be445dacbe": "OptiFine_1.21.3_HD_U_J2.jar",
+ "350f63ec3e59d21227f803d4078883884e482660": "preview_OptiFine_1.21.3_HD_U_J2_pre10.jar",
+ "2c48a4210acd25082c220f9601f17d1cc7769098": "preview_OptiFine_1.21.3_HD_U_J2_pre11.jar",
+ "8f0a097b1f7c9d065396bac9230eab62412a8b54": "preview_OptiFine_1.21.3_HD_U_J2_pre12.jar",
+ "f97df5638fcda7f4380d9284b329569d4e1554aa": "preview_OptiFine_1.21.3_HD_U_J2_pre8.jar",
+ "77df50552deea51687592b60c6d24561ee11aa74": "preview_OptiFine_1.21.3_HD_U_J2_pre9.jar",
+ "bcc6a7a140320566a985b1499a59fcb085255d14": "OptiFine_1.21.4_HD_U_J3.jar",
+ "e7bff4575b7311e11d7111506e855b4ad910481f": "preview_OptiFine_1.21.4_HD_U_J3_pre10.jar",
+ "52b2b6defdb8d1c189afb42125079f1b76ff72e2": "preview_OptiFine_1.21.4_HD_U_J3_pre11.jar",
+ "708f70aa5f70919a40d02ba75fc30d2d60c8e7cd": "preview_OptiFine_1.21.4_HD_U_J3_pre12.jar",
+ "86b796325d03d4571809a155c54cf6cba7c7482b": "preview_OptiFine_1.21.4_HD_U_J3_pre13.jar",
+ "618719a6a69eb674ea50c82cffe3d4e3c2f67abf": "preview_OptiFine_1.21.4_HD_U_J3_pre14.jar",
+ "98dd84b0581fcf7a27aa96238acb615b5b719825": "preview_OptiFine_1.21.4_HD_U_J3_pre15.jar",
+ "5c8573ae921082a069a9e7269500178f0c580c97": "preview_OptiFine_1.21.4_HD_U_J3_pre4.jar",
+ "17d51e1bfc94dde95368ab91aa0bb56e89c706bf": "preview_OptiFine_1.21.4_HD_U_J3_pre5.jar",
+ "1a4311606ac94d682800714793ea887c3276b18d": "preview_OptiFine_1.21.4_HD_U_J3_pre6.jar",
+ "12bf1a1b5607b5c62405a8c6ab4e1bd02bef2c8d": "preview_OptiFine_1.21.4_HD_U_J3_pre7.jar",
+ "f1f56403dc575fd975a000bfb133060285cacd6f": "preview_OptiFine_1.21.4_HD_U_J3_pre8.jar",
+ "9584de0e8204f5c855b60741d58af967dfc599a8": "preview_OptiFine_1.21.4_HD_U_J3_pre9.jar",
+ "0b97631e166ace9346744de33b7772df7bf5fbeb": "preview_OptiFine_1.21.4_HD_U_J4_pre1.jar",
+ "a776ec6c072529d4b731e0e6929a8aee56d04e76": "preview_OptiFine_1.21.4_HD_U_J4_pre2.jar",
+ "2a3fdfcbfc9c572b22c7d15c6129b8ea58ea1712": "preview_OptiFine_1.21.8_HD_U_J6_pre13.jar",
+ "ba7ca56c9b33d2fc7f7d22e20ce2765e4d257299": "preview_OptiFine_1.21.8_HD_U_J6_pre14.jar",
+ "097d3acd315b0682a4565ab9cbb4cdc1cc17d81f": "preview_OptiFine_1.21.8_HD_U_J6_pre15.jar",
+ "d7effca0de34c9442f06776848679a684f1f166a": "preview_OptiFine_1.21.8_HD_U_J6_pre16.jar",
+ "696ed52cdfd0ac2eafab8e98575d146b400de530": "preview_OptiFine_1.21.10_HD_U_J7_pre10.jar",
+ "be7bc81f0c9ce15316f76a059b0a690f62c03a5d": "preview_OptiFine_1.21.10_HD_U_J7_pre11.jar",
+ "731e698abe94bbd90cda628f80b4ce6ac5af8188": "preview_OptiFine_1.21.10_HD_U_J7_pre6.jar",
+ "63f189a4b7ff5b53e5bc56391f5274eab8555def": "preview_OptiFine_1.21.10_HD_U_J7_pre7.jar",
+ "7ccfc0085ccdef3f4ec21918a059ddd05171711a": "preview_OptiFine_1.21.10_HD_U_J7_pre8.jar",
+ "aad53ad3346944a12ed088ffbba98cf9eccc474c": "preview_OptiFine_1.21.10_HD_U_J7_pre9.jar",
+ "2800efeb56565f23494d372e7edac29333113e11": "OptiFine_1.21.11_HD_U_J8.jar",
+ "cee35b83c75da33dc07ffbb344386cae5cdc5c5b": "OptiFine_1.21.11_HD_U_J9.jar",
+ "687046282c370e690ec4b4aa6d90a6b42ada3ee1": "preview_OptiFine_1.21.11_HD_U_J8_pre10.jar",
+ "c09b05637610072bc33023d1c901e2726b7d16ce": "preview_OptiFine_1.21.11_HD_U_J8_pre11.jar",
+ "88682b40f08f462c4daae8e6b25ea99b1ed5cd14": "preview_OptiFine_1.21.11_HD_U_J8_pre12.jar",
+ "1c69de725c249d487df676470c71a7c05ece943c": "preview_OptiFine_1.21.11_HD_U_J8_pre3.jar",
+ "921b68e014539d75b77a47ca2117fc9e09ace4ed": "preview_OptiFine_1.21.11_HD_U_J8_pre4.jar",
+ "2fee496a35eeebf39fbb43017b12d752f5c37dee": "preview_OptiFine_1.21.11_HD_U_J8_pre5.jar",
+ "e5b5da810d43c02dccedfd99f83ae8ad63e49966": "preview_OptiFine_1.21.11_HD_U_J8_pre6.jar",
+ "8309638bab4d99258354b4d13c3cd82ff7c9645b": "preview_OptiFine_1.21.11_HD_U_J8_pre7.jar",
+ "b3d208ec7b5015842fcc77b3399b04b24e0b54cb": "preview_OptiFine_1.21.11_HD_U_J8_pre8.jar",
+ "c4ac7401bb5f668e4e92121501d1537cdbe7343c": "preview_OptiFine_1.21.11_HD_U_J8_pre9.jar",
+ "fd96031b5fc4c41ad71581eea53eb122022fff5b": "preview_OptiFine_1.21.11_HD_U_J9_pre1.jar",
+ "a159a217aba02cd7897394a51bd346c3b658b9f9": "preview_OptiFine_1.21.11_HD_U_J9_pre2.jar",
+ "2a784437076b539ea1a3c1a37ec98ff21bc3952c": "preview_OptiFine_1.21.11_HD_U_J9_pre3.jar",
+ "ee32ce4b406e290a0e99685afd09dc44cad03ddd": "preview_OptiFine_1.21.11_HD_U_J9_pre4.jar"
+}
diff --git a/PCLCS/PCLCS.csproj b/PCLCS/PCLCS.csproj
index ad6fb5f..f4a3203 100644
--- a/PCLCS/PCLCS.csproj
+++ b/PCLCS/PCLCS.csproj
@@ -27,6 +27,7 @@
+
@@ -58,6 +59,7 @@
+
diff --git a/PCLCS/Resource/WikiEntries.txt b/PCLCS/Resource/WikiEntries.txt
index af27856..8adca9b 100644
--- a/PCLCS/Resource/WikiEntries.txt
+++ b/PCLCS/Resource/WikiEntries.txt
@@ -3,7 +3,7 @@ industrial-craft@|工业时代2 (Industrial Craft 2)
@redpower2-core|红石力量2 (RedPower2)
buildcraft@|建筑 (BuildCraft)
forestry@|林业*
-railcraft@railcraft-reborn|铁路*¨railcraft-reborn|铁路 (Railcraft)
+railcraft|铁路*
@ee2|等价交换2 (Equivalent Exchange 2)
@@ -16,7 +16,7 @@ powerconverters-portablejims-fork|能源转换 (PowerConverters)¨powerconverter
modular-forcefield-system|模块化力场系统*
-minechem-recompile|化学 (MineChem) - 非官方重编译版¨minechem-archive|化学 (MineChem)¨73373|化学 (MineChem)
+minechem|化学 (MineChem)¨minechem-recompile|化学 (MineChem) - 非官方重编译版¨minechem-archive|化学 (MineChem)
iron-chests@|更多箱子*¨iron-chests-for-fabric@cyberanner-ironchest|更多箱子 (Iron Chests)¨iron-chests-fabric@|更多箱子 (Iron Chests)
balkons-weaponmod|更多武器 (Balkon's WeaponMod)
advanced-machines|高级机械 (AdvancedMachines) - Chocohead版¨@advanced-machines-uuum|高级机械 (AdvancedMachines) - Immibis版
@@ -192,7 +192,7 @@ invasions|入侵 (Invasion)
mb-battlegear-2|挖矿与砍杀:双持与战备 2 (Mine & Blade: Battlegear 2)
galacticraft-legacy@|星系 (GalactiCraft)
-
+classic-dungeon-pack-mod|地牢拓展 (DungeonPack)
journeymap@|旅行地图 (JourneyMap)
@@ -205,7 +205,7 @@ ars-magica-2|魔法艺术2*
highlands|高地*
doggy-talents|小狗天才*
plasmacraft|电浆工艺 (PlasmaCraft)
-
+more-health-enhanced|更多生命 (More Health ENHANCED)
fossils@fossils-and-archeology-revival|考古与化石 (Fossils and Archeology Revival)
glenns-gases|格林的气体 (Glenn's Gases)
the-lord-of-the-rings-mod-legacy|魔戒:传承 (The Lord of the Rings Mod: Legacy)
@@ -232,7 +232,7 @@ animal-bikes|动物坐骑*
electro-magic-tools|电力魔法工具 (Electro-Magic Tools)
forbidden-magic|禁忌魔法*
mobtalker2|怪物交谈2 (MobTalker 2)
-icbm-classic@icbm|洲际导弹 (ICBM)¨icbm|洲际导弹 (ICBM) - 已停更
+icbm-2|洲际导弹 (ICBM) - 已停更
thaumic-infusion|神秘注魔*
thaumic-exploration|神秘探险*
deconstruction-table|解构工作台*
@@ -278,7 +278,7 @@ betterfarming|农业增强 (Better Farming)
lots-of-food|更多食物 (Lots of Food)
-aquaculture@|水产业2/水产品2 (Aquaculture 2)
+aquaculture@|水产业2 / 水产品2 (Aquaculture 2)
project-bench|高级工作台*
apples-plus|更多苹果 (Apples+)
@@ -323,7 +323,7 @@ metallurgy|冶金*
school-mod-forge-1-14|学校 (School Mod)
witchery|巫术*
-growthcraft|生长工艺 (GrowthCraft)¨growthcraft-community-edition|生长工艺 (GrowthCraft)
+growthcraft-community-edition|生长工艺 (GrowthCraft / Growthcraft Community Edition)¨growthcraft|生长工艺 (GrowthCraft / Growthcraft Community Edition)
gregtech-5-unofficial|格雷科技5 (GregTech 5)
mantle@|地幔*
@@ -399,7 +399,7 @@ atomicstrykers-magic-yarn|AtomicStryker的魔法线 (AtomicStryker's Magic Yarn)
teds-old-world-gen-mod|怀旧地形 (Old World Gen)
-academycraft|超能力/学园都市 (AcademyCraft)
+academycraft@|超能力/学园都市 (AcademyCraft)¨academycraft-official|超能力/学园都市 (AcademyCraft) - 接手后的
the-spice-of-life|生活调味料 (The Spice of Life)
@@ -697,7 +697,7 @@ clockwork-phase|时之沙*
autoreglib@
roots|根源魔法*
-guide-api|指南 (Guide-Api)¨@guide-api-legacy|指南 (Guide-Api) - Archive
+guide-api|指南 (Guide-API)¨@guide-api-legacy|指南 (Guide-API) - Archived
fraghappy-reborn
genetics-reborn|基因重生*
@@ -709,7 +709,7 @@ taoism|御灵*
essentialcraft-4-unofficial|源质魔法4非官方版 (EssentialCraft 4 Unofficial)
celestial-craft|天体*
lost-thaumaturgy|失落神秘 (Pengu's Lost Thaumaturgy)
-compact-machines|更多空间/压缩空间*
+compact-machines|更多空间 / 压缩空间*
ex-nihilo-omnia|无中生有-世间万物*
last-sword-you-will-ever-need-mo@the-last-sword-you-will-ever-need-mod|最终之剑 (The Last Sword You Will Ever Need Mod)
@@ -719,12 +719,12 @@ ftb-library-legacy-forge|FTB Library(旧版) (FTB Library (Forge) (Legacy))
thaumic-potatoes-2|神秘土豆2*
-extraplanets|额外行星 (Extra Planets)
+extraplanets@|额外行星 (Extra Planets)
xtracraft-mod|X工艺 (XtraCraft Mod)
formivore-generators-walled-city-great-wall-ca|城墙城市生成 (Cellular Automata Generator/Great Wall Mod/Walled City Generator)
-
+icbm@|洲际导弹经典版 (ICBM - Classic)
voltz-engine
blocklings|方块酱*
@@ -923,7 +923,7 @@ better-hud|更好的HUD (Better HUD)
custom-stuff-4|自定义物品4*
powered-thingies|特斯拉科技 (Tesla Powered Thingies)
-mcmusicplayer#t1:description
+mcmusicplayer
obsidian-suite
wizards-of-lua|Lua魔导师 (Wizards of Lua)
mystical-agriculture@|神秘农业*
@@ -1113,7 +1113,7 @@ avaritiaddons|无尽收容 / 更多空间箱子*
base
immersive-cables|沉浸线缆*
-better-title-screen|更好的标题页*
+better-title-screen@bettertitlescreen|更好的标题页*
sound-filters|声音滤波器*
lambda-craft|半条命 (LambdaCraft)
vivecraft@¨vivecraft-forge-extensions
@@ -1161,7 +1161,7 @@ jaopcaadditions|JAOPCA附属 (JAOPCAAdditions)
cloche-call
mouse-tweaks|鼠标手势*¨@mouse-tweaks|鼠标手势 (Mouse Tweaks) - 仅部分
jargca|JAOPCA神秘农业附属 (Just A Resource Generation Compatibility Attempt)
-sky-resources|空岛资源2 (Sky Resources2)
+sky-resources|空岛资源2 (Sky Resources 2)
hexxit-gear|Hexxit 装备*¨hexxit-gear-restored|Hexxit 装备 (Hexxit Gear)
magic-clover|幸运四叶草*
@@ -1264,7 +1264,7 @@ crop-eating-animals|动物自动喂食 (Crop-Eating Animals)
refraction|折射*
librarianlib@|图书馆 (LibrarianLib)
-creeper-confetti@|烟花苦力怕*
+creeper-confetti@|烟花苦力怕 / 烟火苦力怕*
funnels|液体漏斗*
advent-of-ascension-nevermine@adventofascension|虚无世界 (Nevermine)
toroquest|托罗探索 (Toro Quest)
@@ -1633,7 +1633,7 @@ deep-mob-learning|深度怪物学习*
tofucraftreload@|豆腐工艺重制版 (TofuCraftReload)
electroblobs-wizardry|巫术学 (Electroblob's Wizardry)
moarsigns|更多告示牌 (MoarSigns)
-kamen-rider-craft|假面骑士工艺*
+kamen-rider-craft@|假面骑士工艺*
avaritia-io|无尽贪婪:接口 (Avaritia IO)
dense-neutron-collectors|致密中子态素收集器*¨dense-neutron-collectors-1-7|致密中子态素收集器 (Dense Neutron Collectors)
pubgmc-mod
@@ -1711,7 +1711,7 @@ terrarium@|地球*
climatic-biomes
howling-moon|狼人*
hostile-worlds-invasions|敌对世界-入侵 (Hostile Worlds - Invasions)
-simple-storage-network|简单存储*
+simple-storage-network@|简单存储*
2973537|虚无世界1 (Eternal Isles)
scaling-health@
minecoprocessors|微处理器*
@@ -1741,7 +1741,7 @@ ping
the-legends-mod
bad-wither-no-cookie-reloaded¨bad-wither-no-cookie-reloaded-fabric
giacomos-fishing-net
-the-hospital-mod|医院 Mod*¨hospital-mod-facilities-pack|医院 Mod (The Hospital Mod)¨hospital-mod-theatres-pack|医院 Mod (The Hospital Mod)¨hospital-mod-pharmacy-pack|医院 Mod (The Hospital Mod)
+the-hospital-mod|医院 Mod*¨hospital-mod-pharmacy-pack|医院 Mod (The Hospital Mod)¨hospital-mod-facilities-pack|医院 Mod (The Hospital Mod)¨hospital-mod-theatres-pack|医院 Mod (The Hospital Mod)¨hospital-mod-xpansions-walls-and-flooring-pack|医院 Mod (The Hospital Mod)
more-charcoal|更多木炭*
born-in-a-barn@
@@ -1970,7 +1970,7 @@ hearth-well
tea-and-biscuits|茶和饼干*
controllable|手柄控制*¨controllable-fabric|手柄控制 (Controllable)
genetic-animals@|遗传动物*
-stone-chest|石头箱子*
+stone-chest@|石头箱子*
iron-shulker-boxes@|更多潜影盒*
mob-dismemberment|怪物肢解*
zoo-wild-animals-rebuild|野生动物园:重制版 (Zoo & Wild Animals Rebuilt)
@@ -2019,7 +2019,7 @@ tetra@
minestrappolation-5
underwater-biome|深海生态*
create@|机械动力*¨create-fabric@|机械动力 (Create)
-super-tnt-port|超级 TNT (Super TNT Mod)
+super-tnt-port|超级 TNT (Super TNT Mod) - 授权续作及转载¨@super-tnt-mod|超级 TNT (Super TNT Mod)
energeticsheep@energetic-sheep|脉冲羊 (EnergeticSheep)
ensorcellation@|万象*
@@ -2035,12 +2035,12 @@ modular-diversity|模块化多样性*
botanic-bonsai|植物魔法盆栽*
modular-magic|模块化魔法*
-schools-of-magic-mod|魔法王国 (Magic Kingdoms Mod/Schools of Magic Mod)¨magic-kingdoms-mod|魔法王国 (Magic Kingdoms Mod/Schools of Magic Mod)
+schools-of-magic-mod|魔法王国 / 魔法学校 (Magic Kingdoms Mod / Schools of Magic Mod)¨magic-kingdoms-mod|魔法王国 / 魔法学校 (Magic Kingdoms Mod / Schools of Magic Mod)
zollern-galaxy|卓伦星系*
macaws-bridges@|Macaw的桥梁 (Macaw's Bridges)
trample-stopper|防止踩踏*¨trample-stopper-fabric|防止踩踏 (Trample Stopper)
-macaws-roofs@|Macaw的屋顶 (Macaw's Roofs)
+macaws-roofs@|Macaw 的屋顶 (Macaw's Roofs)
shadows-of-greg|格雷之影 (Shadows of Greg)
loottabletweaker@
rockycore
@@ -2114,7 +2114,7 @@ emerging-technology-hydroponics|新兴技术 (Emerging Technology)
twilightopia-phantasy|暮托邦之梦 (Twilightopia)
engineers-decor|工程师的装饰 (Engineer's Decor)
engineers-tools|工程师的工具 (Engineer's Tools)
-wesleys-roguelike-dungeons@|Wesley的冒险地牢 (Wesley's Roguelike Dungeons)
+wrd@wesleys-roguelike-dungeons|Wesley的冒险地牢 (Wesley's Roguelike Dungeons)
xp-tome@|经验之书*
varied-commodities
tinkers-things|匠魂扩增 (Tinkers' Things)
@@ -2190,7 +2190,7 @@ electro-magic-tools-ic2-classic|电子神秘工具 (Electro-Thaumic Tools - IC2
forceasciifont|强制ASCII字体 (ForceASCIIFont)
skewers|烤串*
get-in-the-bucket-mod@|进入水桶*¨get-in-the-bucket-mod-fabric|进入水桶 (Get In The Bucket Mod)
-fertilization|施肥*¨fertilization-fabric|施肥 (Fertilization)
+fertilization@|施肥*¨fertilization-fabric|施肥 (Fertilization)
additional-banners@|更多旗帜*
dropt
the-elven-forest|精灵森林 (The Elven Forest)
@@ -2250,7 +2250,7 @@ OpenSecurity|开放式安全*
the-legend-era|传说纪元*
level-up-hp-forge|生命提升 (Level Up HP)¨level-up-hp|生命提升 (Level Up HP)
more-planet-extras
-randompatches@|随意修复 (RandomPatches)¨randompatches-fabric|随意修复 (RandomPatches)
+randompatches-forge@randompatches|随意修复 (RandomPatches)¨randompatches-fabric|随意修复 (RandomPatches)
ships-mod|船*
tfc-metric|公制重量转换 (TFC Metric)
@@ -2449,7 +2449,7 @@ better-drowning@|更好的溺水*
bibliotheca
kubejs@¨kubejs-fabric
tickcentral
-lowocalizatiwn
+l12n
redlib
modern-ui@|现代化 UI (Modern UI)
auto-config-updated-api
@@ -2807,7 +2807,7 @@ minema
tfctech-unofficial|群峦工业非官方版 (TFCTech Unofficial)
@ee1|等价交换 (Equivalent Exchange)
invmove@|边拿边走 (InvMove)¨invmove-fabric|边拿边走 (InvMove)¨invmove-forge|边拿边走 (InvMove)
-autofish-for-forge|自动钓鱼Forge版 (AutoFish for (Neo)Forge)
+autofish-for-forge|自动钓鱼Forge版 (AutoFish for Everyone)
industrial-upgrade@industrialupgrade|工业升级*
rpgstats@
datapackrecipemaker|数据包配方助手 (Datapack Recipe Maker)
@@ -2829,7 +2829,7 @@ blood-in-the-water
bio-technik
-astromine-fabric|天体矿工 (Astromine - Machines n' Space!)
+astromine-fabric|天体矿工 (Astromine)
rustic-thaumaturgy|神秘乡村*
thallium|铊*
@@ -3206,7 +3206,7 @@ jeitweaker@
yungs-law
libx@
atmospheric@|悠然一派*
-monospace-font|等宽字体 (Monospace font)
+monospace-font|等宽字体*
mana-liquidizer@|魔力液化器*
neapolitan@|那不勒斯风味*
@@ -3242,7 +3242,7 @@ stare-till-they-grow|盯到它们熟为止! (Stare Till They Grow!)
vm-computers|虚拟电脑 (VM Computers)
inventory-free|无物品栏 (Inventory-Free)
-randompatches-integration
+randompatches-integration|随意修复集成 (RandomPatches Integration)
bubble-column-elevator-backport|1.13水域机制 (1.13 Bubble Columns for 1.12)
basic-nether-ores@|基础下界矿石*
nuclearcraft-reactor-builder|核电工艺反应堆建造机 (NuclearCraft Reactor Builder)
@@ -3341,7 +3341,7 @@ simple-generators@|简易发电机*
tfc-bonsai|群峦盆栽 (TFC Bonsai)
tfc-drying-rack|群峦晾干架 (TFC Drying Rack)
-lumen|流明 (Lumen 🔥)
+illuminations-legacy|流明 (Illuminations Legacy 🔥 / Lumen 🔥)¨lumen|流明 (Illuminations Legacy 🔥 / Lumen 🔥)
openblocks-elevator@elevatormod|开放式电梯 (OpenBlocks Elevator / ElevatorMod)
crafttweaker-integration|CrT集成 (CraftTweaker Integration)
@@ -3982,11 +3982,11 @@ playtime-counter-fabric|游戏时长计数器 (Playtime Counter)
entity-banners|实体旗帜*
curious-jetpacks
curious-armor-stands@¨curious-armor-stands-fabric
-trinkets-fabric@trinkets
+trinkets@
occultism@|神秘学*
stray-spawn@|流浪者生成微调*¨stray-spawn-fabric|流浪者生成微调 (Stray Spawn)
mooshroom-spawn@|哞菇生成微调*¨mooshroom-spawn-fabric|哞菇生成微调 (Mooshroom Spawn)
-cardinal-components@cardinal-components-api
+cardinal-components-api@
integrated-proxy|集成代理器*
@@ -4243,7 +4243,7 @@ chinese-style-sword@arsenal-core|中式剑 (Arsenal Core)
heroic-armory|英雄武器*
colossal-battery|巨型电池 (ColossalBattery)
industrial-meat
-
+biomancy@
extra-generators@|额外发电机*
horticulture|园艺*
mr-pineapples-food-mod
@@ -4635,7 +4635,7 @@ death-coords|死亡坐标显示*
never-enough-currency|货币多多*
never-enough-currency-lite|货币多多:精简版*
create-chunkloading
-name-pain@namepain
+namepain@
wireless-chargers@|无线充电器*
bouncier-beds@|弹力床*¨bouncier-beds-fabric|弹力床 (Bouncier Beds)
hexlands-ii|六边形地貌 2 (HexLands II)
@@ -4704,7 +4704,7 @@ gamemodeoverhaul@|旧版指令 (GamemodeOverhaul)
dash@
minecraft-dungeons-content@dungeons-content|地下城内容 (Dungeons Content)
old-beacon|旧信标*
-oc2|开放式电脑 II (OpenComputers II)
+oc2@opencomputers-ii|开放式电脑 II (OpenComputers II)
botany-pots-tiers@|更好的植物盆栽*
compatchedstorage|紧凑存储修复 (ComPatchedStorage)
iseedragons
@@ -4797,7 +4797,7 @@ macaws-fences-and-walls@|Macaw 的栅栏与墙 / 麦考的栅栏与墙壁 (Macaw
lunae-silva
rainbow6|我的六号 (Rainbow6:Minesiege)
-friendlyendermite@friendermite|友好的末影螨 (FriendlyEndermite)
+friendermite@|友好的末影螨 (FriendlyEndermite)
food-expansion|食物扩展*
forgotten-items|被遗忘的物品*
food-expansion-reimagined@|食物扩展:重构想 (Food Expansion: Reimagined)
@@ -4941,7 +4941,7 @@ open-to-lan
simple-translation@|简单翻译*
fx-control@|效果控制 (Fx control)
what-are-you-voting-for@
-steam-powered-create@create-steam-powered|蒸汽动力 (Create: Steam Powered)
+
creepers-burn@CreepersBurn
pretty-game-enhhancing-gobblet-pgeg-remake|魔法森林重置版 (Pretty, Game-Enhhancing Gobblet Remake)
@@ -4971,7 +4971,7 @@ environmental-creepers@|环保型苦力怕*
look-at-that
advanced-peripherals@advancedperipherals|高级外设*
-nether-chest-fabric@nether-chest
+better-nether-chest@nether-chest
@essentialaddons
levelz@
betterend-re-forked|更好的末地Forge重铸版 (BetterEnd Reforked)
@@ -5119,7 +5119,7 @@ slimier-slimes
stupid-weapon
slime-carnage|史莱姆杀戮*
portal-tags
-eden-ring@eden-ring-reforked|伊甸星环*
+eden-ring|伊甸星环*
placement-tweaks|放置调整*
kimetsu-animation-demon-slayer-animation|鬼灭动作 (Kimetsu Animation)
hals-enhanced-biomes
@@ -5191,7 +5191,7 @@ warp-pipes
fertile-farmland|沃壤千里*
luckperms@
inv-view@invview
-ftb-industrial-contraptions|FTB工业奇械 (FTB Industrial Contraptions)
+ftb-industrial-contraptions-forge|FTB工业奇械 (FTB Industrial Contraptions)
more-respawn-anchors|更多重生锚*¨more-respawn-anchors-forge|更多重生锚 (More Respawn Anchors)
werewolves-become-a-beast@werewolves|狼人 (Werewolves)
omnipotent-card@|万用卡牌*
@@ -5242,7 +5242,7 @@ lost-and-found
better-fps-render-distance¨better-fps-render-distance-fabric
armor-chroma-for-fabric@|盔甲颜色显示Fabric版 (Armor Chroma for Fabric)
ore-reeds|矿石甘蔗*
-connected-glass@
+connected-glass@|玻璃连结*
blockui
storage-racks
Dung-Pipe
@@ -5380,7 +5380,7 @@ multiblocktweaker
good-ol-currency
macaws-bridges-atmospheric|Macaw 的桥梁:悠然一派附属 (Macaw's Bridges - Atmospheric)
leadvillagers
-fabric-shield-lib@fabricshieldlib
+shield-lib@shieldlib
frys-things-guns-and-more
quickbind|功能集成 (Quick Bind)
ompd|开放式模块化被动防御 (Open Modular Passive Defense)
@@ -5458,7 +5458,7 @@ mc-mods-the-blocks
mc-modsthemodium
ato
just-enough-effect-descriptions-jeed@|JEI药水效果 (Just Enough Effect Descriptions)
-hostile-neural-networks@
+hostile-neural-networks@|敌对神经网络*
mo-cakes|更多蛋糕 (Mo' Cake)
fishing-made-better|更好的钓鱼*
neon-craft-ultimate|霓虹灯艺2 (Neon Craft Ultimate/Neon Craft 2 Mod)
@@ -5615,7 +5615,7 @@ windowed-fullscreen
helpful-hitboxes-forge¨helpful-hitboxes-fabric
vein-mining@|连锁采集*¨vein-mining-fabric|连锁采集 (Vein Mining)
ars-creo@
-it-fell-from-the-sky
+it-fell-from-the-sky|天降之物*
@@ -5633,7 +5633,7 @@ extended-armor-bars
atom-economy|基石-经济 (Atom-Economy)
just-enough-piglin-bartering|JEI猪灵以物易物*
-@aftersans53228-fabric-road|暗访谈的Fabric道路 (aftersans53228's fabric roads)
+@aftersans53228-fabric-road|AFRoads路建 (AFRoads Construction)
primal-magick@|原初魔法*
ore-creeper@|矿石苦力怕*
panthalassa|泛古洋*
@@ -5669,7 +5669,7 @@ biome-id-extender
rereskillable-reborn
rereskillable-rereforked
tetra-pak
-ars-magica-legacy@
+ars-magica-legacy@|魔法艺术:遗产 (Ars Magica: Legacy)
compressium
talking-villagers|会说话的村民*
artifality@
@@ -5678,7 +5678,7 @@ delogger
just-another-vanilla-addon-java|迫真原版增强 (Just Another Vanilla Addon)
spectrite-mod|彩虹 (Spectrite)
genshin-nature@|原神:自然*
-power-utilities-remastered@power-utilities|能源转换重制*
+power-utilities-iu@power-utilities|能源转换重制 (Power Utilities Remastered)
create-gear-addon
gun-mod-tl
@@ -5689,7 +5689,7 @@ simply-quarries@|简易采石场*
lethal-peaceful
-storage-drawers-crafting-recipe
+storage-drawers-crafting-recipe|储物抽屉合成配方*
enhanced-attack-indicator@|增强攻击提示器*
parasites-addon-overlast|寄生兽:末世扩展 (OverLast)
cancel-block-update@|取消方块更新*
@@ -5698,15 +5698,15 @@ d3core
green-thumb-v1-2-03
greenthumb
tfc-adventure|群峦冒险 (TFC+ Adventure)
-just-zoom-forge@just-zoom
+just-zoom@
server-holograms@holograms|全息图 (Holograms)
eidolons-hexblades|幻梦咒剑 (Eidolon's Hexblades)
monke-madness
put-ingot-down|把锭放在地上吧! (Put Ingot Down!)
torchtools
-lottweaks
-quests-additions-fabric|任务拓展 (Quests Additions)¨quests-additions|任务拓展*
+lottweaks@
+quests-additions|任务拓展*¨quests-additions-fabric|任务拓展 (Quests Additions)
custom-mob-spawner|自定义生物生成器*
rpg-hud@¨rpg-hud-fabric
the-wild-update-concept-mod
@@ -5716,7 +5716,7 @@ oreregen|再生矿石 (OreRegen)
eidolon_tweaker
herodotusutils@herodotus-utils
-platypuses
+platypuses|鸭嘴兽*
hostile-villages|敌对村庄*
throwability|投掷*
biomeinfo@|生物群系信息 (BiomeInfo)¨biomeinfo-fabric|生物群系信息 (BiomeInfo)
@@ -5771,7 +5771,7 @@ psicaster
tweakermore@
legacy-display@
the-backrooms
-creatures-of-the-snow@creatures-from-the-snow-fabric|雪地里的生物! (Creatures From The Snow!)¨creatures-from-the-snow-forge|雪地里的生物! (Creatures From The Snow!)
+creatures-from-the-snow-fabric@|雪地里的生物! (Creatures From The Snow!)¨creatures-from-the-snow-forge|雪地里的生物! (Creatures From The Snow!)
collisions-lib@
wooled-boots@|羊毛靴子*
zawa-evolved@|野生动物园:进化 (Zoo and Wild Animals: Evolved)
@@ -5786,12 +5786,12 @@ death-compass-forge|死亡指南针 (Death Compass)¨death-compass-fabric|死亡
portable-stonecutter|便携式切石机*
enchanted-book-redesign@¨enchanted-book-redesign-fabric
-quick-hotbar
+quick-hotbar|快捷工具栏*
modular-augment
lumberjack
better-mods-button@|更好的模组按钮*
-advancement-frames@
+advancement-frames@|进度展示框*
dynmapforge
spellbind@|物品魔法*
@@ -5840,13 +5840,13 @@ feature-nbt-deadlock-be-gone@
real-infinity-bow-allow-inf-mending|真正的无限弓 (Real Infinity Bow)
drink-it-forge|喝! (Drink It!)
foxlib
-tails
+tails|尾巴*
howling-moon-rebooted-forge¨howling-moon-rebooted-fabric
@dustrial-decor
furnish@furnish-furniture
-iammusicplayer@iam-music-player
+iammusicplayer@iam-music-player|Iam 音乐播放器 (Iam Music Player)
pirates|海盗*
comics-bubbles-chat@
@@ -5861,8 +5861,8 @@ orderly-fabric-2-0
entity-texture-features-fabric@entitytexturefeatures|实体纹理特性 (Entity Texture Features)
sculk-plus
-creeper-confetti-fabric|烟花苦力怕Fabric版*
-double-jump-attribute@
+creeper-confetti-fabric|烟花苦力怕 Fabric 版*
+double-jump-attribute@doublejumpattribute
overweight-farming@
healthcare@
betterloadingscreen|加载画面改良 (Better Loading Screen)
@@ -5883,7 +5883,7 @@ worldinfo
@bang
block-helper@
@class-loader-fixer
-@font-fixer
+@font-fixer|字体修复 (Font Fixer)
gregicprobe
travelers-index
@@ -5904,13 +5904,13 @@ tinkers-golems-addon
tinkers-addons-fork
reagenchant
-sim-u|模拟城市/模拟大都市
+sim-u|模拟城市/模拟大都市 (Sim-U)
thorium@|钍*
creative-one-punch@
radon@|氡*
ars-omega
-game-stages-conditions
+game-stages-conditions|游戏阶段条件*
tinkers-construct-tool-leveling-with-random
odd-water-mobs
glowsquids-begone@
@@ -5943,7 +5943,7 @@ custom-fluid-mixin@
slender-reimagined
doors-by-ichun
slender-man-mod¨the-original-slenderman-mod-working|Slender Man - 他人的非官方重上传
-cookielicious|曲奇佳味*
+cookielicious@|曲奇佳味*
the-forbidden|禁忌者*
memory-usage-screen@
evergreenhud@
@@ -5969,7 +5969,7 @@ keygrip-mocap-mod
attachable-grinder
hat-stand
-chunk-copy-fabric@
+chunk-copy-fabric@|区块复制 (Chunk Copy)
inventory-home|回归箱*
nether-hexed-kingdom
@@ -6116,7 +6116,7 @@ simple-discord-rpc@
excore
messmod@
-log4j2-jndi-exploit-fix
+log4j2-jndi-exploit-fix|Log4J2 JNDI 漏洞修复 (Log4J2 JNDI Exploit Fix)
woodcutter¨woodcutter-forge
origins-classes-forge@|起源:职业非官方Forge版 (Origins: Classes (Forge))
tool-stats@
@@ -6525,7 +6525,7 @@ easyexcavate
wooden-shears@|木剪刀*
brick-furnace@|砖熔炉*
brick-hopper@|砖漏斗*
-human-companions
+human-companions|人类同伴*
odysseyhud
colorblindness@
aether-addon
@@ -6685,7 +6685,7 @@ geode
realistic-spiders|真实的蜘蛛*
@timedisplay|时间显示 (Time Display)
biome-particle-weather@biome_particle_weather
-ftb-backups-2|FTB备份2 (FTB Backups 2)
+ftb-backups-2|FTB 备份 2 (FTB Backups 2)
darkkore@
@@ -6833,7 +6833,7 @@ recipe-gui
autotechno@
villager-hats-mod@villager-hats
custom-damage-particles@|自定义伤害粒子*
-@aei|AEI物品管理器 (Always Enough Items)
+@aei|AEI 物品管理器 (Always Enough Items)
cyan-warrior-swords-mod@
plant-in-a-jar@
solid-mobs@solid_mobs
@@ -7031,7 +7031,7 @@ inmis@¨inmis-forge
rechiseled@
durability-tooltip@
-oreganized-mod|井然有矿* - 旧版¨oreganized|井然有矿 (Oreganized Mod) - 2.0+ 版¨@oreganized|井然有矿 (Oreganized Mod)
+oreganized|井然有矿 (Oreganized Mod) - 2.0+ 版¨oreganized-mod|井然有矿* - 旧版¨@oreganized|井然有矿 (Oreganized Mod)
riding-utilities
compact-help-command@¨compact-help-command-fabric
@@ -7096,7 +7096,7 @@ nock-enough-arrows
every-compat@|泛用兼容:木材 (Every Compat (Wood Good))
offline-mode
ghastly-wail@
-immersive-weapons#c71@immersive-weapons|沉浸式武器 (Immersive Weapons)
+immersive-weapons@|沉浸式武器*
clear-skies@
@@ -7404,7 +7404,7 @@ roughly-enough-trades@
simple-quarry@
magitek-mechs|Magitek Mechs - 已停用¨@magitek-mechs
infectum
-nocubes-sea-dwellers
+nocubes-sea-dwellers@aures-sea-dwellers
show-me-your-skin@
invulnerable-pigs
t88@
@@ -7463,7 +7463,7 @@ hookshot@
custom-spawns
create-misc-and-things@|机械动力:实用物件 (Create : Misc & Things)
low-fire@
-infinity-buttons@infinitybuttons|无限按钮*
+infinitybuttons@|无限按钮 (Infinity Buttons)
i-know-what-im-doing-fabric
skin-hotkey@
dyeable-fishing-lines-fabric@dyeable-fishing-lines¨dyeable-fishing-lines-forge
@@ -7488,7 +7488,7 @@ playeranimator@
apathy-mod@apathy
auudio-forge@auudio¨auudio-fabric
-easy-shulker-boxes@¨easy-shulker-boxes-fabric
+easy-shulker-boxes@|简单潜影盒*¨easy-shulker-boxes-fabric|简单潜影盒 (Easy Shulker Boxes)
qu-enchantments@
ironchests@
@@ -7501,7 +7501,7 @@ noits-simple-sorting
colds-gauntlets
level-one@
wilder-wild@
-paintings-with-dragons
+paintings-with-dragons@aures-paintings-with-dragons
more-redstone-lamps|更多红石灯*
placeable|可放置植物 (Placeable Plants)
tfc-hot-or-not@
@@ -7906,7 +7906,7 @@ echoing-depths
advanced-finders
maple-forest|枫林*
-@legacyinputpatch|Legacy Fabric 输入补丁 (LegacyInputPatch)
+@legacyinputpatch|Legacy Fabric 输入补丁 (Legacy Input Patch)
droplight
xanders-sodium-options¨@xanders-sodium-options|Xander's Sodium Options - 已归档
entity-view-distance@
@@ -7966,7 +7966,7 @@ visual-overhaul@
drawerfps-legacy|储物抽屉渲染配置:遗产 (DrawerFPS Legacy)
status-effect-timer@statuseffecttimer
logical-zoom@
-
+no-trampling-on-farmland@|阻止踩踏农田 (No trampling on farmland)
the-space-age-mod|太空时代*
touhou-origins@|起源:东方 Project 附加包*
earth-mobs@earthmobs|地球生物*
@@ -8104,7 +8104,7 @@ toomanyorigins@
evil-regeneration@
food-treasure-box|食物宝盒*
revolution
-apugli¨@apugli
+apugli@
harvest-season
@ic2fix
@extended-bookshelves
@@ -8125,7 +8125,7 @@ id-primeval@primeval
colorfulazaleas@colorful-azaleas|杜鹃缤纷 (Colorful Azaleas)
pigeon-post@
hunted-api
-
+kablade|斩无不断 (Ka Blades)
bigger-structures
find-my-friends@
@@ -8178,7 +8178,7 @@ spice-of-life-apple-pie-edition@|生活调味料:苹果派版 (Spice of Life:
xp-obelisk@|经验方尖碑 (XP Obelisk)
enhanced-searchability@|搜索增强*
compact-ui@
-lets-do-wine@lets-do-vinery|葡园酒香 (Let's do Wine / Vinery)
+lets-do-wine@lets-do-vinery|葡园酒香 ([Let's Do] Vinery)
wealthyandgrowth@
subtitle-highlight@|字幕高亮*
clockhud@clock-hud
@@ -8204,7 +8204,7 @@ compassplus
create-industry@create-tfmg|机械动力:工业长路 (Create: Industry/Create: The Factory Must Grow)
simple-splash-screen@
unusual-prehistory-forge@
-biospheres|生物圈 (Biosphere)
+biospheres|生物圈*
qkl@
dynamic-trees-tech-reborn|动态的树:科技复兴附属 (Dynamic Trees - Tech Reborn)
@@ -8663,7 +8663,7 @@ sorcerium@
zeropoint
campful
-well-rested@
+well-rested|Well Rested - ,此指向的并非本¨@well-rested
raw-input-1-12-2@raw-input
spider-pig
jingames-hair-c@hair-c
@@ -8719,7 +8719,7 @@ rpg-rpgae|RPG天启进化 (RPGApocalypticEvolution)
dungeon-difficulty@
cazfps-chronicles
-unstable-tools@unstable|不稳定金属工具*
+unstable-tools@|不稳定金属工具*
tech-reborn-patchouli
biome-bundle
moon-phase-info@
@@ -8921,7 +8921,7 @@ spellblade-next@spellblades-and-such
netherite-road-2@|下界之路2*
@tileentity-reset-fix
notenoughrecipebook@
-urushi-mod|漆 (Urushi)
+urushi-mod@urushi|漆 (Urushi)
nicephore¨nicephore-fabric¨@nicephore
terraria-paintings¨terraria-paintings-fabric
minegooseduck
@@ -8943,7 +8943,7 @@ no-weather-effects@
ob-tooltips
hekate-lib
loot-journal@¨loot-journal-neoforge¨loot-journal-fabric
-
+flans-mod-ultimate-1-1-modified
@@ -9112,7 +9112,7 @@ chatimage@|聊天栏图片显示 (ChatImage)
@treasurehunt|寻宝 (TreasureHunt)
no-tema-stahp
labels@|存储标签 (Storage Labels)
-@qdaa
+qdaa@
better-creeper-mod|更好的苦力怕 (Better Creeper)
regions-unexplored@|未至之地*
@@ -9167,7 +9167,7 @@ wood-stuff
magmafurnace-weapons-bosses-and-more
monstersregulararmy
why-does-my-food-taste-like-that
-iron-generators
+iron-generators@
elytra-swapper-forge|鞘翅切换*
ftb-team-islands-forge
@@ -9203,7 +9203,7 @@ mob-captains|怪物队长*
snowballing
winter-essentials@winter_essentials
embeddium-extras@|镁/铷附属:土豆版 (Magnesium/Rubidium Extra: Potato Editon*)
-@realistic-cruelty|真实残忍 (Realistic Cruelty)
+realisticcruelty@|真实残忍 (RealisticCruelty)
trapper-pelts@
workshops-of-doom@
create-mechanical-spawner@|机械动力:动力刷怪笼*
@@ -9213,7 +9213,7 @@ fzzy-core@
tnt-breaks-bedrock@
from-the-north@
spruce-willis-the-xmas-tree@
-sweet-potato-core-spc|地瓜核心 (Sweet Potato Core)
+
merge-enchantments@
turkey|火鸡*
@@ -9226,7 +9226,7 @@ villager-comfort|村民舒适度*
ender-quarry|末影采石场*
-mythic-upgrades-fabric@mythic-upgrades¨mythic-upgrades-forge
+mythic-upgrades@
fat-chicken
snowmancy@
@@ -9374,7 +9374,7 @@ item-info
florist
omni
frostrealm@
-nameless-trinkets@
+nameless-trinkets@|无名饰品*
unsafe-spawns
bubbles@pop
@@ -9685,7 +9685,7 @@ tfc_metalwork|群峦金属加工 (TFC Metalwork)
furniture-compatibility-for-macaw-tfc|Macaw 的家具:群峦传说附属 (Furniture Compatibility for Macaw/TFC)
-roof-compatibility-for-tfc-macaw|Macaw的屋顶:群峦传说附属 (Roof Compatibility for TFC/Macaw)
+roof-compatibility-for-tfc-macaw|Macaw 的屋顶:群峦传说附属 (Roof Compatibility for TFC/Macaw)
tfc-supplementaries|群峦锦致装饰 (TFC Supplementaries)
tfc-ie-crossover|群峦传说:沉浸工程兼容附属 (TFC + IE Crossover)
@@ -9916,7 +9916,7 @@ world-of-bosses
mirabilis-vanilla-biome-overhaul
energized-power@
carpenter
-tolerable-creepers
+tolerable-creepers@
anchor
locksmith
mystical-machinery|神秘机械*
@@ -9965,7 +9965,7 @@ bring-color-to-my-skies
portal-dungeons
radiant-gear@¨radiant-gear-fabric
-create-teleporters@|机械动力:传送器 (Create : Teleporters)
+create-teleporters@|机械动力:传送器 (Create: Teleporters)
enchantato
floating-block@floating-cube|浮空立方体 (Floating Cube)
curious-lanterns@
@@ -9987,7 +9987,7 @@ fog-looks-good-now@
guarding@
cats-expanded@
modular-bosses
-experience-obelisk@cognition
+experience-obelisk@cognition|认知 (Cognition*)
here-be-no-dragons
gnumus-settlement
fading-night-vision
@@ -10078,7 +10078,7 @@ completionists-index@
stoneworks@
mob-lassos@|生物套索*
-mutant-monsters@
+mutant-monsters@|突变怪物*
@physics-toys
tarot-cards@|塔罗牌*
@@ -10171,7 +10171,7 @@ blue-archive-halos
@totemcounter
@mana-visualizer
-mhcraft
+m3h
irons-spells-n-spellbooks@|Iron的法术与魔法书 (Iron's Spells 'n Spellbooks)
infernal-enchantments
reimagined-world-menu@
@@ -10202,7 +10202,7 @@ end-origins
extra-classes-origins
wire-decoration|电线装饰*
optimizationsandtweaks@
-
+the-flesh-that-hates@tfth
tabfaces@
mob-armor-mod-v2@mob-armor-mod-v3
umbral-skies
@@ -10413,7 +10413,7 @@ openblocks-trophies@
@shrug-it-off
@f3-t-everywhere
-lootbag-patches
+lootbag-patches@
stargate-journey@sgjourney|星门之旅*
xaero-arrow-fix|Xaero Arrow Fix - 无法¨@xaeroarrowfix
@@ -10746,7 +10746,7 @@ classic-minecraft-icon@
some-useful-ores
@stardew-valley-mod
rainy-harvest
-mythic-mobs@mobs-of-mythology
+mobs-of-mythology@
lost-features@lostfeatures
bagus-lib@
@@ -10792,7 +10792,7 @@ industrybase|工业基石 (IndustryBase)
silent-river-in-the-nether|炎液断蒸*
ramel-reforged
sulfar-mod
-apple-cows
+apple-cows|苹果牛*
gardening-tools@
nether-ores-plus
river-treasures
@@ -11063,7 +11063,7 @@ yeetusexperimentus@yeetus-experimentus
xbob@|准星摇晃 (Crosshair Bobbing)
zombie-horse-spawn@|僵尸马生成微调*¨zombie-horse-spawn-fabric|僵尸马生成微调 (Zombie Horse Spawn)
tinkers-katanas|匠魂武士刀 (Tinkers' Katanas)
-fbp
+fbp@
yeetem-potions@
incapacitated@
@fys|锻汝砧上 (Forge Yourself)
@@ -11089,7 +11089,7 @@ moa-decor-cookery
moa-decor-science
create-guardian-beam-defense
antisocial@
-expanding-technologies@expandingtechnologies
+expandingtechnologies@
despawning-eggs-hatch@
mob-death-messages
chunkapi@
@@ -11200,7 +11200,7 @@ placeable-mobs@placeble-mobs
potion-blender@
t6-auto-attack-mod@t6-auto-attack
forceasciifont-backport
-vmtranslationupdate@vmupdate|VM汉化更新 (VMTranslationUpdateMod)
+vmtranslationupdate@vmtu|VM汉化更新 (VMTranslationUpdateMod)
trample-no-more@
jeremyseq-damage-indicator@jeremyseqs-damage-indicator
@@ -11531,7 +11531,7 @@ mother-silverfish
mcretector@
little-botanics
-ex-pattern-provider@extended-ae|AE2扩展 (ExtendedAE)
+ex-pattern-provider@extended-ae|AE2扩展 (Extended AE)
@integrated-circuit
creative-disk
engineers-construct
@@ -11610,7 +11610,7 @@ bloxys-structures@
enhanced-hordes
niftycarts@
wither-dimension-whitelist
-@hexlink
+hexlink@
usefulfood-reborn@|有用的食物 重生 (UsefulFood Reborn)¨usefulfood-community|有用的食物 重生 (UsefulFood Reborn)
ancient-warfare-2-tweaked@
@@ -11644,7 +11644,7 @@ simply-skills@
-cctv-craft@cctvcraft
+cctvcraft@
redeco@|重铸家具 (Re:Deco)
pocket-storage
animated-player-mod|动画化玩家*
@@ -11677,7 +11677,7 @@ dirtnt@|泥土TNT (DirTNT)
equipable-twilight-forest-charms-tfc|可装备的暮色森林符咒 (Equipable Twilight Forest Charms)
buriedwrecks@buried-wrecks
zapsconverter|Zaps 转换器 (Zaps Convertor)
-amethyst-update
+amethyst-update@
angel-block|天使方块*
angel-block-renewed@
da-bomb@
@@ -11730,7 +11730,7 @@ constructs-armory-1-18-2-port@construct-armory-updated
@videotape
@enchantmenttweaker
-let-me-sleep
+let-me-sleep|让我睡觉*
forge-tooltip-texts-scroller¨fabric-tooltip-texts-scroller
well-behaved-mobs
@@ -11952,7 +11952,7 @@ ahznbs-naruto-mod-addon
random-village-names@¨random-village-names-fabric
mooshroom-tweaks@
grinners-ents
-log-cleaner@
+log-cleaner@|日志清理*
lunar@
cosmetics@cosmetica
@@ -12258,7 +12258,7 @@ qraftyfied
theft-mod@theft
akkamaddis-golden-glitter@
@obsidianbucket
-enhanced-annihilation-planes
+enhanced-annihilation-planes@
akkamaddis-simple-cthon@
@heads-hurt-too!
pooping-animals
@@ -12588,7 +12588,7 @@ better-chunk-loading-forge-fabric
mushroomified
soul-like-boss-epic-fight-addon
-moderately-enough-effect-descriptions-meed-a-jeed-addon@moderately-enough-effect-descriptions-(meed)-jeed-addon¨@moderately-enough-effect-descriptions-meed|Moderately Enough Effect Descriptions - 新,未及时更新
+moderately-enough-effect-descriptions-meed@moderately-enough-effect-descriptions-(meed)-jeed-addon¨@moderately-enough-effect-descriptions-meed|Moderately Enough Effect Descriptions - 新,未及时更新
alexs-caves@|Alex 的洞穴 (Alex's Caves)
bow-spam-be-gone@
lmdcraft
@@ -12640,7 +12640,7 @@ eager-beavers@
laendli-transport
witchs-artifacts
the-pumpkin-challenge@
-loot-crates-plus@loot+
+loot-bags-plus@loot+
fuji@|藤*
legendary-origins@
@@ -12782,7 +12782,7 @@ creatures-of-runeterra@cor
from-another-world@
pumpkin-moon@
zombie-onslaught@
-neighborly
+neighborly@
natural-progressions@natural-progression
charged-explosives@
pulver@
@@ -12804,7 +12804,7 @@ celestial-enchantments|星月附魔*
clearsky|洁净天空 (ClearSky)
educate-nitwit
damage-spawns-mobs
-decorative-sniffer-egg@
+decorative-sniffer-egg@decorative-sniffer-egg-old
gilded-sherds@
camps-castles-carriages
rainbow-reef@
@@ -13201,7 +13201,7 @@ cenozoic-nightmare-the-horror-of-prehistory
quickbackupmulti@|多槽位备份 (QuickBackupMulti)
slashblade-japanese-addon-pack-reforked|拔刀剑日系附属重置版 (SlashBlade Japanese Addon Pack Reforked)
-@create-fabric-fixes
+@create-fabric-fixes|机械动力 Fabric 修复 (Create Fabric Fixes)
@command-block-sceptre|命令方块权杖 (Command Sceptre)
crate-delight-forge@crate-delight|装箱乐事 (Crate Delight)¨crate-delight-fabric|装箱乐事 (Crate Delight)
cultural-creators-forge-create-and-cultural@cultural-crators¨cultural-creators-fabric-create-and-cultural
@@ -13249,7 +13249,7 @@ digestive
inventory-binds@
-octo-lib@
+shatterbyte-lib@
farmers-plus¨farmers-utils|Farmer's Plus - 旧
architects-friend
bagus-cosmetic@
@@ -13294,13 +13294,13 @@ harder-wildlife|更难的野生动物*
harder-farming|更难的农作*
waterproof
entityculling-unofficial@entitycullingunofficial|实体渲染机制优化:非官方版 (EntityCulling Unofficial)
-@sync-projecte-knowledge
+sync-projecte-knowledge@
eventtweaker
craft-vania
lotrextracoins-for-1-7-10|额外魔戒银币 ([Legacy] LotRExtraCoins)
genst
-ae2-network-analyser
+ae2-network-analyser|AE2网络分析仪 (AE2 Network Analyser)
mxtune
customui|自定义UI (CustomUI)
deadly-monsters-patched
@@ -13416,7 +13416,7 @@ everyxdance@|一起跳舞! (EveryXDance)
applied-flux@appflux|应用通量*
tics-delight@tinkers-delight|匠魂乐事 (Tinkers' Delight / TiC's Delight)
-unnamed-desert-structures@unnamed-desert
+unnamed-desert@
bloomingnature@lets-do-bloomingnature|绽芳自然 (Let's Do: BloomingNature)
waila-inhibitors@
thingamabobs-and-doohickeys
@@ -13439,7 +13439,7 @@ better-azalea
tetratic-combat-expanded@
more-beautiful-slabs@
-tools-complement-create@create-complement
+create-complement@
biome-beans
cats-workshop
@@ -13676,7 +13676,7 @@ helpfixer
drippedout@dripped-out
easter-rabbit-life@
sticker-frames@
-tnt-slimes@
+tnt-slimes@|TNT 史莱姆 (TNT Slimes)
armored-redstone@
bismuth-colors@bismuth-2|铋 (Bismuth)
killbind@
@@ -13772,7 +13772,7 @@ lavender-api@lavender
cheatutils
jump-sounds@
kirin@
-llamapalooza
+llamapalooza@
instant-drown
acsguis
game-phase@|游戏阶段*
@@ -14042,7 +14042,7 @@ melee-ex-machina-meexma@melee-ex-machina
arc@
cores@
-citymod-traffic-and-life@citymod|我的城市:交通与生活 (CityMod:Traffic and life)
+citymod-traffic-and-life|我的城市 (CityMod) - 停止维护¨@citymod|我的城市 (CityMod)
too-hard-to-dig@|隐岩砥凿 (Too Hard to Dig)
simplecobblestonegenerator@simple-cobble-gen
natural-baby-animals
@@ -14356,7 +14356,7 @@ per-aspera@
spice-of-life-valheim-edition@mKalCkNV
tfc-paths
binkers-bonstruct
-ranged-weapon-api@
+ranged-weapon-api@|远程武器 API (Ranged Weapon API)
numismatics@
@@ -14377,7 +14377,7 @@ enchantment-enhancements@
mo-enchantments
soul-like-enchantment
-@blockbench-import-library
+blockbench-import-library¨@blockbench-import-library|Blockbench Import Library - 不再更新
mrcrayfish-furniture-mod-rebuilt
btfixes
vmfixes
@@ -14483,7 +14483,7 @@ additional-attributes@
suicide-key
-uranus@
+uranus¨@uranus|Uranus - 不再更新
annotationlib@
@waxed
nether-overload
@@ -14531,7 +14531,7 @@ grieflogger@
the-quest-of-entity-303
pineapple-mending|经验修补:凤梨版*
-@quick-chat|快捷聊天 (Quick Chat)
+quick-chat@|快捷聊天*
magic-vibe-decorations@
valentines-blessing@valentines-blessing-lilypads-roses
decent-biomes@
@@ -14616,7 +14616,7 @@ creature-whisperer
create-molten-metals@
-create-optical|机械动力:光学*¨@create-optical|机械动力:光学 (Create Optical) - 不全
+create-optical@|机械动力:光学*
@farmers-delight-plus
@@ -14726,7 +14726,7 @@ achievement-detection-fix@|成就检测修复*
@myceliumlib|菌丝 (Mycelium Lib)
-
+@xp-formula|经验公式 (Xp Formula)
cataclysmic-illagers
witcherypatch@|巫术补丁 (WitcheryPatch)
pin
@@ -15004,7 +15004,7 @@ what-is-stone-colorful-caves@what-is-stone-(colorful-caves)
vtones
heavy-inventories|物品负重*
vs-addition@|瓦尔基里:附加 (VS Addition)
-gravity-torch@
+gravity-torch@|重力火把*
lifesteal-forge-fabric@lifesteal-mian
mores-by-its-infinite
dragonite-gear
@@ -15195,7 +15195,7 @@ winter-ambience
dralards-rock-candy-mod
-
+vineplicate@|生蔓聚解*
explosion-breaks-no-block@|爆炸不破坏方块*
via-romana@
lithic-coins
@@ -15461,7 +15461,7 @@ aromatic@
onekeyminer-nf@onekeyminer_nf|一键连锁(Neo)Forge (OneKeyMiner(Neo)Forge)
retargetato@|约谊敌众 (ReTargetato)
-iceandfire-ce@|冰火传说社区版 (IceAndFire Community Edition)
+iceandfire-ce|冰火传说社区版 (IceAndFire Community Edition)¨@iceandfire-ce|冰火传说社区版 (IceAndFire Community Edition) - 不再更新
tomanos-vehicle-mod
ancient-sands@
hs-bosses
@@ -15598,7 +15598,7 @@ sparkle@
villagers-inventory
removehud@
@orthocamera|正交相机 (OrthoCamera)
-third-person-crosshair-fabric
+third-person-crosshair-fabric@third-person-crosshair
@hitrange
black-moon@
dynamic-fire-overlay@
@@ -15688,7 +15688,7 @@ datapack-breakpoint@datapack-debugger|断点调试 (Datapack Debugger)
frosted-heart|冬季救援:寒霜之心 (The Winter Rescue: Frosted Heart)
create-planetary-tweaks@cp-tweaks
entris@
-@sushi-bar
+@bento-box
lumi@lumi1710
pet-the-frog@frog-petting
ex-nihilo-extras@
@@ -15712,7 +15712,7 @@ block-parry-dodge
fargos-talismans@|Fargo的护身符 (Fargo's Talismans)
toostrongmonster
simplystronger
-tacz-durability¨@tacz-durability|TACZ: Durability - 停更
+tacz-durability@
bigger-lightning-storms
eternal-limbo
legoman
@@ -15781,7 +15781,7 @@ armor-of-the-ages@|时代铠甲 (Armor of the Ages)
-@betterf3-stationapi
+@betterf3-stationapi|更好的F3 StationAPI (BetterF3 StationAPI)
ftb-quest-localizer|FTB Quest 本地化 (FTB Quest Localizer)
modpack-update-checker@
minimotd-fabric
@@ -15820,12 +15820,12 @@ structure-expansion@
armored-doggo@
the-newest-goatman
epic-mob-siege-nightmare
-jupiter@
+jupiter¨@jupiter|Jupiter - 不再更新
airport
just-dandy@
@uk-roads
my-totem-doll@my_totem_doll
-void-power-for-fabric|虚空动力 (Void Power)¨voidpowermod|虚空动力 (Void Power)
+voidpowermod|虚空动力 (Void Power)¨void-power-for-fabric|虚空动力 (Void Power)
dis-enchanting-table@
@@ -15909,7 +15909,7 @@ reairdrop-supply@|空投供应:重生 (ReAirdrop Supply)
@simply-create-model-mod|简单动力 (Simply Create Model)
mountains-poem@|青丘辞 (Mountain's Poem)
@playtime-reborn|游戏时长计数器:重生 (Playtime Reborn)
-@flavorimmerseddaily|烟火凡人心 (Flavor Immersed Daily)
+flavor-immersed-daily@flavorimmerseddaily|烟火凡人心*
moon-between-medicine|在月亮之间:药学拓展 (Moon Between : medicine)
craftable-chainmail-reborn|可制作的锁链甲:重生*
@@ -16012,7 +16012,7 @@ scholar@
tacz-bullet-proof-enchant-add-on@¨tacz-bullet-proof-enchant-fabric-add-on
no-screen-bobbing@viewbobbingmod
more-spell-attributes-more-magic-series@
-minos-particle-presets
+palette-lib
somewhat-hardcore-fabric-forge@you-die-you-lose-a-heart
@blurred-window
player-list-heads
@@ -16271,13 +16271,13 @@ lets-do-addon-corn-expansion@|玉食俱馩 ([Let's Do Addon] Corn Expansion)
@client-maps
dragon-gear-renewed
-@archers-plushies
+archers-plushies@
@hephaestus-expansion
create-structures-arise@
kilt@
gregtech-extended-chemistry-extended
ulv-covers-modern
-farmers-structures
+farmers-structures@aures-farmers-structures
@minecartspeeddisplay|矿车速度显示 (MinecartSpeedDisplay)
crossstitch@
@@ -16286,7 +16286,7 @@ free-camera-api@|自由相机API (FreeCameraAPI)
@flashback
bloodmagic-meteors-jei-support|血魔法陨星显示 (BloodMagic Meteors JEI Support)
limited-damage-indicator-particle@|伤害粒子限制*
-netherite-extension@netheriteextension|下界合金拓展续作*
+netherite-extension|下界合金拓展续作*¨@netheriteextension|下界合金拓展续作 (Netherite Extension) - 不再更新
immersive-farming@|沉浸农业*
@vpb-too-many-guns
death-angels|死亡天使*
@@ -16301,7 +16301,7 @@ terramity@
-neptune-lib@neptune
+neptune-lib¨@neptune|Neptune - 不再更新
sign-edit-lite@signeditlite|告示牌编辑轻量版*
@book-formatting
@morewaterlogging
@@ -16331,7 +16331,7 @@ hardcore-revive-mod@
petrols-parts@|Petrol 的机件 (Petrol's Parts)
-slavic-delight@
+slavic-delight@|斯拉夫美食*
aquamirae-delight@|海灵乐事*
dumplings-delight-rewrapped@
my-nethers-delight-refabricated@
@@ -16351,7 +16351,7 @@ itemindicator@
kenshiro-mod|北斗神拳*
roamers
@legacycaneditsign
-title-screen-mobs@
+title-screen-mobs¨@title-screen-mobs|Title Screen Mobs - 不再更新
antiblocksrechiseled@
@@ -16426,7 +16426,7 @@ linear-xp-forge|验依定值/线性经验 (Linear Xp Curve)
dumplings-delight-reload@|饺子乐事:重启*
-auto-switch-elytra@autoswitchelytra|自动切换鞘翅*
+auto-switch-elytra|自动切换鞘翅*
gregtech-placeable-emitters@
@@ -16518,7 +16518,7 @@ tct-core@
obscure-tooltips-fix
@notica
-
+mountain-sea-and-continent-three|山海大陆3 (Mountain Sea and Continent Three)
zhonglv-12et@|钟吕十二律 (ZhongLv-12ET)
@@ -16592,7 +16592,7 @@ moremcmeta-emissive-forge@moremcmeta-emissive¨moremcmeta-emissive-fabric
@fantazia
falling-attack
lesraisins-armor@
-goety-spillage@
+goety-spillage@|诡厄溢出 (Goety & Spillage)
waifucraft
sign-to-chat|阅言得知/聊天栏读取告示牌 (Sign to Chat)
rainimatormod@
@@ -16605,11 +16605,11 @@ hardcore-revive-plus
watson@
emerald-matcha-craft-v3|翠茶工藝 (Emerald Matcha Craft)
-cctv-camera
+cctv-camera@cameracraft
trash-compactor@
rustic-delight@|乡村乐事*
total-assault¨@total-assault|Total Assault - 已弃用
-sky-breaker|天穹突破*
+sky-breaker@|天穹突破*
@scala3std
@hoofprint
@@ -16628,7 +16628,7 @@ cobblegen-galore|方块制造器*
create-sky-village
create-crushing@
cushy-pillows|舒适枕头*
-ice-and-fire-patcher@iaf-patcher|冰火传说随意修复*
+ice-and-fire-patcher|冰火传说随意修复*¨@iaf-patcher|冰火传说随意修复 (Ice And Fire Patcher) - 不再更新
goety-revelation@|诡厄巫法:启示录 (Goety: Revelation)
the-mandela-catalogue-alternates@
the-craftela-catalogue
@@ -16644,7 +16644,7 @@ better-modlist-neoforge@better-modlist|更好的模组列表 (Better ModList)
sky-aesthetics@
headshot-bonus|已无可惧 / 简单爆头*
enchantlevelbrek@enchantmentlevelbreak|附魔等级上限突破2 (EnchantmentLevelBreak)
-the-ruler@
+the-ruler@gamerule-manager
biome-borders-revived-liteloader-only
chunkborders|区块边界 (ChunkBorders)
burnt@
@@ -16691,7 +16691,7 @@ patpat
modern-life-patch@modernlifepatch|摩登生活补丁*
@ivr
rusticdelight-refabricated@|乡村乐事:重织 (RusticDelight: Refabricated)
-scape-and-run-meshi@|逃逸:寄生饭 (Scape and Run: Meshi)
+scape-and-run-meshi|逃逸:寄生饭 (Scape and Run: Meshi)¨@scape-and-run-meshi|逃逸:寄生饭 (Scape and Run: Meshi) - 于v2.3停止更新
@bad-apple-world-preset
gastronomy-works@
@create-air-fabric
@@ -16718,7 +16718,7 @@ tokusatsurecord|特摄唱片 (Tokusatsu Record)
origins-backgrounds-forge¨origins-backgrounds
cataclysm-apotheosis-addon
-cave-dweller-reimagined¨cave-dweller-reimagined-fabric
+cave-dweller-reimagined@cave-dweller-reimagined-(fabric)¨cave-dweller-reimagined-fabric
out-of-combat|脱战 (Out of Combat)
soulfragment|灵魂碎片 (Soul Fragment)
@@ -16734,7 +16734,7 @@ its-magispelling-time
@unkindled
recipe-generator@
@carbonfltr
-argonmod@|氩 (Argon)
+argonmod|氩 (Argon) - 无4.0.2+¨@argonmod|氩 (Argon)
foggypalegarden@
@items-stack
arkane-domains
@@ -16749,7 +16749,7 @@ petphrasex@|口癖X (PetPhraseX)
dust-and-ash|尘与烬 (Dust and Ash)
@particle-interactions
@trial-spawner-timer|试炼刷怪笼计时器 (Trial Spawner Timer)
-
+enigmatic-delicacy|神秘佳肴*
slashblade-resharped-renderfix-patch@|拔刀剑:重锋 渲染修复补丁 (SlashBlade Resharped RenderFix Patch)
@invulnerable-wheat
skin3d-but-not-cubic@skins3d-but-not-cubic
@@ -16811,7 +16811,7 @@ game-discs@|游戏光碟*
luncheon-meat-s-delight@|午餐肉乐事 (Luncheon Meat 'S Delight)
vanilla-plus-resourceful-tools¨resource-tools-fabric
-create-horse-power@
+create-horse-power@|机械动力:马力*
ars-technica
plustic-reforged@
spawners-plus@spawners_plus|刷怪笼拓展 (Spawners+)
@@ -16997,7 +16997,7 @@ scroll-tweaks@scrolltweaks|鼠标滚轮调整*
st@server-tools|服务器工具 (Server Tools)
ride-every-thing@|骑乘一切*
cit-resewn-neopatcher@
-legendary-creatures|传说生物*
+legendary-creatures@|传说生物*
@meowcraft-mod
@@ -17063,7 +17063,7 @@ scp-ultimate
herobrines-omen@herobrinesomen
sws-wukong
dragns-valiant-vehicles@dragns-valiant-vehicles!
-
+bio-factory@biofactory
create-ad-astra-compatibility
create-mechanical-chicken@
zbgt@
@@ -17093,7 +17093,7 @@ sons-of-sins-organs-additions|七罪之子:器官添加 (Sons Of Sins: Organs
sons-of-sins-organs-museum|七罪之子:器官博物馆 (Sons of Sins: Organ Museum)
mobs-of-sins-alexs-mobs-integration-forge|七罪之子: Alex的生物集成 (Mobs of Sins: Alex's Mobs Integration [Forge])
stitched-sins|缝合的罪*
-
+@bio-delight
the-sculpture@scp-173,-the-sculpture|SCP-173,雕像 (SCP-173,The Sculpture)
goop@
@@ -17142,7 +17142,7 @@ unilib@
modchu_playerformlittlemaidfml
quiet|迁噪碍音/玩家禁言*
-galacticraft-compatibility@|星系兼容*
+galacticraftcompatibility@|星系兼容 (Galacticraft Compatibility)
@bettertab
modular-machinery-reborn-mekanism@
@@ -17277,8 +17277,8 @@ tfcgenviewer@
terra-math@
lukis-crazy-chambers
tumbleweed-wasteland
-irons-jewelry|Iron的宝石与饰品 (Iron's Gems 'n Jewelry)
-atlas-api
+irons-jewelry@|Iron的宝石与饰品 (Iron's Gems 'n Jewelry)
+atlas-api@
loading-screen-messages
@pipesounds
nemos-invertory-sorting@nemos-inventory-sorting
@@ -17294,7 +17294,7 @@ centrifuge-tiers-reproduced@
dense-mekanism@
simple-missles@
galosphere-spellbooks@
-discerning-the-eldritch|窥玄探秘*
+discerning-the-eldritch@|窥玄探秘*
@hexcassettes
wardens-plus
ender-wyrmlings
@@ -17429,7 +17429,7 @@ enchantmentransfer@|附魔转移 (Enchantment Transfer)
@async
@mtr-ante|无名的纸板箱交通拓展 (Aphrodite's Nemo's Transit Expansion)
-touchcontroller@|触摸控制器 (TouchController)
+touchcontroller|触摸控制器 (TouchController) - 文件暂时不会及时更新¨@touchcontroller|触摸控制器 (TouchController)
let-me-click-and-send@
@@ -17513,7 +17513,7 @@ water-particles-render-fix
ray-trace-library
delayed-thunder@
book-and-quick-save@
-keybaordjs@keyboardjs
+keybaordjs¨@keyboardjs|Keyboard JS - 已弃用
better-eating-mod@better-eating
@heart-effects
@@ -17543,7 +17543,7 @@ canned@
mushroooms@
tacz-compatibility
@baablu-natural-disasters
-@tacz-tweaks
+tacz-tweaks@
un-saddle
@item-landing-sound
rehooked@
@@ -17627,7 +17627,7 @@ portable-craft-bench
portable-tables@ptables
@flux-network-fork-neoforge
resource-backpacks@
-etherology@
+etherology@|以太学*
snackpirates-aeromancy-additions@aeromancy-additions
apothic-enchanting@|神化附魔*
maidsoul-kitchen@|女仆厨房*
@@ -17745,7 +17745,7 @@ the-twilight-forest-unofficial@|暮色森林非官方版*
somnia-awoken-gui-beautify|梦醒时分 - GUI美化 (Somnia Awoken - GUI Beautify)
redstonecraft@redstonecrafts|红石工艺 (RedStoneCraft)
mowzies-mobs-baubles|Mowzie 的生物饰品 (Mowzie's Mobs' Baubles)
-
+@teblslashblades|拔刀剑:最后战线附属包 (SlashBlade: The End Battle Line Addon)
dungeons-and-combat
@blossomlib
@@ -17773,7 +17773,7 @@ checklist
puncher@
-sensible-stackables
+sensible-stackables@
rei-addons-ic2classic
@blossomtpa
@lithium-raycast-fix
@@ -17921,7 +17921,7 @@ plumbob
@more-enchantments-soybeani-more-enchantments|豆浆更多附魔 (More Enchantments by Soybeani)
-@clearviews
+clearviews@
@immersive_weapons_sounds
epic-fight-invincible@epic-fight-invincible-lib|无坚不摧 (Epic Fight - Invincible)
ore-dict-re-order
@@ -17961,7 +17961,7 @@ cosy-critters@
omnilib@
astages
@aloria-loading
-@parentalcontrols
+@parentalcontrols|家长控制 (Parental Controls)
jason-bot|Jason机器人*
fly-in-the-sky|高空飞行 (Fly in the sky)
@@ -18174,7 +18174,7 @@ stacksonstacks
more-of-all@
-chiikawa|吉伊卡哇*
+chiikawa@|吉伊卡哇*
tolkien-tweaks
tolkien-tweaks-mobs-edition
soulplied-energistics
@@ -18265,7 +18265,7 @@ extended-tinker@|匠魂扩张*
bedsheet@|床单 (BedSheet)
despawn-tweaks@
planetguylib
-@fabric-kotlin-extensions
+ethans-kotlin-extensions@
crafting-table-plus@
@replay-export
@loot4everyone
@@ -18295,7 +18295,7 @@ retro-sophisticated-backpacks|复古精妙背包*
grid@
emienchants@
random-complement|随意补充 (RandomComplement)
-thedulling
+the-dulling
batsword
unidye@
obs-overlay@
@@ -18395,7 +18395,7 @@ asyncparticles@|异步粒子 (AsyncParticles)
@dragonfly-model-library
@terrainapi
mnmutils
-betterend-elytra-fix@
+betterend-elytra-fix@|更好的末地鞘翅修复 (BetterEnd Elytra Fix)
player-swap
@configurable-everything
no-hearts-ui@
@@ -18519,7 +18519,7 @@ tinkers-advanced@|前沿匠艺系列 (Tinkers' Advanced) - 前沿匠艺-拆分
more-structure-processors@
quick-stack-to-nearby-chests@quickstack|快速堆叠 (QuickStack / Quick Stack To Nearby Chests)
-@kallfix
+@kallfix|卡了 OK (KAllFix)
yggdrasilproxy@yggdrasil-proxy
thaumic-meme|神秘吐槽*
@@ -18765,7 +18765,7 @@ valkyrien-relogs@
@section-31|简单监控 (Section 31)
chatalert
aaa-particles-world@
-pick-up-tnt@
+pick-up-tnt¨@pick-up-tnt|Pick Up TNT - 不再更新
ymadditions@
immersive-machinery@
xp-synthesiser@
@@ -18809,7 +18809,7 @@ hxchud
sorted-enchantments@|排序附魔*
assassins-creed-parkour-mod|刺客信条跑酷 (Assassin's Creed Parkour Mod)
critter-armory@
-the-harvest
+the-harvest@
better-minoshroomtaur|Better 米诺菇*
moobloom|哞菇与哞花 (Mooblooms and Mooshrooms)
mooblooms-and-mooshrooms-bop-edition|哞菇与哞花BoP版 (Mooblooms and Mooshrooms (BoP Edition))
@@ -18844,7 +18844,7 @@ rough-blade|无锋道*
@appledog|苹狗 (Appledog)
superb-warfare@|卓越前线*
-aetherworks-extended-life@aetherworks-unofficial-extended-life
+aetherworks-extended-life@aetherworks-unofficial-extended-life|天华之作非官方延续版 (Aetherworks Unofficial Extended Life)
pomkots-mechs-extension-pack@
@monkey-utils
some-more-blocks@
@@ -18912,7 +18912,7 @@ tetra-apotheosis-fix@
ron-timer
empty-air-bubbles
bundles-throw-potions
-ftb-team-bases
+ftb-team-bases|FTB 团队基地 (FTB Team Bases)
raworesmelting@
dpt@
potion-effect-enchantment
@@ -18927,7 +18927,7 @@ apothic-supplementaries-enchanting
apothic-amendments-enchanting
apothic-mutant-heads
apothic-science-moa-stats
-ye-gamol-chattels-reborn@
+ye-gamol-chattels-reborn@|伊加墨的财产:重生*
mme@my-more-enchantments|我的更多附魔 (My More Enchantments)
@@ -19060,7 +19060,7 @@ simply-more@simplymore
wetland-whimsy@|奇湿妙想*
-@deputy-placement-switch|求你别放了 (NoG8Put)
+@deputy-placement-switch|求你别放了 (NoG8Put / Deputy placement switch)
ileafcore
dirt-tools-and-armor@|泥土工具与盔甲 (Dirt Tools and Armor)
thaumic-rings-of-power|神秘众戒*
@@ -19078,7 +19078,7 @@ goety-gotta-summon-em-all@goety-gotta-summon-em-all!|诡法的混沌拓展 (Goet
aerlune-rpg-2
origin-furs@
grounded-origins-forge@groundedorigins¨grounded-origins-fabric
-@sand-and-gravel-are-forbidden-to-fall|禁止下落 (Nofall)
+@sand-and-gravel-are-forbidden-to-fall|禁止下落 (Sand and gravel are forbidden to fall)
tinkers-tool-leveling-2@|匠魂工具升级2*
remodifier-reborn|你别造了!!!*
exporbrecall@|经验球召回 (ExpOrbRecall)
@@ -19127,7 +19127,7 @@ growmeal-fabric@growmeal-(fabric)
katharite-slimes@slimes-of-kathare
botania-ceu
-magic-from-the-east@
+magic-from-the-east@|东方秘术*
blatapi@
@materials-lib
cavelib@
@@ -19191,7 +19191,7 @@ cloud-revive@cloud_revive|云生*
paranoia|偏执狂*
thaumic-brewing|神秘酿造学*
aether-treasure-reforging@
-animations@
+animations@animatium-legacy
@pet-necropolis
paddle-boats
true-darkness-elementriy
@@ -19260,7 +19260,7 @@ moves-like-mafuyu@|高速企鹅*
vanillin@flw-vanillin
chain-mining-reforged@chainminingreforged|连锁采集重铸*
hrtffix@|HRTF修复 (HRTF Fix)
-iammusicplayer-renewed@iam-music-player-renewed
+iammusicplayer-renewed@iam-music-player-renewed|Iam 音乐播放器:重生 (Iam Music Player Renewed)
misc-tweaks@misctweaks
ftb-filter-system
neonium@
@@ -19335,7 +19335,7 @@ spitting-image@
mob-journal@|生物图鉴*
sdm-shop@
-economy-coins-bills-and-gems
+economy-coins-bills-and-gems@economy-coins%2C-bills-and-gems!|经济:硬币、纸币和宝石! (Economy: Coins, Bills and Gems!)
multi-hotbar-core
multi-hotbar|多重快捷栏 (Multi-Hotbar)
properties-panel@propertiespanel|属性面板*
@@ -19370,14 +19370,14 @@ flight-affinity@
emcgadgets
@minecraft-engineer-edition
-@eyelib
+eyelib@
custom-armor-bar@
roughly-enough-input-methods@
pirates-doom@
techrebornjei@|科技复兴JEI (TechRebornJEI)
little-joys@
blasting-raw-metal-blocks-into-blocks-fabric-forge@blasting-raw-metal-blocks-into-blocks
-
+pbj-modern-conflict-rearmed
@re_mob-control-wands|重制:怪物控制魔杖 (Re: Mob Control Wands)
nekoration-reborn|猫咪装饰:重生 (Nekoration-Reborn)
@@ -19416,7 +19416,7 @@ gputape@
@limitless-anvil|铁砧限制修复 (Limitless Anvil)
carry-on-extend@|搬运:拓展*
kaleidoscope-doll@|森罗物语:玩偶*
-kamen-tinker|蓝钢匠艺/假面匠艺*
+
agritech-automated-crops@
@pots-idea|脑洞瓦工 (Pot's Idea)
kogtyv-tav@|Kogtyv 的城镇与村庄 (kogtyv-Towny and Village)
@@ -19582,12 +19582,12 @@ embers-underground-rooms@
dontstarve4@|不要饿死 4 (Don't Starve 4)
spark-core@|星火核心*
nether-core-useful-nether-rock|下界核心 (Nether Core)
-slashblade-js|拔刀剑 JS (SlashBlade JS)
+slashblade-js@|拔刀剑 JS (SlashBlade JS)
caerula-arbor@|方块与深蓝之树*
alices-doll|元歌 (Alice's Doll)
bedrock-redux@|基岩再现*
item-entity-control|掉落物清理*
-wishing-fountain|许愿泉*
+wishing-fountain@|许愿泉*
@unbelievable-enchantment|令人不可置信的附魔 (Unbelievable)
@hgws-spyglass-a|Hgw的望远镜 (Hgw's Spyglasses)
we-do-copyright@
@@ -19643,7 +19643,7 @@ sheep-variety@
@tetraclip|易验锻造 (TetraClip)
@rozhud
the-cosmic-spokespersons@|宇宙代言者*
-mc-mods-in-zero@all-in-zero|一切于零 (All In Zero)
+mc-modsinzero@all-in-zero|一切于零 (Allinzero)
yunzhu-transit-extension@|云竹交通拓展*
goodbye-dirt-screen@|澄清素视 / 去你的泥土屏幕*
@@ -19679,7 +19679,7 @@ cybersus@
zettai-rpg@
md-units@md-unit-robots
extreme-core
-dreamless-spells-and-spellbooks
+dreamless-spells
gregtech-meowmelmuku|格雷科技非官方版 - 喵呜酱版 (GregTech - MeowmelMuku)
@namedloot
@enchantment-decay
@@ -19736,7 +19736,7 @@ ships-legacy
traders-backport
banner-patterns-backport@
convenient-effects@
-baguettelib
+baguettelib@
fast-event@fastevent
@citreforged
better-meteorite|更好的陨石*
@@ -19950,11 +19950,11 @@ yuns-weather@
qliphoth-awakening@|逆卡巴拉:觉醒*
-universal-mod-localizer@universal_mod_localizer|通用模组汉化器*
+universal-mod-localizer|通用模组汉化器* - 不再更新¨@universal_mod_localizer|通用模组汉化器 (Universal Mod Localizer)
smart-creeper@|智慧苦力怕*
peaceful-depletion@peaceful_depletion|和平消耗*
@everything-is-tnt
-structure-pool-api@
+structure-pool-api@|结构池API (Structure Pool API)
create-bluemap@
tragicmc-2-continuation|悲惨世界2:延续 (TragicMC 2 Continuation)
nebula-parasites@
@@ -20038,13 +20038,13 @@ mc-modsoy-smelter@alloy-smelter
time-in-a-bottle-charger@
just-a-sculk-vial@
lockylocks@
-server-i18n-api@
+server-i18n-api¨@server-i18n-api|Server I18n API - 不再更新
fragmentum-forge@fragmentum¨fragmentum-neoforge¨fragmentum-fabric
@monument-data-fix|Monument 数据修复 (Monument Data Fix)
@better_tp
waystone-currencys@|消币则至 / 传送石碑:货币 (Waystone: Currencys)
@armor-stand|盔甲架 (ArmorStand)
-threadtweak-reforged|ThreadTweak (Neo)Forge 移植版 (ThreadTweak Reforged)
+threadtweak-reforged
@environmental-creepers-backport
com-bat
touhou-little-maid-rpg-class-task@touhou-little-maid-rpg-task
@@ -20083,7 +20083,7 @@ eiramoticons
horse-breeding-fix@
tablistextension@|TAB 列表扩展 (TabListExtension)
rally-of-the-guard-guardvillagers
-bncci
+bncci@
@recipe-maker
portaltransform@|传送门嬗变 (PortalTransform)
@a555sd|更多的画 (More Paintings)
@@ -20095,7 +20095,7 @@ mekanism-more-machine@mekanismmoremachine|通用机械:更多机器 (Mekanism:
custom-battleroyale@|自定义大逃杀 (Custom BattleRoyale)
improved-pillager-outpost
rebalanced-enchanting@
-dark-doppelganger@
+dark-doppelganger@|黑暗二重身*
enders-spellsandstuff
hazen-n-stuff@
spongeforge@
@@ -20105,7 +20105,7 @@ sdm-market@
omnilook@
survivalist-essentials@
-villager-trading-plus@trading+
+villager-trading-plus@trading+|简单村民交易+*
mending-fix|经验修补修复*
colorwheel@
@@ -20285,7 +20285,7 @@ enchantment-to-attack-faster|并非环取/攻击速度附魔非官方版 (Attack
@stopgrowth|停止生长 (StopGrowth)
squid-no-glitch
@permanent-night-vision|无痕夜视 (Permanent Night Vision)
-@rems-carpet-addition
+rems-carpet-addition@
colorful-hex@
@@ -20297,8 +20297,8 @@ jei-integration-reborn@|JEI扩展:重生 (JEI Integration: Reborn)
appliedsync
jei-uu-assembler@
ominous-overlays
-create-nuclear-shell@
-world-of-wonders
+create-nuclear-shell@|机械动力:核弹 (Create: Nuclear Shell)
+world-of-wonders@world-of-wonders-reforged
horrible-meteor-shower|陨石雨*
desertification@
cinchs-abandoned-houses@
@@ -20527,7 +20527,7 @@ potionsplus
tinkers-wood@
illuminated@
galosphere-argent-edge
-brutality-a-terramity-addon
+brutality-a-terramity-addon@
free-epic-games@|FE 游戏框架 (FreeEpicGames)
fabric-database-h2@|H2数据库*
@@ -20563,9 +20563,9 @@ create-fantasizing-again@|机械动力:又在幻想了 (Create: Fantasizing Ag
crafting-station-jei-edition-updated@
uncraft-everything@
@videoplayer
-net-music-play-list@|网络音乐机:播放列表 (NetMusic: Play List)
+net-music-play-list@|网络音乐机:更好的体验 (Net Music: Better Experience)
-gregs-modern-construct
+gregs-modern-construct@
smart-key-prompts@|灵活按键提示 (SmartKeyPrompts)
@zero-whitelist|Zero白名单 (Zero Whitelist)
@@ -20597,7 +20597,7 @@ neoenchant
enhancedtooltips@
locate-fixer
journeymap-fixes
-ancient-structure@ancient-structures
+ancient-cultural-structures@ancient-structures
wizard-samurai-irons-spells-addon¨@wizard-samurai-irons-spells-addon|Wizard Samurai - Iron's Spells Addon - 更新较慢
survival-instinct
@@ -20692,14 +20692,14 @@ better-questing-immersive-engineering-multiblock
bloodyquests
croaker@
crawl-on-demand@
-gaze-a-malum-addon
+gaze-a-malum-addon|凝瞳 (Gaze)
osce|矿石菌种社区版 (OreSpawn Community Edition)
explosive-arrow
more-relics@
no-sun@no-sun-mod|暗无天日*
opposing-force@|针锋相对*
-@pingfix
+fix-my-pinggggg@pingfix
@volumescroll
talk-balloons@
health-indicator-txf@
@@ -20803,7 +20803,7 @@ creeperhost-presents-steves-carts@
perspatium@per-spatium
offlawn-legacy
-metalborn
+metalborn|金属之子*
@wizards-mod
mo-creatures-nostalgia-edition@
mocreatures-awakened
@@ -20815,7 +20815,7 @@ treetap@
better-cave-update
@affix
starry-end
-dynamic-trees-for-cobblemon
+dynamic-trees-for-cobblemon@
immersive-portal-gun-for-forge@
adorable-hamster-pets@
infinite-lava@|无限熔岩*
@@ -20823,7 +20823,7 @@ ethereal-shots|无限箭制 (Unlimited Arrow Works)
epic-fight-super-golem|超级铁傀儡 (Epic Fight - Super Golem)
fallen-log-hideout
-pastel@pastel-mod|彩绘世界*
+pastel@|彩绘世界*
mob-catcher-unofficial
retro-pet-items
confluence-dimension-patch|汇流来世维度补丁*
@@ -20941,8 +20941,8 @@ fires-ender-expansion
thetitansneo@|泰坦生物Neo (TheTitansNeo)
vectorientation-reneoforge
copyid@|复制ID (CopyID)
-@a-lightcolor-beacon
-@surveyor
+a-light-color-beacon@a-lightcolor-beacon
+surveyor-map-framework@surveyor
@create-portable-packaging
create-more-pipe-bombs-in-packages@
create-bugfix-schematic-patch@|机械动力:蓝图补丁 (Create Bugfix: Schematic Patch)
@@ -20964,7 +20964,7 @@ tiger-shark@tigershark|海虎 (TigerShark)
better-end-cities-better-end@better-end-cities-for-betterend|更好的末地城 (Better End Cities)¨better-end-cities-vanilla@better-end-cities-base|更好的末地城 (Better End Cities)
fallen-gems-affixes
-skill-tree
+skill-tree@
blatium@
trimica@
fantasy-weapons-medieval-series@fantasy_weapons
@@ -21011,7 +21011,7 @@ legends-forge-series-vikings-n-northerners
tinkers-battle-spades
@its-not-real
ly-meteors
-ashvehicle
+ashvehicle@
@smart-absorption
@mooshees
city-of-chambers
@@ -21273,7 +21273,7 @@ ftb-materials
the-great-below
illagerblabber@
-serene-season-extended-fix@serene-seasons-plus
+serene-seasons-plus@¨serene-season-extended-fix
create-enchantment-industry-plus@
boiled-one-unleashed@
creaturecraft-plus
@@ -21390,7 +21390,7 @@ aggro-fix@
chest-curio-items@|箱子里的小饰品*
galaxysimagination|Galaxy的奇思妙想 (Galaxy's Imagination)
delightful-cuisine-for-woodheads-reforged|懒人厨房·重制 (Delightful Cuisine for Woodheads Reforged)
-@loans-cinema
+loans-cinema@
banana-baking@
duacan-delight|岩城乐事*
slashblade-refabricated@|拔刀剑:重织 (SlashBlade: Refabricated)
@@ -21402,7 +21402,7 @@ dirtcraft-unoffical|泥土工艺 - 非官方版 (DirtCraft - Unofficial)
specialmaterials@|材料 (Materials)
@onlytpnext|仅传送Next (OnlyTPNext)
easy-survival-command|简单生存指令TP (EasySurvivalCommand)
-@gensokyo-reverie-of-lost-dreams|梦隐的幻想乡 (Gensokyo Reverie of Lost Dream)
+gensokyo-reverie-of-lost-dreams@|梦隐的幻想乡 (Gensokyo Reverie of Lost Dream)
reliquified-ars-nouveau@
requesting-interface@irequesting
applied-experienced@
@@ -21449,13 +21449,13 @@ inhrtburys-coin|Inhrtbury的金币 (Inhrtbury's Coin)
@firesight
epic-villages
@brainfk-in-minecraft
-@aviator-dreams-reloaded
+aviator-dreams-reloaded@
russian-dream
-cbc-ballistics
+cbc-ballistics|机械动力火炮:弹道学 (CBC Ballistics)
create-programmable-pals
create-ore-excavation-plus@
-@createtreadmill|机械动力:跑步机 (Create:Treadmill)
+create-treadmill@createtreadmill|机械动力:跑步机 (Create: Treadmill)
create-more-package-couriers@
regius@
@@ -21464,7 +21464,7 @@ regius@
dont-make-me-see-red|别让我红温*
peyros-scythe|佩伊洛的镰刀 (Peyro's Scythe)
-
+@kamenriderex-aid|假面骑士:艾克赛德 (Kamen Rider EX-AID)
@readstar|占星术 (ReadStar)
illage-and-legend
giant-dead-oak-tree@
@@ -21492,7 +21492,7 @@ countryball@minecraft-countryball-mod
tinkers-construct-emergence
pointblank-jelly@pb-jelly
terrabnormals
-extra-mining-world
+extra-mining-world@
herobrine011840s-nether-biomes
my-end
update-ender-a-reimagine-of-the-end
@@ -21623,7 +21623,7 @@ audaki-cart-engine@
@force-beacon-load|信标强制加载 (Force Beacon Load)
humansmod@humans-mod
-aquaacrobaticslegacy
+aquaacrobaticslegacy@aqua-acrobatics-legacy-(ragecraft-version)|水游技艺:传承 (Aqua Acrobatics Legacy)
@modmenu-btw
armored-arms@
armored-golems
@@ -21700,7 +21700,7 @@ winefoxs-spellbooks@winefoxs_spellbooks|酒狐的魔法书 (Winefox's Spellbooks
better-allay@
codechicken-lib-cre@
solcarrot-fix|生活调味料:胡萝卜版 - 死吃修复*
-
+roachs-delight-farmers-misery|蟑螂乐事/农夫悲事 (Roach's Delight/FarmerMisery)
nanexs-cherry-biome
digital-botania
@@ -21909,7 +21909,7 @@ no-template-netherite@
@mobcapture
koifish@
-
+@mindshaft
@mcinspects
@csgo-inspects
armor-hud-by-mcjunky33@
@@ -22062,7 +22062,7 @@ amnesia-core
@minecraft-sqlite-jdbc
sqlite-jdbc
forbidden-arcanus-js
-
+@recipe-helper|配方编辑器 (RecipeHelper)
@sha1redemption
f-k-create-world@fcw|不要创建世界 (F××k Create World)
maid-task-scrolling-helper@|女仆任务滚动助手*
@@ -22253,7 +22253,7 @@ gtbcs-geomancy-plus
@hiirosakura
-us-universal-summoning-new|通用召唤 (Universal Summoning)
+us-universal-summoning-new|通用召唤 (Universal Summoning/Universal Summoning New)
@gambac
cad-editor@
@@ -22304,8 +22304,8 @@ makeae2better@
@past-el-palettes
@blowing-bubbles
mobs-n-growths-origins
-roadarchitect-encounters
-
+roadarchitect-encounters@
+@extended-drawers-polymer
@mystcraft-ageless
thaumcraft-return-of-the-ancients@
@@ -22355,7 +22355,7 @@ awakened-craziness
villager-market-nbt-fix|村民市场 - NBT 修复版 (Villager Market - NBT Fix)
illager-expansions
@tropicraft-stationapi
-bbl-shops
+bbl-shops@
@dronebox
@volo-volare
@customanvilrenameable|自定义铁砧改名权 (CustomAnvilRenameable)
@@ -22372,7 +22372,7 @@ recipes-of-the-lost@|失落配方 (Recipes of the Lost)
tacz-pack-upgrader@
-@ping-view
+ping-view@
extravagant-delight@
@@ -22395,7 +22395,7 @@ mytown
@linverticalslab|竖半砖 (Lin Vertical Slab)
@pearlchunkloader|珍珠区块加载器 (PearlChunkLoader)
-@lv-wings
+lv-wings4@lv-wings
@foxbox
@more_than_a_foxbox
@fox-plushies
@@ -22624,7 +22624,7 @@ yumo-isk-stackstackstack|拼好组 (Yumo isk-Stackstackstack)
flourfood|面食 (Flour Food)
-neo-ae2-toogleable-view-cell@|AE2可切换显示原件-Neo (Neo AE2 Toogleable View Cell)
+neo-ae2-toogleable-view-cell@|AE2可切换显示元件-Neo (Neo AE2 Toogleable View Cell)
mtt-more-tetra-tools-new|更多Tetra工具 (More Tetra Tools)
compat-delight@
@@ -22653,7 +22653,7 @@ maid-travel-camera|女仆旅行相机*
nieih@
origins-furs-updated@
-tinkers-gears@|匠械 (Tinkers' Gears)
+tinkers-gears|匠械 (Tinkers' Gears) - TGears V1,¨tinkers-gears-2|匠械 (Tinkers' Gears) - TGears V2¨@tinkers-gears|匠械 (Tinkers' Gears)
moreeverything
epic-fight-skill-tree@
@@ -22691,7 +22691,7 @@ clanging-howl
limbus-company-mod-lcm|边狱公司:麦块部门 (Limbus Company Mine Section)
realistic-bird-behavior@|真实鸟类行为*
-wing-kirin|翼麒麟*
+wing-kirin@wing-kirin-dragon-survival-addon|翼麒麟*
mcheli-reforged-mch-r
@@ -22783,7 +22783,7 @@ parcoolskill@|跑酷技能 (ParCoolSkill)
merchantjs@
fetchjs@
mc-mods-the-mafuyu@all-the-mafuyu|万象瑞雪 (All the Mafuyu)
-goety-end-biomes
+goety-event-horizon@
structure-spawn-area-fix@|结构生成区域修复*
aloof-new@aloof¨aloof|Aloof! - 旧版
@@ -22836,7 +22836,7 @@ display-edit
arthys-elemental-engine-aee-forge
bobby-legacy@
ambience-mini
-arthys-ebonite-ae-forge
+arthys-ebonite-ae-forge@arthys-ebonite-(ae)
enigmatic-arcana
mekanismceu-moremachine|通用机械:更多机械 (Mekanism-CE-Unofficial-MoreMachine)
optifine-cit-enchantment-patch@optifine-cit-patch
@@ -23124,7 +23124,7 @@ industrial-revolution-by-redstone-rebooted
omoshiroi-kamo
death-taxes@death-and-taxes
-@emotional-support-creeper
+emotional-support-creeper@
ly-ender-compass
walking-crops
harken-scythe-resharpened@
@@ -23151,7 +23151,7 @@ dyson-cube-project|戴森立方计划*
annoying-villagers-herobrine-invasion@|烦人的村民 (Annoying Villagers: Herobrine Invasion)
@net-music-peripheral|网络音乐机:电脑外设 (Net Music: Peripheral)
-
+@simpletranslation|简单翻译 (SimpleTranslation)
tacz-golem-compat@|傀儡装配-战术人形 (TaCZ Golem Compat)
customizable-player-health@|可自定义的玩家生命值*
@@ -23316,7 +23316,7 @@ fastconfigapi@
@awakeapi
@anti-offhand
@so-tuff
-
+lootswap@
moreeventsjs
spudiversity-more-and-more-potato|土豆盛宴-更多的土豆! (Spudiversity - More And More Potato)
@@ -23383,7 +23383,7 @@ anothertips@
copper-drops
cooks-collection@
-
+bosses-unleashed
no-end|我的末地呢?!*
ome-tweaks@
clutter-no-more@
@@ -23518,7 +23518,7 @@ craycrafting
@rain-world-weaponry
customtitlescreen
unusual-prehistory-2@|不寻常的史前史2*
-shield-api@
+shield-api@|盾牌 API (Shield API)
brick-lib-api@
whatversioning|申必版本号 (WhatVersioning)
yourender|完了 (YourEnder)
@@ -23657,7 +23657,7 @@ northstar-redux@|机械动力:北极星 - 重制版 (Create: Northstar - Redux
create-igneodynamics@
create-numismatics-utils@
create-vintage-unofficial-port@create-vintage-(unofficial-port)
-create-bits-n-bobs@
+create-bits-n-bobs@|零零件件 (Create: Bits 'n' Bobs)
ccb-tweaks@ccbt
gregtechceu-modern-extra-unofficial@gtceu_extra
geotetraarmor
@@ -23685,7 +23685,7 @@ mossylib@
better-trading-menu@|更好的交易菜单*
easy-npc-config-ui@
evolved-mekanism-extras|通用机械:进化扩展*
-@music-hud
+music-hud@
backups
inventory-particles@|物品栏粒子*
backport-recipes@
@@ -23749,7 +23749,7 @@ tacz-turrets@
health-scoring
supearlposition
daisy@
-no-fall-mod
+no-fall-mod@no-fall-damage
@farmers-assortment
foggy-world
@@ -23759,7 +23759,7 @@ techrot@
create-easyfilling@
mortar-and-pastels@mortar
@delicate_little_garbage|精致小垃圾 (Delicate Little Garbage)
-elementalcraft-reactions@|属性锻造:元素反应 (ElementalCraft: Reactions)
+elementalcraft-reactions@|属性锻造:元素反应 (Elemental : Reactions)
kubejs-recipes-create|KubeJS配方生成 (KubeJS Recipes Create)
hamstercore@|仓鼠核心 (HamsterCore)
@@ -23818,7 +23818,7 @@ spinning-items-displayer-mod@
attack-range-attribute@
kreno-fpatcher@
riautomobility@
-cyberware-reforged@
+cyberware-reforged@|机械改造:重生 (Cyberware: Reforged)
project-plastic
blocky-file@|方块文件*
@@ -23830,7 +23830,7 @@ nocubes-food-desire
prehistoric-rift@
-more-slashblade-ex-enchantment-effects|超多附魔增效 (More SlashBlade Ex Enchantment Effects)
+more-slashblade-ex-enchantment-effects@|超多附魔增效 (More SlashBlade Ex Enchantment Effects)
tinkers-emc|匠魂EMC (Tinker's EMC)
@tacz-advanced-deathinfo|TACZ 高级死亡信息 (TACZ Advanced DeathInfo (Kill Banners))
summon-totem|召唤图腾*
@@ -23867,7 +23867,7 @@ i-f-amphithere-mod
unu-civilian-pack-for-mts@unu-civilian-pack
rlcraft-manhunt
-ancient-forgemastery@
+ancient-forgemastery@|远古锻造*
relentless-undead
@classic-farlands|经典边境之地 (Classic Farlands)
@@ -23890,7 +23890,7 @@ one-enough-enchantment@
one-enough-value@
@coordinate-manager|坐标管理器 (Coordinate Manager)
-
+@legacy-fabric-api-fixes-btw
@gravestones-fix|墓碑修复 (Gravestones Fix)
whimsy-deco@
incendium-translation-fix@
@@ -23958,7 +23958,7 @@ sync-forge
@sync-fabric-reported
player-shells@|玩家躯壳*
cataclysm-ametyst-crab-temple@
-@entity-0-elytra-fix
+entity-0-elytra-fix@
goety-mastery-of-magic-addon@|巫法精通 (Goety: Mastery of Magic Addon)
malisis-doors-revived
akuto-engine
@@ -24013,7 +24013,7 @@ thebladeofchaos49|混乱处刑 (Blade of Chaos)
maophone-trial-version@|MaoPhone体验版 (MaoPhone - Trial Version)
-mrmc|世界之心 (Aether Cores)
+mrmc@|世界之心 (Aether Cores)
@arcane-vortex|秘法涡流 (Arcane Vortex)
@@ -24049,7 +24049,7 @@ hud-control@|HUD 控制 (HUD Control)
mchce|MC 直升机:社区版 (McHeli: Community Edition)
-easier-proud-soul-acquisition|更容易的耀魂碎片获取 (easier proud soul acquisition)
+easier-proud-soul-acquisition@|更容易的耀魂碎片获取 (easier proud soul acquisition)
@slashblade-re-refabricated|拔刀剑:再重织 (SlashBlade: RE-Refabricated)
mystical-agriculture-community-edition@|神秘农业社区版*
lazydfu-reloaded@
@@ -24060,7 +24060,7 @@ easydoll@|简易玩偶 (EasyDoll)
gaiatweaks@
luckier-clover@|更幸运的四叶草*
-create-electro-energetics|机械动力:电力学 (Create: Electro Energetics)
+create-electro-energetics@qYJdIoAx|机械动力:电力学 (Create: Electro Energetics)
universal-trinkets@
roguelike-tower|肉鸽塔 (Roguelike tower)
@@ -24071,7 +24071,7 @@ prims-stranger-things-mod
super-backpack@|超级背包*
-
+ntm-cursed-addon-edition
radiance¨@radiance-mod-windows¨@radiance-mod-linux
xaerolib@
@@ -24095,7 +24095,7 @@ no-fly-zone@
twod-projectiles@twod_projectiles|2D 投掷物 ➵ (2D Projectiles ➵)
morethermalevaporation
autofish-for-tic@|自动钓鱼Forge版-匠魂兼容 (AutoFish for Tic)
-wtc-wizard-terra-curios-new|泰拉饰品拓展 (Wizard Terra Curios/Wizard Terra Curios New)
+wtc-wizard-terra-curios-new|泰拉饰品拓展/泰拉灾厄饰品 (Wizard Terra Curios/Wizard Terra Curios New/Calamity Terra Curios)
invitemmark@|物品标记 (InvItemMark)
book-of-dragons@
@@ -24287,7 +24287,7 @@ debugify-reforged
ae2-tangible-bookmarks@
deadbyskillcheck@
stormies-spiders@
-saints-dragons@
+saints-dragons@|Saint的群龙 (Saint's Dragons)
buildtech|建筑科技 (BuildTech)
@@ -24302,7 +24302,7 @@ buddy-drones@
shels-minechat
legacy-gamemode-switcher
@borukva-food-exotic
-betterblockz@
+betterblockz@|更好的方块 (BetterBlockZ)
packagedtacz|封包TaCZ (PackagedTacz)
lotas-light@
@@ -24311,7 +24311,7 @@ mob-locator@
zoesteria
-@random-optimization|随意优化 (Random Optimization)
+random-optimization@|随意优化*
embergetic-expansion-embers-rekindled
irons-spell-books-arcane-essence-blocks@irons-spellbooks-arcane-essence-blocks
vampirism-irons-spells-compatibility@
@@ -24532,9 +24532,9 @@ santa-logistics@
easy-survival-plus@easy-survival-mod
-
+neon-glitch-exiled-divinity|霓闪感染:被放逐的神迹 (Neon Glitch: Exiled Divinity)
@kaleidoscope-texture-expansion|森罗厨房:乐此不疲 (Kaleidoscope Texture Expansion)
-legendary-additions
+legendary-additions@
tacz-arcana-timeless-and-classics-guns
mebahels-creatures-draugr@|Mebahel 的生物 - 尸鬼 (Mebahel's Creatures - Draugr Invasion)
@@ -24552,7 +24552,7 @@ mace-enchantments
masterful-machinery-fork
enchantment-limiter-fork
cobblemonraiddens@
-
+@terrain-diffusion
heartmod@binding-of-isaac-heart-mod
pokecube-legacy@
seasons-mc
@@ -24606,7 +24606,7 @@ instantworldmirror|瞬时世界之镜 (Instant World Mirror)
@floating-excavation|浮空挖掘 (FloatingExcavation)
hostile-mobs-and-girls-recall|敌对生物与魔物娘:追忆 (Hostile Mobs and Girls: Recall)
@holoinventory-reloaded|物品显示/物品清单:重载版 (HoloInventory-Reloaded)
-@everlaartifacts|七叶镜绫的随想/言引定制 (EverlaArtifacts)
+@everlaartifacts|七叶镜绫的随想 (EverlaArtifacts)
@bright-sunflower|曜日金葵 (Bright Sunflower)
atm-azure-tetra-materials|蓝钢锻艺 (Azure Tetra Materials)
@@ -24675,7 +24675,7 @@ christmascolonies|圣诞殖民地 (ChristmasColonies)
mnaoverpowered@
stack-manager@
ae2-mod-id-view-cell
-@curios-media-holder|我抄饰你的媒 (Curios Media Holder / Trinkets Media Holder)
+@curios-media-holder
custommeteorjs@
kaleidoscope-end@|森罗物语:末地*
macaws-regions-unexplored@
@@ -24701,7 +24701,7 @@ foolish@
entitychinesename@|实体中文名 (Entity Chinese Name)
firma-aircraft@|群峦航线*
-exura@|更多实用设备:再重生 (Extra Utilities Reborn Again)
+extra-utilities-reborn-again@exura|更多实用设备:再重生*¨exura|更多实用设备:再重生 (Extra Utilities Reborn Again)
shaolib@
manage-your-ship@
@@ -24807,7 +24807,7 @@ rats-ratn-edition
@eye_of_dreams
foolish-unofficial-patch
-@damage-engine|伤害引擎 (Damage Engine)
+damage-engine@|伤害引擎*
travelers-lib@
@@ -24825,7 +24825,7 @@ ae2-tech-add-on|AE2 科技扩展 (AE2 Tech Add-On)
@create-nerfad
questextra
flans-mod-npc-vehicles
-@easyloginmod|简易登录 (EasyLogin)
+@easyloginmod|简易登录 (EasyLoginMod)
inventory-sort-nf|背包整理(NeoForge 版) (Inventory Sort (NeoForge Edition))
someordinarytweaks-forge@ordinarytweaks
@@ -24839,9 +24839,9 @@ adventurers-amulets|冒险家的护身符 (Adventurer's Amulets)
create-frequency-filter|机械动力:频率过滤器 (Create: Frequency Filter)
@accurate-skies
-
+@antideath-carpet-addition|AD的Carpet拓展 (Antideath Carpet Addition)
@xytpa|Xy的TPA模组
-
+@hlgid|heef的轻量级游戏信息显示 (Heef's Lightweight Game Information Display)
steves-factory-manager-reborn|史蒂夫工厂-重置 (Steve's Factory Manager Reborn)
steves-addons|史蒂夫工厂管理附加 (Steve's Addons)
ffs-fancy-fluid-storage@|液体存储 (Fancy Fluid Storage)
@@ -24885,7 +24885,7 @@ abyssalcraft-remnant-tweaker
herobrine-companion@herobrine_companion|Herobrine 的陪伴*
industrial-forestry
avaritia-lite-extended
-goety-hostility@
+goety-hostility@|诡厄敌袭*
fish-traps-remastered@|鱼栅非官方重制版*
the-ponderer@|思索者 (Ponderer)
fallen-lib
@@ -24992,7 +24992,7 @@ pulsetech@
@night-lights-polymer
snowscaress@
-@new-sim-u-kraft|新:模拟大都市 (New: Sim-U-Kraft)
+new-sim-u-kraft@|新:模拟大都市 (New: Sim-U-Kraft)
fancy-outlines
ae2-pattern-encoding-access-terminal@
efficient-entities@
@@ -25008,7 +25008,7 @@ goslingcord
emojicord
@logarithmic-volume-control
scarcity@
-mo-bends-unofficial-modern-port@|更多弯曲 [现代化移植] (Mo' Bends [MODERN PORT])
+mo-bends-unofficial-modern-port|更多弯曲 [现代化移植] (Mo' Bends [MODERN PORT])¨@mo-bends-unofficial-modern-port|更多弯曲 [现代化移植] (Mo' Bends [MODERN PORT]) - 更新滞后
@supersteve|超级史蒂夫 (Super Steve)
longroad|前路已明 (Road Is Ahead)
@@ -25035,7 +25035,7 @@ yeti-jar-dweller
create-automotives@
exposure-expanded@
smart-spawn@
-random-mob-textures@
+random-entity-textures@
uifadefx@
daily-boss@
it-seems-loosely-connected-to-the-ceiling@|与洞顶的连接似乎并不牢固 (It seems loosely connected to the ceiling)
@@ -25099,7 +25099,7 @@ ae2-overclocked@|AE2超频 (AE2 Overclocked)
@bred-is-cool
integrated-mekanism@
rainjava
-
+fabric-gui-imgui@
me-soul-card
@@ -25119,7 +25119,7 @@ display-tool|生物显血·极轻量版*
technological-assistance|科技辅助*
not-enough-bandwidth@|网络包优化*
apprentices-codex@|学徒法典 (Apprentice's Codex)
-asterism-arcanum-addon-for-irons-spells-and
+asterism-arcanum-addon-for-irons-spells-and@asterism-arcanum-addon-for-irons-spells-and-spellbooks
wizards-help-irons-spells-n-spellbooks-addon
ftw-addon
new-years-delight-a-farmers-delight-add-on@new-years-delight-(a-farmers-delight-add-on)
@@ -25135,7 +25135,7 @@ armor-3d@
hot-iron
dangerous@
balaclava-mod@
-@goodblock
+@changed_more_creatures
tacz-sound-attracts-zombies@|枪鸣尸至 (TaCZ: Sound Attracts Zombies)
ntrials@
alexs-mobs-fabric|Alex 的生物(Fabric) (Alex's Mobs (Fabric))
@@ -25178,7 +25178,7 @@ you-are-the-zombie-2-0|我是僵尸 (As The Zombie)
mobcivics@
tarotcards-remastered@|塔罗牌:重制 (TarotCards: Remastered)
-@copyblock|复制方块 (Copy Block)
+copyblock@|复制方块 (Copy Block)
@apocalypse_end|天启终焉 (Apocalypse End)
@bypass-fabric-check
@@ -25190,7 +25190,7 @@ openlink-chmlfrp-extension@|开放式联机:Chmlfrp扩展 (OpenLink Chmlfrp Ex
enchantato-enchantment-table
-red-envelope-reforge|红包 (Red Envelope)
+red-envelope-reforge@|红包 (Red Envelope)
advanced-backups-patch@|高级备份补丁*
@network-proxy
@asmcraft
@@ -25238,7 +25238,7 @@ create-fluidlogistic@createfluidlogistic|机械动力:流体包裹 (Create: Fl
kubejs-create-automation@
nether-star-items-forge@nether-star-items¨nether-star-items-fabric
piglin-hunt-fix
-ok-core
+ok-core@|OK 核心 (OK Core)
@ccexpand-peripherals|CC拓展外设 (CCExpand Peripherals)
colored-end-crystals
@@ -25351,7 +25351,7 @@ baby-steps
vintage-damage-indicators@|复古伤害显示*
-
+lol-equipment|LOL装备 (LOL Equipment)¨lol-new|LOL装备 (LOL Equipment)
apricityui@|晴雪UI (ApricityUI)
functionalstoragelegacy@|怀旧功能性存储 (FunctionalStorageLegacy)
@@ -25474,15 +25474,15 @@ mekanism-sun|通用机械:人造太阳*
anvil-lib@
vkbc|葡园酒香森罗酒馆酒瓶兼容 (Vinery & Kaleidoscope Tavern Bottle Compatibility)
-kaleidoscope-world-liquor@|森罗酒馆:世界名酒*
+kaleidoscope-world-liquor@|森罗物语:世界名酒*
@burning
@burning-energy
realisticsunburn
novums-altitude
mystcraft-reborn@|神秘岛:重生*
@cod-pattern
-tacz-lesraisins-tactical-equipements@lr-tactical|TaCZ:绿葡萄战术装备 (TACZ: LesRaisins Tactical Equipements)
-rotten-ruins|腐朽之疫*
+tacz-lesraisins-tactical-equipements@lr-tactical|TaCZ:绿葡萄战术工坊 (TACZ: LesRaisins Tactical Equipements)
+rotten-ruins|腐朽之疫:腐化 (Rotten Ruins: Corruption)
strawgolem-extended-life@straw-golem-unofficial-extended-life|稻草傀儡非官方延续版 (Straw Golem Unofficial Extended Life)
caves-not-cliffs-backport@caves-not-cliffs-backported
irons-spells-n-spellbooks-scroll-description
@@ -25491,7 +25491,7 @@ cnpcextended
yifeis-game-adjustments|Yifei的游戏调整
forcegl3-1
baublevault
-
+universal-draconic-slots|通用龙研格子*
embellish-chat@
changed-extra
@@ -25531,7 +25531,7 @@ debug-block-overlay-reloaded@debug-block-collision-reloaded
@progressive-tiers|阶梯强化 (Progressive Tiers)
apothic-enchanting-addition|通量神化附属*
puddles-floods@
-star-dragon-dragon-survival-addon|星辰龙 (Star Dragon)
+star-dragon-dragon-survival-addon@star-dragon|星辰龙 (Star Dragon)
casual-swing
@carvedmelon
@@ -25621,7 +25621,7 @@ beyond-storage-addon@beyond_storage_addon
decapitation
@narrow-zone
@aekey-legacy
-okbackpack
+okbackpack|OK背包 (OKBackpack)
thirst-was-tweaked@
@loots
@@ -25689,7 +25689,7 @@ tlm-attributedisplay|车万女仆:属性显示 (Touhou Little Maid: Attribute
jadeownerfix@|一眼认主 (JadeOwnerFix)
logistics-network@logisticsnetwork
@the-tnt-mod
-
+stronger-mekasuit|更强的Mekasuit*
@elytra-chestplate-swap
@noloadingterrain|无加载地形中 (No Loading Terrain)
@@ -25719,7 +25719,7 @@ create-paper@|机械动力:纸张*
@a-villagers-dream
colds-wandering-trader
majobroom-kots|魔女的扫帚 - 耕云钓月版 (Majo's Broom KOTS)
-@simupack|模拟大都市:筑艺坊 (Simupack)
+@simcityexpansion|模拟大都市:筑艺坊 (Simupack)
waterwheel-immortal|水车仙人*
tf-remastered|暮色创世 (TF Remastered)
@@ -25755,7 +25755,7 @@ ore-zombies|矿石僵尸*
vaders-ore-spiders-mod|矿石蜘蛛 (Ore Spiders)
-crafting-slots@
+porta-crafty@
ddlc-chibis
create-additional-lights@
@@ -25867,7 +25867,7 @@ lightspeed-kryo
memorycatcher
gtceu-terminals@|格雷科技终端 (Gregtech Terminals)
-superior-spellcasting
+superior-spellcasters
irons-patreon-library@irons-lib
yttrjei@
strange-trinkets@|奇怪饰品*
@@ -25899,8 +25899,8 @@ parkour-and-more
ash-of-sin-no-more-too-many-structures|罪业余烬:不再过多结构 (Ash Of Sin: No More Too Many Structures)
the-between@
evolutionary-defense-tower@|进化防御塔*
-the-zoomify-mod@zoomify!
-origins-neoforge@|起源 (NeoForge) (Origins (NeoForge))
+zoomlens@
+origins-neoforge|起源 (NeoForge) (Origins (NeoForge))¨@origins-neoforge|起源 (NeoForge) (Origins (NeoForge)) - 不再更新
lovecraft-boyfriends-3
saddlebag-wolf-bag-pet-backpack-companion-utility@saddlebag
rpg-attribute-system@
@@ -25927,14 +25927,14 @@ carry-on-back
clone-minerador-clone-miner
zombies-eat-animals@
the-lost-city@the-lost-city-by-berezka
-much-more-dungeons
-patchouli-library@
+much-more-dungeons@
+guide-shelf@
weather-refined@weatherrefind
@death-rewind|死亡回溯 (Death Rewind)
death-keeper@
quickshot@
powerborne-heroes@
-magic-reborn
+magic-reborn@|魔法重生*
excessive-utilities@
kimetsucraft-kc
curiosities-syndicate@
@@ -25959,9 +25959,9 @@ slave-mark|抗争证明 (Mark of Revolution)
headpats|摸摸头*
golem-magicka@|傀儡装配-奥法魔像*
sword-parry-enchant@parry-enchant
-golemera
+golemera|傀儡纪元*
the-imitator
-cyberware-visible-modifications@
+cyberware-visible-modifications¨@cyberware-visible-modifications|Cyberware: Visible Modifications - 已停更
structure-crafter@|构印师匠*
pop-up-emotes@
@@ -25971,7 +25971,7 @@ overgeared-spartan
loot-sentinel@
legendary-titles@
-weapon-rarity\@epic-rpg-weapon-rarity
+weapon-rarity@epic-rpg-rarity-system
party-hud@
rpg-class-artifacts@
average-dps@
@@ -26012,7 +26012,7 @@ time-in-a-bottle-fix-tiab-fix@
item-glint@|手持物品描边*
@mc-273265_fix
sbw-colorized@sbw-colorized!
-fading-time
+fading-time|时光渐陨*
@customnpcs-sortplus
@customnpcs-crafting-view
survival-monitor@
@@ -26034,7 +26034,7 @@ no-lapis-lazuli@|无青金石*
stronger-structures
warning@
create-bbq-belt|机械动力:传送带烧烤 (Create: BBQ Belt)
-shogi
+shogi@
mna-arcane-adornment|奥术饰品 (MnA: Arcane Adornment)
@in-game-log-display|游戏内日志显示 (In-game Log Display)
kindred-legacy¨pokemonmd-disciples-of-corruption
@@ -26076,7 +26076,7 @@ petrescue
simply-tents-blacklist@|简易帐篷:黑名单*
leashall@
auto-swap@autoswap
-@reset-villager-trades
+reset-villager-trades@
cbc-enchanced-shells-create-big-cannons|机械动力火炮:增强型弹药 (CBC Enchanced Shells)
xnet-additions
@@ -26093,7 +26093,7 @@ gabous-libs@
sitoneverything@
epic-tnt-mod@
the-body-boosts@
-f-tech-equipment#project-logo@f-tech-equipment|未来科技:装备 (F-Tech: Equipment)
+f-tech-equipment@|未来科技:装备 (F-Tech: Equipment)
jujutsu-kaisen-ultimate-zenith
terramity-paisleys-summoning@paisleys-summoning
@@ -26111,7 +26111,7 @@ envelope@
@windy
iron-furnaces-fabric-neoforge|更多熔炉(Fabric & NeoForge) (Iron Furnaces (Fabric & NeoForge))
iron-shulkers|更多潜影盒(Fabric & NeoForge) (Iron Shulkers (Fabric & NeoForge))
-iron-chests-fabric-edition|更多箱子(Fabric 版) (Iron Chests (Fabric Edition))
+iron-chests-fabric-edition|更多箱子:重织 (Iron Chests (Refabricated))
@piggy-lib
dungeons-and-villages-deeper-and-darker@
spring-to-life-backport@
@@ -26153,9 +26153,9 @@ simple-snowy-fix-forge-fabric@simple-snowy-fix-(forge-fabric)
enchanting-plus-classic
universal-portals
-oculus-for-simpleclouds
+oculus-for-simpleclouds@oculus-for-simple-clouds
-@yunbeiuc|云北城建 (Yunbei Urban Construction)
+yunbeiuc@|云北城建 (Yunbei Urban Construction)
log-deduplicator
project-atmosphere@
@@ -26183,8 +26183,8 @@ random-tnt-adds-4-useless-tnt-blocks
au-naturel-da-fishing-mod
crafter-hologram
village-utilities
-some-illager-servants
-cataclysm-fallingtree-compat
+some-illager-servants|诡厄巫法:凶兆 (Goety Ominous)
+cataclysm-fallingtree-compat|灾变伐树兼容 (Cataclysm FallingTree Compat)
fip-vips-aimoptimizer
minepersist@
@@ -26208,7 +26208,7 @@ natures-appetite@|生灵食性 (Nature's Appetite)
@misias-manametalmod-extension|米西娅的魔法金属扩展 (Misia's ManaMetalMod Extension)
hunger-begone@|饱腹远行*
the-boreal@
-kerria
+kerria@kerria-opt
cc-complementary-core@
cs-towers
vista-all-the-cassettes@
@@ -26320,11 +26320,11 @@ tidal-commission|潮汐委托* - data文件为英文¨@tidal-commission|潮汐
@arsenal
aaas-strongermobs@strongermobs|更强的怪物 (AAA's StrongerMobs)
-@legacy-of-utopia
+the-king-and-the-queen-legacy-of-utopia@legacy-of-utopia
packcompanion
portalmod@
theworldbelow@alpha-below
-
+@hbm-ntm-high-edition|HBM现代化高版本 (HBM High Edition)
mc-matrix-bridge@
@world-importer
@@ -26451,7 +26451,7 @@ blocklings-nostalgia-edition|方块酱:怀旧版 (Blocklings: Nostalgia Editio
slashblade-amazingshining|荧光惊异 (SlashBlade:AmazingShining)
the-god-fox|御神狐之刃 (The God Fox Reborn)
-godbirdreborn|毕方重生 (GodBirdReborn)
+godbirdreborn|神鸟之刃·棘羽毕方 (GodBirdReborn)
balmungreborn|巴鲁蒙格重生 (BalmungReborn)
pseudo-edge-dawnbreaker|伪格雷普终境之刃·终境破晓 (Pseudo-Edge: Dawnbreaker)
slashblade-thebladechronicles|刀绘卷 (SlashBlade: Egotachi)
@@ -26471,7 +26471,7 @@ clutterbestiary@
custom-murder-mystery@|自定义谁是杀手*
autotranslator-cn@autotranslator|自动翻译 (Auto Translator)
-what-i-wanna-show-u@
+what-i-wanna-show-u
madness-mod@madness_entities
not-so-shrimple-remolted
@peony-from-field-to-table
@@ -26561,7 +26561,7 @@ rumors
animation-api-reborn
attributification@
swgc@
-chunk-animator-embeddium-compat
+chunk-animator-embeddium-compat@
tag-fixes@
suns-son-mod
@@ -26569,7 +26569,7 @@ disable-villages-generation|禁用村庄生成*
locks-reforged@
tidyinv
tetra-data-kubejs
-@letemburn|让它们燃烧! (Create: LET!EM!BURN!)
+let-em-burn@letemburn|让它们燃烧! (LET!EM!BURN!)
kaleidoscope-tavern-refabricated@|森罗物语酒馆:重织*
kaleidoscope-bloodwine@kaleidoscope_bloodwine|森罗酒馆:血酒 (Kaleidoscope: Bloodwine)
@@ -26589,13 +26589,13 @@ mousetweaks-x-accessories-fix@
malice-and-light-cursed-fate-addon-dabura
cursed-fate-divine-general-mahoraga
create-crafts-additions-and-aeronautics-compat@
-cave-dweller-fabric-port
+cave-dweller-fabric-neoforge-port
@152mmboom
wild-caves-4|洞穴装饰 4*
derpy-squid-mod
universal-smithing-template|通用升级模版*
concatenated-compat
-@xaeros-playerposition|Xaero玩家位置显示 (Xaero's Player Position)
+xaeros-playerposition@|Xaero玩家位置显示 (Xaero's Player Position)
feywild-library
grand-depths@grand_depths
@@ -26618,7 +26618,7 @@ giant-ice-spike@|巨型冰刺*
giant-bamboo@|巨型竹子*
quick-boot
zfastnoise@
-collision-damage-port
+collision-damage-port@
disaster-plants-cursed-fate-addon@disaster-plants-cursed-fate-addon.
mrcrayfishs-furniture-mod-tools-refurbished@
hats-x-mo-bends-compat
@@ -26632,7 +26632,7 @@ expanded-ecosphere¨@expanded-ecosphere
thunderbolt-lib@thunderbolt_lib|闪枢库*
crucifix-unbanished
country-road-creature@
-ftb-quests-entity-visualization
+ftb-quests-entity-visualization@
uncapped-spectator-speed
creatures-and-beasts-continued
antlers-of-hunger@
@@ -26675,7 +26675,7 @@ nbtech2fix@|超级牛逼的科技整合包2 一些修复 (nbtech2fix)
better-safe-bed-backport
@sterile-egg|无菌蛋 (Sterile Egg)
-okprogressions
+okprogressions@ok-progressions
ae2enhanced
townstead
mebahels-api@
@@ -26690,7 +26690,7 @@ starfield-pastoral@|星野牧歌 (StarfieldPastoral)
create-radars-unofficial-port@|机械动力:雷达重制版 (Create: Radars Unofficial Port)
create-propulsion-simulated@|机械动力:推进工程 - 模拟物理 (Create Propulsion: Simulated)
-
+easy-create-supplement|简易机械动力*
create-additions-sable-compat@
create-stressbound@|机械动力:应力链界 (Create: Stressbound)
create-tracks
@@ -26700,7 +26700,7 @@ create-dreams-n-desires-updated-to-create-6@
create-more-catalysts@createmore-catalysts|机械动力:更多触媒 (Create:More Catalysts)
create-more-alloys
create-pipesn-physics@create-pipes-n-phisycs
-dabr-dragonsurvivalcompat
+dabr-dragonsurvivalcompat@dabr-dragonsurvival-compat
block-display@
modern-damage-control@|现代伤害控制*
@@ -26730,12 +26730,12 @@ hats-renewed
shared-pets@
err422@
kubejsable@
-geckolibbetterfps
+geckolibbetterfps@
svdialog@
botania-seeds@
shadow-config@
@nuke-block|核弹 (Nuke block)
-projecte-infinite|等价交换无限 (ProjectE Infinite)
+projecte-infinite@|等价交换无限 (ProjectE Infinite)
modernindustrialization-structure-exporter@mi-structure-exporter|现代工业化结构导出工具
chrono-dawn@
too-much-entities|太多的实体*
@@ -26743,7 +26743,7 @@ zero-ordinary-vehicles
false-swipe
ds-caperspectivefix
-create-aeronautics-compatability@
+create-aeronautics-compatability@|机械动力航空学:兼容性 (Create Aeronautics: Compatibility)
create-aeroworks@
@flyhigher|直上九霄 (FlyHigher)
drive-by-wire-with-sable@drive-by-wire-sable|线缆控制:Sable兼容 (Drive-By-Wire With Sable)
@@ -26805,7 +26805,7 @@ illager-structures
prehistoric-seacreatures@
-
+tlm-cp-chesspvp@tlmcp-chesspvp|车万女仆:棋圣 (Chess PVP)
touhou-little-maid-growableores-compat@touhou-little-maidgrowableores-compat|车万女仆:GrowableOres 兼容 (Touhou Little Maid: GrowableOres Compat)
plantasia
animalsplusplus
@@ -26888,7 +26888,7 @@ azumanga-mod@
decofood
dragons-reborn
the-great-outdoors
-riichi-mahjong-forge
+riichi-mahjong
particle-interactions-reforged
inmis-forge-port
luminous-monsters@
@@ -26988,7 +26988,7 @@ future-small-decorations|未来小装饰*
the-wings-of-fire@wings-of-fire!
goetic-legacy@|诡厄遗物*
-@1.0.0|诡厄拓展 (Goety:Expansion)
+goety-expansion@|诡厄拓展 (Goety:Expansion)
an-adaptive-nemesis@anadaptive-nemesis|自适应宿敌 (Adaptive Nemesis)
gourmet-boost@|食补*
gastro-crisis
@@ -27068,7 +27068,7 @@ saverestorer@
camowarfare@|迷彩战车 (CamoWarfare)
-dynamic-surroundings-legacy
+dynamic-surroundings-expanded|动态环境/动态环绕:扩展版 (Dynamic Surroundings (Expanded))
tacz-recycling@tacz_recycling
@the-king-sword
@@ -27078,7 +27078,7 @@ quick-access@
harium@
@shared-folder-skins
@marketmod
-the-summoner-resummoned
+the-summoner-reforged
stupendous-smeltery-accelerator
tiny-potatoes-evolved
@@ -27117,7 +27117,7 @@ lootrbiggerchest@|更大的战利品箱 (Lootr Bigger Chest)
quark-quilts-n-stains
gravity-gun-reforged
stupid-things-even-dumber
-shreks-revenge
+shreks-revenge@
alternative-twilight-remastered-version@alternative-twilight(remastered)|暮色:另类(重置版) (Alternative Twilight Remastere)
compact-f3-plus@
@@ -27125,7 +27125,7 @@ flamboyant-repalletized
bannerpoint@
mrcrayfishs-vehicle-unofficial@|MrCrayfish 的载具非官方版 (MrCrayfish's Vehicle Unofficial)
-@container-indexer-qol|箱柜索引 (Container Indexer)
+container-indexer@container-indexer-qol|箱柜索引*
armor-set-box|套装盒*
have-a-bad-day@
nomorecraters
@@ -27190,7 +27190,7 @@ secondwind@second-wind-mod
@insomnia
ecological-garden@|生态花园*
-defenseturrets|防御炮台 (Defense Turrets)
+defenseturrets@defense-turrets|防御炮台 (Defense Turrets)
@better-furniture-neoforge|更好的家具-NeoForge (Better Furniture-Neoforge)
@lamb-lanterns
better-storage-lectern@|更好的存储讲台*
@@ -27209,7 +27209,7 @@ ice-and-fire-attack-ancient-warfare-2
mythic-tinkers@
@cataclysm-era|灾变纪元 (Cataclysm Era)
-@hive-collective|虫巢集群 (Hive Collective)
+hive-collective@|虫巢集群 (Hive Collective)
@stacksizetweaks
@@ -27225,7 +27225,7 @@ book2map@
simple-music-control@|简单音乐控制*
new-visual-keybing@|可视化按键绑定管理*
-motley-fins
+motley-fins@
rays-of-rament
paradox_
mc-so-easy|MC易如反掌 (MC SO EASY)
@@ -27235,16 +27235,16 @@ arcadia-ah@
creator-hotbar|创造者快捷栏*
ophiopogon-wooden-anvil@|麦冬木砧*
@voxyworldgenxaero-bridge
-goety-aether|诡厄天境*
+goety-aether@|诡厄巫法:天国秘术*
immortality-by-adoleiiiiii@|英雄不屈 (Immortality)
-neopasterdream|新帕斯特之梦 (NeoPasterDream)
+neopasterdream@|新帕斯特之梦 (NeoPasterDream)
voidcraft-phase-technology|虚空工艺 (VoidCraft: Phase Technology)
powah-cable-orb-extension
malisis-doors-reforged
rack-it-up@
lychee-oritech@
-
+spellweaver2|织法者2*
extermination@wotw-extermination
@trims-expanded
auroral@
@@ -27320,7 +27320,7 @@ the-summoner-revived-raid
@moon-spire|月尖塔 (Moon Spire)
@enchanted-display|附魔词条折叠 (Enchanted Display)
corpse-x-dragon-survival|遗体 x 龙之生存 (Corpse x Dragon Survival)
-dragon-barrel-roll|龙之生存:滚筒飞行*
+dragon-barrel-roll@|龙之生存:滚筒飞行*
citadel-legacy
schematicians-goggles@
create-aeronautics-x-curios-api-compat
@@ -27359,8 +27359,8 @@ iskanderts-library@iska-lib
vintage-resourcify@
hp-hariplayer@
harimt@hmt-harimultithread
-
-nearly-enough-items-nei
+neofontrender|焕新字体渲染器 (Neo Fonts Render)
+just-enough-items-legacy
nvlic2machines
@sableedit
the-last-day@the-last-day-reset|最后一日*
@@ -27415,7 +27415,7 @@ create-balanced-flight-fork-neoforge
simplecables76@
jei-gateways
pintonium
-@kaleidoscope_sculk|森罗物语:幽匿 (Kaleidoscope Sculk)
+kaleidoscope-sculk@kaleidoscope_sculk|森罗物语:幽匿*
lotr-modifier-highlights|魔戒装备修饰高亮显示 (LOTR Modifier Highlights)
vista-aeronautics-fix@
let-fish-love-reborn|鱼各有所爱*
@@ -27426,7 +27426,7 @@ lotr-anvil-reforged|魔戒铁砧重铸高亮显示 (LOTR Anvil Reforged)
lotr-journeymap-bridge|魔戒旅行地图联动 (LOTR-JourneyMap Bridge)
ae2-meteorite-addon|AE2陨石附加 (AE2 Meteorite Addon)
async-locator-refined@
-just-dire-things-forge
+just-dire-things-forge@
fluid-pipes@fluidpipes
nekoration-remastered|猫咪装饰:重置*
@chislate|锲石 (Chislate)
@@ -27434,7 +27434,7 @@ nekoration-remastered|猫咪装饰:重置*
more-zombies-legacy|更多僵尸 (Mo' Zombies)
lotr-horse-heal-alert|魔戒马匹喂食提醒 (LOTR Horse Heal Alert)
the-moder
-reborn-core-unoffical-1-21-11
+reborn-core-unoffical-1-21-11|重生核心 [非官方版] (Reborn Core [Unoffical])
@twsmp-discs
@economicmarket|经济市场 (EconomicMarket)
@@ -27469,7 +27469,7 @@ colonylink|殖民地链接 (ColonyLink)
hopper-upper
@noxlights
-@catframe
+catframe@
yawningnekoapi
savemyrecipebook|救救我的配方书 (SaveMyRecipeBook)
@@ -27544,7 +27544,7 @@ emi-recipe-pin@
@dimension-tickrate|维度Tickrate (Dimension Tickrate)
-
+pulsar-lighting-engine
immersive-mechanic
neostructuremapper@|结构注解 (NeoStructureMapper)
pretension
@@ -27569,7 +27569,7 @@ viscriptrecipe@
@deathrollback|死亡回滚 (DeathRollback)
ic2radbauble
-@step-crafter
+step-crafter@
gazetteer@
eclipseui@
@@ -27603,7 +27603,7 @@ oraculum
mek-energistics|通用数据*
oraculumworktables|神谕工作台 (OraculumWorktables)
just-enough-tooltips@|提示酱*
-twist-mod
+twist-mod|扭曲术士 (Twisted Warlock)
kaf-hud@
perdimkeepinvfix
botaniawootaddon@
@@ -27611,7 +27611,7 @@ flower-picking@
datatip
the-curse-of-ramses-ii@|拉美西斯二世的诅咒 (The Curse of Ramses II)
minecraft-mob-armor-mod
-mobspawnswitch@|生物生成开关 (Mob Spawn Switch)
+mobspawncontroller@|生物生成控制器 (MobSpawnController)
@farmers-sellingbin
immersive-storms@
jeirecipemanager|JEI配方管理器 (JEIRecipeManager)
@@ -27624,7 +27624,7 @@ bloodmagicwootaddon@
deployer@
repackaged@
-scp-001-when-day-breaks@scp-001,-when-day-breaks
+scp-001-when-day-breaks@scp-001,-when-day-breaks|SCP-001 - 破晓之时 (SCP-001, When Day Breaks)
eat-with-ease@
happy-ghast-improvements@happyghastimprovements
agritech@
@@ -27653,12 +27653,12 @@ ifwootaddon@
aeronautics-propeller-blur@
advanced-ore-deposits@
create-compact-transmission@create-compact_transmission|机械动力:紧凑型传动 (Create: Compact Transmission)
-@retromod
+retromod@
advanced-turret|高级炮塔*
-@capitals-a-monarchy-mod-for-mca-reborn
-@better-recipe-book-(extended)|更好的配方书(续作) (Better Recipe Book (Extended))
+mca-capitals@capitals-a-monarchy-mod-for-mca-reborn
+better-recipe-book-extended@better-recipe-book-(extended)|更好的配方书(续作) (Better Recipe Book (Adorable♡Girl aVa Seriously Extended))
auto-log-remover@
bettertabinfo@
adkm
@@ -27730,7 +27730,7 @@ sayuki|咲雪随想 (Sayuki Mod)
forget-me-crops@forgetmecrops
vanilla-golden-head
cc-sable@
-@cnpc-sophisticated-backpacks|CNPC商户扣款精妙背包 (CNPC Sophisticated Backpacks)
+cnpc-sophisticated-backpacks|CNPC商户扣款精妙背包 (CNPC Sophisticated Backpacks)
potato-power-craft
honeyexpansion-reborn|蜂蜜拓展重置 (Honey Expansion Reborn)
save-my-ankh-shield
@@ -27767,7 +27767,7 @@ bluemap-ftbchunks
foxdarkmagic@
fox-power-converter@
capture-nets@
-dynamic-waters@dynamic-waters-realistic-flowing-rivers
+dynamic-waters|Dynamic Waters: Realistic Flowing Rivers - 暂时无法访问¨@dynamic-waters-realistic-flowing-rivers
better-than-boats@better_than_boats
realcraft-mcexpand|真实工艺 (Realcraft: Minecraft Expanded!)
@@ -27814,7 +27814,7 @@ stairway-to-heaven@|天堂阶梯 (Stairway to Heaven)
dungeons-dimensions-nether@
flight-kick-bypass@|飞行踢出优化*
funky-effect-lib|奇趣效果Lib*
-@cnpccurios|CNPC可穿戴饰品 (CNPC Curios API)
+cnpc-curios-api|CNPC可穿戴饰品 (CNPC Curios API)
jei-structures
@extended-storage|拓展存储 (Extended Storage)
remote-access@
@@ -27831,9 +27831,9 @@ vintage-delight-kots|腌渍乐事 - 耕云钓月版 (Vintage Delight KOTS)
together-forever-unofficial
cloud-glass@
shield-hider@shieldhider
-golden-dandelion-mod
+golden-dandelion-mod@golden-dandelion-port
pakko@
-inventory-profiles-next-backport
+inventory-profiles-next-backport@
structure-tools@
ae2lt-packaged-pattern-provider@|闪电科技:封包 (AE2LT Packaged Pattern Provider)
low-latency@|低延迟*
@@ -27842,7 +27842,7 @@ tonten@
tpaauto@
healthbar
warborn-renewed
-redemptioncodefabric|兑换码Fabric版 (RedemptionCodeFabric)
+redemptioncodefabric@|兑换码Fabric版 (RedemptionCodeFabric)
@eftlm_weaponofmiracles|史诗战斗车万女仆:奇迹武器扩展 (EFTLM_WeaponOfMiracl)
createatomic@
cobblemon-battle-extras@
@@ -27870,7 +27870,7 @@ malisisdoorsreborn@
mp-moogs-paths@
pickaxe-armor-trims
recipe-crafter
-wavify
+wavify@
magnet-hoppers@magnet-hopper
better-farmlife@
@realplace|真实置物 (RealPlace)
@@ -27914,7 +27914,7 @@ dropsweeper@|掉落物扫地姬
substratum|基质矿物*
@borderless-fullscreen
mortis-fix|毋畏死亡 (MortisFix)
-
+@prefab-custom-addon|预制建筑附属 (Prefab Custom Addon)
utilities-plus@
untagged-untitled
did-that-hurt@|疼吗? (Did That Hurt?)
@@ -27969,7 +27969,7 @@ luminabox|流光音匣 (LuminaBox)
mochas-complicated-dungeon
bridge-worm-reborn@
goety-transcended|诡厄巫法:超越*
-apotheosis-artifice|神化-巧技*
+@apotheosis_artifice|神化-巧技 (Apotheosis Artifice)
potion-bar@
soph-upgrade-addons@|精妙背包升级拓展*
@@ -28022,7 +28022,7 @@ symbiotic-swiss-knife@
just-what-i-needed-mod|刚好是我所需要的*
ranchable-fluid-cows
-
+lingua-peripherals@|语言外设*
hardcore-disabled-fix@hardcore_disabled_fix|极限模式禁用选项修复*
electricityinnovation
colored_water@coloredwater
@@ -28037,10 +28037,10 @@ frame-companion
villagertradeedit@villagertradesedit|村民交易编辑 (VillagerTradesEdit)
no-more-meshes@|不再有筛网*
create-neapolitan@
-create-improve@|机械动力:改进 (Create:Improve)
+create-improve@|机械动力:改进 (Create: Improve)
rsoncreate|存力合作 (RS on Create)
-create-redstone-link-gui@|机械动力:红石信号终端GUI
+create-redstone-link-gui@|机械动力:红石信号终端GUI (Create: Redstone Link GUI)
create-vvvf-simulator|机械动力:VVVF模拟器 (Create: VVVF-Simulator)
create-nowheel@
kroiautilities@kroia_modutilities
@@ -28055,10 +28055,10 @@ farmers-cutting-collection
visuality-reforged-backport
magma-lucky-block
creating-tables
-betterweather-renewed
+betterweather-renewed@
rpg-rpgae-neoforge|RPG天启进化(NeoForge) (RPGApocalypticEvolution)
rebind
-bosses-rise-intro-skipper|跳过剧情等于跳过人生*
+bosses-rise-intro-skipper|首领崛起动画跳过*
ancient-tweaks|古代调整*
deltaforceskills@delta_force_skills|三角洲技艺 (Delta Force Skills)
@@ -28066,13 +28066,13 @@ tacz-40k@tacz40k
carpentry-chisels@carpentry-and-chisels
sky-islands@skyislands|空岛世界*
-more-withers
+more-withers@
@itemcommander
spooky-foods@
peaks
chemlib-neoforged
particular-reforged-backport
-@mtr-traffic-addon
+mtr-traffic-addon@
mundus-magicus
chest-tracker-forge-edition
@@ -28099,7 +28099,7 @@ ef-cz|史诗战斗:巅峰 (EpicFight: ChampionZone)
world-preview-tfc@world-preview-terrafirmacraft|世界预览:群峦 (World Preview TFC)
genesis-world-previewer-pregenerator@
goety-dargui@|诡厄巫法:黑暗祭坛GUI (Goety DarGui)
-radiation-area|辐射区
+radiation-area|辐射区*
galtc
chestcavitytweak
@@ -28130,28 +28130,28 @@ pvputils-fix@
baking-process@|TW的烘培工艺 (TW's Baking Process)
@neko_tech|猫猫科技 (NekoTech)
-taczs-bizarre-enchantments|Tacz的奇特附魔 (Tacz's Bizarre Enchantments)
+taczs-bizarre-enchantments|TaCZ的奇特附魔 (TaCZ's Bizarre Enchantments)
just-enough-freaky-additions-jefa@jefa
numen-ai@numen|言出法随 (Numen)
irons-simple-blood@
functional-chemical
-
+@elytra-trails|鞘翅尾迹 (Elytra Trails)
metus-oblita
twilight-forest-travellers-set-plus|暮色森林:旅行者套装增强 (Twilight Forest: Travellers Set Plus)
-
+@fabric-bedrock-miner
@packwiz-modpack-loader|Packwiz 整合包加载器 (Packwiz Modpack Loader)
wavey-capes-legacy|飘扬披风:传承 (Wavey Capes (Legacy))
-
+xxsx-smart-core|Xxsx的智能核心*
exposure-space@
@weathereffect|天气效果 (Weather Effect)
-@swapkeyboards|交换键盘生存!-幽幽的奇思妙想
+@swapkeyboards|交换键盘生存!-幽幽的奇思妙想 (Uwu Swap Keyboards)
-@avaritia-nirvana|无尽贪婪:涅槃 (Avaritia:Nirvana)
+@avaritia-nirvana|无尽贪婪:涅槃 (Avaritia: Nirvana)
bird-watching|观鸟*
@infinity-item-editor-re|无尽物品编辑器:重生 (Infinity Item Editor Re)
plumes-more-arrows@more_arrows|更多弓箭/更多箭矢 (More Arrows)
@@ -28183,7 +28183,7 @@ death-muffler-fix|死亡音效消除器修复*
simplifygamemodecommands
op-commands@opcommands
new-better-combat@|新更好的战斗*
-the-db@
+the-db|The DB (Horror) - 仅旧¨@the-db|The DB (Horror) - 最新
emi-unofficial-port-unstable
luminanceo
ghostpig-jar@ghostpig.jar
@@ -28195,11 +28195,11 @@ quick-stack
decorative-blocks-reborn@
-@create-villager-labor|机械动力 :村民劳工 (Create Villager Labor)
+@create-villager-labor|机械动力:村民劳工 (Create Villager Labor)
mca-romantic-expansion@|凡家物语:浪漫扩展 (MCA: Romantic Expansion)
@mononym
server-i18n-api-reborn@|Server I18n API 重生版 (Server I18n API (Reborn))
-potion-api|药水 API (Potion API)
+potion-api@|药水 API (Potion API)
@safeparrots|安全的鹦鹉 (Safe Parrots)
simple-world@simple_world|简单世界*
strut-your-stuff@
@@ -28207,7 +28207,7 @@ ii-dust-trench|兢II (Dust Trench)
holy-forging@|神圣锻造*
-twilight-spellbooks-irons-spells-n-spellbooks
+twilight-spellbooks-irons-spells-n-spellbooks|暮色魔法书 (Twilight Spellbooks: Iron's Spells 'n Spellbooks Addon)
cobblemon-utility-ivs-evs-more-no-recipes
@bob-fluid-translator
data-recipe-generator@|数据包配方生成器*
@@ -28216,16 +28216,16 @@ ooundeadexpansion
re-retro-damage-indicators@
forgotten-relics-re|失落遗物学:重现 (Forgotten Relics RE)
visible-barriers@
-nomads-delight@
+nomads-delight@|游牧乐事 (Nomad's Delight)
caves-delights@
momentum-parkour@|动量 (Momentum)
-
+@foodcraft_unofficial|食物工艺非官方版 (FoodCraft Unofficial)
no-double-eat@
iamzombieq@|我是僵尸? (I Am Zombie?)
villager-industries@
-
+btpmod|更好的战术据枪 (Better Tactical Presentation) - 已停止维护¨@btpmod|更好的战术据枪 (Better Tactical Presentation)
vanillin-fly
server-waypoint|服务器路径点*
world-name-terrarified@
@@ -28238,10 +28238,10 @@ trimmable-create-armor
autoafkfish@|自动钓鱼模式 (AutoAFKFish)
dummycritfix@|试验假人暴击修复 (DummyCritFix)
@armor-nerf|护甲调整 (Armor Tweaks)
-
+adventure-power@adventure_power|冒险的力量*
bossspawner
-crystallineflowersearch@|晶化花搜索
+crystallineflowersearch@|晶化花搜索 (Crystalline Flower Search)
shield-banner-fix@
nekomusume|猫娘*
gone-fishin
@@ -28254,18 +28254,18 @@ thermal|热成像*
ae2-favorites@|AE2收藏夹 (AE2 Favorites)
irissearch@
neoshot@|高清截图NeoForge*
-rival-channel-city|争锋频道:我的世界城 (Rival Channel Minecraft City)
+rival-channel-city@rival-channel-minecraft-city|争锋频道:我的世界城 (Rival Channel Minecraft City)
@locator-heads
@lan-enhancer|更好的局域网列表 (LAN Enhancer)
big-charlie@
-@tinkers_organ|匠魂器官 (tinkers_organ)
-
+@tinkers_organ|匠魂器官 (Tinkers Organ)
+@eabs-simple-fast-food|E&B的简单快餐 (E&B's Simple Fast Food)
fkgauntlet@|去他的下界铁掌 (FkGauntlet)
etbw2-curios|暗影饰品 (EtBW2 Curios)
territory-record|领地记录*
-kaleidoscope-old-tavern|森罗酒馆:老牌酒馆
+kaleidoscope-old-tavern|森罗酒馆:老牌酒馆*
tlm-ender|车万女仆:末影 (TLM Ender)
baubley-elytra@
@@ -28275,24 +28275,24 @@ backpackbubbles-cre
betterloot-zibura@
chronicle-engine-rpg-framework|编年史引擎:RPG框架 (Chronicle Engine: RPG Framework)
sable-x-little-tiles-create-aeronautics
-bye-pregen
+bye-pregen|再见?预生成! (Bye?Pregen!)
tree-hollows-forge|树洞Forge版*
yetrealm|未至之域*
@autoeat
-skilltree|技能树 (Skill)
+skilltree@moreskilltree|技能树 (MoreSkillTree)
find-me@|找到我 (Find me)
darkaltarui|黑暗祭坛UI (DarkAltarUI)
@technomod
ahznbs-ranking-system-addon
-kingdomcome-combat@|天国的战斗 (Kindomcome Combat)
+kingdomcome-combat@|天国的战斗*
mining-forks
dodgebullettime@|闪避子弹时间 (DodgeBulletTime)
f1-racing-mod@formula-helmets|方程式头盔 (Formula Helmets)
micro-h-i-d
-voxlink@
+voxlink@|沃克联机 (VoxLink)
create-voidway|机械动力:虚空通道 (Create: Voidway)
@cbc-locometal-armor|机械动力火炮:火车装甲 (CBC: Locometal Armor)
@cbc-terminal-ballistics|机械动力火炮:终端弹道学 (CBC: Terminal Ballistics)
@@ -28354,14 +28354,14 @@ sorcerer-of-madness-goety-addon
@magic-mtr
universal-shops@
window-fix@
-
+chiseled-enchanting-table-unofficial-port|纂刻附魔台—社区版 (Chiseled Enchanting Table—Unofficial Port)
rotten-recycler@
handful@
sky-logistics|天穹物流*
simplest-paxels@
+liu-new-recipes|刘某人的高版本配方 (Liu's New Recipes)
-
-@gtp
+grand-teleport-gtp@gtp
utility-drawers@
mod-toggler
wearable-backpacks-newlcraft-edition
@@ -28383,7 +28383,7 @@ gpushift@
three-dimensional-experience
endcrown|终焉冠冕 (EndCrown)
@csgo-box|CS2 开箱 (CS2 Box)
-
+@sakura-journey|樱花旅途 (Sakura Journey)
ethiums-delight@
create-aeronautics-harness
azimuth-api@
@@ -28411,7 +28411,7 @@ bbs-cml-edition@
jei-biome|JEI群系信息查询 (JEI Biome)
jujutsu-kaisen-jujutsu-verse
-
+@litematica-extra
ender-io-pressure-conduits@|末影接口:气压导管 (Ender IO: Pressure Conduits)
dashpanels@
blockprint-link|蓝图连接 (BlockPrint-Link)
@@ -28426,9 +28426,9 @@ feathered-friend@
coffee-craft-unofficial-port|咖啡工艺移植版*
cinematic-respawn@
-
+w-cryptid-cove-mod|W的神秘生物湾 (W-Cryptid Cove Mod)
take-a-seat@tas
-annihilationbladeex|湮灭之刃-非官方重制版
+slashblade-finale-blades-anctum@annihilationbladeex|拔刀剑:终焉藏剑阁 (SlashBlade: Finale Blade Sanctum)
@uclearwastedisposal|核废料处理 (Nuclear Waste Disposal)
scorched-guns-maid-compat|赤焦枪械:女仆兼容 (Scorched Guns: Maid Compat)
@@ -28437,12 +28437,12 @@ pvputils@pvp_utils
glowing-emissive-ores-definitive-edition@
corail-pillar
mosaic-carpentry@
-antarchy@
+antarchy@|安塔奇*
@simple-durability-tooltip
dream-sakura-blue-archive|碧蓝档案光环(梦樱版)*
-
+exbingo
@impsmtc|Iam 音乐播放器:系统媒体传输控件 (Iam Music Player: System Media Transport Controls)
attribute-adventure@
fast-items
@@ -28457,20 +28457,20 @@ hunters-equipment
advanced-botany-rebloom|高级植物学:重绽 (Advanced Botany: Rebloom)
sway@
isd-irons-spells-delight|奥法乐事 (Iron's Spell's Delight - Iron's Spells Addon)
-bielggs-spells-addon
+bielggs-spells-addon@
armors-api|护甲组合API (Armors API)
apothic-infinite
pokemontcg@pokmontcg
-parasites-delight|寄体乐事 (Parasites' Delight)
+parasites-delight|寄体农家乐 (Parasites' Delight)
murmora
-projectee
+equivox
modern-cave-terrain|现代洞穴地形*
create-randomize-filters@
create-phantom@createphantom|机械动力:幻翼物流*
-create-cosmonautics
-create-advanced-optimization
-cbcmw-recipe-fix|机械动力火炮现代战争:配方修复 (CBCMW recipe fix)
+create-cosmonautics@create-cosmonatics
+create-advanced-optimization@
+cbcmw-recipe-fix@|机械动力火炮现代战争:配方修复 (CBCMW recipe fix)
@beggars|乞讨者 (Beggars)
norecipebook@norecipebookmod
visual-item-edit@|可视化物品编辑器*
@@ -28483,7 +28483,7 @@ mod-migrator|Mod迁移*
shine-vfx@shine
more-animations
-verity-je
+verity-je@verity-je-official
directauth
one-enough-damage@
advanced-tfr-rocketry
@@ -28494,7 +28494,7 @@ always-hostile-animals@
verdant-harvest@|丰年*
liteblur
-e33epus-s-chatscreen@|E33EPUS的聊天界面 (E33EPUS's ChatScreen)
+e33chat@
sound-culling
safe-spawn@safespawn
timber-frames@
@@ -28504,28 +28504,28 @@ modern-apple-cows@
anvilcraft-dingdongji@anvilcraftdingdongji|铁砧工艺:叮咚叽 (AnvilCraft: DingDongJi)
@math-function|数学函数 (Math Function)
-inner-voice|心声 (Inner voice)
+inner-voice@|心声 (Inner voice)
exlines-awnings@
nuclear-bombs-mod
packdev-toolkit@
inspect-animations@
red-bits@
indestructible-fix-for-modular-bees
-
+@universal-survival-kit|通用生存套件 (Universal Survival Kit)
enchanter-tools
mut-create-power@|更多锻造模板:齿轮力量 (MUT Create Power)
@create-schematic-preview
aeroengine@|机械动力:航空发动机 (AeroEngine)
-too-many-tag-viewers
+too-many-tag-viewers@
agony-forge
-
+casual-copy|随心拓印 (CasualCopy)
deep-below@
-chessboard|棋盘 (Chess Board)
+chessboard|棋盘 (ChessBoard)
abundant-vegetation|枝繁叶茂*
educate-your-parrots@
kaleidoscope-doll-plus|森罗物语:玩偶+ (Kaleidoscope Doll +)
-seven-stars-api|七星 API (Seven Stars API)
-of-beasts-and-wild-things|荒灵野物 (Of Beasts and Wild Things)
+seven-stars-api@|七星 API (Seven Stars API)
+of-beasts-and-wild-things@|荒灵野物 (Of Beasts and Wild Things)
horologium-positioning|时钟定位*
digimod-cobblemon@
@taczlevel|TaCZ 等级 (Tacz Level)
@@ -28537,34 +28537,34 @@ hear-the-wind@
fov-effects-backport
future-shops
@sky-whales
-
+musicbridge|音乐桥 (MusicBridge)
additional-planets-a-galacticraft-addon
galacticraft-boobcat-edition|星系Boobcat版*
-transparent-window@
+transparent-window@|透明窗口*
twilight-forest-finale|暮色森林:终之乐章*
-building-saver@|初始小屋*
+starter-cabin@|初始小屋*
efab-unofficial|EFab 非官方版 (EFab - Unofficial)
true-power-optimization@
-
-
-
+@handycommands_lff|奇妙命令 (HandyCommands)
+@anyslottotem|图腾随行 (AnySlotTotem)
+@ffcraft
daily-bounty|每日悬赏*
-ic2-reborn
+
xiaonuoclean|小诺清理 (XiaoNuoClean)
mystical-wildlife@|神秘的野生动物*
-
-sign-preview@
+@-doublejump-|二段跳 (DoubleJump)
+sign-preview@|告示牌和地图预览*
immersive-bonsai@|沉浸盆栽*
contents-director
-miaomodifiesironspellsartifacts|铁魔法修改器 (miaoModifiesIronspellsArtifacts)
+miaomodifiesironspellsartifacts@debugging-iron-spells|铁魔法修改器 (Miao Modifies Iron Spells Artifacts)
@autopack-director
create-wheels-upon-chairs|机械动力:轮椅轮椅 (Create: Wheels Upon Chairs)
@@ -28579,8 +28579,8 @@ applied-dyenamics
colorcush|千坐爱印*
optimized-cushions@|坐垫优化*
skillcore|技能核心 (SkillCore)
-
-
+teamytzs-viewpoint|异天庄的鸟瞰点 (TeamYTZ's Viewpoint)
+fatepath@|命途*
better-jujutsu-craft@
creeper-bats
@@ -28600,37 +28600,37 @@ bmp-background-music-player|背景音乐播放器 (Background Music Player)
anime-characters
wink|眨眼 (Blink)
@nitroito-tooltips
-champions-optimization|冠军 优化*
+champions-optimization|冠军优化*
sakura-library
@modernmite|现代 MITE (Modern MITE)
lc2h@|失落的城市:多线程 (LC²H / Lost Cities: Multithreaded)
-
+maid-tacz-sbw-damage-fix|车万女仆TaCZ/SBW伤害修复补丁 (Maid-TACZ-SBW-Damage-Fix)
@miningfatiguereproductio|挖掘疲劳重置 (MiningFatigueReproduction)
lootrun@|搜完就跑 (LootRun)
reglass@
-
-ecstatic
+@rationalcraft|合理配方 (RationalCraft)
+ecstatic@
poison-dragons-ice-fire-addon
black-gold-alliance@|黑金同盟*
watervision@
mrcrayfish-device-mod-continued
-twilightforest-re26@|暮色森林: Re26 (The Twilight Forest: Re26)
+@twilightforest-re26|暮色森林: Re26 (The Twilight Forest: Re26)
groxs-villagers@
nimbus-scabbards
reload-only-data
@create-vertical-chain-conveyors
-god-damn-repackager@|并行理包*
+god-damn-repackager@|机械动力:并行理包 (Create: God Damn Repackager)
@create-blueprinted
create-deep-seas@
data-energistics|数据能源学*
-@cnpc-gecko-addon-ce
+cnpc-gecko-addon-ce
worldnamepacket
melon-melon|种瓜得瓜*
@@ -28650,8 +28650,8 @@ nuclear-tech-mod-waldemar-edition
beyondenchant
dimension-corrosion-crystal@dimension_corrosion_crystal|次元:侵蚀结晶*
-@wegui|创世神GUI (WorldEdit GUI)
-
+wegui|创世神 GUI (WorldEdit GUI) - 不推荐,滞后¨@wegui|创世神 GUI (WorldEdit GUI) - 推荐,已部署自动,第一时间同步新
+@copy-item
blabby-world@|话痨的世界*
mob-battle-plus
@@ -28660,9 +28660,9 @@ yrka|伊尔卡*
full-metal-combat
alarmist|危言耸听*
cosmic-will|宇宙意志*
-@shades
+shades-hollow-knight@shades
-oh-my-world
+oh-my-world|公式化世界生成器*
inventory-interactions@|物品栏互动*
item-shadows@
@@ -28679,7 +28679,7 @@ oathbound-relics@
@geo-expansion
epiphany-mod@|顿悟 (Epiphany)
phantomrains-worldgen-lib|筑界基石 (PhantomRain's Worldgen Lib)
-
+options-rewriter@|Options重覆写*
zombiegamereborn@|僵尸游戏:重生 (Zombie Game : Reborn)
paranoid|偏执狂*
@@ -28700,10 +28700,10 @@ weapons-of-legendary-monsters-epicfight
packs-editor@
-
+@-empty-hand-|空手 (Empty Hand)
level-difficulty|难度存档化*
-
+@vianeoforgeplus
better-combat-toggler
@sbl
@@ -28729,7 +28729,7 @@ alexs-mobs-re-legacy
woc-render-arts-extra-for-weapons-of-cataclysm
fpvdrones
@lzxnoneterraria
-chainmining|链式挖掘 (ChainMining)
+chainmining@chainminingg|链式挖掘 (ChainMining)
creepyhorse-jar
brokenbots-lost-medias-pentaros
visual-creative-tab-editor@|可视化创造标签页编辑*
@@ -28751,17 +28751,17 @@ aromara-thaumic-perfumery
mace-enchantment2-electric-boogaloo|超级重锤大坐第二季:谁问你了 (Super Mace Slam Enchantment 2: Electric Boogaloo)
-
-pattern-encoding-terminal-quick-math|AE2:畅起速式*
-
-jfmuy
+@perfectmending|完美经验修补 (PerfectMending)
+pattern-encoding-terminal-quick-math@|AE2:畅起速式*
+@ancient-city-underground
+jfmuy@
@anvilcraft-simpleprocessing|铁砧工艺:简易加工
ender-io-source-conduits|末影接口:魔源导管 (Ender IO: Source Conduits)
-loot-all
+loot-all@
fakeneko-config
outbreak-epca-performance-compatibility
mca-descendants@
-
+pangu-spacing@|盘古之白*
ender-contract|终末合约*
secret-rooms-unofficial@|密室-非官方版 (SecretRooms-Unofficial)
@chamber-clarity-reloaded
@@ -28772,13 +28772,13 @@ milkshade-dynamics@
-
+four-seasons-chronicle-of-huayue|四季花月录 (Four Seasons: Chronicle of Huayue)
@eeverything_hurts|万物坠落 (All Falling Damage)
-
+acceleratedrendering-ported@accelerated-rendering-ported|加速渲染:移植 (AcceleratedRendering-Ported)
more-cloud-layers@|更多云层*
sizeable-foliage@
-
+@better-electroblobs-wizardry|更好的巫术学 (Better Electroblob's Wizardry)
@@ -28791,7 +28791,7 @@ med-system@
@highlightitem
-falsity-mod
+falsity-mod@falsity
@playerbatch
mca-r-polygamy
@@ -28802,12 +28802,12 @@ apokinetics@
scs-spell-combo-system-irons-spells-addon|法术连击系统 (Spell Combo System - Iron's Spells Addon)
dream-champions|旧梦词条*
-
+@item-master|物品管理 (Item Master)
@disc-jockey-plus
packagedauto-wireless|ME无线封包供应器 (PackagedAuto Wireless)
@autowork
create-cooling-fan|机械动力:冷却鼓风机*
-@create-avionics
+create-avionics@
create-lights-controls@createlights-controls
emf-compat-core@|实体模型特性兼容:核心 (EMF Compat: Core)
cynosure@
@@ -28827,14 +28827,14 @@ cauldron-cubes@
@create-empty-packages-fly|机械动力:空包裹飞越 (Create: Empty Packages Fly)
mna-integrated-adventures|冒险者魔艺 (MnA Integrated Adventures)
@elytra-slot!
+colorfulblocks@colorful-blocks|给你点颜色瞧瞧! (Colorful Blocks)
+extended-oritech@|Oritech 扩展*
-extended-oritech@|Oritech扩展*
-
-
+biffrunrunrun|Buff,你跑不过我信不信 (buffrunrunrun)
create-crafts-additions-plus
spice-of-life-delicacy-journey|生活调味料:美食征程 (Spice of Life: Delicacy Journey)
uwulan@|幽幽局域网联机 (UWULAN)
-
+@tacz-fixes
ice-and-fire-memory-fix|冰火传说内存修复 (Ice and Fire Memory Fix)
automuteonafk@
builders-shulkers@
@@ -28849,9 +28849,9 @@ moai-statues
intense-horror@intensehorror
dungeons-additions
-
-gt3-racing-pack|GT3赛车包
-f3-f4-gamemode-switcher-for-older-versions
+ritual-crafting-table@ritual_crafting_table|仪式合成台*
+gt3-racing-pack|GT3 赛车包 (GT3 Racing Pack)
+f3-f4-gamemode-switcher-for-older-versions@
@fast-masa-configui
@rankboard|排行榜计分板 (RankBoard)
@@ -28862,20 +28862,2650 @@ lightload@
tfc-music-maker
jade-sable-compat@
-@tierify
+tierify@
visual-mod-edit-vndialog@|可视化VND编辑器 (Visual VND Edit)
stupid-block-animations@
legend-of-the-lucky-blocks@
chronos-backups@
-spacesuit-required-addon-for-galaxy-space
+spacesuit-required-addon-for-galaxy-space@spacesuit-required
gcs-gchouston-command-remover
galacticraft-respawn-fix
-better-paint|更好的画
+better-paint@better-paint-mod|更好的画*
tinkers-golem@|工匠傀儡 (Tinkers' Golem)
-@refined-storage-cross-latitude|精致储存跨维度 (Refined Storage Cross Latitude)
+refined-storage-cross-dimensional@|精致存储跨维度*
lush-grass|茂盛草地*
@(ssrdfv)-separate-sable-render-distance-for-voxy
-sable-assembly-fix|Sable:装配修复*
+sable-assembly-fix@|Sable:装配修复*
@create-droneworks-simulated|机械动力:无人机 (Create: Droneworks Simulated)
-3YV3R=3Xe3X;3X43X/3S]3B'3FY3Ab39i2,[3V^3WE3SG3F43V:3Hp3VH3W}3Tb0012ze35e3V)3Wl3W=3EF3TF3K;31T3YS3KA3O'3Np2!@3Nh3W32z$3MD3G@3Ve3T637{3Qg3Xo2dM3GT2:z3V?2y434(3Od3X]36w38g3Tw3TA39}3XH2o]2uD2rl3Fc2w$3Lf2Nx2Kd2zk26?2M+3G{3F*2S)2Ep3QD3Q[3S53E^3F/2?,2ge3Jt3OA3OU3O:2cU3RL3ON3S?2nC2Kw2k<2su3YA1b*3O$2iz3YR37839e3J=0043XU1%+3OK3LJ3U$2+Y3P*2&+3XW36{3Xy3W;2=;35)3X:2J{3Wa2z3YK2]f3P]3XY3523J'2dI3WJ3BH2]K2zS2Ya3NX3W^2=i3N^2)D2SW3I[3Wz3W@3U03Qj3Ix3T(2]P3N42EP2;33FD2H*2w23Kr2]02m{0063CU3WZ3R:3YG3Uk2}:3Q}3YU2,03Ok32O3Nt35t2OE3Fd3U[33b3QN3UT3Vv3YO3Fp30L3U@3O93T@3Jf3N+37%2+W2%s2Xn2^x2w]2&&3G)3183Tu3K+3R>3X73Xj3T<2Yc3H)2tZ2&^2vr2uy3Vt26%2xR3V#3Kq3V'3IP3Uz2'F3EI3Uv3S(3G+3C{38*35I3YB3UM3XR31u3O#3Vx2)&3P)2,b3RU3MT3J62Jf38u3QG2>P3FO3VE2]&3I836o3S23K,3Sf2:b32k3Sx3EE2&Z3G$3Y034m3T[3W63YD3T/3Ht2WB3L;3V93Ub3Rh0073VY3Eq3U*3Qd3Kj3D70082!n3Ud2;R3F{3Uq32z3JK3Nc3Eb35w3MA34t3Y82n53X}3HP2{z2,93Y63953X)3T+3LT3Tc3Vj3YL3U#2'f34?3Q?3Hh30*3Hv3T,3I53G33XP3VU3SA3X,3Xs3UL3Vo38c3Tg3E23Lp3103XF3P?3QF3J$38^2:%2?:3Aq3UF3W{3K}3XS3Wg3N;2tR00A2hf3TJ3Xp37z3V>3EQ3Uc3Ln00B2(53Ga3BM3003JL2,=3Ot3WG3Dn2F{3W*2/P3Xb2*K3XL3X83X*3J331q3I+3Dp3S+3642*G3Ax3P}3H/2}q32U37>3Vs3D/3Lt2??00C31]3U,3VX2&I3MB2,53Ja30k3Fy3X>2ug3GW3K53MM00D3Ow31O2?L39G3Y72]/00E2Vc2#d3KR2Q83T33892#R33,1=k3Nj3C]3B&2)72p!3P@3I=3Do2[%2?$2>=3P12^l3VM3VN2&?31F2'k3M<2:W38r34632i3Ks3Xm31}3A63F@2Sb3JS3BQ3W<3XT37T3LU3OM3Tz3E;2nv3Db2Rz3M(2jT3G43NT30c3933Pn3OB3N*3OS3KI2y%3W&3HE2$j3AB2X2t{2f!3BK3AX3EZ2}E2=&2?R2I83OP2e+2((3SZ3Sb2kA3CA3SO2:X37(2dS3GQ3Ge3Ce2gO3T;2&>23E)3SV2yu3WM1[Z2?x2^R36d30g3X^2jr3RM2wX3M$3Vu3Mo39]3VV3Ux2$]3Su3013Oj2uw3Gm2*,3H!3T$2(Z3FB3C<2;e3N%2<=3Jr1&s2?31@$2UZ3Au22y1,@2Nl1[H2o53F93B)3PN3C?3Q$3Rb3M}3S!1+a3V<3NF3QT2)q35(2hM22r3MK3Pm2qx3G;2cX3R+3Te2w'2Ye2>,35E2&s3Xn2hL3N32zx2=J33[3Pb3NM3DC3C:2}K2)d3T^3J@2!43A026D2Lc2L^3Xw3Xx36y3Sn3EJ37L33{32(2:r3Tk3WL3RD3W:3Ji2IL2NU3K83F)2,S2#J2,42VO3Um00F3Iz2>j3FK3R42{+3H'2(h1yh1mU3Xv2+@2}}2K82il2}D34i2>63E32r$3Ka3Q/3Xu3I;3U93W%2^e2lj35U3A33I)2CA3Jo2h!25X3L$3DX293V&2uo3DP3C%2%E3GK3W$2!s37w2]b2&732R3L[38J3MZ3TE35{2n%2@<3G?3Wb2(?2qj3P!3O43XZ2#73Ug3Nq3C12Mr2[o3BE2F<2i<2k@2Pw30d2Cw2*h3632v>2PS2kv2vk30D3Hd3R13J>3G/2;t2yz2}72jH2M<2FU2+$3CL2r;2{83RW2RQ27>2t&34T2pD3Dc3N=3Ul2rf3S'3Q^3SM3K[32a2t=2Sn2xa39M2,!1*V2Q:2Y<2nj2U/3993M=3VR2cE3MI3Tn3JA3YW3K@2]839L2>*37v3Gv34R2l63SY3OI3D#35H3LH3U=3Mp3572;}2p$3U}38x3X%39H3IH3Wi3F:3Rf3EW2OQ2:t2mp3Qy3W]2/M3K?38>38)3Rd3O(2!M3I&32m3E*3Uh2UW2pA3WO32G3VA2:k3Hs2;<2,83YF3AI3Lz2(!2Xv2ak30y3Ha2#V3Jp2m<2%/2Ab3SW3Ej3Xq3IG3YQ3S131k3ED38Q3H934h2nK36S3T12r%3P>2'Q2iE3B939*37N2@F3Tr3483ET39B3WC3Nv3QC2'd3BX2>+2,:3Pr3LM36L34]2=c30v2'?2#k3Es2)k2q*2rG3E@30Q2S63S^3L)2E+3AV1+o1!m3M[3H:2)a2}'2k(3Ta3Q#31)3Iv2y&2Yd2,+33n2je2]s2}C2:*2Gi00H31{1]}2{h3QM28U2,#3J13U]2G[37[3K33Qe2>}2xh2(v3Ls3C43GO3VP2za31L3Ut2yM2&!34c2mM2{C3W03DE3M#3Uj3OO3Id2Qe3Vl2iv33]3IZ3Wc36'2ic3AA3R52ye35C2CX2h/1w?3He2}#2![3KN2Tk3W52?v32n3P(3Oh3RA2@C2:{1%n3Nr2i&2[!3G#35k3PW32X2Y73E[1?:3LP3W'35M2[P2B{2*q2=w3IQ2mu2&Y2mo3HU3W225s39^2^?2#z2:l3U52tp3Wu3LL2;]3SX2>73E(3J}3WQ3Df2*L2?c3Ba3Wr3D>2g?2%>3Ci2*n3RJ39O2]@3A42+t2}P3FE2mF2e03LW2kn3923FT35>33W3Az3UY37q2;%3353IV3U/3F52{u3Vk26R38S3I*3M62?+2rM31(2&T3F,2;*39r33c3HQ2>:2'33LN2$t30P3Hz3XN3Lk2ne2h43PF30[2;n2hb2*U2/k3BF3Oa3R}2zQ2=S2or2Wc36@3E&2)v37i2>{3Af3D;3R03WU3W(3HX3Mz3O12p#2(>1>/3B%3TG2'/2=D2}639n39;2&i3Un3FX3SQ2H]2<+3KJ2xM2fK2pm39!3Op2T2[T3NG2q12*g2gP2GI2AO2;S2:@2%M2p*3U{3Ld3S93HY3KT26@34p3GY2!L3EK3Dj3LG2%J3Qs3EB35,2Li3WK2$52)>33^3VC3LY2j<2(w3Bi3O{3Tf2zz2X228z3XX3S$2Y92(j2&z2o/2:f3PR3C72Fg2j#2sU2C22!Q2nF1eL3U;3AL3Lu2h62>d3Jd2}@2H$2!(3Li2Z52e#3Hb3S&31E3LB3K23S;3Jb3LS2sK1({3PV2[52X;2er3KH2}U37u3Md3QV35O3XJ2[#2H)2,m37m1:Q3882Rq3DO2,23Q+2qo3TT3Vh3X(2;73X'3G533#3Kd3DM2@T2z02az2$(1}%2622u33Fb1ut1yO1;[2OT2=Z2CY2sD3Dm2*{2?W35K3Ou3AR38M2,C32C34e2:732Z3Ui3Uf2yc2$T2}%34X3Tl3Ny3Qq2Sc2w(2Cv2Tu38'2bj2#X2Ku37c2^G2Zt3R^3TS2Z(2)U3Xi33V3O@3AO2:a3A:3X{2%%2:E2=t3Cz3GS3SC3Q<3Rc2h&2eH3713TZ3We31n3M>3323IT32b20H3XB38a2!$3I$29738<2Mc2!93Wv2'<2el2p;2?s2&:3MP3N#2c92lK2VN2>O2Xl3Qc2,/39j36,2:I2]Y2J+3Rs2jF22ds3Q!3D[33!2>#2=^2xW20Y3JH22x83OT37=3Jl3J,2gG2bP3Ng3NC3LD2G23PI2=z2UK3R,2vW3FI2KB2(333u31<2CV2#w1},2Hz3D(2XC2pd212k32{#2iX38U1[n2{x2ck39x3V@2s'2Xi3AP2ZJ2])3Q,2sN2e'3W>2I;1od2s$2n(2Vd2A22ok31@3NS2<13Fo3J82&43CX3Cd3Oe2UA2Xe3Qm1n=3Io3D52}L2:g3U'3B#3H+33a2rw3F$2E,2^Z2*N2pv2D33WV38,2Vv2'R1'62T{2cj2{^3Mj2+f3Cp2gE32t3P22'I35'3XD3Q%3DW3YN3J!239c2nw3Ry3Sy3M930W3IW3MG2dD1aL2H72)13M83O!38V2473M03JP2x#3TP2D02n^2?G36P3Fq34>3Gc3Pv33<2{J2!m3Re2+Q2/w3Tv3SH2!U2)%2,E3E,3C;2v(2[{3J01}z36>37@2&k33+38]2I?2}(35R2#C2yV2i@3I92!{2K>2*41}S00I38+3JY3R{35=2xP1vd3D)3Gr3H%2/]3JF3G>3V03U12>82{=3Mt3Q)3CF2)L3Q02<*1lg3VG3I:3RS2g;2k/3L/3Q&2s+2uj2$n3DT23}31w2bW1yA3P<2?y2oD2^W3SD2XH2{v3963VS3Jj39a3702Su2^'2&e3Dq3J?2e72vt2Ig2XA2=o2$92Ei2AH2rb3A{28l2AE3D]2&F2Q@1:V2pn2yo3Kb1lZ2x^2?;2hR2}Q3Ir2x:2uW2bi3Ip3B839z3Dk3Wt2R@2LJ2b3Ms2([2wc36(2^r3N{37l2/'3CQ31t1:(2,*3Oc3W92%g3Ec3U22ty2Oo3Vb1'(3O62>F2Bo2eI2Z82K;3OW3YJ3Wf2*P3R%2v:30I2Zx3Ua3NQ2oQ23)2+#3Wp3TL26530p2;93Qt2=f3Cs2%#3CZ38Z3Q43T#1yE2Ft1?u38i2OP3QQ2Rn3373I#2qn2S#2'52a12}F3Th2]k2]F3N}2/G2v32o&3R/38E3VO3V{2lR2#O3592ks2zW32d3M:3C,2/Z39>3L]2M*3Vr3Cg3LI3LA3T43On2bS3552rW25)2XE2/v2)*3H[2U{2sy3Nk2^52bn32?3Sl26i3OL2Pd2<43243U:2><3H^2b$35#3F02)E3OF3PX2vq2/S2>^1iz2Dd2wq3B^2r}2}]2W43P72m*3O820e2nr3O33GH3Uw3Bm34l2P{3U72GM2]z2(H2sk2rr3Ct2!B1=&2mx3HW34C2)83Ib2wg3GC2qa3Kx2xk38W2'M2+l2e)2p31p;3SK2BQ1j91gY3TQ2qI2!r3M21Ir1841rm1!&1?E19Z1a61Nw1D#3Q22)+2YB3U62fE2f/2dV2!J1ey3M{2*63VI2gr3IX1@'2}d3Tp2Y^2zq2fx3942$c32^3O?2k%28:3Qp3Vm2Vu3531)D2%f2bp1'K1Vo2s@2MN2Df1{52XU1sz1!y3E633s2L<3Rz3JT2o=3Y43UN26c2/l2W?3RX2^L3Bj1z,2tc3Mu2#K3X530@2,>00J2y,2*R3Ad1@62w73V=00K2}B2>c2;C2^g2oj3JW1&>2%z3T?2G@3PA2E<2=Q34K3BI3861aZ24o2PE2Tr26p34O3RO3F73JN2a82^a2A%2]e1WQ2U82yr2Uz3Lc1]u2+D2i$32L22?'1%12'L3H525!2Zv2)Z2rO2u)2=[2Sf33i3E72AF2zZ2&L3DQ2#N2o)2v52?M3JI2+H37^2zT2KD2=@2{a2I12l$2ZW2J32?%2L#2Bt35@2V12fV2>m00L2d)2GV3Vq2Y,3Cm2L*30=2E32oL30}3Q;2'+2;H2dK3Gp3Q*2b83Xa3PT1tT2V83L333d3Ds3Ek2Uv2wV2vE30'39d2;13BO3Wn2Gj2C{2JL2,H30H3Hy1}m2oc2[D3XK3Ob3O>2@y3NV3T%2rs2>22}v3Tq34s30S2}p2'S3L91}(36[3Hi2${3B=3JJ3I13NE3W#2@m2Z339A1xZ2[B2oU2]2/O2{(1)]28,2FP3Iu2B12'D00M2mb2/W2q43Ch37Y2v'2mI2q3Td2qt2,n2zu2gC2ZY2pj3Mm2&g2P42Zj00V00W2R23S*2Wq3If1)A1/w2aa1U82h[1$a30X34f3N@3R<2#f3E<2%F2b11}G3Q:3Ic2;(2x=2u?3BU1/{2YF2wQ2$k2gD2ZK2hV3Q53Gn32%37x3Mw32:2HI1)K2]W24M2f02mC3AG2(+1[O2W52yU1$?23N1%{2px2^V3Nw3D23763Xl21J2SR3N837H22q2Ra3R!2d:3T*2w!3O72oe39U3Gb3DF2'13Ws2u^2mZ29*2D@2Lx2IX2!72{G31A3F<1UY1{@2?{3Rg2#037]22,3IL2U:3C*2}s2{w3Am2V92>?1'X2(X34b2w{2'w2+T3R233O00X2$L2cD2/u3Vf3Iy35W2fR3GX3JM3G]2Mp263Fa2N:2]U2@62!02H<2mT2,@1o:2&c1W>2uL33A3A22)c2,i3XQ2{K2F52&(1]e2*(2=,1'+2$U1;U3D<2!f2+q2=12Z;36E3PM2PZ2HX2IW2pO3TW3Tj2&V2mK2^22)I2%p2{y2hd2[[3Dd2#52XI2FS33M3QP3Mq2C&3Jw34J2=L2}83Sc2R62#Q3RC2ju2;o2uP2$X2>u2<(2*02=}39[3Cr2?91#'2MG2VM2&D2>C3V}3H<2p'2b,3CT2*y28W2q]2v+2p]3042tP1>c2rS2,d2nI00Z1Mp1ew3272)i1aI2[J2}42Dq3X92@H2^+2sl3Jx2811vj3B@28*2#D2;822}2Z62VD3NU2+N2tr3Lb1:?2<;1'}2ik2pG2T>2Q(1}D2;X2$z2J'2YU2@c1:v3S<2zH3NW2>V3B(2W;2KC2I#2iR1c)2vV2^#1(92eF3YE3E41*k1TI3Bp2tM3CV3472mi2*O2:o2hU2qu21S2:53Kc2zX2*J2V}2J,33D2C=2Lp2en3Mb2rn2#M38y1;#2p+2wx3AQ2:+3QU2Kb2UO3Le22!C2yK1##2(Y3Vy1?&2kW3KG2+i2zt2a3Px3Om38(3CB1[E38B2/b3TU2[j3Js1E723?30t3Nm2yx3X[3S63D!3P,3Ty2h*2O!2cc2<)2@S3FQ2$F3PQ3Wq2&h2&;3Dy3UW2y32:p3Gu3GZ3S/3Sv3Ss2?F2sv3N<33}2{U2^%3Lw3D@2>I35y3SB2=62$O3P426+3AY2z^2zo2k!2X^2@=2T]2i:30G3RB2qX3N$3TH2^32w&3283OY2vZ2yj1u:2>J2e}2au2gh2=N1S&2:?3UI11>x3S)37,36T3Bk1^^3G<2yk33j2,336D2'$30i2L13X238Y2p22$>2<:2lG31B2e$1;s2P)2l:2kL3RI2,M2y/3Xz2&@33v2u]3U<2}[3Jv34^3Sk2ls2+=31*3C83UH3Rw3GI29^2;:2^p2R,3Qx3IU2N$2$?2)g2;E2@N22b2?P2s%1,:2v63A%2x?3ER24R2/r2%33CW31H2{c1WU2:T38C2pJ2Q$1t)1WZ22%2/;1!Z2j)2gp1og36;2h^1]53AT3M+24w3L#3WR2:H2sg3R$3GD2mk2t522i2G^2$l21A3IF2h52/>2VK2'u2TX3Ei2Ua3422&22Ym2GB2iA00b3AD1:42jB2&u2lW2552U;2^F1a*2a33Xr2j[1:i2;x3H41*J2et2Av2$R2ui29,3D^2m13F(2S423U2O22my3221;e2kJ2493C$2n;3DL1n22[u2a]2o12mc3S71'V3UD2/%3B[3GR2B22,F2zB3It3H22X!1{21mr1]02Tq34Y2+35c2n?28{2?b3U81[)2/$1zK32323C3Sz1<11(,1U52b?39y3BG2:900d2eN3Gk2mL3N51&43M'2!'2tS37A3N[39l2^I3US2QR2Kv3C'2yw2:M2^Y2HR3D636n2^^2^S2GX2;d22iY2h;36B2vi2n}36%29I1^M1>[3UO2f;2uH34o21*/1%k2un2+h3B02O639f2;?2O^2@x3K>34W3QH2W32}/2/:2tq1lv1:y3Oz3GB22]1%A16M2c{2@b31X39'1ru2Aq1>@2]{3M)3V42Vx27$3EX2Qr24W10l2=G32*3P:2h}3Kv1;82&d1Yi2?Z3Cj38s32T3I/1Mr1]#3Eu32M1}W3BR1$}1En1oN2zA1,b2YV2ov2=A2aT2L/3Ju1}53Aa2JJ2iJ2Ze1[z2462a&2?[2wt2hI1^T2v*1mx2Y%2Hp1*=3Ma2hY3L'30l28/1{j2$e1;'2Hx2xg3Mh1%=2ho2Eg1&?2vd2Pb2L@2n&3QJ21'1}O1{G2^]2J93ME2qT2^j2De2So2<#00e2*21*F00f2f72!z2)<1$C2N%2:>2(i3XV2Ik3Ap35L22wA3R'28J3AU2;F2m1ug2lO1f526S1w>2Tt1t:2tx12!]2g)1m52wz2X{36?2nD3B}36A1:%1${2w13N92l>2Te3HC3C[2Ed2,13BT2uI32g2dn2+p2vM2*D3Ll2Dl2^D2{N3B?2Z&2C92wB36U2nH3692D524u2)z2C/2$K2iL2iC2ut2:d2fi2R82bZ00g3DK2jM2*B3DB2hD3Ep1+H36O2?f3DY2%Q2e<2?82Z02>%1wC2$N3Fw30C33?34#3II2qQ2on2B92xF2)W1?y3Oi2vG2fv1N&2Xy2;{2hX39<33%27R2E&1&(2E53Er39F2/71%T2a,3R(31b3F&1,J3Ti2Rt3Kn34M3O52[;2'63Pd31y31p2kM3Sr2iI2!:2+}3S@2=>3D&2y!2ZE2bX33f3C+3FW34$1,E2eQ2$[2jG3FP2a(2=)2[I38X2>A3061QP1&%2(@2C>3K%1rc2;m2ki2(d3PP3L12tE2dc2K{1h:3DV2L3PJ3Kg2v[2v73Pp1l^3C/1m>2p63E]2r'3Qz34=2f{37R2SX2$y3BN2Fk12*Y3I^30M2gJ33U35o1f$3Al2gw3T)2EY2[g2?J3BB3SI31h34P1zZ3F?2HA3F+2*33Ns2:q2#g23G37J2:&3P%2;v2ZV2/,2I@3E?2KT2t;39k1O&3L!2=%3Vz2X=2]S3Fi2z82An1AZ3GJ2}320W2;B3V12d]2C12^72K'2Ky1),3493I@2:[3U^3913SS20b1E2w,2{22TH2tX2012Q'2b<1!U3UA3J%3Bb2SH3FS3BV2*@2+L38f3Ue3Bw3983Q'3Wo3I32^=26P2[K2HL2')2at2}=2ol2SP3P{36I2[&3Mr32q2k?2jX1vM1ZL1'y34Z3M]1&q1;A1[62(]3Si3E82'E2t/2/s3Eh2n!3B;2C32$02Vz2ED36V1%y2;[3Gl1}82pB2@:3UV2,&38j0(t2e{1!$2Ib1/u2Q72(B2!R2}&2qW18A3Us2FN32c2*z2V#3G%2zn32;2y#2+X18$1{E2jO32)1&k2%02'n2c<2cI3M,2Iq3CJ2%^2'@2b{32J3IO1x52)J2(,1^R3Fg2RY1Be1@%1J%1}}1q:1^>1{62lX3A(1f91%42P/2'l24%2jw1}e2{T1zR2n:2%Y2sT1zz37!2z42[}2NP1hF3Rp1o)2VJ2vU3EH2j&39Z2w82p=2O*38l3Dw33X1KJ1u51S71w=2(a25Y27O2kU2F037g2]*3WF2}a2ZF3A=3Bh2C41MX2p52X02qM2Wg2S31Ch1]n39@3QK3EA2m(22J2L[3ES2Qg2W82L93Fj2Si2^n2'a1([2Pr2'e37Z2wr2fd3Ck3HM2eG34!3Ie2:m2BP30#3XE2*$3J)2RP2x43112tz2qg2}x2tN2zf2Ty3682E82?z2#F2$v2:824f2*)3Je2]V2]H2yZ3833Gj3K93R&2s02I$2j]2VP1*p1}u2rZ2zO2c#2,P2r#1&E3Lo2+F3G22Cn2z+3J+2Q{2ST1G>3L&2:$37W2dC35J1p62c}2u@2dY3Mi1Hv1!:1I$1q[3E%37*2l!2zV2!;1'A2(E3EP2cZ2I:2xT2NF3I<2Z<3DJ1Nk2J@2pX16'38P1y426/32&3873KC2k*2z*2j$2dk2e[1Ok2(*1lJ2vo3Vd32Q2,{2:G2=m2QS2hy1Ls2^b26A2%+2&K1<>2#Y3N&2wi3Bg2u41Jo2QX3V32*I3WY1xW2[+2Yf2!y2FO2fs1}y2i>1um2H}2qs1=z1vX3PZ2/=1p]2@{3CO00l22@38w3N!2D?2]j2r332!37I2HM2r&27,3C&2Rf2yv2qB2Oq3MO36N2ma2nB2#)2wo2#e38d2;L3FG2%B2/x2;#2%<1,736g2Nm00m3BZ3IK3BC2^02r25j35+2,<2sG39q1O*1W33D42,Y2qk2ZI23x2eg2r@3G&2tl2jR2%739023I0]S1yX2B)1,A2R026t35:2Qi2X(2tw2u:3E03811vY27S2zP1sL3771nF2t}2GG2No2Yb1)i2$<1kB1oW2/82d92?a2UV2tH2e93LC2F>2*V3R33My1Zl1@:3B:2iW3I%2Ox3By34w2uR2%t1b&3U42xO35P2[U2052Qp2Ob2w52:Z3YH2zF3H;2MF31g39{2zs2Jt2a<3F]35S3BS34/2@L1du31#3Ij2FH2)F2r>3Tx2#;1nA0*m3I,2;l3653E+2{[2#x1l%37f1f{1,c27c33g1&!2e*2Y>1^k2@z1}@1oO36Q2D^2@71[=3F^1Rb2>i1vI3P&2aY2x*2k21z91[Y3MJ3FV2Vf2;M1'%2ni1]K2[@2eX2B02kh2)n2M!36730/37F22z]2f62)V2?C1@42[>39C2Cp3OH2Dv2v?3B$2?22aG2H!1>72F+2n@1)01ha2E@1;938v2)p1:R1,41;,34G31d2T71VZ2pQ3QW1;*1):1b62V=21W2,j3Mf2G52f12+x2t:2'*2Xg2+r2Qa2O72AN13q2OC30(22+37}28G1qK2(k1=s1ul3VF3HG3C33Cv1:Y37U3A@2RZ12?I3Sj1W{2)Q2/Q2[b00n2]E2!232y0]o2JT3Q11(F1e<0>'1[?28%1M&2m91^h3Fl3Vi2IC2%b00o2aE2;w1v:3Bo2%(3D'0{L1g02j+2HE2$'1;c2as2:y29W25S2+V1?F2nV3821)#1p(1$t2F%3D%2^P2zM30Z2wN1xg2pP1iU2/D1u/3Jq3D:2[32+B2%22xl1{p2w;1,u35l1$&2+a3HJ2Pz3K72?}25*31R2Zs3Ft2$:2P72m$2!Y2qq2ba1@01x^2I424h2D'3F22wG3P533l3UE3O^3Ao2sZ1]z1e?3X036+1Tr2Jk3LO3H*1{72==1>e1{}2Hd2s#2;)3N?2]52)P3Gi1h#2@g1v<2s]3E93Kz2v^2s42j02>k2/V2&H15W3Ay2'J35!2KA2MP1E11}x2n92+{2Vs2]T2h32BN2EO29p3Iw30E3Q=2U12qd2+n2F[2Gy2gY2Qf2aS1]32}e3Q82iU3HS1dN0;t1)^2iF2(=2Da2w^2PQ2b'1Hn2ku31D2gU34r2+Z2;c2KL1y#2z=1%w2^!2B32;r2:B1Ze3UQ2FA3QE2od2K?1WR2=b2TM1a[33z2tI2,p2=g2&v1aD3UU1$#3Fe1ZM2T^2?(2[y1cP29r1xy2#(2;W2Vk2jg2>v1)S1=H13Q2cg1nG1=*20L3Gf1%f3EC2M}1M62K#35%2mG2Bn1Th3H@2!E23$1wv2Z!1km1l$2aI32+2O82'T1'0,61bJ1rL2Wo2zC2Kf1+B2)s1wF1OS2vn1%z1)f1Ad3M&1j*2Ks1$b17z0;A0}X1AI1mS1j71&F1[o2WA2sL1j)2Rg3Cb3412DJ2G{2AS2xm32o2Ny29e29N2UP2Kh2KW2Gs2T:1z+1R^1K:2bb29x2BO2?&2Pk3OV1!!2VE3Eg2B^2xu2@&2nd2>h24K36K2)23K(0%r2uM2{E2g/2d&1,s2Pl1vk1xN1Pa1Wd1vO1yb2'X1?g2Wn2}l38b1t]2f=2l)1aC2MQ1y&2mJ22M2lH1nB2o{2z12?12Q>1)*2i01dX32e3Cy1/i3Hx2[d1>k2PW27112{2fu2CL2<<1i51l[1xj223O2@n2uT1qu30R2Zd2us2&,3K=1!K2)$2TF1E925$22t1i92[W2&y2BR2dG2B51n'2?/2@E2v12Z>1n[27t1{l1BI2s32@X2Ov2HV2q010i2o(3ND2;&2,t2Es1#B1+42XK2*a1%81KM2Md2fa2IE2@@2gv1[c2VT2,}2%;2$b2P'2PL2)x2?639N2X12:w1We2b&3W738@2:=32u1]Z3Lx2fM1/72s,2&'2802RF2zN1;X2V<2}W2ss28Y2*H2/[2#&38&3O=2M=2Gl1,z2I'2OF2Qy20B2J/2OZ3NZ2(O2Bw2w[2Uo2d;3Pe2rA2ag1My1L)2x93KZ1'i2y52f@1[^26l35q1}r2682hQ2}O3L^21n2:D2P62W!1]y3Oy38:2;>2s72of30O2b[00p3Qn2P&1&n2X$2N11dv2YL2'g2s61n)1=630B2;j2:K2kj1;E2ZN2*A2kX2#q3NB2H{2GL3B32)A2{02x]2NE2fS2sQ2/01+L2!G1%g2TE1W:36Z2Q]2Il1)I1n}31c2)?3Sw2cq1x+29?2E*33(2Ap3790]i1JK2qG35Q2}w28c2pI2OH2583R)2[x1b:2,k3Ol2(;3Mk2ad2@I2{51m$2OJ2ez2dd2}m2Q)2d43AZ2Lw1KZ1%i2SN3KY2H52yY2R+1#Z25K2^K3G72)[2GY2jV3A81yt2M:2wS3742rg1h71'q2pl2F82kq2!o34&2hW1NZ2&M3M^2ld2?o2,^2$42Xp2x%1^H2]10<72}11:J2&S2GP1#=2mh2+d2Yu23q1wi1Ml1wp0'Z2N52Ej12iw3K/1=o1yV2q/2v<3Vw2bg2tt2jq14{1CT1dF2bh3342!H3DI3Qo2Qj1zl2=71%52K+1Hz19;1V129v1{N2MI2TA21G3N'3UJ2m22id3ID2mR2>42ET3TB2RG1o42=+2?w1#d25w14W38q2gZ1(I2HT34z31G2iG2tU1lt1m,3A)1vZ2MT2fl1:g2Jn2;a2*C28[23@2$D3Qr2D=2RN34N2!b2%P2',2fy3B,32v2#u2QI1}X1gT2!T36k23%1>$35s1+W2vL1t<2Jb2?u23]2v{1DF2n'3Ca1i@1z72>D2=02Ea1)22D!1=12To28(2T;26V2[c2aZ1>02T!3T!2Fe2wY2qm2n61c[2@j3IN35<2ON1?J12$3MF3DN2<]1G?1?j2^c2>p2gu2,X1'p3C92431)r2C^2(11HX3B*3An3Qa2VI2Cc2P033*2z'2c>1{O2cC2lg2lz1wn1<21$[12Z2x[16k2h@1&{3NO1Im2G/2>U1hB11D0%p1=%1NS2nx34S1O81=S1692[Z2dT1])2!P39u2$Y1:*2+c2jm31K2Fv1mm3HZ1tM38T3CY3GV2H22CD3PU3NJ1wz2282L!2h>13N1B%1iF2=l1$*1#W11R25k1tf2+k1ZE2BT29b2b>2/T2h01^11&,1t^2Sp1p31&G1vK2i82t%29@1U!3C61tj2V{25#2is10a2cv2212Rc1j21#}1QH31z2?H2As2Kn2oO2p&3A]1s/2(}2FT30r21v3RP2)31I22q(2N,2,f1v%2dJ1Y/2SE2h12+72RB1))3SF2Bs1{e2/o1wI2X]3Nb3K)2e>0u2fJ2i42Mn27?23b3FC27E2M]2Ba2w41]d1C03Rj2uV1he23F1Q1%#1(52/f1C]2sr29[2bA2<'1J;0,u1m821)2YQ17G1Lh2hS27o1;o3H83LZ2ax2981s{2eu1dr1Hj2(V2Oj0@c1!X1&z2(72Ae1>31Dc1fm2@'1o$2:#1vP3G*2]%2UN3A^3262EB2P82Xj15;3Pg1]c2=p1>51ar2I91%>2N22?B1cY2Be3PB2m&37j2G<2ES11F29t29D17+1'<1&u3Ex1rs2Xt1K82hc2ep2YZ1#J2TZ1R;2Ue23:1:/2Y*31o1Rc1eK1+F1t&0>d1O/25t1Zs2ub30^2BE2@R1}d2aH1$G28}2@l2C$00q2xA2gl2E40{+2BH2G=10K2Tz2'01,M2br2/21Lz0>%1]S2Zp0:q2UF2rm1Le17=1Nu0=v2W+2SG1&C2*'2Mq3D+1KG1WV2nS21227g0'/1Gf2LQ2/*2^w1BB2g71g=2e]1Ek2y^2MK3AW3Bd2sI1c<2^M3O22DQ22P2/337K1g11'Z1L@2@G1n?1&;1/}1+O2]M2tJ2Q/39J1$h2p[1bo3I!2+91W02AX2@d1zC1Y!1c/2j12!k2wu2ay2dj1:o2;O2RH1K)2;z3JQ1F72oz2q63O&2tC3J;1}<2)52!62Sl1t41X]2O3051WG2!I20C26W27C2S11Un2zJ2<937D1%Y1k32eb2al2KE1H?2a+1Wf0k83Ey2M01!h22c1{s1jN2##3EM1P<1,O1w{2yi31:1]p23w2Bh31[2V^1%62#h2Io1%l1,j1Uz2,,1zp3TD1yn2w918Y1$<2I<3C!2RA23u36]2e%1*:2OO2a#22{3Pf3Hu1Ka2LP1aA0'P1bO32h2[H2z/2341%F1Vu2Ix1Oo2V51ht1{/1Oa1>v3H]1@q1>3H}1u#2^u2p11x&1$P2!h1Ev2yL2s^1v62=u2[Q2dW1]]2nG2f}2r!37s2]G1a92(b1u%1zO0},30,2LT3J<2Fj25W2CT1QT2^92k)2XQ3C#2Uw1'22f42y(1k]1OO1;m30u36W2J*2%R1d^2sH2Xw2201;+2o91}M2Q%1DJ1Y21Mm1&K2A91+;3Ni2];3501)w2*W2$s1AQ2O>16E2W22<[11G3SE2M72)N0/G1[}3J231?0mE1gp17P2e&2EI2m]2X)2HJ3F61)a3Hk1jn1?R2PP25f2<233935832=2Fb10V1x;26E1n+3Ia2S92eA1}#1)m2m/3I?1,d1Lt2P}3I71!p1e=1w91?i2o?1{$1v41Z021s1HT3I21=;2'o2nq23V1s[2YD2*w20S3VB11*X1cw2)]2%[33h39K2YR2l^1G=3AN2&O2Um1(72i(0z/3EN2/@2vR3PC30o3YI2Nj2s?0'T25y2;Q0>^2Dh11M2hk32W0]%2nu2VZ33Z21p22[2xs1]g2]h2cx2Ql1bt1k>26g2A020m2LX1{<2nb36z1tB2Jh2G;2UR1nb2jl2yh1jX1701W}2qh1#y2b)2uh2fo1i$2NB1)t27x1Te2MC1A]2Xf2ME2gW2vK2aA2<,23s1,R1(i2=W2Km39w2dH3P+1KB1,I1I'3HD22&1z:1zg1zc3B21s)3E#2g,2U)2A31A42V:23+2}V1:S1VQ2)o2Ax3U)3Pc2W2UT1=w2H>3HR2VC0zN1b>2yP1FX19k1hG1D21dU2y82*#1Cr2e(11/1bD16c1;=2a:0'h0:o2u}2m%1Jh1{H1@70}01N71uX1i11aM1MH2ym2x73Ag2=*00s2e21Cg2$81nC2fD2cK2AP2rP28I1T82{e2vl2xq1*h2#U2xN2sh1zH2SC0>H2>N0l1g!0:=2[M1C/1''1M21Z'1Q=2cT2I{1Jv2lq14j2,r2eC1}N26C2QF1*{1Uc25b20Z3W+1vE2Wd2HS1dy1j11Y&2(:2/51sp1Z<2]Z2yd2aP2@J1EM1yN1+M2Cq3CE2z51,w2@]2:u1eA22*1vB1Aq1gf28V0'd3Ih2V!2:h37y1eP1Y:1I52P,1f,3Qv2!<2P^1dV2nP1g$2Gk2Y61pw2Z+2+]35Z2c,2:U2la1xk2b32oq2Se27(2lE1{n2xI1Wk1Ia2;P2=v1M83FH2>o2k42xj2x/10%2rz1N82mN23a1cv2N>2c'1qQ2I(2pp31^1OC31m3D}1^C2l83Nu2Jz2ll2sb3IB1R#2z{2tg24J2CU2ia2Ta1+n2={2Z42Bb29y2gK2u>2>'31324g2Kr1WL1FD2IN2x633m1by18%1O@1Gg0,<2*T1u421X=2yI2jN2?Q2Xo1*S1Gq2dz1f1Pn1p?1vz1tQ2yl1m)2k#1rF2j91jI2EC3Ac12ts1OA1Fy1OU1/J1&X36<1Ec1Tl1:z2r721D1*P2y>2o32v#2gj1L{2&l1,F2XL2w02fn2LL37$2}Z26n2S22wb2ps2i91rX2AI2(s2u{33k1kp2mv3192hp0;T0>,1sI1mC2Qs3122#T27:1g+3V522;2!A2CJ1Ti21d1d;29&2:P1Yl1Qg25&3MS2B$1gK3KX26Y1[F1'&2T[15v3R61u83G[1uM1y21d'1^Z1Xs2FV3ML19=2sp1Gb2[v1^82dN2'Y1Cc0,22)C2{:1p!3Q>25(2%C3JR1JC2)f1CF1u&2@r30!2l735N2^m2m=1(r1683MU1eg1%@0:}3D*1T91/L1k#1X;1X[2nz0(r2K31=@2[r2t+2?=2%'2^12's2q,2&{2B&2BU2{k2=U1;C1ZF2='2Ud1v#0{M2lU2T)1Zc28F1bq2,K3Dh2{{1=O3L*1&H1i#11#2+m1X%2mQ2}$1mN2772c22T61w#1Dy10P0*C3So2P?1Dz0!*2HW2372jx2],1]Q1tK29H2/L1?X1xI1B;1x=2h81(+2ln1p'1G32=k29<1(M1F%2@D2[(2W{16Q2;g2PR1@A2E635G2rT2DT1Vq1z}0}?1y)2E]2t[3142a>2?U1!u2i[1B+37)2aB24;27G2RC24H1PH1=82OD19L2Do2YN2Wr1p+2t<0:314U1W+1yZ00u2}j1#I1;P31V2Pt2702ZC2$32a?1df1,p1?#1'724P2HZ31$2B;1A^0{U0(N2C1E)2it2m+2{q3As21r30<1n$1;u1HF2oM2ow2^X20D2Ff3Jy24l1Ol2l52Bv1nz2v=2<@27a2/(3Sa1wr2i=2Hi2o;2+J1jh2w61yT2#B2bF1#[1#{2^42!l2!t2jL36b2c:33J0(p2833EV2,g3202uA2*[2?@2nc2rF3HK1BR1rR2{p2cz1Q)2Kj1K#1bH1@r34<0x'2eP25Q2ZO2s(28o28$2HK2f^2>K1@81nh2iQ29n2BX2j82&t1{f2,e3TX1g,3XO2X30#f2gB1c51j>2@?1$42=:1as1FM2)r1y:3Q{2Dk2dB2k12D[2:n1?(1v&2D723j2tO2%A1782[p1]<1)E2*Q2Mu2E:2v;1;}2n423c2wU2r]3CD1*}2Hu3CK2YI2Ci1tu1x}3P^2Ss2rD2HF1*M2A!2mt2/t1Lq28s2ch2jc1X91((26d1FF2^f3Cn2Y{34{1O72LH1su26J0;u3X62)j2uq1@Y0)d1Z#00w2/i1zj1y2:i36q00z1Xi1z=11,2g31pE2/!2Dp2[F2+s13@1!<2CS34F2ID1[21+S1:01OP2=$1'd18I1VW1wB1j&0&T2c)1lX2pM1Ww2>w2WR1v=27v1lS1wb1+33V228A0&n0#;1Ko3G61CN1(d23^1<@2v%3FL2Jo1N02uQ1QN1z(2D*2E)1+s14w2A)1J:2f'38!1*41%v2Y$1Iz1AD12+G2@i1LC2ff2@Y26!2m51?l2lY35f2Sq2d/1s}1X!2@}2a!2Oy1p{2]A1iI1J{1nl2EF1&l19(1892NV1n%0:r18K12,2b*14>1,]22/2^y1iO1Gh2aK1WF1(o2rd2$@1v'1=(2/K3HV1=l1bP2L>2'q13x2Lf2c12:s2tA2}y1sN2@U0:Q2$Z26f3FZ2b^2ix1Q'2v81:m1,22C*37+36M1@y1lx23IS1z;1pe2@v1&J1DC3Cf1UE31P2HC1CJ2@Q3Cu0uQ2=h28H1uz1'C17N2t40'J29m1T^1hL2y12Op0>N2Ll1hI19q11*3A/3J:0ob2Fl23Y1gZ1U22E/1t713&1[&2tb2dq1;k1d52Yn16H2{I0wU1:e1C{1T:1a;0:i2y02BS0;K0]>1lQ1FN1V]29P2](1cQ0{I2fQ38m1IN27i2962US1>{2=F2t$1jM2]$1a71!71s&1Xe3Jc1&M27W2FB2O)2r=1qO2z)1Cj22$1h52g81ME1:O1;Y1s41}U2152R41p$1p72[s1$714e1v*2}91+k1U=0@,1Df0'a16&1!42c52%D1Vr29l1o?2Bk2,A2nk2l}1u21B(2{b0]^2g>2DV1I,1e32oE2+;2[L2!#1Bj2)@2B}1mb2mA1rD2vz3M*11X2''1@j2sq1$61b(1#o1<62Gu27m1uh1Mj1!e2aU2xB1&/2W}2pa1(s2ND2T42FC3L}2oS2:C0*b2F!2n]34d3DS1<91vn2Ke1FG1sw16Y1[r2850{d1{m1;G2061{W1,%1=[1FC1r^19D2$21Hh3Ak2$^2Vm0k22&$1mZ2S>1US2;h1&L0;w2Bd13'2)/0zo1jo15X2#p2ea1UF1{?2:J1yG1wQ2Ck0}a1l818Z2$C1cI1j51',1*I2Z%2di2oF24+2+*2QO1b72}22cl22D2&n1bY2M11/=1x!2bk1'm2Lg2Eb2?E3Kl3Kp0[61w22ve2}S3Jg1Ta1;N20,2SL2Wu2?50='22p1sm33y0y21/q0od1ph28E1?Y2q%1ZN1Q!0[P2dy2i71kq1hk1}v2g51TE1^@1mz28O21Mn3Bq2Dg0^c0(H1vb1g;0us15m2422@>2a41yS2Ij13H1Jm27q1Lc2a'2m62%L1hp1{C1NB2l=2F?22l0x#1yu2F210;2Aw0!F2i+1VF1'u2Kt0jb0(X1Ro1251,/0#&1zF1fz34j2Fp1eQ22>38I1uR1wY1G[2)G1m;1l]1+m1q,1xE1g)2rp1Xb1cW2{$14;1sy2P>1xO1$W1uG2YE2jZ1qX1[v1F,2RS1*L0(Y2WZ0wc1{I1!w2JH1{y17l2PF0@S1k!1U,1Y[1yD17'1JO2lN33S26N1SN1gu0yE0m;2#!1h!2!}0#]3Q@1'Y25U2rI1WC1%M0*l1:71Kq0'614,1aB1DX1hV29R0]70,(2SV1Dj1[91WN2pk2{Q2Lo1!)1231]B2Bz1L}2Gc1r;0zV2#637'1TG31S20v1#>1[D2EW1Dr1d}1q(2UI1m32A:1U11xm2nM0]I1If0<#1iC1Vj1tP1un1:E1/]16r1<72q72e,1LO1@l1d+1Eg1Tv14A1XI1&=1mV1Sz3603C(1px1js22E1X:1XF1c>0>11bk1ps18q1OJ2q'1e21Q01>M2vb1kG1!%1]^2CK2mH1+P2mw1L21l>1{k2fk1J^3TY1z]0<^2C(1Bo0=!1l{31W0/#25,2z;20V2It2Fd2(P2ER1,,2Ir2Qq2Ha31'2Xr1ep2En2;'2ny2MO2Qm23*38}2B#2l;29)1iX0@P1P52@^1sR1rq2&q1=Q1{'1#Q2Lq2Yq2Hw3971+62Q[20F1L3Bt1w$0}30*r1=]1Mv2+z3J72kZ29q0xv1kQ2bO1(L11a17u0:K1a@3Mv2*536}1zV1G01}31q81ke2E#29$1j%1'!2oV2hA2FQ1,32g11lF1z*0%u1G%2Cy2(F2Y42yt2#>2vS2wd1h30'b22Q1R&0:T1OD0<10^f1es2cR0{:1gU1:r1w*1(&2{'1L/1,80&G1wU0[j2Wk1S@1LD1J/1*b1Ud0{Y2Qc0)>1NC0>u1JA1P>2$!2'm1nX1){2ms2&R1/S1N91h+2gf1?[2S2/z1aP2so1%B1!]2eB00/1)F1Dp3Ii2'h3Lv10,2yn2}g1xG2!81S[1By1Sj2U?1T32Jr2da0+n2V71991CH1v}2zw2lA23L2}T1@o37B1So2g*2481Lw2C!1Ho0>/0&Q2Gp1?526(2w)2D<2Wj1&t1L50;)23/2>g2::26e1nn2{i2Na1uH2*&1^=1WA2{n1eC2%!2(n1WT1yR2Kg1@51zY2vN1AK35p22u2eV1di1@N1!>1:I1eh2QJ1(k2Q<25o2Wz2fp1i71gH2^;2e/2W/1*]1^I1n^2X#3Gw1B{3B12?]3La3AC2qR1pz2;631Q2Y/3Hg1wu0:M2+51i^0s61JV18c2lV28B2P#2Eh24F1UU31U30Y1zx2AL1R}1Yg2K,1rU1&)1?739W2]^2/e10R0{$2g$1Z}1%N3Ah1n{2tf2QD2)92'W3I>1sB3O,0&X2Ns2BY2Qu1,?24&2!32M82km2a%13>24V1k12J01];2P32bv2Zg2Ut0&b2R?2Ge2NK2}A3J{1j!2ib1602$i2A81$d2fG2[R1#12m01vi1541B72sV3FN1q}1iV1xb18M1(O3LQ15^1y93MR3IM2r80q$2M&29Y1Xj1Cl1e80:$2hF1%h2l]2/}1vD2?Y32p0:/1'O1Ug1O$0z{2a621&y1c]1{T1r81p<2V*1Q31/<1yp1O%1qe1;b0;l0)+1m}27r21u1eR1E[1a]1t51I11JR1)G1(n1'>24b1KK22V1i60>E13V1AL1hb0:R2R)0zp1!50#O2xG2142H316s2&f35a2l,2rq28K1%32d<2%r1(?21F1>81[A2IF1Y82>[18k1B:0+O18(3622GD2eq2<>1J+2Z21&g2A{1{(2#^1@&2jo1+G2Ga0[p3F>1i:0wo3E11U(0(B37P3A'2Gn2bU0p!2H%1R$0}@2cb2@42^v2902A@1*1sW1I=1l=1LE1?C2bM1@p39p1@U1&h1tE1k/1:@1A$2VR2XN1rj2O/1$%2Z,0)]2H:2!c1U<0}j2Hm1Dk1qh2tT1/r1x%2g92%k2Vj2MW2R[2r02bQ0&@2nW2i61WH1Fc1d@1C}2T,17>1c61V*2S[1ri1351HY1/%1Gp18D2h+2$&1am3H61b81oH2KF1f00'*14o2$B1q41q<1eO1Tx1t#18;00+1Bu1,}0=311W1IP0[u2Zu2=?2fL1Kk1z32Oa2o%26F1]t2xi1pZ2wl24Q2i;1{Y2Rh1N+32[2TQ2?D1H&1[V1<}2]92RT2OU1!*1&B1(82r[1rv2iZ1mG19s2wR2K22lu1EV1Ar2BB2(91{83Ev2;U0=g1(Z0yn1ce1/v2A*2H'1XO1qa1d!25;1wd0=U1IL2TL0*+1wG2$%2lF0@w3Du2kH1eD17{0;32DK35&2X53N)2g01(}1uv2kN1;12D%39=2Mt2he1rS1AV0=n1V41N@1E51Tj18f2P(1z%12X20o1)x0t#0kF1N53J^1M)2qc26x1L3HT2by0!v2Wl1yI0+o12f2YG17m2*:2ky2i50z+1]H2&b1SI1Y*0i[1BM1#x0d53G!3Hq0[12%)2Ru1{A2kw1^02&m1B&1/D2na27n2DF1hu2KX1Pr1OK2A'2n=1/N1o11P81y>1q$2f?1JB1e;1o%22v1h{2B/1DL1f)1v024)1Dt20$2fB2jn1%L0w,1/t33w0wd1VU1101Bk2oh2M;2sS2292e@1>z0s<1os2$72#*2ZX2m>2sm3FF2130%31rJ1dm2Ii1l)1C;2zp15w1%J2JF1VV36C27}0zT1aH25r2IO2Yk1WE2ij3E=3JV2{71h61=d2d}2Nw0;%16i2793PE2J^2qO1+82($1d62cO0vZ1YF2t(2N=1IR31>1?a22W2Y32{A23R2vY2!u2NR2I*1fO1!j0<81Fh1r/3QX25G0sM1uC0,>2N<2R&25a0%q1nt2JO1:]15#2f*2%X1Jk1r<2eh2jh1**2Pv12?0{)141fK1w01lP2{R1S$14l2d+0nY24?2@91(x0=z1p%2T?2o}23<1w61Qw0}f2hC2v!1Z60+L10$1xB1;q0!>2]+1jt1()1=020c15G13K1uS1;W2820gj2)R1]Y1T}1*m2KP0[A1fH1:>1*H2&311b1po1Z70(72}k1BN1261+51ES26{1RS2Kp2Uk1==21yQ2dU2gA1mi1(R26L23S2X*0<$2io25>1EI17)29U1?z0rl1t21ej3MW3DD2{]1ic1wV10c2WW0,Q2aw2cy1XG2%V0}41G!1fC0[e2*X0(31^m2T21lu1b^2C81412sa2$+1o718721,1n51D40jB1h?2%41ZB0:g14(1ds1q@2G)1a(1$D2]72J!2(^1&Q1bj0za1MU1zm1(j1y628'2LO0z61E@2tj0pZ0xL1ow0);21k1]h2kB1+^2{!2wn2?m2XZ18G2b/1661m71Nx31i1Uw1:F2w:1it1u;2FJ2ZU10=3A,2MY2Qx2F)1]w3V[1*10;[0Y]16e2K[00=29g2^{2+/28<1Rw1ss1St1x31,112w2rJ18J1cX32N1s;00!1#]2d%0[b2@q0}G1>P1ci2F:1F?2NH1/C1S'1H*2P<2732PH1#^1vm1dw1m?1H=2w%0su2t@2!p1$S1d,0]1sY1r11jU2%y38%1H/2;y3M%0oo1>F35$2=#1!P2,l20%2JD1w+1nJ28Q2G&2E!1;)2mU10m2?T0:Z2v@1^X2Ti0)Z1d21f}2Tj1OX0?n2ai30f2c=2vs1vL1M72bG2gs3P#20p2KZ1yL0:^2JY1)e2Cl1P(0?U2Q^2'j2@M1El1K%19x0[$1uT2W$2if1PW2{B1iv2Z/3K&1qt2UL1}=1[g1TK2bH18o2g'1xD2g=2Pe1d<2Rk2tV1(/1Gr2wT37e16R1l12022K@2I71y52W(1y;1dQ2F13LK2PI1x)1/f1@k1=)1KP1=K34@3Kf2Kc2zc2d(2c;1Nl0/}28^2dR1fu1WP0]g12v2g+2u52uc1iL2xZ2L]2081@B15S1%x2Jy1{91LK1Dq1*)20f1q&1*O2DX1Q[2r62#v1hA12>021U2l%36#2qP2+u1X^1>q2>)2*l2]?2xU1#31yg1sk1')2H^0rZ2!&0(Q3QL1<:1&S23r23o1371In1#f2$)1*s21V1FQ2q)2qN0nc2{F2[)2te1#z2]y27j19h1f61;/1L(2bx1%u3Aw1*91IH1hq1aE1L62E?2vj1;n1)y1!02MS3Rq1[[1c@1r&1y*1^F1bK0>U20T1Fr1{w2Q42D92g:2]O1643B42C[1;@1b51'@1K[1c=2#t1>#0&11YI1S,2j41bB1Ob0[E1fd1bA2:627/00@2B?1>K0/k1H!1M*2V?1>!1Fa2GQ2]q1l&2nE2r?024a0wT2Uq0(C2A41aT1#!1[31AB2U>0:e1Tk1ku1lh2:12K/0(d1,>2F71IT1K62Co2%O11g1uA1gG1#(2,I1io1=U1SJ1pq1hm1Yu1dz1yr0qT0&:1sq2@%1QG1Kg2WX1S%1@i1,51,K2mY1)?1iW35D1Ub2aL1]91282mm1R11Ja1oD2BF1}i39(2p71@H1NM1pt0o&1k21oj1r:26G2NG2/R2Ai1;?23T2%62@01GD0^v1U@1gI1eB2jU2nN2f:1tF1@W2;01Uk1lT1Q21L72W71uI0kC1}11Z51&U1Jz1qo1wJ1y[0}H1ge1uo2G}1NA3O]1D&2Vg1$e1MO1!J1a30<%0*D1kn0eE21y2U32Ca1kM1's2[i1(@30>1b)0[m1z42=j1do21Y2Sx2@82Rs1w41}61Lo2ZM22o1gc2;21}41,G1<421l1gr2D(1da0,Y2@$2u;1fY1^v1r?1W&1Z!1/T1r(1lf2[z1pr1$n2sW2Xk2L61vQ0u@1H'1G*1if0;V17C2uC2GJ2P%1i>27)1e41vp0)=19T1NW2]o1{30]=1F:1*x2V>3UK2+'2cu17n0xQ2rE15+1f&0=L1Vt1T722R2aj2QH2{42!w1?11k:1zu3T}1Z/2;V1(c2wP1Wa2/I3C52F32o#3JG0;e1vx1Rt2Cd1yq26m1gJ24/2LI1Qd1l;1g?1]*3E{2;I30x2L02jz2}J1yF1^(1tg1C40n#1C!2K:29}19r1pT29X0z00'82ao1fq1[m17r1%e14*38h28R0[!1i31mB2d51&b1]T1wH2jS38R1Gj1Yw2E;1f;2vP1:}25?1{U2J}1h>20?3Gq0tm2d*0!+1q^1DO20Q2^E2'c1xp2ii2c$1RB17W2l&1;K1='14X2Of1S60/l2lT2A61kI1c!2o'1y}2wO1d>2vD2E92u'1?K0&91mE1#H1z{1!D1ba2951dC2X}1TM2vy2O&3L+2&522N1]s2?X0pz2T%1=W1O^1=C1ju2T/2hz3CI2*e2#%1*(2hT1(:1MI1f?2/d1$T1pn1Bp1^N1BA1k42>Y1%<2Br1+'1ua2AB0x,1&R2s>1nH2t91fU2w#27&3Cc0>p1!q2Ev2GR1d%1n,2i!1W#1'x0'%22#1Zo2,J1D/16W2?d1Qi0s30xX2^80zZ1$O1?k1#t0%J2um1&O1fL1U%2IY1/>2xH1!i11Qa0=F1mo1=!1+12d'38?0>S1=g1b'15y1B}2m^1!f1sl1k'0x)0$x1:Z1yJ1Q]2LA28q1V02fw1,T1VD1(D0#01me1&P38O2LN0?/1On1h$2?035b0vz1c$0:x1$^1/62lo2$E1T<1Vc1ca2u<2Sj28+2p?1o{0tN1Cw2Hg2(z2881o[2[^18&21O1Jb21T1S<18H1xz2G02S;0v<1P$1R'1B21ax0(+1=f0$E12<2QC1l92+A1CI0s%1Zf1#u0,v1cH1j41U[0uO1I[31x1ch0^@0]J1G91%,2gI33H2GK1Hi2H;3A[2;k19/1tC1MK0:51V(16p1Ty1PI1F32y]28C1,L2WK2I31F11t>12S14/0w{1t*1ou2lD1>&0)R1;p1r}24C0?o10:1sJ2Mv2Oh2eo0#*0uE2381o>0r>0;R1C70/C1u{1/W1@91I@15$0(u1G(1o+1oS1oF2N#2=229=27=1dG2I61T51SA1$:38#2=e1ID1Io2!^1rE2n$1Vd1oY1!n2ab2#30;Z2B83P=2l92fz2YJ2F(27N23g1V+2661ry1A%2]X2Vo1:=12E2{Z2SA2L=27@2D;1sF2#$2MD2Vi0yb2E%1R217!01vg2p43C}1qG33C1201Oy2s&2yE2%N2DY1{R15V2oX1jV1Vz1XY1W=2Am1n00,w16/1562Eu1hy2:Y2uX0qb1d:1pu0{O1gR2}r1=a22!16q1X@1Nm1v^1;]1[:1Jf1L^1j'2zL0:k24,1'03Y91C(1C?38L2nY1h%1g71Fv2)K1:!2sX35F1dx3T:0#z15)1l50z)15l1Hu13l1Ke1tw2+[3GG1Y?0$D2w>1OB1ZP2d11s92v92$h2Y]2101Af2RL0(z1Wz00$2ux2F'2Ie2DN1,B2{}1&91RC1Mo1{c2GA1m[2Tc13b2ob2g&10G2c/1ET3161ZG1&D0*91P%2Th2I21d=3D000%1^)12b1H>1H82l41ko24}11t27%1MJ1m%2Y=1$w2=X1pB26u1[;2!v21?32S2%U2^<2>s1RP2e61v(2z%1Xt1B016=23P1V%1UC1e:0$Z1:M3M51q#2OB1R]2J?1I*0&{3BL1380l^0%c0}D1k)2hx1y02ha1Bd35/1A:0xY0%g1m(0!h2a*1b]14I1eU14?34'1k@28D0W81eG2MU1QX0?h2$61i/1Od16)2o22^N0^y0#J2!?2NJ2Lm2O,0%(2RJ2S@1WO1]F2@a1J31O)1gy1v{1af0/u0!c1W'00^2^}27F2ZA1?0,'0>r0>[1Xg2pe1(A1F(0t/2&B1!S24[2Tp2F#3G}21+1%X1o21iR1m62+^0o32u01Fn2'%0)i2Yt1oc1o61TA3Vp1S^1Vf1L31n@2Q31w)24q1n&2s}3XC2G>1u=1fA1$l2#P2qi1ji15D1jK1(p1zb2Ui0>71zn1>D39%1A'26k1u*1bp0'K2/j1tN1p}2]}1{L1M+3A92xc1J!1LM2=r0/K1iN1)51uu2jC2b72(2/g2';2g%3VD0wD1s%2443DU2ZR13y1!;0;x28P2n,1f21^E1e%1hc2H42{f2BV1,90$U1@x0('1uw1?m0:s1N40'91cs0+t1u(2zv0$*18d00*31']2dZ1lE27Q2&P1gV2241(]32A1^J2gF1?$19t1b$0}v1xc2u&1BK0uS2SZ0y?2=P0w}32K1(P0]L1S>1h113I15134v2W@1r]1&a37a1402#,2P*16D1CS1S929c0[t2;N2EM1)o1&c1m91k92Re2SD0s)0}z2L$1XB20l1I/2Mb2F*2PC1:22XV2C+0%81sK21%0'V2fH1Q*0}Y11+2K^1[p1{r1;B1Fi1/+1ag1#n2Yl0?523M2hl3S42Gr2OM2YS2R}0]+2ZL1qd0}k2hj1j@2QN1qR2&[24S2h=1RL2,o28r1nM2es1<82Oi3F}2u63Mg0){1^G1H;3Jm0nj2e42kt2!N1T/2?g0,,0:E2J61Sf2j@2va2IS19^1LY16Z2]=1P!1!a1YV2,]3C^2692=q2Xh2OL2781=q2Ve2[N2qK1W]0}[1%71(=2KM1392KU2(20XI2632'i1Xl1'a13$2q:1v92tm2e11wf1'81o;2Xq1E=1Xh2#l1?h1E62B%1=A2nL2XT2S'2o82Ma2{W1kw1b33W)2GS2xS0>22>;20[2l32U,1>%1!I1431ra30w1XM00&3751?02SM2<71]=1SU1oX3NR1hS0x$0p+2UD1{h14y0!d39E1r$1=x2B'2hh2?>2Q01Wi2=Y1W10}V1rA1eb2ip1oq15o0po3EG2Pg1:l2Jp1qH0@a1;!1H42j;1^Y1$,1Tn11y2$=2q=0tS1n41cx2@#2f[2{S1U^1C@2Rj1Hp1d&0rq2l/1P)1f+2:x2Xb1ee1Sb1fs2VF2QP2A(1GF2*<1]{1XZ0U[26o2z&18L1IY1Ak0#C2UG2Ju1P]1;M0]X1Me2t,1Ca1xX1l32cA2(m1=t0ri0xH1tZ1kO0[N0;61gn2UH0k&1g231+1SK1#h1T11IM2VH1Qn1$f1{g36)3P01Zv2zg1br29{0!m0)<1dZ1J(2'^27]1fa1k&1$01m42Kx1cR1bl1A91v71*B2:A1D52N02]<1$'2ee2IZ1eV1:11o]1ff1hE2R52?S1wN1X<1iw1>I0x]1uk1DA0+]2+)2I^2Yp0x>1Py1@I1DU0&!1<#1y'2AT3Jn1g%0+,1>Q2T+2X<22Y2Y[1TN0#/1K@0+V0]A0*=1o=25p0}r2h%1L&28)30s3A127A2)S0''19o1aX1b+14R0wp1Zg1lY1eq1QA2xf2O11L'12F1D;1cu0$n2m;1531SX1T+1JD0!V1sG1ZY2R#23Q2fI31r3L20qf1C:2Nf10y2H/1ab1sM1X>1d$1JI1g@1P#10U0bk3450sn2bV2FY1@21CV2cd2YO1Vy2Z)2*u1!A0&R3T82jd1,y0xr2[O1yK2C)1$Y2]C2E=0@(25]1Q134U1@Q2Kk1pW1E31U:2xY2)h2G!2=K2qF1O<2hs2q;1TP2#b1B@1zk1U#0j01Q>1#S2Ho2WQ2Jv1z035B1=?2M?2Zz2r^0g?0eA38K2K$2%W2Vr2X'1*80fg12n1R@3G(0a40yG0?C1;d1YJ2n)2ev3KO1>i1}21Pu1;w2Bu0,+0[%0z'1/:2ua2Va2;b2S&19821/2$P39v25:2T82f$2Ip2Kz1IW1$E1s$0k]1{x1G,22)1z#0wq0^62Ao2&j2w<1<;2?V2AR1hn1]U2@B11&2Y}1+Z1HW1G]1+@1Da0kr1r@1C#1ot0?i0[71Rd1LJ30$2vu1E^35u2V'2X/10#2fr2Z{26Q12>2,U19b1E'2O]2VB2+,0>O2N40SU11H2Ad0v/1hR1)2L;1}R1aq20r2MV35T1UI12A1w}1Sm1Vv2!V3JB0@Q3Lh1u^1z/1,q0vg1lW1EA0'$2U=27z0,y1vt2cm0,a1@+2xp2n70(a0]H1yd1Iv39T2{d1F}2HB1#R2jP2k:2b;2P50/b0&52st1t+12(1N}1b{0{x2&x2pH1yo2Iw1Hs21#2({0)w29>1vo1N>2(l1Ib1J)1?U2+210z1Re10^0&C0^L2K}0;G1Z,13611J1VH22l(1Z41J03Pi1QL1j#1tI1}E1Vk1/!21C36J1w82#}2rL1w72hm0%K1w,1gq3071Ou2zr2N(2G32aW2Yv2Pn1%H2SO1fv1(12Nh3M42b@38o01&w1^{1nT24T1iY1:q1Sw27;2Nz1yw1iP0[R1$=2bC1hw0&c1$(1*w0;y1H02H91)W2c71,)236i2V02k,00*1jb2rh2tW14)2v]0k'3KK2X423=2^,02Ef1,k1KH1x21i=1(!2e!27h1o00'Y1g32<01Z%1$q0>+1M%1#:2g{1Q;11;1^O2QU2%H1>Y1A+2$r2&*3Fu1cc1fZ1rB3Qb2q>2%:0b*1Ee0>&13g1I61v21+!1P[1Kj3250Y#0h*0u:1M?1V53Vg2601KC2zK20)2TD1N;2!,23B2[k0}d2#L2s{1?c1ww2D,2G*2>x0(R2pT2/Y1@[0[n1qv1;L1cL25+1R<2<$1C+2oI1RU1'L1jj2Jd25E2d61X&1XJ2=R1oR2Z]0lr0?<2;p2t^1C)0!71qf0/n2i22Sk1q>1fe1q;0mt2Ul2w?0];0{y1{q1T,3RF1'P1j$1$J1}{1[%2Ld0%z1h^2SQ1k+2AY2BM2ql1*g14&1*51n!0oQ0)z1e72LR2G'3Gt17&2Fs2D82FZ1r41so1BW0##0q,2001+D2L?2KS0>{1cC1xL1}P0yC1Z&1[x2Ka0lF1CW0xg1111&23Ru2zD1GB1YW1Wq10{1Bq1r61;<1Z+1}H0,725'0+^1}F1zt1qE1tk2Rb1WX1z50{(0,z0@42;Y1b!1pa1ms0^#0*!16l1+>1O01IO38A2(p1yc1E?1N{1MT1T22LG0z$2*p1^P2a;0oL0(e1J'0(s2A&2z!0*c1kR0zD1p#2Z*1f=1zL2B@1ap0=X0r^13C2uf1kU2vp1x@2c&2X810*081&A1#$0gf1wD26;2sc0rY2R!1ZS0z=0tn0!60[<0xO0%a1';1t/1UL1Ic2cw1YD1lC2IB1Aa1=u0$A2sR1)n1'31z@2M%1@>2X:21t31l18,20/2B[0'W2cN1o31o(1iM2c31>h1*?2S:1g(2D61[j2A}1tU0t+1r>1?32;40@[1sa1+l1om1tL1FJ0qO2^J3EL0'[1vV0$a1qT1]72Fq1[41[<0%k1Hk2qC1q%1KN1pI1TY29]2}b1Vw29!1V<2%e1F'1SD0[21#k2QM2bD0^[0Zg0s^0{r2nZ2N612121j0/D2PV2Yx2r21!/1hX27X1v10{!2Sv0:[0{}0,S1G20[Q2l'2m?1vR1E#1GT0*x1P?1rk2H+0!Y10S1o#1Xp25z2z23A#1Xz1nc1TL0+h1)70,h2!/2Bi16^1]C1n82iu1xw1Ul15O0%I1HD1;J190ey2zE1#%1XC2'C2Ys2GW1b?1(C2nJ1gj2HP1R:2':2$a2NM2wE0}B2C61gQ2?K1V,2Z@1D(2nX2*^2d@28=2Dx1'{2jI14z1^i1Yd0{o3RT1Ts2JK1Yx14p0'i1C'17Z1O[1EJ2Y+1}k1FS2@h0&I1M(1RX26q1S!2gX0l60?R0[^22^2Qw1u!2do1EP0>=0=h2V+2pL1mR2z70;730j2>/1H31u30:72LD2d>0wa0=r1h]0*Z29(2b61^/2F$10e1=}0qp0$(0/F0*,24'0)P1Wx1uB1Bf2d=1!o0}M1t%0$G16P1gA1oZ1D$1hQ1j;0t^1UP0%90m81'=0}Z0k<0*#36H2y@2>Z1eH0,31Pm0pQ3L?2uB2273O*2U}0w60q62cr1K^1//0d;2u(0s=0wy1V>1e@2K)29G2111+j1A32k+1;02N/0]T00)2H(1rY11K2bd1W20!(2I!1^S1Y915H1}Q1e{1)L1;h1>0^D2HD2$#16<2Cj1'F1rI26)1l!0wF2;+1Y}1,g1r21(;10+1,^1#/2ce1>s2M,1)Z1=/0W1$F2gc13}1+20%01>}1nx1Uo1S#2F]3U%2/m1f:2IP2Fm1PK2kT21K2$,1+T1Kb0nA0vb2/63MH0:V1Hq3BP1fi0+b1!,1}V0>X1xa1Ns1Ax1^+2ga1)Q0v=2mg2Bl1<^1RM1r70iG1:b2(K2j512e2?n2Ts1R,2p81Dv10T1wP17;1kT00q@2em1P^1340p;1%s1mv29'2S+2V,1#E2yR2Zi2IJ2x31E&1Dn1ui1pl0ev2p@2X62HH2v23020bz2Y80:N2p02#Z2)!2N;2vQ1e]1Qq0)&0@{1Uu10D1:+2WC2j'3V!1oL2NZ1wL2!O2!g0/M2ru2V20x}1c12HO1B82Up1Fw2LB1/p16N1+v2h70:41LR2/q2[q1hW2'p2hJ1EE2{,2eD0Zq1=Z1Fo1fw0{<1$12F62Iu2p(2rV1+&2W915e0eY00[0XS2,;1(321<2CH26j2u[1bn2Sw0Xl1Mz2(t0{s2wf2VS12G1x<2(U2W#19$0J2E12%q1:60z^1Y70nX1O10kt00{0eB0vD0ho1pF2Us1tr0a01Pv2Q625}1cy0@52K<1U60(=2@f1c;1^A1oI2Z12Nv2qA1!'0y91OL2[<1lq36p1bE1e1jY0]80;c1SW1Ri2M'1{*0@}2>W2T'0[g1ML1nK1+#0!)1iq1I]2d[2=B2LZ1KD2q&0,F2uK1hJ21;2KQ2dX0%[0u[1/@2cG2#i2o01121rr0)p1B'0Y1YM2p)2S524D1&I2dg1e02wH1}T2(r1nk2KJ1Ao1Ew2q?1:X27J2P!10o1Hc1E:11T1*C2Tx2QZ2E}2[21n11VX2452ei21m0/<0$P11h1091YA1cZ3R72N&3G81qs1s#2cF1CU1Pz2M^0=o1Y10o)2XX14612a2Pa2af33T1+[0jQ0*72040)42Jm1e*2sE1hY1N?1[K17a21c2*72Nb2sM32/3V61d]1XV0@h1EC1SL0m%2cs1c:0@:14s28w1U30lT1][1p&1Gx1kf1}C1m23Hr2oK1J&1Um1%02RU2q31MC2ed1:f35*29C1'I20w1!81BS1*a2Lz1?91LU2dP1ZV1Qz1z813X2){0%m1u91Iw0{T0qG0=+2i/2W[2O;1G)1ub15,2HG2Ec0r01f11^c23X15<1J}0f10[C2i'2+12OA2dr0(D1kL2T921R1Kr1(G2{r0xh26:1Li2Iy1D%18x2&a2qb1HH1kJ2;u1#T0}w1?,15n1jL1?S0>M0;z0s80$)0E1OH17^0wB2qJ1+,2WY1L422s1Y@1Es1MF1PR1C80,n1130}'0wG1O,1851Pc0k,1s61IE0}>17313K624k1u11R+1c}1q313e0cb0oh0xG2*]1YR2p90(00$@3Hm0vE16#0iD0mZ2P]14t1zU1oi1p*1]R1m*1tx1o'1}s1'/29#2aJ25d0cr0zE2r<0(K2j{1#51n*2d22Uj2A50gQ2Os1o&1lU1P:2W,1zf1N127I0lt1w;1Yy2Iv1V=1rx1!@2xn1*Q2Dn1=E1Zk2h22K41r*2!!1Sn2PN2Mh27D1(T2cV2[V0,020s2D$1Fs2BD1fR1V{2b]1mO1RF2Y;2tK1':0/v23!3Is2ws3F82L31Rl0):1kr0R]2$f1=e1iD26$2762i^1WY1kN0x029:2[Y30:1W*1zI1P02]40%i0+r0u=2Zr0!n0kT17$24=1'91h'23W1c32b51xT1^918R1q13L51!N37d28#3L(2?A2#r1g:2!a1SE2]'1(u00<1It2*x0])1Gs2O}030b#0aM1i+1tO1D918U1#p23Z2fN1A?1QQ2G%1$K3V,2E^0z12u#2?r2pz1kP1Ez0^s0gV0oW12@1NN1P42ww0{^1X70d[1D]0%P1md2[00TX0uF24n1S]1Mf1k72%x3TO1qb1&116F2ht1UO0gD19d1Il2QK0[*2RW0+x0>j2th2jf1DV1IS0y&2>e1YG1ah37O1QY1Nr0gk12j0'w13D1)j0;>3Aj1k{0!i1ln1(q1BV0yP1IQ1Fz1$Q2H&2Yj1+y0tO24Y1Jx2vF1I30pR1Pi33G1>10p?1G@3G910@1Kn1{>1:A1Dx1iZ22F2C,1c00%n2Di1}J1dR0'11gB0p{0(f1yY0d:15q0/w1qU1!Y1D{2pC2pK0}]2db0:<2KR0(q1^;23,1'r1x01mJ2cn1NI0%12T@17s2Z'0mk1/d1qi2dv3OQ1yW1xh1tV1#61kX0{00!!0>s1dW1;(0bM0&<1qI2bT1lk1'W1U)1,+2VQ1E{1N20t*1l:1W%2wW2s/1GU0$$1K(2*i1IX1ol15T2F}1Po0lC2mV1Pf1vl1*z2YH1'R2PD1S{2E015J0{/0'70[Y1F>1*u2+?1Oi1Rs0!o0x[0Ta0bV2*m1zw1k,1Ru0az1YZ0n[18V0l(0!t1F@1I<3G=0%j0::1T)2Z}1IA1dA1[a12q0'A1nN0'{2Jc3D33F'3Da2JU0;^1K<0rt1!2FD2+R0:A20d2Un1z22Fz2T52Wy1%j2XB0?)1+p1>X3W[1Of1I70ew0nT16a0$[0sW1*%0lg2Po2YT18W0(w1P&15%0r;0ta1(a1:K00>1^w1{F1K70'^2k;1+Q2^@2Ce1n1JF1/k2@s0^d1Y^1kA0}W2GZ1+h0z&0Yc1zA0>a13^10w2Wa1:p1QC1id1(<12P1@J1(60(!0vo1kk2S(0$r0wH0e>1'c1HN2BG1g514f1vc2i*1g[2W)1+91PL1W81fp2BC0wn2j=2@*2Qo24m1t'0>I00;1fb2321qL1Mg2R32Zw2>$0$c22d2ie2N81)>1lI1JG1Yq2]g1F*1N(0[v2d{1{)1d#1jy1>o1x>2C}2CE0@]2B:2$x1Z11^61oA1A,2/N2,B2PG1ac1}g2jk2AW1(^1CR0$}1k(1Rv2MA1=h1wg3Di2kD2=(14@1Fx1]l0zw0!<1[b2F,0=91hh1*T0's2g#1Ua2Yg1dK1cb2]63XM2YX1xx2oT1Rz1EY0>m1'12^k25n2!e1tJ2Ex3A;1G^0@E1bI2Q+2E'2yN1ij2Y12HY1S12]m0rT14C0r411U2932l00zd1+*11r1u}0=&1jc1gC3Ly25%37r1j:3S[1cT1K/1d32I&2b!1pA16S2pu2%w1[L1tl1L?2pi0y,2:40@?0'@1g*1)C0=Y0j;2N}2Sy1H518*1}c1XL1,D1Ph2wI2hH1l71SO2Mz1Nb1a02Dr1nj1]@1zE1/E0?^28i0n]1Ky20+1:L29Z3Hj1]o25=2{Y1#e2md1}01lR2$w0[:1r#18<25Z1U$0/)2#o27b0}t0r816I1QW1w&2l214J0=@2am1pM1P21e,1hz1/81?W1$52KI2[,2js1P122(2dw2b%03Ae1t[2JE1yx1J[0}l11{0&(1Tp1Et25A1D<0w10)x2F^1/)27p2bE1D@1nR1XP1yf0sU0wv1$v0lD10Y0b<1g<2x}2ja16:1^z2cL1n61)g2V(1*W1BC1pL1ga0wY2Jw0{J1Pq2=E1Tz25<13+2%K2J>1/?1?M29z2!Z1Z>2PJ2MX0zF1!?0>F1H]0}#0'R2PA0h21&@1,62fT2(q1bR2^q0:W1Ld2f)1HZ0@C1&61DI1mK2U'2pw2L)1LH3Be1(v0>31AE1cS0[31Uy1+C2f,37t37/1CP1R41yj2%S1)@1GQ1st2Nn12y0eS0jU1Qb0fx1Mk1H^1]A18!26v1BZ0+P1#21GO0}T1qS1Qr1>b1nm2yF0>}0}70;;1ox1e(2c+1U]1+U1Ih2i32T<0Os1AF2Py0u]1s+2Bx2:21FU1Wn0(%24>1ho1dO2mB1=B0cl0>k1]m1jH1Lj0jz0q21{42n{0g71P}1/*29M18u20'2iS2n21@L15K33'1/'1x#2Zo1D,14E2AK2Mo2Pp1:H2Ug2ap1u+2Sd1bL1Ov0Qt24d1/,1@s2[C1/o1741G+2Zh0[;0@m1,P2V]1a#1ta1cG1rt2IK1Wb24!1uJ1[M1hg1&$2M$00:2n32*d2[82U%1ql15p1EB0)U0mi2Et2:V1e)1A@2W61BD27u0;o29i1qM0/%1lp0:;1#m1h/0rK1hU2J52251PO0]O1r1@C21b2YP0dd1&&2%d1'G1jw1j}1}p0;*2fY1Yo2PY16h1qg1!C0x90dF0kW0kz0rm0hb0yQ0l{1Jr1f@2>n0/*2,s1mM24B1u<1i%1Qo1Xd0%b2Mi1I41D'0;81C*1s]1)k16o2fO23e1RZ1DG1$!0}U0#90@t0+X1XW0ve13[2wh1Tq1@z1VI1SM1&71*[1q]1ck1UK25g22626y1xK3Ea22e17H13]1D^2kc2U41uf2NT2ZT1a+0p31B*0}g0x318y0^=1jP24L0;M1ue2hi0^k2;f1pU0o@1eX2N)1d11270&t1aK1Wp22n18B1?H1Su1v[2lr2rX1441Js23p1%K0&?2{o1f]1Ac2a52H80}N1qm2VU2Q&1W40]#1V'1Z:13f1Ag3803EO0ix11N0[]1S}0uz1CD0^E1/[2MM18i2mD1N:2571@m0tr2,v1;S0wh0p616]20g1XX0v:2ZB2^h0eZ2WD1!M2J71%:0jo0re1$u1m11AX18g2DB22=15d0[G0#X1y]1EF0)a2j22JW2K!0'e2KH0i71A>1F^1p)0?r1N%1ZX1JL0}K1$B1!T3KL1=c18813%0ad0W22<&0#20l10@s1z11#r1@10?g2Qt1QM1Kh0;:1cl0#:2N?0nR1^q1j31,&2aF2oW2#:1gP1P/1AJ1H)1VM1+$2aQ2VG1I;1s^0uM0[q0+[2f80q%0@X1r)0&z1O>1$;1JN1*e1nY0y;0$!2=/2Uy21{1^:2kQ1<*2XM1X20uv2840>90}/0:b0?[1BG0WQ1>d13?18e1O;0m^1w/0,42S/1TJ1JU2D/1}$1BJ0td2U]20G2#22K11:;2642Hc2y$0tI0e10'z0m<1Cd0=*0@R1zQ15I19J0yH1u'0$o2K526<1]M1#Y1L>2ji2Fw1g80f!0to3L{0{z1bS2l[1LI2{g0t<0&w1[W2S]0?80oM0yT16z1Qy1ld1gb26[1c&1h)0#L0y72G?2sJ1fF1qJ0hc0v31PJ2}51(t2IT1pX20=1'Q1t;15t2U(0{90wE0y$14q1i*1Du1uO1*&1Y]2;51vw1Y)0{Z1't1]W1fE0;L1Bh19C1W(0f:2E{0$L0#<2cP1)$10&1^!0%A1>B0#p0*01P*1$X1nO2qw2(o39Q0]}1a=24(1Vb0>A2'91Zi0#b1t}1F+1:D2m81K{2Yw10'0ts0q>0wJ0y)0!^1;H1861BT0@+2lM0{52b#21P2r+0/V1?o2Sm0ZK1*@2Ro1TB0<00t{1Xu0xi1YK1?42b91v+2{&2s90uH1Ge1)s0,A1K10xt15a1{#20A1mh1ly1th1F&1UX0][15?2a01f[2k'2q[24x2Rl33o1bF1P61}:0)e21g2B<12B17K21M1JY1mY1Hd0&o1xV1Dg2912#81)81Hg0^:1QE0u#1A526b2FX0sX1Wy1Jt2}u1OE17X1w32#90y>0;(27k1eJ0{?1r31x90jt0@N1Rk0(k1Kl0Z80vv1EQ0(n11n1ih0YG1Yr0;P2C#12H2eE2M/22C11'1]f2/#1Ks0rE1K]1r{0>C0]b1yi1mT1};1&:1}'1K$2Uu1vG0*K0'32ox1rf2(80#l1W^11o1%G0l'2g!0(]1q?2Ag2Hv0/j1N)2Im22z1V72Nq2P$2uJ0ug1XD0ij0pG2;i1*d2DG1uW2k00jF2^>26]1[/0/R1>p1M}2O%20U1:N2JI1mj2hP2!51[C1E81i]0=12zb1AU0ti2=<2Lt0+d0,{2Ms20737n0w]1CB0),1y(1#,1uQ1X11Tm1/n1eo2Sr1YN1,i0}C1C11C^1$i0b(1Hr1dJ13m1L[1QO2/10dN0{K0+i0&61;%2N91@{26&2b22Ey0j$2My37;0cH1hM1/O1YX21e0si1<[1Q}1Ut1?%0lc1*i0S!0i}1?>1Aj0@*2r(1n>2Er0mV0eJ2w2II0eW2M#17/1Ss1ng2HQ0cT0yc0cE1gi1i?0f]0f41Hl2Zb20{1YO2yQ0nI1VY2kO1+V2ke2U[27U25h23(2xQ1>Z3Br1Yc16m0f{0q[0tW1Em10<0pO1nW3H=2tD0zl1EL0>i0A1[T1h}2161yC1il0eq0@Y1jQ0rx0bp0vm0;S24p1ty2zh0z!0^w1?d1iA2Id0jh1@}1sO0qU1Mu1#c2TC1a{1UG0/T0+{0tK0b/1s70Rd0$M0#q1O?2Od1rl2AC0l!0zx0xZ0gq2f(0z;0'E23i2qy1%!1[N0Z<1g41Iu0kL1:n0er19m1P'1&i0:829j2Zy1CA0n51FV0WW1FA1jR1:G1q*2Hq2iq1],24O2Dj0Yg0Tu0TF0Zz0Xx0!;0w*0RM0'x0jw0%e2OG2He3Up2[]0kH0+70@<2400dq1]a19,0m12an1RN12'0[&1Z(1,Q1d82;J1i'0gb0l,1*,0Y$1k^0?10ra0m$1$p1[01+K2C;23'0S?0sD0%$0;j0o{0n628e2P@0h=0v00u;1Sk2E[1:'0ke0we0Yh0yw00,0jp1{a1jz0gW0XR0e21al2/<0>y1>^1@@1op1H+1pN1E}0]w1z!0=t0g*20a2!%0u62a{0sJ0P&38k0z*21(1h&2A[0J&1ed1h@0iT37V0{m1Gm1R{1r'1?81Cv0Z:1ts2301V82Cu1'?0)91?N0gH0ch0PI1M'0dG0jV17[0ik1yH0oO2n>2Zf0j80uT1wK3291mc0kB0e;1E20ae0<&1@)2Ry1@O19e0^?1yB19R1@c2DP1i<0;B1vT2}!0ZG0Tx0K?0wC0RV12Q0m90it0cB0ci0*y0QH0ea0YC0oX0qc2ud2lb0^l25V0;D1/#1S*0rL1}a1(J1A21yk0{p1Ox0TM1Zz0&K1E<15z0pP1p[1l?1U/1I:1w%0kU22K2pt1Wu2Fx2IA13S0h40S>0dI15F2b:1EO0W92GF0cW0YD0vU0p70)%0b31O20lU0#u0[{1w[1EZ0qq1gw0lx0?L1K>1f82AZ1c'21@2QB0W51j<0fq0XP1VJ0kI0',0hA0c^11I0m40#61+g0py25F19X0v*1R)0a+0fA1Qs1!O1bi2]x0/!1t{2C%1UM1^D1m<0!p19I0*42*>1k}0,;0[40li2eO1;^1>a2nQ0vK0oD1tb1$M1sD16>22O2F;2fb2du1Co0Uo0100zm0iI0>J0RN0)}0)f1)N1zB1SQ0R&0x!0TN1I80YE0Ql1F41yM2U!2In0jZ2c@0h(1Z80}O1X,1He1*^2Mm0tT0hk1I#1,028d1s31?@1/X33E0,*1sS2r*0r62KK1pm1*>10A1U;0cm13W0*A0s92()0s41jZ1HA0Zv0(>1AY220x2dt152%@1B92cQ1i,1*Y1L+26M1Cz0{12WP1jv0(J0[=1QZ0n424E1FB2Q12q21(l0&'2),11f10n0s?0jC0sd29w2lw1Fp0^>12/1zT1I!2oG2np0$B2WS2L+0iy0Oo0o*0UR0({0Xm2N^1T?2Is1d{0z82fq18v2CM0]n1dg1@X2IU0ym0R1%q0Q(0Th2A<15[1lo2590/70+10#W2:;1K;2L{2wC1L!0mX0n$2+%0q]2hg0QM0V}0pL0xp13r1K310d10}0](1T@0k$0cX1fP0tA0%U27{1E$1d)1>>1yU0#32>B1,f2u701L]2Fi1;l1Rp14v0bZ0f50:c1GH1Z)1Ex0,81at0;]1>V1A61Gc0vi0Sb2If1570yd0*@1*R1IC1YL1D70/o2K*2me0nU0^}2hN0zJ2d!15x1=L0sq0>n1:h0S;1c40oR1Nj0jq1rM1aR1BE1ON11w1ad3Kt14]0@^0]<20R2Pm1jB1L93KF2m'1VN1QU1xY2V)2m)2Mk0JT1Bs1GA1I90zI0j[1[J1D30tJ0,e0wb0zh2oH10b&1C$2gL0>41Nc0ud1Q(0s50*B1VR2!S23y2Wb2ul2kz1Gn1]:2qp0#=1k;1I+0rG0eK0X,0R?0af0ek0eO1sv0?k1av1$g0!w1A{19U1N<2P;20z1#82+U1+c14:2Iz0<}1]q0IE1H}0L511P32w0ls1582M(2pq1[f01!W0rH1ZU1nw0sN1X#1M00qm2U^0x<1M@1?^1&1xP2&N31&2bu1JZ16T2eW1pS1&*1{d1!90*i2IM23h0U+19i2f<1bU0r&0&21Q:0rg1AR0x*0MS2U22tn1Hy0=E2xe2^(1oh1n/0gx0}^1c{0se0>t1)42Uf1A=1MG1Og1901f41,=0,f2g[1a}2#/1D>2QQ0hd0=^00xu0yJ1*j2J11x:1%m1OZ0f$1>S2IV0<628722m0;#0{h1a814=1t(1n:1Cs1Zb1DH0#427Y1g>12I0qK1D=0'=1*U1S(1T{1rN1Fd22k1U02GN0or1ea1150nm2Rp1#b1$22M[1*'0^M0^O2q^23E2y'1Ji1xJ1^]2?*1fk16u2Jj30%1F81*t0121Z[0d]2kE3RH1Ps1Kp2UM2171L#1a!0{&14b2o!2YA0p%0?u1OF2?N1}71J,1'*17,11913n1Jn1EN2@50+u2GH1,{2FR3S>1r[1W!0f&2LU1UB1lN16O12Y1$c23A1Oc1>j0pk1fJ2Nr0Pt27!1wk28v1(Q2CF2jE22h1{u0p80*U0r10[k0il0lZ1y{1z'0eP25m0U^20q1BH0Q/0=]1#X1eF0up0l81W70ib1Ay0[@0]Q19&1gW29V1[e0*o1d71[G1)U1V$1v)2BK1^[1Hw1YC1[(1mH1Jp2Q91Yp2222{/2UQ1OG1i&1j+0sv0ui0t41UH0{k0%M1qk1pk0?Y0@80{a2v/0)j0WO18m1jm0]W1k*1M[1+]1{K1<,1qP2Y?0?}1NF11}1{;1i42Mj0<91Cp11d0<+0,#1H10jd1gk2El2qD2R;2Tn1HJ1%p1FW1X'2q91LA1bx22G0Ty2LE1'50Zi0^$1FZ26r0%{2NQ1,'1de0y<1ev1Zm1Lk1QR1#G1z617f27T1tc0;C1PM0nO1hj1nQ1go2ft1Gd1Tc2%]0rd0Z?0S&0i?0v(0Y<0k50dY0ag1Vl1!E2J]1wa1Z;1#g1y%0kf1)h2^/0*u1mn0$H0j93842a22kR2S}2J<2DI1ys1(E2eT1dL2++1S/1cJ1Ap1Y+0%%2J:1!g1X80131no0[(0a[2h?2we0he1jq0=i0&30/[0nn17O0:m0@=16B0@H0+*25O0ng2Rw1=r2N]1x62^d1NJ0r92I00*E0i+0wQ0!k2Jq1#?2G+1C90[I0!M11i1}]1:31wE0WS17(1;F0zt0Zc1R52*b0hJ1sH0ZB2C<0)Q38p1vq0;10&k0+40}11%Q0tB01S+2L:2(41&m1Az14m1242oo1P+0*W0{F1LS0/h0vf0,/0la1!B1/42KO0sF0s72fm0p:0wj15926z24z1kc17Y1:513)0:X0sw0nS1sb1(h1K40cd1ER1*21?{0l+0Rj2le20}0Y%0}*1&W0X?2H,1)60o>0sx1(m1c+0,M2$I2!q1Y52K]1:{1]20d/1'#1rW0wr1Do1KE1li1p822j0m*0qg1DP0%D0SC0o41z)0rQ1s00gR2mE1mW34A2Vh1;O1Ba2+o2P:2@A0zi1HK1Wh1gD1K92n/0]&2$A0p}0pb1mQ2z#1GW2qV1qB15A2sd11=2VL1JJ0im1p00;{1zN0qs0{[1q!0$e2Ri13o01@]2EE2%m0%}0=S0Wg2K&0$z1R?22LV0pp0($1Xn2Ch1j=0$d0zj0}80l?0<:1*f0wz0m[0e!0&Z0[M14V0/H0tX2CI12&0(M1N*19!1^20ru0r<0c90w#1/b1K=0ph20*1iE0R'0dL14}0v62Bm0#$0#g0o[1{]1To1LL1D[1H61L02[E1LV2Hj1G{2Wh2#m0;f2l@3M/0x72Aj0)E0,p1;42oA0Kj1hK0$s0!20tG1](1ni1*l1&+1KR2*=0qS0gY0@U0*P0{>0&i1E!15&0jr2S$1+I1I(1Vg0[F0xP0?61SF2eK1H@1Ft21$2C:1J920u16b0(I0t,0@>1+z11L1BU0w$10N0Xy0$21xl0c'1J81oz14h0+Q1]i0rM0)u0h[0b413T0+C1N!1B#10q0tg0fN0yi0{Q1310&r0n%0=Z0/e0q;0'y1aU1vF20X1Uf0kJ0#Q0YA0d@1o,2m31Xc2Q22n#2S%1o@0+M0ty1v]1NK0'!12u2yb1dk1Wj0rz0,i2nO1rZ0z(0qJ2gd1Oq0g,0wR1N]2Ji0:h0ig2cW2i%2Az2CQ2Qh1Gv0[)0$30&Y0sA0/Y0+H0;I2Ph0!314K0]B1Ct1Dd0Re0+80U20}e1gh1^#1hO0$?1y@1F;2EL20<1HV11E0gc1]60*50ap0N41W;1Rq1E,0y40T811Z1+/2TP0]k0(,0Yx0?x0>f0ub1T>1D}0/W0gs0}b0m:0aq0!H1s11or0k!0$/12K0Wk1uZ0)W0+D2GU1#w0tL0Rz0?F0St2o^0w%0Zr2Zk1;{29u0$f1)92Zc1vU2I=1&^2h)2J#1jS1$j0yA1f/1Q725J1p@1T40,T1'h2xw14#2kr0!u2vc1]D2H?0+l0sk0)v10]0+v12c1Fq1?v0$<1Tt1)&15b3Jk1D10&N3Av0v81/g1QF1=j0^R1E01,x1A<29/0VA1QS2R$1Ei0!I1Ln2JQ1iB0<0:&1,U2jp1=40!f0UQ1B11^u1970?V2DA0TK2gV1Go0H{0,:0nC0UG19*13M0/f1Pb1GX10x1'D0I[0es0sr0Rh1GM0}Q1x81500e}0S*1@Z10I0141De0j^0o;17g0Z/29225/0NY0=T0Xc36G2Ln1+}0eb1O=0*G0{60h81Zy0zz1(V0IB0ov24U0/Z0{u0g&2a^0w?0Z217%0/P0+s1oK0^41ak0)!1f<1)q0(L1wS0fO1t!2Hh2J;2F&2f224Z2jY1x?2oZ1GI1Pw0/:16f0+60#v0S10jg1hv2@;1lz1Jd2G60hi1^n1/K0ce1[u2DU2g61X+0n{0[D1%/0MG11:0sY0mb1&v0W!0Nu1{,1A)26H2Nu3S=1Gi0N#0r*0;d0^{0#h10)2G(0i81Lb1rQ1e$28X2FM1er0Y>0Yy0,%12bI1930Np0?#1e>0O!0oE1B517o2f90h@0]l0Tz1xe1NY1t92P233$0@;1Yz0%l0*;1R81Sp1$H1x(1+%0sO0(?1lK0ul0N$0aV0gZ0pr1is2e;2Fo2bz1%?0oJ0Z(2M51Ng0^&0w^0R*0V&0fB1JH0+w0,q0^J0L60]m0Tw0Wz0bd10?0rh1B=1Vs0#i0}h1kz0'f0:*2:<0ww0t&0dx1s50J,2St25e1'g1hZ0(80z}2wZ0)n0+;0q90oA1sC0Wt1Ha2oi0bt1V/2@10?y0wM1Q80gX0XD0o00nG0>@0Xz0kO0+y1c%14$1AS1c#1Y61DB0?$0vy0X+0Mj0hR30312g0=[0P{1i[1jW18O19>1EK3380ip0XW0={1mp0,P0qx0qL1Za1i)1q)0v41i{1GY1Zu1oa0b!0LQ1o!0T/0)G1E>0mc0=d0W?0P>0Gc2J20*v2uv0Q10[r0wN1U70vM0g$1Km1Kt0n>0*60f80p>0,b2A70iM0G2C'23t1CX1s@1<]1(U24{1&[1em20O0]Z0,c0oi0h]0;U0UL13;2#A0lV1]N0mF1=M1i;2G819A1La0%'1>21R[0%50vJ0&x0@L0lv0UV0uW1<<0de0PU0^51gL0']0th0UM0#T0iX0R/0WE00't18F1Ms1V?0*s2lL0UH2Al0X(0^/0o10Pb0w&1h*0KX0d60ji1Fk0P40>*1DD0WF0Q=2sA2s<0%N0c10uG0#@1Sr1[$0Zw0lJ0,L0xn0cc0:]1cU1J21oM0um1pb1h81N[1Ny1J41&j0]01LW1m00X@0k=0=w0V=0/51BX13B0Hl25c1VT0fr0XB1?T0h;2k81b411l0s>1qx1w<11j1HU0ma0!T0J%0Gy1PY0w70u'0$'2fA26>1kl18p1Ey12[1NL2yD0^912V0lz1V[1@E1Lp0b[0k%2Hb1K01Vm0+R0oz0e)0n}0t50VW1^j0W60^A0hf0/r13U0/?0#,0tP0Y&0gg0]r0aF1IU0#k0X}2:'1nL0yW0n^0=N0=(0)A1L$1('1ro0#w1Lx0=p1'f0@q0I,2bw2OS2'#1$31r%2fe2T$1Am0uw0n21kx2vm0tb1sd1;21E]0zQ0^+1R*24G1ig0^C1O60)g2JX1im2+v0j20,U1Na13E0n)33P1'w0pD0Nf1?Z0'r14<1>H17j0n(1lr2ir0RB0;a2CB0^m1Pj0yo19F0<=0j&22<0W@1+X0t(1uF1ZW1zo2Xc28m0*20s;2ya1iQ0#!0!?0w>0$J0>(1c90l00<20?]01A/1SS0U]1N^32Y0i<0j31za0bG0b}0{C0/c1%[0aL14S0Y71630:#2[40]d1Up0tQ1180/;1BQ0!81F$1>t0ut19f1W?1y=0)B0>)1=m1!F1)T0wk1)J1vs0;b0zX0iJ0W#0qv1IF0t737h0rU0bN0X$0#?0h:1:U0[h2^$16w2IQ0YU0eQ1l02}i1Nv1X)1i!0>T0&u0O50WA1td0<*1)H2c81ia1{B0Xq0RC12}1a:17h0ol0Zt0V[13,0nD0!E0ht0]e2$/0p(0=P2350=u1IG1@#0>b0hK0{P1Nf0jx0%x0k00Ui3C>2{>1oG1}I1+e29A2FF1PB0]R0w)0)'2e531v1U}2X70E}10:S0l20MY0m(1l#0^Y28k0y+0Wx0s&2(N0eM2to0'20>P0'>0*L1Jl1c(0:(0=}0)k0X51dl0=e0mC0t00*q0op1#N1wW2?j2=H1tp0vq2%c14Y0>51@g0b$02L813v0:21V90&=0!$0v11RA2lc1P=1^'1g{1yP0e61NE1C=0:z1f#2eR0sy0r#0=k0vc0gS0:00{f0B%0Tm0GH0YN18w1S80<;0*$1CY10/1AC1pJ1M#0^h0;X1nI0]h0jM1dS19n0%41cA0i90at0c=0Wb0P,1RV0@b0y@0!r0X12A,2N{0fP0yR1y30*d0(x1V^0Pc0*a0S(0L?1Bb1}B0?,1E/1S=2rB2O+1!V0/&11p0&P0r+1WB0yg0!:0[J0WD0ec0PS0dA1QV1TZ2Wt1+q0cN2im0Vr0Wl0%W1WJ1,r0w/1v!0h^0,V2H00s*0c60hE16$0le0qa12C0r(2O#0aG1ne0tk0xB2Qk2#I21q0r=0@u0pd0xc2h<0$K0Wp0LS1Q$0u*15@0l<0[01J?0w[0nE1$/0D)1ae0Qv0rn1<30f}0so0(51s<1Oj1H<1a&1Qm0Kv0$60l)0>Q0Zx1dD2A10g{1s>0b:2SY0df2tY17y1pf0;921:1L;0w31BP0kv0Uv0a;28@1Ej0dg1^x0?30dR0fs1Bi1Ip0eh0/@0>w15f1DE31s0Z)0xJ0z:0sI2EJ1Mx1wX0'H0!N17J19O2JA1(S1O!0'D02QV0yj0CF0Wc0bq0mL0C=0DO0T)0L;0P81p>0QZ0O'0U&0hx0g;1pD0*:2a70}y0el0/S0os0pX0k318P1ft0%<1>g0X^0v,1S42KY1uK1w^1G61fW2I51dT23k1l,1W$2oP1Kv1)R2V;0U*0&U0,B0+E011!0P%0Vg0g]1fN1420%71Lu0ny0#N0+00$>0Vy0]D2Mx1>N1)%1H:0;42W<19:12L11DK0=q1;I1=D0WT0g82G$0Oz0PJ0OV0%/1X32ex1J<0m]2DC1mP0)?2yC0NZ0Xn2pf2I)0nz0sz0c;0Qx0M;0oj0%+0O{0U?0NW2R<0qw0sK0#%1eY0m,0n/0bO1fc1!G1on1Nt0+A1);0ie0{]01615N0v@0Vu0Pv0Wy0r70jN1Q@0O*0gA1e+14Z0f%2XS12R1M,0{{1B!0)#1tz1wm1QI1ib0)y0D0iq1LQ0cz0z22d,1R/0Em1n32+<1O(1LX1I00wf1gN2{60b70+F17M1p90/i0e/0h#0!j0^72L71?w2Ml1K'11<1K}1Ah13h0]:0ux0u,0>G26B1GK0y]0>#0:I15u2UC1Fj3EY1KS0'O2U01kh1ao1F!10J0&H1Ff0@n1A70+j10Q0ju0aO1qr0Pj1710T&0xz15'0mQ2pF0NA0Z>1F[0Qa0@O1$R0kZ1A80ue0#c1ix0hg1Yh0d^0y^1}K1+=0lO1Mc1S;0(@0sG10k0[/0,}0F@2@p1m+0mD14P0di0Q>0>60!&2Ds0jk0MT2h:0Hq1gO0Xt1zP1Sv0#A17F1WK1{b1ti1ZJ0#I0/g2B60d123l0zR0=B1Ii0V?0}F1wc2k^17]2sF0z30[90>h0+S2L}1f*0Ru2CR1]O3Cw0!z1P@0$X1%D20(1Jq1nd1VB1b[1M:1DM1nE1Q<1a?1tG0h<0pi19g0#50jl19z0WZ0=f0XG0f*0[T0OH0K^0pe0#{1Zq0VM1rp0u40]11Iq0z]0R:0>o0O>0a30b'0QV0y#17S0;0Ue0u!0?J0]s0w;1]L0:f17A2Em1g^0xR0hU2x<0QA0uX0#d0@)19+1mI1EH1@(0^r0(l1tS0tc0q021Z0v0F,0X)0k?0;'1;60:U0qM0[l18#1(y1C60ZY0^Z1%c0go0iC0Nw0j/0YB1Kd0fK0kd10$+0]!0I<0fc0cJ2Gx0mM0jS0uY1VK12W0rf0pT1K+0qd2MH17B0tu0(;26*0lh0,^1DQ0UN1cB0f317}1MB0/+1rh0Kq0Dm0Hm1hf0T?1^70'+0*80mW0ei0&y0du0i)21o1bg0V41&80ne0]z0Z^1'M0PV0y00fL0Uj0i#0zr1Ux0;O0%R0@V1X40Fs1Y{14[1AH2q0JQ12M0q&0=41cm1KO1lD0!A0L%0ga1Z]2O?0=$0^S16X0q<0o:22I0kR0Pw0Pq0Qw0Kr0Jb0PE28M2H11la10t1#40o!1+x0ZH0;?1Tu1iG1y$2nA1:s21]1tm1{X0f,0Gf0#K0Yi0P01[10rW0jy1Z@1Nn0aC0ed0oc10f0Lc0Wn0KR0,k0Qo0;k0oY0p#0y10ca0v#2Me1M1HL2PX0hu2(C1zW0AJ0MQ0MN0)h0c$0R(0MC0L,0MH1Qh1SB18}13d0qr0yx0(^0hj0Gk0YW0fY0=x0#R0+p0x?0kP0]t0LZ0MD15E0bD0o60G$0$g0]E1a)1x*0UW0X:0iP1wO1k?2N[0Fe0%o28L1aG1et0lK0bE0m{16J1B$0a&0LT0J>1Ci0UD0R50FV0c41J$0rO0yS0Ln1p40r?0Aj0IN0SP1wM0If0vN0/U0m)0K;1cV0yr1%21TR0K90+G0nu0oT0ws0g(0VV0@d0q71A(1,C24y1,!1ud2Px20J1s,1=G22X0xK0Mg0tj0EI1Xr2ra1uE0?21KI0zK0gF0jv0VF0aE0gt19w0*k0r)0P$0F#0VQ0Hw0Jm0Px0La0iR0H!0ih0vO0Z@0dP0rb0qP0cC1TC0?X0HF04u05#0Vj0Jf09}0AE0}o1Bm1ZQ0W/0dj0}R0)61UT1&r1#j0hZ0F]0N:1/a0P10iv0u00ba0N@0Bu0Oa1xr0qN1N626w1UQ27^0U@1720xo1771OR0/80!}1WI0=513P0$m2^&0xW0]U1Zh1V}1y,0[y1Z{0$Y1^a1r=0)o1Va1Je0sZ1J@0@00p^0a(0Ux0j*0{41k60gp14n1O'0S{0WR1q'0x/0dO0rI0g/0%V2Vq0xl0jO1sT0K01g/0Ro0Y?0/a0S@0R11Sc0d=0)H0><0Q*16,1Q{0YO0bF1An0US1ip0B:0B&2GE0E20I60[X0JX0C&0x50zu0@30VC0cn0MO0IG0b,0FK0ML0TC0JL0I20PC0d,0dk0HK1kd0RQ1Ur0^H1<=0yD1^}0E)0qC1S50)X0+%0p=0/30+'0E:0dT0Vp09n1Sh1rz1zs0':0Q{1#P1{S0yt0&V1081SZ0jG0g)28g1*v0lp0}p2de0Ou1PZ07}0=y0*f0uj0xE0SW0a{0Mx2a=0Py0Y112*19[1x40>;0iz0kp0{i1oU09(07#0G]0,$0I#1%%0Y20{j0qn0QR0B{0VG0eF0y{1ND0Hj1:P0:P0Hd1HO0M/0T90a/0Yz1qj0uZ0I>0M(0c!0)b18:0R82a@0ZC0An0Zj0T;0ZJ0cD0tq0y!0ge1Wm1+J0k{12z0t[0bJ1Xq0}m0;v0m@0wl0<)0jK0oq0w:0<@0PZ1Gl0}S0;Q2L40Ib0R)0j]0Jp0r{1q+0n00m30s[0Y'0WU0fI0l[0?D1@S0g50kD1Lr0hr1q60Up0u70oN0QF0,I30U2Ot2PM1V#1?r0/p0tY1o81Wo0]G0[a2u12B>2K00c&0O21P70D02=80Xh0jH0r}1:^1H70e:1fy0G?0AY0Ol0B!0IX0k[0T21^r0m70e@18z14g0P+0>V0a,0@90e'11C1Gy1821(>0z,0yM1,Z0et0!l0/,1SC0kQ0kq0&B0:@0cR0r]0?:1R(1(b10C16x2N!2IH1u60vr0i,0jT0iY1k02c%0c20Xd0$51d?0K10,)1GJ1m&0zS0O90FD0S30g02n+0!X0$,0IY0M}0Q80Ve0Pu0r@0v$1aF1iS0*z2L50[+0@o0a70Oy0uu0h'0QI0NL0g90)q0bQ15g1u[1A&0[>1^K0ze0>B0tw16}0=V0HZ0ka0B;0K'1)+0Eb0bT0bH0Q70$90<<0aP1sn0MV0M#1L:1k80oH0]V1G'0TV0?P1Om0h/0mR0wW0@&11[0:B0s@1E*0eG0VT0YI0p90ZR0(b1ZD21z0jD0@e2:e1:T0oe0$0LC0W:1CQ1q70QN0a60?A0(E0[d0P20mA0YX0Ff0Nh0Qy0P}0a@0g[0U/0,C0H@0k61Kw0CV0EM0ou0l*0U30S40SO0ET0Ks0VR0T,0Io0tM0AL0Q?1f311s0Vk0#U1N31!=0d80YJ0i/0h)1l@0X'1q21I&0u<0N'1c21FH0E&2Ar0k;0Gb0ZS0Ci0N51B/0H}0b>0D?2NA0n?0T32Vy0W^1Mi0e+0r'0'41QJ1%r0r$19P0^01G:0R90;E0@y1u$1Fe0bx0d&2J[2Qb00K20zA0;@0Hx1r00ZZ0l@2s81AN0C!0v{0Q40{V0T*0u/0Fg1F<0tR1rO0Ec0fl1cK1JQ0Z,0#80zL1M{0}q0{E0mm1pK1(01Jg0iV1'n1Cu16;15/0Pf1eu24e0k^1nV0)70+Y1VC28b26s0{w0z?2/J0P=0XU0Ur12t0V{0Z{1E+0(h0Tq1220be1JM0uU1PN0:)1PS2c(1FE2W]0Q219G0Qp0e#0O@0/00^u0N[0Op0p)14i0lG1?20qi0nF0k/17V0yY0;/1pH18j1B60L(0kV0n@0kG0Z$0aH1ay0n&0pY0n+0BZ0Ic0@j14!1,0PH0ct0IK0gn0Z#0>x0o#0'(0YL1lj0Wm0Gr0o,0Zd1VO1[s0U}1>=1>U1@t1b90!B0VU0*{10g0*'0]]1p,0kS0qy16+1%$0Rs0o72SJ0(i0=c0pE0f?0/90T10bA0cL1CG1Uv0kM0t;0'00lP0Kh0Zk0U90HP0OW0aI0dv0C>0FP0Ey09;0Gs0Dy0J70hD0e=0l/0xU0uc2mr1^g0yp0+(0v+1^d1RH1Qc0ZT0,50IH1MD0Z+11x2Qn0#e1q02Dc1KY1i20rP12m0mI0sp1U90en0bf1E%0$I0Cr0?90xb09614u0HX0LM0!K0H#0fZ2?q0IZ0Ee0C$0M70VN0jm2TR0t10rc0p50?a0fa0a*0?B0OQ0HC0K#0F11l(0Ld0:'0vW0mS1+N0?z0>?1FT0C221*0J^0Pg0CY0Zs0?'0?70>g0d*0i>1Ce0[U0wS0XF0b]0e,0dU0U,2fg0KS1YP0WB1pg0X70fp0F{0{N1T;1Xf0@l0$11v30yZ0p&1zD1M10O:1ZR0e[0:,0an1aw1OI0un0uk0vt0cw0f)14'2411X}2LF0*H0}c1Zw0g:1451051Us0H:0bg0?b0B*0yu0[w0!x0*(0s]0h$1dh1+<0qW0ej0rV0ss0nJ2LC0xw0TP0R215k0V00TQ0S)2310R,16?2q#0j40Bh1Ki0VJ1X(0%F0q+0:j0}20p10:Y1(20He0rB1I)0WJ0xq0)M0SS06T0h01q/0k40NM0H'0PT0W+0aR0SI0Gd0Pl2hK15s0QS0FX2U+0+B1Xy0v^0'n0?t0dl0ys0/s0o=1>T1H#0FL0By08c0Ge0Ls0@B0Uy0^n0lq0#B0<[0nK0?N0l#1JW1Bt0VS2be0g}2Y@1/z1Rr0@'0Hk0ai0o81mF0Cj0T:0ZU1Q%0Ly0E%0kb0e00Q^0TD0YY0Ii0,&0170b@0S20dt1ir0?H0l%0!O1o90:J0hL0%Z0o'2I/1Bc0ms0%!0nb10p16t0lB1fX0#Y0$C0f[0)C1,a0=G1=T0Lh0@@1gF0aY1RO0q?1Jj0x+17k1>l0sB0*X0=a0F&0Y,0;m2VA0,t1kj0[s0zY0OX0a81n<1wA0l]0dm2/&13L2r10X=1#@0/O0UJ0fh0pm0=<0ZD2y{1yz0x:1]j1Zd1Ra0+N0FG0Z90Y)0xm0V11b00iQ0q^0ry0u%0?>0WK0[50y80p20t=0t]0u82=90=)0OC0OR0j=0W%0fS0Xi0eH1FP1F92o:1u01fV0dQ1P,0(21Uq0P]0j51(e0TE0J=0Wr0sS1dp0@W0Om0eR12;0GV1/c1Eb0W)0jP1U*0Z'09y0hM0&s0Yn0S51b<1GP0'I0Lv0DT0C10Bf20P0Un0P;0D&0TA0BA0S60L80$u0xx0H/0Qq0N{0'Q1ei0T(0rJ0=A0gN0Lw0YQ0gi1co1]$0q520#0ha1p20Mh0Ep0OY0+)07,12h0L>0M00?=0wi0++0Ua08N0TH0Zl2WO0SL2/A1%O0/m0U>0xd1fS1Ij0/I0Yo0Rv1VL0g11E(0c/0i10E*0q30JY0X[1ec0HG0j?09<0nH1S)0Fp0rr0i]1!r0Pm0ua0Ma0da0tC0?40Bi19?1TH1zi1G50q=0cf0c<0aK0!@0180Cn0Vl0;J0EY12N0J}1G#0dn0A:0)N0Rw0UE0s10c)0uy1Al0V;1RI0Ti0K30mj0qQ0ki18>0+I0Ka1!L0EJ0O61PF0M&0=l1=90wx1,$0cK1P;0Za0Ix0G>0Cs1DR07(0*/0iF0{W0j<0$h0w@0sa0d}0Ps0Xj0nw0aZ09G2qr0p*0F$09)0S+07f0h{1be0Mq0,[0580hn1]X0D!0bu0j60vR1Hm0e<0d(0tD0cM0Kz0190v>0%T09f08x0U00LI0Eu0c>0zB0j+1Nh0cG0nv0mN0vs0'U1DW0n30Pn0ya0QO0XV0V:0Xr0FY0aU1020*Q0w90LD0iK1{V0@Z0]?0mv1uj0;00LN0Ca0dJ2]c0FH0u>0d!0GS0VO0a=00o}1[I2D]1H,1m!0hN1J60H90L)07P1G$0Jk0<>0Mr1HC0E40vS1aY13F1rH0b%0aW0Sn0Mb0Jy08V0C+0HR0x^10h0hO0Uu0T'0V(0S=0RL11m0sg0oZ0tZ0l>1ED0/]1610av0lj0'50MZ0=%0ez0v50wt1n90F62WN1EX1Wg0J10bh0RH0bU0Ll0je0JR0K%08k0^T19Q33>0NT0G;0So0xS0KF0Al0Sx0(S1ob0qe0XK14r0jn0p01b;0rN0=I0I;0h10(90sC1$90o/0^30n70)^0>Z0HS0Sy0r21&d0Sc0V20V,0Ob0Kt0;g0Wu1w@0yk0Uk01A0o90s#1Z30%=0G{0eI0GT0HA0;20!S0)I0GF0W[0l40Ns1VP1Rx0T[0G%0ni0p[0'j0pV0%v1XR1Y#0?j0pK0yq1&51/Q10u0fC1VS0G80CG0<'0B)0FO08l0E'0Q$0LW1TF0[}0(j0J;0'l0P!0X/0gB0hy0Yq0Yj0Xo0Q+2AA1:t1CC0U41W90c[0(T2df1K*0J)0Ef0*R0mn0;s1TO0Lk0Pz29f0Mu0(y0wu0Yk0r[0c50dw0m#0wg0pM0@J18n0D,0,O0Wo00qz0R{0CL0Eq0Vw0VH0Bm0KB07N0%@0+=1Nq2=C0iO0Xv0G(10X0Qk0Qg0j)0zs0fR0>c1550Fl0'k0!{0ks0I91Zx0^80W'0fQ0)30i&0uN0dC0wA05o0hX0ar0p,0tl0[O0?v0f+0u12)'0Xw0Sk1#;0$%1iu2dF0dV0VK0s{0E,0Tr0X!2Z:1zd0A}0TG0Z40i^0HU0/t0DM0Zp0!P0)r0Rk1XE0F*0oU0&W0q10B80h}0Z%0'c0,d0eD1Id0Oc06h15]11]0gI1y^1F00)813Z0{@0kg2AG1Vn0}%0=C0eo07Q0y'0%20SY1V&0A20n<0H608y0kj17p0+J0!416G0UY0X80VX0^t0]*0d209Z0J<1+Y0/60Gg1/;0Tv0${0v}1Y$1$A0@/1#A0QC0Lf1Fl0g!0zf0P513a0b80fD1:w0EK0pN0nQ0vT0mT0H21w50no0ZA0uo0u20RI1Wc1ZK0Ms0bW0&80uh0Nl0B,0PD0EV0ZW0ft0h&1/10D80V)0C)0sT0Uq0KU1s=0K$0JJ0H50&]0mg0hH0DE1Sl0C'1&e0{b0d'1gX0Q!0MM10L0+#0mJ0$T0vH0V<1Pe1Tw0(&1W51GN0ep0H[0YK0Vb17q1/Z0?!1cp0dr1G/0&,1hd05f0U#0/y1rb1ct0u90j(0=Q0&%1A!0uV0Kb0do0GK0L40ic0B}1!H0#}1pY0C30F70990x@0$y01B1}L1GR1MW0Rx0Qj0e30&v0db0$j1u70c+0k#0fj0RR1R90id0l:0>]0pq0T@0wL1bG1=n1@T0H$0J80R[1JX08E1Pl0a#0/(15h1{D0U70zk0(#0SF1xR0Vc0NU06x1EU0U(0bb0S70+20lH0;$0sE1[80s:1bh0om0XQ0(:0^i0F80E^0N>0Q)0Nm14k0OS0<]0@!0{'0e*0)F0]/0Nk0&&0Wv0Yu0OG0Jc0Gn03m0C009J0L90G90Ju0G30Ig0X>0Vm1AT0ds11e0a}1C20+a0R<0*S06r0C]0780Me1a20Vs1BF0VL0NI0)O0h+29F0{q0T#0vd08v0RE0e70LE1Q+0C40J!0L+0890E50ZL0}+0L}0Ag07G0Cg09^0I$0Ai0%B0Dn0Ww0Z70sP1Or0%X0^U0ps0Jz0Zb0yy0TT0O]0V60sf27V0gl1Md0%Q0q{0&J0k70+30)s0WH0hh0c00#Z0Y90n:18{0w51QK1Nz1I^1?D0G:0ox1GL1Dh0D%0ex0To0Vh0IC0]50I%0Of0#j0lE0d40G/0Lg0J60]N0f90Il1/$0Ew1[+08S0ff0X<0z@0d#0Fq0Hr0i00Z00GU0T$1SG0?{0Mt0,J0}I0ee0ZM0$^0co0?%0st0m>0A)0jI0>:0#S1IV0UO0lw0q'0%&1F/0G}1m{0Ht0Hn14H0HH0L[0,10??1c^0Di0LV0l$0W]0;i0P315!0Sl0Og0Ie0S$0JB0M40OJ0Xp0CW1F)0Br0EW0AZ09a0M=0IR00a)0WX0bv0,Z0TW0$&0ZN0)l0Uf0%G05u0h%0Ml0S[0Q&0Ke1670v;0KV07)0Hg0M80iZ1Ow0S80sV0pt0Sp0F21>:04l0TZ1pi0WC0]q0gu18S0!U12i0y61[>0i30rS1^30a10!50Uw0O(0hB0nq0s$0t:0<319@0al0r30UA0B^0oV0M90E$19S0JC0j>02v0L105D08W1&}0dy06M0802Go0my09A0SH0EU0F00eN0Ts0Ws0F90Nq1910gU0>K0#V0JU17?0hY0t'0x60k10?p0RJ0W,0TU0U{0nZ0/=0P:0Tt0Qn0#[0q#0K,0PF0fU0IM0r:0{#0gO0rs0+!0W00,K0WL1p:0U51H%0Ek0Pk0Cu0H<1Fm1h90Gl0i*0BR0[L0Sg0*%0o]0fu0if0lk0PB0F}1]I0y:0Iv0?m0XX0f@0}<0Kf0Bg1Oz0NR0G'0x40Iu0GY0QJ0;50zM0f'0nr0Lx0S}0O,0u)0of16g0oa0CT0A@0a]0Mv0<40*N04D0A#1Di0Gh0G)0cY08L0gG0>00IU0[K0c?0G<0Oh0rw0Cb0C50is0PK05407<0A'0ef0IS0Da2890Jr0+K2xC21B1=^1}w1Bn1RR3I{04=0Jg0kX0Ds0u30ED0UP0gJ13310>0RZ0I:0T^07T0Gt08m06y06,09z0OT06009u06s05K07[08508F07H06@0j@0A&0OL0E@0B108204V03h0Bc01C03606t04I04306d04T06u04z0Cv06n0W&07$03i0R%08106z05*07u08X0B[04R06i0Mm09?06*0410FT06W05S06N05T09K0D10CX04K0790EN0ZF04f0Cf0DW08u0A807%0fv0C;0VD0Q;01D0%w0Q'0mo0GL08J0SZ09[0o<0Q[0!y1B]0!90pC1160[o0=D04v0BD0E#0bo0Gu0SQ0YM2I]0Go0E60xe0Tk0rX0sQ0O70K&0AU0D90E70G^0F!0Ej0920s!0ns02]2N711A0Tb0P90bI0QB0Oi0n'0@z0nN0e(0ST0jY0+f0500E30X]0HD08q04}25x0GW0eu0VE1$k0Ij0A<1Cq0W=0X%0H%0Nb0z50Rl0HI0hC0F<0m!0IA0590HL0BU0XL0O)0GO0Tn1gE0V90Lm0H70PX0H>0Sm08h0B712T1%]0jX1=y0LA0Ez0Cc0O00470Fu0N&0CJ0GM09@0CK0A30K[0J91#i1Av1np1Ix1SH0K509R0!%00FW04;0C?05a0e90J/02t0Ba0aB0C[0I&08@0m}08T0Iz0AS0L@09L07g06j1K!0Vx0vw0SJ0JV16j2dQ1ym0}L0iS06:0Jh0h!0^a0w+0gw0X90{80I?0g%03G09t1*n09:0M:1XT06P0CD0Z}0Vq0E(0W*0jJ0Z50L*0W<0xF0Gi0IW0mY0DU0U=0P60U$0NF1TS0yU17i0Qc0B<0Cz0*?0k+0AN05704a0B90o$09T0br0Qd0P@0Js06Z0D#0Ji0Iq0WM0/40D306%0rD1cn0*}1b@0gP0Kg0PN0d{1SV0UB09M12U0gy0jE03z0MW0J?0T40390Hv0=b09O0j70HJ0NJ04G12r0OO0,!09H0740CP0Ak0Q@08=0L#0Ph0Je0Vo0950tv1c*0kw0Z=0bi0Gm08P0)t04L0LJ0KJ0G40yz0Es03(03,0w20LR0Ax0EA05y0i50P(0F'0nB0oB0BH05V0KG0E/0ZO0Zu0QU0E[0O}0Hi0Tc0J[0R30DR0Bt0bX1OW0BI0D40bK0Co0Ia0UZ0D^0i:0SN0H31a504x08M0Bk09$07*08d0Dt0WV0X;0DB0&+06)0JE0I10c708B0h?05g0*O0&E07Z0C{0Lp0<50:G0(*0T+0Fw0Mn0I*0480Sd0Ck0y(0@K0o%17905{0vB0V30/10Ys1070E>08Z06605}0%f0Ao0M10GG0FE0B?0Bo0RU0Dr0qk0sc11(1O40Ja0O40GQ0CA0DX0T}0c{0UU0330FF0E+05L05<0W>0HT0cq08>0r,0ao0H80D[0Y!1NV0#r0AO0J@1CE09p02M06C0ME0uJ03W0Lq03n0S<08*0750V%0QK0Bq0TR0N^06B0My04<0VY06<0m=0Ug0Dk0bP1IK0Hz06(0MA06Q0B408G0Yw0n108i0Kw08C0)/0)c0L]0!#11V0D:0@k0I70O#0HV0JW0mO0s20%H09/0TB1830}n0KH0OD0Df0Ab1Ie0o20(A0aT1T&0WI0AT04j0i!1d90Pa09%08#0DF0GA08;0H40WG0Zn0O$05h0O80:{06>0eL0LK04J05c0N!0Kl0860D'09S07?0J#0IO0^K0M'0Uh0jc0KD0NQ0jL0q*0(/05W0v&0[z0bR0hP0}u0dp0%O0w'0Ye02w0m006707C0A,015R05i0BM0A$0PG0{D1Rf05'0Vz0J30oC13z03j03C0830N*0Bl0I404$0I(04&12D0Dv03Y0Fx02G03w0H+0M,0h30N?0Ze0,m0ZP0WP0Rg0X00uC0M]0P/07h0cv0F30e51fg1Br0DC0hQ08706H0L707l0$00Hy04)0K40460Jj06R08z0fo02102J01s04:08$0Ed0RG1Xw0Gw0Q31Qk0b00Ik0PA0Kx0^'1mX1Se1Cf0?+0ii1170h>0hS0C@04^0Ub0Yl0EZ0610Q50DG0nV0ER0N}0DD0Fy0Dw0+50UC0Ar0Gp0*)0NK0Eg0fF03H0490W(0HN0p]08H05M0{20880D(06v14M0BB0A00Sa0QW0En0iB02a0LO1W,1480TS0MF0I)0f(0MJ0&F0G,0Fh0nL0?&0cx0i60lQ0F?09q0dD0J$0N<0b90ia0RD0Xu0jA0^(0As0ND0JF0)@0cA0I@1VE0RP0Jw0N00G20T=0IJ0K=0O10NG0EC0GD0Q002h0BJ0nW0f=0Ea0R=08)06a0Dg0N30qR1iT07z0J+0Lr0760Mo03c0MP0D}03k0MR0H10Mc0Td0aj0C:0Hs0c%0LF0Rq0MB0kE0a>0PO0V@0XH0b10XN0mr04(0Mz05%0Dh05d0:?0B$0E80BW0N70Dp0d>0i(0LH1TT0xs0JP0Tj0ZE0^,0F>0Li0YT0M!0Kp09w0SB0Sz05!0C%0%>0Gz1T$1O30bB0H;0B#0J]08U0Fi0G&0F^0V^05U04b09X0B>0=60380Jn0PL0RT0@f0L=0N(0cP0qo02}0u^02/0Ky0R!01[03P0b20VI08(0M{0aa06w0lL0vn0Qz07b0AA04s07t0FA07c09P03u0N801f02d0JS02004A0D50E;06[0f>02i03>0A[0U80h60420Fj0370f^0p40Hc0M502K0a!0A*0AK05,0560a$01)0AB0JK08I0am0J:0DY08r0I=0300A]04t03D0Uz0Od0Dd02[0C*0AW0>z0Cd0K*0Tg03o0g>0dX03r13w0HQ0}s0GE03x0QL0Y30PY1$o03Z0Cm0o^06?0Us0Y40nl0Qs08[04+04%0Ir09k03Q0FN0Ny0Rc0Pe05b02!0DH0Yf03I0Iy01>0]j0F(0LB07/02S0Yp01!0hI0V/05z09{0zg07W03!05H02A0250Eh0CH06f0x=03$0Mf05/0CN0H^0EX0BE0M<04W0B50DV02,04m0F;03L08s02l0J50ay04!0Mp01@0B@0G*0Jv08:0N904S06806S0R^0KN0BF09U0EH0iW02D1Lm02x0CE0c(0LY07K06b02Q04i0P#06V0kx0@$03?04?0Bw0C}05v04n0I50#+0]F0'v0M)09x0EB0U%02@0At09v08403A02f0BX06!0H?0Hp0G@0KZ0YF0Nd02j04C0MK0JA04M0AD0H*0Nn01q01?0BN05X0Ac07105>08'07]0BK1az0x{0LU1iy0290bL03E0lR02%0Dz09C0Q,07R0q(0V701+0C#04E0G50In0Lj05&06I0f;02b02X0UK0Is07L03/01j06c0PP0Pi0JD07;05N06J08e02203)02z0520N=0B002309V02V02Y0Bs0FQ05j1Z=04@0770Cp0hv01X0^q0t>0A=0980A604F0A709Y08w0E=03s0E!0G008!0Tl0Fm1pp0io0F=0kY0Oj01y0Qu0F)02;0CQ07i0AF03}0OI0KE0R$0Nt09>0dK0720F50TL07>04d03B0#s12O0GZ03%0BV1A102*09r02g09+0FU0]c06K04k0GP03V0Ap02q0D]0FR0No07m04N0N203F0J*01'0p/0H(0j#09c0!/0&}0FB0tE0qu04c03t0M20VP0511g60%#0^<04O0AP0Fb0W70M?0Hu0CR09I0Uc0cZ0d30HY0Bd08f09l0LL0Ku0It0fw03#04X05m03;05O0Nr0Dl0Jt03@0Ne09m09d03d08}05n07:0(<0L/01h02:08a01#0K<06D0Bx0Ch0!a01k09003102L08j09W0Qr02^0M^0K>08%05R0%*09g03+08o02$0H=0T!03e06O0EQ05[03a06^07308Q09Q07D13p0Ay02R0BS0JM0FS0Db0I{02E0BY02?04e0Av0MX0Xf0L&02n0XC0GR06/02r03f0lI07v0HO06L0t?0C^0H,0D70U10NN0Ex04o0690S^04>03J0A102<0P70C<0BO0CI01x0G105A02+0a?08Y04h1kF0XA0t20bj0E?0o?09h0B+0DQ0Cw0940NX0%:07{01n0J(0Cl0De05s0Fc0X*0[#03M09&05P02u0Ry03407w0lu07E0LG03{0AI0GB06F0as0Fz01w02N06p0LP0530Qm0JN0Du0Te01$02'03S0BG0Be08D0CZ0HB0IT0K(0QX05k08g0&h01<0dH09=05I0Gx03[06+02F02s05?05w05^0S01Nd04'0Eo0on0OE0I00D20Cx0Ok03U0fM0aN0Ud0cQ0Zf08^0Dc0B(08<0JG0Nj09!0Pp03^0FJ0A>0EE0Ce0YP0Gj0oy0M+0FM0S%0KK0CU0fm02H0&m02#06q07+0A;01G0O<05:0Bv0F405e05x0Az06g0bc0OK04H0R60Gq0g^0M60Y{0Qh0I/0dE0Yt06&0Ad0D{04U0dc0C(06=0IQ06l0Ae0H)09s2A?05l0Z&05B0Dx0K{05+0Md03:0Lb0Jq07r09D0KL0HW0Bp0AX05@0E102O02B03=0ID0Mi0Rm0Q%0S:0T00fV0T50Wf0A%06X0L302=0HE07@0A{08/0Fn0G60I}0R#0J'0gC0H&0QY0R707'0Y=05;0g60C/03b0S#08+0Et02(09e04P0El0A/0Ng09'0U)02601b06]0J{03p02T04q04[0I+0Iw02y0BP06E03R03K0I80D=05]0Rp0X{0Y@0+?0Y}0ck02c04Y0OM03O0Ei0F[06Y0ES07n09*0Y*0{704008R0!e0R;09F07!0B30Qi0Cq0eX0{c0Sr0KO0P^0P)0Sh0Wa0a:0Fk02Z0[Z0BQ0AC0L!0DN0Q:0Xb0gK0Qe0ah0cs0Nz07F02m0D$11B0CS02p0R002U0ac06207d0kk0t@0qj0sh0rv0!b0Aw0Fo07A0NO0A+01P0BT01o05Y0DS0K)0W;0CB07X06'04p02&03T04r07M0G=04406m04#0K:07I0Bb04,07j0630Ym0Y50Z60Ri0W10Z]0c:05=07a0B=04]03<0Ow03]01t01;01c01^0Rb04y07o04*0KA0640Ct05J0K!0S]0Pr0L<0KI0Ss01l07S08p0A!0A^0G[07x07=0450RX0KP0OU0GJ02P02702801p0CC02I05C01H04{0AQ08b07e01I03N01:01&05t0A?02e01Y01}05G02W01g03507Y0l70hW0pI0d$0Z!0b+0jW0bs01u01%01r01m03v01R01M03l03&01]01N01Z01v01{01a01O01K01J01d01Q01=01i01z02C02k01,03g04B01L01T01S01V02>01W01/01e01U01*
\ No newline at end of file
+@infinite-storage|无限存储 (Infinite Storage)
+ocelotsignmod@|迷上城建:豹猫指示牌 (Mishanguc: OcelotSign)
+
+
+tianjin-metro-mtr3-adapted-edition|天津地铁 - MTR3适配版 (Tianjin Metro - MTR3 Adapted Edition)
+personaldimension|个人维度 (Personal Dimension)
+@dragionns-stuff
+mmr-moogs-mineshafts-reimagined@
+lightsaber-reforge|光剑:重铸 (LightSaber Reforge)
+by-powder-and-steel@|硝烟与钢火 (By Powder and Steel)
+simple-gravel-ores@|沙砾矿石*
+auto-torch-skr|自动插火把*
+appleskin-numerical-edition|苹果数据(数字版苹果皮) (AppleStats)
+factory-gauge-enhance@|机械动力:工厂仪表增强 (Create:Factory Gauge Enhance)
+
+breezes-settlements@|万家烟火 (Breeze's Settlements)
+@vajra-renewed|金刚杵:延续 (Vajra Renewed)
+singularity-iteration|奇点迭代*
+girlfriends@|女友*
+magic-brooms@
+dungeons-libraries-port
+cosmere@|三界宙*
+sable-ragdolllib@sableragdolllib|物理布娃娃库 (Sable: RagdollLib)
+sable-maidragdoll@|女仆布娃娃 (Sable: MaidRagdoll)
+maidtelepathic-ragdoll@|电波女仆:装死 (MaidTelepathic & Ragdoll)
+@em4es
+@wuzhongshengyou|无中生有:神赐重制版 (Ex Deorum Reuse)
+@player-locator-plus-reforged
+@alterna
+modular-backpacks@|模块化背包*
+mace-skyfall@|重锤:天陨 (Mace: Skyfall)
+advanced-memory-card@|高级内存卡*
+@moretetrabench
+arcanemag@|奥术弹匣 (ArcaneMag - TaCZ × Iron's Spells Addon)
+@vercte-satchels
+sniffers-sniffs-delights
+alexs-caves-mobs-accurate-mob-spawn@|Alex的洞穴:成倍生成 (Alex's Caves Accurate Mob Spawn)
+glowstone-wire-reforged
+scalingguis-reborn|界面缩放:重生 (ScalingGUIs Reborn)
+
+instantly-destroy-tree-clear-path-for-horse-riding|骑行秒清树 (Instantly Destroy Tree: Clear Path for Horse Riding)
+toastsflyingtools|吐司的飞行工具 (ToastsFlyingTools)
+
+mo-creatures-revival
+more-attributes@|更多属性 (MoreAttributes)
+iepowerpackfix|沉浸工程电容背包兼容 (IE Powerpack Fix)
+@toads-better-straw-beds
+propeller-hats
+
+protection-engineering|工程防护*
+@legacyforgej8
+
+
+schematica-plus@
+only-tp@|只能TP (Only TP)
+shadow-drop@
+@no-fire-tick
+
+@pack-folders
+@smooth-hover
+@effortless-extract|探囊取物 (Effortless Extract)
+meds-and-herbs-reborn@|医疗与草药:重生*
+charm-of-undying-reborn@|不死图腾槽位:重生 (Charm of Undying: Reborn)
+ichun-gravity-gun-mod-revival
+
+alexs-caves-neo
+alexs-mobs-neo
+
+drzharks-magic-carpet-mod-revival
+boss-companions@
+
+tips-extension@|Tips 扩展*
+wanderers-campsite@|流浪商人营地*
+touhou-little-maid-crimson-heart-covenant|车万女仆:绯心待契 (Touhou Little Maid: Crimson Heart Covenant)
+sable-ragdoll-patch@sableragdoll-patch
+
+command-block-studio@|命令坊块*
+
+
+mbs-moogs-bountiful-structures@
+@mca-tacz-compatibility
+
+little-maid-harvest-helper|小女仆丰收助手*
+touhou-death-sound@touhou-death-sound-mod
+cloudworks-api@|沉云工坊API (CloudWorks API)
+@stronger-armored-mobs
+xiaofulans-secret-alchemy|小符兰的秘密药剂 (Xiaofulan's Secret Alchemy)
+@lava-pockets-removed
+precraft-accelerator@pcaprecraft-accelerator|前置合成管理器 (PreCraft Accelerator)
+prospect@
+
+@mekanismlightning-generator|通用机械:闪电发电机 (Mekanism: Lightning Generator)
+@rs2ae_cell
+eating-animation-fork@|进食动画分叉版*
+saucelib@sauce-lib
+@no-input-lag-tick-rate|无游戏刻输入延迟 (No Input Lag Tick Rate)
+only-tp-violent-build|只能TP暴力版 (Only TP Violent Build)
+xercas-tools@
+spell-trigger@spelltrigger|施法扳机*
+magneticraft-reborn@magneticraftreborn|磁场工艺:重生 (MagnetiCraft: Reborn)
+inventoryadvancementaccelerator@|背包成就性能优化 (InventoryAdvancementAccelerator)
+projectef|等价交换Neo (ProjectEF Neo)
+create-curios-backtank
+mekanism-overclocked|超频 - 通用机械分叉 (Overclocked - A Mekanism Fork)
+moonstone-gene-recombination@|月之石:基因重组 (Moonstone: Gene Recombination)
+jfi@
+player-utils@|玩家工具箱*
+cc-graphics@
+@trial-chamber-time-remover
+rpg-enchantments
+skeleton-marksman
+blue-archive-halos-pyroxene@
+alexs-caves-refabricated@
+molecules-neoforge
+butdays-blueprint|Butday的蓝图 (Butday's Blueprint)
+battery-factory|電池工廠*
+alexs-mobs-delight-legacy|Alex 的生物农家乐 (Alex's Mobs Delight Legacy)
+ends-delight-legacy|末地农家乐 (End's Delight Legacy)
+nethers-delight-legacy|下界农家乐 (Nether's Delight Legacy)
+@legendarys-delight|传奇盛宴 (Legendary's Feast)
+
+sleepie|睡眠派*
+abyss-sonata|深渊奏鸣*
+proper-blindness
+
+
+
+
+ftb-button-fix@|FTB按钮修复 (FTB Button FIx)
+quantum-chromodynamic-charge|量子色动力学爆弹*
+shulker-box-labels@
+agility-enchantment
+veinminer-enchantment
+pineapple-delight-legacy
+brewin-and-chewin-legacy|饮酒作乐·上炕! (Brewin' And Chewin' Legacy)
+twilight-delight-legacy
+extra-delight-legacy|额外农家乐*
+bosses-oddities
+
+@kaleidoscope-grilling|森罗物语:烟火 (Kaleidoscope Grilling)
+goety-buffed-apostle
+the-ultimate-raid
+idealland-shrine|理想境-神碑*
+lightning-rod-zombie@|雷霆之杖僵尸 (lightning rod zombie)
+alone-host|一人成军*
+@ourvillagers
+
+player-npc-weapons-expansion@annoying-villagers-player-npc-weapons-expansion
+
+
+
+create-resonance|机械动力:共鸣 (Create: Resonance)
+@carryon-aeronautics-compat
+
+spore-serene-seasons-bridge|孢子 × 静谧四季/季节联动*
+jasione@
+cave-dweller-reforked
+food-ores-neo@food-ores|食物矿石:革新*
+inf-team|信息团队 (Inf-Team)
+fungal-infection-spore-infnexus|真菌感染:孢子 感染枢纽 (Fungal Infection: Spore Infnexus)
+
+
+chat-canvas|聊天画布*
+led-it@|灵光同步 (Led it!)
+findme-salvation@findmesalvation|找到我:救赎 (Findme: Salvation)
+cnpc-tacz-fire
+@ftb-quests-background|FTB任务背景 (FTB Quests Background)
+
+radical-exp-strategy@|激进经验策略*
+villager-trading-overhaul@|村民交易界面优化*
+tinker-lens-curios-support|余烬传奇之丢失的眼角膜*
+heaven-dimension-mod
+@better-language|更好的语言 (Better Language)
+@sable-vivecraft-fix
+
+
+smileys-better-voice
+laowu-meme@|老吴~*
+icy-lib|冰洁柠檬心的Lib*
+cnpc-epicfight-addon-ce
+mythical-creatures-reborn@|神话生物重制版*
+compactwaterturbines|压缩水轮机 (CompactWaterTurbines)
+@better-footage|更好的录制素材 (Better Footage)
+cnpc-plus-fix
+lenstrack|追镜 (LensTrack)
+
+icy-punishing|Icy战双帕弥什*
+i-know-my-effects
+hall|腐朽之疫:王庭 (Rotten Ruins:the Hall)
+caustica@
+carpet-fga-addition@
+shanhaixiantu|山海仙途3 (ShanHaiXianTu)
+@permissionmanager
+emf|异常管理基金会 (Exception Management Foundation)
+piglin-outposts@|猪灵营地*
+divine-workshop@divinework-shop|神咒工坊*
+galosphere-spelunkery-compat@
+epca-visionfix|EPCA 适应视觉修复 (Epca‑VisionFix)
+godsick|创疴 (GodSick)
+the-fall|神陨传说 (Fallen)
+destructive-spelunking
+datastats|数据统计 (DataStats)
+botania-backpack-upgrades@|植物魔法背包升级*
+@chat-optimizer|聊天优化 (Chat Optimizer)
+@map-chameleon|地图变色龙 (Map Chameleon)
+@create-embedded-freights-fly|机械动力:嵌入式包裹飞越 (Create: Embedded Freights Fly)
+piston-scanner|活塞扫描仪*
+@create-ccbr
+infectioncoreframework|感染核心框架 (InfectionCoreFramework)
+create-petrochem@
+
+@villagertradestats
+tube-transport-system-reforged|管道传输系统:重铸 (Tube Transport System : Reforged)
+@commonprosperity|经验共享 (Common Prosperity)
+cnpc-npcpathfinding
+
+rebindnarrator-fabric@rebindnarrator¨rebindnarrator
+@create-labor-rush|机械动力:劳工冲刺 (Create: Labor Rush)
+create-flight-control@|机械动力:飞控学 (Create: Flight Control)
+aeronautics-interstellar-expansion@aeroie|航空学:星际扩展 (Aeronautics: InterStellar Expansion)
+
+viscriptquests@
+@floodgate
+
+
+nolando-apocalypse@
+
+extended-mining-tiers-jade-compat|扩展挖掘等级:Jade 兼容 (Extended Mining Tiers - Jade Compat)
+apothic-attributes-whitelist|神化属性白名单*
+@lots-of-harm-visualization|好多伤害可视化 (Lots of Harm Visualization)
+the-hybrid
+dimensionpotion@|维度药水 (Dimension Potion)
+walking-cane|步行手杖*
+mobmind|生物心智 (MobMind)
+terrafirmacraft-immersive-gardening|群峦传说:沉浸园艺 (TerraFirmaCraft: Immersive Gardening)
+tfc-scraping-knives|群峦刮刀*
+ae2-autocrafts-thaumcraft-and-botania
+better-config@
+sodiumleacculling-unofficial@sodiumleafculling-unofficial|钠:树叶剔除-非官方版 (SodiumLeafCulling-Unofficial)
+mo-bends-reforged|更多弯曲:重铸 (Mo' Bends (Reforged))
+excavar@
+net-music-better-loginfa@|网络音乐机:更好的登录FA (Net Music: Better Login FA)
+emi-swift-copy|EMI 迅速复制 (EMI Swift Copy)
+super-factory-manager-gui
+hunting-quest|狩猎任务*
+
+nofireworkfly@no-fire-work-fly|无烟花飞行 (NoFireworkFly)
+
+better-smithing-template@|好锻!*
+@reveal-index-codex|辑录与揭秘 (Reveal: Index & Codex)
+
+el-and-ls-dyes@el-and-ls-dye-mod
+
+more-strong-commands|更多强力命令*
+
+bakeries-simulation@|烘焙坊模拟经营*
+ex-nihilo-abnormals@
+@glow-my-teammates|发光吧,我的队友 (Glow My Teammates)
+ex-nihilo-additions@
+chinese-weapons@|中式甲兵*
+@metaphysics-reset
+openblocks-reborn|开放式方块:重生 (OpenBlocks Reborn)
+portablestorage-rift@
+smelting-enchantment
+@versiont
+@mcpythonon
+@s1-mtr-addon|S1的MTR扩展 (S1's MTR addon)
+carpet-primaryuan-addition@carpet-pry-addition
+no-singleplayer@|无单人模式*
+legendary-delicacies|传奇珍味*
+double-doors-continued@|双开门延续版*
+
+@boats-is-jumping
+brilliant-text
+legendary-monsters-tetra-material|传奇怪物:Tetra兼容*
+kaleidoscope-nether-refabricated@|森罗物语:下界——重织*
+
+bird-watching-community-ports|新·观鸟 (Neo Guan Niao / Bird Watching - Community Ports)
+luckperms-gui-nametags
+@the-roads-more-travelled
+@killblock|杀敌方块 (KillBlock)
+@ciallominecamera|你好,我的相机! (Ciallo Mine Camera)
+serverwarashi|座服童子 (ServerWarashi)
+bamboo-tweaks
+be-beryllium|铍 (Beryllium)
+create-track-switch-radio@|机械动力:转辙机无线电 (Create: Track Switch Radio)
+@launchers_and_arrows
+
+
+@isocraft
+gtnh-external-lib
+
+toilet-technology|厕所技艺*
+immortal-cultivation@immortal-cultivation-mod|修仙之路*
+tfc-punishment-for-death@|群峦死亡惩罚 (TFC Punishment for Death)
+liubai@|留白*
+impirium@
+@playeruploadermod|上传玩家位置 (Player Uploader)
+
+@veinmine|连锁挖掘 (Vein Mine)
+
+mishanguc-better-colortool@|迷上城建:更好的颜色工具 (Mishanguc: Better Colortool)
+lm-addons@
+kubejs-cuisine
+create-diesel-generator-unofficial-fork-for|机械动力:柴油动力 - 非官方分支 (Create Diesel Generator - Unofficial Fork for NYfAxSMP3)
+create-bits-n-tracks@
+irongolems-life|铁傀儡人生体验 (Iron Golem Player / IronGolem's Life)
+tacz-caliber-ammo|TacZ:火力重塑 (TacZ: Caliber Ammo)
+
+
+
+@maid-tavern|女仆酒馆 (Maid Tavern)
+super-flat-core
+oritongs-diamond-core
+
+@just-enough-accidents|险兆备份 (Just Enough Accidents)
+
+lr-tactical-1-21-1@lr-tactical-1.21.1
+rs-integration@|共振存储 (RS Integration)
+create-ages
+
+roguelike-dungeons-arcana-edition
+
+rangers-apprentice-mod@rangers-apprentice|游侠学徒 (Ranger's Apprentice)
+omni-upgrades@|全能升级*
+iron-chest-fix@|更多箱子修复*
+tfc-lunch-box@|群峦午餐盒 (TFC Lunch Box)
+returnfeatures
+@etherstweaks
+blockshin-menu|方神菜单*
+
+@void-power|虚空动力(重置版) (Void Power Reset)
+@classic-rblx-tools
+blockestra
+new-collisiondamage@|碰撞伤害:重置 (New CollisionDamage)
+avariria-progression-expansion
+
+hostility-staff@|敌意之杖*
+chocolatiers-delight
+farmers-spell@|魔法食事 (Farmer's Spell 'n Spell Book)
+@libr-getter
+uei@|通用附魔信息 (Universal Enchantment Info (JEI/REI/EMI))
+tacz-auto-fire|TACZ:自动射击 (TACZ: Auto Fire)
+universal-container|通用容器*
+moremaidtask|更多女仆工作模式 (MoreMaidTask)
+thunderbolt-core@
+@living-item|活物品 (Living Item)
+
+worldhistory|寰世忆影 (WorldHistory)
+irons-spells-3d-cast-preview@|铁魔法法术3D预览 (Iron's Spells 3D Cast Preview)
+tconstructs-loli|匠魂萝莉 (TConstruct's loli)
+litematica-print|更智能的投影打印机 (Litematica-Print)
+evolveequipment|更多升级装备 (EvolveEquipment)
+
+ds-neck-fix-paperdoll-compat|龙之生存:纸娃娃兼容修复 (DS Neck Fix - PaperDoll Compat)
+
+@smoothcamera|平滑相机 (Smooth Camera)
+touhou-maid-eat-properly|车万女仆:好好吃饭 (Touhou Maid: Eat properly)
+chiseled-bookshelf-searcher|雕纹书架搜索器*
+@sable-quota|Sable:配额管理
+
+@daydram-glittering|浮世幻梦 (Daydream: Glittering)
+
+
+brilliant-text-remixin
+flashlightmod|手电筒 (FlashlightMod)
+showcaser@|展示器*
+@ciallo-mine-datapack|你好,我的数据包! (Ciallo Mine Datapack)
+
+@cavebiomesapi
+mbts-mobs|Mbt的人形怪 (Mbt's Mobs)
+
+
+tree-chopper-continued|砍树延续版*
+
+@worldgen-devtools|世界生成开发工具 (Worldgen Devtools)
+
+@carpet-ice-addition|冰毯 (Carpet Ice Addition)
+
+ala-industrial@
+
+greglink|格雷桥接器 (GregLink)
+@automaticcrafting|自动合成台 (Auto Crafter)
+@the-final-boss
+touhou-little-maid-love-loathe|车万女仆:爱憎分明 (Love & Loathe)
+entity-modifier|可视化实体修改器*
+zettas-spells
+dimension-leak-fix@|维度内存泄露修复*
+
+@manhunt-wildcard|猎人游戏-外卡 (Manhunt Wildcard)
+visor@
+jdte
+dog@devourer-of-gods|神明吞噬者 (Devourer of Gods)
+alexs-caves-fabric-neoforge-port
+bob-the-toolbox
+
+fastgelica
+cnpc-enhance
+
+@tlm-maid-survival|车万女仆附属:女仆生存 (TLM: Maid-Survival)
+dnz-skibidi-toilet@
+@input-method-restore|撤销输入法锁定 (Input Method Restore)
+@trashslot-mite|垃圾槽 - MITE (TrashSlot - MITE)
+@trash-slot
+@inventory-crafting-stick-standalone|便携工作台 (Inventory Crafting Stick)
+jasons-disenchantment-forge
+
+flexibook|自定义书 (FlexiBook)
+pu-dragon|钚龙 (Plutonium Dragon)
+
+@listmore
+
+better-amethyst-plus@amethyst-plus|紫水晶拓展 (Amethyst Plus)
+
+launchpad@
+tfcreate-compat@
+show-me-your-skin-neoforge-port@
+anvilcraft-slugplus@|铁砧工艺:蛞蝓+ (AnvilCraft: SlugPlus)
+ae2-uelm
+@fluxnautics
+autofish-for-fishingoverhaul|自动钓鱼XPlus版 - Fishing Overhaul 兼容 (AutoFish for Fishing Overhaul)¨@autofish-for-fishingoverhaul|自动钓鱼XPlus版 - Fishing Overhaul 兼容 (AutoFish for Fishing Overhaul) - 正在
+@miehex|咩之咒法 (MieHex)
+@miehexrevolution|咩之咒法:变革 (MieHex: Revolution)
+fruits-delight-legact|果园农家乐 (Fruits Delight Legacy)
+neopasterdreamsanity|新帕斯特之梦-乱 (NeoPasterDreamSanity)
+neopasterdreammeltdream|新帕斯特之梦-融梦 (NeoPasterDreamMeltDream)
+neopasterdreamspells|新帕斯特之梦-咒语 (NeoPasterDreamSpells)
+apothic-enchanting-vanilla-integration|神化附魔原版兼容*
+re-avaritia-armor@avaritia-armor|无尽贪婪:重生:盔甲 (Re:Avaritia: Armor)
+vintage-tech
+hydrofarm@
+@clean-keystrokes
+player-beacons|玩家信标*
+enhanced-celestials-2-default-lunar-events@|月亮事件 2:默认月亮事件 (Enhanced Celestials 2: Default Lunar Events)
+horde-moon-2
+dynamic-trees-pale-bloom
+dramatictrees-palebloom-cr@
+blade-tetra-forged-styles|拔刀剑:百构流派 (Blade Tetra: Forged Styles)
+project-souls@
+placeable-gaze-manual|可放置越幔全典*
+
+enhanced-celestials-2-shader-support@|月亮事件 2:光影支持 (Enhanced Celestials 2: Shader Support)
+contract-blade|车万女仆:契约之刃*
+@fabric-custom-names
+ars-nouveau-combat-glyphs
+@thip-mm|特摄英雄补完计划-城市超人 (THIP Metro Man)
+@homelander-lasers
+
+unofficial-tacz-refabricated|永恒枪械工坊:零 - Fabric(非官方) ([UNOFFICIAL]TaCZ Refabricated)
+sign-pack@the-sign-pack
+
+
+
+
+gtnh-lotr-nei@gtnh-nei-lotr|魔戒NEI插件:GTNH 版 (GTNH LOTR NEI)
+enhanced-celestials-2-core@|月亮事件 2:核心 (Enhanced Celestials 2: Core)
+peaceful-moon-2
+hyperslide@
+@outln.frombelowland
+nei-resources@
+pama-mobs@|PAMA模组 (PAMA-mobs)
+@modernobscure|提示框杂烩 (ModernObscure)
+dimensions-of-alexs-caves-jei-integration@
+
+ld|传奇珍味NeoForge版 (Legendary Delicacies NeoForge)
+harvestgalacticraft
+biomas-vanilla-renovados@
+grapplemod-skybound@
+dpsmeter|秒伤统计面板 (DPS Meter)
+pulse-trims@|脉动纹饰*
+
+@personal-anti-cheat|反个人作弊 (Personal Anti-Cheat)
+ironfurnacesfix|更多熔炉修复 (IronFurnacesFix)
+
+
+@hydro-agility
+reimus-initial-dimension|灵梦的初始维度 (Reimu's Initial Dimension)
+ae2-crafting-cpu-item-count-display|AE2合成CPU物品数量显示 (AE2 Crafting CPU Item Count Display)
+dynamic-trees-regions-unexplored@dynamic-trees-ru|动态的树:未至之地附属 (Dynamic Trees - Regions Unexplored)
+
+dragon-ars-bridge
+skip-title-screen|跳过标题画面*
+f-tech@
+@tfc-info-integration|群峦信息显示 (tfc info integration)
+highlands-for-all
+homeostatic-seasons@
+ae2-additions
+survivaltoolbox@|生存工具箱 (SurvivalToolbox)
+
+loot-box|战利品箱*
+autoemc@
+
+
+
+team-view-relay@
+
+chatorder|聊天点单 (ChatOrder)
+tactical-melee-attribute-compat|绿葡萄战术装备属性修复*
+
+streams-reflowing@|溪流:重流*
+runfast|迅步疾行 (runfast)
+ender-trigon-unofficial|末影三头龙:非官方版*
+enderman-xtra|末影人:恶意 (enderman xtra)
+legend-star@legendstar|传奇之星*
+
+kilagraph@
+@enchantment-book-of-undying
+the-reverse@reverse_mc|重返MC (Reverse:MC)
+axon-technologies@axontechnologies¨redthunderaniummod@axon-technologies
+
+cybernetics-cyberchems@
+heavyspear@|重矛 (Heavy Spear)
+@item-texture-exporter|物品纹理导出 (Item Texture Exporter)
+ae2ud@
+stellarcreateoptimization
+create-coasters-simulated@
+freshness|新鲜度*
+
+@create-ore-excavation-deposits
+fluorite-the-realm-of-dreams
+
+@ghastling_sound_fix|小乐魂声音修复 (Ghastling Sound Fix)
+
+
+neoloading-vulkan-fix@
+
+pehkui-rebuilt@|Pehkui 重构版*
+ars-arcane-matrix|奥术矩阵*
+trade-stages
+tradestages-legacy
+refart|响屁不臭*
+@everlatweaker|言引定制/七叶镜绫的修改 (EverlaTweaker)
+a-wish-yet-to-bloom|未竟花愿 (A Wish Yet to Bloom)
+
+
+chinese-horror-bride-in-red@chinese_horror_bride_in_red|中式恐怖-红衣鬼新娘*
+bing-agriculture-extend|冰·农业工具扩展*
+food-vendor|美食小摊*
+@probability-pattern|AE2 概率样板 (Probability Pattern for AE2)
+cave-dweller-overhaul@
+tinkers-metallurgy
+bbs-fs@
+
+
+
+anvilcraft-pigeon-plus@anvilcraft-pigeonplus|铁砧工艺:鸽+ (AnvilCraft: Pigeon Plus)
+the-goetyard
+@tacz-bleeding
+
+ragdollified@
+fractured-bones-and-more-fracturedbones|骨折 (Fractured Bones & more)
+@empiremod|帝国 (Empire)
+forolite
+
+auto-seam-blend@|自动连接纹理*
+
+carpettngaddtion@
+@seed-map-for-xaero
+botania-overhaul
+raithaumcraftadditions@
+
+
+ars-noita-addition|更Noita的新生魔艺*
+slashblade-a-belated-gift|拔刀剑:迟来的礼物 (SlashBlade:A Belated Gift)
+resourceignorer@|资源加载忽略 (ResourceIgnorer)
+item-cleaner-cat|清理喵*
+
+cobblemon-droploottables@
+create-green-print|机械动力:绿图 (Create: Green Print)
+history-stages@|历史阶段*
+libvulpes-continuation|LibVulpes - 延续版 (LibVulpes - Continuation)
+advanced-rocketry-continuation|高级火箭 - 延续版 (Advanced Rocketry - Continuation)
+xaeros-maps-multiplayer-plus@
+item-get@|物品提醒 (Item Get!)
+legacy-hellfire
+cdmlloader
+ocelot5836s-craytunes
+extra-ons
+super-mario-world-application
+bubble-burst
+kabores-discord-application
+device-mod-apps
+apps-mod
+spyeedys-shop-app
+calculatorplus
+model-creator-app
+smartqueue@
+hachimis-buoyancy-machine|哈基米的浮力机 (Hachimi's Buoyancy Machine)
+answertime|答题时间 (AnswerTime)
+legacy-textiles
+
+hephaestus-forge
+
+
+tester-mod@|测试者模组*
+ae2-batchcraft|AE2 批量工艺 (AE2 BatchCraft)
+multi-function-trash-cannon@|多功能垃圾炮
+
+mc-mods-crash@all-crash|通通崩溃 (allcrash)
+millager@|戍村卫民 (Millager (Village Defenders))
+modularshoot@|模块化射击 (ModularShoot)
+
+
+emoticons-reforged|动作表情:重铸*
+jei-tag-groups|JEI 物品配方折叠 (JEI Tag Groups)
+bettergamerules|更好的游戏规则 (BetterGamerules)
+
+
+mine-slayspire@|杀戮尖塔2 (Mine-SlaySpire)
+touhoulittlemaid-mimo-tts|车万女仆:MIMO语音合成支持 (TouhouLittleMaid MiMo TTS)
+@amatweaks
+
+tctb|匠拉 (TConstruct-Tetra Bridge)
+modtweaker-community-edition
+@pretender|伪装者 (Pretender)
+
+
+
+jei-trade|JEI交易 (JEI Trade)
+enchanted-outlines@|轮廓即宣言*
+
+
+@spiritingaway|应隐待捉/八云紫的神隐 (Yukari's Spiriting Away)
+
+custom-recipes-editor|自定义配方*
+
+
+legendary-farming@
+
+pipez-optimizer@|Pipez优化器*
+tinkers-planner-antique
+
+voltex@
+horizonui@
+collapsible-groups
+
+@pipez-filter|Pipez 过滤升级 (Pipez Filter)
+achievement-trophies|成就奖杯*
+@charliezoom|Charlie 放大 (CharlieZoom)
+ae2-quick-calculation|AE2快速计算 (AE2 Quick Calculation)
+create-extend-extendo-grip|长臂猿,现在就在你家门口! (Create: Extend Extendo Grip)
+@yourstageskybox
+real-night|真实黑暗 (RealNight)
+twilight-aether@
+@ivars-bosses
+
+
+buildcraft-community-edition@|建筑社区版 (BuildCraft Community Edition)
+construction-wand-1-12-forge|建筑手杖 1.12 (Construction Wand 1.12 Forge Porting)
+mcgs-questborne@
+copper-furnace|会氧化的铜熔炉*
+zifeng-s-custom-skill-tree|子枫的自定义技能树 (zifeng_s_custom_skill_tree)
+modularshootammo|模块化射击:弹药 (ModularShootAmmo)¨@modularshootammo|模块化射击:弹药 (ModularShootAmmo) - 暂未过审
+icy-iron-spell|冰的铁法术魔女*
+ocelotsignyunbei@|云北城建:豹猫指示牌 (YunbeiUC: Ocelot Sign)
+emcmap-addon@
+universal-block@|通用格挡*
+ore-sheep-mod
+metal-wings@metalwings
+tacz-mesh-loader@
+@chromatic-aberration-mod|色差 (Chromatic Aberration Mod)
+improved-villagers-organized-combat
+supreme-gold|至尊金*
+
+time-bus|时间总线*
+farmers-future-delight|未世之乐 (Farmer's Future Delight)
+spartanapothiccompat@|斯巴达武器神化兼容 (SpartanApothicCompat)
+jinzai-traffic-lights@|津仔的交通灯 (JINZAI Traffic Lights)
+
+modular-muskets@
+penetration-enchantment|洞穿附魔*
+herowolf|豪狼 (HeroWolf)
+
+perspective-api@|视角 API (Perspective API)
+gregtech-universal-frame
+@lost-soul|传说之下:离魂惘途 (Lost Soul)
+mianbaos-newmodernwarfare|面包的新现代战争 (Mianbao's NewModernWarfare)
+no-bedrock
+serverlogin|服务器登录 (ServerLogin)
+collections-of-optimizations
+one-night-to-die|一夜致死*
+
+beyond-the-bedrock@
+neoterraforged|新:地形重锻 (NeoTerraForged)
+@fooddelivery|外卖系统 (Food Delivery System)
+constructum-tech|构元科技*
+tinkers-strainer|匠魂滤网 (Tinker's Strainer)
+gears-of-valor
+ftb-project-ex-1-7-10-backport|等价交换升级(非官方移植版) (Project EX (Unofficial Backport))
+alexs-caves-up
+
+celestisynth-enhancement|Celestisynth 武器增强*
+create-cats-dont-care@
+create-re-packager-fix@|机械动力:理包机修复 (Create: Re-Packager Fix)
+
+smart-zombies-mobs|僵智*
+trade-preset@|交易预设*
+bettersmithingplus
+tacz-gun-damage-regulator|TaCZ全局伤害调节 (TaCZ Gun Damage Regulator)
+jei-plus-plus@
+
+
+
+
+
+
+ae2-quick-encoding|AE2快速编码 (AE2 Quick Encoding)
+ae2-quick-encoding-upload|AE2快速编码上传 (AE2 Quick Encoding Upload)
+delta-chunk@deltachunk
+@bilingual-tooltips|双语灵动岛 / 双语 Tooltip (Bilingual Tooltips)
+miners-delight-bridge|矿工桥家乐 (Miner's Delight Bridge)
+covenant-of-the-seven
+vvvf-simulator-library@|VVVF模拟器核心库 (VVVF Simulator Library)
+
+
+faster-scrolling@
+solo-quests|FTB任务独立 (FTB Solo Quests)
+@preventbuild
+rod-of-discord|混沌传送杖 (Rod of Discord)
+create-meowchanics|机械动力:老吴学 (Create: Meowchanics)
+@miniscaled-forge-unofficial
+
+modernica@modernica-fabric
+enchantlib
+gensou-works|幻想营造*
+gtbcs-cataclysmic-boss-ui@
+
+cnpc-bbs-integration@cnpcs-bbs-addon
+create-advanced-frequency-network|机械动力:高级频段网络 (Create: Advanced Frequency Network)
+mapart-helper@
+
+leak-warning|厚里泄!*
+netmusic-createstorage-compat@|网络音乐机 x Create: Storage 兼容修复 (NetMusic CreateStorage Compat)
+bettervein|更好的的连锁 (Better Vein)
+experience-durability@|经验耐久*
+touhoulittlemaid-self-talk@|车万女仆:女仆自言自语 (TouhouLittleMaid Self Talk)
+@khdgxnn|更新按钮
+extra-ons-2
+touhou-little-maid-maid-manager|车万女仆:便携管理 (Touhou Little Maid: Maid Manager)
+
+ring-of-the-hundred-curses@|玩游戏时在做什么?有没有空?可以加上百咒吗?/ 百咒之戒 (Ring of the Hundred Curses)
+item-alchemy-expansion@
+plumes-summoner|羽光沉璧的召唤器 (Plume's Summoner)
+@infinite_card|无限卡牌 (Infinite_Card)
+kaleidoscopecookery-unofficial-26-neo-ver|森罗物语:厨房非官方26Neo版 (KaleidoscopeCookery Unofficial 26 Neo Ver)
+mythika@
+kaleidoscope-extension@kaleidoscope-jei-extension|森罗物语:厨房JEI拓展 (Kaleidoscope Jei Extension)
+dragon-survival-tacz-compat@|龙之生存:龙持枪?! (Dragon Survival TACZ Compat)
+@tfc-auto-knapping|群峦自动打制 (TFC Auto Knapping)
+box-of-structures-legendary-monsters
+
+maid-mining|矿透女仆*
+
+mr-yao-fantasy-creatures-mod|Mr.Yao的幻想生物 (Mr.Yao Fantasy Creatures)
+@qed|伤害溢出修复 (Quite Enough Damage)
+rfapi@|水库 (Reservoir Fluid API)
+
+ferric-oxide@|氧化铁 (FerricOxide)
+
+combatives@
+@enchantment-glint-outline|附魔轮廓 (Enchantment Glint Outline)
+more-vanilla-shields@
+
+@hunters-compass|猎人游戏-指南针 (Hunter's Compass)
+resonant-synthesis@
+archaion
+
+yqils-arknights|YqIl的明日方舟 (YqIl's Arknights)
+functional-statues@
+bloodmagic-akashic-records|血魔法:阿卡西记录 (BloodMagic:Akashic Records)
+@threateningly-mobs-continued
+yazzs-dungeons-the-sequel
+
+bbbbeacon|信标光束改良 (BBBBeacon)
+modern-companions@
+@custom-playerdoll|玩家模型玩偶 (Custom Playerdoll)
+physics-mobs-death@
+monster-frenzy|怪物狂潮 (Monster frenzy)
+
+macabre
+thaumic-dabblery@
+@movablegui
+@throw-it|万物皆可抛 (Throw it)
+bomberbeast@
+abandoned-post-apocalyptic-buildings
+bullets-boats@
+
+dreamshift@
+tacz-project-pneuma
+shape-shifters-compass|幻形者罗盘 (Shape Shifter's Compass)
+
+
+
+
+
+
+smileys-better-brain
+douyinview|游戏内抖音悬浮窗 (douyinview)
+
+
+pams-harvestcraft-2-tweak@|潘马斯农场2修复 (Pam's HarvestCraft 2 Tweak)
+
+
+productive-bees-genesis|资源蜜蜂·创世*
+mob-crops
+modularrarity@|模块化稀有度 (ModularRarity)
+create-level|机械动力:等级 (Create: Level)
+tinkers-assembly|工匠装配 (Tinkers' Assembly)
+create-waterparked@|机械动力:水上乐园 (Create: Waterparked)
+sleepingoverhaul
+
+@spreadspawnpoints|扩散出生点 (Spread Spawnpoints)
+autofishs@|自动钓鱼S (AutoFishS)
+
+@blessingofpandora|潘多拉之祝 (Blessing of Pandora)
+@suiyuemo|沉重系列
+ae2-addon-infinite-expansion
+
+
+better-sparse-structures
+goety-spell-source@goety-spell-source-api|诡厄巫法:法术源 API (Goety: Spell Source API)
+magical-psi-revival@
+pact-curios@|平等契约 (Pact curios)
+advanced-mob-leveling
+signedit|告示牌编辑 (SignEdit)
+jei-enchantment-info-1-12-2
+chat-heads-vintage
+anvilcraft-doge-plus@anvilcraft_doge_plus|铁砧工艺:Doge+ (AnvilCraft Doge+)
+steam-powered-create@create-steam-powered|蒸汽动力(非官方) (Create: Steam Powered)
+
+
+
+tfc-more-cans-and-jars@|群峦更多罐头 (TFC More Cans and Jars)
+
+@rgb-chat|给你点颜色瞧瞧:文字版 (RGB Chat Reborn)
+
+
+poof
+
+chunk-plan|探索限额*
+@rebetterend
+
+
+htmlcraft-api@
+polymer-neo
+create-gt-compatibility-of-boards|机械动力 : 格雷科技的材料制造兼容 (Create : GT Compatibility of boards)
+blocks-toukenranbu|方块与刀剑乱舞 (Blocks & Toukenranbu)
+
+
+leapcraft|越级合成 (LeapCraft)
+fantasy-pattern|AE:幻梦编码*
+spice-of-life-stick-edition|生活调味料:木棍版 (Spice of Life: Stick Edition)
+drop-confirm@
+notify-server-messages
+@intelium-mod
+cnpc-bettercombat
+orcinvasion|兽人入侵 (orcinvasion)
+
+@superb-warfare-refabricated
+
+mca-quests@
+fish-n-ships@
+incision
+
+rift-gun|裂隙传送枪*
+
+sixseven@sixsevenstack
+vivid-move|灵动! (Vivid Move!)
+
+deermod-by-arisuwumei@deermod
+reterraforged-unofficial
+black-knight-armor-and-food|冰火传说:黑骑士扩展
+field-guide-monster-checklist@field-guide-monster-check-list|Field Guide:里程碑提升 (Field Guide: Monster Check List)
+fkferrouswroughtnaut@|去他的钢铁守护者 (FkFerrousWroughtnaut)
+multigolem
+neovitae@
+whatstheloot
+hbm-mekanism-compat@
+@antideath-survival-assistant
+focus@
+super-graphite-electrode|超级石墨电极*
+@quickcraft-container-projection
+hud-menu@|Hud菜单*
+honeymilkbucket@honey-milk-bucket|蜂蜜奶桶 (Honey Milk Bucket)
+ananke|命途未央 (ANANKE)
+arcane-patternworks
+tetra-insight
+@create-schematic-compute|机械动力:蓝图计算机 (Create: Schematic Compute)
+ftech-industry|异星科技 (FTechIndustry)
+@microtimingreplay|微时序回放器 (MicroTimingReplay)
+
+polyglottooltip
+@simple_chess|国际象棋 (Chess)
+analyst|分析者*
+masonry@tm-masonry|石工工艺*
+winefoxmoreanimation|酒狐更多动画 (WineFox More Animation)
+@ride-together-mca-immersive-vehicles
+post-it@
+
+@collect-everything|收集一切 (Collect Everything)
+
+@simple-farming-reworked|简单农业:重构版 (Simple Farming Reworked)
+tastebud-delights|味蕾乐事 (Tastebud delights)
+teyvats-delight-a-farmers-delight-add-on@teyvats-delight|提瓦特乐事 (Teyvat's Delight)
+
+
+
+structure-race|结构竞速*
+creature-corner@creaturecorner
+q-shop|企鹅商店 (Qshop)
+@phayriosiscataclysm
+the-last-sword-you-never-forgot@|最终之剑:重铸*
+
+inventory-item-groups@|物品分组*
+ae2-recent-search|AE2 最近搜索 (AE2 Recent Search)
+piglin-bartering-for-jei@
+thaumcraft-aspect-annotations|神秘时代要素注释*
+rs-search-history|RS 历史搜索记录 (Refined Storage Search History)
+carpet-dds-addition@
+hps-portable-workstations|HP的便携式工作方块 (HP's Portable Workstations)
+@bulletproof-armor|防弹衣 (Bulletproof Armor)
+flower-tea|花茶*
+not-so-shrimple-reshrimpled@not-so-shrimple-(reshrimpled)
+z-core@|Z-核心 (Z-Core)
+crabbers-delight-upgradable-crab-trap
+villager-trading-station@|村民交易站*
+
+
+@litematica-printer-hana|投影打印机 Hana版 (litematica-printer-hana)
+modularshoot-panel@|模块化射击:插件面板 (ModularShoot: Panel)
+depth-crawler-the-horror-of-exploration
+avalonbase
+matrix-speak-to-me@
+targetsindicate|目标血显 (Targets Indicate)
+nineturnring|九转戒 (Nine Turn Ring)
+compass-to-map@
+endsustain@|落幕终焉 (endsustain)
+cobblemarket|方可梦市场 (CobbleMarket)
+
+
+@dialogautologin
+@bettersearch
+wet-farmland-mod@|湿耕地 (Wet Farmland)
+ancient-warfare-2-remastered
+
+flux-networks-ultimate-addon
+@all-powerful_translator_mod|AI全能翻译 (All-Powerful Translator)
+easy-magic-apotheosis-compat
+
+@unnofficial-port-apocalyptic-fortress
+create-beyond-stock-fix|机械动力&超越维度兼容性修复*
+
+red-eyes@|赤瞳*
+cat-idol|猫神像*
+kaleidoscope-hodgepodge@|森罗物语:杂烩*
+ftb-quests-container-integration|FTB检测兼容 (FTB Quests Container Integration)
+the-village-fights-back@
+tgzjdvs-chat@|TGZJDV的聊天 (TGZJDV's Chat)
+project-expansion-arcanum
+rinku@
+pianolib
+@twilight-iris-xe-fix
+anti-spectator-noclip@
+not-so-hardcore@notsohardcore
+es-esoteric-spells-irons-spells-addon|秘法法术 (Esoteric Spells - Iron's Spells Addon)¨@esesoteric-spells-irons-spells-addon|秘法法术 (Esoteric Spells - Iron's Spells Addon) - ,暂时无法正常
+entity-player-compat
+gremlib@
+opencomputers-rebooted|开放式电脑:重启 (OpenComputers: Rebooted)
+railways-untold@
+irons-artifice@|Iron的武备与巧械 (Iron's Arms 'n Artifice)
+potion-coating@potion_coating|药水涂层*
+itemphysic-guns@itemphysicguns
+scannable-jei-compat
+betterblockz-decorz@
+@better-multiworld
+embers-delight@
+immersive-fixes-old-ie|沉浸工程修复 - 旧版 IE (Immersive Fixes - Old IE)
+my-nethers-delight-fix@
+@kaleidoscope-donkey-meat-reborn|森罗物语:驴肉重生 (Kaleidoscope Donkey Meat Reborn)
+cdna@
+@presence-footsteps-lite|脚步声 Lite (Presence Footsteps Lite)
+@qqbot
+dungeon-train@|地牢列车 (Dungeon Train: A Lore-Rich Roguelite RPG Adventure)
+tacz-accessory-table|TaCZ配件桌 (TaCZ Accessory Table)
+
+findme-cobblemon|找到我:方块宝可梦 (FindMe: Cobblemon)
+
+touhou-maid-mine-together|车万女仆:一起挖矿 (Touhou Maid: Mine Together)
+
+@sable-fix-mod|Sable:复制修复 (Sable Fix Mod)
+
+
+
+
+villager-inventory-viewer
+dimensional-depths-rexplored
+oneworld@|三界合一 (oneworld)
+old-debug-rendering@
+falling-meteors-remaster
+ae2-search-optimization|AE2搜索优化 (AE2 Search Optimization)
+grotesque-steve-safety-edition
+@starrailexpress|开拓星穹谋杀案 (StarRailExpress)
+stoneycore@
+ic2-nuclear-external-cooling|核电外置冷却 (IC2 Nuclear External Cooling)
+food-enchanting-table|食物附魔台 (FoodEnchantingTable)
+xmly-enchantmentstooltip@
+kenshicraft
+knights-and-heraldry@
+
+@curiousmobs|万物皆饰 (Curios Mobs)
+
+irons-spells-x-electroblobs-wizardry-redux
+
+minecraft-dungeons-sands-temples
+@ndpreforged-mod
+device-lock|设备封禁*
+itemban|物品封禁*
+dysoncubeproject-addon|戴森立方计划附属 (Dyson Cube Project Addon)
+@moemusic
+drawing-board@|画板*
+
+
+
+
+
+simple-card-memo|简易备忘录*
+massive-cells-ae2
+infinite-lava-cell-ae2
+tiny-cells-ae2
+custom-attack|自定义袭击*
+create-buddycards@
+kindred@
+combateventfix@|战斗事件修复 (CombatEventFix)
+strata-rock-bursts
+@coordinate-record-book|坐标记录簿 (Coordinate Record Book)
+sophisticated-atm-tiers
+apothenchantmentmenu-java-apotheosis
+more-create-burners-with-ember-burner@
+ntge-bobfluidtranslator
+create-transit@|机械动力:跨境转运 (Create: Transit)
+@-titanium-|钛 (Titanium)
+
+
+power-gems-mod
+sortscroller@sort-scroller
+gt-exoskeleton-legs
+
+halfmasa@
+recasting2|重铸2 (Recasting 2)
+wings-2|翅膀 2*
+@dabaojianspracticaltools|大宝剑的实用工具(dabaojian's practical tools)
+confluence-lootr|汇流来世Lootr兼容*
+poopsky-flyimpact|空中厕所:蝇趴 (PoopSky: Flyimpact)
+
+
+tfc-debark@
+nbs-player
+create-routes@|机械动力:路線 (Create: Routes)
+
+
+
+ender-chest-persistence@
+adventure-item-names@adventureitemnames
+adventure-item-stats@adventure-items-stats
+genesis-an-origins-addon
+create-lift-n-load@
+create-overpressure@createoverpressure|机械动力:气动物流 (Create: OverPressure)
+big-tires@
+create-rolling-tones@
+
+emf-compat-immersive-melodies@|实体模型特性兼容:沉浸式奏乐 (EMF Compat: Immersive Melodies)
+emf-compat-not-enough-animations@not-enough-animations-emf-compat|实体模型特性兼容:更多动画 (EMF Compat: Not Enough Animations)
+emf-compat-irons-spells-n-spellbooks@|实体模型特性兼容:Iron的法术与魔法书 (EMF Compat: Iron's Spells 'n Spellbooks)
+emf-compat-supplementaries@|实体模型特性兼容:锦致装饰 (EMF Compat: Supplementaries)
+aeronautics-modernui-compat@|航空学:现代化UI兼容 (Aeronautics: ModernUI Compat)
+
+emf-compat-carry-on@|实体模型特性兼容:搬运 (EMF Compat: Carry On)
+emf-compat-quark@|实体模型特性兼容:夸克 (EMF Compat: Quark)
+create-cosmonautics-expansion@
+create-aeronautics-discovery@
+emf-compat-exposure@U71mw0ra|实体模型特性兼容:拾光定影 (EMF Compat: Exposure)
+emf-compat-watut@|实体模型特性兼容:WATUT (EMF Compat: WATUT)
+emf-compat-tacz@|实体模型特性兼容:永恒枪械工坊零 (EMF Compat: TACZ)
+create-parallel-tracks
+create-liberate@|机械动力:解放斗士 (Create: Liberate)
+create-heat-pipe|机械动力:导热管 (Create: Heat Pipe)
+createbettercoal@createbetter-coal|机械动力:更好的煤炭 (Create: Better Coal)
+create-schematicannon-auto-cutting|机械动力:蓝图炮自动切石 (Create: Schematicannon Auto Cutting)
+functional-storage-js
+create-railway-automation|机械动力:铁道智行 (Create: Railway Automation)
+
+create-steam-ages|机械动力:"蒸汽"时代 (Create: "Steam" Ages)
+create-big-cannon-autogun-revolution@create-big-cannon-autogun-re|机械动力火炮:机炮革命
+
+rollingcats-transit-expansion@|滚猫交通扩展*
+
+
+
+touhou-little-maid-senju|车万女仆:千手女仆 (Touhou Little maid:senju)
+piggyback-legacy
+
+
+macaws-betters@
+@dimension-locker|维度锁 (Dimension Locker)
+@PG1zrN9b
+the-joy-of-tinkering@
+world-alive@
+
+twilight-boss-respawn|暮色Boss重生*
+alphaprotocol@alpha-protocol
+@vertical-half-brick|竖半砖! (KC Vertical Half Brick)
+colored-redstone-reborn@
+thaumic-energistics-interaction|神秘能源交互*
+better-removal
+netmusic-kugou@netmusic_kugou|网络音乐机:酷狗概念版 (NetMusicNeedKuGou)
+perfect-plushies@
+epiphany-journal@
+@nti-modern-impression-lerian-nature|NTI-现代印象-灵耶自然 (NTI-Modern Impression-lerian nature)
+realistic-world-gen-revived|真实的世界生成:重生 (Realistic World Gen: Revived)
+
+railcraft-reborn@
+
+
+web-slinger
+wandscape|魔法小镇*
+goety-owned-null-guard-fix|诡厄巫法召唤物崩溃补丁*
+pattern-checker|样板检测工具*
+slashexpansion
+
+decorblock
+starfall-core|沉星行旅 (StarFall: Core)
+mekanism-me-integration
+hextech-augments|海克斯强化*
+general-tools@|通用工具*
+dungeons-content-addon@dungeons-content-plus
+natrium-mob-naming-utilities|Natrium生物命名实用*
+
+actinium-1-12-2-optimization
+kamitesque
+vibrancy@
+purification-totem|净化图腾*
+@ae2-vm|AE2 合成虚拟机 (AE2 VM)
+
+gui-commands
+ae2-texture-updater
+maid-restaurant-storage@maid-restaruant-storage|女仆餐厅:储存 (Maid Restaurant: Storage)
+reneighborly@
+astral-dice@|星之骰戏*
+@fungal-infection-cataclysm|真菌感染:灾变 (Fungal Infection: Cataclysm)
+kaleidoscope-immersive-eating|森罗物语: 沉浸式品尝 (Kaleidoscope: Immersive Eating)¨@immersive-eating|森罗物语: 沉浸式品尝 (Kaleidoscope: Immersive Eating) - 正在审核
+mcr-blocks-fix
+@better-wither
+crazyae-nyonification|疯狂的AE桥接器 (CrazyAE Nyonification)
+
+
+custom-apotheosis-bosses|自定义神化BOSS (Icy Apotheosis Boss)
+@particledrawing|粒子绘制器 (ParticleDrawing)
+zconfig@
+souls-combat-hud@
+revo-ui|焕新UI (Revo UI)
+@big-shot-lib
+buff-particle-remover|第一人称药水粒子效果移除*
+@worldreset-fabric
+jade-tetra
+@fmbautofishing|FMB 自动钓鱼 (FMB Auto Fishing)
+
+kubejs-assets-override|KubeJS 客户端资源覆盖 (KubeJS Assets Override)
+modern-morph@
+mc-modsiance-netherite-monstrosity@alliance-netherite-monstrosity
+fungal-infection-spore-ai|真菌感染:孢子 AI接入 (Spore AI)
+
+mekanism-magic|通用魔法*
+@better-pie-chart
+@custom-client-brand
+@old-name-tags
+@no-chat-clear
+@map-rendering-disabler
+@resource-pack-profiler
+@no-see-through-text-displays
+kings-monsters
+
+mmce-more-bus@|MMCE:更多总线 (MMCE More Bus)
+simple-structure-desert
+goety-invasion|诡厄侵扰 (Goety & Invasion)
+respawn-recap
+
+iron-tanks-community-edition@irontanks-community-edition|更多储罐社区版*
+buildcraft-community-edition-localizations@|建筑社区版:本地化 (BuildCraft Community Edition: Localizations)
+@mob-rate|生物倍率 (Mob Rate)
+souls-like-bosses@
+deadly-guardians
+exp-ores-kots|经验矿石-耕云钓月版 (Exp Ores KOTS)
+third-person-death-effect@
+player-hurt-number|玩家受伤数字显示*
+conflux-map
+polymorph-pages|多态合成翻页支持*
+laser-eyes@
+symbiote-a-bonding-experience@
+@tp-players
+beyond-craftlines|超越维度:合成链*
+@water-in-nether
+
+holy-crusade|神圣征伐*
+ultimateminepiece
+maid-restaurant-now-open|女仆餐厅:营业中 (Maid Restaurant: Now Open)¨@maid-restaurant-business|女仆餐厅:营业中 (Maid Restaurant: Now Open) - 在审核
+range-harvest@|快速丰收*
+@afk-camera
+@anvilcraft-fe-grid|铁砧工艺:FE电网 (AnvilCraft FE Grid)
+confluence-infernum@
+dlss-style
+modern-baby-animals|现代宝宝*
+darys-decoratives-curtains
+totem-expansion
+ae2-emi-shift-craft
+initial-dim-choice|初始维度选单*
+
+
+
+
+fresh-armor-bar@
+@strinova-hud|卡拉彼丘HUD (Strinova (CalabiYau) HUD)
+cgm-ununofficial|MrCrayfish的枪:非非官方版 (MrCrayfish's Gun Mod: UnUnofficial)
+irons-spells-light-pollution@|铁魔法:光污染 (Iron's Spells: Light Pollution)
+twilightteleport@
+scp-610-flesh-that-hates@scp-610,-flesh-that-hates
+adventurebags|冒险背包 (AdventureBags)
+greedbundle|贪婪之袋 (GreedBundle)
+big-xp-drops
+talisman-jackiechan@|符咒*
+calendar|日历 (Calendar Mod)
+et-futurum-requiem-reforged|把未来带回现实:重铸版*
+
+ender-terg
+
+farmers-delight-meal-mastery@
+nfu-library
+text-display-pen|自定义文本展示实体 (Text Display Editor)
+see-through-my-mount
+
+@progression-reshuffled
+
+
+embers-re-ignited@|余烬再复刻版 (Embers Re-Ignited)
+@client-recipe-fix|客户端配方修复 (Client Recipe Fix)
+
+rustic-pipes
+cosmiclib
+touhou-shrine-maiden@|幻想巫女祭*
+
+
+reflyky-addon-aot
+
+
+
+@dismantle-table|拆解台 (Dismantle Table)
+momentum-limit|除其速势*
+
+@sprintable
+
+@jsonwrangler
+
+
+mekanical-create@|通用动力*
+
+bren-reforged-unofficial@
+more-lectern-variants-unofficial|更多讲台非官方移植*
+exp-ores@|经验矿石*
+opencomputers-ii-modern
+echostruct|残墟遗响*
+
+sarkazs-furnace-side-fables|无终奇语 (Sarkaz's Furnace Side Fables)
+ink-scale|墨鳞*
+mob-horde|游荡集群*
+
+
+spice-of-overhaul@
+radium-re-reforged
+show-dimension-in-name
+jei-malum|JEI 灵灾 (JEI Malum)
+spider-overhaul@
+
+
+asian-wildlife
+south-american-wildlife
+north-american-wildlife
+
+
+
+aeronautics-gravity-visualization|航空学:重力可视化 (Aeronautics:Gravity Visualization)
+cannibalvillages@cannibal-villages
+
+interactivestuff@
+lib-5555ff
+narwhal-mod
+digital-storage-cloud|汤姆的简易存储:云上加仓*
+
+building-gadgets2-ae2-addon|建筑小帮手AE2插件 (Building Gadgets2 AE2 Addon)
+sporeai|孢子AI (SporeAI)
+fis-cordyceps|真菌感染:孢子 虫草 (FIS Cordyceps)
+nenus-pop-plushies
+
+thermal-more-integral-components@
+recipehandlerragecraftedition|合成冲突消除:重铸版 (No More Recipe Conflict Reforged)
+keymap-viewer
+
+
+
+multitools-enhanced@multitool-enhanced
+
+cc-my-peripheral-extender@|外设扩展器 (Peripheral Extender)
+hbmtweaks
+
+pinyin-search-for-sophisticated-backpacks|精妙背包拼音搜索 (Sophisticated Backpacks Pinyin)
+relog-health-fix|退出重进血量修复*
+snow-imprints@
+more-difficult-wither-storm|更难的凋灵风暴*
+jcraft-additions@
+
+farmers-delight-26-neo-ver|农夫乐事 26 Neo 版 (Farmer's Delight 26 Neo Ver)
+flans-mod-ultimate-2
+calamitymeter|灾厄怒气与肾上腺素 (Calamity Meter)
+
+
+
+
+mixauth
+
+just-enough-drops|想查就查*
+stopcheat
+@item-editor
+eden-ring-reforked@
+tusk-jcraft-addon@tusk-act-4-(jcraft-addon)
+spin-jcraft-addon
+
+
+clientcommands-neoforged@
+tetra-material-reclamation|Tetra材料返还*
+@twilight-mobs-loots|暮色生物战利品 (Twilight Mobs Loots)
+mekanism-more-multiblock
+
+
+mythicbotany-legacy|神话植物学:遗产 (MythicBotany: Legacy)
+torchautocraft|火把自动合成 (TorchAutoCraft)
+custom-gun-continued@|自定义枪械永续*
+cgc-config-addon@|自定义枪械永续配置扩展 (CGC Config Addon)
+@fluorescentink|荧光墨水 (Fluorescent Ink)
+
+
+ascendanttreasures
+collection-book@|收藏册/收藏之书*
+goety-astrology|诡厄巫法:星象学 (Goety: Astrology)
+better-portals-refitted
+jinzai-street-props|津仔的街道设施 (JINZAI Street Props)
+@gtmadvancedhatch-novafork
+@sparse-vertical-expansion|稀疏垂直扩展 (Sparse Vertical Expansion)
+cubic-reworked
+multicore-helper-coffee-expansion
+
+weeping-angels|哭泣天使*
+
+
+
+
+
+
+applied-energistics-quantization@|应用能源:量子化 (Applied Energistics: Quantization)
+
+vmp-veinminerplus@veinminer-pro|连锁挖矿加强版 (VeinMinerPlus)
+lootr-multiplayer-only|仅多人战利品*
+vitrail-shaders@
+emc-motor|EMC 马达 (EMC Motor)¨@emcmotor|EMC 马达 (EMC Motor) - 在审核
+fangs-n-claws@
+chunkumulator@
+
+
+
+enchantment-configurator@enchantment-config
+
+
+graveless@
+
+unofficial-tacz-renovated|永恒枪械工坊:零:焕新 (TaCZ: Renovated)
+howling-werewolf|月厄狼人*
+neosync@|新克隆 (NeoSync)
+midnight-nightmares@
+
+
+@tab-compass
+magnetization
+lucis@
+azotosaurus-freesky-dragon-survival-add-on|氮沧龙 (Azotosaurus Freesky Dragon)
+tml-avaritia-addon@tml_avaritia_addon|车万女仆:无尽贪婪 (TML Avaritia Addon)
+
+
+
+useful-projecte|更好的转化桌 (Useful ProjectE)
+
+macaws-for-terrafirmacraft-reborn
+reportality@
+touhoulittlemaid-shogi|车万女仆:将棋附属 (TouhouLittleMaid Shogi)
+desert-expansion
+
+es-entomology-spell@esentomology_spell|铁魔法:昆虫学 (Entomology Spell)
+
+@chinese-anti-japanese-war-equipment
+
+
+create-sifting-create-fabric-6-0-8-1@create-sifting-fabric-updated|机械动力:筛子 - Create Fabric 6.0.8.1 (Create Sifting — Create Fabric 6.0.8.1)
+@cursed-breeding
+
+@judgement-bird|审判鸟 (Judgement Bird)
+
+
+@rick-technology|瑞克科技 (Rick Technology)
+
+
+usefull-cows-much-more-cows-mod
+
+a-better-fishing@better-fishing-system
+enchanted-fishing-line@
+no-tree-punching-no-additional-features|无树可撸(无额外功能版) (No Tree Punching (No Additional Features))
+mobends-x-cnpc-compatibility-layer
+mango-fruitmc|芒果 (Mango)
+homestead-sell-veggies|多多卖菜*
+animal-husbandry@animalhusbandry
+
+kaleidoscopechinesefood-refabricated|森罗物语:国味——重织 (Kaleidoscope ChineseFood Refabricated)¨@kaleidoscopechinesefood-refabricated|森罗物语:国味——重织 (Kaleidoscope ChineseFood Refabricated) - 无法访问,可能为
+
+@opticores
+ether-craft|以太工艺*
+jinghui2|镜回2 (JingHui 2)
+rpgdamageoverhaul@rpgdo
+dreamdisplays
+matter-orb
+fps-overlay@fpsoverlay|信息叠加层 (Info Overlay)
+onegunlifetime@|一人一枪一辈子 (One Gun Lifetime)
+
+applied-exchange
+
+
+
+
+tagtooltips@tag-tooltips|标签提示框 (Tag Tooltips)
+mo-creatures-renewed
+perfect-birbs@
+
+karma-in-undertale@|罪业 (Karma)
+mathmaster@|数学大师
+turnkey-factory
+
+alexs-caves-renewed
+
+
+@twilight-ruined-portal|暮色废弃传送门 (Twilight Ruined Portal)
+
+
+simplesulfur@
+visible-energy
+
+@mpkmod-2
+cobblemon-emi
+
+touhou-little-maid-carry-on|车万女仆:酒狐举高高 (Touhou Little Maid: Carry On)
+tetra-tool-changer|Tetra工具等级编辑器 (Tetra tool changer)
+takeitout
+create-compactmachinespor
+spell-forge-for-electroblobs-wizardry-redux
+universal-control-overlay|通用扳手控制*
+tfmg-community-edition@|机械动力:工业长路 社区版 (Create: TFMG Community Edition)
+create-xaeros-map
+
+create-balloon@|机械动力:气球*
+create-colored-connections@|机械动力:彩色连接线 (Create: Colored Connections)
+explorers-compass-enhance
+enhance-now|强化!就现在! (Enhance now!)
+network-tool-plus@
+not-enough-dataenergitic-and-ae2lighteningtech|Not Enough DataEnergitic and AE2LighteningTech Incompatible Fix - 核心¨not-enough-dataenergitic-and-ae2lighteningtech-service|Not Enough DataEnergitic and AE2LighteningTech Incompatible Fix - 前置
+@create-gl4es-stencil-fix
+gmcs-useful-gadgets|粥粥的实用物品 (GMC's Useful Gadgets)
+modpedia
+maid-file-manager|车万女仆档案(迁移)管理器*
+
+littlemaidsomeinstructions@|车万女仆:一些指令 (Little Maid: Some Instructions)
+backpack-side-gui-kots|精妙背包扩展GUI - 耕云钓月版 (Backpack Side GUI KOTS)
+slashblade-return-journey|拔刀剑:归途 (SlashBlade: Return Journey)
+export-language-keys-for-compasses|为指南针导出语言键 (Export Language Keys for Compasses)
+quizcraft-pro
+
+cnpc-obj-models-compat
+cnpc-immersiveboss
+@firecracker|鞭炮 (Firecrackers)
+limitless-logistics
+create-better-belt@|机械动力:更好的传送带 (Create: Better Belt)
+strife-and-calamity@|战伐祸乱 (Strife and Calamity)
+forgiving-item|仁慈的物品*
+me-building-gadgets@gadgetsmenetwork
+redstone-flight-control-set@|红石飞控组件*
+voxkbd@|沃克键盘 (VoxKbd)
+alexs-mobs-delight-neoforge|Alex 的生物乐事 NeoForge 版 (Alex's Mobs Delight NF)
+craftflow@craftfolw|合成流 (CraftFlow)
+the-impossible-library-new
+
+ice-and-fire-dragon-seeking-staff|冰火传说:寻龙杖 (Ice and Fire Dragon Seeking Staff)
+
+
+terra-plate-extension
+
+xiaozhitpa@|小志的TPA (Xiaozhi TPA)
+@all-is-random|一切皆随机 (All Is Random)
+
+ancient-tech|远古科技*
+@third-person-nametags|第三人称玩家名称 (Third Person Nametags)
+@daysplayed|游戏天数 (Days Played)
+true-adaptive-music@
+fused-critical|统合暴击*
+nimble-pattern|灵巧样板*
+let-s-do-bugs-fix
+@enigmatic_extra|神秘遗物:附加 (Enigmatic Extra)
+music-triggers-new
+scp-facility@
+advanced-core-info@
+playerblockstate|玩家区块状态
+vlorant|无畏契约 (Valorant)
+immortalitytotem|永生图腾 (Immortality Totem)
+@extractinatorforked|提炼机(分支版) (ExtractinatorForked)
+simple-rpg
+portable-clicker|随身连点器*
+mc-paint-rebirth|涂画 (MC Paint:Rebirth)
+artifacts-delight
+subnautica-ember
+frost-dragon|寒霜龙*
+
+@me-spawner|ME刷怪笼 (ME Spawner)
+eeeabs-mobs-lost-content-addon
+epca-pestilence-of-the-marrow|归寄-疫至深髓 (EPCA-Pestilence of the Marrow)
+apocalypse-tnt
+metal-upscaler
+draw-the-world|手绘世界*
+
+hdd-mode|HDD模式 (HDD Mode)
+
+structure-no-overlap|阻止结构重叠*
+@planifolia
+tacz-dual-wield
+mana-transform|魔力转换*
+
+lootr-break-to-loot|Lootr:破箱取宝 (Lootr: Break to Loot)
+@the-aurorian-reborn|极光幽境重生 (The Aurorian Reborn)
+better-end-sky-retro|更好的末地天空:复古*
+emi-structures@
+mtr-psd-lcd
+auto-tosser|自动投物器*
+backport-update
+legendary-no-more|传奇不再*
+
+
+
+kaleidoscope-bountiful-fares@kaleidoscope-bountifulfares|森罗物语:丰饶食记*
+
+roxy@
+unseen-world@
+botany-pots-renewed
+ifc-integrations@
+bleed-zone-7|七号区 (Bleed Zone)
+first-class-flying@|头等飞行*
+one-dimension@
+
+
+thunderhead
+new-armor-system@|新护甲系统*
+codxlib@
+astages-ftb-quests@
+mob-spawner-tweaks|刷怪笼控制与机制修改 (Spawner Tweaks)
+animalia-exotica@animalia-bestiary
+
+visual-iron-mobs-edit@vimevisual-irons-mobs-edit|全民普法/可视化铁魔法生物编辑器 (Visual Iron's Mobs Edit)
+the-twilight-moonshine|暮色月光*
+anka-mobs|安卡顽敌*
+walk-reveal
+dbes-spark-engine|星火引擎 (DBE's Spark Engine)
+@simple-text-chat|简单的文本聊天 (Simple Text Chat)
+tinkers-part-reclaimer|匠魂部件返还*
+
+the-corners-renewed
+@animated-typing
+dawn-star@|黎明之星*
+@kubejs-studio
+rock-n-stone@
+chat-highlight-sound@chat-highlight-n-sound
+special-effect-text@|特效文本*
+
+focus-value|专注值*
+
+glass-bridge
+map-3d-usseewa
+
+beecrasy|蜂会*
+skillplants|技能:位面 (Skill Plants)
+mythical-extension
+memoryjournal|旅行手账 (MemoryJournal)
+realistic-ore-veins
+ncb|新世纪道路方块 (New Century Road Block)
+
+immersive-portal
+immersive-portal-irons-spells-n-spellbooks-addon|沉浸式传送门法术 (Immersive Portal - Iron's Spells 'n Spellbooks Addon)
+mekanism-expand|通用机械:拓展 (Mekanism:Expand)
+
+@mtr-fare-pro
+lingxiis-mtr3-backport-pack|泠惜的MTR拓展 (Lingxi's MTR Transport Extension)
+@pingnametags
+@ponder-plus-plus
+rockore|开山掘石 (RockOre)
+trade-picker@
+
+benchmark|性能基准测试*
+rings-of-ascension-reborn|提升戒指:重生 (Rings of Ascension:Reborn)
+
+real-time-craftingtable|实时工作台 (Real-time CraftingTable)
+cnpc-compatible-with-kingdomcome-combat|CNPC兼容:天国的战斗 (CNPC compatible with Kingdomcome Combat)
+quick-craft
+tetrawear
+etg-crystal-engineering|ETG晶体工程 (ETG Crystal Engineering)
+
+tinkers-construct-filter|匠魂材料筛选*
+faketimemod|客户端时间 (FakeTimeMod)
+energy-tower|能量塔科技*
+hec-veinmining|『HEC』恒创-功能全面的连锁采集 (HEC VeinMining)
+
+enigmatic-liberator|神秘遗物:解放者*
+survivors-arsenal
+
+devil-mine-craft
+
+shaderpack-kaiguan|光影控制器 (Shaderpack KaiGuan)
+block-drops-tweaker
+deathlogplus@
+attribute-modify@
+frutigeraero-craft@frutigeraero_craft
+
+
+armadillo|犰狳 1.12.2*
+yujian-craft|御剑工艺*
+
+
+@create-patina|机械动力:铜染光阴 (Create: Patina)
+mite-underworld|MITE:地下世界 (MITE:Underworld)
+@better-sign|更好的告示牌 (Better Sign)
+
+
+eye-cross@|眼之交叉*
+mikus-leek-ryouri@|初音的葱料理 (Miku's Leek Ryouri)
+transparenthud|可透明的用户界面 (Transparent Hud)
+
+frost-ship
+ultra-sprite-kaiju-battleground|奥特幻影大怪兽格斗*
+youkaishomecoming-curios-transfer-the-fix|妖怪们的归家饰品跨维度修复 (Youkaishomecoming Curios Transfer the Fix)
+particle-shield|粒子屏蔽*
+
+frutigeraerodecor@
+@dimension-level-data
+haven-cobble-generators
+applied-generators@
+cataclysm-x-yungs
+
+stellarview-redshift@
+tech-ascension-stellar-age@techascension|科技飞升 (Tech Ascension)
+
+@lambda
+destruction-infection|毁灭感染*
+
+cards-legends-of-the-three-kingdoms-basic|卡牌:三国杀(基本牌) (Cards: Legends of the Three Kingdoms(Basic))
+cards-legends-of-the-three-kingdoms-character|卡牌:三国杀(武将牌) (Cards:Legends of the Three Kingdoms(Character))
+cards-legends-of-the-three-kingdoms-identity|卡牌:三国杀(身份牌) (Cards: Legends of the Three Kingdoms(Identity))
+hg-keyradial|冲突按键二级菜单 (HG KeyRadial)
+
+originfall-cataclysm|源石计划*
+
+harvest-festival-replanted|丰收物语:非官方版 (Harvest Festival-Unofficial)
+@simudelight|模拟大都市:农夫 (SimuDelight)
+
+
+modern-overclock-for-gtm|现代化超频 (Modern Overclock For GTM)
+sable-stop-now|哦不快停下 (Sable: Stop Now)
+create-firefighting-additions@|机械动力:消防附加 (Create: FireFighting Additions)
+@helium_client
+@i18nautoupdatemod
+simpledusts
+@usage-ticker-reloaded|物品计数器重制版 (Usage Ticker Reloaded)
+kubejs-eyejs
+fated-inventory@
+bottled-milk
+
+
+slag-n-embers@
+real-time-enchantmenttable|实时附魔台 (Real-time EnchantmentTable)
+
+
+@blockdiff|区域快照 (BlockDiff)
+
+touhou-little-maid-personality|车万女仆:性格 (Touhou Little Maid - Personality)
+little-maid-more-action|车万女仆附属:更多动作*
+tlm-speak-human-language|车万女仆:说人话
+
+
+arsarms-player-subject|ArsArms:玩家主体 (ArsArms: Player Subject)
+industrial-crops|尖端工业化农作物*
+grounded-electroblobs-wizardry-redux
+prefab-goety-ritual-altars|预制建筑 - 诡厄巫法祭坛 (Prefab - Goety Ritual Altars)
+skeleton-spell|可施法骷髅 (Skeleton With Spell)
+l-ender-s-cataclysm-x-t-o-magic-n-extras
+
+
+@serendimodguarder
+emerald-edition@
+dabaojians-dummy|大宝剑的假人 (Dabaojian's Dummy)
+@endefinder|末影探索者 (Endefinder)
+@sinkhole-restorer
+
+@death_back
+gregtech-calculator-board
+@equipment-inscriber|装备刻录仪 (Equipment Inscriber)
+cave-roamer|洞穴漫游者*
+valemetry|值域协议*
+neofuture
+velvet-advanced-alloys
+neko-adventure|猫的旅途*
+better-gold-expansion|更有用的金 新约*
+
+
+world-painter
+rphone
+cave-game
+generic-henshin|通用变身*
+biolith-x-mcreator-biome-fix
+mcphone
+curios-pre-calculate-available-slots
+wikievery|万象通揽 (WikiEvery)¨@wikievery|万象通揽 (WikiEvery) - 正在审核
+
+kamen-rider-zeztz
+viafabricplus-bedrock@
+
+@muisc-disc|音乐唱片 (Music Disc)
+torcherinoae|AE加速器 (Torcherino AE)
+
+tinkers-jei-prefilter
+@record-able
+shovel-something-offhand@shovel_somethingoffhand|铲物,双手合一 (Shovel Something/Offhand)
+target-dummy-dependency-fix|试验假人前置修复*
+diamond-in-the-rough
+sfm-factory-studio|SFM 智造工坊 (SFM Factory Studio)
+
+@qiusoptimization|Qiu的优化 (Qiu's Optimization)
+bc-lightning-terrain|可视化地形节点编辑器 (LightningTerrain)
+advanced-worldgen-info
+spellcaster
+
+
+@cosmonautics-deep-air
+ts-modify
+block-outline-customizer@
+@ironsspellbooks-ui|铁魔法UI (ISS UI)
+curios-swich|饰品套装切换 (Curios Set Switcher)
+slashblade-reborn|SEAC拔刀剑附属 旧梦重铸 (slashblade legacy compat)
+
+apex-arcana-irons-spells-n-spellbooks-addon
+@flaming_remastered|火焰熊熊:重制版 (Flaming: REmastered)
+bigger-stacks-2|更大堆叠2*
+
+irons-spell-smithing-template-addon|铁魔法:锻造模板附加 (Iron's Spell: Smithing Template Addon)
+botania-biomes@biotania
+codechickencore-1-8-9
+notenoughitems-1-8-9
+
+
+mekanismceu-qio-storage|MekCeu QIO 存储 (MekanismCeu-QIO-Storage)
+
+
+create-big-cannons-ballistic-computer|机械动力火炮:弹道计算机 (Create Big Cannons: Ballistic Computer)
+mithril-banner-protection|秘银旗帜保护*
+ancient-remnants
+@fourleafcrystal|四叶水晶 (Four Leaf Crystal)
+fog-fix-legacy@
+maid-musketeer
+
+mod-access-control@|模组准入控制*
+terracliff@
+
+damage-stats|伤害溯源*
+slashblade-resharped-recipe-fix|拔刀剑:合成表错乱修复补丁 (SlashBlade Resharped Recipe Fix)
+lei-lazy-enough-items|懒人物品管理器 (Lazy Enough Items)
+@xehtascing
+@hexsbm
+hexxy-attributes@hexxyattributes
+@hex-machina
+ioticblocks@
+@phlexiful
+@hexshield
+@hexchanting
+@hexdeco
+@slate-works|石板工程 (Slate Works)
+caduceus@
+hexthings@
+@yaha
+hexxyplanes@
+@hexboard
+hexweb@
+@hextext
+@abitmorehex-recasted
+@kvha
+@hexportation
+@heartxxy
+@help-from-hexxy
+@hexic
+@iotaworks
+hexcessible@|咒法通达*
+@hexpats
+@hexthingy
+@merlingsgrace
+hexstruction@
+hierophantics@
+complex-hex@
+@hex-casting-media-display
+@lapisworks|青金工程 (Lapisworks)
+@hex-spell-wheel
+@lesser-teleport
+@hexdentity
+cinnamoroll-friends|玉桂狗之友*
+mekanisms-modern-industrialization
+hgs-backpack-smelter|打包烧制 (HG's Backpack Smelter)
+hexjsneo@
+
+
+apoli-stream-leak
+
+rail-placement-fix@|铁轨放置修复*
+scorchedgunsreforged-addon|Scorched-Guns-2-Flintlocks 备弹配置 (ScorchedGunsReforged-Addon)
+gunsmiths-gadgets-n-gizmos
+boids-reforged
+joy-of-painting-reforged|绘画之乐重铸版 (Joy of Painting Reforged)
+sink-faster
+codechickenlib-1-8-9
+toastsweapons|吐司的武器 (Toast's Weapons)
+scalable-lux-x-sable-compat
+simplehats-lite|简单帽子:轻量版 (SimpleHats-Lite)
+custom-mob-spells|丘丘人也要学魔法*
+enigmatic-armor@|神秘护甲*
+prolong|效果延长*
+
+better-fox-trot-brew|更好的狐步酿香*
+auto-librarian
+
+
+more-coal-craft|更多的煤炭工艺*
+
+universal-talent-editor|通用可视化天赋编辑器*
+
+
+bdlib-rescaled
+cys-attributes
+jei-unofficial
+@quadcasting
+@pointless-machine
+@minihex
+hexssence@
+@hexshadowing
+@hexvidia
+@almightly-staff|万法之杖 (Almightly Staff)
+@focalworks
+@hexoncommand
+atomchat@|原子聊天 (AtomChat)
+scorched-guns-scg-extra@
+
+bread-reborn-reborn@|面包重生:重生 (Bread Reborn: Reborn)
+somnia-awoken-reforged|梦醒时分 - 重制 (Somnia-Awoken-Reforged)
+
+create-fly-steam-n-rails
+nointernet|禁止联网 (NoInternet)
+
+
+@pigmentum
+bee-in-a-jar-reborn|罐中蜜蜂 — 重生 (Bee in a Jar - Reborn)
+beyondinfinity|超越无限 (BeyondInfinity)
+compressorfix|无尽奇点压缩机修复 (CompressorFix)
+mahoraga
+spellbooks-of-twilight-irons-spells-x-the-twilight
+irons-spells-n-spellbooks-elden-ring|Iron的法术与魔法书:艾尔登法环 (Iron's Spells 'n Spellbooks: Elden Ring)
+who-goes-there|谁在那! (Who Goes There?)
+wine-cabinet-compat|森罗Vinery酒柜兼容 (wine-cabinet-compat)
+auto-window-size@autowindowsize|自动窗口大小*
+enchantlib-example
+silent-gear-catalog|寂静装备目录*
+@hexnbt
+@hexintent
+@hexpose
+@stackpatterns
+teekaspaste@
+
+black-ops-armor-plate|黑色行动防弹插板 (Black ops Armor Plate)
+simple-boss-damage-cap
+murmol@murmol-mod|幻星之咒*
+
+
+eai-goety-patch|阻止使徒能力外泄!/ Enhanced AI & Goety 补丁 (EAI & Goety Patch)
+
+do-another-barrel-roll@
+star-fantasy-library
+
+
+cgc-compat-packloader@|自定义枪械永续兼容:包加载 (CGC Compat: PackLoader)
+matesignal-unofficial
+cgc-compat-machinemax@|自定义枪械永续兼容:极械工坊 (CGC Compat: MachineMax)
+framed-maps-fix@
+onlytinkeralmost|几乎只有匠魂 (OnlyTinkerAlmost)
+kineticcore
+universal-preview|通用预览*
+mekanism-heated|通用机械:热力学 (Mekanism: Heated)
+cobblemon-player-xp-share|方块宝可梦:玩家经验共享 (Cobblemon Player XP Share)
+mcphone-apps-extension
+
+@fresco
+polymorph-legacy|多态合成-怀旧*
+
+spirit-pearl-and-demon-pill|灵珠与魔丸 (Spirit Pearl and Demon Pill)
+
+apollyoncat|亚小猫 (ApollyonCat)
+
+
+communism-mod-reborn|共产主义重生*
+
+zbw3790s-fashion@3790s-vanilla-style-fashion|3790的时装 (3790's Fashion)
+
+ae2-stuff-rescaled
+
+maid-tech|女仆科技拓展*
+
+silk-road|丝绸之路*
+grand-strategy|大战略 (GrandStrategyMC)
+back-to-greece|重返希腊*
+supporoform
+dragon-mounts-reforged
+dog-reborn@dogreborn|狼复活*
+blood-reborn|血之重生*
+place-skull-on-death
+blow-balls
+death-teleporter
+
+dglib¨@dglib|DGLib - 已停更
+mixintrace-reborn
+defaulted-hotkeys
+
+integrated-core
+shining-champions|闪耀!冠军生物*
+modular-machinery-community-refoxed@|模块化机械:社区版非官方重制版 (Modular Machinery:Community Refoxed)
+pyrologer-and-friends-port
+curse-of-abyss
+applied-oritech
+fancy-tab-sections@fancytabsections
+frameframe@
+tinkers-sort|工匠典序 (Tinkers' Sort)
+kaleidoscope-flora|森罗物语:花香四溢*
+maidassemblyline|女仆流水线 (MaidAssemblyLine)
+tlm-statue-animation@|车万女仆:雕像动画 (TLM: Statue Animation)
+better-disenchanter|更好的祛魔台*
+
+custom-rarity
+tame-ervery-mob@tame-every-mob
+apocalypselib
+
+terror-of-the-spinosaurus-dinosaur-horror
+defense-innovation@defense-innovation-al1s|防御革新*
+carry-on-creative-world|随身创境 (Carry-on Creative World)
+warriorcats-events@warrior-cats-events
+@stamina-dltb
+
+
+
+more-compressed-mek-factories
+more-compressed-mek-generators
+minecamera|我的视角 (MineCamera)
+
+create-magic-blueprint|机械动力:魔法蓝图 (Create: Magic Blueprint)
+really-fast-load
+bossesrise-cinematic-unlock|Bosses'Rise 镜头限制移除 (Bosses'Rise Cinematic Unlock)
+dnfenhance@|装备强化 (DNF Enhance)
+matcha-flavoured-fabric@
+mc-258859@
+bayou-reimagined|长沼蓝调:重新构想 (Bayou Blues: Reimagined)
+compression-upgrade-kits
+sky-island-generator|空岛生成预设*
+wds-selling-bin@
+baochuan-treasure-ships|宝船 (Baochuan - Treasure Ships)
+@lookatplayer
+alexs-caves-continued@
+legendary-shrines
+
+fastchunkgen
+pets-mod@
+perpetual-day-or-perpetual-night|永昼?永夜?*
+@zephyr-hauler
+masiks-puzzle-dungeon@puzzle-dungeon
+i-cant-play-mite-|我不能玩MITE (I Can't Play MITE)
+
+more-infinite-arrows-enchantments|更多的无限附魔书*
+alexs-mobs-continued@
+accessories-compat-vanilla@
+@fox-trot-brew-refabricated|狐步酿香:重织 (Fox Trot Brew (Refabricated))
+izanami|伊邪娜美*
+most-important-question@|史生大事*
+continuity-neoforged@
+@elysium
+
+compact-extreme-reactor|紧凑极限反应堆*
+immersivethunder-reforged@
+lolaccessories|英雄联盟饰品 (LOLAccessories)
+better-advanced-tooltips@
+chemek@|通用化学 (CheMek)
+yes-slashblade|YSM × 拔刀剑重锋 兼容修复 (Yes Steve Model x SlashBlade Fix)
+yes-bsl|BSL 光影 × YSM 兼容修复 (YES_BSL)
+
+enhanced-equipment-display
+dynamic-surroundings-rebirth@
+darwin-soldier|达尔文士兵*
+the-possessive-knocker
+
+extra-dungeons@
+desert-dungeon-dungeonz-addon@
+stackablepotionsplus|可堆叠的药水:强化 (Stackable Potions Plus)
+tinkers-meat-shredder|匠魂绞肉锯*
+mod-menu-forge-by-bogdan-tokarev|模组菜单(Forge) (Mod Menu (Forge))
+betterchunkculling
+create-aeronautics-fade|机械动力航空学:虚化 (Create Aeronautics: Fade)
+catch-the-rainbow|彩虹捕手*
+
+mekanism-combining-factory|融合工厂副输入升级 (MekAddon / Mekanism Combining Factory)
+
+cbr-create-blaze-burner-recipe|机械动力:烈焰人燃烧室配方 (Create: Blaze Burner Recipe)
+
+cape-3d-layers|3D披风层 (Cape 3D Layer)
+
+legendary-inventory
+
+guns-workshop-origins|枪械工坊:起源*
+
+
+ae2-pattern-disk@|AE2样板磁盘 (AE2 Pattern Disk)
+
+user-9k2h8ismc9exbn45-eternal-food|永恒原版食物 (Eternal Food)
+advanced-apples
+flexible-dodge|灵巧闪避*
+@misia-ui|米西娅UI (Misia UI)
+
+carry-on-toggle|搬运开关*
+
+blacksoil-delight|黑土乐事*
+quarkful-delight
+collectors-reap-unofficial-port@
+
+larp-eccentric-tome
+
+goety-starfantasy|诡厄巫法:星翼幻想 (Goety: StarFantasy)
+
+custom-enigmatic-relic|自定义七咒之遗物*
+emerging-technology-hydroponics-community-edition|新兴技术:社区版 (Emerging Technology: Community Edition)
+mebahels-rpg-villager-quests-and-companions@
+damagestats@|伤害统计 (DamageStats)
+
+
+sdm-shop-2
+villagerstradingplus@
+relic-ward|遗境守望*
+mc-phone|MC手机 (MCPhone)
+applied-slash|Slash存储元件*
+
+
+trading-stalls@
+village-shop-system@
+modern-content-backport|现代内容移植*
+eye-of-dragons-reborn|龙之眼:重生 (Eye of Dragons Reborn)
+relics-thirteen-flames
+jaams-weaponry@
+
+
+texture-scaler|自动贴图缩放Mod*
+
+throwabletorches@
+hooked-sable-physics-link|抓钩物理结构兼容*
+cataclysm-curios-edited|灾变饰品槽位修改*
+@primogemcraft|原石工艺:重生 (PrimogemCraftNeo)
+ice-and-fire-rlcraft-modern|冰火传说-RLCraft现代版 (Ice and Fire: RLCraft Modern)
+miguelnetwork|米格尔网络 (MiguelNetwork)
+schematicaplusreforged
+ragecraftmalisisdoors
+
+maldict@|咒邪*
+
+classic-gamerule@
+poopy-cobblemon
+quick-container-tabs@|便捷容器标签*
+mineagent@
+@crosshair-damage-indicator
+bedrock-allow-deny-border
+@villagers-wand
+webshooter
+applied-ember|应用余烬*
+upgrader-items@upgrade-items
+
+
+@createmaxcraft
+
+
+
+durability-display-hud@durability-display-hud-hud|耐久显示 HUD (Durability Display HUD)
+ultimate-difficulty
+cnpc-x-spiritoffight-compatibility
+cinematic-zoom@cinematiczoom-original
+
+mechanical-infection|械器感染*
+tinkers-of-cataclysm|灾变匠魂材料 (Tinkers of Cataclysm)
+rainbow-lotus|彩虹莲*
+twilight-sparks-delight|暮光乐事 / 暮光农家乐 (Twilight Spark's Delight)
+cataclysm-primed-soul-addon-unofficial-work-in
+
+blackannins-drone@|BlackAnnin的无人机 (BlackAnnin's Drone)
+better-ie-coke-oven@|更好的沉浸工程焦炉 (Better IE Coke Oven)
+eosp2p
+more-health-reforged|更多生命:重铸版 (More Health (Reforged))
+fastadvancements
+vulkan-early-loading@|Vulkan 早期加载*
+@nera_jadis
+refugee|难民*
+genshin-moonoracle|原神:月谕圣牌 (Genshin Moon Oracle)
+the-call-of-carmen|卡门的呼唤 (The Call of Carmen)
+manabove|高人一等 (ManAbove)
+create-shining-stage|机械动力:闪耀舞台*
+external-override-model-library@|外置模型拓展*
+simpledifficulty-reforged|坚定意志:重铸版 (SimpleDifficulty Reforged)
+
+continuity-version-fix
+mekanism-empowered-unleashed|通用机械:增强·解放 (Mekanism: Empowered Unleashed)
+conveyor-belt-plus|传送带+*
+industrial-foregoing-extra|工业先锋扩展*
+sanity-renewed-for-tfc@|群峦San值 (Sanity: Renewed For TFC)
+advanced-tfc-info@|高级群峦信息显示 (Advanced TFC Info)
+simple-tfc-ore-sluicing@|简单群峦洗矿 (Simple TFC Ore Sluicing)
+mystian-apiary@
+
+easy-villagers-iron-spells-compat|铁魔法简单村民兼容*
+
+mezzconfiggui@
+mezzconfig@
+snow-waifu-spell-resumed|雪下的誓言·再续 (Snow Waifu Spell·Resumed)
+modernui-unofficial-port|现代化UI非官方版 (ModernUI Unofficial Port)
+storage-consolidator|TOM存储整理*
+
+libtooltips@
+@stardewvalley|Stardewvalley星露谷 (Stardewvalley)
+mds-api@
+golden-tweaks@goldentweaks|金子修改*
+spartan-shields-fabric@|斯巴达之盾 [非官方版] (Spartan Shields [Unofficial])
+fontswap@
+sync-fix
+integrated-mowzies-mobs@
+small-plane|小飞机 (SmallPlane)
+timeless-echoes
+cargo-ghast|货运善魂*
+fancy-notify@
+overshot|蓄力刚射*
+command-adjust|指令调整*
+@usedtotemmessage
+totemdoll@|图腾娃娃 (TotemDoll)
+icy-l2hostility-small-extra|莱特兰恶意小拓展 (Icy L2Hostility Small Extra)
+
+
+kubejs-pneumaticcraft
+eye-of-dragons-reborn-additions|龙之眼:重生 - 额外内容 (Eye of Dragons Reborn: Additions)
+river-fishing@
+mineral-xp-siphon|矿物经验汲取 (Mineral XP Siphon)
+teleport-gate@teleportgate|传送方块*
+performancehud@
+chunksmith-modern-gui|Chunksmith现代化GUI (Chunksmith Modern GUI)
+
+
+enhanced-iss-ui|铁魔法法术栏增强 (Enhanced ISS UI)
+hassium@hassium-limuqy|小水管救星*
+sealed-word-orb@|缄言珠*
+travelers-backpack-stack|旅行者背包:堆叠提升 (Traveler's Backpack Stack)
+
+pickupcard|拾起卡片 (Pick Up Card)
+tinker-foundry|匠魂冶炼*
+akadaemon-addon
+eternal-golden-apple|永恒金苹果*
+modern-damage-system@|现代化伤害系统*
+
+
+@elementmark|元素标记 (ElementMark)
+
+elytra-renewed@elytra_renewed|鞘翅革新*
+parallelapi
+field-emitters@
+legendary-block-entities@
+data-sync-lib
+blade-forge-workshop|锻刀工坊*
+villager-backport
+
+item-drops@
+corpseorigin|尸源 (CorpseOrigin)
+ommc-fg
+
+player-interact@|玩家交互*
+minecraft-earth-reborn
+
+
+
+
+
+
+
+
+
+laicaps@
+epiphany-extra@|顿悟 · 拓展*
+eternity-enchantment|永恒附魔*
+@ae2cc-bridge-forge
+
+lycanitestweaks
+
+unchanged-world
+bricklands
+
+applied-delight@|应用乐事*
+better-snow-villages|更好的雪村*
+@cyberware-unofficial|机械改造非官方版 (Cyberware Unofficial)
+antos
+
+
+@ae2-channel-alert|AE2频道过载提示音 (AE2 Channel Alert)
+ssc-lso-compat
+locknar-door-kick|TaCZ-动画附加 (Tacz-Animation-Additions)
+loot-bag-renewed-fixed-version|战利品包-修复版 (Loot Bag - Renewed (Fixed Version))
+kmd-travel@
+echoing-magic-esoteric-spells-of-the-fallen
+ultra-cell|究极元件 (UltraCell)
+dragon-loot-reforge|龙战利品:重铸 (Dragon Loot ReForge)
+the-13th-blade|十三契刃 (Thirteen Blade)
+
+quality-tools-jei-compat|工具品质 JEI 兼容 (Quality Tools JEI Compat)
+iron-jetpacks-port
+world-music-player|世界音乐播放器*
+
+@vcoasters
+smidgeon-o-bliss-legacy@
+
+@woodlandsextra
+guardian-stone@|玩家传送石头*
+
+smartmaid|智能女仆 (SmartMaid)
+furkin@|绒亲*
+greedy-villagers@|更良心的村民*
+cataclysm-magic-compat|灾变魔法兼容*
+pikafishing|皮卡钓鱼 (PikaFishing)
+teyvat-artifacts|提瓦特饰品*
+exploitation-timer@
+modern-regen-mod@modern-regen
+dappled-camp|斑驳营地*
+auto-mod-fetcher@automodfetcher
+ore-food@|矿物食品/矿物牛排*
+@radial
+create-feed-me-packages|机械动力:喂我发包! (Create: Feed Me Packages!)
+attributelimiter@attribute-limiter|属性限制器 (AttributeLimiter)
+easy-ants
+cgc-compat-legacyitem@|自定义枪械永续兼容:夕拾 (CGC Compat: LegacyItem)
+cgc-compat-shader@|自定义枪械永续兼容:光影 (CGC Compat: Shader)
+@cc-audio-expand|CC音频拓展 (CC Audio Expand)
+jdt-kubejs
+ans-ars-nouveau-spellbooks-irons-spells-addon|魔艺法术 (Ars Nouveau Spellbooks - Iron's Spells Addon)
+sophisticated-plus|精妙背包++*
+
+dimensiontech@dimension-tech|维度科技 (DimensionTech)
+eunomia
+gregtech-true-age-of-steam@
+chest-cavity-legacy|胸腔-复古版*
+lootbag-patches-fixed|战利品袋-修复版 (LootBag-Patches-Fixed)
+mxt|觅仙途 (MiXianTu)
+
+create-easy-stock-ticker@
+create-on-the-move
+create-high-skies
+create-stock-keeper-bookmarks@
+create-superflat-dimension|机械动力:超平坦维度 (Create: Superflat Dimension)
+create-crystal-industry|晶簇工业 (Create: Crystal Industry)
+attribute-reset|属性重置*
+
+@aoa-3.6.11-fix-addon|虚无世界3.6.11修复 (AoA 3.6.11 Fix Addon)
+
+quest-language-selection|FTB任务书语言选择*
+ae2-lightning-tech-reborn|闪电科技:重生 (AE2 Lightning Tech Reborn)
+@create-bionics
+create-compact-flap@
+fov-utils
+
+caerula-arbor-crop-compatibility|深蓝之树作物兼容*
+
+barley-porridge
+end-element-journey|终末-元素奇旅 (End-Element Journey)
+tick-weave
+do-a-barrel-roll-1-12-port
+epic-fight-retaliation
+avaritia-furnace@|无尽贪婪熔炉*
+haibaras-traverse|海拔拉的测绘 (Haibara's Traverse)
+
+
+
+wgpu-mc-neo|琥珀金 (Neolectrum)
+olympus-mythology|奥林匹斯! (Olympus!)
+mts-iv-official-automobile-pack@immersive-vehicles-official-automobile-pack|沉浸车辆官方汽车包 (Immersive Vehicles - Official Automobile Pack)
+@windows-priority-boost
+
+forbidden-chimera|禁忌嵌合体*
+@theseus-quests
+macaws-roads-and-streets
+@gameinfo|GameInfo 非官方移植 (Gameinfo for 26.3)
+
+
+vttas-viewtrackingtargetacquisitionsystem|视角追踪索敌系统 (View Tracking Target Acquisition System)
+curvy-blocks|弯曲方块*
+@watermedia-android-bridge
+teyvats-delight-meeting-in-outrealm|提瓦特乐事:异世相逢 (Teyvat's Delight Meeting in Outrealm)
+
+better-beyond-dimensions|更好的超越维度*
+venominus-bloodbath
+godfall-trinkets|登神残饰*
+on-ancient-ground-core@
+shape-shifter-curse-forge|幻形者诅咒非官方forge版*
+
+otcaddon
+
+end-parasitize-and-spartan-all|归寄万物与斯巴达全系列 (End-Parasitize and Spartan All)
+@flashier-flashlights
+
+advanced-fake-player@
+nimble-spiders
+penetrable-platform|穿透平台*
+more-backpack-upgrades-neoforge@
+mmce-advancedbuildertool
+
+
+@simple-backups-for-fabric|简单备份 Fabric 版 (Simple Backups for Fabric)
+
+autofarming|自动农场 (Auto Farm / AutoFarming)
+not-enough-game-designs
+
+endless-inventory-refined-integration@|留了亿手 (Endless-Inventory Refined Integration)
+
+@guard-villagers-tacz-support|警卫村民 TaCZ 支持 (Guard Villagers TACZ Support)
+smart-workbench|智能工作台*
+variants-more
+salt-powder|盐与火药 (Salt & Powder)
+oritech-addons-one@|Oritech:插件合一*
+junjietrafficmod|俊杰的交通模组 (JunjieTraffic)
+how-to-go@howtogo|问道*
+
+epic-sanji-fork
+@anima-mitama|赋灵 (Anima)
+bloodbathen@
+
+@p2p-logistics
+@bedrock-skins
+@tlm-substitute-jizo-expand|车万女仆:替身地藏扩展 (Touhou Little Maid: Substitute-Jizo-Expand)
+maidmorework|酒狐的更多工作 (MaidMoreWork)
+
+
+
+
+touhoulittlemaidcombat|车万女仆:战斗增强 (Touhou Little Maid: Combat Plus)
+promaid|更智能的车万女仆*
+
+
+@touhou-little-maidmaid-command-chat|车万女仆:女仆指令聊天 (Touhou Little Maid: Maid Command Chat)
+touhou-little-maid-unofficial|车万女仆:非官方移植版 (Touhou Little Maid: Unofficial)
+fenneclib|漠漠的前置库 (FennecLib / MomoLib)
+amethyst-craft-time-and-space|紫水晶工艺 (Amethyst Craft)
+
+wither-sickness-potions|凋零腐败药水*
+
+
+sable-aeronautics-scaling@|航空学物理结构缩放 (sable aeronautics scaling)
+mob-forceload|远游但载*
+creeper-spider-mod
+nsukdelightcropaddons|NSUK:乐事作物附属 (NSUK Delight Crop Addons)
+
+tacz-burst-pitch|压音订正 (TACZ Burst Pitch)
+
+@bye-bye-buttons
+@tpa-tinmoli
+anvilcraft-tofusthinking|铁砧工艺:豆之思维 (AnvilCraft: Tofu's Thinking)
+infinity-what|什么无限?*
+
+hexcasting-legacy|咒法学:遗产 (Hex Casting: Legacy)
+
+kubejs-custom-rarity
+
+loot-stacker|战利品自动堆叠*
+
+
+gretech-5-unofficial-gtnh|格雷科技 5 - GTNH 非官方版 (Gretech 5 Unofficial GTNH)
+
+
+directtouch
+
+nova-inventory
+madness-combat-mod
+render-360-core
+
+keerdms-binoculars@
+apple-trees-revived-reborn|苹果树:再复生 (Apple Trees Revived: Reborn)
+sky-isle|天空岛*
+
+veinrebirth|矿脉重生 (VeinRebirth)
+hedges-bestiary
+better-inventory-and-backpacks
+kaleidoscope-world-liquor-refabricated|森罗物语:世界名酒——重织 (Kaleidoscope WorldLiquor Refabricated)
+refinedstorage-fabric|精致存储-Fabric (Refined Storage-Fabric)
+merlinlib
+tinkers-organ-new|匠器之锻 (Tinkers Organ)
+flex-fov-cleanroom-port|扭曲视野(Cleanroom 移植版) (Flex FOV (Cleanroom Port))
+the-boys-unbalanced@|黑袍纠察队:失衡 (The Boys: Unbalanced)
+ricks-stuff
+efficient-hashing@
+portals-relinked
+asterion
+safesave|安全保存 (SafeSave)
+@hide-names
+
+text-placeholder-api-unofficial-forge|文本占位符 API [非官方 Forge] (Text Placeholder API [Unofficial Forge])
+hostile-humans-unified|敌对人类:统一版*
+
+
+player-radar@
+@jei-sdfalt|格雷科技与 JEI 兼容性修复 (GTM JEI Startup Crash Fix)
+sweatyfeet|汗脚
+
+modern-trials-integration|现代试炼大厅移植*
+
+echoes-of-horizons
+crycraft|晶体工艺 (Crystal Craft)
+hammercraft-fantasy|中古战锤:混沌魔域 (HammerCraft: Chaos Realm / HammerCraft: Fantasy)
+sophisticated-redox|精妙背包:氧化还原*
+lunalaces-movement-overhaul|LunaLace 的移动大修 (LunaLace's Movement Overhaul)
+lightless-dreams|无光噩梦*
+create-adapted
+
+@carpet-aji-addition
+
+reload-emc-command
+
+keenlib
+
+
+jei-guest|JEI猜你想搜 (JEI Guess)
+stellara@
+
+dawn-star-battle-preparation@|黎明之星:星之战备 (Dawn Star: Battle Preparation)
+chronoclones@|时间克隆*
+appliedas|应用星辉 (Applied Astralsorcery)
+crafty-cards|方块卡牌*
+summy-reliquary|七罪遗物*
+hlink|云联*
+coppermc|铜月饼 (Copper Mooncake)
+secure-pouch@
+gouge@
+
+oh-the-biomes-youll-go-legacy-edition|你将去的生物群系:传承版 (Oh The Biomes You'll Go: Legacy Edition)
+
+
+armor-rework|护甲机制大修*
+ice-and-fire-community-delight|冰火乐事:社区版 (Ice and Fire Community Delight)
+convenient-equivalent|便捷等价*
+refinedstorageaddons-fabric|精致存储附属-Fabric (Refined Storage Addons-Fabric)
+hazens-archaic-hexerei-armaments
+yakisugi@
+
+disease|疾病*
+create-fly-farmers@
+@create-better-wrench|机械动力:更好的扳手 (Create Better Wrench)
+create-aeronautics-easy-assembly@|机械动力航空学:简易组装 (Create Aeronautics : Easy Assembly)
+emf-compat-parcool@|实体模型特性兼容:跑酷! (EMF Compat: Parcool!)
+
+hp-end-expansion|末地生物拓展 (HP End Expansion)
+
+music-player-reborn|音乐机 重生*
+torcherino-community-edition-remake|加速火把社区版:经典重制版*
+beyond-emc-addon
+
+lfgm
+oritech-smart-splitter@|Oritech:智能分流 (Oritech Smart Spiltter)
+better-fluid-pipes@
+terrafirmaearth|群峦地球 (TerraFirmaEarth)
+
+world-settings-quick-exit|世界设置便携退出*
+medievalcraftweapons@medieval-craft-(weapons)|中世纪工艺(武器) (Medieval Craft (Weapons))
+metal-swords|金属刀剑*
+
+saberforge@
+parallel-torcherino|无限加速*
+librarian-1@librarian
+chuying-proxy-play|车万女仆:褚嬴代打*
+ac-core
+structblend|融构 (StructBlend)
+ragdollified-reactions
+traceable-print@|足影寻踪*
+
+
+create-fly-power-grid@create-fly-power-grid-unofficial-port|机械动力飞跃版:交错电网 (Create Fly: Power Grid)
+smoothplayeranimations@|平滑玩家动作 (SmoothPlayerAnimations)
+
+@litematlist
+obsidian-bucket|黑曜石桶*
+framepacer@
+concurrent-chunk-management-engine-forge
+echo-warrior|英灵回声*
+echoes-core
+
+@curios-slot|自定义生物饰品栏 (Curios Slot)
+carry-cats@carry-cats!
+immaterial-drawers
+tainted-tools|污浊工具*
+
+authcmd|命令权限编辑器 (AuthCmd)
+
+team-economy|团队经济/梭哈吧史蒂夫 (TeamEconomy) - 作者预览页,项目¨@team-economy|团队经济/梭哈吧史蒂夫 (TeamEconomy) - 作者项目,
+lootr-liaison
+enfc-exriconniours-foodscraft|ExriconNiour的食物工艺 ([ENFC]ExriconNiour's FoodsCraft)
+
+
+zombie-legion-tactics|僵尸军团:扩展*
+eeeabs-mobs-ascend-to-godhood
+
+
+@deathcore|死亡榜 (deathcore)
+aether-spellbooks|天境魔法书*
+tfcmodernlife|群峦现代化生活 (TFC Modern Life)
+immersiveaircraftmodernization|沉浸飞机:现代化 (Immersive Aircraft Modernization)
+better-blood-overlay@|血迹覆层增强*
+book-of-sins|罪孽之书 (Book of Sins)
+
+vaskars-remains
+
+
+the-long-travail@|苦旅*
+brnquest@
+
+
+
+bundle-stash@|探囊取物*
+projectexpansionneo|等价升华:Neo (ProjectExpansionNeo)
+
+simplistic-parasites
+
+
+
+health-up
+forge-client-reset-packet
+gregtech-6-neoforge|格雷科技 6 NeoForge (GregTech 6 NeoForge)
+no-starry-drunkenness@|啊啊啊啊啊吃天体果实能不能不要有星辉酩酊*
+
+
+
+
+ok-integrated-dynamics
+create-crafts-additions-adapted
+@stevens-mod-api
+plague-disease|鼠疫 (plague disease)
+origins-legacy-neoforged@
+origins-legacy@
+create-fly-crafts-additions@create-fly-crafts-additions-unofficial-port|机械动力飞跃版:创想附加 (Create Fly: Crafts & Additions)
+chemica@
+@create-stellaris
+forge-client-reset-packet-forward@forward-forge-client-reset-packet
+
+chest-item-vows|箱子里的小饰品:誓令 (Chest Item: Vows)
+hardcore-itemstages-reborn
+pouch-of-unknown-reborn|未知之袋:重生*
+
+enderpearl-backport@
+tongby-adventurer-guild|冒险者协会 (Tongby adventurer guild)
+emotecraft-unofficial-port|表情工艺(非官方移植版) (Emotecraft (Unofficial Port))
+
+
+permissionless-tp|无权限TP (permissionless_tp)
+charta@
+speed-display|速度显示 (speed display)
+xiancontrollersupport@|显的手柄支持 (Xian Controller Support)
+better-connections
+
+bettergregtechponder|更好的格雷科技思索 (BetterGregTechPonder)
+twilight-sparks-delight-fabric|暮光乐事:重织 (Twilight Spark's Delight Fabric)
+
+
+
+@scratch
+mystical-agriculture-omnia
+@smoothsneakingmod
+ambient-camera@
+
+
+
+more-machines-formula|机械动力·更多装配 (Create:More Machines Formula)
+
+crafter-block-backport@crafter-backport
+plants-zombies-skyblock-wheel|pvz附属:转盘空岛
+
+ae2-screenshot@|AE2截图 (AE2 ScreenShot)
+cgc-animation-addon@|自定义枪械永续动画扩展 (CGC Animation Addon)
+@mouseclickswap
+nifty-ships-biomes-oplenty-compat-update-muddyfork
+
+sulfur-and-potassium-1-20-1-backport
+
+spatial-gui@
+everrose@|蔷薇合金*
+
+
+
+
+random-equipment-attributes|装备随机属性*
+omni-display|全周天驾驶舱*
+cthulhu-creatures|克苏鲁生物 (cthulhu creatures)
+camera-inertia@camerainertia
+
+chat-colours-modified
+3w'3qN3w63wn3vp3wS3ra3aC3d&3Y^3Xj3Nq3uY3u=3qx3dK3uf3f&3tv3ve3r;0012'+3TY3uc3vD3vQ3cd3ru3jK3P33w>3ie3nZ3l(32)3l$3uo2,33kW3fC3t:3rm3V*3pG3wK2zc3et3Le3uS2:I3T33m}3wh3U#3Wf3sF3rr3X)3v!2*k2}A2[a3dz2;53j!2j32gK2'$2R{2h:3e'3eL2pj2Zw3ow3pX3qj3d23d'34a2!P3iA3mW3m!3nb2yP3p=3mt3rO2^u2f*2$Q2]A3w/1[<3nc2@H3w<3VC3X/3iB0043K&3v>2Fm3mb3jZ3tN30}3oM39v3IP3v'3VA3wR3vm33B3T#3wo2fs3u,3HS3a73W*3qL3t{3OP3iI3Y*3fo3o33m:3uN3PX3gS3rg3v73jE34s3SK3l}3rP3mL3pz3Jp3w*3E?3oP3v,3T83iV2zk3u&3ZZ3E/2'd2uu3lw3vb31q3mF3CW2o13hJ3vO3vV3sf3o<3g*3sQ3E^3lH2aM3JX3dV2dA23i;3EP2^30053an3v13qY3w$3t43HY3pV3w:3M?3n23QG3l[3T/2j:3d*3tT3R63o@3s%3uL3w]3d{3N}3tD3md3sO3ht3mC3V;30a37X2te38p2>'3B13f33O[3sD3j13qU3vt3wB3sV2um3f;2](3AC23AH3Y]3oR3f,3G*3QV3V}3uG3c73j:33l00B3Ps3th3t(39C3kQ3N03hz3Oz3d[3wj2}V3ej3iT3kb00C3nE3O;33a3XR3wy3FK00D2sv35E3iu2lt3rn3W635Z3R{1:63l?3a)3Z}3Cg2(a3oE3h13b@3E333/3JF3nN38*3t+3t?39$3P73MD3lD3L03Wq3R}3QX3i{3wE3P%3YB3e02o43hx3ZV3vg3w03Vd3j?3mj3sJ3d52&23by2n43l82@q3eN3ld3OA3Wx3n<3mY3mH3m$3id2:*3vZ3fE36f00E3X}3H}3D22;931V2Y73TQ21836i2a53mc3Rp3u#2pU3cD2>!2%^2[]3B#2w93FC2@T3tl3NG3hb2$%2#[29k3XD3U,3Rz3K^3FT3rp3TV3w{3cJ2^g3k93nA34,3TJ3pf35/2k<3p]3a^3ND35(3jB3I'2{)2+^3Zn3Ys3c?3GU31p33P2dO3mq2/[3Br3q(3r42$u3aG3q/3L43V=2z/3ei3e:3a>2=T3s=39[3I33te3dX3q*2:!3u$2B533+3903UG3OH3wb2@w3p!2>63k:3uK3kr3X?3t&3tP37U3rF3N+3m>2}C3ez3BI3g03sT3B$3dO3a}3K43mO3IF3h'25>32<20I2p,3Y$2MS2J*2im29X2&F3dG3aM3no3a[3pD3p[3l43re1>y3un3lh3o!3DN3Tp2!a2MA3ka3oL2[23fD2yN3qI3r,2>]2uH3Jk3T639/3wF2!A3l22'x31Q3RV3nu3le3bY3b93GZ3Cn3sa3iF3213YG2QY2gD2g$3wO3wQ3V13r73cX3VB3R&3Q,3LA3s53u%3pk3vo3i32df2iq3in3eC3NL3503M+2q}3t500F3g<3I:3dg3pg3GO3gC3C11}51!p3wP30/3H92f92?v3GW3S+3Im3cS2[(3j(3p43wN3hF3sg3vj38N2$p3TB3X(3hI2W}3h<2!l2PZ3kG3bc3Hs39>3I{3ua2}63bv3b037E3ef3vS32'3V/3Em39A3QT3k73WY3ko3rq3T)2&D34=3fB3v33B,2)D3oG3mo3w134{3s'3m63a22i03D,3Z82an2@72#p2kk3OW2XK3A+3U322Z(30q3aL2[c3FN3p*2mV2SN2{R3S02*t3bk3m73tQ2)}3rc3pQ3q&3jH3QS2{t2oS2;O3XM3NM26t2o02u!2^!2q#3XJ3l03t#2x>3kd3s73hZ3w,3j43Ek3XN3JH3Vu3e*3Sf2%O3q)3mp3cA3TH3jl3tL3ku3T13Kg2(c3td3Wk3wa3XE3gW3vE3eA3qH3c#2jI3LC2^M3o>3vc2,83j03W:3W+3p,3nP32M3h23Qi3dB3s:2p(2*s3u;3P>3to3La3f%3KX3NX3w@3Ya3k83C42ta2wQ3P03fb35z3i22^s37W2VV3q}3c+3wI3gX3w}3ql3PN3ci3WL3fO3Sj2&93UF3rd2[D3oi3M42?93Z33X$3VJ33>3s83S83ct3X83uu3l{3oh3L'3Zi3JR3N!3o53jh3T'3TU31E3Op3MR35c3c[3C@2)n2)$3d83N>2n73rZ3kL2ZM3YN1;11'93lE3gG3Co3HB2#*3r*3pK3P}3g)2:y2uN3Ne3RP2@/3FD3Gk3ME2bl00H3Px2BV3F^3ov2TK3Np3hR3tX2c!3Vz3ic3o)3JZ2;F3Bl3k33aQ3el3t=2'k3O^3tI2;*39m3S)2%*3FU3up3bW3k]3tM3m%3gu2l'3uA2?x3R*3gx3v23U]2?j3YR3pp2:o3TD2XX2!#1{23gp3HH32^3it2pJ3ut33o3Qa3ob3n13pb34V3Lx23;3l<2?&3EA3e(3TR3n&3QE2u53c'1,x3ju3vn3TE3Dh2Wt3Ad31c3gf2%,39P2^c3fl3uy2Pl3Xz39a35<3L73sr2]}3vM3jz3Kd3q@3I]3dE3iY3u<3b/3A(33y3ZY3vK3cH2!Q37r3al3Au3pm3XQ3F63YD3143Gx3dW2%T2/y3jy2#=3W@3dy3T}3RH3Yo3t23Vn3Kh3Q(3gr3tR3dD3Gw3u62RA3WO3hc3kN33=2)z3Pr39e3eW3Kb3Xs3RM3fU3JV3Ld3j<36?3Ok3g23v^3j[2^'2!43nf3P93KB2!Z3Aj2,d3ZF3m+3qO2'M3162&}2r?3Uz3c}3DJ3VV3Jr3Yc3cI3pi3u{3vf3fq3k)3me2(>3B[2Fd3aV3r[3M%31U3GI3Xg3YC39w3tG3dw3q$2ck3I53io2>[2+j2(83Xp3n63H;2L73d}3Z02oZ3nB3I?3Dl3lS2)B3Ag2=H2a^2U$3J&3LU37G2(Y3tb3k03qw3fZ3iz2RZ3Sd3ex3293ch3b(3jQ36^3pB3ca3T?2g]3u(35=3DM3RU3tu3jp2#83B%3Z?3nJ3r]2'=2sr2TH3v:3rT2t?3By39i2*T3K'3nr3aB2aX2#q2[t2Wj32t2^e1vF3tc3YQ3k62!C3I^3ib3Hr2c(32]3j>2vA2+73fx3rX3PD3jP3ip3rl3h%3j#2[p28f3n$3Dc2uI2/p3if3H43WE3kv3o%3TI3v%3EJ2dl3Nr3Vm2G+3WF2ms3bV3Mx3o,2)Q3r%3u33we3J%3wp3eE3R+3i%3bn34l2'52wj36+2C(2Q42{T3dx1(<1{{2GU2ja31I2XI2[j3b:3BF33M3S;3n93YM3W33NQ3Q73Sy3Kv3P,3t63t92:A3693G)3SS3s13mg3p52n}2>^2X22pF3X52xA35L2fv3Vg3882vH3qM3r@2v(3DA3wA3RJ3nF3YF3LV3Z53wl37x3K:31d3b83eh3qs3p{3p<2?L2/a3U'3r>3v53PI3l33Q/3gn3QA2K63vz3Wc3313hA2Tv3W&2h?3273vN3M&2+L2((33*3AM3kq3m82yV2$e2r63Is2th3o?3N#3Xk3U$3K{3Ee2e,3q62@+3HV3h93i63W!3l+3Gr3e730P34Q3IT3e=3Sq2@#2n]2[;3QD3f]2:[3TP2v13rh2=N36L3jA2yU3wf2Er3qQ3Fr2SG3Ed39G3C!2x^2>/3X!3Q*3Z#2T&2z(3pE3cQ3Rx3JP32I2;82K93hk3Ig2b$3O!3Fc2,v2;V2rx1np3bG3j52=P3Gi3pS3V73P43iO3hX3wL2Tl39,3od3Y13mr3lj1xP2MY23y2>;3m;3Vx3i03iN2=X2x63lz3lY3jR2b93n/31j2qq3qf2u3U=3973mI3Vp2,'3aJ3Po2Hv3NK3m=3uw37s3c!3sl2{g2jP3t>2Iw3mU3J72Wr2/;2vE2f<3m]3w^3vC3Al3qZ2<:3OV2wM3t03lr2&u2Nr30,3vI3r!2QM3Ol3Ls3o[31l3a<37h3af3WS3ok3sR1}F2aU1,b3Wy2kM3o/2nd3Q!3hK2)F2oG3M72v'3Gm3s33E%3ER3mN2,N2}*2*J3qF3Wi3t^3uj2$Y34^3S:2#s2'V3Ry3lX3a'2,X3X%3kK2i)3uJ3ag3jf3jV3rx3m,2xh3S>2)^2P^2tf2,l3DO3f[2r82[,3l@37,2x#3Qm3r92Ri3ml2lT3He3P$3tk3J<3g92xt3Up3d13CF3mh3n#2Q3a62[m3HJ2s53ni2^p3m)2K42^[3mn3em3tO3Zy3SR2k;3so2bH3F33BJ2[$2[d3a=32G1:Q2%[3f/3R'3CN3g,2>t3eg2)E3j72;e3WP3L]30f2+V2*P1$w3q'2W71/g1xM3r'2)132b3kk1Wt1L(1^N1'u1,s1NT1qj1dK1Sf3ol3D32uQ3sh2+l2+w2zW32+1u'3l)3Ac3tz2=y3gv20Z3Gn3sX2uh2't2+<3W;3723Qv3nU2$I2U>3p23uV2ri3S[28!37<2xR2IB1m02]F2hR2YY2B82tT1&+1'm3cR3R%2hF3qG3h/2*g3wv3sw2R?2,k2sm3pu37;3Zz123KC38+2*M3h&26138e3sS2bx3nj2Z%31K3SF3Zw3WK1qQ2ON2k#2pi2RH3SE3p#3dh3h$2wG38:2V$3Ey1lp2p?2'32q<3jo2A@2,[2@C3Q43H>3M63c82!@2@E3OC3DC3F+3hW1hd2m=3c:3Y:2rm3ZM3UM2$32rt3b$3sB3px3c{32!3091j@2+%2*@2MB34Z2rh37C2(:3j82c02Md3W13B!2Su2%s3d#3u[30S2%i2V03i'3t83fI2yF2)V3g'3Ot2z<3qT3qi2]:2cc2bs3m13b+2:h3En2Ni3XV3VM3B{2i,2i?1dJ3KU2ME2iv2jf1;w2a%2TV1v62Uo3NO3jY3q43L@3FV3U@3Fa3p}2zt2n51g82Kg33[23i3Lq3fQ2P[2w63C>2[<2>U31/2nz3RR3cc2Uw2'P39K3bg35t2*L2}m33T3hh30v3V!2'!2fJ31;3GL2dE2%42u}2eT33n2hS2Wf3U02rO2=43Jy00L2/72bt3uD2ur3a{2hN3O$2Y+2&q3Pf3pW3Mh3J^2z!3f53pM2w$3w33n=1*E2r73jI3RN3cW3c^2qa2>n2}{3Ox3Xn3Jh3ZH3vG2bL2X(2el3OM3O53g62DZ2*E3E23v)3m{3nX34k3lv3sY2[A3Ii3HE3s43SZ3OD3HO3M83jJ2Db3U(3fy36:3Zq3hy3gd3lT3vU34e2u*3X11]>3Dp2*=3Hw3wt3vi30U3Mf3UH1#)23<2XV3Fw3JJ2,Q3F>29P2TP2aE3g(2Vi3M500M2%q2,I2(g3ah3Vv2<&2%c3IS3BZ2]m3P&3bm00N00O3Yb00Q3d]2tq3KP3lq3DE3Fl3YY3ud2v62p931v3bO2:)1x[3i+2*Q30C3qB3tZ3VW2;x2SJ3p$3rE1=S3r82/S3L:1)q00S3oK2]N2563Q#38B00T2DG2tu20u24=2nT3Kl3AG3MZ00U3rW2gW3S*3NN3JS3s02[33No2,G2=j2v@2)43lc39]2kG2vq00V00W2mm3rU2uA3gw28i1>62wf1j12?F2343ON3SI3mQ3qP35k3dQ37K2ws2Cw3p+3g/3Kf2;z2}o3Zd1>z2t!2>S36u2=*2v52!&3oZ3f?3R=3V'3kx3RZ2b{28c3E]2O72+P2^13YI3Ch2A02s92:P22^2Nc24V2(h38g3l&3bz3VD3wD2Lm2o^3lg3V52N42m!3qt2/i3sj2;i3mZ2*n3Xt3e,3bd3M93vL2}N2^O2T^2YZ2g?2dt32U3Fj3PP3eJ1kB2Cf34J3q035U3V[2Mz3gk2rj3a,3HF3G93Yu2q:3Jf2IO3B]3SY2>:3M'30%3p?3R500X36m2y62,q3u13g+3TW2+b3ep3h^3fA2iB3Hl2^v2O&1;}2(}2pz32H1'P26Y1i23Eg3J$27F1TI3OO3cE2Z)3OX2M:2zZ3p>1p+2k23b,3S<3gP36t3NP2$J3Wd3RK3u@2<93WT1b92<'2zw2vT3mB2Hy2ZR3c&3CO3iL3R#34;2k42Eh3e42jx3E=34831'2d?2%l3Nu1$639<1mp2{[3Qq3YL3Cd3Nj3v[3Fe2Zv3AB2A<3B831>2I}36a2Fp3cM32j30g30>2v%3UT3n'2kg2c=2du2**3r<3s939R2%m37^3Cb3823G62?33EW3b<34$2s>2aO3Rs3p13lF2XZ3iU3S631R3Gp3rQ2mg35l3p@2#Y3K02{]36)3JA3IV3AD32Q3YE3ax33L22D2hm2rC38}3I%3um3gJ2(d2yo3b73BD2S!2)U2>32(p3O72],2E[2)<3NI2^@00a1b@1w23P]3C?1q83Dv3GK2Yf3vx34y38y2]P3iC2Ss1)&3Z(2TU3593J#2NQ2v42q$3ly30l2{83j'2Hz3I(2I<2@42(92pc2mM2CM3KD37B2fE2ue34&2HD3rk2'K3l>3Ja3Z:2s)2fW2d#2@91td2}v38,27}2/q3w#3cu27T1i,3Z@2]'3a$3Sb2^J3A^3LE2!c2)'2LA3Kj3i#2'a3A92r%2ff3R72Xo2g<2+53k&2[l35S3WW2G=2)h2>o3Yw3LQ3pT2fj2q13j%3H(2{{2bz3Jj29t3h{3t%3i[3ik2x$3gE3F#2fP3Mw3S72fh2C92RQ3Hh3QR3Zh2{N32B2;[22:3Bo3uO2012$G3i:30Q2')3Ic3Kq3H237j3fG3nK1,33Gz27U3AN3p:3g^3Ux2uY3B:2xE29h3nT3is3h!3HT3K>3DQ3Tc3os3ul3tW2BK2:M35}3S/3Zp2fw3bM37R3WD2w13j$3JY3oD3n43W<3ad29s3WQ2,U3r(3Eq3h;1SV2N{3O%3l,2:<3wm3qm3c93oT3sU2!%2j[2ye3IW35i3dj3763n+3vP3A839?3c33s!2:$3L>3f93e?3rH3rD3rA33g2]K3mm3R]3G738w3k53cN3J13US3qq31a36h3n:2RS3Y=2,92'r2$k2uK34?2ph2@23OR3pj2)63mS3rv37/2;Q3QF3nM23Il2+'2w%2=x3171iH3L53s<2D^3L;2^t1kq3YU2,c2&v3vR2bb2qo37@21S2zS2tk3e>30K34w2:&2rH2/'3C22=[2V!2KH2]J2Tr2zv2;w1'p3je3i&3b!3oq1*b3kO2FU3rf3WG3U)3Z%26R3fm2:q3SM3M@3T;3Mg3OJ2fz3vv3W#2(f37H3I+2$<3O,2/)2G12lO2%t2#r3pc3NE2:@3wT39{3Re2}^3tn3H=3iE3Sc3r52%u3123P(3at3s?3qK3eb2T>3Ke38%2n{3pZ3h:2j938Q3C{3J*34G2MC34f2{<2Jg2}&3Y!2:e3c*2Ob2,r3713a?3Pj3GQ1l/3K*3WC2(H2mF1*(1m92Me30W1:d2#R2=u1#Q3V32?X2Ag3YX3ls2P33kX3v03K]2{93qe3e^2^j2{:2NY2b&37'2L43hH2={30e2q(3M[2oy3d32qI3S93AS2uZ2a#2?G00c3Y92GZ2@u39!2$d2PK2rW3861q:2w#3wM2@'2Hs3K?3fk27J2/w2XF36!2}82VD3cP2^k3eQ2nP2Nm2i<2^+3Rg2Fw2#U2Ol3bo2*i3b[1?$3EF2x12&%2%+3qu2I13s#30R3Z{3gB2Vc3M}2'83g[3fX2t,2A'1?22A!2rU3Sp3I)39%2'z22T15M3UK2X92Gc3Tb2&R2S^33j3ss29#2,#1<73Qp2M$3rR2D*28j1jn2y&3Yj3aK3LF00e2/b3fF2%v3lQ25i3l633^2{j3V63mX3Xf3843s{2lr2f[3bH2:u3K=37)2c%3ba3V839138c2ba3J,3ID2vG2g=3On3l71>72*b2?g2?53UN22Tb24e2Fa3sz2!N2{?3Si3Hc2]!2]]3V$2##3C[3VL3su2K*38'39'3s)2j!35{3UW2!,2]n2CT2(42oa2=g3i?31Y2mj2)028d1jk2}[3fc3O93YK2?O25!2p;3BM2h53EU2nb3nm3X@38<3V03bR2g92T12Q(2Hp1am2o?2x]2F52ux2EZ2E43as2{>2#D2lB3Z^29125A2}t30(3Y&2jU3XX3LJ2nQ35R3jO3Sr3o$2tY3G;2,!2{m1!Y2Hi3nR3e+2Mv23X1Jj2zL34X3PF3YW1^(2VM2Fe3F}3la3tt2r<2Sr3c(2mW2O$1C*31H3R33oz2!=3i(2Fk39L1o,33t3bl3X43QW3hl1bq2BW3dI3Q92Ch3Z*24S1Tl1#G2'b2KD2vJ2*)32k2wL2iz3i82C]3Yk2eo2?{2vR29*2O42wu33}2>+2!b25u2<{1!$2v22c{27d3km2!k3k@3OG2TA2Co37Q2GR2cT2;t3lL25<2!)2Z225'2};2lE2ho2*K3p72M52C+2B438;2eK3kf2(v3992YE2n<3Ix00f3A<27300g2+R32:3DD22Z2jN3L=3CI3v;2d<3Yp3T53H[3QL3An3bi2!q2?W2;h3f@2H633'3I}2]+29d1w(2Id2}#2v,2w:3Bw2c*31r2>a3qg2Tz3Yq3J)3H#2y]2FV1(S2%n1vb2Q,1{w2p}1*W2{#2E^2BY3ro3BW3ZE2(s3mw3L!2V72Fo3ue2'63Dq3W,2+r2}P3w53133R42&K3Ay2j/3qC2;K39p3Q)3BA3Ga2nG3da3q,3es2']37n2NS32v34P3Nn2Nq1@O2%H2*^3ll3u72R32Z<2T53pa2]V2UN2o:2m13Y33N?2v}1(U2hf2?$1[N3W935x3Mj2R>3se3hv3Z73G}2iF2t*1Yl2^?3K;3D#30N2dS3KK3Wv3Do3a13jg2$'2u73u93BU3N'2^^2#}2VN3A>3Y832,3332!y1!D2>$2ts3Um2^%3aH3UD2Ie23f2<$3lR2%82pG3fi3b22Zx3M>3Zm2}}3Qe2+T30o2}y3A73kY2YJ37>3F<3a52wg2Wv2>e3Uc2^>3U12Yq2Pc3C*2X<36S2?o2?@2<63LL2+z2nC2yE00h3bf2@$3AU3bh2?B3dU1;o3WR33v3cY37z2/,33X2vs3Jc1]136p3e83Ob3SH3S]3gl2)Z2(72W22;P3D51,o3m'22:}2u@2z)3Rv3bX3dr3S^2JV2/j36n2@Z3eB2wn31@3D?3Wr3Ij3OZ1gF2753D72Y43jN1&V3KA2%U3B;3nw3jj2{62/12g51yu3c53H:2Cc3Fd2([23[3ff36/37i00j1h=2zU1>b2%Y1w,2N:3H<3Tj3WZ3m@2]<3rN2wJ2yu2;41P73TF3V:2s{2[h3Q%3s;2LP3E*3Ak2p/2%(3F82k32'h2s03JB3ne3i)2<)23MX3tS3XU3q{2L62D@3N(2ep2t&2p62:]2pN2>V1*)1{I3Fx2aN24B2k+2]02?D3I=2;Z3G52qB2]?2J<2mS2x*1:h3st3i93Zj2o93d(3Z;3B(31X3Wp3t33aO3XO3pl3vT3gR38u2R03EO2cl3M!2xq3H+2*e2pP3p63UA3E73kz3QM2#%2#E1]31p=2JX3T03lP26O2Fj2Aq3CT3r33cU3M)2{p2,%3cr2&W3Z<2XP37V2r$2ZD3Uw24j3L83f22C!2*>35u3tm3Nl3WV0,n2+s1,D2e21>n2lz3Cm32X3H72('1Lc3tC2bK3Q03A,2sR3e[2';3Ro2'230X1Ni2Bk2@}3Q[26536=3Mu2/22x'3l52d(3aT37T3My2yX3P?3g#1]&3CR3Cj25Q3eD2m)1PM20%1ZV2De1^n25(2D?2$(3Z11vj2432k$3MA2Ph2#b2Ct3F%1}3W02'F3EH2jB1xv3qE1#!2r22<[3cp2$=3Xx2>C2(x2kH3W$3c03R!1Zi1(=1hN1]:3C]2QN2S72#c2Z/3Vq3Fm3u'3Gt2u:3Z43Zg2X>1cq2*?2t62)G2sO2oD1Qp2A*3Yr3o(3cx2^$2L:2g,3c@2mX2sY2gS3e12o+38j3MT28%2lk3MO3Va2>)2=#3aY3fN2/e3S,3gq3Ll2WS3O+3v&3B53iq2nR2;E3QJ2{22)l3HR2]>2,e2qm3T@2Yd33s35]36'3Lz2P63EK3h@3Ep3Eo2'43W83f63i]3qo2[)2e=2$O2r527O2DN2)?2'e2z=3NB2[P25Z3k430:3eY2Xd2,K3h,2mh2n*1VY3lI3Lu3Vh2zV3Ty1$Z2/P2}w2z%1Wc1'X1YS1^>3dA3V^2%933U33F2H%3C%3cy2z42eI2;#2iy3h=2v<3bb1d*2f12)I1Ll3W}1}o2Ta3Q^3W53ia2$c2,j2%g2z;2+S1e+3D11@(2>F3u53Q@3N[3K)31g2ls2!*1cM39o2ST37&39z2E'35b3l;2>m3Z>2{s1Y62l&3ts3Bs3vB1{Z3F02ug33E2aB2=V2D22@31(/2d12)w1:=1)/3oO2,u1%334[3aw00m2N83XC3mK2Z83FA2)m3Q;3Wt2cs2[W2S@3bx2m[2:z2)52jr3ki3Uf2^A2&435^2>O35p3Wl3J[3d%37[2,p3KR3872JT3U/2jp00n3a93g}3Zt38@3IA31t3Y'3M/3SC1d$3GG2MF38o3t[3a(2yI3lf2(L3Ws3ns2>L2ci3eK3FM3Xw2$+2jY2>12;j2X3c/3WJ1[G2SL2'&1&}3Vy1?x2}12by2jL2uf29Z3741+=1#a2,22zO34W2p^2][2/Z3jW2bA3AT3p%3k>1pN20;3ao2@=3hL2l03aX3Sx2<]37*1sE3sn2;M3Tm3D'2J,2mH2kA2<*3L63w%2:'3gt2iG3Qh3Yl2,C2f42x23eI3Td3Za3Sg34A1uK3Pp3hU2cK3Df2[U3sN3701?g0,G3hf3KM3U73dv3Ge36B1?@3W21w&2JW2S*3RO28B2+H2vm26e35v2EL1@'3Uv2Yo34m2Ak3ea1hy3Jz1[P3og2xG2:a2#o1}'2A33ks3d?2rw3KL2I#2&y2An3Eu2/{2V=2$F3Cx2iJ3Ut3O&3VU3IN3iw3sd3Ir2$M3Me3P[3n}3BN1$i3l=3j31,W3UO3lC3R83c;3Ih2[H33q3Yt2ly2tw2E62QU2y)2V62Tq24y3iX2[03Bq2]42^:20U2j]2@e3L?29=3gm2)Y3KW3G?2O:1tS3uC2S03I93PV2!?2;)2J(3q13612+q3n]1([2%A2)N3Q'3L93Xv2<#2}223{3U%2J^2ei2sV2#k2TO3FP24p3h>2?:2(F2B>2Jw1z'2ZH2Wz2Vk1MS2GA39l2aa2,A2+D3C:3522023ET3XW2X!3m(2YS2>43aa34O2wE2dz2ES2bW2&T29D1yM2Zf2Fs3Wz3Ds2G*2J42IP3R(3PL2oU1l;2(n3p82Gm29c1rU2sx2LB3N]3lN2bC2+U31A2{f3M,2tv30w2mc2jl2U@1GK2j*3P52NE3V,2S]1^H3CL1:w1[?3u03gH3bI3cv2G'3V@3Y)2nE2E+1J?2PM2QL1&h30s3A!2Ww3022#C2i#18K3ZX2;f2#m2/g2oq3oY2uv2u13393rB1n33Db2,x3E500o3E:34p3Q>12l2ew3o#28}1we18/29^2T21cV2&M26H3eV3uE2d*37}00p2wP3LX1[l3ar3A33d013?1wP2#>2dC38&2Fq2w(3MN2Tu2Ql31w1,f2&H3Xq2AJ1%223z2a{3ce38#2'Z3O/2;@1}62*{1z!2'>1[Z3i=3cw3DG30M36y2;>2Bb2;d2JP3To23730*3f'2lv3ir36&2QF3O]2wC3ed36[2lh2^H32m2)+2x)20W1{x2ec2Ox2Ym3dc2>%3o73SU3sq3np3Y[2]O2By1wA3vr3U:1la2ee3jn3gZ2C531h2F62B'2cX2]e3L23mP3F23CZ3e<1yJ35+1[q2{A3cs3jT2>G2[q2@d3J{30=39F1Id3ZW3MI3UX2f?2h@1S}2C'2^w30[2sW3Eh2!J2V'2Z12T;3h43O)3pH2q{2(;30u2b}2cn2!v2n>2wV2Ai3G'3ot2?z3fv1v718}2Ao2@N3D[2Yb2;62kb2yH1Wk2$f3Pn2=)3TM3033Kw2f#1}j2,M25J38]2W43Ko3L*1pu3s[2av3or2*w2gC1mN32/2o>1sD3SA2]Z3Oh3243A=1qn3s>22>3eR1q&2q734b3D;1tD2Tw1{S36j3Kx2s12#^3Jm29H1,B1H>2zq1@W1:)2L23f723'3cq2i41bn2h%3Tw2*82W^1kM3gj3442OM1{u2wb1=T1!:2wY3RQ2kI3MM2D(1)z2^<3Ye2332U=1&32X71{B1WM1p}1IM2@*2h{3IU3UY2rZ2Hu2!h2rk3252xH3nt2(b3B/2,W2u[3VH32f3bE3Q+3f$2>M2T=3L+1102OB2]z1+Z3PE2=h2<3P#2TE38T1UA27<1vu1&f1PN2]c2B03ZL19[20D1RV0:71t524,1+<21s21W2e82I)2D)1,i1{a2%K2;}2Vo2o;2g82md3oF2[%2B&3Tr3Z,1+@2+G35q1Xv3X>3S{3IR2JC2}X30x2OK2e%1@)3Sn2(Z1y12[C1WZ2D#2'}3dn3Tq39V2G41C<1sh1*l2uO2'12g21;e3E!1[T1eU2<+2452Al1P03lZ1+H2gQ23x1M!18^16m1Pp1?71/{25)2AV2sG2]T1+E2nI3a!3Sw2Ys2c22Vf2:=3Ql2kt2U(2Tx2q22hQ2he2c[2r>12W&2:s36s2^&3Ji2O(3XK3CX3ji0>s2{,3H/2!p2/L2L;2lZ1]41{C1f51nh1)a1>U3Ml1,*2t53H53WX1(k2=;2%B1q<2hk1}x2%=2M72$U1@D2(P2'v33R2n629I2#e1uA3Qc3b=1>T3g53D]2FL2l;2S(1GX2=E2XN3Iv1zF1!I1{]3I#3k}2%f2{J2wi2hJ2/x2(533%24m2hH28+1c2{&3A42Td2nL2'i2GV2rl3G!2]C2T63C$30Z36W3Xu3nd2iE2bu2KE2eh2ju2mI2Kj2fb2lN3m93B&2WT2;N2qn2/=3n[2)s2yf1ck1bj2;b3jC2Ip2:D2=52BF2R!3U82DK2Qu2![3G]3lK2Lu3LM2lF2uE2B^3n@3XP3MH2[!2&>3Os2x(00q3pA2l(26s2uJ2i!1uO2v73NF2]X1#11:H3N;3LG3LS2$92Gk2we3C&2#&35s3m32di2cB3ZT3CJ3F42;p2jJ2!F2]j2,S1;@32x24+2qF1pb3U&2my2dv2981#r3O:3D83rw2z81{Q2UK2aF3R;2Vw3U{12d1Xh2)93T43Hj2Tk2*;2kY2Pu3qV3D:1s}3Nw3nC3CU3lO2x934z3H{1@/2kF2+{2/&3HQ2m+2za3Y/2gy1ah24R2o(3j/2cE2:l2nv22A2Pv38W3e/3C^2bO2@f3Y{1Z3az2[O1yi2IJ2(,2a12#)32l3Wa2!{1cy3933l]2%r3463OK36#2tW2:627w3Ej15%3H02H$39x2bh2322*j31b2vX2N!1]Z1d51]A1BD2i=2ae2D%2?>3j+1'e1}l2)(2<%3uU2ym2{Y2#61IZ1Qn1uJ2xz3R@3363cG3pJ2mP12m]3S333<38P3N@2=k3a@3Qu35j2nO2Cu1x+3CP3Uy2OP2GE3T{1;S2D2[/2&k1te34S3ha3Vc2k51,w1G83kn3b]3Iz1Wz1,I38G3J:2!G3N92I&3b62Of29T2Z}3Bv1XX3a+3aP3o'2ra2XB2lo3SQ2,+2z{2Ca2yT2^x2$#1}Q2E$23s1Eo2;/1L/2?(27(3l^1XE2da3KV1yv1E50>*1'Q1cz2&l3S&1d61,]1JX3Dt2/?2CB33h3Y637M2I;32D2%D3Pd2bX1?A3f^1(H3X<3am3f82cM2W;3n%3m41]L2P$2h}2@R1GT1Po1y/32p2392291EB2Q$1[n31m1qk2WB2T(2x{30#2!r25I27b1(j2pt1#p26M1)^2?s2j2A?1Q]3qW2}=1yj2NW2DW3D*30A3Lo27t1DW2!13G@2ic3nH0:A3E(3Vk1+K1@#2{h1<%3K924Y28[3051R]2]%2VX2xs3J/1Y[1Dk1?32M+2u=1M61cZ2@K2UX2Hj3gK3kD2xJ2T$1*;2+[1ut1W{3D92j@0}21'a26$3B?2Vy2Fh1TY1v'35O1#y3Mr1)w3g33FF2qU3a03Q?2Zq2ka2t;1K63ox2A>32c2E{1q(2d^25d2il33H1uB2WX3n)2^X3W42b<2ZW1Ex2VQ2U!1LZ2I+26u3dH1^w2yK1aH2?#2+12vg21L2pa1iE2qG2P&2I62vp3Rh1g:1x91;<1(Z1841fg2QR1qZ2}Z3PB2Xa35A2D,2x422*2U^35X2YP00r2;,2!K2bT1452Va2b'1DA2q^3L}2K#2z23011be18T2A=2wH1Bl2q)2]&1b71L'1dt0[)2t{2oQ27Y3C62jq3cm1aD1mf2&e2L$2Sd1B/1Ve2iN31N39X1So2=D1y]2+M1UY30p2ht3YP3Zv2]p1t%38m3m#2ZV2M&3073We1xY2J51a(35w1@s27y1>*1;d3Fq2},2pl3XY22q2)21sk3hj30?1l#2XD35d1<}1ph1tZ2@o33I2>,2+f2z*2G{3LR2m&1b23Ki3iD1To2*92)R3nk2]g3i^2Dn3C)32N2o[1*C1pB3IO37:1?{2Br3O*2q;3hQ3qp1M&1zR2@J2wp1ra1;%39)2#I1VS2!^1cb37A3gg3Nf3VP1oJ2W@2=J1:y3o13Pw2P,2&a2Wb35W2JH2'l2F@3OL1m?33@2M<2S62Sl2ox1l*3003Ia3Vr2401=k2+82x}2gl1XN2xZ1nG0rg3ds2hE1,e2M'2D61+(36U3c=1gZ2Kr1}J2:+3QI2EQ2Oz2WK3Qk2r!24s38U2d:23^2Ja1lS3PA1>a3r&1}#2>E1M]2492eN3bq2n#2Oq3Vw2/>27[2k{2wt2N$3o93g$1ad2hz1q]1CA1sn3Q<3E42':2Ne25j1lQ2eB1eV2r/1/S2C=1e?2F>3ge21J2F+3oc2'#1M^1HA1@b30G2}E2fd36<2(z2(N3Qg3Cp3Bj2f&27$3qr2zB3k$20m2J%1:<25w2y}2QV2//2R*2X2QS1#h3hC2oT2+E2Do2Ac2^I3iH2KI1a$2m?3hO1'>1wn1]J2142*o2DX1]G1rO2L@1WA3gQ1,O3Mk2&&2Q#1*w2t>3A{2LI3t}2El2LL2qb1kt1FI1pU35o2^f3F(2c81$[1Eu1YF21z1(f2Z#1H}1$j3s$2Y*3Cr2qv2031+]30r34I2%b2tS2>w2;U2,m3981Zv2A13Of2Ko2)@2IT3do1):1a%0']1t}1!!36w1w%2N^3eU2u'1$k2{n2'n3L)3GF2;{2kU38i1<[2e>2j11oG1gl25L25z1XJ2Cs23A1ie1wj3Us3XG3Ou1qd2&f1g$2uG3P+21(027s1Hz1Zp2Y82u(1z32]v1SB21X1{R3r12BC2jk38I2<<3dm3Bc1#k1sI1ud2Zs2bR1%R2cp3T:2va2R<1=n2Nw1&!1+92b]3N40'C23(1V31fr0[12:02#J2Dg2Qi35)3dk2;C3U;26m1:K1jp2}d1t02JD2Pz2?[3HN3NH2HB3MG22/2Pr2hq2%M2/92s#1]n2C,1{71JQ2!:2Qd2?830d1(p2l134x2<121i2z:2lu2h#2&c3LW2821fJ2H40;p2RE3c41'c1*/2ad2PX13l2D&2sI0#72=a2TR2ke2qX3O}29)3R,31<2Vh1h<3h02Ge3aZ1XO2)/3HG3R<22I1tI2PY1Ax2ny27;1tg3Es38X3S13Xa2u62%o1Vc3ZP3Ae2r{27:2@Y0^M3dF31(2;R3n^3Pl3w&2kq2{D1Bp2QW3Kc1902ZP1ET2!z3RA12$2&/2r'3R:2M?2NP2:22CN3FE2ze2mR1wf1=<2R$2U}2KT2h32E72&J3VZ1(b2fB2c+2qt1#s2#L2:S1+S1Na1my2)O22h2y,2}(2=/1+p2jD2992Sx1l32iL1Rb2x,2ia2=r2>>2xn3I$2Ov2J/28C32Z2h[3X:2z$3oH1ZN2JI1Z>3hs2M>1G3Z[1)N3dt2!I2uP2Wc1O!2sb2Oo3Hb2Is1nT3D>2V@3ty3n{3M<1%W2:;1}*2NV19g1;J1h42r^1+52ZK2yZ1+:1Ev2,60,T21'2!72E*2r=1'12e*3gV2r@0&11si2:H1Tx1Ps1zH1Sg1uf2'Y3Bm1Q:2!<1FQ1rC1Ks2H52yC1Ch1B,272;u29636O2;c2{I1>[2pq18(3J?18N3L[1yR1AZ3Ec1SS2Ka1bt1qY1h>2yt2ex1ZR2^61J{3Or2+?2DB2Qw2m#2801kN2RR2Kf3vl1[B2xX2f^1y21//1rH3DT30Y1&l1r43E>2'G2wF34n1UH1}f1,M2X$3bj2,o2J)36K3Mm1w^2N61[&1PC1xg2Ue1Hj3h*2r)3LY3V>1wt1o;1Xq2n11/w3ps34g2lQ1v82(j1y,2b%2vO1%c2v[31B3T(2zJ3L$2%$1};2xi2*D2q%2S%2$[2C22;'1m/1X<3J;31)1bQ3d>3K62$N2;<2;r1F62{M1cw2^o2N/1tV2j(2zK1^I2f$2)q3QQ1et3QY3dC25a2$]3nI2gM2^P2]@3hu1hk30n2{@2O)2Xz2@62pS1;U3202v82Wp2Wu2!X3A}21k51f71Y}1p02:j2$B33]2t[28H1Wu2+g2Ee2;y2H^1ft1$e1))1(731S1%k2&P1%@2$l1+l2Z43Yg2FI1p$3L&2?N2#]1]=1:+3As2*02=A1$X3V)3IY1iu36V1{n1,:26d00u2'O34:2x?2+Y2D72V91K72rP1m,3C#21Un00v1hF1>V26^3U*1S,1l$2In2[12L>27Q2'N2&;2;!2!31bd3Aq2JZ2tZ2<@2=v2gz3V#3H!2Te2ot2>92)J2@?1&K2V}3C721xr3t@2O832O2XO1j:2N'1ur2U83K$1pV1i#2Qp3k=2XY1w>3jG2Rk29+2J{2s41Jf3p&1)D3fY1)c1<51v?25e1o42a+3lm1O32]Q1W@3EI24o2/C3MP1Q/1C!3Dz3H11%D3py2QZ38a3iM1YP3DS1QZ1]235P3O(2%13UV38^2^a29N1Kh3l91w)24^1B{3c$1mg1>o1=h1o$1ou2&70,;2gv1:i3Er2>g34038[38E3Nz2[63Aw2X/2Wi3GC32q2G&1qA32>2sg1]%15m2%J2rD1p[2S{1s:3Nv3d+3G81'53lu25q1/k1Ea31J1oI2^Z3It1#52R:2z?2pK1{l1R@1C(0,13rV2mz1S)0[k2dJ2N}2$R3Fy2CO1[42T:30V1,K182aJ2B19<1H11m'1}i00w3G[24G2Gx3PT2l}2SX2u+3672xa1t{2K;1,S2I=2Pa2dy3R02XW1P21461273Iq37u2CA2kd2Em20X2Yn2Th2gm2vz1{<2>y3Y(1o{1xZ2Q'2Vd2FZ1Tj2@)2&Z3Gh3ZJ2L(3Pi1#}2HR1YQ2&*2(M3852LF2at3i*2P71eB2$,2Y11@=2>c3JT2SZ30m3q]1]}2@W2ek2(i31G1/j2;l1}k35>2xm25c22N38n34/33b2%V3VY2/I3S=0,s2U*3dL3OT3QO2{r3Bi3472&C2[J3f*1P[1^q3Gv2z61iW2g71aE1r/2123T!0$)2+m2Qv2v*2}e2Vn2T02eU2=l3Jv20<1#72$s2XT2W]2@{3A?2DF3NC3s61y&3v<2s%0N2JL2&Y2PA2>{2]s3bL27V2f63bZ2up2Ya1(m1{k3oU2oV2>x2dZ27)2WG2&I2,}1c/2TI2zh2#O1nb29A2RM1U:3963bs2vf3Sk1e*2g'1&@2SV19m3v/3Cq2}M1,;11^1q!00y2,Z1>O2E@2f02T+1B$1XR1Ty1+I00z1Ib2h&2<20[]2Ru1p!3E92[i3Y}3H'1sP1pe1xm3Zu38h10{2pI2{$2iP2#+2P{12v3B60[Z2Pm1yG2?J1}K28e2[n1z,1Tw1l?2D81*<2V<1dP1/71qN1?}2O!2Om2aV2%:2'A2W,2xM21P1r{2w[2kR1{p1P33k;1]X1}C3H$3O63Fg0>x1%>2nf1(n1hi00/2AA1ul2sF3E$3ry2Za3NV3543mx2=C1/]2+W1bg2ip1JY1791+N1t'2041&D23W2R'2gj2$q23E2AM27'2w'1cX2b[2uU1'Z2G:1=)25v1/[2F%3M33Vb00+1o11>M1Fs2?A1%82,w2Zj3F=3231G%1'^2YB3T^2gL29>1;N2H*1eY31?2JF1N61l:1]?1+f0'02!o1=a2)f1nm3J}2sy1]H2T[1?q1]t1;{3t!2Uc0,q0>$1dX3e!1Q'28R2O32F32>b3g=2fY1dE2}J1gg1>r2ZA2b31;>1Kk2Ye1ZC2=,3XZ27h24*2v#1X}1O@2Ew2d72P131T35a1bh2+x35N2Sm2^W22;2%w3UB2qu2+=1(A1pT36F2xo2kl1$;3F)1/x1a31$x2aZ26x1O71M?2ln1$U1B;1MJ1GZ2y81Ie2LQ2O@39&1+v1V!2zM1m!2A&2]q37l1{01::30E3g71:?1uE2i23N$1HW2ig2z03Mc2{'3H)1(+35C19w38!2R93d@2zz2$b1ge21!%3KO3g]1>21$S35;26q1ST3cB1k73Q]2cH1TS3643a%0!g32=2Tn1)02K?1L^20x[2c$2O61!t1mL2eP1)X1G;2Ba22WD18@13m1?T1Ub1lZ2V;3HW1uR13;2+)3Xd1Y12SY2X*2rY2G$34u2{w1/l3Fo1r01'd1*h1o/3iS26#2S22es2kx2[x1^C2,J1R32Mu1yg2!t1bN2Ir2Gs1*Y2ED2L52p:1%{1$=3E[22[1J[1[!3JC1;b1n10{)1R{1D>1LF1'n2yh37b1o%2U;1#]2YU3OY2(T2%a1[v1RX3H@15A2?12Z!1Y21wV2[z32w3D}34F1QW3D/2Xh1@Z2^V1&{2>z3l/1Ey3NR21M2{l24h1!323N2Ei2cw2Sy1)E1cW1,G2w<2:T27Z2tR2(W28O2jF2on2Z'3kp2*O3Kp0,d2c42*73TC3cj2Eb1[d2g01Vp1((1Lv29,2T!14l2DH2G52L02Bw2J>2131T]1(}1O*36Q1X13Y%3732s(0rP3BQ1#M2o!1kO3L/25/19@2Xx1H,3DP0&H1+A1K335@2+n1lt2Cy3Mn1<11]E2Yp14;1=w38R1u)1/;2JJ26r2y72/k2&^2P?36c2np1sm3Gq2zy2N+39=1sL2ir1>=1}W2yQ2KL2ih2aA34U3jt3j&12O1>92>h3Hv3ih1kL2GM2M@2pf2uj34N0[[2QA1*F3SO0%n1;90w+1)92TQ20k2[L1qo1hI13{2/42@j1=g1/u2E82=}1kE26W1@?2U?3I@3v]2AQ1x]1+F3C+1)y2H]3wd2mJ2(=29Q3Yn3Og2KF3Ef2+61*H1gU1zi2OV2)H3K10wr2&G1^Z2v&2k/2cq2WN1f83531K!1c]39n2572&)2Qh2dx1u]2Rx2:C1{^1*i1tF1Nk2kO2F71*}3Bt3Mt2bY2ld1ty1qI0!(1IN2Uy2EH2N?0'q0'21l+20+3p;0$I1;D34R3Dj1!E3Z!1c)3bP2a90;k0,W1[+1yq0?h1Ix2VL34+2x511<<1yY3TN2cf1wd2Oj3W]1{/1]e1V%3EV1$J1?Q1:11%$1{W1x:2]B1o&1vB3H&1J21(R2l61{M23l1)Y2uR2#'1^F2BD1Vg2nJ27j10)2sw0@;2Dt1'T2f82CD1Lg2l70}31=Q1lY1ql1}t1K+1YE2%S3St2RG1ix1x*0%/0u)37P1zK34D016'1/q1n=1*+1)I2Hm1>/1K)2Jp2)!2+c1a!23o1vn1T>1nD1I'1oj27M1@;1id3Ub3be1$c1+e2M61oC1qt1uv19F1t91%A1O11dz2)y1v91f'2FX2}>1=J20O2D[2Yi2%j1;+2&Q1b;1!,2B,2+:1ZO3s21<^17{2aq1Q+0[v1?03P:0&{2Ra2''2LR2d&2b13C=2bo2K/2f+2mY2dR3RB2t/1vy2ah3Kt2*H2jV2n:2O[3X&2Wm2%P2Z31?E0}!1f=36E1&,1&b3A61:R2C#22v2kB2vD2d+3X01,T2nm2MX2FW2T'1:{3S$2BS1q)2i12%<3A%2,F2A+2J]3B02}R2WM1eZ2QJ2li1Pr2l92Q61iz3Fi2$}1(G2Ha3ac1{V14*10Z2061d032d3i52$T2W60%Z1=N2yB28;1F[1Mw19n1sX3l13Ar3Vj1>e1Ww2Dr1%B1=W2aP2UV1+O2J#2)x2!j2aR2Le2=s1!h1:80;u1W;2YQ3Cv2ub2,L36@2,/2;G1y>1Bg2Nn1iZ1Ah1dy16S0;)1wk2zx16j1+72G]1{328^3Hp1b#2Jl0:=1]611h2u<1jM1b:1aP28q1lL14V2nF11&1c=19f1Zj1gp39H3N^1%<2A^2*v3Bb1:;1e51z#2!H22@3I,3Hx1Ts1p?1bH2H>1p<1U51f31qm2g)2r:2tc22W24[1ei1b}2/@27%3f}2yw1BT2(12PL1qM2b827{1;E37q2E21x=1/n2O91zp2:J2pd3bQ1i62zG2R81&B2[=2;&1RH27p3Zc3d<2*l2oF1a&1U$2Z[1oh15I1#,1$<3kH2[719h1[C1#(10w2112kD34>19Y1Wq1bA1v<1hU1dH2s<2ss3M20zb2P=3KI32L1tu2}T24A1'b2=O00=29L1Rs3hD3N/3k%1Dn2,=3Hg1]@34o1jX1U71jT2sl1lh2fl2/N0(32rL1Q^1Ql1[)32V2^22N@3HU21B3Vf1jg2!f2P51an2Y$1Yu18a0:w2c721h2SU2:Y2Yy2t$2871Z)1A12Pi3Ks3MS2S11#T3H*2j;1[V3B^24(1mb3F,1vS38b3DB1n912?i1q>24P3aA1$W2}h2ok3DZ3P;3iQ1[A3om0,^2k12X,2nN2Lp2RD33{2jv2%62y01IV2PE1=L2fZ2Cj2l:2zl2ve2q'10A2o=2d02i%3Go3im1=E2@[1KS3812Yt24a2!U3Fk21u2^,1P1f&1%]2Ho19R11t1@m2Z$2MI1w71UC1tT1*P1XB1X*29y28Z2JK2Py1a?2No1zb17^1G/1Oy1z419&2or0&+1,)0}s2'D2LJ2eF1K$3Be3Te2&=22@&3Am2c@1;V1NA2Fr0}d2qZ11gu1go1<>2Zi1$02L[0/z1/%1:G2YH2M31i02YI3hG2]x2?E20}2351/s1#+2d52Vv2nn3p33NY2{e2tK2b@1J:28l0:30)f26i2D>2pV0%a28/2FN1aa33!1}<2161>v2qH1Pt2V*1>j0*!1bR1kV3Pe1G,1*q2C&1qi11{;2TJ1i/1sY2Y{31%23e1&M2&+1'W1'/2{W2A%2&L16(3r{2Lg2aI2W$2U91#v2*}2h/2Gg1*Q1Ym1!v1af21!2y321*3X]20o26h1)d1@a2I81Ph2rB2vd1^:2k[25%2yG11Q2eH33z1mv15'2eX1SH1^J2<01>w1}(2!g37O2rg2j#2nX2[M2yk0';2&!2#u1oH1Us1vG1S%2q+1Pg1t>1lu2q,1(N1GA1Zq1;r1XC1Mc2@c37]1s$3fT1sc1$y2fy1y91CR1I#36J1^l1&01wa1kc1)T1N}00!1RN2KV0)*1Gr1Y]14K2wo31*2=]1bk12({2Q]2HE2'U1%42:k2Oa2#K2Dz2n+1db3R>2pn35'1Zm2Hq2Gf3Ez2ni2kw1,v25=28s2{51[D2@Q1!u1PJ2>q2h42$&1UK1Q@2Wn3Bd2CV3fK3LB0[a29a0&L1tL1'62YG2f51oS1%(1vm2RW1{J0[e1Z'2py0,]1]f38L2$W0{[3ck2#z1w41NG19S2ZU3Ur2vj3n02!s29p1)%2^r2Gq2c]3Yh2j'2@P1&41Oz0[j1m31eG1UJ1m11N12l$1;$1H22N32AN0!z0s=1dj3ig1dx2[{2S}2Ec2c52Ig1$D27^3sI1('1u{1xJ1n$1!W2J21N>1X@1,+1/U1g)1zA28u1+V0[f2Dl2952B{27!2se2E31@&1Hk2k81j*2Qe39B2MV3RT1QU0]e3Gb0($3mM1OH1/a1dN0s'2Y@2xD1Q{1T01^]1Od1r=1,V1?C2Nz1gf23!2S?2fC28a1j>2o#2Xg2PC1,43F/1Bh3RX37L2E>1}E36Y2p*1%F3pq3Ao2M}1o83B@2Dw1Ca1)<2UT1=b18B3gF2x<0]K2so1>40)j1Ha2wz1MC3CQ2$a2#S0&q2B(3Ai1jl1uC0qm1QV21)0kR3gM3gY15B38{2om2C*2#:2543BX1Rv1>L2*h2Sw2YX1zx2iO1fS1ex2Xe2*I1<)1#b1hD1;s1&?2?a1a71yw1$P2OX1zy2Xv1Uo1yy1[g2PR1T!2Ms2!w2#y26;0$X1:43Rq0#]1l[1Dq1P$2):2k^2{12OF2=p2F'0=Q1$d3A037e2vc2^z2{73fn2L<0;^1^,1x72fQ1!j1a{2,)1KK24;2h71mA3UQ2Ze0^J1ry2SE2fA2vZ1n@2%/3d/3iW3G41zr1,22+d2lG19q1L<2V13o22g#2}i1;Q3D61vT2yp0?%1q42}S2kK1Y{3Q}20N2NA2xT3GP2PV2'S33(2i+2h(1w{20L17Q1VT1&y3pU2R50!s1($1GI2ky2n%2Sg0;/1%O2fG2Ke1Jn2!;3A@1Z21&52=f2#P28A2l+1Gb15k2E!2OZ2gP22C1ZD1L?36%2y;1Gs29g24?2ps2a02IE3Yx2pv2@y1B]3dM2V/25T2l,1cJ2n(2hT2Uj2s&3I!3n31j71,l32&2F[1w:1[:1!>3HX1jA1I+2+a0v%2Qj35I2AX0[<1^x2qN2*Z2Q&11{y2Gv2W(0oN3Dg2Bf1j627K2gh11z1x,2I'27c3A51FS1^11qb11V3Hi1SI1H]1:E1TO2St1iX2hV2s/1,U3J@2:L22ZL2hA0*W1Ue23Zf2kW2oj2b=2EE3u*26!1Bm0f51Kx2iw00?2V]3A$31^2V%1jm1&k1qx1}G2JY1HC2)%1Nq1s<3Q$1*,00@23G2+*12h35n14{2HX1uH2bp1U,2i(1>,1j%1Yi2m}2S<2mf22)1[(1xp1#e1X)2'H0!V21=t0+}3Zk3S}2!61)u1:51r!2Yz1YR1na2:%0!]1:V2oR2Hx1*T1*x1/i38Z3XA1YN3L33l#0xz2E&3Uk31}1:r3Oo2Q82g!12c;3k22l=1}S1;?22H20g1b31'A3Ua3kF2hl2,(2=$2/%1f,0)>2UQ2/Y1xA1o)14H1F@2?%2<;2}x1zM2:n2lR2K]20^1J'25?2hM2D11bB1S?29j2MP1^'28W2bm1i'2[936z1yL2Gd2e?1V]29%1n631!3c,0!i0&=38z2VW1mG1{b0$D3Cz1sM1qC2Sp2lI1d{3Bx20s2PP2Jj0{U2$^1Ob1{z2Uu1)j1xH1NN31{0%G1wE2H:2)W1%w2202{^1Pv1;a10p1q?28r2&{1(62IL2)j1h$35h1#E25}2Np1/41f(1,(11/2qg2Lz1mO2f=1gr3sG1gD2GB2c}3601r^1cK20*1$73k!0;U3jr2R41TV2A[2qe2[+3G:38M1+[2yy2q039b2[y3Y@0>P1%K2uz1Nl33J3T]2tj2y+1Ae1712#Q3Qo1*%1t+2B21;02IS2jH2Da2EY1Va15z0=#2Y=2z]1NO3341uM2{L1C12Eo2Uv1[%3KG2L%2^#3V(2[@31&1o[2H(3Lg3CV3JE2:,21?1;g1)G2K02f30=834i0,[3pL2If26*2OO2OE1G*1Y)22n37?28I2N21Vq2[N2<80wy3Gl3G22>I25m3Fs2TX1Nj1vz2Hl1cB2yY24&3Zo28V1Y#1=11r51a=2iW22Kb2A41,c2j,3qR2Bh1uo1&n1<,26'1sQ18F2NM1c82EJ2ob2a[2!/3Gg1J&3bA2aK2G,1sB2Jy1b81vk39U2G)0:/1rX1k02#x1to1fe12W1yT1rv3L^2Ut00$2a)2FH0(I1Ye1dY2s62HT1VN2cF3GV1!H2&O2]G16<2Q02HG1}V2m%2wA2M]21/1=]2}g2%E15j2{b1qV2=23GT1,[25[0?P0q'31k23I1Z=3J62ng2A#1=U1!y2sq1OQ2DQ1j?1RZ1a*2V>2F=2LZ2qM2rK1HD1'R2Q}1HU1#>24C24'2L!1Bn2yW2CW0?f2Z{2PD0$12r&0,?2U&1rB23R29{1O}2sB1BG1ll1=V1@J3Mv2h!10t2L*2c61a41ab2d]39:1Ft1(h1yI23p3O<1+T1:g1lF1^X1zt1qF1v/1>K0/Z0,B1(C34<1h+1a/2v!1kW21q2Jm2Jq2^92BH1=63Xc1mB2y52DC1HR2&V1ij1aI1#<2W+2Lo3Z92[E22j1f<1%M0xQ1+&1#=1*=2Rh2lm30{2Y02HP2O>38k34T1bM0:{1ko1!k1wF2%X2(m2?l1(O21}3Lr1n21#c1gS1ar2tN1[a0uL2Dm1r;26z1ZK1&)1{@1>s16V1xS1{d2fK1e(3n!1TC2sU25;1d21'M1rg17G11$1?!0ld2MM2r02Y,1!{2M43F*28<3Py1t713g1>I32W1xU2NX2o@34(2ov1]a2CX1d+2wd2d91y03Lp2Ds2Kp2F(2M/1xw2ZI1vN1D)35#2>R1zT25U1&^1om1rj1;P1^}1?%3F@1&C24K2{Z2u42gr1[E0?n1Yg1Wx1+n1Ai1M12}b2cb2mD1!'2TS1w#1{&11m1Nx1fk3IE2CP15W1WN27L2wK3tH33e2/T1M}0#{2)&1KX1x50(z1nE1jE2M%2w!2m:3GB33N20G1?c1;R3sk1qe3Lm28&2;=1mR2,n3b^2d[2(B3h}1A31]'1hO2X@1}r2Rr1/c2Q%2g;1g=1#@1/?2C03d$3J>3PC2h82^L3Ho1{v25n1)C1RI0xK1Q}2hI2XU1OZ1%12U#0%b1Co2ya1x<2B=1L)24n1I[3Xo2Ui13/1z^1!}2+O27]2B+1]c2$j3Yv1X,1rt2a61w=2>s2Jd2R+2C[2g31zQ2Lh3gA0!d2/*0]R1(,1RK2LG39;3N61}+2$72=b1k@1L&2^D2G721p1I22l81jv0)^2%R2bk1=X1xd2)b1>f2:31w+2>p2ZO2>K21T0'w1@}22S1:Y20M1ta2W01vI2vb1jQ2>l2mZ3k#39*2O<2Bv36M0yg2rR1'J1g{1'@1?m2q/2#W3bD3Cy36628v2^82Cp1eO1yX2,^2361%d1R<26N1R71+w3KE26:2Y%1:O1[#2XH0%92B/2>(1@@2}O1w;2:?2WQ3b418+1,p2cC2dK1wT1%U2%#1m:2JU1C)2Pn1qH3O41T}1J*35r1g}0+,0$$3AK0^?22!1,}23]0>(2;729e1y61k,2f@1:m2'91,N2FO2u31I]1#31q*1,u1i(0(!1@81,y1;Z2+23Y+18u1'l1uQ1KG1Qz2&$20H1(M1!b0$u0>f2K&1}p1he2gt2Ua1le2?U2K71l]29i0<41@f28,3W)2i50{o1fu1zc34'3VR0#S1tM1A422{1;p2^K3BE1nI1m@1u02>}2oN2V[2}F1$M0@J1Tb2c)3D02VB1%p3Ei1M(2LO1ZI2LY1jB1N^20&2bZ2qr0@h1f)1kR1QL1r$10c1'F0>b1K=2mp1!X32o1S50=&1rh22P1Cm1th1+G1lw0?i1Z@3R21xV0,F13&1W529K2=%3SD2bM1W]2hW3Z'3Lv1Op1*v1c61AE1m{1K'1m[1hJ1VV2,$2Ud2MD2r;2ed1Yc1(t1Fl1J40#)1]P1$g2%d2HJ1132H<1&:2P40{C1GY1k'2nW2?Q022$1r:1[W2)73cO1^73Ta1FT1g+2{x2,438r2d22EB1I>2*!1+%1l=1oB1oZ2V:1@>1EH1MQ1JH2a71yo3M;2;a0z,1v[1&114b1x?3Ip1'32SP1N+1pi1e11}P2IZ2CE1Zd1cL1!a2'[1AT2Q32Mj3w=1R^1R83XI2*<1y*1yh1Wv3HI2I>2{E3Uo1u*3ta0}J1J}1!(0*R1JZ1Z{1H@1ch1[m32A3fr1qW0>{2'p1fF1qq2/W1*y2;J36(2vw2M^1Og2n311e1pG00^21iV1b(2EI2cx1@j2qk1H)2*u2@k1D^2z71UW3Ov1q/26V0,N1iL2pw2d{1zD3cb00&26%1Hr1W%1XZ2&A1?n2Q{1GL2UJ1f?1$L2vL24/33O1%m2R)2CK33$2Ny3S238O39j3N11i72!51{o2,y1ok1Qw1LU2OH1mz1mC1xE0%15$1!e2#4129u1]p2%72zp3IB25F2#;21R3hB1dQ1oU1CU1s)1bL0ry2x01Dl0[z1Zk0c^3rS1qr1BH1UD39@1Dm3V]2Go31C3O32@13uq0$T1[t2Os3cK2xg1I?20p1A'2U72(/1zB24<1w11=c2cI3G>2Wo2Kz0;Q24b11A1[}21d1A+1fA1Bu1vW0(21]730^0;41L]16=1CG3ng0'D2Ku2+;1==2Ur3AI1x}2N(29/3S%27,2#$24#1O,1uS16s1;22>d1Qr0?w2p$0^g32}0#F3Qb28N13n1l}1/K1G!1Jt3U52t11&>28n3WU1Jq36r2m31K;1Q!1i+2VH15!3K72a=29o27H1@K1+b2pu2qQ0!e1912hv1oK2Lx1Yr2j22c>2mG2Jz2wD2Yg0':1(:2Mc1A,2=@1hj19b1F32hr2Af2D32H01T)1>?1rx24L2wc0]]2Ot2#@3rJ2ce2os2v32pX14M2xc1&<15g2@v1=u2m81^43DF2Or2?,1iq3PK2US1@k2?K2Ev2j)3f=2}c3l:12u27N1Y03j90xv2+Z2$v35Y1kT34}1Eg1AV2g61jK2$V2<1UE1<61@32+03D%1,r0+L0%U1(o1=o12F19W1/T2sp0tz1+y3R$1lm23g1k*1XF2s!1je25{2Fg3W73nx1tW30I1s*2W30}L13p1u+1aw3Oy2X81/O1='24z1?W2i^1u^1tN1Qv1]527&3L%1S[2jQ3Hf25y2=R2gF1x22H,1$s1wH1ya2mr33:1]o1oe1+62F!0%x1]R1SM0)#31Z2f>2vi0$z1gG22m1SA0,V2FE12wx1jD01bb2Wy3RW3ZS2U63EZ1D61O>1sd1ue1K10$k1r@1^f1wM1iC2,P2m/1c;1G^1Tu1u!0>t2*/1Lk1jb1kd1Z70]81(L1r,2q52PS2!u3QK3j,0/K1Sx2kZ1D[2dQ1t)1[01pL1w*1bm1y(1gR1Eq0iS3Uh0=Z2yx2e+21K1Rl2/62vh1nK2w;3BR2460:d3rt2%W2LE0%}3GH1{1ks0qw1i;2382eL2s^2hu1;v3Uq21a2jX2y92[V0n(0le3ZB2id38t2tp2v02770mC1H#1kw3fR0g)0%Q0{h2KJ1pJ2(<2!d3j=2IY2D;1gv2L&2X#1EZ1400&$1;'22@02fV2kj1Y*24t1(E0tQ2GO1YC2PJ1:^0%j0:@2W83Da30@2F;36A2Wh1z@2ER37a1F;2w,1;:1d&1Y(1:!1S(0tl1*z1Tc1$v0}W13U1k61cl3O>2;k1UQ3Wu2sT2x/1El2?Y2y@2Sh1Ik3P21P11U32pD2s*30<18]2j$0XQ1D&2X00$s1zv2E/1sj1#V2bN0!82+p1}w0}n2uy2&t2L,0$e0yz0[P1t!2io1L+13*0:Z1E}1E;1A^1t#2kN10x0*X1G01of1Gu2jK1Kn3AX0{523m1sl2cP2HU2i92E}1ss2O]2i$3UI1l>1Hl1}b1jo1ms37k3i70{z3k,1[S1>!2K{0@71$A1Sq1B@2ry2U21D71]V2z[1EK24)2:U2&:11K13N1>;1aQ3Y,3G#1WT2dV21;2%k2%!2zT2l!0*F0:52}B1[51F&1eu1t814[3CS2[b1>R2gc1Wr2Po3EC12}2U[1{g1e63FL1YY1aL20v34H1F01ik1GW0'A0,R2g:1AB1sZ1I61G11nu3JK2@,13e1%o1VJ2dB0&f1g>0mr10C2^i1se1Zs3op1h%1=F1)S2GD1m$1,h2NH3Vs1{(36{2S1]x1z93PJ1g,31L2mi2b(2y22zC2mt24:2o,1xQ29E2jh3ms2z13YO17/21x0/e2}/0{]2I00e:2'71(Q16;1sV1px3Y<14N1e=0[%3e&0:B1i42413D+2Y]1G+1'y2;130&2#52}'1hs1V71P/0xR2!82r92vr2br3ja3BC2=92sH2W115=1q+2Sj2fT0k&1Gv3D!19!2g&29F25f1$'2SQ1/b2I$1lv2W#2lp112323u2yM1+,0,j26928(1AR1Xr2eZ2B@2zN2K!3JL2sz1us1zq3e52I^2Xw1Fm1(F1SW1df2z@1mx1Im1xl0;i1I01JF14%1141N[0&92xN2c?2#03WB2sn2^T00)1?G2]62&0t&3mu2t82P!39Z17,27+0we2IG2Rs1?^1&E3QU1,{1Z*0#N119k3RI2'(3If0s*1Z12Ft0$f1;q2E:2W52v91/033021=1gE20a2dW2hd23T17p16T0:a1Zy2kL2Li1ps13O01r825#1CV1f024I2?V1iN1GQ2AR2n83DV2H&1PX38F3B)3d=1v+1x/1&L3p^2}43C00i=1T51A51H$1Yo1)]1'v1g71aC3RF0eq0q20&C1cS1lq3uM2eu1cg2,s2L{2rM1g%3652Pj3Ew16D37c2}Y2B?1{42b42dr3KS14m2[s33&22f13b1[i2F{1v;2R;1k23P*1WU2*Y1i]2KC1={2ib2UI2=+1p31n?33#1^S2y/0vK0=1R$0[Q1)L0)G2$$2sS1*n1/:1*^0vT2vF2:916o14c2Ek1kJ3q?2KS1=M25s2HH2Bn2i{0:p1+j2rT1!S2V(2Y?2[e28M1Ja27r1$+0xa12j1v22kc2e93ga1Mq2er2Yj2en1(B1(11Pb0>I0/*2L11:32iC2h91Ap1tE1}&2FS0%<1s02B;2i:0u[1T40$L1Gp27=3q>2,*1W41qs1o?1Gx1S71*U2LT1s[2E)1E)2R@0)12F01'L1*?1)?2p+1p91'o16k1D?0}N3Mi1tP1$z1#60'h11i1L51'G1i<1Z#3X;3C(1;,1X81fZ1fB1jN2h+0*x3Ca2782zA0x]11J1aF11>2Xs30j10d1*X0^s1%;2w{1zI1''2Yu1tb0]V0=W1IQ2;T1=?2>k10{w29v1y[1CE2VJ2tP2y?2R%1d}1O80[40&}1qJ0()1=#2e$2Bi2+K2%>2u?12m2i&0>i0ji0}917q27q23C0oL1{D2Y22}]0+32o*1r<0*80?E0]S1510$;0:x2Kc1)v1ky1a'2/01pD1@Y2fi1Rm20B0<=2];2AP2Lj1'02jR23q2w22QD3R11P=2Mw2aW1Fu2/J1^91^*1/)2/K2I!29f2re1yV2aw2H+2az1)O0?J1*G1,%3L10}x1[w1:#1%%1)i1V40z%3AL3dY1F]1]r0>z1()2C{2cQ2C12B}0;[1Xs2[B1&F1dR1$@1o92YV3Io1mr2Wa1n^3AE1aq1i>12+23a2n$2zH0,O0f!0!^16M2(q2i'1GM2N>0&72m^2w?2}H22?1zO2WE1[816^2s31Cf15N1D81Vd12<2&i2&61]g1T;1Vl10y1hK1(q2eE0]<1Ep1%+1rL2Qk30O3ai1rR1^D1j=0)l2BE1I$34d2e@1Md2F&1#*2%z1>k1ng1J80>,1YH2KG2H!1r)1{r2TD1%?1/X2t41xI1:T1@e12T1[,1}22FQ1u11(r1,z0$%0)/0n)2DR1b<1'z2L}2&011E0,81Os2q?14h0+B1Ws0}k1!61dZ0@M21D1s51x41c?0%$1640;C1y+0;+1K{19x2sc2;:1Ih1#:0&l38J2fM2QQ1P&1lc1{f32*1mc3M11'k2)t3Q332u2e{1[>2G?1&N0!O2Mn1:02qL16@2&w3H]2W:2e031W1W*2rq1Ru2gn1bE29C1!s2v+2EN1,C00[2J'0a$2a>1{L2Mr2P#1lX1*32E=0l/30422k1pO3N32vI2eY1u828L2)P1z(2dT1jH3OS3AO2ns2:w1802al1/>34#1n'2yO1T?2[v3F?2?^2X+2dk2J;2$?1I&2A91rz1663q!1or2hY1pS1LG1Dj1Tv1PI1hC1TW2xu2EF1WE35&0,t1f[1l92S'1l52?T0t{0>814z2S#2na1{i1fK2!S1XP1AC0[M2xS2{U1@62'?1BZ3Q83K%1W(1(&1C@2j52+v0^h0]u1zw12%2ZQ2yq26Q2ct1F:1',0/a0>N0(e1172RT12e1p#1{N1Rf2+u21016B1]I0:91Lw1zN1%)1TZ1=r1#Y0?H1m]0'/0vP2L'16N0t?11l3Vl2,73Ju1y;1F81gx0zN3mV2>T2VA3o82rX0$M0/f2+(1a^1;50lB2;H0!l0$o1mi1zV2k&2Xm2NJ1:l1R>2(@2Ix2lx15D00]2gk1(41Fy2/z1o'0{R2jz2741r91K,2E(1/'29[2I:2GF2Q<2O;2?f1mj1^01uj1[11b00+>2?u2Zu1um19#0,k2eO3Aa1No2Y!2M81&c2Ug1$]0#}3Md1rT2Mg1*f29@1E62Kd22o2zr2I22jy2C720q1AI2L^19c2472?y1Jl1,$0;02Ij1#21k:1l12be3t/36]1xX2e42e/1hX2%%2Mk3891'K1cs0wA0@82,<3mG1B*1Y43a31wG0[J1,d2MQ18;1}e1g11Re26[2?42Bd0@A2*F2a,2Iy1ir1}30rp2K13C/2$g1G)34t2r41ic2['1U91E@1{51M'1?D18O2091}n2UW3Du1)J1m}1Nb1b*0'a10<0&U0gH1l<3wH2xd3f(2]h2?/35D2'L2*13Cf3BP0x?1Z}2{C1%C1})2}D2o73J+1Iv0{/1NK0o#1b>3A;0>C2Ce1;G2Rb2Z;0#p1?>1UO2Xb32r2Kv3gT2f:32@1t=3221q50/n2!Y1h91It0y;29J1^R2WO2qV2uB25W30)2zi2hy2;;1Ur1Sb1]<1&w0ns2[S2u%2d'2;33PY0mj2yb1Ba2)[36;3F52kn2p3D{2u,1P>18)1h:2U%1%,2Tm2a;20T29w1H!21^y1**2/B1TT1ho2kf0[H1r'0x+2us1KO1M/2oc2z+3UZ20@0rN0,{2N#11,2g}1wO2{d1+*1ff2BM1O22MN3A#2j{2}k3Rb3t)1=D1qP0}p1YO1ke0vQ2/c1v$0;F1KL2Vl1k/0uw2G01%I1a81!q2Fb1@L3hm2)a1b11oD2AE2pT2>W1gO2@M2J83U+2Un2Lt2Na1,#1QQ27x2le23O1d!2=U1q;1kb20F1Jb3FJ0>o1[u1Z+1720/#0['2$n2t<2me1cC1[]1O42e}2dD0/A1yN28w2S+1MF1b{0o512^2#n33G2oo2=F10o1+;2q62Nv1bF29U3IQ0%M2Tj1b?2f'1Tp1Pj3A'2[X1XV1?J3NS26,18124f1LV1!421918P1B<0!Z0>a17<2V21<:2K%0,@2sC21H0us1T131z31$00>1I@1Wn2HO1f*1Mg0#?2}j23V2u]1c22Rd1sa1UR1f>1gX1S/1E+1GB18#0$U1nW1OI1g^0u;1['1Ze17:1MD2KM1t21ht2(r1R?1p41s%1Z!1:913G1@U0ui3m<1Mn2/31TN0:y1(X1xe1m*1i$1m41b'2eb2BI0}(3Sm2DV1tk1yc1vX1lH1x!1r10[83Oj1n[2^Q3jk2S31]*1iT1xR1^P1Jp0j70xr0%?3Ff1q'2}$11)0>'3hM0%w1MZ0p?0vv2m$1Il1;B1^c12bV20=1sR2@;2i]1)H35J1kr2oE2iQ2UY2AS2=q3Fh1Ct2U32eS1V/2ZF1xs1nQ2/f1$/1k82zg2;v2O%0*c2Rw3hp2,]3ey2iM1l(14!1?s0XL39c20d1?Y2SW2Ve2^n1oi1!?0%+2d63E}3Q61pA1;^1h@3F!0,L0]W0#(2?P0]b0r*1ML2WU2IQ1!)2RP1t/2y^1@2(J1T31bi0^w3Ku1oy1sT3Xb1ip1g<0n+1HJ1FM1KE2Gz1A(3ZR1@$0}D1?l2AL1QN0^91Z31WI2512ey2wX21G0!a2Q@1ao2,f1ZS0/!1gP3Ts2K[0z71Xb3fu1F{1eM2F42NB1S;1!@2O*2b61uY0:?2a42IX1uT1D]1zf0+/12Z1>H0k#1MM0*Y1&]23j1T[2;I2)d17g2+J1H62nV10@29M2Pe2J:1'=1?+2%h1e711:2q>1Ma2zo0vl1;c1&t2/^3n>13cC3e$3cf2i71ES1c00?N2K81;k1(g2;X1pj21N1RY0{^2tE0{j1${2ai2(l3nn1=z1D40xA1@00rX1I,2{q1980lY2C@0)U25R2sJ0#21nk1:I1322tX2}l2$z1hg1Dc3K20*z1S+1uU1md22y35,1PL0?g1@S1zs37p2ql2tz2/+1gI1,?1sF1du3AZ3J82K)2OS38D1JM1Aw2e!36X1CI2Px2s@1;42c<2q=2uS28=2vl0}+21>2H'3v#1f#1b)0m:0wj1L*11?0!x2B60s]2s}2xP1M,11[1f:1L30=o0?82Cb2Iq00:26c2FD1c{1Iu2k3Dn2a}2Jr19/0r=1^p1Mo2E<3G(1Ii1mH1Ia2I{0tt2QC1TK1}41Np2!$1QK12G0@{1vA0w:1j41!w1^k21^1){1>^20!1)x2km2Nx2/M2Vm1sJ3Q&0z#0[A0&w2t:2Wk0i!2CU1JI2W92Hc2rn2T#0{+1>(1o(2^F0]s2T*1Lb16P1ug0$/1Qq2bG1q@0h=1tq2sM1{T0+z2l)1&r1DJ1UF1CY1(I27v2*&2Xn1=!17)1Si1+c1U'1QE0;y2',0oS2)i1,Z1:t1)M2?H1j#2>?2D]1s92a83fw1(V2WC1v%1!Q1,723*1'H1OK3UP3RS3Wb2+>1ti21b2(+25M2722QE1>)2+t1aJ0;D33Z24T1>A2ID1fH1;739t14x1tc1@215a2dX20P0&x0fV1;z18d1Ko1Ga2vV2JS1hp1+42Az1Jd23)2D412w3S(0$*1!d2qs0>A0#Z0lt2Iu1ZA2X)1yB1J]1](2^S1zm2zj1'Y1k^1q=1!02Z50%I2^y37%2no2ZC1]d18<00'1+{2P]1%[1e<2pR2y[3Js0,P2Oh2#l2k02D'1?r1eA1tQ3Jq1V;1gL13t2=L2Di1w'1=l2H91'N2c/2de0:j2Yc39}1re26p1^G1PV31y3Q52q41rZ2FK2$:2WV2BQ1R*0>l1#X1kX2lD21&1}$3d;2%}32#1Kv1Wa2G90(J12S2G32eW0)[1+!28X1D{2(U1mP2xy1u;1t;3Gd3w22x31;O2*%1iB1VD19:2KN39f2TT37+1]j2a]3br1d90<<1vO2p12cV30D1+g2y12hn1h&3HZ0+;1Lh0+Y1M72WI2&z0&r21+1IG1[[0{11?&1zz3mR2SB3W'1#A3sH1xa1bv1yC2gd2@^1&%1OP2]L3Bg2F81(z1d32))0*?3M(0'P1Cl1/r2Aj0]40s,2o}2r[1c%1Nt2FA1q02Lb1k!2:72#H1!+1l72kr1e{1uV2bi1^d2Dq1;I1;60{:2YC0x11eK2N;2JO2Yk3h52C>2SS3G&2C32&,2LD1$O3tr39Y17F1*j1N:2Wg1nH0[B3Ah2Vz18r0+T1N51h]1':2)K1I*0[Y2/V1&U1h*1x)1=41'+22a24J2hi3HP2*U1jS2Qb2?S2+N18x0vs1rF1Lr0#&1cj1IY1%V1$,21j1'f28o2p]1FF3Li0/G2u/2Ul2oO2Cr2@S3Dx1:%2Rj2^(1@g2oi2j?1=G1J/2LN2/v2700>T1,Q2si3B*26j2y>2^{30!2='3D^1{#1/d2R11hr3262iZ16H1Xi0z^2c^2S51i53Nc1T*2[#2C62Ed1y31#t2gx1A[3b51}M2k61'[1cv17K1I=1031mo1V92Q;1W/0%>11a2bw2052XR2?]1V*1^V1ux1:N0?B0^P27e0vL1Fg0in1/52'o2&n1L,2712@p1$F2D{2ti2Du1Q<1[=1/}0^K2jG19K1hG3351nv2R21IJ3922k]1'72172Xi34!1sW2mN2ji0&a25B17x1a<18[1CX2oM0pP2Av2Ow2!}3H31u33FG1A]1b$2#A1bW0}l27g1WF1^52sL2)o2j81ds3aj2E118j1P}1wW14L1o#1;]2#?3Y>3Z21V61i81,83Az2Bp1Yz1)*2o61Hi0mY0r]1nw0nj1ci1au2DD1QA2UH1TQ0(D23:1W017t1)P1nF2Jo1[^2,i1Aj19'1BE1*51/h2+31me20]1bT2$r2w&0UT1TA2rS0^Q1*:2eR3Nx1Vt1ov11;2X:1?K1z$2*+2000jX19o2FY1@z1dB0s00zm2FC2{O0nm1gV21m2Zy1OD2R[2(I2&p25S1K03Un1,F1;M2zn1V(1Kl2XL2mU2p%2Pk2u#2=I2;B1]z2q&1un1hw0Vm2UC1'<21y3JM1,11O%1Z02ys14Z0<82Nd2uV1sS1]y1y41)m2g/1sO2B$2UR1],2Ib1+12GP2m500,2(D3Gu3H?2w51)Q1Lm1WG16I0vi2eC3NZ1z=1S^2uF1R/2V{1C%2YF1&[0(;1&G1E&24g1?Z0=?1z[2hb2OJ1js16l2JB1X21ru2M{2NZ2,{29]2BZ27l1F?3lG37Y2d,0^$1dC2EG3e]1N02'I2K,2522P}2y*0mN27@3C52MZ1?61!F2Gn1BM2!e1ro2td1L61^i21r0^A0n=0v90uE0!)0qk0(j0xG1eH1xj3Mp0({3R[1?<2Qy1{,1@H1is1tO0;m2k91dF1Z41F!1S{1]/2Bj1Mi2@V2WP1ja1TE25X19d0;j0>w0[#1q[0@'1K22,g1rk24c1uh1pK2G#2Au1[91za1nj2QI2MJ2SR1}^3eq2Pp1PQ1M01WC2*r2uW1{s2j}2xb1vo0zH1Sr19G0^'1O:0,o1?82Vb1E!1{92@(10G3Na1)>0y<1wq2nK1vV1FD0,e1u?1nq2P(1RJ27C1n(1V23D1X[14/2$)2i}2kT1GR2n,0rA1XS1Vz1%h0{21jZ1sp1b]17z24D22c3pt1,^1O+1Me0hC0b{3M#0S26]25V0}h2p=1iy1ek1CO1v>0;I2nl0vj28)1+P2NR2+Q2)g3951!M1m<1T,1Yp1pv1'#2zs2yJ1Zb1]K0$Q13x0)]2!]0//0!0:22=<2D01FN28'0'I2I]0;&10u1i[26=1)F2]Y3Mq3Z&16E1vr2To1r#1Ak3ZA1sg0;:1]01X52K32()1d,2zY1G?0?30/b0$Y0^q0}F2It1NF1TU0}]2*X15r2^72O52>20)521E2tr0hg2A$2qE1nX18v0@K1qz0$t1p,23h2+h1<23K,2}u0@!1ak2DI1Ci1bl0*I1Kt2I42P21$#1%i1[Q1d?1nB16t1LR2/$1y$2&@2{B2Rm2qJ3Tg1u71iR2Fx13:2O}2l51J$1N]2O+1hl1%#1c10:^1;/1R'2WF3Ap2EO1a)10'1l20@s1Pe2Y}2fe0!n1p71a>3Jg1gh1Ot1>Y3DK38)0&;1Bv2YM1yE16q1&i1>Z0uG0}e1ol12&1cH0h50%q1Y914O1Hs1*60f[1rc1Ab2nw1H;2!22lc2O'1Fo2Gp34C1dI0+g1b41]M1Ay1991:b1#n2IV29l2HI1eg2s'1{U10L1EI2[R1)s3Dw0;q1rp1Km2600tm2#,15G1&$2bP2j60[{1iv2hZ2SH1pm2o&2oI2;S0!/1rq0y!0zI3N729z2cy1{t2^N0tM3B+2V#2J}0]H2HM1e]2xK2UO2K+2h<1{82*x34q2CC1j81+L0{a34*1Sm0%E37J2lq0[E1Gk2l*2Xp3YA0&M1RC16X1'i26w1;F1py1ni1'E1/E2s,1y'2R^18U1W:1Y:29R0kP1Z81/B1JW1k'1j233c0mg17k0]E0'#2K^2nM22M2ZN2?*2e70t;2l43Y00kq1#P20e1sA2OG0?U2Lw1l!1sU29W0up2D=0W>0vZ23L1SJ0'12<>1%62cN0u#0l@3LD0n%1fv1vM1$K1Ro22=1tx0/r38l1]W1OF1%r1X#0101?a2:>2Bc0{x1G62p316*0hs2xp2,D2Dj1!<2We1dm1w339W2Gb1N&2Nb1V>14i1<=1/!0,f0xd10,0{I1Mx10vz0c?0(o0$'1F92)>1VG1KA2Kh2f,0pl2mo1N=1lx1&Z2kX0l=0&p0j{1=&1[20q!0pQ1ZG2y!2Q*1wu31M0xe1oX2*#20b2[G2yr2V&2Vt2Qg2:m2Ry3cg1q$1S20p40=d0#d1ZE1Iy0/[1%Z3i!2:{0*L1Wg18p18L1jf1K51Sj3Fv2{+2I[32y2Km2H?1%e2R#2241&P0ne02WL2as0fm0Yr0Y$0gt0fb0}z0%40Wt1Dx0sl0'$2p42g[3uH3KT0ud0(+0:42VY0lR2E]1RS0wv2zX1mu1K&1751ub2N<1zl3N51$a0q@0uj2Dx0fW1$10;50!q0z827P2E922K2bc2Ux0Xr0?011k1DD0y>0x{2b*2nU0qA0(%0#n1oW2hB2NI0ub0^x0gS0[n0110uy2Fn1$Y0qK0fX0nW1vD33K1D12L826X1{K1XG1*11Zr1C^22E0<%0rE2Qn37o0$F2/(0@00Ty3a:0[^2QX1=K2Z*0M/1yx1?v0tV3ZN1Bx1bK1*o1}s24$1T:0h:1)$2Vp1pW2bq2N*13f20h0tf0kf0Ue1jt0oW0s!1WW0t}1>'0y22[?2+@0sP0%H1;f3U!1*L0t*0n;1Xg0h#18824r2p!26&1SQ11r1'*1S@26Z2bg1$%1Er1<'3Mb0j80bQ0Nt0&X0W}1Hh0v>0uA0kt0l81180WB0m$0ge0/g0=p2'j2*A10X2Xf1BX27G1kC0=N2KO2D+1Ow1:C15#1l%0Z#1u21A21XH1Qj0=41]S1%q1n]1e[1>J0u!2QK2]#1qO2gB2is1J+0rJ0Ze0l,1Ln2/H1W20b>2fU0lS0gr0#e0z=12s0j91jF0yL13C17Y1>t1VH0+?1=x0ue0m2g41oV2881&J0];1TF14s3D)1#B1G#13<0x'2@t2Jf2MU2{}0%d0/S1}R27f11Nf2PW2fH2?c2#t1Vu0a)0120[F0s71C;0V/16p16J2Ji1,61m>0YA0&h0ZZ1fq0g80Vc1ZJ20y2vK2jo0sA2@O0tW1s^17L1uq1em2AC2rE0$G0sh1a92P02YR1{+22l1:J3Ud1Gg1]N2>50@%2m'1%f2AU1EQ1n}0kb1JN1250=@3Ht0!{1#i1Y%0g[13a1SL3Lw2(R0UA2H#2'^1tv2eQ2=&2H{1=,2Hh2&S0yW26{3u80W?1gq3Hz2=?3XT2$>2fL3Gf0p50X@0}R1>B1d731O20x1+r1I%0yu2*'2M02fa2Rn2DL1dd1@43W>1er1j[2OR0qb1,q1hA0pR01324E2tJ0u]1N42y41?P0mG2ap1O93X,1]Q1&(3ee2Mf39y2U11]]2$S2Wd2G[1RP3NA1ed1}g1Xw2/O2ar1MH28*1Qs1u40;61al0TU0d920f1KY20S0e^0mV0mQ3Ky3AA1W12+A1!L2At1f62X'1T<16x2wh1?R14714#1m60xu2V,1Xk2q]2{k28]13h3GX1Ic1Gn0?{0tG0@?2cu2[F1W}0'%1Mf20K1ay2}W2(y0>c2w/2jn0sw0UC0+h0a=19E0fK2nH1pP2j71y%0(?2$y1P,2cm16Q1+m23Z2oY0*r1Cx2(G1V^2Hn2?d1EL28P0$41Rx1u51)!3T<2762+i0*<1d@1YT14P0^21=Y1GG0d1mT23+20yr37S0=j2*30WS0cI0!90^T1Jv1dw1G31IA16>1qT0tN0l21=*0#L0'Q2W{1bu1@%2NF1:S0's3L#2RF2:g1A&1cd0&J2AI1Rk2271kY1YD0j=2EW1gK1i&2g*2Kt1nc1On0l30oo1EW1b/1xc1aM1GC1w[1E'2O#1VO1aN0$90Yn2hK1K?0*412b29x1c}1uF1W70)?2l[2(o0yh0,g2%00[h2!D1Oi23b0=w1A82O,0bK1xz0ze1hM0uk1&Q1/+1R(1hx1Nc1/V3my1OT0:M17m2Nt2qi1@<1i13k(2;n1oA1i}1:*2w)2]R2mO0Mo1U81c'1bw0&<0s?2FM1X=0#P1Fa0^a0^i2}Q2Hb1k&1000oa2[o2H=1;j27m1Gl0=50%J1y!1bC0x42Pf0y/11F2}z1*&2zF1ME1mU0v21HT1190tX1HL0:U1bI1v^2fx1B(25:11+s1*O1n82[K2Rz16W1H42Lr0*O0(}0jb1W?2#<19=1jL0@@1iY0?O1481pz36>2TZ2xC2'<2&]1fE2Hd2>00;g1^m1aO0@30p}0gT0Y+0k%0n}0nn1}]0{;1t427*0<:1Su1S01g02o$2S$22+34j1')1K[2h11Dh2GX0L71cI0OO1Je3TK0++1NB2q!2}n2Ex1Bb2bd1cA2Uz2J[1!V27n1U/27X0y%1QR1qL1Lo1xf26J0[02?C2MK2yn2]*2$82}<2,51r?1CT1W&0=O0rq1f{2Jx1Y<0q03ST0L0%y2Kk1g'22r1xW1=/2;A1NV0^U1p/2Od1)31jq0)60*]1}{1fb1?[18:1C{13$0%k1^s2ca1nL2G@2l{0#G14E1/J13H1{$0>W1wg0Yx23J1BN1!T1RA1F42Bg1b+1,<1Z920Q1gj1lf0%@1mX1oL0:q1{*3JD1Pu15E22x2]70{61l81523Tt1+R0{i2Mo1/0g@3EB2%L0yl0v70*d0*'2C;2kV1;)28b1jc0ot2M(2m;1Bc2cW2Wl1G=17V1z?1LQ1:L1&'1S!1r>1WD0<52X=1?u1G$0+U1W=1Do2FB1no1rs1*{1b,2So1lr2e#0+41#u1K(0y+2tA27D2AW2lP2BJ12M12f220w0m}2Y#0b02Rg1bP0W@0J12c0}a0!T1Qe1EX0:}1Q70<,0'42ak0+m2sZ2622nS20/3Ex1jW0=]2mA0,&0sp0&%0{&2m{26S2f(1Vr17}0:R1Nw2K'2K=1:}0ck1Tm2QT0){0h31j}3Gs0s11[J0gy2do17[3Zl1<&1KI15H0}[1E82M=0#H1Cy1MO1@A1NC17X0+51U+0xn1nV2jC1]h2PQ3421)73Ow3CE1=d1:u0nb1OU18l0'31ku0]C0}@2262@i14<1]T0oj1Q)0u?0=q0h61BV1tl1{H1Qf15S22B21]2ie2!O0yP1$o0}/2%Q2(O24{1S'2:x1#K3X70rS1HE1XL1GJ1?f1@M1n&2n/3FX2DJ1Ul1M@1L72N0[91XM1e31$V1*#2Rl0+Z0%e1U;13R0bF0=(1:s0=F1{=0ql2}71*93Y;2xI2PN1Uj38f2qd39M0{P1Y@1s,1%L1ib2}%1Cz3Cc0#Q0/Y1%x3BL1f92>Y1,J1NE2;W1N#2xe1c+0tS1*!1Dg1,50+w17N1]80'i2v$1Mb1Br1%H1Es1UX1gs0wf1;u1cE1st0pf1?F1ri1Hn0gb1S31?)1xo26b10*0yf1a:1u<2m72Si3A[25$0=z0ib24u0:N2gT26l2ol1tU0lT20z0o92Vg1B:0(,1jO2em0)v1HY1ju2?+23P18k1i?1y)0pA1kv1Hb1}!1j90&N1vp17u1/L0k^0kS0?(0)82wk1K}21w0s<0bn15X0v(2GK1vY2<^0>?1Jz32{1UZ27W2ik38S0'W0{S0er2o310v1rn3P<26K3Iy2Ok2n;0zc14J1rV2d81%^0,v0]{1FV0w$19Z2D}0%K0+^0pH10=17r1P50]00$v2e'1Zf16#1h11R,28x0={0?X0mF0%i20'1p;0@12bI1(20Yf0m21T#0&m2b>11}0;R0yn2OW1pZ1eP1im1dg1dr3K51e:2p71Z?2xl3D(1P{2^]3oQ0(Y2cd14I1N$2P82,B0O^1&X13'0:#0@,2Gh1(!2F?2B11c<3GS0/60oX0>013V18c1111WX1U00uc2u>1,R1cN1sf19i0&g0;81uZ2^b1Y>1cm2Qx2iT1ey2U]1Rh1890$[0'*25o1Nu1Up0$p1G[0he11L1'(0m81e91[@1PW0]m2H10!o16/0pq0k61O&0)I1nJ1VK1Iw0@x0q#0([19H1Jw10$0+a00f<0mW1]k2&31uN2qj2(02t]1<30}#0(*21g1lE1H'1N*39h1+z1v:0[!1M42>P1}H0>j0?Z2%)1lG0sK0^Y1in2p01C20sU2?Z2(Q2Z+2dn2s81c:1860,c17&0@/0{40;*1C#2xW0@1aZ2gJ2R]1d%1J50qj2KU11G0i;0Rl1+k1m(1W'0*G0aR1IS20r2ru1De1920hI0;S1O(0#z1n+1Wy0>+0xb1B)0y,0jI0>h1,=1{}0wg13L1PD0dA1<;1DL0]d2hc26G0@i0Zg0;'0ZI2{z0&!0i]2+}2Sa2cz0'92F]2/]23t2n=2CR2$h2qK1$^25O0*U1^t1qh2ZS1(;1ny1HH2Rp32C1Uf2{X1M931]2HY2jm0]=0@t16!1Io0>}1LE1fO25N15e1pk2IF1NW3j;1Tf12*3b)0$824%1k124212#1Ys2P91YV2c'0d01k92sh1g20;91fw2oK1+^1Gj0zf0}:17A1?k0*60^,1730;K0@[1:71S119]2p<0uH1U]1mJ0}o0qB1$!0(]1/*1i)2*$0YV2ET1Ef1&m2250(p2TW29O1541dl2bf1Zw2LX3Gj1bO3281tY0sJ0op0!A0xf0od0pB0u$0/?2*[0'=0rT1Bf1r*0&O0[N0nc1k31LS1]q1mK0J32Xy1D$1Kb0=G1ai1uy0r}0zi1X^1:c1?o2S=1Gh2ag2$C2FG12L0a31X:29<1U10>Q2f]0Z)2$x1aK0Lb1PY0x=0cM1RO1Ki0C0wk2sj0v!1l2qW3V20:W1+Q1041A@1n:1p:2B[1'}2630@W1Gc1&S0{k0SE0uq0q>0+d1*02@F2mC2*V2E#0zn0it2qP1yp1390((0Y{0dx0pz1kl0>q1IE15f0O&19r0Y[0fM0lZ1K>0#51ca1t&0'k1Dw1%:1Jk1OC3Tx0[t0$A0o{21V0N72uw2a32O?1#812r0>Y31#14j0{l0!W0@]1}[0h,1dU2<=0n,1qa38/1Bd0&01lC0so0fY0zB0/31Mu0f60wV0]n1&z1S$1V}1+u1s/1Y?1430*l0iM0Q;0s53Z]1MY0,>0Xi1%t1&91We1c,1d^3V&0t00ff0,91^g1PG0!&0#s1w?1#^1>F0*91=%1hP1!c1{h0p<0Q%1>W0cZ14Q1ae0=012(0el0V$0IR2u015t32h0W#1B40*y1u90$,0rc1iw1fm0/y1L#0o$0@c1IB2ZG0y61J(0r$1{X2G81y713D15y0>10q31!G2kp0@0l^1JO2AD3O=2eV2X[1X!1;32LU2Bq2cv2BT1=j2UL1571G]0z)0sH1D*0dX1Ju3A)0vf2Ns0x227R1(u2l]1Sw1p)10B2O11wh12N0)212z0,l0+H0cz0^<2L?0no0U!11O1?H1J60^E0e812n0w(0cb0gn1E21ZY12>0Wd0h@1A61!;0oC1LM0,M0lU01710^1DE1xi2+#2M12++1u61&70&:0(w2@<12a1UB1Z^1j;2Ht0$w12I1en1%*0jD0)J1JP1O[1k$1sG16K2*]0cr2ix0k!0'+0=K0Tt0[C1&d0N80tH0wp1cn0V{1R51U?0ii0YI30k2:t12i0kH0$<0'S1nN2GI0kd0yR1K/00n81G41/$1p61A1x;1Nd0%r1{%1>%1M)1f!0+n0;A0N>0KS1mM0)E0&d0,52[^2Y&1!o1S&1Vh1Ho1dO3B=14R1Ny0+I1xF2A}1fz0mn0vU2ko1eQ1tm0>40?I0qg0/s0#T0cO2C$0dB15O0s>0>p1SK0{Q0,r0#w0hb0sQ1Fj0lH1e20:f0gz3UU1)[0[c0+V0<^0{=1D(1g&2N=1}01201g@0]12Qs10i0Lu2%52tm3SB2Ae1}N2]52v?1VX0*J0y72He31:0@}1>D2Ki1aV0]F15Y1n#2f{1*S12J1pH16U2kz1)831f0=11P%1jd1M<0z13bU2Q^0!:0Vw2921L:1Q#2Il1UL0?x1<]32T0Zl1GN2i612A1lk0(61YL1Cw0t>2aj0e'29S0%028Y1v&22u2=G2fr1210#[35*1}y1&811y0>E0^80,h1F*1/e0ut1Al0>U18i00T?0PX0k*2]90)k23v0y819^1SG0)Z0/T1#{1e%2GH1pd2>*0]t1Rr1Qc1]91z)0]60yC0w/0't0l&0Xs12o0g60ms0tx1Z/16,17=1Pc0=20va1[;0QF0);0'X0N!2p'1zP1AL0]!0YC11o2G/0/00vb2GC1YB15T0/m1t@0}X0$B00]G0tJ1/m2AH1C}1vx11+1TM1kk0g$1kG3V{0uU0xo21$0mD0kh19C0}S2Eq0je1QF0i:1f11G73Mo1Fn1tA0^F1Pi0'{1aA002T71AF0ra1z62[I0Z00pp0nf0h*0QW2l?1W,1Q*2>H0%*1xN1Lu0Nl1I;1cp0u/1Mh0yv2aC1@10*@0b<0d=0tc0#O1}/1$B11%1f%0%o0h$0eF0*,23#0VL0Bc0lL0yj0/825D0]A1AP1Dt0{A1J=0!00Rs0=H1*'12/2nj0]o0dT0#f3GJ0pJ2::1He1D21Hx1931h'1#S1Iz0>#18s0e41yH0[I0zG0$C18q0/c2EP22F3CK38C1'g0$+3E61Nr1E[29B0kW19V2^510g2f/1Mr1Fe1sH18m0{}0#B1lI2]11o<2B]1?,1'$0m'1li1Yq1FU1+i2^l0@G0$a0{F0%,0p(0rB1Li1DR0DO0c80I(0iR1U#1s;1IC1Az1dD1PZ1X$1)Z1qv13[1QY1)U1B00v[1)A1cF1701?10/O0vX0x80fS0XP1w511R0]r0,m0jW2jE2xO0q]0(L23F14:18D1s#0Vq18Q0a/0R^1Z(2Ng16f1d41tB36I2+!2810<31PT10D0#/1p>0(r0><17;0de0nL0U00md1ly1rJ2?h26n0jO2%I0f^0eY0'^1vw2VZ0&51<#0sg1Ge2co0#J0kn0pw1QP0yw0@m1I70)L2r*0kx1^#0))0}&2ui3Dd2ZX0$m13Z0+r0;]2*N10M0hJ0Q31s80&D1RQ0wq1HI1m)0*e0xO2Hg0Fy1=00XZ0#U2UE0sm0#r14}1}?1kh1ZQ1?O1q30Ok0,S0xp1Ky2%F0k;1#I2c:0p'1]$0pa2oC0n:3371V$1]s1CC2VC1ga0[T1YW0wJ0hp0n^2s;1gm0ok2A80;G0o10pC1Z<1jJ0rQ0>)1C=1ZH1l^3U20rC0^t0[G0^]2lX1q^23S1Px0<)1RD1Ss2yj2AZ1s{1Ej1B=0>216L0rr0y10(E2]U2@n25,13S1eL0u+1Oj0jP10(0'T2oH0!y0wb0wi1C63fP2D!2Pq2z,0]v0Dq0f10n!0x!0D&0Eu0d40RG0W31;&0a40Xm0bo0s:0yo2Xc19t2xU1C50pn0:S0z[0+s0tO1Vb1^[10N2T<0fr0^Z1mF2w+1[{1}71XD1yd2kh1x12Xl1^M1o@3151lM2JE2@b0eO1B91Ff10n1HO1pC1220[R16F2I71(?1Um1$21}%0)=1;l11*1As0f&0rK0Ys0jM1vq0ab0${2[T1M>1FA1In1V81CD0<(24Q1632U{1oQ1MV17y0@w0Xe3Jb0oI0!J2KB0b?2Z>0lm0He0lM0QP1oo0X}0?}0E@0KK0;B0j51[M2/D0/t1010$N0SL0@e1=p0YR1cU0=30z&0PO1>Q0Xy0hQ1Xp10%0dP0du0fn0^z0t$1g30si0*D1762wZ1W)1:P0HM0hR2b00UD1By1/32Fc0*%0/&0TG0:k0F71@V1>u1Uu1=s1&61zu1Hp0P=1=(1F(2w*0cJ1Ng0ij0eN0pc1!/1N!0,:1mZ0z]0'50)R0;a0eU1T82rv2Rq2TL1kA1Kf2%&1Z,1Ke2iA2e[14a1rM35B1t?1=>1s&2g^23K[2pO23Q0(M2pY1J,1Wm1c*026L0e(0o[2k!0U}0VI0aW18J1=^2^*1r[0/]2dU1]C16736$0U#0k?2;L2la0+K0%^0qZ0Yj0S%0@41550WQ0gu0S*2!T0^N0@p11f1!r0/40yx0j;21l2NC1>>1n00>X2qT0s81F+0181T@0^X0hG0Y70dz0@C0yF1rS0S]0q{1@h1N;0q&2?w1I(1k)1At1Yt16%1;*24M1rE1(@1CN1Pn2Qa0z:2Yl0s@0qC1{e0@j1Cj0)91Ox0:<0>51D!0se1k[0l#0,Q2>r1lV0I@1[737v1ow1lJ1wv0}01=33Jw0j?0]U1hW1{j0]20nJ0sc0;=1022#v25+2z51s=1V11mQ1Xd1O#1DZ0}50$#1CQ2dg1Yv0]c1E{1G}1bU2z>1eR3ix1xB1H^2?e1{m1!71op1KH1D;1ep0'U1d10>M1Uz0x}0ig1{E0V%1Xl0dY0)31g*0zz2>J0T)0kz1j30b=19O29q0u=1hT0&y13K1]w0s}1sw0n40,U2Sv22O0yX1lo1pr14e0&V1V[17#1FG0IF3D<1#q0yp1L$0uV0YX1H{01Vi30t0[u15L1Da0]Y2tt1>g0bR2i;2Iz3h713>1tw1Zx2KP2hC1d>1;Y1!f1$31tC1iP1}}1/21?51;m0uC0!M1Vx13]0tg1VE0hA0}{0i00uM18y0Wa0Q/0[U17U1&s0i124i0%T1J91hu1620aI1Rt0Xz0k/0la0X/0{(1XT1E11XK0jk0WC0gp0yi16+0VN0@<1lA0'n0nR1h,0yc1H01TG1[y0pW0>g0{g1{61:X1(W1Le11!1MA2Fu1j$0}H1xh1jj0(t13P1/M1M51C/1JA25t15P0vG2e<0IK0Uc1/80U)2!'24U2Q71AM11S0bM2h631P0(B0e+1yO0;v19A2P<0c'0%A0}11AA0}f2KR1Ip1UT2tF1[Y0)t0wK34@0V?0*i0:&10e1X71*$1n42G}19,1Dy20R0^O0=h2Z61Fw0/514C2ac1p@0gf0!C0mR2KA16R0Ui0SM2C<0p{1Jc0JP0k70/}1Td2RY1Ly0@u1A>1Vj2Ep1j+0i518G2Ly0r<0r/0TB0x&0gh1m80v^0xE2QP2Qz17O0xW0my0#40<60rR0vV0$b0J!0fs0TH16v2w00u{0S<0ch0=r1?h1340mk1M%1@R15n1U*13i18R0Ni0wW0qc2lg0=k0/E0>61va1K%0!r0+p1(P0?=2tI1Zn0^51F22mu0/v1LH1ac0bg1!O0p$1yP1u[1Fh24Z0Rq0F=0LT1^L0c22Hw1T91EN0?10p:13A0u,0$}2dY1!^0eG2KX0y&1Cp0l$2Rv0UU0[V0vg0bx0yT0[L1+#1Fx13q11P1z{0JF1wb1Xo1v{3Ri1R%1Eb0wG2nA0Of0th0[(1Yn12U0OG0Cx15v1F'3J'1B[1Yw1WV0'y2AB1x#0*j2&h2YO1FJ3JG0v<0>30+:1X(1/91iQ2%x0d*0wl0$(0Nx1&o1IP0Ow1NS0?60;L1/Q1d81'O0>O0QZ0q71wB2zb0;H12[1e,0](0#a2Xq0xI0Zh0aM0b40Pm0PF0Z%2iU2f)1>+1SN2L/0=<2A/0o@1L41/W1,t27S2<(2S&2aD1:q2I/0v+0L214(0i60Zz2b?0?K0t]1+M1ia0jf0v&0/(1M+0R&0l[0QL1QH0ZA1Hc0?a0=/0*Z0pg0(F2vn2SC0{J2?I3Pv1pl2EX2vu0&>3Jt21{0Ar0S00TR1Ez0o]0av0T10S>0U11/D1nO1fG1Rc0{#0;o1GD0w*0K?0iU0sv0;N0,*0:)0]&0w!15&0Qm0P}1aj0rF0%S0Ij1Ek1Pl1?N21C0dU0jr0w=2B:1&q2q80Ie19l2lY1)V21e0=s0pF0&?1YG1VU0m%0Rm0QC1fU0f{0Z10KZ0qD1i:0^&0}P0Vj1'?0*s0Cy0M{0ak1:(0P50(T0;20+c0Ot1/f0{p2Iv1wr0aS0;X0#I0@#0{>0t%0e512t0?b1X02a@2mw2a(25k2yR2X{23w2Ej2d/0(^0R:0(k0H{1xt2;Y25x14W1kH0>n0zW0zg0k:0tP0w01n>17o0*t0XM0MM0db0L@0Q:0ZC0Rd0xS0L%0zS0^/0k<0xw0(c0(&0qx1z/10h0MS06I07F0h<0O90BL0CE19a0r(1dn2Xu0nM0rh1NQ17R1v(2G%2J+0?p0MU0Wh27#0i)0x>0[?0v00dG0Fs0XI2H30(x1sC2d>1+/2rQ0e$1h20]B1aB1p%0{%0;w1+W0:]1Q(1Cs3I10)!1GU1?d1!m21t1Qd1$b18'2nZ24d1A)2PH0ft1oY0%g1q,0,p0=$0mt0fF0u41O/0r&1%!0rk1VQ1o20ac0fk21[050T71?;0d<0nT11<0ZD0YP1uu0z519T1KJ0XB1WR1q%0ir0nv1Y!0bp1^%0E*0E+2rr0Ik0NI1F}0PB0Ft0'B15Z19L0iu0ux0S10K)0oO0Je0Sg0hS0N]0NC0Yt0uD0pM0NO1][0g,1t]18V2Nj0,X2L90HZ0[o1zC1N?0}$0^e0{M0}Y0H}0xC0gA0BM1vP20#2oX1O]0a}26@2NN0]i16g1Mz1w00zO0ug2g(2IK0zt1E$2$m0Yb1=O09=0>u17*0(40%c0a00kc0RC2^)0e60fy1L%1U425C1P<0t'0z31E323B0Ck09o0KL1PP0Qa2J?0l}1Se0<@0k10E)0j!0v?0'E1r60NZ2PO1QM0OI1r30U@0au0r40mz23r0&@0O40e,0pN1C31cG0b)2?=0nU0B}0jg0bL0kU0ls0^j0{'0y$1+827B0/M1U60&Y0nK1zY1ef1M;0z*0{X1F<0w20+O0:c1Ce0UL1o=1Bi1EY2qR0Qj0eu0@L0VO0[@2580$q0w'0(@0jQ0e[0m,0yI1I!2J10s30uW1u,0rY1<{0cv0^)0?@0WU1Jr3ZU2$D2wB1*B2P@11]0)V1)k1/v1MB1Cq3492l%2r#0q+0V}1vL0IB3EX0j#0=}0;?2i*1hL0wB1(*0Ne0E60Y10E!0P60z?0dQ2FF0@Q0sT1Uy1Y80Uf1O=0lx19j0tq1ZZ1kZ1bf2aL1Sv0}A2ab0sV0,A0>G1=;0+D0zX1C01RG0m)0$=13F1@q2Uh1T^1ax30b2o{25l10z0xt0zo0z91*>2>f0xx0hD14G1@r0T21R#1f42M#1FK0Wb0KM0bZ0zq2;]1681Bo0OA0Ut0c/0fZ0ZX0%(0&Q1/&1@B12]2t}15;01@d1SX10b2qO2}31yQ0?Q1J>1K90;<1DM0kZ0W41BY0po1GF12=1PU0?!1's19415h0:t1fi0!*1r21A71MN0zj25H0(l1![3oa1Of1e'1R00V<0(u0ki1h(1;;0Wu0rZ1501F/1VM0a60+i0qS0Lh0Ud0Zm0YT0wH0=%0h[1b60N<0+t1qG0Go0Hu0(#0zY0j20aX0ih0LW0Wv0e)0hn0P!0<#0D>0c[2F}1a}0fz11@1m=2O{0oq0hc0t70w<1:f0ou1h2UA1m+0+W2Se1/p1g(1Y^0Wq2212$i0zK21c19u0;x1z%1vC2fp2jW1Du0:;3KZ0Xa0i20e=1Xm0gg0js1kD1Cc0cw1S40l]1fx0^p1t$1ox1vt36G1g/2(u0gE1X&0d(0v*0Y,1Eh1gM0W50Yo0[,1W<0>K2LW0&b1070$V1Th0:*1M823?1V=1iI0X20/H0^;0@Y0oJ0m71/H0/h0$H0+80FX0RL12{1bc2TG0b%0J+1kP0;,1b&0jZ0kj0q$2dL0S(0RM1=72K@0C?0=A2g+0c>0qy0Oo0wE0xy1X]0}?1R;0rv21(0m00L(0%V0nZ1v42F:0iV2Z?2TB2Mx1>E00Lk0DP0MK0Hn0O{0*{0r60zl0(80%231s2Cv0(U0>d0)42Lf1uG1pq0j*1X{0O/1p'0nF1c>2=K1D,2852xV1d(1@n0$W1TX0yG0#b1=y0vR0tC1*r1Ao0Hv1AK0)P0Am1Sn0N^0W,16b0Nu0[+3cV0Pr0Ka0I60Rb0gU0z(2]30],0[50^C17v0q,0{u1KB0d/0NJ0a10L:2S:0Uu1Xe15*0^[26B11X1I51n;0Fm2x=0Qn0bS0HE0me0,)0;b1E:0m[0uX1c[1CH0<$0hi0o30q?0p60fL32S0XV1z*0w)20n0iz0$g0L31Oo1@o1zG15l0'd2Cx10;0}i2791rP0ba1%90/d1Rd0uN1$51rl00@N2WH1ye0N{0HI0De0O,0Wi1490mh18W0xh16C1Q%0/$13u0wm1og1bV0nV1[x2]k0/+2{42L+1;n1A{0Sz0yY0?z1]U0HN0ke0o81^e1vZ0Xx0KJ0w?0?l0iA0m]0$&0P)1fR0190v80f'0r920$13#0%v17Z25E1Or0u}1GH0^*2xr1n,0/C1F#0?v1UG1Ud0x51&;15F18,0oz17e2d=0}r2Mb0SN1Gz22%0sx1#U14^1^=13(1wc2Y910/1Ij10&0L/0lz1Xy2(S1X?2301FO15u0Zw14T2Dh2Ky0#l0?#3Dm1lR39g0k>2JM11H0c*0y{0&(19s0lf3I62Be0*m2Vs1(31xx0>y0Kr0to0mE0;E0jH1)@0t)0$x0*P0&i17a0h!1E(0'F0%=0*S0'G0^(3MF10H0Ug0U<0z00f20vH0im0r;1rN1gt33825Y1:&0%51$>1E01&I0eV0+P2a'0lV0Qx0ol0$]1(#15C0XE0/P1c^0NP26T1t30m>0yd1*u0=M0D10y*1Wp0om0ad1*[1iK1N70Y20IS0G!0G?2qY0k80b[0J{0f30El0f/0Vg1T61DY0Pw0n60f@1U@2640gQ0^+1C'0)h0RF0ma0vI1:o2t(0*32mQ0/Q28E0W/0Jj0hK18&0A^1a10Wr0XN1F>11Y1E90vm09t0b:0s#2#d0dZ3AJ2QO11C0fe18>20A1vc10f0lN0a[1}m0tT1bp0zv0x*0N?0^{0Qs0qd2Ea0S'0}'0JX0%f1@G0MT0,60!j2SK0e21AQ0cx0=I15}17+0Ex1Za1)+2RK10d10ix18f1O;00q*0D:36l0{m0Td0D}0j$0A&16c1^o0U&1Pq08c0uQ2f;0Jq0ks0tn0&n1=R0oD0n70$50v)0Sd01B11p17C0CN0A$0n?0X#0Ki0^r0]*0zC1vJ0qp0??0<&0;#1g61mm0[d0U'0:h0X70gi0i70ka0K{0!H1U>1BW1ID0WE0y=2ZZ1G'1Uq16$2A)1Q90T&0HF0rG3V+0M&0}}0v@0KR0j>0lg1cP0%B2NT1gJ1ls0ej0mx0%)0>=2VF1?#17h1HB0Z42IH2Ck0^60U*1^B2+,1KZ1Wd0vD0pY0vB0;t0,H2E?1?=0*u0wX0%C1uI0gV1AX1+J1eo2H22Re1zW0Wk0Nd2Z,1^W1X%1%u0lW0%O0b'1Gm1O01lK1DV0YJ1OS1oP2r]2v=0K}0Dr2B#0al0N90Y=0OW0x;0&)0Q40ju10+14X0hh0D+0fT0$>0l<0bC0sZ2BR0qF19{0}u0!'0:X0>Z0eT0u*0]%0Kp0i30[=1C[0f>1Oa0@q2T}2#M1y@24]0@$1+U0VE0UM0Ef1m20V81de0mH1zZ0IL1301:x1fh2F$0&A0@R0k{0ZQ0VJ0B'0MB0PD0D0&c1Zh0>;1mk0p>0@k1eN0cN1MW0!b0'71jY22<0LH2(?1%}1'h0hH0)i0e}0wO0WV0!R0S?0St0C;1E<1ea3h?0dL0Pb0m#0:$0Vk0E]0n>1YJ2Cn13B0mi1W#0+'0$h29'0{W0,Z0bi0sq1DP0*V2Mm0:G1R!0#t1LC1b%0Og0oh0}I2dP0d$0r10u60X!0fo1TR0k92I50>:0hV01C0,%0}621A1R}0R]0yN0OH0RI1J717!1br0N:0i<0(>0aN1$)1*N0q60S)0}j0*&1P80=^1I31^j1[X13c0=b0[p2cR2I*1hH0!w1;i0NU0FJ1T20E{0M00BX0KO0d%0Z[1?*1T71Sa0V^1gw0b80iW0w90y30ko0j(0jR0Xn2gU2d)1pa0vE1(50y:1HV3I71zn0T[0L81OO0{G1XI1{P0aT0d52$o0Vn1PH0;(0i{0)00qr0t@0^114A0]@1D91yA0K51fy0x,1Tn0Qg0J?18$0@l1LX2861BR08k0Fz0)m0fw0f#1<@1L{0(R2+$2ku0^@0W$0:J0fN1/@0wn2h*1Ew0R10oK0Rt0w@0{K1c71r]0]w0Wy0B*0X%0u:1Z&1AG1Vs0dv0zA2@z0zp30626)1p*26/2Gr1X40y41u$0,i05:0Y!2IN0#C3ES0s)0Ol0]j0h/0H)0X'0oE0o}0H+0X008#1ED1DG1x83L<0&]0sn0S[1fd0gR0gI0#R13)15+1jP1tn0mu1fL1E/1Q20Sh2221Wh0ic0zw1JJ0=P0}v0pD0>[07?0wx0oM0#u0)F1LD1Bt0tY0[w3bw0t+0a72u;1Q01';36H0p10dn0)A0NM0q10zF31=2F/0F$0*(0$J0{!0Ti18H0TW0v}0n010:1U{0hx20,0Sp0)r1LT1370Gu0{N0oe1rm1kI0zd1v=0c@09<1kz1n*0!U2F11nr1Df1WY1H&0vn2k:2Ap1W$1T+0,(09k0;W1cY0r'1@P0EK0(Q0Pi0CO0[61ns1Fk1G21z20hd0lh0gB1cO1Zu0=J0G50R'2K>1HF0Ny2J70lq1Aa1CP1;82QG1HN2Op0b}0hv1]#0{b1Dv0n@1fX0#>14)2fX0O51B>1Dz11N0%z0NQ2En0^S0mv0{V17w0hN1];1{:0T90t,1O?0{T0f,0J;0cK0M,0zr0%]0ym2U'0K*0jv0I71240kr0UQ2A,0Vr0ca0R{1Xu1CK0{c0Nm1$l0Ho2e)1aS0pK28t0YE0Ru1PA0^0ef1$}27k1OW1{>22X0#+0SX0h>0j61r}2Kl1A#1,L0yD1tt1Rp26<08i0eX19}2As1>$14+0=X13j1F^1h50:Y0U,0=B0O70Y}0^L0Km2Q[1RW2O00Ha1N30Op0Gk0')1J^01D2gb2Cm1%'0f]0Yc0zL1lO0uu1E?24q0q(10F0z40ZJ1?e0%F0zD1J110l0g'1DN2Bo2HV2RO0RA0R#0pT1+q0C^1>i0sX0'g1b=2jc0iP13!1OG0cT2J@0kl0Yy0Ag1u@0nX0p;0bl0'Y0!m1M#0'N2n^0:D22#11I0xc1N<1HK0Mw0L+0Tn0Zb0T'1sq0Vx1(917'1RT0u<1RU1&u0'b1*40%N1P(14&12:0O=07G0KF0Gz0SV0S+0g+0X30RQ0zP0kk1u#0s[1n!0mS1@*0,a0aU1JK09f0PG0An0?22JQ1O'1[j0sS0j)1N20!$2in1'B0p+1HZ0By0o/13%0W11(K0H[0X80ZE0E}0Q=0@B1h)0T%0DJ0Bo0GI0EB0V(0E:1X30NN0l*0jw0v1I<1j]0Po2cZ0T}0aF1xb0lu0b/1W[1QI20t0Mi0gv0{d0##1Jy0hw1qB0st0o*0V30ky0Tz0iE0c;0r70F'1?40HU0Nf0F,0HB0b50SA1m51/=0jc1Vv0a+0X(0*)0xT0q%0&E0cX0fG0m?1e}0iF0uR2Q91xk2A20'H0Sl2/A0UV0jl1N80E#0nd1+}0J:0c#07&0#$0Lg0mO1wS1A$0!20*H0m+2fR0lI0hB0c]0l90wP0:K16?0Gp0vx0EH0?/2HW1az1L@0]D0}K1C>2M!1Am0,b0<]0Z^1pI1lB0+A1kg0lJ1870/o2h21EE0cf1vK0h]1]D0uI16:0t80jU0Ll0Eo0}B0*}0y}0sY2Fl0M=0;31>]0z21aR0P<0@X10s0!P0uo0cY0P'0nG0:81V<0:635m0Qf0V'1h!0a%0rL0g]0nk1SE0dF1O<0,/1r70q:1NL08$0)b0ap0vy0e00PL1aT1Ec0VM0A90U50br0>>1#F0e%0}E1f$0pG0M62!M08R0eL2Ab0l?1p50xL1i918Y1gY1AS2it0t=0*:2m,0qU1QB0ik0Wz0yq1950)d1BO1ZT1yS0k0d)0O*1=90Um12y05Q0W)09d0IO2)]0^708p0CW2?!0]?0E20(Z0PR0c(0x$0{O0&u0R>0d[1ki0/i1mW1JC0R/1nP0+e0}T16Z11D1N'0c$0h(0f80gM1St1310aK0cQ0Yw1MI1EU0S@0b20v{0U>0}g1O50vY0'p11d0pX1rD0hq2C?0k@1^/0T50nw0G70ae1/N23c0PJ0?)0Em1Q=0t91Nn15[0^D0&T0?40a'0aY2hg1Cn0SY1dM0#10&e1fo0YF0Hw1>30hm0Zi1560VR0Qo0nq1co1Q>0=n0}%0T*0dR0Zc15o0#=1zL0)B0H?0I]0}C0ov1/t1vR07z0RR1!50Pg0Q@0$60Fv1Q11Tr0XW1b50(a0TJ0Z515]1@I0J=0J@1LY0mJ0As0CP0Ja0+@0Tc0Mk3450co0}Z3CM2o52dh2gZ1k}1!U3mk0B(0bs1Af0Kg0'K0JT0ys0,J1vf1sz0p70lF0+#0Iq0bU0G}0F%0GS0QJ0kI0DK0RN0GA0EN0J40HL0SZ0Iv0GO15^0Qz0h40fO0Oa0KG0Ae0AR0Tu01E09F0FA0AG0BI0Ec0Bd0JG0Bs0Q*0CR0{B0a^09&0t10KP0G80DZ0J#0HW0Xj0Bz0G@0sa0Mb0Fg0BT0VV0DL0CZ0GJ0Ca0Kx0TC0Tg09T0QX0S{0r0Su09>0P*0MC0zE0t60VA0qz2Cz0#c0g{0YU0of0X]0B0cU0J52SD0]X0I!0AO0B]0CX1dv0H40J}0I&0+j08j0RS0tI0W%0Ry0(b0EF0/'1ot0ie2u$0!D1D:0B!23K0[S0Wl1DS08'07u0EU2Ml21Y0Un006c1yZ0ob1x$0wN0=60IJ0Z'0U[08d0O}13k0o(0FM0Hy0770AC0yH0I30AE2gf0JY0,D0*00p[1s60EW0Gf0E81Ei1:@0Ii0,y0n11F50FY1k?1(x2am2Gy2T]0Tp0e&12B1H+1FH0dH1ev0f90F!0f+28>0T80Vb0$r0MN0I40}V0sz0P00Fw0A%0Zd0Nb0UF0MV0Pc0Ah0Ga0Fx0OB0p=0t#1hQ0H;1oz1yD1Fp0Fn21%1[z0UN0B<0Ph08A0Cs0H50+G2H)0/w1*g1kU1Q[0xq0FT0eB0S30Li0K^0?C0Q!1C80%D1Vf0^c0J60KH0V41&v0eH18E1X/0C71=e26f17b0m!0C:0DB0D40bV1m#0T<0Qt0Gb0TA0B>0Jl0yb0z{1a00n#0}<12C0dj1ua0N@0D$0M:0ZR0ME0PS1ND1d#1Rq0VF1WS1I^1mD0kV0QD1K@1B50vt0K@0m&00w>0%P1#O0cp1M20,=1FX0SQ1w80Db1)f12D1WJ1Tk0PT0V=1611fQ0Cd0U;1>&0Z+1)50YL17S13I0D20Ob1ma08z0d:0WM0&B1CW0s415<0Sv0d?1081qR0Ro0AV0Zq0EV0&j0p!06R0Xf0!c0K&0c90FN18A0L'0kp0J%0tp0Ia0D]0Bt2Lc0=+1D%0x(0XJ21#3K}2U41nY0;Y0CL0WR0:i1z+0:F0@610Q1j'0d>0[&06}0H,2nD0M20vW2Mt0M*0O<00h{0z+0#X0?L07O0d60bG0B?0A[0pj0ai1AY0Fl17?0um0Tw0Mq0@T22Y1*s0F>0i$1)l0Te06J0C80l41UU08Y0dC0BA0?&0WG0Cz0)S0z@0Ib0#1O$1p]16h2L]00Lq0?R1iG2Q!0Ct0&o0YZ1k<1^809+07<0N00rs0Sw0sC0Ce0fx0B%1'x0Z@08%0Ua08?08V0dg0f:0<;0bz0w31?I0u>0u20e@0pZ1Jm0g}0ws0EP0'<0sG1gd2cG1{'0QN1EF0O60GD0c60Da1y^0u%09*0^:09{0fg0H*0Ml1Oq04!08s04c0E00fH0fl0<02vy14U1U&1>:1E]0h00*b0o<1e#2SI1^K2DS1p{15{23,18%0{v0O)09s1061T%0Xg0A30w[0N}1A%0P10h10Qb0Xt0V[1eq0:u0F;0Q^1,E0nx0i,1D509h08e0:l0tA0#h0G/0Cm1tf0G60*K0Cn1UN0Pk0Qc0mK0?j0il0M[1BA08t0nO2T326+0=a0wL0Q80]J0k]1b[0cg0M41L}1wX1Gt0[;1Yd0Uq0NA0,}0P>0tB0vF0]/0j,0sf0]N2Vj0MO0iq1771=H0<{0oQ2LS0@Z0o>0v#0O?1fI0R60kK0qf0Y;0NS0M@18M05]0Hi10lK0Zf0^>0ph0i/0):0o+0wQ0+$1u:0Gg17H0CI0UB0Dn2N%0My0VX0QE0zh0R71XU1h[0j%2Lq1dV0V]0?e0qV1=I0aE0#!19%0oc0WH0Mf0q}0]I0MY0aw1iO0{32oB1:'0(=0x60KQ0[W0vo0Xc0Zx0SR0#g0Dz08G0wR0QK22U09K0RJ0aA0d71$40Tm0&^0(V0*+0J[1Nh06'0n20xX05R0Il1LL10?0H#0*Q10j0DQ1ka1KW0!h0RO0Ic09l0ja0u70FK0Pz0EC0v105N08Z0sD05o0C40sB0m*0D%1Ir05w0Gy0SB1SF1Cd0Jm0)e09D1c&1^u0jz1E=06X0&K0c=0Qq0Id0I>17J05l0Ou0+u0q<11{0p]0lb0JW0i80B30j@0Aq0GX0q/0iL0U+0800*n0VS2K:0j/0*A1En0O$17B1Q;0Hp27z0iQ1!C0mm09m0@a0}Q0=)2^40Dc0Ng1T=0HR0^f0)$1Qu10R0D(0Hd0D*0r?0P/0AU0Ws0xj0!@0%l0DR09Z0Uw0)c0C)0?*06+2J60ZN0Ww0E90Gh13T07>1gn0)w0dm1P!0Lm0C[09g06=05u0rx1YX0E$1q#0D70u^0Lr0Sa0qJ0dD0c30?D0En0KU0e*0EX0Bm0XC08B0H(09L0b*0$n0M70/>06o0Vu0bq0uh0XR0vp0920GF0F10ps0vO0mp0N*0SS1j&06Y2fk0Dk0aB19)0=v0TS0FL0M'0LL0+o2Zz0GN1C$1av08,0Ac0j10)W0GQ0AS0YK1iU1]l1x30d{0Ls0X$0/l06N0OT0Kn0K#06t06S0es0Hf0q=0tU0wI0=y0,70+(0M#0AD0hT0+M0M;0Mm0cA0r,06705!0VY0a&0Sx0K[0ST0Nj0ED0YG2VI1=A0m32h,0781(^0JL1jh07P0jj0!,0!I0sk2MH13305?0dw0A<0o=0lc0q^0E30TE1W^0CA06y1U20{q0Zn0L^03x0K,0q80(d0$K0Zk0RK0RV0H604'0@o0JH06O0BY0;}0N607I0Iw05G06Z1A;0q40ZF2YN0Y&0vd0*g1Zo03O1'S1ws0ey0m10WT0S=0UJ0G[0Ld0qO09;0Xu0h?0Gq10O0b!3Bp1s(0TL1W80t!05p0@b0UX08H0U70Y30Ly0B^0!=0ll1W>0+q0I$16i0GB0QQ0wt0b60ID0Cp1(Y21o0y(0Jd0Y?2Oe0Hj0c70C>0%{0kA2530Ew0Ix0ZL0DG0'u0D?0l;0iY0bt0/%0G*0='0CJ0#608S1QJ0k,1h}0O12Lk1vv0x70U81fN1ZL0Lt0GR0F*0d30]O1J#0Df2Z=2C%27?0R+0U$0,I1Xx0?'0oU0WP0T]19e1UV0@H0+20gZ0gC0I%0sr0iC1Di2DE0BJ0Gv0Du0C{0E<14]0k40])0Ci0[}0Q50QT0Dg0IH0Fd0Sr2GL1#R05e0Hz0Kk05212p0dy0!!0Qk2Eg0650Z]0Ir09P0Kt0Wn0*70AJ1ii0xk0e70Ve0HP1rG0hy1Vn0GC0Y806j0!?0#i0T30Jx0#Y0D50R%0s+0Tx1C,0JR0jS0N(1@l0Uo07U0OX0YW0p%0gJ0/j0CY0Sb0Fe0L!0TX0[y0A*1KM0+=08P1eT1KU0RW0Az0BZ1IH0{n0*10a*22t0O>0{$0at2Ls1({0w40I+0SI1!#0G10Jn0RX0JZ1*e0d^10S12!0610d;0G30LI1e00Dv0U32&[0;z1}Z0;P0Z*1NU0PV0OY0Xp0a50Q00oG1j50PY05'0uZ0a80gc0DX17D1*d2DM0HS0Rv0OP07Y0(O0CS0JI1;C0K71hV0YS1d;1VF0GG1Xz0$O06]0H70W{0zT0MW0cB0+y1MX0gK0Bp1V006g07@08@0JU0HK0A>0JV0Yk0VT0kL0n[0J80Lf1%g0621AH0+)0?$0Cu0bT0bN0aa05J08I0Nk0C,0E%17@2?<0Nc0W+2QH0u80g&0Nw0S&0+%0B411Z1NX1Ag1cQ1q60Lv0Y*0/,0Q90Mg0^H0,30(q1G{0Nh0c!0Vh0vq0Gl0)N1:,0c%1?w0p90lv1960XT0G<1qc07!1[e0wT0Ba0C&0ON0N101I1k{0hW13W0hj0F]0I:0g<0Q{2fq1&W0DC0!}0PW1Hq0a<1rQ0h'0Q,17f2HC0Yu0z/0eW0EJ1H90Z?0P@0'Z0G+0Zu14=0MP3Ea0da0>R0Ez0mX0jp0Oq0x<0A:1Hy0!70Iy0MQ0o)0fi0ve0=Y0Mn0+N07D0890Ed0k(0a#0rH0qE0hO13w0jE1wN0p^0y?0Hk0Kw0ZM0?S07V0!#0Pj0P+0Q$0bb1qX0Rr1Kr0gq0,K0T+0os0g(1D00T61oc0A,1#L0@U09(14B0!t0X50Gm0TT0LV0OJ0Q?0F?0r[0JS0<}0HG1lP0A(07Z0+[0nr0SJ08]0Jt0EZ0sM0wD0&k0Xd1B60,!0Tj0B/0Cq0w^1IF0oV1GS19y14o1!K0?q0)T0Gd0Qd1e^0Oh0>]1Ad17i0Mr15i10V0Ms0s91++2i80X+0XX2cU1Xn0QO0LS0OE1P'0XS1]^2vW0)s0Sn0ox0m;1J;0&'15,0vu0CF2*c0?r0hY0+l0g40jF0>e15b11U0f40!Q0{?19p0S$0KV0*C2K}0dq0Rc1SR06F1pM0T{0LC0#V1AJ0,413z0:L1k>0uv0TM2NG0XH1tp0d'03y1P?0T=0gX0*v1&/1}I1H<0P;0q;0Re0Zr0AX0Rg0=E0pU0OK1$C0Dp0LX0yZ1#W0ez0qv0Pq0nS0M514g1Q40'!0=f0'l1Q,0==1xO0r+1GV0Iz0i911g0W70ln0Bf0540MF1!n0?+12E0Ps1j{0ro1S90O@0eM16)0=L0Vf0/D0oR0lA0@O06z0f=0bv0uJ0$!0fD0&0V;0G]0Yd0r:1Ra1HQ1G&0(N0uY0zM1!*1C91TD0ea19v0SU0Y50/q0b^1Y/07*0Gt0]}1x60R;0IV0Jr0bE0k)14>0Om0Ur0dJ0h20K=0M<1eD07'0Sj0LD0k}0vr0m^0qP0Al09)0D<0A]1mV0+f1EV1BS0gs0[*0dS10Qi0F/0J20g*1F)0)u0*q2Bl0Jg015U0Pe0I^0B;0ep07W0ek0i%0K<0:m1SZ0D/0h}0KE1hZ0QH0Q]13=0za0R$0IQ1PE0GH0nP07r09^1l02c10b90/V1&g09[09@0)C0K$0*=1121FE0*k0tv1B'0PM0@D0ag22s0W80an0]^0]L0Ax0J<0eh0QU0G(0J^0p&0a90Js1FP0Q}0Xo0R}1Fi0Uy0,E2WW28z0cq0FO0cd0Qr0aP0u@0w;0Wo0ur0s&0L)0D)0LZ08f0&z0W^0RZ0gk0G>14k0Ta0B@1Fc0XK04j0AW0a;03s0L?06?2C^06h00aq0R(0bW13,0c)0s{2$*0CC0L{0M81H=0*21ld0It0{s0Au0La12g07J0/=0bH0iD0:V0bA0i@1w$0D320c05>04I1DT06$1I:0Eh0WI0qH0J]1>q1uL0S70WW0YO0!F2@X0wY09z0C/0#;0SC09W0Hl0C50FP0Ei0H=05#0ml0NE0Lz0Y:2]r0Iu1M=0ax0Ff0g=1SP0pk0Pl1c30+C0V00JM0Jy0O21+$0Ea0V&0%L0Mc0=!0BF0D80No0VG0A50A70R=0V50A!0li0o!2ao0j00(g0!;0ZV0hE1vd1O{0ei0qQ0R80B51]F0L&0E(0E^0Ks09v07E0AT1f20LJ0Z;0tb0Ku0Im0bX0pe1L80830F(0Cb0g^0f*0j^0O011u0j&0DY0WJ0V60P]13r0U60a,0V71V)0cC0fA0iZ0)K0LE0{70=>0K81U}0Qe0Yl0x90Nq0ZB1Ua0X*0fQ0'V0Xl1B?0Y60cG0iG0aQ0zR0W00DN0]30fp0Kl07=0Hq07d0Bg05q08y0hk0G;0,z0+k0zy08T0U^0a]1(v0A;0YM0Hr0bc0Ju04(0pv08<0N[0'v0S40iH1g#1A}0xZ0lo0y00960NF0Or1nR04007k0YQ0LF0gD1A90bI0PH0dE0/B0EQ14v0eD0<90Uz0?G0NG0*E0F51RL03z17%0Mj0IW0&G1)o0pO0=C0f}0*;0;M07#0T^0cD0Od0#^04404?07l05v06k04l07B07$07(06G09b0H$0@>0C}0In0Si0c40%W0DD0EA1#g0@90aH1A*0aO1P61HG07)16[08)0C<0aJ18?0Uv0Is0y@1Lf0Oi0UY0ct0cR0Eb0VB0Q10gw0Do0K00f(0L<0w,10P0d}0Tr09X1!l0iJ1Cg0{80b&0c50Z:0Tf1F,06<0jY0g50q[1Qi0tF1Ne1aX0HC0MH0O#0cy19I0Y902p0AH11b0Ri0oY1y80qt0W;0R)0T(0^u1G:0ZW0dV0g10j+0PI0Ge0I81J30K!0JJ0Zt0j<0l51X90Vz0bJ0zV0LQ0rz1}908l0fI0G$1Hv0[m0GY1aG0GT0h%0be1bG0g!2OT0hl0K;1ZB21f0#*0uF0vM1Dp0tK0+E0y#0XU0)Q0{D11#0(i0C*0Tb0ML0TN0ET09/0Ub0?M10I0ZY0+60!%0>H08!0nz0FU0Ln0g71DC0Bb04208W05a0Cg0dc0)70!Y0FV0@f0f00bf1{q0VH0fc0j]0$c0+F08[0T,0jJ1/A0Ej0L}0IX0*[0US14w0jC0Pn0Zs0Zv0m(01K0Fp0Md05B1sv08g09O04F09Q0{e0mq0kw0D[09U05S0NV0On1Yb0Y@0Io0cH0#m0x#0i}1740e>1g]1tX0S!1QC0bw1Lz0Rp0W20w#0xV0DE0Ts0C30F)0sE0Dl0l(0oy0[X0J'0P80Dh0Dw09i1)(0FW0F@0IY0h;0!K2Q+0BO0AZ1VC0H:21:0p)0UK0680E50B60xJ0Mu0VW0B:0o?04q0V:0D'1580ER0HX0FF0Av0mL2D$0Yh1kx0Rk02v0fj0o^0:I0>m0%'0iv0lj0/{0Oj0A?1B20Z{0rD0E&1LA0H802c0bB04%0BP2840kE02@0H'0S,1>x0ay0Ai07,03/05+0K909H0P{0&S0mf0A/0c:0/W0%!0W91bZ0k00BB0P#0t205W0DH0H&0cW0QA0Cj0e;1nz06U0{<0jN0%[0p*06p0FG1(w0S81Uw0W<0Sk0r@0$30?70y)0:,0F90'@0)y0!p0/)0[713M0%10?>13d0H%07[0A603c0Kc18n04V08m0CT1EG04905b0WO04^05i04S03T0L40!S07A06e08=0VC09:09]0Dx0H907{0w60F{01L07e0L508q0>70Bu09c0e]04a0D=0DA0DF07f18w05909q03J0k=0WD0D^0X?0fB0BQ07;0A@06w0OU0Jh0E40kM0WZ0P$03$0vJ0ci0C#0mT08n0X90B)0!10b#0c<03E17]0B70G'07s1090NW0dd0:v0N&1pQ17s1}d0AP05L09Y0Y/04607v0FQ0uP05s0XF03R0Kh0C109a0Dd0Ky1B714Y03j02;02d02V03F02A0340Vi0Jz0Kd1ZX07g08J0F60bY0I006i0Bj0900J00H^0X)0O;1k%02H0%Y06u0MI0E,1dp06D07a0CG0OL0eg0F+08D08+09j0V@0r%0n50cn1d'0R20l007006l04t1es0Fa0Ig04b0i404503+04k05g0Ih04y08E03Y0Z/0KW1Qh0g?05305K0*w0o40Ad06{0I90[$1VW0I109#0HH0i^0Cc0a{0kF04)05r05j0^00SD03%04J07]0uK0D!0v$1u/0D;06>0Di06@0QY0oZ0AA0vS0nY0ZH1fY0v,0'r0+00=l0bO0@(0Tk0n/0NH0T/0GE0J90Z(0Vo0R?0u00bd12R0d#0e90%t0h71'40FH0X{0Dm0CU05{0E/0C$0S;0d80Q(0xD0Pa0l:04+0Bv0Jv0XY0sI0PN0Fh03o04&0Xq0B10@I0UO06K07+0T$03a0TY0Sy0OC0850Uk0c00LO09'0Co0FR0B#0R50kN0Cv0rW13s0S90Rx07K0AK05X07L0H306(0CQ0Ee0G90+*0740600OF0JB04*05*07h07i1Ta0kT0pV0ua0u'0mb0w10yk0690HT1tH04z08U0BH0LK0L[0TF0w70p20Kz1C]06%06a06P0B=02W0A{0B$1cr0Y(09R03p0S:0U90D@03^0Lp0GP04@0P208X0DU0Nz0Rj0Q&0P%0Q21$m0DT0g>0N/02q0s608r0Ep04=0B80Cw0A#07:0970y'0P90Sc04m03U0M90Hg0re09,0d+08^0hf0M%0Kv04,04W04n0g;15V1D/0+{0IE0IM0P:0u(0az0/N0ss0]70C!09E0Le0fC0=[0H>1z50BC0dk02U0B[05502$14?0Bq05@0A+0Qv05Y03@0IN0Bn0+v09I05(04Q04r06V05C1Bz08:07506n0G=0RP0OV0Pf0d@0XA0W'0lX0Kq0E[0R*04X0I)06q0+!0m/0jh04R05E04u0M^0F30H!0mB0G:0nD04T03M0E10D,02J0U=0Fq0Bh07103504[0og0jV0Ye1NR0X>0,<03I05O04A0CV0SK0WA0Z30HD06m0N%04M1Zg02,08/03807m04}0B20BD08*2Dd0{y0qq06B1BJ0Bw1KN0Bk0lC0P(0L00R90RT0X[0K10Wc07n0760mP0Hs0Ji0CD0$P0Ip06f03d0qT03k0=i08o0310EG03=02j0R30KX03D02*0][05,0:e0L>0A=0QB08h0Px08406^0P30T!1B%0l'0am0$70oA0Vv01}02k0C(0E=03&0Zo05$0OQ0yU0m40a?0l%0uz2hx01#06T08F09109V07T07M08;09x0A004L03q03V03n03B04U03N03b03:02%03C02<02>02n04i02602Y03602!05602=03A05%05z03l05P0J)0#%09307R0Oz0OD0R@0iw0Yv0Vl0W&04f0a(0O%0iN0&Z1it0V#0x30O[0220C202]02S0lQ01t01>01?02M02D02P05x01$01+0Nn0Ul04O04d05707w05M04P0XO06)0fv0cL1h#04:06&05c01M05}0I/0Jo0L10K40N30NX0Rn0ts0E?08K0FS07t07%04B0390D00Ek0CM0eb06!0G)06b0CH0CK1^304E02u05h0G40JK03*05/04109M02805<03t03!03<03v04]0AF0Aa0oH0fE0dN0Up0Ym0Xv0Oe0Vt1tR0gl0SW0Eq05)0KI03r0IZ0wS0hZ0V*05k0Br0Af03h0Lw08u0630]906#02a0D#09%0Fr0AB0Os0ZO0'O0ZU0X;0rb0R!0QV0aC0wd0T00x)0Q)0R<0Np0oB0n]0YD0c104Y0kG0AL0GL0GM0Fb0J*03;0cj0N=08a02(09e0Q<0BR0DI0Bl07j04D0BU06W0K%0wF0kC0?[0B908v0JD0KY1?]0P40a:0Gr1<90=706;0LM0BS09J08C0eJ05T0Y<0L60UZ10k0^v0p#0(A0DV0EM0370n31LN0GU0K(03(0860Me03206A04g05D0Mt01x06C02w08w0C+0eP04K02^03Q0Fk0Hm0N+0R[1yl05^0OZ0LA0JE0We0T40Pv0TO0sb1If0jd0If06*0Dy07}0730Wj08b0hP0Et04#03)0BK0b(08Q0tL0lr0kO0Ra04v0M]03w0d&07X09n0Cr0Py0Ao05n05F0Gi0PA04x03f0nh0i&0bP0ed0(G0jq0f)0rf0wZ0K:0W60A103'06/0Ov07S0K/06[03,02s02l0BV0C=0240E>08704C0HJ0AM02)0xH06r0640m50Ns0L;0HV0SP0f%08O0Y#0Q>0Wx0Mz0dK0O]0i+0Ch0MD0C608>03?01r02301/07y09S01&0Ht05H04h0km0X60i>02:05;09407b0RD02505y03>03S02z03H01*02/0O80Lo0Z904o0330Er0Rf0gx0LP0J&0Ql0LN0di0n'05I0I?0JA0}M0S^0O30LG05102I0Aj09504p03i0AN05U03[0U(0EE0FI0ha02B05803]0HA0Fu03W0Dj0K60RB0Bx02{07^05Z04$04/06602f07x04{07902Q05t04w03K05[0Yi0470G209C02h0G,0ao0iK0!k0l60cu0fJ0n$0OM0/<0MJ0P^0MR02o04;02}03g02'05&02?01=01q02T04306E02i06H07N03{02E04N01:02t0BW02e0C%0A805A0A'0HY0I20O:0Hh0PK0Ma0Wp0N40L,01[01(01@08802102m0KA0Ab0A)07p04802O03m05d06L01p02x01z0AY07209A04e0U40500DW02C02b02F05m06:03#07C06Q01N06v09}0N20G%0KB0K>0J>0eQ0W!03P02g03L02702K02X01j02r02Z02903e01^0N501;0Gn03Z06x01]0HQ01{01'06s04H0Tl02R0I;0Jp0L*0Ke0Kf0TQ03G01l02&05=02N0E;01,02+03}05V02#04G02y01%01<02[03X01w04Z04s01!02L01s0Mh0F40F#0F}0LR0G{0F[0Mv01f01v01o02G01k01m01y01Q01P01n01Y01h01O01d01W01e01a01X01b02001T01R01i01U01g01)01V01S01u01Z01c
\ No newline at end of file
diff --git a/Plain Craft Launcher 2/Application.xaml.vb b/Plain Craft Launcher 2/Application.xaml.vb
index db89387..2b5e788 100644
--- a/Plain Craft Launcher 2/Application.xaml.vb
+++ b/Plain Craft Launcher 2/Application.xaml.vb
@@ -9,7 +9,10 @@ Public Class Application
'核心初始化
MeloongCore.Main.Init("PCL")
MeloongCore.Wpf.Main.Init()
- Logger.Instance = New PclLogger With {.logFolder = Paths.BaseThenName, .MinLevel = If(ModeDebug, LogLevel.Trace, LogLevel.Info)}
+ If Not (e.Args.Contains("--update") OrElse e.Args.Contains("--gpu") OrElse e.Args.Contains("--memory")) Then '若是通过命令行调用,则不检查单例、不轮换日志(#9137)
+ WaitingMutex(e)
+ Logger.Instance = New PclLogger With {.logFolder = Paths.BaseThenName, .MinLevel = If(ModeDebug, LogLevel.Trace, LogLevel.Info)}
+ End If
'提升主线程优先级
Thread.CurrentThread.Priority = ThreadPriority.Highest
'执行开发版测试
@@ -47,7 +50,7 @@ Public Class Application
Catch ex As Exception
Environment.Exit(ProcessReturnValues.Fail)
End Try
- ElseIf e.Args(0).StartsWithF("--memory") Then
+ ElseIf e.Args(0) = "--memory" Then
'内存优化
Dim Ram = My.Computer.Info.AvailablePhysicalMemory
Try
@@ -70,7 +73,7 @@ Public Class Application
CheckPermissionWithException(Paths.Base & "PCL\")
Catch ex As Exception
MsgBox($"PCL 没有对当前文件夹的权限({Paths.Base}PCL\),请尝试:" & vbCrLf &
- "1. 将 PCL 移动到其他文件夹" & If(Paths.Base.StartsWithF("C:", True), ",例如 C 盘和桌面以外的其他位置。", "。") & vbCrLf &
+ "1. 将 PCL 移动到其他文件夹" & If(PathUtils.GetDiskName(Paths.Base) = "C"c, ",例如 C 盘和桌面以外的其他位置。", "。") & vbCrLf &
"2. 删除当前目录中的 PCL 文件夹,然后再试。" & vbCrLf &
"3. 右键 PCL 选择属性,打开 兼容性 中的 以管理员身份运行此程序。",
MsgBoxStyle.Critical, "运行环境错误")
@@ -81,7 +84,7 @@ RetryCacheCheck:
DirectoryUtils.Create(PathTemp)
CheckPermissionWithException(PathTemp)
Catch ex As Exception
- If PathTemp = Path.GetTempPath() & "PCL\" Then
+ If PathUtils.IsSame(PathTemp, Path.GetTempPath() & "PCL\") Then
MyMsgBox("PCL 无法访问缓存文件夹,可能导致程序出错或无法正常使用!" & vbCrLf & vbCrLf & "错误原因:" & ex.GetDisplay(True), "缓存文件夹不可用")
Else
MyMsgBox("手动设置的缓存文件夹不可用,PCL 将使用默认缓存文件夹。" & vbCrLf & vbCrLf & "错误原因:" & ex.GetDisplay(True), "缓存文件夹不可用")
@@ -92,8 +95,6 @@ RetryCacheCheck:
End Try
DirectoryUtils.Create(PathTemp & "Cache\")
DirectoryUtils.Create(Paths.AppDataThenName)
- '要求单例
- WaitingMutex(e)
'设置 ToolTipService 默认值
ToolTipService.InitialShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(100))
'设置网络配置默认值
@@ -231,7 +232,7 @@ RetryCacheCheck:
End Function
End Sub
Private Shared Sub ExtractLibwebp() '这个方法会调用 ModBase,进而调用 MeloongCore,所以不能放在 New 里
- SetDllDirectory(PathPure.Value.TrimEnd("\"c))
+ SetDllDirectory(PathUtils.RemoveSlashSuffix(PathPure.Value))
Try
ExtractResources(PathPure.Value & "libwebp.dll", "libwebp64")
Catch ex As Exception
diff --git a/Plain Craft Launcher 2/Controls/Behaviors/ClipboardInterceptor.vb b/Plain Craft Launcher 2/Controls/Behaviors/ClipboardInterceptor.vb
index 6e594c8..ea83e13 100644
--- a/Plain Craft Launcher 2/Controls/Behaviors/ClipboardInterceptor.vb
+++ b/Plain Craft Launcher 2/Controls/Behaviors/ClipboardInterceptor.vb
@@ -44,8 +44,8 @@ Namespace Controls.Behaviors
Private Shared Sub AddCommandBindingsToTextBox(tb As TextBox)
tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyTextBox))
- tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutTextBox))
- tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteTextBox))
+ tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Cut, AddressOf OnCutTextBox, AddressOf CanEditTextBox))
+ tb.CommandBindings.Add(New CommandBinding(ApplicationCommands.Paste, AddressOf OnPasteTextBox, AddressOf CanEditTextBox))
End Sub
Private Shared Sub AddCommandBindingsToRichTextBox(rtb As RichTextBox)
@@ -58,42 +58,61 @@ Namespace Controls.Behaviors
dg.CommandBindings.Add(New CommandBinding(ApplicationCommands.Copy, AddressOf OnCopyDataGrid))
End Sub
+ Private Shared Sub SetClipboardText(text As String)
+ Forms.Clipboard.SetDataObject(text, False, retryTimes:=10, retryDelay:=100) '实际的复制
+ Try
+ System.Windows.Clipboard.Flush() '将数据持久化到系统剪贴板,避免应用程序退出后数据丢失
+ Catch ex As Exception '持久化失败不抛出异常
+ Logger.Warn(ex, $"剪贴板持久化失败(错误码:0x{ex.HResult:X8})")
+ End Try
+ End Sub
+
Private Shared Sub OnCopyTextBox(sender As Object, e As ExecutedRoutedEventArgs)
Dim tb = TryCast(sender, TextBox)
If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(tb.SelectedText, True)
+ SetClipboardText(tb.SelectedText)
Catch ex As Exception
- Logger.Warn(ex, "复制失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"复制失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
End Try
e.Handled = True
End Sub
+ Private Shared Sub CanEditTextBox(sender As Object, e As CanExecuteRoutedEventArgs)
+ Dim tb = TryCast(sender, TextBox)
+ e.CanExecute = tb IsNot Nothing AndAlso Not tb.IsReadOnly AndAlso
+ (e.Command IsNot ApplicationCommands.Cut OrElse tb.SelectionLength > 0)
+ e.Handled = True
+ End Sub
+
Private Shared Sub OnCutTextBox(sender As Object, e As ExecutedRoutedEventArgs)
Dim tb = TryCast(sender, TextBox)
- If tb Is Nothing OrElse tb.SelectionLength <= 0 Then Return
+ e.Handled = True
+ If tb Is Nothing OrElse tb.IsReadOnly OrElse tb.SelectionLength <= 0 Then Return
Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(tb.SelectedText, True)
+ SetClipboardText(tb.SelectedText)
Catch ex As Exception
- Logger.Warn(ex, "剪切失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"剪切失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
+ Return
End Try
tb.SelectedText = String.Empty
- e.Handled = True
End Sub
Private Shared Sub OnPasteTextBox(sender As Object, e As ExecutedRoutedEventArgs)
Dim tb = TryCast(sender, TextBox)
- If tb Is Nothing Then Return
+ e.Handled = True
+ If tb Is Nothing OrElse tb.IsReadOnly Then Return
Try
- If Forms.Clipboard.ContainsText() Then
- Dim pasteText = Forms.Clipboard.GetText()
+ Dim pasteText = Retrier.Attempt(func:=
+ Function(Attempt) As String
+ Return If(Forms.Clipboard.ContainsText(), Forms.Clipboard.GetText(), Nothing)
+ End Function, maxAttempts:=10, delay:=Function() TimeSpan.FromMilliseconds(100))
+ If pasteText IsNot Nothing Then
'将换行符替换为空格(#7825)
If Not tb.AcceptsReturn Then pasteText = pasteText.ReplaceLineEndings(" ", mergeMultiple:=True)
@@ -105,10 +124,8 @@ Namespace Controls.Behaviors
tb.SelectionLength = 0
End If
Catch ex As Exception
- Logger.Warn(ex, "粘贴失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"粘贴失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
End Try
-
- e.Handled = True
End Sub
Private Shared Sub OnCopyRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
@@ -119,10 +136,9 @@ Namespace Controls.Behaviors
If String.IsNullOrEmpty(textRange.Text) Then Return
Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(textRange.Text, True)
+ SetClipboardText(textRange.Text)
Catch ex As Exception
- Logger.Warn(ex, "复制失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"复制失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
End Try
e.Handled = True
@@ -134,16 +150,16 @@ Namespace Controls.Behaviors
Dim selection = New TextRange(rtb.Selection.Start, rtb.Selection.End)
If String.IsNullOrEmpty(selection.Text) Then Return
+ e.Handled = True
Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(selection.Text, True)
+ SetClipboardText(selection.Text)
Catch ex As Exception
- Logger.Warn(ex, "剪切失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"剪切失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
+ Return
End Try
selection.Text = String.Empty
- e.Handled = True
End Sub
Private Shared Sub OnPasteRichTextBox(sender As Object, e As ExecutedRoutedEventArgs)
@@ -151,9 +167,11 @@ Namespace Controls.Behaviors
If rtb Is Nothing Then Return
Try
- If Not Forms.Clipboard.ContainsText() Then Return
-
- Dim pasteText = Forms.Clipboard.GetText()
+ Dim pasteText = Retrier.Attempt(func:=
+ Function(Attempt) As String
+ Return If(Forms.Clipboard.ContainsText(), Forms.Clipboard.GetText(), Nothing)
+ End Function, maxAttempts:=2, delay:=Function() TimeSpan.FromMilliseconds(200))
+ If pasteText Is Nothing Then Return
Dim selection = rtb.Selection
selection.Text = pasteText
@@ -162,7 +180,7 @@ Namespace Controls.Behaviors
rtb.CaretPosition = caretPos
rtb.Selection.Select(caretPos, caretPos)
Catch ex As Exception
- Logger.Warn(ex, "粘贴失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"粘贴失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
End Try
e.Handled = True
@@ -187,10 +205,9 @@ Namespace Controls.Behaviors
Dim sbStr = sb.ToString().TrimEnd(ControlChars.Cr, ControlChars.Lf)
Try
- Forms.Clipboard.Clear()
- Forms.Clipboard.SetDataObject(sbStr, True)
+ SetClipboardText(sbStr)
Catch ex As Exception
- Logger.Warn(ex, "复制失败,请稍后再试", LogBehavior.Toast)
+ Logger.Warn(ex, $"复制失败,请稍后再试(错误码:0x{ex.HResult:X8})", LogBehavior.Toast)
End Try
e.Handled = True
diff --git a/Plain Craft Launcher 2/Controls/MyCard.vb b/Plain Craft Launcher 2/Controls/MyCard.vb
index 08ced68..11d0a90 100644
--- a/Plain Craft Launcher 2/Controls/MyCard.vb
+++ b/Plain Craft Launcher 2/Controls/MyCard.vb
@@ -102,73 +102,36 @@ Public Class MyCard
RunInUi(Sub() UseAnimation = RawUseAnimation, True)
End If
End Sub
- Public Sub StackInstall()
- StackInstall(SwapControl, SwapType, Title)
- TriggerForceResize()
+
+ '填充
+ Private ContentBuilder As Action(Of Panel)
+ Public Sub SetContentBuilder(Builder As Action(Of Panel))
+ ContentBuilder = Builder
End Sub
- Public Shared Sub StackInstall(ByRef Stack As StackPanel, Type As Integer, Optional CardTitle As String = "")
- '这一部分的代码是好几年前留下的究极屎坑,当时还不知道该咋正确调用这种方法,就写了这么一坨屎
- '但是现在……反正勉强能用……懒得改了就这样吧.jpg
- '别骂了别骂了.jpg
- If Stack.Tag Is Nothing Then Return
- '排序
- Dim HasDuplicates As Boolean = False
- Select Case Type
- Case 3
- Stack.Tag = CType(Stack.Tag, List(Of DlOptiFineListEntry)).SortByComparison(Function(a, b) CompareVersionGE(a.DisplayName, b.DisplayName))
- Case 4, 10
- Stack.Tag = CType(Stack.Tag, List(Of DlLiteLoaderListEntry)).SortByComparison(Function(a, b) CompareVersionGE(a.Inherit, b.Inherit))
- Case 6
- Stack.Tag = CType(Stack.Tag, List(Of DlForgeVersionEntry)).OrderByDescending(Function(a) a).ToList
- Case 8, 9
- Stack.Tag = CType(Stack.Tag, List(Of ResourceVersion)).SortByComparison(Function(a, b) a.ReleaseDate > b.ReleaseDate)
- HasDuplicates =
- CType(Stack.Tag, List(Of ResourceVersion)).DistinctBy(Function(a) a.Display).Count <>
- CType(Stack.Tag, List(Of ResourceVersion)).Count
- End Select
- '控件转换
- Select Case Type
- Case 6
- ForgeDownloadListItemPreload(Stack, Stack.Tag, AddressOf ForgeSave_Click, True)
- Case 8
- PageDownloadResourceDetail.ResourceFilesCardPreload(Stack, Stack.Tag)
- End Select
- '实现控件虚拟化
- For Each Data As Object In Stack.Tag
- Select Case Type
- Case 0
- Stack.Children.Add(CType(Data, McInstance).ToListItem(AddressOf PageSelectRight.McInstanceListContent))
- Case 2
- Stack.Children.Add(McDownloadListItem(Data, AddressOf McDownloadMenuSave, True))
- Case 3
- Stack.Children.Add(OptiFineDownloadListItem(Data, AddressOf OptiFineSave_Click, True))
- Case 6
- Stack.Children.Add(ForgeDownloadListItem(Data, AddressOf ForgeSave_Click, True))
- Case 7
- '不能使用 AddressOf,这导致了 #535,原因完全不明,疑似是编译器 Bug
- Stack.Children.Add(McDownloadListItem(Data, Sub(sender, e) FrmDownloadInstall.MinecraftSelected(sender, e), False))
- Case 8
- '若存在重复的版本名,则显示文件名而非版本名(#1344)
- Stack.Children.Add(CType(Data, ResourceVersion).ToListItem(
- AddressOf FrmDownloadResourceDetail.Save_Click, IsBadDisplay:=HasDuplicates))
- Case 9
- '若存在重复的版本名,则显示文件名而非版本名(#1344)
- Stack.Children.Add(CType(Data, ResourceVersion).ToListItem(
- AddressOf FrmDownloadResourceDetail.Install_Click, AddressOf FrmDownloadResourceDetail.Save_Click, IsBadDisplay:=HasDuplicates))
- Case 10
- Stack.Children.Add(LiteLoaderDownloadListItem(Data, AddressOf LiteLoaderSave_Click, True))
- Case 11
- Stack.Children.Add(CType(Data, HelpEntry).ToListItem)
- Case 12
- Stack.Children.Add(FabricDownloadListItem(CType(Data, JObject), AddressOf FrmDownloadInstall.Fabric_Selected))
- Case 13
- Stack.Children.Add(NeoForgeDownloadListItem(Data, AddressOf NeoForgeSave_Click, True))
- Case Else
- Logger.Error($"未知的虚拟化种类:{Type}")
- End Select
- Next
- Stack.Children.Add(New FrameworkElement With {.Height = 18}) '下边距,同时适应折叠
- Stack.Tag = Nothing
+ Public Sub SetContentBuilder(Of T)(Items As IEnumerable(Of T), ItemBuilder As Func(Of T, UIElement))
+ SetContentBuilder(
+ Sub(Stack)
+ For Each Item In Items
+ Stack.Children.Add(ItemBuilder(Item))
+ Next
+ Stack.Children.Add(New FrameworkElement With {.Height = 18})
+ End Sub)
+ End Sub
+ '''
+ ''' 使用 ContentBuilder 生成卡片内容。
+ '''
+ Public Sub BuildContent()
+ If ContentBuilder Is Nothing Then Return
+ Dim Stack = TryCast(SwapControl, Panel)
+ If Stack Is Nothing Then Return
+ Try
+ ContentBuilder(Stack)
+ ContentBuilder = Nothing
+ Catch
+ Stack.Children.Clear()
+ Throw
+ End Try
+ TriggerForceResize()
End Sub
'动画
@@ -278,10 +241,6 @@ Public Class MyCard
Public SwapControl As FrameworkElement
Public Property CanSwap As Boolean = False
'''
- ''' 被折叠的种类,用于控件虚拟化。
- '''
- Public Property SwapType As Integer
- '''
''' 是否已被折叠。
'''
Public Property IsSwapped As Boolean
@@ -293,7 +252,7 @@ Public Class MyCard
_IsSwapped = value
If SwapControl Is Nothing Then Return
'展开
- If Not IsSwapped AndAlso TypeOf SwapControl Is StackPanel Then StackInstall(SwapControl, SwapType, Title)
+ If Not IsSwapped Then BuildContent()
'若尚未加载,会在 Loaded 事件中触发无动画的折叠,不需要在这里进行
If Not IsLoaded Then Return
'更新样式
@@ -397,4 +356,4 @@ Partial Public Module ModAnimation
If CallBack IsNot Nothing Then CallBack(Control)
End If
End Sub
-End Module
\ No newline at end of file
+End Module
diff --git a/Plain Craft Launcher 2/Controls/MyImage.vb b/Plain Craft Launcher 2/Controls/MyImage.vb
index a7784ef..b385ea7 100644
--- a/Plain Craft Launcher 2/Controls/MyImage.vb
+++ b/Plain Craft Launcher 2/Controls/MyImage.vb
@@ -90,7 +90,7 @@ Public Class MyImage
Catch ex As Exception
Logger.Warn(ex, $"加载图片失败({value})")
Try
- If value.StartsWithF(PathTemp) Then FileUtils.Delete(value)
+ If value.StartsWithF(PathTemp, True) Then FileUtils.Delete(value)
Catch
End Try
End Try
diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb
index 49e51e8..902abdb 100644
--- a/Plain Craft Launcher 2/FormMain.xaml.vb
+++ b/Plain Craft Launcher 2/FormMain.xaml.vb
@@ -11,6 +11,13 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
If BuildType = BuildTypes.Release Then
+ If LastVersion < 411 Then 'Release 2.14.0.0
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "新增:允许修改、添加、移除、更新已安装版本的 MC 版本以及各个组件,可从版本设置中进入"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:启动游戏时允许按 Esc 取消"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:允许复制主页的启动日志中的内容"))
+ FeatureCount += 19
+ BugCount += 26
+ End If
If LastVersion < 408 Then 'Release 2.13.1.1
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:版本设置中,添加打开截图文件夹的快捷方式"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:导出整合包时,可以勾选导出光影设置文件"))
@@ -93,6 +100,13 @@ Public Class FormMain
'3:BUG+ IMP* FEAT-
'2:BUG* IMP-
'1:BUG-
+ If LastVersion < 412 Then 'Snapshot 2.14.0.0
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "新增:允许修改、添加、移除、更新已安装版本的 MC 版本以及各个组件,可从版本设置中进入"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:启动游戏时允许按 Esc 取消"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:允许复制主页的启动日志中的内容"))
+ FeatureCount += 19
+ BugCount += 26
+ End If
If LastVersion < 410 Then 'Snapshot 2.13.1.1
If LastVersion = 409 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:更新 Mod 时可能更新成另一个 Mod 加载器的版本"))
FeatureCount += 2
@@ -786,7 +800,7 @@ Public Class FormMain
If PanMsg.Children.Any Then
If e.Key = Key.Enter Then
CType(PanMsg.Children(0), Object).Btn1_Click()
- ElseIf e.Key = Key.Escape OrElse (e.Key = Key.W AndAlso Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) Then
+ ElseIf e.Key = Key.Escape Then
Dim Msg As Object = PanMsg.Children(0)
If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
Msg.Btn3_Click()
@@ -803,13 +817,13 @@ Public Class FormMain
' 在没有弹窗时:继续检查……
'==========================
- '按 ESC:启动中则取消启动,否则返回上一级
+ '按 ESC 取消启动,或返回上一级
If e.Key = Key.Escape Then
- If McLaunchLoader.State = LoadState.Loading Then
- McLaunchCancel()
- Else
- TriggerPageBack()
+ If PageCurrent = FormMain.PageType.Launch AndAlso McLaunchLoader.State = LoadState.Loading Then
+ FrmLaunchLeft.BtnCancel_Click()
+ Return
End If
+ TriggerPageBack()
End If
'更改隐藏版本可见性
If e.Key = Key.F11 AndAlso PageCurrent = FormMain.PageType.InstanceSelect Then
@@ -834,11 +848,6 @@ Public Class FormMain
If TypeOf PageRight Is IRefreshable Then CType(PageRight, IRefreshable).Refresh()
Return
End If
- 'Ctrl + w 关闭程序
- If e.Key = Key.W AndAlso Keyboard.Modifiers.HasFlag(ModifierKeys.Control) Then
- EndProgram(True)
- Return
- End If
'调用启动游戏
If e.Key = Key.Enter AndAlso PageCurrent = FormMain.PageType.Launch Then
If IsAprilEnabled AndAlso Not IsAprilGiveup Then
@@ -1026,14 +1035,14 @@ Public Class FormMain
If FilePathList.Count > 1 Then
'必须要求全部为 jar 文件
For Each File In PathList
- If Not {"jar", "litemod", "disabled", "old"}.Contains(File.AfterLast(".").Lower) Then
+ If Not {"jar", "litemod", "disabled", "old"}.Contains(PathUtils.GetExtension(File)) Then
Hint("一次请只拖入一个文件!", HintType.Red)
Return
End If
Next
End If
'主页
- Dim Extension As String = FilePath.AfterLast(".").Lower
+ Dim Extension As String = PathUtils.GetExtension(FilePath)
If Extension = "xaml" Then
Logger.Info("文件后缀为 XAML,作为主页加载")
If FileUtils.Exists(Paths.Base & "PCL\Custom.xaml") Then
@@ -1054,9 +1063,9 @@ Public Class FormMain
If PageInstanceMod.InstallMods(PathList) Then Return
'安装整合包
If {"zip", "rar", "mrpack"}.Any(Function(t) t = Extension) Then '部分压缩包是 zip 格式但后缀为 rar,总之试一试
- Logger.Info("文件为压缩包,尝试作为整合包安装")
- Hint("检测到压缩包拖入,正在准备安装……")
+ Hint("正在读取压缩包……")
Try
+ Logger.Info("文件为压缩包,尝试作为整合包安装")
ModpackInstall(FilePath)
RunInUi(Sub() FrmMain.PageChange(FormMain.PageType.TaskManager))
Return
@@ -1067,7 +1076,7 @@ Public Class FormMain
End If
'RAR 处理
If Extension = "rar" Then
- Hint("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试!")
+ Hint("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试!", HintType.Red)
Return
End If
'错误报告分析
@@ -1083,7 +1092,7 @@ Public Class FormMain
Logger.Error(ex, "自主错误报告分析失败")
End Try
'未知操作
- Hint("PCL 无法确定应当执行的文件拖拽操作……")
+ Hint("PCL 无法确定适合的操作……", HintType.Red)
End Sub, "文件拖拽")
End Sub
@@ -1225,9 +1234,10 @@ Public Class FormMain
OtherTest = 2
InstanceOverall = 0
InstanceSetup = 1
- InstanceMod = 2
- InstanceModDisabled = 3
- InstanceExport = 4
+ InstanceModify = 2
+ InstanceMod = 3
+ InstanceModDisabled = 4
+ InstanceExport = 5
End Enum
'''
''' 获取次级页面的名称。若并非次级页面则返回空字符串,故可以以此判断是否为次级页面。
@@ -1392,6 +1402,10 @@ Public Class FormMain
'''
Private Sub PageChangeActual(Stack As PageStackData, Optional SubType As PageSubType = -1)
If PageCurrent = Stack AndAlso (PageCurrentSub = SubType OrElse SubType = -1) Then Return
+ If Stack.Page = PageType.InstanceSetup AndAlso PageInstanceLeft.Instance IsNot Nothing AndAlso McInstanceLock.IsLocked(PageInstanceLeft.Instance) Then
+ Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
+ Return
+ End If
AniControlEnabled += 1
Try
diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
index c591cc6..6a89d7f 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
@@ -6,12 +6,12 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
- Public Const VersionBaseName As String = "2.13.1.1" '显示用版本名
+ Public Const VersionBaseName As String = "2.14.0.0" '显示用版本名
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
#If RELEASE Then
- Public Const VersionCode As Integer = 408 '正式版
+ Public Const VersionCode As Integer = 411 '正式版
#Else
- Public Const VersionCode As Integer = 410 '快照版
+ Public Const VersionCode As Integer = 412 '快照版
#End If
'版本信息
@@ -47,7 +47,7 @@ Public Module ModBase
'''
''' 程序的缓存文件夹路径,以 \ 结尾。
'''
- Public PathTemp As String = If(Settings.Get(Of String)("SystemSystemCache") = "", Path.GetTempPath() & "PCL\", Settings.Get(Of String)("SystemSystemCache")).ToString.Replace("/", "\").TrimEnd("\") & "\"
+ Public PathTemp As String = PathUtils.AddSlashSuffix(If(Settings.Get(Of String)("SystemSystemCache") = "", Path.GetTempPath() & "PCL\", Settings.Get(Of String)("SystemSystemCache")).Replace("/", "\"))
'''
''' 当前程序的语言。
'''
@@ -75,7 +75,7 @@ Public Module ModBase
'''
''' 系统盘盘符,以 \ 结尾。例如 “C:\”。
'''
- Public OsDrive As String = Environment.GetLogicalDrives().Where(Function(p) Directory.Exists(p)).First.Upper.First & ":\" '#3799
+ Public OsDrive As String = Environment.GetLogicalDrives().First(Function(p) Directory.Exists(p)) '#3799
Public ReadOnly Property ModeDebug As Boolean
Get
@@ -576,7 +576,7 @@ Public Module ModBase
Try
If String.IsNullOrEmpty(Folder) Then Return False
Folder = PathUtils.AddSlashSuffix(Folder)
- If Folder.EndsWithF(":\System Volume Information\") OrElse Folder.EndsWithF(":\$RECYCLE.BIN\") Then Return False
+ If Folder.EndsWithF(":\System Volume Information\", True) OrElse Folder.EndsWithF(":\$RECYCLE.BIN\", True) Then Return False
If Not DirectoryUtils.Exists(Folder) Then Return False
Dim TestFilePath As String = $"{Folder}CheckPermission{GetUuid()}.txt"
FileUtils.Write(TestFilePath, "临时文件,用于检测该文件夹的权限是否正常。")
@@ -593,7 +593,7 @@ Public Module ModBase
Public Sub CheckPermissionWithException(Folder As String)
If String.IsNullOrWhiteSpace(Folder) Then Throw New ArgumentNullException("文件夹名不能为空!")
Folder = PathUtils.AddSlashSuffix(Folder)
- If Folder.EndsWithF(":\System Volume Information\") OrElse Folder.EndsWithF(":\$RECYCLE.BIN\") Then Throw New UnauthorizedAccessException("没有对系统文件夹的权限!")
+ If Folder.EndsWithF(":\System Volume Information\", True) OrElse Folder.EndsWithF(":\$RECYCLE.BIN\", True) Then Throw New UnauthorizedAccessException("没有对系统文件夹的权限!")
If Not DirectoryUtils.Exists(Folder) Then Throw New DirectoryNotFoundException("文件夹不存在!")
Dim TestFilePath As String = $"{Folder}CheckPermission{GetUuid()}.txt"
FileUtils.Write(TestFilePath, "临时文件,用于检测该文件夹的权限是否正常。")
@@ -788,7 +788,7 @@ Public Module ModBase
'''
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
'''
- Public PathPure As Lazy(Of String) = New Lazy(Of String)(
+ Public PathPure As New Lazy(Of String)(
Function()
If Paths.Base.IsAsciiOnly() Then
Return Paths.Base & "PCL\"
@@ -845,6 +845,12 @@ Public Module ModBase
Return (Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000
End Function
'''
+ ''' 获取十进制 Unix 时间戳。
+ '''
+ Public Function ToUnixTimestampUtc(Time As Date) As Long
+ Return (Time.ToUniversalTime().Ticks - 621355968000000000) / 10000000
+ End Function
+ '''
''' 时间戳转化为日期。
'''
Public Function GetDate(timeStamp As Integer) As Date
@@ -1021,20 +1027,22 @@ Public Module ModBase
'''
''' 设置剪贴板。将在另一线程运行,且不会抛出异常。
'''
- Public Sub ClipboardSet(Text As String, Optional ShowSuccessHint As Boolean = True, Optional SuccessHint As String = "")
+ Public Sub ClipboardSet(Text As String, Optional ShowSuccessHint As Boolean = True)
RunInThread(
Sub()
- RunInUi(
- Sub()
- Try
- My.Computer.Clipboard.Clear()
- If Not String.IsNullOrEmpty(Text) Then My.Computer.Clipboard.SetText(Text)
- If ShowSuccessHint Then Hint(If(String.IsNullOrEmpty(SuccessHint), "已成功复制!", SuccessHint), HintType.Green)
- Catch ex As Exception
- Logger.Error(ex, behavior:=LogBehavior.None)
- Hint("复制失败,可能由于剪贴板被其他程序占用!", HintType.Red)
- End Try
- End Sub)
+ Try
+ Retrier.Attempt(delay:=Function(Attempt) TimeSpan.FromMilliseconds(200), maxAttempts:=4, isRetryAllowed:=Function(ex) True, action:=
+ Sub()
+ RunInUiWait(
+ Sub()
+ My.Computer.Clipboard.Clear()
+ If Not String.IsNullOrEmpty(Text) Then My.Computer.Clipboard.SetText(Text)
+ End Sub)
+ End Sub)
+ If ShowSuccessHint Then Hint("已成功复制!", HintType.Green)
+ Catch ex As Exception
+ Logger.Error(ex, "可能由于剪贴板被其他程序占用,文本复制失败", LogBehavior.Toast)
+ End Try
End Sub)
End Sub
'''
diff --git a/Plain Craft Launcher 2/Modules/Base/ModNet.vb b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
index 34c994e..36b39ce 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModNet.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
@@ -1396,7 +1396,7 @@ FinishExCatch:
Public Overrides Sub Start(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = False)
If Input IsNot Nothing Then Files = New ConcurrentQueue(Of NetFile)(CType(Input, IEnumerable(Of NetFile)))
'去重
- Files = New ConcurrentQueue(Of NetFile)(Files.DistinctBy(Function(a) a.LocalPath))
+ Files = New ConcurrentQueue(Of NetFile)(Files.DistinctBy(Function(a) PathUtils.ForCompare(a.LocalPath).Lower()))
'设置剩余文件数
SyncLock FileRemainLock
FileRemain += Files.Where(Function(f) f.State <> NetState.Finished).Count
@@ -1421,7 +1421,7 @@ FinishExCatch:
Next
If Not File.HasAvailableSource() Then Throw New ArgumentException("输入的下载链接不正确!")
File.LocalPath = File.LocalPath.Replace("/", "\")
- If Not File.LocalPath.Lower.Contains(":\") Then Throw New ArgumentException("输入的本地文件地址不正确:" & File.LocalPath)
+ If Not File.LocalPath.Contains(":\") Then Throw New ArgumentException("输入的本地文件地址不正确:" & File.LocalPath)
If File.LocalPath.EndsWithF("\") Then Throw New ArgumentException("请输入含文件名的完整文件路径:" & File.LocalPath)
DirectoryUtils.Create(PathUtils.RemoveLastPart(File.LocalPath)) '创建目标文件夹
Next
@@ -1519,7 +1519,7 @@ FinishExCatch:
Select(Function(FolderName) (FolderName, File.LocalPath.IndexOfF(FolderName, True))).
Where(Function(kv) kv.Item2 >= 0).ToList
If Not TypeIndexes.Any Then
- If File.LocalName.EndsWithF(".jar") Then
+ If PathUtils.GetExtension(File.LocalName) = "jar" Then
TypeIndexes.Add(("\versions\", 1)) '总是对 jar 进行版本文件检查,以包括另存为 jar 的情况
Else
Return Nothing
@@ -1547,7 +1547,7 @@ FinishExCatch:
Case "versions\"
'版本 jar 或 json:查找 MC 文件夹下的各个版本文件夹
For Each VersionFolder In VersionFolders
- For Each Candidate In DirectoryUtils.EnumerateFiles(VersionFolder, searchPattern:="*." & PathUtils.GetLastPart(File.LocalPath).AfterLast(".").Lower)
+ For Each Candidate In DirectoryUtils.EnumerateFiles(VersionFolder, searchPattern:="*." & PathUtils.GetExtension(File.LocalPath))
If CheckCandidate(Candidate, File.Check) Then Return Candidate
Next
Next
diff --git a/Plain Craft Launcher 2/Modules/Base/ModValidate.vb b/Plain Craft Launcher 2/Modules/Base/ModValidate.vb
index d24cc90..7122390 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModValidate.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModValidate.vb
@@ -382,7 +382,7 @@ Public Class ValidateFolderPath
Public Overrides Function Validate(Str As String) As String
'去除尾部斜线,统一为 \
Str = Str.Replace("/", "\")
- If Not Str.TrimEnd("\").EndsWithF(":") Then Str = Str.TrimEnd("\")
+ If Not PathUtils.RemoveSlashSuffix(Str).EndsWithF(":") Then Str = PathUtils.RemoveSlashSuffix(Str)
'检查是否为空
Dim LengthCheck As String = New ValidateNullOrWhiteSpace().Validate(Str)
If LengthCheck <> "" Then Return LengthCheck
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
index 4b30a0b..ba029b1 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
@@ -92,7 +92,7 @@ Public Class CrashAnalyzer
'尝试视作压缩包解压
Try
Dim Info = FileUtils.GetInfo(FilePath)
- If Info.Exists AndAlso Info.Length > 0 AndAlso Not FilePath.EndsWithF(".jar", True) Then
+ If Info.Exists AndAlso Info.Length > 0 AndAlso Not PathUtils.GetExtension(FilePath) = "jar" Then
FileUtils.ExtractToDirectory(FilePath, TempFolder & "Temp\")
Logger.Info($"已解压导入的日志文件:{FilePath}")
GoTo Extracted
@@ -163,9 +163,9 @@ Extracted:
Else
TargetType = AnalyzeFileType.ExtraLogFile
End If
- ElseIf MatchName.EndsWithF(".log", True) Then
+ ElseIf PathUtils.GetExtension(MatchName) = "log" Then
TargetType = AnalyzeFileType.ExtraLogFile
- ElseIf MatchName.EndsWithF(".txt", True) Then
+ ElseIf PathUtils.GetExtension(MatchName) = "txt" Then
TargetType = AnalyzeFileType.ExtraReportFile
Else
Logger.Info($"{MatchName} 分类为 Ignore")
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
index 67490af..ce90887 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
@@ -242,8 +242,6 @@ Public Module ModDownload
DlPreferMojang = DeltaTime < 4000
Logger.Info($"Mojang 官方源加载耗时:{DeltaTime}ms,{If(DlPreferMojang, "可优先使用官方源", "不优先使用官方源")}")
End If
- '添加 PCL 特供项
- If FileUtils.Exists(PathTemp & "Cache\download.json") Then Versions.Merge(FileUtils.ReadAsJson(PathTemp & "Cache\download.json"))
'返回
Loader.Output = New DlClientListResult With {.IsOfficial = True, .SourceName = "Mojang 官方源", .Value = Json}
'MC 更新提示
@@ -438,7 +436,7 @@ Public Module ModDownload
.FileName = If(Name(i).ContainsIgnoreCase("pre"), "preview_", "") & "OptiFine_" & Name(i).Replace(" ", "_") & ".jar",
.RequiredForgeVersion = Forge(i).Replace("Forge ", "").Replace("#", "")}
If Entry.RequiredForgeVersion.Contains("N/A") Then Entry.RequiredForgeVersion = Nothing
- Entry.InstanceName = Entry.Inherit & "-OptiFine_" & Name(i).ToString.Replace(" ", "_").Replace(Entry.Inherit & "_", "")
+ Entry.InstanceName = Entry.Inherit & "-OptiFine_" & Name(i).AfterFirst(" ").Replace(" ", "_")
Versions.Add(Entry)
Next
Loader.Output = New DlOptiFineListResult With {.IsOfficial = True, .SourceName = "OptiFine 官方源", .Value = Versions}
@@ -581,7 +579,7 @@ Public Module ModDownload
If Version <> other.Version Then
Return Version.CompareTo(other.Version)
Else
- Return CompareVersion(VersionName, other.VersionName)
+ Return McUtils.CompareVersion(VersionName, other.VersionName)
End If
End Function
End Class
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
index 7ce900d..20ef01b 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
@@ -18,7 +18,7 @@ Public Module ModJava
'强制选择的 Java
Dim SelectedJavaSetting = Settings.Get(Of String)("LaunchArgumentJavaSelect")
Dim SelectedJava = If(SelectedJavaSetting.StartsWithF("{"), SelectedJavaSetting.DeserializeJson(Of JObject)()("Path").ToString, "")
- Dim Match = OldJavaList.FirstOrDefault(Function(j) j.Folder.Equals(SelectedJava, StringComparison.OrdinalIgnoreCase))
+ Dim Match = OldJavaList.FirstOrDefault(Function(j) PathUtils.IsSame(j.Folder, SelectedJava))
If Match IsNot Nothing Then
OldJavaList.Remove(Match)
OldJavaList.Insert(0, Match)
@@ -78,7 +78,7 @@ Public Module ModJava
Return
End If
'不再移除它
- Configs.JavaRemovedList.Edit(Sub(ByRef List) List.RemoveIf(Function(f) f.Equals(NewJava.Folder, StringComparison.OrdinalIgnoreCase)))
+ Configs.JavaRemovedList.Edit(Sub(ByRef List) List.RemoveIf(Function(f) PathUtils.IsSame(f, NewJava.Folder)))
'加入列表顶部
Configs.JavaList.Edit(
Sub(ByRef List)
@@ -150,16 +150,16 @@ Public Module ModJava
End Sub
'原版 26-:通过版本号判断
- If (Not Instance.Version.Vaild AndAlso Instance.ReleaseTime >= New Date(2024, 4, 2)) OrElse
- (Instance.Version.Vaild AndAlso Instance.Version.Vanilla >= New Version(20, 0, 5)) Then
+ If (Not Instance.Version.Valid AndAlso Instance.ReleaseTime >= New Date(2024, 4, 2)) OrElse
+ (Instance.Version.Valid AndAlso Instance.Version.Vanilla >= New Version(20, 0, 5)) Then
'1.20.5+(24w14a+):至少 Java 21
AddConstraint(ValueRange(Of Version).AtLeast(New Version(21, 0)))
- ElseIf (Not Instance.Version.Vaild AndAlso Instance.ReleaseTime >= New Date(2021, 11, 16)) OrElse
- (Instance.Version.Vaild AndAlso Instance.Version.Vanilla.Major >= 18) Then
+ ElseIf (Not Instance.Version.Valid AndAlso Instance.ReleaseTime >= New Date(2021, 11, 16)) OrElse
+ (Instance.Version.Valid AndAlso Instance.Version.Vanilla.Major >= 18) Then
'1.18 pre2+:至少 Java 17
AddConstraint(ValueRange(Of Version).AtLeast(New Version(17, 0)))
- ElseIf (Not Instance.Version.Vaild AndAlso Instance.ReleaseTime >= New Date(2021, 5, 11)) OrElse
- (Instance.Version.Vaild AndAlso Instance.Version.Vanilla.Major >= 17) Then
+ ElseIf (Not Instance.Version.Valid AndAlso Instance.ReleaseTime >= New Date(2021, 5, 11)) OrElse
+ (Instance.Version.Valid AndAlso Instance.Version.Vanilla.Major >= 17) Then
'1.17+ (21w19a+):至少 Java 16
AddConstraint(ValueRange(Of Version).AtLeast(New Version(16, 0)))
ElseIf Instance.ReleaseTime.Year >= 2017 Then 'Minecraft 1.12 与 1.11 的分界线正好是 2017 年,太棒了
@@ -185,7 +185,7 @@ Public Module ModJava
End If
'OptiFine 检测
- If Instance.Version.HasOptiFine AndAlso Instance.Version.Vaild Then '不管非标准版本
+ If Instance.Version.HasOptiFine AndAlso Instance.Version.Valid Then '不管非标准版本
If Instance.Version.Vanilla.Major < 7 Then
'<1.7:至多 Java 8
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
@@ -199,11 +199,11 @@ Public Module ModJava
End If
'Forge 检测(部分测试结果见 #8432)
- If Instance.Version.HasForge Then
+ If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then
If Instance.Version.Vanilla >= New Version(6, 0, 1) AndAlso Instance.Version.Vanilla <= New Version(7, 0, 2) Then
'1.6.1 - 1.7.2:必须 Java 7
AddConstraint(ValueRange(Of Version).ClosedOpen(New Version(7, 0), New Version(8, 0)))
- ElseIf Instance.Version.Vanilla.Major <= 12 OrElse Not Instance.Version.Vaild Then '非标准版本
+ ElseIf Instance.Version.Vanilla.Major <= 12 OrElse Not Instance.Version.Valid Then '非标准版本
'<=1.12:Java 8
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
ElseIf Instance.Version.Vanilla.Major <= 14 Then
@@ -212,38 +212,38 @@ Public Module ModJava
ElseIf Instance.Version.Vanilla.Major = 15 Then
'1.15:Java 8 - 15
AddConstraint(ValueRange(Of Version).ClosedOpen(New Version(8, 0), New Version(16, 0)))
- ElseIf CompareVersionGE(Instance.Version.Forge, "34.0.0") AndAlso CompareVersionGE("36.2.25", Instance.Version.Forge) Then
+ ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "34.0.0") AndAlso McUtils.CompareVersionGE("36.2.25", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
'1.16.3~5,Forge 34.0.0 ~ 36.2.25:最高 Java 8u320
AddConstraint(ValueRange(Of Version).AtMost(New Version(8, 0, 320)))
- ElseIf CompareVersionGE(Instance.Version.Forge, "36.2.26") AndAlso CompareVersionGE("36.999999.999999", Instance.Version.Forge) Then
+ ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "36.2.26") AndAlso McUtils.CompareVersionGE("36.999999.999999", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
'1.16.5,Forge 36.2.26+,<37.0.0:最高 Java 23
AddConstraint(ValueRange(Of Version).LessThan(New Version(24, 0)))
- ElseIf CompareVersionGE(Instance.Version.Forge, "37.0.0") AndAlso CompareVersionGE("37.0.79", Instance.Version.Forge) Then
+ ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "37.0.0") AndAlso McUtils.CompareVersionGE("37.0.79", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
'1.17.1,Forge 37.0.0 ~ 37.0.79:最高 Java 16
AddConstraint(ValueRange(Of Version).LessThan(New Version(17, 0)))
ElseIf Instance.Version.Vanilla.Major = 18 AndAlso Instance.Version.HasOptiFine Then '#305
'1.18:若安装了 OptiFine,最高 Java 18
AddConstraint(ValueRange(Of Version).LessThan(New Version(19, 0)))
- ElseIf CompareVersionGE(Instance.Version.Forge, "45.0.21") AndAlso CompareVersionGE("45.0.65", Instance.Version.Forge) Then
+ ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "45.0.21") AndAlso McUtils.CompareVersionGE("45.0.65", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
'1.19.4,Forge 45.0.21 ~ 45.0.65:最高 Java 19
AddConstraint(ValueRange(Of Version).LessThan(New Version(20, 0)))
- ElseIf CompareVersionGE(Instance.Version.Forge, "45.0.66") AndAlso CompareVersionGE("47.4.8", Instance.Version.Forge) Then
+ ElseIf McUtils.CompareVersionGE(Instance.Version.ModLoaderVersions(ModLoaders.Forge), "45.0.66") AndAlso McUtils.CompareVersionGE("47.4.8", Instance.Version.ModLoaderVersions(ModLoaders.Forge)) Then
'1.19.4~1.20.1,Forge 45.0.66 ~ 47.4.8:最高 Java 21
AddConstraint(ValueRange(Of Version).LessThan(New Version(22, 0)))
End If
End If
'NeoForge 检测
- If Instance.Version.HasNeoForge Then
+ If Instance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then
If Instance.Version.Vanilla = New Version(20, 0, 1) OrElse
- (CompareVersionGE("20.2.62-beta", Instance.Version.NeoForge) AndAlso Not Instance.Version.NeoForge.Contains("25w14craftmine")) Then
+ (McUtils.CompareVersionGE("20.2.62-beta", Instance.Version.ModLoaderVersions(ModLoaders.NeoForge)) AndAlso Not Instance.Version.ModLoaderVersions(ModLoaders.NeoForge).Contains("25w14craftmine")) Then
'1.20.1,以及 1.20.2 的 20.2.62-beta 之前:最高 Java 21
AddConstraint(ValueRange(Of Version).LessThan(New Version(22, 0)))
End If
End If
'Fabric 检测
- If Instance.Version.HasFabric AndAlso Instance.Version.Vaild Then '不管非标准版本
+ If Instance.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) AndAlso Instance.Version.Valid Then '不管非标准版本
If Instance.Version.Vanilla.Major >= 15 AndAlso Instance.Version.Vanilla.Major <= 16 Then
'1.15 - 1.16:Java 8+
AddConstraint(ValueRange(Of Version).AtLeast(New Version(8, 0)))
@@ -251,15 +251,14 @@ Public Module ModJava
'1.18+:Java 17+
AddConstraint(ValueRange(Of Version).AtLeast(New Version(17, 0)))
End If
- If Instance.Version.Fabric <> "未知版本" AndAlso
- CompareVersion(Instance.Version.Fabric, "0.17.0") < 0 Then
+ If Instance.Version.ModLoaderVersions(ModLoaders.Fabric) <> "未知版本" AndAlso McUtils.CompareVersion(Instance.Version.ModLoaderVersions(ModLoaders.Fabric), "0.17.0") < 0 Then
'Fabric Loader 0.16.x 及更早版本的 Mixin/ASM 不兼容 Java 25
AddConstraint(ValueRange(Of Version).LessThan(New Version(25, 0)))
End If
End If
'LiteLoader 检测
- If Instance.Version.HasLiteLoader AndAlso Instance.Version.Vaild Then '不管非标准版本
+ If Instance.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) AndAlso Instance.Version.Valid Then '不管非标准版本
'最高 Java 8
AddConstraint(ValueRange(Of Version).LessThan(New Version(9, 0)))
End If
@@ -411,9 +410,9 @@ Public Module ModJava
Dim Components = DownloadListWorker.LastResult
'确定要下载的目标 Java
- Dim JavaToDownload As JavaDownloadInfo = If(
- Components.FirstOrDefault(Function(Comp) Comp.Java("version")("name").ToString = RecommendedComponent), '优先选择指定的 Component
- Components.FirstOrDefault(Function(Comp) Range.Contains(Comp.JavaVersion)))
+ Dim JavaToDownload As JavaDownloadInfo = Components.FirstOrDefault(
+ Function(Comp) Comp.Java("version")("name").ToString = RecommendedComponent, '优先选择指定的 Component
+ Function(Comp) Range.Contains(Comp.JavaVersion))
If JavaToDownload Is Nothing Then
Logger.Warn($"Mojang 提供的 Java 列表中没有合适的 Java,无法自动下载")
'提示需要手动下载 Java
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
index 71bedf7..504cd96 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
@@ -48,7 +48,7 @@ Public Module ModLaunch
End Try
'检查版本
CurrentLaunchOptions.Instance.Load()
- If CurrentLaunchOptions.Instance.State = McInstanceState.Error Then
+ If CurrentLaunchOptions.Instance.State = McInstance.McInstanceState.Error Then
Hint($"无法启动 {CurrentLaunchOptions.Instance.Name}:{CurrentLaunchOptions.Instance.Info}", HintType.Red)
Return False
End If
@@ -57,6 +57,10 @@ Public Module ModLaunch
FrmLaunchLeft.RefreshButtonsUI()
FrmLaunchLeft.RefreshPage(False, False)
End If
+ If McInstanceSelected IsNot Nothing AndAlso McInstanceLock.IsLocked(McInstanceSelected) Then
+ Hint($"版本 {McInstanceSelected.Name} 正在被修改,请稍后再启动!", HintType.Red)
+ Return False
+ End If
FrmMain.AprilGiveup()
'禁止进入版本选择页面(否则就可以在启动中切换 McInstanceSelected 了)
FrmMain.PageStack = FrmMain.PageStack.Where(Function(p) p.Page <> FormMain.PageType.InstanceSelect).ToList
@@ -70,7 +74,12 @@ Public Module ModLaunch
'''
Public Sub McLaunchLog(Text As String, Optional Level As LogLevel = LogLevel.Info)
Text = FilterUserName(FilterAccessToken(Text, "*"), "*")
- If ModeDebug Then RunInUi(Sub() FrmLaunchRight.LabLog.Text += $"{vbCrLf}[{Date.Now:HH':'mm':'ss'.'fff}] {Text}")
+ If ModeDebug Then
+ RunInUi(
+ Sub()
+ FrmLaunchRight.LabLog.AppendText($"[{Date.Now:HH':'mm':'ss'.'fff}] {Text}{vbCrLf}")
+ End Sub)
+ End If
Logger.Log(Text, Level)
End Sub
@@ -196,25 +205,6 @@ NextInner:
End Try
End Sub
- '''
- ''' 取消正在进行的游戏启动。
- '''
- Public Sub McLaunchCancel()
- If McLaunchLoaderReal IsNot Nothing Then
- McLaunchLoaderReal.Cancel()
- McLaunchLog("已取消启动")
- Try
- If McLaunchWatcher IsNot Nothing Then
- McLaunchWatcher.Kill()
- ElseIf McLaunchProcess IsNot Nothing Then
- If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
- End If
- Catch ex As Exception
- Logger.Error(ex, "取消启动结束进程失败", LogBehavior.Toast)
- End Try
- End If
- End Sub
-
#End Region
#Region "内存优化"
@@ -249,7 +239,7 @@ NextInner:
'检查版本
If McInstanceSelected Is Nothing Then Throw New Exception("未选择 Minecraft 版本!")
McInstanceSelected.Load()
- If McInstanceSelected.State = McInstanceState.Error Then Throw New Exception("Minecraft 存在问题:" & McInstanceSelected.Info)
+ If McInstanceSelected.State = McInstance.McInstanceState.Error Then Throw New Exception("Minecraft 存在问题:" & McInstanceSelected.Info)
'检查输入信息
Dim CheckResult As String = ""
RunInUiWait(Sub() CheckResult = McLoginAble(McLoginInput()))
@@ -557,7 +547,7 @@ NextInner:
'检查是否已经登录完成
Dim ExpiresAt = Settings.Get(Of Long)("CacheMsV2Expires")
If Not Data.IsForceRestarting AndAlso '不要求强行重启
- ExpiresAt > 0 AndAlso ExpiresAt > GetUnixTimestampUtc() AndAlso 'AccessToken 尚未过期
+ ExpiresAt > 0 AndAlso ExpiresAt > ToUnixTimestampUtc(Date.UtcNow) AndAlso 'AccessToken 尚未过期
Input.UserName = Settings.Get(Of String)("CacheMsV2Name") Then
Data.Output = New McLoginResult With {
.Name = Input.UserName, .Type = "Microsoft",
@@ -1052,7 +1042,7 @@ Retry:
Dim ResultJson As JObject = Result.DeserializeJson()
Return (
ResultJson("access_token").ToString,
- ResultJson("expires_in").ToObject(Of Integer) + GetUnixTimestampUtc() - 1200) '提前 20 分钟视作过期
+ ResultJson("expires_in").ToObject(Of Integer) + GetUnixTimestampUtc() - 3600) '提前 1 小时视作过期
End Function
'微软登录步骤 5:验证微软账号是否持有 MC,这也会刷新 XGP
Private Sub MsLoginStep5(AccessToken As String)
@@ -1382,16 +1372,11 @@ NextInstance:
'Log4j 漏洞防御参数
Args.Add("-Dlog4j2.formatMsgNoLookups=true")
- '编码(#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
+ '编码(#4700、#5892、#5909、#6934、#8950、#9241)
+ Dim UseCompatEncoding = McLaunchJavaSelected.Version.Major >= 18
+ Dim EncodingName = If(UseCompatEncoding,
+ McLaunchJavaSelected.NativeEncodingName, 'Java 18+ 会添加 COMPAT,因此 Java 会回退到 native.encoding
+ McLaunchJavaSelected.FileEncodingName) 'Java 17- 直接使用 file.encoding
Try
McLaunchEncoding = Encoding.GetEncoding(If(EncodingName.Equals("GBK", StringComparison.OrdinalIgnoreCase), "GB18030", EncodingName))
Catch ex As Exception
@@ -1405,7 +1390,7 @@ NextInstance:
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
+ If UseCompatEncoding AndAlso Not Args.Any(Function(a) a.StartsWithF("-Dfile.encoding=")) Then Args.Add("-Dfile.encoding=COMPAT") '防止老版本 MC 与部分 Mod 不兼容 UTF-8
'为 JLW 添加 -jar,它必须放在最后
If UseJLW Then
@@ -1465,7 +1450,8 @@ NextInstance:
Arg &= " " & CustomArg
'把 OptiFineForgeTweaker 放在参数的末尾
- If (McInstanceSelected.Version.HasForge OrElse McInstanceSelected.Version.HasLiteLoader) AndAlso McInstanceSelected.Version.HasOptiFine Then
+ If (McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Forge) OrElse McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader)) AndAlso
+ McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.OptiFineAsMod Then
If Arg.Contains("--tweakClass optifine.OptiFineForgeTweaker") Then
McLaunchLog("发现正确的 OptiFineForge TweakClass,目前的游戏参数:" & Arg)
Arg = Arg.Replace(" --tweakClass optifine.OptiFineForgeTweaker", "") & " --tweakClass optifine.OptiFineForgeTweaker"
@@ -1520,10 +1506,10 @@ NextInstance:
Private Iterator Function McLaunchArgumentsReplace(Arguments As List(Of String)) As IEnumerable(Of (Key As String, Value As String))
'基础参数
Yield ("${classpath_separator}", ";")
- Yield ("${natives_directory}", GetNativesFolder().TrimEnd("\"c))
+ Yield ("${natives_directory}", PathUtils.RemoveSlashSuffix(GetNativesFolder()))
Yield ("${library_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
Yield ("${libraries_directory}", PathUtils.ToShortPath(McFolderSelected & "libraries"))
- Yield ("${pure_directory}", PathPure.Value.TrimEnd("\"c)) '由 PCL 添加,这会允许在分割参数并去重后再替换路径,防止路径中的特殊字符影响参数分割和去重
+ Yield ("${pure_directory}", PathUtils.RemoveSlashSuffix(PathPure.Value)) '由 PCL 添加,这会允许在分割参数并去重后再替换路径,防止路径中的特殊字符影响参数分割和去重
Yield ("${launcher_name}", "PCL")
Yield ("${launcher_version}", VersionCode)
Yield ("${version_name}", McInstanceSelected.Name)
@@ -1568,9 +1554,8 @@ NextInstance:
Case Else
TargetSize = New Size(854, 480)
End Select
- If McInstanceSelected.Version.Vanilla.Major <= 12 AndAlso
- McLaunchJavaSelected.Version >= New Version(8, 0, 200) AndAlso McLaunchJavaSelected.Version <= New Version(8, 0, 321) AndAlso
- Not McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.HasForge Then '修复 1.12.2- 下 JRE 8u200~321 下窗口大小为设置大小的 DPI% 倍(#3463)
+ If McInstanceSelected.Version.Vanilla.Major <= 12 AndAlso McLaunchJavaSelected.Version >= New Version(8, 0, 200) AndAlso McLaunchJavaSelected.Version <= New Version(8, 0, 321) AndAlso
+ Not McInstanceSelected.Version.HasOptiFine AndAlso Not McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then '修复 1.12.2- 下 JRE 8u200~321 下窗口大小为设置大小的 DPI% 倍(#3463)
McLaunchLog($"已应用窗口大小过大修复(Java 版本:{McLaunchJavaSelected.Version})")
TargetSize.Width /= DPI / 96
TargetSize.Height /= DPI / 96
@@ -1694,7 +1679,7 @@ NextInstance:
End Try
For Each Entry In Zip.Entries
Dim FileName As String = Entry.FullName
- If FileName.EndsWithF(".dll", True) Then
+ If PathUtils.GetExtension(FileName) = "dll" Then
'实际解压文件的步骤
Dim FilePath As String = Target & FileName
ExistFiles.Add(FilePath)
@@ -1738,8 +1723,9 @@ NextInstance:
'''
''' 获取 Natives 文件夹路径,以 \ 结尾。
'''
- Private Function GetNativesFolder() As String
- Dim Result As String = PathUtils.AddSlashSuffix(PathUtils.ToShortPath(McInstanceSelected.PathVersion)) & McInstanceSelected.Name & "-natives\"
+ Public Function GetNativesFolder(Optional Instance As McInstance = Nothing) As String
+ If Instance Is Nothing Then Instance = McInstanceSelected
+ Dim Result As String = PathUtils.AddSlashSuffix(PathUtils.ToShortPath(Instance.PathVersion)) & Instance.Name & "-natives\"
If Not (IsGBKEncoding OrElse Result.IsAsciiOnly()) Then
Result = Paths.AppData & ".minecraft\bin\natives\"
If Not Result.IsAsciiOnly() Then
@@ -1865,7 +1851,7 @@ NextInstance:
Dim CurrentLang As String = ReadIni(SetupFileAddress, "lang", "none")
Dim RequiredLang As String = If(CurrentLang = "none" OrElse Not DirectoryUtils.Exists(McInstanceSelected.PathIndie & "saves"), '#3844,整合包可能已经自带了 options.txt
If(Settings.Get(Of Boolean)("ToolHelpChinese"), "zh_cn", "en_us"), CurrentLang.Lower)
- If Not McInstanceSelected.Version.Vaild OrElse McInstanceSelected.Version.Vanilla.Major <= 10 Then
+ If Not McInstanceSelected.Version.Valid OrElse McInstanceSelected.Version.Vanilla.Major <= 10 Then
'将最后两位改为大写,前面的部分保留
RequiredLang = RequiredLang.Substring(0, RequiredLang.Length - 2) & RequiredLang.Substring(RequiredLang.Length - 2).Upper
End If
@@ -1908,53 +1894,40 @@ NextInstance:
If McLoginLoader.Input.Type = McLoginType.Legacy AndAlso Settings.Get(Of Integer)("LaunchSkinType") = 4 AndAlso FileUtils.Exists(Paths.AppDataThenName & "CustomSkin.png") Then
Dim MetaFileAddress As String = PathTemp & "pack.mcmeta"
Dim PackPicAddress As String = PathTemp & "pack.png"
- Dim PackFormat As Integer
- Select Case McInstanceSelected.Version.Vanilla.Major
- Case 0, 1, 2, 3, 4, 5
- '更早的版本没有资源包
- McLaunchLog("Minecraft 版本过老,尚不支持自定义离线皮肤")
- GoTo IgnoreCustomSkin
- Case 6, 7, 8
- PackFormat = 1
- Case 9, 10
- PackFormat = 2
- Case 11, 12
- PackFormat = 3
- Case 13, 14
- PackFormat = 4
- Case 15
- PackFormat = 5
- Case 16
- PackFormat = 6
- Case 17
- PackFormat = 7
- Case 18
- If McInstanceSelected.Version.Vanilla.Minor <= 2 Then
- PackFormat = 8
- Else
- PackFormat = 9
- End If
- Case 19
- If McInstanceSelected.Version.Vanilla.Minor <= 3 Then
- PackFormat = 9
- Else
- PackFormat = 12
- End If
- Case 20
- If McInstanceSelected.Version.Vanilla.Minor <= 1 Then
- PackFormat = 15
- Else
- PackFormat = 17
- End If
- Case Else '快照版是 9999
- PackFormat = 17
- 'https://zh.minecraft.wiki/w/数据包#数据包版本
- End Select
- McLaunchLog("正在构建自定义皮肤资源包,格式为:" & PackFormat)
+ If McInstanceSelected.Version.Vanilla.Major < 6 Then
+ McLaunchLog("Minecraft 版本过老,尚不支持自定义离线皮肤")
+ GoTo IgnoreCustomSkin
+ End If
+ Dim PackVersionJToken As JToken = McInstanceSelected.JsonVersion?("pack_version")
+ If TypeOf PackVersionJToken Is JObject Then PackVersionJToken = DirectCast(PackVersionJToken, JObject)("resource") '从 1.17 开始,可以从 pack_version.resource 获取资源包版本
+ Dim PackVersion As Integer = Val(PackVersionJToken?.ToString)
+ If PackVersion <= 0 Then '没有对应字段的老版本 MC,或兜底
+ Select Case McInstanceSelected.Version.Vanilla.Major
+ Case 6, 7, 8
+ PackVersion = 1
+ Case 9, 10
+ PackVersion = 2
+ Case 11, 12
+ PackVersion = 3
+ Case 13, 14
+ PackVersion = 4
+ Case 15
+ PackVersion = 5
+ Case 16
+ PackVersion = If(McInstanceSelected.Version.Vanilla.Build <= 1, 5, 6)
+ Case 17
+ PackVersion = 7
+ Case 18
+ PackVersion = 8
+ Case Else '旧版快照可能没有可用的资源包格式声明
+ PackVersion = 17
+ End Select
+ End If
+ McLaunchLog($"正在构建自定义皮肤资源包,版本号 {PackVersion},MC 版本 {McInstanceSelected.Version.Vanilla}")
'准备文件
Dim Bit As New MyBitmap(PathImage & "Heads/Logo.png")
Bit.Save(PackPicAddress)
- FileUtils.Write(MetaFileAddress, "{""pack"":{""pack_format"":" & PackFormat & ",""description"":""PCL 自定义离线皮肤资源包""}}")
+ FileUtils.Write(MetaFileAddress, "{""pack"":{""pack_format"":" & PackVersion & ",""description"":""PCL 自定义离线皮肤资源包""}}")
Dim Skin As New MyBitmap(Paths.AppDataThenName & "CustomSkin.png")
If (McInstanceSelected.Version.Vanilla.Major = 6 OrElse McInstanceSelected.Version.Vanilla.Major = 7) AndAlso Skin.Pic.Height = 64 Then
McLaunchLog("该 Minecraft 版本不支持双层皮肤,已进行裁剪")
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
index f6ddaba..ee84df6 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
@@ -15,7 +15,7 @@ Public Module ModMinecraft
End Set
End Property
Private Sub SetMcFolder(Value As String) '等同 McFolderSelected.Set
- If _McFolderSelected = Value Then Return
+ If PathUtils.IsSame(_McFolderSelected, Value.Replace("$", Paths.Base)) Then Return
_McFolderSelected = Value.Replace("$", Paths.Base)
_McFolderSelected = PathUtils.AddSlashSuffix(PathUtils.ForCompare(_McFolderSelected))
Settings.Set("LaunchFolderSelect", Value.Replace(Paths.Base, "$"))
@@ -44,7 +44,7 @@ Public Module ModMinecraft
Public Overrides Function Equals(obj As Object) As Boolean
If Not (TypeOf obj Is McFolder) Then Return False
Dim Folder = DirectCast(obj, McFolder)
- Return Name = Folder.Name AndAlso Location = Folder.Location AndAlso Type = Folder.Type
+ Return Name = Folder.Name AndAlso PathUtils.IsSame(Location, Folder.Location) AndAlso Type = Folder.Type
End Function
Public Overrides Function ToString() As String
Return Location
@@ -76,7 +76,7 @@ Public Module ModMinecraft
'扫描官启文件夹
Dim MojangPath As String = Paths.AppData & ".minecraft\"
- If (Not CacheMcFolderList.Any OrElse MojangPath <> CacheMcFolderList(0).Location) AndAlso '当前文件夹不是官启文件夹
+ If (Not CacheMcFolderList.Any OrElse Not PathUtils.IsSame(MojangPath, CacheMcFolderList(0).Location)) AndAlso '当前文件夹不是官启文件夹
DirectoryUtils.Exists(MojangPath & "versions\") Then '具有权限且存在 versions 文件夹
CacheMcFolderList.Add(New McFolder With {.Name = "官方启动器文件夹", .Location = MojangPath, .Type = McFolder.Types.Vanilla})
End If
@@ -98,7 +98,7 @@ Public Module ModMinecraft
'若已有该文件夹,则直接重命名;没有则添加
Dim Renamed As Boolean = False
For Each OriginalFolder As McFolder In CacheMcFolderList
- If OriginalFolder.Location = FolderPath Then
+ If PathUtils.IsSame(OriginalFolder.Location, FolderPath) Then
OriginalFolder.Name = FolderName
OriginalFolder.Type = McFolder.Types.RenamedVanilla
Renamed = True
@@ -217,6 +217,19 @@ Public Module ModMinecraft
Public Class McInstance
+ Public Enum McInstanceState
+ [Error]
+ Original
+ Snapshot
+ Fool
+ OptiFine
+ Old
+ Forge
+ NeoForge
+ LiteLoader
+ Fabric
+ End Enum
+
'''
''' 版本文件夹路径,以 \ 结尾。
'''
@@ -303,8 +316,7 @@ Public Module ModMinecraft
Public ReadOnly Property Modable As Boolean
Get
If Not IsLoaded Then Load()
- Return Version.HasFabric OrElse Version.HasForgelike OrElse Version.HasLiteLoader OrElse
- DisplayType = McInstanceCardType.API '#223
+ Return Version.ModLoaders.Flags.Any OrElse DisplayType = McInstanceCardType.API '#223
End Get
End Property
'''
@@ -313,135 +325,15 @@ Public Module ModMinecraft
Public Property Version As McVersion
Get
If _Version IsNot Nothing Then Return _Version
- _Version = New McVersion
-#Region "获取游戏版本"
Try
- '获取发布时间并判断是否为老版本
- Try
- If JsonObject("releaseTime") Is Nothing Then
- ReleaseTime = New Date(1970, 1, 1, 15, 0, 0) '未知版本也可能显示为 1970 年
- Else
- ReleaseTime = JsonObject("releaseTime").ToObject(Of Date)
- End If
- If ReleaseTime.Year > 2000 AndAlso ReleaseTime.Year < 2013 Then
- _Version.VanillaName = "Old"
- GoTo VersionSearchFinish
- End If
- Catch
- ReleaseTime = New Date(1970, 1, 1, 15, 0, 0)
- End Try
- '实验性快照
- If If(JsonObject("type"), "") = "pending" Then
- _Version.VanillaName = "pending"
- GoTo VersionSearchFinish
- End If
- '从 PCL 下载的版本信息中获取版本号
- If JsonObject("clientVersion") IsNot Nothing Then
- _Version.VanillaName = JsonObject("clientVersion")
- GoTo VersionSearchFinish
- End If
- '从 HMCL 下载的版本信息中获取版本号
- If JsonObject("patches") IsNot Nothing Then
- For Each Patch As JObject In JsonObject("patches")
- If If(Patch("id"), "").ToString = "game" AndAlso Patch("version") IsNot Nothing Then
- _Version.VanillaName = Patch("version").ToString
- GoTo VersionSearchFinish
- End If
- Next
- End If
- '从 Forge / NeoForge Arguments 中获取版本号
- If JsonObject("arguments") IsNot Nothing AndAlso JsonObject("arguments")("game") IsNot Nothing Then
- Dim Mark As Boolean = False
- For Each Argument In JsonObject("arguments")("game")
- If Mark Then
- _Version.VanillaName = Argument.ToString
- GoTo VersionSearchFinish
- End If
- If Argument.ToString = "--fml.mcVersion" Then Mark = True
- Next
- End If
- '从继承版本中获取版本号
- If Not InheritName = "" Then
- _Version.VanillaName = If(JsonObject("jar"), "").ToString 'LiteLoader 优先使用 Jar
- If _Version.VanillaName = "" Then _Version.VanillaName = InheritName
- GoTo VersionSearchFinish
- End If
- '从下载地址中获取版本号
- Dim Regex As String = If(JsonObject("downloads"), "").ToString.RegexSeek("(?<=launcher.mojang.com/mc/game/)[^/]*")
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '从 Forge 版本中获取版本号
- Dim LibrariesString As String = JsonObject("libraries").ToString
- Regex = If(LibrariesString.RegexSeek("(?<=net.minecraftforge:forge:)[0-9]{1,2}.[0-9+.]+"), LibrariesString.RegexSeek("(?<=net.minecraftforge:fmlloader:)[0-9]{1,2}.[0-9+.]+"))
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '从 OptiFine 版本中获取版本号
- Regex = LibrariesString.RegexSeek("(?<=optifine:OptiFine:)[0-9]{1,2}.[0-9+.]+")
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '从 Fabric 版本中获取版本号
- Regex = LibrariesString.RegexSeek("(?<=((fabricmc)|(quiltmc)):intermediary:)[^""]*")
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '从 jar 项中获取版本号
- If JsonObject("jar") IsNot Nothing Then
- _Version.VanillaName = JsonObject("jar").ToString
- GoTo VersionSearchFinish
- End If
- '从 jar 文件的 version.json 中获取版本号
- If JsonVersion?("name") IsNot Nothing Then
- Dim JsonVerName As String = JsonVersion("name").ToString
- If JsonVerName.Length < 32 Then '因为 wiki 说这玩意儿可能是个 hash,虽然我没发现
- _Version.VanillaName = JsonVerName
- Logger.Info($"从版本 jar 中的 version.json 获取到版本号:{JsonVerName}")
- GoTo VersionSearchFinish
- End If
- End If
- '从 JSON 的 ID 中获取
- Static Pattern = "(([1-9][0-9]w[0-9]{2}[a-g])|((1|[2-9][0-9])\.[0-9]+(\.[0-9]+)?(-(pre|rc|snapshot-?)[1-9]*| Pre-Release( [1-9])?)?))(_unobfuscated)?"
- Regex = JsonObject("id").ToString.RegexSeek(Pattern, RegularExpressions.RegexOptions.IgnoreCase)
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '非准确的版本判断警告
- Logger.Info($"无法完全确认 MC 版本号的版本:{Name}")
- _Version.Reliable = False
- '从文件夹名中获取
- Regex = Name.RegexSeek(Pattern, RegularExpressions.RegexOptions.IgnoreCase)
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '从 JSON 出现的版本号中获取
- Dim JsonRaw As JObject = JsonObject.DeepClone()
- JsonRaw.Remove("libraries")
- Dim JsonRawText As String = JsonRaw.ToString
- Regex = JsonRawText.RegexSeek(Pattern, RegularExpressions.RegexOptions.IgnoreCase)
- If Regex IsNot Nothing Then
- _Version.VanillaName = Regex
- GoTo VersionSearchFinish
- End If
- '无法获取
- _Version.VanillaName = "Unknown"
- Info = "PCL 无法识别该版本的 MC 版本号"
+ Dim Result = New McVersion(Name, JsonObject, JsonVersion)
+ _Version = Result
+ If Result.VanillaName = "Unknown" Then Info = "PCL 无法识别该版本的 MC 版本号"
Catch ex As Exception
Logger.Warn(ex, "识别 Minecraft 版本时出错")
- _Version.VanillaName = "Unknown"
+ _Version = New McVersion("Unknown")
Info = "无法识别:" & ex.Message
End Try
-#End Region
-VersionSearchFinish:
- '获取版本号
- _Version.VanillaName = _Version.VanillaName.Replace("_unobfuscated", "").Replace(" Unobfuscated", "")
Return _Version
End Get
Set(value As McVersion)
@@ -453,7 +345,11 @@ VersionSearchFinish:
'''
''' 版本的发布时间。
'''
- Public ReleaseTime As New Date(1970, 1, 1, 15, 0, 0)
+ Public ReadOnly Property ReleaseTime As Date
+ Get
+ Return Version.ReleaseTime
+ End Get
+ End Property
'''
''' 获取该版本的 JSON 路径。
@@ -741,42 +637,28 @@ Recheck:
State = McInstanceState.Error
Case "Old"
State = McInstanceState.Old
- Case Else '根据 API 进行筛选
- Dim RealJson As String = If(JsonObject, JsonText).ToString
+ Case Else
'愚人节与快照版本
- Dim FixedReleaseTime = ReleaseTime.ToUniversalTime().AddHours(2)
- Dim JsonType = If(JsonObject("type"), "").ToString
- If JsonType = "fool" OrElse
- (FixedReleaseTime.Month = 4 AndAlso FixedReleaseTime.Day = 1 AndAlso JsonType = "snapshot") OrElse
- GetMcFoolName(Version.VanillaName) <> "" Then
+ If Version.IsFool Then
State = McInstanceState.Fool
- ElseIf IsSnapshot() Then
+ ElseIf Version.IsSnapshot Then
State = McInstanceState.Snapshot
End If
'OptiFine
- If RealJson.Contains("optifine") Then
+ If Version.HasOptiFine Then
State = McInstanceState.OptiFine
- Version.OptiFine = If(RealJson.RegexSeek("(?<=HD_U_)[^"":/]+"), "未知版本")
End If
'LiteLoader
- If RealJson.Contains("liteloader") Then
+ If Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) Then
State = McInstanceState.LiteLoader
- Version.HasLiteLoader = True
End If
- 'Fabric、Forge
- If RealJson.Contains("net.fabricmc:fabric-loader") OrElse RealJson.Contains("org.quiltmc:quilt-loader") Then
+ 'Fabric、Forge、NeoForge
+ If Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then
State = McInstanceState.Fabric
- Version.Fabric = If(RealJson.RegexSeek("(?<=(net.fabricmc:fabric-loader:)|(org.quiltmc:quilt-loader:))[0-9\.]+(\+build.[0-9]+)?"), "未知版本").Replace("+build", "")
- ElseIf RealJson.Contains("minecraftforge") AndAlso Not RealJson.Contains("net.neoforge") Then
+ ElseIf Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then
State = McInstanceState.Forge
- Version.Forge = RealJson.RegexSeek("(?<=forge:[0-9\.]+(_pre[0-9]*)?\-)[0-9\.]+")
- If Version.Forge Is Nothing Then Version.Forge = RealJson.RegexSeek("(?<=net\.minecraftforge:minecraftforge:)[0-9\.]+")
- If Version.Forge Is Nothing Then Version.Forge = If(RealJson.RegexSeek("(?<=net\.minecraftforge:fmlloader:[0-9\.]+-)[0-9\.]+"), "未知版本")
- ElseIf RealJson.Contains("net.neoforge") Then
- '1.20.1 JSON 范例:"--fml.forgeVersion", "47.1.99"
- '1.20.2+ JSON 范例:"--fml.neoForgeVersion", "20.6.119-beta"
+ ElseIf Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then
State = McInstanceState.NeoForge
- Version.NeoForge = If(RealJson.RegexSeek("(?<=orgeVersion"",[^""]*?"")[^""]+(?="",)"), "未知版本")
End If
End Select
#End Region
@@ -808,18 +690,7 @@ ExitDataLoad:
End Select
End If
'确定版本描述
- Dim CustomInfo As String = ReadIni(PathVersion & "PCL\Setup.ini", "CustomInfo")
- If CustomInfo <> "" Then
- Info = CustomInfo
- Else
- Info = VersionDisplayName()
- If State = McInstanceState.Fool Then
- Info = GetMcFoolName(Version.VanillaName)
- ElseIf State <> McInstanceState.Error Then
- If Settings.Get(Of Integer)("VersionServerLogin", Instance:=Me) = 3 Then Info += ", 统一通行证验证"
- If Settings.Get(Of Integer)("VersionServerLogin", Instance:=Me) = 4 Then Info += ", Authlib 验证"
- End If
- End If
+ RefreshInfo()
'确定版本收藏状态
IsStar = ReadIni(PathVersion & "PCL\Setup.ini", "IsStar", False)
'确定版本显示种类
@@ -832,11 +703,11 @@ ExitDataLoad:
End If
If State <> McInstanceState.Error AndAlso Version.Reliable Then
WriteIni(PathVersion & "PCL\Setup.ini", "ReleaseTime", ReleaseTime.ToString("yyyy'-'MM'-'dd HH':'mm"))
- WriteIni(PathVersion & "PCL\Setup.ini", "VersionFabric", Version.Fabric)
- WriteIni(PathVersion & "PCL\Setup.ini", "VersionOptiFine", Version.OptiFine)
- WriteIni(PathVersion & "PCL\Setup.ini", "VersionLiteLoader", Version.HasLiteLoader)
- WriteIni(PathVersion & "PCL\Setup.ini", "VersionForge", Version.Forge)
- WriteIni(PathVersion & "PCL\Setup.ini", "VersionNeoForge", Version.NeoForge)
+ WriteIni(PathVersion & "PCL\Setup.ini", "VersionFabric", If(Version.ModLoaders.HasFlagF(ModLoaders.Fabric), Version.ModLoaderVersions(ModLoaders.Fabric), Nothing))
+ WriteIni(PathVersion & "PCL\Setup.ini", "VersionOptiFine", If(Version.OptiFineAsMod, Nothing, Version.OptiFine))
+ WriteIni(PathVersion & "PCL\Setup.ini", "VersionLiteLoader", Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader))
+ WriteIni(PathVersion & "PCL\Setup.ini", "VersionForge", If(Version.ModLoaders.HasFlagF(ModLoaders.Forge), Version.ModLoaderVersions(ModLoaders.Forge), Nothing))
+ WriteIni(PathVersion & "PCL\Setup.ini", "VersionNeoForge", If(Version.ModLoaders.HasFlagF(ModLoaders.NeoForge), Version.ModLoaderVersions(ModLoaders.NeoForge), Nothing))
WriteIni(PathVersion & "PCL\Setup.ini", "VersionVanillaName", Version.VanillaName)
WriteIni(PathVersion & "PCL\Setup.ini", "VersionVanilla", Version.Vanilla.ToString)
End If
@@ -850,26 +721,36 @@ ExitDataLoad:
End Try
Return Me
End Function
- Private Function IsSnapshot() As Boolean
- Dim jsonType As String = If(JsonObject("type"), "").ToString
- Return {"w", "snapshot", "rc", "pre", "experimental", "-"}.Any(Function(s) Version.VanillaName.ContainsIgnoreCase(s)) OrElse
- Name.ContainsIgnoreCase("combat") OrElse
- jsonType = "snapshot" OrElse jsonType = "pending" OrElse jsonType = "fool"
- End Function
-
Public IsLoaded As Boolean = False
'''
+ ''' 根据当前组件信息刷新版本描述。
+ '''
+ Public Sub RefreshInfo()
+ Dim CustomInfo As String = ReadIni(PathVersion & "PCL\Setup.ini", "CustomInfo")
+ If CustomInfo <> "" Then
+ Info = CustomInfo
+ Else
+ Info = VersionDisplayName()
+ If State = McInstanceState.Fool Then
+ Info = GetMcFoolName(Version.VanillaName)
+ ElseIf State <> McInstanceState.Error Then
+ If Settings.Get(Of Integer)("VersionServerLogin", Instance:=Me) = 3 Then Info += ", 统一通行证验证"
+ If Settings.Get(Of Integer)("VersionServerLogin", Instance:=Me) = 4 Then Info += ", Authlib 验证"
+ End If
+ End If
+ End Sub
+ '''
''' 获取对版本信息的简短描述。
''' 例如 “快照 16w01a”、“原版 1.12.2, Forge 1.2.3”、“愚人节版本 2.0”。
'''
Public Function VersionDisplayName() As String
'Mod Loader 信息
Dim ModLoaderInfo As String = ""
- If Version.HasForge Then ModLoaderInfo += ", Forge" & If(Version.Forge = "未知版本", "", " " & Version.Forge)
- If Version.HasNeoForge Then ModLoaderInfo += ", NeoForge" & If(Version.NeoForge = "未知版本", "", " " & Version.NeoForge)
- If Version.HasFabric Then ModLoaderInfo += ", Fabric" & If(Version.Fabric = "未知版本", "", " " & Version.Fabric)
+ If Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then ModLoaderInfo += ", Forge" & If(Version.ModLoaderVersions(ModLoaders.Forge) = "未知版本", "", " " & Version.ModLoaderVersions(ModLoaders.Forge))
+ If Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then ModLoaderInfo += ", NeoForge" & If(Version.ModLoaderVersions(ModLoaders.NeoForge) = "未知版本", "", " " & Version.ModLoaderVersions(ModLoaders.NeoForge))
+ If Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then ModLoaderInfo += ", Fabric" & If(Version.ModLoaderVersions(ModLoaders.Fabric) = "未知版本", "", " " & Version.ModLoaderVersions(ModLoaders.Fabric))
If Version.HasOptiFine Then ModLoaderInfo += ", OptiFine" & If(Version.OptiFine = "未知版本", "", " " & Version.OptiFine.Replace("-", " ").Replace("_", " "))
- If Version.HasLiteLoader Then ModLoaderInfo += ", LiteLoader"
+ If Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) Then ModLoaderInfo += ", LiteLoader"
'基础信息
Dim Info As String
Select Case State
@@ -882,7 +763,7 @@ ExitDataLoad:
Info = "实验性快照" & Version.VanillaName
ElseIf Version.VanillaName = "pending" Then
Info = "实验性快照"
- ElseIf IsSnapshot() Then
+ ElseIf Version.IsSnapshot Then
Info = If(Version.Reliable, "快照版 " & Version.VanillaName.Replace("-snapshot", ""), "快照版")
Else
Info = If(Version.Reliable, "正式版 " & Version.VanillaName, "正式版")
@@ -927,287 +808,91 @@ ExitDataLoad:
End Function) With {.Height = 42}
End Function
+ '''
+ ''' 重命名 MC 版本。
+ '''
+ Public Function Rename(NewName As String) As McInstance
+ Dim OldName = Name
+ Dim OldPath = PathVersion
+ Dim NewPath = PathUtils.AddSlashSuffix(Path.Combine(PathUtils.RemoveLastPart(OldPath), NewName))
+ '重新读取版本 JSON 信息,避免 JsonObject 中已被合并的项被重新存储
+ Dim JsonObject As JObject
+ Dim OldJsonPath = GetJsonPath()
+ Try
+ JsonObject = FileUtils.ReadAsJson(OldJsonPath)
+ Catch ex As Exception
+ Logger.Warn(ex, "在重命名读取 JSON 时失败")
+ JsonObject = Me.JsonObject
+ End Try
+ '清理缓存
+ Config.Save()
+ ResetSettingsCache()
+ '重命名主文件夹
+ DirectoryUtils.Move(OldPath, NewPath)
+ '重命名 jar 文件与 natives 文件夹
+ '不能进行遍历重命名,否则在版本名很短的时候容易误伤其他文件(#6443)
+ If DirectoryUtils.Exists($"{NewPath}{OldName}-natives") Then DirectoryUtils.Move($"{NewPath}{OldName}-natives", $"{NewPath}{NewName}-natives")
+ If FileUtils.Exists($"{NewPath}{OldName}.jar") Then FileUtils.Move($"{NewPath}{OldName}.jar", $"{NewPath}{NewName}.jar")
+ '替换版本设置文件中的路径
+ If FileUtils.Exists(NewPath & "PCL\Setup.ini") Then
+ FileUtils.Write(NewPath & "PCL\Setup.ini", FileUtils.ReadAsString(NewPath & "PCL\Setup.ini").Replace(OldPath, NewPath))
+ End If
+ '更改已选中的版本
+ If ReadIni(McFolderSelected & "PCL.ini", "Version") = OldName Then WriteIni(McFolderSelected & "PCL.ini", "Version", NewName)
+ '更新版本 Json
+ Try
+ JsonObject("id") = NewName
+ FileUtils.Delete(NewPath & PathUtils.GetLastPart(OldJsonPath))
+ FileUtils.Write(NewPath & NewName & ".json", JsonObject.ToString)
+ Catch ex As Exception
+ Logger.Warn(ex, "重命名版本 json 失败")
+ End Try
+ Return New McInstance(NewPath).Load()
+ End Function
+
'运算符支持
Public Overrides Function Equals(obj As Object) As Boolean
Dim version = TryCast(obj, McInstance)
- Return version IsNot Nothing AndAlso PathVersion = version.PathVersion
+ Return version IsNot Nothing AndAlso PathUtils.IsSame(PathVersion, version.PathVersion)
End Function
Public Shared Operator =(a As McInstance, b As McInstance) As Boolean
If a Is Nothing AndAlso b Is Nothing Then Return True
If a Is Nothing OrElse b Is Nothing Then Return False
- Return a.PathVersion = b.PathVersion
+ Return PathUtils.IsSame(a.PathVersion, b.PathVersion)
End Operator
Public Shared Operator <>(a As McInstance, b As McInstance) As Boolean
Return Not (a = b)
End Operator
+
End Class
- Public Enum McInstanceState
- [Error]
- Original
- Snapshot
- Fool
- OptiFine
- Old
- Forge
- NeoForge
- LiteLoader
- Fabric
- End Enum
'''
- ''' Minecraft 版本号和附加组件信息。
+ ''' MC 版本独占锁。
'''
- Public Class McVersion
-
- '原版
-
- '''
- ''' 原版版本名。
- ''' 如 26.1,26.1-snapshot-1,1.12.2,16w01a。
- '''
- Public Property VanillaName As String
+ Public NotInheritable Class McInstanceLock
+ Private Shared ReadOnly LockedPaths As New ConcurrentDictionary(Of String, IWorker)(StringComparer.OrdinalIgnoreCase)
+ Friend Shared ReadOnly Property IsAnyLocked As Boolean
Get
- Return _VanillaName
- End Get
- Set(value As String)
- If _VanillaName = value Then Return
- _VanillaName = value
- Vanilla = NameToVersion(_VanillaName)
- End Set
- End Property
- Private _VanillaName As String
- '''
- ''' 可比较的三段式原版版本号。
- ''' 对老版本格式,例如 1.20.1,会被转换为 20.0.1。
- ''' 若没有版本号,例如旧快照,则为 9999.0.0。
- '''
- Public Vanilla As Version
- '''
- ''' 指示原版版本号是否可靠(不是通过猜测获取)。
- '''
- Public Reliable As Boolean = True
- '''
- ''' 原版版本号是否有效。
- '''
- Public ReadOnly Property Vaild As Boolean
- Get
- Return Vanilla.Major < 1000
+ Return Not LockedPaths.IsEmpty
End Get
End Property
'''
- ''' 可供比较的原版 Drop 序数。
- ''' 例如 26.3.2 为 263,1.21.5 为 210。
- ''' 若没有版本号,例如旧快照,则直接指定为 209。
+ ''' 在 结束前,锁定指定的 MC 版本。当 结束时,会自动将锁定释放。
+ ''' 仅在该版本已被锁定时返回 false,此时不会改变锁定状态。
'''
- Public ReadOnly Property Drop As Integer
- Get
- Return If(Vaild, Vanilla.Major * 10 + Vanilla.Minor, 209)
- End Get
- End Property
-
- 'OptiFine
-
- '''
- ''' 该版本是否通过 JSON 安装了 OptiFine。
- '''
- Public ReadOnly Property HasOptiFine As Boolean
- Get
- Return OptiFine IsNot Nothing
- End Get
- End Property
- '''
- ''' OptiFine 版本名,如 C8、C9_pre10。
- '''
- Public OptiFine As String = Nothing
- '''
- ''' 可供比较的 OptiFine 版本序数。
- '''
- Public ReadOnly Property OptiFineCode As Integer
- Get
- If OptiFine Is Nothing OrElse OptiFine = "未知版本" Then Return 0
- '字母编号,如 G2 中的 G(7)
- Dim Result As Integer = Asc(OptiFine.Upper.First) - Asc("A"c) + 1
- '末尾数字,如 C5 beta4 中的 5
- Result *= 100
- Result += Val(Right(OptiFine, OptiFine.Length - 1).RegexSeek("[0-9]+"))
- '测试标记(正式版为 99,Pre[x] 为 50+x,Beta[x] 为 x)
- Result *= 100
- If OptiFine.ContainsIgnoreCase("pre") Then Result += 50
- If OptiFine.ContainsIgnoreCase("pre") OrElse OptiFine.ContainsIgnoreCase("beta") Then
- If Val(Right(OptiFine, 1)) = 0 AndAlso Right(OptiFine, 1) <> "0" Then
- Result += 1 '为 pre 或 beta 结尾,视作 1
- Else
- Result += Val(OptiFine.Lower.RegexSeek("(?<=((pre)|(beta)))[0-9]+"))
- End If
- Else
- Result += 99
- End If
- Return Result
- End Get
- End Property
-
- 'Forge/NeoForge
-
- '''
- ''' 该版本是否安装了 Forge。
- '''
- Public ReadOnly Property HasForge As Boolean
- Get
- Return Forge IsNot Nothing
- End Get
- End Property
- '''
- ''' 该版本是否安装了 NeoForge。
- '''
- Public ReadOnly Property HasNeoForge As Boolean
- Get
- Return NeoForge IsNot Nothing
- End Get
- End Property
- '''
- ''' 该版本是否安装了 Forge 或 NeoForge。
- '''
- Public ReadOnly Property HasForgelike As Boolean
- Get
- Return HasForge OrElse HasNeoForge
- End Get
- End Property
- '''
- ''' Forge 版本名,如 31.1.2、14.23.5.2847。
- '''
- Public Forge As String = Nothing
- '''
- ''' NeoForge 版本名,如 47.1.79、21.0.2-beta、26.1.0.0-alpha.14+snapshot-11。
- '''
- Public NeoForge As String = Nothing
- '''
- ''' 可供比较的类 Forge 版本序数。
- '''
- Public ReadOnly Property ForgelikeCode As Integer
- Get
- If Not HasForgelike Then Return 0
- If (Forge Is Nothing OrElse Forge = "未知版本") AndAlso
- (NeoForge Is Nothing OrElse NeoForge = "未知版本") Then Return 0
- Dim Segments = If(HasForge, Forge, NeoForge).RegexSearch("\d+").ToList
- Select Case Segments.Count
- Case Is > 4
- Return Val(Segments(0)) * 1000000 + Val(Segments(1)) * 10000 + Val(Segments(3))
- Case 3
- Return Val(Segments(0)) * 1000000 + Val(Segments(1)) * 10000 + Val(Segments(2))
- Case 2
- Return Val(Segments(0)) * 1000000 + Val(Segments(1)) * 10000
- Case Else
- Return Val(Segments(0)) * 1000000
- End Select
- End Get
- End Property
-
- 'Fabric
-
- '''
- ''' 该版本是否安装了 Fabric。
- '''
- Public ReadOnly Property HasFabric As Boolean
- Get
- Return Fabric IsNot Nothing
- End Get
- End Property
- '''
- ''' Fabric 版本名,如 0.7.2.175。
- '''
- Public Fabric As String = Nothing
-
- 'LiteLoader
-
- '''
- ''' 该版本是否安装了 LiteLoader。
- '''
- Public HasLiteLoader As Boolean = False
-
- 'Helpers
-
- '''
- ''' 获取该版本包含的 Mod Loader。
- '''
- Public ReadOnly Property ModLoaders As ModLoaders
- Get
- Dim Result As ModLoaders = ModLoaders.None
- If HasForge Then Result = Result Or ModLoaders.Forge
- If HasNeoForge Then Result = Result Or ModLoaders.NeoForge
- If HasFabric Then Result = Result Or ModLoaders.Fabric
- If HasLiteLoader Then Result = Result Or ModLoaders.LiteLoader
- Return Result
- End Get
- End Property
- '''
- ''' 版本字符串是否符合 Minecraft 原版格式,例如 1.x、26.x。
- '''
- Public Shared Function IsFormatFit(Version As String) As Boolean
- If Version Is Nothing Then Return False
- If Version.RegexCheck("^1\.\d") Then Return True
- If Val(Version.RegexSeek("^[2-9]\d\.\d+")) >= 26 Then Return True
- Return False
+ Public Shared Function TryAcquire(Worker As IWorker, InstancePath As String) As Boolean
+ InstancePath = PathUtils.ForCompare(InstancePath)
+ If Not LockedPaths.TryAdd(InstancePath, Worker) Then Return False
+ AddHandler Worker.Stopped, Sub() LockedPaths.TryRemove(InstancePath, Nothing)
+ Return True
End Function
'''
- ''' 将版本名转换为 Drop 序数。
- ''' 若无法转换则返回 209。
+ ''' 检查 MC 版本是否正被锁定。
'''
- Public Shared Function VersionToDrop(VanillaName As String) As Integer
- If VanillaName Is Nothing Then Return 209
- Dim Version = NameToVersion(VanillaName)
- If Version.Major >= 1000 Then Return 209
- Return Version.Major * 10 + Version.Minor
+ Public Shared Function IsLocked(Instance As McInstance) As Boolean
+ If Instance Is Nothing Then Return False
+ Return LockedPaths.ContainsKey(PathUtils.ForCompare(Instance.PathVersion))
End Function
- '''
- ''' 将 Drop 序数转换为版本字符串。
- '''
- Public Shared Function DropToVersion(Drop As Integer) As String
- If Drop >= 250 Then
- Return $"{Drop \ 10}.{Drop Mod 10}"
- ElseIf Drop = 209 Then
- Logger.Warn(New Exception("尝试将旧快照版 Drop 序数转换为版本字符串,这不应该发生!"))
- Return "1.20"
- Else
- Return $"1.{Drop \ 10}"
- End If
- End Function
- '''
- ''' 将版本名转换为可比较的三段式原版版本号。
- ''' 对老版本格式,例如 1.20.3,会被转换为 20.0.3。
- ''' 对愚人节版本,返回其基于的正式版版本号。
- ''' 若没有版本号,例如旧快照,则为 9999.0.0。
- '''
- Public Shared Function NameToVersion(Name As String) As Version
- Name = Name.Lower.Replace("_unobfuscated", "").Replace(" Unobfuscated", "")
- '愚人节版本
- If Name.StartsWithF("2.0") Then Return NameToVersion("1.5.1")
- If Name = "15w14a" Then Return NameToVersion("1.8.3")
- If Name.Contains(".rv-pre") Then Return NameToVersion("1.9.2")
- If Name.Contains("shareware") Then Return NameToVersion("1.13.2")
- If Name.StartsWithF("20w14") AndAlso Name <> "20w14a" Then Return NameToVersion("1.15.2")
- If Name.Contains("oneblockatatime") Then Return NameToVersion("1.18.2")
- If Name.Contains("23w13a") AndAlso Name <> "20w13a" Then Return NameToVersion("1.19.4")
- If Name = "24w14potato" Then Return NameToVersion("1.20.4")
- If Name = "25w14craftmine" Then Return NameToVersion("1.21.4")
- If Name = "26w14a" Then Return NameToVersion("26.1.1")
- '其余版本
- If Name.StartsWithF("1.") Then
- Dim Segments = Name.Split(" _-.".ToCharArray)
- Return New Version(
- Val(If(Segments.Count >= 2, Segments(1), "0")),
- 0,
- Val(If(Segments.Count >= 3, Segments(2), "0")))
- ElseIf Name.RegexCheck("^[2-9][0-9]\.") Then
- Dim Segments = Name.Split(" _-.".ToCharArray)
- Return New Version(
- Val(Segments(0)),
- Val(If(Segments.Count >= 2, Segments(1), "0")),
- Val(If(Segments.Count >= 3, Segments(2), "0")))
- Else
- Return New Version(9999, 0, 0)
- End If
- End Function
-
End Class
'''
@@ -1315,7 +1000,7 @@ OnLoaded:
If SavedSelection <> "" Then
For Each Card As KeyValuePair(Of McInstanceCardType, List(Of McInstance)) In McInstanceList
For Each Instance As McInstance In Card.Value
- If Instance.Name = SavedSelection AndAlso Not Instance.State = McInstanceState.Error Then
+ If Instance.Name = SavedSelection AndAlso Not Instance.State = McInstance.McInstanceState.Error Then
'使用已储存的选择
McInstanceSelected = Instance
Logger.Info($"选择该文件夹储存的 Minecraft 版本:{McInstanceSelected.PathVersion}")
@@ -1324,7 +1009,7 @@ OnLoaded:
Next
Next
End If
- If Not McInstanceList.First.Value(0).State = McInstanceState.Error Then
+ If Not McInstanceList.First.Value(0).State = McInstance.McInstanceState.Error Then
'自动选择第一项
McInstanceSelected = McInstanceList.First.Value(0)
Logger.Info($"自动选择 Minecraft 版本:{McInstanceSelected.PathVersion}")
@@ -1372,40 +1057,58 @@ OnLoaded:
Instance.Info = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "CustomInfo", "")
If Instance.Info = "" Then Instance.Info = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "Info", Instance.Info)
Instance.Logo = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "Logo", Instance.Logo)
- Instance.ReleaseTime = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "ReleaseTime", Instance.ReleaseTime)
Instance.State = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "State", Instance.State)
Instance.IsStar = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "IsStar", False)
Instance.DisplayType = ReadIni(Folder & "PCL\Setup.ini", "DisplayType", McInstanceCardType.Auto)
- If Instance.State <> McInstanceState.Error AndAlso
- ReadIni(Instance.PathVersion & "PCL\Setup.ini", "VersionVanillaName", "Unknown") <> "Unknown" Then
- '读取版本信息
- Dim ReadCachedInfo =
- Function(Key As String) As String
- Dim Value = ReadIni(Instance.PathVersion & "PCL\Setup.ini", Key, Nothing)
- Return If(Value = "", Nothing, Value) '对老版本 Setup.ini 的空值兼容
- End Function
- Dim VersionInfo As New McVersion With {
- .Fabric = ReadCachedInfo("VersionFabric"),
- .Forge = ReadCachedInfo("VersionForge"),
- .NeoForge = ReadCachedInfo("VersionNeoForge"),
- .OptiFine = ReadCachedInfo("VersionOptiFine"),
- .HasLiteLoader = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "VersionLiteLoader", False),
- .VanillaName = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "VersionVanillaName", "Unknown")
- }
- Instance.Version = VersionInfo
+ Dim Manifest As McInstallManifest = If(Instance.State = McInstance.McInstanceState.Error, Nothing, Configs.McInstallManifest.Get(Instance.Config))
+ '检查 manifest 是否有过期文件,并进行更新
+ If Manifest IsNot Nothing AndAlso Manifest.SchemaVersion <= Versions.McInstallManifestVersion AndAlso Manifest.ManagedFiles.Any(Function(File) File.Component IsNot Nothing) Then
+ Dim LatestManifest = Manifest.RefreshModComponents(Instance.PathIndie)
+ If LatestManifest IsNot Manifest Then
+ Manifest = LatestManifest
+ Configs.McInstallManifest.Set(Manifest, Instance.Config)
+ Instance.Config.Save()
+ End If
+ End If
+ Dim CachedVanillaName = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "VersionVanillaName", "Unknown")
+ If Instance.State <> McInstance.McInstanceState.Error AndAlso (Manifest IsNot Nothing OrElse CachedVanillaName <> "Unknown") Then
+ Dim Version As McVersion
+ If Manifest IsNot Nothing Then
+ '从 manifest 中读取版本信息
+ Version = New McVersion(Manifest.Components) With {
+ .OptiFineAsMod = Manifest.ManagedFiles.Any(Function(File) File.Component = "OptiFine")}
+ Else
+ '从 Setup.ini 中读取版本信息
+ Dim ReadCachedInfo =
+ Function(Key As String) As String
+ Dim Value = ReadIni(Instance.PathVersion & "PCL\Setup.ini", Key, Nothing)
+ Return If(Value = "", Nothing, Value) '对老版本 Setup.ini 的空值兼容
+ End Function
+ Version = New McVersion(CachedVanillaName) With {.OptiFine = ReadCachedInfo("VersionOptiFine")}
+ For Each Loader In {ModLoaders.Fabric, ModLoaders.Forge, ModLoaders.NeoForge}
+ Dim CachedVersion = ReadCachedInfo($"Version{Loader}")
+ If CachedVersion IsNot Nothing Then Version.ModLoaderVersions(Loader) = CachedVersion
+ Next
+ If ReadIni(Instance.PathVersion & "PCL\Setup.ini", "VersionLiteLoader", False) Then Version.ModLoaderVersions(ModLoaders.LiteLoader) = "未知版本"
+ End If
+ Version.ReleaseTime = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "ReleaseTime", New Date(1970, 1, 1, 15, 0, 0))
+ Version.IsFool = Version.IsFool OrElse Instance.State = McInstance.McInstanceState.Fool
+ Version.IsSnapshot = Version.IsSnapshot OrElse Instance.State = McInstance.McInstanceState.Snapshot OrElse Instance.Name.ContainsIgnoreCase("combat")
+ Instance.Version = Version
+ If Manifest IsNot Nothing Then Instance.RefreshInfo()
Else
Instance.Load()
End If
'重新检查错误版本
- If Instance.State = McInstanceState.Error Then
+ If Instance.State = McInstance.McInstanceState.Error Then
'重新尝试获取版本信息
Dim OldDesc As String = Instance.Info
- Instance.State = McInstanceState.Original
+ Instance.State = McInstance.McInstanceState.Original
Instance.Check()
'校验错误原因是否改变
Dim CustomInfo As String = ReadIni(Instance.PathVersion & "PCL\Setup.ini", "CustomInfo")
- If Instance.State = McInstanceState.Original OrElse (CustomInfo = "" AndAlso Not OldDesc = Instance.Info) Then
+ If Instance.State = McInstance.McInstanceState.Original OrElse (CustomInfo = "" AndAlso Not OldDesc = Instance.Info) Then
Logger.Info($"版本 {Instance.Name} 的错误状态已变更,新的状态为:{Instance.Info}")
Return Nothing
End If
@@ -1480,41 +1183,41 @@ OnLoaded:
If InstanceStar.Any Then InstanceListOriginal.Add(McInstanceCardType.Star, InstanceStar)
'预先筛选出愚人节和错误的版本
- McInstanceFilter(InstanceList, InstanceListOriginal, {McInstanceState.Error}, McInstanceCardType.Error)
- McInstanceFilter(InstanceList, InstanceListOriginal, {McInstanceState.Fool}, McInstanceCardType.Fool)
+ McInstanceFilter(InstanceList, InstanceListOriginal, {McInstance.McInstanceState.Error}, McInstanceCardType.Error)
+ McInstanceFilter(InstanceList, InstanceListOriginal, {McInstance.McInstanceState.Fool}, McInstanceCardType.Fool)
'筛选 API 版本
- McInstanceFilter(InstanceList, InstanceListOriginal, {McInstanceState.Forge, McInstanceState.NeoForge, McInstanceState.LiteLoader, McInstanceState.Fabric}, McInstanceCardType.API)
+ McInstanceFilter(InstanceList, InstanceListOriginal, {McInstance.McInstanceState.Forge, McInstance.McInstanceState.NeoForge, McInstance.McInstanceState.LiteLoader, McInstance.McInstanceState.Fabric}, McInstanceCardType.API)
'将老版本预先分类入不常用,只剩余原版、快照、OptiFine
Dim InstanceUseful As New List(Of McInstance)
Dim InstanceRubbish As New List(Of McInstance)
- McInstanceFilter(InstanceList, {McInstanceState.Old}, InstanceRubbish)
+ McInstanceFilter(InstanceList, {McInstance.McInstanceState.Old}, InstanceRubbish)
'确认最新版本,若为快照则加入常用列表
Dim LargestInstance As McInstance = InstanceList.
- Where(Function(v) v.State = McInstanceState.Original OrElse v.State = McInstanceState.Snapshot).
+ Where(Function(v) v.State = McInstance.McInstanceState.Original OrElse v.State = McInstance.McInstanceState.Snapshot).
MaxBy(Function(v) v.ReleaseTime)
- If LargestInstance IsNot Nothing AndAlso LargestInstance.State = McInstanceState.Snapshot Then
+ If LargestInstance IsNot Nothing AndAlso LargestInstance.State = McInstance.McInstanceState.Snapshot Then
InstanceUseful.Add(LargestInstance)
InstanceList.Remove(LargestInstance)
End If
'将剩余的快照全部拖进不常用列表
- McInstanceFilter(InstanceList, {McInstanceState.Snapshot}, InstanceRubbish)
+ McInstanceFilter(InstanceList, {McInstance.McInstanceState.Snapshot}, InstanceRubbish)
'获取每个 Drop 下最新的原版与 OptiFine
Dim NewerInstance As New Dictionary(Of String, McInstance)
Dim ExistDrops As New List(Of Integer)
For Each Instance As McInstance In InstanceList
- If Not Instance.Version.Vaild Then Continue For
+ If Not Instance.Version.Valid Then Continue For
If Not ExistDrops.Contains(Instance.Version.Drop) Then ExistDrops.Add(Instance.Version.Drop)
Dim Key As String = Instance.Version.Drop & "-" & Instance.State
If Not NewerInstance.ContainsKey(Key) Then
NewerInstance.Add(Key, Instance)
Continue For
End If
- If Instance.Version.HasOptiFine Then
+ If Instance.State = McInstance.McInstanceState.OptiFine Then
If Instance.Version.OptiFineCode > NewerInstance(Key).Version.OptiFineCode Then NewerInstance(Key) = Instance 'OptiFine 根据版本号判断
Else
If Instance.ReleaseTime > NewerInstance(Key).ReleaseTime Then NewerInstance(Key) = Instance '原版根据发布时间判断
@@ -1523,10 +1226,10 @@ OnLoaded:
'将每个 Drop 下的最常规版本加入
For Each Drop As Integer In ExistDrops
- If NewerInstance.ContainsKey(Drop & "-" & McInstanceState.OptiFine) AndAlso NewerInstance.ContainsKey(Drop & "-" & McInstanceState.Original) Then
+ If NewerInstance.ContainsKey(Drop & "-" & McInstance.McInstanceState.OptiFine) AndAlso NewerInstance.ContainsKey(Drop & "-" & McInstance.McInstanceState.Original) Then
'同时存在 OptiFine 与原版
- Dim VanillaInstance As McInstance = NewerInstance(Drop & "-" & McInstanceState.Original)
- Dim OptiFineInstance As McInstance = NewerInstance(Drop & "-" & McInstanceState.OptiFine)
+ Dim VanillaInstance As McInstance = NewerInstance(Drop & "-" & McInstance.McInstanceState.Original)
+ Dim OptiFineInstance As McInstance = NewerInstance(Drop & "-" & McInstance.McInstanceState.OptiFine)
If VanillaInstance.Version.Drop > OptiFineInstance.Version.Drop Then
'仅在原版比 OptiFine 更新时才加入原版
InstanceUseful.Add(VanillaInstance)
@@ -1534,14 +1237,14 @@ OnLoaded:
End If
InstanceUseful.Add(OptiFineInstance)
InstanceList.Remove(OptiFineInstance)
- ElseIf NewerInstance.ContainsKey(Drop & "-" & McInstanceState.OptiFine) Then
+ ElseIf NewerInstance.ContainsKey(Drop & "-" & McInstance.McInstanceState.OptiFine) Then
'没有原版,直接加入 OptiFine
- InstanceUseful.Add(NewerInstance(Drop & "-" & McInstanceState.OptiFine))
- InstanceList.Remove(NewerInstance(Drop & "-" & McInstanceState.OptiFine))
- ElseIf NewerInstance.ContainsKey(Drop & "-" & McInstanceState.Original) Then
+ InstanceUseful.Add(NewerInstance(Drop & "-" & McInstance.McInstanceState.OptiFine))
+ InstanceList.Remove(NewerInstance(Drop & "-" & McInstance.McInstanceState.OptiFine))
+ ElseIf NewerInstance.ContainsKey(Drop & "-" & McInstance.McInstanceState.Original) Then
'没有 OptiFine,直接加入原版
- InstanceUseful.Add(NewerInstance(Drop & "-" & McInstanceState.Original))
- InstanceList.Remove(NewerInstance(Drop & "-" & McInstanceState.Original))
+ InstanceUseful.Add(NewerInstance(Drop & "-" & McInstance.McInstanceState.Original))
+ InstanceList.Remove(NewerInstance(Drop & "-" & McInstance.McInstanceState.Original))
End If
Next
@@ -1588,11 +1291,11 @@ OnLoaded:
If (Left.ReleaseTime.Year >= 2000 OrElse Right.ReleaseTime.Year >= 2000) AndAlso
Left.ReleaseTime <> Right.ReleaseTime Then Return Left.ReleaseTime > Right.ReleaseTime
'附加组件种类
- If Left.Version.HasFabric <> Right.Version.HasFabric Then Return Left.Version.HasFabric
- If Left.Version.HasNeoForge <> Right.Version.HasNeoForge Then Return Left.Version.HasNeoForge
- If Left.Version.HasForge <> Right.Version.HasForge Then Return Left.Version.HasForge
+ If Left.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) <> Right.Version.ModLoaders.HasFlagF(ModLoaders.Fabric) Then Return Left.Version.ModLoaders.HasFlagF(ModLoaders.Fabric)
+ If Left.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) <> Right.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge) Then Return Left.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge)
+ If Left.Version.ModLoaders.HasFlagF(ModLoaders.Forge) <> Right.Version.ModLoaders.HasFlagF(ModLoaders.Forge) Then Return Left.Version.ModLoaders.HasFlagF(ModLoaders.Forge)
If Left.Version.HasOptiFine <> Right.Version.HasOptiFine Then Return Left.Version.HasOptiFine
- If Left.Version.HasLiteLoader <> Right.Version.HasLiteLoader Then Return Left.Version.HasLiteLoader
+ If Left.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) <> Right.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader) Then Return Left.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader)
'附加组件版本
If GetComponentCode(Left) <> GetComponentCode(Right) Then Return GetComponentCode(Left) > GetComponentCode(Right)
'名称
@@ -1612,6 +1315,7 @@ OnLoaded:
WriteIni(Folder & "PCL.ini", "CardValue" & (i + 1), Value)
Next
#End Region
+
Return Results
End Function
'''
@@ -1620,7 +1324,7 @@ OnLoaded:
''' 用于筛选的列表。
''' 需要筛选出的版本类型。-2 代表隐藏的版本。
''' 卡片的名称。
- Private Sub McInstanceFilter(ByRef InstanceList As List(Of McInstance), ByRef Target As Dictionary(Of McInstanceCardType, List(Of McInstance)), Formula As McInstanceState(), CardType As McInstanceCardType)
+ Private Sub McInstanceFilter(ByRef InstanceList As List(Of McInstance), ByRef Target As Dictionary(Of McInstanceCardType, List(Of McInstance)), Formula As McInstance.McInstanceState(), CardType As McInstanceCardType)
Dim KeepList = InstanceList.Where(Function(v) Formula.Contains(v.State)).ToList
'加入版本列表,并从剩余中删除
If KeepList.Any Then
@@ -1634,7 +1338,7 @@ OnLoaded:
''' 用于筛选的列表。
''' 需要筛选出的版本类型。-2 代表隐藏的版本。
''' 传入需要增加入的列表。
- Private Sub McInstanceFilter(ByRef InstanceList As List(Of McInstance), Formula As McInstanceState(), ByRef KeepList As List(Of McInstance))
+ Private Sub McInstanceFilter(ByRef InstanceList As List(Of McInstance), Formula As McInstance.McInstanceState(), ByRef KeepList As List(Of McInstance))
KeepList.AddRange(InstanceList.Where(Function(v) Formula.Contains(v.State)))
'加入版本列表,并从剩余中删除
If KeepList.Any Then
@@ -1909,7 +1613,7 @@ OnLoaded:
'根据 Inherit 获取最深层版本
Dim OriginalInstance As McInstance = Instance
'1.17+ 的 Forge 不寻找 Inherit
- If Not (Instance.Version.HasForgelike AndAlso Instance.Version.Vanilla.Major >= 17) Then
+ If Not ((Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) OrElse Instance.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge)) AndAlso Instance.Version.Vanilla.Major >= 17) Then
Do Until OriginalInstance.InheritName = ""
If OriginalInstance.InheritName = OriginalInstance.Name Then Exit Do
OriginalInstance = New McInstance(McFolderSelected & "versions\" & OriginalInstance.InheritName & "\")
@@ -2045,7 +1749,7 @@ OnLoaded:
ResultArray.Add(Key & GetUuid(), BasicArray(i))
Else
Logger.Info($"发现重复的支持库:{BasicArray(i)} ({BasicArrayVersion}) 与 {ResultArray(Key)} ({ResultArrayVersion}),已忽略其中之一")
- If CompareVersionGE(BasicArrayVersion, ResultArrayVersion) Then
+ If McUtils.CompareVersionGE(BasicArrayVersion, ResultArrayVersion) Then
ResultArray(Key) = BasicArray(i)
End If
End If
@@ -2415,82 +2119,6 @@ OnLoaded:
End Try
End Sub
- '''
- ''' 比较两个版本名;等同 Left >= Right。
- ''' 无法比较两个预发布版的大小。
- ''' 支持的格式:未知版本, 1.13.2, 1.7.10-pre4, 1.8_pre, 1.14 Pre-Release 2, 1.14.4 C6
- '''
- Public Function CompareVersionGE(Left As String, Right As String) As Boolean
- Return CompareVersion(Left, Right) >= 0
- End Function
- '''
- ''' 比较两个版本名,若 Left 较新则返回 1,相同则返回 0,Right 较新则返回 -1;等同 Left - Right。
- ''' 无法比较两个预发布版的大小。
- ''' 支持的格式:未知版本, 26.1-snapshot-1,1.13.2, 1.7.10-pre4, 1.8_pre, 1.14 Pre-Release 2, 1.14.4 C6
- '''
- Public Function CompareVersion(Left As String, Right As String) As Integer
- If Left = "未知版本" OrElse Right = "未知版本" Then
- If Left = "未知版本" AndAlso Right <> "未知版本" Then Return 1
- If Left = "未知版本" AndAlso Right = "未知版本" Then Return 0
- If Left <> "未知版本" AndAlso Right = "未知版本" Then Return -1
- End If
- Left = Left.Lower
- Right = Right.Lower
- Dim Lefts = Left.Replace("快照", "snapshot").Replace("预览版", "pre").RegexSearch("[a-z]+|[0-9]+").ToList
- Dim Rights = Right.Replace("快照", "snapshot").Replace("预览版", "pre").RegexSearch("[a-z]+|[0-9]+").ToList
- Dim i As Integer = 0
- While True
- '两边均缺失,感觉是一个东西
- If Lefts.Count - 1 < i AndAlso Rights.Count - 1 < i Then
- If Left > Right Then Return 1
- If Left < Right Then Return -1
- Return 0
- End If
- '确定两边的数值
- Dim LeftValue As String = If(Lefts.Count - 1 < i, 0, Lefts(i))
- Dim RightValue As String = If(Rights.Count - 1 < i, 0, Rights(i))
- If LeftValue = RightValue Then GoTo NextEntry
- If LeftValue = "rc" Then LeftValue = -1
- If LeftValue = "pre" Then LeftValue = -2
- If LeftValue = "snapshot" Then LeftValue = -3
- If LeftValue = "experimental" Then LeftValue = -4
- Dim LeftValValue = Val(LeftValue)
- If RightValue = "rc" Then RightValue = -1
- If RightValue = "pre" Then RightValue = -2
- If RightValue = "snapshot" Then RightValue = -3
- If RightValue = "experimental" Then RightValue = -4
- Dim RightValValue = Val(RightValue)
- If LeftValValue = 0 AndAlso RightValValue = 0 Then
- '如果没有数值则直接比较字符串
- If LeftValue > RightValue Then
- Return 1
- ElseIf LeftValue < RightValue Then
- Return -1
- End If
- Else
- '如果有数值则比较数值
- '这会使得一边是数字一边是字母时数字方更大
- If LeftValValue > RightValValue Then
- Return 1
- ElseIf LeftValValue < RightValValue Then
- Return -1
- End If
- End If
-NextEntry:
- i += 1
- End While
- Return 0
- End Function
- '''
- ''' 比较两个版本名的排序器。
- '''
- Public Class VersionComparer
- Implements IComparer(Of String)
- Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
- Return CompareVersion(x, y)
- End Function
- End Class
-
'''
''' 打码字符串中的 AccessToken。
'''
@@ -2514,14 +2142,10 @@ NextEntry:
'''
Public Function FilterUserName(Raw As String, FilterChar As Char) As String
If Raw.Contains(":\Users\") Then
- For Each Token In Raw.RegexSearch("(?<=:\\Users\\)[^\\]+")
- Raw = Raw.Replace("\Users\" & Token, "\Users\" & New String(FilterChar, Token.Count))
- Next
+ Raw = RegularExpressions.Regex.Replace(Raw, "(?<=:\\Users\\)[^\\]+", Function(Token) New String(FilterChar, Token.Length))
End If
If Raw.Contains(":/Users/") Then
- For Each Token In Raw.RegexSearch("(?<=:/Users/)[^/]+")
- Raw = Raw.Replace("/Users/" & Token, "/Users/" & New String(FilterChar, Token.Count))
- Next
+ Raw = RegularExpressions.Regex.Replace(Raw, "(?<=:/Users/)[^/]+", Function(Token) New String(FilterChar, Token.Length))
End If
Return Raw
End Function
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb
index 5b86369..eb55c72 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb
@@ -74,7 +74,7 @@ Public Module ModModpack
Catch ex As Exception
If ex.GetDisplay(True).Contains("Error.WinIOError") Then
Throw New Exception("打开整合包文件失败", ex)
- ElseIf File.EndsWithF(".rar", True) Then
+ ElseIf PathUtils.GetExtension(File) = "rar" Then
Throw New Exception("PCL 无法处理 rar 格式的压缩包,请在解压后重新压缩为 zip 格式再试", ex)
Else
Throw New Exception("打开整合包文件失败,文件可能损坏或为不支持的压缩包格式", ex)
@@ -119,8 +119,8 @@ Public Module ModModpack
''' 对路径末尾是否为 \ 没有要求。
'''
Private Sub CopyOverrideDirectory(OverridesFolder As String, VersionFolder As String, Loader As LoaderBase)
- If Not OverridesFolder.EndsWithF("\") Then OverridesFolder += "\"
- If Not VersionFolder.EndsWithF("\") Then VersionFolder += "\"
+ OverridesFolder = PathUtils.AddSlashSuffix(OverridesFolder)
+ VersionFolder = PathUtils.AddSlashSuffix(VersionFolder)
'复制文件
If DirectoryUtils.Exists(OverridesFolder) Then
Logger.Info($"处理整合包覆写文件夹:{OverridesFolder} → {VersionFolder}")
@@ -174,25 +174,25 @@ Public Module ModModpack
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
End If
+ Dim VersionFolder As String = PathUtils.AddSlashSuffix(Path.Combine(McFolderSelected, "versions", InstanceName) & "\")
'获取 Mod API 版本信息
- Dim TargetVersion As New McVersion
- TargetVersion.VanillaName = Json("minecraft")("version").ToString
+ Dim TargetVersion As New McVersion(Json("minecraft")("version").ToString)
For Each Entry In If(Json("minecraft")("modLoaders"), {})
Dim Id As String = If(Entry("id"), "").ToString.Lower
If Id.StartsWithF("forge-") Then
'Forge 指定
If Id.Contains("recommended") Then Throw New Exception("该整合包版本过老,已不支持进行安装!")
Logger.Info($"整合包 Forge 版本:{Id}")
- TargetVersion.Forge = Id.Replace("forge-", "")
+ TargetVersion.ModLoaderVersions(ModLoaders.Forge) = Id.Replace("forge-", "")
ElseIf Id.StartsWithF("neoforge-") Then
'NeoForge 指定
Logger.Info($"整合包 NeoForge 版本:{Id}")
- TargetVersion.NeoForge = Id.Replace("neoforge-", "")
+ TargetVersion.ModLoaderVersions(ModLoaders.NeoForge) = Id.Replace("neoforge-", "")
ElseIf Id.StartsWithF("fabric-") Then
'Fabric 指定
Logger.Info($"整合包 Fabric 版本:{Id}")
- TargetVersion.Fabric = Id.Replace("fabric-", "")
+ TargetVersion.ModLoaderVersions(ModLoaders.Fabric) = Id.Replace("fabric-", "")
Else
NotifyIncompatibleLoader(Id)
End If
@@ -202,12 +202,12 @@ Public Module ModModpack
Dim InstallLoaders As New List(Of LoaderBase)
Dim OverrideHome As String = If(Json("overrides"), "")
If OverrideHome <> "" Then
+ Dim OverridesFolder As String = InstallTemp & ArchiveBaseFolder & If(OverrideHome = "." OrElse OverrideHome = "./", "", OverrideHome) '#5613
+ If Not PathUtils.IsParentOf(InstallTemp, OverridesFolder) Then Throw New Exception("整合包的 overrides 路径超出了解压目录,请向整合包作者反馈此问题!")
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
- CopyOverrideDirectory(
- InstallTemp & ArchiveBaseFolder & If(OverrideHome = "." OrElse OverrideHome = "./", "", OverrideHome), '#5613
- $"{McFolderSelected}versions\{InstanceName}", Task)
+ CopyOverrideDirectory(OverridesFolder, VersionFolder, Task)
End Sub) With {
.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
End If
@@ -293,7 +293,7 @@ Public Module ModModpack
Dim File = ResourceVersion.FromPlatformJson(ModJson, Type)
If Not File.DownloadAvailable Then Continue For
'实际的添加
- FileList.Add(Id, File.ToNetFile($"{McFolderSelected}versions\{InstanceName}\{TargetFolder}\",
+ FileList.Add(Id, File.ToNetFile(PathUtils.AddSlashSuffix(Path.Combine(VersionFolder, TargetFolder)),
ResourceVersion.DownloadReason.ModPack, TargetVersion.VanillaName, TargetVersion.ModLoaders))
Task.Progress += 1 / (1 + ModList.Count)
Next
@@ -307,15 +307,9 @@ Public Module ModModpack
End If
'构造加载器
- Dim Request As New McInstallRequest With {
- .NewInstanceName = InstanceName,
- .VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
- .MinecraftName = TargetVersion.VanillaName,
- .ForgeVersion = TargetVersion.Forge,
- .NeoForgeVersion = TargetVersion.NeoForge,
- .FabricVersion = TargetVersion.Fabric
- }
- Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
+ Dim Target As New McComponents(TargetVersion.VanillaName, TargetVersion.ModLoaderVersions)
+ Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
+ .NewInstanceName = InstanceName, .InstanceFolder = VersionFolder, .Components = Target})
'构造总加载器
Dim Loaders As New List(Of LoaderBase)
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
@@ -323,7 +317,6 @@ Public Module ModModpack
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
Sub(Task As LoaderTask(Of String, String))
'设置图标
- Dim VersionFolder As String = $"{McFolderSelected}versions\{InstanceName}\"
If Logo IsNot Nothing AndAlso FileUtils.Exists(Logo) Then
FileUtils.Copy(Logo, VersionFolder & "PCL\Logo.png")
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
@@ -337,10 +330,10 @@ Public Module ModModpack
FileUtils.Delete(MapFile)
Next
'删除原始整合包文件
- For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
- If FileUtils.Exists(Target) Then
- Logger.Info($"删除原始整合包文件:{Target}")
- FileUtils.Delete(Target)
+ For Each FileToDelete As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
+ If FileUtils.Exists(FileToDelete) Then
+ Logger.Info($"删除原始整合包文件:{FileToDelete}")
+ FileUtils.Delete(FileToDelete)
End If
Next
If FileUtils.Exists(FileAddress) AndAlso PathUtils.GetFileNameWithoutExtension(FileAddress) = "modpack" Then
@@ -358,7 +351,7 @@ Public Module ModModpack
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
- Loader.Start(Request.VersionFolder)
+ Loader.Start(VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
Return Loader
@@ -376,20 +369,21 @@ Public Module ModModpack
End Try
If Json("dependencies") Is Nothing OrElse Json("dependencies")("minecraft") Is Nothing Then Throw New Exception("Modrinth 整合包未提供 Minecraft 版本信息")
'获取 Mod API 版本信息
- Dim TargetVersion As New McVersion
+ 'TODO: 改为使用类似 InstallPackMMC 中,一个版本名一个字典的方式来存储它,不要用 Unknown
+ Dim TargetVersion As New McVersion("Unknown")
For Each Entry As JProperty In If(Json("dependencies"), {})
Select Case Entry.Name.Lower
Case "minecraft"
TargetVersion.VanillaName = Entry.Value.ToString
Case "forge" 'eg. 14.23.5.2859 / 1.19-41.1.0
- TargetVersion.Forge = Entry.Value.ToString
- Logger.Info($"整合包 Forge 版本:{TargetVersion.Forge}")
+ TargetVersion.ModLoaderVersions(ModLoaders.Forge) = Entry.Value.ToString
+ Logger.Info($"整合包 Forge 版本:{TargetVersion.ModLoaderVersions(ModLoaders.Forge)}")
Case "neoforge", "neo-forge" 'eg. 20.6.98-beta
- TargetVersion.NeoForge = Entry.Value.ToString
- Logger.Info($"整合包 NeoForge 版本:{TargetVersion.NeoForge}")
+ TargetVersion.ModLoaderVersions(ModLoaders.NeoForge) = Entry.Value.ToString
+ Logger.Info($"整合包 NeoForge 版本:{TargetVersion.ModLoaderVersions(ModLoaders.NeoForge)}")
Case "fabric-loader" 'eg. 0.14.14
- TargetVersion.Fabric = Entry.Value.ToString
- Logger.Info($"整合包 Fabric 版本:{TargetVersion.Fabric}")
+ TargetVersion.ModLoaderVersions(ModLoaders.Fabric) = Entry.Value.ToString
+ Logger.Info($"整合包 Fabric 版本:{TargetVersion.ModLoaderVersions(ModLoaders.Fabric)}")
Case Else
NotifyIncompatibleLoader(Entry.Name)
End Select
@@ -402,18 +396,15 @@ Public Module ModModpack
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
End If
+ Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
'解压
Dim InstallTemp As String = RequestTaskTempFolder()
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.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.5))
- CopyOverrideDirectory(
- InstallTemp & ArchiveBaseFolder & "overrides",
- McFolderSelected & "versions\" & InstanceName, Task)
- CopyOverrideDirectory(
- InstallTemp & ArchiveBaseFolder & "client-overrides",
- McFolderSelected & "versions\" & InstanceName, Task)
+ CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "overrides", VersionFolder, Task)
+ CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "client-overrides", VersionFolder, Task)
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
'获取下载文件列表
Dim FileList As New List(Of NetFile)
@@ -436,8 +427,8 @@ Public Module ModModpack
Urls = ResourceVersion.ParseModrinthTrackArguments(Urls,
ResourceVersion.DownloadReason.ModPack, TargetVersion.VanillaName, TargetVersion.ModLoaders).ToList 'Modrinth 来源追踪信息
Urls = Urls.Distinct.ToList()
- Dim TargetPath As String = Path.Combine(McFolderSelected, "versions", InstanceName, File("path").ToString().TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
- If Not PathUtils.IsParentOf($"{McFolderSelected}versions\{InstanceName}\", TargetPath) Then
+ Dim TargetPath As String = Path.Combine(VersionFolder, File("path").ToString().TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
+ If Not PathUtils.IsParentOf(VersionFolder, TargetPath) Then
MyMsgBox($"整合包的文件路径超出了版本文件夹,请向整合包作者反馈此问题!{vbCrLf}目标:{Path.GetFullPath(TargetPath)}{vbCrLf}错误的文件:{TargetPath}", "文件路径校验失败", IsWarn:=True)
Throw New OperationCanceledException
End If
@@ -449,15 +440,10 @@ Public Module ModModpack
End If
'构造加载器
- Dim Request As New McInstallRequest With {
- .NewInstanceName = InstanceName,
- .VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
- .MinecraftName = TargetVersion.VanillaName,
- .ForgeVersion = TargetVersion.Forge,
- .NeoForgeVersion = TargetVersion.NeoForge,
- .FabricVersion = TargetVersion.Fabric
- }
- Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
+ Dim Target As New McComponents(TargetVersion.VanillaName, TargetVersion.ModLoaderVersions)
+ Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
+ .NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
+ .Components = Target})
'构造总加载器
Dim Loaders As New List(Of LoaderBase)
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
@@ -465,7 +451,6 @@ Public Module ModModpack
Loaders.Add(New LoaderTask(Of String, String)("最终整理文件",
Sub(Task As LoaderTask(Of String, String))
'设置图标
- Dim VersionFolder As String = $"{McFolderSelected}versions\{InstanceName}\"
If Logo IsNot Nothing AndAlso FileUtils.Exists(Logo) Then
FileUtils.Copy(Logo, VersionFolder & "PCL\Logo.png")
WriteIni(VersionFolder & "PCL\Setup.ini", "Logo", "PCL\Logo.png")
@@ -473,10 +458,10 @@ Public Module ModModpack
Logger.Info($"已设置整合包 Logo:{Logo}")
End If
'删除原始整合包文件
- For Each Target As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
- If FileUtils.Exists(Target) Then
- Logger.Info($"删除原始整合包文件:{Target}")
- FileUtils.Delete(Target)
+ For Each FileToDelete As String In {VersionFolder & "原始整合包.zip", VersionFolder & "原始整合包.mrpack"}
+ If FileUtils.Exists(FileToDelete) Then
+ Logger.Info($"删除原始整合包文件:{FileToDelete}")
+ FileUtils.Delete(FileToDelete)
End If
Next
If FileUtils.Exists(FileAddress) AndAlso PathUtils.GetFileNameWithoutExtension(FileAddress) = "modpack" Then
@@ -494,7 +479,7 @@ Public Module ModModpack
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
- Loader.Start(Request.VersionFolder)
+ Loader.Start(VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
Return Loader
@@ -515,24 +500,21 @@ Public Module ModModpack
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
+ Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
'解压
Dim InstallTemp As String = RequestTaskTempFolder()
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.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
- CopyOverrideDirectory(
- InstallTemp & ArchiveBaseFolder & "minecraft",
- McFolderSelected & "versions\" & InstanceName, Task)
+ CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "minecraft", VersionFolder, Task)
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
'构造游戏本体安装加载器
If Json("gameVersion") Is Nothing Then Throw New Exception("该 HMCL 整合包未提供游戏版本信息,无法安装!")
- Dim Request As New McInstallRequest With {
- .NewInstanceName = InstanceName,
- .VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
- .MinecraftName = Json("gameVersion").ToString
- }
- Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
+ Dim Target As New McComponents(Json("gameVersion").ToString, New Dictionary(Of ModLoaders, String))
+ Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
+ .NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
+ .Components = Target})
'构造总加载器
Dim Loaders As New List(Of LoaderBase) From {
New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)},
@@ -546,7 +528,7 @@ Public Module ModModpack
End If
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
- Loader.Start(Request.VersionFolder)
+ Loader.Start(VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
Return Loader
@@ -568,16 +550,22 @@ Public Module ModModpack
If Validate.Validate(InstanceName) <> "" Then InstanceName = ""
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
+ Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
'解压
Dim InstallTemp As String = RequestTaskTempFolder()
- Dim SetupFile As String = $"{McFolderSelected}versions\{InstanceName}\PCL\Setup.ini"
+ Dim SetupFile As String = VersionFolder & "PCL\Setup.ini"
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.55))
- CopyOverrideDirectory(
- InstallTemp & ArchiveBaseFolder & ".minecraft",
- McFolderSelected & "versions\" & InstanceName, Task)
+ 'Prism 优先使用 minecraft/ 而非 .minecraft/(#9272)
+ Dim MmcGameRoot As String
+ If DirectoryUtils.Exists(InstallTemp & ArchiveBaseFolder & ".minecraft") AndAlso Not DirectoryUtils.Exists(InstallTemp & ArchiveBaseFolder & "minecraft") Then
+ MmcGameRoot = InstallTemp & ArchiveBaseFolder & ".minecraft"
+ Else
+ MmcGameRoot = InstallTemp & ArchiveBaseFolder & "minecraft"
+ End If
+ CopyOverrideDirectory(MmcGameRoot, VersionFolder, Task)
'读取 MMC 设置文件(#2655)
Try
Dim MmcSetupFile As String = InstallTemp & ArchiveBaseFolder & "instance.cfg"
@@ -611,7 +599,7 @@ Public Module ModModpack
If Logo <> "" AndAlso FileUtils.Exists($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png") Then
WriteIni(SetupFile, "LogoCustom", True)
WriteIni(SetupFile, "Logo", "PCL\Logo.png")
- FileUtils.Copy($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png", $"{McFolderSelected}versions\{InstanceName}\PCL\Logo.png")
+ FileUtils.Copy($"{InstallTemp}{ArchiveBaseFolder}{Logo}.png", VersionFolder & "PCL\Logo.png")
Logger.Info($"迁移 MultiMC 版本独立设置:版本图标({Logo}.png)")
End If
'JVM 参数
@@ -633,19 +621,20 @@ Public Module ModModpack
End Sub) With {.ProgressWeight = FileUtils.GetInfo(FileAddress).Length / 1024 / 1024 / 6, .Block = False}) '每 6M 需要 1s
'构造版本安装请求
If PackJson("components") Is Nothing Then Throw New Exception("该 MMC 整合包未提供游戏版本信息,无法安装!")
- Dim Request As New McInstallRequest With {.NewInstanceName = InstanceName, .VersionFolder = $"{McFolderSelected}versions\{InstanceName}\"}
+ Dim MinecraftVersion As String = Nothing
+ Dim ModLoaderVersions As New Dictionary(Of ModLoaders, String)
For Each Component As JObject In PackJson("components")
If Not Component.ContainsKey("uid") Then Continue For
Dim UID As String = Component("uid").ToString
Select Case UID
Case "net.minecraft"
- Request.MinecraftName = Component("version")
+ MinecraftVersion = Component("version")
Case "net.minecraftforge"
- Request.ForgeVersion = Component("version")
+ ModLoaderVersions(ModLoaders.Forge) = Component("version")
Case "net.neoforged"
- Request.NeoForgeVersion = Component("version")
+ ModLoaderVersions(ModLoaders.NeoForge) = Component("version")
Case "net.fabricmc.fabric-loader"
- Request.FabricVersion = Component("version")
+ ModLoaderVersions(ModLoaders.Fabric) = Component("version")
Case Else
If UID.StartsWithF("org.lwjgl") Then '#8210
Logger.Info($"已跳过 LWJGL 项:{UID}")
@@ -655,7 +644,10 @@ Public Module ModModpack
End Select
Next
'构造加载器
- Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
+ Dim Target As New McComponents(MinecraftVersion, ModLoaderVersions)
+ Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
+ .NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
+ .Components = Target})
'构造总加载器
Dim Loaders As New List(Of LoaderBase)
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
@@ -670,7 +662,7 @@ Public Module ModModpack
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
- Loader.Start(Request.VersionFolder)
+ Loader.Start(VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
Return Loader
@@ -695,16 +687,15 @@ Public Module ModModpack
If InstanceName = "" Then InstanceName = MyMsgBoxInput("输入版本名称", "", "", New Collection(Of Validate) From {Validate})
If String.IsNullOrEmpty(InstanceName) Then Throw New OperationCanceledException
End If
+ Dim VersionFolder As String = Path.Combine(McFolderSelected, "versions", InstanceName) & "\"
'解压
Dim InstallTemp As String = RequestTaskTempFolder()
- Dim SetupFile As String = $"{McFolderSelected}versions\{InstanceName}\PCL\Setup.ini"
+ Dim SetupFile As String = VersionFolder & "PCL\Setup.ini"
Dim InstallLoaders As New List(Of LoaderBase)
InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件",
Sub(Task As LoaderTask(Of String, Integer))
ExtractModpackFiles(InstallTemp, FileAddress, Task.CreateCancellationToken(), Task.CreateSyncProgressProvider(ToPercentage:=0.6))
- CopyOverrideDirectory(
- InstallTemp & ArchiveBaseFolder & "overrides",
- McFolderSelected & "versions\" & InstanceName, Task)
+ CopyOverrideDirectory(InstallTemp & ArchiveBaseFolder & "overrides", VersionFolder, Task)
'JVM 参数
If Json("launchInfo") IsNot Nothing Then
Dim LaunchInfo As JObject = Json("launchInfo")
@@ -723,16 +714,26 @@ Public Module ModModpack
Hint("PCL 不支持安装 Quilt 整合包!", HintType.Red)
Throw New OperationCanceledException
End If
- Dim Request As New McInstallRequest With {
- .NewInstanceName = InstanceName,
- .VersionFolder = $"{McFolderSelected}versions\{InstanceName}\",
- .MinecraftName = Addons("game"),
- .OptiFineVersion = If(Addons.ContainsKey("optifine"), Addons("optifine"), Nothing),
- .ForgeVersion = If(Addons.ContainsKey("forge"), Addons("forge"), Nothing),
- .NeoForgeVersion = If(Addons.ContainsKey("neoforge"), Addons("neoforge"), Nothing),
- .FabricVersion = If(Addons.ContainsKey("fabric"), Addons("fabric"), Nothing)
- }
- Dim MergeLoaders As List(Of LoaderBase) = McInstallLoader(Request)
+ Dim ModLoaderVersions As New Dictionary(Of ModLoaders, String)
+ If Addons.ContainsKey("forge") Then ModLoaderVersions(ModLoaders.Forge) = Addons("forge")
+ If Addons.ContainsKey("neoforge") Then ModLoaderVersions(ModLoaders.NeoForge) = Addons("neoforge")
+ If Addons.ContainsKey("fabric") Then ModLoaderVersions(ModLoaders.Fabric) = Addons("fabric")
+ Dim OptiFineEntry As JObject = Nothing
+ If Addons.ContainsKey("optifine") Then
+ Dim MinecraftVersion = Addons("game")
+ If MinecraftVersion.EndsWithF(".0") Then MinecraftVersion = MinecraftVersion.Substring(0, MinecraftVersion.Length - 2)
+ Dim OptiFineFileSuffix = "_HD_" & Addons("optifine").AfterLast("HD_") & ".jar"
+ '从镜像源拉取 OptiFine 列表
+ If DlOptiFineListBmclapiLoader.State <> LoadState.Finished Then DlOptiFineListBmclapiLoader.WaitForExit()
+ Dim Entry = DlOptiFineListBmclapiLoader.Output.Value.FirstOrDefault(
+ Function(v) v.Inherit = MinecraftVersion AndAlso v.FileName.EndsWithF(OptiFineFileSuffix))
+ If Entry Is Nothing Then Throw New Exception($"OptiFine 列表中没有整合包所需的 OptiFine {Addons("optifine")}(Minecraft {Addons("game")})")
+ OptiFineEntry = JObject.FromObject(Entry)
+ End If
+ Dim Target As New McComponents(Addons("game"), ModLoaderVersions, OptiFineEntry)
+ Dim MergeLoaders = McInstallLoadersGet(New McInstallRequest With {
+ .NewInstanceName = InstanceName, .InstanceFolder = VersionFolder,
+ .Components = Target})
'构造总加载器
Dim Loaders As New List(Of LoaderBase)
Loaders.Add(New LoaderCombo(Of String)("整合包安装", InstallLoaders) With {.Show = False, .Block = False, .ProgressWeight = InstallLoaders.Sum(Function(l) l.ProgressWeight)})
@@ -748,7 +749,7 @@ Public Module ModModpack
'启动
Dim Loader As New LoaderCombo(Of String)(LoaderName, Loaders) With {.OnStateChanged = AddressOf McInstallState}
'If Archive IsNot Nothing Then Archive.Dispose() '解除占用,以免在加载器中触发 “正由另一进程使用,因此该进程无法访问此文件”
- Loader.Start(Request.VersionFolder)
+ Loader.Start(VersionFolder)
LoaderTaskbarAdd(Loader)
FrmMain.BtnExtraDownload.ShowRefresh()
Return Loader
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
index 3bd883c..15d373d 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
@@ -319,6 +319,8 @@ Public Module ModWatcher
GetClassName(hwnd, str, str.Capacity)
Dim ClassName As String = str.ToString
If Not (ClassName = "GLFW30" OrElse ClassName = "SDL_app" OrElse ClassName = "LWJGL" OrElse ClassName = "SunAwtFrame") Then Return
+ 'SDL 会先创建隐藏窗口,待初始化完成后才显示(#9073)
+ If ClassName = "SDL_app" AndAlso Not IsWindowVisible(hwnd) Then Return
'获取窗口标题名
str = New StringBuilder(512)
GetWindowText(hwnd, str, str.Capacity)
@@ -347,6 +349,7 @@ Public Module ModWatcher
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (hWnd As Integer, str As StringBuilder, maxCount As Integer) As Integer
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (hWnd As Integer, str As String) As Boolean
Private Declare Function ShowWindow Lib "user32" (hWnd As IntPtr, cmdWindow As UInteger) As Boolean
+ Private Declare Function IsWindowVisible Lib "user32" (hWnd As IntPtr) As Boolean
Private Declare Function GetWindowThreadProcessId Lib "user32" (hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
'崩溃处理
diff --git a/Plain Craft Launcher 2/Modules/ModEvent.vb b/Plain Craft Launcher 2/Modules/ModEvent.vb
index 5565e72..5db54c4 100644
--- a/Plain Craft Launcher 2/Modules/ModEvent.vb
+++ b/Plain Craft Launcher 2/Modules/ModEvent.vb
@@ -1,6 +1,9 @@
+
#Region "附加属性"
+Imports PCL.FormMain
+
'''
''' 用于在 XAML 中初始化列表对象。
''' 附加属性无法在 XAML 中为每个对象初始化独立的列表对象,因此需要一个包装类,然后在 XAML 中显式初始化。
@@ -272,9 +275,23 @@ Public Class CustomEvent
Hint(Arg0.Replace("\n", vbCrLf), If(Args.Length = 1, HintType.Blue, EnumUtils.FromString(Of HintType)(Arg1)))
Case EventType.切换页面
- RunInUi(Sub() FrmMain.PageChange(
- EnumUtils.FromString(Of FormMain.PageType)(Arg0),
- If(Args.Length = 1, FormMain.PageSubType.Default, EnumUtils.FromString(Of FormMain.PageSubType)(Arg1))))
+ RunInUi(
+ Sub()
+ Dim TargetPage = EnumUtils.FromString(Of PageType)(Arg0)
+ If TargetPage = PageType.InstanceSetup Then
+ If McInstanceSelected Is Nothing Then
+ Hint("请先选择一个 Minecraft 版本!", HintType.Red)
+ Return
+ End If
+ If McInstanceLock.IsLocked(McInstanceSelected) Then
+ Hint("该版本正在被修改,暂时无法进入版本设置!", HintType.Red)
+ Return
+ End If
+ PageInstanceLeft.Instance = McInstanceSelected
+ End If
+ FrmMain.PageChange(TargetPage,
+ If(Args.Length = 1, PageSubType.Default, EnumUtils.FromString(Of PageSubType)(Arg1)))
+ End Sub)
Case EventType.导入整合包, EventType.安装整合包
RunInUi(Sub() ModpackInstall())
@@ -295,7 +312,7 @@ Public Class CustomEvent
Case 2
PageOtherTest.StartCustomDownload(Arg0, Arg1)
Case Else
- PageOtherTest.StartCustomDownload(Arg0, Arg(1), Args(2))
+ PageOtherTest.StartCustomDownload(Arg0, Args(1), Args(2))
End Select
Catch
PageOtherTest.StartCustomDownload(Arg0, "未知")
@@ -304,16 +321,16 @@ Public Class CustomEvent
Case EventType.修改设置, EventType.写入设置
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 UiLauncherTransparent|400")
- Settings.SetSafe(Arg0, Arg1, Instance:=McInstanceSelected)
- If Args.Length = 2 Then Hint($"已写入设置:{Arg0} → {Arg1}", HintType.Green)
+ Settings.SetSafe(Arg0, Args(1), Instance:=McInstanceSelected)
+ If Args.Length = 2 Then Hint($"已写入设置:{Arg0} → {Args(1)}", HintType.Green)
Case EventType.修改变量, EventType.写入变量
If Args.Length = 1 Then Throw New Exception($"EventType {Type} 需要至少 2 个以 | 分割的参数,例如 VariableName|SomeValue")
Try
- RegistryUtils.Write($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{Arg0}", Arg1)
- If Args.Length = 2 Then Hint($"已写入变量:{Arg0} → {Arg1}", HintType.Green)
+ RegistryUtils.Write($"HKEY_CURRENT_USER\Software\{RegFolder}", $"CustomEvent{Arg0}", Args(1))
+ If Args.Length = 2 Then Hint($"已写入变量:{Arg0} → {Args(1)}", HintType.Green)
Catch ex As Exception
- Logger.Warn(ex, $"写入变量失败:{Arg0} → {Arg1}", LogBehavior.Toast)
+ Logger.Warn(ex, $"写入变量失败:{Arg0} → {Args(1)}", LogBehavior.Toast)
End Try
Case EventType.加入房间
@@ -353,7 +370,7 @@ Public Class CustomEvent
Dim RawFileName As String
Try
RawFileName = PathUtils.GetLastPart(RelativeUrl)
- If Not RawFileName.EndsWithF(".json", True) Then Throw New Exception("未指向 .json 后缀的文件")
+ If Not PathUtils.GetExtension(RawFileName) = "json" Then Throw New Exception("未指向 .json 后缀的文件")
Catch ex As Exception
Throw New Exception("联网帮助页面须指向一个帮助 JSON 文件,并在同路径下包含相应 XAML 文件!" & vbCrLf &
"例如:" & vbCrLf &
diff --git a/Plain Craft Launcher 2/Modules/ModMain.vb b/Plain Craft Launcher 2/Modules/ModMain.vb
index ff4b31a..529ac16 100644
--- a/Plain Craft Launcher 2/Modules/ModMain.vb
+++ b/Plain Craft Launcher 2/Modules/ModMain.vb
@@ -414,6 +414,7 @@ EndHint:
Public FrmInstanceModDisabled As PageInstanceModDisabled
Public FrmInstanceSetup As PageInstanceSetup
Public FrmInstanceExport As PageInstanceExport
+ Public FrmDownloadModify As PageDownloadModify
'资源信息分页声明
Public FrmDownloadResourceDetail As PageDownloadResourceDetail
@@ -510,7 +511,7 @@ EndHint:
EventData = If(JsonData("EventData"), "")
IsEvent = True
Else
- Dim XamlAddress As String = FilePath.Lower.Replace(".json", ".xaml")
+ Dim XamlAddress As String = Path.ChangeExtension(FilePath, ".xaml")
If FileUtils.Exists(XamlAddress) Then
XamlContent = FileUtils.ReadAsString(XamlAddress)
IsEvent = False
@@ -596,9 +597,9 @@ EndHint:
'读取自带文件
For Each File In DirectoryUtils.EnumerateFiles(PathTemp & "Help", True)
'跳过非 json 文件与以 . 开头的文件夹
- If PathUtils.RemoveLastPart(File).Replace(PathTemp & "Help", "").Contains("\.") OrElse PathUtils.GetExtension(File) <> "json" Then Continue For
+ If PathUtils.RemoveLastPart(File).Substring((PathTemp & "Help").Length).Contains("\.") OrElse PathUtils.GetExtension(File) <> "json" Then Continue For
'检查忽略列表
- Dim RealPath As String = File.Replace(PathTemp & "Help\", "")
+ Dim RealPath As String = File.Substring((PathTemp & "Help\").Length)
For Each Ignore In IgnoreList
If RealPath.RegexCheck(Ignore) Then
Logger.Trace($"已忽略 {RealPath}:{Ignore}")
@@ -857,10 +858,10 @@ 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", "")))
+ Text = Text.Replace("{forge}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Forge), McInstanceSelected.Version.ModLoaderVersions(ModLoaders.Forge), "")))
+ Text = Text.Replace("{fabric}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.Fabric), McInstanceSelected.Version.ModLoaderVersions(ModLoaders.Fabric), "")))
+ Text = Text.Replace("{neoforge}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.NeoForge), McInstanceSelected.Version.ModLoaderVersions(ModLoaders.NeoForge), "")))
+ Text = Text.Replace("{liteloader}", Replacer(If(McInstanceSelected.Version.ModLoaders.HasFlagF(ModLoaders.LiteLoader), "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))
diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb
index 871970d..a3d54c9 100644
--- a/Plain Craft Launcher 2/Modules/ModMusic.vb
+++ b/Plain Craft Launcher 2/Modules/ModMusic.vb
@@ -320,7 +320,7 @@ Public Module ModMusic
Hint("由于音频设备变更,音乐播放功能在重启 PCL 后才能恢复!", HintType.Red)
Thread.Sleep(1000000000)
End If
- If Not (MusicCurrent.EndsWithF(".wav", True) OrElse MusicCurrent.EndsWithF(".mp3", True) OrElse MusicCurrent.EndsWithF(".flac", True)) OrElse
+ If Not ({"wav", "mp3", "flac"}.Contains(PathUtils.GetExtension(MusicCurrent))) OrElse
ex.Message.Contains("0xC00D36C4") Then '#5096:不支持给定的 URL 的字节流类型。 (异常来自 HRESULT:0xC00D36C4)
Hint("播放音乐失败(" & PathUtils.GetLastPart(MusicCurrent) & "):PCL 可能不支持此音乐格式,请将格式转换为 .wav、.mp3 或 .flac 后再试", HintType.Red)
Else
diff --git a/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb b/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb
index 2d22d88..b48bead 100644
--- a/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/LocalResourceFile.vb
@@ -25,7 +25,7 @@ Public Class LocalResourceFile
End Get
End Property
'''
- ''' 假若该资源未被禁用时,文件的文件名。
+ ''' 假若该资源未被禁用时,文件的文件名。包含 .jar/.litemod 等后缀。
'''
Public ReadOnly Property EnabledName As String
Get
@@ -57,7 +57,7 @@ Public Class LocalResourceFile
Public Property Display As String
Get
If _Display Is Nothing Then _Display = ProjectVersion?.Display
- If _Display Is Nothing Then _Display = PathUtils.GetFileNameWithoutExtension(File.FullName)
+ If _Display Is Nothing Then _Display = PathUtils.GetFileNameWithoutExtension(EnabledName)
Return _Display
End Get
Set(value As String)
@@ -238,7 +238,7 @@ Public Class LocalResourceFile
Private _CurseForgeHash As UInteger?
'''
- ''' 获取用于 Modrinth 信息获取的 Hash 值(SHA1)。
+ ''' 获取用于 Modrinth 信息获取的 Hash 值(SHA1)。固定为小写。
'''
Public ReadOnly Property ModrinthHash As String
Get
@@ -269,7 +269,7 @@ Public Class LocalResourceFile
End Function
Public Overrides Function Equals(obj As Object) As Boolean
Dim Target = TryCast(obj, LocalResourceFile)
- Return Target IsNot Nothing AndAlso File.FullName = Target.File.FullName
+ Return Target IsNot Nothing AndAlso PathUtils.IsSame(File.FullName, Target.File.FullName)
End Function
#End Region
diff --git a/Plain Craft Launcher 2/Modules/Resource/LocalResourceLoaders.vb b/Plain Craft Launcher 2/Modules/Resource/LocalResourceLoaders.vb
index 4bed629..a36c715 100644
--- a/Plain Craft Launcher 2/Modules/Resource/LocalResourceLoaders.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/LocalResourceLoaders.vb
@@ -24,11 +24,10 @@ Public Module LocalResourceLoaders
'获取 Mod 文件夹下的可用文件列表
Dim ModFileList As New List(Of String)
If DirectoryUtils.Exists(Loader.Input) Then
- Dim RawName As String = Loader.Input.Lower
For Each File In DirectoryUtils.EnumerateFiles(Loader.Input, True)
- If File.BeforeLast("\").Lower & "\" <> RawName Then
+ If Not PathUtils.IsSame(PathUtils.RemoveLastPart(File), Loader.Input) Then
'仅当 Forge 1.13- 且文件夹名与版本号相同时,才加载该子文件夹下的 Mod
- If Not (PageInstanceLeft.Instance IsNot Nothing AndAlso PageInstanceLeft.Instance.Version.HasForge AndAlso
+ If Not (PageInstanceLeft.Instance IsNot Nothing AndAlso PageInstanceLeft.Instance.Version.ModLoaders.HasFlagF(ModLoaders.Forge) AndAlso
PageInstanceLeft.Instance.Version.Vanilla.Major < 13 AndAlso
PathUtils.GetLastPart(PathUtils.RemoveLastPart(File)) = $"1.{PageInstanceLeft.Instance.Version.Vanilla.Major}.{PageInstanceLeft.Instance.Version.Vanilla.Build}") Then
Continue For
@@ -36,12 +35,9 @@ Public Module LocalResourceLoaders
End If
Static IsModFile As Func(Of String, Boolean) =
Function(FullName As String)
- If FullName Is Nothing OrElse Not FullName.Contains(".") Then Return False
- FullName = FullName.Lower
- If FullName.EndsWithF(".jar", True) OrElse FullName.EndsWithF(".zip", True) OrElse FullName.EndsWithF(".litemod", True) OrElse
- FullName.EndsWithF(".jar.disabled", True) OrElse FullName.EndsWithF(".zip.disabled", True) OrElse FullName.EndsWithF(".litemod.disabled", True) OrElse
- FullName.EndsWithF(".jar.old", True) OrElse FullName.EndsWithF(".zip.old", True) OrElse FullName.EndsWithF(".litemod.old", True) Then Return True
- Return False
+ If FullName Is Nothing Then Return False
+ If {"disabled", "old"}.Contains(PathUtils.GetExtension(FullName)) Then FullName = PathUtils.GetFileNameWithoutExtension(FullName)
+ Return {"jar", "zip", "litemod"}.Contains(PathUtils.GetExtension(FullName))
End Function
If IsModFile(File) Then ModFileList.Add(File)
Next
@@ -271,7 +267,7 @@ Public Module LocalResourceLoaders
Dim EntryVersion As String = Entry("gameVersion")
Return EntryVersion IsNot Nothing AndAlso EntryVersion = VanillaVersion
End Function).
- MaxByAll(Function(Entry) Entry("gameVersion").ToString, New VersionComparer) '只保留最新的 MC 版本
+ MaxByAll(Function(Entry) Entry("gameVersion").ToString, Comparer(Of String).Create(Function(x, y) McUtils.CompareVersion(x, y))) '只保留最新的 MC 版本
For Each Entry In LatestFiles
Dim FileId = Entry("fileId").ToObject(Of Integer)
If Not UpdateFileIds.ContainsKey(FileId) Then UpdateFileIds(FileId) = New List(Of LocalResourceFile)
diff --git a/Plain Craft Launcher 2/Modules/Resource/ResourceProject.vb b/Plain Craft Launcher 2/Modules/Resource/ResourceProject.vb
index 53e70d9..b2deefb 100644
--- a/Plain Craft Launcher 2/Modules/Resource/ResourceProject.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/ResourceProject.vb
@@ -184,11 +184,11 @@ Public Class ResourceProject
If Not NewFile.DownloadAvailable Then Continue For
ModLoaders = ModLoaders Or NewFile.ModLoaders
Dim GameVersions = File("gameVersions").ToObject(Of List(Of String))
- If Not GameVersions.Any(Function(v) McVersion.IsFormatFit(v)) Then Continue For
+ If Not GameVersions.Any(Function(v) McVersion.IsStandardFormat(v)) Then Continue For
Files.Add(New KeyValuePair(Of Integer, List(Of String))(File("id"), GameVersions))
Next
For Each File In If(Data("latestFilesIndexes"), New JArray) '这俩玩意儿包含的文件不一样,见 #3599
- If Not McVersion.IsFormatFit(File("gameVersion")) Then Continue For
+ If Not McVersion.IsStandardFormat(File("gameVersion")) Then Continue For
Files.Add(New KeyValuePair(Of Integer, List(Of String))(File("fileId"), {File("gameVersion").ToString}.ToList))
Next
CurseForgeFileIds = Files.Select(Function(f) f.Key).Distinct.ToList
diff --git a/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb b/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb
index c7734ca..81d0810 100644
--- a/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/ResourceSearcher.vb
@@ -99,12 +99,12 @@ Public Class ResourceSearcher
Dim Address As String = $"https://api.modrinth.com/v2/search?limit={RESULT_PAGE_SIZE}&index=relevance"
If Not String.IsNullOrEmpty(SearchText) Then Address += "&query=" & StringUtils.UrlEscape(SearchText)
If Storage.ModrinthOffset > 0 Then Address += "&offset=" & Storage.ModrinthOffset
- 'facets=[["categories:'game-mechanics'"],["categories:'forge',categories:'fabric'"],["versions:1.19.3"],["project_type:mod"]]
+ 'facets=[["categories:'game-mechanics'"],["categories:forge","categories:fabric"],["versions:1.19.3"],["project_type:mod"]]
Dim Facets As New List(Of String)
Facets.Add($"[""project_type:{Type.ToString.Lower}""]")
If Not String.IsNullOrEmpty(Tag) Then Facets.Add($"[""categories:'{Tag.AfterLast("/")}'""]")
If ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter Then
- Facets.Add($"[""categories:'{ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join("',categories:'")}'""]")
+ Facets.Add($"[""categories:{ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join(""",""categories:")}""]")
End If
If Not String.IsNullOrEmpty(GameVersion) Then Facets.Add($"[""versions:'{GameVersion}'""]")
Address += "&facets=[" & String.Join(",", Facets) & "]"
@@ -378,21 +378,19 @@ NextPage:
If Request.Type <> ResourceTypes.Any AndAlso Not Project.Types.HasFlagF(Request.Type) Then Continue For
If Not String.IsNullOrEmpty(Request.Tag) AndAlso
Not JsonEntry("categories").Any(Function(c) c.ToString = Request.Tag.AfterLast("/")) Then Continue For 'Project.Tags 已经转换成中文了,只能从 json 判
+ If Request.ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter AndAlso
+ Not Project.ModLoaders.Flags.Intersect(Request.ModLoaders.Flags).Any() Then Continue For
+ If Not String.IsNullOrEmpty(Request.GameVersion) AndAlso
+ Not Project.UnsafeGameVersions.Any(Function(d) d = Request.GameVersion) Then Continue For
ProjectList.Add(Project)
Next
- Dim Facets As New List(Of String)
- If Request.ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter Then
- Facets.Add($"[""categories:'{Request.ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join("'"",""categories:'")}'""]")
- End If
- If Not String.IsNullOrEmpty(Request.GameVersion) Then Facets.Add($"[""versions:'{Request.GameVersion}'""]")
- If ProjectList.Any AndAlso Facets.Any Then
- Facets.Add("[""project_id:" & ProjectList.Select(Function(p) p.Id).Join(""",""project_id:") & """]")
- Dim FilterUrl As String = $"https://api.modrinth.com/v2/search?limit={Math.Min(ProjectList.Count, 100)}&facets=[" & String.Join(",", Facets) & "]"
- Logger.Info($"开始 Modrinth 直接获取筛选:{FilterUrl}")
- Dim MatchedIds As New List(Of String)
- For Each JsonEntry As JObject In DlModRequest(FilterUrl)("hits")
- MatchedIds.Add(JsonEntry("project_id").ToString)
- Next
+ If ProjectList.Any AndAlso Request.ModLoaders <> ModLoaders.None AndAlso Not IgnoreModLoaderFilter AndAlso
+ Not String.IsNullOrEmpty(Request.GameVersion) Then
+ Dim ProjectIds = ProjectList.Select(Function(p) p.Id).Join(""",""project_id:")
+ Dim Loaders = Request.ModLoaders.Flags.Select(Function(f) f.ToString.Lower).Join(""",""categories:")
+ Dim FilterUrl = $"https://api.modrinth.com/v2/search?limit={ProjectList.Count}&facets=" &
+ $"[[""project_id:{ProjectIds}""],[""categories:{Loaders}""],[""versions:{Request.GameVersion}""]]"
+ Dim MatchedIds = DlModRequest(FilterUrl)("hits").Select(Function(h) h("project_id").ToString).ToList
ProjectList.KeepIf(Function(p) MatchedIds.Contains(p.Id))
End If
'更新结果
diff --git a/Plain Craft Launcher 2/Modules/Resource/ResourceVersion.vb b/Plain Craft Launcher 2/Modules/Resource/ResourceVersion.vb
index 857c7e4..2272fc3 100644
--- a/Plain Craft Launcher 2/Modules/Resource/ResourceVersion.vb
+++ b/Plain Craft Launcher 2/Modules/Resource/ResourceVersion.vb
@@ -90,7 +90,7 @@ Public Class ResourceVersion
'''
Public DownloadUrls As List(Of String)
'''
- ''' 对应文件的 SHA1 或 MD5。
+ ''' 对应文件的 SHA1 或 MD5。固定为小写。
'''
Public Hash As String = Nothing
'''
@@ -127,8 +127,9 @@ Public Class ResourceVersion
.DownloadCount = Data("downloadCount")
.FileName = Data("fileName")
.Size = Data("fileLength")
- .Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 1)?("value")
- If .Hash Is Nothing Then .Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 2)?("value")
+ If .Size = 0 Then .Size = -1 'CurseForge 可能错误地返回 0 尺寸(#9104)
+ .Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 1)?("value")?.ToString().Lower()
+ If .Hash Is Nothing Then .Hash = CType(Data("hashes"), JArray).ToList.FirstOrDefault(Function(s) s("algo").ToObject(Of Integer) = 2)?("value")?.ToString().Lower()
'DownloadAddress
Dim Url = Data("downloadUrl").ToString
If Url = "" Then Url = $"https://edge.forgecdn.net/files/{CInt(.Id.ToString.Substring(0, 4))}/{CInt(.Id.ToString.Substring(4))}/{ .FileName}"
@@ -145,13 +146,13 @@ Public Class ResourceVersion
'GameVersions
Dim RawVersions As List(Of String) = Data("gameVersions").Select(Function(t) t.ToString.Trim.Lower).ToList
.GameVersions = RawVersions.
- Where(Function(v) McVersion.IsFormatFit(v)).
+ Where(Function(v) McVersion.IsStandardFormat(v)).
Select(Function(v) v.Replace("-snapshot", " 预览版")).
Distinct.ToList
If .GameVersions.IsSingle Then
.GameVersions = .GameVersions.ToList
ElseIf .GameVersions.Count > 1 Then
- .GameVersions = .GameVersions.SortByComparison(AddressOf CompareVersionGE).ToList
+ .GameVersions = .GameVersions.SortByComparison(AddressOf McUtils.CompareVersionGE).ToList
If .ResourceType = ResourceTypes.ModPack Then .GameVersions = { .GameVersions(0)}.ToList '整合包理应只 “支持” 一个版本
Else
.GameVersions = New List(Of String) From {"未知版本"}
@@ -176,7 +177,7 @@ Public Class ResourceVersion
.FileName = File("filename")
.DownloadUrls = New List(Of String) From {File("url"), DlSourceModGet(File("url"))}.Distinct.ToList '同时添加了镜像源
.Size = File("size")
- .Hash = File("hashes")("sha1")
+ .Hash = File("hashes")("sha1")?.ToString.Lower()
End If
'类别与 Loaders
'结果可能混杂着 Mod、数据包和服务端插件
@@ -208,7 +209,7 @@ Public Class ResourceVersion
If .GameVersions.IsSingle Then
'无需处理
ElseIf .GameVersions.Count > 1 Then
- .GameVersions = .GameVersions.SortByComparison(AddressOf CompareVersionGE).ToList
+ .GameVersions = .GameVersions.SortByComparison(AddressOf McUtils.CompareVersionGE).ToList
If .ResourceType = ResourceTypes.ModPack Then .GameVersions = New List(Of String) From { .GameVersions(0)} '整合包理应只 “支持” 一个版本
ElseIf RawVersions.Any(Function(v) v.RegexCheck("[0-9]{2}w[0-9]{2}[a-z]")) Then
.GameVersions = RawVersions.Where(Function(v) v.RegexCheck("[0-9]{2}w[0-9]{2}[a-z]")).ToList
@@ -355,7 +356,7 @@ Public Class ResourceVersion
.Info =
Iterator Function()
If ModLoaders <> ModLoaders.None Then Yield ModLoaders.Flags.Join("、"c)
- If .Title <> FileName.BeforeLast(".") Then Yield FileName.BeforeLast(".")
+ If .Title <> PathUtils.GetFileNameWithoutExtension(FileName) Then Yield PathUtils.GetFileNameWithoutExtension(FileName)
If Dependencies.Any Then Yield $"{Dependencies.Count} 项前置"
If GameVersions.All(Function(v) Not v.Contains(".") OrElse {"w", "snapshot", "rc", "pre", "experimental", "-"}.Any(Function(s) v.ContainsIgnoreCase(s))) Then Yield $"游戏版本 {GameVersions.Join("、"c)}"
If DownloadCount > 0 Then Yield $"下载 {If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万", DownloadCount.ToString() + " ")}次" 'CurseForge 的下载次数经常错误地返回 0
diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
index c71c896..fb6f794 100644
--- a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
+++ b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
' 方法是按如下所示使用“*”
-
-
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
index 852556f..afab214 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
@@ -4,12 +4,10 @@ Public Module ModDownloadLib
'''
''' 获取下载某个 Minecraft 版本的加载器列表。
- ''' 它必须安装到 McFolderSelected,但是可以自定义版本名(不过自定义的版本名不会修改 Json 中的 id 项)。
'''
- Private Function McDownloadClientLoader(Id As String, Optional JsonUrl As String = Nothing, Optional InstanceName As String = Nothing) As List(Of LoaderBase)
- InstanceName = If(InstanceName, Id)
- Dim VersionFolder As String = McFolderSelected & "versions\" & InstanceName & "\"
-
+ ''' 版本文件输出目录。
+ Private Function McDownloadClientLoader(Id As String, JsonUrl As String, VersionFolder As String) As List(Of LoaderBase)
+ Dim InstanceName = PathUtils.GetLastPart(VersionFolder)
Dim Loaders As New List(Of LoaderBase)
Dim NewInstance As McInstance = Nothing
@@ -54,7 +52,7 @@ Public Module ModDownloadLib
'顺手添加 Json 项目
Try
Dim InstanceJson As JObject = FileUtils.ReadAsJson(VersionFolder & InstanceName & ".json")
- InstanceJson.Add("clientVersion", Id)
+ InstanceJson("clientVersion") = Id
FileUtils.Write($"{VersionFolder}{InstanceName}.json", InstanceJson.ToString)
Catch ex As Exception
Throw New Exception("添加客户端版本失败", ex)
@@ -242,11 +240,11 @@ pause"
New NetFile(DlSourceLauncherOrMetaGet(JsonUrl), VersionFolder & Id & ".json", New FileChecker With {.IsJson = True})
}) With {.ProgressWeight = 2})
'获取支持库文件地址
- Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析核心 JAR 文件下载地址",
+ Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("分析版本 JAR 文件下载地址",
Sub(Task) Task.Output = New List(Of NetFile) From {DlClientJarGet(New McInstance(VersionFolder), False)}
) With {.ProgressWeight = 0.5, .Show = False})
'下载支持库文件
- Loaders.Add(New LoaderDownload("下载核心 JAR 文件", New List(Of NetFile)) With {.ProgressWeight = 5})
+ Loaders.Add(New LoaderDownload("下载版本 JAR 文件", New List(Of NetFile)) With {.ProgressWeight = 5})
'启动
Dim Loader As New LoaderCombo(Of String)("Minecraft " & Id & " 下载", Loaders) With {.OnStateChanged = AddressOf LoaderStateChangedHintOnly}
@@ -326,7 +324,6 @@ pause"
Private Sub McDownloadOptiFineSave(DownloadInfo As DlOptiFineListEntry)
Try
- Dim Id As String = DownloadInfo.InstanceName
Dim Target As String = Dialogs.SaveFile("选择保存位置", DownloadInfo.FileName, filter:={("jar", "OptiFine Jar")})
If Target Is Nothing Then Return
@@ -374,9 +371,9 @@ pause"
'添加 Java Wrapper 作为主 Jar
Dim Arguments As String
If UseJavaWrapper AndAlso Not Settings.Get(Of Boolean)("LaunchAdvanceDisableJLW") Then
- Arguments = $"-Doolloo.jlw.tmpdir=""{PathPure.Value.TrimEnd("\")}"" -Duser.home=""{BaseMcFolderHome.TrimEnd("\")}"" -cp ""{Target}"" -jar ""{LaunchUtils.ExtractPatch("Launch\JavaWrapper.jar", PathPure.Value)}"" optifine.Installer"
+ Arguments = $"-Doolloo.jlw.tmpdir=""{PathUtils.RemoveSlashSuffix(PathPure.Value)}"" -Duser.home=""{PathUtils.RemoveSlashSuffix(BaseMcFolderHome)}"" -cp ""{Target}"" -jar ""{LaunchUtils.ExtractPatch("Launch\JavaWrapper.jar", PathPure.Value)}"" optifine.Installer"
Else
- Arguments = $"-Duser.home=""{BaseMcFolderHome.TrimEnd("\")}"" -cp ""{Target}"" optifine.Installer"
+ Arguments = $"-Duser.home=""{PathUtils.RemoveSlashSuffix(BaseMcFolderHome)}"" -cp ""{Target}"" optifine.Installer"
End If
If Java.Version.Major >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
'开始启动
@@ -473,13 +470,12 @@ pause"
Private Function McDownloadOptiFineLoader(DownloadInfo As DlOptiFineListEntry, McFolder As String, ClientDownloadLoader As LoaderCombo(Of String), ClientFolder As String) As List(Of LoaderBase)
'参数初始化
- Dim IsCustomFolder As Boolean = McFolder <> McFolderSelected
Dim Id As String = DownloadInfo.InstanceName
Dim VersionFolder As String = McFolder & "versions\" & Id & "\"
Dim IsNewerVersion As Boolean = DownloadInfo.Inherit.Contains("w") OrElse McVersion.VersionToDrop(DownloadInfo.Inherit) >= 140
Dim Target As String = If(IsNewerVersion,
- $"{RequestTaskTempFolder()}OptiFine.jar",
- $"{McFolder}libraries\optifine\OptiFine\{DownloadInfo.FileName.Replace("OptiFine_", "").Replace(".jar", "").Replace("preview_", "")}\{DownloadInfo.FileName.Replace("OptiFine_", "OptiFine-").Replace("preview_", "")}")
+ $"{RequestTaskTempFolder(True)}OptiFine.jar",
+ $"{McFolder}libraries\optifine\OptiFine\{PathUtils.GetFileNameWithoutExtension(DownloadInfo.FileName).Replace("OptiFine_", "").Replace("preview_", "")}\{DownloadInfo.FileName.Replace("OptiFine_", "OptiFine-").Replace("preview_", "")}")
Dim Loaders As New List(Of LoaderBase)
'获取下载地址
@@ -522,7 +518,6 @@ pause"
Loop
If Task.IsCanceled Then Return
'复制原版文件
- If Not IsCustomFolder Then Return
SyncLock VanillaSyncLock
Dim ClientName As String = PathUtils.GetLastPart(ClientFolder)
DirectoryUtils.Create(McFolder & "versions\" & DownloadInfo.Inherit)
@@ -540,7 +535,7 @@ pause"
Logger.Info($"检测为新版 OptiFine:{DownloadInfo.Inherit}")
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("安装 OptiFine(方式 A)",
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
- Dim BaseMcFolderHome As String = RequestTaskTempFolder()
+ Dim BaseMcFolderHome As String = RequestTaskTempFolder(True)
Dim BaseMcFolder As String = BaseMcFolderHome & ".minecraft\"
Try
'准备安装环境
@@ -597,7 +592,7 @@ Retry:
""releaseTime"": """ & If(DownloadInfo.ReleaseTime = "", InheritInstance.ReleaseTime.ToString("yyyy'-'MM'-'dd"), DownloadInfo.ReleaseTime.Replace("/", "-")) & "T23:33:33+08:00"",
""type"": ""release"",
""libraries"": [
- {""name"": ""optifine:OptiFine:" & DownloadInfo.FileName.Replace("OptiFine_", "").Replace(".jar", "").Replace("preview_", "") & """},
+ {""name"": ""optifine:OptiFine:" & PathUtils.GetFileNameWithoutExtension(DownloadInfo.FileName).Replace("OptiFine_", "").Replace("preview_", "") & """},
{""name"": ""net.minecraft:launchwrapper:1.12""}
],
""mainClass"": ""net.minecraft.launchwrapper.Launch"","
@@ -785,19 +780,14 @@ Retry:
''' 这不会补全所需的支持库文件,需要后续手动补全支持库。
'''
Private Function McDownloadLiteLoaderLoader(DownloadInfo As DlLiteLoaderListEntry, McFolder As String) As List(Of LoaderBase)
-
- '参数初始化
- Dim IsCustomFolder As Boolean = McFolder <> McFolderSelected
- Dim Id As String = DownloadInfo.Inherit
- Dim Target As String = PathTemp & "Download\" & Id & "-Liteloader.jar"
- Dim VersionName As String = DownloadInfo.Inherit & "-LiteLoader"
- Dim VersionFolder As String = McFolder & "versions\" & VersionName & "\"
Dim Loaders As New List(Of LoaderBase)
'安装
Loaders.Add(New LoaderTask(Of String, String)("安装 LiteLoader",
Sub(Task As LoaderTask(Of String, String))
Try
+ Dim VersionName As String = DownloadInfo.Inherit & "-LiteLoader"
+ Dim VersionFolder As String = McFolder & "versions\" & VersionName & "\"
'构造版本 Json
Dim VersionJson As New JObject
VersionJson.Add("id", VersionName)
@@ -945,7 +935,7 @@ Retry:
'添加 Java Wrapper 作为主 Jar
Dim Arguments As String
If UseJavaWrapper AndAlso Not Settings.Get(Of Boolean)("LaunchAdvanceDisableJLW") Then
- 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}"
+ Arguments = $"-Doolloo.jlw.tmpdir=""{PathUtils.RemoveSlashSuffix(PathPure.Value)}"" -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
@@ -1078,9 +1068,7 @@ Retry:
''' 获取下载某个 Forgelike 版本的加载器列表。
'''
Private Function McDownloadForgelikeLoader(IsNeoForge As Boolean, LoaderVersion As String, NewInstanceName As String, Inherit As String, Info As DlForgelikeEntry, McFolder As String, ClientDownloadLoader As LoaderCombo(Of String), ClientFolder As String) As List(Of LoaderBase)
-
'参数初始化
- McFolder = If(McFolder, McFolderSelected)
If IsNeoForge AndAlso Info Is Nothing Then
'需要传入 API Name,但整合包版本可能不以 1.20.1- 开头,所以需要进行特别处理
If Inherit = "1.20.1" AndAlso Not LoaderVersion.StartsWithF("1.20.1-") Then
@@ -1095,12 +1083,9 @@ Retry:
LoaderVersion = LoaderVersion.AfterLast("-")
End If
Dim LoaderName As String = If(IsNeoForge, "NeoForge", "Forge")
- Dim IsCustomFolder As Boolean = McFolder <> McFolderSelected
- Dim InstallerAddress As String = RequestTaskTempFolder() & "forge_installer.jar"
+ Dim InstallerAddress As String = RequestTaskTempFolder(True) & "forge_installer.jar"
Dim VersionFolder As String = $"{McFolder}versions\{NewInstanceName}\"
- Dim DisplayName As String = $"{LoaderName} {Inherit} - {LoaderVersion}"
Dim Loaders As New List(Of LoaderBase)
- Dim LibVersionFolder As String = $"{McFolderSelected}versions\{NewInstanceName}\" '作为 Lib 文件目标的版本文件夹
'获取 Forge 下载信息
If Info Is Nothing Then
@@ -1112,7 +1097,7 @@ Retry:
Task.Progress = 0.8
'查找对应版本
For Each ForgeVersion In ForgeLoader.Output
- If CompareVersion(ForgeVersion.Version.ToString, LoaderVersion) = 0 Then
+ If McUtils.CompareVersion(ForgeVersion.Version.ToString, LoaderVersion) = 0 Then
Info = ForgeVersion
Return
End If
@@ -1147,6 +1132,7 @@ Retry:
Loaders.Add(New LoaderDownload($"下载 {LoaderName} 主文件", New List(Of NetFile)) With {.ProgressWeight = 9})
'安装(仅在新版安装时需要原版 Jar)
+ Dim CurrentMcFolder = McFolderSelected
If IsNeoForge OrElse LoaderVersion.BeforeFirst(".") >= 20 Then
Logger.Info($"检测为{If(IsNeoForge, " Neo", "新版 ")}Forge:{LoaderVersion}")
Dim Libs As List(Of McLibEntry) = Nothing
@@ -1162,7 +1148,7 @@ Retry:
Dim Json2 As JObject = Installer.GetEntry("version.json").Open().ReadString().DeserializeJson()
Json.Merge(Json2)
'获取 Lib 下载信息
- Libs = McLibListGetWithJson(Json, True)
+ Libs = McLibListGetWithJson(Json, True, CurrentMcFolder)
'添加 Mappings 下载信息
If Json("data") IsNot Nothing AndAlso Json("data")("MOJMAPS") IsNot Nothing Then
'下载原版 Json 文件
@@ -1170,7 +1156,7 @@ Retry:
Dim RawJson As JObject = NetRequestByLoader(DlSourceLauncherOrMetaGet(DlClientListGet(Inherit)), IsJson:=True).DeserializeJson()
'[net.minecraft:client:1.17.1-20210706.113038:mappings@txt] 或 @tsrg]
Dim OriginalName As String = Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).BeforeFirst("@")
- Dim Address = McLibGet(OriginalName).Replace(".jar", "." & Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Split("@")(1))
+ Dim Address = Path.ChangeExtension(McLibGet(OriginalName, CustomMcFolder:=CurrentMcFolder), "." & Json("data")("MOJMAPS")("client").ToString.Trim("[]".ToCharArray()).Split("@")(1))
Dim ClientMappings As JToken = RawJson("downloads")("client_mappings")
Libs.Add(New McLibEntry With {
.IsNatives = False, .LocalPath = Address, .OriginalName = OriginalName,
@@ -1187,7 +1173,7 @@ Retry:
Exit For
End If
Next
- Task.Output = McLibNetFilesFromTokens(Libs, McFolderSelected)
+ Task.Output = McLibNetFilesFromTokens(Libs, CurrentMcFolder)
Catch ex As Exception
Throw New Exception($"获取{If(IsNeoForge, " Neo", "新版 ")}Forge 支持库列表失败", ex)
Finally
@@ -1198,13 +1184,11 @@ Retry:
Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)($"获取 {LoaderName} 支持库文件",
Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
#Region "Forgelike 文件"
- If IsCustomFolder Then
- For Each LibFile As McLibEntry In Libs
- Dim RealPath As String = LibFile.LocalPath.Replace(McFolderSelected, McFolder)
- If Not FileUtils.Exists(RealPath) Then FileUtils.Copy(LibFile.LocalPath, RealPath)
- Logger.Trace($"复制的 {LoaderName} 支持库文件:{LibFile.LocalPath}")
- Next
- End If
+ For Each LibFile As McLibEntry In Libs
+ Dim RealPath As String = Path.Combine(McFolder, LibFile.LocalPath.Substring(CurrentMcFolder.Length))
+ If Not FileUtils.Exists(RealPath) Then FileUtils.Copy(LibFile.LocalPath, RealPath)
+ Logger.Trace($"复制的 {LoaderName} 支持库文件:{LibFile.LocalPath}")
+ Next
#End Region
#Region "原版文件"
'等待原版文件下载完成
@@ -1218,7 +1202,6 @@ Retry:
Loop
If Task.IsCanceled Then Return
'复制原版文件
- If Not IsCustomFolder Then Return
SyncLock VanillaSyncLock
Dim ClientName As String = PathUtils.GetLastPart(ClientFolder)
DirectoryUtils.Create(McFolder & "versions\" & Inherit)
@@ -1233,14 +1216,10 @@ Retry:
End Sub) With {.ProgressWeight = 0.1, .Show = False})
Loaders.Add(New LoaderTask(Of Boolean, Boolean)(If(IsNeoForge, "安装 NeoForge", "安装 Forge(方式 A)"),
Sub(Task As LoaderTask(Of Boolean, Boolean))
- Dim Installer As ZipArchive = Nothing
Try
Logger.Info($"开始进行 Forgelike 安装:{InstallerAddress}")
'记录当前文件夹列表(在新建目标文件夹之前)
Dim OldList = DirectoryUtils.EnumerateDirectories(McFolder & "versions\").ToList()
- '解压并获取信息
- Installer = FileUtils.OpenZip(InstallerAddress)
- Dim Json As JObject = Installer.GetEntry("install_profile.json").Open().ReadString().DeserializeJson()
'新建目标版本文件夹
DirectoryUtils.Create(VersionFolder)
Task.Progress = 0.04
@@ -1292,7 +1271,6 @@ Retry:
Finally
'清理文件
Try
- Installer?.Dispose()
FileUtils.Delete(InstallerAddress)
Catch ex As Exception
Logger.Warn(ex, $"安装 {LoaderName} 清理文件时出错")
@@ -1487,19 +1465,19 @@ Retry:
'''
''' 尝试获取某个 MC 版本对应的 Forge 推荐版本。如果不可用会返回 Nothing。
'''
- Public Function McDownloadForgeRecommendedGet(McVersion As String) As String
+ Public Function McDownloadForgeRecommendedGet(McVersionName As String) As String
Try
- If McVersion Is Nothing Then Return Nothing
+ If McVersionName Is Nothing Then Return Nothing
Dim List As String = FileUtils.TryReadAsString(PathTemp & "Cache\ForgeRecommendedList.json")
If String.IsNullOrEmpty(List) Then
Logger.Info("没有 Forge 推荐版本缓存文件")
Return Nothing
End If
Dim Json As JObject = List.DeserializeJson()
- If Json Is Nothing OrElse (Not If(McVersion, "").Contains(".")) OrElse Not Json.ContainsKey(McVersion) Then Return Nothing
- Return If(Json(McVersion), "").ToString
+ If Json Is Nothing OrElse (Not If(McVersionName, "").Contains(".")) OrElse Not Json.ContainsKey(McVersionName) Then Return Nothing
+ Return If(Json(McVersionName), "").ToString
Catch ex As Exception
- Logger.Error(ex, $"获取 Forge 推荐版本失败({If(McVersion, "null")})")
+ Logger.Error(ex, $"获取 Forge 推荐版本失败({If(McVersionName, "null")})")
Return Nothing
End Try
End Function
@@ -1640,7 +1618,6 @@ Retry:
Private Function McDownloadFabricLoader(FabricVersion As String, MinecraftName As String, McFolder As String) As List(Of LoaderBase)
'参数初始化
- Dim IsCustomFolder As Boolean = McFolder <> McFolderSelected
Dim Id As String = "fabric-loader-" & FabricVersion & "-" & MinecraftName
Dim VersionFolder As String = McFolder & "versions\" & Id & "\"
Dim Loaders As New List(Of LoaderBase)
@@ -1702,83 +1679,437 @@ Retry:
#End Region
-#Region "合并安装"
+#Region "安装"
'''
''' 安装请求。
'''
Public Class McInstallRequest
-
'''
- ''' 必填。安装目标版本名称。
+ ''' 新版本安装必填。安装目标版本名称。
'''
Public NewInstanceName As String
'''
''' 必填。安装目标文件夹。
'''
- Public VersionFolder As String
-
+ Public InstanceFolder As String
'''
- ''' 必填。欲下载的 Minecraft 的版本名。
+ ''' 必填。欲安装的 Minecraft 与组件版本。
'''
- Public MinecraftName As String = Nothing
+ Public Components As McComponents
'''
''' 可选。欲下载的 Minecraft Json 地址。
'''
Public MinecraftJson As String = Nothing
-
- '若要下载 OptiFine,则需要在下面两项中完成至少一项
- '''
- ''' 欲下载的 OptiFine 版本名。例如 HD_U_F6_pre1。
- '''
- Public OptiFineVersion As String = Nothing
- '''
- ''' 欲下载的 OptiFine 详细信息。
- '''
- Public OptiFineEntry As DlOptiFineListEntry = Nothing
-
- '若要下载 Forge,则需要在下面两项中完成至少一项
- '''
- ''' 欲下载的 Forge 版本名。接受例如 36.1.4 / 14.23.5.2859 / 1.19-41.1.0 的输入。
- '''
- Public ForgeVersion As String = Nothing
'''
''' 欲下载的 Forge。
'''
Public ForgeEntry As DlForgeVersionEntry = Nothing
-
- '若要下载 NeoForge,则需要在下面两项中完成至少一项
- '''
- ''' 欲下载的 NeoForge 版本名。
- '''
- Public NeoForgeVersion As String = Nothing
'''
''' 欲下载的 NeoForge。
'''
Public NeoForgeEntry As DlNeoForgeListEntry = Nothing
-
- '''
- ''' 欲下载的 Fabric Loader 版本名。
- '''
- Public FabricVersion As String = Nothing
-
'''
''' 欲下载的 Fabric API 信息。
'''
Public FabricApi As ResourceVersion = Nothing
-
'''
''' 欲下载的 OptiFabric 信息。
'''
Public OptiFabric As ResourceVersion = Nothing
-
'''
''' 欲下载的 LiteLoader 详细信息。
'''
Public LiteLoaderEntry As DlLiteLoaderListEntry = Nothing
-
+ '''
+ ''' 是否为中间产物。
+ '''
+ Public IsIntermediateOutput As Boolean = False
End Class
+ '''
+ ''' 获取合并安装加载器列表。
+ '''
+ Public Function McInstallLoadersGet(Request As McInstallRequest) As List(Of LoaderBase)
+ '获取缓存目录(安装 Mod 加载器的文件夹不能包含空格)
+ Dim TempMcFolder As String = RequestTaskTempFolder(Request.Components.OptiFineEntry IsNot Nothing OrElse
+ Request.Components.ModLoaderVersions.ContainsKey(ModLoaders.Forge) OrElse Request.Components.ModLoaderVersions.ContainsKey(ModLoaders.NeoForge))
+
+ '获取各个 Mod 加载器的缓存文件夹
+ Dim OptiFineEntry = Request.Components.OptiFineEntry?.ToObject(Of DlOptiFineListEntry)()
+ Dim OptiFineFolder = If(OptiFineEntry Is Nothing, Nothing, $"{TempMcFolder}versions\{OptiFineEntry.InstanceName}")
+ Dim ForgeVersion = If(Request.Components.ModLoaderVersions.ContainsKey(ModLoaders.Forge), Request.Components.ModLoaderVersions(ModLoaders.Forge), Nothing)
+ Dim ForgeFolder = If(ForgeVersion Is Nothing, Nothing, $"{TempMcFolder}versions\forge-{ForgeVersion}")
+ Dim NeoForgeVersion = If(Request.Components.ModLoaderVersions.ContainsKey(ModLoaders.NeoForge), Request.Components.ModLoaderVersions(ModLoaders.NeoForge), Nothing)
+ Dim NeoForgeFolder = If(NeoForgeVersion Is Nothing, Nothing, $"{TempMcFolder}versions\neoforge-{NeoForgeVersion}")
+ Dim LiteLoaderVersion = If(Request.Components.ModLoaderVersions.ContainsKey(ModLoaders.LiteLoader), Request.Components.ModLoaderVersions(ModLoaders.LiteLoader), Nothing)
+ Dim LiteLoaderFolder = If(LiteLoaderVersion Is Nothing, Nothing, $"{TempMcFolder}versions\{Request.Components.MinecraftVersion}-LiteLoader")
+ Dim FabricVersion = If(Request.Components.ModLoaderVersions.ContainsKey(ModLoaders.Fabric), Request.Components.ModLoaderVersions(ModLoaders.Fabric), Nothing)
+ Dim FabricFolder = If(FabricVersion Is Nothing, Nothing, $"{TempMcFolder}versions\fabric-loader-{FabricVersion}-{Request.Components.MinecraftVersion}")
+
+ '判断 OptiFine 是否作为 Mod 进行下载
+ Dim Modable = Request.Components.ModLoaderVersions.Any
+ Dim ModsTempFolder As String = $"{TempMcFolder}mods\"
+ Dim OptiFineAsMod = OptiFineEntry IsNot Nothing AndAlso Modable '选择了 OptiFine 与任意 Mod 加载器
+ If OptiFineAsMod Then
+ Logger.Info("OptiFine 将作为 Mod 进行下载")
+ If LiteLoaderVersion IsNot Nothing Then
+ OptiFineFolder = $"{ModsTempFolder}{Request.Components.MinecraftVersion}\" '#8147
+ Else
+ OptiFineFolder = ModsTempFolder
+ End If
+ End If
+
+ '记录日志
+ If OptiFineFolder IsNot Nothing Then Logger.Info($"OptiFine 缓存:{OptiFineFolder}")
+ If ForgeFolder IsNot Nothing Then Logger.Info($"Forge 缓存:{ForgeFolder}")
+ If NeoForgeFolder IsNot Nothing Then Logger.Info($"NeoForge 缓存:{NeoForgeFolder}")
+ If FabricFolder IsNot Nothing Then Logger.Info($"Fabric 缓存:{FabricFolder}")
+ If LiteLoaderFolder IsNot Nothing Then Logger.Info($"LiteLoader 缓存:{LiteLoaderFolder}")
+ Logger.Info($"对应的原版版本:{Request.Components.MinecraftVersion}")
+
+ '重复版本检查
+ Dim VersionFolder As String = PathUtils.AddSlashSuffix(Request.InstanceFolder)
+ If FileUtils.Exists($"{VersionFolder}{Request.NewInstanceName}.json") Then
+ Hint("版本 " & Request.NewInstanceName & " 已经存在!", HintType.Red)
+ Throw New OperationCanceledException
+ End If
+
+ Dim LoaderList As New List(Of LoaderBase)
+ Dim ManagedFileSources As New Dictionary(Of String, String)
+ '添加忽略标识
+ LoaderList.Add(New LoaderTask(Of Integer, Integer)("添加忽略标识", Sub() FileUtils.Write(VersionFolder & ".pclignore", "用于临时地在 PCL 的版本列表中屏蔽此版本。")) With {.Show = False})
+ 'Fabric API
+ If Request.Components.FabricApiVersion IsNot Nothing Then
+ Dim DownloadFile = Request.FabricApi.ToNetFile(ModsTempFolder, ResourceVersion.DownloadReason.Dependency, Request.Components.MinecraftVersion, ModLoaders.Fabric)
+ ManagedFileSources.Add("FabricApi", DownloadFile.LocalPath)
+ LoaderList.Add(New LoaderDownload("下载 Fabric API", New List(Of NetFile) From {DownloadFile}) With {
+ .ProgressWeight = 3, .Show = True, .Block = False})
+ End If
+ 'OptiFabric
+ If Request.Components.OptiFabricVersion IsNot Nothing Then
+ Dim DownloadFile = Request.OptiFabric.ToNetFile(ModsTempFolder, ResourceVersion.DownloadReason.Dependency, Request.Components.MinecraftVersion, ModLoaders.Fabric)
+ ManagedFileSources.Add("OptiFabric", DownloadFile.LocalPath)
+ LoaderList.Add(New LoaderDownload("下载 OptiFabric", New List(Of NetFile) From {DownloadFile}) With {
+ .ProgressWeight = 3, .Show = True, .Block = False})
+ End If
+ '原版
+ Dim ClientLoader = New LoaderCombo(Of String)("下载原版 " & Request.Components.MinecraftVersion,
+ McDownloadClientLoader(Request.Components.MinecraftVersion, Request.MinecraftJson, VersionFolder)) With {
+ .ProgressWeight = 39, .Show = False, .Block = Not Modable AndAlso OptiFineEntry Is Nothing}
+ LoaderList.Add(ClientLoader)
+ 'OptiFine
+ If OptiFineEntry IsNot Nothing Then
+ If OptiFineAsMod Then ManagedFileSources.Add("OptiFine", OptiFineFolder & OptiFineEntry.FileName)
+ LoaderList.Add(New LoaderCombo(Of String)("下载 OptiFine " & OptiFineEntry.DisplayName,
+ If(OptiFineAsMod,
+ McDownloadOptiFineSaveLoader(OptiFineEntry, OptiFineFolder & OptiFineEntry.FileName),
+ McDownloadOptiFineLoader(OptiFineEntry, TempMcFolder, ClientLoader, VersionFolder))) With {
+ .ProgressWeight = If(Modable, 16, 24), .Show = False, .Block = Not Modable})
+ End If
+ 'Forge
+ If ForgeVersion IsNot Nothing Then
+ LoaderList.Add(New LoaderCombo(Of String)("下载 Forge " & ForgeVersion,
+ McDownloadForgelikeLoader(False, ForgeVersion, "forge-" & ForgeVersion, Request.Components.MinecraftVersion, Request.ForgeEntry, TempMcFolder, ClientLoader, VersionFolder)) With {
+ .ProgressWeight = 25, .Show = False, .Block = FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing AndAlso Request.NeoForgeEntry Is Nothing})
+ End If
+ 'NeoForge
+ If NeoForgeVersion IsNot Nothing Then
+ LoaderList.Add(New LoaderCombo(Of String)("下载 NeoForge " & NeoForgeVersion,
+ McDownloadForgelikeLoader(True, NeoForgeVersion, "neoforge-" & NeoForgeVersion, Request.Components.MinecraftVersion, Request.NeoForgeEntry, TempMcFolder, ClientLoader, VersionFolder)) With {
+ .ProgressWeight = 25, .Show = False, .Block = Request.ForgeEntry Is Nothing AndAlso FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing})
+ End If
+ 'LiteLoader
+ If LiteLoaderVersion IsNot Nothing Then
+ LoaderList.Add(New LoaderCombo(Of String)("下载 LiteLoader " & Request.Components.MinecraftVersion,
+ McDownloadLiteLoaderLoader(Request.LiteLoaderEntry, TempMcFolder)) With {
+ .ProgressWeight = 1, .Show = False, .Block = FabricVersion Is Nothing})
+ End If
+ 'Fabric
+ If FabricVersion IsNot Nothing Then
+ LoaderList.Add(New LoaderCombo(Of String)("下载 Fabric " & FabricVersion,
+ McDownloadFabricLoader(FabricVersion, Request.Components.MinecraftVersion, TempMcFolder)) With {
+ .ProgressWeight = 2, .Show = False, .Block = True})
+ End If
+ '合并安装
+ Dim MinecraftFolder = McFolderSelected
+ Dim TargetFolder As String = Nothing
+ LoaderList.Add(New LoaderTask(Of String, String)("安装游戏",
+ Sub(Task As LoaderTask(Of String, String))
+ '合并 JSON:将多个版本 JSON 进行合并,如果已存在则直接覆盖
+ MergeJson(VersionFolder, OptiFineFolder, OptiFineAsMod, ForgeFolder, NeoForgeFolder, FabricFolder, LiteLoaderFolder)
+ Task.Progress = 0.2
+ '迁移文件
+ DirectoryUtils.Copy(TempMcFolder & "libraries", MinecraftFolder & "libraries")
+ Task.Progress = 0.8
+ '创建 Mod 和资源包文件夹
+ TargetFolder = If(Request.IsIntermediateOutput, VersionFolder, New McInstance(VersionFolder).PathIndie) '版本隔离信息在此时被决定
+ Dim ModsFolder = TargetFolder & "mods\"
+ If DirectoryUtils.Exists(ModsTempFolder) Then
+ DirectoryUtils.Copy(ModsTempFolder, ModsFolder)
+ ElseIf Modable Then
+ DirectoryUtils.Create(ModsFolder)
+ Logger.Info($"自动创建 Mod 文件夹:{ModsFolder}")
+ End If
+ Dim ResourcepacksFolder = TargetFolder & "resourcepacks\"
+ DirectoryUtils.Create(ResourcepacksFolder)
+ Logger.Info($"自动创建资源包文件夹:{ResourcepacksFolder}")
+ End Sub) With {.ProgressWeight = 2, .Block = True})
+ '补全文件
+ Dim LoadersLib As New List(Of LoaderBase)
+ LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task) Task.Output = McLibNetFilesFromInstance(New McInstance(VersionFolder))) With {.ProgressWeight = 1, .Show = False})
+ LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
+ LoaderList.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
+ '记录安装清单
+ LoaderList.Add(New LoaderTask(Of Integer, Integer)("记录安装清单",
+ Sub()
+ Dim ManagedFiles As New List(Of McInstallManifest.ManagedFile)
+ '记录由 PCL 管理的 Mod 信息
+ For Each Entry In ManagedFileSources
+ Dim RelativePath = Entry.Value.Substring(ModsTempFolder.Length)
+ Dim FullPath = PathUtils.ForCompare(Path.Combine(TargetFolder, "mods", RelativePath))
+ ManagedFiles.Add(New McInstallManifest.ManagedFile("mods/" & RelativePath.Replace("\", "/").ToLowerInvariant(),
+ CryptographyUtils.ComputeFileHash(FullPath, CryptographyUtils.HashMethod.Sha1), FileUtils.GetInfo(FullPath).LastWriteTimeUtc, Entry.Key))
+ Next
+ '处理加载器版本信息
+ Dim TempLoaderVersions As New Dictionary(Of ModLoaders, String)(Request.Components.ModLoaderVersions)
+ If ForgeVersion IsNot Nothing AndAlso ForgeVersion.StartsWithF("1.") AndAlso ForgeVersion.Contains("-") Then
+ TempLoaderVersions(ModLoaders.Forge) = ForgeVersion.AfterLast("-")
+ End If
+ If NeoForgeVersion IsNot Nothing AndAlso NeoForgeVersion.StartsWithF("1.20.1-") Then
+ TempLoaderVersions(ModLoaders.NeoForge) = NeoForgeVersion.Replace("1.20.1-", "")
+ End If
+ '存储 Manifest
+ Dim Target = New McComponents(Request.Components.MinecraftVersion, TempLoaderVersions,
+ Request.Components.OptiFineEntry, Request.Components.FabricApiVersion, Request.Components.OptiFabricVersion)
+ Dim InstanceConfig = New McInstance(VersionFolder).Config
+ Configs.McInstallManifest.Set(New McInstallManifest(Versions.McInstallManifestVersion, Target, Date.UtcNow, ManagedFiles), InstanceConfig)
+ InstanceConfig.Save()
+ End Sub) With {.Show = False})
+ '删除忽略标识
+ If Not Request.IsIntermediateOutput Then
+ LoaderList.Add(New LoaderTask(Of Integer, Integer)("删除忽略标识", Sub() FileUtils.Delete(VersionFolder & ".pclignore")) With {.Show = False})
+ End If
+ '总加载器
+ Return LoaderList
+ End Function
+ Private Sub MergeJson(VersionFolder As String, OptiFineFolder As String, OptiFineAsMod As Boolean,
+ ForgeFolder As String, NeoForgeFolder As String, FabricFolder As String, LiteLoaderFolder As String)
+ Dim ProfileSources As New List(Of (Name As String, Folder As String)) From {("Minecraft", VersionFolder)}
+ If OptiFineFolder IsNot Nothing AndAlso Not OptiFineAsMod Then ProfileSources.Add(("OptiFine", OptiFineFolder))
+ If ForgeFolder IsNot Nothing Then ProfileSources.Add(("Forge", ForgeFolder))
+ If NeoForgeFolder IsNot Nothing Then ProfileSources.Add(("NeoForge", NeoForgeFolder))
+ If LiteLoaderFolder IsNot Nothing Then ProfileSources.Add(("LiteLoader", LiteLoaderFolder))
+ If FabricFolder IsNot Nothing Then ProfileSources.Add(("Fabric", FabricFolder))
+ Logger.Info($"开始进行版本合并,输出:{VersionFolder}," & String.Join(",", ProfileSources.Select(Function(Source) $"{Source.Name}:{Source.Folder}")))
+ '读取文件并检查文件是否合规
+ Dim LoadedProfiles As New List(Of (Name As String, Json As JObject))
+ For Each Source In ProfileSources
+ Dim ProfilePath = Path.Combine(Source.Folder, PathUtils.GetLastPart(Source.Folder) & ".json")
+ Dim ProfileText = If(FileUtils.TryReadAsString(ProfilePath), "")
+ If Not ProfileText.StartsWithF("{") Then Throw New Exception($"{Source.Name} json 有误,地址:{ProfilePath},前段内容:{ProfileText.Substring(0, Math.Min(ProfileText.Length, 1000))}")
+ LoadedProfiles.Add((Source.Name, ProfileText.DeserializeJson(Of JObject)()))
+ Next
+ '先获取 minecraftArguments,避免合并时原版参数被覆盖
+ Dim AllArguments = LoadedProfiles.Select(Function(Profile) If(Profile.Json("minecraftArguments")?.ToString(), " ")).Join(" ")
+ '合并(相关讨论见 #2801)
+ Dim MergedJson = LoadedProfiles(0).Json 'Minecraft 原版 JSON
+ For Each Loaded In LoadedProfiles.Skip(1)
+ Loaded.Json.Remove("releaseTime")
+ Loaded.Json.Remove("time")
+ MergedJson.Merge(Loaded.Json)
+ Next
+ '填入 minecraftArguments
+ Dim SplitArguments As New List(Of String)
+ For Each Argument In AllArguments.Split(" ", True).Select(Function(Value) Value.Trim())
+ If Not Argument.StartsWithF("-") AndAlso SplitArguments.Any Then
+ Dim LastArgument = SplitArguments.Last
+ If LastArgument.StartsWithF("-") AndAlso Not LastArgument.Contains(" ") Then
+ SplitArguments(SplitArguments.Count - 1) = LastArgument & " " & Argument
+ Continue For
+ End If
+ End If
+ SplitArguments.Add(Argument)
+ Next
+ If SplitArguments.Any() Then MergedJson("minecraftArguments") = SplitArguments.Distinct().Join(" ")
+ '修改
+ MergedJson.Remove("_comment_")
+ MergedJson.Remove("inheritsFrom")
+ MergedJson.Remove("jar")
+ Dim VersionName = PathUtils.GetLastPart(VersionFolder)
+ MergedJson("id") = VersionName
+ '保存
+ FileUtils.Write(Path.Combine(VersionFolder, VersionName & ".json"), MergedJson.ToString())
+ Logger.Info($"版本合并 {VersionName} 完成")
+ End Sub
+ '''
+ ''' 进行合并安装。返回是否已经开始安装。
+ '''
+ Public Function McInstallStart(Request As McInstallRequest) As Boolean
+ Try
+ Dim Loader As New LoaderCombo(Of String)(Request.NewInstanceName & " 安装", McInstallLoadersGet(Request)) With {.OnStateChanged = AddressOf McInstallState}
+ '启动
+ Loader.Start(Request.InstanceFolder)
+ LoaderTaskbarAdd(Loader)
+ FrmMain.BtnExtraDownload.ShowRefresh()
+ FrmMain.BtnExtraDownload.Ribble()
+ Return True
+ Catch ex As Exception
+ Logger.Error(ex, "开始合并安装失败")
+ Return False
+ End Try
+ End Function
+ '''
+ ''' 进行修改安装。返回是否已经开始安装。
+ '''
+ Public Function McModificationStart(Request As McInstallRequest, Instance As McInstance) As Boolean
+ Try
+ '检查版本目录下的 Natives,防止修改正在运行的游戏
+ Dim TargetFolder = Instance.PathIndie
+ Dim SubLoaders As New List(Of LoaderBase)
+ SubLoaders.Add(New LoaderTask(Of Integer, Integer)("检查 Natives 文件占用",
+ Sub()
+ For Each File In DirectoryUtils.EnumerateFiles(GetNativesFolder(Instance), includeSubDirectories:=True, searchPattern:="*.dll")
+ If Not FileUtils.IsAvailable(File) Then Throw New Exception($"Natives 文件正在被占用,请关闭游戏后再次尝试:{File}")
+ Next
+ End Sub) With {.Show = False})
+ '安装修改后的 MC 版本
+ Dim BuildFolder = RequestTaskTempFolder() & Instance.Name & "\"
+ Dim BuildRequest As New McInstallRequest With {
+ .NewInstanceName = Instance.Name,
+ .InstanceFolder = BuildFolder,
+ .Components = Request.Components,
+ .MinecraftJson = Request.MinecraftJson,
+ .ForgeEntry = Request.ForgeEntry,
+ .NeoForgeEntry = Request.NeoForgeEntry,
+ .FabricApi = Request.FabricApi,
+ .OptiFabric = Request.OptiFabric,
+ .LiteLoaderEntry = Request.LiteLoaderEntry,
+ .IsIntermediateOutput = True
+ }
+ SubLoaders.AddRange(McInstallLoadersGet(BuildRequest))
+ '版本合并
+ Dim RenameFailed As Boolean = False
+ SubLoaders.Add(New LoaderTask(Of Integer, Integer)("修改版本",
+ Sub(Task)
+ 'TODO: 提交前显示文件修改列表(大量文件按“XXX 文件夹下 XXX 项”汇总),可以询问玩家是否覆盖原版本或作为新版本安装(不覆盖)?
+ McInstallCommit(Instance, Configs.McInstallManifest.Get(New McInstance(BuildFolder).Config), BuildFolder, TargetFolder)
+ '重命名和引用交接
+ Dim NewInstance As McInstance = Nothing
+ If Request.NewInstanceName Is Nothing Then
+ NewInstance = New McInstance(Instance.PathVersion).Load()
+ Else
+ Try
+ NewInstance = Instance.Rename(Request.NewInstanceName)
+ Catch ex As Exception
+ RenameFailed = True
+ Logger.Warn(ex, $"版本修改成功,但重命名为 {Request.NewInstanceName} 失败:{ex.GetDisplay(False)}", LogBehavior.None)
+ NewInstance = New McInstance(Instance.PathVersion).Load()
+ End Try
+ End If
+ If NewInstance Is Nothing Then NewInstance = New McInstance(Instance.PathVersion).Load()
+ RunInUiWait(
+ Sub()
+ WriteIni(McFolderSelected & "PCL.ini", "InstanceCache", "")
+ '未切换则选中修改后的版本
+ If PageInstanceLeft.Instance IsNot Nothing AndAlso
+ PathUtils.IsSame(PageInstanceLeft.Instance.PathVersion, Instance.PathVersion) Then
+ PageInstanceLeft.Instance = NewInstance
+ End If
+ If McInstanceSelected IsNot Nothing AndAlso
+ PathUtils.IsSame(McInstanceSelected.PathVersion, Instance.PathVersion) Then
+ McInstanceSelected = NewInstance
+ End If
+ End Sub)
+ End Sub) With {.ProgressWeight = 1, .Block = True})
+ '实际修改任务
+ Dim Loader As New LoaderCombo(Of String)(Instance.Name & " 修改", SubLoaders) With {.OnStateChanged =
+ Sub(CurrentLoader)
+ '流程收尾
+ Select Case CurrentLoader.State
+ Case LoadState.Finished
+ If Not RenameFailed Then
+ Hint(CurrentLoader.Name & "成功!", HintType.Green)
+ Else
+ Hint(CurrentLoader.Name & "成功,但重命名失败!", HintType.Green)
+ End If
+ Case LoadState.Failed
+ MyMsgBox(CurrentLoader.Error.GetDisplay(True), CurrentLoader.Name & "失败", IsWarn:=True)
+ Case LoadState.Canceled
+ Hint(CurrentLoader.Name & "已取消!", HintType.Blue)
+ End Select
+ End Sub}
+ Dim Worker As New RedoableWorker(Sub() Loader.WaitForExit(Instance.PathVersion))
+ '启动
+ If McInstanceLock.TryAcquire(Worker, Instance.PathVersion) Then
+ AddHandler Worker.Stopped, Sub() RunInUi(Sub() LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\"))
+ Worker.Start()
+ '加锁后刷新版本列表,隐藏正在修改的实例。
+ LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
+ Else
+ Logger.Error("版本被其他 Worker 占用,版本修改失败")
+ Return False
+ End If
+ LoaderTaskbarAdd(Loader)
+ FrmMain.BtnExtraDownload.ShowRefresh()
+ FrmMain.BtnExtraDownload.Ribble()
+ Return True
+ Catch ex As Exception
+ LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
+ Logger.Error(ex, "开始修改版本失败", LogBehavior.Toast)
+ Return False
+ End Try
+ End Function
+
+ '''
+ ''' 将安装好的临时版本文件夹覆盖到一个现有文件夹中。
+ '''
+ Public Sub McInstallCommit(Instance As McInstance, NewManifest As McInstallManifest, BuildFolder As String, TargetFolder As String)
+ Dim OldFiles = If(Configs.McInstallManifest.Get(Instance.Config)?.ManagedFiles, {})
+ Dim NewFiles = NewManifest.ManagedFiles
+
+ '============== 整理变更的文件列表 ==============
+
+ Dim FilesToDelete As New List(Of String)
+ Dim FilesToMove As New List(Of (Source As String, Target As String))
+ 'ManagedFiles
+ '新版里有:添加或覆盖新版文件
+ For Each NewFile In NewFiles
+ FilesToMove.Add((Path.Combine(BuildFolder, NewFile.RelativePath), Path.Combine(TargetFolder, NewFile.RelativePath)))
+ Next
+ '新版里没有,老版里有:删除本地文件到回收站
+ Dim NewFilePaths As New HashSet(Of String)(NewFiles.Select(Function(File) File.RelativePath))
+ For Each OldFile In OldFiles
+ If NewFilePaths.Contains(OldFile.RelativePath) Then Continue For
+ FilesToDelete.Add(PathUtils.ForCompare(Path.Combine(TargetFolder, OldFile.RelativePath)))
+ Next
+ '老版本 MC 的 assets 文件
+ If DirectoryUtils.Exists(BuildFolder & "resources\") Then DirectoryUtils.Copy(BuildFolder & "resources\", TargetFolder & "resources\")
+ 'json 与 jar
+ Dim OldJsonPath As String = Instance.GetJsonPath()
+ FilesToDelete.Add(OldJsonPath)
+ FilesToDelete.Add(Path.ChangeExtension(OldJsonPath, ".jar"))
+ FilesToDelete.Add(Instance.PathVersion & Instance.Name & ".jar")
+ FilesToDelete = FilesToDelete.Distinct(StringComparer.OrdinalIgnoreCase).ToList()
+
+ '============== 实际修改 ==============
+
+ Instance.Config.Save()
+ For Each TargetPath In FilesToDelete
+ FileUtils.Delete(TargetPath, True)
+ Next
+ FileUtils.Move(BuildFolder & Instance.Name & ".jar", Instance.PathVersion & Instance.Name & ".jar")
+ FileUtils.Move(BuildFolder & Instance.Name & ".json", OldJsonPath)
+ For Each File In FilesToMove
+ DirectoryUtils.Create(PathUtils.RemoveLastPart(File.Target))
+ FileUtils.Copy(File.Source, File.Target)
+ Next
+ Dim ManagedFiles = NewFiles.Select(Function(File) New McInstallManifest.ManagedFile(File.RelativePath, File.Sha1,
+ FileUtils.GetInfo(Path.Combine(TargetFolder, File.RelativePath)).LastWriteTimeUtc, File.Component)).ToList()
+ Configs.McInstallManifest.Set(New McInstallManifest(NewManifest.SchemaVersion, NewManifest.Components, NewManifest.LastModifiedUtc, ManagedFiles), Instance.Config)
+ Instance.Config.Save()
+ End Sub
+
'''
''' 在加载器状态改变后显示一条提示。
''' 不会进行任何其他操作。
@@ -1813,345 +2144,22 @@ Retry:
LoaderFolderRun(McInstanceListLoader, McFolderSelected, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
End Sub
Public Sub McInstallFailedClearFolder(Loader)
- Try
- If Loader.State <> LoadState.Failed AndAlso Loader.State <> LoadState.Canceled Then Return
- Thread.Sleep(1000) '防止存在尚未完全释放的文件,导致清理失败(例如整合包安装)
- '删除版本文件夹
- If DirectoryUtils.Exists(Loader.Input & "saves\") OrElse DirectoryUtils.Exists(Loader.Input & "versions\") Then
- Logger.Warn($"由于版本已被独立启动,不清理版本文件夹:{Loader.Input}")
- Else
- Logger.Warn($"由于下载失败或取消,清理版本文件夹:{Loader.Input}")
- DirectoryUtils.Delete(Loader.Input)
- End If
- Catch ex As Exception
- Logger.Warn(ex, "下载失败或取消后清理版本文件夹失败")
- End Try
- End Sub
-
- '''
- ''' 进行合并安装。返回是否已经开始安装(例如如果没有安装 Java 则会进行提示并返回 False)
- '''
- Public Function McInstall(Request As McInstallRequest) As Boolean
- Try
- Dim SubLoaders = McInstallLoader(Request)
- If SubLoaders Is Nothing Then Return False
- Dim Loader As New LoaderCombo(Of String)(Request.NewInstanceName & " 安装", SubLoaders) With {.OnStateChanged = AddressOf McInstallState}
-
- '启动
- Loader.Start(Request.VersionFolder)
- LoaderTaskbarAdd(Loader)
- FrmMain.BtnExtraDownload.ShowRefresh()
- FrmMain.BtnExtraDownload.Ribble()
- Return True
-
- Catch ex As Exception
- Logger.Error(ex, "开始合并安装失败")
- Return False
- End Try
- End Function
- '''
- ''' 获取合并安装加载器列表,并进行前期的缓存清理与 Java 检查工作。
- '''
- Public Function McInstallLoader(Request As McInstallRequest) As List(Of LoaderBase)
- '获取缓存目录(安装 Mod 加载器的文件夹不能包含空格)
- Dim TempMcFolder As String = RequestTaskTempFolder(Request.OptiFineEntry IsNot Nothing OrElse Request.ForgeEntry IsNot Nothing OrElse Request.NeoForgeEntry IsNot Nothing)
-
- '获取参数
- Dim VersionFolder As String = McFolderSelected & "versions\" & Request.NewInstanceName & "\"
- If DirectoryUtils.Exists(TempMcFolder) Then DirectoryUtils.Delete(TempMcFolder)
- Dim OptiFineFolder As String = Nothing
- If Request.OptiFineVersion IsNot Nothing Then
- If Request.OptiFineVersion.Contains("_HD_U_") Then Request.OptiFineVersion = "HD_U_" & Request.OptiFineVersion.AfterLast("_HD_U_") '#735
- Request.OptiFineEntry = New DlOptiFineListEntry With {
- .DisplayName = Request.MinecraftName & " " & Request.OptiFineVersion.Replace("HD_U_", "").Replace("_", "").Replace("pre", " pre"),
- .Inherit = Request.MinecraftName,
- .IsPreview = Request.OptiFineVersion.ContainsIgnoreCase("pre"),
- .InstanceName = Request.MinecraftName & "-OptiFine_" & Request.OptiFineVersion,
- .FileName = If(Request.OptiFineVersion.ContainsIgnoreCase("pre"), "preview_", "") &
- "OptiFine_" & Request.MinecraftName & "_" & Request.OptiFineVersion & ".jar"
- }
- End If
- If Request.OptiFineEntry IsNot Nothing Then OptiFineFolder = TempMcFolder & "versions\" & Request.OptiFineEntry.InstanceName
- Dim ForgeFolder As String = Nothing
- If Request.ForgeEntry IsNot Nothing Then Request.ForgeVersion = If(Request.ForgeVersion, Request.ForgeEntry.VersionName)
- If Request.ForgeVersion IsNot Nothing Then ForgeFolder = TempMcFolder & "versions\forge-" & Request.ForgeVersion
- Dim NeoForgeFolder As String = Nothing
- If Request.NeoForgeEntry IsNot Nothing Then Request.NeoForgeVersion = If(Request.NeoForgeVersion, Request.NeoForgeEntry.VersionName)
- If Request.NeoForgeVersion IsNot Nothing Then NeoForgeFolder = TempMcFolder & "versions\neoforge-" & Request.NeoForgeVersion
- Dim FabricFolder As String = Nothing
- If Request.FabricVersion IsNot Nothing Then FabricFolder = TempMcFolder & "versions\fabric-loader-" & Request.FabricVersion & "-" & Request.MinecraftName
- Dim LiteLoaderFolder As String = Nothing
- If Request.LiteLoaderEntry IsNot Nothing Then LiteLoaderFolder = TempMcFolder & "versions\" & Request.MinecraftName & "-LiteLoader"
-
- '判断 OptiFine 是否作为 Mod 进行下载
- Dim Modable As Boolean = Request.FabricVersion IsNot Nothing OrElse Request.ForgeEntry IsNot Nothing OrElse Request.NeoForgeEntry IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing
- Dim ModsTempFolder As String = TempMcFolder & "mods\"
- Dim OptiFineAsMod As Boolean = Request.OptiFineEntry IsNot Nothing AndAlso Modable '选择了 OptiFine 与任意 Mod 加载器
- If OptiFineAsMod Then
- Logger.Info("OptiFine 将作为 Mod 进行下载")
- If Request.LiteLoaderEntry IsNot Nothing Then
- OptiFineFolder = ModsTempFolder & Request.MinecraftName & "\" '#8147
- Else
- OptiFineFolder = ModsTempFolder
- End If
- End If
-
- '记录日志
- If OptiFineFolder IsNot Nothing Then Logger.Info($"OptiFine 缓存:{OptiFineFolder}")
- If ForgeFolder IsNot Nothing Then Logger.Info($"Forge 缓存:{ForgeFolder}")
- If NeoForgeFolder IsNot Nothing Then Logger.Info($"NeoForge 缓存:{NeoForgeFolder}")
- If FabricFolder IsNot Nothing Then Logger.Info($"Fabric 缓存:{FabricFolder}")
- If LiteLoaderFolder IsNot Nothing Then Logger.Info($"LiteLoader 缓存:{LiteLoaderFolder}")
- Logger.Info($"对应的原版版本:{Request.MinecraftName}")
-
- '重复版本检查
- If FileUtils.Exists($"{VersionFolder}{Request.NewInstanceName}.json") Then
- Hint("版本 " & Request.NewInstanceName & " 已经存在!", HintType.Red)
- Throw New OperationCanceledException
- End If
-
- Dim LoaderList As New List(Of LoaderBase)
- '添加忽略标识
- LoaderList.Add(New LoaderTask(Of Integer, Integer)("添加忽略标识", Sub() FileUtils.Write(VersionFolder & ".pclignore", "用于临时地在 PCL 的版本列表中屏蔽此版本。")) With {.Show = False, .Block = False})
- 'Fabric API
- If Request.FabricApi IsNot Nothing Then
- LoaderList.Add(New LoaderDownload("下载 Fabric API", New List(Of NetFile) From {Request.FabricApi.ToNetFile(ModsTempFolder, ResourceVersion.DownloadReason.Dependency, Request.MinecraftName, ModLoaders.Fabric)}) With {.ProgressWeight = 3, .Block = False})
- End If
- 'OptiFabric
- If Request.OptiFabric IsNot Nothing Then
- LoaderList.Add(New LoaderDownload("下载 OptiFabric", New List(Of NetFile) From {Request.OptiFabric.ToNetFile(ModsTempFolder, ResourceVersion.DownloadReason.Dependency, Request.MinecraftName, ModLoaders.Fabric)}) With {.ProgressWeight = 3, .Block = False})
- End If
- '原版
- Dim ClientLoader = New LoaderCombo(Of String)("下载原版 " & Request.MinecraftName, McDownloadClientLoader(Request.MinecraftName, Request.MinecraftJson, Request.NewInstanceName)) With {.Show = False, .ProgressWeight = 39,
- .Block = Request.ForgeVersion Is Nothing AndAlso Request.NeoForgeVersion Is Nothing AndAlso Request.OptiFineEntry Is Nothing AndAlso Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing}
- LoaderList.Add(ClientLoader)
- 'OptiFine
- If Request.OptiFineEntry IsNot Nothing Then
- If OptiFineAsMod Then
- LoaderList.Add(New LoaderCombo(Of String)("下载 OptiFine " & Request.OptiFineEntry.DisplayName, McDownloadOptiFineSaveLoader(Request.OptiFineEntry, OptiFineFolder & Request.OptiFineEntry.FileName)) With {.Show = False, .ProgressWeight = 16,
- .Block = Request.ForgeVersion Is Nothing AndAlso Request.NeoForgeVersion Is Nothing AndAlso Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing})
- Else
- LoaderList.Add(New LoaderCombo(Of String)("下载 OptiFine " & Request.OptiFineEntry.DisplayName, McDownloadOptiFineLoader(Request.OptiFineEntry, TempMcFolder, ClientLoader, Request.VersionFolder)) With {.Show = False, .ProgressWeight = 24,
- .Block = Request.ForgeVersion Is Nothing AndAlso Request.NeoForgeVersion Is Nothing AndAlso Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing})
- End If
- End If
- 'Forge
- If Request.ForgeVersion IsNot Nothing Then
- LoaderList.Add(New LoaderCombo(Of String)("下载 Forge " & Request.ForgeVersion, McDownloadForgelikeLoader(False, Request.ForgeVersion, "forge-" & Request.ForgeVersion, Request.MinecraftName, Request.ForgeEntry, TempMcFolder, ClientLoader, Request.VersionFolder)) With {.Show = False, .ProgressWeight = 25,
- .Block = Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing AndAlso Request.NeoForgeEntry Is Nothing})
- End If
- 'NeoForge
- If Request.NeoForgeVersion IsNot Nothing Then
- LoaderList.Add(New LoaderCombo(Of String)("下载 NeoForge " & Request.NeoForgeVersion, McDownloadForgelikeLoader(True, Request.NeoForgeVersion, "neoforge-" & Request.NeoForgeVersion, Request.MinecraftName, Request.NeoForgeEntry, TempMcFolder, ClientLoader, Request.VersionFolder)) With {.Show = False, .ProgressWeight = 25,
- .Block = Request.ForgeEntry Is Nothing AndAlso Request.FabricVersion Is Nothing AndAlso Request.LiteLoaderEntry Is Nothing})
- End If
- 'LiteLoader
- If Request.LiteLoaderEntry IsNot Nothing Then
- LoaderList.Add(New LoaderCombo(Of String)("下载 LiteLoader " & Request.MinecraftName, McDownloadLiteLoaderLoader(Request.LiteLoaderEntry, TempMcFolder)) With {.Show = False, .ProgressWeight = 1,
- .Block = Request.FabricVersion Is Nothing})
- End If
- 'Fabric
- If Request.FabricVersion IsNot Nothing Then
- LoaderList.Add(New LoaderCombo(Of String)("下载 Fabric " & Request.FabricVersion, McDownloadFabricLoader(Request.FabricVersion, Request.MinecraftName, TempMcFolder)) With {.Show = False, .ProgressWeight = 2,
- .Block = True})
- End If
- '合并安装
- LoaderList.Add(New LoaderTask(Of String, String)("安装游戏",
- Sub(Task As LoaderTask(Of String, String))
- '合并 JSON
- MergeJson(VersionFolder, VersionFolder, OptiFineFolder, OptiFineAsMod, ForgeFolder, Request.ForgeVersion, NeoForgeFolder, Request.NeoForgeVersion, FabricFolder, LiteLoaderFolder)
- Task.Progress = 0.2
- '迁移文件
- DirectoryUtils.Copy(TempMcFolder & "libraries", McFolderSelected & "libraries")
- Task.Progress = 0.8
- '创建 Mod 和资源包文件夹
- Dim ModsFolder = New McInstance(VersionFolder).PathIndie & "mods\" '版本隔离信息在此时被决定
- If DirectoryUtils.Exists(ModsTempFolder) Then
- DirectoryUtils.Copy(ModsTempFolder, ModsFolder)
- ElseIf Modable Then
- DirectoryUtils.Create(ModsFolder)
- Logger.Info($"自动创建 Mod 文件夹:{ModsFolder}")
- End If
- Dim ResourcepacksFolder = New McInstance(VersionFolder).PathIndie & "resourcepacks\"
- DirectoryUtils.Create(ResourcepacksFolder)
- Logger.Info($"自动创建资源包文件夹:{ResourcepacksFolder}")
- End Sub) With {.ProgressWeight = 2, .Block = True})
- '补全文件
- If Request.OptiFineEntry IsNot Nothing OrElse (Request.ForgeVersion IsNot Nothing AndAlso Request.ForgeVersion.BeforeFirst(".") >= 20) OrElse Request.NeoForgeVersion IsNot Nothing OrElse Request.FabricVersion IsNot Nothing OrElse Request.LiteLoaderEntry IsNot Nothing Then
- Dim LoadersLib As New List(Of LoaderBase)
- LoadersLib.Add(New LoaderTask(Of String, List(Of NetFile))("分析游戏支持库文件(副加载器)", Sub(Task) Task.Output = McLibNetFilesFromInstance(New McInstance(VersionFolder))) With {.ProgressWeight = 1, .Show = False})
- LoadersLib.Add(New LoaderDownload("下载游戏支持库文件(副加载器)", New List(Of NetFile)) With {.ProgressWeight = 7, .Show = False})
- LoaderList.Add(New LoaderCombo(Of String)("下载游戏支持库文件", LoadersLib) With {.ProgressWeight = 8})
- End If
- '删除忽略标识
- LoaderList.Add(New LoaderTask(Of Integer, Integer)("删除忽略标识", Sub() FileUtils.Delete(VersionFolder & ".pclignore")) With {.Show = False})
- '总加载器
- Return LoaderList
- End Function
-
- '''
- ''' 将多个版本 JSON 进行合并,如果目标已存在则直接覆盖。失败会抛出异常。
- '''
- Private Sub MergeJson(OutputFolder As String, MinecraftFolder As String, Optional OptiFineFolder As String = Nothing, Optional OptiFineAsMod As Boolean = False, Optional ForgeFolder As String = Nothing, Optional ForgeVersion As String = Nothing, Optional NeoForgeFolder As String = Nothing, Optional NeoForgeVersion As String = Nothing, Optional FabricFolder As String = Nothing, Optional LiteLoaderFolder As String = Nothing)
- Logger.Info($"开始进行版本合并,输出:{OutputFolder},Minecraft:{MinecraftFolder}" &
- If(OptiFineFolder IsNot Nothing, ",OptiFine:" & OptiFineFolder, "") &
- If(ForgeFolder IsNot Nothing, ",Forge:" & ForgeFolder, "") &
- If(NeoForgeFolder IsNot Nothing, ",NeoForge:" & NeoForgeFolder, "") &
- If(LiteLoaderFolder IsNot Nothing, ",LiteLoader:" & LiteLoaderFolder, "") &
- If(FabricFolder IsNot Nothing, ",Fabric:" & FabricFolder, ""))
- DirectoryUtils.Create(OutputFolder)
-
- Dim HasOptiFine As Boolean = OptiFineFolder IsNot Nothing AndAlso Not OptiFineAsMod, HasForge As Boolean = ForgeFolder IsNot Nothing, HasNeoForge As Boolean = NeoForgeFolder IsNot Nothing, HasLiteLoader As Boolean = LiteLoaderFolder IsNot Nothing, HasFabric As Boolean = FabricFolder IsNot Nothing
- Dim OutputName As String, MinecraftName As String, OptiFineName As String, ForgeName As String, NeoForgeName As String, LiteLoaderName As String, FabricName As String
- Dim OutputJsonPath As String, MinecraftJsonPath As String, OptiFineJsonPath As String = Nothing, ForgeJsonPath As String = Nothing, NeoForgeJsonPath As String = Nothing, LiteLoaderJsonPath As String = Nothing, FabricJsonPath As String = Nothing
- Dim OutputJar As String, MinecraftJar As String
-#Region "初始化路径信息"
- If Not OutputFolder.EndsWithF("\") Then OutputFolder += "\"
- OutputName = PathUtils.GetLastPart(OutputFolder)
- OutputJsonPath = OutputFolder & OutputName & ".json"
- OutputJar = OutputFolder & OutputName & ".jar"
-
- If Not MinecraftFolder.EndsWithF("\") Then MinecraftFolder += "\"
- MinecraftName = PathUtils.GetLastPart(MinecraftFolder)
- MinecraftJsonPath = MinecraftFolder & MinecraftName & ".json"
- MinecraftJar = MinecraftFolder & MinecraftName & ".jar"
-
- If HasOptiFine Then
- If Not OptiFineFolder.EndsWithF("\") Then OptiFineFolder += "\"
- OptiFineName = PathUtils.GetLastPart(OptiFineFolder)
- OptiFineJsonPath = OptiFineFolder & OptiFineName & ".json"
- End If
-
- If HasForge Then
- If Not ForgeFolder.EndsWithF("\") Then ForgeFolder += "\"
- ForgeName = PathUtils.GetLastPart(ForgeFolder)
- ForgeJsonPath = ForgeFolder & ForgeName & ".json"
- End If
-
- If HasNeoForge Then
- If Not NeoForgeFolder.EndsWithF("\") Then NeoForgeFolder += "\"
- NeoForgeName = PathUtils.GetLastPart(NeoForgeFolder)
- NeoForgeJsonPath = NeoForgeFolder & NeoForgeName & ".json"
- End If
-
- If HasLiteLoader Then
- If Not LiteLoaderFolder.EndsWithF("\") Then LiteLoaderFolder += "\"
- LiteLoaderName = PathUtils.GetLastPart(LiteLoaderFolder)
- LiteLoaderJsonPath = LiteLoaderFolder & LiteLoaderName & ".json"
- End If
-
- If HasFabric Then
- If Not FabricFolder.EndsWithF("\") Then FabricFolder += "\"
- FabricName = PathUtils.GetLastPart(FabricFolder)
- FabricJsonPath = FabricFolder & FabricName & ".json"
- End If
-#End Region
-
- Dim OutputJson As JObject, MinecraftJson As JObject, OptiFineJson As JObject = Nothing, ForgeJson As JObject = Nothing, NeoForgeJson As JObject = Nothing, LiteLoaderJson As JObject = Nothing, FabricJson As JObject = Nothing
-#Region "读取文件并检查文件是否合规"
- Dim MinecraftJsonText As String = If(FileUtils.TryReadAsString(MinecraftJsonPath), "")
- If Not MinecraftJsonText.StartsWithF("{") Then Throw New Exception("Minecraft json 有误,地址:" & MinecraftJsonPath & ",前段内容:" & MinecraftJsonText.Substring(0, Math.Min(MinecraftJsonText.Length, 1000)))
- MinecraftJson = MinecraftJsonText.DeserializeJson()
-
- If HasOptiFine Then
- Dim OptiFineJsonText As String = If(FileUtils.TryReadAsString(OptiFineJsonPath), "")
- If Not OptiFineJsonText.StartsWithF("{") Then Throw New Exception("OptiFine json 有误,地址:" & OptiFineJsonPath & ",前段内容:" & OptiFineJsonText.Substring(0, Math.Min(OptiFineJsonText.Length, 1000)))
- OptiFineJson = OptiFineJsonText.DeserializeJson()
- End If
-
- If HasForge Then
- Dim ForgeJsonText As String = If(FileUtils.TryReadAsString(ForgeJsonPath), "")
- If Not ForgeJsonText.StartsWithF("{") Then Throw New Exception("Forge json 有误,地址:" & ForgeJsonPath & ",前段内容:" & ForgeJsonText.Substring(0, Math.Min(ForgeJsonText.Length, 1000)))
- ForgeJson = ForgeJsonText.DeserializeJson()
- End If
-
- If HasNeoForge Then
- Dim NeoForgeJsonText As String = If(FileUtils.TryReadAsString(NeoForgeJsonPath), "")
- If Not NeoForgeJsonText.StartsWithF("{") Then Throw New Exception("NeoForge json 有误,地址:" & NeoForgeJsonPath & ",前段内容:" & NeoForgeJsonText.Substring(0, Math.Min(NeoForgeJsonText.Length, 1000)))
- NeoForgeJson = NeoForgeJsonText.DeserializeJson()
- End If
-
- If HasLiteLoader Then
- Dim LiteLoaderJsonText As String = If(FileUtils.TryReadAsString(LiteLoaderJsonPath), "")
- If Not LiteLoaderJsonText.StartsWithF("{") Then Throw New Exception("LiteLoader json 有误,地址:" & LiteLoaderJsonPath & ",前段内容:" & LiteLoaderJsonText.Substring(0, Math.Min(LiteLoaderJsonText.Length, 1000)))
- LiteLoaderJson = LiteLoaderJsonText.DeserializeJson()
- End If
-
- If HasFabric Then
- Dim FabricJsonText As String = If(FileUtils.TryReadAsString(FabricJsonPath), "")
- If Not FabricJsonText.StartsWithF("{") Then Throw New Exception("Fabric json 有误,地址:" & FabricJsonPath & ",前段内容:" & FabricJsonText.Substring(0, Math.Min(FabricJsonText.Length, 1000)))
- FabricJson = FabricJsonText.DeserializeJson()
- End If
-#End Region
-
-#Region "处理 JSON 文件"
- '获取 minecraftArguments
- Dim AllArguments As String =
- If(MinecraftJson("minecraftArguments"), " ").ToString & " " &
- If(OptiFineJson IsNot Nothing, If(OptiFineJson("minecraftArguments"), " ").ToString, " ") & " " &
- If(ForgeJson IsNot Nothing, If(ForgeJson("minecraftArguments"), " ").ToString, " ") & " " &
- If(NeoForgeJson IsNot Nothing, If(NeoForgeJson("minecraftArguments"), " ").ToString, " ") & " " &
- If(LiteLoaderJson IsNot Nothing, If(LiteLoaderJson("minecraftArguments"), " ").ToString, " ")
- '分割参数字符串
- Dim RawArguments As List(Of String) = AllArguments.Split(" ", True).Select(Function(l) l.Trim).ToList
- Dim SplitArguments As New List(Of String)
- For i = 0 To RawArguments.Count - 1
- If RawArguments(i).StartsWithF("-") Then
- SplitArguments.Add(RawArguments(i))
- ElseIf SplitArguments.Any AndAlso SplitArguments.Last.StartsWithF("-") AndAlso Not SplitArguments.Last.Contains(" ") Then
- SplitArguments(SplitArguments.Count - 1) = SplitArguments.Last & " " & RawArguments(i)
- Else
- SplitArguments.Add(RawArguments(i))
- End If
- Next
- Dim RealArguments As String = SplitArguments.Distinct.Join(" ")
- '合并
- '相关讨论见 #2801
- OutputJson = MinecraftJson
- If HasOptiFine Then
- '合并 OptiFine
- OptiFineJson.Remove("releaseTime")
- OptiFineJson.Remove("time")
- OutputJson.Merge(OptiFineJson)
- End If
- If HasForge Then
- '合并 Forge
- ForgeJson.Remove("releaseTime")
- ForgeJson.Remove("time")
- OutputJson.Merge(ForgeJson)
- End If
- If HasNeoForge Then
- '合并 NeoForge
- NeoForgeJson.Remove("releaseTime")
- NeoForgeJson.Remove("time")
- OutputJson.Merge(NeoForgeJson)
- End If
- If HasLiteLoader Then
- '合并 LiteLoader
- LiteLoaderJson.Remove("releaseTime")
- LiteLoaderJson.Remove("time")
- OutputJson.Merge(LiteLoaderJson)
- End If
- If HasFabric Then
- '合并 Fabric
- FabricJson.Remove("releaseTime")
- FabricJson.Remove("time")
- OutputJson.Merge(FabricJson)
- End If
- '修改
- If RealArguments IsNot Nothing AndAlso RealArguments.Replace(" ", "") <> "" Then OutputJson("minecraftArguments") = RealArguments
- OutputJson.Remove("_comment_")
- OutputJson.Remove("inheritsFrom")
- OutputJson.Remove("jar")
- OutputJson("id") = OutputName
-#End Region
-
-#Region "保存"
- FileUtils.Write(OutputJsonPath, OutputJson.ToString)
- FileUtils.Copy(MinecraftJar, OutputJar)
- Logger.Info($"版本合并 {OutputName} 完成")
-#End Region
-
+ If Loader.State <> LoadState.Failed AndAlso Loader.State <> LoadState.Canceled Then Return
+ RunInThread(
+ Sub()
+ Try
+ Thread.Sleep(1000) '防止存在尚未完全释放的文件,导致清理失败(例如整合包安装)
+ '删除版本文件夹
+ If DirectoryUtils.Exists(Loader.Input & "saves\") OrElse DirectoryUtils.Exists(Loader.Input & "versions\") Then
+ Logger.Warn($"由于版本已被独立启动,不清理版本文件夹:{Loader.Input}")
+ Else
+ Logger.Warn($"由于下载失败或取消,清理版本文件夹:{Loader.Input}")
+ DirectoryUtils.Delete(Loader.Input)
+ End If
+ Catch ex As Exception
+ Logger.Warn(ex, "下载失败或取消后清理版本文件夹失败")
+ End Try
+ End Sub)
End Sub
#End Region
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
index 2e97def..6a8a852 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
@@ -1,7 +1,7 @@
@@ -14,19 +14,96 @@
+
+
+
+
+ M9.83,3.17 A1.18,1.18 0 0 1 9.83,4.83 L6.85,7.82 H14.5 A6.68,6.68 0 0 1 14.5,21.18 H11 A1.18,1.18 0 0 1 11,18.82 H14.5 A4.32,4.32 0 0 0 14.5,10.18 H6.85 L9.83,13.17 A1.18,1.18 0 0 1 8.17,14.83 L3.17,9.83 A1.18,1.18 0 0 1 3.17,8.17 L8.17,3.17 A1.18,1.18 0 0 1 9.83,3.17 Z
+ 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
+
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+