| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- -- 百战成神(跨服 CS)
- --
- -- 职责:
- -- 1) 活动周期: Timer.oneMin/onHour -> timedStageHandle 开/关轮、发奖
- -- 2) 玩家数据: 积分、排行、匹配、REGISTER/UPDATE_SHOW
- -- 3) 协议: 处理普通服 LW_* , 回 WL_* 到对应 logic fd
- -- 4) 断连补偿: 逻辑服 LW_HELLO -> onLogicServerConnect 补 ACT_START/待发奖
- --
- -- 对外导出:
- -- oneMin, onHour, onLogicServerConnect, syncActStateToAllConnected
- -- N2C_* (InnerHandler 注册)
- local InnerMsg = require("core.InnerMsg")
- local Util = require("common.Util")
- local Timer = require("core.Timer")
- local MiddleManager = require("middle.MiddleManager")
- local BaiZhanChengShenDB = require("baiZhanChengShen.BaiZhanChengShenDB")
- local BaiZhanChengShenDefine = require("baiZhanChengShen.BaiZhanChengShenDefine")
- local BzcsLog = require("baiZhanChengShen.BaiZhanChengShenLog")
- ------------------------------------ 活动周期调度 ------------------------------------
- local wDay
- -- 本轮发奖 Timer 已调度(进程内防重; rewardIssued 在调度前落库防 oneMin 重复触发)
- local rewardIssueInProgress = false
- -- 上一 tick 是否处于可挑战窗口(用于 0:10 到点补广播, 跨服重启后首次 tick 也会触发一次)
- local prevIsRunning = false
- -- 刷新缓存的当前星期
- local function updateWDay()
- wDay = Util.getWeekDay()
- end
- -- 今日 0 点时间戳
- local function getTodayStartTime()
- return Util.getDayStartTime(os.time())
- end
- -- 将 baseTime 对齐到所在周开放首日 0:10 (getWeekDay: 1=周日, 7=周六)
- local function alignRoundStart(baseTime)
- local startW = BaiZhanChengShenDefine.BZCS_OPEN_WDAY_AREA[1]
- local endW = BaiZhanChengShenDefine.BZCS_OPEN_WDAY_AREA[2]
- local w = Util.getWeekDay(baseTime)
- local sub
- if startW <= endW then
- if w >= startW and w <= endW then
- sub = w - startW
- elseif w < startW then
- sub = w + 7 - startW
- else
- sub = w - startW
- end
- elseif w >= startW then
- sub = w - startW
- else
- sub = w + 7 - startW
- end
- local dayStart = Util.getDayStartTime(baseTime)
- return dayStart - sub * 86400 + BaiZhanChengShenDefine.BZCS_START_SEC
- end
- -- 由开局时间推算结束日(周日) 23:00 时间戳
- local function calcRoundEnd(startTime)
- local openStart = alignRoundStart(startTime)
- local endDayOffset = BaiZhanChengShenDefine.GetOpenEndDayOffset()
- local endDayStart = Util.getDayStartTime(openStart) + endDayOffset * 86400
- return endDayStart + BaiZhanChengShenDefine.BZCS_END_SEC
- end
- -- 当前是否在周六~周日开放日
- local function isInOpenWday()
- if not wDay then updateWDay() end
- local startW = BaiZhanChengShenDefine.BZCS_OPEN_WDAY_AREA[1]
- local endW = BaiZhanChengShenDefine.BZCS_OPEN_WDAY_AREA[2]
- if startW <= endW then
- return wDay >= startW and wDay <= endW
- end
- return wDay >= startW or wDay <= endW
- end
- -- 本轮在 DB 中仍有效(未过 endTime 且处于开放周), 含 startTime 前待开启时段
- local function hasActiveRound(now)
- now = now or os.time()
- local startTime, endTime = BaiZhanChengShenDB.GetActivityTimes()
- if startTime <= 0 or endTime <= 0 then
- return false
- end
- if now >= endTime then
- return false
- end
- return isInOpenWday()
- end
- -- 活动是否处于可挑战窗口(已过本轮 startTime)
- local function isRunning()
- local now = os.time()
- local startTime, endTime = BaiZhanChengShenDB.GetActivityTimes()
- if startTime == 0 or endTime == 0 then
- return false
- end
- if now < startTime or now > endTime then
- return false
- end
- return isInOpenWday()
- end
- -- 严格判断当前是否可开启新一轮: 周末 + 距上轮足够 + 已过本轮周六 0:10 + 上轮已结束
- local function canOpenNewRoundNow(now, lastReset, startTime, endTime)
- now = now or os.time()
- if not isInOpenWday() then
- return false
- end
- local roundStart = alignRoundStart(now)
- if now < roundStart then
- return false
- end
- if lastReset == 0 then
- return true
- end
- if Util.diffDay(lastReset) < BaiZhanChengShenDefine.BZCS_CYCLE_DAYS then
- return false
- end
- if startTime > 0 and now < endTime then
- return false
- end
- return true
- end
- -- 汇总本次 WL 广播已通知的逻辑服 serverId(MiddleManager_GetAllFD 返回 SVRINDEX_2_FD, key 即 serverId)
- local function formatNotifyServerIds(svrIndex2Fd)
- local seen, serverIds = {}, {}
- for serverId, _ in pairs(svrIndex2Fd or {}) do
- if serverId and not seen[serverId] then
- seen[serverId] = true
- serverIds[#serverIds + 1] = serverId
- end
- end
- -- 合服扩展连接(仅 MERGE 表有登记时补充)
- for serverId, _ in pairs(SVRINDEX_2_FD_MERGE or {}) do
- if serverId and not seen[serverId] then
- seen[serverId] = true
- serverIds[#serverIds + 1] = serverId
- end
- end
- table.sort(serverIds)
- return table.concat(serverIds, ",")
- end
- -- 向单个逻辑服 fd 推送当前活动状态(重连/跨服重启后补偿, 避免错过广播)
- local function sendActStateToFd(fd)
- if not fd then return end
- local serverId = MiddleManager.FD_2_SVRINDEX[fd] or 0
- local startTime, endTime = BaiZhanChengShenDB.GetActivityTimes()
- if hasActiveRound() then
- local msgData = InnerMsg.wl.WL_BZCS_ACT_START
- msgData.startTime = startTime
- msgData.endTime = endTime
- InnerMsg.sendMsg(fd, msgData)
- BzcsLog.logAction("act_open", string.format(
- "tag=sync_fd serverId=%s fd=%s start=%s end=%s running=%s",
- serverId, fd, startTime, endTime, isRunning() and 1 or 0
- ))
- else
- local msgData = InnerMsg.wl.WL_BZCS_ACT_END
- InnerMsg.sendMsg(fd, msgData)
- BzcsLog.logAction("act_close", string.format(
- "tag=sync_fd serverId=%s fd=%s start=%s end=%s running=0",
- serverId, fd, startTime, endTime
- ))
- end
- end
- -- 逻辑服连上跨服时: 同步活动状态 + 补发断连期间缓存的周期奖励
- function onLogicServerConnect(fd)
- if _G.is_middle ~= true or not fd then return end
- sendActStateToFd(fd)
- local serverId = MiddleManager.FD_2_SVRINDEX[fd]
- if not serverId then return end
- local pending = BaiZhanChengShenDB.TakePendingRewards(serverId)
- if #pending > 0 then
- local msgData = InnerMsg.wl.WL_BZCS_ISSUE_REWARD
- msgData.rewardList = pending
- InnerMsg.sendMsg(fd, msgData)
- BzcsLog.logAction("reward_reissue", string.format("serverId=%s cnt=%s", serverId, #pending))
- end
- end
- -- 跨服启动后向已连接逻辑服同步活动状态
- function syncActStateToAllConnected()
- if _G.is_middle ~= true then return end
- local fdList = MiddleManager.MiddleManager_GetAllFD()
- for _, fd in pairs(fdList) do
- sendActStateToFd(fd)
- end
- end
- -- 广播活动开启, 普通服写入 KEY_BZCS_START_TIME; tag 用于区分开轮/时间修正等场景
- function ActOpen(startTime, tag)
- tag = tag or "broadcast"
- local msgData = InnerMsg.wl.WL_BZCS_ACT_START
- msgData.startTime = startTime or os.time()
- local _, endTime = BaiZhanChengShenDB.GetActivityTimes()
- msgData.endTime = endTime
- local svrIndex2Fd = MiddleManager.MiddleManager_GetAllFD()
- local fdCnt = 0
- for serverId, fd in pairs(svrIndex2Fd) do
- InnerMsg.sendMsg(fd, msgData)
- fdCnt = fdCnt + 1
- end
- BzcsLog.logAction("act_open", string.format(
- "tag=%s start=%s end=%s fdCnt=%s running=%s servers=%s",
- tag, msgData.startTime, msgData.endTime or 0, fdCnt, isRunning() and 1 or 0,
- formatNotifyServerIds(svrIndex2Fd)
- ))
- end
- -- 广播活动结束; tag 用于区分正常结算/放弃上轮等场景
- function ActEnd(tag)
- tag = tag or "broadcast"
- local startTime, endTime = BaiZhanChengShenDB.GetActivityTimes()
- local msgData = InnerMsg.wl.WL_BZCS_ACT_END
- local svrIndex2Fd = MiddleManager.MiddleManager_GetAllFD()
- local fdCnt = 0
- for serverId, fd in pairs(svrIndex2Fd) do
- InnerMsg.sendMsg(fd, msgData)
- fdCnt = fdCnt + 1
- end
- BzcsLog.logAction("act_close", string.format(
- "tag=%s start=%s end=%s fdCnt=%s rewardIssued=%s servers=%s",
- tag, startTime or 0, endTime or 0, fdCnt, BaiZhanChengShenDB.IsRewardIssued() and 1 or 0,
- formatNotifyServerIds(svrIndex2Fd)
- ))
- end
- -- 按 serverId 汇总待发奖 {{uuid,rank},...}
- local function groupRewardsByServer(playerList)
- local byServer = {}
- for _, info in ipairs(playerList) do
- local uuid, rank, serverId = info[1], info[2], info[3]
- if serverId then
- local list = byServer[serverId]
- if not list then
- list = {}
- byServer[serverId] = list
- end
- list[#list + 1] = {uuid, rank}
- end
- end
- return byServer
- end
- -- 向指定逻辑服批量下发排名奖励(每服一次 WL); 未连接则整批入 pending
- local function issueRewardBatch(serverId, rewardList)
- if not rewardList or #rewardList == 0 then return end
- local fd = MiddleManager.getFDBySvrIndex(serverId)
- if fd then
- local msgData = InnerMsg.wl.WL_BZCS_ISSUE_REWARD
- msgData.rewardList = rewardList
- InnerMsg.sendMsg(fd, msgData)
- BzcsLog.logAction("reward_issue_send", string.format("serverId=%s cnt=%s", serverId, #rewardList))
- else
- BaiZhanChengShenDB.AddPendingRewards(serverId, rewardList)
- BzcsLog.logAction("reward_issue_offline", string.format("serverId=%s cnt=%s", serverId, #rewardList))
- end
- end
- -- 活动结束发奖: 按逻辑服批量 WL_BZCS_ISSUE_REWARD(服与服之间 2s 节流)
- function IssueRewardManager()
- if BaiZhanChengShenDB.IsRewardIssued() or rewardIssueInProgress then
- return
- end
- local rewardPlayers = BaiZhanChengShenDB.GetAllPlayersForReward()
- local byServer = groupRewardsByServer(rewardPlayers)
- local serverList = {}
- for serverId, rewardList in pairs(byServer) do
- serverList[#serverList + 1] = {serverId, rewardList}
- end
- if #serverList == 0 then
- BaiZhanChengShenDB.SetRewardIssued(true)
- return
- end
- rewardIssueInProgress = true
- -- 先落库标记, 避免异步 Timer 完成前 timedStageHandle/oneMin 重复调度
- BaiZhanChengShenDB.SetRewardIssued(true)
- BzcsLog.logAction("reward_issue", string.format("playerCnt=%s serverCnt=%s", #rewardPlayers, #serverList))
- local delay = 0
- local onlineCnt, pendingCnt = 0, 0
- for _, entry in ipairs(serverList) do
- local serverId, rewardList = entry[1], entry[2]
- local fd = MiddleManager.getFDBySvrIndex(serverId)
- if not fd then
- BaiZhanChengShenDB.AddPendingRewards(serverId, rewardList)
- pendingCnt = pendingCnt + 1
- else
- delay = delay + 2
- onlineCnt = onlineCnt + 1
- Timer.addLater(delay, issueRewardBatch, serverId, rewardList)
- end
- end
- rewardIssueInProgress = false
- BzcsLog.logAction("reward_issue_scheduled", string.format(
- "onlineCnt=%s pendingCnt=%s delaySec=%s", onlineCnt, pendingCnt, delay
- ))
- end
- -- 开启新周期: 重置 DB 并 ActOpen
- local function newRoundHandle(now)
- now = now or os.time()
- local startTime = alignRoundStart(now)
- local endTime = calcRoundEnd(startTime)
- BaiZhanChengShenDB.ResetForNewRound(startTime, endTime)
- ActOpen(startTime, "new_round")
- end
- -- 结束当前周期: 发奖 + ActEnd
- local function endRoundHandle()
- if BaiZhanChengShenDB.IsRewardIssued() or rewardIssueInProgress then
- return
- end
- BzcsLog.logAction("act_settle", "begin_issue_reward")
- IssueRewardManager()
- ActEnd("end_round")
- end
- -- 放弃上轮未完成的周期发奖(满21天开新轮时不再补发)
- local function abandonUnissuedRewards()
- if BaiZhanChengShenDB.IsRewardIssued() then
- return
- end
- BzcsLog.logAction("reward_abandon", "new_round_skip")
- BaiZhanChengShenDB.SetRewardIssued(true)
- BaiZhanChengShenDB.ClearAllPendingRewards()
- ActEnd("abandon_new_round")
- end
- -- 是否应开启新轮; 条件满足则执行 newRoundHandle 并广播
- local function tryOpenNewRound(now, lastReset, startTime, endTime)
- if not canOpenNewRoundNow(now, lastReset, startTime, endTime) then
- return false
- end
- if lastReset > 0 and not BaiZhanChengShenDB.IsRewardIssued() then
- abandonUnissuedRewards()
- end
- newRoundHandle(now)
- return true
- end
- -- 周期阶段机 (oneMin/onHour 调用):
- -- 1) 严格满足开新轮条件(周末/间隔/已过周六0:10/上轮已结束) -> newRoundHandle + ActOpen
- -- 2) 已过 endTime 且未发奖 -> endRoundHandle
- -- 3) 刚进入可挑战窗口(如周六0:10) -> ActOpen 补偿逻辑服
- local function timedStageHandle()
- local now = os.time()
- local lastReset = BaiZhanChengShenDB.GetLastResetTime()
- local startTime, endTime = BaiZhanChengShenDB.GetActivityTimes()
- local running = isRunning()
- if tryOpenNewRound(now, lastReset, startTime, endTime) then
- prevIsRunning = isRunning()
- return
- end
- if startTime > 0 and now >= endTime and not BaiZhanChengShenDB.IsRewardIssued() then
- endRoundHandle()
- prevIsRunning = false
- return
- end
- if running and not prevIsRunning then
- ActOpen(startTime, "window_open")
- end
- prevIsRunning = running
- end
- -- Timer 每分钟(跳过整点)检查阶段
- function oneMin()
- if _G.is_middle ~= true then return end
- if Util.getMin() == 0 then return end
- timedStageHandle()
- end
- -- Timer 每小时检查阶段, 0 点刷新星期
- function onHour(hour)
- if _G.is_middle ~= true then return end
- if hour == 0 or not wDay then
- updateWDay()
- end
- timedStageHandle()
- end
- ------------------------------------ N2C (普通服 LW -> 本模块 -> WL 回包) ------------------------------------
- -- msg 中带 sourceServerId/playerUuid, 通过 MiddleManager.getFDBySvrIndex 回包
- -- 向逻辑服 fd 发送 WL 协议
- local function sendWL(fd, msgData)
- if not fd then return false end
- InnerMsg.sendMsg(fd, msgData)
- return true
- end
- -- 业务失败时回 WL_BZCS_TIPS
- local function errTips(sourceServerId, playerUuid, errCode)
- BzcsLog.logAction("err_tips", string.format("serverId=%s uuid=%s err=%s", sourceServerId or 0, playerUuid or "", errCode or 0))
- local msgData = InnerMsg.wl.WL_BZCS_TIPS
- msgData.playerUuid = playerUuid
- msgData.errCode = errCode or 0
- local fd = MiddleManager.getFDBySvrIndex(sourceServerId)
- if not fd then return end
- sendWL(fd, msgData)
- end
- -- LW_BZCS_MATCH -> WL_BZCS_MATCH (±500步进扩大, 窗口内随机匹配最多3人; refreshRanks 非空时仅刷新展示)
- function N2C_Match(msg)
- local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId)
- if not isRunning() then
- return errTips(msg.sourceServerId, msg.playerUuid, BaiZhanChengShenDefine.BZCS_ERR_NOT_OPEN)
- end
- local pinfo = BaiZhanChengShenDB.GetPlayer(msg.playerUuid)
- local myScore = pinfo and pinfo.score or BaiZhanChengShenDefine.BZCS_INIT_SCORE
- local refreshRanks = msg.refreshRanks
- local opponents
- if refreshRanks and #refreshRanks > 0 then
- opponents = BaiZhanChengShenDB.GetMatchOpponentsByRanks(refreshRanks)
- if #opponents < #refreshRanks then
- opponents = BaiZhanChengShenDB.GetMatchOpponents(msg.playerUuid, myScore, {})
- end
- else
- opponents = BaiZhanChengShenDB.GetMatchOpponents(msg.playerUuid, myScore, {})
- end
- local msgData = InnerMsg.wl.WL_BZCS_MATCH
- msgData.playerUuid = msg.playerUuid
- msgData.myScore = myScore
- msgData.myRank = BaiZhanChengShenDB.GetRankByUuid(msg.playerUuid)
- msgData.opponentList = opponents
- sendWL(fd, msgData)
- end
- -- LW_BZCS_RANK_LIST -> WL_BZCS_RANK_LIST
- function N2C_RankList(msg)
- local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId)
- local msgData = InnerMsg.wl.WL_BZCS_RANK_LIST
- msgData.playerUuid = msg.playerUuid
- msgData.rankList = BaiZhanChengShenDB.GetRankList(BaiZhanChengShenDefine.BZCS_RANK_MAX)
- msgData.myRankInfo = BaiZhanChengShenDB.BuildPlayerRankInfo(msg.playerUuid)
- sendWL(fd, msgData)
- end
- -- LW_BZCS_OPPONENT_INFO -> WL_BZCS_OPPONENT_INFO
- function N2C_OpponentInfo(msg)
- local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId)
- local target = BaiZhanChengShenDB.GetPlayerByRank(msg.targetRank)
- local msgData = InnerMsg.wl.WL_BZCS_OPPONENT_INFO
- msgData.playerUuid = msg.playerUuid
- msgData.res = target and 0 or -1
- msgData.targetInfo = BaiZhanChengShenDB.BuildOpponentInfoSnapshot(target) or {}
- sendWL(fd, msgData)
- end
- -- LW_BZCS_OPPONENT_LINEUP -> WL_BZCS_OPPONENT_LINEUP (含机器人 showInfo)
- function N2C_OpponentLineup(msg)
- local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId)
- local target = BaiZhanChengShenDB.GetPlayerByRank(msg.targetRank)
- local msgData = InnerMsg.wl.WL_BZCS_OPPONENT_LINEUP
- msgData.playerUuid = msg.playerUuid
- msgData.targetRank = msg.targetRank or 0
- msgData.showInfo = target and target.showInfo or {}
- msgData.isRobot = target and target.isRobot or 0
- sendWL(fd, msgData)
- end
- -- LW_BZCS_CAN_FIGHT -> WL_BZCS_CAN_FIGHT (按开战时全服名次锁定对手, 扣次在 NS C2N_CanFight)
- function N2C_CanFight(msg)
- local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId)
- if not isRunning() then
- return errTips(msg.sourceServerId, msg.playerUuid, BaiZhanChengShenDefine.BZCS_ERR_NOT_OPEN)
- end
- local targetRank = msg.targetRank
- if not targetRank or targetRank < 1 then
- return errTips(msg.sourceServerId, msg.playerUuid, BaiZhanChengShenDefine.BZCS_ERR_TARGET_INVALID)
- end
- local target = BaiZhanChengShenDB.GetPlayerByRank(targetRank)
- if not target then
- return errTips(msg.sourceServerId, msg.playerUuid, BaiZhanChengShenDefine.BZCS_ERR_TARGET_INVALID)
- end
- if target.uuid == msg.playerUuid then
- return errTips(msg.sourceServerId, msg.playerUuid, BaiZhanChengShenDefine.BZCS_ERR_TARGET_INVALID)
- end
- local msgData = InnerMsg.wl.WL_BZCS_CAN_FIGHT
- msgData.playerUuid = msg.playerUuid
- msgData.targetRank = targetRank
- msgData.defUuid = target.uuid
- msgData.defServerId = target.serverId or 0
- local si = target.showInfo or {}
- msgData.defName = si.name or ""
- msgData.defScore = target.score or BaiZhanChengShenDefine.BZCS_INIT_SCORE
- msgData.isRobot = target.isRobot or 0
- msgData.res = 0
- sendWL(fd, msgData)
- end
- -- LW_BZCS_REGISTER 首次挑战注册跨服玩家(保留已有积分/firstJoinTime)
- function N2C_Register(msg)
- local pinfo = msg.playerInfo
- if not pinfo or not pinfo.uuid then return end
- local old = BaiZhanChengShenDB.GetPlayer(pinfo.uuid)
- if old then
- pinfo.score = old.score
- pinfo.scoreTime = old.scoreTime
- if (old.firstJoinTime or 0) > 0 then
- pinfo.firstJoinTime = old.firstJoinTime
- end
- else
- pinfo.score = BaiZhanChengShenDefine.BZCS_INIT_SCORE
- pinfo.firstJoinTime = pinfo.firstJoinTime or os.time()
- pinfo.scoreTime = os.time()
- end
- pinfo.isRobot = 0
- BaiZhanChengShenDB.UpsertPlayer(pinfo.uuid, pinfo)
- BzcsLog.logAction("register", string.format("uuid=%s serverId=%s score=%s firstJoin=%s", pinfo.uuid, pinfo.serverId or 0, pinfo.score or 0, pinfo.firstJoinTime or 0))
- end
- -- LW_BZCS_UPDATE_SHOW 增量合并展示数据
- function N2C_UpdateShow(msg)
- local pinfo = BaiZhanChengShenDB.GetPlayer(msg.playerUuid)
- if not pinfo or not msg.showInfo then return end
- pinfo.showInfo = pinfo.showInfo or {}
- BaiZhanChengShenDefine.MergeShowInfo(pinfo.showInfo, msg.showInfo)
- BaiZhanChengShenDB.UpsertPlayer(msg.playerUuid, pinfo)
- BzcsLog.logAction("update_show", string.format("uuid=%s type=%s race=%s", msg.playerUuid, msg.updateType or 0, msg.race or 0))
- end
- -- REGISTER 尚未落库时, 用 FIGHT_END 包字段建最小攻方记录(兜底乱序/丢包)
- local function ensureAtkRegistered(msg)
- local atkUuid = msg and msg.atkUuid
- if not atkUuid or atkUuid == "" then return end
- if BaiZhanChengShenDB.GetPlayer(atkUuid) then return end
- local pinfo = {
- uuid = atkUuid,
- serverId = msg.atkServerId or 0,
- score = BaiZhanChengShenDefine.BZCS_INIT_SCORE,
- firstJoinTime = os.time(),
- scoreTime = os.time(),
- isRobot = 0,
- showInfo = { name = msg.atkName or "" },
- }
- BaiZhanChengShenDB.UpsertPlayer(atkUuid, pinfo)
- BzcsLog.logAction("register_fallback", string.format("uuid=%s serverId=%s", atkUuid, pinfo.serverId))
- end
- -- LW_BZCS_FIGHT_END 整场结算: 攻守加减分, WL 通知攻方; 真人守方另发 WL_BZCS_DEF_NOTIFY
- function N2C_FightEnd(msg)
- local atkUuid = msg.atkUuid
- local defUuid = msg.defUuid
- local atkWin = msg.atkWin == 1
- local atkDelta = atkWin and BaiZhanChengShenDefine.BZCS_ATK_WIN_SCORE or BaiZhanChengShenDefine.BZCS_ATK_LOSE_SCORE
- local defDelta = atkWin and BaiZhanChengShenDefine.BZCS_DEF_LOSE_SCORE or BaiZhanChengShenDefine.BZCS_DEF_WIN_SCORE
- ensureAtkRegistered(msg)
- local atkScore = BaiZhanChengShenDB.UpdateScore(atkUuid, atkDelta)
- local defScore = BaiZhanChengShenDB.UpdateScore(defUuid, defDelta)
- if not atkScore then
- BzcsLog.logAction("fight_end_atk_score_fail", string.format(
- "atk=%s atkSvr=%s delta=%s", atkUuid or "", msg.atkServerId or 0, atkDelta
- ))
- atkScore = BaiZhanChengShenDefine.BZCS_INIT_SCORE + atkDelta
- end
- BzcsLog.logAction("fight_end", string.format(
- "atk=%s def=%s atkWin=%s atkDelta=%s defDelta=%s atkScore=%s defScore=%s atkSvr=%s defSvr=%s",
- atkUuid or "", defUuid or "", msg.atkWin or 0, atkDelta, defDelta, atkScore, defScore or -1,
- msg.atkServerId or 0, msg.defServerId or 0
- ))
- local atkFd = MiddleManager.getFDBySvrIndex(msg.atkServerId)
- local wlAtk = InnerMsg.wl.WL_BZCS_FIGHT_END
- wlAtk.playerUuid = atkUuid
- wlAtk.atkWin = msg.atkWin or 0
- wlAtk.scoreChange = atkDelta
- wlAtk.myScore = atkScore
- wlAtk.defName = msg.defName or ""
- wlAtk.defServerId = msg.defServerId or 0
- wlAtk.raceResults = msg.raceResults or {}
- if not sendWL(atkFd, wlAtk) then
- BzcsLog.logAction("fight_end_wl_fail", string.format("atk=%s atkSvr=%s", atkUuid or "", msg.atkServerId or 0))
- end
- local defInfo = BaiZhanChengShenDB.GetPlayer(defUuid)
- if defInfo and defInfo.isRobot ~= 1 and defInfo.serverId and defScore then
- local defFd = MiddleManager.getFDBySvrIndex(defInfo.serverId)
- if defFd then
- local wlDef = InnerMsg.wl.WL_BZCS_DEF_NOTIFY
- wlDef.playerUuid = defUuid
- wlDef.atkName = msg.atkName or ""
- wlDef.atkServerId = msg.atkServerId or 0
- wlDef.atkWin = msg.atkWin == 1 and 0 or 1
- wlDef.scoreChange = defDelta
- wlDef.myScore = defScore
- wlDef.raceResults = msg.raceResults or {}
- sendWL(defFd, wlDef)
- end
- elseif defInfo and defInfo.isRobot ~= 1 and not defScore then
- BzcsLog.logAction("fight_end_def_score_fail", string.format(
- "def=%s defSvr=%s delta=%s", defUuid or "", defInfo.serverId or 0, defDelta
- ))
- end
- end
|