Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
696f1bcbdb | ||
|
|
5c45ddb80b | ||
|
|
14de836089 | ||
|
|
1c4f804738 |
@@ -2,7 +2,6 @@ package act{id}
|
||||
|
||||
import (
|
||||
service2 "github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type sAct{id} struct {
|
||||
@@ -14,7 +13,7 @@ func New() *sAct{id} {
|
||||
|
||||
var (
|
||||
ActId = {id}
|
||||
ctx = gctx.New()
|
||||
Name = ""
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
|
||||
@@ -9,7 +9,7 @@ type s{name} struct {
|
||||
}
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
|
||||
)
|
||||
|
||||
func New() *s{name} {
|
||||
|
||||
@@ -62,9 +62,9 @@ func MiddlewareAdmin(r *ghttp.Request) {
|
||||
ip := r.GetClientIp()
|
||||
r.SetCtxVar("ip", ip)
|
||||
|
||||
get := r.Cookie.Get("uid")
|
||||
getUid := r.Cookie.Get("uid")
|
||||
|
||||
if get == nil {
|
||||
if getUid == nil {
|
||||
//调试模式允许不验证用户名
|
||||
debug, _ := g.Cfg().GetWithEnv(nil, "debug")
|
||||
if !debug.Bool() {
|
||||
@@ -82,7 +82,13 @@ func MiddlewareAdmin(r *ghttp.Request) {
|
||||
|
||||
}
|
||||
|
||||
uid := get.Int()
|
||||
uid := getUid.Int()
|
||||
|
||||
//获取所有请求的信息
|
||||
get := r.GetRequestMapStrStr()
|
||||
if _, ok := get["uid"]; ok {
|
||||
r.SetCtxVar("uid", get["uid"])
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
|
||||
|
||||
1
go.mod
1
go.mod
@@ -28,6 +28,7 @@ require (
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/elastic/elastic-transport-go/v8 v8.6.1 // indirect
|
||||
github.com/emersion/go-imap/v2 v2.0.0-beta.5 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -77,6 +77,8 @@ github.com/elastic/elastic-transport-go/v8 v8.6.1 h1:h2jQRqH6eLGiBSN4eZbQnJLtL4b
|
||||
github.com/elastic/elastic-transport-go/v8 v8.6.1/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
|
||||
github.com/elastic/go-elasticsearch/v8 v8.17.1 h1:bOXChDoCMB4TIwwGqKd031U8OXssmWLT3UrAr9EGs3Q=
|
||||
github.com/elastic/go-elasticsearch/v8 v8.17.1/go.mod h1:MVJCtL+gJJ7x5jFeUmA20O7rvipX8GcQmo5iBcmaJn4=
|
||||
github.com/emersion/go-imap/v2 v2.0.0-beta.5 h1:H3858DNmBuXyMK1++YrQIRdpKE1MwBc+ywBtg3n+0wA=
|
||||
github.com/emersion/go-imap/v2 v2.0.0-beta.5/go.mod h1:BZTFHsS1hmgBkFlHqbxGLXk2hnRqTItUgwjSSCsYNAk=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/ayflying/utility_go/internal/model/do"
|
||||
"github.com/ayflying/utility_go/internal/model/entity"
|
||||
"github.com/ayflying/utility_go/package/aycache"
|
||||
"github.com/ayflying/utility_go/pgk"
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
service2 "github.com/ayflying/utility_go/service"
|
||||
@@ -72,7 +71,7 @@ func (s *sGameAct) Info(uid int64, actId int) (data *g.Var, err error) {
|
||||
_, err = g.Redis().Set(ctx, keyCache, data)
|
||||
|
||||
var CacheKey = fmt.Sprintf("act:update:%d", uid)
|
||||
pkg.Cache("redis").Set(ctx, CacheKey, uid, time.Hour*24*3)
|
||||
pkg.Cache("redis").Set(ctx, CacheKey, uid, time.Hour*24*1)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -138,29 +137,22 @@ func (s *sGameAct) Save(actId int) (err error) {
|
||||
}
|
||||
|
||||
cacheGet, _ := g.Redis().Get(ctx, cacheKey)
|
||||
//最后删除key
|
||||
delKey = append(delKey, cacheKey)
|
||||
|
||||
if uid == 0 {
|
||||
//跳过为空的用户缓存
|
||||
continue
|
||||
}
|
||||
if cacheGet.IsEmpty() {
|
||||
//空数据也不巴保存
|
||||
//空数据也不保存
|
||||
continue
|
||||
}
|
||||
|
||||
var CacheKey = fmt.Sprintf("act:update:%d", uid)
|
||||
//如果有活跃,跳过持久化
|
||||
if getBool, _ := aycache.New("redis").Contains(ctx, CacheKey); getBool {
|
||||
if getBool, _ := pkg.Cache("redis").Contains(ctx,
|
||||
fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
continue
|
||||
}
|
||||
|
||||
////如果1天没有活跃,跳过
|
||||
//user, _ := service.MemberUser().Info(uid)
|
||||
//if user.UpdatedAt.Seconds < gtime.Now().Add(consts.ActSaveTime).Unix() {
|
||||
// continue
|
||||
//}
|
||||
|
||||
//获取数据库数据
|
||||
var data *entity.GameAct
|
||||
// 从数据库中查询活动信息
|
||||
@@ -185,7 +177,8 @@ func (s *sGameAct) Save(actId int) (err error) {
|
||||
data.Action = actionData
|
||||
add = append(add, data)
|
||||
}
|
||||
|
||||
//最后删除key
|
||||
delKey = append(delKey, cacheKey)
|
||||
}
|
||||
|
||||
//批量写入数据库
|
||||
|
||||
125
internal/logic/gameKv/gameKv.go
Normal file
125
internal/logic/gameKv/gameKv.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package gameKv
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/ayflying/utility_go/tools"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
Name = "game_kv"
|
||||
)
|
||||
|
||||
type sGameKv struct {
|
||||
Lock sync.Mutex
|
||||
}
|
||||
|
||||
func New() *sGameKv {
|
||||
return &sGameKv{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterGameKv(New())
|
||||
|
||||
//支付钩子
|
||||
//task.Task.Trigger(tasks.TaskType_PAY, service.GameKv().HookPay)
|
||||
//task.Task.Trigger(tasks.TaskType_WARDROBE_LEVEL, service.GameKv().HookLevelRwd)
|
||||
}
|
||||
|
||||
// SavesV1 方法
|
||||
//
|
||||
// @Description: 保存用户KV数据列表。
|
||||
// @receiver s: sGameKv的实例。
|
||||
// @return err: 错误信息,如果操作成功,则为nil。
|
||||
func (s *sGameKv) SavesV1() (err error) {
|
||||
// 从Redis列表中获取所有用户KV索引的键
|
||||
//keys, err := utils.RedisScan("user:kv:*")
|
||||
err = tools.Redis.RedisScanV2("user:kv:*", func(keys []string) (err error) {
|
||||
// 定义用于存储用户数据的结构体
|
||||
type ListData struct {
|
||||
Uid int64 `json:"uid"`
|
||||
Kv interface{} `json:"kv"`
|
||||
}
|
||||
var list []*ListData
|
||||
// 初始化列表,长度与keys数组一致
|
||||
list = make([]*ListData, 0)
|
||||
//需要删除的key
|
||||
var delKey []string
|
||||
// 遍历keys,获取每个用户的数据并填充到list中
|
||||
for _, cacheKey := range keys {
|
||||
//g.Log().Infof(ctx, "保存用户kv数据%v", v)
|
||||
//uid := v.Int64()
|
||||
//cacheKey = "user:kv:" + strconv.FormatInt(uid, 10)
|
||||
result := strings.Split(cacheKey, ":")
|
||||
var uid int64
|
||||
uid, err = strconv.ParseInt(result[2], 10, 64)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
g.Redis().Del(ctx, cacheKey)
|
||||
continue
|
||||
}
|
||||
|
||||
////如果1天没有活跃,跳过
|
||||
//user, _ := service.MemberUser().Info(uid)
|
||||
//if user.UpdatedAt.Seconds < gtime.Now().Add(consts.ActSaveTime).Unix() {
|
||||
// continue
|
||||
//}
|
||||
|
||||
get, _ := g.Redis().Get(ctx, cacheKey)
|
||||
var data interface{}
|
||||
get.Scan(&data)
|
||||
list = append(list, &ListData{
|
||||
Uid: int64(uid),
|
||||
Kv: data,
|
||||
})
|
||||
|
||||
delKey = append(delKey, cacheKey)
|
||||
}
|
||||
|
||||
// 将列表数据保存到数据库
|
||||
if len(list) > 0 {
|
||||
_, err2 := g.Model("game_kv").Batch(30).Data(list).Save()
|
||||
list = make([]*ListData, 0)
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
return
|
||||
}
|
||||
|
||||
//批量删除key
|
||||
for _, v := range delKey {
|
||||
_, err2 = g.Redis().Del(ctx, v)
|
||||
if err2 != nil {
|
||||
g.Log().Errorf(ctx, "删除存档错误:%v,err=%v", v, err2)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
delKey = make([]string, 0)
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, "当前kv数据入库失败: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
////跳过
|
||||
//if len(keys) == 0 {
|
||||
// return
|
||||
//}
|
||||
////一次最多处理10w条
|
||||
//if len(keys) > 10000 {
|
||||
// keys = keys[:10000]
|
||||
//}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package logic
|
||||
|
||||
import (
|
||||
_ "github.com/ayflying/utility_go/internal/logic/gameAct"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/gameKv"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/ip2region"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/logData"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/systemCron"
|
||||
|
||||
@@ -69,6 +69,10 @@ func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath stri
|
||||
fileBytes := gfile.GetBytes(filepath)
|
||||
arr, _ := gjson.DecodeToJson(fileBytes)
|
||||
list := arr.Array()
|
||||
|
||||
//排除注释行
|
||||
list = s.RemoveComments(list, fileItem.Json)
|
||||
|
||||
//格式化item格式
|
||||
if len(fileItem.Items) > 0 {
|
||||
list = s.itemsFormat(list, fileItem.Items)
|
||||
@@ -98,105 +102,193 @@ func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath stri
|
||||
return
|
||||
}
|
||||
|
||||
//排除配置中注释行
|
||||
func (s *Excel) RemoveComments(list []interface{}, json []string) []interface{} {
|
||||
var temp = make([]interface{}, 0)
|
||||
// 遍历列表中的每个元素
|
||||
for _, v2 := range list {
|
||||
var add = true
|
||||
// 遍历当前元素的每个键值对
|
||||
for _, v3 := range v2.(g.Map) {
|
||||
// 如果字符串中存在//则跳过不写入temp
|
||||
if gstr.Contains(gconv.String(v3), "//") {
|
||||
//delKey = append(delKey, k2)
|
||||
add = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if add {
|
||||
temp = append(temp, v2)
|
||||
}
|
||||
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// itemsFormat 格式化列表中的道具字段
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Items: 包含需要处理的道具字段名称的切片
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) itemsFormat(list []interface{}, Items []string) []interface{} {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
// 检查当前键是否在需要处理的道具字段列表中
|
||||
if gstr.InArray(Items, k3) {
|
||||
// 检查当前值是否为字符串类型
|
||||
if _, ok := v3.(string); ok {
|
||||
// 如果是字符串类型,调用 Spilt2Item 函数将其转换为 [][]int64 类型,并更新到列表中
|
||||
list[k2].(g.Map)[k3] = Spilt2Item(v3.(string))
|
||||
} else {
|
||||
// 如果不是字符串类型,记录错误日志
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
// itemsMapFormat 将列表中指定字段的道具信息转换为映射格式
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Items: 包含需要处理的道具字段名称的切片
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) itemsMapFormat(list []interface{}, Items []string) []interface{} {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
// 检查当前键是否在需要处理的道具字段列表中
|
||||
if gstr.InArray(Items, k3) {
|
||||
// 检查当前值是否为字符串类型
|
||||
if _, ok := v3.(string); ok {
|
||||
// 如果是字符串类型,调用 Spilt2Item 函数将其转换为 [][]int64 类型
|
||||
get := Spilt2Item(v3.(string))
|
||||
// 调用 Items2Map 函数将 [][]int64 类型的数据转换为映射格式,并更新到列表中
|
||||
list[k2].(g.Map)[k3] = s.Items2Map(get)
|
||||
} else {
|
||||
// 如果不是字符串类型,记录错误日志
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
// sliceFormat 格式化列表中指定字段为切片格式
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Slice: 一个映射,键为需要处理的字段名,值为目标类型(如 "int", "int64", "float64")
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) sliceFormat(list []interface{}, Slice map[string]string) []interface{} {
|
||||
// 遍历 Slice 映射中的每个键值对
|
||||
for s1, s2 := range Slice {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
//判断是否存在
|
||||
// 判断当前键是否与 Slice 中的键匹配
|
||||
if s1 != k3 {
|
||||
// 不匹配则跳过当前循环
|
||||
continue
|
||||
}
|
||||
// 检查当前值是否为空字符串
|
||||
if gconv.String(v3) == "" {
|
||||
// 若为空,则将该字段设置为空字符串切片
|
||||
list[k2].(g.Map)[k3] = []string{}
|
||||
// 跳过当前循环
|
||||
continue
|
||||
}
|
||||
// 用于存储分割后的字符串切片
|
||||
var parts []string
|
||||
//断言是否成功
|
||||
// 断言当前值是否为字符串类型
|
||||
if get, ok := v3.(string); !ok {
|
||||
//g.Log().Errorf(gctx.New(), "当前类型断言失败:%v", v3)
|
||||
// 若断言失败,将当前值转换为字符串并作为唯一元素存入 parts
|
||||
parts = []string{gconv.String(v3)}
|
||||
|
||||
} else {
|
||||
// 若为字符串类型,将字符串中的特殊字符替换为 "|"
|
||||
for _, v := range shadiao {
|
||||
get = strings.ReplaceAll(get, v, "|")
|
||||
}
|
||||
parts = strings.Split(get, "|") // 分割字符串
|
||||
// 按 "|" 分割字符串
|
||||
parts = strings.Split(get, "|")
|
||||
}
|
||||
|
||||
// 根据 Slice 映射中的值进行类型转换
|
||||
switch s2 {
|
||||
case "int":
|
||||
// 创建一个长度为 parts 的 int 切片
|
||||
var temp = make([]int, len(parts))
|
||||
// 遍历 parts 切片,将每个元素转换为 int 类型
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.Atoi(v)
|
||||
}
|
||||
// 将转换后的切片存入列表中
|
||||
list[k2].(g.Map)[k3] = temp
|
||||
case "int64":
|
||||
// 创建一个长度为 parts 的 int64 切片
|
||||
var temp = make([]int64, len(parts))
|
||||
// 遍历 parts 切片,将每个元素转换为 int64 类型
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.ParseInt(v, 10, 64)
|
||||
}
|
||||
case "float64":
|
||||
// 创建一个长度为 parts 的 float64 切片
|
||||
var temp = make([]float64, len(parts))
|
||||
// 遍历 parts 切片,将每个元素转换为 float64 类型
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.ParseFloat(v, 64)
|
||||
}
|
||||
// 将转换后的切片存入列表中
|
||||
list[k2].(g.Map)[k3] = temp
|
||||
default:
|
||||
// 若未匹配到指定类型,直接将 parts 存入列表中
|
||||
list[k2].(g.Map)[k3] = parts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
// jsonFormat 将列表中指定字段的 JSON 字符串解析为 Go 数据结构
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Items: 包含需要处理的 JSON 字段名称的切片
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) jsonFormat(list []interface{}, Items []string) []interface{} {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
// 检查当前键是否在需要处理的 JSON 字段列表中
|
||||
if gstr.InArray(Items, k3) {
|
||||
// 检查当前值是否为字符串类型
|
||||
if _, ok := v3.(string); ok {
|
||||
// 用于存储解析后的 JSON 数据
|
||||
var get interface{}
|
||||
// 将字符串解析为 JSON 数据
|
||||
json.Unmarshal([]byte(v3.(string)), &get)
|
||||
// 将解析后的 JSON 数据更新到列表中
|
||||
list[k2].(g.Map)[k3] = get
|
||||
} else {
|
||||
// 如果不是字符串类型,记录错误日志
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
32
service/game_kv.go
Normal file
32
service/game_kv.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package service
|
||||
|
||||
type (
|
||||
IGameKv interface {
|
||||
// SavesV1 方法
|
||||
//
|
||||
// @Description: 保存用户KV数据列表。
|
||||
// @receiver s: sGameKv的实例。
|
||||
// @return err: 错误信息,如果操作成功,则为nil。
|
||||
SavesV1() (err error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localGameKv IGameKv
|
||||
)
|
||||
|
||||
func GameKv() IGameKv {
|
||||
if localGameKv == nil {
|
||||
panic("implement not found for interface IGameKv, forgot register?")
|
||||
}
|
||||
return localGameKv
|
||||
}
|
||||
|
||||
func RegisterGameKv(i IGameKv) {
|
||||
localGameKv = i
|
||||
}
|
||||
@@ -15,7 +15,7 @@ type randMod struct {
|
||||
// RandomAll 按权重随机选取 N 个不重复的元素
|
||||
func (m *randMod) RandomAll(data map[int]int, n int) []int {
|
||||
if n > len(data) {
|
||||
return nil
|
||||
n = len(data)
|
||||
}
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
// 复制权重映射,避免修改原始数据
|
||||
|
||||
@@ -223,3 +223,33 @@ func ReverseSlice[T comparable](s []T) []T {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 道具数量合并
|
||||
func (m *tools) ItemsMerge(_items ...[][]int64) [][]int64 {
|
||||
var items [][]int64
|
||||
for _, v := range _items {
|
||||
items = append(items, v...)
|
||||
}
|
||||
if len(items) == 0 {
|
||||
return [][]int64{}
|
||||
}
|
||||
var temp = make(map[int64]int64)
|
||||
for _, v := range items {
|
||||
if len(v) < 2 {
|
||||
g.Log().Errorf(ctx, "分解的物品格式不对:%v", v)
|
||||
continue
|
||||
}
|
||||
if _, ok := temp[v[0]]; !ok {
|
||||
temp[v[0]] = 0
|
||||
}
|
||||
temp[v[0]] += v[1]
|
||||
}
|
||||
|
||||
items = make([][]int64, len(temp))
|
||||
i := 0
|
||||
for k, v := range temp {
|
||||
items[i] = []int64{k, v}
|
||||
i++
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user