1061 lines
30 KiB
Go
1061 lines
30 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"mongo.games.com/goserver/core/basic"
|
|
"mongo.games.com/goserver/core/logger"
|
|
"mongo.games.com/goserver/core/module"
|
|
"mongo.games.com/goserver/core/task"
|
|
|
|
"mongo.games.com/game/common"
|
|
"mongo.games.com/game/model"
|
|
"mongo.games.com/game/proto"
|
|
"mongo.games.com/game/protocol/friend"
|
|
"mongo.games.com/game/worldsrv/internal"
|
|
)
|
|
|
|
// 列表类型
|
|
const (
|
|
ListTypeFriend int32 = iota // 0.好友列表
|
|
ListTypeApply // 1.申请列表
|
|
ListTypeRecommend // 2.推荐列表
|
|
)
|
|
|
|
// 好友操作
|
|
const (
|
|
OpTypeApply int32 = iota // 0.申请,申请添加好友
|
|
OpTypeAgree // 1.同意,同意添加好友
|
|
OpTypeRefuse // 2.拒绝,拒绝添加好友
|
|
OpTypeDelete // 3.删除,删除好友
|
|
)
|
|
|
|
// 是否同意邀请进入游戏
|
|
const (
|
|
InviteAgree int = iota // 0.同意
|
|
InviteRefuse // 1.拒绝
|
|
)
|
|
|
|
const FriendMaxNum = 200 // 好友最大数量
|
|
const ShieldMaxNum = 10000 // 最大屏蔽人数
|
|
const FriendApplyMaxNum = 1000 // 好友申请上限
|
|
const FriendWrite = "FriendWrite" // 好友数据修改线程名称
|
|
|
|
var FriendMgrSingleton = &FriendMgr{
|
|
FriendList: make(map[string]map[int32]*model.Friend),
|
|
TsInviteCd: make(map[string]map[string]int64),
|
|
}
|
|
|
|
type FriendMgr struct {
|
|
FriendList map[string]map[int32]*model.Friend // 平台id:snid:好友信息
|
|
TsInviteCd map[string]map[string]int64 // 平台id:邀请人id_被邀请人id:邀请cd时间
|
|
}
|
|
|
|
func (this *FriendMgr) ModuleName() string {
|
|
return "FriendMgr"
|
|
}
|
|
|
|
func (this *FriendMgr) Init() {
|
|
}
|
|
|
|
// Add 缓存玩家信息
|
|
func (this *FriendMgr) Add(platform string, snid int32) {
|
|
logger.Logger.Trace("(this *FriendMgr) Add ", snid)
|
|
if this.FriendList[platform] == nil {
|
|
this.FriendList[platform] = make(map[int32]*model.Friend)
|
|
}
|
|
if _, exist := this.FriendList[platform][snid]; !exist {
|
|
p := PlayerMgrSington.GetPlayerBySnId(snid)
|
|
if p != nil {
|
|
this.FriendList[platform][snid] = model.NewFriend(p.Platform, p.SnId)
|
|
this.UpdateInfo(p.Platform, p.SnId)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Del 删除玩家缓存
|
|
func (this *FriendMgr) Del(platform string, snid int32) {
|
|
if this.FriendList[platform] == nil {
|
|
return
|
|
}
|
|
if _, exist := this.FriendList[platform][snid]; exist {
|
|
delete(this.FriendList[platform], snid)
|
|
}
|
|
}
|
|
|
|
// CanInvite 是否可以邀请,邀请冷却
|
|
// snid 发起人
|
|
// fsnid 被邀请人
|
|
func (this *FriendMgr) CanInvite(platform string, snid, fsnid int32) bool {
|
|
if this.TsInviteCd[platform] == nil {
|
|
this.TsInviteCd[platform] = make(map[string]int64)
|
|
}
|
|
strSnid := strconv.FormatInt(int64(snid), 10) + "_" + strconv.FormatInt(int64(fsnid), 10)
|
|
if _, exist := this.TsInviteCd[platform][strSnid]; !exist {
|
|
this.TsInviteCd[platform][strSnid] = time.Now().Unix()
|
|
return true
|
|
}
|
|
if this.TsInviteCd[platform][strSnid] == 0 {
|
|
this.TsInviteCd[platform][strSnid] = time.Now().Unix()
|
|
return true
|
|
}
|
|
if time.Now().Unix()-this.TsInviteCd[platform][strSnid] > 30 {
|
|
this.TsInviteCd[platform][strSnid] = time.Now().Unix()
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// AgreeApply 同意好友申请
|
|
func (this *FriendMgr) AgreeApply(platform string, snid int32, bf *model.BindFriend) friend.OpResultCode {
|
|
logger.Logger.Trace("(this *FriendMgr) AgreeApply ", snid, " BindFriend: ", bf)
|
|
if bf == nil || bf.Platform != platform {
|
|
return friend.OpResultCode_OPRC_Friend_NoPlayer
|
|
}
|
|
if this.FriendList[platform] == nil {
|
|
this.FriendList[platform] = make(map[int32]*model.Friend)
|
|
}
|
|
|
|
// 是否为好友
|
|
if this.IsFriend(platform, snid, bf.SnId) {
|
|
return friend.OpResultCode_OPRC_Friend_AlreadyAdd
|
|
}
|
|
|
|
// 检查好友数量
|
|
dflDest := this.GetFriendList(platform, snid)
|
|
if dflDest != nil {
|
|
if len(dflDest) >= FriendMaxNum {
|
|
return friend.OpResultCode_OPRC_Friend_DestFriendMax
|
|
}
|
|
}
|
|
dfl := this.GetFriendList(platform, bf.SnId)
|
|
if dfl != nil {
|
|
if len(dfl) >= FriendMaxNum {
|
|
return friend.OpResultCode_OPRC_Friend_FriendMax
|
|
}
|
|
}
|
|
|
|
bf.CreateTime = time.Now().Unix()
|
|
this.FriendList[platform][snid].BindFriend = append(this.FriendList[platform][snid].BindFriend, bf)
|
|
this.FriendList[platform][snid].Dirty = true
|
|
return friend.OpResultCode_OPRC_Sucess
|
|
}
|
|
|
|
// RemoveFriend 删除好友
|
|
func (this *FriendMgr) RemoveFriend(platform string, snid, destSnid int32) bool {
|
|
logger.Logger.Trace("(this *FriendMgr) RemoveFriend ", snid, " destSnid: ", destSnid)
|
|
if this.FriendList[platform] == nil {
|
|
return false
|
|
}
|
|
if fl, exist := this.FriendList[platform][snid]; exist {
|
|
for i, f := range fl.BindFriend {
|
|
if f.SnId == destSnid {
|
|
fl.BindFriend = append(fl.BindFriend[:i], fl.BindFriend[i+1:]...)
|
|
fl.Dirty = true
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (this *FriendMgr) UpdateInfo(platform string, snid int32) {
|
|
logger.Logger.Trace("(this *FriendMgr) UpdateInfo ", snid)
|
|
if this.FriendList[platform] == nil {
|
|
return
|
|
}
|
|
|
|
p := PlayerMgrSington.GetPlayerBySnId(snid)
|
|
if p == nil {
|
|
return
|
|
}
|
|
|
|
info, ok := this.FriendList[platform][snid]
|
|
if !ok {
|
|
return
|
|
}
|
|
info.Name = p.Name
|
|
info.Head = p.Head
|
|
info.HeadUrl = p.HeadUrl
|
|
info.Sex = p.Sex
|
|
info.Coin = p.Coin
|
|
info.Diamond = p.Diamond
|
|
item := BagMgrSingleton.GetItem(p.SnId, common.ItemIDVCard)
|
|
if item != nil {
|
|
info.VCard = item.ItemNum
|
|
}
|
|
info.Roles = p.Roles.ModUnlock
|
|
info.Pets = p.Pets.ModUnlock
|
|
info.Age = p.Age
|
|
info.Signature = p.Signature
|
|
info.GameID = p.GameID
|
|
info.UpdateTime = time.Now().Unix()
|
|
info.Dirty = true
|
|
|
|
for _, v := range info.BindFriend {
|
|
if v == nil {
|
|
continue
|
|
}
|
|
in := this.FriendList[platform][v.SnId]
|
|
if in == nil {
|
|
continue
|
|
}
|
|
for _, vv := range in.BindFriend {
|
|
if vv != nil && vv.SnId == snid {
|
|
vv.Name = p.Name
|
|
vv.Head = p.Head
|
|
vv.HeadUrl = p.HeadUrl
|
|
vv.Sex = p.Sex
|
|
vv.LogoutTime = p.LastLogoutTime.Unix()
|
|
vv.RoleId = p.Roles.ModId
|
|
in.Dirty = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetPlayer 获取玩家信息
|
|
func (this *FriendMgr) GetPlayer(platform string, snid int32) *model.Friend {
|
|
if this.FriendList[platform] == nil {
|
|
return nil
|
|
}
|
|
if fi, exist := this.FriendList[platform][snid]; exist {
|
|
this.UpdateInfo(platform, snid)
|
|
return fi
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetFriendList 获取好友列表
|
|
func (this *FriendMgr) GetFriendList(platform string, snid int32) []*model.BindFriend {
|
|
var allFriend []*model.BindFriend
|
|
if this.FriendList[platform] == nil {
|
|
return nil
|
|
}
|
|
if f, exist := this.FriendList[platform][snid]; exist {
|
|
if f != nil && f.BindFriend != nil {
|
|
for _, bindFriend := range f.BindFriend {
|
|
allFriend = append(allFriend, bindFriend)
|
|
}
|
|
}
|
|
}
|
|
return allFriend
|
|
}
|
|
|
|
// IsFriend 是否好友关系
|
|
func (this *FriendMgr) IsFriend(platform string, snid, destSnid int32) bool {
|
|
logger.Logger.Trace("(this *FriendMgr) IsFriend ", snid, " -> ", destSnid)
|
|
dfl := this.GetFriendList(platform, snid)
|
|
if dfl != nil && len(dfl) != 0 {
|
|
for _, df := range dfl {
|
|
if df.SnId == destSnid {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ApplyList 查询好友申请列表
|
|
func (this *FriendMgr) ApplyList(platform string, snid int32) {
|
|
var err error
|
|
list := &model.ApplyList{}
|
|
ret := &model.FriendApply{}
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
ret, err = model.QueryFriendApplyBySnid(platform, snid)
|
|
if err != nil {
|
|
logger.Logger.Errorf("(this *FriendMgr) ApplyList QueryFriendApplyBySnid %v", err)
|
|
}
|
|
list, err = model.QueryFriendApplyListBySnid(platform, snid)
|
|
if err != nil {
|
|
logger.Logger.Errorf("(this *FriendMgr) ApplyList QueryFriendApplyListBySnid %v", err)
|
|
}
|
|
return ret
|
|
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
|
|
if ret != nil && ret.ApplySnids != nil {
|
|
pack := &friend.SCFriendApplyData{}
|
|
for _, as := range ret.ApplySnids {
|
|
p := PlayerMgrSington.GetPlayerBySnId(as.SnId)
|
|
if p != nil {
|
|
as.Name = p.Name
|
|
}
|
|
fa := &friend.FriendApply{
|
|
Snid: proto.Int32(as.SnId),
|
|
Name: proto.String(as.Name),
|
|
CreateTs: proto.Int64(as.CreateTs),
|
|
}
|
|
pack.FriendApplys = append(pack.FriendApplys, fa)
|
|
}
|
|
if len(pack.FriendApplys) > 0 {
|
|
proto.SetDefaults(pack)
|
|
p := PlayerMgrSington.GetPlayerBySnId(snid)
|
|
if p != nil {
|
|
p.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendApplyData), pack)
|
|
logger.Logger.Trace("SCFriendApplyData: 好友申请列表 pack: ", pack)
|
|
}
|
|
}
|
|
}
|
|
if list != nil && list.List != nil {
|
|
p := PlayerMgrSington.GetPlayerBySnId(snid)
|
|
if p != nil {
|
|
p.ApplyList = list.List
|
|
this.SendApplyList(p)
|
|
}
|
|
}
|
|
})).StartByFixExecutor("QueryFriendApplyBySnid")
|
|
}
|
|
|
|
// AddShield 屏蔽好友消息
|
|
// snid屏蔽ssnid的消息
|
|
func (this *FriendMgr) AddShield(platform string, snid, ssnid int32) {
|
|
if this.FriendList[platform] == nil {
|
|
return
|
|
}
|
|
if fl, exist := this.FriendList[platform][snid]; exist {
|
|
if fl.Shield == nil {
|
|
fl.Shield = []int32{}
|
|
}
|
|
if len(fl.Shield) > ShieldMaxNum {
|
|
return
|
|
}
|
|
fl.Shield = append(fl.Shield, ssnid)
|
|
fl.Dirty = true
|
|
}
|
|
}
|
|
|
|
// DelShield 解除消息屏蔽
|
|
func (this *FriendMgr) DelShield(platform string, snid, ssnid int32) {
|
|
if this.FriendList[platform] == nil {
|
|
return
|
|
}
|
|
if fl, exist := this.FriendList[platform][snid]; exist {
|
|
if fl.Shield == nil {
|
|
return
|
|
}
|
|
if len(fl.Shield) == 0 {
|
|
return
|
|
}
|
|
fl.Shield = common.DelSliceInt32(fl.Shield, ssnid)
|
|
fl.Dirty = true
|
|
}
|
|
}
|
|
|
|
// IsShield 是否屏蔽消息
|
|
// snid的玩屏蔽ssnid的消息
|
|
func (this *FriendMgr) IsShield(platform string, snid, ssnid int32) bool {
|
|
if this.FriendList[platform] == nil {
|
|
return false
|
|
}
|
|
if fl, exist := this.FriendList[platform][snid]; exist {
|
|
if fl.Shield == nil {
|
|
return false
|
|
}
|
|
if len(fl.Shield) == 0 {
|
|
return false
|
|
}
|
|
return common.InSliceInt32(fl.Shield, ssnid)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// UpdateLogoutTime 更新玩家下线时间
|
|
func (this *FriendMgr) UpdateLogoutTime(platform string, snid int32) {
|
|
if this.FriendList[platform] == nil {
|
|
return
|
|
}
|
|
if fl, exist := this.FriendList[platform][snid]; exist {
|
|
fl.LogoutTime = time.Now().Unix()
|
|
fl.Dirty = true
|
|
if fl.BindFriend != nil {
|
|
for _, bf := range fl.BindFriend {
|
|
if this.FriendList[bf.Platform] != nil {
|
|
if data, ok := this.FriendList[bf.Platform][bf.SnId]; ok {
|
|
if data.BindFriend != nil {
|
|
for _, bindFriend := range data.BindFriend {
|
|
if bindFriend.SnId == snid {
|
|
bindFriend.LogoutTime = time.Now().Unix()
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *FriendMgr) FriendOp(opcode int32, p *Player, destP *model.BindFriend) {
|
|
switch opcode {
|
|
case OpTypeApply:
|
|
logger.Logger.Trace("@Apply friend", p.SnId, " -> ", destP.SnId)
|
|
this.FriendApply(p, destP)
|
|
case OpTypeAgree:
|
|
logger.Logger.Trace("@AgreeApply friend", p.SnId, " -> ", destP.SnId)
|
|
this.FriendAgree(p, destP)
|
|
case OpTypeRefuse:
|
|
logger.Logger.Trace("@Refuse friend", p.SnId, " -> ", destP.SnId)
|
|
this.FriendRefuse(p, destP)
|
|
case OpTypeDelete:
|
|
logger.Logger.Trace("@Delete friend", p.SnId, " -> ", destP.SnId)
|
|
this.FriendDelete(p, destP)
|
|
}
|
|
}
|
|
|
|
// FriendApply 好友申请
|
|
// 记录在数据库
|
|
// p 发起方
|
|
// destP 接收方
|
|
func (this *FriendMgr) FriendApply(p *Player, destP *model.BindFriend) {
|
|
var applyList []int32
|
|
SendToClick := func(retCode friend.OpResultCode, self ...bool) {
|
|
pack := &friend.SCFriendOp{
|
|
OpCode: proto.Int32(OpTypeApply),
|
|
SnId: proto.Int32(destP.SnId),
|
|
OpRetCode: retCode,
|
|
}
|
|
if len(self) == 0 {
|
|
p.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
if applyList != nil {
|
|
p.ApplyList = applyList
|
|
this.SendApplyList(p)
|
|
}
|
|
} else {
|
|
destPs := PlayerMgrSington.GetPlayerBySnId(destP.SnId)
|
|
if destPs != nil && destPs.IsOnLine() {
|
|
roleId := common.DefaultRoleId
|
|
if p.Roles != nil {
|
|
roleId = int(p.Roles.ModId)
|
|
}
|
|
pack.Friend = &friend.FriendInfo{
|
|
SnId: proto.Int32(p.SnId),
|
|
Name: proto.String(p.Name),
|
|
Sex: proto.Int32(p.Sex),
|
|
Head: proto.Int32(p.Head),
|
|
HeadUrl: proto.String(p.HeadUrl),
|
|
CreateTs: proto.Int64(time.Now().Unix()),
|
|
LogoutTs: proto.Int64(p.LastLogoutTime.Unix()),
|
|
RoleId: int32(roleId),
|
|
}
|
|
destPs.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
}
|
|
}
|
|
logger.Logger.Tracef(">>FriendApply %d -> %d, %v", p.SnId, destP.SnId, pack)
|
|
}
|
|
if FriendMgrSingleton.IsFriend(p.Platform, p.SnId, destP.SnId) {
|
|
SendToClick(friend.OpResultCode_OPRC_Friend_AlreadyAdd)
|
|
return
|
|
}
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
ret, err := model.QueryFriendApplyBySnid(p.Platform, destP.SnId)
|
|
if err != nil {
|
|
return friend.OpResultCode_OPRC_Error
|
|
}
|
|
if ret != nil {
|
|
//在申请列表
|
|
if ret.ApplySnids != nil {
|
|
if len(ret.ApplySnids) > FriendApplyMaxNum {
|
|
return friend.OpResultCode_OPRC_Friend_DestApplyFriendMax //对方好友申请已达上限
|
|
}
|
|
for _, as := range ret.ApplySnids {
|
|
if as.SnId == p.SnId {
|
|
return friend.OpResultCode_OPRC_Friend_AlreadyApply //已经申请过好友
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
//不在申请列表 新增
|
|
ret = model.NewFriendApply(destP.SnId)
|
|
}
|
|
roleId := common.DefaultRoleId
|
|
if p.Roles != nil {
|
|
roleId = int(p.Roles.ModId)
|
|
}
|
|
ret.ApplySnids = append(ret.ApplySnids, &model.FriendApplySnid{
|
|
SnId: p.SnId,
|
|
Name: p.Name,
|
|
Head: p.Head,
|
|
HeadUrl: p.HeadUrl,
|
|
CreateTs: time.Now().Unix(),
|
|
RoleId: int32(roleId),
|
|
})
|
|
model.UpsertFriendApply(p.Platform, destP.SnId, ret)
|
|
|
|
data, err := model.QueryFriendApplyListBySnid(p.Platform, p.SnId)
|
|
if err != nil {
|
|
logger.Logger.Errorf("QueryFriendApplyListBySnid err:%v", err)
|
|
} else {
|
|
if data == nil {
|
|
data = model.NewApplyList(p.SnId)
|
|
}
|
|
if !common.InSliceInt32(data.List, destP.SnId) {
|
|
data.List = append(data.List, destP.SnId)
|
|
model.UpsertApplyList(p.Platform, data)
|
|
applyList = data.List
|
|
}
|
|
}
|
|
|
|
return friend.OpResultCode_OPRC_Sucess
|
|
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess, false) // 对方
|
|
SendToClick(data.(friend.OpResultCode)) // 自己
|
|
})).StartByFixExecutor(FriendWrite)
|
|
}
|
|
|
|
// FriendAgree 同意好友申请
|
|
// p 同意者
|
|
// destP 申请者
|
|
func (this *FriendMgr) FriendAgree(p *Player, destP *model.BindFriend) {
|
|
var applyList, meApplyList []int32
|
|
SendToClick := func(retCode friend.OpResultCode, self ...bool) {
|
|
pack := &friend.SCFriendOp{
|
|
OpCode: proto.Int32(OpTypeAgree),
|
|
SnId: proto.Int32(destP.SnId),
|
|
OpRetCode: retCode,
|
|
}
|
|
if len(self) == 0 {
|
|
roleId := common.DefaultRoleId
|
|
if destP.RoleId != 0 {
|
|
roleId = int(destP.RoleId)
|
|
}
|
|
pack.Friend = &friend.FriendInfo{
|
|
SnId: proto.Int32(destP.SnId),
|
|
Name: proto.String(destP.Name),
|
|
Sex: proto.Int32(destP.Sex),
|
|
Head: proto.Int32(destP.Head),
|
|
HeadUrl: proto.String(destP.HeadUrl),
|
|
CreateTs: proto.Int64(time.Now().Unix()),
|
|
LogoutTs: proto.Int64(destP.LogoutTime),
|
|
RoleId: int32(roleId),
|
|
}
|
|
p.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
if meApplyList != nil {
|
|
p.ApplyList = meApplyList
|
|
this.SendApplyList(p)
|
|
}
|
|
} else {
|
|
destPs := PlayerMgrSington.GetPlayerBySnId(destP.SnId)
|
|
if destPs != nil && destPs.IsOnLine() {
|
|
roleId := common.DefaultRoleId
|
|
if p.Roles != nil {
|
|
roleId = int(p.Roles.ModId)
|
|
}
|
|
pack.Friend = &friend.FriendInfo{
|
|
SnId: proto.Int32(p.SnId),
|
|
Name: proto.String(p.Name),
|
|
Sex: proto.Int32(p.Sex),
|
|
Head: proto.Int32(p.Head),
|
|
HeadUrl: proto.String(p.HeadUrl),
|
|
CreateTs: proto.Int64(time.Now().Unix()),
|
|
LogoutTs: proto.Int64(p.LastLogoutTime.Unix()),
|
|
RoleId: int32(roleId),
|
|
}
|
|
destPs.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
if applyList != nil {
|
|
destPs.ApplyList = applyList
|
|
this.SendApplyList(destPs)
|
|
}
|
|
}
|
|
}
|
|
logger.Logger.Tracef(">>FriendAgree %d -> %d, %v", p.SnId, destP.SnId, pack)
|
|
}
|
|
me := FriendMgrSingleton.GetPlayer(p.Platform, p.SnId)
|
|
if me == nil {
|
|
SendToClick(friend.OpResultCode_OPRC_Error)
|
|
return
|
|
}
|
|
if FriendMgrSingleton.IsFriend(p.Platform, p.SnId, destP.SnId) { //已经是好友了
|
|
SendToClick(friend.OpResultCode_OPRC_Friend_AlreadyAdd)
|
|
return
|
|
}
|
|
//验证自己
|
|
if len(me.BindFriend) >= FriendMaxNum {
|
|
SendToClick(friend.OpResultCode_OPRC_Friend_FriendMax)
|
|
return
|
|
}
|
|
|
|
destPFriend := FriendMgrSingleton.GetPlayer(destP.Platform, destP.SnId)
|
|
if destPFriend != nil {
|
|
if len(destPFriend.BindFriend) >= FriendMaxNum {
|
|
SendToClick(friend.OpResultCode_OPRC_Friend_DestFriendMax)
|
|
return
|
|
}
|
|
}
|
|
|
|
var friendDB *model.Friend // 申请者好友列表
|
|
var err error
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
if destPFriend == nil {
|
|
// 不在线
|
|
friendDB, err = model.QueryFriendBySnid(destP.Platform, destP.SnId)
|
|
if err != nil {
|
|
logger.Logger.Error("QueryFriendBySnid:", err, destP.SnId)
|
|
return friend.OpResultCode_OPRC_Error
|
|
}
|
|
if friendDB == nil || friendDB.SnId != destP.SnId {
|
|
friendDB = model.NewFriend(destP.Platform, destP.SnId)
|
|
}
|
|
|
|
if len(friendDB.BindFriend) >= FriendMaxNum {
|
|
return friend.OpResultCode_OPRC_Friend_FriendMax
|
|
}
|
|
|
|
for _, v := range friendDB.BindFriend {
|
|
if v.SnId == p.SnId {
|
|
return friend.OpResultCode_OPRC_Friend_AlreadyAdd
|
|
}
|
|
}
|
|
}
|
|
|
|
// 删除申请者的申请列表
|
|
delApplyListFunc := func(plt string, snid int32, applySnid int32) friend.OpResultCode {
|
|
// 删除被申请者的申请列表
|
|
list1, err := model.QueryFriendApplyBySnid(plt, snid)
|
|
if err != nil {
|
|
logger.Logger.Errorf("QueryFriendApplyBySnid %v error: %v", snid, err)
|
|
return friend.OpResultCode_OPRC_Error
|
|
}
|
|
if list1 != nil {
|
|
k := 0
|
|
for k < len(list1.ApplySnids) {
|
|
if list1.ApplySnids[k].SnId == applySnid {
|
|
list1.ApplySnids = append(list1.ApplySnids[:k], list1.ApplySnids[k+1:]...)
|
|
model.UpsertFriendApply(plt, snid, list1)
|
|
} else {
|
|
k++
|
|
}
|
|
}
|
|
}
|
|
// 删除发起方的申请列表
|
|
list2, err := model.QueryFriendApplyListBySnid(plt, applySnid)
|
|
if err != nil {
|
|
logger.Logger.Errorf("QueryFriendApplyListBySnid %v error: %v", applySnid, err)
|
|
return friend.OpResultCode_OPRC_Error
|
|
}
|
|
if list2 != nil {
|
|
k := 0
|
|
for k < len(list2.List) {
|
|
if list2.List[k] == snid {
|
|
list2.List = append(list2.List[:k], list2.List[k+1:]...)
|
|
model.UpsertApplyList(plt, list2)
|
|
} else {
|
|
k++
|
|
}
|
|
}
|
|
}
|
|
|
|
if applySnid == destP.SnId && list2 != nil {
|
|
applyList = list2.List
|
|
}
|
|
|
|
if applySnid == p.SnId && list2 != nil {
|
|
meApplyList = list2.List
|
|
}
|
|
|
|
return friend.OpResultCode_OPRC_Sucess
|
|
}
|
|
|
|
//查看是否在申请列表
|
|
code := delApplyListFunc(p.Platform, p.SnId, destP.SnId)
|
|
if code != friend.OpResultCode_OPRC_Sucess {
|
|
return code
|
|
}
|
|
code = delApplyListFunc(p.Platform, destP.SnId, p.SnId)
|
|
if code != friend.OpResultCode_OPRC_Sucess {
|
|
return code
|
|
}
|
|
// 保存好友关系
|
|
if friendDB != nil {
|
|
friendDB.BindFriend = append(friendDB.BindFriend, &model.BindFriend{
|
|
SnId: p.SnId,
|
|
CreateTime: time.Now().Unix(),
|
|
})
|
|
model.UpsertFriend(friendDB)
|
|
}
|
|
|
|
return nil
|
|
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
|
|
if data != nil {
|
|
logger.Logger.Error("FriendAgree data:", data)
|
|
SendToClick(data.(friend.OpResultCode))
|
|
return
|
|
}
|
|
|
|
//同意者加入到被同意者好友里
|
|
if destPlayer := FriendMgrSingleton.GetPlayer(destP.Platform, destP.SnId); destPlayer != nil {
|
|
roleId := common.DefaultRoleId
|
|
if p.Roles != nil {
|
|
roleId = int(p.Roles.ModId)
|
|
}
|
|
result := FriendMgrSingleton.AgreeApply(destP.Platform, destP.SnId, &model.BindFriend{
|
|
SnId: p.SnId,
|
|
CreateTime: time.Now().Unix(),
|
|
Platform: p.Platform,
|
|
Name: p.Name,
|
|
Head: p.Head,
|
|
HeadUrl: p.HeadUrl,
|
|
Sex: p.Sex,
|
|
LogoutTime: p.LastLogoutTime.Unix(),
|
|
RoleId: int32(roleId),
|
|
})
|
|
if result != friend.OpResultCode_OPRC_Sucess && result != friend.OpResultCode_OPRC_Friend_AlreadyAdd {
|
|
logger.Logger.Warn("AgreeApply error: ", result)
|
|
SendToClick(result)
|
|
return
|
|
}
|
|
}
|
|
|
|
// 被同意者加入到同意者好友里
|
|
result := FriendMgrSingleton.AgreeApply(p.Platform, p.SnId, destP)
|
|
if result != friend.OpResultCode_OPRC_Sucess {
|
|
SendToClick(result, false)
|
|
SendToClick(result)
|
|
return
|
|
}
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess, false)
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess)
|
|
})).StartByFixExecutor(FriendWrite)
|
|
}
|
|
|
|
func (this *FriendMgr) FriendRefuse(p *Player, destP *model.BindFriend) {
|
|
var applyList []int32
|
|
SendToClick := func(retCode friend.OpResultCode, self ...bool) {
|
|
pack := &friend.SCFriendOp{
|
|
OpCode: proto.Int32(OpTypeRefuse),
|
|
SnId: proto.Int32(destP.SnId),
|
|
OpRetCode: retCode,
|
|
}
|
|
if len(self) == 0 {
|
|
p.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
} else {
|
|
destPs := PlayerMgrSington.GetPlayerBySnId(destP.SnId)
|
|
if destPs != nil && destPs.IsOnLine() {
|
|
destPs.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
}
|
|
}
|
|
logger.Logger.Tracef(">>FriendRefuse %d -> %d, %v", p.SnId, destP.SnId, pack)
|
|
}
|
|
if FriendMgrSingleton.IsFriend(p.Platform, p.SnId, destP.SnId) {
|
|
SendToClick(friend.OpResultCode_OPRC_Friend_AlreadyAdd)
|
|
return
|
|
}
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
ret, _ := model.QueryFriendApplyBySnid(p.Platform, p.SnId)
|
|
if ret != nil {
|
|
if ret.ApplySnids != nil {
|
|
for i, as := range ret.ApplySnids {
|
|
if as.SnId == destP.SnId {
|
|
ret.ApplySnids = append(ret.ApplySnids[:i], ret.ApplySnids[i+1:]...)
|
|
model.UpsertFriendApply(p.Platform, p.SnId, ret)
|
|
|
|
data, err := model.QueryFriendApplyListBySnid(p.Platform, destP.SnId)
|
|
if err != nil {
|
|
logger.Logger.Errorf("QueryFriendApplyListBySnid err:%v", err)
|
|
} else {
|
|
if data == nil {
|
|
data = model.NewApplyList(destP.SnId)
|
|
}
|
|
for k, v := range data.List {
|
|
if v == p.SnId {
|
|
data.List = append(data.List[:k], data.List[k+1:]...)
|
|
model.UpsertApplyList(p.Platform, data)
|
|
applyList = data.List
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return errors.New("not in apply")
|
|
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
|
|
//拒绝了不提醒
|
|
if data != nil {
|
|
logger.Logger.Error("FriendRefuse data:", data)
|
|
SendToClick(friend.OpResultCode_OPRC_Error)
|
|
return
|
|
}
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess)
|
|
|
|
// 刷新发起者的申请好友列表
|
|
destPs := PlayerMgrSington.GetPlayerBySnId(destP.SnId)
|
|
if destPs != nil && destPs.IsOnLine() {
|
|
if applyList != nil {
|
|
destPs.ApplyList = applyList
|
|
this.SendApplyList(destPs)
|
|
}
|
|
}
|
|
})).StartByFixExecutor(FriendWrite)
|
|
}
|
|
|
|
func (this *FriendMgr) FriendDelete(p *Player, destP *model.BindFriend) {
|
|
SendToClick := func(retCode friend.OpResultCode, self ...bool) {
|
|
pack := &friend.SCFriendOp{
|
|
OpCode: proto.Int32(OpTypeDelete),
|
|
SnId: proto.Int32(destP.SnId),
|
|
OpRetCode: retCode,
|
|
}
|
|
if len(self) == 0 {
|
|
pack.SnId = destP.SnId
|
|
p.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
logger.Logger.Tracef(">>FriendDelete %d -> %d, %v", p.SnId, destP.SnId, pack)
|
|
} else {
|
|
destPs := PlayerMgrSington.GetPlayerBySnId(destP.SnId)
|
|
if destPs != nil && destPs.IsOnLine() {
|
|
pack.SnId = p.SnId
|
|
destPs.SendToClient(int(friend.FriendPacketID_PACKET_SCFriendOp), pack)
|
|
logger.Logger.Tracef(">>FriendDelete dest %d -> %d, %v", p.SnId, destP.SnId, pack)
|
|
}
|
|
}
|
|
}
|
|
f := FriendMgrSingleton.GetPlayer(p.Platform, destP.SnId)
|
|
if f != nil {
|
|
//发起者删除被删除者
|
|
isok1 := FriendMgrSingleton.RemoveFriend(p.Platform, p.SnId, f.SnId)
|
|
if !isok1 {
|
|
logger.Logger.Warn("RemoveFriend error: ", p.SnId, " del friend:", f.SnId)
|
|
SendToClick(friend.OpResultCode_OPRC_Error)
|
|
return
|
|
}
|
|
//被删除者删除发起者
|
|
isok2 := FriendMgrSingleton.RemoveFriend(f.Platform, f.SnId, p.SnId)
|
|
if !isok2 {
|
|
logger.Logger.Warn("RemoveFriend error: ", f.SnId, " del friend:", p.SnId)
|
|
//删除失败不用通知
|
|
} else {
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess, false)
|
|
}
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess)
|
|
ChatMgrSington.DelChat(p.Platform, p.SnId, f.SnId)
|
|
} else {
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
ret, _ := model.QueryFriendBySnid(p.Platform, destP.SnId)
|
|
if ret != nil {
|
|
//被删除者删除发起者
|
|
if ret.BindFriend != nil {
|
|
for i, bindFriend := range ret.BindFriend {
|
|
if bindFriend.SnId == p.SnId {
|
|
ret.BindFriend = append(ret.BindFriend[:i], ret.BindFriend[i+1:]...)
|
|
model.UpsertFriend(ret)
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess, false)
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return errors.New("not in apply")
|
|
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
|
|
if data != nil {
|
|
logger.Logger.Error("FriendDelete data:", data)
|
|
SendToClick(friend.OpResultCode_OPRC_Error)
|
|
return
|
|
} else {
|
|
//发起者删除被删除者
|
|
isok1 := FriendMgrSingleton.RemoveFriend(p.Platform, p.SnId, destP.SnId)
|
|
if !isok1 {
|
|
logger.Logger.Warn("RemoveFriend error: ", p.SnId, " del friend:", destP.SnId)
|
|
//SendToClick(friend.OpResultCode_OPRC_Error)
|
|
//return
|
|
}
|
|
SendToClick(friend.OpResultCode_OPRC_Sucess)
|
|
}
|
|
ChatMgrSington.DelChat(p.Platform, p.SnId, destP.SnId)
|
|
})).StartByFixExecutor(FriendWrite)
|
|
}
|
|
}
|
|
|
|
func (this *FriendMgr) Update() {
|
|
}
|
|
|
|
func (this *FriendMgr) Shutdown() {
|
|
module.UnregisteModule(this)
|
|
}
|
|
|
|
func (this *FriendMgr) UpdateName(snId int32, name string) {
|
|
p := PlayerMgrSington.GetPlayerBySnId(snId)
|
|
if p != nil {
|
|
this.UpdateInfo(p.Platform, p.SnId)
|
|
}
|
|
}
|
|
|
|
func (this *FriendMgr) UpdateHead(snId, head int32) {
|
|
p := PlayerMgrSington.GetPlayerBySnId(snId)
|
|
if p != nil {
|
|
this.UpdateInfo(p.Platform, p.SnId)
|
|
}
|
|
}
|
|
|
|
func (this *FriendMgr) SendApplyList(p *Player) {
|
|
pack := &friend.SCRequestAddFriend{}
|
|
for _, v := range p.ApplyList {
|
|
pack.RequestAddFriend = append(pack.RequestAddFriend, v)
|
|
}
|
|
p.SendToClient(int(friend.FriendPacketID_PACKET_SCRequestAddFriend), pack)
|
|
logger.Logger.Tracef("SCRequestAddFriend:%v %v", pack, p.SnId)
|
|
}
|
|
|
|
//========================implement IPlayerLoad ==============================
|
|
|
|
func (this *FriendMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay {
|
|
return nil
|
|
}
|
|
|
|
func (this *FriendMgr) Callback(player any, ret *internal.PlayerLoadReplay) {
|
|
}
|
|
|
|
func (this *FriendMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay {
|
|
ret := &internal.PlayerLoadReplay{
|
|
Platform: platform,
|
|
Snid: snid,
|
|
}
|
|
|
|
// 查询好友列表
|
|
friendDB, err := model.QueryFriendBySnid(platform, snid)
|
|
if err != nil {
|
|
logger.Logger.Error("QueryFriendBySnid:", err, snid)
|
|
ret.Err = err
|
|
return ret
|
|
}
|
|
|
|
if friendDB == nil {
|
|
return ret
|
|
}
|
|
|
|
// 查询好友信息
|
|
var offSnID []int32
|
|
for _, v := range friendDB.BindFriend {
|
|
roleId := common.DefaultRoleId
|
|
if v.RoleId != 0 {
|
|
roleId = int(v.RoleId)
|
|
}
|
|
p := PlayerMgrSington.GetPlayerBySnId(v.SnId)
|
|
if p != nil {
|
|
v.Platform = p.Platform
|
|
v.Name = p.Name
|
|
v.Head = p.Head
|
|
v.HeadUrl = p.HeadUrl
|
|
v.Sex = p.Sex
|
|
if !p.IsOnLine() {
|
|
v.LogoutTime = p.LastLogoutTime.Unix()
|
|
}
|
|
v.RoleId = int32(roleId)
|
|
} else {
|
|
offSnID = append(offSnID, v.SnId)
|
|
}
|
|
}
|
|
|
|
if len(offSnID) > 0 {
|
|
offFriends, err := model.QueryFriendsBySnids(platform, offSnID)
|
|
if err != nil {
|
|
logger.Logger.Error("QueryFriendsBySnids is err:", err)
|
|
ret.Err = err
|
|
return ret
|
|
}
|
|
for _, offFriend := range offFriends {
|
|
for _, v := range friendDB.BindFriend {
|
|
roleId := common.DefaultRoleId
|
|
if v.RoleId != 0 {
|
|
roleId = int(v.RoleId)
|
|
}
|
|
if v.SnId == offFriend.SnId {
|
|
v.Platform = offFriend.Platform
|
|
v.Name = offFriend.Name
|
|
v.Head = offFriend.Head
|
|
v.HeadUrl = offFriend.HeadUrl
|
|
v.Sex = offFriend.Sex
|
|
v.LogoutTime = offFriend.LogoutTime
|
|
v.RoleId = int32(roleId)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ret.Data = friendDB
|
|
|
|
return ret
|
|
}
|
|
|
|
func (this *FriendMgr) CallbackAfter(ret *internal.PlayerLoadReplay) {
|
|
if ret == nil || ret.Platform == "" || ret.Snid <= 0 {
|
|
return
|
|
}
|
|
|
|
if ret.Err != nil {
|
|
logger.Logger.Error("(this *FriendMgr) CallbackAfter err:", ret.Err)
|
|
return
|
|
}
|
|
if ret.Data == nil {
|
|
this.Add(ret.Platform, ret.Snid)
|
|
logger.Logger.Infof("(this *FriendMgr) LoadFriendData New: %+v", *this.GetPlayer(ret.Platform, ret.Snid))
|
|
return
|
|
}
|
|
|
|
data, ok := ret.Data.(*model.Friend)
|
|
if !ok {
|
|
logger.Logger.Error("bug")
|
|
return
|
|
}
|
|
|
|
if this.FriendList[ret.Platform] == nil {
|
|
this.FriendList[ret.Platform] = make(map[int32]*model.Friend)
|
|
}
|
|
|
|
this.FriendList[ret.Platform][ret.Snid] = data
|
|
logger.Logger.Infof("(this *FriendMgr) LoadFriendData db: %+v", *data)
|
|
p := PlayerMgrSington.GetPlayerBySnId(ret.Snid)
|
|
if p != nil {
|
|
this.UpdateInfo(ret.Platform, ret.Snid)
|
|
}
|
|
FriendUnreadMgrSington.LoadFriendUnreadData(ret.Platform, ret.Snid)
|
|
this.ApplyList(ret.Platform, ret.Snid)
|
|
}
|
|
|
|
func (this *FriendMgr) Save(platform string, snid int32, isSync, force bool) {
|
|
logger.Logger.Trace("(this *FriendMgr) SaveFriendData ", snid)
|
|
ret := this.GetPlayer(platform, snid)
|
|
if ret == nil || (!ret.Dirty && !force) {
|
|
return
|
|
}
|
|
|
|
var res bool
|
|
f := func() {
|
|
res = model.UpsertFriend(ret) != nil
|
|
}
|
|
cf := func() {
|
|
if res {
|
|
ret.Dirty = false
|
|
}
|
|
}
|
|
|
|
if isSync {
|
|
f()
|
|
cf()
|
|
return
|
|
}
|
|
|
|
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
|
f()
|
|
return nil
|
|
}), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
|
|
cf()
|
|
})).StartByFixExecutor(fmt.Sprintf("player%v", ret.SnId))
|
|
}
|
|
|
|
func (this *FriendMgr) Release(platform string, snid int32) {
|
|
this.Del(platform, snid)
|
|
}
|
|
|
|
func init() {
|
|
module.RegisteModule(FriendMgrSingleton, time.Hour, 0)
|
|
internal.RegisterPlayerLoad(FriendMgrSingleton)
|
|
}
|