package main import ( "bytes" "fmt" "os" "path/filepath" "strings" "text/template" "github.com/tealeg/xlsx" "mongo.games.com/goserver/core" ) type SheetColumnMetaStruct struct { ColIndex int ColName string ColType int CTString string IsArray bool IsMap bool } type SheetMetaStruct struct { AbsPath string FileName string ProtoName string Cols []*SheetColumnMetaStruct } const ( INTTYPE string = "(int)" INT64TYPE string = "(int64)" STRTYPE = "(str)" ARRINTTYPE = "(arrint)" ARRINT64TYPE = "(arrint64)" ARRSTRTYPE = "(arrstr)" INTTYPE_PROTO = "int32" INT64TYPE_PROTO = "int64" STRTYPE_PROTO = "string" MAPTYPE string = "(map)" MAP_PROTO = "map" ) var templates *template.Template func main() { defer core.ClosePackages() core.LoadPackages("config.json") smsMap := make(map[string]*SheetMetaStruct) for xlsxFileName, xlsxFilePath := range XlsxFiles { xlsxFile, err := xlsx.OpenFile(xlsxFilePath) if err != nil { fmt.Println("excel file open error:", err, " filePath:", xlsxFilePath) continue } for _, sheet := range xlsxFile.Sheets { sms := &SheetMetaStruct{ AbsPath: xlsxFilePath, FileName: xlsxFileName, ProtoName: strings.TrimSuffix(xlsxFileName, ".xlsx"), Cols: make([]*SheetColumnMetaStruct, 0, sheet.MaxCol)} for _, row := range sheet.Rows { for i, cell := range row.Cells { s := cell.String() if strings.HasSuffix(s, INTTYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, INTTYPE), 1, INTTYPE_PROTO, false, false}) } else if strings.HasSuffix(s, STRTYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, STRTYPE), 2, STRTYPE_PROTO, false, false}) } else if strings.HasSuffix(s, ARRINTTYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ARRINTTYPE), 3, INTTYPE_PROTO, true, false}) } else if strings.HasSuffix(s, ARRSTRTYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ARRSTRTYPE), 4, STRTYPE_PROTO, true, false}) } else if strings.HasSuffix(s, INT64TYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, INT64TYPE), 5, INT64TYPE_PROTO, false, false}) } else if strings.HasSuffix(s, ARRINT64TYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ARRINT64TYPE), 6, INT64TYPE_PROTO, true, false}) } else if strings.HasSuffix(s, MAPTYPE) { sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, MAPTYPE), 7, MAP_PROTO, false, true}) } } break //only fetch first row } smsMap[sms.ProtoName] = sms break //only fetch first sheet } } geneProto(smsMap) } func geneProto(xlsxs map[string]*SheetMetaStruct) { if xlsxs == nil { return } geneAgcHelper(xlsxs) //生成 xlsx转二进制文件(.json,.dat) geneDataStructProto(xlsxs) //生成 xlsx转protobuf结构文件(pbdata.proto) //geneDataSingleStructProto(xlsxs) //geneChhDataMgrHeader(xlsxs)//生成 c头文件 //geneCppDataMgrHeader(xlsxs)//生成 c源文件 //copyNoDataProtoToLua() for _, val := range xlsxs { genGoDataMgr(val) // 生成Go对象文件 genTsDataMgr(val) // 生成TypeScript对象文件 } } // geneAgcHelper 生成go代码,读取xlsx数据 func geneAgcHelper(xlsxs map[string]*SheetMetaStruct) { dm := map[string]interface{}{ "data": xlsxs, "opath": filepath.Join(Config.WorkPath, Config.DataPath), "isMapCol": isMapColumn(xlsxs), } outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "agc", dm) if err != nil { fmt.Println("geneProto ExecuteTemplate error:", err) return } helperGoFile := filepath.Join(Config.WorkPath, Config.ConvertToolPath, "agc.go") err = os.WriteFile(helperGoFile, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("geneProto WriteFile error:", err) return } } // geneDataStructProto 生成xlsx的proto文件 func geneDataStructProto(xlsxs map[string]*SheetMetaStruct) { outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "gpb", xlsxs) if err != nil { fmt.Println("geneDataStructProto ExecuteTemplate error:", err) return } protoFile := filepath.Join(Config.WorkPath, Config.ProtoPath, Config.ProtoFile) err = os.WriteFile(protoFile, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("geneDataStructProto error:", err) } } func geneDataSingleStructProto(xlsxs map[string]*SheetMetaStruct) { for k, v := range xlsxs { outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "gpb_single", v) if err != nil { fmt.Println("geneDataSingleStructProto ExecuteTemplate error:", err) return } protoFile := filepath.Join(Config.WorkPath, Config.ProtoLuaPath, strings.ToLower(k)+".proto") err = os.WriteFile(protoFile, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("geneDataSingleStructProto error:", err) } } } // genGoDataMgr 生成go代码,读取.dat文件数据 func genGoDataMgr(sms *SheetMetaStruct) { if sms == nil { return } outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "gpb_mgr", sms) if err != nil { fmt.Println("genGoDataMgr ExecuteTemplate error:", err) return } opath := filepath.Join(Config.WorkPath, Config.GoFilePath, strings.ToLower(fmt.Sprintf("%v.go", sms.ProtoName))) err = os.WriteFile(opath, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("genGoDataMgr WriteFile error:", err) return } } // genTsDataMgr 生成ts类模板 func genTsDataMgr(sms *SheetMetaStruct) { if sms == nil { return } outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "gpb_mgr_ts", sms) if err != nil { fmt.Println("genTsDataMgr ExecuteTemplate error:", err) return } //opath := filepath.Join(Config.WorkPath, Config.TsFilePath, strings.ToLower(fmt.Sprintf("%v.ts", sms.ProtoName))) opath := fmt.Sprintf("%v/%v", Config.TsFilePath, strings.ToLower(fmt.Sprintf("%v.ts", sms.ProtoName))) err = os.WriteFile(opath, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("genTsDataMgr WriteFile error:", err) return } } func geneChhDataMgrHeader(xlsxs map[string]*SheetMetaStruct) { dm := map[string]interface{}{ "data": xlsxs, } outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "gpb_mgr_h", dm) if err != nil { fmt.Println("geneProto ExecuteTemplate error:", err) return } helperChhFile := filepath.Join(Config.WorkPath, Config.CppFilePath, "DataMgrAgc.h") err = os.WriteFile(helperChhFile, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("geneProto WriteFile error:", err) return } } func geneCppDataMgrHeader(xlsxs map[string]*SheetMetaStruct) { dm := map[string]interface{}{ "data": xlsxs, } outputHelper := bytes.NewBuffer(nil) err := templates.ExecuteTemplate(outputHelper, "gpb_mgr_c", dm) if err != nil { fmt.Println("geneProto ExecuteTemplate error:", err) return } helperChhFile := filepath.Join(Config.WorkPath, Config.CppFilePath, "DataMgrAgc.cpp") err = os.WriteFile(helperChhFile, outputHelper.Bytes(), os.ModePerm) if err != nil { fmt.Println("geneProto WriteFile error:", err) return } } func copyNoDataProtoToLua() { protoFile := filepath.Join(Config.WorkPath, Config.ProtoPath) rootdir, pathopen := os.Open(protoFile) if pathopen != nil { fmt.Println("Path open error.") } else { files, _ := rootdir.Readdir(0) for _, fi := range files { if strings.HasSuffix(fi.Name(), ".proto") && !strings.Contains(fi.Name(), "pbdata.proto") { datas, err := os.ReadFile(filepath.Join(Config.WorkPath, Config.ProtoPath, fi.Name())) if err == nil { strContent := string(datas[:]) strContent = strings.Replace(strContent, `"protocol/`, `"`, -1) dest := filepath.Join(Config.WorkPath, Config.ProtoLuaPath, fi.Name()) fmt.Println("==========dest", dest) os.WriteFile(dest, []byte(strContent), os.ModePerm) } else { fmt.Println(err) } } } } } func isMapColumn(xlsxs map[string]*SheetMetaStruct) bool { for _, sheet := range xlsxs { for _, col := range sheet.Cols { if col.IsMap { return true } } } return false }