local skynet = require "skynet" local oo = require "Class" local log = require "Log" local pb = require "pb" local dataType = require "DataType" local errorInfo = require "ErrorInfo" local redisKeyUrl = require "RedisKeyUrl" local json =require "json" local serverId = tonumber(skynet.getenv "serverId") local Personal = oo.class() Personal.MaxColorType = 3 --最大颜色类型 Personal.MaxNickNameLen = 21 --最大昵称长度 Personal.AddGoods = 1 --添加物品 Personal.DelGoods = 2 --移除物品 Personal.listNewPartnerId = {} --当前正在创建的partnerId列表 --初始数据 function Personal:InitData( player ) player.gameData.personal.clothesData = {} player.gameData.personal.colorData = {} --所有数据默认为0 for i = 1, dataType.ClothesType_Max - 1 , 1 do player.gameData.personal.clothesData[ i ] = 0 end for i = 1, self.MaxColorType, 1 do player.gameData.personal.colorData[ i ] = 0 end --默认服饰 2,3,10,14,17,16 local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local cfgDefalutClothes = cfgSValue.characterDefalutClothes local cfgClothes = skynet.server.gameConfig:GetPlayerAllCfg( player , "Clothes") for k1, v1 in pairs( cfgDefalutClothes ) do for k2, v2 in pairs( cfgClothes ) do if v1 == v2.id then player.gameData.personal.clothesData[ v2.type ] = v1 break end end --将该商品赠送到玩家背包里 skynet.server.bag:AddGoods( player , dataType.GoodsType_Clothes , v1 , 1) end --默认颜色 1 6 26 local cfgDefalutColor = cfgSValue.characterDefalutColor local cfgColor = skynet.server.gameConfig:GetPlayerAllCfg( player , "Color") for k1, v1 in pairs( cfgDefalutColor ) do for k2, v2 in pairs( cfgColor ) do if v1 == v2.id then player.gameData.personal.colorData[ v2.types ] = v1 break end end end player.gameData.personal.headId = 1 player.gameData.personal.headFrameId = 13 player.gameData.personal.title1 = 1 player.gameData.personal.title2 = 11 player.gameData.personal.medals = { 0 ,0 ,0 } local clothesData = player.gameData.personal.clothesData local colorData = player.gameData.personal.colorData local whileCount = 0 while true do whileCount = whileCount + 1 --已经有玩家ID,就不再处理 if "" ~= player.gameData.partner.id or whileCount >= 100 then break end local myPartnerId = skynet.server.common:RandIDNoIAndL(12) if not self.listNewPartnerId [ myPartnerId ] then self.listNewPartnerId [ myPartnerId ] = true --先本地缓存一下是否存在好友ID,可能同时生成相同的好友ID --local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , myPartnerId ) --local curRedis = skynet.server.redisCenter:GetPartnerRedis( myPartnerId ) --根据partnerId来获取redis索引 if not self:IsExistDetailKey( myPartnerId ) then --新生成的partnerId,保存到用户相关数据中去 local account = player.basicInfo.accountName skynet.server.redisCenter:SetRedisDBInfo( account , "PartnerId" , myPartnerId ) --初始化个人redis数据 player.gameData.partner.id = myPartnerId local initData = {} initData[ "dbIndex" ] = player.basicInfo.dbIndex initData[ "platform" ] = player.basicInfo.platform initData[ "account" ] = account initData[ "userId" ] = player.userId initData[ "partnerId" ] = tostring(player.gameData.partner.id) initData[ "nickName" ] = player.gameData.nickName initData[ "headId" ] = 1 initData[ "headFrameId" ] = 13 initData[ "level" ] = player.gameData.level initData[ "title1" ] = 1 initData[ "title2" ] = 11 initData[ "medals1" ] = 0 initData[ "medals2" ] = 0 initData[ "medals3" ] = 0 initData[ "cuisineLevel" ] = 1 initData[ "fishLevel" ] = 1 initData[ "isOnline" ] = true initData[ "gameServerId" ] = serverId initData[ "newFriendCount" ] = 0 initData[ "groupId" ] = "" initData[ "groupExitTime" ] = 0 initData[ "clothesData1" ] = clothesData[ dataType.ClothesType_Head ] initData[ "clothesData2" ] = clothesData[ dataType.ClothesType_Hair ] initData[ "clothesData3" ] = clothesData[ dataType.ClothesType_Eyes ] initData[ "clothesData4" ] = clothesData[ dataType.ClothesType_HeadWear ] initData[ "clothesData5" ] = clothesData[ dataType.ClothesType_Clothes ] initData[ "clothesData6" ] = clothesData[ dataType.ClothesType_Trousers ] initData[ "clothesData7" ] = clothesData[ dataType.ClothesType_Suit ] initData[ "clothesData8" ] = clothesData[ dataType.ClothesType_Shoes ] initData[ "clothesData9" ] = clothesData[ dataType.ClothesType_Earrings ] initData[ "clothesData10" ] = clothesData[ dataType.ClothesType_Facing ] initData[ "colorData1" ] = colorData[ 1 ] --发色 initData[ "colorData2" ] = colorData[ 2 ] --瞳色 initData[ "colorData3" ] = colorData[ 3 ] --肤色 initData[ "rechargeAmount" ] = 0 initData[ "lastWeekGameTime" ] = 0 initData[ "updateTime" ] = skynet.GetTime() local packData = skynet.server.common:PackData( initData ) local redisDetailKey = string.format( redisKeyUrl.GameServerPersonalDetail , myPartnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( myPartnerId ) curPartnerRedis:hmset( redisDetailKey , table.unpack( packData )) --self:SetDetail( myPartnerId, table.unpack( packData )) self.listNewPartnerId[ myPartnerId ] = nil --玩家成功注册了,删除本地缓存 log.debug(string.format("玩家 %d 生成伙伴码 %s" , player.userId , myPartnerId)) break else self.listNewPartnerId[ myPartnerId ] = nil --已经有玩家注册了,删除本地缓存 end else log.info("随机出来相同的partnerId,重新生成" , myPartnerId , player.basicInfo.accountName ) end end end --检查是否有新的默认头像 function Personal:LoginInitData( player ) local cfgAllHead = skynet.server.gameConfig:GetPlayerAllCfg( player , "Head") local ownHeadIds = player.gameData.personal.ownHeadIds local ownHeadFrameIds = player.gameData.personal.ownHeadFrameIds for k, v in pairs( cfgAllHead ) do if dataType.HeadGainType_Default == v.obtainWay then if dataType.HeadType_Head == v.type then if not skynet.server.common:IsExist( v.id , ownHeadIds ) then --不存在该数据才会保存 self:ChangeGainInfo(player , dataType.GoodsType_HeadAndHeadFrame , v.id , dataType.HeadType_Head , skynet.server.personal.AddGoods) end elseif dataType.HeadType_Frame == v.type then if not skynet.server.common:IsExist( v.id , ownHeadFrameIds ) then --不存在该数据才会保存 self:ChangeGainInfo(player , dataType.GoodsType_HeadAndHeadFrame , v.id , dataType.HeadType_Frame , skynet.server.personal.AddGoods) end end end end local cfgAllTitle = skynet.server.gameConfig:GetPlayerAllCfg( player , "Title") local ownTitle1s = player.gameData.personal.ownTitle1s local ownTitle2s = player.gameData.personal.ownTitle2s for k, v in pairs( cfgAllTitle ) do if dataType.TitleGainType_Default == v.obtainWay then --不存在该数据才会保存 if dataType.TitleType_Adj == v.type and not skynet.server.common:IsExist( v.id , ownTitle1s ) then table.insert( player.gameData.personal.ownTitle1s , v.id ) elseif dataType.TitleType_Noun == v.type and not skynet.server.common:IsExist( v.id , ownTitle2s ) then table.insert( player.gameData.personal.ownTitle2s , v.id ) end end end local cfgAllBadge = skynet.server.gameConfig:GetPlayerAllCfg( player , "Badge") local ownMedals = player.gameData.personal.ownMedals for k, v in pairs( cfgAllBadge ) do if dataType.MedalGainType_Default == v.obtainWay then if not skynet.server.common:IsExist( v.id , ownMedals ) then --不存在该数据才会保存 table.insert( player.gameData.personal.ownMedals , v.id ) end end end end --个人特征展示 function Personal:Show( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPersonalShow", c2sData.data )) local data ={} --策划把45号头像配成了头像框,这里需要做一下兼容 local ownHeadIds = player.gameData.personal.ownHeadIds local ownHeadFrameIds = player.gameData.personal.ownHeadFrameIds for k, v in pairs( ownHeadFrameIds ) do if v == 45 then --如果存在45号关像框,就把它替换成头像 table.insert( ownHeadIds , 45 ) table.remove( ownHeadFrameIds , k ) break end end data.personalInfo = self:GetInfo( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_PersonalShow") s2cData.data = assert(pb.encode("S2CPersonalShow", data)) end --个人特征改变 function Personal:Change( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPersonalChange", c2sData.data )) local personalInfo = c2sData.data.personalInfo local data ={} if not personalInfo or not personalInfo.nickName or not personalInfo.clothesData or not personalInfo.colorData or #personalInfo.nickName > self.MaxNickNameLen then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif skynet.server.common:IsExistSpecialChar( personalInfo.nickName ) then s2cData.code = errorInfo.ErrorCode.ExistSpecialChar elseif skynet.server.common:IsMaskWords( personalInfo.nickName ) then s2cData.code = errorInfo.ErrorCode.ExistMaskWords else local isChangeClothes = false --衣服是否有变化 player.gameData.nickName = personalInfo.nickName local myPlayerId = player.gameData.partner.id self:SetDetail( myPlayerId ,"nickName", player.gameData.nickName) --更新服装数据 for k, goodsId in pairs( personalInfo.clothesData ) do local cfgClothes = nil if 0 ~= goodsId then cfgClothes = skynet.server.gameConfig:GetPlayerCurCfg( player , "Clothes" , goodsId ) end if ( 4 == k or 7 == k or 9 == k or 10 == k) and 0 == goodsId then --头饰,套装,耳饰,面饰可能为0,直接赋值就行 player.gameData.personal.clothesData[ k ] = goodsId elseif cfgClothes and k == cfgClothes.type and player:IsBuyGoods( dataType.GoodsType_Clothes , goodsId ) then --类型必须一致,并且玩家有该商品 player.gameData.personal.clothesData[ k ] = goodsId isChangeClothes = true end end if isChangeClothes then skynet.server.levelTask:Modify( player , 22 , 1 ) skynet.server.taskListEvent:Modify( player , 22 , 1 ) end --更新色彩数据 for k, v in pairs( personalInfo.colorData ) do --背包中没有该商品,并且商品id不等于0 if skynet.server.gameConfig:GetPlayerCurCfg( player , "Color", v ) then player.gameData.personal.colorData[ k ] = v end end local curInfo = self:GetInfo( player ) --个人特征改变,更新到redis local myPlayerId = player.gameData.partner.id self:SetDetail( myPlayerId ,"clothesData1", curInfo.clothesData[ dataType.ClothesType_Head ] ,"clothesData2", curInfo.clothesData[ dataType.ClothesType_Hair ] , "clothesData3", curInfo.clothesData[ dataType.ClothesType_Eyes ] ,"clothesData4", curInfo.clothesData[ dataType.ClothesType_HeadWear ] , "clothesData5", curInfo.clothesData[ dataType.ClothesType_Clothes ] ,"clothesData6", curInfo.clothesData[ dataType.ClothesType_Trousers ] , "clothesData7", curInfo.clothesData[ dataType.ClothesType_Suit ] ,"clothesData8", curInfo.clothesData[ dataType.ClothesType_Shoes ] , "clothesData9", curInfo.clothesData[ dataType.ClothesType_Earrings ] ,"clothesData10", curInfo.clothesData[ dataType.ClothesType_Facing ] , "colorData1" , curInfo.colorData[ 1 ] , "colorData2" , curInfo.colorData[ 2 ] ,"colorData3" , curInfo.colorData[ 3 ]) data.clothesData = player.gameData.personal.clothesData data.colorData = player.gameData.personal.colorData data.personalInfo = curInfo end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PersonalChange") s2cData.data = assert(pb.encode("S2CPersonalChange", data)) end --个人特征改变 function Personal:Rename( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPersonalRename", c2sData.data )) local nickName = c2sData.data.nickName local data ={} if not nickName or #nickName > self.MaxNickNameLen then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif skynet.server.common:IsExistSpecialChar( nickName ) then s2cData.code = errorInfo.ErrorCode.ExistSpecialChar elseif skynet.server.common:IsMaskWords( nickName ) then s2cData.code = errorInfo.ErrorCode.ExistMaskWords else player.gameData.nickName = nickName data.nickName = nickName local myPlayerId = player.gameData.partner.id self:SetDetail( myPlayerId ,"nickName", nickName) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PersonalRename") s2cData.data = assert(pb.encode("S2CPersonalRename", data)) end --个人获取资料 function Personal:GetData( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPersonalGetData", c2sData.data )) local data = {} data.curData = {} data.curData.partnerId = player.gameData.partner.id data.curData.nickName = player.gameData.nickName data.curData.headId = player.gameData.personal.headId data.curData.headFrameId = player.gameData.personal.headFrameId data.curData.level = player.gameData.level data.curData.exp = player.gameData.exp data.curData.title1 = player.gameData.personal.title1 data.curData.title2 = player.gameData.personal.title2 data.curData.medals = player.gameData.personal.medals data.curData.DIYHeadInfo = player.gameData.personal.diyHeadInfo data.curData.birthdayDate=player.gameData.personal.birthday.birthdayDate data.ownData = {} data.ownData.headIds = player.gameData.personal.ownHeadIds data.ownData.headFrameIds = player.gameData.personal.ownHeadFrameIds data.ownData.title1s = player.gameData.personal.ownTitle1s data.ownData.title2s = player.gameData.personal.ownTitle2s data.ownData.medals = player.gameData.personal.ownMedals data.ownData.gainPersonalInfos = player.gameData.personal.gainGoodsInfo skynet.server.msgTips:Reduce(player , 52) s2cData.cmd = pb.enum("MsgType","CMD_S2C_PersonalGetData") s2cData.data = assert(pb.encode("S2CPersonalGetData", data)) end --个人设置资料 function Personal:SetData( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPersonalSetData", c2sData.data )) local curData = c2sData.data.curData local data ={} if not curData or #curData.nickName > self.MaxNickNameLen then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif skynet.server.common:IsExistSpecialChar( curData.nickName ) then s2cData.code = errorInfo.ErrorCode.ExistSpecialChar elseif skynet.server.common:IsMaskWords( curData.nickName ) then s2cData.code = errorInfo.ErrorCode.ExistMaskWords else player.gameData.nickName = curData.nickName player.gameData.personal.headId = curData.headId player.gameData.personal.headFrameId = curData.headFrameId player.gameData.personal.title1 = curData.title1 player.gameData.personal.title2 = curData.title2 player.gameData.personal.medals = curData.medals local myPartnerId = player.gameData.partner.id self:SetDetail( myPartnerId , "nickName" , player.gameData.nickName or "" , "headId" , player.gameData.personal.headId or 1 , "headFrameId" , player.gameData.personal.headFrameId or 0, "title1" , player.gameData.personal.title1 or 0, "title2" , player.gameData.personal.title2 or 0, "medals1" , curData.medals[1] or 0, "medals2" , curData.medals[2] or 0, "medals3" , curData.medals[3] or 0 ) --这几种数据无法修改 curData.partnerId = player.gameData.partner.id curData.level = player.gameData.level curData.exp = player.gameData.exp --自定义头像由专门的协议接口修改 curData.DIYHeadInfo = player.gameData.personal.diyHeadInfo data.curData = curData end --data.nickName = curData.nickName s2cData.cmd = pb.enum("MsgType","CMD_S2C_PersonalSetData") s2cData.data = assert(pb.encode("S2CPersonalSetData", data)) end --获取个人详情 function Personal:GetDetail( partnerId ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --当前好友ID数据可能未迁移到新的redis,所以从旧的数据库去查找 curPartnerRedis = skynet.server.redisCenter:GetPartnerOldRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --完全没有好友信息,就直接返回null return nil end end local basicInfo = curPartnerRedis:hgetall(redisKey) basicInfo = redisKeyUrl:CovertTable(basicInfo) --自定义头像单独处理 if basicInfo.DIYHeadInfo ~= nil and basicInfo.DIYHeadInfo ~="" then basicInfo.DIYHeadInfo = json:decode(basicInfo.DIYHeadInfo) end basicInfo.medals = {} table.insert( basicInfo.medals , basicInfo.medals1 ) table.insert( basicInfo.medals , basicInfo.medals2 ) table.insert( basicInfo.medals , basicInfo.medals3 ) return basicInfo end --获取个人多个参数详情 function Personal:GetMulDetail( partnerId , ... ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then return nil end local value = curPartnerRedis:hmget(redisKey , ...) local newValue = {} for k, v in pairs( value ) do table.insert( newValue , redisKeyUrl:CovertValue(v) ) end return newValue end --获取个人单个参数详情 function Personal:GetCurDetail( partnerId , keyName ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --当前好友ID数据可能未迁移到新的redis,所以从旧的数据库去查找 curPartnerRedis = skynet.server.redisCenter:GetPartnerOldRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --完全没有好友信息,就直接返回null return nil end end local value = curPartnerRedis:hget(redisKey , keyName) return redisKeyUrl:CovertValue( value ) end --设置个人详情 function Personal:SetDetail( partnerId , ... ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --当前好友ID数据可能未迁移到新的redis,所以从旧的数据库去查找 curPartnerRedis = skynet.server.redisCenter:GetPartnerOldRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --完全没有好友信息,就直接返回null return nil end end curPartnerRedis:hmset( redisKey , "updateTime" , skynet.GetTime() , ... ) end --个人详情累加(整型数据才能操作) function Personal:AccDetail( partnerId , key , value ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --当前好友ID数据可能未迁移到新的redis,所以从旧的数据库去查找 curPartnerRedis = skynet.server.redisCenter:GetPartnerOldRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then --完全没有好友信息,就直接返回null return nil end end curPartnerRedis:hincrby( redisKey , key , tonumber(value) ) curPartnerRedis:hset( redisKey , "updateTime" , skynet.GetTime()) end --获取信息 function Personal:GetInfo( player ) local data = {} data.nickName = player.gameData.nickName data.clothesData = player.gameData.personal.clothesData data.colorData = player.gameData.personal.colorData return data end --增加拥有的各种信息 function Personal:AddOwnData( player , ownType , ownIds , newOwn ) local curData = player.gameData.personal if nil == ownIds then return end if "table" == type( ownIds ) then --如果传进来是个表,就遍历 for k, v in pairs( ownIds ) do --头衔需要根据ID获取下类型 if dataType.PersonalOwnType_Title1 == ownType or dataType.PersonalOwnType_Title2 == ownType then ownType = self:GetTitleOwnType( player , v ) end if ownType == dataType.PersonalOwnType_Head then self:ChangeGainInfo(player , dataType.GoodsType_HeadAndHeadFrame , v , dataType.HeadType_Head , skynet.server.personal.AddGoods) elseif ownType == dataType.PersonalOwnType_HeadFrame then self:ChangeGainInfo(player , dataType.GoodsType_HeadAndHeadFrame , v , dataType.HeadType_Frame , skynet.server.personal.AddGoods) elseif ownType == dataType.PersonalOwnType_Title1 then table.insert( curData.ownTitle1s , v ) elseif ownType == dataType.PersonalOwnType_Title2 then table.insert( curData.ownTitle2s , v ) elseif ownType == dataType.PersonalOwnType_Medal then table.insert( curData.ownMedals , v ) end table.insert( newOwn , { ownType = ownType , ownId = v }) end else if 0 == ownIds then return end if dataType.PersonalOwnType_Title1 == ownType or dataType.PersonalOwnType_Title2 == ownType then ownType = self:GetTitleOwnType( player , ownIds ) end if ownType == dataType.PersonalOwnType_Head then self:ChangeGainInfo(player , dataType.GoodsType_HeadAndHeadFrame , ownIds , dataType.HeadType_Head , skynet.server.personal.AddGoods) elseif ownType == dataType.PersonalOwnType_HeadFrame then self:ChangeGainInfo(player , dataType.GoodsType_HeadAndHeadFrame , ownIds , dataType.HeadType_Frame , skynet.server.personal.AddGoods) elseif ownType == dataType.PersonalOwnType_Title1 then table.insert( curData.ownTitle1s , ownIds ) elseif ownType == dataType.PersonalOwnType_Title2 then table.insert( curData.ownTitle2s , ownIds ) elseif ownType == dataType.PersonalOwnType_Medal then table.insert( curData.ownMedals , ownIds ) end table.insert( newOwn , { ownType = ownType , ownId = ownIds }) end end --获取头衔信息 function Personal:GetTitleOwnType( player , titleId ) local cfgOne = skynet.server.gameConfig:GetPlayerCurCfg( player , "Title" , titleId) if dataType.TitleType_Adj == cfgOne.type then return dataType.PersonalOwnType_Title1 elseif dataType.TitleType_Noun == cfgOne.type then return dataType.PersonalOwnType_Title2 end end --[[ --是否存在该玩家 function Personal:IsExist( partnerId ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then return false end return true end ]] --更新个人获取物品信息 function Personal:ChangeGainInfo( player , goodsType , goodsId , type , status ) if status == self.AddGoods then --先添加对应物品 if type == dataType.HeadType_Head then table.insert(player.gameData.personal.ownHeadIds , goodsId) elseif type == dataType.HeadType_Frame then table.insert(player.gameData.personal.ownHeadFrameIds , goodsId) end --再更新对应记录 table.insert(player.gameData.personal.gainGoodsInfo , {type = goodsType , id = goodsId , count = 1 , gainTime = skynet.GetTime()}) elseif status == self.DelGoods then --先移除对应物品 if type == dataType.HeadType_Head then for k ,v in pairs(player.gameData.personal.ownHeadIds) do if v == goodsId then table.remove(player.gameData.personal.ownHeadIds , k) break end end elseif type == dataType.HeadType_Frame then for k ,v in pairs(player.gameData.personal.ownHeadFrameIds) do if v == goodsId then table.remove(player.gameData.personal.ownHeadFrameIds , k) break end end end --再移除对应记录 for k ,v in pairs(player.gameData.personal.gainGoodsInfo) do if v.type == goodsType and v.id == goodsId then table.remove(player.gameData.personal.gainGoodsInfo , k) break end end end end --添加离线消息partnerId , msgType , data , retainTime , sendMailTime 分别为好友ID, 消息类型 ,消息数据, 保留时间, 发送邮件时间(如果该时间未到,暂时不删除该离线消息) function Personal:AddOfflineMsg( partnerId , msgType , data , retainTime , sendMailTime ) local msgData = {} msgData.type = msgType msgData.data = data retainTime = retainTime or 7 --如果没有指定保留时间,默认7天 retainTime = retainTime * dataType.OneDaySec msgData.outOfTime = skynet.GetTime() + retainTime msgData.sendMailTime = sendMailTime or 0 --0表示立即发送 local redisKey = string.format( redisKeyUrl.GameServerPersonalOfflineMsgList , partnerId ) skynet.server.redis:rpush( redisKey , json:encode( msgData )) skynet.server.redis:expire( redisKey , math.random( 60 * dataType.OneDaySec , 65 * dataType.OneDaySec ) ) --设置60天~65天过期时间 end --检查离线消息 function Personal:CheckOfflineMsg( player ) local myParentId = player.gameData.partner.id local redisKey = string.format( redisKeyUrl.GameServerPersonalOfflineMsgList , myParentId ) local allOfflineMsg = skynet.server.redis:lrange( redisKey , 0 , -1) local curTime = skynet.GetTime() local listNoDeleteOfflineMsg = {} --暂时不删除的离线消息 --对玩家的各种离线消息进行处理 for k, jsonData in pairs( allOfflineMsg ) do function Do() local msgData = json:decode( jsonData ) if curTime <= msgData.outOfTime then --在有效期内的离线消息才会被处理 local data = msgData.data if 0 ~= msgData.sendMailTime and curTime < msgData.sendMailTime then --未到指定时间,暂时不删除该离线消息 table.insert( listNoDeleteOfflineMsg, jsonData ) else if dataType.OfflineMsgType_ActivityDecoRankId == msgData.type then --周赛邮件 --周赛结算邮件 local rankRange = data.rankRange local rankRewardId = data.rankRewardId --发送邮件 local award = skynet.server.playerLand:GetRewardInfoNoPlayer( rankRewardId ) local content = string.format("感谢您参与本次的设计师周赛,您的排名位于此次参赛设计师的前%d" , math.floor( rankRange * 100)) .."%" .. ",奖励已随邮件发放,期待您的下次参与哦!" --由于有个百分号,只能采取拼接方式 skynet.server.mail:AddNewMail( player, skynet.server.mail.MailType_Award , "装修周赛奖励" , content , award) self:SetDetail( myParentId , "decoWeekRewardStatus" , dataType.DecoWeekRewardStatus_SendMail ) skynet.server.msgTips:ReduceAll( player , 122 ) --清除红点 elseif dataType.OfflineMsgType_DoubleSpaceDissolve == msgData.type then --双人空间解散 local removeFurnitures = data.removeFurnitures for k, goodsId in pairs( removeFurnitures ) do skynet.server.bag:RemovePutGoodsMaxCount( player , dataType.GoodsType_Furniture , goodsId , 1 ) log.debug(string.format("玩家 %d 双人空间场景 离线移除 家具ID %d " , player.userId , goodsId )) end elseif dataType.OfflineMsgType_AddMail == msgData.type then --新增游戏邮件 local mailData = data.mailData skynet.server.mail:AddNewMail(player, mailData.mailType, mailData.mailTitle, mailData.mailText, mailData.award, false ) elseif dataType.OfflineMsgType_PayFailed == msgData.type then --支付失败 local c2sData = {} local s2cData = {} c2sData.account = data.account c2sData.storeId = data.storeId c2sData.count = 1 skynet.server.gameServer:AddPayInfo( c2sData , s2cData ) local award = {} skynet.server.mail:AddNewMail( player , skynet.server.mail.MailType_Msg, "充值物品已到账", "亲爱的小蜗:\ 因一些异常情况,导致您之前购买的物品未能及时到货,现在为您补发,请小蜗注意查收~", award, true) log.debug(string.format("玩家 %s 从缓存中发放充值礼包 %d 数量 %d", data.account , data.storeId , data.count )) end end end return true end local isDo,callData = pcall( Do ) if not isDo then local errorText = string.format("Personal:CheckOfflineMsg 内部错误") log.warning( errorText , callData , player.basicInfo.accountName) end end --删除玩家所有的离线消息 skynet.server.redis:del(redisKey) --将不删除的离线消息重新保存到redis中 for k, jsonData in pairs( listNoDeleteOfflineMsg ) do skynet.server.redis:rpush( redisKey , jsonData ) skynet.server.redis:expire( redisKey , math.random( 60 * dataType.OneDaySec , 65 * dataType.OneDaySec ) ) --设置60天~65天过期时间 end end --是否存在Key function Personal:IsExistDetailKey( partnerId ) local redisKey = string.format( redisKeyUrl.GameServerPersonalDetail , partnerId ) local curPartnerRedis = skynet.server.redisCenter:GetPartnerRedis( partnerId ) if not curPartnerRedis:exists( redisKey ) then --如果在新的redis中不存在,就去旧的redis中查找 curPartnerRedis = skynet.server.redisCenter:GetPartnerOldRedis( partnerId ) if not curPartnerRedis:exists( redisKey) then return false end end return true end skynet.server.personal = Personal return Personal