package friend import ( "fmt" cardCfg "server/conf/card" friendCfg "server/conf/friend" "server/game/mod/card" "server/game/mod/item" GoUtil "server/game_util" "server/msg" ) type FriendMod struct { FriendList map[int]struct{} // TODO 废弃 好友列表 NewFriendList map[int]*FriendInfo // 好友列表 ApplyList map[int]int64 // 好友请求列表 SendApply map[int]int64 // 发送的申请 Apply []*ApplyInfo // 其他请求列表 Card map[string]*card.CardInfo // 收到的申请交换 Log []*LogInfo // 日志 AutoId int Id int64 // 已同步msg ID Npc []int // npc id Bubble map[int]*BubbleInfo // 气泡 ActivityLog []*ActLogInfo // 活动日志 ReplyList []*ReplyInfo // 好友回复列表 DailySponsor int // 好友赞助次数 } type ReplyInfo struct { Id int Uid int Type int Param string Status int AddTime int64 ReplyTime int64 EndTime int64 Items []*item.Item } type ActLogInfo struct { Type int Time int64 Param string } type BubbleInfo struct { Id int // 气泡ID Time int64 // 气泡时间 Type int ItemList []*item.Item // 奖励物品 } type FriendInfo struct { AddTime int64 Interact []*Interact // 拜访记录 } type Interact struct { VisitTime int64 // 拜访时间 Type int // 1:拜访 2:点赞 } type ApplyInfo struct { Type int // 1:申请 2:同意 3:拒绝 4:删除 Time int64 Uid int64 } const ( REPLY_TYPE_GREETING = 1 // 问候 REPLY_TYPE_GREETING_Get = 2 // 收到问候 REPLY_TYPE_CATNIP = 3 // 猫薄荷加好友 REPLY_TYPE_CATNIP_ITEMS = 4 // 收到猫薄荷好友道具 ) // 24小时内与玩家进行过以下互动的用户,若被选中参加本次宠物宝藏,在其头像旁添加礼物盒 const ( INTERACT_TYPE_VISIT = 1 // 拜访过玩家的Pet Playroom并进行过小游戏或点赞的用户 INTERACT_TYPE_UPVOTE = 2 // 为玩家的图鉴全收集信息点过赞的用户 INTERACT_TYPE_CARD = 3 // 向玩家赠送过卡牌的用户 INTERACT_TYPE_EX = 4 // 向玩家发起过卡牌交换 INTERACT_TYPE_WISH = 5 // 邀请玩家一同参加活动的用户 ) const ( LOG_TYPE_FRIEND_APPLY = 1 // 收到申请好友 LOG_TYPE_FRIEND_BECOME = 2 // 成为好友 LOG_TYPE_CARD_EX_SEND = 3 // 发起卡牌交换申请 LOG_TYPE_CARD_SEND = 4 // 赠送卡牌 LOG_TYPE_CARD_GIVE = 5 // 请求卡牌 LOG_TYPE_CARD_SELECT_GET = 6 // 选择卡牌交换 LOG_TYPE_CARD_ACCEPT_GIVE = 7 // 接受卡牌 LOG_TYPE_CARD_EX_GET = 8 // 收到卡牌交换申请 LOG_TYPE_CARD_SELECT_SEND = 9 // 选择卡牌交换 LOG_TYPE_CARD_EX_SUCCESS_1 = 10 // 卡牌交换成功 LOG_TYPE_CARD_EX_SUCCESS_2 = 11 // 卡牌交换成功 LOG_TYPE_FRIEND_DELETE = 14 // 删除好友 LOG_TYPE_PLAYROOM_VISIT = 15 // 非小猫游戏,他人偷走了玩家的猫币 LOG_TYPE_HANDBOOK = 16 // 图鉴收集 LOG_TYPE_HANDBOOK_UPVOTE = 17 // 图鉴点赞 LOG_TYPE_CHARGE_SEND = 18 // 赠送充值礼物 LOG_TYPE_CHARGE_RECEIVE = 19 // 收到充值礼物 LOG_TYPE_WISH = 20 // 心愿单请求 LOG_TYPE_FRIEND_BECOME_NPC = 21 // npc成为好友 LOG_TYPE_PLAYROOM_UPVOTE = 22 // playroom点赞 LOG_TYPE_PLAYROOM_CHAMPSHIP = 23 // 竞标赛排名 LOG_TYPE_TREASURE = 24 // 好友宝藏 LOG_TYPE_CARD_SEND_ACCEPT = 25 // 收到赠送卡牌 LOG_TYPE_PLAYROOM_CAT_WIN = 26 // 小猫游戏,给小猫成功装箱 LOG_TYPE_PLAYROOM_CAT_LOSE = 27 // 小猫游戏,装箱小猫未成功 LOG_TYPE_CARD_GIVE_ACCEPT = 28 // 接受卡牌请求 LOG_TYPE_FRIEND_INVITE = 29 // 邀请注册 LOG_TYPE_TREASURE_HELP = 30 // 好友宝藏帮助 LOG_TYPE_FRIEND_SPONSOR = 31 // 好友赞助体力 LOG_TYPE_FRIEND_SPONSOR_GET = 32 // 获得好友赞助体力 ) const ( FRIEND_NOTIFY_APPLY = 1 FRIEND_NOTIFY_AGREE = 2 FRIEND_NOTIFY_REFUSE = 3 FRIEND_NOTIFY_DEL = 4 ) const ( APPLY_TYPE_WISH = 1 // 心愿单请求 ) const ( ACT_LOG_TYPE_FIRST_LOGIN = 1 // 首次登入游戏 ACT_LOG_TYPE_COMPLETE_RESTROOM = 2 // 完成休息室 ACT_LOG_TYPE_COMPLETE_RESTAURANT = 3 // 完成餐厅 ACT_LOG_TYPE_COMPLETE_BATHROOM = 4 // 完成浴室 ACT_LOG_TYPE_COMPLETE_CLOAKROOM = 5 // 完成衣帽间 ACT_LOG_TYPE_GET_NEW_AVATAR = 6 // 获得新头像 ACT_LOG_TYPE_GET_NEW_AVATAR_FRAME = 7 // 获得新头像框 ACT_LOG_TYPE_GET_NEW_EMOTION = 8 // 获得新表情 ACT_LOG_TYPE_GET_NEW_DECORATION = 9 // 获得新装饰品 ACT_LOG_TYPE_GET_NEW_COSTUME = 10 // 获得新服装 ACT_LOG_TYPE_COMPLETE_CARD_ALBUM = 11 // 完成卡册收集 ACT_LOG_TYPE_COMPLETE_ALL_CARDS = 12 // 完成全卡牌收集 ACT_LOG_TYPE_GET_CHAMPIONSHIP_RANK = 13 // 获得锦标赛名次 ACT_LOG_TYPE_GET_CHAMPIONSHIP_PRIZE = 14 // 获得锦标赛大奖 ACT_LOG_TYPE_GET_LIMITED_ACTIVITY_PRIZE = 15 // 获得限时活动大奖 ACT_LOG_TYPE_JOIN_FRIEND_COOP_ACTIVITY = 16 // 参加好友合作类活动 ACT_LOG_TYPE_GET_VISIT_GAME_PRIZE = 17 // 获得拜访小游戏大奖 翻牌 ACT_LOG_TYPE_GET_VISIT_GAME_PRIZE_1 = 18 // 获得拜访小游戏大奖 除了翻牌 ACT_LOG_TYPE_OPEN_PET_TREASURE = 19 // 打开宠物宝藏 ACT_LOG_TYPE_VISIT_UPVOTE = 20 // 拜访时点赞 ACT_LOG_TYPE_COMPLETE_HANDBOOK_ACHIEVEMENT = 21 // 完成图鉴收集成就 ACT_LOG_TYPE_COMPLETE_CHAPTER_SCENES = 22 // 完成第X章所有场景 ACT_LOG_TYPE_LOST_USER_RETURN = 23 // 流失用户回归 ACT_LOG_TYPE_ACCEPT_MY_INVITE_REGISTER = 24 // 接受"我"的邀请注册 ACT_LOG_TYPE_BECOME_MY_FRIEND = 25 // 成为"我"的好友 ACT_LOG_TYPE_SEND_CARD_TO_ME = 26 // 向"我"赠送卡牌 ACT_LOG_TYPE_CARD_EXCHANGE_WITH_ME = 27 // 与"我"达成卡牌交换 ACT_LOG_TYPE_APPEAR_IN_MY_PET_TREASURE = 28 // 出现在"我"的宠物宝藏中并被选中 ACT_LOG_TYPE_VISIT_MY_CAT_PRIVATE_TREASURE = 29 // 拜访"我"并玩了猫猫私房宝 ACT_LOG_TYPE_VISIT_MY_OTHER_GAME_WIN = 30 // 拜访"我"并玩了猫猫私房宝以外的小游戏,成功装箱 ACT_LOG_TYPE_VISIT_MY_OTHER_GAME_LOSE = 31 // 拜访"我"并玩了猫猫私房宝以外的小游戏,未成功装箱 ACT_LOG_TYPE_UPVOTE_MY_COLLECTION_INFO = 32 // 为"我"的全收集信息点赞 ACT_LOG_TYPE_UPVOTE_MY_ROOM = 33 // 为"我"的房间点赞 ACT_LOG_TYPE_JOIN_COOP_ACTIVITY_WITH_ME = 34 // 与"我"一起参加好友合作类活动 ) type LogInfo struct { Id int Uid int Type int Time int64 Param string Upvote bool // 点赞 Reward bool // 是否已领取奖励 } func (f *FriendMod) InitData() { if f.FriendList == nil { f.FriendList = make(map[int]struct{}) } if len(f.ActivityLog) == 0 { f.ActivityLog = make([]*ActLogInfo, 0) f.AddActLog(ACT_LOG_TYPE_FIRST_LOGIN, "") } if f.ApplyList == nil { f.ApplyList = make(map[int]int64) } if f.Card == nil { f.Card = make(map[string]*card.CardInfo) } if f.SendApply == nil { f.SendApply = make(map[int]int64) } if f.NewFriendList == nil { f.NewFriendList = make(map[int]*FriendInfo) } if f.Bubble == nil { f.Bubble = make(map[int]*BubbleInfo) } if len(f.FriendList) > 0 && len(f.NewFriendList) == 0 { for k := range f.FriendList { f.NewFriendList[k] = &FriendInfo{ AddTime: GoUtil.Now(), } } } } func (f *FriendMod) ZeroUpdate() { f.DailySponsor = f.GetDailySponsorLimit() } func (f *FriendMod) GetNpc() []int { return f.Npc } func (f *FriendMod) SetNpc(id int) error { if !friendCfg.IsNpcFriend(id) { return fmt.Errorf("not npc friend") } for _, v := range f.Npc { if v == id { return fmt.Errorf("npc already exist") } } f.Npc = append(f.Npc, id) return nil } func (f *FriendMod) GetSyncId() int64 { return f.Id } func (f *FriendMod) SetSyncId(Id int64) { f.Id = Id } func (f *FriendMod) Interact(id, t int, T int64) { if _, ok := f.NewFriendList[id]; !ok { return } for _, v := range f.NewFriendList[id].Interact { if v.Type == t && v.VisitTime < T { v.VisitTime = T return } } f.NewFriendList[id].Interact = append(f.NewFriendList[id].Interact, &Interact{ VisitTime: T, Type: t, }) } func (f *FriendMod) GetInteractTime(id int) int64 { if _, ok := f.NewFriendList[id]; !ok { return 0 } LastTime := int64(0) // 获取最近一次拜访或点赞的时间 for _, v := range f.NewFriendList[id].Interact { if v.VisitTime > LastTime { LastTime = v.VisitTime } } return LastTime } func (f *FriendMod) GetAddTime(id int) int64 { if _, ok := f.NewFriendList[id]; !ok { return 0 } return f.NewFriendList[id].AddTime } func (f *FriendMod) AddFriend(id int) { f.NewFriendList[id] = &FriendInfo{ AddTime: GoUtil.Now(), } delete(f.ApplyList, id) } func (f *FriendMod) GetCardInfo(Id string) *card.CardInfo { v, ok := f.Card[Id] if !ok { return nil } return v } func (f *FriendMod) SetCardInfo(CardInfo *card.CardInfo) { f.Card[CardInfo.Id] = CardInfo } func (f *FriendMod) DelCardInfo(Id string) { delete(f.Card, Id) } func (f *FriendMod) DelFriend(id int) { delete(f.NewFriendList, id) } func (f *FriendMod) CheckFriend(Uid int) bool { _, ok := f.NewFriendList[Uid] return ok } func (f *FriendMod) RefuseApply(id int) { delete(f.ApplyList, id) delete(f.SendApply, id) } func (f *FriendMod) CheckApply(id int) bool { _, ok := f.ApplyList[id] return ok } func (f *FriendMod) GetFriendNum() int { return len(f.NewFriendList) } func (f *FriendMod) GetFriendList() map[int]*FriendInfo { return f.NewFriendList } func (f *FriendMod) GetSimpleFriendList() []int { rs := make([]int, 0, len(f.NewFriendList)) for k := range f.NewFriendList { rs = append(rs, k) } return rs } // 收到申请 func (f *FriendMod) AddFriendApply(Uid int) { f.ApplyList[Uid] = GoUtil.Now() } // 发送申请 func (f *FriendMod) AddSendApply(Uid int) bool { if _, ok := f.SendApply[Uid]; ok { return true } f.SendApply[Uid] = GoUtil.Now() return false } func (f *FriendMod) CheckSendApply(Id int) bool { _, ok := f.SendApply[Id] return ok } func (f *FriendMod) AgreeApply(UId int) { f.AddFriend(UId) delete(f.SendApply, UId) delete(f.ApplyList, UId) } func (f *FriendMod) AddLog(Uid, Type int, Param string) int { f.AutoId++ f.Log = append(f.Log, &LogInfo{ Id: f.AutoId, Uid: Uid, Type: Type, Time: GoUtil.Now(), Param: Param, }) switch Type { case LOG_TYPE_HANDBOOK_UPVOTE: f.AddBubble(f.AutoId, Type, nil) case LOG_TYPE_PLAYROOM_UPVOTE: f.AddBubble(f.AutoId, Type, nil) case LOG_TYPE_TREASURE_HELP: ItemNum := GoUtil.RandNum(2, 5) ItemList := []*item.Item{item.NewItem(item.ITEM_STAR_ID, ItemNum)} f.AddBubble(f.AutoId, Type, ItemList) } if len(f.Log) > 30 { f.Log = f.Log[len(f.Log)-30:] } return f.AutoId } func (f *FriendMod) AddBubble(Id, Type int, ItemList []*item.Item) { f.Bubble[Id] = &BubbleInfo{ Id: Id, Time: GoUtil.Now(), Type: Type, ItemList: ItemList, } } func (f *FriendMod) GetBubbble(Id int) *msg.FriendBubbleInfo { if v, ok := f.Bubble[Id]; ok { return &msg.FriendBubbleInfo{ Id: int32(v.Id), Type: int32(v.Type), Items: item.ItemToMsg(v.ItemList), } } return nil } func (f *FriendMod) BubbleBackData() *msg.ResFriendBubble { rs := make([]*msg.FriendBubbleInfo, 0, len(f.Bubble)) for _, v := range f.Bubble { rs = append(rs, &msg.FriendBubbleInfo{ Id: int32(v.Id), Type: int32(v.Type), Items: item.ItemToMsg(v.ItemList), }) } return &msg.ResFriendBubble{ Bubble: rs, } } func (f *FriendMod) ResetGoldCardEx() { for _, v := range f.Card { if cardCfg.CheckCardIsGold(v.CardId) || cardCfg.CheckCardIsGold(v.ExId) { v.EndTime = 1 } } } func (f *FriendMod) AddActLog(Type int, Param string) { f.ActivityLog = append(f.ActivityLog, &ActLogInfo{ Type: Type, Time: GoUtil.Now(), Param: Param, }) if len(f.ActivityLog) > 20 { f.ActivityLog = f.ActivityLog[len(f.ActivityLog)-20:] } } func (f *FriendMod) Upvote(Id int) ([]*item.Item, int, error) { info := &LogInfo{} for _, v := range f.Log { if v.Id == Id { info = v break } } if info.Id == 0 { return nil, 0, fmt.Errorf("log not exist") } if info.Upvote { return nil, 0, fmt.Errorf("already upvote") } info.Upvote = true return []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, 5)}, info.Uid, nil } func (f *FriendMod) GetReward(Id int) ([]*item.Item, error) { info, ok := f.Bubble[Id] if !ok { return nil, fmt.Errorf("bubble not exist") } reward := []*item.Item{} switch info.Type { case LOG_TYPE_HANDBOOK_UPVOTE: reward = append(reward, item.NewItem(item.ITEM_ENERGY_ID, 5)) case LOG_TYPE_PLAYROOM_UPVOTE: reward = append(reward, item.NewItem(item.ITEM_ENERGY_ID, 5)) case LOG_TYPE_TREASURE_HELP: reward = append(reward, info.ItemList...) default: return nil, fmt.Errorf("log type not support") } delete(f.Bubble, Id) return reward, nil } func (f *FriendMod) AddWishApply(Uid int64) error { for _, v := range f.Apply { if v.Type == APPLY_TYPE_WISH && v.Uid == Uid { return fmt.Errorf("wish apply already exist") } } f.Apply = append(f.Apply, &ApplyInfo{ Type: APPLY_TYPE_WISH, Uid: Uid, Time: GoUtil.Now(), }) return nil } func (f *FriendMod) GetWishApply() []*ApplyInfo { rs := []*ApplyInfo{} for _, v := range f.Apply { if v.Type == APPLY_TYPE_WISH { rs = append(rs, v) } } return rs } func (f *FriendMod) ApplyWish(Uid int64) error { for k, v := range f.Apply { if v.Type == APPLY_TYPE_WISH && v.Uid == Uid { r := make([]*ApplyInfo, len(f.Apply)-1) copy(r, f.Apply[:k]) f.Apply = append(r, f.Apply[k+1:]...) return nil } } return fmt.Errorf("wish apply not exist") } func (f *FriendMod) GetActLogLast() *ActLogInfo { if len(f.ActivityLog) == 0 { return nil } return f.ActivityLog[len(f.ActivityLog)-1] } func (f *FriendMod) AddReplyInfo(Uid int, Type int, Param string, EndTime int64, Items []*item.Item) *ReplyInfo { f.AutoId++ ReplyInfo := &ReplyInfo{ Id: f.AutoId, Uid: Uid, Type: Type, Param: Param, Status: 0, AddTime: GoUtil.Now(), EndTime: EndTime, Items: Items, } f.ReplyList = append(f.ReplyList, ReplyInfo) return ReplyInfo } func (f *FriendMod) ReplyFriend(LogId int) *ReplyInfo { for _, v := range f.ReplyList { if v.Id == LogId { v.Status = 1 v.ReplyTime = GoUtil.Now() return v } } return nil } func (f *FriendMod) GetSponsor() int { return f.DailySponsor } func (f *FriendMod) GetDailySponsorLimit() int { len := len(f.FriendList) if len < 5 { return 3 } if len <= 30 { return 2 } return 1 } func (f *FriendMod) GetSponsorReward() ([]*item.Item, error) { if f.DailySponsor <= 0 { return nil, fmt.Errorf("no sponsor left") } f.DailySponsor-- return []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, 25)}, nil }