using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEditor; using System.Text; using System; using Game.Config; using RO.Editor; using LuaInterface; using System.Linq; using System.Text.RegularExpressions; public class CfgLanguageCfg : GameData { public string CfgName; public string Field; public string CfgID; public int CfgType; public int Enable; public CfgLanguageCfg() { CfgName = ""; Field = ""; CfgID = ""; CfgType = 0; Enable = 0; } public static void OnCsvLoad(CsvReader csvReader) { CfgLanguageCfg.Onload(csvReader); } public static string FileName_S() { return ""; } } public class LanguageCfg : GameData { public string key; public string Language; public LanguageCfg() { key = ""; Language = ""; } public static void OnCsvLoad(CsvReader csvReader) { LanguageCfg.Onload(csvReader); } public static string FileName_S() { return ""; } } public class CsvToLua : EditorWindow { public static string CSV_PATH = "csv path"; public static string LUA_PATH = "lua path"; public static string START_LINE = "start line"; public string tableDirectoryName; public string luaDirectoryName; public int startDataLine = 1; public static bool IsObj; [MenuItem("Tools/CsvToLua")] static void Init() { CsvToLua window = (CsvToLua)GetWindow(typeof(CsvToLua)); window.Show(); } void OnEnable() { tableDirectoryName = EditorPrefs.GetString(CSV_PATH); luaDirectoryName = EditorPrefs.GetString(LUA_PATH); startDataLine = EditorPrefs.GetInt(START_LINE); } void OnDisable() { EditorPrefs.SetString(CSV_PATH, tableDirectoryName); EditorPrefs.SetString(LUA_PATH, luaDirectoryName); EditorPrefs.SetInt(START_LINE, startDataLine); } private void OnGUI() { GUILayout.Label("Base Settings", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); tableDirectoryName = EditorGUILayout.TextField("TableDirectory Name", tableDirectoryName); if (GUILayout.Button("选择csv路径", GUILayout.Width(200))) { tableDirectoryName = GetFilePath(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); luaDirectoryName = EditorGUILayout.TextField("LuaDirectory Name", luaDirectoryName); if (GUILayout.Button("选择到处table路径", GUILayout.Width(200))) { luaDirectoryName = GetFilePath(); } EditorGUILayout.EndHorizontal(); startDataLine = EditorGUILayout.IntField("StartDataLine", startDataLine); if (GUILayout.Button("CsvToLua")) Change(); if (GUILayout.Button("测试")) { string lua = @"local aaa = { [1] = { ['a'] = 1, ['b'] = '2', ['c'] = 'asd' , ['d'] = {1,2,3,{{1,2},{3,4},{1.2,0},{0}}}, ['aId'] = 1, } , } return aaa"; using (LuaState runTime = new LuaState()) { runTime.Start(); //LuaState runTime = LuaClient.Instance.luaState; runTime.DoFile("Assets\\Editor\\CsvToLua\\table-save.lua"); LuaTable luaTable = runTime.DoString(lua); RolePreviewWindow.SaveToLua(runTime, "aaa.lua", luaTable, "AAA",""); } } if (GUILayout.Button("检查")) { CheckCgf(); } IsObj = GUILayout.Toggle(IsObj,"运行时启动"); if (GUILayout.Button("更改CardCfg")) { ChangeLuaCfg("Assets/Lua/Config/CardCfg.lua", "Assets\\Editor\\CsvToLua\\LuaCfg.lua", "Build/NewCfg/CardCfg.lua"); } if (GUILayout.Button("合并Language")) { MergeLanauage("Assets/Content/Config/LanguagePackage_cn.csv", "Build/NewCfg/ROLanguagePackage_cn.csv", "Build/NewCfg/Language_merge.csv"); } } public static string GetFilePath() { OpenDialogDir ofn2 = new OpenDialogDir(); ofn2.pszDisplayName = new string(new char[2000]); ; // 存放目录路径缓冲区 ofn2.lpszTitle = "Open Project";// 标题 //ofn2.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX; // 新的样式,带编辑框 IntPtr pidlPtr = DllOpenFileDialog.SHBrowseForFolder(ofn2); char[] charArray = new char[2000]; for (int i = 0; i < 2000; i++) charArray[i] = '\0'; DllOpenFileDialog.SHGetPathFromIDList(pidlPtr, charArray); string fullDirPath = new String(charArray); fullDirPath = fullDirPath.Substring(0, fullDirPath.IndexOf('\0')); return fullDirPath; } public void Change() { Debug.Log(tableDirectoryName); foreach (var item in Directory.GetFiles(tableDirectoryName)) { if (item.Contains(".meta")) continue; CreatLuaTable(item); } } void CreatLuaTable(string filePath) { CreatDirectory(); Save(GetSavePath(filePath), GetSaveContext(filePath)); } void CreatDirectory() { string path = luaDirectoryName; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); AssetDatabase.Refresh(); } } string GetSavePath(string filePath) { string fileName = GetFileName(filePath); return luaDirectoryName + "/" + fileName + ".lua"; } string GetFileName(string filePath) { string targetPath = filePath.Replace(@"\", "/"); string[] strs = targetPath.Split('/'); targetPath = strs[strs.Length - 1]; strs = targetPath.Split('.'); string fileName = strs[0]; return fileName; } string GetSaveContext(string filePath) { string fileName = GetFileName(filePath); List context = GetContext(filePath); string[] propertyName = GetPropertyName(context[1]); string[] typeName = GetPropertyName(context[2]); StringBuilder sb = new StringBuilder(); sb.Append("local " + fileName + " = {" + "\n"); for (int i = startDataLine; i < context.Count; i++) { context[i] = context[i].Replace(" ", ""); string[] details = context[i].Split(','); sb.Append("[" + details[0] + "]={" + "\n"); for (int j = 0; j < propertyName.Length; j++) { sb.Append("['" + propertyName[j] + "']="); if (typeName[j].Equals("string")) sb.Append("'" + details[j] + "'," + "\n"); else if (typeName[j].Equals("bool")) { sb.Append(details[j].ToLower() + "," + "\n"); } else if (typeName[j].Equals("list")) { if (details[j].IndexOf(';') > 0) { ParseTable(sb, details[j], ';'); } else if (details[j].IndexOf(':') > 0 && details[j].IndexOf(';') < 0) { sb.Append("{"); ParseTable(sb, details[j], ':'); sb.Append("}"); } else { sb.Append("{"); try { if (details[j].IndexOf('.') > 0) { Convert.ToDouble(details[j]); } else { Convert.ToInt32(details[j]); } sb.Append(details[j]); } catch { if (!string.IsNullOrEmpty(details[j])) sb.Append("'" + details[j] + "'"); } sb.Append("}"); } sb.Append(",\n"); } else if (typeName[j].Equals("enum")) { sb.Append("Enum." + propertyName[j] + "." + details[j] + "," + "\n"); } else { string num = "0"; if (details[j] != "") { num = details[j]; } sb.Append(num + "," + "\n"); } } sb.Append("}," + "\n"); } sb.Append("}" + "\n"); sb.Append("return " + fileName); return sb.ToString(); } void ParseTable(StringBuilder sb, string content, char split) { string[] strs = content.Split(split); sb.Append("{"); for (int m = 0; m < strs.Length; ++m) { try { if (strs[m].IndexOf(':') > 0) { ParseTable(sb, strs[m], ':'); } else { if (strs[m].IndexOf('.') > 0) { Convert.ToDouble(strs[m]); } else { Convert.ToInt32(strs[m]); } sb.Append(strs[m]); } } catch { if (!string.IsNullOrEmpty(strs[m])) sb.Append("'" + strs[m] + "'"); } if (m < strs.Length - 1) { sb.Append(","); } } sb.Append("}"); } List GetContext(string filePath) { StreamReader sr = new StreamReader(filePath); List contexts = new List(); string line; while ((line = sr.ReadLine()) != null) contexts.Add(line); return contexts; } string[] GetPropertyName(string line) { string[] names = line.Split(','); return names; } void Save(string path, string information) { if (File.Exists(path)) File.Delete(path); FileStream aFile = new FileStream(@"" + path, FileMode.OpenOrCreate, FileAccess.ReadWrite); StreamWriter sw = new StreamWriter(aFile); sw.Write(information); sw.Close(); sw.Dispose(); aFile.Close(); aFile.Dispose(); sw = null; aFile = null; AssetDatabase.Refresh(); } public static Dictionary> GetCfgLanguageCfg(string path) { Dictionary> ret = new Dictionary>(); TextAsset ta = AssetDatabase.LoadAssetAtPath(path); CsvReader csvReader = new CsvReader(CfgLanguageCfg.FileName_S(), ta.bytes); CfgLanguageCfg.OnCsvLoad(csvReader); CfgLanguageCfg.Foreach(it => { if (it.Enable == 0) { return; } if (ret.ContainsKey(it.CfgName)) { ret[it.CfgName].Add(it); } else { List cfgs = new List(); cfgs.Add(it); ret.Add(it.CfgName,cfgs); } //Debug.Log(it.BaseName); }); CfgLanguageCfg.Clear(); return ret; } public static Dictionary GetLanguageCfg(string path) { Dictionary ret = new Dictionary(); TextAsset ta = AssetDatabase.LoadAssetAtPath(path); CsvReader csvReader = new CsvReader(LanguageCfg.FileName_S(), ta.bytes,1,2,3); LanguageCfg.OnCsvLoad(csvReader); LanguageCfg.Foreach(it => { if (!ret.ContainsKey(it.key)) { ret.Add(it.key, it); } else { ret.Add(it.key+ret.Count,it); Debug.Log("重复项:" + it.key); } //Debug.Log(it.BaseName); }); LanguageCfg.Clear(false); return ret; } public static void CheckCgf() { string luaPath = "Assets/Lua/Config/"; string csvPath = "Assets/Content/Config/"; string OutPutPath = "Build/NewCfg/"; Dictionary> cfgs = GetCfgLanguageCfg("Assets/Editor/CsvToLua/CfgLanguageCfg.csv"); Dictionary language = GetLanguageCfg("Assets/Content/Config/LanguagePackage_cn.csv"); float ckcount = 0; foreach (var item in cfgs) { ckcount+=1; List value = item.Value; EditorUtility.DisplayProgressBar("检测配置中", $"检测:{item.Key}...", ckcount/cfgs.Count); string cfgPath = ""; if (value[0].CfgType == 1) { cfgPath = luaPath + item.Key + ".lua"; CheckLauCfg_CS(value,cfgPath,language, $"{OutPutPath}lua/{value[0].CfgName}.lua"); } else { cfgPath = csvPath + item.Key + ".csv"; CheckCsvCfg(value, cfgPath, language, $"{OutPutPath}csv/{value[0].CfgName}.csv"); } } EditorUtility.ClearProgressBar(); CsvWriter csvWriter = new CsvWriter(OutPutPath+ "Language.csv", "Language.csv",language.Values.ToList(), LanguageCfg.GetFormatInfo()); csvWriter.Write(); } private static void CheckLauCfg(List cfg,string path, Dictionary language,string outputPath) { using (LuaState runTime = new LuaState()) { runTime.Start(); RolePreviewWindow.LuaForEach(runTime, path, (id,luatable) => { for (int i = 0; i < cfg.Count; i++) { if (cfg[i].Enable == 0) continue; string value = luatable.RawGet(cfg[i].Field); if (string.IsNullOrEmpty(value)) { continue; } KeyValuePair valuePair = language.FirstOrDefault(it => { return string.Equals(it.Value.Language, value); }); if (!string.IsNullOrEmpty(valuePair.Key)) { luatable.RawSet(cfg[i].Field, valuePair.Key); } else { string key = cfg[i].CfgID + id; luatable.RawSet(cfg[i].Field, key); if (value.Contains("\n")) { Debug.Log(value); value = value.Replace("\n","\\n"); Debug.Log(value); } language.Add(key,new LanguageCfg() { key = key,Language = value}); } } },(ltab)=> { bool useObj = IsObj; if (useObj) { LuaState luaState = LuaClient.Instance.luaState; luaState.DoFile("Assets\\Editor\\CsvToLua\\table-save.lua"); RolePreviewWindow.SaveToLua(luaState, outputPath, ltab, cfg[0].CfgName, "1"); } else { LuaState luaState = runTime; luaState.DoFile("Assets\\Editor\\CsvToLua\\table-save.lua"); RolePreviewWindow.SaveToLua(luaState, outputPath, ltab, cfg[0].CfgName, ""); } }); } } private static void SetLuaLine(string[] rowDatas,int id,string key,string data,string dataF = "'{0}',") { string idkey = $"[{id}]"; string keykey = $"'{key}'"; string wdata = string.Format(dataF,data);//$"'{data}',"; bool isFind = false; for (int line = 0; line < rowDatas.Length; line++) { if (rowDatas[line].Trim().IndexOf("--") == 0) { Debug.Log("注释跳过"); } if (rowDatas[line].Contains(idkey)) { isFind = true; } if (isFind && rowDatas[line].Contains(keykey)) { int s = rowDatas[line].IndexOf('['); string p = ""; if (s > 0) { for (int i = 0; i < s; i++) { p += " "; } } string newstr = $"{p}[{keykey}]={wdata}" ; rowDatas[line] = newstr; break; } } } private static void CheckLauCfg_CS(List cfg, string path, Dictionary language, string outputPath) { string[] rowDatas = File.ReadAllLines(path); bool iswrite = true; using (LuaState runTime = new LuaState()) { runTime.Start(); RolePreviewWindow.LuaForEach(runTime, path, (id, luatable) => { for (int i = 0; i < cfg.Count; i++) { if (cfg[i].Enable == 0) { iswrite = false; continue; } string value = luatable.RawGet(cfg[i].Field); if (string.IsNullOrEmpty(value)) { continue; } KeyValuePair valuePair = language.FirstOrDefault(it => { return string.Equals(it.Value.Language, value); }); if (!string.IsNullOrEmpty(valuePair.Key)) { luatable.RawSet(cfg[i].Field, valuePair.Key); SetLuaLine(rowDatas,id, cfg[i].Field, valuePair.Key); } else { string key = cfg[i].CfgID + id; luatable.RawSet(cfg[i].Field, key); if (value.Contains("\n")) { //Debug.Log(value); value = value.Replace("\n", "\\n"); //Debug.Log(value); } if (!language.ContainsKey(key)) { valuePair = language.FirstOrDefault(it => { return string.Equals(it.Value.key, value); }); if (string.IsNullOrEmpty(valuePair.Key)) { SetLuaLine(rowDatas, id, cfg[i].Field, key); language.Add(key, new LanguageCfg() { key = key, Language = value }); } } } } }); } if (iswrite) File.WriteAllLines(outputPath,rowDatas); } private static void CheckCsvCfg(List cfg, string path, Dictionary language, string outputPath) { CsvReader csvReader = new CsvReader(path,1,2,3); string[][] datas = csvReader.RowDatas; for (int i = csvReader.StartLine; i < datas.Length; i++) { string[] curLine = datas[i]; for (int j = 0; j < cfg.Count; j++) { if (cfg[j].Enable == 0) continue; string value = csvReader.GetDataByFieldName(cfg[j].Field,i); if (string.IsNullOrEmpty(value)) { continue; } KeyValuePair valuePair = language.FirstOrDefault(it => { return string.Equals(it.Value.Language, value); }); if (!string.IsNullOrEmpty(valuePair.Key)) { csvReader.SetDataByFieldName(cfg[j].Field, valuePair.Key, i); } else { string key = cfg[j].CfgID + i; csvReader.SetDataByFieldName(cfg[j].Field, key,i); language.Add(key, new LanguageCfg() { key = key, Language = value }); } } } FileHelper.WirteStringToFile(outputPath,csvReader.GetString()); } private static void ChangeLuaCfg(string luacfgpath,string luachagepath,string outputPath) { string[] rowDatas = File.ReadAllLines(luacfgpath); using (LuaState runTime = new LuaState()) { runTime.Start(); LuaTable luaTable = runTime.DoFile(luachagepath); RolePreviewWindow.LuaForEach(runTime, luacfgpath, (id, luatable) => { LuaFunction luaFunction = luaTable.GetLuaFunction("IsChangefg"); bool ischange = luaFunction.Invoke(luaTable,luatable); if (ischange) { LuaTable fieldValue = luaTable.Invoke("GetFieldAddValue", luaTable); string field = fieldValue.RawGet("field"); string value = fieldValue.RawGet("value"); SetLuaLine(rowDatas,id,field,value.ToString(),"{0},"); } }); } File.WriteAllLines(outputPath, rowDatas); } struct lgInfo { public int index; public int off; } private static void MergeLanauage(string oldPath,string newPath, string outputPath) { List oldLg = File.ReadAllLines(oldPath).ToList(); List newLg = File.ReadAllLines(newPath).ToList(); Dictionary cfgmap = new Dictionary(); int length = oldLg.Count; int off = -1; for (int i = 0; i < length; i++) { off = oldLg[i].IndexOf(','); if (off < 0) { continue; } string key = oldLg[i].Substring(0,off); if (!cfgmap.ContainsKey(key)) { lgInfo info = new lgInfo(); info.index = i; info.off = off; cfgmap.Add(key, info); } } foreach (var item in newLg) { if (item == "" || item == ","||item == "key"||item == "string") continue; off = item.IndexOf(','); if (off < 0) { continue; } string key = item.Substring(0,off); if (!cfgmap.ContainsKey(key)) { Debug.Log($"不包含:{key} off = {off}"); oldLg.Add(item); } else { lgInfo lgIf = cfgmap[key]; oldLg[lgIf.index] = item; } } string data = FileHelper.CatStringArray(oldLg,"\r\n"); FileHelper.WirteStringToFile(outputPath, data); } }