From fa565e0c47dfd1d9d94b27263f27b2377ecba312 Mon Sep 17 00:00:00 2001 From: zhouhaihai Date: Sat, 23 Nov 2019 11:40:08 +0800 Subject: [PATCH] 优化结构 --- src/RedisKeys.lua | 3 --- src/actions/HangAction.lua | 3 +-- src/actions/PvpAction.lua | 23 ++++++++++++++--------- src/actions/RoleAction.lua | 45 +++++++++++++++++++++++++-------------------- src/agent.lua | 35 ++--------------------------------- src/models/Pvp.lua | 75 --------------------------------------------------------------------------- src/models/Role.lua | 25 +++++++++++++++++++++++++ src/models/RoleCross.lua | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/models/RolePlugin.lua | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------- src/models/RolePvp.lua | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/services/mcast_util.lua | 4 ++++ src/shared/ModelBase.lua | 54 ++++++++++++++++++++++++++++++++++++++---------------- 12 files changed, 559 insertions(+), 232 deletions(-) delete mode 100644 src/models/Pvp.lua create mode 100644 src/models/RoleCross.lua create mode 100644 src/models/RolePvp.lua diff --git a/src/RedisKeys.lua b/src/RedisKeys.lua index 19f6b6c..b5f15cd 100644 --- a/src/RedisKeys.lua +++ b/src/RedisKeys.lua @@ -18,10 +18,7 @@ RANK_DINER = {"rank:diner1", "rank:diner2"} -- 餐厅排行榜 两个每天互 RANK_DINER_INFO = "rank:diner:info" RANK_PVP_COMMON = "rank:pvpc" -RANK_PVP_INFO_COMMON = "rank:pvpc:info" - RANK_PVP_HIGHT = "rank:pvph" -RANK_PVP_INFO_HIGHT = "rank:pvph:info" -- -- role -- R_FARM_KEY = "role:%d:farm" -- R_TOWER_KEY = "role:%d:tower" diff --git a/src/actions/HangAction.lua b/src/actions/HangAction.lua index cf2303d..34f52bd 100644 --- a/src/actions/HangAction.lua +++ b/src/actions/HangAction.lua @@ -208,8 +208,7 @@ function _M.roleFormatRpc(agent , data) hangTeam.heros[slot] = heroId end hangTeam.leader = msg.leader - - role:updateProperty({field = "hangTeam", value = hangTeam}) + role:saveHangTeam(hangTeam) SendPacket(actionCodes.Hang_roleFormatRpc, '') return true end diff --git a/src/actions/PvpAction.lua b/src/actions/PvpAction.lua index 4369f07..bd5ecec 100644 --- a/src/actions/PvpAction.lua +++ b/src/actions/PvpAction.lua @@ -10,21 +10,26 @@ local _M = {} function _M.formatCommonRpc(agent , data) local role = agent.role + local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) - local pvpFC = role.pvpData:getProperty("pvpFC") + local pvpTC = role:getProperty("pvpTC") for slot, heroId in pairs(msg.heros) do if not role.heros[heroId] then return end end - table.clear(pvpFC) - pvpFC.heros = {} - for slot, heroId in pairs(msg.heros) do - pvpFC.heros[slot] = heroId + if not next(msg.heros) then + return end - pvpFC.leader = msg.leader - role.pvpData:updateProperty({field = "pvpFC", value = pvpFC}) + table.clear(pvpTC) + pvpTC.heros = {} + for slot, heroId in pairs(msg.heros) do + pvpTC.heros[slot] = heroId + end + pvpTC.leader = msg.leader + + role:savePvpCTeam(pvpTC) SendPacket(actionCodes.Pvp_formatCommonRpc, '') return true end @@ -32,10 +37,10 @@ end function _M.formatHighRpc(agent , data) local role = agent.role local msg = MsgPack.unpack(data) - local pvpFH = role.pvpData:getProperty("pvpFH") + local pvpTH = role.pvpData:getProperty("pvpTH") - role.pvpData:updateProperty({field = "pvpFH", value = pvpFH}) + role.pvpData:updateProperty({field = "pvpTH", value = pvpTH}) SendPacket(actionCodes.Pvp_formatHighRpc, '') return true end diff --git a/src/actions/RoleAction.lua b/src/actions/RoleAction.lua index 6f9abca..8dff9c1 100644 --- a/src/actions/RoleAction.lua +++ b/src/actions/RoleAction.lua @@ -124,7 +124,7 @@ function _M.loginRpc( agent, data ) role:setProperty("ltime", now) redisproxy:zadd(FRIEND_RECOMMEND, now, roleId) - for _, name in ipairs({"dailyData", "dinerData", "pvpData"}) do + for _, name in ipairs({"dailyData", "dinerData"}) do response[name] = role[name]:data() end @@ -201,27 +201,23 @@ function _M.loginRpc( agent, data ) end curWave = curWave + heroWave - -- role:log("login", { ip = agent.ip, diamond = role:getProperty("diamond"), reDiamond = role:getProperty("reDiamond")}) - - datacenter.set("agent", roleId, { - serv = skynet.self(), - fd = agent.client_fd, - gate_serv = agent.gate_serv, - }) - agent.role = role + - start_agent_timer() -- 注册全服广播 - local channel = math.randomInt(1, 1) - role._channelIdx = channel - local w_channel = datacenter.get( ("MC_W_CHANNEL" .. channel) ) - if w_channel then - mcast_util.sub_world(w_channel) + if not role._channelIdx then + local channel = math.randomInt(1, 1) + role._channelIdx = channel + end + if not mcast_util.channel_world() then + local w_channel = datacenter.get( ("MC_W_CHANNEL" .. role._channelIdx) ) + if w_channel then + mcast_util.sub_world(w_channel) + end end -- 发下缓存的世界消息 local worldChatResponse = {worldChats = {}} - local ok, msgs = pcall(skynet.call, 'GLOBALD', "lua", "getWorldMsg", channel) + local ok, msgs = pcall(skynet.call, 'GLOBALD', "lua", "getWorldMsg", role._channelIdx) if not ok then msgs = {} end @@ -232,6 +228,16 @@ function _M.loginRpc( agent, data ) SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(worldChatResponse)) + datacenter.set("agent", roleId, { + serv = skynet.self(), + fd = agent.client_fd, + gate_serv = agent.gate_serv, + }) + agent.role = role + + start_agent_timer() + -- role:log("login", { ip = agent.ip, diamond = role:getProperty("diamond"), reDiamond = role:getProperty("reDiamond")}) + return true end @@ -616,7 +622,7 @@ function _M.chatRpc(agent, data) if now < role._worldChatLimit.canSayt then result = 2 - waitTime = canSayt - now + waitTime = role._worldChatLimit.canSayt - now return end @@ -634,14 +640,13 @@ function _M.chatRpc(agent, data) return end end - mcast_util.pub_world(actionCodes.Role_chat, MsgPack.pack(response)) - pcall(skynet.call, 'GLOBALD', "lua", "sendWorldMsg", role._channelIdx, response) + pcall(skynet.send, 'GLOBALD', "lua", "sendWorldMsg", role._channelIdx, response) end, -- 私聊 [2] = function () local objectId = msg.roleId - + response.objId = objectId if 0 == redisproxy:exists(string.format("role:%d", objectId)) then result = 1 return diff --git a/src/agent.lua b/src/agent.lua index 3584856..f8e59da 100644 --- a/src/agent.lua +++ b/src/agent.lua @@ -114,38 +114,8 @@ function rpcRole(roleId, funcName, ...) return true, skynet.call(agent.serv, "role", funcName, ...) end else - local rediskey = string_format("role:%d", roleId) - if funcName == "setProperty" then - return false, redisproxy:hset(rediskey, ...) - elseif funcName == "getProperty" then - return false, redisproxy:hget(rediskey, ...) - elseif funcName == "getProperties" then - local sRole = require("models.Role") - local returnValue = redisproxy:hmget(rediskey, table_unpack(...)) - local ret = {} - for index, key in ipairs(fields) do - local typ = sRole.schema[key][1] - local def = sRole.schema[key][2] - if typ == "number" then - ret[key] = tonumber(returnValue[index] or def) - else - ret[key] = returnValue[index] - end - end - return false, ret - elseif funcName == "setProperties" then - local result = {} - for k,v in pairs(fields) do - result[#result+1] = k - result[#result+1] = v - end - return false, redisproxy:hmset(rediskey, table_unpack(result)) - elseif funcName == "friendSInfo" or funcName == "friendInfo" then - local sRole = require("models.Role").new({key = rediskey}) - sRole:load() - sRole:loadAll() - return false, sRole[funcName] and sRole[funcName](sRole, ...) - end + local roleCross = require("models.RoleCross") + return false, roleCross.handle(funcName, roleId, ...) end end @@ -264,7 +234,6 @@ function CMD.close() cancel_agent_timer() mcast_util.usub_world() mcast_util.usub_union() - local role = agentInfo.role if not role then return end role:log("logout", {online = skynet.timex()-role:getProperty("ltime")}) diff --git a/src/models/Pvp.lua b/src/models/Pvp.lua deleted file mode 100644 index 7d19ec3..0000000 --- a/src/models/Pvp.lua +++ /dev/null @@ -1,75 +0,0 @@ --- 日常数据 - -local Pvp = class("Pvp", require("shared.ModelBase")) - -function Pvp:ctor(properties) - Pvp.super.ctor(self, properties) -end - -Pvp.schema = { - pvpFC = {"table", {}}, -- pvp 编队普通 - pvpFH = {"table", {}}, -- pvp 编队高级 - matchC = {"table", {}}, -- pvp 匹配的对手 普通 {{t = 1, id = roleId}, {t = 2, id = id}, {t = 2, id = id}} -- t 1 玩家 2 机器人 - matchH = {"table", {}}, -- pvp 匹配的对手 高级 {{t = 1, id = roleId}, {t = 2, id = id}, {t = 2, id = id}} -- t 1 玩家 2 机器人 -} - -function Pvp:updateProperty(params) - if params.delta then - self:incrProperty(params.field, params.delta) - if not params.notNotify then - self.owner:notifyUpdateProperty(params.field, self:getProperty(params.field)) - end - return true - end - if params.value then - self:setProperty(params.field, params.value) - if not params.notNotify then - self.owner:notifyUpdateProperty(params.field, self:getProperty(params.field)) - end - return true - end - return false -end - - - -function Pvp:refreshDailyData(notify) - -end - -function Pvp:rankResetData(notify) - -end - -function Pvp:refreshMatchC(score) - local roleId = self.owner:getProperty("id") - local score = score or redisproxy:zscore(RANK_PVP_COMMON, roleId) - local redret = redisproxy:pipelining(function(red) - - end) -end - - -function Pvp:changeScoreCommon(score) - local roleId = self.owner:getProperty("id") - local newScore = tonumber(redisproxy:ZINCRBY(RANK_PVP_COMMON, score, roleId)) - if newScore < 0 then -- 最低0分 - newScore = 0 - redisproxy:zadd(RANK_PVP_COMMON, 0, roleId) - end - self:refreshMatch(newScore) - return newScore -end - - - - - -function Pvp:data() - return { - pvpFC = self:getProperty("pvpFC"), - pvpFH = self:getProperty("pvpFH"), - } -end - -return Pvp \ No newline at end of file diff --git a/src/models/Role.lua b/src/models/Role.lua index d04536d..19d066e 100644 --- a/src/models/Role.lua +++ b/src/models/Role.lua @@ -4,10 +4,15 @@ local RolePlugin = import(".RolePlugin") local RoleTask = import(".RoleTask") local RoleActivity = import(".RoleActivity") local RoleChangeStruct = import(".RoleChangeStruct") +local RolePvp = import(".RolePvp") +local RoleCross = import(".RoleCross") + RolePlugin.bind(Role) RoleTask.bind(Role) RoleActivity.bind(Role) RoleChangeStruct.bind(Role) +RolePvp.bind(Role) +RoleCross.bind(Role) function Role:ctor( properties ) Role.super.ctor(self, properties) @@ -61,11 +66,28 @@ Role.schema = { --挂机相关 hangPass = {"table", {}}, -- 挂机通过的最大关卡 hangTeam = {"table", {}}, -- 挂机队伍 + hangTS = {"table", {}}, -- 挂机队伍他人可读的队伍信息 + hangTB = {"table", {}}, -- 挂机队伍他人可用的战斗信息 + hangTBV = {"number", 0}, -- 挂机队伍他人可用的战斗力 + hangInfo = {"table", {}}, -- 当前挂机信息 hangBag = {"table", {}}, -- 背包 hangBagLimit = {"number", globalCsv.idle_field_origin}, --背包上限 bTeam = {"table", {}}, -- 奖励副本队伍 + pvpTC = {"table", {}}, -- pvp 编队普通 + pvpTSC = {"table", {}}, -- pvp 他人可读的队伍信息 + pvpTBC = {"table", {}}, -- pvp 他人可用的战斗信息 + pvpTBVC = {"number", 0}, -- pvp 他人可用的战斗力 + pvpMC = {"table", {}}, -- pvp 匹配的对手 普通 {{t = 1, id = roleId}, {t = 2, id = id}, {t = 2, id = id}} -- t 1 玩家 2 机器人 + + pvpTH = {"table", {}}, -- pvp 编队高级 + pvpTSH = {"table", {}}, -- pvp 他人可读的队伍信息 + pvpTBH = {"table", {}}, -- pvp 他人可用的战斗信息 + pvpTBVH = {"table", {}}, -- pvp 他人可用的战斗力 + pvpMH = {"table", {}}, -- pvp 匹配的对手 高级 {{t = 1, id = roleId}, {t = 2, id = id}, {t = 2, id = id}} -- t 1 玩家 2 机器人 + + potionBag = {"table", {}}, -- 营养剂背包 storyB = {"table", {}}, -- 剧情记录 @@ -216,6 +238,9 @@ function Role:data() hangBagLimit = self:getProperty("hangBagLimit"), bTeam = self:getProperty("bTeam"), + pvpTC = self:getProperty("pvpTC"), + pvpTH = self:getProperty("pvpTH"), + potionBag = self:getProperty("potionBag"), storyB = self:getProperty("storyB"), equips = self:getProperty("equips"), diff --git a/src/models/RoleCross.lua b/src/models/RoleCross.lua new file mode 100644 index 0000000..d62c7d6 --- /dev/null +++ b/src/models/RoleCross.lua @@ -0,0 +1,174 @@ + +-- 跨越 agent 获取数据使用 +local RoleCross = {} + +--*********************************** agent 存在时调用 ****************************************-- +RoleCross.bind = function (Role) + -- 好友列表简约信息 + function Role:friendSInfo() + local info = { + name = self:getProperty("name"), + level = self:getProperty("level"), + headId = self:getProperty("headId"), + ltime = self:getProperty("ltime"), + battleV = self:getProperty("pvpTBVC") ~= 0 and self:getProperty("pvpTBVC") or self:getProperty("hangTBV") + } + return info + end + + -- 好友详细队伍信息 + function Role:friendInfo() + local info = self:friendSInfo() + local heros = self:getProperty("pvpTBVC") ~= 0 and self:getProperty("pvpTSC") or self:getProperty("hangTS") + info.heros = heros + return info + end + + -- 好友队伍战斗信息 + function Role:friendBattleInfo() + return self:getProperty("pvpTBVC") ~= 0 and self:getProperty("pvpTBC") or self:getProperty("hangTB") + end + + -- pvp 战斗数据 + function Role:pvpCBattleInfo() + return self:getProperty("pvpTBC") + end + + -- pvp 简略数据 + function Role:pvpCSInfo() + local info = { + name = self:getProperty("name"), + level = self:getProperty("level"), + headId = self:getProperty("headId"), + ltime = self:getProperty("ltime"), + battleV = self:getProperty("pvpTBVC"), + heros = self:getProperty("pvpTSC"), + } + return info + end + +end + + +--*********************************** agent 不存在时调用 ***************************************-- +local CMD = {} +local SRole +local function unpackRoleField(field, value) + if not SRole.schema[field] then + return nil + end + local typ, def = table.unpack(SRole.schema[field]) + + if typ == "number" then + value = tonumber(value or def) + elseif typ == "table" then + if type(value) == "string" then + value = MsgPack.unpack(value) + else + value = def + end + end + return value +end + +local function packRoleField(field, value) + if not SRole.schema[field] then + return nil + end + local typ, def = table.unpack(SRole.schema[field]) + + if typ == "table" then + if type(value) == "table" then + value = MsgPack.pack(value) + end + end + return value +end + +local function getRoleKey(roleId) + return string.format("role:%d", roleId) +end + +function CMD.setProperty(roleId, field, value) + local value = packRoleField(field, value) + if not value then return end + return redisproxy:hset(getRoleKey(roleId), field, value) +end + + +function CMD.setProperties(roleId, fields) + local result = {} + for k,v in pairs(fields) do + local value = packRoleField(k, v) + if value then + result[#result + 1] = k + result[#result + 1] = value + end + end + return redisproxy:hmset(getRoleKey(roleId), table.unpack(result)) +end + +function CMD.getProperty(roleId, field) + return unpackRoleField(field ,redisproxy:hget(getRoleKey(roleId), field)) +end + +function CMD.getProperties(roleId, fields) + local returnValue = redisproxy:hmget(getRoleKey(roleId), table.unpack(fields)) + local ret = {} + for index, key in ipairs(fields) do + ret[key] = unpackRoleField(key, returnValue[index]) + end + return ret +end + +function CMD.friendSInfo(roleId) + local info = CMD.getProperties(roleId, {"name", "level", "headId", "ltime", "pvpTBVC", "hangTBV"}) + return { + name = info.name, + level = info.level, + headId = info.headId, + ltime = info.ltime, + battleV = info.pvpTBVC ~= 0 and info.pvpTBVC or info.hangTBV, + } +end + +function CMD.friendInfo(roleId) + local info = CMD.getProperties(roleId, {"name", "level", "headId", "ltime", "pvpTBVC", "hangTBV", "pvpTSC", "hangTS"}) + return { + name = info.name, + level = info.level, + headId = info.headId, + ltime = info.ltime, + battleV = info.pvpTBVC ~= 0 and info.pvpTBVC or info.hangTBV, + heros = info.pvpTBVC ~= 0 and info.pvpTSC or info.hangTS + } +end + +function CMD.friendBattleInfo(roleId) + local info = CMD.getProperties(roleId, {"pvpTBC", "hangTB"}) + return next(info.pvpTBC) and info.pvpTBC or info.hangTB +end + +function CMD.pvpCBattleInfo(roleId) + return CMD.getProperty(roleId, "pvpTBC") +end + +function CMD.pvpCSInfo(roleId) + local info = CMD.getProperties(roleId, {"name", "level", "headId", "pvpTBVC", "pvpTSC"}) + return { + name = info.name, + level = info.level, + headId = info.headId, + battleV = info.pvpTBVC, + heros = info.pvpTSC, + } +end + +RoleCross.handle = function(cmd, roleId, ...) + SRole = SRole or require("models.Role") + if CMD[cmd] then + return CMD[cmd](roleId, ...) + end +end + +return RoleCross \ No newline at end of file diff --git a/src/models/RolePlugin.lua b/src/models/RolePlugin.lua index 8689423..7996cb3 100644 --- a/src/models/RolePlugin.lua +++ b/src/models/RolePlugin.lua @@ -14,7 +14,6 @@ function RolePlugin.bind(Role) self:loadRunes() self:loadHeros() self:loadDiner() - self:loadPvp() end function Role:reloadWhenLogin() @@ -32,7 +31,6 @@ function RolePlugin.bind(Role) self.dailyData:refreshDailyData(notify) self.dinerData:refreshDailyData(notify) - self.pvpData:refreshDailyData(notify) self:setProperty("dTask", {}) response.dTask = {} @@ -73,7 +71,6 @@ function RolePlugin.bind(Role) local response = {} self.dinerData:rankResetData(notify) - self.pvpData:rankResetData(notify) return response end @@ -433,17 +430,6 @@ function RolePlugin.bind(Role) end end - function Role:loadPvp() - local roleId = self:getProperty("id") - local dataKey = string.format(R_PVP, roleId) - self.pvpData = require("models.Pvp").new({key = dataKey}) - self.pvpData.owner = self - if not redisproxy:exists(dataKey) then - self.pvpData:create() - else - self.pvpData:load() - end - end function Role:loadEquips() -- 放role 里面了 @@ -723,27 +709,6 @@ function RolePlugin.bind(Role) end end - function Role:getTeamBattleValue(heros) - local battleV = 0 - for _, heroId in pairs(heros) do - local hero = self.heros[heroId] - battleV = battleV + hero:getProperty("battleV") - end - return battleV - end - - function Role:recordRankTeam(heroIds) - local heros = {} - for slot, heroId in pairs(heroIds) do - local hero = self.heros[heroId] - heros[slot] = { - htype = hero:getProperty("type"), - lv = hero:getProperty("level"), - wakeL = hero:getProperty("wakeL"), - } - end - return heros - end local StdDinerRankTime = toUnixtime("20190101"..string.format("%02x", RESET_RANK_TIME)) --跨天时间 function Role:getCurDinerRankKey() @@ -770,7 +735,7 @@ function RolePlugin.bind(Role) lv = self:getProperty("level"), batteV = battleV, level = level, - format = self:recordRankTeam(towerTeam.heros), + format = self:getTeamHerosInfo(towerTeam.heros), } local roleId = self:getProperty("id") redisproxy:pipelining(function (red) @@ -831,56 +796,69 @@ function RolePlugin.bind(Role) end self:updateProperty({field = "advL", value = advL}) end - -- 好友列表简约信息 - function Role:friendSInfo() - local info = { - name = self:getProperty("name"), - level = self:getProperty("level"), - headId = self:getProperty("headId"), - ltime = self:getProperty("ltime"), - battleV = self:getTeamBattleValue(self:getProperty("hangTeam").heros or {}), -- Todo - } - return info - end - local slotToPos = { - [1] = 6, - [2] = 2, - [3] = 35, - [4] = 32, - [5] = 29, - } function Role:getTeamBattleInfo(team) - local heros = {} - -- local activeRelation = self:getHeroActiveRelation(team.heros) + local teamInfo = {heros = {}} + local activeRelation = self:getHeroActiveRelation(team.heros) for slot, id in pairs(team.heros or {}) do - local info = {id = id} - local hero = self.heros[info.id] + local info = {} + local hero = self.heros[id] if not hero then - print("error heroid " .. info.id) + print("error heroid " .. id) + end + local attrs = hero:getTotalAttrs({activeRelation = activeRelation}) + for k, v in pairs(AttsEnumEx) do + info[v] = (attrs[v] or 0) end - -- local attrs = hero:getTotalAttrs({activeRelation = activeRelation}) - -- for k, v in pairs(AttsEnumEx) do - -- info[v] = (attrs[v] or 0) - -- end - -- info.blockLevel = hero:getSkillLevel(4) - -- info.specialLevel = hero:getSkillLevel(1) - info.type = hero:getProperty("type") info.level = hero:getProperty("level") - info.wakeL = hero:getProperty("wakeL") - heros[slot] = info + info.blockLevel = hero:getSkillLevel(4) + info.specialLevel = hero:getSkillLevel(1) + teamInfo.heros[slot] = info + end + -- todo 支援技能 + return teamInfo + end + + function Role:getTeamHerosInfo(heroIds) + local heros = {} + for slot, heroId in pairs(heroIds or {}) do + local hero = self.heros[heroId] + heros[slot] = { + type = hero:getProperty("type"), + level = hero:getProperty("level"), + wakeL = hero:getProperty("wakeL"), + } end return heros end - -- 角色详细信息 - function Role:friendInfo() - local info = self:friendSInfo() - local heros = self:getTeamBattleInfo(self:getProperty("hangTeam")) - info.heros = heros - return info + function Role:getTeamBattleValue(heros) + local battleV = 0 + for _, heroId in pairs(heros or {}) do + local hero = self.heros[heroId] + battleV = battleV + hero:getProperty("battleV") + end + return battleV + end + + function Role:saveHangTeam(team) + self:updateProperty({field = "hangTeam", value = team}) + self:setProperties({ + hangTS = self:getTeamHerosInfo(team.heros), + hangTB = self:getTeamBattleInfo(team), + hangTBV = self:getTeamBattleValue(team.heros), + }) + end + + function Role:savePvpCTeam(team) + self:updateProperty({field = "pvpTSC", value = team}) + self:setProperties({ + pvpTSC = self:getTeamHerosInfo(team.heros), + pvpTBC = self:getTeamBattleInfo(team), + pvpTBVC = self:getTeamBattleValue(team.heros), + }) end end diff --git a/src/models/RolePvp.lua b/src/models/RolePvp.lua new file mode 100644 index 0000000..c68f550 --- /dev/null +++ b/src/models/RolePvp.lua @@ -0,0 +1,224 @@ + +local RolePvp = {} + +RolePvp.bind = function (Role) + +local PVP_RANK_TIME_SORT_STD = 1924876800 -- 2030-12-31 00:00:00 +local PVP_RANK_TIME_SORT_PLACE = 1000000 -- 时间戳占据 6位数 +local PVP_RANK_TIME_SORT_PRECISION = 360 -- 时间精度 每6分钟忽略差异 +local PVP_RANK_ROBOT_SCORE = 1000 -- 机器人积分 + +local function unpackScore(score) + score = tonumber(score or 0) + return math.floor(score / PVP_RANK_TIME_SORT_PLACE) +end + +local function packScore(score, now) + now = now or skynet.timex() + return math.floor(score * PVP_RANK_TIME_SORT_PLACE + (PVP_RANK_TIME_SORT_STD - now) / PVP_RANK_TIME_SORT_PRECISION) +end + + +function Role:changePvpScoreCommon(matchId, isWin) + local roleId = self:getProperty("id") + local isPlayer = matchId ~= -1 + local redret = redisproxy:pipelining(function(red) + red:zscore(RANK_PVP_COMMON, roleId) + if isPlayer then + red:zscore(RANK_PVP_COMMON, matchId) + end + end) + local myScore = unpackScore(redret[1]) + local matchScore = PVP_RANK_ROBOT_SCORE + if isPlayer then + matchScore = unpackScore(redret[2]) + end + + if isWin then + local scoreChange = math.ceil(60 / (1 + 10 ^ ((myScore - matchScore) / 400))) + myScore = myScore + scoreChange + matchScore = matchScore - scoreChange + else + local scoreChange = math.ceil(60 / (1 + 10 ^ ((matchScore - myScore) / 400))) + myScore = myScore - scoreChange + matchScore = matchScore + scoreChange + end + + myScore = math.max(myScore, 0) + matchScore = math.max(matchScore, 0) + + local now = skynet.timex() + redisproxy:pipelining(function(red) + red:zadd(RANK_PVP_COMMON, packScore(myScore, now), roleId) + if isPlayer then + red:zadd(RANK_PVP_COMMON, packScore(matchScore, now), matchId) + end + end) + self:refreshMatchC(myScore) + return myScore +end + +function Role:refreshPvpMatchC(score) + local roleId = self:getProperty("id") + local score = score or redisproxy:zscore(RANK_PVP_COMMON, roleId) + + local function getPlayers(levels) + local redret = redisproxy:pipelining(function(red) + for _, level in ipairs(levels) do + local low, high = table.unpack(level) + red:zadd(RANK_PVP_COMMON, low * PVP_RANK_TIME_SORT_PLACE, "std_temp1") + red:zadd(RANK_PVP_COMMON, high * PVP_RANK_TIME_SORT_PLACE + PVP_RANK_TIME_SORT_PLACE - 1, "std_temp2") + red:ZREVRANK(RANK_PVP_COMMON, "std_temp1") + red:ZREVRANK(RANK_PVP_COMMON, "std_temp2") + end + red:zrem(RANK_PVP_COMMON, "std_temp1", "std_temp2") + end) + + local PreGetCount = 7 + local redret = redisproxy:pipelining(function(red) + for idx, level in ipairs(levels) do + local rank1 = tonumber(redret[(idx - 1) * 4 + 3]) + local rank2 = tonumber(redret[(idx - 1) * 4 + 4]) + if rank1 - rank2 > PreGetCount then + rank2 = math.randomInt(rank2, rank1 - PreGetCount + 1) + rank1 = rank2 + PreGetCount - 1 + end + red:ZREVRANGE(RANK_PVP_COMMON, rank2, rank1) + end + end) + return redret + end + + local findIdx = #globalCsv.pvp_division + for idx, limit in ipairs(globalCsv.pvp_division) do + if score < limit then + findIdx = idx - 1 + break + end + end + local levels = { + {}, {}, {} + } + if globalCsv.pvp_division[findIdx + 1] then + levels[1] = {globalCsv.pvp_division[findIdx + 1], (globalCsv.pvp_division[findIdx + 2] or 100000000) - 1} + end + levels[2] = {globalCsv.pvp_division[findIdx], (globalCsv.pvp_division[findIdx + 1] or 100000000) - 1} + if globalCsv.pvp_division[findIdx - 1] then + levels[3] = {globalCsv.pvp_division[findIdx - 1], globalCsv.pvp_division[findIdx] - 1} + end + local redirect = {} + for i = #levels , 1, -1 do + if not next(levels[i]) then + table.remove(levels, i) + redirect[i] = -1 + for _, v in pairs(redirect) do + redirect[_] = v - 1 + end + else + redirect[i] = i + end + end + + local result = getPlayers(levels) + local matchC = self:getProperty("pvpMC") + local hadPlayer = {[roleId] = 1} + local hadRobot = {} + for _, one in pairs(matchC) do + if one.t == 1 then + hadPlayer[one.id] = 1 + elseif one.t == 2 then + hadRobot[one.id] = 1 + end + end + + for _, temp in pairs(result) do + for i = #temp, 1, -1 do + local id = tonumber(temp[i]) + if hadPlayer[id] then + table.remove(temp, i) + else + temp[i] = id + hadPlayer[id] = 1 + end + end + end + -- 增加第几个 + local function getPlayer(idx) + for i = idx, 3 do + if redirect[i] ~= -1 then + local curR = result[redirect[i]] or {} + if next(curR) then + local curIdx = math.randomInt(1, #curR) + local objId = curR[curIdx] + table.remove(curR, curIdx) + return objId + end + end + end + end + + local tempMatchC = {} + local curCount = 0 + for i = 1, 3 do + local objId = getPlayer(i) + if objId then + tempMatchC[i] = {t = 1, id = objId} + curCount = curCount + 1 + end + end + + -- 正常的玩家不够了 低一档继续 + if curCount < 3 then + local level = nil + if globalCsv.pvp_division[findIdx - 2] then + level = {globalCsv.pvp_division[findIdx - 2], globalCsv.pvp_division[findIdx - 1] - 1} + end + if level then + local result = getPlayers({level})[1] or {} + for i = #result, 1, -1 do + local id = tonumber(result[i]) + if hadPlayer[id] then + table.remove(result, i) + else + result[i] = id + hadPlayer[id] = 1 + end + end + + if next(result) then + for i = curCount + 1, 3 do + local curIdx = math.randomInt(1, #result) + local objId = result[curIdx] + table.remove(result, curIdx) + tempMatchC[i] = {t = 1, id = objId} + curCount = curCount + 1 + if not next(result) then + break + end + end + end + end + end + + -- 增加机器人 + if curCount < 3 then + for i = curCount + 1, 3 do + while true do + local id = math.randomInt(1, #csvdb["pvp_robotCsv"]) + if not hadRobot[id] then + hadRobot[id] = 1 + tempMatchC[i] = {t = 2, id = id} + break + end + end + end + end + + self:setProperty("pvpMC", tempMatchC) +end + + +end + + +return RolePvp \ No newline at end of file diff --git a/src/services/mcast_util.lua b/src/services/mcast_util.lua index 85346f1..94c5483 100644 --- a/src/services/mcast_util.lua +++ b/src/services/mcast_util.lua @@ -24,6 +24,10 @@ function _M.sub_world(w_channel) chan_w:subscribe() end +function _M.channel_world() + return chan_w +end + function _M.usub_world() if chan_w then chan_w:unsubscribe() diff --git a/src/shared/ModelBase.lua b/src/shared/ModelBase.lua index faee246..e699bc3 100644 --- a/src/shared/ModelBase.lua +++ b/src/shared/ModelBase.lua @@ -32,7 +32,7 @@ function ModelBase:ctor(properties) end if type(properties) ~= "table" then properties = {} end - self:setProperties(properties, true) --缺少的域将设置默认值 + self:loadProperties(properties) --缺少的域将设置默认值 end -- startCache 和 endCache 在恰当的时候*配对使用* 嵌套使用多次增加引用计数 直到引用计数为0 写入 @@ -107,7 +107,7 @@ function ModelBase:load(properties) end if not next(properties) then return false end - self:setProperties(properties, true) + self:loadProperties(properties) self:onLoad() @@ -126,6 +126,7 @@ function ModelBase:create() return self end + -- save 忽略 缓存配置 function ModelBase:save() local redisProperties = self:getProperties() @@ -158,7 +159,7 @@ end --[[-- -修改对象的属性。 +加载对象的属性进内存。 NOTE: 如果properties缺少schema中的域, 将用默认值来填充 **Parameters:** @@ -166,11 +167,9 @@ NOTE: 如果properties缺少schema中的域, 将用默认值来填充 - properties: 包含属性值的数组 ]] -function ModelBase:setProperties(properties, notWrite) +function ModelBase:loadProperties(properties) assert(type(properties) == "table", "Invalid properties") - -- string_format("%s [%s:setProperties()] Invalid properties", tostring(self), self.class.__cname)) - local params = {} for field, schema in pairs(self.class.schema) do local typ, def = table_unpack(schema) local propname = field .. "_" @@ -186,18 +185,8 @@ function ModelBase:setProperties(properties, notWrite) string_format("%s [%s:setProperties()] Type mismatch, %s expected %s, actual is %s", tostring(self), self.class.__cname, field, typ, type(val))) self[propname] = val - if not self.cacheFields[field] then - table_insert(params, field) - if typ == "table" then - val = MsgPack.pack(val) - end - table_insert(params, val) - end end end - if not notWrite and next(params) then - redisproxy:hmset(self:getKey(), table_unpack(params)) - end end --[[-- @@ -270,6 +259,39 @@ function ModelBase:setProperty(property, value) end end +function ModelBase:setProperties(fields) + local result = {} + for property, value in pairs(fields) do + if not self.class.schema[property] then + print(string_format("%s [%s:setProperty()] Invalid property : %s", + tostring(self), self.class.__cname, property)) + else + local typ, def = table_unpack(self.class.schema[property]) + local propname = property .. "_" + if typ == "number" then value = tonumber(value) end + if typ == "table" and not value then + value = self[propname] -- table 可以用自己的缓冲 + end + assert(type(value) == typ, + string_format("%s [%s:setProperties()] Type mismatch, %s expected %s, actual is %s", + tostring(self), self.class.__cname, property, typ, type(value))) + self[propname] = value + + if not self.cacheFields[property] then + table_insert(result, property) + if typ == "table" then + table_insert(result, MsgPack.pack(self[propname])) + else + table_insert(result, self[propname]) + end + end + end + end + if next(result) then + redisproxy:hmset(self:getKey(), table_unpack(result)) + end +end + function ModelBase:incrProperty(property, value) if not self.class.schema[property] then print(string_format("%s [%s:setProperty()] Invalid property : %s", -- libgit2 0.21.2