Files
zmkgC/api/v1/common/source/pak/pak.go
2025-07-07 20:11:59 +08:00

149 lines
4.0 KiB
Go

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
}