Files
hk4e/gs/game/user_login.go
2022-12-12 10:30:21 +08:00

380 lines
13 KiB
Go

package game
import (
pb "google.golang.org/protobuf/proto"
"time"
gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/model"
"hk4e/pkg/logger"
"hk4e/pkg/reflection"
"hk4e/protocol/cmd"
"hk4e/protocol/proto"
)
func (g *GameManager) OnLogin(userId uint32, clientSeq uint32) {
logger.LOG.Info("user login, uid: %v", userId)
player, asyncWait := USER_MANAGER.OnlineUser(userId, clientSeq)
if !asyncWait {
g.OnLoginOk(userId, player, clientSeq)
}
}
func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq uint32) {
if player == nil {
g.SendMsg(cmd.DoSetPlayerBornDataNotify, userId, clientSeq, new(proto.DoSetPlayerBornDataNotify))
return
}
player.OnlineTime = uint32(time.Now().UnixMilli())
player.Online = true
// 初始化
player.InitAll()
//player.TeamConfig.UpdateTeam()
// 创建世界
world := WORLD_MANAGER.CreateWorld(player)
world.AddPlayer(player, player.SceneId)
player.WorldId = world.id
player.CombatInvokeHandler = model.NewInvokeHandler[proto.CombatInvokeEntry]()
player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]()
//// TODO 薄荷标记
//if world.IsBigWorld() {
// bigWorld := world.GetSceneById(3)
// for pos := range g.worldManager.worldStatic.terrain {
// bigWorld.CreateEntityGadget(&model.Vector{
// X: float64(pos.X),
// Y: float64(pos.Y),
// Z: float64(pos.Z),
// }, 3003009)
// }
//}
g.LoginNotify(userId, player, clientSeq)
player.SceneLoadState = model.SceneNone
g.SendMsg(cmd.PlayerEnterSceneNotify, userId, clientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_SELF))
}
func (g *GameManager) OnReg(userId uint32, clientSeq uint32, payloadMsg pb.Message) {
logger.LOG.Debug("user reg, uid: %v", userId)
req := payloadMsg.(*proto.SetPlayerBornDataReq)
logger.LOG.Debug("avatar id: %v, nickname: %v", req.AvatarId, req.NickName)
exist, asyncWait := USER_MANAGER.CheckUserExistOnReg(userId, req, clientSeq)
if !asyncWait {
g.OnRegOk(exist, req, userId, clientSeq)
}
}
func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userId uint32, clientSeq uint32) {
if exist {
logger.LOG.Error("recv reg req, but user is already exist, userId: %v", userId)
return
}
nickName := req.NickName
mainCharAvatarId := req.GetAvatarId()
if mainCharAvatarId != 10000005 && mainCharAvatarId != 10000007 {
logger.LOG.Error("invalid main char avatar id: %v", mainCharAvatarId)
return
}
player := g.CreatePlayer(userId, nickName, mainCharAvatarId)
if player == nil {
logger.LOG.Error("player is nil, uid: %v", userId)
return
}
USER_MANAGER.AddUser(player)
g.SendMsg(cmd.SetPlayerBornDataRsp, userId, clientSeq, new(proto.SetPlayerBornDataRsp))
g.OnLogin(userId, clientSeq)
}
func (g *GameManager) OnUserOffline(userId uint32) {
logger.LOG.Info("user offline, uid: %v", userId)
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
logger.LOG.Error("player is nil, userId: %v", userId)
return
}
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world != nil {
g.UserWorldRemovePlayer(world, player)
}
player.OfflineTime = uint32(time.Now().Unix())
player.Online = false
player.TotalOnlineTime += uint32(time.Now().UnixMilli()) - player.OnlineTime
USER_MANAGER.DeleteUser(player)
}
func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq uint32) {
g.SendMsg(cmd.PlayerDataNotify, userId, clientSeq, g.PacketPlayerDataNotify(player))
g.SendMsg(cmd.StoreWeightLimitNotify, userId, clientSeq, g.PacketStoreWeightLimitNotify())
g.SendMsg(cmd.PlayerStoreNotify, userId, clientSeq, g.PacketPlayerStoreNotify(player))
g.SendMsg(cmd.AvatarDataNotify, userId, clientSeq, g.PacketAvatarDataNotify(player))
g.SendMsg(cmd.OpenStateUpdateNotify, userId, clientSeq, g.PacketOpenStateUpdateNotify())
}
func (g *GameManager) PacketPlayerDataNotify(player *model.Player) *proto.PlayerDataNotify {
playerDataNotify := &proto.PlayerDataNotify{
NickName: player.NickName,
ServerTime: uint64(time.Now().UnixMilli()),
IsFirstLoginToday: true,
RegionId: player.RegionId,
PropMap: make(map[uint32]*proto.PropValue),
}
for k, v := range player.PropertiesMap {
propValue := &proto.PropValue{
Type: uint32(k),
Value: &proto.PropValue_Ival{Ival: int64(v)},
Val: int64(v),
}
playerDataNotify.PropMap[uint32(k)] = propValue
}
return playerDataNotify
}
func (g *GameManager) PacketStoreWeightLimitNotify() *proto.StoreWeightLimitNotify {
storeWeightLimitNotify := &proto.StoreWeightLimitNotify{
StoreType: proto.StoreType_STORE_TYPE_PACK,
// 背包容量限制
WeightLimit: 30000,
WeaponCountLimit: 2000,
ReliquaryCountLimit: 1500,
MaterialCountLimit: 2000,
FurnitureCountLimit: 2000,
}
return storeWeightLimitNotify
}
func (g *GameManager) PacketPlayerStoreNotify(player *model.Player) *proto.PlayerStoreNotify {
playerStoreNotify := &proto.PlayerStoreNotify{
StoreType: proto.StoreType_STORE_TYPE_PACK,
WeightLimit: 30000,
}
itemDataMapConfig := gdc.CONF.ItemDataMap
for _, weapon := range player.WeaponMap {
pbItem := &proto.Item{
ItemId: weapon.ItemId,
Guid: weapon.Guid,
Detail: nil,
}
itemData, ok := itemDataMapConfig[int32(weapon.ItemId)]
if !ok {
logger.LOG.Error("config is nil, itemId: %v", weapon.ItemId)
return nil
}
if itemData.ItemEnumType != constant.ItemTypeConst.ITEM_WEAPON {
continue
}
affixMap := make(map[uint32]uint32)
for _, affixId := range weapon.AffixIdList {
affixMap[affixId] = uint32(weapon.Refinement)
}
pbItem.Detail = &proto.Item_Equip{
Equip: &proto.Equip{
Detail: &proto.Equip_Weapon{
Weapon: &proto.Weapon{
Level: uint32(weapon.Level),
Exp: weapon.Exp,
PromoteLevel: uint32(weapon.Promote),
AffixMap: affixMap,
},
},
IsLocked: weapon.Lock,
},
}
playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem)
}
for _, reliquary := range player.ReliquaryMap {
pbItem := &proto.Item{
ItemId: reliquary.ItemId,
Guid: reliquary.Guid,
Detail: nil,
}
if itemDataMapConfig[int32(reliquary.ItemId)].ItemEnumType != constant.ItemTypeConst.ITEM_RELIQUARY {
continue
}
pbItem.Detail = &proto.Item_Equip{
Equip: &proto.Equip{
Detail: &proto.Equip_Reliquary{
Reliquary: &proto.Reliquary{
Level: uint32(reliquary.Level),
Exp: reliquary.Exp,
PromoteLevel: uint32(reliquary.Promote),
MainPropId: reliquary.MainPropId,
// TODO 圣遗物副词条
AppendPropIdList: nil,
},
},
IsLocked: reliquary.Lock,
},
}
playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem)
}
for _, item := range player.ItemMap {
pbItem := &proto.Item{
ItemId: item.ItemId,
Guid: item.Guid,
Detail: nil,
}
itemDataConfig := itemDataMapConfig[int32(item.ItemId)]
if itemDataConfig != nil && itemDataConfig.ItemEnumType == constant.ItemTypeConst.ITEM_FURNITURE {
pbItem.Detail = &proto.Item_Furniture{
Furniture: &proto.Furniture{
Count: item.Count,
},
}
} else {
pbItem.Detail = &proto.Item_Material{
Material: &proto.Material{
Count: item.Count,
DeleteInfo: nil,
},
}
}
playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem)
}
return playerStoreNotify
}
func (g *GameManager) PacketAvatarDataNotify(player *model.Player) *proto.AvatarDataNotify {
chooseAvatarId := player.MainCharAvatarId
avatarDataNotify := &proto.AvatarDataNotify{
CurAvatarTeamId: uint32(player.TeamConfig.GetActiveTeamId()),
ChooseAvatarGuid: player.AvatarMap[chooseAvatarId].Guid,
OwnedFlycloakList: player.FlyCloakList,
// 角色衣装
OwnedCostumeList: player.CostumeList,
AvatarList: make([]*proto.AvatarInfo, 0),
AvatarTeamMap: make(map[uint32]*proto.AvatarTeam),
}
for _, avatar := range player.AvatarMap {
pbAvatar := g.PacketAvatarInfo(avatar)
avatarDataNotify.AvatarList = append(avatarDataNotify.AvatarList, pbAvatar)
}
for teamIndex, team := range player.TeamConfig.TeamList {
var teamAvatarGuidList []uint64 = nil
for _, avatarId := range team.GetAvatarIdList() {
teamAvatarGuidList = append(teamAvatarGuidList, player.AvatarMap[avatarId].Guid)
}
avatarDataNotify.AvatarTeamMap[uint32(teamIndex)+1] = &proto.AvatarTeam{
AvatarGuidList: teamAvatarGuidList,
TeamName: team.Name,
}
}
return avatarDataNotify
}
func (g *GameManager) PacketOpenStateUpdateNotify() *proto.OpenStateUpdateNotify {
openStateUpdateNotify := &proto.OpenStateUpdateNotify{
OpenStateMap: make(map[uint32]uint32),
}
openStateConstMap := reflection.ConvStructToMap(constant.OpenStateConst)
for _, v := range openStateConstMap {
openStateUpdateNotify.OpenStateMap[uint32(v.(uint16))] = 1
}
return openStateUpdateNotify
}
func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvatarId uint32) *model.Player {
player := new(model.Player)
player.PlayerID = userId
player.NickName = nickName
player.Signature = ""
player.MainCharAvatarId = mainCharAvatarId
player.HeadImage = mainCharAvatarId
player.Birthday = []uint8{0, 0}
player.NameCard = 210001
player.NameCardList = make([]uint32, 0)
player.NameCardList = append(player.NameCardList, 210001, 210042)
player.FriendList = make(map[uint32]bool)
player.FriendApplyList = make(map[uint32]bool)
player.RegionId = 1
player.SceneId = 3
player.PropertiesMap = make(map[uint16]uint32)
// 初始化所有属性
propList := reflection.ConvStructToMap(constant.PlayerPropertyConst)
for fieldName, fieldValue := range propList {
if fieldName == "PROP_EXP" ||
fieldName == "PROP_BREAK_LEVEL" ||
fieldName == "PROP_SATIATION_VAL" ||
fieldName == "PROP_SATIATION_PENALTY_TIME" ||
fieldName == "PROP_LEVEL" {
continue
}
value := fieldValue.(uint16)
player.PropertiesMap[value] = 0
}
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL] = 1
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL] = 0
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_SPRING_AUTO_USE] = 1
player.PropertiesMap[constant.PlayerPropertyConst.PROP_SPRING_AUTO_USE_PERCENT] = 100
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_FLYABLE] = 1
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_TRANSFERABLE] = 1
player.PropertiesMap[constant.PlayerPropertyConst.PROP_MAX_STAMINA] = 24000
player.PropertiesMap[constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA] = 24000
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_RESIN] = 160
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE] = 2
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_MP_MODE_AVAILABLE] = 1
player.FlyCloakList = make([]uint32, 0)
player.FlyCloakList = append(player.FlyCloakList, 140001)
player.FlyCloakList = append(player.FlyCloakList, 140002)
player.FlyCloakList = append(player.FlyCloakList, 140003)
player.FlyCloakList = append(player.FlyCloakList, 140004)
player.FlyCloakList = append(player.FlyCloakList, 140005)
player.FlyCloakList = append(player.FlyCloakList, 140006)
player.FlyCloakList = append(player.FlyCloakList, 140007)
player.FlyCloakList = append(player.FlyCloakList, 140008)
player.FlyCloakList = append(player.FlyCloakList, 140009)
player.FlyCloakList = append(player.FlyCloakList, 140010)
player.CostumeList = make([]uint32, 0)
player.CostumeList = append(player.CostumeList, 200301)
player.CostumeList = append(player.CostumeList, 201401)
player.CostumeList = append(player.CostumeList, 202701)
player.CostumeList = append(player.CostumeList, 204201)
player.CostumeList = append(player.CostumeList, 200302)
player.CostumeList = append(player.CostumeList, 202101)
player.CostumeList = append(player.CostumeList, 204101)
player.CostumeList = append(player.CostumeList, 204501)
player.CostumeList = append(player.CostumeList, 201601)
player.CostumeList = append(player.CostumeList, 203101)
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)
player.GameObjectGuidMap = make(map[uint64]model.GameObject)
player.DropInfo = model.NewDropInfo()
player.ChatMsgMap = make(map[uint32][]*model.ChatMsg)
// 添加选定的主角
player.AddAvatar(mainCharAvatarId)
// 添加初始武器
avatarDataConfig, ok := gdc.CONF.AvatarDataMap[int32(mainCharAvatarId)]
if !ok {
logger.LOG.Error("config is nil, mainCharAvatarId: %v", mainCharAvatarId)
return nil
}
weaponId := uint64(g.snowflake.GenId())
player.AddWeapon(uint32(avatarDataConfig.InitialWeapon), weaponId)
// 角色装上初始武器
player.WearWeapon(mainCharAvatarId, weaponId)
player.TeamConfig = model.NewTeamInfo()
player.TeamConfig.GetActiveTeam().SetAvatarIdList([]uint32{mainCharAvatarId})
return player
}