diff --git a/cmd/dispatch/application.toml b/cmd/dispatch/application.toml index 3f13c154..dd84dc9c 100644 --- a/cmd/dispatch/application.toml +++ b/cmd/dispatch/application.toml @@ -10,7 +10,7 @@ max_size = 10485760 url = "mongodb://mongo:27017" [redis] -addr = "redis:6379" +addr = "redis://redis:6379" password = "" [mq] diff --git a/cmd/gs/application.toml b/cmd/gs/application.toml index 18c01615..9f965f0c 100644 --- a/cmd/gs/application.toml +++ b/cmd/gs/application.toml @@ -14,7 +14,7 @@ max_size = 10485760 url = "mongodb://mongo:27017" [redis] -addr = "redis:6379" +addr = "redis://redis:6379" password = "" [mq] diff --git a/dispatch/controller/controller.go b/dispatch/controller/controller.go index 22808ef9..1a50366d 100644 --- a/dispatch/controller/controller.go +++ b/dispatch/controller/controller.go @@ -137,7 +137,6 @@ func (c *Controller) registerRouter() { } engine.Use(c.authorize()) engine.POST("/gate/token/verify", c.gateTokenVerify) - engine.POST("/gate/token/reset", c.gateTokenReset) port := config.GetConfig().HttpPort addr := ":" + strconv.Itoa(int(port)) err := engine.Run(addr) diff --git a/dispatch/controller/gate_controller.go b/dispatch/controller/gate_controller.go index 7de51e34..8814b0fc 100644 --- a/dispatch/controller/gate_controller.go +++ b/dispatch/controller/gate_controller.go @@ -3,6 +3,7 @@ package controller import ( "net/http" "strconv" + "time" "hk4e/pkg/logger" @@ -51,12 +52,7 @@ func (c *Controller) gateTokenVerify(context *gin.Context) { verifyFail(account.PlayerID) return } - if account.ComboTokenUsed { - verifyFail(account.PlayerID) - return - } - _, err = c.dao.UpdateAccountFieldByFieldName("AccountID", account.AccountID, "ComboTokenUsed", true) - if err != nil { + if time.Now().UnixMilli()-int64(account.ComboTokenCreateTime) > time.Minute.Milliseconds()*5 { verifyFail(account.PlayerID) return } @@ -67,32 +63,3 @@ func (c *Controller) gateTokenVerify(context *gin.Context) { PlayerID: account.PlayerID, }) } - -type TokenResetReq struct { - PlayerId uint32 `json:"playerId"` -} - -type TokenResetRsp struct { - Result bool `json:"result"` -} - -func (c *Controller) gateTokenReset(context *gin.Context) { - req := new(TokenResetReq) - err := context.ShouldBindJSON(req) - if err != nil { - context.JSON(http.StatusOK, &TokenResetRsp{ - Result: false, - }) - return - } - _, err = c.dao.UpdateAccountFieldByFieldName("PlayerID", req.PlayerId, "ComboTokenUsed", false) - if err != nil { - context.JSON(http.StatusOK, &TokenResetRsp{ - Result: false, - }) - return - } - context.JSON(http.StatusOK, &TokenResetRsp{ - Result: true, - }) -} diff --git a/dispatch/controller/login_controller.go b/dispatch/controller/login_controller.go index 1a90e767..8158af55 100644 --- a/dispatch/controller/login_controller.go +++ b/dispatch/controller/login_controller.go @@ -101,6 +101,7 @@ func (c *Controller) apiLogin(context *gin.Context) { // 自动注册 accountId, err := c.dao.GetNextAccountId() if err != nil { + logger.Error("get next account id error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-1" context.JSON(http.StatusOK, responseData) @@ -108,6 +109,7 @@ func (c *Controller) apiLogin(context *gin.Context) { } playerID, err := c.dao.GetNextYuanShenUid() if err != nil { + logger.Error("get next player id error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-2" context.JSON(http.StatusOK, responseData) @@ -125,6 +127,7 @@ func (c *Controller) apiLogin(context *gin.Context) { } _, err = c.dao.InsertAccount(regAccount) if err != nil { + logger.Error("insert account error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-3" context.JSON(http.StatusOK, responseData) @@ -142,6 +145,7 @@ func (c *Controller) apiLogin(context *gin.Context) { account.Token = base64.StdEncoding.EncodeToString(random.GetRandomByte(24)) _, err = c.dao.UpdateAccountFieldByFieldName("AccountID", account.AccountID, "Token", account.Token) if err != nil { + logger.Error("update account token error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-4" context.JSON(http.StatusOK, responseData) @@ -149,6 +153,7 @@ func (c *Controller) apiLogin(context *gin.Context) { } _, err = c.dao.UpdateAccountFieldByFieldName("AccountID", account.AccountID, "TokenCreateTime", time.Now().UnixMilli()) if err != nil { + logger.Error("update account token time error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-5" context.JSON(http.StatusOK, responseData) @@ -233,13 +238,15 @@ func (c *Controller) v2Login(context *gin.Context) { account.ComboToken = random.GetRandomByteHexStr(20) _, err = c.dao.UpdateAccountFieldByFieldName("AccountID", account.AccountID, "ComboToken", account.ComboToken) if err != nil { + logger.Error("update combo token error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-1" context.JSON(http.StatusOK, responseData) return } - _, err = c.dao.UpdateAccountFieldByFieldName("AccountID", account.AccountID, "ComboTokenUsed", false) + _, err = c.dao.UpdateAccountFieldByFieldName("AccountID", account.AccountID, "ComboTokenCreateTime", time.Now().UnixMilli()) if err != nil { + logger.Error("update combo token time error: %v", err) responseData.Retcode = -201 responseData.Message = "服务器内部错误:-2" context.JSON(http.StatusOK, responseData) diff --git a/dispatch/dao/account_mongo.go b/dispatch/dao/account_mongo.go index bfe3ce5f..0c92a17f 100644 --- a/dispatch/dao/account_mongo.go +++ b/dispatch/dao/account_mongo.go @@ -27,7 +27,7 @@ func (d *Dao) InsertAccount(account *model.Account) (primitive.ObjectID, error) func (d *Dao) UpdateAccountFieldByFieldName(fieldName string, fieldValue any, fieldUpdateName string, fieldUpdateValue any) (int64, error) { db := d.db.Collection("account") - updateCount, err := db.UpdateOne( + updateCount, err := db.UpdateMany( context.TODO(), bson.D{ {fieldName, fieldValue}, diff --git a/dispatch/dao/account_redis.go b/dispatch/dao/account_redis.go index 3a7f9564..f537fa0e 100644 --- a/dispatch/dao/account_redis.go +++ b/dispatch/dao/account_redis.go @@ -22,7 +22,13 @@ func (d *Dao) GetNextYuanShenUid() (uint32, error) { } func (d *Dao) redisInc(keyName string) (uint32, error) { - exist, err := d.redis.Exists(context.TODO(), keyName).Result() + var exist int64 = 0 + var err error = nil + if d.redisCluster != nil { + exist, err = d.redisCluster.Exists(context.TODO(), keyName).Result() + } else { + exist, err = d.redis.Exists(context.TODO(), keyName).Result() + } if err != nil { return 0, err } @@ -33,12 +39,22 @@ func (d *Dao) redisInc(keyName string) (uint32, error) { } else if keyName == RedisPlayerKeyPrefix+":"+YuanShenUidRedisKey { value = YuanShenUidBegin } - err := d.redis.Set(context.TODO(), keyName, value, 0).Err() + var err error = nil + if d.redisCluster != nil { + err = d.redisCluster.Set(context.TODO(), keyName, value, 0).Err() + } else { + err = d.redis.Set(context.TODO(), keyName, value, 0).Err() + } if err != nil { return 0, err } } - id, err := d.redis.Incr(context.TODO(), keyName).Result() + var id int64 = 0 + if d.redisCluster != nil { + id, err = d.redisCluster.Incr(context.TODO(), keyName).Result() + } else { + id, err = d.redis.Incr(context.TODO(), keyName).Result() + } if err != nil { return 0, err } diff --git a/dispatch/dao/dao.go b/dispatch/dao/dao.go index 14237dc8..d4179511 100644 --- a/dispatch/dao/dao.go +++ b/dispatch/dao/dao.go @@ -2,6 +2,7 @@ package dao import ( "context" + "strings" "hk4e/common/config" "hk4e/pkg/logger" @@ -13,13 +14,15 @@ import ( ) type Dao struct { - mongo *mongo.Client - db *mongo.Database - redis *redis.Client + mongo *mongo.Client + db *mongo.Database + redis *redis.Client + redisCluster *redis.ClusterClient } func NewDao() (r *Dao) { r = new(Dao) + clientOptions := options.Client().ApplyURI(config.GetConfig().Database.Url).SetMinPoolSize(10).SetMaxPoolSize(100) client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { @@ -33,18 +36,37 @@ func NewDao() (r *Dao) { } r.mongo = client r.db = client.Database("dispatch_hk4e") - r.redis = redis.NewClient(&redis.Options{ - Addr: config.GetConfig().Redis.Addr, - Password: config.GetConfig().Redis.Password, - DB: 0, - PoolSize: 10, - MinIdleConns: 1, - }) - err = r.redis.Ping(context.TODO()).Err() + + r.redis = nil + r.redisCluster = nil + redisAddr := strings.ReplaceAll(config.GetConfig().Redis.Addr, "redis://", "") + if strings.Contains(redisAddr, ",") { + redisAddrList := strings.Split(redisAddr, ",") + r.redisCluster = redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: redisAddrList, + Password: config.GetConfig().Redis.Password, + PoolSize: 10, + MinIdleConns: 1, + }) + } else { + r.redis = redis.NewClient(&redis.Options{ + Addr: redisAddr, + Password: config.GetConfig().Redis.Password, + DB: 0, + PoolSize: 10, + MinIdleConns: 1, + }) + } + if r.redisCluster != nil { + err = r.redisCluster.Ping(context.TODO()).Err() + } else { + err = r.redis.Ping(context.TODO()).Err() + } if err != nil { logger.Error("redis ping error: %v", err) return nil } + return r } @@ -53,7 +75,11 @@ func (d *Dao) CloseDao() { if err != nil { logger.Error("mongo close error: %v", err) } - err = d.redis.Close() + if d.redisCluster != nil { + err = d.redisCluster.Close() + } else { + err = d.redis.Close() + } if err != nil { logger.Error("redis close error: %v", err) } diff --git a/dispatch/model/account.go b/dispatch/model/account.go index 492bae2c..a25cf556 100644 --- a/dispatch/model/account.go +++ b/dispatch/model/account.go @@ -3,15 +3,15 @@ package model import "go.mongodb.org/mongo-driver/bson/primitive" type Account struct { - ID primitive.ObjectID `bson:"_id,omitempty"` - AccountID uint32 `bson:"AccountID"` - PlayerID uint32 `bson:"PlayerID"` - Username string `bson:"Username"` - Password string `bson:"Password"` - Token string `bson:"Token"` - TokenCreateTime uint64 `bson:"TokenCreateTime"` // 毫秒时间戳 - ComboToken string `bson:"ComboToken"` - ComboTokenUsed bool `bson:"ComboTokenUsed"` - Forbid bool `bson:"Forbid"` - ForbidEndTime uint32 `bson:"ForbidEndTime"` // 秒时间戳 + ID primitive.ObjectID `bson:"_id,omitempty"` + AccountID uint32 `bson:"AccountID"` + PlayerID uint32 `bson:"PlayerID"` + Username string `bson:"Username"` + Password string `bson:"Password"` + Token string `bson:"Token"` + TokenCreateTime uint64 `bson:"TokenCreateTime"` // 毫秒时间戳 + ComboToken string `bson:"ComboToken"` + ComboTokenCreateTime uint64 `bson:"ComboTokenCreateTime"` // 毫秒时间戳 + Forbid bool `bson:"Forbid"` + ForbidEndTime uint32 `bson:"ForbidEndTime"` // 秒时间戳 } diff --git a/docker/3rd/mongo/mongo_cluster/create_cluster.sh b/docker/3rd/mongo/mongo_cluster/create_cluster.sh new file mode 100755 index 00000000..7250c501 --- /dev/null +++ b/docker/3rd/mongo/mongo_cluster/create_cluster.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# shard1 +mongo --host 192.168.199.233 --port 27118 < 1000 && itemId < 2000 { avatarId := (itemId % 1000) + 10000000 - _, exist := player.AvatarMap[avatarId] + dbAvatar := player.GetDbAvatar() + _, exist := dbAvatar.AvatarMap[avatarId] if !exist { g.AddUserAvatar(player.PlayerID, avatarId) } else { constellationItemId := itemId + 100 - if player.GetItemCount(constellationItemId) < 6 { - g.AddUserItem(player.PlayerID, []*UserItem{{ItemId: constellationItemId, ChangeCount: 1}}, false, 0) + dbItem := player.GetDbItem() + if dbItem.GetItemCount(player, constellationItemId) < 6 { + g.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: constellationItemId, ChangeCount: 1}}, false, 0) } } } else if itemId > 10000 && itemId < 20000 { g.AddUserWeapon(player.PlayerID, itemId) } else { - g.AddUserItem(player.PlayerID, []*UserItem{{ItemId: itemId, ChangeCount: 1}}, false, 0) + g.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: itemId, ChangeCount: 1}}, false, 0) } // 计算星尘星辉 @@ -294,7 +296,7 @@ func (g *GameManager) DoGachaReq(player *model.Player, payloadMsg pb.Message) { } // 星尘 if xc != 0 { - g.AddUserItem(player.PlayerID, []*UserItem{{ + g.AddUserItem(player.PlayerID, []*ChangeItem{{ ItemId: 222, ChangeCount: xc, }}, false, 0) @@ -305,7 +307,7 @@ func (g *GameManager) DoGachaReq(player *model.Player, payloadMsg pb.Message) { } // 星辉 if xh != 0 { - g.AddUserItem(player.PlayerID, []*UserItem{{ + g.AddUserItem(player.PlayerID, []*ChangeItem{{ ItemId: 221, ChangeCount: xh, }}, false, 0) @@ -392,7 +394,8 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab } // 获取用户的卡池保底信息 - gachaPoolInfo := player.DropInfo.GachaPoolInfo[gachaType] + dbGacha := player.GetDbGacha() + gachaPoolInfo := dbGacha.GachaPoolInfo[gachaType] if gachaPoolInfo == nil { logger.Error("user gacha pool info not found, gacha type: %v", gachaType) return false, 0 diff --git a/gs/game/player_gcg.go b/gs/game/player_gcg.go index afa445e9..2ef244d4 100644 --- a/gs/game/player_gcg.go +++ b/gs/game/player_gcg.go @@ -169,6 +169,7 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message) }, } // 玩家信息列表 + dbAvatar := player.GetDbAvatar() for _, controller := range game.controllerMap { gcgControllerShowInfo := &proto.GCGControllerShowInfo{ ControllerId: controller.controllerId, @@ -177,7 +178,7 @@ func (g *GameManager) GCGAskDuelReq(player *model.Player, payloadMsg pb.Message) // 如果为玩家则更改为玩家信息 if controller.controllerType == ControllerType_Player { gcgControllerShowInfo.ProfilePicture.AvatarId = player.HeadImage - gcgControllerShowInfo.ProfilePicture.AvatarId = player.AvatarMap[player.HeadImage].Costume + gcgControllerShowInfo.ProfilePicture.AvatarId = dbAvatar.AvatarMap[player.HeadImage].Costume } gcgAskDuelRsp.Duel.ShowInfoList = append(gcgAskDuelRsp.Duel.ShowInfoList) } @@ -481,6 +482,8 @@ func (g *GameManager) PacketGCGGameBriefDataNotify(player *model.Player, busines }, IsNewGame: true, // TODO 根据游戏修改 } + dbTeam := player.GetDbTeam() + dbAvatar := player.GetDbAvatar() for _, controller := range game.controllerMap { gcgPlayerBriefData := &proto.GCGPlayerBriefData{ ControllerId: controller.controllerId, @@ -494,8 +497,8 @@ func (g *GameManager) PacketGCGGameBriefDataNotify(player *model.Player, busines // 玩家信息 if controller.player != nil { gcgPlayerBriefData.Uid = player.PlayerID - gcgPlayerBriefData.ProfilePicture.AvatarId = player.TeamConfig.GetActiveAvatarId() - gcgPlayerBriefData.ProfilePicture.CostumeId = player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Costume + gcgPlayerBriefData.ProfilePicture.AvatarId = dbTeam.GetActiveAvatarId() + gcgPlayerBriefData.ProfilePicture.CostumeId = dbAvatar.AvatarMap[dbTeam.GetActiveAvatarId()].Costume gcgPlayerBriefData.NickName = player.NickName } gcgGameBriefDataNotify.GcgBriefData.PlayerBriefList = append(gcgGameBriefDataNotify.GcgBriefData.PlayerBriefList) diff --git a/gs/game/player_item.go b/gs/game/player_item.go index a7511f21..207b94a0 100644 --- a/gs/game/player_item.go +++ b/gs/game/player_item.go @@ -8,7 +8,7 @@ import ( "hk4e/protocol/proto" ) -type UserItem struct { +type ChangeItem struct { ItemId uint32 ChangeCount uint32 } @@ -49,7 +49,7 @@ func (g *GameManager) GetAllItemDataConfig() map[int32]*gdconf.ItemData { } // AddUserItem 玩家添加物品 -func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bool, hintReason uint16) { +func (g *GameManager) AddUserItem(userId uint32, itemList []*ChangeItem, isHint bool, hintReason uint16) { player := USER_MANAGER.GetOnlineUser(userId) if player == nil { logger.Error("player is nil, uid: %v", userId) @@ -58,6 +58,7 @@ func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bo playerPropNotify := &proto.PlayerPropNotify{ PropMap: make(map[uint32]*proto.PropValue), } + dbItem := player.GetDbItem() for _, userItem := range itemList { // 物品为虚拟物品则另外处理 switch userItem.ItemId { @@ -83,7 +84,7 @@ func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bo g.AddUserPlayerExp(userId, userItem.ChangeCount) default: // 普通物品直接进背包 - player.AddItem(userItem.ItemId, userItem.ChangeCount) + dbItem.AddItem(player, userItem.ItemId, userItem.ChangeCount) } } if len(playerPropNotify.PropMap) > 0 { @@ -97,10 +98,10 @@ func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bo for _, userItem := range itemList { pbItem := &proto.Item{ ItemId: userItem.ItemId, - Guid: player.GetItemGuid(userItem.ItemId), + Guid: dbItem.GetItemGuid(userItem.ItemId), Detail: &proto.Item_Material{ Material: &proto.Material{ - Count: player.GetItemCount(userItem.ItemId), + Count: dbItem.GetItemCount(player, userItem.ItemId), }, }, } @@ -127,7 +128,7 @@ func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bo } } -func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) { +func (g *GameManager) CostUserItem(userId uint32, itemList []*ChangeItem) { player := USER_MANAGER.GetOnlineUser(userId) if player == nil { logger.Error("player is nil, uid: %v", userId) @@ -136,6 +137,7 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) { playerPropNotify := &proto.PlayerPropNotify{ PropMap: make(map[uint32]*proto.PropValue), } + dbItem := player.GetDbItem() for _, userItem := range itemList { // 物品为虚拟物品则另外处理 switch userItem.ItemId { @@ -164,7 +166,7 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) { // 冒险阅历应该也没人会去扣吧? default: // 普通物品直接扣除 - player.CostItem(userItem.ItemId, userItem.ChangeCount) + dbItem.CostItem(player, userItem.ItemId, userItem.ChangeCount) } } if len(playerPropNotify.PropMap) > 0 { @@ -176,13 +178,13 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) { ItemList: make([]*proto.Item, 0), } for _, userItem := range itemList { - count := player.GetItemCount(userItem.ItemId) + count := dbItem.GetItemCount(player, userItem.ItemId) if count == 0 { continue } pbItem := &proto.Item{ ItemId: userItem.ItemId, - Guid: player.GetItemGuid(userItem.ItemId), + Guid: dbItem.GetItemGuid(userItem.ItemId), Detail: &proto.Item_Material{ Material: &proto.Material{ Count: count, @@ -200,11 +202,11 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) { GuidList: make([]uint64, 0), } for _, userItem := range itemList { - count := player.GetItemCount(userItem.ItemId) + count := dbItem.GetItemCount(player, userItem.ItemId) if count > 0 { continue } - storeItemDelNotify.GuidList = append(storeItemDelNotify.GuidList, player.GetItemGuid(userItem.ItemId)) + storeItemDelNotify.GuidList = append(storeItemDelNotify.GuidList, dbItem.GetItemGuid(userItem.ItemId)) } if len(storeItemDelNotify.GuidList) > 0 { g.SendMsg(cmd.StoreItemDelNotify, userId, player.ClientSeq, storeItemDelNotify) diff --git a/gs/game/player_login.go b/gs/game/player_login.go index 31cb7594..a3401b2d 100644 --- a/gs/game/player_login.go +++ b/gs/game/player_login.go @@ -56,7 +56,15 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u player.GateAppId = gateAppId // 初始化 - player.InitAll() + player.InitOnlineData() + dbAvatar := player.GetDbAvatar() + dbAvatar.InitAllAvatar(player) + dbReliquary := player.GetDbReliquary() + dbReliquary.InitAllReliquary(player) + dbWeapon := player.GetDbWeapon() + dbWeapon.InitAllWeapon(player) + dbItem := player.GetDbItem() + dbItem.InitAllItem(player) // 确保玩家位置安全 player.Pos.X = player.SafePos.X @@ -68,9 +76,6 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u player.Rot = &model.Vector{X: 0, Y: 307, Z: 0} } - player.CombatInvokeHandler = model.NewInvokeHandler[proto.CombatInvokeEntry]() - player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]() - if userId < PlayerBaseUid { return } @@ -196,12 +201,15 @@ func (g *GameManager) PacketStoreWeightLimitNotify() *proto.StoreWeightLimitNoti } func (g *GameManager) PacketPlayerStoreNotify(player *model.Player) *proto.PlayerStoreNotify { + dbItem := player.GetDbItem() + dbWeapon := player.GetDbWeapon() + dbReliquary := player.GetDbReliquary() playerStoreNotify := &proto.PlayerStoreNotify{ StoreType: proto.StoreType_STORE_PACK, WeightLimit: constant.STORE_PACK_LIMIT_WEIGHT, - ItemList: make([]*proto.Item, 0, len(player.WeaponMap)+len(player.ReliquaryMap)+len(player.ItemMap)), + ItemList: make([]*proto.Item, 0, len(dbItem.ItemMap)+len(dbWeapon.WeaponMap)+len(dbReliquary.ReliquaryMap)), } - for _, weapon := range player.WeaponMap { + for _, weapon := range dbWeapon.WeaponMap { itemDataConfig := gdconf.GetItemDataById(int32(weapon.ItemId)) if itemDataConfig == nil { logger.Error("get item data config is nil, itemId: %v", weapon.ItemId) @@ -233,7 +241,7 @@ func (g *GameManager) PacketPlayerStoreNotify(player *model.Player) *proto.Playe } playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem) } - for _, reliquary := range player.ReliquaryMap { + for _, reliquary := range dbReliquary.ReliquaryMap { itemDataConfig := gdconf.GetItemDataById(int32(reliquary.ItemId)) if itemDataConfig == nil { logger.Error("get item data config is nil, itemId: %v", reliquary.ItemId) @@ -262,7 +270,7 @@ func (g *GameManager) PacketPlayerStoreNotify(player *model.Player) *proto.Playe } playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem) } - for _, item := range player.ItemMap { + for _, item := range dbItem.ItemMap { itemDataConfig := gdconf.GetItemDataById(int32(item.ItemId)) if itemDataConfig == nil { logger.Error("get item data config is nil, itemId: %v", item.ItemId) @@ -293,24 +301,25 @@ func (g *GameManager) PacketPlayerStoreNotify(player *model.Player) *proto.Playe } func (g *GameManager) PacketAvatarDataNotify(player *model.Player) *proto.AvatarDataNotify { - chooseAvatarId := player.MainCharAvatarId + dbAvatar := player.GetDbAvatar() + dbTeam := player.GetDbTeam() avatarDataNotify := &proto.AvatarDataNotify{ - CurAvatarTeamId: uint32(player.TeamConfig.GetActiveTeamId()), - ChooseAvatarGuid: player.AvatarMap[chooseAvatarId].Guid, + CurAvatarTeamId: uint32(dbTeam.GetActiveTeamId()), + ChooseAvatarGuid: dbAvatar.AvatarMap[dbAvatar.MainCharAvatarId].Guid, OwnedFlycloakList: player.FlyCloakList, // 角色衣装 OwnedCostumeList: player.CostumeList, AvatarList: make([]*proto.AvatarInfo, 0), AvatarTeamMap: make(map[uint32]*proto.AvatarTeam), } - for _, avatar := range player.AvatarMap { + for _, avatar := range dbAvatar.AvatarMap { pbAvatar := g.PacketAvatarInfo(avatar) avatarDataNotify.AvatarList = append(avatarDataNotify.AvatarList, pbAvatar) } - for teamIndex, team := range player.TeamConfig.TeamList { + for teamIndex, team := range dbTeam.TeamList { var teamAvatarGuidList []uint64 = nil for _, avatarId := range team.GetAvatarIdList() { - teamAvatarGuidList = append(teamAvatarGuidList, player.AvatarMap[avatarId].Guid) + teamAvatarGuidList = append(teamAvatarGuidList, dbAvatar.AvatarMap[avatarId].Guid) } avatarDataNotify.AvatarTeamMap[uint32(teamIndex)+1] = &proto.AvatarTeam{ AvatarGuidList: teamAvatarGuidList, @@ -336,7 +345,6 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata player.PlayerID = userId player.NickName = nickName player.Signature = "" - player.MainCharAvatarId = mainCharAvatarId player.HeadImage = mainCharAvatarId player.Birthday = []uint8{0, 0} player.NameCard = 210001 @@ -368,29 +376,28 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata player.Pos = &model.Vector{X: 2747, Y: 194, Z: -1719} player.Rot = &model.Vector{X: 0, Y: 307, Z: 0} - player.ItemMap = make(map[uint32]*model.Item) - player.WeaponMap = make(map[uint64]*model.Weapon) - player.ReliquaryMap = make(map[uint64]*model.Reliquary) - player.AvatarMap = make(map[uint32]*model.Avatar) + dbAvatar := player.GetDbAvatar() + dbAvatar.MainCharAvatarId = mainCharAvatarId + player.GameObjectGuidMap = make(map[uint64]model.GameObject) - player.DropInfo = model.NewDropInfo() player.GCGInfo = model.NewGCGInfo() // 添加选定的主角 - player.AddAvatar(mainCharAvatarId) - // 添加初始武器 + dbAvatar.AddAvatar(player, mainCharAvatarId) + // 添加主角初始武器 avatarDataConfig := gdconf.GetAvatarDataById(int32(mainCharAvatarId)) if avatarDataConfig == nil { logger.Error("config is nil, mainCharAvatarId: %v", mainCharAvatarId) return nil } weaponId := uint64(g.snowflake.GenId()) - player.AddWeapon(uint32(avatarDataConfig.InitialWeapon), weaponId) - // 角色装上初始武器 - player.WearWeapon(mainCharAvatarId, weaponId) + dbWeapon := player.GetDbWeapon() + dbWeapon.AddWeapon(player, uint32(avatarDataConfig.InitialWeapon), weaponId) + weapon := dbWeapon.WeaponMap[weaponId] + dbAvatar.WearWeapon(mainCharAvatarId, weapon) - player.TeamConfig = model.NewTeamInfo() - player.TeamConfig.GetActiveTeam().SetAvatarIdList([]uint32{mainCharAvatarId}) + dbTeam := player.GetDbTeam() + dbTeam.GetActiveTeam().SetAvatarIdList([]uint32{mainCharAvatarId}) player.ChatMsgMap = make(map[uint32][]*model.ChatMsg) diff --git a/gs/game/player_reliquary.go b/gs/game/player_reliquary.go index 47db032b..f2a5c2b1 100644 --- a/gs/game/player_reliquary.go +++ b/gs/game/player_reliquary.go @@ -46,8 +46,9 @@ func (g *GameManager) AddUserReliquary(userId uint32, itemId uint32) uint64 { // 圣遗物主属性 mainPropId := uint32(reliquaryMainConfig.MainPropId) // 玩家添加圣遗物 - player.AddReliquary(itemId, reliquaryId, mainPropId) - reliquary := player.GetReliquary(reliquaryId) + dbReliquary := player.GetDbReliquary() + dbReliquary.AddReliquary(player, itemId, reliquaryId, mainPropId) + reliquary := dbReliquary.GetReliquary(reliquaryId) if reliquary == nil { logger.Error("reliquary is nil, itemId: %v, reliquaryId: %v", itemId, reliquaryId) return 0 @@ -108,8 +109,9 @@ func (g *GameManager) CostUserReliquary(userId uint32, reliquaryIdList []uint64) GuidList: make([]uint64, 0, len(reliquaryIdList)), StoreType: proto.StoreType_STORE_PACK, } + dbReliquary := player.GetDbReliquary() for _, reliquaryId := range reliquaryIdList { - reliquaryGuid := player.CostReliquary(reliquaryId) + reliquaryGuid := dbReliquary.CostReliquary(player, reliquaryId) if reliquaryGuid == 0 { logger.Error("reliquary cost error, reliquaryId: %v", reliquaryId) return diff --git a/gs/game/player_scene.go b/gs/game/player_scene.go index 4c711ff6..55ac0ab4 100644 --- a/gs/game/player_scene.go +++ b/gs/game/player_scene.go @@ -148,8 +148,9 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes }, AvatarEnterInfo: make([]*proto.AvatarEnterSceneInfo, 0), } + dbAvatar := player.GetDbAvatar() for _, worldAvatar := range world.GetPlayerWorldAvatarList(player) { - avatar := player.AvatarMap[worldAvatar.GetAvatarId()] + avatar := dbAvatar.AvatarMap[worldAvatar.GetAvatarId()] avatarEnterSceneInfo := &proto.AvatarEnterSceneInfo{ AvatarGuid: avatar.Guid, AvatarEntityId: world.GetPlayerWorldAvatarEntityId(player, worldAvatar.GetAvatarId()), @@ -652,7 +653,8 @@ func (g *GameManager) PacketSceneEntityInfoAvatar(scene *Scene, player *model.Pl Z: float32(entity.GetPos().Z), } worldAvatar := scene.GetWorld().GetWorldAvatarByEntityId(entity.GetId()) - avatar, ok := player.AvatarMap[worldAvatar.GetAvatarId()] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[worldAvatar.GetAvatarId()] if !ok { logger.Error("avatar error, avatarId: %v", worldAvatar.GetAvatarId()) return new(proto.SceneEntityInfo) @@ -897,7 +899,8 @@ func (g *GameManager) PacketSceneEntityInfoGadget(scene *Scene, entityId uint32) } func (g *GameManager) PacketSceneAvatarInfo(scene *Scene, player *model.Player, avatarId uint32) *proto.SceneAvatarInfo { - avatar, ok := player.AvatarMap[avatarId] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[avatarId] if !ok { logger.Error("avatar error, avatarId: %v", avatarId) return new(proto.SceneAvatarInfo) diff --git a/gs/game/player_shop.go b/gs/game/player_shop.go index 0a3b30a5..794e00c2 100644 --- a/gs/game/player_shop.go +++ b/gs/game/player_shop.go @@ -80,19 +80,20 @@ func (g *GameManager) BuyGoodsReq(player *model.Player, payloadMsg pb.Message) { return } - if player.GetItemCount(201) < costHcoinCount { + dbItem := player.GetDbItem() + if dbItem.GetItemCount(player, 201) < costHcoinCount { return } - g.CostUserItem(player.PlayerID, []*UserItem{{ + g.CostUserItem(player.PlayerID, []*ChangeItem{{ ItemId: 201, ChangeCount: costHcoinCount, }}) - g.AddUserItem(player.PlayerID, []*UserItem{{ + g.AddUserItem(player.PlayerID, []*ChangeItem{{ ItemId: buyItemId, ChangeCount: buyItemCount, }}, true, constant.ActionReasonShop) - req.Goods.BoughtNum = player.GetItemCount(buyItemId) + req.Goods.BoughtNum = dbItem.GetItemCount(player, buyItemId) buyGoodsRsp := &proto.BuyGoodsRsp{ ShopType: req.ShopType, @@ -110,15 +111,16 @@ func (g *GameManager) McoinExchangeHcoinReq(player *model.Player, payloadMsg pb. } count := req.Hcoin - if player.GetItemCount(203) < count { + dbItem := player.GetDbItem() + if dbItem.GetItemCount(player, 203) < count { return } - g.CostUserItem(player.PlayerID, []*UserItem{{ + g.CostUserItem(player.PlayerID, []*ChangeItem{{ ItemId: 203, ChangeCount: count, }}) - g.AddUserItem(player.PlayerID, []*UserItem{{ + g.AddUserItem(player.PlayerID, []*ChangeItem{{ ItemId: 201, ChangeCount: count, }}, false, 0) diff --git a/gs/game/player_social.go b/gs/game/player_social.go index 53251b61..35468e13 100644 --- a/gs/game/player_social.go +++ b/gs/game/player_social.go @@ -127,7 +127,8 @@ func (g *GameManager) SetPlayerHeadImageReq(player *model.Player, payloadMsg pb. logger.Debug("user change head image, uid: %v", player.PlayerID) req := payloadMsg.(*proto.SetPlayerHeadImageReq) avatarId := req.AvatarId - _, exist := player.AvatarMap[avatarId] + dbAvatar := player.GetDbAvatar() + _, exist := dbAvatar.AvatarMap[avatarId] if !exist { logger.Error("the head img of the avatar not exist, uid: %v", player.PlayerID) return diff --git a/gs/game/player_team.go b/gs/game/player_team.go index d308f8f1..cd6c4cc5 100644 --- a/gs/game/player_team.go +++ b/gs/game/player_team.go @@ -39,7 +39,8 @@ func (g *GameManager) ChangeAvatarReq(player *model.Player, payloadMsg pb.Messag return } if !world.GetMultiplayer() { - player.TeamConfig.CurrAvatarIndex = uint8(newAvatarIndex) + dbTeam := player.GetDbTeam() + dbTeam.CurrAvatarIndex = uint8(newAvatarIndex) } world.SetPlayerAvatarIndex(player, newAvatarIndex) oldAvatarEntityId := world.GetPlayerWorldAvatarEntityId(player, oldAvatarId) @@ -89,31 +90,33 @@ func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Mes return } avatarGuidList := req.AvatarTeamGuidList - selfTeam := teamId == uint32(player.TeamConfig.GetActiveTeamId()) + dbTeam := player.GetDbTeam() + selfTeam := teamId == uint32(dbTeam.GetActiveTeamId()) if (selfTeam && len(avatarGuidList) == 0) || len(avatarGuidList) > 4 { g.SendError(cmd.SetUpAvatarTeamRsp, player, &proto.SetUpAvatarTeamRsp{}) return } avatarIdList := make([]uint32, 0) + dbAvatar := player.GetDbAvatar() for _, avatarGuid := range avatarGuidList { - for avatarId, avatar := range player.AvatarMap { + for avatarId, avatar := range dbAvatar.AvatarMap { if avatarGuid == avatar.Guid { avatarIdList = append(avatarIdList, avatarId) } } } - player.TeamConfig.GetTeamByIndex(uint8(teamId - 1)).SetAvatarIdList(avatarIdList) + dbTeam.GetTeamByIndex(uint8(teamId - 1)).SetAvatarIdList(avatarIdList) avatarTeamUpdateNotify := &proto.AvatarTeamUpdateNotify{ AvatarTeamMap: make(map[uint32]*proto.AvatarTeam), } - for teamIndex, team := range player.TeamConfig.TeamList { + for teamIndex, team := range dbTeam.TeamList { avatarTeam := &proto.AvatarTeam{ TeamName: team.Name, AvatarGuidList: make([]uint64, 0), } for _, avatarId := range team.GetAvatarIdList() { - avatarTeam.AvatarGuidList = append(avatarTeam.AvatarGuidList, player.AvatarMap[avatarId].Guid) + avatarTeam.AvatarGuidList = append(avatarTeam.AvatarGuidList, dbAvatar.AvatarMap[avatarId].Guid) } avatarTeamUpdateNotify.AvatarTeamMap[uint32(teamIndex)+1] = avatarTeam } @@ -133,7 +136,7 @@ func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Mes } currAvatarId := currAvatar.AvatarId currAvatarIndex := world.GetPlayerAvatarIndexByAvatarId(player, currAvatarId) - player.TeamConfig.CurrAvatarIndex = uint8(currAvatarIndex) + dbTeam.CurrAvatarIndex = uint8(currAvatarIndex) world.SetPlayerAvatarIndex(player, currAvatarIndex) sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world) @@ -157,12 +160,13 @@ func (g *GameManager) ChooseCurAvatarTeamReq(player *model.Player, payloadMsg pb g.SendError(cmd.ChooseCurAvatarTeamRsp, player, &proto.ChooseCurAvatarTeamRsp{}) return } - team := player.TeamConfig.GetTeamByIndex(uint8(teamId) - 1) + dbTeam := player.GetDbTeam() + team := dbTeam.GetTeamByIndex(uint8(teamId) - 1) if team == nil || len(team.GetAvatarIdList()) == 0 { return } - player.TeamConfig.CurrTeamIndex = uint8(teamId) - 1 - player.TeamConfig.CurrAvatarIndex = 0 + dbTeam.CurrTeamIndex = uint8(teamId) - 1 + dbTeam.CurrAvatarIndex = 0 // player.TeamConfig.UpdateTeam() world.SetPlayerAvatarIndex(player, 0) world.SetPlayerLocalTeam(player, team.GetAvatarIdList()) @@ -239,7 +243,8 @@ func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeam logger.Error("scene is nil, sceneId: %v", worldPlayer.SceneId) return new(proto.SceneTeamUpdateNotify) } - worldPlayerAvatar := worldPlayer.AvatarMap[worldAvatar.GetAvatarId()] + worldPlayerDbAvatar := worldPlayer.GetDbAvatar() + worldPlayerAvatar := worldPlayerDbAvatar.AvatarMap[worldAvatar.GetAvatarId()] equipIdList := make([]uint32, 0) weapon := worldPlayerAvatar.EquipWeapon equipIdList = append(equipIdList, weapon.ItemId) diff --git a/gs/game/player_vehicle.go b/gs/game/player_vehicle.go index c2453220..51e2fcf8 100644 --- a/gs/game/player_vehicle.go +++ b/gs/game/player_vehicle.go @@ -114,7 +114,9 @@ func (g *GameManager) DestroyVehicleEntity(player *model.Player, scene *Scene, v // 如果玩家正在载具中 if g.IsPlayerInVehicle(player, gadgetEntity.GetGadgetVehicleEntity()) { // 离开载具 - g.ExitVehicle(player, entity, player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid) + dbTeam := player.GetDbTeam() + dbAvatar := player.GetDbAvatar() + g.ExitVehicle(player, entity, dbAvatar.AvatarMap[dbTeam.GetActiveAvatarId()].Guid) } // 删除已创建的载具 scene.DestroyEntity(entity.GetId()) @@ -220,7 +222,9 @@ func (g *GameManager) VehicleInteractReq(player *model.Player, payloadMsg pb.Mes return } - avatarGuid := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid + dbTeam := player.GetDbTeam() + dbAvatar := player.GetDbAvatar() + avatarGuid := dbAvatar.AvatarMap[dbTeam.GetActiveAvatarId()].Guid switch req.InteractType { case proto.VehicleInteractType_VEHICLE_INTERACT_IN: diff --git a/gs/game/player_weapon.go b/gs/game/player_weapon.go index ec1ca928..453d1054 100644 --- a/gs/game/player_weapon.go +++ b/gs/game/player_weapon.go @@ -50,8 +50,9 @@ func (g *GameManager) AddUserWeapon(userId uint32, itemId uint32) uint64 { return 0 } weaponId := uint64(g.snowflake.GenId()) - player.AddWeapon(itemId, weaponId) - weapon := player.GetWeapon(weaponId) + dbWeapon := player.GetDbWeapon() + dbWeapon.AddWeapon(player, itemId, weaponId) + weapon := dbWeapon.GetWeapon(weaponId) if weapon == nil { logger.Error("weapon is nil, itemId: %v, weaponId: %v", itemId, weaponId) return 0 @@ -70,8 +71,9 @@ func (g *GameManager) CostUserWeapon(userId uint32, weaponIdList []uint64) { GuidList: make([]uint64, 0, len(weaponIdList)), StoreType: proto.StoreType_STORE_PACK, } + dbWeapon := player.GetDbWeapon() for _, weaponId := range weaponIdList { - weaponGuid := player.CostWeapon(weaponId) + weaponGuid := dbWeapon.CostWeapon(player, weaponId) if weaponGuid == 0 { logger.Error("weapon cost error, weaponId: %v", weaponId) return @@ -142,7 +144,8 @@ func (g *GameManager) WeaponAwakenReq(player *model.Player, payloadMsg pb.Messag return } // 摩拉数量是否足够 - if player.GetItemCount(constant.ITEM_ID_SCOIN) < weaponConfig.AwakenCoinCostList[weapon.Refinement] { + dbItem := player.GetDbItem() + if dbItem.GetItemCount(player, constant.ITEM_ID_SCOIN) < weaponConfig.AwakenCoinCostList[weapon.Refinement] { logger.Error("item count not enough, itemId: %v", constant.ITEM_ID_SCOIN) g.SendError(cmd.WeaponAwakenRsp, player, &proto.WeaponAwakenRsp{}, proto.Retcode_RET_SCOIN_NOT_ENOUGH) return @@ -224,7 +227,7 @@ func (g *GameManager) WeaponAwakenReq(player *model.Player, payloadMsg pb.Messag return } // 消耗作为精炼材料的道具 - g.CostUserItem(player.PlayerID, []*UserItem{ + g.CostUserItem(player.PlayerID, []*ChangeItem{ { ItemId: item.ItemId, ChangeCount: 1, @@ -236,7 +239,7 @@ func (g *GameManager) WeaponAwakenReq(player *model.Player, payloadMsg pb.Messag return } // 消耗摩拉 - g.CostUserItem(player.PlayerID, []*UserItem{ + g.CostUserItem(player.PlayerID, []*ChangeItem{ { ItemId: constant.ITEM_ID_SCOIN, ChangeCount: weaponConfig.AwakenCoinCostList[weapon.Refinement], @@ -260,7 +263,8 @@ func (g *GameManager) WeaponAwakenReq(player *model.Player, payloadMsg pb.Messag // 更新武器的物品数据 g.SendMsg(cmd.StoreItemChangeNotify, player.PlayerID, player.ClientSeq, g.PacketStoreItemChangeNotifyByWeapon(weapon)) // 获取持有该武器的角色 - avatar, ok := player.AvatarMap[weapon.AvatarId] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[weapon.AvatarId] // 武器可能没被任何角色装备 仅在被装备时更新面板 if ok { weaponAwakenRsp.AvatarGuid = avatar.Guid @@ -315,22 +319,23 @@ func (g *GameManager) WeaponPromoteReq(player *model.Player, payloadMsg pb.Messa return } // 将被消耗的物品列表 - costItemList := make([]*UserItem, 0, len(weaponPromoteConfig.CostItemMap)+1) + costItemList := make([]*ChangeItem, 0, len(weaponPromoteConfig.CostItemMap)+1) // 突破材料是否足够并添加到消耗物品列表 for itemId, count := range weaponPromoteConfig.CostItemMap { - costItemList = append(costItemList, &UserItem{ + costItemList = append(costItemList, &ChangeItem{ ItemId: itemId, ChangeCount: count, }) } // 消耗列表添加摩拉的消耗 - costItemList = append(costItemList, &UserItem{ + costItemList = append(costItemList, &ChangeItem{ ItemId: constant.ITEM_ID_SCOIN, ChangeCount: uint32(weaponPromoteConfig.CostCoin), }) // 突破材料以及摩拉是否足够 + dbItem := player.GetDbItem() for _, item := range costItemList { - if player.GetItemCount(item.ItemId) < item.ChangeCount { + if dbItem.GetItemCount(player, item.ItemId) < item.ChangeCount { logger.Error("item count not enough, itemId: %v", item.ItemId) // 摩拉的错误提示与材料不同 if item.ItemId == constant.ITEM_ID_SCOIN { @@ -357,7 +362,8 @@ func (g *GameManager) WeaponPromoteReq(player *model.Player, payloadMsg pb.Messa // 更新武器的物品数据 g.SendMsg(cmd.StoreItemChangeNotify, player.PlayerID, player.ClientSeq, g.PacketStoreItemChangeNotifyByWeapon(weapon)) // 获取持有该武器的角色 - avatar, ok := player.AvatarMap[weapon.AvatarId] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[weapon.AvatarId] // 武器可能没被任何角色装备 仅在被装备时更新面板 if ok { // 角色更新面板 @@ -576,10 +582,10 @@ func (g *GameManager) WeaponUpgradeReq(player *model.Player, payloadMsg pb.Messa return } // 将被消耗的物品列表 - costItemList := make([]*UserItem, 0, len(req.ItemParamList)+1) + costItemList := make([]*ChangeItem, 0, len(req.ItemParamList)+1) // 突破材料是否足够并添加到消耗物品列表 for _, itemParam := range req.ItemParamList { - costItemList = append(costItemList, &UserItem{ + costItemList = append(costItemList, &ChangeItem{ ItemId: itemParam.ItemId, ChangeCount: itemParam.Count, }) @@ -592,13 +598,14 @@ func (g *GameManager) WeaponUpgradeReq(player *model.Player, payloadMsg pb.Messa return } // 消耗列表添加摩拉的消耗 - costItemList = append(costItemList, &UserItem{ + costItemList = append(costItemList, &ChangeItem{ ItemId: constant.ITEM_ID_SCOIN, ChangeCount: coinCost, }) // 校验物品是否足够 + dbItem := player.GetDbItem() for _, item := range costItemList { - if player.GetItemCount(item.ItemId) < item.ChangeCount { + if dbItem.GetItemCount(player, item.ItemId) < item.ChangeCount { logger.Error("item count not enough, itemId: %v", item.ItemId) // 摩拉的错误提示与材料不同 if item.ItemId == constant.ITEM_ID_SCOIN { @@ -652,7 +659,8 @@ func (g *GameManager) WeaponUpgradeReq(player *model.Player, payloadMsg pb.Messa g.SendMsg(cmd.StoreItemChangeNotify, player.PlayerID, player.ClientSeq, g.PacketStoreItemChangeNotifyByWeapon(weapon)) // 获取持有该武器的角色 - avatar, ok := player.AvatarMap[weapon.AvatarId] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[weapon.AvatarId] // 武器可能没被任何角色装备 仅在被装备时更新面板 if ok { // 角色更新面板 @@ -660,9 +668,9 @@ func (g *GameManager) WeaponUpgradeReq(player *model.Player, payloadMsg pb.Messa } // 将给予的材料列表 - addItemList := make([]*UserItem, 0, len(returnItemList)) + addItemList := make([]*ChangeItem, 0, len(returnItemList)) for _, param := range returnItemList { - addItemList = append(addItemList, &UserItem{ + addItemList = append(addItemList, &ChangeItem{ ItemId: param.ItemId, ChangeCount: param.Count, }) diff --git a/gs/game/tick_manager.go b/gs/game/tick_manager.go index 7140fd8d..0270b8de 100644 --- a/gs/game/tick_manager.go +++ b/gs/game/tick_manager.go @@ -194,19 +194,19 @@ func (t *TickManager) onTickMinute(now int64) { i := int32(0) for itemId := range allItemDataConfig { num := random.GetRandomInt32(1, 9) - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: uint32(itemId), ChangeCount: uint32(num)}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: uint32(itemId), ChangeCount: uint32(num)}}, true, 0) i++ if i > count { break } } - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 102, ChangeCount: 30}}, true, 0) - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 201, ChangeCount: 10}}, true, 0) - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 202, ChangeCount: 100}}, true, 0) - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 203, ChangeCount: 10}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: 102, ChangeCount: 30}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: 201, ChangeCount: 10}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: 202, ChangeCount: 100}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: 203, ChangeCount: 10}}, true, 0) // 蓝球粉球 - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 223, ChangeCount: 1}}, true, 0) - GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 224, ChangeCount: 1}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: 223, ChangeCount: 1}}, true, 0) + GAME_MANAGER.AddUserItem(player.PlayerID, []*ChangeItem{{ItemId: 224, ChangeCount: 1}}, true, 0) } } } diff --git a/gs/game/world_manager.go b/gs/game/world_manager.go index 04bfc220..b84153ba 100644 --- a/gs/game/world_manager.go +++ b/gs/game/world_manager.go @@ -309,11 +309,12 @@ func (w *World) AddPlayer(player *model.Player, sceneId uint32) { w.peerList = append(w.peerList, player) w.playerMap[player.PlayerID] = player // 将玩家自身当前的队伍角色信息复制到世界的玩家本地队伍 - team := player.TeamConfig.GetActiveTeam() + dbTeam := player.GetDbTeam() + team := dbTeam.GetActiveTeam() if player.PlayerID == w.owner.PlayerID { w.SetPlayerLocalTeam(player, team.GetAvatarIdList()) } else { - activeAvatarId := player.TeamConfig.GetActiveAvatarId() + activeAvatarId := dbTeam.GetActiveAvatarId() w.SetPlayerLocalTeam(player, []uint32{activeAvatarId}) } playerNum := w.GetWorldPlayerNum() @@ -328,7 +329,8 @@ func (w *World) AddPlayer(player *model.Player, sceneId uint32) { for _, worldPlayer := range w.playerMap { list := w.GetPlayerWorldAvatarList(worldPlayer) maxIndex := len(list) - 1 - index := int(worldPlayer.TeamConfig.CurrAvatarIndex) + worldPlayerDbTeam := worldPlayer.GetDbTeam() + index := int(worldPlayerDbTeam.CurrAvatarIndex) if index > maxIndex { w.SetPlayerAvatarIndex(worldPlayer, 0) } else { diff --git a/gs/game/world_scene.go b/gs/game/world_scene.go index 44135568..d7f3bde6 100644 --- a/gs/game/world_scene.go +++ b/gs/game/world_scene.go @@ -88,7 +88,8 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro return } // 获取角色 - avatar, ok := player.AvatarMap[entity.avatarEntity.avatarId] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[entity.avatarEntity.avatarId] if !ok { logger.Error("avatar is nil, avatarId: %v", avatar) return @@ -139,7 +140,8 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.ENTITY_ID_TYPE_AVATAR) - avatar, ok := player.AvatarMap[avatarId] + dbAvatar := player.GetDbAvatar() + avatar, ok := dbAvatar.AvatarMap[avatarId] if !ok { logger.Error("avatar error, avatarId: %v", avatar) return 0 @@ -153,7 +155,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 moveState: uint16(proto.MotionState_MOTION_NONE), lastMoveSceneTimeMs: 0, lastMoveReliableSeq: 0, - fightProp: player.AvatarMap[avatarId].FightPropMap, // 使用角色结构的数据 + fightProp: dbAvatar.AvatarMap[avatarId].FightPropMap, // 使用角色结构的数据 entityType: uint32(proto.ProtEntityType_PROT_ENTITY_AVATAR), avatarEntity: &AvatarEntity{ uid: player.PlayerID, @@ -169,7 +171,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 EntityId: entity.id, FightPropMap: entity.fightProp, Uid: entity.avatarEntity.uid, - AvatarGuid: player.AvatarMap[avatarId].Guid, + AvatarGuid: dbAvatar.AvatarMap[avatarId].Guid, }, }) return entity.id diff --git a/gs/model/chat.go b/gs/model/chat_msg.go similarity index 100% rename from gs/model/chat.go rename to gs/model/chat_msg.go index 7f99fed4..2f49131c 100644 --- a/gs/model/chat.go +++ b/gs/model/chat_msg.go @@ -13,8 +13,8 @@ type ChatMsg struct { ID primitive.ObjectID `bson:"_id,omitempty"` Sequence uint32 `bson:"-"` Time uint32 `bson:"Time"` - ToUid uint32 `bson:"ToUid"` Uid uint32 `bson:"Uid"` + ToUid uint32 `bson:"ToUid"` IsRead bool `bson:"IsRead"` MsgType uint8 `bson:"MsgType"` Text string `bson:"Text"` diff --git a/gs/model/avatar.go b/gs/model/db_avatar.go similarity index 84% rename from gs/model/avatar.go rename to gs/model/db_avatar.go index 3e4435c4..c47db2cb 100644 --- a/gs/model/avatar.go +++ b/gs/model/db_avatar.go @@ -8,6 +8,20 @@ import ( "hk4e/pkg/logger" ) +type DbAvatar struct { + AvatarMap map[uint32]*Avatar // 角色列表 + MainCharAvatarId uint32 // 主角id +} + +func (p *Player) GetDbAvatar() *DbAvatar { + if p.DbAvatar == nil { + p.DbAvatar = &DbAvatar{ + AvatarMap: make(map[uint32]*Avatar), + } + } + return p.DbAvatar +} + type Avatar struct { AvatarId uint32 // 角色id LifeState uint16 // 存活状态 @@ -35,26 +49,26 @@ type Avatar struct { ExtraAbilityEmbryos map[string]bool `bson:"-" msgpack:"-"` } -func (p *Player) InitAllAvatar() { - for _, avatar := range p.AvatarMap { - p.InitAvatar(avatar) +func (a *DbAvatar) InitAllAvatar(player *Player) { + for _, avatar := range a.AvatarMap { + a.InitAvatar(player, avatar) } } -func (p *Player) InitAvatar(avatar *Avatar) { +func (a *DbAvatar) InitAvatar(player *Player, avatar *Avatar) { // 角色战斗属性 - p.InitAvatarFightProp(avatar) + a.InitAvatarFightProp(avatar) // guid - avatar.Guid = p.GetNextGameObjectGuid() - p.GameObjectGuidMap[avatar.Guid] = GameObject(avatar) + avatar.Guid = player.GetNextGameObjectGuid() + player.GameObjectGuidMap[avatar.Guid] = GameObject(avatar) avatar.EquipGuidMap = make(map[uint64]uint64) avatar.EquipReliquaryMap = make(map[uint8]*Reliquary) - p.AvatarMap[avatar.AvatarId] = avatar + a.AvatarMap[avatar.AvatarId] = avatar return } // InitAvatarFightProp 初始化角色面板 -func (p *Player) InitAvatarFightProp(avatar *Avatar) { +func (a *DbAvatar) InitAvatarFightProp(avatar *Avatar) { avatarDataConfig := gdconf.GetAvatarDataById(int32(avatar.AvatarId)) if avatarDataConfig == nil { logger.Error("avatarDataConfig error, avatarId: %v", avatar.AvatarId) @@ -77,10 +91,10 @@ func (p *Player) InitAvatarFightProp(avatar *Avatar) { avatar.FightPropMap[uint32(constant.FIGHT_PROP_CRITICAL_HURT)] = float32(avatarDataConfig.CriticalHurt) // 元素充能 avatar.FightPropMap[uint32(constant.FIGHT_PROP_CHARGE_EFFICIENCY)] = 1.0 - p.SetCurrEnergy(avatar, avatar.CurrEnergy, true) + a.SetCurrEnergy(avatar, avatar.CurrEnergy, true) } -func (p *Player) AddAvatar(avatarId uint32) { +func (a *DbAvatar) AddAvatar(player *Player, avatarId uint32) { avatarDataConfig := gdconf.GetAvatarDataById(int32(avatarId)) if avatarDataConfig == nil { logger.Error("avatar data config is nil, avatarId: %v", avatarId) @@ -140,11 +154,11 @@ func (p *Player) AddAvatar(avatarId uint32) { avatar.PromoteRewardMap[promoteLevel] = false } - p.InitAvatar(avatar) - p.AvatarMap[avatarId] = avatar + a.InitAvatar(player, avatar) + a.AvatarMap[avatarId] = avatar } -func (p *Player) SetCurrEnergy(avatar *Avatar, value float64, max bool) { +func (a *DbAvatar) SetCurrEnergy(avatar *Avatar, value float64, max bool) { var avatarSkillDataConfig *gdconf.AvatarSkillData = nil if avatar.AvatarId == 10000005 || avatar.AvatarId == 10000007 { avatarSkillDepotDataConfig := gdconf.GetAvatarSkillDepotDataById(int32(avatar.SkillDepotId)) @@ -175,9 +189,8 @@ func (p *Player) SetCurrEnergy(avatar *Avatar, value float64, max bool) { } } -func (p *Player) WearReliquary(avatarId uint32, reliquaryId uint64) { - avatar := p.AvatarMap[avatarId] - reliquary := p.ReliquaryMap[reliquaryId] +func (a *DbAvatar) WearReliquary(avatarId uint32, reliquary *Reliquary) { + avatar := a.AvatarMap[avatarId] reliquaryConfig := gdconf.GetItemDataById(int32(reliquary.ItemId)) if reliquaryConfig == nil { logger.Error("reliquary config error, itemId: %v", reliquary.ItemId) @@ -188,9 +201,8 @@ func (p *Player) WearReliquary(avatarId uint32, reliquaryId uint64) { avatar.EquipGuidMap[reliquary.Guid] = reliquary.Guid } -func (p *Player) TakeOffReliquary(avatarId uint32, reliquaryId uint64) { - avatar := p.AvatarMap[avatarId] - reliquary := p.ReliquaryMap[reliquaryId] +func (a *DbAvatar) TakeOffReliquary(avatarId uint32, reliquary *Reliquary) { + avatar := a.AvatarMap[avatarId] reliquaryConfig := gdconf.GetItemDataById(int32(reliquary.ItemId)) if reliquaryConfig == nil { logger.Error("reliquary config error, itemId: %v", reliquary.ItemId) @@ -201,17 +213,15 @@ func (p *Player) TakeOffReliquary(avatarId uint32, reliquaryId uint64) { delete(avatar.EquipGuidMap, reliquary.Guid) } -func (p *Player) WearWeapon(avatarId uint32, weaponId uint64) { - avatar := p.AvatarMap[avatarId] - weapon := p.WeaponMap[weaponId] +func (a *DbAvatar) WearWeapon(avatarId uint32, weapon *Weapon) { + avatar := a.AvatarMap[avatarId] avatar.EquipWeapon = weapon weapon.AvatarId = avatarId avatar.EquipGuidMap[weapon.Guid] = weapon.Guid } -func (p *Player) TakeOffWeapon(avatarId uint32, weaponId uint64) { - avatar := p.AvatarMap[avatarId] - weapon := p.WeaponMap[weaponId] +func (a *DbAvatar) TakeOffWeapon(avatarId uint32, weapon *Weapon) { + avatar := a.AvatarMap[avatarId] avatar.EquipWeapon = nil weapon.AvatarId = 0 delete(avatar.EquipGuidMap, weapon.Guid) diff --git a/gs/model/drop.go b/gs/model/db_gacha.go similarity index 85% rename from gs/model/drop.go rename to gs/model/db_gacha.go index acdbd9f2..3789bfc5 100644 --- a/gs/model/drop.go +++ b/gs/model/db_gacha.go @@ -8,12 +8,19 @@ type GachaPoolInfo struct { MustGetUpPurple bool // 是否4星大保底 } -type DropInfo struct { +type DbGacha struct { GachaPoolInfo map[uint32]*GachaPoolInfo } -func NewDropInfo() (r *DropInfo) { - r = new(DropInfo) +func (p *Player) GetDbGacha() *DbGacha { + if p.DbGacha == nil { + p.DbGacha = NewDbGacha() + } + return p.DbGacha +} + +func NewDbGacha() (r *DbGacha) { + r = new(DbGacha) r.GachaPoolInfo = make(map[uint32]*GachaPoolInfo) r.GachaPoolInfo[300] = &GachaPoolInfo{ // 温迪 diff --git a/gs/model/db_item.go b/gs/model/db_item.go new file mode 100644 index 00000000..4038156e --- /dev/null +++ b/gs/model/db_item.go @@ -0,0 +1,89 @@ +package model + +import "hk4e/common/constant" + +type DbItem struct { + ItemMap map[uint32]*Item // 道具仓库 +} + +func (p *Player) GetDbItem() *DbItem { + if p.DbItem == nil { + p.DbItem = &DbItem{ + ItemMap: make(map[uint32]*Item), + } + } + return p.DbItem +} + +type Item struct { + ItemId uint32 // 道具id + Count uint32 // 道具数量 + Guid uint64 `bson:"-" msgpack:"-"` +} + +func (i *DbItem) InitAllItem(player *Player) { + for itemId, item := range i.ItemMap { + item.Guid = player.GetNextGameObjectGuid() + player.GameObjectGuidMap[item.Guid] = GameObject(item) + i.ItemMap[itemId] = item + } +} + +func (i *DbItem) GetItemGuid(itemId uint32) uint64 { + itemInfo := i.ItemMap[itemId] + if itemInfo == nil { + return 0 + } + return itemInfo.Guid +} + +func (i *DbItem) GetItemCount(player *Player, itemId uint32) uint32 { + prop, ok := constant.VIRTUAL_ITEM_PROP[itemId] + if ok { + value := player.PropertiesMap[prop] + return value + } else { + itemInfo := i.ItemMap[itemId] + if itemInfo == nil { + return 0 + } + return itemInfo.Count + } +} + +func (i *DbItem) AddItem(player *Player, itemId uint32, count uint32) { + itemInfo := i.ItemMap[itemId] + if itemInfo == nil { + // 该物品为新物品时校验背包物品容量 + // 目前物品包括材料和家具 + if len(i.ItemMap) > constant.STORE_PACK_LIMIT_MATERIAL+constant.STORE_PACK_LIMIT_FURNITURE { + return + } + itemInfo = &Item{ + ItemId: itemId, + Count: 0, + Guid: player.GetNextGameObjectGuid(), + } + player.GameObjectGuidMap[itemInfo.Guid] = GameObject(itemInfo) + } + itemInfo.Count += count + i.ItemMap[itemId] = itemInfo +} + +func (i *DbItem) CostItem(player *Player, itemId uint32, count uint32) { + itemInfo := i.ItemMap[itemId] + if itemInfo == nil { + return + } + if itemInfo.Count < count { + itemInfo.Count = 0 + } else { + itemInfo.Count -= count + } + if itemInfo.Count == 0 { + delete(i.ItemMap, itemId) + delete(player.GameObjectGuidMap, itemInfo.Guid) + } else { + i.ItemMap[itemId] = itemInfo + } +} diff --git a/gs/model/reliquary.go b/gs/model/db_reliquary.go similarity index 53% rename from gs/model/reliquary.go rename to gs/model/db_reliquary.go index 24753f6b..9e4a01ca 100644 --- a/gs/model/reliquary.go +++ b/gs/model/db_reliquary.go @@ -6,6 +6,19 @@ import ( "hk4e/pkg/logger" ) +type DbReliquary struct { + ReliquaryMap map[uint64]*Reliquary // 圣遗物背包 +} + +func (p *Player) GetDbReliquary() *DbReliquary { + if p.DbReliquary == nil { + p.DbReliquary = &DbReliquary{ + ReliquaryMap: make(map[uint64]*Reliquary), + } + } + return p.DbReliquary +} + type Reliquary struct { ReliquaryId uint64 // 圣遗物的唯一id ItemId uint32 // 圣遗物的道具id @@ -19,44 +32,45 @@ type Reliquary struct { Guid uint64 `bson:"-" msgpack:"-"` } -func (p *Player) InitReliquary(reliquary *Reliquary) { +func (r *DbReliquary) InitAllReliquary(player *Player) { + for _, reliquary := range r.ReliquaryMap { + r.InitReliquary(player, reliquary) + } +} + +func (r *DbReliquary) InitReliquary(player *Player, reliquary *Reliquary) { // 获取圣遗物配置表 reliquaryConfig := gdconf.GetItemDataById(int32(reliquary.ItemId)) if reliquaryConfig == nil { logger.Error("reliquary config error, itemId: %v", reliquary.ItemId) return } - reliquary.Guid = p.GetNextGameObjectGuid() - p.GameObjectGuidMap[reliquary.Guid] = GameObject(reliquary) - p.ReliquaryMap[reliquary.ReliquaryId] = reliquary + reliquary.Guid = player.GetNextGameObjectGuid() + player.GameObjectGuidMap[reliquary.Guid] = GameObject(reliquary) + r.ReliquaryMap[reliquary.ReliquaryId] = reliquary if reliquary.AvatarId != 0 { - avatar := p.AvatarMap[reliquary.AvatarId] + dbAvatar := player.GetDbAvatar() + avatar := dbAvatar.AvatarMap[reliquary.AvatarId] avatar.EquipGuidMap[reliquary.Guid] = reliquary.Guid avatar.EquipReliquaryMap[uint8(reliquaryConfig.ReliquaryType)] = reliquary } } -func (p *Player) InitAllReliquary() { - for _, reliquary := range p.ReliquaryMap { - p.InitReliquary(reliquary) - } -} - -func (p *Player) GetReliquaryGuid(reliquaryId uint64) uint64 { - reliquaryInfo := p.ReliquaryMap[reliquaryId] +func (r *DbReliquary) GetReliquaryGuid(reliquaryId uint64) uint64 { + reliquaryInfo := r.ReliquaryMap[reliquaryId] if reliquaryInfo == nil { return 0 } return reliquaryInfo.Guid } -func (p *Player) GetReliquary(reliquaryId uint64) *Reliquary { - return p.ReliquaryMap[reliquaryId] +func (r *DbReliquary) GetReliquary(reliquaryId uint64) *Reliquary { + return r.ReliquaryMap[reliquaryId] } -func (p *Player) AddReliquary(itemId uint32, reliquaryId uint64, mainPropId uint32) { +func (r *DbReliquary) AddReliquary(player *Player, itemId uint32, reliquaryId uint64, mainPropId uint32) { // 校验背包圣遗物容量 - if len(p.ReliquaryMap) > constant.STORE_PACK_LIMIT_RELIQUARY { + if len(r.ReliquaryMap) > constant.STORE_PACK_LIMIT_RELIQUARY { return } itemDataConfig := gdconf.GetItemDataById(int32(itemId)) @@ -76,16 +90,16 @@ func (p *Player) AddReliquary(itemId uint32, reliquaryId uint64, mainPropId uint AvatarId: 0, Guid: 0, } - p.InitReliquary(reliquary) - p.ReliquaryMap[reliquaryId] = reliquary + r.InitReliquary(player, reliquary) + r.ReliquaryMap[reliquaryId] = reliquary } -func (p *Player) CostReliquary(reliquaryId uint64) uint64 { - reliquary := p.ReliquaryMap[reliquaryId] +func (r *DbReliquary) CostReliquary(player *Player, reliquaryId uint64) uint64 { + reliquary := r.ReliquaryMap[reliquaryId] if reliquary == nil { return 0 } - delete(p.ReliquaryMap, reliquaryId) - delete(p.GameObjectGuidMap, reliquary.Guid) + delete(r.ReliquaryMap, reliquaryId) + delete(player.GameObjectGuidMap, reliquary.Guid) return reliquary.Guid } diff --git a/gs/model/team.go b/gs/model/db_team.go similarity index 87% rename from gs/model/team.go rename to gs/model/db_team.go index 6ada0eb0..a93db526 100644 --- a/gs/model/team.go +++ b/gs/model/db_team.go @@ -32,7 +32,7 @@ func (t *Team) SetAvatarIdList(avatarIdList []uint32) { } } -type TeamInfo struct { +type DbTeam struct { TeamList []*Team CurrTeamIndex uint8 CurrAvatarIndex uint8 @@ -40,8 +40,15 @@ type TeamInfo struct { TeamResonancesConfig map[int32]bool `bson:"-" msgpack:"-"` } -func NewTeamInfo() (r *TeamInfo) { - r = &TeamInfo{ +func (p *Player) GetDbTeam() *DbTeam { + if p.DbTeam == nil { + p.DbTeam = NewDbTeam() + } + return p.DbTeam +} + +func NewDbTeam() (r *DbTeam) { + r = &DbTeam{ TeamList: []*Team{ {Name: "冒险", AvatarIdList: make([]uint32, 4)}, {Name: "委托", AvatarIdList: make([]uint32, 4)}, @@ -54,7 +61,7 @@ func NewTeamInfo() (r *TeamInfo) { return r } -func (t *TeamInfo) UpdateTeam() { +func (t *DbTeam) UpdateTeam() { activeTeam := t.GetActiveTeam() // TODO 队伍元素共鸣 t.TeamResonances = make(map[uint16]bool) @@ -88,11 +95,11 @@ func (t *TeamInfo) UpdateTeam() { } } -func (t *TeamInfo) GetActiveTeamId() uint8 { +func (t *DbTeam) GetActiveTeamId() uint8 { return t.CurrTeamIndex + 1 } -func (t *TeamInfo) GetTeamByIndex(teamIndex uint8) *Team { +func (t *DbTeam) GetTeamByIndex(teamIndex uint8) *Team { if t.TeamList == nil { return nil } @@ -103,11 +110,11 @@ func (t *TeamInfo) GetTeamByIndex(teamIndex uint8) *Team { return activeTeam } -func (t *TeamInfo) GetActiveTeam() *Team { +func (t *DbTeam) GetActiveTeam() *Team { return t.GetTeamByIndex(t.CurrTeamIndex) } -func (t *TeamInfo) GetActiveAvatarId() uint32 { +func (t *DbTeam) GetActiveAvatarId() uint32 { team := t.GetActiveTeam() if team == nil { return 0 diff --git a/gs/model/weapon.go b/gs/model/db_weapon.go similarity index 51% rename from gs/model/weapon.go rename to gs/model/db_weapon.go index 6705f68f..d97b5b85 100644 --- a/gs/model/weapon.go +++ b/gs/model/db_weapon.go @@ -6,6 +6,19 @@ import ( "hk4e/pkg/logger" ) +type DbWeapon struct { + WeaponMap map[uint64]*Weapon // 武器背包 +} + +func (p *Player) GetDbWeapon() *DbWeapon { + if p.DbWeapon == nil { + p.DbWeapon = &DbWeapon{ + WeaponMap: make(map[uint64]*Weapon), + } + } + return p.DbWeapon +} + type Weapon struct { WeaponId uint64 // 武器的唯一id ItemId uint32 // 武器的道具id @@ -19,38 +32,39 @@ type Weapon struct { Guid uint64 `bson:"-" msgpack:"-"` } -func (p *Player) InitWeapon(weapon *Weapon) { - weapon.Guid = p.GetNextGameObjectGuid() - p.GameObjectGuidMap[weapon.Guid] = GameObject(weapon) - p.WeaponMap[weapon.WeaponId] = weapon +func (w *DbWeapon) InitAllWeapon(player *Player) { + for _, weapon := range w.WeaponMap { + w.InitWeapon(player, weapon) + } +} + +func (w *DbWeapon) InitWeapon(player *Player, weapon *Weapon) { + weapon.Guid = player.GetNextGameObjectGuid() + player.GameObjectGuidMap[weapon.Guid] = GameObject(weapon) + w.WeaponMap[weapon.WeaponId] = weapon if weapon.AvatarId != 0 { - avatar := p.AvatarMap[weapon.AvatarId] + dbAvatar := player.GetDbAvatar() + avatar := dbAvatar.AvatarMap[weapon.AvatarId] avatar.EquipGuidMap[weapon.Guid] = weapon.Guid avatar.EquipWeapon = weapon } } -func (p *Player) InitAllWeapon() { - for _, weapon := range p.WeaponMap { - p.InitWeapon(weapon) - } -} - -func (p *Player) GetWeaponGuid(weaponId uint64) uint64 { - weaponInfo := p.WeaponMap[weaponId] +func (w *DbWeapon) GetWeaponGuid(weaponId uint64) uint64 { + weaponInfo := w.WeaponMap[weaponId] if weaponInfo == nil { return 0 } return weaponInfo.Guid } -func (p *Player) GetWeapon(weaponId uint64) *Weapon { - return p.WeaponMap[weaponId] +func (w *DbWeapon) GetWeapon(weaponId uint64) *Weapon { + return w.WeaponMap[weaponId] } -func (p *Player) AddWeapon(itemId uint32, weaponId uint64) { +func (w *DbWeapon) AddWeapon(player *Player, itemId uint32, weaponId uint64) { // 校验背包武器容量 - if len(p.WeaponMap) > constant.STORE_PACK_LIMIT_WEAPON { + if len(w.WeaponMap) > constant.STORE_PACK_LIMIT_WEAPON { return } itemDataConfig := gdconf.GetItemDataById(int32(itemId)) @@ -72,16 +86,16 @@ func (p *Player) AddWeapon(itemId uint32, weaponId uint64) { for _, skillAffix := range itemDataConfig.SkillAffix { weapon.AffixIdList = append(weapon.AffixIdList, uint32(skillAffix)) } - p.InitWeapon(weapon) - p.WeaponMap[weaponId] = weapon + w.InitWeapon(player, weapon) + w.WeaponMap[weaponId] = weapon } -func (p *Player) CostWeapon(weaponId uint64) uint64 { - weapon := p.WeaponMap[weaponId] +func (w *DbWeapon) CostWeapon(player *Player, weaponId uint64) uint64 { + weapon := w.WeaponMap[weaponId] if weapon == nil { return 0 } - delete(p.WeaponMap, weaponId) - delete(p.GameObjectGuidMap, weapon.Guid) + delete(w.WeaponMap, weaponId) + delete(player.GameObjectGuidMap, weapon.Guid) return weapon.Guid } diff --git a/gs/model/item.go b/gs/model/item.go deleted file mode 100644 index c20e14ab..00000000 --- a/gs/model/item.go +++ /dev/null @@ -1,76 +0,0 @@ -package model - -import "hk4e/common/constant" - -type Item struct { - ItemId uint32 // 道具id - Count uint32 // 道具数量 - Guid uint64 `bson:"-" msgpack:"-"` -} - -func (p *Player) InitAllItem() { - for itemId, item := range p.ItemMap { - item.Guid = p.GetNextGameObjectGuid() - p.GameObjectGuidMap[item.Guid] = GameObject(item) - p.ItemMap[itemId] = item - } -} - -func (p *Player) GetItemGuid(itemId uint32) uint64 { - itemInfo := p.ItemMap[itemId] - if itemInfo == nil { - return 0 - } - return itemInfo.Guid -} - -func (p *Player) GetItemCount(itemId uint32) uint32 { - prop, ok := constant.VIRTUAL_ITEM_PROP[itemId] - if ok { - value := p.PropertiesMap[prop] - return value - } else { - itemInfo := p.ItemMap[itemId] - if itemInfo == nil { - return 0 - } - return itemInfo.Count - } -} - -func (p *Player) AddItem(itemId uint32, count uint32) { - itemInfo := p.ItemMap[itemId] - if itemInfo == nil { - // 该物品为新物品时校验背包物品容量 - // 目前物品包括材料和家具 - if len(p.ItemMap) > constant.STORE_PACK_LIMIT_MATERIAL+constant.STORE_PACK_LIMIT_FURNITURE { - return - } - itemInfo = &Item{ - ItemId: itemId, - Count: 0, - Guid: p.GetNextGameObjectGuid(), - } - p.GameObjectGuidMap[itemInfo.Guid] = GameObject(itemInfo) - } - itemInfo.Count += count - p.ItemMap[itemId] = itemInfo -} - -func (p *Player) CostItem(itemId uint32, count uint32) { - itemInfo := p.ItemMap[itemId] - if itemInfo == nil { - return - } - if itemInfo.Count < count { - itemInfo.Count = 0 - } else { - itemInfo.Count -= count - } - if itemInfo.Count == 0 { - delete(p.ItemMap, itemId) - delete(p.GameObjectGuidMap, itemInfo.Guid) - } else { - p.ItemMap[itemId] = itemInfo - } -} diff --git a/gs/model/player.go b/gs/model/player.go index 94350402..e9d40987 100644 --- a/gs/model/player.go +++ b/gs/model/player.go @@ -25,45 +25,43 @@ type GameObject interface { type Player struct { // 离线数据 请尽量不要定义接口等复杂数据结构 - ID primitive.ObjectID `bson:"_id,omitempty"` - PlayerID uint32 `bson:"PlayerID"` // 玩家uid - NickName string // 玩家昵称 - Signature string // 玩家签名 - HeadImage uint32 // 玩家头像 - Birthday []uint8 // 生日 - NameCard uint32 // 当前名片 - NameCardList []uint32 // 已解锁名片列表 - FriendList map[uint32]bool // 好友uid列表 - FriendApplyList map[uint32]bool // 好友申请uid列表 - OfflineTime uint32 // 离线时间点 - OnlineTime uint32 // 上线时间点 - TotalOnlineTime uint32 // 玩家累计在线时长 - PropertiesMap map[uint16]uint32 // 玩家自身相关的一些属性 - FlyCloakList []uint32 // 风之翼列表 - CostumeList []uint32 // 角色衣装列表 - SceneId uint32 // 场景 - SafePos *Vector // 玩家在陆地时的坐标 - Pos *Vector // 玩家坐标 - Rot *Vector // 玩家朝向 - ItemMap map[uint32]*Item // 玩家统一大背包仓库 - WeaponMap map[uint64]*Weapon // 玩家武器背包 - ReliquaryMap map[uint64]*Reliquary // 玩家圣遗物背包 - TeamConfig *TeamInfo // 队伍配置 - AvatarMap map[uint32]*Avatar // 角色信息 - DropInfo *DropInfo // 掉落信息 - MainCharAvatarId uint32 // 主角id - GCGInfo *GCGInfo // 七圣召唤信息 - IsGM uint8 // 管理员权限等级 - DbQuest *DbQuest // 任务 + ID primitive.ObjectID `bson:"_id,omitempty"` + PlayerID uint32 `bson:"PlayerID"` // 玩家uid + NickName string // 昵称 + Signature string // 签名 + HeadImage uint32 // 头像 + Birthday []uint8 // 生日 + NameCard uint32 // 当前名片 + NameCardList []uint32 // 已解锁名片列表 + FriendList map[uint32]bool // 好友uid列表 + FriendApplyList map[uint32]bool // 好友申请uid列表 + OfflineTime uint32 // 离线时间点 + OnlineTime uint32 // 上线时间点 + TotalOnlineTime uint32 // 累计在线时长 + PropertiesMap map[uint16]uint32 // 玩家自身相关的一些属性 + FlyCloakList []uint32 // 风之翼列表 + CostumeList []uint32 // 角色衣装列表 + SceneId uint32 // 场景 + IsGM uint8 // 管理员权限等级 + SafePos *Vector // 在陆地时的坐标 + Pos *Vector // 坐标 + Rot *Vector // 朝向 + DbItem *DbItem // 道具 + DbWeapon *DbWeapon // 武器 + DbReliquary *DbReliquary // 圣遗物 + DbTeam *DbTeam // 队伍 + DbAvatar *DbAvatar // 角色 + DbGacha *DbGacha // 卡池 + DbQuest *DbQuest // 任务 // 在线数据 请随意 记得加忽略字段的tag LastSaveTime uint32 `bson:"-" msgpack:"-"` // 上一次保存时间 - EnterSceneToken uint32 `bson:"-" msgpack:"-"` // 玩家的世界进入令牌 + EnterSceneToken uint32 `bson:"-" msgpack:"-"` // 世界进入令牌 DbState int `bson:"-" msgpack:"-"` // 数据库存档状态 WorldId uint32 `bson:"-" msgpack:"-"` // 所在的世界id GameObjectGuidCounter uint64 `bson:"-" msgpack:"-"` // 游戏对象guid计数器 LastKeepaliveTime uint32 `bson:"-" msgpack:"-"` // 上一次保持活跃时间 - ClientTime uint32 `bson:"-" msgpack:"-"` // 玩家客户端的本地时钟 - ClientRTT uint32 `bson:"-" msgpack:"-"` // 玩家客户端往返时延 + ClientTime uint32 `bson:"-" msgpack:"-"` // 客户端的本地时钟 + ClientRTT uint32 `bson:"-" msgpack:"-"` // 客户端往返时延 GameObjectGuidMap map[uint64]GameObject `bson:"-" msgpack:"-"` // 游戏对象guid映射表 Online bool `bson:"-" msgpack:"-"` // 在线状态 Pause bool `bson:"-" msgpack:"-"` // 暂停状态 @@ -78,6 +76,7 @@ type Player struct { GateAppId string `bson:"-" msgpack:"-"` // 网关服务器的appid FightAppId string `bson:"-" msgpack:"-"` // 战斗服务器的appid GCGCurGameGuid uint32 `bson:"-" msgpack:"-"` // GCG玩家所在的游戏guid + GCGInfo *GCGInfo `bson:"-" msgpack:"-"` // 七圣召唤信息 // 特殊数据 ChatMsgMap map[uint32][]*ChatMsg `bson:"-" msgpack:"-"` // 聊天信息 数据量偏大 只从db读写 不保存到redis } @@ -87,17 +86,15 @@ func (p *Player) GetNextGameObjectGuid() uint64 { return uint64(p.PlayerID)<<32 + p.GameObjectGuidCounter } -func (p *Player) InitAll() { +func (p *Player) InitOnlineData() { + // 在线数据初始化 p.GameObjectGuidMap = make(map[uint64]GameObject) p.CoopApplyMap = make(map[uint32]int64) - p.StaminaInfo = new(StaminaInfo) - p.VehicleInfo = new(VehicleInfo) - p.VehicleInfo.LastCreateEntityIdMap = make(map[uint32]uint32) + p.StaminaInfo = NewStaminaInfo() + p.VehicleInfo = NewVehicleInfo() + p.CombatInvokeHandler = NewInvokeHandler[proto.CombatInvokeEntry]() + p.AbilityInvokeHandler = NewInvokeHandler[proto.AbilityInvokeEntry]() p.GCGInfo = NewGCGInfo() // 临时测试用数据 - p.InitAllAvatar() - p.InitAllWeapon() - p.InitAllItem() - p.InitAllReliquary() } // 多人世界网络同步包转发器 diff --git a/gs/model/stamina.go b/gs/model/stamina.go index e2125c79..3c7b2bb1 100644 --- a/gs/model/stamina.go +++ b/gs/model/stamina.go @@ -18,6 +18,10 @@ type StaminaInfo struct { DrownBackDelay uint8 // 溺水返回安全点延时 } +func NewStaminaInfo() *StaminaInfo { + return new(StaminaInfo) +} + // SetStaminaCost 设置动作需要消耗的耐力 func (s *StaminaInfo) SetStaminaCost(state proto.MotionState) { // 根据状态决定要修改的耐力 diff --git a/gs/model/vehicle.go b/gs/model/vehicle.go index 33256fd2..8f0baa36 100644 --- a/gs/model/vehicle.go +++ b/gs/model/vehicle.go @@ -6,3 +6,11 @@ type VehicleInfo struct { // TODO 玩家可以在其他世界创建载具 需要额外处理 LastCreateEntityIdMap map[uint32]uint32 // 最后一次创建载具的实体Id map[vehicleId]EntityId } + +func NewVehicleInfo() *VehicleInfo { + return &VehicleInfo{ + InVehicleEntityId: 0, + LastCreateTime: 0, + LastCreateEntityIdMap: make(map[uint32]uint32), + } +}