package game import ( "context" "database/sql" "encoding/json" "errors" "math" "server/conf" activityCfg "server/conf/activity" cardCfg "server/conf/card" chargeCfg "server/conf/charge" guesscolorCfg "server/conf/guess_color" itemCfg "server/conf/item" limitedTimeEventCfg "server/conf/limited_time_event" mergeDataCfg "server/conf/merge_data" miningCfg "server/conf/mining" playroomCfg "server/conf/playroom" "server/db" "server/ga" "server/game/mod/activity" "server/game/mod/friend" "server/game/mod/item" limitedTimeEvent "server/game/mod/limited_time_event" MsgMod "server/game/mod/msg" "server/game/mod/playroom" "server/game/mod/quest" GoUtil "server/game_util" "server/msg" telog "server/thinkdata" "strconv" "sync" "time" "server/pkg/github.com/name5566/leaf/gate" "server/pkg/github.com/name5566/leaf/log" "server/pkg/github.com/name5566/leaf/timer" "github.com/robfig/cron/v3" "google.golang.org/protobuf/proto" ) // import "reflect" //"fmt" type Player struct { PlayerBaseMod *PlayerBaseData PlayMod PlayerMod M_DwUin int64 agent gate.Agent lock sync.Mutex stopSignal chan bool Msg []PlayerMsg Trigger []*quest.Trigger MDispatr *timer.Dispatcher McronSave *cron.Cron McronSaveID cron.EntryID msgChan chan *MsgMod.Msg args map[string]interface{} timerList map[string]*timer.Timer activity map[int]*ActivityInfo stop bool wg sync.WaitGroup } type PlayerBackUp struct { Data msg.ResPlayerBaseInfo PlayMod []byte } type PlayerMsg struct { F string B []byte } func (p *Player) Stop() { select { case <-p.stopSignal: // 通道已经关闭 return default: p.wg.Wait() close(p.stopSignal) close(p.msgChan) } G_GameLogicPtr.AddLog(&Log{ Uid: p.M_DwUin, EventName: "Login_Out", }) p.McronSave.Stop() p.stop = true } func (p *Player) CallEvent(Duration time.Duration, F func(), Label string) { if v, ok := p.timerList[Label]; ok { v.Stop() } t := p.MDispatr.AfterFunc(Duration, F) p.timerList[Label] = t } // 异步请求 func (p *Player) Send(m *MsgMod.Msg) error { if m == nil { return nil } p.wg.Add(1) p.msgChan <- m return nil } func (p *Player) Call(m MsgMod.Msg) { p.HandleMsg(m.Clone()) } func (p *Player) SendClientRes() { for _, v := range p.Msg { G_GameLogicPtr.PackResInfo(p.GetAgent(), v.F, v.B) } p.Msg = make([]PlayerMsg, 0) } func (p *Player) PushClientRes(m proto.Message) { key := GetStructName(m) buff, _ := proto.Marshal(m) p.Msg = append(p.Msg, PlayerMsg{ F: key, B: buff, }) } func (p *Player) PushAndSendClienRes(m proto.Message) { key := GetStructName(m) buff, _ := proto.Marshal(m) G_GameLogicPtr.PackResInfo(p.GetAgent(), key, buff) } func (p *Player) SendErrClienRes(m proto.Message) { key := GetStructName(m) buff, _ := proto.Marshal(m) G_GameLogicPtr.PackResInfo(p.GetAgent(), key, buff) } func (p *Player) QuestTrigger(tr *quest.Trigger) { p.Trigger = append(p.Trigger, tr) } func (p *Player) QuestTriggerList(tr []*quest.Trigger) { p.Trigger = append(p.Trigger, tr...) } func (p *Player) ProcessTrigger() { IsDailyBack := false DailyTaskMod := p.PlayMod.getDailyTaskMod() MailMod := p.PlayMod.getMailMod() PlayroomMod := p.PlayMod.getPlayroomMod() GuideTaskMod := p.PlayMod.getGuideTaskMod() IsPlayroomBack := false IsMailBack := false IsGuideTask := false for _, tr := range p.Trigger { if DailyTaskMod.Trigger(tr) { IsDailyBack = true } if p.MailTrigger(tr) { IsMailBack = true } if PlayroomMod.QuestTrigger(tr) { IsPlayroomBack = true } if GuideTaskMod.Trigger(tr) { IsGuideTask = true } } if IsDailyBack { p.PushClientRes(DailyTaskMod.BackData()) } if IsMailBack { p.PushClientRes(MailMod.BackData()) } if IsPlayroomBack { p.NotifyPlayroomTask() } if IsGuideTask { p.PushClientRes(GuideTaskMod.BackData()) } p.Trigger = make([]*quest.Trigger, 0) } // 接口请求之前备份数据 func (p *Player) BackUp() *PlayerBackUp { BackUp := PlayerBackUp{} p.PlayMod.BackUp(&BackUp) BackUp.Data = p.GetPlayerBaseMod().BackUp() return &BackUp } // 接口发生错误时 还原数据 func (p *Player) Recover(backUp *PlayerBackUp) { // p.GetPlayerBaseMod().Data = backUp.Data p.PlayMod.Recover(backUp) p.Msg = make([]PlayerMsg, 0) } func (p *Player) InitPlayer(UserName string) error { p.lock.Lock() defer p.lock.Unlock() p.msgChan = make(chan *MsgMod.Msg, 100) p.Msg = make([]PlayerMsg, 0) p.args = make(map[string]interface{}) p.timerList = make(map[string]*timer.Timer) p.MDispatr = timer.NewDispatcher(100) p.stopSignal = make(chan bool) Base := &PlayerBaseData{p: p} // 玩家基础数据 ok := Base.LoadDataFromDB(UserName) if !ok { log.Debug("load PlayerBaseData failed:", UserName) return errors.New("load PlayerBaseData failed") } p.PlayerBaseMod = Base p.M_DwUin = Base.Data.DwUin // 棋盘数据 // 玩家模块数据 modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)} ok = modData.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerModData failed:", UserName) return errors.New("load PlayerModData failed") } IsUpdate, err := modData.InitMod(p) if err != nil { log.Debug("InitMod failed:", err) return err } p.PlayMod.mod_list = modData.ModList p.PlayMod.is_update = IsUpdate // 启动定时器 p.DispatcherHandle() p.McronSave = cron.New() _, err = p.McronSave.AddFunc("@every 1m", p.AutoSaveData) if err != nil { log.Debug("AddFunc failed:", err) } p.McronSave.Start() p.initAcitivity() p.ZeroUpdate(nil) p.NoonUpdate(nil) p.Login() p.OrderShip() p.UpdateUserInfo() // fix bug ChargeMod := p.PlayMod.getChargeMod() ChessMod := p.PlayMod.getChessMod() ChargeMod.FixBug(ChessMod.GetEmitList()) p.FixOrderBug() //p.FixDecorate() return nil } func (p *Player) OrderShip() { OrderList, err := db.GetPlayerChargeDataList(int(p.M_DwUin)) if err != nil { return } // 避免为每个订单创建 goroutine,改为批量处理或同步处理 for _, OrderInfo := range OrderList { // 直接同步处理,避免创建过多 goroutine p.TriggerShippingOrderOrigin(&msg.ReqShippingOrder{ OrderSn: OrderInfo.OrderId, }) } } // 零点更新 func (p *Player) ZeroUpdate(a []interface{}) { VarMod := p.PlayMod.getVarMod() zeroTimestamp := GoUtil.ZeroTimestamp() PlayerBaseMod := p.GetPlayerBaseMod() // 零点更新 if VarMod.DailyResetTime < zeroTimestamp { VarMod.DailyResetTime = zeroTimestamp VarMod.DailyVar = make(map[int]interface{}) //卡牌 赛季结束补发图鉴奖励 HandbookItem := p.PlayMod.getCardMod().ZeroUpdate(G_GameLogicPtr.SeverInfo.OpenTime) p.HandleItem(HandbookItem, msg.ITEM_POP_LABEL_AllCollectRewardHB.String()) p.PushClientRes(p.PlayMod.getCardMod().BackData()) // 每日任务 p.PlayMod.getDailyTaskMod().ZeroUpdate(p.GetPlayerBaseMod().GetLevel(), p.PlayMod.getDecorateMod().GetAreaId()) p.PushClientRes(p.PlayMod.getDailyTaskMod().BackData()) // 能量商店 p.PlayMod.getBaseMod().ZeroUpdate() p.PushClientRes(p.PlayMod.getBaseMod().BackData()) // 七日签到 p.PlayMod.getSevenLoginMod().ZeroUpdate(PlayerBaseMod.GetSevenLoginAdd(), PlayerBaseMod.GetLastLoginTime()) p.PushClientRes(p.PlayMod.getSevenLoginMod().BackData()) // 礼包充值 ChessMod := p.PlayMod.getChessMod() ChargeMod := p.PlayMod.getChargeMod() ChargeMod.ZeroUpdate(ChessMod.GetEmitList()) p.ChargeBackData() // 无尽礼包 p.PlayMod.getEndlessMod().ZeroUpdate(p.PlayMod.getChargeMod().GetMaxCharge(), p.PlayMod.getBaseMod().GetLevel()) p.PushClientRes(p.PlayMod.getEndlessMod().BackData()) // 宠物宝箱 p.PlayMod.getFriendTreasureMod().ZeroUpdate() // p.PushClientRes(p.PlayMod.getFriendTreasureMod().BackData()) // 好友功能 p.PlayMod.getFriendMod().ZeroUpdate() p.PlayMod.getLimitedTimeEventMod().ZeroUpdate(p.GetPlayerBaseMod().GetLevel()) // playroom PlayroomMod := p.PlayMod.getPlayroomMod() PlayroomMod.ZeroUpdate() if ChargeMod.IsWeeklyDiscountDay() { PlayroomMod.ResetWeeklyDiscount() } p.PlayroomBackData() p.PlayMod.getChampshipMod().ZeroUpdate() p.initAcitivity() p.ActivityZeroUpdate() p.QuestTrigger(&quest.Trigger{Label: quest.TRIGGER_LABEL_LOGIN}) p.PlayMod.save() } // 周更新 weekZeroTimestamp := GoUtil.WeekZeroTimestamp() if VarMod.WeeklyResetTime < weekZeroTimestamp { VarMod.WeeklyResetTime = weekZeroTimestamp VarMod.WeeklyVar = make(map[int]interface{}) p.PlayMod.getDailyTaskMod().WeekUpdate() p.PushClientRes(p.PlayMod.getDailyTaskMod().BackData()) p.PlayMod.getLimitedTimeEventMod().WeekUpdate() p.PlayMod.save() } } // 十二点更新 func (p *Player) NoonUpdate(a []interface{}) { VarMod := p.PlayMod.getVarMod() noonTimestamp := GoUtil.NoonTimestamp() // 零点更新 if VarMod.NoonResetTime < noonTimestamp { VarMod.NoonResetTime = noonTimestamp ChessMod := p.PlayMod.getChessMod() // 礼包充值 p.PlayMod.getChargeMod().NoonUpdate(ChessMod.GetEmitList()) p.ChargeBackData() p.PlayMod.save() } } func (p *Player) Login() { // 添加定时器 // 限时事件触发 p.LimitedTimeEventTrigger(0) // 猪猪银行触发 p.LimitedTimePiggyBankTrigger() BaseMod := p.PlayMod.getBaseMod() FaceMod := p.PlayMod.getFaceMod() ChargeMod := p.PlayMod.getChargeMod() AvatarMod := p.PlayMod.getAvatarMod() PlayBaseMod := p.GetPlayerBaseMod() GuideTaskMod := p.PlayMod.getGuideTaskMod() // playroom触发 p.LimitedTimePlayroomTrigger() // playroom数值变化 LimitedTimePlayroomWorkTrigger(p) // playroom打工 LimitedTimeEnergyAdd(p) // 能量定时处理 p.ActivityLogin() // 活动登录 p.Compensation() SyncMailMsg(p) // 同步邮件 Duration := BaseMod.Login() ChargeMod.Login(Duration) GuideTaskMod.Login() FaceMod.Login(PlayBaseMod.GetRegisterTime()) AvatarMod.Login(PlayBaseMod.GetRegisterTime()) HandbookItem := p.PlayMod.getCardMod().Login(G_GameLogicPtr.SeverInfo.OpenTime) p.HandleItem(HandbookItem, msg.ITEM_POP_LABEL_AllCollectRewardHB.String()) // 每周优惠特殊处理 WeeklyStartTime, WeeklyEndTime := chargeCfg.GetWeeklyDiscountStartEnd() now := GoUtil.Now() if now >= WeeklyStartTime && now <= WeeklyEndTime { ChargeMod.WeeklyEndTime = WeeklyEndTime } if WeeklyStartTime > now { p.CallEvent(time.Duration(WeeklyStartTime-now)*time.Second, func() { ChargeMod.WeeklyEndTime = WeeklyEndTime ChargeMod.ResetWeeklyDiscount() PlayroomMod := p.PlayMod.getPlayroomMod() PlayroomMod.ResetWeeklyDiscount() p.ChargeBackData() p.PlayroomBackData() }, "WeeklyDiscountStart") } if WeeklyEndTime > now { p.CallEvent(time.Duration(WeeklyEndTime-now)*time.Second, func() { ChargeMod.WeeklyEndTime = 0 p.ChargeBackData() p.PlayroomBackData() LimitEventMod := p.PlayMod.getLimitedTimeEventMod() LimitEventMod.EndCatDaySale() p.PushClientRes(LimitEventMod.BackData()) }, "WeeklyDiscountEnd") } if Duration > 604800 { FriendMod := p.PlayMod.getFriendMod() FriendMod.AddActLog(friend.ACT_LOG_TYPE_LOST_USER_RETURN, "") } } func (p *Player) Outline() { PlayroomMod := p.PlayMod.getPlayroomMod() PlayroomMod.Outline() PlayerBaseMod := p.GetPlayerBaseMod() Now := GoUtil.Now() Cacumulative := Now - PlayerBaseMod.GetLoginTime() BaseMod := p.PlayMod.getBaseMod() BaseMod.Outline(int(Cacumulative)) p.PlayMod.save() p.TeLog("logout", map[string]interface{}{ "caccumulative": Cacumulative, "order_list": p.PlayMod.getOrderMod().GetOrderList(), "after_level": p.PlayMod.getBaseMod().GetLevel(), "tmp_diamond": p.PlayMod.getBaseMod().GetDiamond(), "tmp_energy": p.PlayMod.getBaseMod().GetEnergy(), }) p.UpdateUserInfo() } // 离线 保存数据 func (p *Player) ClearData() { log.Release("uid: %d, outline save data", p.M_DwUin) p.Outline() ctx := context.Background() txOptions := &sql.TxOptions{} tx, err := db.SqlDb.BeginTx(ctx, txOptions) if err != nil { log.Debug("ClearData BeginTx failed:", err) return } Uid := int(p.M_DwUin) p.PlayerBaseMod.ClearData() p.PlayMod.ClearData(p) tx.Commit() p.Stop() G_GameLogicPtr.DelPlayer(p) SendMsgToCenterAsync(&MsgMod.Msg{ From: Uid, HandleType: MsgMod.HANDLE_MDO_PLAYER_LOGOUT, }) } func (p *Player) AutoSaveData() { p.lock.Lock() defer p.lock.Unlock() //保存数据 ctx := context.Background() txOptions := &sql.TxOptions{} tx, err := db.SqlDb.BeginTx(ctx, txOptions) if err != nil { log.Debug("AutoSaveData BeginTx failed:", err) return } p.PlayerBaseMod.SaveDataFromDB("") p.PlayMod.ClearData(p) err = tx.Commit() if err != nil { log.Debug("AutoSaveData Commit failed:", err) } } // 重新连接 func (p *Player) Reconnect() { } // 获取conn连接 func (p *Player) GetAgent() gate.Agent { return p.agent } // 设置conn连接 func (p *Player) SetAgent(a gate.Agent) { p.agent = a } func (p *Player) GetPlayerBaseMod() *PlayerBaseData { return p.PlayerBaseMod } func (p *Player) GetAgentByPlayer() gate.Agent { return p.agent } // 处理物品 func (p *Player) HandleLoseItem(itemList []*item.Item, Label string) error { for _, v := range itemList { if v.Num > 0 { v.Num = -v.Num } } return p.HandleItem(itemList, Label) } func (p *Player) HandleItem(itemList []*item.Item, Label string) error { if len(itemList) == 0 { return nil } is_update := false ResCard := make([]*msg.CardPack, 0) ResItem := make([]*msg.ItemInfo, 0) ItemMod := p.PlayMod.getItemMod() AvatarMod := p.PlayMod.getAvatarMod() EmojiMod := p.PlayMod.getEmojiMod() FaceMod := p.PlayMod.getFaceMod() BackDataType := map[int]struct{}{} for _, v := range itemList { if v.Num == 0 { continue } if v.Num > 0 && Label != "" { ResItem = append(ResItem, &msg.ItemInfo{Id: int32(v.Id), Num: int32(v.Num)}) } var change_type string if v.Num < 0 { change_type = "consume" } else { change_type = "gain" } IType := itemCfg.GetItemType(v.Id) if IType == 0 { return errors.New("item type error, item id :" + strconv.Itoa(v.Id)) } switch IType { case item.ITEM_TYPE_ENERGY: // 能量 err := p.GetPlayerBaseMod().AddEnergy(p, v.Num) p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": math.Abs(float64(v.Num)), "change_after": p.GetPlayerBaseMod().GetEnergy(), "change_reason": Label, }) is_update = true if err != nil { return err } case item.ITEM_TYPE_STAR: // 星星 err := p.GetPlayerBaseMod().AddStar(p, v.Num) is_update = true if err != nil { return err } p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": math.Abs(float64(v.Num)), "change_after": p.GetPlayerBaseMod().GetStar(), "change_reason": Label, }) case item.ITEM_TYPE_DIAMOND: // 钻石 err := p.GetPlayerBaseMod().AddDiamond(v.Num) is_update = true if err != nil { return err } if v.Num < 0 { p.QuestTrigger(&quest.Trigger{Label: quest.TRIGGER_LABEL_DIAMOND, A: []interface{}{-v.Num}}) } p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": math.Abs(float64(v.Num)), "change_after": p.GetPlayerBaseMod().GetDiamond(), "change_reason": Label, }) case item.ITEM_TYPE_CARD: // 卡牌 Effect := itemCfg.GetItemEffect(v.Id) p.AddCard(Effect) case item.ITEM_TYPE_CARD_PACK: // 卡包 CardMod := p.PlayMod.getCardMod() Effect := itemCfg.GetItemEffect(v.Id) for i := 0; i < v.Num; i++ { NewCard, err := CardMod.OpenCardPack(Effect) if err != nil { return err } ResCard = append(ResCard, &msg.CardPack{Id: int32(v.Id), Card: GoUtil.SliceIntToInt32(NewCard)}) IsGold := false IsRepeat := false Sticker := 0 for _, v := range NewCard { Gold := cardCfg.CheckCardIsGold(v) if Gold { IsGold = true } if CardMod.GetCardNum(v) > 1 { IsRepeat = true Sticker++ } else { p.TeLog("get_new_card", map[string]interface{}{ "season_id": CardMod.EndTime, "card_id": v, "card_typenumbers": len(CardMod.CardList), }) } } p.TeLog("card_pack_open", map[string]interface{}{ "season_id": CardMod.EndTime, "card_pack_type": v.Id, "card_number": len(NewCard), "card_list": NewCard, "income_from": Label, "is_goldcard": IsGold, "is_repeat": IsRepeat, "is_card_festival": CardMod.GetCardFestival(), "sticker_number": Sticker, }) } case item.ITEM_TYPE_MASTER_CARD: // 万能卡 CardMod := p.PlayMod.getCardMod() Effect := itemCfg.GetItemEffect(v.Id) for i := 0; i < v.Num; i++ { CardMod.AddMasterCard(Effect) } case item.ITEM_TYPE_CHESS: // 棋子 ChessMod := p.PlayMod.getChessMod() if v.Num < 0 { err := ChessMod.LosePart(v.Id, -v.Num) if err != nil { return err } p.TeLog("chess_part_consume", map[string]interface{}{ "chess_id": v.Id, "chess_name": mergeDataCfg.GetNameById(v.Id), "consume_num": -v.Num, "remain_num": ChessMod.PartBag.List[v.Id].Num, "consume_from": Label, }) continue } for i := 0; i < v.Num; i++ { ChessMod.AddChessBuff(v.Id) } Type := mergeDataCfg.GetTypeById(v.Id) if Type == "Chest" || Type == "Gift" { p.TeLog("get_chest", map[string]interface{}{ "chest_id": v.Id, "chest_name": mergeDataCfg.GetNameById(v.Id), "get_source": Label, }) } p.PushClientRes(ChessMod.BackData()) case item.ITEM_TYPE_LIMIED_TIME_EVENT: // 限时事件 EffectList := itemCfg.GetItemEffectList(v.Id) LimitedTimeEventMod := p.PlayMod.getLimitedTimeEventMod() if len(EffectList) < 2 { log.Debug("Effect List error;item id :%d", v.Id) continue } EndTime := LimitedTimeEventMod.AddEvent(EffectList[0], EffectList[1]) p.PushClientRes(&msg.LimitEventNotify{ Id: int32(EffectList[0]), Type: limitedTimeEvent.EVENT_NOTIFY_TYPE_ADD, EndTime: int32(EndTime), Cd: int32(EffectList[1]), }) // 触发订单事件 生成超级订单 卡牌节 p.LimitedTimeEventTrigger(EffectList[0]) p.TeLog("time_limited_event_enable", map[string]interface{}{ "event_type": limitedTimeEventCfg.GetEventName(EffectList[0]), "enable_type": Label, }) case item.ITEM_TYPE_PIGGY_BANK: // 猪猪银行 PiggyBankMod := p.PlayMod.getPiggyBankMod() Effect := itemCfg.GetItemEffect(v.Id) PiggyBankMod.AddPiggyBank(Effect) p.LimitedTimePiggyBankTrigger() p.PushClientRes(PiggyBankMod.BackData()) p.TeLog("piggy_bank_income", map[string]interface{}{ "piggy_bank_type": Effect, "income_from": Label, }) case item.ITEM_TYPE_AVATAR: // 头像框 Effect := itemCfg.GetItemEffectList(v.Id) AvatarMod.Unlock(Effect[0], Effect[1]) p.TeLog("avatarIcon_income", map[string]interface{}{ "avatar_id": Effect[0], "income_from": Label, }) FriendMod := p.PlayMod.getFriendMod() FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_AVATAR_FRAME, "") p.PlayerDecoLog("avatar", Effect[0], Label) BackDataType[item.ITEM_TYPE_AVATAR] = struct{}{} case item.ITEM_TYPE_EMOJI: // 表情 Effect := itemCfg.GetItemEffectList(v.Id) EmojiMod.Unlock(Effect[0], Effect[1]) p.TeLog("emoji_income", map[string]interface{}{ "emoji_id": Effect[0], "income_from": Label, }) FriendMod := p.PlayMod.getFriendMod() FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_EMOTION, "") p.PlayerDecoLog("emoji", Effect[0], Label) BackDataType[item.ITEM_TYPE_EMOJI] = struct{}{} case item.ITEM_TYPE_FACE: // 头像 Effect := itemCfg.GetItemEffectList(v.Id) FaceMod.Unlock(Effect[0], Effect[1]) p.TeLog("face_income", map[string]interface{}{ "face_id": Effect[0], "income_from": Label, }) FriendMod := p.PlayMod.getFriendMod() FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_AVATAR, "") p.PlayerDecoLog("face", Effect[0], Label) BackDataType[item.ITEM_TYPE_FACE] = struct{}{} case item.ITEM_TYPE_ACTIVITY_RACE: // 活动竞速 ActivityInfo := p.GetActivityInfo(activity.ACT_TYPE_RACE) if ActivityInfo == nil { continue } RaceMod := p.PlayMod.getRaceMod() RaceMod.AddCoin(v.Num) p.RaceBackData() case item.ITEM_TYPE_PLAYROOM_VISIT: // 拜访玩家 Target := p.GetVisitorPlayer() playroomMod := p.PlayMod.getPlayroomMod() playroomMod.Target = Target playroomMod.Status = playroom.STATUS_VISIT // PlayroomVisit(p, Target) p.PlayroomBackData() case item.ITEM_TYPE_PLAYROOM_DECORATION: // playroom装饰 Effect := itemCfg.GetItemEffect(v.Id) PlayroomMod := p.PlayMod.getPlayroomMod() PlayroomMod.AddCollect(Effect, Label) BackDataType[item.ITEM_TYPE_PLAYROOM_DECORATION] = struct{}{} Type, Name := playroomCfg.GetDecoInfo(Effect) FriendMod := p.PlayMod.getFriendMod() FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_DECORATION, "") p.TeLog("room_deco_get", map[string]interface{}{ "room_deco_type": Type, "room_deco_name": Name, "room_deco_get_type": Label, }) case item.ITEM_TYPE_PLAYROOM_DRESS: // playroom服饰 Effect := itemCfg.GetItemEffect(v.Id) PlayroomMod := p.PlayMod.getPlayroomMod() PlayroomMod.AddDress(Effect, Label) BackDataType[item.ITEM_TYPE_PLAYROOM_DRESS] = struct{}{} Type := playroomCfg.GetDressPart(Effect) Name := playroomCfg.GetDressName(Effect) FriendMod := p.PlayMod.getFriendMod() FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_COSTUME, "") p.TeLog("pet_deco_get", map[string]interface{}{ "pet_deco_type": Type, "pet_deco_name": Name, "pet_deco_get_type": Label, }) case item.ITEM_TYPE_PLAYROOM_DECORATION_SET: // playroom装饰套装 Effect := itemCfg.GetItemEffectList(v.Id) PlayroomMod := p.PlayMod.getPlayroomMod() for _, v := range Effect { if v == 0 { continue } PlayroomMod.AddCollect(v, Label) Type, Name := playroomCfg.GetDecoInfo(v) p.TeLog("room_deco_get", map[string]interface{}{ "room_deco_type": Type, "room_deco_name": Name, "room_deco_get_type": Label, }) } BackDataType[item.ITEM_TYPE_PLAYROOM_DECORATION_SET] = struct{}{} case item.ITEM_TYPE_PLAYROOM_DRESS_SET: // playroom服饰套装 Effect := itemCfg.GetItemEffectList(v.Id) PlayroomMod := p.PlayMod.getPlayroomMod() for _, v := range Effect { if v == 0 { continue } PlayroomMod.AddDress(v, Label) Name := playroomCfg.GetDressName(v) Type := playroomCfg.GetDressPart(v) p.TeLog("pet_deco_get", map[string]interface{}{ "pet_deco_type": Type, "pet_deco_name": Name, "pet_deco_get_type": Label, }) } BackDataType[item.ITEM_TYPE_PLAYROOM_DRESS_SET] = struct{}{} case item.ITEM_TYPE_ACT_PASS: // 活动通行证 ActivityInfo := p.GetActivityInfo(activity.ACT_TYPE_PASS) if ActivityInfo == nil { continue } PassMod := p.PlayMod.getPassMod() PassMod.AddExp(v.Num) p.ActPassBackData() default: err := ItemMod.AddItem(v.Id, v.Num) p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": math.Abs(float64(v.Num)), "change_after": ItemMod.GetItem(v.Id), "change_reason": Label, }) if err != nil { return err } } } ResItemPopId := 0 if v, ok := p.args["ResItemPopId"]; ok { ResItemPopId = GoUtil.Int(v) } if len(ResItem) != 0 || len(ResCard) != 0 { p.PushClientRes(&msg.ResItemPop{ Id: int32(ResItemPopId), Items: ResItem, CardPacks: ResCard, Lable: Label, }) } for k := range BackDataType { switch k { case item.ITEM_TYPE_AVATAR: p.BackUserInfo() case item.ITEM_TYPE_EMOJI: p.BackUserInfo() case item.ITEM_TYPE_FACE: p.BackUserInfo() case item.ITEM_TYPE_PLAYROOM_DECORATION, item.ITEM_TYPE_PLAYROOM_DRESS, item.ITEM_TYPE_PLAYROOM_DECORATION_SET, item.ITEM_TYPE_PLAYROOM_DRESS_SET: p.PlayroomBackData() } } p.PetItemUseLog(itemList) CardMod := p.PlayMod.getCardMod() p.PushClientRes(CardMod.NotifyCard()) p.PushClientRes(ItemMod.NotifyItem()) p.PlayMod.save() if is_update { p.PushClientRes(p.GetPlayerBaseMod().BackAsset()) } return nil } // 登录返回数据 func (p *Player) LoginBackData() { SendMsgToCenterSync(&MsgMod.Msg{ From: int(p.M_DwUin), HandleType: MsgMod.HANDLE_MOD_PLAYER_LOGIN, Extra: conf.Server.ServerID, }) p.PushClientRes(p.PlayMod.mod_list.Base.BackData()) p.PushClientRes(p.PlayMod.mod_list.Handbook.BackData()) p.PushClientRes(p.PlayMod.mod_list.Base.BackData()) p.PushClientRes(p.PlayMod.mod_list.Chess.BackData()) p.PushClientRes(p.PlayMod.mod_list.Order.BackData()) p.PushClientRes(p.PlayMod.mod_list.Card.BackData()) p.PushClientRes(p.PlayMod.mod_list.Decorate.BackData()) p.PushClientRes(p.PlayMod.mod_list.DailyTask.BackData()) p.PushClientRes(p.PlayMod.mod_list.SevenLogin.BackData()) p.PushClientRes(p.PlayMod.mod_list.LimitedTimeEvent.ProgressBackData()) p.PushClientRes(p.PlayMod.mod_list.Charge.PetWorkBackData()) p.PushClientRes(p.PlayMod.mod_list.Endless.BackData()) p.PushClientRes(p.PlayMod.mod_list.PiggyBank.BackData()) p.PushClientRes(p.PlayMod.mod_list.Item.BackData()) p.PushClientRes(p.GetPlayerBaseMod().BackAsset()) p.PushClientRes(p.PlayMod.mod_list.Kv.BackData()) p.PushClientRes(p.PlayMod.mod_list.GuideTask.BackData()) p.PushClientRes(p.PlayMod.mod_list.Friend.BubbleBackData()) p.PushClientRes(p.PlayMod.mod_list.Guide.BackData()) p.BackDataActivity() p.ChargeBackData() p.BackChampship() p.BackUserInfo() } func (p *Player) InitPlayerOnly() { p.lock.Lock() defer p.lock.Unlock() p.Msg = make([]PlayerMsg, 0) p.args = make(map[string]interface{}) p.timerList = make(map[string]*timer.Timer) p.MDispatr = timer.NewDispatcher(10) p.stopSignal = make(chan bool) Base := &PlayerBaseData{p: p} // 玩家基础数据 ok := Base.GetDataByUid(p.M_DwUin) if !ok { return } p.PlayerBaseMod = Base p.M_DwUin = Base.Data.DwUin // 玩家模块数据 modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)} ok = modData.LoadDataFromDB(Base.Data.DwUin) if !ok { return } modData.InitMod(p) p.PlayMod.mod_list = modData.ModList } // 获取玩家简单数据 func (p *Player) GetSimpleData(Uid int, simple *PlayerSimpleData) error { p.M_DwUin = int64(Uid) p.InitPlayerOnly() Base := p.GetPlayerBaseMod() if Base == nil { return errors.New("GetSimpleData failed") } simple.Name = p.PlayMod.getBaseMod().NickName simple.Avatar = p.PlayMod.getAvatarMod().SetId simple.Face = p.PlayMod.getFaceMod().SetId simple.Level = p.GetPlayerBaseMod().GetLevel() simple.Decorate = p.PlayMod.getDecorateMod().DecorateNum simple.Login = int64(Base.Data.LoginTime) simple.Star = p.GetPlayerBaseMod().GetStar() simple.Loginout = int64(Base.Data.LogoutTime) simple.FaceBook = Base.Data.FaceBookId simple.FaceBookPic = p.PlayMod.getBaseMod().FacebookUrl simple.Playroom = p.PlayMod.getPlayroomMod().Room simple.Chess = p.PlayMod.getChessMod().GetUnlockChessList() simple.WorkStart = p.PlayMod.getPlayroomMod().Starttime simple.Chip = p.PlayMod.getPlayroomMod().GetChip() simple.PetName = p.PlayMod.getBaseMod().PetName simple.Emoji = p.PlayMod.getEmojiMod().Set return nil } func (p *Player) UpdateUserInfo() { simple := &PlayerSimpleData{} Base := p.GetPlayerBaseMod() CardMod := p.PlayMod.getCardMod() BaseMod := p.PlayMod.getBaseMod() simple.Name = p.PlayMod.getBaseMod().NickName simple.Avatar = p.PlayMod.getAvatarMod().SetId simple.Uid = int(p.M_DwUin) simple.Star = p.GetPlayerBaseMod().GetStar() simple.Face = p.PlayMod.getFaceMod().SetId simple.Level = p.GetPlayerBaseMod().GetLevel() simple.Decorate = p.PlayMod.getDecorateMod().DecorateNum simple.Login = int64(BaseMod.LoginTime) simple.Loginout = int64(BaseMod.LogoutTime) simple.FaceBook = Base.Data.FaceBookId simple.FaceBookPic = p.PlayMod.getBaseMod().FacebookUrl simple.Playroom = p.PlayMod.getPlayroomMod().Room simple.Chess = p.PlayMod.getChessMod().GetUnlockChessList() simple.WorkStart = p.PlayMod.getPlayroomMod().Starttime simple.Chip = p.PlayMod.getPlayroomMod().GetChip() simple.PetName = p.PlayMod.getBaseMod().PetName simple.Emoji = p.PlayMod.getEmojiMod().Set simple.Friend = p.PlayMod.getFriendMod().GetSimpleFriendList() simple.Upvote = p.PlayMod.getPlayroomMod().Upvote simple.DressSet = p.PlayMod.getPlayroomMod().DressSet simple.CardInfo = CardMod.GetCardList() simple.ActLog = p.PlayMod.getFriendMod().GetActLogLast() simple.Physiology = p.PlayMod.getPlayroomMod().GetPhysiologyList() //TODO 存储到redis 在新版本中将优化成gob进行压缩 value, _ := json.Marshal(simple) IdStr := GoUtil.String(p.M_DwUin) go db.RedisSetKeyBytes(IdStr, value, 0) } func (p *Player) HandleInUserRank() { DecorateMod := p.PlayMod.getDecorateMod() Score := float64(DecorateMod.GetDecorateNum()) BaseMod := p.PlayMod.getBaseMod() Score += float64(BaseMod.GetLevel()) * 1000000 // 等级加成 // 更新排行榜 m := &MsgMod.Msg{ Type: MsgMod.HANDLE_TYPE_RANK, SendT: GoUtil.Now(), Extra: RankMsg{ Uid: int(p.M_DwUin), Score: float64(Score), RankType: RANK_TYPE_USER, }, } G_GameLogicPtr.RankMgrSend(m) } func (p *Player) HandleInChampshipRank() { ChampshipMod := p.PlayMod.getChampshipMod() Score := float64(ChampshipMod.GetScore()) if Score <= 0 { return } // 更新排行榜 m := &MsgMod.Msg{ Type: MsgMod.HANDLE_TYPE_CHAMPSHIP_INRANK, SendT: GoUtil.Now(), Extra: CRank{ Uid: int(p.M_DwUin), Score: Score, H: ChampshipMod.GetH(), N: ChampshipMod.GetN(), }, End: GoUtil.ZeroTimestamp() + 86400, // 第二天零点删除 HandleType: MsgMod.HANDLE_MDO_CHAMPSHIP_INRANK, } SendMsgToCenterAsync(m) } func (p *Player) AddLog(Uid int, Type int, Param string, Time int64) { FriendMod := p.PlayMod.getFriendMod() Id := FriendMod.AddLog(Uid, Type, Param) p.PlayMod.save() p.PushClientRes(&msg.NotifyFriendLog{ Info: &msg.ResFriendLog{ Player: G_GameLogicPtr.GetResSimplePlayerByUid(Uid), Type: int32(Type), Param: Param, Id: int32(Id), Time: int32(Time), }, Bubble: FriendMod.GetBubbble(Id), }) } func (p *Player) TeLog(Type string, Param map[string]interface{}) { G_GameLogicPtr.AddLog(&Log{ Uid: p.M_DwUin, EventName: Type, Param: Param, }) agent := p.GetAgent() if Param == nil { Param = make(map[string]interface{}) } if agent != nil && Param != nil { Param["Ip"] = agent.RemoteAddr().String() } //Param["#zone_offset"] = -5 // 游戏内TE日志 BaseMod := p.PlayMod.getBaseMod() UidStr := GoUtil.String(p.M_DwUin) go telog.Te.Track(BaseMod.Account, UidStr, Type, Param) //途游GA go ga.GAlogEvent(Type, BaseMod.Account, "", Param) } func (p *Player) Kafka(Type string, Param map[string]interface{}) { G_GameLogicPtr.AddLog(&Log{ Uid: p.M_DwUin, EventName: Type, Param: Param, }) } // 初始化活动 func (p *Player) initAcitivity() { p.activity = make(map[int]*ActivityInfo) ActivityList := activityCfg.GetActivityList() Level := p.GetPlayerBaseMod().GetLevel() ActivityMod := p.PlayMod.getActivityMod() for _, v := range ActivityList { if v.Level > Level { continue } Status := ActivityMod.GetActivityStatus(v) if Status == 0 { continue } p.activity[v.Id] = &ActivityInfo{ StartT: v.StartTime, EndT: v.EndTime, Id: v.Id, Type: v.Type, Status: Status, Title: v.Title, } } } func (p *Player) BackDataActivity() { ResActivityList := make([]*msg.ActivityInfo, 0) for _, v := range p.activity { Red := p.GetRed(v) ResActivityList = append(ResActivityList, &msg.ActivityInfo{ Id: int32(v.Id), Type: int32(v.Type), StartTime: int32(v.StartT), EndTime: int32(v.EndT), Status: int32(v.Status), Title: v.Title, Red: int32(Red), }) } p.PushClientRes(&msg.ResActivity{ ActiveList: ResActivityList, }) } func (p *Player) GetRed(AI *ActivityInfo) int { Status := p.GetActivityStatus(AI.Type) if Status != ACT_STATUS_START { return 0 } // 限时活动红点 if AI.Type == activity.ACT_TYPE_MINING { ItemId := miningCfg.GetActivityItemId(AI.Id) return p.PlayMod.getItemMod().GetItem(ItemId) } if AI.Type == activity.ACT_TYPE_GUESS_COLOR { ItemId := guesscolorCfg.GetActivityItemId(AI.Id) return p.PlayMod.getItemMod().GetItem(ItemId) } return 0 } func (p *Player) NotifyRed(actType int) { ActivityInfo := p.GetActivityInfo(actType) Status := p.GetActivityStatus(actType) if Status != ACT_STATUS_START { return } if ActivityInfo == nil { return } Red := p.GetRed(ActivityInfo) p.PushClientRes(&msg.NotifyActRed{ Id: int32(ActivityInfo.Id), Red: int32(Red), }) } func (p *Player) AddCard(Id int) { CardMod := p.PlayMod.getCardMod() CardMod.AddCard(Id) p.TeLog("asset_change", map[string]interface{}{ "item_id": Id, "change_type": "gain", "change_num": 1, "change_after": CardMod.CardList[Id], "change_reason": "exchange_card", }) } func (p *Player) SubCard(Id int) error { CardMod := p.PlayMod.getCardMod() err := CardMod.SubCard(Id) if err != nil { return err } p.TeLog("asset_change", map[string]interface{}{ "item_id": Id, "change_type": "gain", "change_num": 1, "change_after": CardMod.CardList[Id], "change_reason": "exchange_card", }) return nil } func (p *Player) GetIp() string { if p.GetAgent() == nil { return "" } return p.GetAgent().RemoteAddr().String() } func (p *Player) DispatcherHandle() { go func() { var cb *timer.Timer for { select { case <-p.stopSignal: return case cb = <-p.MDispatr.ChanTimer: if cb != nil { cb.Cb() } else { log.Debug("Timer callback or Timer is nil") } case msg := <-p.msgChan: if msg != nil { p.wg.Done() log.Debug("player %d recive msg %v", p.M_DwUin, msg) // 直接在当前 goroutine 中处理,避免创建过多 goroutine p.HandleMsg(msg.Clone()) } } } }() }