game_sync/worldsrv/friendmgr.go

1017 lines
28 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 (
ListType_Friend int32 = iota // 0.好友列表
ListType_Apply // 1.申请列表
ListType_Recommend // 2.推荐列表
)
const (
OpType_Apply int32 = iota // 0.申请
OpType_Agree // 1.同意
OpType_Refuse // 2.拒绝
OpType_Delete // 3.删除
)
const (
Invite_Agree int = iota // 0.同意
Invite_Refuse // 1.拒绝
)
const FriendMaxNum = 200
const ShieldMaxNum = 10000
const FriendApplyMaxNum = 1000 //好友申请上限
const FriendWrite = "FriendWrite"
var FriendMgrSington = &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:snid:邀请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 是否可以邀请,邀请冷却
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, VCard)
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 {
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 屏蔽好友消息
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 OpType_Apply:
logger.Logger.Trace("@Apply friend", p.SnId, " -> ", destP.SnId)
this.FriendApply(p, destP)
case OpType_Agree:
logger.Logger.Trace("@AgreeApply friend", p.SnId, " -> ", destP.SnId)
this.FriendAgree(p, destP)
case OpType_Refuse:
logger.Logger.Trace("@Refuse friend", p.SnId, " -> ", destP.SnId)
this.FriendRefuse(p, destP)
case OpType_Delete:
logger.Logger.Trace("@Delete friend", p.SnId, " -> ", destP.SnId)
this.FriendDelete(p, destP)
}
}
// FriendApply 好友申请
// 记录在数据库
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(OpType_Apply),
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 FriendMgrSington.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 同意好友申请
func (this *FriendMgr) FriendAgree(p *Player, destP *model.BindFriend) {
var applyList []int32
SendToClick := func(retCode friend.OpResultCode, self ...bool) {
pack := &friend.SCFriendOp{
OpCode: proto.Int32(OpType_Agree),
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)
} 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 := FriendMgrSington.GetPlayer(p.Platform, p.SnId)
if me == nil {
SendToClick(friend.OpResultCode_OPRC_Error)
return
}
if FriendMgrSington.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 := FriendMgrSington.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
}
}
}
ret, err := model.QueryFriendApplyBySnid(p.Platform, p.SnId)
if err != nil {
return friend.OpResultCode_OPRC_Error
}
//查看是否在申请列表
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
}
}
}
// 保存好友关系
if friendDB != nil {
friendDB.BindFriend = append(friendDB.BindFriend, &model.BindFriend{
SnId: p.SnId,
CreateTime: time.Now().Unix(),
})
model.UpsertFriend(friendDB)
}
return nil
}
}
}
}
return friend.OpResultCode_OPRC_Error
}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
if data != nil {
logger.Logger.Error("FriendAgree data:", data)
SendToClick(data.(friend.OpResultCode))
return
}
//同意者加入到被同意者好友里
if destPlayer := FriendMgrSington.GetPlayer(destP.Platform, destP.SnId); destPlayer != nil {
roleId := common.DefaultRoleId
if p.Roles != nil {
roleId = int(p.Roles.ModId)
}
result := FriendMgrSington.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 := FriendMgrSington.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(OpType_Refuse),
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 FriendMgrSington.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(OpType_Delete),
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 := FriendMgrSington.GetPlayer(p.Platform, destP.SnId)
if f != nil {
//发起者删除被删除者
isok1 := FriendMgrSington.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 := FriendMgrSington.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 := FriendMgrSington.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(FriendMgrSington, time.Hour, 0)
internal.RegisterPlayerLoad(FriendMgrSington)
}