diff --git a/src/ProtocolCode.lua b/src/ProtocolCode.lua index d37af8a..395d733 100644 --- a/src/ProtocolCode.lua +++ b/src/ProtocolCode.lua @@ -27,6 +27,10 @@ actionCodes = { Hero_wakeRpc = 205, Hero_skillUpRpc = 206, Hero_talentRpc = 207, + Hero_likeHeroRpc = 208, + Hero_commentHeroRpc = 209, + Hero_getCommentsRpc = 210, + Hero_likeCommentRpc = 211, } rpcResponseBegin = 10000 diff --git a/src/RedisKeys.lua b/src/RedisKeys.lua index fbd49bb..949f9f1 100644 --- a/src/RedisKeys.lua +++ b/src/RedisKeys.lua @@ -3,6 +3,7 @@ R_INCR = "role:%d:autoincr" R_HEROS = "role:%d:heroIds" R_HERO = "hero:%d:%d" +R_DAILY = "role:%d:daily" -- -- role -- R_FARM_KEY = "role:%d:farm" diff --git a/src/actions/HeroAction.lua b/src/actions/HeroAction.lua index 7a2a593..368f6c9 100644 --- a/src/actions/HeroAction.lua +++ b/src/actions/HeroAction.lua @@ -12,6 +12,7 @@ local tonumber = tonumber local require = require local table_insert = table.insert local tconcat = table.concat +local table_unpack = table.unpack local _M = {} function _M.levelUpRpc( agent, data ) @@ -128,4 +129,208 @@ function _M.talentRpc(agent, data) return true end +-- 暂时没有这个功能 +function _M.likeHeroRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local heroType = msg.type + local result = {status = 0} + local isLike = false + local hadLike = role:getProperty("likeHero"):toArray(true, "=") + for _, v in pairs(hadLike) do + if v == heroType then + isLike = true + break + end + end + if isLike then + result.status = 1 + else + redisproxy:hincrby("hero:like", "hero:"..heroType, 1) + table.insert(hadLike, heroType) + role:setProperty("likeHero", table.concat(hadLike, "=")) + end + + SendPacket(actionCodes.Hero_likeHeroRpc, MsgPack.pack(result)) + return true +end +local RankLikeNum = 5 --热度显示几个 +local TimeLikeNum = 95 -- 时间显示几个 +local function getCommentKey(heroType) + return { + commentListKey = string.format("list:%d:herocomments", heroType), + commentRankKey = string.format("rank:%d:herocomments", heroType), + commentKey = string.format("hero:%d:comments", heroType), + } +end + +local function trimComment(heroType, commentId) -- 剪裁 CommentList + local commentKey = getCommentKey(heroType) + local redret = redisproxy:pipelining(function (red) + red:lpush(commentKey.commentListKey, commentId) + red:lrange(commentKey.commentListKey, TimeLikeNum,-1) + red:ltrim(commentKey.commentListKey, 0, TimeLikeNum - 1) + red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) + end) + local hots = {} + for _, hot in pairs(redret[4]) do + hots[hot] = 1 + end + redisproxy:pipelining(function (red) + local needDel = {} + for _, tempId in pairs(redret[2]) do + if not hots[tempId] then + table.insert(needDel, tempId) + end + end + if #needDel > 0 then + red:zrem(commentKey.commentRankKey, table_unpack(needDel)) + red:hdel(commentKey.commentKey, table_unpack(needDel)) + end + end) +end + + +function _M.commentHeroRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local heroType = msg.type + local content = msg.content + + local result = {status = 0} -- status 0 成功 1 已经评论过了 + local curStutus = role.dailyData:getProperty("commentHero") + if curStutus:getv(heroType, 0) ~= 0 then + result.status = 1 + else + local commentKey = getCommentKey(heroType) + local SERV = string.format("NAMED%d", math.random(1, 5)) + local legal, mod = skynet.call(SERV, "lua", "check", content) + if not legal then + content = mod or "" + end + local commentId = tostring(redisproxy:hincrby("hero:comment:autoincr", "hero:" .. heroType, 1)) + local comment = { + commentId = commentId, + content = content, + roleId = role:getProperty("id"), + name = role:getProperty("name"), + -- time = skynet.timex() + } + redisproxy:hset(commentKey.commentKey, commentId, json.encode(comment)) + trimComment(heroType, commentId) + + comment.like = 0 + result.comment = comment + role.dailyData:setProperty("commentHero", curStutus:setv(heroType, 1)) + end + SendPacket(actionCodes.Hero_commentHeroRpc, MsgPack.pack(result)) + return true +end + +function _M.getCommentsRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local heroType = msg.type + local list = {} -- 评论列表 + local commentKey = getCommentKey(heroType) + local commentRoleKey = string.format("comment:%d:like", role:getProperty("id")) + local redret = redisproxy:pipelining(function (red) + red:lrange(commentKey.commentListKey, 0,TimeLikeNum - 1) + red:zrevrange(commentKey.commentRankKey, 0, -1, "WITHSCORES") --热门 + red:hget("hero:like", "hero:"..heroType) + red:lrange(commentRoleKey, 0, 999) + end) + + local likeMap = {} + local idList = {} + local liked = {} + for i = 1, #redret[2], 2 do + likeMap[redret[2][i]] = redret[2][i + 1] + if i < RankLikeNum * 2 then + table.insert(idList, redret[2][i]) + end + end + for i = 1, #redret[1] do + table.insert(idList, redret[1][i]) + end + for i = 1, #redret[4] do + liked[redret[4][i]] = 1 + end + + local commentData = redisproxy:pipelining(function (red) + for _, commentId in ipairs(idList) do + red:hget(commentKey.commentKey, commentId) + end + end) + for _, commentS in ipairs(commentData or {}) do + local comment = json.decode(commentS) + comment.like = likeMap[tostring(comment.commentId)] or 0 + comment.liked = liked[heroType .. ":" .. comment.commentId] or 0 + table.insert(list, comment) + end + SendPacket(actionCodes.Hero_getCommentsRpc, MsgPack.pack({list = list, like = tonumber(redret[3] or 0)})) + return true +end + +function _M.likeCommentRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local actType = msg.actType -- 1 顶 2 踩 + local heroType = msg.type + local commentId = msg.commentId --评论id + local commentKey = getCommentKey(heroType) + local add = 0 + if actType == 1 then + add = 1 + elseif actType == 2 then + add = -1 + else + return + end + + local result = {status = 0} + local commentIndex = heroType .. ":" .. commentId + local commentRoleKey = string.format("comment:%d:like", role:getProperty("id")) + local redret = redisproxy:pipelining(function (red) + red:hexists(commentKey.commentKey, commentId) + red:lrem(commentRoleKey, 1, commentIndex) + red:lpush(commentRoleKey, commentIndex) + red:ltrim(commentRoleKey, 0, 999) + end) + if (tonumber(redret[2]) or 0) > 0 then + result.status = 1 + else + if redret[1] == 1 then-- 查不到也返回ture + local redret2 = redisproxy:pipelining(function (red) + red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) --热门 + red:zincrby(commentKey.commentRankKey, add, commentId) + red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) --热门 + end) + local out = {} + for _, v in pairs(redret2[1]) do + out[v] = 1 + end + local new = {} + for _, v in pairs(redret2[3]) do + if out[v] then + out[v] = nil + else + new[v] = 1 + end + end + for tempId, _ in pairs(out) do + trimComment(heroType, tempId) + end + redisproxy:pipelining(function (red) + for tempId, _ in pairs(new) do + red:lrem(commentKey.commentListKey, 0, tempId) + end + end) + end + end + + SendPacket(actionCodes.Hero_likeCommentRpc, MsgPack.pack(result)) + return true +end + return _M \ No newline at end of file diff --git a/src/actions/RoleAction.lua b/src/actions/RoleAction.lua index 1bcfe7d..6577307 100644 --- a/src/actions/RoleAction.lua +++ b/src/actions/RoleAction.lua @@ -121,9 +121,13 @@ function _M.loginRpc( agent, data ) -- 跨天登陆事件 role:onCrossDay(now) - role:setProperty("ltime", now) + + for _, name in ipairs({"dailyData"}) do + response[name] = role[name]:data() + end + response.role = role:data() response.result = "SUCCESS" response.serverTime = now diff --git a/src/models/Daily.lua b/src/models/Daily.lua new file mode 100644 index 0000000..fb8d8f2 --- /dev/null +++ b/src/models/Daily.lua @@ -0,0 +1,52 @@ +-- 日常数据 + +local Daily = class("Daily", require("shared.ModelBase")) + +function Daily:ctor(properties) + Daily.super.ctor(self, properties) +end + +Daily.schema = { + key = {"string"}, -- redis key + commentHero = {"string", ""}, --单日评论食灵记录 type=1 +} + +Daily.fields = { + commentHero = true, +} + +function Daily:updateProperty(params) + local type, default = table.unpack(self.schema[params.field]) + + if params.delta then + self:setProperty(params.field, self:getProperty(paramsfield) + params.delta) + self.owner:notifyUpdateProperty(params.field, self:getProperty(params.field)) + return true + end + if params.value then + self:setProperty(params.field, params.value) + self.owner:notifyUpdateProperty(params.field, self:getProperty(params.field)) + return true + end + return false +end + +function Daily:refreshDailyData(notify) + for field, schema in pairs(self.schema) do + if field ~= "key" then + local typ, def = table.unpack(schema) + self:setProperty(field, def) + end + end + if notify then + self.owner:notifyUpdateProperties(self:data()) + end +end + +function Daily:data() + return { + -- dailyTaskStatus = self:getProperty("dailyTaskStatus"), + } +end + +return Daily \ No newline at end of file diff --git a/src/models/RolePlugin.lua b/src/models/RolePlugin.lua index f71ddb9..fc7fc7e 100644 --- a/src/models/RolePlugin.lua +++ b/src/models/RolePlugin.lua @@ -9,14 +9,27 @@ function RolePlugin.bind(Role) end function Role:loadAll() + self:loadDaily() self:loadHeros() end function Role:reloadWhenLogin() end - function Role:onCrossDay(now) + function Role:onCrossDay(now, notify) + local roleId = self:getProperty("id") + local ltime = self:getProperty("ltime") + + if isCrossDay(ltime, now) then + local response = {} + self.dailyData:refreshDailyData(notify) + + if notify then + self:notifyUpdateProperties(response) + end + return true + end end function Role:onOfflineEvent() @@ -28,11 +41,17 @@ function RolePlugin.bind(Role) local curType = itemData.type local change = {} -- 奖励被转化为了其他奖励 id = count - if curType == ItemType.Hero then - params.type = itemId - ItemStartId.Hero - for i = 1, count do - self:addHero(params) - end + local itemTypeAward = { + [ItemType.Hero] = function() + params.type = itemId - ItemStartId.Hero + for i = 1, count do + self:addHero(params) + end + end, + } + + if itemTypeAward[curType] then + itemTypeAward[curType]() else params.itemId = itemId params.count = count @@ -171,6 +190,17 @@ function RolePlugin.bind(Role) end end + function Role:loadDaily() + local roleId = self:getProperty("id") + local dataKey = string.format(R_DAILY, roleId) + self.dailyData = require("models.Daily").new({key = dataKey}) + self.dailyData.owner = self + if not redisproxy:exists(dataKey) then + self.dailyData:create() + else + self.dailyData:load() + end + end end return RolePlugin \ No newline at end of file -- libgit2 0.21.2