-- 异界之战(DB) local LuaMongo = _G.lua_mongo local DB = require("common.DB") local AnotherWorldBattleDefine = require("anotherWorldBattle.AnotherWorldBattleDefine") local AnotherWorldBattleConfig = require("excel.anotherWorldBattle") local dbUpdate = {_id=nil} local dbUpdateField = {} -- db AnotherWorldBattleData = { -- lastRoundStartTime = 0, -- 上一轮活动开启时间。实际为当前轮活动开始时间, 已有正式数据, 变量名不改了. -- stage = 1, -- 当前阶段 -- joinUnionArr = { -- { unionId = "", serverId = 123, power = 9999}, -- }, -- groupArray = { -- [1] = {unionId1, unionId2, unionId3, unionId4, unionId5, unionId6, unionId7, unionId8}, -- [2] = {unionId9, unionId10,...}, -- }, -- unionList = { -- [unionId1] = { -- serverId = 123, -- 公会所在服务器Id -- power = 9999, -- name = "111", -- baseCityId = 123, -- 出生城池 -- baseCityStartTime = nil, -- 出生城的开始占领时间 -- occupCityList = { -- 城池列表(包括曾占领过, 当前成功占领, 当前只占领过一个或多个据点) -- [cityId1] = { -- isOccupy = false, --当前是否占领 -- occupyPointList = { --占领本城池中的据点列表 -- [pointId1] = { playerUuid = "", occupyTimeArr = { {startTime1, endTime1}, {startTime2, endTime2}}, }, -- }, -- }, -- }, -- gatherInfo = { --集结信息 -- gatherTime = 0, -- gatherCity = 123, -- }, -- }, -- }, -- playerList = { -- [playerUuid] = { -- name = "", -- lv = 200, -- head = 1234, -- headFrame = 1234, -- power = 999, -- challengeTimes = 10, -- lastTime = nil, -- 上一次更新的时间戳 -- unionId = "", -- heroList = { -- [cityId] = { -- [pointIdx] = { -- { -- heroUuid = "sdgjdjdj", -- heroStar = 111, -- heroLevel = 111, -- heroCamp = 1, -- heroBody = 111, -- heroIcon = 111, -- heroPower = 11111, -- heroId = 111, -- heroQuality = 1, -- }, -- }, -- }, -- } -- }, -- } } -- 所有分组的城池信息, 启动服务器后生成, 用于快速获取城池信息 Group_2_CityList = { -- [groupId] = { -- [cityId] = { -- occupyUnion = { -- 占领公会信息, 没有公会占领时为nil -- serverId = 124, -- unionId = "123", -- }, -- pointArr = { -- 城池中所有据点信息, 没人占领时, unionId, playerUuid为nil -- {unionId = nil, playerUuid = nil, }, -- {unionId = nil, playerUuid = nil, }, -- } -- }, -- }, } -- 所有分组的公会排行榜, 启动服务器后生成 Group_2_UnionRankList = {} -- 所有分组的玩家排行榜, 启动服务器后生成 Group_2_PlayerRankList = {} -- 区服Id - 公会列表 映射表 Server_2_UnionArr = { -- [serverId] = {unionId1, unionId2}, } -- 公会 - 所属分组 映射表 Union_2_Group = { -- [unionId] = groupId, } local function initData() AnotherWorldBattleData.lastRoundStartTime = 0 AnotherWorldBattleData.stage = AnotherWorldBattleDefine.AB_STATE_END LuaMongo.insert(DB.db_anotherWorldBattle, AnotherWorldBattleData) end local function loadData() LuaMongo.find(DB.db_anotherWorldBattle) local data = {} if LuaMongo.next(data) then AnotherWorldBattleData = data else initData() end end -- 修改db单个字段 local function updateValue(key, value) if not key then return end if value then dbUpdateField["$set"] = {[key]=value} dbUpdateField["$unset"] = nil else dbUpdateField["$set"] = nil dbUpdateField["$unset"] = {[key]=1} end dbUpdate._id = AnotherWorldBattleData._id LuaMongo.update(DB.db_anotherWorldBattle, dbUpdate, dbUpdateField) end -- 生成城池数据 local function genCityList(net, unionIdArr) local function getUnionByCityId(targetCityId) for _, unionId in ipairs(unionIdArr) do local unionInfo = AnotherWorldBattleData.unionList[unionId] -- 其他城池 if unionInfo and unionInfo.occupCityList then for occupyCityId, occupyCityinfo in pairs(unionInfo.occupCityList) do if occupyCityId == targetCityId and occupyCityinfo.isOccupy then return unionId end end end -- 出生城池 if unionInfo and unionInfo.baseCityId == targetCityId then return unionId end end return nil end local function getPointOccupyPlayer(targetCityId, targetPointIdx) for _, unionId in ipairs(unionIdArr) do local unionInfo = AnotherWorldBattleData.unionList[unionId] if unionInfo and unionInfo.occupCityList and unionInfo.occupCityList[targetCityId] then local pointList = unionInfo.occupCityList[targetCityId].occupyPointList if pointList and pointList[targetPointIdx] and pointList[targetPointIdx].playerUuid then return unionId, pointList[targetPointIdx].playerUuid end end end return nil, nil end for cityId, cityCfg in ipairs(AnotherWorldBattleConfig.city) do local cityEntry = { pointArr = {} } net[cityId] = cityEntry local unionId = getUnionByCityId(cityId) if unionId then cityEntry.occupyUnion = unionId end local pointArr = cityEntry.pointArr for i=1, AnotherWorldBattleDefine.AB_POINT_MAX_NUM do local unionId1, playerUuid = getPointOccupyPlayer(cityId, i) if unionId1 and playerUuid then pointArr[i] = { unionId = unionId1, playerUuid = playerUuid } else pointArr[i] = {} end end end end -- 工会排行榜 -- 目前最多8条 local function createGuildRank() local guilds = {} -- id -> guildRec(永久表,不删) local rank = {} -- 1..#guilds 复用数组 local dirty = true -- 脏标记:true表示rank需要重新计算 local function cmp(a, b) if a.occupyCityNum ~= b.occupyCityNum then return a.occupyCityNum > b.occupyCityNum end if a.occupyPointNum ~= b.occupyPointNum then return a.occupyPointNum > b.occupyPointNum end return a.power > b.power end local function updateGuild(id, name, occupyCityNum, occupyPointNum, power) local g = guilds[id] if not g then g = { id = id, name = name or "", occupyCityNum = occupyCityNum or 0, occupyPointNum = occupyPointNum or 0, power = power or 0 } guilds[id] = g else -- 原地更新,保持table引用 g.occupyCityNum = occupyCityNum or g.occupyCityNum g.occupyPointNum = occupyPointNum or g.occupyPointNum g.power = power or g.power if name then g.name = name end end -- 标记rank缓存失效(数据量小,但统一设计模式) dirty = true end -- 内部函数:按需重新排序 local function sortIfNeeded() if not dirty then return end -- 全量收集到rank(复用数组) local n = 0 for _, v in pairs(guilds) do n = n + 1 rank[n] = v end -- 排序 if n > 1 then table.sort(rank, cmp) end -- 清除尾部残留数据 local rankMax = AnotherWorldBattleDefine.AB_RANK_MAX_NUM for i = rankMax + 1, #rank do rank[i] = nil end dirty = false end local function getRankList() -- 确保排行已更新 sortIfNeeded() -- 构建返回列表 local ret = {} for i = 1, #rank do local g = rank[i] ret[i] = { rank = i, guildId = g.id, name = g.name, occupyCityNum = g.occupyCityNum, occupyPointNum = g.occupyPointNum, power = g.power } end return ret end local function getGuildDetail(id) return guilds[id] end return { updateGuild = updateGuild, getRankList = getRankList, getGuildDetail = getGuildDetail } end -- 玩家排行榜 -- 当前每个公会最多25人,8个公会为一组,最多200人 local function createPlayerRank() local players = {} -- id -> rec(永久存在,不删) local rank = {} -- 已排序的前RANK_MAX名,复用 local tmp = {} -- 临时排序数组,预分配 local dirty = true -- 脏标记:true表示rank需要重新计算 local function cmp(a, b) if a.pointNum ~= b.pointNum then return a.pointNum > b.pointNum end if a.pointAllWeight ~= b.pointAllWeight then return a.pointAllWeight > b.pointAllWeight end return a.power > b.power end -- 预分配tmp容量,避免运行时动态扩容 for i = 1, 500 do tmp[i] = nil end local function updatePlayer(id, name, power, pNum, pWeight) -- 更新或创建玩家记录 local rec = players[id] if not rec then rec = { id = id, name = name or "", power = power or 0, pointNum = pNum or 0, pointAllWeight = pWeight or 0 } players[id] = rec else -- 原地更新,保持table引用不变 rec.power = power if pNum ~= nil then rec.pointNum = pNum end if pWeight ~= nil then rec.pointAllWeight = pWeight end if name then rec.name = name end end -- 标记rank缓存失效 dirty = true end -- 内部函数:按需重新排序 local function sortIfNeeded() if not dirty then return end -- 收集所有玩家记录到tmp(仅复制引用) local n = 0 for _, v in pairs(players) do n = n + 1 tmp[n] = v end -- 排序 if n > 1 then table.sort(tmp, cmp) end -- 将前RANK_MAX名复制到rank(复用数组) local rankMax = AnotherWorldBattleDefine.AB_RANK_MAX_NUM local oldRankLen = #rank for i = 1, rankMax do rank[i] = tmp[i] -- 若i>n,则赋值为nil,自动缩小rank长度 end -- 清除rank数组尾部残留的旧数据 for i = rankMax + 1, oldRankLen do rank[i] = nil end dirty = false end local function getRankList() -- 确保排行已更新 sortIfNeeded() -- 构建返回列表 local ret = {} for i = 1, #rank do local p = rank[i] ret[i] = { rank = i, playerId = p.id, name = p.name, power = p.power, pointNum = p.pointNum, pointAllWeight = p.pointAllWeight } end return ret end local function getPlayerDetail(id) return players[id] end return { updatePlayer = updatePlayer, getRankList = getRankList, getPlayerDetail = getPlayerDetail, } end -- 生成公会排行榜 local function genGroupUnionRankList(unionRank, unionIdArr) local function getUnionRankVal(union) local occupyCityNum, occupyPointNum, power = 0, 0, 0 power = union.power or 0 for _, v in pairs(union.occupCityList or {}) do if v.isOccupy then occupyCityNum = occupyCityNum + 1 end for _, pointInfo in pairs(v.occupyPointList or {}) do if pointInfo and pointInfo.playerUuid then occupyPointNum = occupyPointNum + 1 end end end return occupyCityNum, occupyPointNum, power end for _, unionId in ipairs(unionIdArr) do local unionData = AnotherWorldBattleData.unionList[unionId] if unionData then local occupyCityNum, occupyPointNum, power = getUnionRankVal(unionData) unionRank.updateGuild(unionId, unionData.name, occupyCityNum, occupyPointNum, power) end end end -- 生成个人排行榜 local function genGroupPlayerRankList(playerRank, unionIdArr, playerListData) local function insertPlayerRank(unionId) if not playerListData then return end for playerUuid, playerInfo in pairs(playerListData) do if playerInfo.unionId == unionId then local pointNum, pointAllWeight = 0, 0 for cityId, pointList in pairs(playerInfo.heroList or {}) do for _, _ in pairs(pointList) do pointNum = pointNum + 1 local cityCfg = AnotherWorldBattleConfig.city[cityId] pointAllWeight = pointAllWeight + (cityCfg and cityCfg.pointWeight or 0) end end playerRank.updatePlayer(playerUuid, playerInfo.name, playerInfo.power, pointNum, pointAllWeight) end end end for _, unionId in ipairs(unionIdArr) do insertPlayerRank(unionId) end end -- 生成 "公会-公会所属分组Id" 映射表 local function genUnion2GroupList(groupId, unionIdArr) for _, unionId in ipairs(unionIdArr) do Union_2_Group[unionId] = groupId end end -- 生成 "serverId - 公会Array" 映射表 local function genServer2UnionArr(unionRank) local rankList = unionRank.getRankList() for _, rankInfo in ipairs(rankList) do local unionId = rankInfo.guildId local unionInfo = AnotherWorldBattleData.unionList[unionId] if unionInfo then local serverId = unionInfo.serverId Server_2_UnionArr[serverId] = Server_2_UnionArr[serverId] or {} Server_2_UnionArr[serverId][#Server_2_UnionArr[serverId]+1] = unionId end end end -- 生成各组的缓存数据 local function genGroupCache() if not AnotherWorldBattleData.groupArray then return end local playerListData = AnotherWorldBattleData.playerList for groupId, unionIdArr in ipairs(AnotherWorldBattleData.groupArray) do -- 城池 Group_2_CityList[groupId] = {} genCityList(Group_2_CityList[groupId], unionIdArr) -- 公会排行榜 Group_2_UnionRankList[groupId] = createGuildRank() genGroupUnionRankList(Group_2_UnionRankList[groupId], unionIdArr) -- "serverId -- unionIdArray" 映射表 genServer2UnionArr(Group_2_UnionRankList[groupId]) -- 个人排行榜 Group_2_PlayerRankList[groupId] = createPlayerRank() genGroupPlayerRankList(Group_2_PlayerRankList[groupId], unionIdArr, playerListData) -- "公会-公会所属分组" 映射表 genUnion2GroupList(groupId, unionIdArr) end end function initAfterStart() if _G.is_middle ~= true then return end loadData() genGroupCache() end -- 重置数据 function ResetData() Group_2_CityList = {} Group_2_UnionRankList = {} Group_2_PlayerRankList = {} Union_2_Group = {} Server_2_UnionArr = {} AnotherWorldBattleData.lastRoundStartTime = os.time() -- AnotherWorldBattleData.stage = AnotherWorldBattleDefine.AB_STATE_JOIN AnotherWorldBattleData.joinUnionArr = nil AnotherWorldBattleData.groupArray = nil AnotherWorldBattleData.unionList = nil AnotherWorldBattleData.playerList = nil dbUpdate._id = AnotherWorldBattleData._id LuaMongo.update(DB.db_anotherWorldBattle, dbUpdate, AnotherWorldBattleData) end -- 获取公会所在分组的Id function GetUnionGroupId(unionId) return Union_2_Group[unionId] end -- 当自己公会没有参赛时, 获取本服第一个公会所在分组Id function GetGroupIdByServerId(serverId) local unionArr = Server_2_UnionArr[serverId] if unionArr and unionArr[1] then local unionId = unionArr[1] return GetUnionGroupId(unionId) end end -- 获取活动当前阶段 function GetStage() return AnotherWorldBattleData.stage end -- 更新活动当前阶段 function UpdateStage(newStage) AnotherWorldBattleData.stage = newStage updateValue("stage", newStage) if newStage == AnotherWorldBattleDefine.AB_STATE_BATTLE then genGroupCache() end end -- 获取活动上一轮的开始时间 function GetLastRoundStartTime() return AnotherWorldBattleData.lastRoundStartTime end function UpdateLastRoundStartTime(newTime) AnotherWorldBattleData.lastRoundStartTime = newTime updateValue("lastRoundStartTime", newTime) end -- 获取参赛公会列表 function GetJoinUnionArr() return AnotherWorldBattleData.joinUnionArr end -- 更新参赛公会列表 function UpdateJoinUnionArr(newJoinUnionArr) AnotherWorldBattleData.joinUnionArr = newJoinUnionArr updateValue("joinUnionArr", newJoinUnionArr) end -- 获取分组列表 function GetGroupArray() return AnotherWorldBattleData.groupArray end -- 更新分组列表 function UpdateGroupArray(newGroupArray) AnotherWorldBattleData.groupArray = newGroupArray updateValue("groupArray", newGroupArray) end -- 获取公会名字 function GetUnionName(unionId) return AnotherWorldBattleData.unionList and AnotherWorldBattleData.unionList[unionId].name or "" end -- 获取某个公会数据 function GetUnionData(unionId) return AnotherWorldBattleData.unionList and AnotherWorldBattleData.unionList[unionId] end -- 更新某个公会数据 function UpdateUnionData(unionId, newUnionData) if not AnotherWorldBattleData.unionList then AnotherWorldBattleData.unionList = {} -- updateValue("unionList", AnotherWorldBattleData.unionList) end AnotherWorldBattleData.unionList[unionId] = newUnionData updateValue("unionList"..".".. unionId, newUnionData) end -- 获取公会列表 function GetUnionList() return AnotherWorldBattleData.unionList end -- 获取玩家名字 function GetPlayerName(playerUuid) local playerListData = AnotherWorldBattleData.playerList if playerListData and playerListData[playerUuid] then return playerListData[playerUuid].name or "" end return "" end -- 获取玩家数据 function GetPlayerData(playerUuid) return AnotherWorldBattleData.playerList and AnotherWorldBattleData.playerList[playerUuid] end -- 更新玩家数据 function UpdatePlayerData(playerUuid, newPlayerData) if not AnotherWorldBattleData.playerList then AnotherWorldBattleData.playerList = {} -- updateValue("playerList", AnotherWorldBattleData.playerList) end AnotherWorldBattleData.playerList[playerUuid] = newPlayerData updateValue("playerList".. "." .. playerUuid, newPlayerData) end -- 获取公会列表 function GetPlayerList() return AnotherWorldBattleData.playerList end -- 获取城池数据 function GetCityData(groupId, cityId) if Group_2_CityList[groupId] then return Group_2_CityList[groupId][cityId] end end -- 更新城池数据 function UpdateCityData(groupId, cityId, newCityData) if Group_2_CityList[groupId] then Group_2_CityList[groupId][cityId] = newCityData end end -- 获取所有城池数据 function GetCityListByGroupId(groupId) return Group_2_CityList[groupId] end -- 更新所有城池数据 function UpdateCityList(groupId, newCityList) Group_2_CityList[groupId] = newCityList end -- 获取公会排行数据 function GetUnionRankList(groupId) local unionRank = Group_2_UnionRankList[groupId] if unionRank then return unionRank.getRankList() end end -- 更新公会的排行榜数据, cityVal, pointVal为变化的值 function UpdateUnionRankList(groupId, unionId, cityVal, pointVal, newPower) local unionRank = Group_2_UnionRankList[groupId] if unionRank then local unionRankInfo = unionRank.getGuildDetail(unionId) unionRankInfo.occupyCityNum = unionRankInfo.occupyCityNum + cityVal unionRankInfo.occupyPointNum = unionRankInfo.occupyPointNum + pointVal if newPower then unionRankInfo.power = newPower end unionRank.updateGuild(unionId, unionRankInfo.name, unionRankInfo.occupyCityNum, unionRankInfo.occupyPointNum, unionRankInfo.power) end end -- 生成玩家用于排名的数据 local function genPlayerRankVal(playerUuid) local playerListData = AnotherWorldBattleData.playerList local name, power, pointNum, pointAllWeight = "", 0, 0, 0 if playerListData and playerListData[playerUuid] then power = playerListData[playerUuid].power or 0 name = playerListData[playerUuid].name or "" for cityId, pointList in pairs(playerListData[playerUuid].heroList or {}) do for _, _ in pairs(pointList) do pointNum = pointNum + 1 local cityCfg = AnotherWorldBattleConfig.city[cityId] pointAllWeight = pointAllWeight + (cityCfg and cityCfg.pointWeight or 0) end end end return name, power, pointNum, pointAllWeight end -- 获取玩家排行数据 function GetPlayerRankList(groupId) local playerRank = Group_2_PlayerRankList[groupId] if playerRank then return playerRank.getRankList() end end -- 更新玩家排行数据, pointVal, pointWeightVal为变化的值 function UpdatePlayerRankList(groupId, playerUuid, pointVal, pointWeightVal, newPower) local playerRank = Group_2_PlayerRankList[groupId] if playerRank then local playerRankData = playerRank.getPlayerDetail(playerUuid) if not playerRankData then playerRankData = {} local name, power, pointNum, pointAllWeight = genPlayerRankVal(playerUuid) playerRankData.name = name playerRankData.power = power playerRankData.pointNum = pointNum playerRankData.pointAllWeight = pointAllWeight else playerRankData.pointNum = playerRankData.pointNum + pointVal playerRankData.pointAllWeight = playerRankData.pointAllWeight + pointWeightVal if newPower then playerRankData.power = newPower end end playerRank.updatePlayer(playerUuid, playerRankData.name, playerRankData.power, playerRankData.pointNum, playerRankData.pointAllWeight) end end