local skynet = require "skynet" local oo = require "Class" local pb = require "pb" local log = require "Log" local errorInfo = require "ErrorInfo" local dataType = require "DataType" local redisKeyUrl = require "RedisKeyUrl" local sqlUrl = require "SqlUrl" local json = require "json" local serverId = tonumber(skynet.getenv "serverId") local Partner = oo.class() Partner.QueryType_ID = 1 --玩家ID查询 Partner.QueryType_NickName = 2 --玩家昵称查询 Partner.MaxQueryCount = 4 --最大查询数量 Partner.MaxResetQueryTime = 300 --最大还原查询时间 Partner.MsgType_Text = 1 --文本消息 Partner.MsgType_Gift = 2 --礼物 Partner.MsgType_InviteDoubleSpace = 3 --双人空间邀请 --双人空间购买房间邀请 Partner.MsgType_InviteDoubleSpaceBuyHouse = 4 --双人空间购买装修方案邀请 Partner.MsgType_InviteDoubleSpaceBuyHouseScheme = 5 --双人空间代购房间通知 Partner.MsgType_InviteDoubleSpaceBuyHouseNotice = 6 --双人空间代购装修方案通知 Partner.MsgType_InviteDoubleSpaceBuyHouseSchemeNotice = 7 Partner.MaxMsgRecordToClient = 50 --发送给客户端最大的消息记录数量 Partner.MaxMsgRecord = 2000 --好友消息记录最大数量 Partner.MaxFriendCount = 30 --最大好友数量 Partner.HouseDetailMaxOutTime = 3600 --好友房子过期时间 Partner.MaxGetOnlineCount = 200 --最大获取在线用户数量 Partner.RefreshOnlineInterval = 120 --刷新在线用户间隔 --邀请状态 Partner.InviteStatus_Inviting = 1 --正在邀请中 Partner.InviteStatus_Agree = 2 --已同意邀请 Partner.InviteStatus_Refuse = 3 --已拒绝邀请 Partner.InviteStatus_OutOfTime = 4 --已过期 function Partner:Init() self.onlineUserList = {} --在线用户列表 skynet.server.timer:Add( dataType.Timer_SyncOnlineUser , self.RefreshOnlineInterval , self["SyncOnlineList"] , self ) end --好友列表 function Partner:MyList( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerMyList", c2sData.data )) local data = {} data.infos = self:GetFriendList( player ) skynet.server.msgTips:ReduceAll( player , 53 ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerMyList") s2cData.data = assert(pb.encode("S2CPartnerMyList", data)) end --获取好友列表 function Partner:GetFriendList( player ) local data = {} local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local myPlayerId = player.gameData.partner.id local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) local friendList = skynet.server.redis:zrange( redisKey , 0 , -1 ) --检查下我有不有新的朋友 local myDetail = skynet.server.personal:GetDetail( myPlayerId ) if not myDetail then return data end if myDetail.newFriendCount and myDetail.newFriendCount > 0 then --有条件才触发任务 skynet.server.levelTask:Modify( player , 73 , myDetail.newFriendCount ) skynet.server.taskListEvent:Modify( player , 73 , myDetail.newFriendCount ) skynet.server.personal:SetDetail( myPlayerId ,"newFriendCount", 0) end --遍历好友列表 for k, otherPartnerId in pairs( friendList ) do local curDetail = skynet.server.personal:GetDetail( otherPartnerId ) if curDetail then --获取我和该玩家的未读消息数量 local redisKey = string.format( redisKeyUrl.GameServerPartnerUnreadMsgIndexZSet , myPlayerId ) local minIndex = tonumber(skynet.server.redis:zscore( redisKey , otherPartnerId )) if not minIndex then skynet.server.redis:zadd( redisKey , 0 , otherPartnerId) end --最新消息数量 redisKey = self:GetMsgKey( myPlayerId , otherPartnerId ) local msgList = skynet.server.redis:zrangebyscore( redisKey , (minIndex or 0 ) + 1 , "+inf" ) local count = 0 for i = 1, #msgList, 1 do local tmp = json:decode(msgList[i]) if myPlayerId ~= tmp.sendPartnerId and tmp.isShowMsg then count = count + 1 end end curDetail.unReadCount = count --是否与好友是双人空间 local myInfoKey = skynet.server.doubleSpace:GetMyInfoKey( myPlayerId , otherPartnerId ) if skynet.server.redis:exists( myInfoKey ) then curDetail.isDoubleSpace = true skynet.server.levelTask:Modify( player , 74 , 1 ) skynet.server.taskListEvent:Modify( player , 74 , 1 ) else curDetail.isDoubleSpace = false end --检查下好友的数量达到没有 local doubleSpaceCount = tonumber(curDetail.doubleSpaceCount) or 0 if doubleSpaceCount >= cfgSValue.coupleHouseLimit then curDetail.isInviteDoubleBtn = false else curDetail.isInviteDoubleBtn = true end --是否离线 if not curDetail.isOnline then curDetail.offlineTime=curDetail.updateTime end table.insert( data , curDetail ) end end return data end --好友推荐 function Partner:Recommend( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerRecommend", c2sData.data )) local data = {} data.querys = {} local myPlayerId = player.gameData.partner.id local tmpPartner = player.tmpData.partner local firstQuery = true --第一次查询 --把我的好友先添加进去 local function AddMyFriend() tmpPartner.alreadyQueryUser = {} table.insert( tmpPartner.alreadyQueryUser , myPlayerId) --自己加进去 local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) local friendList = skynet.server.redis:zrange( redisKey , 0 , -1 ) for k, v in pairs( friendList ) do table.insert( tmpPartner.alreadyQueryUser , v) --我的好友加进去 end end --是否存在好友 local function IsExistFriend( partnerId ) for k, v in pairs( tmpPartner.alreadyQueryUser ) do if partnerId == v then return true end end return false end --查询在线用户 local function QuerynlineUser() if 0 == #tmpPartner.alreadyQueryUser or #tmpPartner.alreadyQueryUser >= 50 then AddMyFriend() end local count = 0 local isEnough = false for k, v in pairs( self.onlineUserList ) do if not IsExistFriend( v.partnerId ) then table.insert( tmpPartner.alreadyQueryUser , v.partnerId) table.insert( data.querys , { info = v , isApply = self:IsApply( player , v.partnerId )}) count = count + 1 end if count >= self.MaxQueryCount then isEnough = true break end end if not isEnough and firstQuery then firstQuery = false --找出来数量不够就清空重新找 tmpPartner.alreadyQueryUser = {} data.querys = {} QuerynlineUser() end end QuerynlineUser() s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerRecommend") s2cData.data = assert(pb.encode("S2CPartnerRecommend", data)) end --好友查询 function Partner:Query( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerQuery", c2sData.data )) local data = {} data.querys = {} local queryType = c2sData.data.queryType local queyValue = c2sData.data.queyValue if not queryType then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local myPlayerId = player.gameData.partner.id local queryAll = {} if self.QueryType_ID == queryType and queyValue and myPlayerId ~= queyValue then table.insert(queryAll , queyValue ) elseif self.QueryType_NickName == queryType and queyValue then --[[暂时不用 local redisKey = redisKeyUrl.GameServerPartneNickNameZSet local tmpQueryData = skynet.server.redis:zscan( redisKey ,0,"match" , string.format("*%s*",queyValue)) --根据关键字模糊查询相关昵称 for k, v in pairs( tmpQueryData[2] ) do if 2 == k and myPlayerId ~= v then table.insert(queryAll , v ) end end ]] else if myPlayerId == queyValue then s2cData.code = errorInfo.ErrorCode.NoQueryMySelf else s2cData.code = errorInfo.ErrorCode.ErrRequestParam end end local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) local friendList = skynet.server.redis:zrange( redisKey , 0 , -1 ) --根据找到的数据获取详情 for k1, v1 in pairs( queryAll ) do local curDetail = skynet.server.personal:GetDetail( v1 ) if curDetail then if not curDetail.birthdayShow then curDetail.birthdayDate = "" end data.partnerDetail = curDetail data.isApply = self:IsApply( player , v1 ) data.isFriend = false data.birthdayDate=curDetail.birthdayDate --看看是不是我的好友 for k2, v2 in pairs( friendList ) do if v1 == v2 then data.isFriend = true break end end end end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerQuery") s2cData.data = assert(pb.encode("S2CPartnerQuery", data)) end --好友添加 function Partner:Add( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerAdd", c2sData.data )) local data = {} data.query = {} local myPlayerId = player.gameData.partner.id local partnerId = c2sData.data.partnerId if not partnerId or myPlayerId == partnerId then --不能加自己 s2cData.code = errorInfo.ErrorCode.ErrRequestParam else if not self:IsAddFriend( myPlayerId ) then s2cData.code = errorInfo.ErrorCode.MyFriendMaxLimit elseif self:IsOtherApply( myPlayerId , partnerId ) then --看看别人申请了我没有,别人申请了就不用再申请了。 s2cData.code = errorInfo.ErrorCode.OtherFriendApplyFriendForMe else --先要检查下存不存在 local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local basicInfo = skynet.server.personal:GetDetail( partnerId ) if not basicInfo then s2cData.code = errorInfo.ErrorCode.NoExistUser elseif basicInfo.level < cfgSValue.partnerUnlockLvl then s2cData.code = errorInfo.ErrorCode.NoFriendFunc else local isApply = self:IsApply( player , partnerId ) data.query.info = basicInfo if not isApply then --加入到我的申请列表 local myPlayerId = player.gameData.partner.id local redisKey = string.format( redisKeyUrl.GameServerPartnerMyApplyOtherZSet , myPlayerId ) skynet.server.redis:zadd( redisKey , skynet.GetTime() , partnerId ) --加入到别人的申请列表 redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , partnerId ) skynet.server.redis:zadd( redisKey , skynet.GetTime() , myPlayerId ) self:SendMsgTips( partnerId , 54 , true ) log.debug(string.format("玩家 %d 好友 向 %s 发出添加好友邀请", player.userId , partnerId )) else log.debug(string.format("玩家 %d 好友 已经向 %s 发出添加好友邀请", player.userId , partnerId )) end data.query.isApply = true end end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerAdd") s2cData.data = assert(pb.encode("S2CPartnerAdd", data)) end --好友删除 function Partner:Delete( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerDelete", c2sData.data )) local data = {} local otherPartnerId = c2sData.data.partnerId if not otherPartnerId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else --友谊小船说翻就翻 好友互删 local myPartnerId = player.gameData.partner.id local redisKey = nil redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPartnerId ) skynet.server.redis:zrem( redisKey , otherPartnerId ) redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , otherPartnerId ) skynet.server.redis:zrem( redisKey , myPartnerId ) --清空聊天记录 redisKey = self:GetMsgKey( myPartnerId , otherPartnerId ) skynet.server.redis:del( redisKey ) --清空消息ID local _,redisKey = self:GetLastMsgID( myPartnerId , otherPartnerId ) skynet.server.redis:del( redisKey ) --删除好友空间 redisKey = skynet.server.doubleSpace:GetMyInfoKey( myPartnerId , otherPartnerId ) if skynet.server.redis:exists( redisKey ) then skynet.server.doubleSpace:RemovePutFurniture(player, myPartnerId, otherPartnerId ) skynet.server.redis:del( redisKey ) skynet.server.personal:AccDetail( myPartnerId ,"doubleSpaceCount", -1) --减少双人空间数量 skynet.server.personal:AccDetail( otherPartnerId ,"doubleSpaceCount", -1) --减少双人空间数量 end data.infos = self:GetFriendList( player ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerDelete") s2cData.data = assert(pb.encode("S2CPartnerDelete", data)) end --好友申请列表 function Partner:ApplyList( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerApplyList", c2sData.data )) local data = {} data.infos = self:GetApplyList( player ) skynet.server.msgTips:ReduceAll( player , 54 ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerApplyList") s2cData.data = assert(pb.encode("S2CPartnerApplyList", data)) end --好友申请回应 function Partner:ApplyRespond( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerApplyRespond", c2sData.data )) local data = {} data.infos = {} local partnerId = c2sData.data.partnerId local isAgree = c2sData.data.isAgree if not partnerId or 0 == #partnerId or nil == isAgree then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local myPlayerId = player.gameData.partner.id local function DeleteApplyFriend() --从该玩家的申请列表中删除我 local redisKey = string.format( redisKeyUrl.GameServerPartnerMyApplyOtherZSet , partnerId ) skynet.server.redis:zrem( redisKey , myPlayerId ) --从别人加我的申请列表中删除该玩家 redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , myPlayerId ) skynet.server.redis:zrem( redisKey , partnerId) end local isAdd1 = self:IsAddFriend( myPlayerId ) local isAdd2 = self:IsAddFriend( partnerId ) if isAdd1 and isAdd2 and isAgree then --将该玩家加入到我的好友列表中 DeleteApplyFriend() local t = skynet.GetTime() local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) skynet.server.redis:zadd( redisKey , t , partnerId ) --将我也加入到该玩家的好友列表中 redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , partnerId ) skynet.server.redis:zadd( redisKey , t , myPlayerId ) skynet.server.personal:AccDetail( partnerId ,"newFriendCount", 1) skynet.server.levelTask:Modify( player , 73 , 1 ) skynet.server.taskListEvent:Modify( player , 73 , 1 ) --发送下最新的好友列表 local friendData = {} friendData.infos = self:GetFriendList( player ) skynet.server.gameServer:SendMsgToUser( player.userId , "CMD_S2C_PartnerMyList" , friendData ) log.debug(string.format("玩家 %d 好友 成功加入好友 %s", player.userId , partnerId )) else if isAgree then if not isAdd1 then s2cData.code = errorInfo.ErrorCode.MyFriendMaxLimit end if not isAdd2 then s2cData.code = errorInfo.ErrorCode.OtherFriendMaxLimit end log.warning(string.format("玩家 %d 好友 好友数量已满,无法加入 %s %s", player.userId , myPlayerId , partnerId )) else DeleteApplyFriend() end end data.infos = self:GetApplyList( player ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerApplyRespond") s2cData.data = assert(pb.encode("S2CPartnerApplyRespond", data)) end --好友聊天记录 function Partner:HistoryMsg( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerHistoryMsg", c2sData.data )) local data = {} local otherPartnerId = c2sData.data.partnerId local earliestMsgId = c2sData.data.earliestMsgId if not otherPartnerId or not earliestMsgId or earliestMsgId < 0 then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else data.partnerId = otherPartnerId data.msgs = {} local myPartnerId = player.gameData.partner.id local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local msgList = nil if 0 == earliestMsgId then --清理过期消息 local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local outOfTime = ( cfgSValue.friendChatSave ) * 3600 --好友聊天内容有效期 self:ClearOutOfTimeMsg( myPartnerId , otherPartnerId , outOfTime ) --传0就发送最近指定数目的消息 msgList = skynet.server.redis:zrevrange( msgKey , 0 , self.MaxMsgRecordToClient - 1 ) else local max = earliestMsgId - 1 local min = earliestMsgId - self.MaxMsgRecordToClient msgList = skynet.server.redis:zrevrangebyscore( msgKey , max < 0 and 0 or max , min < 0 and 0 or min ) end local lastMsgId = 0 local msgData = nil for k, v in pairs( msgList ) do msgData = json:decode(v) if nil == msgData.isShowMsg then --兼容线上数据,可能没有这值 msgData.isShowMsg = true end table.insert( data.msgs , msgData) --获取最新的消息ID if lastMsgId < msgData.msgId then lastMsgId = msgData.msgId end end if 0 == earliestMsgId then --如果获取最新的消息,那就把查看最新消息的索引设置为最新的消息ID local redisKey = string.format( redisKeyUrl.GameServerPartnerUnreadMsgIndexZSet , myPartnerId ) skynet.server.redis:zadd( redisKey , lastMsgId , otherPartnerId ) end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerHistoryMsg") s2cData.data = assert(pb.encode("S2CPartnerHistoryMsg", data)) end --好友发送消息 function Partner:SendMsg( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerSendMsg", c2sData.data )) local data = {} local otherPartnerId = c2sData.data.partnerId local msgType = c2sData.data.msgType local msgText = c2sData.data.msgText if not otherPartnerId or not msgType or not msgText then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif skynet.server.common:IsMaskWords( msgText ) then s2cData.code = errorInfo.ErrorCode.ExistMaskWords else local myPartnerId = player.gameData.partner.id local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local maxCount = skynet.server.redis:zcard( msgKey ) if maxCount >= self.MaxMsgRecord then --玩家的消息记录过多 s2cData.code = errorInfo.ErrorCode.MaxLimit else local redisBanChatKey = string.format( redisKeyUrl.ChatManageBanChatTimeString, myPartnerId ) local unbanChatTime = tonumber(skynet.server.redis:get( redisBanChatKey )) or 0 --获取玩家解禁的时间 local isShowMsg = ( 0 == unbanChatTime ) and true or false --是否显示消息 --将消息转化为json,保存到消息列表中 local msgData,lastMsgId = self:InitMsg( myPartnerId , otherPartnerId , self.MsgType_Text , isShowMsg ) msgData.msgText = msgText skynet.server.redis:zadd( msgKey , lastMsgId , json:encode(msgData) ) data.partnerId = otherPartnerId --将好友的ID发送给自己 data.lastMsg = msgData if isShowMsg then self:SendMsgToFriend( myPartnerId , otherPartnerId , msgData ) end end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerSendMsg") s2cData.data = assert(pb.encode("S2CPartnerSendMsg", data)) end --好友礼物背包 function Partner:GiftBag( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerGiftBag", c2sData.data )) local data = {} local npcId = c2sData.data.npcId if not npcId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerGiftBag") s2cData.data = assert(pb.encode("S2CPartnerGiftBag", data)) end --好友赠送礼物 function Partner:GiftGive( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerGiftGive", c2sData.data )) local data = {} local partnerId = c2sData.data.partnerId local goodsInfo = c2sData.data.goodsInfo if not skynet.server.bag:IsValidGoodsType( goodsInfo.goodsType ) or goodsInfo.goodsId <= 0 or goodsInfo.goodsCount <= 0 then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif dataType.GoodsType_CuisineMaterial ~= goodsInfo.goodsType and dataType.GoodsType_Seed ~= goodsInfo.goodsType then --赠送食材原材料和种子 s2cData.code = errorInfo.ErrorCode.ErrRequestParam else --给好友赠送礼物次数 local partnerGiftCount = player.gameData.todayGain.partnerGiftCount if not partnerGiftCount[ partnerId ] then partnerGiftCount[ partnerId ] = 0 end local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") if partnerGiftCount[ partnerId ] >= cfgSValue.friendGiftLimit then --超过最大限制 s2cData.code = errorInfo.ErrorCode.TodayMaxLimit else local myPlayerId = player.gameData.partner.id local msgKey = self:GetMsgKey( myPlayerId , partnerId ) --判断赠送的道具是否合规 local canSend = self:CanSendGoods(player , partnerId , goodsInfo.goodsType , goodsInfo.goodsId) if canSend then if not skynet.server.bag:RemoveGoods( player , goodsInfo.goodsType , goodsInfo.goodsId , goodsInfo.goodsCount ) then s2cData.code = errorInfo.ErrorCode.NoEnoughGoods else --将消息转化为json,保存到消息列表中 local msgData,lastMsgId = self:InitMsg( myPlayerId , partnerId , self.MsgType_Gift , true ) msgData.gift.info = goodsInfo msgData.gift.status = dataType.GiftStatus_NoGain skynet.server.redis:zadd( msgKey , lastMsgId , json:encode(msgData)) data.lastMsg = msgData partnerGiftCount[ partnerId ] = partnerGiftCount[ partnerId ] + 1 skynet.server.levelTask:Modify( player , 65 , goodsInfo.goodsCount) skynet.server.achieveTask:Modify( player , 65 , goodsInfo.goodsCount) skynet.server.taskListEvent:Modify( player , 65 , goodsInfo.goodsCount) if dataType.GoodsType_CuisineMaterial == goodsInfo.goodsType then skynet.server.levelTask:Modify( player , 80 , goodsInfo.goodsCount) skynet.server.taskListEvent:Modify( player , 80 , goodsInfo.goodsCount) end self:SendMsgToFriend( myPlayerId , partnerId , msgData ) end else s2cData.code = errorInfo.ErrorCode.NoGiveGoodsToPlayer end end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerGiftGive") s2cData.data = assert(pb.encode("S2CPartnerGiftGive", data)) end --好友获取礼物 function Partner:GiftGet( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerGiftGet", c2sData.data )) local data = {} local partnerId = c2sData.data.partnerId local msgId = c2sData.data.msgId if not partnerId or not msgId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local myPlayerId = player.gameData.partner.id local msgKey = self:GetMsgKey( myPlayerId , partnerId ) local msgData = skynet.server.redis:zrangebyscore( msgKey , msgId , msgId) msgData = json:decode( msgData[1] ) if self.MsgType_Gift ~= msgData.msgType then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif dataType.GiftStatus_AlreadyGain == msgData.gift.status then s2cData.code = errorInfo.ErrorCode.AlreadyGet else --发货 msgData.gift.status = dataType.GiftStatus_AlreadyGain --事务流程替换原数据 skynet.server.redis:zremrangebyscore( msgKey , msgId , msgId) skynet.server.redis:zadd( msgKey , msgId , json:encode(msgData)) local goodsInfo = msgData.gift.info skynet.server.bag:AddGoodsNoExp( player , goodsInfo.goodsType , goodsInfo.goodsId , goodsInfo.goodsCount ) --根据赠送的礼物 判断是否需要刷新相关数据 if dataType.GoodsType_Fish == goodsInfo.goodsType then skynet.server.fishShop:FishRefreshRedDot(player, goodsInfo.goodsId ) elseif dataType.GoodsType_Coffee == goodsInfo.goodsType then --skynet.server.coffeeShop:GainCoffee(player, goodsInfo.goodsId ) elseif dataType.GoodsType_CuisineMenu == goodsInfo.goodsType then skynet.server.cuisineShop:RefreshData(player, goodsInfo.goodsId ) end data.partnerId = partnerId data.msg = msgData self:SendMsgToFriend( myPlayerId , partnerId , msgData ) end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerGiftGet") s2cData.data = assert(pb.encode("S2CPartnerGiftGet", data)) end --好友详情 function Partner:Detail( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerDetail", c2sData.data )) local data = {} local partnerId = c2sData.data.partnerId if not partnerId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local basicInfo = skynet.server.personal:GetDetail( partnerId ) if basicInfo then data.partner = basicInfo else s2cData.code = errorInfo.ErrorCode.NoExistUser end data.partner.birthdayDate=basicInfo.birthdayDate or "" if basicInfo.birthdayShow==false then data.partner.birthdayDate="" end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerDetail") s2cData.data = assert(pb.encode("S2CPartnerDetail", data)) end --获取好友房间信息 function Partner:ShowFriendHouse( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerShowFriendHouse", c2sData.data )) local data = {} local partnerId = c2sData.data.partnerId local houseId = c2sData.data.houseId if not partnerId or not houseId or houseId < 0 then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local houseDetail = {} local redisKey = string.format( redisKeyUrl.GameServerHouseDetailHash , partnerId ) if not skynet.server.redis:exists( redisKey) then --没有玩家的缓存数据,需要从DB中加载 local detail = skynet.server.personal:GetDetail( partnerId ) if not detail then s2cData.code = errorInfo.ErrorCode.NoExistUser else local dbIndex = detail.dbIndex local userId = detail.userId --从DB中获取玩家数据 local sql = string.format(sqlUrl.queryAccountFromPlayer , userId ) local queryData = skynet.server.db:QueryPlayer( dbIndex , sql ) --local queryData = skynet.server.mongo[ "player".. dbIndex ]:findOne({ _id = userId } , { GameData = 1 } ) if not queryData then s2cData.code = errorInfo.ErrorCode.NoExistHouse else queryData = queryData[1] local gameData = json:decode(queryData.GameData) houseDetail.curHouseId = gameData.curHouseID --当前房间ID houseDetail.flowerpot = gameData.flowerpot --花盆信息 houseDetail.houseList = {} --由于房间数据过大,分批次保存到redis for k, v in pairs( gameData.house ) do if skynet.server.house.Status_AlreadyBuy == v.status or skynet.server.house.Status_Live == v.status then skynet.server.redis:hset( redisKey , "houseData_"..k , json:encode(v) ) table.insert( houseDetail.houseList, k ) if gameData.curHouseID == k then houseDetail.curHouseData = v --当前房间信息 end end end --将一些信息保存到redis中 skynet.server.redis:hmset( redisKey , "curHouseId" , gameData.curHouseID , "flowerpot" , json:encode(gameData.flowerpot) , "houseList" , json:encode(houseDetail.houseList)) end end else --从redis中读取数据 local tmpData = skynet.server.redis:hmget( redisKey , "curHouseId", "flowerpot" , "houseList") houseDetail.curHouseId = tonumber( tmpData[1]) houseDetail.flowerpot = json:decode(tmpData[2]) houseDetail.houseList = json:decode(tmpData[3]) --如果为0查询默认房间数据 ,非0根据玩家发送的houseId查询房间数据 if 0 ~= houseId then houseDetail.curHouseId = houseId end houseDetail.curHouseData = skynet.server.redis:hget( redisKey , "houseData_"..houseDetail.curHouseId) houseDetail.curHouseData = json:decode(houseDetail.curHouseData) end skynet.server.levelTask:Modify( player , 76 , 1 , nil , partnerId ) skynet.server.taskListEvent:Modify( player , 76 , 1 ) skynet.server.redis:expire( redisKey , self.HouseDetailMaxOutTime ) --设置过期时间为1小时 data = self:GetFriendHouseData( partnerId , houseDetail ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerShowFriendHouse") s2cData.data = assert(pb.encode("S2CPartnerShowFriendHouse", data)) end --好友消除红点 function Partner:ClearRedDot( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerClearRedDot", c2sData.data )) local data = {} local partnerId = c2sData.data.partnerId if not partnerId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else data.partnerId = partnerId local myPlayerId = player.gameData.partner.id local msgKey = self:GetMsgKey( myPlayerId , partnerId ) local msgList = skynet.server.redis:zrange( msgKey , -1 , -1 ) local lastMsgId = 0 local tmpData = nil for k, v in pairs( msgList ) do tmpData = json:decode(v) local redisKey = string.format( redisKeyUrl.GameServerPartnerUnreadMsgIndexZSet , myPlayerId ) skynet.server.redis:zadd( redisKey , tmpData.msgId , partnerId ) break end skynet.server.msgTips:ReduceAll( player , 53 ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerClearRedDot") s2cData.data = assert(pb.encode("S2CPartnerClearRedDot", data)) end --好友组建双人空间请求 function Partner:DoubleSpaceRequest( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerDoubleSpaceRequest", c2sData.data )) local data = {} local otherPartnerId = c2sData.data.partnerId if "" == otherPartnerId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local t1 = skynet.GetTime() local myPartnerId = player.gameData.partner.id local msgData = self:GetMsgDataForType( myPartnerId , otherPartnerId , self.MsgType_InviteDoubleSpace ) if msgData and ( t1 - msgData.updateTime ) <= dataType.OneDaySec then --如果小于1天,就不允许再发送消息 s2cData.code = errorInfo.ErrorCode.AlreadyApplyDoubleSpace --已经申请 else --走到这里,表示消息已经过期,如果还是邀请状态就改为过期状态 if msgData and self.InviteStatus_Inviting == msgData.doubleSpace.inviteStatus then msgData.doubleSpace.inviteStatus = self.InviteStatus_OutOfTime self:SetMsgData( myPartnerId , otherPartnerId , msgData.msgId , msgData ) end local myCount = skynet.server.personal:GetCurDetail( myPartnerId , "doubleSpaceCount" ) local otherCount = skynet.server.personal:GetCurDetail( otherPartnerId , "doubleSpaceCount" ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") if nil == myCount then s2cData.code = errorInfo.ErrorCode.MyNoEnoughLevel --自己等级未达到 elseif nil == otherCount then s2cData.code = errorInfo.ErrorCode.OtherNoEnoughLevel --对方等级未达到 elseif myCount >= cfgSValue.coupleHouseLimit then s2cData.code = errorInfo.ErrorCode.MyDoubleSpaceNoCount --我的空间数量已达上限 elseif otherCount >= cfgSValue.coupleHouseLimit then s2cData.code = errorInfo.ErrorCode.OtherDoubleSpaceNoCount --对方空间数量已达上限 elseif skynet.server.doubleSpace:IsExist( myPartnerId , otherPartnerId ) then s2cData.code = errorInfo.ErrorCode.AlreadyExistDoubleSpace --双方已经建立了空间 else --发送邀请好友消息 local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local msgData,lastMsgId = self:InitMsg( myPartnerId , otherPartnerId , self.MsgType_InviteDoubleSpace , true ) msgData.doubleSpace.inviteStatus = self.InviteStatus_Inviting skynet.server.redis:zadd( msgKey , lastMsgId , json:encode(msgData)) --好友在线,也将该消息给他 self:SendMsgToFriend( myPartnerId , otherPartnerId , msgData ) data.lastMsg = msgData end end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerDoubleSpaceRequest") s2cData.data = assert(pb.encode("S2CPartnerDoubleSpaceRequest", data)) end --好友组建双人空间回应 function Partner:DoubleSpaceResponse( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerDoubleSpaceResponse", c2sData.data )) local data = {} local otherPartnerId = c2sData.data.partnerId local msgId = c2sData.data.msgId local isAgree = c2sData.data.isAgree local myPartnerId = player.gameData.partner.id if not otherPartnerId or not msgId or nil == isAgree then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local msgData = skynet.server.redis:zrangebyscore( msgKey , msgId , msgId) msgData = json:decode( msgData[1] ) --不是邀请双人空间消息或者 状态不是邀请中都报异常 if self.MsgType_InviteDoubleSpace ~= msgData.msgType or self.InviteStatus_Inviting ~= msgData.doubleSpace.inviteStatus then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else msgData.doubleSpace.inviteStatus = self.InviteStatus_Refuse if true == isAgree then --如果同意了,再检查下自己和别人是否数量已达上限 local myCount = skynet.server.personal:GetCurDetail( myPartnerId , "doubleSpaceCount" ) local otherCount = skynet.server.personal:GetCurDetail( otherPartnerId , "doubleSpaceCount" ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") if myCount >= cfgSValue.coupleHouseLimit then --我的已经达到上限 s2cData.code = errorInfo.ErrorCode.MyDoubleSpaceNoCount elseif otherCount >= cfgSValue.coupleHouseLimit then --对方已经达上线 s2cData.code = errorInfo.ErrorCode.OtherDoubleSpaceNoCount else msgData.doubleSpace.inviteStatus = self.InviteStatus_Agree --创建双人空间 skynet.server.doubleSpace:Cretate( player , msgData.sendPartnerId ) end end --替换原数据 skynet.server.redis:zremrangebyscore( msgKey , msgId , msgId) skynet.server.redis:zadd( msgKey , msgId , json:encode(msgData)) self:SendMsgToFriend( myPartnerId , otherPartnerId , msgData ) data.partnerId = otherPartnerId data.msg = msgData end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerDoubleSpaceResponse") s2cData.data = assert(pb.encode("S2CPartnerDoubleSpaceResponse", data)) end --好友一键申请回应 function Partner:AllApplyRespond( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPartnerAllApplyRespond", c2sData.data )) local data = {} data.infos = {} local isAgree = c2sData.data.isAgree if nil == isAgree then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local myPlayerId = player.gameData.partner.id local redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , myPlayerId ) local applyPartnerIds = skynet.server.redis:zrange( redisKey , 0 , -1 ) --获取申请加我的人 redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) local myFriendCount = skynet.server.redis:zcard( redisKey ) --我的好友数量 if isAgree and myFriendCount + #applyPartnerIds > self.MaxFriendCount then --如果我的好友数量+申请人的数量 大于最大值就不能加成功 s2cData.code = errorInfo.ErrorCode.MyFriendMaxLimit else for k, partnerId in pairs( applyPartnerIds ) do local function DeleteApplyFriend() --从该玩家的申请列表中删除我 local redisKey = string.format( redisKeyUrl.GameServerPartnerMyApplyOtherZSet , partnerId ) skynet.server.redis:zrem( redisKey , myPlayerId ) --从别人加我的申请列表中删除该玩家 redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , myPlayerId ) skynet.server.redis:zrem( redisKey , partnerId) end local isAdd = self:IsAddFriend( partnerId ) if isAdd and isAgree then DeleteApplyFriend() --如果能加该好友,并且同意,将该玩家加入到我的好友列表中 local t = skynet.GetTime() local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) skynet.server.redis:zadd( redisKey , t , partnerId ) --将我也加入到该玩家的好友列表中 redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , partnerId ) skynet.server.redis:zadd( redisKey , t , myPlayerId ) skynet.server.personal:AccDetail( partnerId ,"newFriendCount", 1) skynet.server.levelTask:Modify( player , 73 , 1 ) skynet.server.taskListEvent:Modify( player , 73 , 1 ) log.debug(string.format("玩家 %d 好友 一键成功加入好友 %s", player.userId , partnerId )) else if isAgree then if not isAdd then s2cData.code = errorInfo.ErrorCode.OtherFriendMaxLimit end log.warning(string.format("玩家 %d 好友 一键好友数量已满,无法加入 %s %s", player.userId , myPlayerId , partnerId )) else DeleteApplyFriend() end end end --发送下最新的好友列表 local friendData = {} friendData.infos = self:GetFriendList( player ) skynet.server.gameServer:SendMsgToUser( player.userId , "CMD_S2C_PartnerMyList" , friendData ) end data.infos = self:GetApplyList( player ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PartnerAllApplyRespond") s2cData.data = assert(pb.encode("S2CPartnerAllApplyRespond", data)) end --初始化消息 function Partner:InitMsg( myPartnerId , otherPartnerId , msgType , isShowMsg ) local lastMsgId = self:GetLastMsgID( myPartnerId , otherPartnerId ) local msgData = {} msgData.msgId = lastMsgId msgData.sendPartnerId = myPartnerId msgData.updateTime = skynet.GetTime() msgData.msgType = msgType msgData.msgText = "" msgData.gift = {} msgData.doubleSpace = {} msgData.isShowMsg = isShowMsg return msgData,lastMsgId end --获取好友房间数据 function Partner:GetFriendHouseData( partnerId , houseDetail ) local data = {} local curHouseId = houseDetail.curHouseId local curSchemeId = houseDetail.curHouseData.curSchemeId --当前场景ID --组装数据 data.partnerId = partnerId data.houseId = curHouseId data.houseIdList = houseDetail.houseList data.furnitureInfo = self:GetCurSchemeFurniture( curHouseId , curSchemeId , houseDetail ) data.decorateInfo = self:GetCurSchemeDecorate( curHouseId , curSchemeId , houseDetail ) --当前已经解锁的区域ID data.areaId = {} for areaId, v in pairs( houseDetail.curHouseData.unlockAreaList ) do if true == v then table.insert( data.areaId , areaId ) end end return data end --获取当前房间当前方案所有花盆信息 function Partner:GetFlowerpot( curHouseId , curSchemeId, flowerpotInfo ) local furnitureInfo = nil local isExist = false for k, v in pairs( flowerpotInfo.nowPos ) do --当前房间和当前方案下的花盆位置 if curHouseId == v.houseId and curSchemeId == v.schemeId then furnitureInfo = {} --将当前花盆的基本信息拷贝过来 for k, v in pairs( flowerpotInfo ) do furnitureInfo[ k ] = v end furnitureInfo.furnitureInfo = nil --这个值不传客户端去 furnitureInfo.nowPos = {} furnitureInfo.nowPos.x = v.x furnitureInfo.nowPos.y = v.y furnitureInfo.isPutInFurniture = v.isPutInFurniture or false break end end return furnitureInfo end --获取当前方案 function Partner:GetCurScheme( curSchemeId , houseDetail ) for k, v in pairs( houseDetail.curHouseData.scheme ) do if curSchemeId == v.id then return v end end return nil end --获取当前方案下的家具和花盆 function Partner:GetCurSchemeFurniture( curHouseId , curSchemeId , houseDetail ) local furnitureInfo = {} local curScheme = self:GetCurScheme( curSchemeId , houseDetail ) --将家具和花盆打包在一起发给客户端 for k, v in pairs( curScheme.furniture ) do table.insert( furnitureInfo , v ) end for k, v in pairs( houseDetail.flowerpot ) do --从花盆列表中找到当前方案下的位置信息 local flowerpotInfo = self:GetFlowerpot( curHouseId , curSchemeId , v ) if flowerpotInfo then table.insert( furnitureInfo , flowerpotInfo ) end end return furnitureInfo end --获取当前方案下的装修 function Partner:GetCurSchemeDecorate( curHouseId , curSchemeId , houseDetail ) local furnitureInfo = {} for k1, v1 in pairs( houseDetail.curHouseData.scheme ) do if curSchemeId == v1.id then return v1.decorate end end return furnitureInfo end --是否添加好友 function Partner:IsAddFriend( partnerId ) local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , partnerId ) local addCount = skynet.server.redis:zcard( redisKey ) if addCount < self.MaxFriendCount then return true end return false end --别人是否申请了我的好友 function Partner:IsOtherApply( myPartnerId , otherPartnerId ) local redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , otherPartnerId ) local applyPartnerIds = skynet.server.redis:zrange( redisKey , 0 , -1 ) --获取申请加我的人 for k, partnerId in pairs( applyPartnerIds ) do if myPartnerId == partnerId then return true end end return false end --是否已申请好友 function Partner:IsApply( player , addPlayerId ) local myPlayerId = player.gameData.partner.id local redisKey = string.format( redisKeyUrl.GameServerPartnerMyApplyOtherZSet , myPlayerId ) local isApply = skynet.server.redis:zrank( redisKey , addPlayerId ) if isApply then return true end redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) isApply = skynet.server.redis:zrank( redisKey , addPlayerId ) if isApply then return true end return false end --获取最新的申请列表 function Partner:GetApplyList( player ) local data = {} local myPlayerId = player.gameData.partner.id local redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , myPlayerId ) local applyList= skynet.server.redis:zrevrange( redisKey , 0 , -1 , "withscores") --获取所有加我的人 applyList = redisKeyUrl:CovertTable( applyList ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local outOfTime = ( cfgSValue.friendApplyTimeLimit ) * 3600 --超时 for otherPartnerId , applyTime in pairs( applyList ) do if skynet.GetTime() >= applyTime + outOfTime then --skynet.server.redis:multi() --从该玩家的申请列表中删除我 redisKey = string.format( redisKeyUrl.GameServerPartnerMyApplyOtherZSet , otherPartnerId ) skynet.server.redis:zrem( redisKey , myPlayerId ) --从别人加我的列表中删除玩家 redisKey = string.format( redisKeyUrl.GameServerPartnerOtherApplyMyZSet , myPlayerId ) skynet.server.redis:zrem( redisKey , otherPartnerId ) --skynet.server.redis:exec() else local basicInfo = skynet.server.personal:GetDetail( otherPartnerId ) if basicInfo then table.insert( data , basicInfo ) end end end return data end --获取消息的Key function Partner:GetMsgKey( myPlayerId , otherPlayerId ) local key = "" --谁的ID大就谁在前面 if myPlayerId > otherPlayerId then key = string.format("%s-%s" , myPlayerId , otherPlayerId ) else key = string.format("%s-%s" , otherPlayerId , myPlayerId ) end local redisKey = string.format( redisKeyUrl.GameServerPartnerMsgRecordZSet , key ) return redisKey end --获取最新的消息ID function Partner:GetLastMsgID( myPlayerId , otherPlayerId ) local key = "" --谁的ID大就谁在前面 if myPlayerId > otherPlayerId then key = string.format("%s-%s" , myPlayerId , otherPlayerId ) else key = string.format("%s-%s" , otherPlayerId , myPlayerId ) end local redisKey = string.format( redisKeyUrl.GameServerPartnerMsgID , key ) local msgId = skynet.server.redis:incr( redisKey ) return msgId,redisKey end --同步在线玩家数据 function Partner:SyncOnlineList() self.onlineUserList = {} local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( nil , "SValue") local redisKey = redisKeyUrl.GameServerPartnerAllUserZSet local queryData = skynet.server.redis:zrevrange( redisKey , 0, self.MaxGetOnlineCount -1 ) --根据找到的数据获取详情 for k, v in pairs( queryData ) do local curDetail = skynet.server.personal:GetDetail( v ) if curDetail and curDetail.partnerId and curDetail.level >= cfgSValue.partnerUnlockLvl and self:IsAddFriend( v ) then table.insert( self.onlineUserList , curDetail ) end end end --发送消息到好友 function Partner:SendMsgToFriend( sendPartnerId , toPartnerId , msgData ) local playerDetail = skynet.server.personal:GetDetail( toPartnerId ) --获取个人详情 if not playerDetail then return end local tmpData = {} tmpData.partnerId = sendPartnerId tmpData.lastMsg = msgData local cmd = "CMD_S2C_PartnerSendMsg" local returnValue = skynet.server.playerCenter:IsSameServer( toPartnerId ) if nil == returnValue then return elseif true ==returnValue then --在同一服务器 skynet.server.gameServer:SendMsgToUser( playerDetail.userId , cmd , tmpData ) local player = skynet.server.playerCenter:GetPlayer( playerDetail.userId ) if player then --发送红点信息 skynet.server.msgTips:Add( player , 53 ) end elseif false ==returnValue then --不在同一服务器,将聊天消息推到玩家所在的游戏服 local sendData = {} sendData.userId = playerDetail.userId sendData.cmd = cmd sendData.data = tmpData local serverCmd = skynet.server.gameServer.GameToGame_NetMsg skynet.server.gameServer:SendMsgToServer( playerDetail.gameServerId , serverCmd, sendData ) end end --发送消息到好友 function Partner:SendMsgTips( toPartnerId , tipsId , isSend ) local playerDetail = skynet.server.personal:GetDetail( toPartnerId ) --获取个人详情 if not playerDetail then return end local returnValue = skynet.server.playerCenter:IsSameServer( toPartnerId ) if nil == returnValue then return elseif true ==returnValue then local player = skynet.server.playerCenter:GetPlayer( playerDetail.userId ) if player then --发送红点信息 if isSend then skynet.server.msgTips:Add( player , tipsId ) else skynet.server.msgTips:ReduceAll( player , tipsId ) end end elseif false ==returnValue then --不在同一服务器,将聊天消息推到玩家所在的游戏服 local sendData = {} sendData.userId = playerDetail.userId sendData.cmd = "CMD_Temp_TipsMsg" sendData.isSend = isSend sendData.data = tipsId local serverCmd = skynet.server.gameServer.GameToGame_NetMsg skynet.server.gameServer:SendMsgToServer( playerDetail.gameServerId , serverCmd, sendData ) end end --取消Tips消息 function Partner:ReduceAllMsgTips( toPartnerId , tipsId ) local playerDetail = skynet.server.personal:GetDetail( toPartnerId ) --获取个人详情 if not playerDetail then return end local returnValue = skynet.server.playerCenter:IsSameServer( toPartnerId ) if nil == returnValue then return elseif true ==returnValue then local player = skynet.server.playerCenter:GetPlayer( playerDetail.userId ) if player then --发送红点信息 skynet.server.msgTips:ReduceAll( player , tipsId ) end elseif false ==returnValue then --不在同一服务器,将聊天消息推到玩家所在的游戏服 local sendData = {} sendData.userId = playerDetail.userId sendData.cmd = "CMD_Temp_TipsMsg" sendData.isSend = false sendData.data = tipsId local serverCmd = skynet.server.gameServer.GameToGame_NetMsg skynet.server.gameServer:SendMsgToServer( playerDetail.gameServerId , serverCmd, sendData ) end end --判断赠送的道具是否合规 function Partner:CanSendGoods(player , partnerId , goodsType , goodsId) local basicInfo = skynet.server.personal:GetDetail(partnerId) local cfgCuisineMenu = skynet.server.gameConfig:GetPlayerAllCfg( player , "CuisineMenu") local cfgCuisineMaterial = skynet.server.gameConfig:GetPlayerAllCfg( player , "CuisineMaterial") local cfgFishType = skynet.server.gameConfig:GetPlayerAllCfg( player , "FishType") if dataType.GoodsType_CuisineMenu == goodsType then --如果赠送的道具是料理店相关的 判断该玩家是否可以接受 local sendCuisineLevel = cfgCuisineMenu[goodsId].menuLevel --解锁菜的菜单等级 local cuisineLevel = basicInfo.cuisineLevel --该玩家的菜单等级 local unlockCondition = skynet.server.map:GetUnlockCondition( player , 6 ) --判断玩家等级是否达到料理店解锁等级 --如果不满足相关条件 则不可赠送 if cuisineLevel and unlockCondition and basicInfo.level >= unlockCondition[ 2 ] and sendCuisineLevel <= cuisineLevel then return true else return false end elseif dataType.GoodsType_CuisineMaterial == goodsType then --如果赠送的道具是料理店相关的 判断该玩家是否可以接受 local materialLevel = cfgCuisineMaterial[goodsId].menuLevel --解锁材料的菜单等级 local cuisineLevel = basicInfo.cuisineLevel --该玩家的菜单等级 local unlockCondition = skynet.server.map:GetUnlockCondition( player , 6 ) --判断玩家等级是否达到料理店解锁等级 --如果不满足相关条件 则不可赠送 if cuisineLevel and unlockCondition and basicInfo.level >= unlockCondition[ 2 ] and materialLevel <= cuisineLevel then return true else return false end elseif dataType.GoodsType_Fish == goodsType then --如果赠送的道具是鱼 判断该玩家是否可以接受 local sendFishLevel = cfgFishType[goodsId].fishType --该鱼的等级 local fishLevel = basicInfo.fishLevel --该玩家可获取鱼的最高等级 local unlockCondition = skynet.server.map:GetUnlockCondition( player , 5 ) --判断玩家等级是否达到渔店解锁等级 --如果不满足相关条件 则不可赠送 if fishLevel and unlockCondition and basicInfo.level >= unlockCondition[ 2 ] and sendFishLevel <= fishLevel then return true else return false end else --其他的物品不做限制 return true end end --清理过期消息 function Partner:ClearOutOfTimeMsg( myPartnerId , otherPartnerId , outOfTime ) local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local msgList = skynet.server.redis:zrange( msgKey , 0 , -1 ) --将我与该好友的消息全部取出 local msgData = nil local startPos,endPos = 0,0 --过期消息的开始位置和结束位置 for k, v in pairs( msgList ) do msgData = json:decode( v ) --只清理文档过期消息 if self.MsgType_Gift ~= tonumber( msgData.msgType ) and skynet.GetTime() >= tonumber( msgData.updateTime ) + outOfTime then if 0 == startPos then --记录开始和结束位置 startPos = msgData.msgId endPos = msgData.msgId elseif 0 ~= startPos then --记录结束位置 endPos = msgData.msgId end --双人空间消息如果还是邀请状态并且过期了就改为过期状态 if self.MsgType_InviteDoubleSpace == tonumber( msgData.msgType ) and self.InviteStatus_Inviting == msgData.doubleSpace.inviteStatus then local diffTime = skynet.GetTime() - msgData.updateTime if diffTime > dataType.OneDaySec then msgData.doubleSpace.inviteStatus = self.InviteStatus_OutOfTime self:SetMsgData( myPartnerId , otherPartnerId , msgData.msgId , msgData ) end end end end if 0 ~= startPos then --删除所有过期数据 skynet.server.redis:zremrangebyscore( msgKey , startPos , endPos) end end --[[ --清理过期消息 function Partner:ClearOutOfTimeMsg( player , myPlayerId ) --清空我与其它玩家的过期消息 local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local outOfTime = ( cfgSValue.friendChatSave ) * 3600 --好友聊天内容有效期 --获取我所有的好友 local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPlayerId ) local friendList = skynet.server.redis:zrange( redisKey , 0 , -1 ) for k, otherPlayerId in pairs( friendList ) do local msgKey = self:GetMsgKey( myPlayerId , otherPlayerId ) local msgList = skynet.server.redis:zrange( msgKey , 0 , -1 ) --将我与该好友的消息全部取出 local tmpMsg = nil local startPos,endPos = 0,0 --过期消息的开始位置和结束位置 for k, v in pairs( msgList ) do tmpMsg = json:decode( v ) --只清理文档过期消息 if self.MsgType_Gift ~= tonumber(tmpMsg.msgType) and os.time() >= tonumber(tmpMsg.updateTime) + outOfTime then if 0 == startPos then --记录开始和结束位置 startPos = tmpMsg.msgId endPos = tmpMsg.msgId elseif 0 ~= startPos then --记录结束位置 endPos = tmpMsg.msgId end end end if 0 ~= startPos then --删除所有过期数据 skynet.server.redis:zremrangebyscore( msgKey , startPos , endPos) end end end ]] --根据类型获取消息数据(只获取没有过期的消息) function Partner:GetMsgDataForType( myParentId , otherParentId , msgType ) local msgKey = self:GetMsgKey( myParentId , otherParentId ) local msgList = skynet.server.redis:zrange( msgKey , 0 , -1 ) --将我与该好友的消息全部取出 local tmpMsg = nil for k, v in pairs( msgList ) do tmpMsg = json:decode( v ) --只有正在邀请的才会获取 if msgType == tonumber( tmpMsg.msgType ) and self.InviteStatus_Inviting == tmpMsg.doubleSpace.inviteStatus then return tmpMsg end end return nil end --获取消息数据 function Partner:GetMsgData( myPartnerId , otherPartnerId , msgId ) local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local msgData = skynet.server.redis:zrangebyscore( msgKey , msgId , msgId) msgData = json:decode( msgData[1] ) return msgData end --设置消息数据 function Partner:SetMsgData( myPartnerId , otherPartnerId , msgId , newMsgData ) local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) skynet.server.redis:zremrangebyscore( msgKey , msgId , msgId) skynet.server.redis:zadd( msgKey , msgId , json:encode( newMsgData )) end --好友双人空间购买房屋邀请 function Partner:DoubleSpaceBuyInvite( player , otherPartnerId,msgType,houseId,schemeId ) if "" == otherPartnerId then return end local t1 = skynet.GetTime() local myPartnerId = player.gameData.partner.id local msgData = self:GetMsgDataForTypeAndId( myPartnerId , otherPartnerId , msgType ,houseId ,schemeId) if msgData and ( t1 - msgData.updateTime ) <= dataType.OneDaySec then --如果小于1天,就不允许再发送消息 log.info("双人空间购买房间邀请 重复申请") return --已经申请 end --走到这里,表示消息已经过期,如果还是邀请状态就改为过期状态 if msgData and self.InviteStatus_Inviting == msgData.doubleSpace.inviteStatus then msgData.doubleSpace.inviteStatus = self.InviteStatus_OutOfTime self:SetMsgData( myPartnerId , otherPartnerId , msgData.msgId , msgData ) end --发送邀请好友消息 local msgKey = self:GetMsgKey( myPartnerId , otherPartnerId ) local msgData,lastMsgId = self:InitMsg( myPartnerId , otherPartnerId , msgType , true ) msgData.doubleSpace.inviteStatus = self.InviteStatus_Inviting msgData.doubleSpace.houseID = houseId msgData.doubleSpace.schemeID = schemeId skynet.server.redis:zadd( msgKey , lastMsgId , json:encode(msgData)) --好友在线,也将该消息给他 self:SendMsgToFriend( myPartnerId , otherPartnerId , msgData ) --推送给自己 self:SendMsgToFriend( otherPartnerId , myPartnerId , msgData ) end --好友双人空间购买房屋回应 function Partner:DoubleSpaceBuyInviteRespond( player , otherParentId,msgType,houseId,schemeId ) local myPartnerId = player.gameData.partner.id local msgKey = self:GetMsgKey( myPartnerId , otherParentId ) local msgList = skynet.server.redis:zrange( msgKey , 0 , -1 ) --将我与该好友的消息全部取出 local tmpMsg = nil for k, v in pairs( msgList ) do tmpMsg = json:decode( v ) --只有正在邀请的才会获取 if msgType == tonumber( tmpMsg.msgType ) and self.InviteStatus_Inviting == tmpMsg.doubleSpace.inviteStatus and tonumber(tmpMsg.doubleSpace.houseID) == houseId and tonumber(tmpMsg.doubleSpace.schemeID) == schemeId then local msgId = tmpMsg.msgId --设置已同意 tmpMsg.doubleSpace.inviteStatus=self.InviteStatus_Agree --替换原数据 skynet.server.redis:zremrangebyscore( msgKey , msgId , msgId) skynet.server.redis:zadd( msgKey , msgId , json:encode(tmpMsg)) --好友在线,也将该消息给他 self:SendMsgToFriend( myPartnerId , otherParentId , tmpMsg ) --推送给自己 self:SendMsgToFriend( otherParentId , myPartnerId , tmpMsg ) end end end --根据类型获取消息数据(只获取没有过期的消息) function Partner:GetMsgDataForTypeAndId( myParentId , otherParentId , msgType , houseId , schemeId ) local msgKey = self:GetMsgKey( myParentId , otherParentId ) local msgList = skynet.server.redis:zrange( msgKey , 0 , -1 ) --将我与该好友的消息全部取出 local tmpMsg = nil for k, v in pairs( msgList ) do tmpMsg = json:decode( v ) --只有正在邀请的才会获取 if msgType == tonumber( tmpMsg.msgType ) and tmpMsg.sendPartnerId == myParentId and self.InviteStatus_Inviting == tmpMsg.doubleSpace.inviteStatus and tonumber(tmpMsg.doubleSpace.houseID) == houseId and tonumber(tmpMsg.doubleSpace.schemeID) == schemeId then return tmpMsg end end return nil end skynet.server.partner = Partner return Partner