保存玩家游戏数据
This commit is contained in:
parent
a77cfa41dd
commit
fa57f5e8e6
|
@ -452,6 +452,22 @@ func SliceValueWeight(sl []int, index int) float64 {
|
|||
return float64(value) / float64(totle)
|
||||
}
|
||||
|
||||
func GetMapKeys[K comparable, V any](data map[K]V) []K {
|
||||
var ret []K
|
||||
for k := range data {
|
||||
ret = append(ret, k)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetMapValues[K comparable, V any](data map[K]V) []V {
|
||||
var ret []V
|
||||
for _, v := range data {
|
||||
ret = append(ret, v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type Int32Slice []int32
|
||||
|
||||
func (p Int32Slice) Len() int { return len(p) }
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package svc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/rpc"
|
||||
|
||||
"github.com/globalsign/mgo"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
|
||||
"mongo.games.com/game/dbproxy/mongo"
|
||||
"mongo.games.com/game/model"
|
||||
)
|
||||
|
||||
var (
|
||||
PlayerGameDataDBName = "user"
|
||||
PlayerGameDataCollName = "user_gamedata"
|
||||
PlayerGameDataColError = errors.New("PlayerGameData collection open failed")
|
||||
PlayerGameDataSvcSingle = &PlayerGameDataSvc{}
|
||||
)
|
||||
|
||||
func PlayerGameDataCollection(plt string) *mongo.Collection {
|
||||
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, PlayerGameDataDBName)
|
||||
if s != nil {
|
||||
c, first := s.DB().C(PlayerGameDataCollName)
|
||||
if first {
|
||||
c.EnsureIndex(mgo.Index{Key: []string{"snid", "id"}, Unique: true, Background: true, Sparse: true})
|
||||
c.EnsureIndex(mgo.Index{Key: []string{"id"}, Background: true, Sparse: true})
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
rpc.Register(PlayerGameDataSvcSingle)
|
||||
}
|
||||
|
||||
type PlayerGameDataSvc struct{}
|
||||
|
||||
func (p *PlayerGameDataSvc) Save(req *model.PlayerGameSaveReq, b *bool) error {
|
||||
c := PlayerGameDataCollection(req.Platform)
|
||||
if c == nil {
|
||||
return PlayerGameDataColError
|
||||
}
|
||||
|
||||
for _, v := range req.Data {
|
||||
_, err := c.Upsert(bson.M{"snid": v.SnId, "id": v.Id}, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*b = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PlayerGameDataSvc) Find(req *model.PlayerGameDataFindReq, res *model.PlayerGameDataFindRes) error {
|
||||
c := PlayerGameDataCollection(req.Platform)
|
||||
if c == nil {
|
||||
return PlayerGameDataColError
|
||||
}
|
||||
|
||||
var ret []*model.PlayerGameData
|
||||
err := c.Find(bson.M{"snid": req.SnId}).All(&ret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.Data = ret
|
||||
return nil
|
||||
}
|
|
@ -68,8 +68,8 @@ const (
|
|||
)
|
||||
|
||||
type Player struct {
|
||||
model.PlayerData //po 持久化对象
|
||||
ExtraData interface{} //扩展接口
|
||||
model.WGPlayerInfo
|
||||
ExtraData interface{} //具体游戏对局中的玩家扩展信息
|
||||
gateSess *netlib.Session //所在GateServer的session
|
||||
worldSess *netlib.Session //所在WorldServer的session
|
||||
scene *Scene //当前所在个Scene
|
||||
|
@ -141,13 +141,15 @@ func NewPlayer(sid int64, data []byte, ws, gs *netlib.Session) *Player {
|
|||
RankScore: make(map[int32]int64),
|
||||
}
|
||||
|
||||
// 需要make的,统一在这里初始化默认值,别的地方就不用再初始化了
|
||||
p.PlayerData = model.PlayerData{
|
||||
//TotalGameData: make(map[int][]*model.PlayerGameTotal),
|
||||
GDatas: make(map[string]*model.PlayerGameInfo),
|
||||
ShopTotal: make(map[int32]*model.ShopTotal),
|
||||
ShopLastLookTime: make(map[int32]int64),
|
||||
IsFoolPlayer: make(map[string]bool),
|
||||
//todo 初始化
|
||||
p.WGPlayerInfo = model.WGPlayerInfo{
|
||||
PlayerData: &model.PlayerData{
|
||||
GDatas: make(map[string]*model.PlayerGameInfo),
|
||||
ShopTotal: make(map[int32]*model.ShopTotal),
|
||||
ShopLastLookTime: make(map[int32]int64),
|
||||
IsFoolPlayer: make(map[string]bool),
|
||||
},
|
||||
GameData: make(map[int32]*model.PlayerGameData),
|
||||
}
|
||||
|
||||
if p.init(data) {
|
||||
|
@ -373,7 +375,20 @@ func (this *Player) OnAudienceLeave(reason int) {
|
|||
}
|
||||
|
||||
func (this *Player) MarshalData(gameid int) (d []byte, e error) {
|
||||
d, e = netlib.Gob.Marshal(&this.PlayerData)
|
||||
// 防止参数遗漏
|
||||
for k, v := range this.GameData {
|
||||
if v.SnId == 0 {
|
||||
v.SnId = this.SnId
|
||||
}
|
||||
if v.Platform == "" {
|
||||
v.Platform = this.Platform
|
||||
}
|
||||
if v.Id == 0 {
|
||||
v.Id = k
|
||||
}
|
||||
}
|
||||
|
||||
d, e = netlib.Gob.Marshal(&this.WGPlayerInfo)
|
||||
logger.Logger.Trace("(this *Player) MarshalData(gameid int)")
|
||||
return
|
||||
}
|
||||
|
@ -382,7 +397,7 @@ func (this *Player) UnmarshalData(data []byte) bool {
|
|||
if len(data) == 0 {
|
||||
return true
|
||||
}
|
||||
err := netlib.Gob.Unmarshal(data, &this.PlayerData)
|
||||
err := netlib.Gob.Unmarshal(data, &this.WGPlayerInfo)
|
||||
if err == nil {
|
||||
this.dirty = true
|
||||
return true
|
||||
|
|
|
@ -1984,7 +1984,7 @@ func (this *Scene) TryBillExGameDrop(p *Player) {
|
|||
itemData := srvdata.GameItemMgr.Get(p.Platform, id)
|
||||
if itemData != nil {
|
||||
p.AddItems(&model.AddItemParam{
|
||||
P: &p.PlayerData,
|
||||
P: p.PlayerData,
|
||||
Change: nil,
|
||||
GainWay: common.GainWay_Game,
|
||||
Operator: "system",
|
||||
|
@ -2021,7 +2021,7 @@ func (this *Scene) DropCollectBox(p *Player) {
|
|||
if itemData != nil {
|
||||
pack.Items = map[int32]int32{itemData.Id: 1}
|
||||
p.AddItems(&model.AddItemParam{
|
||||
P: &p.PlayerData,
|
||||
P: p.PlayerData,
|
||||
Change: []*model.Item{
|
||||
{
|
||||
ItemId: itemData.Id,
|
||||
|
|
|
@ -1803,7 +1803,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
// vip加成分
|
||||
vipScore = int64(math.Ceil(float64(rankScore) * float64(losePlayer.VipExtra) / 100.0))
|
||||
// 角色加成分
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&losePlayer.PlayerData, common.RoleAddRankScore)
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(losePlayer.PlayerData, common.RoleAddRankScore)
|
||||
roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0))
|
||||
//周卡加成
|
||||
if losePlayer.GetWeekCardPrivilege(2) {
|
||||
|
@ -1945,7 +1945,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
// vip加成分
|
||||
vipScore = int64(math.Ceil(float64(rankScore) * float64(lastWinPlayer.VipExtra) / 100.0))
|
||||
// 角色加成分
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&lastWinPlayer.PlayerData, common.RoleAddRankScore)
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(lastWinPlayer.PlayerData, common.RoleAddRankScore)
|
||||
roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0))
|
||||
//周卡加成
|
||||
if lastWinPlayer.GetWeekCardPrivilege(2) {
|
||||
|
@ -2056,7 +2056,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
// vip加成分
|
||||
vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0))
|
||||
// 角色加成分
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore)
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(playerEx.PlayerData, common.RoleAddRankScore)
|
||||
roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0))
|
||||
//周卡加成
|
||||
if playerEx.GetWeekCardPrivilege(2) {
|
||||
|
@ -2161,7 +2161,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
// vip加成分
|
||||
vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0))
|
||||
// 角色加成分
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore)
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(playerEx.PlayerData, common.RoleAddRankScore)
|
||||
roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0))
|
||||
//周卡加成
|
||||
if playerEx.GetWeekCardPrivilege(2) {
|
||||
|
@ -2310,7 +2310,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
// vip加成分
|
||||
vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0))
|
||||
// 角色加成分
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore)
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(playerEx.PlayerData, common.RoleAddRankScore)
|
||||
roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0))
|
||||
//周卡加成
|
||||
if playerEx.GetWeekCardPrivilege(2) {
|
||||
|
@ -2442,7 +2442,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
// vip加成分
|
||||
vipScore = int64(math.Ceil(float64(rankScore) * float64(playerEx.VipExtra) / 100.0))
|
||||
// 角色加成分
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(&playerEx.PlayerData, common.RoleAddRankScore)
|
||||
_, roleAdd = srvdata.RolePetMgrSington.GetRoleAdd(playerEx.PlayerData, common.RoleAddRankScore)
|
||||
roleScore = int64(math.Ceil(float64(rankScore) * float64(roleAdd) / 100.0))
|
||||
//周卡加成
|
||||
if playerEx.GetWeekCardPrivilege(2) {
|
||||
|
@ -2613,7 +2613,7 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
|
|||
}
|
||||
}
|
||||
p.AddItems(&model.AddItemParam{
|
||||
P: &p.PlayerData,
|
||||
P: p.PlayerData,
|
||||
Change: items,
|
||||
GainWay: common.GainWayRoomGain,
|
||||
Operator: "system",
|
||||
|
|
|
@ -344,6 +344,13 @@ type MatchFreeSignupRec struct {
|
|||
UseTimes int32 //累计使用免费次数
|
||||
}
|
||||
|
||||
// WGPlayerInfo 游戏服玩家信息
|
||||
// 大厅玩家信息发送给游戏服
|
||||
type WGPlayerInfo struct {
|
||||
*PlayerData
|
||||
GameData map[int32]*PlayerGameData // 游戏数据,只允许存储玩家对应某个游戏需要持久化的数据
|
||||
}
|
||||
|
||||
type PlayerData struct {
|
||||
Id bson.ObjectId `bson:"_id"`
|
||||
AccountId string //账号id
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
)
|
||||
|
||||
type PlayerGameData struct {
|
||||
Platform string `bson:"-"`
|
||||
SnId int32
|
||||
Id int32 // 游戏id或场次id
|
||||
Data interface{} // 数据
|
||||
}
|
||||
|
||||
type PlayerGameSaveReq struct {
|
||||
Platform string
|
||||
Data []*PlayerGameData
|
||||
}
|
||||
|
||||
func SavePlayerGameData(platform string, data []*PlayerGameData) error {
|
||||
if rpcCli == nil {
|
||||
logger.Logger.Error("model.SavePlayerGameData rpcCli == nil")
|
||||
return nil
|
||||
}
|
||||
b := false
|
||||
err := rpcCli.CallWithTimeout("PlayerGameDataSvc.Save", &PlayerGameSaveReq{Platform: platform, Data: data}, &b, time.Second*30)
|
||||
if err != nil {
|
||||
logger.Logger.Error("model.SavePlayerGameData err:%v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PlayerGameDataFindReq struct {
|
||||
Platform string
|
||||
SnId int32
|
||||
}
|
||||
|
||||
type PlayerGameDataFindRes struct {
|
||||
Data []*PlayerGameData
|
||||
}
|
||||
|
||||
func GetPlayerGameData(platform string, snid int32) ([]*PlayerGameData, error) {
|
||||
if rpcCli == nil {
|
||||
logger.Logger.Error("model.GetPlayerGameData rpcCli == nil")
|
||||
return nil, nil
|
||||
}
|
||||
res := &PlayerGameDataFindRes{}
|
||||
err := rpcCli.CallWithTimeout("PlayerGameDataSvc.Find", &PlayerGameDataFindReq{Platform: platform, SnId: snid}, res, time.Second*30)
|
||||
if err != nil {
|
||||
logger.Logger.Error("model.GetPlayerGameData err:%v", err)
|
||||
return nil, err
|
||||
}
|
||||
return res.Data, nil
|
||||
}
|
|
@ -1663,14 +1663,21 @@ func (this *Player) OnLogouted() {
|
|||
}
|
||||
|
||||
func (this *Player) MarshalData() (d []byte, e error) {
|
||||
d, e = netlib.Gob.Marshal(this.PlayerData)
|
||||
data := &model.WGPlayerInfo{
|
||||
PlayerData: this.PlayerData,
|
||||
}
|
||||
info := PlayerInfoMgrSingle.Players[this.SnId]
|
||||
if info != nil {
|
||||
data.GameData = info.GameData
|
||||
}
|
||||
d, e = netlib.Gob.Marshal(data)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalData 更新玩家数据
|
||||
// 例如游戏服数据同步
|
||||
func (this *Player) UnmarshalData(data []byte, scene *Scene) {
|
||||
pd := &model.PlayerData{}
|
||||
pd := &model.WGPlayerInfo{}
|
||||
if err := netlib.Gob.Unmarshal(data, pd); err != nil {
|
||||
logger.Logger.Warn("Player.SyncData err:", err)
|
||||
return
|
||||
|
@ -1687,6 +1694,12 @@ func (this *Player) UnmarshalData(data []byte, scene *Scene) {
|
|||
this.GDatas[v] = d
|
||||
}
|
||||
}
|
||||
// PlayerInfo 同步
|
||||
info := PlayerInfoMgrSingle.Players[this.SnId]
|
||||
if info == nil {
|
||||
PlayerInfoMgrSingle.Players[this.SnId] = &PlayerInfo{}
|
||||
}
|
||||
info.GameData = pd.GameData
|
||||
|
||||
this.LastRechargeWinCoin = pd.LastRechargeWinCoin
|
||||
oldRecharge := int64(0)
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"mongo.games.com/goserver/core/basic"
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
"mongo.games.com/goserver/core/task"
|
||||
|
||||
"mongo.games.com/game/common"
|
||||
"mongo.games.com/game/model"
|
||||
"mongo.games.com/game/worldsrv/internal"
|
||||
)
|
||||
|
||||
/*
|
||||
玩家信息加载,缓存,持久化,缓存释放
|
||||
*/
|
||||
|
||||
func init() {
|
||||
internal.RegisterPlayerLoad(PlayerInfoMgrSingle)
|
||||
}
|
||||
|
||||
var PlayerInfoMgrSingle = &PlayerInfoMgr{
|
||||
Players: make(map[int32]*PlayerInfo),
|
||||
}
|
||||
|
||||
type AllPlayerInfo struct {
|
||||
GameData []*model.PlayerGameData
|
||||
}
|
||||
|
||||
// PlayerInfo 玩家信息
|
||||
type PlayerInfo struct {
|
||||
GameData map[int32]*model.PlayerGameData // 游戏数据
|
||||
}
|
||||
|
||||
type PlayerInfoMgr struct {
|
||||
Players map[int32]*PlayerInfo
|
||||
}
|
||||
|
||||
func (p *PlayerInfoMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay {
|
||||
var err error
|
||||
allPlayerInfo := &AllPlayerInfo{
|
||||
GameData: make([]*model.PlayerGameData, 0),
|
||||
}
|
||||
// 游戏数据
|
||||
gameData, err := model.GetPlayerGameData(platform, snid)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("GetPlayerGameData snid:%v error: %v", snid, err)
|
||||
goto here
|
||||
}
|
||||
allPlayerInfo.GameData = gameData
|
||||
// ...
|
||||
|
||||
here:
|
||||
return &internal.PlayerLoadReplay{
|
||||
Platform: platform,
|
||||
Snid: snid,
|
||||
Err: err,
|
||||
Data: allPlayerInfo,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PlayerInfoMgr) Callback(player any, ret *internal.PlayerLoadReplay) {
|
||||
if ret.Err != nil {
|
||||
return
|
||||
}
|
||||
data, ok := ret.Data.(*AllPlayerInfo)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
info := &PlayerInfo{
|
||||
GameData: make(map[int32]*model.PlayerGameData),
|
||||
}
|
||||
|
||||
// 游戏数据
|
||||
for _, v := range data.GameData {
|
||||
info.GameData[v.Id] = v
|
||||
}
|
||||
// ...
|
||||
|
||||
p.Players[ret.Snid] = info
|
||||
}
|
||||
|
||||
func (p *PlayerInfoMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PlayerInfoMgr) CallbackAfter(ret *internal.PlayerLoadReplay) {
|
||||
|
||||
}
|
||||
|
||||
func (p *PlayerInfoMgr) Save(platform string, snid int32, isSync, force bool) {
|
||||
var err error
|
||||
f := func() {
|
||||
data, ok := p.Players[snid]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// 游戏数据
|
||||
err = model.SavePlayerGameData(platform, common.GetMapValues(data.GameData))
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("SavePlayerGameData snid:%v error: %v", snid, err)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
cf := func() {
|
||||
|
||||
}
|
||||
|
||||
if isSync {
|
||||
f()
|
||||
cf()
|
||||
return
|
||||
}
|
||||
|
||||
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
||||
f()
|
||||
return nil
|
||||
}), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
|
||||
cf()
|
||||
}), "SavePlayerInfo").StartByFixExecutor("SnId:" + strconv.Itoa(int(snid)))
|
||||
}
|
||||
|
||||
func (p *PlayerInfoMgr) Release(platform string, snid int32) {
|
||||
delete(p.Players, snid)
|
||||
}
|
Loading…
Reference in New Issue