|
|
@@ -5,7 +5,8 @@
|
|
|
--
|
|
|
-- 数据分工:
|
|
|
-- 跨服 DB: 积分、排行、匹配池、玩家展示(REGISTER/UPDATE_SHOW)
|
|
|
--- 本地 human.db.baiZhanChengShen: 免费次数、战报、匹配缓存、crossRegistered
|
|
|
+-- 本地 human.db.baiZhanChengShen: 免费次数、战报、crossRegistered
|
|
|
+-- human.bzcs_Match_Cache: 匹配列表/积分内存缓存(TTL 见 BZCS_MATCH_CACHE_TTL, 不持久化)
|
|
|
-- CommonDB.KEY_BZCS_START_TIME: 本服活动轮次标记(与跨服 WL_BZCS_ACT_START 同步)
|
|
|
--
|
|
|
-- 跨服同步策略:
|
|
|
@@ -107,66 +108,110 @@ local function actStartTimeCheck()
|
|
|
return IsRunning(startTime)
|
|
|
end
|
|
|
|
|
|
--- 新活动轮次时清空本地战报与匹配缓存
|
|
|
+-- 新活动轮次时清空本地战报
|
|
|
local function clearRoundLocalData(db)
|
|
|
db.warReport = {}
|
|
|
- db.matchList = {}
|
|
|
- db.matchScore = nil
|
|
|
db.crossRegistered = false
|
|
|
end
|
|
|
|
|
|
--- 积分变化后清空匹配列表, 下次须重新 CG_BZCS_MATCH_LIST
|
|
|
-local function invalidateMatchCache(db)
|
|
|
- db.matchList = {}
|
|
|
- db.matchScore = nil
|
|
|
+-- 清除匹配内存缓存(积分变化/新轮/强制刷新)
|
|
|
+local function clearMatchCache(human)
|
|
|
+ if human then
|
|
|
+ human.bzcs_Match_Cache = nil
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
-- 活动开始时间变化(新轮开启/结束)时重置本地轮次数据
|
|
|
-local function resetRoundLocalIfNeeded(db)
|
|
|
+local function resetRoundLocalIfNeeded(human, db)
|
|
|
local actStart = CommonDB.getValueByKey(CommonDB.KEY_BZCS_START_TIME) or 0
|
|
|
if (db.actStartTime or 0) ~= actStart then
|
|
|
db.actStartTime = actStart
|
|
|
clearRoundLocalData(db)
|
|
|
+ clearMatchCache(human)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
-- 玩家本地百战成神数据 (不入跨服 Mongo)
|
|
|
--- freeTimes 今日剩余免费挑战次数
|
|
|
--- dailyReset 上次日重置时间戳(0点)
|
|
|
+-- freeTimes 今日剩余免费挑战次数(跨天由 updateDaily 重置)
|
|
|
-- actStartTime 已同步的活动轮开始时间(与 KEY_BZCS_START_TIME 对比清轮次数据)
|
|
|
-- crossRegistered 本轮是否已向跨服 REGISTER
|
|
|
--- lastScore 上次已知积分(匹配缓存/断连降级展示)
|
|
|
--- matchList 缓存的匹配对手(积分不变则复用)
|
|
|
--- matchScore 生成 matchList 时的积分
|
|
|
-- warReport 本地战报 {warType,...}, 按时间尾插(最老在[1]), 下发时倒序为新在前
|
|
|
local function getBzcsDb(human)
|
|
|
human.db.baiZhanChengShen = human.db.baiZhanChengShen or {
|
|
|
freeTimes = BaiZhanChengShenDefine.BZCS_FREE_TIMES,
|
|
|
- dailyReset = 0,
|
|
|
actStartTime = 0,
|
|
|
crossRegistered = false,
|
|
|
- lastScore = nil,
|
|
|
warReport = {},
|
|
|
- matchList = {},
|
|
|
- matchScore = nil,
|
|
|
}
|
|
|
- resetRoundLocalIfNeeded(human.db.baiZhanChengShen)
|
|
|
- local now = os.time()
|
|
|
- local dayStart = Util.getDayStartTime(now)
|
|
|
- if human.db.baiZhanChengShen.dailyReset ~= dayStart then
|
|
|
- human.db.baiZhanChengShen.dailyReset = dayStart
|
|
|
- human.db.baiZhanChengShen.freeTimes = BaiZhanChengShenDefine.BZCS_FREE_TIMES
|
|
|
- end
|
|
|
+ resetRoundLocalIfNeeded(human, human.db.baiZhanChengShen)
|
|
|
return human.db.baiZhanChengShen
|
|
|
end
|
|
|
|
|
|
--- 校验 rank 是否属于当前 matchList(全服名次, 非列表下标 1~3)
|
|
|
+local function getMatchCache(human)
|
|
|
+ return human and human.bzcs_Match_Cache
|
|
|
+end
|
|
|
+
|
|
|
+local function setMatchCache(human, myScore, opponentList)
|
|
|
+ human.bzcs_Match_Cache = {
|
|
|
+ myScore = myScore,
|
|
|
+ matchScore = myScore,
|
|
|
+ opponentList = opponentList or {},
|
|
|
+ cacheTime = os.time(),
|
|
|
+ }
|
|
|
+end
|
|
|
+
|
|
|
+-- 展示刷新: 保留 matchScore(匹配基准), 更新对手展示并重置 TTL
|
|
|
+local function refreshMatchCacheDisplay(human, myScore, opponentList)
|
|
|
+ local cache = getMatchCache(human)
|
|
|
+ human.bzcs_Match_Cache = {
|
|
|
+ myScore = myScore,
|
|
|
+ matchScore = cache and cache.matchScore or myScore,
|
|
|
+ opponentList = opponentList or {},
|
|
|
+ cacheTime = os.time(),
|
|
|
+ }
|
|
|
+end
|
|
|
+
|
|
|
+-- 积分变动: 清空对手列表, 重置 matchScore/TTL(从变动时刻重新计时)
|
|
|
+local function resetMatchCacheOnScoreChange(human, newScore)
|
|
|
+ if not human then return end
|
|
|
+ newScore = newScore or BaiZhanChengShenDefine.BZCS_INIT_SCORE
|
|
|
+ human.bzcs_Match_Cache = {
|
|
|
+ myScore = newScore,
|
|
|
+ matchScore = newScore,
|
|
|
+ opponentList = {},
|
|
|
+ cacheTime = os.time(),
|
|
|
+ }
|
|
|
+end
|
|
|
+
|
|
|
+local function isMatchCacheFresh(human)
|
|
|
+ local cache = getMatchCache(human)
|
|
|
+ if not cache or not cache.opponentList or not next(cache.opponentList) then
|
|
|
+ return false
|
|
|
+ end
|
|
|
+ if (cache.myScore or 0) ~= (cache.matchScore or 0) then
|
|
|
+ return false
|
|
|
+ end
|
|
|
+ local ttl = BaiZhanChengShenDefine.BZCS_MATCH_CACHE_TTL or 30
|
|
|
+ return (os.time() - (cache.cacheTime or 0)) < ttl
|
|
|
+end
|
|
|
+
|
|
|
+local function collectRefreshRanks(opponentList)
|
|
|
+ local ranks = {}
|
|
|
+ for _, opp in ipairs(opponentList or {}) do
|
|
|
+ if opp.rank and opp.rank > 0 then
|
|
|
+ ranks[#ranks + 1] = opp.rank
|
|
|
+ end
|
|
|
+ end
|
|
|
+ return ranks
|
|
|
+end
|
|
|
+
|
|
|
+-- 校验 rank 是否属于当前匹配缓存(全服名次, 非列表下标 1~3)
|
|
|
local function resolveMatchOpponentByRank(human, rank)
|
|
|
if not rank or rank < 1 then
|
|
|
return nil
|
|
|
end
|
|
|
- local db = getBzcsDb(human)
|
|
|
- for _, opp in ipairs(db.matchList or {}) do
|
|
|
+ local cache = getMatchCache(human)
|
|
|
+ for _, opp in ipairs(cache and cache.opponentList or {}) do
|
|
|
if opp.rank == rank and opp.uuid then
|
|
|
return opp
|
|
|
end
|
|
|
@@ -174,18 +219,6 @@ local function resolveMatchOpponentByRank(human, rank)
|
|
|
return nil
|
|
|
end
|
|
|
|
|
|
--- 积分未变且已有匹配列表时可直接下发, 无需请求跨服
|
|
|
-local function canUseCachedMatch(db)
|
|
|
- if not db.matchList or not next(db.matchList) then
|
|
|
- return false
|
|
|
- end
|
|
|
- if not db.matchScore then
|
|
|
- return false
|
|
|
- end
|
|
|
- local curScore = db.lastScore or BaiZhanChengShenDefine.BZCS_INIT_SCORE
|
|
|
- return db.matchScore == curScore
|
|
|
-end
|
|
|
-
|
|
|
-- 组装并下发 GC_BZCS_MATCH_LIST
|
|
|
local function sendMatchListGC(human, myScore, opponentList)
|
|
|
local db = getBzcsDb(human)
|
|
|
@@ -563,35 +596,44 @@ end
|
|
|
------------------------------------ 客户端请求 (Handler.lua -> BZCS_*) ------------------------------------
|
|
|
-- 由 Handler.lua 转发; 需跨服的走 sendLwToMiddle, 仅本地数据的直接 GC
|
|
|
|
|
|
--- 请求跨服匹配列表; forceRefresh=true 时忽略本地缓存
|
|
|
+-- 请求跨服匹配列表; forceRefresh=true 时全量重匹配
|
|
|
local function requestMatchList(human, forceRefresh)
|
|
|
- local db = getBzcsDb(human)
|
|
|
- local fallbackScore = db.lastScore or BaiZhanChengShenDefine.BZCS_INIT_SCORE
|
|
|
- local fallbackList = db.matchList or {}
|
|
|
+ if human.fd then
|
|
|
+ ObjHuman.updateDaily(human)
|
|
|
+ end
|
|
|
+ getBzcsDb(human)
|
|
|
if not isServerEligible() then
|
|
|
- return sendMatchListGC(human, BaiZhanChengShenDefine.BZCS_INIT_SCORE, {})
|
|
|
+ return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
|
|
|
end
|
|
|
if not actStartTimeCheck() then
|
|
|
return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
|
|
|
end
|
|
|
if forceRefresh then
|
|
|
- invalidateMatchCache(db)
|
|
|
- elseif canUseCachedMatch(db) then
|
|
|
- return sendMatchListGC(human, db.lastScore, db.matchList)
|
|
|
+ clearMatchCache(human)
|
|
|
+ end
|
|
|
+ if isMatchCacheFresh(human) then
|
|
|
+ local cache = getMatchCache(human)
|
|
|
+ return sendMatchListGC(human, cache.myScore, cache.opponentList)
|
|
|
end
|
|
|
if not isMiddleReady() then
|
|
|
- return sendMatchListGC(human, fallbackScore, fallbackList)
|
|
|
+ return Broadcast.sendErr(human, Lang.MIDDLE_SVR_ERR_CONNECT)
|
|
|
end
|
|
|
+ local cache = getMatchCache(human)
|
|
|
local msgData = InnerMsg.lw.LW_BZCS_MATCH
|
|
|
msgData.sourceServerId = Config.SVR_INDEX
|
|
|
msgData.playerUuid = human.db._id
|
|
|
+ msgData.refreshRanks = {}
|
|
|
+ if cache and cache.opponentList and next(cache.opponentList)
|
|
|
+ and (cache.myScore or 0) == (cache.matchScore or 0) then
|
|
|
+ msgData.refreshRanks = collectRefreshRanks(cache.opponentList)
|
|
|
+ end
|
|
|
if not sendLwToMiddle(human, msgData) then
|
|
|
- sendMatchListGC(human, fallbackScore, fallbackList)
|
|
|
+ return
|
|
|
end
|
|
|
end
|
|
|
|
|
|
-- 匹配主界面: 下发 myScore + 3 名对手(score/name/power)
|
|
|
--- 积分未变且 matchList 非空则本地缓存直返; 跨服断连时降级返回缓存/初始分
|
|
|
+-- 内存缓存未过期直返; 过期则跨服按 rank 刷新展示; 无缓存则全量匹配
|
|
|
function BZCS_MatchList(human)
|
|
|
requestMatchList(human, false)
|
|
|
end
|
|
|
@@ -702,6 +744,7 @@ function C2N_Act_Start(msg)
|
|
|
if (human.db.baiZhanChengShen.actStartTime or 0) ~= actStart then
|
|
|
human.db.baiZhanChengShen.actStartTime = actStart
|
|
|
clearRoundLocalData(human.db.baiZhanChengShen)
|
|
|
+ clearMatchCache(human)
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
@@ -715,6 +758,7 @@ function C2N_Act_End(msg)
|
|
|
if human.db and human.db.baiZhanChengShen then
|
|
|
clearRoundLocalData(human.db.baiZhanChengShen)
|
|
|
human.db.baiZhanChengShen.actStartTime = 0
|
|
|
+ clearMatchCache(human)
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
@@ -734,16 +778,21 @@ function C2N_ErrTips(msg)
|
|
|
Broadcast.sendErr(human, Lang.DATA_ERR)
|
|
|
end
|
|
|
|
|
|
--- WL_BZCS_MATCH -> GC_BZCS_MATCH_LIST, 写入 matchList/matchScore 缓存
|
|
|
+-- WL_BZCS_MATCH -> GC_BZCS_MATCH_LIST, 写入内存匹配缓存
|
|
|
function C2N_Match(msg)
|
|
|
local human = ObjHuman.onlineUuid[msg.playerUuid]
|
|
|
if not human then return end
|
|
|
- local db = getBzcsDb(human)
|
|
|
local myScore = msg.myScore or BaiZhanChengShenDefine.BZCS_INIT_SCORE
|
|
|
- db.matchList = msg.opponentList or {}
|
|
|
- db.matchScore = myScore
|
|
|
- db.lastScore = myScore
|
|
|
- sendMatchListGC(human, myScore, db.matchList)
|
|
|
+ local opponentList = msg.opponentList or {}
|
|
|
+ local cache = getMatchCache(human)
|
|
|
+ local isDisplayRefresh = cache and cache.matchScore and cache.matchScore == myScore
|
|
|
+ and cache.opponentList and next(cache.opponentList)
|
|
|
+ if isDisplayRefresh then
|
|
|
+ refreshMatchCacheDisplay(human, myScore, opponentList)
|
|
|
+ else
|
|
|
+ setMatchCache(human, myScore, opponentList)
|
|
|
+ end
|
|
|
+ sendMatchListGC(human, myScore, opponentList)
|
|
|
end
|
|
|
|
|
|
local function fillBzcsRankNet(net, info)
|
|
|
@@ -779,12 +828,11 @@ function C2N_OpponentInfo(msg)
|
|
|
return Broadcast.sendErr(human, Lang.DATA_ERR)
|
|
|
end
|
|
|
local t = msg.targetInfo or {}
|
|
|
- local si = t.showInfo or {}
|
|
|
local msgRet = Msg.gc.GC_BZCS_OPPONENT_INFO
|
|
|
- msgRet.name = si.name or ""
|
|
|
- msgRet.head = si.head or 0
|
|
|
- msgRet.headFrame = si.headFrame or 0
|
|
|
- msgRet.power = BaiZhanChengShenDefine.CalcPlayerPower(si)
|
|
|
+ msgRet.name = t.name or ""
|
|
|
+ msgRet.head = t.head or 0
|
|
|
+ msgRet.headFrame = t.headFrame or 0
|
|
|
+ msgRet.power = t.power or 0
|
|
|
msgRet.score = t.score or BaiZhanChengShenDefine.BZCS_INIT_SCORE
|
|
|
Msg.send(msgRet, human.fd)
|
|
|
end
|
|
|
@@ -829,7 +877,7 @@ local function getBzcsRaceIdxByCombatType(combatType)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
--- CG_COMBAT_BEGIN: 挑战一次依次调用 TYPE39~43; param=全服名次rank(须在本地 matchList 中)
|
|
|
+-- CG_COMBAT_BEGIN: 挑战一次依次调用 TYPE39~43; param=全服名次rank(须在内存匹配缓存中)
|
|
|
function fight(human, args, combatType)
|
|
|
local raceIdx = getBzcsRaceIdxByCombatType(combatType)
|
|
|
if not raceIdx then
|
|
|
@@ -838,6 +886,7 @@ function fight(human, args, combatType)
|
|
|
|
|
|
if raceIdx == 1 then
|
|
|
-- 首场: 校验次数/道具、五族阵容, 请求跨服 CAN_FIGHT(扣次在 C2N_CanFight)
|
|
|
+ ObjHuman.updateDaily(human)
|
|
|
local rank = tonumber(args[1])
|
|
|
if not rank then
|
|
|
return
|
|
|
@@ -988,32 +1037,25 @@ function C2N_CanFight(msg)
|
|
|
startRaceCombat(human, human.bzcs_Battle_Cache)
|
|
|
end
|
|
|
|
|
|
--- WL_BZCS_FIGHT_END: 同步攻方积分并失效匹配缓存
|
|
|
+-- WL_BZCS_FIGHT_END: 攻方积分变化, 重置匹配缓存与 TTL
|
|
|
function C2N_FightEnd(msg)
|
|
|
local human = ObjHuman.onlineUuid[msg.playerUuid]
|
|
|
if not human then return end
|
|
|
local db = getBzcsDb(human)
|
|
|
db.crossRegistered = true
|
|
|
- db.lastScore = msg.myScore
|
|
|
- invalidateMatchCache(db)
|
|
|
+ resetMatchCacheOnScoreChange(human, msg.myScore)
|
|
|
BzcsLog.logAction("fight_end_ns", string.format("uuid=%s atkWin=%s scoreChange=%s myScore=%s", msg.playerUuid or "", msg.atkWin or 0, msg.scoreChange or 0, msg.myScore or 0))
|
|
|
end
|
|
|
|
|
|
-- WL_BZCS_DEF_NOTIFY: 防守方战报(在线/离线)
|
|
|
function C2N_DefNotify(msg)
|
|
|
local human = ObjHuman.onlineUuid[msg.playerUuid]
|
|
|
+ local offlineSave = false
|
|
|
if not human then
|
|
|
- local db = RoleDBLogic.getDb(msg.playerUuid)
|
|
|
+ local db = RoleDBLogic.getDb(msg.playerUuid, {baiZhanChengShen = 1})
|
|
|
if not db then return end
|
|
|
- db.baiZhanChengShen = db.baiZhanChengShen or {
|
|
|
- actStartTime = 0,
|
|
|
- crossRegistered = false,
|
|
|
- warReport = {},
|
|
|
- matchList = {},
|
|
|
- matchScore = nil,
|
|
|
- }
|
|
|
- resetRoundLocalIfNeeded(db.baiZhanChengShen)
|
|
|
human = {db = db}
|
|
|
+ offlineSave = true
|
|
|
end
|
|
|
local defWin = msg.atkWin == 1
|
|
|
addWarReport(human, {
|
|
|
@@ -1022,17 +1064,24 @@ function C2N_DefNotify(msg)
|
|
|
oppName = msg.atkName or "",
|
|
|
scoreChange = msg.scoreChange or 0,
|
|
|
})
|
|
|
- if human.db.baiZhanChengShen then
|
|
|
- human.db.baiZhanChengShen.lastScore = msg.myScore
|
|
|
- end
|
|
|
- if not human.fd then
|
|
|
- ObjHuman.save(human)
|
|
|
+ if human.fd then
|
|
|
+ resetMatchCacheOnScoreChange(human, msg.myScore)
|
|
|
+ elseif offlineSave then
|
|
|
+ RoleDBLogic.saveRoleSset(human.db)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
------------------------------------ 对外接口 ------------------------------------
|
|
|
-- 供红点/活动状态/阵容展示同步等其它模块调用
|
|
|
|
|
|
+-- 跨天重置免费挑战次数(由 ObjHuman.updateDaily 调用)
|
|
|
+function updateDaily(human)
|
|
|
+ if not human.db.baiZhanChengShen then
|
|
|
+ return
|
|
|
+ end
|
|
|
+ human.db.baiZhanChengShen.freeTimes = BaiZhanChengShenDefine.BZCS_FREE_TIMES
|
|
|
+end
|
|
|
+
|
|
|
local ACT_STATE_NOOPEN = 0 -- 活动未开启
|
|
|
local ACT_STATE_START = 2 -- 活动进行中(与 JjcActLogic.STATE_START 一致)
|
|
|
|