Files
MRCC/launcher/PCL-CE/Plain Craft Launcher 2/Modules/Minecraft/ModFolder.cs
T
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

231 lines
8.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using PCL.Core.App;
using PCL.Core.App.Localization;
using PCL.Core.Utils;
using PCL.Core.Utils.Exts;
namespace PCL;
public static class ModFolder
{
/// <summary>
/// 当前的 Minecraft 文件夹路径,以"\"结尾。
/// </summary>
public static string mcFolderSelected;
/// <summary>
/// 当前的 Minecraft 文件夹列表。
/// </summary>
public static List<McFolder> mcFolderList = new();
public class McFolder // 必须是 Class,否则不是引用类型,在 ForEach 中不会得到刷新
{
public enum Types
{
Original,
RenamedOriginal,
Custom
}
/// <summary>
/// 文件夹路径。
/// 以 \ 结尾,例如 "D:\Game\MC\.minecraft\"。
/// </summary>
public string Location;
public string Name;
public Types type;
public override bool Equals(object obj)
{
if (obj is not McFolder)
return false;
var folder = (McFolder)obj;
return (Name ?? "") == (folder.Name ?? "") && (Location ?? "") == (folder.Location ?? "") &&
type == folder.type;
}
public override string ToString()
{
return Location;
}
}
/// <summary>
/// 加载 Minecraft 文件夹列表。
/// </summary>
public static ModLoader.LoaderTask<int, int> mcFolderListLoader = new("Minecraft Folder List",
_ => McFolderListLoadSub(), priority: ThreadPriority.AboveNormal);
private static void McFolderListLoadSub()
{
try
{
// 初始化
var cacheMcFolderList = new List<McFolder>();
#region 读取自定义(Custom)文件夹,可能没有结果
// 格式:TMZ 12>C://xxx/xx/|Test>D://xxx/xx/|名称>路径
foreach (string folder in (IEnumerable)((dynamic)States.Game.Folders).Split("|"))
{
if (string.IsNullOrEmpty(folder))
continue;
if (!folder.Contains(">") || !folder.EndsWithF(@"\"))
{
HintService.Hint(Lang.Text("Select.Folder.Invalid", folder), HintType.Error);
continue;
}
var name = folder.Split(">")[0];
var path = folder.Split(">")[1];
try
{
ModBase.CheckPermissionWithException(path);
cacheMcFolderList.Add(new McFolder { Name = name, Location = path, type = McFolder.Types.Custom });
}
catch (Exception ex)
{
ModMain.MyMsgBox(
Lang.Text("Select.Folder.Invalid.WithDetail", path, ex.ToString()),
Lang.Text("Select.Folder.InvalidTitle"), isWarn: true);
ModBase.Log(ex, $"无法访问 Minecraft 文件夹 {path}");
}
}
#endregion
#region 读取默认(Original)文件夹,即当前、官启文件夹,可能没有结果
var currentMcFolderList = new List<McFolder>();
var originalMcFolderList = new List<McFolder>();
// 扫描当前文件夹
try
{
if (Directory.Exists(ModBase.exePath + @"versions\"))
originalMcFolderList.Add(new McFolder
{ Name = Lang.Text("Select.Folder.CurrentFolder"), Location = ModBase.exePath, type = McFolder.Types.Original });
foreach (var folder in new DirectoryInfo(ModBase.exePath).GetDirectories())
if (Directory.Exists(Path.Combine(folder.FullName, "versions")) || folder.Name == ".minecraft")
{
var newCurrentFolder = new McFolder
{ Name = folder.Name, Location = folder.FullName + @"\", type = McFolder.Types.Original };
originalMcFolderList.Add(newCurrentFolder);
currentMcFolderList.Add(newCurrentFolder);
}
}
catch (Exception ex)
{
ModBase.Log(ex, "扫描 PCL 所在文件夹中是否有 MC 文件夹失败");
}
// 扫描官启文件夹
var mojangPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".minecraft") + @"\";
if ((!currentMcFolderList.Any() || (mojangPath ?? "") != (currentMcFolderList[0].Location ?? "")) &&
Directory.Exists(Path.Combine(mojangPath, "versions"))) // 当前文件夹不是官启文件夹
// 具有权限且存在 versions 文件夹
originalMcFolderList.Add(new McFolder
{ Name = Lang.Text("Select.Folder.OfficialLauncherFolder"), Location = mojangPath, type = McFolder.Types.Original });
ModBase.Log(cacheMcFolderList.Count + " 个自定义文件夹," + originalMcFolderList.Count + " 个原始文件夹");
foreach (var newOriginalFolder in originalMcFolderList)
{
var unAdded = true;
foreach (var cacheFolder in cacheMcFolderList)
if ((cacheFolder.Location ?? "") == (newOriginalFolder.Location ?? ""))
{
if ((cacheFolder.Name ?? "") != (newOriginalFolder.Name ?? ""))
cacheFolder.type = McFolder.Types.RenamedOriginal;
else
cacheFolder.type = McFolder.Types.Original;
unAdded = false;
}
if (unAdded)
cacheMcFolderList.Add(newOriginalFolder); // 如果没有重命名,则添加当前文件夹
}
#endregion
#region 读取自定义文件夹情况并写入设置
// 将自定义文件夹情况同步到设置
var config = new List<string>();
foreach (var Folder in cacheMcFolderList)
config.Add(Folder.Name + ">" + Folder.Location);
if (!config.Any())
config.Add(""); // 防止 0 元素 Join 返回 Nothing
States.Game.Folders = config.Join("|");
#endregion
// 若没有可用文件夹,则创建 .minecraft
if (!cacheMcFolderList.Any())
{
Directory.CreateDirectory(ModBase.exePath + @".minecraft\versions\");
cacheMcFolderList.Add(new McFolder
{ Name = Lang.Text("Select.Folder.CurrentFolder"), Location = ModBase.exePath + @".minecraft\", type = McFolder.Types.Original });
}
foreach (var Folder in cacheMcFolderList) McFolderLauncherProfilesJsonCreate(Folder.Location);
if (Config.Debug.AddRandomDelay)
Thread.Sleep(RandomUtils.NextInt(200, 2000));
// 回设
mcFolderList = cacheMcFolderList;
}
catch (Exception ex)
{
ModBase.Log(
ex,
Lang.Text("Select.Folder.Error.Load"),
ModBase.LogLevel.Feedback,
userSummary: Lang.Text("Select.Folder.Error.Load"));
}
}
/// <summary>
/// 为 Minecraft 文件夹创建 launcher_profiles.json 文件。
/// </summary>
public static void McFolderLauncherProfilesJsonCreate(string folder)
{
try
{
if (File.Exists(Path.Combine(folder, "launcher_profiles.json")))
return;
var now = DateTime.Now;
var resultJson = @"{
""profiles"": {
""PCL"": {
""icon"": ""Grass"",
""name"": ""PCL"",
""lastVersionId"": ""latest-release"",
""type"": ""latest-release"",
""lastUsed"": """ + now.ToString("yyyy'-'MM'-'dd", CultureInfo.InvariantCulture) + "T" +
now.ToString("HH':'mm':'ss", CultureInfo.InvariantCulture) + @".0000Z""
}
},
""selectedProfile"": ""PCL"",
""clientToken"": ""23323323323323323323323323323333""
}";
ModBase.WriteFile(Path.Combine(folder, "launcher_profiles.json"), resultJson, encoding: Encoding.GetEncoding("GB18030"));
ModBase.Log("[Minecraft] 已创建 launcher_profiles.json" + folder);
}
catch (Exception ex)
{
ModBase.Log(
ex,
"创建 launcher_profiles.json 失败(" + folder + "",
ModBase.LogLevel.Feedback,
userSummary: Lang.Text("Minecraft.Folder.Error.OperationFailed"));
}
}
}