840 lines
18 KiB
Go
840 lines
18 KiB
Go
package util
|
||
|
||
import (
|
||
"backend/msg"
|
||
"bytes"
|
||
"crypto/aes"
|
||
"crypto/cipher"
|
||
crand "crypto/rand"
|
||
"encoding/base64"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"math/rand"
|
||
"os"
|
||
"path/filepath"
|
||
"reflect"
|
||
"regexp"
|
||
"slices"
|
||
"strconv"
|
||
"strings"
|
||
"text/template"
|
||
"time"
|
||
"unicode"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/gorilla/websocket"
|
||
"google.golang.org/protobuf/proto"
|
||
)
|
||
|
||
var MergeData = make(map[string]interface{})
|
||
var MergeEmitData = make(map[string]interface{})
|
||
var FrameData = make(map[string]interface{})
|
||
var CardData = make(map[string]interface{})
|
||
var CardCollectData = make(map[string]interface{})
|
||
var NetAssetData = make(map[string]interface{})
|
||
var ItemData = make(map[string]interface{})
|
||
|
||
func init() {
|
||
data, err := os.ReadFile("config/MergeData.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal MergeData.json: %v", err)
|
||
} else {
|
||
MergeData = m
|
||
}
|
||
}
|
||
data, err = os.ReadFile("config/MergeDataEmit.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal MergeEmitData.json: %v", err)
|
||
} else {
|
||
MergeEmitData = m
|
||
}
|
||
}
|
||
data, err = os.ReadFile("config/Avatar.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal FrameData.json: %v", err)
|
||
} else {
|
||
FrameData = m
|
||
}
|
||
}
|
||
data, err = os.ReadFile("config/CardDetail.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal CardData.json: %v", err)
|
||
} else {
|
||
CardData = m
|
||
}
|
||
}
|
||
|
||
data, err = os.ReadFile("config/CardCollect.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal CardCollectData.json: %v", err)
|
||
} else {
|
||
CardCollectData = m
|
||
}
|
||
}
|
||
data, err = os.ReadFile("config/NetAssetData.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal NetAssetData.json: %v", err)
|
||
} else {
|
||
NetAssetData = m
|
||
}
|
||
}
|
||
data, err = os.ReadFile("config/Item.json")
|
||
if err == nil {
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(data, &m); err != nil {
|
||
log.Printf("failed to unmarshal ItemData.json: %v", err)
|
||
} else {
|
||
ItemData = m
|
||
}
|
||
}
|
||
}
|
||
|
||
func GetItemName(itemId int) string {
|
||
id := strconv.Itoa(itemId)
|
||
if v, ok := ItemData[id]; ok && v != nil {
|
||
entry, ok := v.(map[string]interface{})
|
||
if ok {
|
||
return String(entry["Name"])
|
||
}
|
||
}
|
||
return id
|
||
}
|
||
|
||
// 获取结构体名称
|
||
func GetStructName(v interface{}) string {
|
||
t := reflect.TypeOf(v)
|
||
if t.Kind() == reflect.Ptr {
|
||
t = t.Elem()
|
||
}
|
||
if t.Kind() == reflect.Struct {
|
||
return t.Name()
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func PackMsg(m proto.Message) []byte {
|
||
buf, _ := proto.Marshal(m)
|
||
Func := GetStructName(m)
|
||
req := &msg.AdminReq{
|
||
Func: Func,
|
||
Info: buf,
|
||
}
|
||
buf, _ = proto.Marshal(req)
|
||
return append([]byte{0, 2}, buf...)
|
||
}
|
||
|
||
func UnpackMsg(buf []byte, n int) (string, error) {
|
||
// 检查数据长度
|
||
if n < 2 {
|
||
return "", fmt.Errorf("message too short: got %d bytes, need at least 2", n)
|
||
}
|
||
res := &msg.AdminRes{}
|
||
err := proto.Unmarshal(buf[2:n], res)
|
||
if err != nil {
|
||
// 记录更详细的错误信息
|
||
log.Printf("UnpackMsg error: %v, data length: %d, hex: %x", err, n-2, buf[2:n])
|
||
return "", fmt.Errorf("proto unmarshal error: %v", err)
|
||
}
|
||
return res.Info, nil
|
||
}
|
||
|
||
func ParseUid(uid int) (int, int) {
|
||
AppId := uid / 100000000
|
||
ServerId := uid % 100000000 / 100000
|
||
return AppId, ServerId
|
||
}
|
||
|
||
func Int(a interface{}) int {
|
||
if a == nil {
|
||
return 0
|
||
}
|
||
switch v := a.(type) {
|
||
case int:
|
||
return v
|
||
case int32:
|
||
return int(v)
|
||
case int64:
|
||
return int(v)
|
||
case float64:
|
||
return int(v)
|
||
case string:
|
||
r, err := strconv.Atoi(v)
|
||
if err != nil {
|
||
return 0
|
||
}
|
||
return r
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func String(a interface{}) string {
|
||
if a == nil {
|
||
return ""
|
||
}
|
||
switch v := a.(type) {
|
||
case string:
|
||
return v
|
||
case int:
|
||
return strconv.Itoa(v)
|
||
case int32:
|
||
return strconv.Itoa(int(v))
|
||
case int64:
|
||
return strconv.FormatInt(v, 10)
|
||
case float64:
|
||
return strconv.FormatFloat(v, 'f', -1, 64)
|
||
case []byte:
|
||
return string(v)
|
||
default:
|
||
rv := reflect.ValueOf(a)
|
||
if !rv.IsValid() {
|
||
return ""
|
||
}
|
||
// unwrap pointer
|
||
if rv.Kind() == reflect.Ptr && !rv.IsNil() {
|
||
rv = rv.Elem()
|
||
}
|
||
kind := rv.Kind()
|
||
// if it's a struct/map/slice/array convert to JSON
|
||
if kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice || kind == reflect.Array {
|
||
b, err := json.Marshal(a)
|
||
if err == nil {
|
||
return string(b)
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
}
|
||
|
||
func InArray(Id int, s []int) bool {
|
||
for _, v := range s {
|
||
if v == Id {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func Now() int64 {
|
||
return time.Now().Unix()
|
||
}
|
||
|
||
func Year() int {
|
||
return time.Now().Year()
|
||
}
|
||
|
||
func NowFormat() string {
|
||
return time.Now().Format("2006-01-02 15:04:05")
|
||
}
|
||
|
||
func SendAdminMsg(ws *websocket.Conn, req proto.Message) (map[string]interface{}, error) {
|
||
reqBuf := PackMsg(req)
|
||
err := ws.WriteMessage(websocket.BinaryMessage, reqBuf)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to write to websocket: %v", err)
|
||
}
|
||
|
||
_, readbuf, err := ws.ReadMessage()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to read from websocket: %v", err)
|
||
}
|
||
n := len(readbuf)
|
||
|
||
resBuf, err := UnpackMsg(readbuf, n)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to unpack message: %v", err)
|
||
}
|
||
|
||
r := make(map[string]interface{})
|
||
err = json.Unmarshal([]byte(resBuf), &r)
|
||
if err != nil {
|
||
log.Printf("Failed to unmarshal response: %v, %s", err, resBuf)
|
||
return nil, fmt.Errorf("failed to unmarshal response: %v, %s", err, resBuf)
|
||
}
|
||
return r, nil
|
||
}
|
||
|
||
func FloatDecimals(f float64, n int) float64 {
|
||
format := fmt.Sprintf("%%.%df", n)
|
||
r, _ := strconv.ParseFloat(fmt.Sprintf(format, f), 64)
|
||
return r
|
||
}
|
||
|
||
// 将两个参数转换成浮点数,如果无法转换则为0,实现两个浮点数的除法,除数为0的话,返回0
|
||
func FloatDiv(a, b interface{}, Decimal int) float64 {
|
||
af := toFloat64(a)
|
||
bf := toFloat64(b)
|
||
if bf == 0 {
|
||
return 0
|
||
}
|
||
result := af / bf
|
||
format := fmt.Sprintf("%%.%df", Decimal)
|
||
r, _ := strconv.ParseFloat(fmt.Sprintf(format, result), 64)
|
||
return r
|
||
}
|
||
|
||
func Decimal(f float64, n int) float64 {
|
||
format := fmt.Sprintf("%%.%df", n)
|
||
r, _ := strconv.ParseFloat(fmt.Sprintf(format, f), 64)
|
||
return r
|
||
}
|
||
|
||
// 辅助函数:将interface{}转换为float64
|
||
func toFloat64(v interface{}) float64 {
|
||
switch val := v.(type) {
|
||
case int:
|
||
return float64(val)
|
||
case int32:
|
||
return float64(val)
|
||
case int64:
|
||
return float64(val)
|
||
case float32:
|
||
return float64(val)
|
||
case float64:
|
||
return val
|
||
case string:
|
||
r, err := strconv.ParseFloat(val, 64)
|
||
if err != nil {
|
||
return 0
|
||
}
|
||
return r
|
||
default:
|
||
return 0
|
||
}
|
||
}
|
||
|
||
const (
|
||
SECRET_KEY = ")VQbB(vpy=U(wcp)"
|
||
)
|
||
|
||
// 加密字符串
|
||
func Encrypt(plainText string) (string, error) {
|
||
block, err := aes.NewCipher([]byte(SECRET_KEY))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
cipherText := make([]byte, aes.BlockSize+len(plainText))
|
||
iv := cipherText[:aes.BlockSize]
|
||
if _, err := io.ReadFull(crand.Reader, iv); err != nil {
|
||
return "", err
|
||
}
|
||
|
||
stream := cipher.NewCFBEncrypter(block, iv)
|
||
stream.XORKeyStream(cipherText[aes.BlockSize:], []byte(plainText))
|
||
|
||
return base64.URLEncoding.EncodeToString(cipherText), nil
|
||
}
|
||
|
||
// 解密字符串
|
||
func Decrypt(cipherText string) (string, error) {
|
||
cipherTextBytes, err := base64.URLEncoding.DecodeString(cipherText)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
block, err := aes.NewCipher([]byte(SECRET_KEY))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
if len(cipherTextBytes) < aes.BlockSize {
|
||
return "", fmt.Errorf("cipherText too short")
|
||
}
|
||
|
||
iv := cipherTextBytes[:aes.BlockSize]
|
||
cipherTextBytes = cipherTextBytes[aes.BlockSize:]
|
||
|
||
stream := cipher.NewCFBDecrypter(block, iv)
|
||
stream.XORKeyStream(cipherTextBytes, cipherTextBytes)
|
||
|
||
return string(cipherTextBytes), nil
|
||
}
|
||
|
||
func ParseTmpl(file string, data interface{}) string {
|
||
t, err := template.ParseFiles(file)
|
||
if err != nil {
|
||
log.Fatalf("failed to parse template file: %v", err)
|
||
}
|
||
var buf bytes.Buffer
|
||
err = t.Execute(&buf, data)
|
||
if err != nil {
|
||
log.Fatalf("failed to execute template: %v", err)
|
||
}
|
||
s := buf.String()
|
||
return s
|
||
}
|
||
|
||
// 将字符串转换成一行的字符串格式,并再进行一次转义输出
|
||
func ToTmplStr(input string) string {
|
||
// 转义换行符
|
||
escapedStr := strings.ReplaceAll(input, "\r", "")
|
||
escapedStr = strings.ReplaceAll(escapedStr, "\n", "\\n")
|
||
escapedStr = strings.ReplaceAll(escapedStr, "\"", "\\\"")
|
||
// 转义输出
|
||
// return template.HTMLEscapeString(escapedStr)
|
||
return escapedStr
|
||
}
|
||
|
||
func Ternary(condition bool, trueVal, falseVal interface{}) interface{} {
|
||
if condition {
|
||
return trueVal
|
||
}
|
||
return falseVal
|
||
}
|
||
|
||
func TimestampToDate(timestamp int64, Tz string) string {
|
||
loc, err := time.LoadLocation(Tz)
|
||
if err != nil {
|
||
log.Printf("failed to load location %s: %v", Tz, err)
|
||
loc = time.UTC // 默认使用UTC
|
||
}
|
||
t := time.Unix(timestamp, 0).In(loc)
|
||
return t.Format("2006-01-02")
|
||
}
|
||
func TimestampToDateTime(timestamp int64, Tz string) string {
|
||
loc, err := time.LoadLocation(Tz)
|
||
if err != nil {
|
||
log.Printf("failed to load location %s: %v", Tz, err)
|
||
loc = time.UTC // 默认使用UTC
|
||
}
|
||
t := time.Unix(timestamp, 0).In(loc)
|
||
return t.Format("2006-01-02 15:04:05")
|
||
}
|
||
|
||
func GenerateToken() string {
|
||
// 生成一个安全的随机token,适合网页登录
|
||
b := make([]byte, 32)
|
||
if _, err := crand.Read(b); err != nil {
|
||
return ""
|
||
}
|
||
return base64.URLEncoding.EncodeToString(b)
|
||
}
|
||
|
||
func GeneratedCode(Phone string) (string, error) {
|
||
Code := Rand6DigitNumber()
|
||
err := SmsCode(Phone, Code)
|
||
if err != nil {
|
||
return "", fmt.Errorf("failed to send SMS code: %v", err)
|
||
}
|
||
return Code, err
|
||
}
|
||
|
||
func Rand6DigitNumber() string {
|
||
n := rand.Intn(1000000)
|
||
return fmt.Sprintf("%06d", n)
|
||
}
|
||
|
||
func GetToken(c *gin.Context) string {
|
||
// 从请求头中获取Token
|
||
token := c.GetHeader("Authorization")
|
||
if len(token) > 7 && token[:7] == "Bearer " {
|
||
token = token[7:] // 去掉"Bearer "前缀
|
||
}
|
||
return token
|
||
}
|
||
|
||
const (
|
||
RoleSuper = "super"
|
||
RoleAdmin = "admin"
|
||
RoleUser = "user"
|
||
RoleWbTransfer = "wb_transfer"
|
||
RoleGuest = "guest"
|
||
)
|
||
|
||
func GetRole(code int) string {
|
||
switch code {
|
||
case 0:
|
||
return RoleSuper
|
||
case 1:
|
||
return RoleAdmin
|
||
case 2:
|
||
return RoleUser
|
||
case 99:
|
||
return RoleWbTransfer
|
||
default:
|
||
return RoleGuest
|
||
}
|
||
}
|
||
|
||
func ToJson(v interface{}) string {
|
||
data, err := json.Marshal(v)
|
||
if err != nil {
|
||
log.Printf("failed to marshal to JSON: %v", err)
|
||
return ""
|
||
}
|
||
return string(data)
|
||
}
|
||
|
||
func AddAdminLog(c *gin.Context, action string, params interface{}) {
|
||
admin := c.GetString("admin")
|
||
ip := c.ClientIP()
|
||
db := MPool.GetGameDB()
|
||
defer db.Close()
|
||
_, err := db.Exec("INSERT INTO admin_log (admin, action, params, ip, createTime) VALUES (?, ?, ?, ?, ?)",
|
||
admin, action, ToJson(params), ip, Now())
|
||
if err != nil {
|
||
fmt.Printf("failed to insert admin log: %v", err)
|
||
return
|
||
}
|
||
}
|
||
|
||
func ParseParam(s string) map[string]interface{} {
|
||
result := make(map[string]interface{})
|
||
if strings.TrimSpace(s) == "" {
|
||
return result
|
||
}
|
||
if err := json.Unmarshal([]byte(s), &result); err != nil {
|
||
return map[string]interface{}{}
|
||
}
|
||
return result
|
||
}
|
||
|
||
func CheckContainChess(ChessList []string, Emit []string) bool {
|
||
if len(Emit) == 0 {
|
||
return true
|
||
}
|
||
for _, c := range ChessList {
|
||
d, ok := MergeData[c]
|
||
if !ok {
|
||
continue
|
||
}
|
||
if d == nil {
|
||
continue
|
||
}
|
||
m, ok := d.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
Color := m["Color"].(string)
|
||
Serise := getSeriseByColor(Color)
|
||
if InArrayStr(Serise, Emit) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func InArrayStr(s string, arr []string) bool {
|
||
return slices.Contains(arr, s)
|
||
}
|
||
|
||
func getSeriseByColor(Color string) string {
|
||
for k, v := range MergeEmitData {
|
||
d := v.(map[string]interface{})
|
||
colors, ok := d["Order_Type"].(string)
|
||
if !ok {
|
||
continue
|
||
}
|
||
colorList := strings.Split(colors, ",")
|
||
if InArrayStr(Color, colorList) {
|
||
return k
|
||
}
|
||
}
|
||
return Color
|
||
}
|
||
|
||
func Success(c *gin.Context, message string) {
|
||
c.JSON(200, gin.H{
|
||
"code": 0,
|
||
"message": message,
|
||
})
|
||
}
|
||
|
||
func LoginSuccess(c *gin.Context, message string, Port int, Host string, ServerId int) {
|
||
c.JSON(200, gin.H{
|
||
"code": 0,
|
||
"message": message,
|
||
"Port": Port,
|
||
"Host": Host,
|
||
"ServerId": ServerId,
|
||
})
|
||
}
|
||
|
||
func GetChessURL(ChessId string) string {
|
||
key := fmt.Sprintf("UI_MergeData_%s", ChessId)
|
||
return GetLanguageImageURL(key)
|
||
}
|
||
|
||
func GetLanguageImageURL(key string) string {
|
||
// 检查是否符合 UI_MergeData_<id> 格式
|
||
re := regexp.MustCompile(`^UI_MergeData_(\d+)$`)
|
||
m := re.FindStringSubmatch(key)
|
||
if len(m) == 2 {
|
||
id := m[1]
|
||
// 从 MergeData 中取出对应 id 的 Icon 字段
|
||
if v, ok := MergeData[id]; ok && v != nil {
|
||
if entry, ok2 := v.(map[string]interface{}); ok2 {
|
||
var iconStr string
|
||
if iv, ok3 := entry["Icon"]; ok3 && iv != nil {
|
||
switch t := iv.(type) {
|
||
case string:
|
||
iconStr = t
|
||
case float64:
|
||
iconStr = strconv.Itoa(int(t))
|
||
default:
|
||
iconStr = fmt.Sprintf("%v", t)
|
||
}
|
||
}
|
||
if iconStr != "" {
|
||
// baseDir := `D:\Github\AplusB_Pet_nation\Assets\GameMain\UI\UISprites\MergeObj`
|
||
baseDir := `/data/AplusB_Pet_nation/Assets/Art_SubModule/GameMain/UI/UISprites/MergeObj`
|
||
if fi, err := os.Stat(baseDir); err == nil && fi.IsDir() {
|
||
var found string
|
||
walkErr := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
if info.IsDir() {
|
||
return nil
|
||
}
|
||
// 忽略大小写匹配文件名包含 iconStr
|
||
if strings.Contains(strings.ToLower(info.Name()), strings.ToLower(iconStr)) {
|
||
found = path
|
||
return errors.New("found")
|
||
}
|
||
return nil
|
||
})
|
||
if found != "" {
|
||
// 截取从 "Assets" 开始的相对路径,统一为斜杠形式
|
||
lower := strings.ToLower(found)
|
||
idx := strings.Index(lower, "assets")
|
||
if idx >= 0 {
|
||
return filepath.ToSlash(found[idx:])
|
||
}
|
||
return filepath.ToSlash(found)
|
||
}
|
||
if walkErr != nil && walkErr.Error() == "found" && found != "" {
|
||
lower := strings.ToLower(found)
|
||
idx := strings.Index(lower, "assets")
|
||
if idx >= 0 {
|
||
return filepath.ToSlash(found[idx:])
|
||
}
|
||
return filepath.ToSlash(found)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 头像
|
||
reHead := regexp.MustCompile(`^Data_HeadName_(\d+)$`)
|
||
if m := reHead.FindStringSubmatch(key); len(m) == 2 {
|
||
id := Int(m[1])
|
||
return GetFaceURL(id)
|
||
}
|
||
// 头像框
|
||
reFrame := regexp.MustCompile(`^Data_HeadFrameName_(\d+)$`)
|
||
if m := reFrame.FindStringSubmatch(key); len(m) == 2 {
|
||
id := Int(m[1])
|
||
return GetFrameURL(id)
|
||
}
|
||
// Emoji
|
||
reEmoji := regexp.MustCompile(`^Data_EmojiName_(\d+)$`)
|
||
if m := reEmoji.FindStringSubmatch(key); len(m) == 2 {
|
||
return GetEmojiURL(Int(m[1]))
|
||
}
|
||
// 卡牌
|
||
reCard := regexp.MustCompile(`^UI_MainCardPanel_cardName_`)
|
||
if reCard.MatchString(key) {
|
||
parts := strings.Split(key, "_")
|
||
name := strings.TrimSpace(parts[len(parts)-1])
|
||
for _, v := range CardData {
|
||
if v == nil {
|
||
continue
|
||
}
|
||
entry, ok := v.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
if String(entry["Name"]) == name {
|
||
icon := String(entry["Icon"])
|
||
if icon != "" {
|
||
return fmt.Sprintf("UI/UISprites/%s.png", icon)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 卡牌收集
|
||
reCardCollect := regexp.MustCompile(`^UI_MainCardPanel_groupName_`)
|
||
if reCardCollect.MatchString(key) {
|
||
parts := strings.Split(key, "_")
|
||
name := strings.TrimSpace(parts[len(parts)-1])
|
||
for _, v := range CardCollectData {
|
||
if v == nil {
|
||
continue
|
||
}
|
||
entry, ok := v.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
if String(entry["Name"]) == name {
|
||
return String(entry["ResourcesPath"])
|
||
}
|
||
}
|
||
}
|
||
//猫咪毛皮
|
||
reCat := regexp.MustCompile(`^UI_PetFurName_(\d+)$`)
|
||
if m := reCat.FindStringSubmatch(key); len(m) == 2 {
|
||
id := Int(m[1])
|
||
return fmt.Sprintf("UI/UISprites/Shop/Packed/Skin_pic_cat%d.png", id)
|
||
}
|
||
|
||
// 场景预览图
|
||
reScene := regexp.MustCompile(`^CS_ScenePanel_Scene(\d+)$`)
|
||
m = reScene.FindStringSubmatch(key)
|
||
if len(m) == 2 {
|
||
return fmt.Sprintf("UI/UISprites/Area/merge_pic_s%s.png", m[1])
|
||
}
|
||
//发射器插图
|
||
reNetAsset := regexp.MustCompile(`^UI_MainLvPanel_chapterTip_lv_(\d+)$`)
|
||
if reNetAsset.MatchString(key) {
|
||
if v, ok := NetAssetData[key]; ok && v != nil {
|
||
entry, ok := v.(map[string]interface{})
|
||
if !ok {
|
||
return ""
|
||
}
|
||
icon := String(entry["Picture"])
|
||
if icon != "" {
|
||
return fmt.Sprintf("UI/UISprites/%s.png", icon)
|
||
}
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func ParseNodeTags(tags string) []string {
|
||
if tags == "" {
|
||
return []string{}
|
||
}
|
||
return strings.Split(tags, ",")
|
||
}
|
||
|
||
func GetAppName(AppId int) string {
|
||
switch AppId {
|
||
case 0:
|
||
return "正式服"
|
||
case 1:
|
||
return "测试服"
|
||
case 2:
|
||
return "QA服"
|
||
default:
|
||
return "未知服"
|
||
}
|
||
}
|
||
|
||
func GetAppRegion(AppId int) string {
|
||
switch AppId {
|
||
case 0:
|
||
return "prod"
|
||
default:
|
||
return "test"
|
||
}
|
||
}
|
||
|
||
func GetEmojiURL(EmojiId int) string {
|
||
return _GetURL(EmojiId, 109)
|
||
}
|
||
|
||
func GetFaceURL(HeadId int) string {
|
||
return _GetURL(HeadId, 110)
|
||
}
|
||
|
||
func GetFrameURL(FrameId int) string {
|
||
return _GetURL(FrameId, 105)
|
||
}
|
||
|
||
func _GetURL(Id, Type int) string {
|
||
for _, v := range ItemData {
|
||
info, ok := v.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
if Int(info["IType"]) == Type {
|
||
effect := String(info["Effect"])
|
||
effectList := strings.Split(effect, ",")
|
||
if Id == Int(effectList[0]) && len(effectList) > 0 {
|
||
return info["FullResourcePath"].(string)
|
||
}
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func GetCardURL(CardId string) string {
|
||
info, ok := CardData[CardId]
|
||
if ok && info != nil {
|
||
entry, ok := info.(map[string]interface{})
|
||
if ok {
|
||
return String(entry["ResourcesPath"])
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func GetCardCollectURL(name string) string {
|
||
for _, v := range CardCollectData {
|
||
info, ok := v.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
if String(info["Name"]) == name {
|
||
return String(info["ResourcesPath"])
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func GetNetAssetURL(Key string) string {
|
||
info, ok := NetAssetData[Key]
|
||
if ok && info != nil {
|
||
entry, ok := info.(map[string]interface{})
|
||
if ok {
|
||
return String(entry["Picture"])
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func CountDisplayLen(s string) int {
|
||
total := 0
|
||
for _, r := range s {
|
||
if unicode.In(r, unicode.Han) {
|
||
total += 2
|
||
continue
|
||
}
|
||
total += 1
|
||
}
|
||
return total
|
||
}
|
||
|
||
func FormatJson(v string) string {
|
||
var data interface{}
|
||
err := json.Unmarshal([]byte(v), &data)
|
||
if err != nil {
|
||
log.Printf("failed to unmarshal JSON: %v", err)
|
||
return ""
|
||
}
|
||
jsonBytes, err := json.Marshal(data)
|
||
if err != nil {
|
||
log.Printf("failed to marshal JSON: %v", err)
|
||
return ""
|
||
}
|
||
return string(jsonBytes)
|
||
}
|