package player import ( "blazing/common/data/xmlres" "blazing/common/socket/errorcode" "blazing/common/utils" "blazing/cool" "blazing/logic/service/common" "blazing/logic/service/fight/info" "blazing/logic/service/space" "sync/atomic" "blazing/modules/base/service" blservice "blazing/modules/blazing/service" "context" "github.com/antlabs/timer" "github.com/gogf/gf/v2/frame/g" "github.com/panjf2000/gnet/v2" ) func ConutPlayer() int { count := 0 Mainplayer.Range(func(uint32, *Player) bool { count++ return true // 继续遍历 }) return count } var Mainplayer = &utils.SyncMap[uint32, *Player]{} //玩家数据 type OgreInfo struct { Data [9]OgrePetInfo } type OgrePetInfo struct { Id uint32 Shiny uint32 Lv uint32 `struc:"skip"` //等级 Item uint32 `struc:"skip"` //奖励,如果有的话 Ext uint32 `struc:"skip"` //是否变尼尔尼奥 } type Player struct { MainConn gnet.Conn baseplayer IsLogin bool //是否登录 Done StopChan timer.TimeNoder context.Context Fightinfo info.Fightinfo //当前邀请的玩家ID Logintime uint32 //当前登录时间 OgreInfo OgreInfo Service *blservice.UserService User *service.BaseSysUserService // PVP被邀请信息 HavePVPinfo []common.PlayerI monsters [3]int //0 无,1可以刷怪,2是切换过地图 Canmon uint32 //可以刷怪 // Changemap bool //是否切换过地图 } // PlayerOption 定义配置 Player 的函数类型 type PlayerOption func(*Player) func WithConn(c gnet.Conn) PlayerOption { return func(p *Player) { p.MainConn = c } } func (p *Player) UseCoins(t uint32) bool { if p.Info.Coins < t { return false } return true } func (p *Player) UseGold(t uint32) bool { if p.User.GetGold(uint(p.Info.UserID)) < t { return false } //p.Info.GoldBean = p.Info.GoldBean - t return true } func (p *Player) GetAction() { } func (f *Player) InvitePlayer(ff common.PlayerI) { f.HavePVPinfo = append(f.HavePVPinfo, ff) tt := common.NewTomeeHeader(2501, f.GetInfo().UserID) f.SendPack(tt.Pack(&info.NoteInviteToFightOutboundInfo{ UserID: ff.GetInfo().UserID, Nick: ff.GetInfo().Nick, Mode: ff.Getfightinfo().Mode, })) } func (p *Player) Getfightinfo() info.Fightinfo { return p.Fightinfo } func (p *Player) QuitFight() { p.FightC = nil atomic.StoreUint32(&p.Fightinfo.Mode, 0) } func (p *Player) GetSpace() *space.Space { return space.GetSpace(p.Info.MapID) } // 0无战斗,1PVP,2,BOOS,3PVE func (p *Player) CanFight() bool { if len(p.Info.PetList) == 0 { atomic.StoreUint32(&p.Fightinfo.Mode, 0) return false } if p.FightC != nil { atomic.StoreUint32(&p.Fightinfo.Mode, 0) return false } // if p.GetSpace().ARENA.ChallengerID == p.Info.UserID || p.GetSpace().ARENA.Id == p.Info.UserID { // return false // } for _, v := range p.Info.PetList { if v.Hp > 0 { // 只要找到一个血量大于0的宠物,就可以战斗 return true } } // 遍历完所有宠物,都没有血量大于0的,才不能战斗 atomic.StoreUint32(&p.Fightinfo.Mode, 0) return false // } // return false } func (p *Player) SendPack(b []byte) error { if p.MainConn == nil { return nil } _, ok := p.MainConn.Context().(*ClientData) if ok { return p.MainConn.Context().(*ClientData).SendPack(b) } return nil } // 添加物品 返回成功添加的物品 func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) { switch ItemId { case 1: //塞尔豆 p.Info.Coins = p.Info.Coins + ItemCnt return true case 3: //累计经验 p.Info.ExpPool = p.Info.ExpPool + ItemCnt return true case 5: //金豆ItemAdd p.User.SetGold(p.Info.UserID, uint32(p.User.GetGold(uint(p.Info.UserID))+ItemCnt*100)) return true default: itemx, ok := xmlres.ItemsMAP[int(ItemId)] if !ok { cool.Loger.Error(context.TODO(), "物品不存在", ItemId) t1 := common.NewTomeeHeader(2601, p.Info.UserID) t1.Result = uint32(errorcode.ErrorCodes.ErrSystemError200007) p.SendPack(t1.Pack(nil)) //准备包由各自发,因为协议不一样 return false } if itemx.Max == 0 { itemx.Max = 1 } if p.Service.Item.CheakItem(ItemId)+ItemCnt > uint32(itemx.Max) { println(p.Info.UserID, "物品超过拥有最大限制", ItemId) t1 := common.NewTomeeHeader(2601, p.Info.UserID) t1.Result = uint32(errorcode.ErrorCodes.ErrTooManyOfItem) p.SendPack(t1.Pack(nil)) //准备包由各自发,因为协议不一样 return false } p.Service.Item.AddItem(ItemId, ItemCnt) return true } return false } func (player1 *Player) Kick() { if player1.IsLogin { //取成功,否则创建 //player1.Save() //先保存数据再返回 head := common.NewTomeeHeader(1001, player1.Info.UserID) head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere) //实际上这里有个问题,会造成重复保存问题 player1.SendPack(head.Pack(nil)) CloseChan := make(chan struct{}) player1.MainConn.CloseWithCallback(func(c gnet.Conn, err error) error { close(CloseChan) return nil }) <-CloseChan } } func (p *Player) Cheak(b error) { if b != nil { g.Log().Error(context.Background(), "出现错误", p.Info.UserID, b.Error()) } }