Просмотр исходного кода

Merge branch 'main' of ssh://192.168.0.8:29418/XianJing into hy_en

ybx_Gdn 1 год назад
Родитель
Сommit
be532ab747

+ 0 - 2
Assets/Content/Config/LanguagePackage_cn.csv

@@ -4523,8 +4523,6 @@ SkillDesc_90635,對單體敵人發起審判,造成高額傷害,降低其防
 SkillDesc_90636,蓄力後,對全體敵人造成大量傷害,同時沉默全體並打斷
 SkillDesc_90637,蓄力後,召喚水柱衝擊單體目標,造成高額傷害,同時令其短時間降低傷害
 SkillDesc_90638,蓄力後,對全體目標造成大量傷害,同時驅散全體
-,
-,
 SkillDesc_90800,尖嘯  -  造成0.3s眩暈
 SkillDesc_90801,毒霧  -  施加持續5秒總計降低30%生命的持續傷害效果
 SkillDesc_90802,衝頂  -  額外造成0.4s眩暈

+ 83 - 0
Assets/Editor/CsvToLua/CfgLanguageCfg.csv

@@ -0,0 +1,83 @@
+ ID,CfgName,Field,CfgID,CfgType
+ int,string,string,string,int
+1,ConditionCfg,ConditionDescribe,ConditionCfg_ConditionDescribe_,1
+2,MapCfg,Name,MapCfg_Name_,0
+3,ActivitiesDiscountsCfg,Name,ADCfg_Name_,1
+4,ActivitiesTaskCfg,Title,ATCfg_Title_,1
+5,ArenaLevelCfg,ArenaLevelName,ALCfg_ArenaLevelName_,1
+6,ArtifactCfg,Name,ArtifactCfg_Name_,1
+7,BattleFailedTipsCfg,Content,BFTCfg_Content_,1
+8,BoliShopCfg,GoodsName,BSCfg_GoodsName_,1
+9,BoliShopCfg,GoodsDesc,BSCfg_GoodsDesc_,1
+10,CardCfg,CardName,CardCfg_CardName_,1
+11,CardIdentification,CardName,CI_CardName_,1
+12,CardIdentification,CardDescribe,CI_CardDescribe_,1
+13,CardSuitNewCfg,Name,CSNCfg_Name_,1
+14,DesignationCfg,Name,DCCfg_Name_,1
+15,DesignationCfg,TaskConditionDesc,DCCfg_TaskConditionDesc_,1
+16,DesignationCfg,TimeDesc,DCCfg_TimeDesc_,1
+17,EquipCfg,Name,ECfg_Name_,1
+18,EquipSuitNewCfg,Name,ESNCfg_Name_,1
+19,ExpeditionBuffCfg,Desc,EBCfg_Desc_,1
+20,ExpeditionBuffCfg,Name,EBCfg_Name_,1
+21,FashionCfg,FashionName,FCfg_FashionName_,1
+22,FashionCfg,FashionDepict,FCfg_FashionDepict_,1
+23,FashionPaperCfg,PaperName,FPCfg_PaperName_,1
+24,FashionSuitCfg,SuitName,FSCfg_SuitName_,1
+25,FightCfg,Desc,FCfg_Desc_,1
+26,GuildWarBuffCfg,Desc,GWBCfg_Desc_,1
+27,GuildWarBuffCfg,Name,GWBCfg_Name_,1
+28,GuildWarDojoCfg,Name,GWDCfg_Name_,1
+29,ItemCfg1,Describe,ICfg_Describe_,1
+30,ItemCfg1,Name,ICfg_Name_,1
+31,ItemCfg2,Describe,ICfg_Describe_,1
+32,ItemCfg2,Name,ICfg_Name_,1
+33,KeepSakeCfg,Name,KSCfg_Name_,1
+34,KeepSakeCfg,Describe,KSCfg_Describe_,1
+35,LineMissionCfg,TargetTaskDescribe,LMCfg_TargetTaskDescribe_,1
+36,MapCfg,Name,MapCfg_Name_,1
+37,MissionCfg,TargetTaskDescribe,MCfg_TargetTaskDescribe_,1
+38,NatureCfg,Name,NCfg_Name_,1
+39,NpcCfg1,Name,NpcCfg_Name_,1
+40,NpcCfg1,Desc,NpcCfg_Desc_,1
+41,NpcCfg2,Name,NpcCfg_Name_,1
+42,NpcCfg2,Desc,NpcCfg_Desc_,1
+43,NpcCfg3,Name,NpcCfg_Name_,1
+44,NpcCfg3,Desc,NpcCfg_Desc_,1
+45,ParterSkillTreeCfg,Name,PSTCfg_Name_,1
+46,PassiveSkillCfg,Name,PSCfg_Name_,1
+47,PassiveSkillCfg,Desc,PSCfg_Desc_,1
+48,PetCfg,Name,PetCfg_Name_,1
+49,PetCfg,Desc,PetCfg_Desc_,1
+50,PetEquipCfg,Name,PetEquipCfg_Name_,1
+51,PetEquipSuitCfg,Name,PetEquipSuitCfg_Name_,1
+52,PetpartnerCfg,Name,PetpartnerCfg_Name_,1
+53,RuneShopGiftsCfg,Name,RSGCfg_Name_,1
+54,RuneShopGuildBattleCfg,Name,RSGBCfg_Name_,1
+55,RuneShopGuildBattleCfg,ExtraNum,RSGBCfg_ExtraNum_,1
+56,RuneShopLimitCfg,Name,RSLCfg_Name_,1
+57,RuneShopRankAidouluCfg,Name,RSRACfg_Name_,1
+58,RuneShopRankAidouluCfg,ExtraNum,RSRACfg_ExtraNum_,1
+59,RuneShopRankArenaCfg,Name,RSRArCfg_Name_,1
+60,RuneShopRankArenaCfg,ExtraNum,RSRArCfg_ExtraNum_,1
+61,RuneShopRankMapCfg,Name,RSRMCfg_Name_,1
+62,RuneShopRankMapCfg,ExtraNum,RSRMCfg_ExtraNum_,1
+63,RuneShopRankPetCfg,Name,RSRKCfg_Name_,1
+64,RuneShopRankPetCfg,ExtraNum,RSRKCfg_ExtraNum_,1
+65,RuneShopRankSkillCfg,Name,RSRSCfg_Name_,1
+66,RuneShopRankSkillCfg,ExtraNum,RSRSCfg_ExtraNum_,1
+67,RuneShopRankTowerCfg,Name,RSRTCfg_Name_,1
+68,RuneShopRankTowerCfg,ExtraNum,RSRTCfg_ExtraNum_,1
+69,RushListTargetCfg,Label,RLTCfg_Label_,1
+70,RushListTargetCfg,Des,RLTCfg_Des_,1
+71,ShopCfg,GoodsName,ShopCfg_GoodsName_,1
+72,ShopCfg,GoodsDesc,ShopCfg_GoodsDesc_,1
+73,ShopTypeCfg,Name,ShopTypeCfg_Name_,1
+74,SkillShowCfg,Name,SkillShowCfg_Name_,1
+75,SkillSuitNewCfg,Name,SkillSuitNewCfg_Name_,1
+76,SkillUpEffectCfg1,Name,SUECfg_Name_,1
+77,SkillUpEffectCfg1,Desc,SUECfg_Desc_,1
+78,SkillUpEffectCfg2,Name,SUECfg_Name_,1
+79,SkillUpEffectCfg2,Desc,SUECfg_Desc_,1
+80,StoryChapterCfg,Name,SCCfg_Name_,1
+81,StoryChapterCfg,Content,SCCfg_Content_,1

