Commit c384626d845578e857ce20618d5e7ede204dffbe

Authored by zhouhaihai
1 parent 679a1fc5

好友

@@ -72,6 +72,7 @@ ItemId = { @@ -72,6 +72,7 @@ ItemId = {
72 Exp = 2, -- 经验 72 Exp = 2, -- 经验
73 Diamond = 3, -- 钻石 73 Diamond = 3, -- 钻石
74 PlayerExp = 4, -- 突破材料 74 PlayerExp = 4, -- 突破材料
  75 + FriendPoint = 5, -- 友情点
75 BreakCost = 10, -- 突破材料 76 BreakCost = 10, -- 突破材料
76 EquipUp = 11, -- 装备升级材料 77 EquipUp = 11, -- 装备升级材料
77 DinerCoin = 12, --后勤物资 78 DinerCoin = 12, --后勤物资
src/ProtocolCode.lua
@@ -32,6 +32,8 @@ actionCodes = { @@ -32,6 +32,8 @@ actionCodes = {
32 Role_taskRpc = 117, 32 Role_taskRpc = 117,
33 Role_taskActiveRpc = 118, 33 Role_taskActiveRpc = 118,
34 Role_achiveRpc = 119, 34 Role_achiveRpc = 119,
  35 + Role_chatRpc = 120,
  36 + Role_chat = 121,
35 37
36 Adv_startAdvRpc = 151, 38 Adv_startAdvRpc = 151,
37 Adv_startHangRpc = 152, 39 Adv_startHangRpc = 152,
@@ -110,6 +112,20 @@ actionCodes = { @@ -110,6 +112,20 @@ actionCodes = {
110 Car_runeUpRpc = 402, 112 Car_runeUpRpc = 402,
111 Car_saleEquipRpc = 403, 113 Car_saleEquipRpc = 403,
112 Car_saleRuneRpc = 404, 114 Car_saleRuneRpc = 404,
  115 +
  116 +
  117 + Friend_searchRpc = 450,
  118 + Friend_applyRpc = 451,
  119 + Friend_applyListRpc = 452,
  120 + Friend_handleApplyRpc = 453,
  121 + Friend_listRpc = 454,
  122 + Friend_deleteRpc = 455,
  123 + Friend_blockRpc = 456,
  124 + Friend_blockListRpc = 457,
  125 + Friend_infoRpc = 458,
  126 + Friend_pointRpc = 459,
  127 + Friend_updateProperty = 460,
  128 + Friend_randomRpc = 461,
113 } 129 }
114 130
115 rpcResponseBegin = 10000 131 rpcResponseBegin = 10000
@@ -42,8 +42,13 @@ RANK_DINER_INFO = "rank:diner:info" @@ -42,8 +42,13 @@ RANK_DINER_INFO = "rank:diner:info"
42 -- BOSS_SET = "boss:%d:%d" 42 -- BOSS_SET = "boss:%d:%d"
43 -- BOSS_INFO = "boss:battle" 43 -- BOSS_INFO = "boss:battle"
44 44
45 --- FRIEND_KEY = "role:%d:friend" --哈希表  
46 --- FRIEND_APPLY_KEY = "role:%d:apply" -- set 45 +FRIEND_KEY = "role:%d:friend" --哈希表 好友
  46 +FRIEND_APPLY_KEY = "role:%d:apply" -- sort set 申请列表
  47 +FRIEND_BLACK_KEY = "role:%d:black" -- set 黑名单
  48 +FRIEND_POINT = "role:%d:point" -- set 当天送给我心的人
  49 +FRIEND_RECOMMEND = "friend:recommend" -- sort set 登录排序 获取推荐好友
  50 +
  51 +
47 -- FRIEND_DINER_LIKE_KEY = "role:%d:diner:like" -- list 52 -- FRIEND_DINER_LIKE_KEY = "role:%d:diner:like" -- list
48 53
49 -- UNION_SET = "global:union" 54 -- UNION_SET = "global:union"
src/actions/FriendAction.lua 0 → 100644
@@ -0,0 +1,630 @@ @@ -0,0 +1,630 @@
  1 +local ipairs = ipairs
  2 +local table = table
  3 +local math = math
  4 +local string = string
  5 +local redisproxy = redisproxy
  6 +local MsgPack = MsgPack
  7 +local string_format = string.format
  8 +local tonumber = tonumber
  9 +local table_insert = table.insert
  10 +local table_unpack = table.unpack
  11 +local table_find = table.find
  12 +local table_nums = table.nums
  13 +local math_random = math.randomInt
  14 +
  15 +local _M = {}
  16 +
  17 +local function formatArray(tb)
  18 + tb = tb or {}
  19 + local t = {}
  20 + for _, objectId in ipairs(tb) do
  21 + t[tonumber(objectId)] = 1
  22 + end
  23 + return t
  24 +end
  25 +
  26 +local function checkFriendLimit(roleId)
  27 + roleId = tonumber(roleId)
  28 + local count = redisproxy:hlen(FRIEND_KEY:format(roleId))
  29 + return count < globalCsv.friendListLimit
  30 +end
  31 +
  32 +
  33 +local function addAndCheckApplyLimit(roleId, objId)
  34 + roleId = tonumber(roleId)
  35 + local dbKey = FRIEND_APPLY_KEY:format(roleId)
  36 + local redret = redisproxy:pipelining(function (red)
  37 + red:zadd(dbKey, skynet.timex(), objId)
  38 + red:zremrangebyrank(dbKey, 0, -(globalCsv.friendApplyLimit + 1))
  39 + end)
  40 +end
  41 +
  42 +local function checkBlackLimit(roleId)
  43 + roleId = tonumber(roleId)
  44 + local count = redisproxy:scard(FRIEND_BLACK_KEY:format(roleId))
  45 + return count < globalCsv.friendListLimit
  46 +end
  47 +
  48 +local function getRoleInfo(roleId)
  49 + local online, info = rpcRole(roleId, "friendSInfo")
  50 + return online, info
  51 +end
  52 +
  53 +local function getRoleAllInfo(roleId)
  54 + local online, info = rpcRole(roleId, "friendInfo")
  55 + return online, info
  56 +end
  57 +
  58 +local function table_merge(tab1, tab2, filter)
  59 + tab1 = tab1 or {}
  60 + tab2 = tab2 or {}
  61 + filter = filter or {}
  62 + for k_, v_ in pairs(tab2) do
  63 + if not filter[k_] then
  64 + tab1[k_] = v_
  65 + end
  66 + end
  67 + return tab1
  68 +end
  69 +
  70 +function _M.searchRpc(agent, data)
  71 + local role = agent.role
  72 + local roleId = role:getProperty("id")
  73 + local msg = MsgPack.unpack(data)
  74 + local key = msg.key
  75 +
  76 + if not key then return end
  77 +
  78 + local objIds = {}
  79 + local tempId = tonumber(key)
  80 + if tempId then
  81 + if redisproxy:exists(string_format("role:%d", tempId)) then
  82 + objIds[tempId] = 1
  83 + end
  84 + end
  85 + local tempId = redisproxy:get(string_format("user:%s", string.upper(key)))
  86 + if tempId then
  87 + objIds[tonumber(tempId)] = 1
  88 + end
  89 + objIds[roleId] = nil --不能有自己
  90 +
  91 + local searchList = {}
  92 + for objId, _ in pairs(objIds) do
  93 + local online, info = getRoleInfo(objId)
  94 + local redret = redisproxy:pipelining(function (red)
  95 + red:hexists(FRIEND_KEY:format(roleId), objId)
  96 + red:zscore(FRIEND_APPLY_KEY:format(objId), roleId)
  97 + red:sismember(FRIEND_BLACK_KEY:format(roleId), objId)
  98 + end)
  99 + local isFriend = redret[1] == 1 and 1 or nil
  100 + local hadApply = redret[2] and 1 or nil
  101 + local inBlack = redret[3] == 1 and 1 or nil
  102 +
  103 + table.insert(searchList, table_merge({
  104 + roleId = objId,
  105 + online = online,
  106 + isFriend = isFriend,
  107 + hadApply = hadApply,
  108 + inBlack = inBlack,
  109 + }, info, {
  110 +
  111 + }))
  112 + end
  113 + SendPacket(actionCodes.Friend_searchRpc, MsgPack.pack({searchList = searchList}))
  114 + return true
  115 +end
  116 +
  117 +
  118 +function _M.applyRpc(agent, data)
  119 + local role = agent.role
  120 + local roleId = role:getProperty("id")
  121 +
  122 + local msg = MsgPack.unpack(data)
  123 + local objectId = msg.roleId
  124 +
  125 + if objectId == roleId then
  126 + return
  127 + end
  128 +
  129 + local result = nil
  130 + local redret = redisproxy:pipelining(function (red)
  131 + red:exists(string_format("role:%d", objectId))
  132 + red:hexists(FRIEND_KEY:format(roleId), objectId)
  133 + red:zscore(FRIEND_APPLY_KEY:format(objectId), roleId)
  134 + red:sismember(FRIEND_BLACK_KEY:format(objectId), roleId)
  135 + red:sismember(FRIEND_BLACK_KEY:format(roleId), objectId)
  136 + red:hlen(FRIEND_KEY:format(roleId))
  137 + red:hlen(FRIEND_KEY:format(objectId))
  138 + end)
  139 + -- 玩家id不存在
  140 + if not result and redret[1] ~= 1 then
  141 + result = 1
  142 + end
  143 +
  144 + -- 已经有这个好友
  145 + if not result and redret[2] == 1 then
  146 + result = 2
  147 + end
  148 + -- 已经申请
  149 + if not result and redret[3] then
  150 + result = 3
  151 + end
  152 + -- 对方把你拉黑
  153 + if not result and redret[4] == 1 then
  154 + result = 4
  155 + end
  156 +
  157 + -- 你把对方拉黑了
  158 + if not result and redret[4] == 1 then
  159 + result = 5
  160 + end
  161 +
  162 + -- 自己好友已经满
  163 + if not result and redret[6] >= globalCsv.friendListLimit then
  164 + result = 6
  165 + end
  166 + -- 对方的好友已满
  167 + if not result and redret[7] >= globalCsv.friendListLimit then
  168 + result = 7
  169 + end
  170 +
  171 + if not result then
  172 + addAndCheckApplyLimit(objectId, roleId)
  173 + local myInfo = role:friendSInfo()
  174 + myInfo.roleId = roleId
  175 + myInfo.online = true
  176 + myInfo.hadApply = true
  177 + rpcRole(objectId, "SendPacket", actionCodes.Friend_updateProperty, MsgPack.pack({newApply = 1, info = {myInfo}})) -- 通知对方
  178 + end
  179 + SendPacket(actionCodes.Friend_applyRpc, MsgPack.pack({result = result}))
  180 + return true
  181 +end
  182 +
  183 +function _M.applyListRpc(agent, data)
  184 + local role = agent.role
  185 + local roleId = role:getProperty("id")
  186 +
  187 + local applyList = {}
  188 +
  189 + local friends = redisproxy:zrange(FRIEND_APPLY_KEY:format(roleId), 0, -1)
  190 + for _ , id in pairs(friends) do
  191 + id = tonumber(id)
  192 + local online, info = getRoleInfo(id)
  193 + table.insert(applyList, table_merge({
  194 + roleId = id, online = online
  195 + }, info, {
  196 +
  197 + }))
  198 + end
  199 + SendPacket(actionCodes.Friend_applyListRpc, MsgPack.pack({list = applyList}))
  200 + return true
  201 +end
  202 +
  203 +local function checkHandleApply(roleId, objectId)
  204 + local result = nil
  205 + local redret = redisproxy:pipelining(function (red)
  206 + red:hlen(FRIEND_KEY:format(roleId))
  207 + red:hlen(FRIEND_KEY:format(objectId))
  208 + red:sismember(FRIEND_BLACK_KEY:format(objectId), roleId)
  209 + red:sismember(FRIEND_BLACK_KEY:format(roleId), objectId)
  210 + end)
  211 + --自己好友满了
  212 + if not result and redret[1] >= globalCsv.friendListLimit then
  213 + result = 1
  214 + end
  215 + -- 对方好友满了
  216 + if not result and redret[2] >= globalCsv.friendListLimit then
  217 + result = 2
  218 + end
  219 + -- 对方把你拉黑
  220 + if not result and redret[3] == 1 then
  221 + result = 3
  222 + end
  223 + -- 你把对方拉黑了
  224 + if not result and redret[4] == 1 then
  225 + result = 4
  226 + end
  227 + return result
  228 +end
  229 +
  230 +function _M.handleApplyRpc(agent, data)
  231 + local role = agent.role
  232 + local roleId = role:getProperty("id")
  233 +
  234 + local msg = MsgPack.unpack(data)
  235 + local cmd = msg.cmd
  236 +
  237 + local newTag = MsgPack.pack({ skynet.timex(), 1})
  238 + local result = nil
  239 + if cmd == 1 then --同意
  240 +
  241 + local objectId = msg.roleId
  242 +
  243 + if not redisproxy:zscore(FRIEND_APPLY_KEY:format(roleId), objectId) then
  244 + return
  245 + end
  246 + result = checkHandleApply(roleId, objectId)
  247 +
  248 + if not result then
  249 + redisproxy:pipelining(function (red)
  250 + red:ZREM(FRIEND_APPLY_KEY:format(roleId), objectId)
  251 + red:ZREM(FRIEND_APPLY_KEY:format(objectId), roleId)
  252 + red:hsetnx(FRIEND_KEY:format(roleId), objectId, newTag)
  253 + red:hsetnx(FRIEND_KEY:format(objectId), roleId, newTag)--告知对放有新好友
  254 + end)
  255 + local myInfo = role:friendSInfo()
  256 + myInfo.online = true
  257 + myInfo.roleId = roleId
  258 + myInfo.isFriend = 1
  259 + local redret = redisproxy:pipelining(function (red)
  260 + red:sismember(FRIEND_POINT:format(objectId), roleId)
  261 + red:sismember(FRIEND_POINT:format(roleId), objectId)
  262 + end)
  263 + myInfo.pGet = redret[1] == 1 and 1 or nil
  264 + rpcRole(objectId, "SendPacket", actionCodes.Friend_updateProperty, MsgPack.pack({newFriend = 1, info = {myInfo}})) -- 通知对方
  265 + local online , otherInfo = getRoleInfo(objectId)
  266 + otherInfo.roleId = objectId
  267 + otherInfo.online = online
  268 + otherInfo.isFriend = true
  269 + otherInfo.pGet = redret[2] == 1 and 1 or nil
  270 + SendPacket(actionCodes.Friend_updateProperty, MsgPack.pack({newFriend = 1, info = {otherInfo}}))
  271 + end
  272 +
  273 + elseif cmd == 0 then -- 不同意
  274 + local objectId = msg.roleId
  275 + if not redisproxy:zscore(FRIEND_APPLY_KEY:format(roleId), objectId) then
  276 + return
  277 + end
  278 + redisproxy:ZREM(FRIEND_APPLY_KEY:format(roleId), objectId)
  279 + elseif cmd == 2 then -- 一键拒绝
  280 + redisproxy:del(FRIEND_APPLY_KEY:format(roleId))
  281 + elseif cmd == 3 then -- 一键同意
  282 + local redret = redisproxy:pipelining(function(red)
  283 + red:zrange(FRIEND_APPLY_KEY:format(roleId))
  284 + red:SMEMBERS(FRIEND_POINT:format(roleId))
  285 + end)
  286 + local allIds = redret[1]
  287 + local fpoint = formatArray(redret[2])
  288 + local needAdd = {}
  289 + local needAddMy = {}
  290 + local needAddInfo = {}
  291 + for _, objId in ipairs(allIds) do
  292 + objId = tonumber(objId)
  293 + local cr = checkHandleApply(roleId, objId)
  294 + if not cr then
  295 + table.insert(needAdd, objId)
  296 + table.insert(needAddMy, objId)
  297 + table.insert(needAddMy, newTag)
  298 + local online, otherInfo = getRoleInfo(objId)
  299 + otherInfo.online = true
  300 + otherInfo.roleId = objId
  301 + otherInfo.isFriend = true
  302 + otherInfo.pGet = fpoint[objId] and 1 or nil
  303 + table.insert(needAddInfo, otherInfo)
  304 + end
  305 + end
  306 +
  307 + redisproxy:pipelining(function (red)
  308 + red:ZREM(FRIEND_APPLY_KEY:format(roleId), table_unpack(needAdd))
  309 + red:hsetnx(FRIEND_KEY:format(roleId), table_unpack(needAddMy))
  310 + for _, objectId in pairs(needAdd) do
  311 + red:ZREM(FRIEND_APPLY_KEY:format(objectId), roleId)
  312 + red:hsetnx(FRIEND_KEY:format(objectId), roleId, newTag)--告知对放有新好友
  313 + end
  314 + end)
  315 + local myInfo = role:friendSInfo()
  316 + myInfo.roleId = roleId
  317 + myInfo.online = true
  318 + myInfo.isFriend = 1
  319 + local giveFP = role.dailyData:getProperty("giveFP")
  320 + for _, objectId in pairs(needAdd) do
  321 + myInfo.pGet = giveFP[objectId]
  322 + rpcRole(objectId, "SendPacket", actionCodes.Friend_updateProperty, MsgPack.pack({newFriend = 1, info = {myInfo}})) -- 通知对方
  323 + end
  324 + if next(needAdd) then
  325 + SendPacket(actionCodes.Friend_updateProperty, MsgPack.pack({newFriend = 1, info = needAddInfo}))
  326 + else
  327 + result = 1
  328 + end
  329 +
  330 + else --不存在
  331 + return
  332 + end
  333 +
  334 + SendPacket(actionCodes.Friend_handleApplyRpc, MsgPack.pack({result = result}))
  335 + return true
  336 +end
  337 +
  338 +function _M.listRpc(agent, data)
  339 + local role = agent.role
  340 + local roleId = role:getProperty("id")
  341 +
  342 + local friendList = {}
  343 + local redret = redisproxy:pipelining(function (red)
  344 + red:hgetall(FRIEND_KEY:format(roleId))
  345 + red:SMEMBERS(FRIEND_POINT:format(roleId))
  346 + end)
  347 +
  348 + local friends = redret[1]
  349 + local fpoint = formatArray(redret[2])
  350 + local hadGet = role.dailyData:getProperty("getFP")
  351 + local hadGive = role.dailyData:getProperty("giveFP")
  352 +
  353 + local clearRed = {}
  354 + for i = 1, #friends, 2 do
  355 + local id = friends[i]
  356 + local data = friends[i + 1]
  357 + local friendInfo = MsgPack.unpack(data)
  358 + id = tonumber(id)
  359 + local online, info = getRoleInfo(id)
  360 + local roleInfo = {
  361 + roleId = id,
  362 + online = online,
  363 + addTime = friendInfo[1],
  364 + isNew = friendInfo[2],
  365 + pGive = hadGive[id],
  366 + pGet = hadGet[id] and -1 or (fpoint[id] and 1 or nil)
  367 + }
  368 + roleInfo = table_merge(roleInfo, info, {})
  369 +
  370 + friendList[#friendList + 1] = roleInfo
  371 +
  372 + if friendInfo[2] then
  373 + friendInfo[2] = nil --清除新好友标记
  374 + clearRed[#clearRed + 1] = id
  375 + clearRed[#clearRed + 1] = MsgPack.pack(friendInfo)
  376 + end
  377 + end
  378 + if next(clearRed) then
  379 + redisproxy:hmset(FRIEND_KEY:format(roleId), table_unpack(clearRed)) --清除新好友标记
  380 + end
  381 +
  382 + SendPacket(actionCodes.Friend_listRpc, MsgPack.pack({list = friendList}))
  383 + return true
  384 +end
  385 +
  386 +function _M.deleteRpc(agent, data)
  387 + local role = agent.role
  388 + local roleId = role:getProperty("id")
  389 + local msg = MsgPack.unpack(data)
  390 + local objectId = msg.roleId
  391 + if not redisproxy:exists(string_format("role:%d", objectId)) then
  392 + return
  393 + end
  394 + -- 是否在好友列表中
  395 + if redisproxy:hexists(FRIEND_KEY:format(roleId), objectId) then
  396 + redisproxy:pipelining(function (red)
  397 + red:hdel(FRIEND_KEY:format(roleId), objectId)
  398 + red:hdel(FRIEND_KEY:format(objectId), roleId)
  399 + red:ZREM(FRIEND_APPLY_KEY:format(roleId), objectId)
  400 + red:ZREM(FRIEND_APPLY_KEY:format(objectId), roleId)
  401 + end)
  402 + end
  403 + rpcRole(objectId, "SendPacket", actionCodes.Friend_updateProperty, MsgPack.pack({deleteFriend = 1, roleId = roleId}))
  404 +
  405 + SendPacket(actionCodes.Friend_deleteRpc, MsgPack.pack(""))
  406 + return true
  407 +end
  408 +
  409 +function _M.blockRpc(agent, data)
  410 + local role = agent.role
  411 + local roleId = role:getProperty("id")
  412 + local msg = MsgPack.unpack(data)
  413 + local cmd = msg.cmd
  414 + local objectId = msg.roleId
  415 + if not redisproxy:exists(string_format("role:%d", objectId)) then
  416 + return
  417 + end
  418 +
  419 + local result = nil
  420 + if cmd == 1 then
  421 + -- 黑名单满了
  422 + if not result and not checkBlackLimit(roleId) then
  423 + result = 1
  424 + end
  425 + -- 删除好友
  426 + if not result then
  427 + redisproxy:pipelining(function (red)
  428 + red:hdel(FRIEND_KEY:format(roleId), objectId)
  429 + red:hdel(FRIEND_KEY:format(objectId), roleId)
  430 + red:sadd(FRIEND_BLACK_KEY:format(roleId), objectId)
  431 + end)
  432 + end
  433 + elseif cmd == 2 then
  434 + redisproxy:SREM(FRIEND_BLACK_KEY:format(roleId), objectId)
  435 + else
  436 + return
  437 + end
  438 +
  439 + SendPacket(actionCodes.Friend_blockRpc, MsgPack.pack({result = result}))
  440 + return true
  441 +end
  442 +
  443 +function _M.blockListRpc(agent, data)
  444 + local role = agent.role
  445 + local roleId = role:getProperty("id")
  446 +
  447 + local blockList = {}
  448 +
  449 + local friends = redisproxy:SMEMBERS(FRIEND_BLACK_KEY:format(roleId))
  450 + for _ , id in pairs(friends) do
  451 + id = tonumber(id)
  452 + local online, info = getRoleInfo(id)
  453 + table.insert(blockList, table_merge({
  454 + roleId = id, online = online
  455 + }, info, {
  456 +
  457 + }))
  458 + end
  459 + SendPacket(actionCodes.Friend_blockListRpc, MsgPack.pack({list = blockList}))
  460 + return true
  461 +end
  462 +
  463 +function _M.infoRpc(agent, data)
  464 + local role = agent.role
  465 + local roleId = role:getProperty("id")
  466 + local msg = MsgPack.unpack(data)
  467 + local objectId = msg.roleId
  468 + if not redisproxy:exists(string_format("role:%d", objectId)) then
  469 + return
  470 + end
  471 +
  472 + local online, info = getRoleAllInfo(objectId)
  473 + local redret = redisproxy:pipelining(function (red)
  474 + red:hexists(FRIEND_KEY:format(roleId), objectId)
  475 + red:zscore(FRIEND_APPLY_KEY:format(objectId), roleId)
  476 + red:sismember(FRIEND_BLACK_KEY:format(roleId), objectId)
  477 + end)
  478 + local isFriend = redret[1] == 1 and 1 or nil
  479 + local hadApply = redret[2] == 1 and 1 or nil
  480 + local inBlack = redret[3] == 1 and 1 or nil
  481 +
  482 + local objInfo = table_merge({
  483 + roleId = objectId,
  484 + online = online,
  485 + isFriend = isFriend,
  486 + hadApply = hadApply,
  487 + inBlack = inBlack,
  488 + }, info, {
  489 +
  490 + })
  491 + SendPacket(actionCodes.Friend_infoRpc, MsgPack.pack({info = objInfo}))
  492 + return true
  493 +end
  494 +
  495 +function _M.pointRpc(agent, data)
  496 + local role = agent.role
  497 + local roleId = role:getProperty("id")
  498 + local msg = MsgPack.unpack(data)
  499 + local cmd = msg.cmd
  500 + local result = nil
  501 + local reward = {}
  502 + if cmd == 1 then -- 赠送
  503 + local objId = msg.roleId
  504 + local giveP = role.dailyData:getProperty("giveFP")
  505 + if not result and giveP[objId] then
  506 + result = 1
  507 + end
  508 + if not result and not redisproxy:hexists(FRIEND_KEY:format(roleId), objId) then
  509 + result = 2
  510 + end
  511 + if not result then
  512 + redisproxy:sadd(FRIEND_POINT:format(objId), roleId)
  513 + giveP[objId] = 1
  514 + role.dailyData:updateProperty({field = "giveFP", value = giveP})
  515 + rpcRole(objId, "SendPacket", actionCodes.Friend_updateProperty, MsgPack.pack({newPoint = 1, roleId = roleId}))
  516 + end
  517 + elseif cmd == 2 then -- 领取
  518 + local objId = msg.roleId
  519 + local getP = role.dailyData:getProperty("getFP")
  520 + if not result and table.numbers(getP) >= globalCsv.friendPointLimit then
  521 + result = 1
  522 + end
  523 + if not result and getP[objId] then
  524 + result = 2
  525 + end
  526 + if not redisproxy:sismember(FRIEND_POINT:format(roleId), objId) then
  527 + result = 3
  528 + end
  529 + if not result then
  530 + getP[objId] = 1
  531 + reward = role:award({[ItemId.FriendPoint] = 1})
  532 + role.dailyData:updateProperty({field = "getFP", value = getP})
  533 + end
  534 + elseif cmd == 3 then -- 一键赠送领取
  535 + -- 赠送
  536 + local giveP = role.dailyData:getProperty("giveFP")
  537 + local friends = redisproxy:hgetall(FRIEND_KEY:format(roleId))
  538 + local change = false
  539 + redisproxy:pipelining(function(red)
  540 + for i = 1, #friends , 2 do
  541 + local objId = tonumber(friends[i])
  542 + if not giveP[objId] then
  543 + giveP[objId] = 1
  544 + change = true
  545 + red:sadd(FRIEND_POINT:format(objId), roleId)
  546 + rpcRole(objId, "SendPacket", actionCodes.Friend_updateProperty, MsgPack.pack({newPoint = 1, roleId = roleId}))
  547 + end
  548 + end
  549 + end)
  550 + if change then
  551 + role.dailyData:updateProperty({field = "giveFP", value = giveP})
  552 + else
  553 + result = 1
  554 + end
  555 +
  556 + --领取
  557 + local getP = role.dailyData:getProperty("getFP")
  558 + local curCount = table.numbers(getP)
  559 + local getCount = 0
  560 + if curCount < globalCsv.friendPointLimit then
  561 + for _, objId in pairs(redisproxy:SMEMBERS(FRIEND_POINT:format(roleId))) do
  562 + local objId = tonumber(objId)
  563 + if not getP[objId] then
  564 + getCount = getCount + 1
  565 + curCount = curCount + 1
  566 + getP[objId] = 1
  567 + if curCount >= globalCsv.friendPointLimit then
  568 + break
  569 + end
  570 + end
  571 + end
  572 + if getCount > 0 then
  573 + reward = role:award({[ItemId.FriendPoint] = getCount})
  574 + role.dailyData:updateProperty({field = "getFP", value = getP})
  575 + else
  576 + result = result + 2
  577 + end
  578 + end
  579 + else
  580 + return
  581 + end
  582 + SendPacket(actionCodes.Friend_pointRpc, MsgPack.pack({result = result, reward = reward}))
  583 + return true
  584 +end
  585 +function _M.randomRpc(agent, data)
  586 + local role = agent.role
  587 + local roleId = role:getProperty("id")
  588 +
  589 + local redret = redisproxy:pipelining(function (red)
  590 + red:hgetall(FRIEND_KEY:format(roleId))
  591 + red:zrevrange(FRIEND_RECOMMEND, 0, globalCsv.friendRecommendLimit + globalCsv.friendListLimit)
  592 + end)
  593 +
  594 + local friends = redret[1]
  595 + local newList = redret[2]
  596 + local needRoleIds = {}
  597 + for _, newId in pairs(newList) do
  598 + local numNewId = tonumber(newId)
  599 + if numNewId ~= roleId and not friends[newId] then
  600 + table.insert(needRoleIds, numNewId)
  601 + end
  602 + end
  603 +
  604 + local randomRoles = {}
  605 + for _, objId in ipairs(needRoleIds) do
  606 + local online, info = getRoleInfo(objId)
  607 + local redret = redisproxy:pipelining(function (red)
  608 + red:zscore(FRIEND_APPLY_KEY:format(objId), roleId)
  609 + red:sismember(FRIEND_BLACK_KEY:format(roleId), objId)
  610 + end)
  611 + local hadApply = redret[1] and 1 or nil
  612 + local inBlack = redret[2] == 1 and 1 or nil
  613 +
  614 + table.insert(randomRoles, table_merge({
  615 + roleId = objId,
  616 + online = online,
  617 + hadApply = hadApply,
  618 + inBlack = inBlack,
  619 + }, info, {
  620 +
  621 + }))
  622 + if #randomRoles >= globalCsv.friendRecommendLimit then break end
  623 + end
  624 +
  625 + SendPacket(actionCodes.Friend_randomRpc, MsgPack.pack({list = randomRoles}))
  626 + return true
  627 +end
  628 +
  629 +
  630 +return _M
0 \ No newline at end of file 631 \ No newline at end of file
src/actions/RoleAction.lua
@@ -122,7 +122,7 @@ function _M.loginRpc( agent, data ) @@ -122,7 +122,7 @@ function _M.loginRpc( agent, data )
122 role:onCrossDay(now) 122 role:onCrossDay(now)
123 role:onResetRank(now) 123 role:onResetRank(now)
124 role:setProperty("ltime", now) 124 role:setProperty("ltime", now)
125 - 125 + redisproxy:zadd(FRIEND_RECOMMEND, now, roleId)
126 126
127 for _, name in ipairs({"dailyData", "dinerData"}) do 127 for _, name in ipairs({"dailyData", "dinerData"}) do
128 response[name] = role[name]:data() 128 response[name] = role[name]:data()
@@ -161,7 +161,7 @@ function _M.loginRpc( agent, data ) @@ -161,7 +161,7 @@ function _M.loginRpc( agent, data )
161 end 161 end
162 end 162 end
163 163
164 - response.wave = 1 + heroWave + runeWave 164 + response.wave = 1 + heroWave + runeWave + 1
165 165
166 SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response)) 166 SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))
167 167
@@ -213,10 +213,24 @@ function _M.loginRpc( agent, data ) @@ -213,10 +213,24 @@ function _M.loginRpc( agent, data )
213 start_agent_timer() 213 start_agent_timer()
214 -- 注册全服广播 214 -- 注册全服广播
215 local channel = math.randomInt(1, 1) 215 local channel = math.randomInt(1, 1)
  216 + role._channelIdx = channel
216 local w_channel = datacenter.get( ("MC_W_CHANNEL" .. channel) ) 217 local w_channel = datacenter.get( ("MC_W_CHANNEL" .. channel) )
217 if w_channel then 218 if w_channel then
218 mcast_util.sub_world(w_channel) 219 mcast_util.sub_world(w_channel)
219 end 220 end
  221 +
  222 + -- 发下缓存的世界消息
  223 + local worldChatResponse = {worldChats = {}}
  224 + local ok, msgs = pcall(skynet.call, 'GLOBALD', "lua", "getWorldMsg", channel)
  225 + if not ok then
  226 + msgs = {}
  227 + end
  228 + worldChatResponse.worldChats = msgs
  229 + worldChatResponse.chatWave = curWave + 1
  230 + curWave = curWave + 1
  231 +
  232 + SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(worldChatResponse))
  233 +
220 return true 234 return true
221 end 235 end
222 236
@@ -352,7 +366,7 @@ function _M.openTimeBoxRpc(agent, data) @@ -352,7 +366,7 @@ function _M.openTimeBoxRpc(agent, data)
352 local itemId = msg.itemId 366 local itemId = msg.itemId
353 if role:getItemCount(itemId) < 1 then return end 367 if role:getItemCount(itemId) < 1 then return end
354 local itemData = csvdb["itemCsv"][itemId] 368 local itemData = csvdb["itemCsv"][itemId]
355 - local randomData = csvdb["item_randomCsv"][tonumber(itemData.use_effect)] 369 + local randomData = csvdb["item_randomCsv"][itemId]
356 if not randomData or randomData.openTime <= 0 then return end 370 if not randomData or randomData.openTime <= 0 then return end
357 371
358 if boxL[slot] then return end 372 if boxL[slot] then return end
@@ -364,7 +378,7 @@ function _M.openTimeBoxRpc(agent, data) @@ -364,7 +378,7 @@ function _M.openTimeBoxRpc(agent, data)
364 if not boxL[slot] then return end 378 if not boxL[slot] then return end
365 if boxL[slot].gem or boxL[slot].time <= skynet.timex() then return end 379 if boxL[slot].gem or boxL[slot].time <= skynet.timex() then return end
366 local itemData = csvdb["itemCsv"][boxL[slot].id] 380 local itemData = csvdb["itemCsv"][boxL[slot].id]
367 - local randomData = csvdb["item_randomCsv"][tonumber(itemData.use_effect)] 381 + local randomData = csvdb["item_randomCsv"][itemId]
368 local num = randomData[gemId .. "_gem_num"] 382 local num = randomData[gemId .. "_gem_num"]
369 if not num then return end 383 if not num then return end
370 384
@@ -383,7 +397,7 @@ function _M.openTimeBoxRpc(agent, data) @@ -383,7 +397,7 @@ function _M.openTimeBoxRpc(agent, data)
383 end 397 end
384 398
385 local itemData = csvdb["itemCsv"][boxL[slot].id] 399 local itemData = csvdb["itemCsv"][boxL[slot].id]
386 - local randomData = csvdb["item_randomCsv"][tonumber(itemData.use_effect)] 400 + local randomData = csvdb["item_randomCsv"][itemId]
387 reward = randomData.gift:toNumMap() -- 固定奖励 401 reward = randomData.gift:toNumMap() -- 固定奖励
388 -- 随机奖励 402 -- 随机奖励
389 local randomGift = randomData.random_gift 403 local randomGift = randomData.random_gift
@@ -551,5 +565,73 @@ function _M.achiveRpc(agent, data) @@ -551,5 +565,73 @@ function _M.achiveRpc(agent, data)
551 return true 565 return true
552 end 566 end
553 567
  568 +function _M.chatRpc(agent, data)
  569 + local role = agent.role
  570 + local roleId = role:getProperty("id")
  571 + local msg = MsgPack.unpack(data)
  572 +
  573 + local cmd = msg.cmd
  574 + local content = msg.content
  575 +
  576 + if not content then return end
  577 +
  578 + local now = skynet.timex()
  579 + -- 判断禁言
  580 + local result = nil
  581 +
  582 + local SERV = string_format("CHATED%d", math.random(1, 5))
  583 + local legal, mod = skynet.call(SERV, "lua", "check", content)
  584 + if not legal then
  585 + content = mod or ""
  586 + end
  587 +
  588 + if content == "" then
  589 + result = -1
  590 + end
  591 +
  592 + local response = {
  593 + chatType = cmd,
  594 + player = {
  595 + roleId = role:getProperty("id"),
  596 + name = role:getProperty("name"),
  597 + level = role:getProperty("level"),
  598 + headId = role:getProperty("headId"),
  599 + },
  600 + content = content,
  601 + time = now,
  602 + }
  603 +
  604 + local check = {
  605 + ["world"] = function ()
  606 + if role:getProperty("silent") > now then --禁言
  607 + result = 1
  608 + return
  609 + end
  610 + mcast_util.pub_world(actionCodes.Role_chat, MsgPack.pack(response))
  611 + pcall(skynet.call, 'GLOBALD', "lua", "sendWorldMsg", role._channelIdx, response)
  612 + end,
  613 + ["p2p"] = function ()
  614 + -- local result
  615 + -- local objectId = msg.objectId
  616 + -- if redisproxy:hexists(FRIEND_KEY:format(roleId), objectId) then
  617 + -- response.to = objectId
  618 + -- result = mcast_util.pub_person(agent.client_fd, objectId, actionCodes.Role_chat, MsgPack.pack(response))
  619 + -- else
  620 + -- result = SYS_ERR_CHAT_NOT_FRIEND
  621 + -- end
  622 + -- if result then
  623 + -- role:sendSysErrMsg(result)
  624 + -- end
  625 + end,
  626 + }
  627 + if not check[cmd] then return end
  628 +
  629 + if not result then
  630 + check[cmd]()
  631 + end
  632 + SendPacket(actionCodes.Role_chatRpc, MsgPack.pack({result = result}))
  633 + return true
  634 +end
  635 +
554 636
555 return _M 637 return _M
556 \ No newline at end of file 638 \ No newline at end of file
@@ -140,6 +140,11 @@ function rpcRole(roleId, funcName, ...) @@ -140,6 +140,11 @@ function rpcRole(roleId, funcName, ...)
140 result[#result+1] = v 140 result[#result+1] = v
141 end 141 end
142 return false, redisproxy:hmset(rediskey, table_unpack(result)) 142 return false, redisproxy:hmset(rediskey, table_unpack(result))
  143 + elseif funcName == "friendSInfo" or funcName == "friendInfo" then
  144 + local sRole = require("models.Role").new({key = rediskey})
  145 + sRole:load()
  146 + sRole:loadAll()
  147 + return false, sRole[funcName] and sRole[funcName](sRole, ...)
143 end 148 end
144 end 149 end
145 end 150 end
src/models/Daily.lua
@@ -15,7 +15,9 @@ Daily.schema = { @@ -15,7 +15,9 @@ Daily.schema = {
15 advBC = {"number", 0}, -- 冒险次数购买次数(冒险体力购买次数) 15 advBC = {"number", 0}, -- 冒险次数购买次数(冒险体力购买次数)
16 advElBC = {"number", 0}, -- 无尽次数购买次数(冒险体力购买次数) 16 advElBC = {"number", 0}, -- 无尽次数购买次数(冒险体力购买次数)
17 advWs = {"table", {}}, -- 冒险队工坊 17 advWs = {"table", {}}, -- 冒险队工坊
18 - bonusC = {"table", {}} -- 奖励副本 次数 {[type] = {c = 0, b = 0}} 18 + bonusC = {"table", {}}, -- 奖励副本 次数 {[type] = {c = 0, b = 0}}
  19 + giveFP = {"table", {}}, -- 给谁送过心心
  20 + getFP = {"table", {}}, -- 领过谁的心心
19 } 21 }
20 22
21 function Daily:updateProperty(params) 23 function Daily:updateProperty(params)
@@ -35,6 +37,7 @@ function Daily:updateProperty(params) @@ -35,6 +37,7 @@ function Daily:updateProperty(params)
35 end 37 end
36 38
37 function Daily:refreshDailyData(notify) 39 function Daily:refreshDailyData(notify)
  40 + redisproxy:del(FRIEND_POINT:format(self.owner:getProperty("id")))
38 for field, schema in pairs(self.schema) do 41 for field, schema in pairs(self.schema) do
39 if field ~= "key" then 42 if field ~= "key" then
40 local typ, def = table.unpack(schema) 43 local typ, def = table.unpack(schema)
@@ -56,6 +59,8 @@ function Daily:data() @@ -56,6 +59,8 @@ function Daily:data()
56 advElBC = self:getProperty("advElBC"), 59 advElBC = self:getProperty("advElBC"),
57 advWs = self:getProperty("advWs"), 60 advWs = self:getProperty("advWs"),
58 bonusC = self:getProperty("bonusC"), 61 bonusC = self:getProperty("bonusC"),
  62 + giveFP = self:getProperty("giveFP"),
  63 + getFP = self:getProperty("getFP"),
59 } 64 }
60 end 65 end
61 66
src/models/Role.lua
@@ -41,6 +41,7 @@ Role.schema = { @@ -41,6 +41,7 @@ Role.schema = {
41 funcLv = {"table", {}}, --功能等级 41 funcLv = {"table", {}}, --功能等级
42 loveStatus = {"string", ""}, --统计角色的最高 好感度等级 类型相关 -- type=loveL type=loveL 42 loveStatus = {"string", ""}, --统计角色的最高 好感度等级 类型相关 -- type=loveL type=loveL
43 crown = {"number", 0}, -- 看伴娘 43 crown = {"number", 0}, -- 看伴娘
  44 + silent = {"number", 0}, --禁言解禁时间
44 45
45 bagLimit = {"table", globalCsv.store_limit_max}, 46 bagLimit = {"table", globalCsv.store_limit_max},
46 47
src/models/RolePlugin.lua
@@ -19,6 +19,10 @@ function RolePlugin.bind(Role) @@ -19,6 +19,10 @@ function RolePlugin.bind(Role)
19 function Role:reloadWhenLogin() 19 function Role:reloadWhenLogin()
20 end 20 end
21 21
  22 + function Role:SendPacket(...)
  23 + SendPacket(...)
  24 + end
  25 +
22 function Role:onCrossDay(now, notify) 26 function Role:onCrossDay(now, notify)
23 local ltime = self:getProperty("ltime") 27 local ltime = self:getProperty("ltime")
24 28
@@ -72,7 +76,8 @@ function RolePlugin.bind(Role) @@ -72,7 +76,8 @@ function RolePlugin.bind(Role)
72 end 76 end
73 77
74 function Role:onOfflineEvent() 78 function Role:onOfflineEvent()
75 - 79 + -- 设置最新的登录时间
  80 + self:setProperty("ltime", skynet.timex())
76 end 81 end
77 82
78 local function checkItemCount(self, itemId, count) 83 local function checkItemCount(self, itemId, count)
@@ -613,8 +618,8 @@ function RolePlugin.bind(Role) @@ -613,8 +618,8 @@ function RolePlugin.bind(Role)
613 return result 618 return result
614 end 619 end
615 620
616 - function Role:getRealBattleValue(heros) -- 获取队伍战斗力 羁绊加成  
617 - local activeRelation = self:getHeroActiveRelation(heros) 621 + function Role:getRealBattleValue(heros, activeRelation) -- 获取队伍战斗力 羁绊加成
  622 + local activeRelation = activeRelation or self:getHeroActiveRelation(heros)
618 local battleValue = 0 623 local battleValue = 0
619 for _, id in pairs(heros) do 624 for _, id in pairs(heros) do
620 local hero = self.heros[id] 625 local hero = self.heros[id]
@@ -719,7 +724,7 @@ function RolePlugin.bind(Role) @@ -719,7 +724,7 @@ function RolePlugin.bind(Role)
719 heros[slot] = { 724 heros[slot] = {
720 htype = hero:getProperty("type"), 725 htype = hero:getProperty("type"),
721 lv = hero:getProperty("level"), 726 lv = hero:getProperty("level"),
722 - breakL = hero:getProperty("breakL"), 727 + wakeL = hero:getProperty("wakeL"),
723 } 728 }
724 end 729 end
725 return heros 730 return heros
@@ -811,6 +816,57 @@ function RolePlugin.bind(Role) @@ -811,6 +816,57 @@ function RolePlugin.bind(Role)
811 end 816 end
812 self:updateProperty({field = "advL", value = advL}) 817 self:updateProperty({field = "advL", value = advL})
813 end 818 end
  819 + -- 好友列表简约信息
  820 + function Role:friendSInfo()
  821 + local info = {
  822 + name = self:getProperty("name"),
  823 + level = self:getProperty("level"),
  824 + headId = self:getProperty("headId"),
  825 + ltime = self:getProperty("ltime"),
  826 + battleV = self:getTeamBattleValue(self:getProperty("hangTeam").heros or {}), -- Todo
  827 + }
  828 + return info
  829 + end
  830 +
  831 + local slotToPos = {
  832 + [1] = 6,
  833 + [2] = 2,
  834 + [3] = 35,
  835 + [4] = 32,
  836 + [5] = 29,
  837 + }
  838 + function Role:getTeamBattleInfo(team)
  839 + local heros = {}
  840 + -- local activeRelation = self:getHeroActiveRelation(team.heros)
  841 +
  842 + for slot, id in pairs(team.heros or {}) do
  843 + local info = {id = id}
  844 + local hero = self.heros[info.id]
  845 + if not hero then
  846 + print("error heroid " .. info.id)
  847 + end
  848 + -- local attrs = hero:getTotalAttrs({activeRelation = activeRelation})
  849 + -- for k, v in pairs(AttsEnumEx) do
  850 + -- info[v] = (attrs[v] or 0)
  851 + -- end
  852 + -- info.blockLevel = hero:getSkillLevel(4)
  853 + -- info.specialLevel = hero:getSkillLevel(1)
  854 +
  855 + info.type = hero:getProperty("type")
  856 + info.level = hero:getProperty("level")
  857 + info.wakeL = hero:getProperty("wakeL")
  858 + heros[slot] = info
  859 + end
  860 + return heros
  861 + end
  862 +
  863 + -- 角色详细信息
  864 + function Role:friendInfo()
  865 + local info = self:friendSInfo()
  866 + local heros = self:getTeamBattleInfo(self:getProperty("hangTeam"))
  867 + info.heros = heros
  868 + return info
  869 + end
814 end 870 end
815 871
816 return RolePlugin 872 return RolePlugin
817 \ No newline at end of file 873 \ No newline at end of file
src/services/globald.lua
@@ -17,7 +17,6 @@ local pointDataMark = {} @@ -17,7 +17,6 @@ local pointDataMark = {}
17 local utils = {} 17 local utils = {}
18 18
19 local CHECK_MAIL_STATUS_INTERVAL = 60 19 local CHECK_MAIL_STATUS_INTERVAL = 60
20 -  
21 local function mailQuene() 20 local function mailQuene()
22 local delayEmail = tonum(redisproxy:hget("autoincrement_set", "delay_email")) 21 local delayEmail = tonum(redisproxy:hget("autoincrement_set", "delay_email"))
23 if delayEmail == 0 then 22 if delayEmail == 0 then
@@ -91,15 +90,40 @@ local function check_mail_queue() @@ -91,15 +90,40 @@ local function check_mail_queue()
91 skynet.timeout(CHECK_MAIL_STATUS_INTERVAL, check_mail_queue) 90 skynet.timeout(CHECK_MAIL_STATUS_INTERVAL, check_mail_queue)
92 end 91 end
93 92
  93 +
  94 +
94 local CMD = {} 95 local CMD = {}
  96 +
  97 +local cacheWorldMsg = {}
  98 +local CACHE_WORLD_MSG_COUNT = 50
  99 +function CMD.sendWorldMsg(channel, msg)
  100 + cacheWorldMsg[channel] = cacheWorldMsg[channel] or {}
  101 + table.insert(cacheWorldMsg[channel], msg)
  102 + for i = #cacheWorldMsg[channel] - CACHE_WORLD_MSG_COUNT, 1, -1 do
  103 + table.remove(cacheWorldMsg[channel], i)
  104 + end
  105 +end
  106 +
  107 +
  108 +function CMD.getWorldMsg(channel)
  109 + local msgs = cacheWorldMsg[channel] or {}
  110 + return msgs
  111 +end
  112 +
95 function CMD.start() 113 function CMD.start()
96 check_mail_queue() 114 check_mail_queue()
97 end 115 end
98 116
99 local function __init__() 117 local function __init__()
100 skynet.dispatch("lua", function(_, _, command, ...) 118 skynet.dispatch("lua", function(_, _, command, ...)
101 - if CMD[command] then  
102 - skynet.ret(skynet.pack(CMD[command](...))) 119 + local f = CMD[command]
  120 + if f then
  121 + if command == "sendWorldMsg" then
  122 + skynet.ignoreret()
  123 + f(...)
  124 + else
  125 + skynet.ret(skynet.pack(f(...)))
  126 + end
103 end 127 end
104 end) 128 end)
105 redisd = harbor.queryname("REDIS") 129 redisd = harbor.queryname("REDIS")
src/services/named.lua
@@ -39,7 +39,7 @@ if mode == &quot;sub&quot; then @@ -39,7 +39,7 @@ if mode == &quot;sub&quot; then
39 end) 39 end)
40 else 40 else
41 skynet.start(function() 41 skynet.start(function()
42 - local ok, forbidNames = pcall(require, "csvdata.name_forbid") 42 + local ok, forbidNames = pcall(require, "csvdata.forbid_name")
43 if not ok then forbidNames = {} end 43 if not ok then forbidNames = {} end
44 44
45 local words = {} 45 local words = {}
src/utils/TableUtil.lua
@@ -11,4 +11,12 @@ function table.clear(tab) @@ -11,4 +11,12 @@ function table.clear(tab)
11 for k, _ in pairs(tab) do 11 for k, _ in pairs(tab) do
12 tab[k] = nil 12 tab[k] = nil
13 end 13 end
  14 +end
  15 +
  16 +function table.numbers(tab)
  17 + local count = 0
  18 + for k, _ in pairs(tab) do
  19 + count = count + 1
  20 + end
  21 + return count
14 end 22 end
15 \ No newline at end of file 23 \ No newline at end of file