package pak import ( "fmt" "github.com/gogf/gf/v2/net/ghttp" "github.com/tiger1103/gfast/v3/api/v1/common/globe" "github.com/tiger1103/gfast/v3/api/v1/common/tool" "github.com/tiger1103/gfast/v3/database" "github.com/tiger1103/gfast/v3/database/sqlite" "math" "net/http" "os" "path" "strconv" "strings" ) const ( image = "image" terrain = "terrain" ) func InitPakData(group *ghttp.RouterGroup) { //group.GET("/data/pak/{source_id}/{z}/{x}/{y}.*", pakCallback) //group.GET("/data/pak/{source_id}/layer.json", pakCallback) group.GET("/data/pak/{source_id}/*.action", pakCallback) } type Json struct { Layerjson []byte `json:"layerjson"` } // 获取pak文件中的表名 func gettablename(x int, y int, z int) string { if z < 10 { return "blocks" } else { tx := math.Ceil(float64(x / 512)) ty := math.Ceil(float64(y / 512)) return "blocks_" + strconv.Itoa(z) + "_" + strconv.Itoa(int(tx)) + "_" + strconv.Itoa(int(ty)) } } type Tile struct { Tile []byte `json:"tile"` Z int `json:"z"` X int `json:"x"` Y int `json:"y"` } func pakCallback(request *ghttp.Request) { sourceId := request.Get("source_id").String() pakobj := database.GetSourceDB(sourceId) if pakobj.DB == nil { request.Response.WriteStatus(http.StatusNotFound) return } suffix := path.Ext(request.RequestURI) if suffix == ".json" { json := Json{} pakobj.DB.Model(&Info{}).First(&json) request.Response.Header().Set("content-type", "application/json") globe.RenderData(request, json.Layerjson) return } else { uri := request.RequestURI arr := strings.Split(uri, "/") //z := request.Get("z").Int() //x := request.Get("x").Int() //y := request.Get("y").Int() z, _ := strconv.Atoi(arr[7]) x, _ := strconv.Atoi(arr[8]) y, _ := strconv.Atoi(strings.Split(arr[9], ".")[0]) //y = int(math.Pow(2, float64(z))) - 1 - y tile := Tile{} RowsAffected := pakobj.DB.Table(gettablename(x, y, z)).Select("tile").Where(&Tile{Z: z, X: x, Y: y}).First(&tile).RowsAffected if RowsAffected > 0 { request.Response.Header().Set("content-type", pakobj.ContentType) if pakobj.Gzip { request.Response.Header().Set("Content-Encoding", "gzip") } globe.RenderData(request, tile.Tile) return } else { request.Response.WriteStatus(http.StatusNotFound) } } } type Info struct { Minx float64 `json:"minx"` Miny float64 `json:"miny"` Maxx float64 `json:"maxx"` Maxy float64 `json:"maxy"` Minlevel int `json:"minlevel"` Maxlevel int `json:"maxlevel"` Type string `json:"type"` Zip int `json:"zip"` //Layerjson []byte `json:"layerjson"` Contenttype string `json:"contenttype"` } func OpenPak(pakPath string, sourceID string) (error, *database.SourceObj) { //if !globe.IS_OFFLINE_VERSION { // //网络版事 需要拼接数据地址,方便服务器迁移 // pakPath = path.Join(globe.SOURCE, pakPath) //} getwd, err := os.Getwd() if err != nil { return err, nil } pakPath = path.Join(getwd, pakPath) if !tool.PathExists(pakPath) { return globe.GetErrors("资源不存在," + pakPath), nil } fmt.Println("资源存在") db, err := sqlite.OpenDB(pakPath) if err != nil { fmt.Println(err) return err, nil } var obj database.SourceObj obj.DB = db info := Info{} db.Model(&Info{}).First(&info) if info.Type == image { obj.Type = globe.LAYER obj.ContentType = info.Contenttype obj.Url = "/zm/api/v1/data/pak/" + sourceID + "/{z}/{x}/{y}." + strings.Split(obj.ContentType, "/")[1] } if info.Type == terrain { obj.Type = globe.TERRAIN obj.ContentType = "application/octet-stream" obj.Url = "/zm/api/v1/data/pak/" + sourceID + "/" } if info.Zip > 0 { obj.Gzip = true } obj.Info.MaxLevel = info.Maxlevel obj.Info.MinLevel = info.Minlevel obj.Info.West = strconv.FormatFloat(info.Minx, 'f', -1, 64) obj.Info.South = strconv.FormatFloat(info.Miny, 'f', -1, 64) obj.Info.East = strconv.FormatFloat(info.Maxx, 'f', -1, 64) obj.Info.North = strconv.FormatFloat(info.Maxy, 'f', -1, 64) database.SetSourceDB(sourceID, obj) return err, &obj }