三国卡牌客户端基础资源仓库
hch
2026-05-19 2b58e2ea2fc26e9aa58e960c2bbcde8f564ba0ae
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
 
/// <summary>
/// 配置生成器 - 用于自动生成配置管理器代码
/// </summary>
public static class ConfigGenerater
{
    // 常量定义
    private const string ResourcesOutConfigPath = "Assets/ResourcesOut/Config";
    private const string ConfigClassesPath = "Assets/Scripts/Main/Config/Configs";
    private const string ConfigManagerPath = "Assets/Scripts/Main/Config/ConfigManager.cs";
 
    public static List<string> ExcludeClassList = new List<string>()
    {
        //  特殊表格(由 preInitConfig 单独加载,不进入 configTypes)
        // "InitialFunctionConfig",
        // "PriorLanguageConfig",
        // "FuncConfigConfig",
 
        //  暂时无用的表
        "PlayerFacePicStarConfig",
        "PlayerFaceStarConfig",
    };
 
    [MenuItem("Tools/手动刷新")]
    public static void Refresh()
    {
        AssetDatabase.Refresh();
    }
 
    /// <summary>
    /// 生成配置管理器菜单项
    /// </summary>
    [MenuItem("Tools/生成配置管理器")]
    public static void Generate()
    {
        try
        {
            // 1. 获取所有配置类(去除排除项)
            List<string> configClasses = GetAllConfigClasses()
                .Where(c => !ExcludeClassList.Contains(c))
                .Where(c => !string.IsNullOrEmpty(c) && char.IsUpper(c[0]))
                .ToList();
 
            string configManagerPath = Path.Combine(Application.dataPath, ConfigManagerPath.Replace("Assets/", ""));
            var lines = File.ReadAllLines(configManagerPath).ToList();
 
            // --- 更新 configTypes HashSet ---
            int loadConfigsIdx = lines.FindIndex(l => l.Contains("protected async UniTask LoadConfigs()"));
            if (loadConfigsIdx < 0)
            {
                Debug.LogError("未找到 'protected async UniTask LoadConfigs()',请检查 ConfigManager.cs 结构。");
                return;
            }
 
            var configTypeLines = new List<string>();
            configTypeLines.Add("        // 加载配置文件");
            configTypeLines.Add("        HashSet<Type> configTypes = new HashSet<Type>() {");
            for (int i = 0; i < configClasses.Count; i++)
            {
                configTypeLines.Add($"            typeof({configClasses[i]}){(i < configClasses.Count - 1 ? "," : "")}");
            }
            configTypeLines.Add("        };");
 
            int configTypesStart = lines.FindIndex(loadConfigsIdx, l => l.Contains("HashSet<Type> configTypes"));
            int configTypesEnd = configTypesStart;
            while (configTypesEnd < lines.Count && !lines[configTypesEnd].Trim().EndsWith("};")) configTypesEnd++;
            configTypesEnd++;
            lines.RemoveRange(configTypesStart, configTypesEnd - configTypesStart);
            lines.InsertRange(configTypesStart, configTypeLines);
 
            // --- 更新 Release() 方法体 ---
            int releaseIdx = lines.FindIndex(l => l.TrimStart().StartsWith("public override void Release()"));
            if (releaseIdx >= 0)
            {
                int releaseOpen = lines.FindIndex(releaseIdx, l => l.Trim() == "{");
                int releaseClose = releaseOpen;
                int braceCount = 1;
                for (int i = releaseOpen + 1; i < lines.Count; i++)
                {
                    foreach (char ch in lines[i])
                    {
                        if (ch == '{') braceCount++;
                        if (ch == '}') braceCount--;
                    }
                    if (braceCount == 0) { releaseClose = i; break; }
                }
 
                var releaseLines = new List<string>();
                foreach (string className in configClasses)
                {
                    releaseLines.Add($"        // 清空 {className} 字典");
                    releaseLines.Add($"        ClearConfigDictionary<{className}>();");
                }
                lines.RemoveRange(releaseOpen + 1, releaseClose - releaseOpen - 1);
                lines.InsertRange(releaseOpen + 1, releaseLines);
            }
 
            // 保存文件
            File.WriteAllLines(configManagerPath, lines);
 
            Debug.Log($"ConfigManager.cs 自动生成成功,共 {configClasses.Count} 个类型。");
            AssetDatabase.Refresh();
        }
        catch (Exception ex)
        {
            Debug.LogError($"自动生成 ConfigManager 时发生错误: {ex.Message}\n{ex.StackTrace}");
        }
    }
 
    /// <summary>
    /// 获取所有配置类
    /// </summary>
    /// <returns>配置类名称列表</returns>
    public static List<string> GetAllConfigClasses()
    {
        // 以 ResourcesOut/Config 为权威来源,扫描 .txt 文件生成类名
        string fullResPath = Path.Combine(Application.dataPath, ResourcesOutConfigPath.Replace("Assets/", ""));
        string fullCsPath  = Path.Combine(Application.dataPath, ConfigClassesPath.Replace("Assets/", ""));
 
        if (!Directory.Exists(fullResPath))
        {
            Debug.LogError($"ResourcesOut/Config 目录不存在: {fullResPath}");
            return new List<string>();
        }
 
        try
        {
            List<string> configClasses = new List<string>();
 
            // 扫描 ResourcesOut/Config 下的 .txt 文件,构造类名 = 文件名 + "Config"
            string[] txtFiles = Directory.GetFiles(fullResPath, "*.txt", SearchOption.TopDirectoryOnly);
 
            foreach (string file in txtFiles)
            {
                string baseName  = Path.GetFileNameWithoutExtension(file);
                string className = baseName + "Config";
 
                // 交叉验证:对应的 C# 类文件必须存在
                string csFile = Path.Combine(fullCsPath, className + ".cs");
                if (!File.Exists(csFile))
                    continue;
 
                configClasses.Add(className);
            }
 
            return configClasses;
        }
        catch (Exception ex)
        {
            Debug.LogError($"扫描配置类时发生错误: {ex.Message}");
            return new List<string>();
        }
    }
}