pet_home_server/src/server/game/mod/friend/Friend.go
2025-11-12 15:46:52 +08:00

549 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package friend
import (
"fmt"
"server/GoUtil"
cardCfg "server/conf/card"
"server/game/mod/card"
"server/game/mod/item"
"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
}
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 // 收到问候
)
// 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) {
f.Npc = append(f.Npc, id)
}
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) {
f.AutoId++
EndTime := GoUtil.Now() + 24*3600
f.ReplyList = append(f.ReplyList, &ReplyInfo{
Id: f.AutoId,
Uid: Uid,
Type: Type,
Param: Param,
Status: 0,
AddTime: GoUtil.Now(),
EndTime: EndTime,
})
}
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
}