package main import ( "encoding/json" "fmt" "io" "log" "os" "os/exec" "strconv" "strings" ) /* 说明: 大厅部分的project.manifest需要拷贝回resources/version,打包需要重新编译一次 */ const PthSep = string(os.PathSeparator) type VersionInfo struct { Url string Version string PubDir string OutDir string PrePubDir string Modules []string Cdn_dir string MetaVersion string XXTeaSign string XXTeaKey string EncodeSufix []string } func Marshal(v VersionInfo) []byte { data, err := json.Marshal(v) if err != nil { log.Fatal(err) } return data } func Unmarshal(data []byte) VersionInfo { var user VersionInfo err := json.Unmarshal(data, &user) if err != nil { log.Fatal(err) } return user } func Read() []byte { fp, err := os.OpenFile("./creatorversion.json", os.O_RDONLY, 0755) defer fp.Close() if err != nil { log.Fatal(err) } data := make([]byte, 1024) n, err := fp.Read(data) if err != nil { log.Fatal(err) } return data[:n] } func Write(data []byte) { fp, err := os.OpenFile("./creatorversion.json", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { log.Fatal(err) } defer fp.Close() _, err = fp.Write(data) if err != nil { log.Fatal(err) } } func removeManifest(srcPath string) { dir, err := os.ReadDir(srcPath) if err != nil { return } for _, fi := range dir { if fi.IsDir() { // 忽略目录 removeManifest(srcPath + PthSep + fi.Name()) } else { if fi.Name() == "project.manifest" || fi.Name() == "version.manifest" { os.Remove(srcPath + PthSep + fi.Name()) } } } } func makeManifest(version, url, dir, out_dir, name string) { fmt.Println("makeManifest ", version, url, dir, out_dir, name) cmd := exec.Command("node", "version_generator.js", "-v", version, "-u", url, "-s", dir, "-d", out_dir, "-n", name) stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } // 保证关闭输出流 defer stdout.Close() // 运行命令 if err := cmd.Start(); err != nil { log.Fatal(err) } // 读取输出结果 opBytes, err := io.ReadAll(stdout) if err != nil { log.Fatal(err) } log.Println(string(opBytes)) cmd.Start() cmd.Wait() } func isNeedEncode(file string, postFixes []string) bool { for _, v := range postFixes { if strings.HasSuffix(file, v) { return true } } return false } func main() { defer func() { fmt.Println("结束,按任意键退出") var endInput string fmt.Scanln(&endInput) }() versionInfo := Unmarshal(Read()) fmt.Println(versionInfo) if len(os.Args) >= 2 && os.Args[1] == "decode" { fmt.Println("开始还原加密") StartDecodeDir(versionInfo.PubDir+PthSep+"assets", versionInfo.PubDir+PthSep+"assets", versionInfo.XXTeaKey, versionInfo.XXTeaSign, versionInfo.EncodeSufix) return } v := strings.Split(versionInfo.Version, ".") if len(v) <= 0 { return } if versionInfo.XXTeaKey != "" { fmt.Println("xxtea 加密") StartEncodeDir(versionInfo.PubDir+PthSep+"assets", versionInfo.PubDir+PthSep+"assets", versionInfo.XXTeaKey, versionInfo.XXTeaSign, versionInfo.EncodeSufix) } // 拷贝预发布 fmt.Println("正在拷贝预发布") os.RemoveAll(versionInfo.PrePubDir) copyDir(versionInfo.PubDir+PthSep+"src", versionInfo.PrePubDir+PthSep+"src") copyDir(versionInfo.PubDir+PthSep+"assets", versionInfo.PrePubDir+PthSep+"assets") outputVersion := versionInfo.Version outputDir := fmt.Sprintf("release%v%v", PthSep, outputVersion) os.RemoveAll(outputDir) os.MkdirAll(outputDir+PthSep+"assets", 0777) subModule := "assets" // subpackages // 子模块编译到assets目录中去了,先把子模块代码抽出来 for _, v := range versionInfo.Modules { fmt.Println("正在生成manifest", v) //moduleDest := outputDir + PthSep + subModule + PthSep + v //os.MkdirAll(moduleDest, 0777) makeManifest(versionInfo.Version, versionInfo.Url+"assets/"+v+"/", versionInfo.PrePubDir+PthSep+subModule+PthSep+v, versionInfo.PrePubDir+PthSep+subModule+PthSep+v, "") CopyFile(versionInfo.PubDir+subModule+PthSep+v+"/project.manifest", versionInfo.PrePubDir+PthSep+subModule+PthSep+v+"/project.manifest") src := versionInfo.PrePubDir + PthSep + subModule + PthSep + v dst := outputDir + PthSep + subModule + PthSep + v fmt.Printf("转移模块 %v -> %v\n", src, dst) err := os.Rename(src, dst) if err != nil { fmt.Printf("%v\n", err) } } /**outputDir = fmt.Sprintf("release%v%v", PthSep, outputVersion) fmt.Println("正在copy src目录") copyDir(versionInfo.PubDir+"/src", fmt.Sprintf("%v/src", outputDir)) fmt.Println("正在copy assets") copyDir(versionInfo.PubDir+"/assets", fmt.Sprintf("%v/assets", outputDir))*/ fmt.Println("正在制作大厅 manifest") makeManifest(versionInfo.Version, versionInfo.Url, versionInfo.PrePubDir, versionInfo.PrePubDir, "") CopyFile(versionInfo.OutDir+"/project.manifest", versionInfo.PrePubDir+PthSep+"project.manifest") CopyFile(outputDir+PthSep+"/project.manifest", versionInfo.PrePubDir+PthSep+"project.manifest") CopyFile(outputDir+PthSep+"/version.manifest", versionInfo.PrePubDir+PthSep+"version.manifest") copyDir(versionInfo.PrePubDir+PthSep+"src", outputDir+PthSep+"src") copyDir(versionInfo.PrePubDir+PthSep+"assets", outputDir+PthSep+"assets") // 把大厅的manifest拷贝到build目录下 fmt.Println("正在拷贝大厅 manifest") CopyFile(versionInfo.PubDir+subModule+PthSep+versionInfo.MetaVersion, versionInfo.PrePubDir+PthSep+"project.manifest") // 通过比较,生成delta文件 if versionInfo.Cdn_dir != "" { fmt.Println("正在生成delta 文件 ", versionInfo.Cdn_dir) deltaDir := fmt.Sprintf("delta%v%v", PthSep, outputVersion) compareFolder(outputDir, versionInfo.Cdn_dir, deltaDir) } // 删除无用部分 fmt.Println("正在删除无更新游戏目录") for _, v := range versionInfo.Modules { dir := fmt.Sprintf("delta%v%v/assets/%s", PthSep, outputVersion, v) if isDeltaEmpty(dir) { fmt.Printf(" %s\n", dir) os.RemoveAll(dir) } } // 版本维护 lastVersion, _ := strconv.ParseInt(v[len(v)-1], 10, 32) lastVersion++ v[len(v)-1] = fmt.Sprintf("%d", lastVersion) newVersion := fmt.Sprintf("%v", v[0]) for i := 1; i < len(v); i++ { newVersion = fmt.Sprintf("%v.%v", newVersion, v[i]) } versionInfo.Version = newVersion fmt.Println("正在更新版本号 为 ", versionInfo.Version) data := Marshal(versionInfo) Write(data) }