+ 7 - 0
Assets/Editor/CsvToLua/CfgLanguageCfg.csv.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 67c5cbd7f5b4238419afa91bd8521968
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 379 - 2
Assets/Editor/CsvToLua/CsvToLua.cs

@@ -1,10 +1,68 @@
-using System.Collections;
+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<CfgLanguageCfg>
+{
+    public string CfgName;
+
+    public string Field;
+
+    public string CfgID;
+    public int CfgType;
+
+    public CfgLanguageCfg()
+    {
+        CfgName = "";
+        Field = "";
+        CfgID = "";
+        CfgType = 0;
+    }
+    public static void OnCsvLoad(CsvReader csvReader)
+    {
+        CfgLanguageCfg.Onload(csvReader);
+    }
+
+    public static string FileName_S()
+    {
+        return "";
+    }
+}
+
+
+public class LanguageCfg : GameData<LanguageCfg>
+{
+    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
 {
@@ -15,7 +73,7 @@ public class CsvToLua : EditorWindow
     public string tableDirectoryName;
     public string luaDirectoryName;
     public int startDataLine = 1;
-
+    public static bool IsObj;
 
     [MenuItem("Tools/CsvToLua")]
     static void Init()
@@ -62,6 +120,40 @@ public class CsvToLua : EditorWindow
 
         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<LuaTable>(lua);
+                RolePreviewWindow.SaveToLua(runTime, "aaa.lua", luaTable, "AAA","");
+
+            }
+
+        }
+
+
+        if (GUILayout.Button("检查"))
+        {
+            CheckCgf();
+        }
+
+        IsObj =  GUILayout.Toggle(IsObj,"运行时启动");
     }
 
     public static string GetFilePath()
@@ -285,4 +377,289 @@ public class CsvToLua : EditorWindow
 
         AssetDatabase.Refresh();
     }
+
+
+    public static Dictionary<string, List<CfgLanguageCfg>> GetCfgLanguageCfg(string path)
+    {
+        Dictionary<string, List<CfgLanguageCfg>> ret = new Dictionary<string, List<CfgLanguageCfg>>();
+        
+        TextAsset ta = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
+        CsvReader csvReader = new CsvReader(CfgLanguageCfg.FileName_S(), ta.bytes);
+        CfgLanguageCfg.OnCsvLoad(csvReader);
+        CfgLanguageCfg.Foreach(it =>
+        {
+            if (ret.ContainsKey(it.CfgName))
+            {
+                ret[it.CfgName].Add(it);
+            }
+            else 
+            {
+                List<CfgLanguageCfg> cfgs = new List<CfgLanguageCfg>();
+                cfgs.Add(it);
+                ret.Add(it.CfgName,cfgs);
+            }
+            //Debug.Log(it.BaseName);
+        });
+        CfgLanguageCfg.Clear();
+        return ret;
+    }
+
+    public static Dictionary<string, LanguageCfg> GetLanguageCfg(string path)
+    {
+        Dictionary<string, LanguageCfg> ret = new Dictionary<string, LanguageCfg>();
+       
+        TextAsset ta = AssetDatabase.LoadAssetAtPath<TextAsset>(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<string, List<CfgLanguageCfg>> cfgs = GetCfgLanguageCfg("Assets/Editor/CsvToLua/CfgLanguageCfg.csv");
+        Dictionary<string, LanguageCfg> language = GetLanguageCfg("Assets/Content/Config/LanguagePackage_cn.csv");
+        float ckcount = 0;
+        foreach (var item in cfgs)
+        {
+            ckcount+=1;
+            List<CfgLanguageCfg> 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<LanguageCfg> csvWriter = new CsvWriter<LanguageCfg>(OutPutPath+ "Language.csv", "Language.csv",language.Values.ToList(), LanguageCfg.GetFormatInfo());
+        csvWriter.Write();
+
+    }
+
+
+    private static void CheckLauCfg(List<CfgLanguageCfg> cfg,string path, Dictionary<string, LanguageCfg> language,string outputPath)
+    {
+        using (LuaState runTime = new LuaState())
+        {
+            runTime.Start();
+            RolePreviewWindow.LuaForEach<int, LuaTable>(runTime, path, (id,luatable) =>
+            {
+
+                for (int i = 0; i < cfg.Count; i++)
+                {
+                    string value = luatable.RawGet<string, string>(cfg[i].Field);
+                    if (string.IsNullOrEmpty(value))
+                    {
+                        continue;
+                    }
+                    KeyValuePair<string,LanguageCfg> valuePair = language.FirstOrDefault(it => 
+                    {                     
+                        return string.Equals(it.Value.Language, value);
+                    });
+
+                    if (!string.IsNullOrEmpty(valuePair.Key))
+                    {
+                        luatable.RawSet<string, string>(cfg[i].Field, valuePair.Key);
+                    }
+                    else
+                    {
+                        string key = cfg[i].CfgID + id;
+                        luatable.RawSet<string, string>(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 idkey = $"[{id}]";
+        string keykey = $"'{key}'";
+        string wdata = $"'{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<CfgLanguageCfg> cfg, string path, Dictionary<string, LanguageCfg> language, string outputPath)
+    {
+        string[] rowDatas = File.ReadAllLines(path);
+       
+        using (LuaState runTime = new LuaState())
+        {
+            runTime.Start();
+            RolePreviewWindow.LuaForEach<int, LuaTable>(runTime, path, (id, luatable) =>
+            {
+
+                for (int i = 0; i < cfg.Count; i++)
+                {
+                    string value = luatable.RawGet<string, string>(cfg[i].Field);
+                    if (string.IsNullOrEmpty(value))
+                    {
+                        continue;
+                    }
+                    KeyValuePair<string, LanguageCfg> valuePair = language.FirstOrDefault(it =>
+                    {
+                        return string.Equals(it.Value.Language, value);
+                    });
+
+                    if (!string.IsNullOrEmpty(valuePair.Key))
+                    {
+                        luatable.RawSet<string, string>(cfg[i].Field, valuePair.Key);
+                        SetLuaLine(rowDatas,id, cfg[i].Field, valuePair.Key);
+                    }
+                    else
+                    {
+                        string key = cfg[i].CfgID + id;
+                        luatable.RawSet<string, string>(cfg[i].Field, key);
+                        SetLuaLine(rowDatas, id, 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 });
+                    }
+
+                }
+
+            });
+
+        }
+
+        File.WriteAllLines(outputPath,rowDatas);
+
+    }
+
+    private static void CheckCsvCfg(List<CfgLanguageCfg> cfg, string path, Dictionary<string, LanguageCfg> 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++)
+            {
+                string value = csvReader.GetDataByFieldName(cfg[j].Field,i);
+
+                if (string.IsNullOrEmpty(value))
+                {
+                    continue;
+                }
+
+
+                KeyValuePair<string, LanguageCfg> 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());
+
+    }
+
+
+    
 }

+ 189 - 0
Assets/Editor/CsvToLua/table-save.lua

@@ -0,0 +1,189 @@
+do
+    -- declare local variables
+    -- // exportstring( string )
+    -- // returns a "Lua" portable version of the string
+    local function exportstring(s)
+        return string.format("%q", s)
+    end
+
+    -- // The Save Function
+    function table.save(tbl, filename)
+        local charS, charE = "   ", "\n"
+        local file, err = io.open(filename, "wb")
+        if err then
+            return err
+        end
+
+        -- initiate variables for save procedure
+        local tables, lookup = {tbl}, {
+            [tbl] = 1
+        }
+        file:write("return {" .. charE)
+
+        for idx, t in ipairs(tables) do
+            file:write("-- Table: {" .. idx .. "}" .. charE)
+            file:write("{" .. charE)
+            local thandled = {}
+
+            for i, v in ipairs(t) do
+                thandled[i] = true
+                local stype = type(v)
+                -- only handle value
+                if stype == "table" then
+                    if not lookup[v] then
+                        table.insert(tables, v)
+                        lookup[v] = #tables
+                    end
+                    file:write(charS .. "{" .. lookup[v] .. "}," .. charE)
+                elseif stype == "string" then
+                    file:write(charS .. exportstring(v) .. "," .. charE)
+                elseif stype == "number" then
+                    file:write(charS .. tostring(v) .. "," .. charE)
+                end
+            end
+
+            for i, v in pairs(t) do
+                -- escape handled values
+                if (not thandled[i]) then
+
+                    local str = ""
+                    local stype = type(i)
+                    -- handle index
+                    if stype == "table" then
+                        if not lookup[i] then
+                            table.insert(tables, i)
+                            lookup[i] = #tables
+                        end
+                        str = charS .. "[{" .. lookup[i] .. "}]="
+                    elseif stype == "string" then
+                        str = charS .. "[" .. exportstring(i) .. "]="
+                    elseif stype == "number" then
+                        str = charS .. "[" .. tostring(i) .. "]="
+                    end
+
+                    if str ~= "" then
+                        stype = type(v)
+                        -- handle value
+                        if stype == "table" then
+                            if not lookup[v] then
+                                table.insert(tables, v)
+                                lookup[v] = #tables
+                            end
+                            file:write(str .. "{" .. lookup[v] .. "}," .. charE)
+                        elseif stype == "string" then
+                            file:write(str .. exportstring(v) .. "," .. charE)
+                        elseif stype == "number" then
+                            file:write(str .. tostring(v) .. "," .. charE)
+                        end
+                    end
+                end
+            end
+            file:write("}," .. charE)
+        end
+        file:write("}")
+        file:close()
+    end
+
+    -- // The Load Function
+    function table.load(sfile)
+        local ftables, err = loadfile(sfile)
+        if err then
+            return _, err
+        end
+        local tables = ftables()
+        for idx = 1, #tables do
+            local tolinki = {}
+            for i, v in pairs(tables[idx]) do
+                if type(v) == "table" then
+                    tables[idx][i] = tables[v[1]]
+                end
+                if type(i) == "table" and tables[i[1]] then
+                    table.insert(tolinki, {i, tables[i[1]]})
+                end
+            end
+            -- link indices
+            for _, v in ipairs(tolinki) do
+                tables[idx][v[2]], tables[idx][v[1]] = tables[idx][v[1]], nil
+            end
+        end
+        return tables[1]
+    end
+    -- close do
+
+    function table.SaveTableContent(file, obj, isfirst)
+        local szType = type(obj);
+        print(szType);
+        if szType == "number" then
+            file:write(obj);
+        elseif szType == "string" then
+            file:write(string.format("\'%s\'", obj));
+        elseif szType == "boolean" then
+            local str = obj and "true" or "false"
+            file:write(str);
+        elseif szType == "table" then
+            -- 把table的内容格式化写入文件
+            isfirst = isfirst + 1
+
+            if isfirst > 3 then
+                file:write("{");
+                for i, v in pairs(obj) do
+                    table.SaveTableContent(file, v, isfirst);
+                    file:write(",");
+                end
+                file:write("}");
+            else
+                local sortParams = {}
+                local keyType = ""
+                for kv in pairs(obj) do
+                    if kv ~= nil then
+                        table.insert(sortParams, kv)
+                        keyType = type(kv)
+                    end
+                end
+
+                if keyType == "number" then
+                    table.sort(sortParams, function(a, b)
+                        return a < b
+                    end)
+                elseif keyType == "string" then
+
+                    table.sort(sortParams, function(a, b)
+                        error(string.find("1222", "Id"))
+                        if a == "Id" or (string.find(a, "Id") ~= nil and string.find(b,"Id") == nil)then
+                            return true
+                        else
+                            return a < b
+                        end
+                    end)
+                end
+
+                file:write("{\n");
+                for _, v in pairs(sortParams) do
+                    file:write("[");
+                    table.SaveTableContent(file, v, isfirst);
+                    file:write("]=");
+                    table.SaveTableContent(file, obj[v], isfirst);
+                    file:write(", \n");
+                end
+                file:write("}");
+            end
+
+        else
+            error("can't serialize a " .. szType);
+        end
+    end
+
+    function table.SaveTable(luaTable, path, TableName)
+        local file, err = io.open(path, "wb")
+        if err then
+            return err
+        end
+        assert(file);
+        local oneLine = string.format("local %s=", TableName)
+        file:write(oneLine);
+
+        table.SaveTableContent(file, luaTable, 1);
+        file:write(string.format("\n return %s", TableName));
+        file:close();
+    end
+end

+ 7 - 0
Assets/Editor/CsvToLua/table-save.lua.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: db6a46868783eea4ea614271786bc593
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 41 - 3
Assets/Editor/RolePreview/RolePreviewWindow.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
@@ -537,7 +537,7 @@ namespace RO.Editor
             {
                 Debug.LogError(c_RoleCfgPath + "存在相同的Id :" + key);
                 return;
-            }
+            }     
             RoleCfgData roleCfgData = new RoleCfgData()
             {
                 id = key,
@@ -646,10 +646,11 @@ namespace RO.Editor
             m_LanguageMap.Add(key, language);
         }
 
-        private void LuaForEach<K, V>(LuaState luaState, string luaFile, Action<K, V> foreachFun)
+        public static void LuaForEach<K, V>(LuaState luaState, string luaFile, Action<K, V> foreachFun,Action<LuaTable> EndCB = null)
         {
             using (LuaTable luaTable = luaState.DoFile<LuaTable>(luaFile))
             {
+              
                 try
                 {
                     using (LuaDictTable<K, V> luaDictTable = luaTable.ToDictTable<K, V>())
@@ -671,9 +672,46 @@ namespace RO.Editor
                 {
                     Debug.LogException(e);
                 }
+
+                EndCB?.Invoke(luaTable);
             }
         }
 
+        public static void SaveToLua(LuaState runTime,string path,LuaTable luaTable,string tableName,string log)
+        {
+            string luaCode = @"
+                local SaveHelper = {}
+               function SaveHelper:SaveToLua(path,luatable,tableName,isLog)
+                    if isLog == '1' then
+                        LogError(path)
+                    end
+                    --
+                    --local file = io.open(path, 'w')
+                    --if file then
+                    --    table.save(luatable, file)
+                    --    file:close()
+                    --    LogError('保存到路径:'..path)
+                    --else
+                    --    LogError('保存失败')
+                    --end
+                    --saveErr = table.save(luatable,path)    
+                    saveErr = table.SaveTable(luatable,path,tableName)    
+                     if isLog == '1' then
+                        if saveErr ~=  nil then 
+                            LogError('保存失败'..saveErr)
+                        else
+                            LogError('保存到路径:'..path)
+                        end    
+                    end
+                   
+               end
+                return SaveHelper
+            ";
+            LuaTable  saveHelper = runTime.DoString<LuaTable>(luaCode);
+            saveHelper.Call("SaveToLua", saveHelper, path, luaTable, tableName, log);
+        }
+
+
         private Vector3 LuaTableToVector3(LuaTable luaArrayTable)
         {
             Vector3 value = Vector3.zero;

+ 64 - 5
Assets/Src/Core/DownLoad/CsvReader.cs

@@ -11,18 +11,27 @@ namespace Game.Config
     public class CsvReader
     {
         private List<string[]> rowDatas;
+        private Dictionary<string, int> fieldKey;
         private string path;
         private Encoding encoding;
         private bool isgb2312;
-
+        private int fieldLine;
+        private int typeLine;
+        private int startLine;
         public string Name;
-        public CsvReader(string csvpath, Encoding edg = null)
+
+        public int StartLine { get { return startLine; } set { startLine = value; } }
+        public CsvReader(string csvpath, int fl = 0,int tl = 1 ,int sl = 2,Encoding edg = null)
         {
             if (string.IsNullOrEmpty(csvpath))
             {
                 throw new ArgumentNullException("path");
             }
+            fieldLine = fl;
+            typeLine = tl;
+            startLine = sl;
             rowDatas = new List<string[]>();
+            fieldKey = new Dictionary<string, int>();
             encoding = edg;
             path = csvpath;
             if (edg == null)
@@ -36,14 +45,20 @@ namespace Game.Config
             }
             Name =FileHelper.GetName(path);
             ReadFromCsv();
+            InitFieldKey();
         }
 
-        public CsvReader(string name,byte[] bytes)
+        public CsvReader(string name,byte[] bytes,int fl = 0, int tl = 1, int sl = 2)
         {
+            fieldLine = fl;
+            typeLine = tl;
+            startLine = sl;
             rowDatas = new List<string[]>();
+            fieldKey = new Dictionary<string, int>();
             isgb2312 = false;
             Name = name;
             ReadFromMemory(bytes);
+            InitFieldKey();
         }
 
         public string[][] RowDatas
@@ -56,14 +71,48 @@ namespace Game.Config
 
         public string[] Fields()
         {
-            return rowDatas[0];
+            return rowDatas[fieldLine];
         }
 
+        public string GetDataByFieldName(string fieldName,int line)
+        {
+            string ret = "";
+            if (fieldKey.ContainsKey(fieldName) && rowDatas.Count > line)
+            {
+                ret = rowDatas[line][fieldKey[fieldName]];
+            }
+            return ret;
+        }
+        public void SetDataByFieldName(string fieldName, string value,int line)
+        {
+            
+            if (fieldKey.ContainsKey(fieldName) && rowDatas.Count > line)
+            {
+                 rowDatas[line][fieldKey[fieldName]] = value;
+            }
+          
+        }
+        public bool HasField(string fieldName)
+        {
+            return fieldKey.ContainsKey(fieldName);
+        }
         public string[] Types()
         {
-            return rowDatas[1];
+            return rowDatas[typeLine];
         }
 
+
+        public string GetString()
+        {
+            StringBuilder stringBuilder = new StringBuilder();
+
+            for (int i = 0; i < rowDatas.Count; i++)
+            {
+                stringBuilder.Append(CsvWriter<GameData>.ToCsvLine(rowDatas[i]));
+            }
+
+            return stringBuilder.ToString();
+        }
         private void ReadFromCsv()//改异步
         {
             string[] datas = File.ReadAllLines(path, encoding);
@@ -98,6 +147,16 @@ namespace Game.Config
             }
         }
 
+        private void InitFieldKey()
+        {
+            string[] fields = rowDatas[fieldLine];
+
+            for (int i = 0; i < fields.Length; i++)
+            {
+                fieldKey.Add(fields[i],i);
+            }
+        }
        
+        
     }
 }

+ 16 - 6
Assets/Src/Core/DownLoad/ExcelParser.cs

@@ -22,12 +22,22 @@ namespace Game.Config
                 FieldInfo field = type.GetField(fields[i]);
                 if (field != null)
                 {
-
-                    object value = GetSetFieldValue(field.FieldType, data[i]);
-
-                    //Debug.Log(value);
-                    field.SetValue(obj, value);
-                }          
+                    if (data.Length > i)
+                    {
+                        object value = GetSetFieldValue(field.FieldType, data[i]);
+
+                        //Debug.Log(value);
+                        field.SetValue(obj, value);
+                    }
+                    else
+                    {
+                        Debug.LogError("反射失败,检查数据:"+ data[0]);
+                    }
+                }
+                else
+                {
+                    Debug.LogError("反射查找失败,检查数据:" + data[0]);
+                }
             }
 
             return obj;

+ 22 - 13
Assets/Src/Core/DownLoad/GameDatabase.cs

@@ -27,22 +27,28 @@ using UnityEngine;
         }
 
 
-        protected static void Onload(CsvReader csvReader)
+    protected static void Onload(CsvReader csvReader)
+    {
+        configDatas.Clear();
+        string[][] datas = csvReader.RowDatas;
+        fields = csvReader.Fields();
+        types = csvReader.Types();
+        int length = datas.Length;
+        bool IsHasID = csvReader.HasField("ID");
+
+        for (int i = csvReader.StartLine; i < length; i++)
         {
-            configDatas.Clear();
-            string[][] datas = csvReader.RowDatas;
-            fields = csvReader.Fields();
-            types = csvReader.Types();
-            int length = datas.Length;
-            for (int i = 2; i < length; i++)
+            T data = ExcelParser.Serializable<T>(fields, datas[i]);
+            //Debug.Log(data.FlieName() + data.ID);
+            if (!IsHasID)          
             {
-                T data = ExcelParser.Serializable<T>(fields, datas[i]);
-                //Debug.Log(data.FlieName() + data.ID);
-                configDatas.Add(data.ID, data);
+                data.ID = configDatas.Count;                
             }
+            configDatas.Add(data.ID, data);
         }
+    }
 
-        public static T GetData(int id)
+    public static T GetData(int id)
         {
             T data = null;
             if (configDatas.ContainsKey(id))
@@ -73,12 +79,15 @@ using UnityEngine;
             }
         }
 
-        public static void Clear()
+    public static void Clear(bool isClear = true)
+    {
+        configDatas.Clear();
+        if (isClear)
         {
-            configDatas.Clear();
             fields = null;
             types = null;
         }
+    }
 
         public static List<T> AllData()
         {