AnotherWorldBattleDB.lua 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  1. -- 异界之战(DB)
  2. local LuaMongo = _G.lua_mongo
  3. local DB = require("common.DB")
  4. local AnotherWorldBattleDefine = require("anotherWorldBattle.AnotherWorldBattleDefine")
  5. local AnotherWorldBattleConfig = require("excel.anotherWorldBattle")
  6. local dbUpdate = {_id=nil}
  7. local dbUpdateField = {}
  8. -- db
  9. AnotherWorldBattleData = {
  10. -- lastRoundStartTime = 0, -- 上一轮活动开启时间
  11. -- stage = 1, -- 当前阶段
  12. -- joinUnionArr = {
  13. -- { unionId = "", serverId = 123, power = 9999},
  14. -- },
  15. -- groupArray = {
  16. -- [1] = {unionId1, unionId2, unionId3, unionId4, unionId5, unionId6, unionId7, unionId8},
  17. -- [2] = {unionId9, unionId10,...},
  18. -- },
  19. -- unionList = {
  20. -- [unionId1] = {
  21. -- serverId = 123, -- 公会所在服务器Id
  22. -- power = 9999,
  23. -- name = "111",
  24. -- baseCityId = 123, -- 出生城池
  25. -- baseCityStartTime = nil, -- 出生城的开始占领时间
  26. -- occupCityList = { -- 城池列表(包括曾占领过, 当前成功占领, 当前只占领过一个或多个据点)
  27. -- [cityId1] = {
  28. -- isOccupy = false, --当前是否占领
  29. -- occupyPointList = { --占领本城池中的据点列表
  30. -- [pointId1] = { playerUuid = "", occupyTimeArr = { {startTime1, endTime1}, {startTime2, endTime2}}, },
  31. -- },
  32. -- },
  33. -- },
  34. -- gatherInfo = { --集结信息
  35. -- gatherTime = 0,
  36. -- gatherCity = 123,
  37. -- },
  38. -- },
  39. -- },
  40. -- playerList = {
  41. -- [playerUuid] = {
  42. -- name = "",
  43. -- lv = 200,
  44. -- head = 1234,
  45. -- headFrame = 1234,
  46. -- power = 999,
  47. -- challengeTimes = 10,
  48. -- lastTime = nil, -- 上一次更新的时间戳
  49. -- unionId = "",
  50. -- heroList = {
  51. -- [cityId] = {
  52. -- [pointIdx] = {
  53. -- {
  54. -- heroUuid = "sdgjdjdj",
  55. -- heroStar = 111,
  56. -- heroLevel = 111,
  57. -- heroCamp = 1,
  58. -- heroBody = 111,
  59. -- heroIcon = 111,
  60. -- heroPower = 11111,
  61. -- heroId = 111,
  62. -- heroQuality = 1,
  63. -- },
  64. -- },
  65. -- },
  66. -- }
  67. -- },
  68. -- }
  69. }
  70. -- 所有分组的城池信息, 启动服务器后生成, 用于快速获取城池信息
  71. Group_2_CityList = {
  72. -- [groupId] = {
  73. -- [cityId] = {
  74. -- occupyUnion = { -- 占领公会信息, 没有公会占领时为nil
  75. -- serverId = 124,
  76. -- unionId = "123",
  77. -- },
  78. -- pointArr = { -- 城池中所有据点信息, 没人占领时, unionId, playerUuid为nil
  79. -- {unionId = nil, playerUuid = nil, },
  80. -- {unionId = nil, playerUuid = nil, },
  81. -- }
  82. -- },
  83. -- },
  84. }
  85. -- 所有分组的公会排行榜, 启动服务器后生成
  86. Group_2_UnionRankList = {}
  87. -- 所有分组的玩家排行榜, 启动服务器后生成
  88. Group_2_PlayerRankList = {}
  89. -- 区服Id - 公会列表 映射表
  90. Server_2_UnionArr = {
  91. -- [serverId] = {unionId1, unionId2},
  92. }
  93. -- 公会 - 所属分组 映射表
  94. Union_2_Group = {
  95. -- [unionId] = groupId,
  96. }
  97. local function initData()
  98. AnotherWorldBattleData.lastRoundStartTime = 0
  99. AnotherWorldBattleData.stage = AnotherWorldBattleDefine.AB_STATE_END
  100. LuaMongo.insert(DB.db_anotherWorldBattle, AnotherWorldBattleData)
  101. end
  102. local function loadData()
  103. LuaMongo.find(DB.db_anotherWorldBattle)
  104. local data = {}
  105. if LuaMongo.next(data) then
  106. AnotherWorldBattleData = data
  107. else
  108. initData()
  109. end
  110. end
  111. -- 修改db单个字段
  112. local function updateValue(key, value)
  113. if not key then return end
  114. if value then
  115. dbUpdateField["$set"] = {[key]=value}
  116. dbUpdateField["$unset"] = nil
  117. else
  118. dbUpdateField["$set"] = nil
  119. dbUpdateField["$unset"] = {[key]=1}
  120. end
  121. dbUpdate._id = AnotherWorldBattleData._id
  122. LuaMongo.update(DB.db_anotherWorldBattle, dbUpdate, dbUpdateField)
  123. end
  124. -- 生成城池数据
  125. local function genCityList(net, unionIdArr)
  126. local function getUnionByCityId(targetCityId)
  127. for _, unionId in ipairs(unionIdArr) do
  128. local unionInfo = AnotherWorldBattleData.unionList[unionId]
  129. -- 其他城池
  130. if unionInfo and unionInfo.occupCityList then
  131. for occupyCityId, occupyCityinfo in pairs(unionInfo.occupCityList) do
  132. if occupyCityId == targetCityId and occupyCityinfo.isOccupy then
  133. return unionId
  134. end
  135. end
  136. end
  137. -- 出生城池
  138. if unionInfo and unionInfo.baseCityId == targetCityId then
  139. return unionId
  140. end
  141. end
  142. return nil
  143. end
  144. local function getPointOccupyPlayer(targetCityId, targetPointIdx)
  145. for _, unionId in ipairs(unionIdArr) do
  146. local unionInfo = AnotherWorldBattleData.unionList[unionId]
  147. if unionInfo and unionInfo.occupCityList and unionInfo.occupCityList[targetCityId] then
  148. local pointList = unionInfo.occupCityList[targetCityId].occupyPointList
  149. if pointList and pointList[targetPointIdx] and pointList[targetPointIdx].playerUuid then
  150. return unionId, pointList[targetPointIdx].playerUuid
  151. end
  152. end
  153. end
  154. return nil, nil
  155. end
  156. for cityId, cityCfg in ipairs(AnotherWorldBattleConfig.city) do
  157. local cityEntry = { pointArr = {} }
  158. net[cityId] = cityEntry
  159. local unionId = getUnionByCityId(cityId)
  160. if unionId then
  161. cityEntry.occupyUnion = unionId
  162. end
  163. local pointArr = cityEntry.pointArr
  164. for i=1, AnotherWorldBattleDefine.AB_POINT_MAX_NUM do
  165. local unionId1, playerUuid = getPointOccupyPlayer(cityId, i)
  166. if unionId1 and playerUuid then
  167. pointArr[i] = {
  168. unionId = unionId1,
  169. playerUuid = playerUuid
  170. }
  171. else
  172. pointArr[i] = {}
  173. end
  174. end
  175. end
  176. end
  177. -- 工会排行榜
  178. local function createGuildRank()
  179. local state = {
  180. guilds = {}, -- {[guildId] = {id, name, power, occupyCityNum, occupyPointNum, ...}}
  181. sortedGuilds = {}, -- 排序后的工会数组
  182. isDirty = true,
  183. maxSize = 8
  184. }
  185. -- 创建接口表
  186. local interface = {}
  187. -- 计算组合键
  188. local function getGuildSortKey(occupyCityNum, occupyPointNum, power)
  189. return occupyCityNum * 100000000000000000000 + -- 10^20
  190. occupyPointNum * 1000000000000 + -- 10^12
  191. power
  192. end
  193. -- 使用组合键进行比较
  194. local function compareGuilds(a, b)
  195. local keyA = getGuildSortKey(a.occupyCityNum, a.occupyPointNum, a.power)
  196. local keyB = getGuildSortKey(b.occupyCityNum, b.occupyPointNum, b.power)
  197. if keyA ~= keyB then
  198. return keyA > keyB -- 组合键大的排名高
  199. end
  200. -- 组合键相同,按ID排序
  201. return a.id < b.id
  202. end
  203. local function quickSort(arr, left, right)
  204. if left >= right then return end
  205. local pivot = arr[math.floor((left + right) / 2)]
  206. local i, j = left, right
  207. while i <= j do
  208. while compareGuilds(arr[i], pivot) do i = i + 1 end
  209. while compareGuilds(pivot, arr[j]) do j = j - 1 end
  210. if i <= j then
  211. arr[i], arr[j] = arr[j], arr[i]
  212. i = i + 1
  213. j = j - 1
  214. end
  215. end
  216. quickSort(arr, left, j)
  217. quickSort(arr, i, right)
  218. end
  219. local function refreshRank()
  220. -- 收集所有工会到数组
  221. local guildArray = {}
  222. for _, guild in pairs(state.guilds) do
  223. table.insert(guildArray, guild)
  224. end
  225. -- 使用快速排序
  226. if #guildArray > 0 then
  227. quickSort(guildArray, 1, #guildArray)
  228. end
  229. -- 只保留前8名
  230. state.sortedGuilds = {}
  231. for i = 1, math.min(state.maxSize, #guildArray) do
  232. state.sortedGuilds[i] = {
  233. guildId = guildArray[i].id,
  234. rank = i,
  235. power = guildArray[i].power,
  236. name = guildArray[i].name,
  237. occupyCityNum = guildArray[i].occupyCityNum,
  238. occupyPointNum = guildArray[i].occupyPointNum
  239. }
  240. end
  241. state.isDirty = false
  242. end
  243. -- 定义接口函数
  244. function interface.updateGuild(guildId, name, power, occupyCityNum, occupyPointNum)
  245. if not state.guilds[guildId] then
  246. state.guilds[guildId] = {
  247. id = guildId,
  248. name = name,
  249. power = power,
  250. occupyCityNum = occupyCityNum or 0,
  251. occupyPointNum = occupyPointNum or 0
  252. }
  253. else
  254. state.guilds[guildId].power = power
  255. state.guilds[guildId].occupyCityNum = occupyCityNum or state.guilds[guildId].occupyCityNum
  256. state.guilds[guildId].occupyPointNum = occupyPointNum or state.guilds[guildId].occupyPointNum
  257. if name then
  258. state.guilds[guildId].name = name
  259. end
  260. end
  261. state.isDirty = true
  262. end
  263. function interface.updateOccupyCityNum(guildId, occupyCityNum)
  264. if state.guilds[guildId] then
  265. state.guilds[guildId].occupyCityNum = occupyCityNum
  266. state.isDirty = true
  267. end
  268. end
  269. function interface.updateOccupyPointNum(guildId, occupyPointNum)
  270. if state.guilds[guildId] then
  271. state.guilds[guildId].occupyPointNum = occupyPointNum
  272. state.isDirty = true
  273. end
  274. end
  275. function interface.updatePower(guildId, power)
  276. if state.guilds[guildId] then
  277. state.guilds[guildId].power = power
  278. state.isDirty = true
  279. end
  280. end
  281. function interface.disbandGuild(guildId)
  282. if state.guilds[guildId] then
  283. state.guilds[guildId] = nil
  284. state.isDirty = true
  285. return true
  286. end
  287. return false
  288. end
  289. function interface.getRankList()
  290. if state.isDirty then
  291. refreshRank()
  292. end
  293. return state.sortedGuilds
  294. end
  295. function interface.getGuildRank(guildId)
  296. if state.isDirty then
  297. refreshRank()
  298. end
  299. for i, guild in ipairs(state.sortedGuilds) do
  300. if guild.guildId == guildId then
  301. return i
  302. end
  303. end
  304. return nil
  305. end
  306. function interface.getGuildDetail(guildId)
  307. if state.isDirty then
  308. refreshRank()
  309. end
  310. for i, guild in ipairs(state.sortedGuilds) do
  311. if guild.guildId == guildId then
  312. return {
  313. rank = i,
  314. guildId = guild.guildId,
  315. name = guild.name,
  316. power = guild.power,
  317. occupyCityNum = guild.occupyCityNum,
  318. occupyPointNum = guild.occupyPointNum
  319. }
  320. end
  321. end
  322. return nil
  323. end
  324. function interface.hasGuild(guildId)
  325. return state.guilds[guildId] ~= nil
  326. end
  327. function interface.getTotalGuilds()
  328. return tableCount(state.guilds)
  329. end
  330. function interface._getState()
  331. return {
  332. totalGuilds = tableCount(state.guilds),
  333. isDirty = state.isDirty
  334. }
  335. end
  336. return interface
  337. end
  338. -- 玩家排行榜
  339. local function createPlayerRank()
  340. local state = {
  341. players = {}, -- {[playerId] = {id, name, power, pointNum, pointAllWeight, ...}}
  342. rankArray = {}, -- 排行榜数组,按组合键排序
  343. playerIndex = {}, -- {[playerId] = 在rankArray中的索引}
  344. candidateMap = {}, -- 候选玩家 {[playerId] = true}
  345. maxSize = AnotherWorldBattleDefine.AB_RANK_MAX_NUM,
  346. size = 0
  347. }
  348. -- 创建接口表
  349. local interface = {}
  350. -- 计算组合键
  351. local function getPlayerSortKey(pointNum, pointAllWeight, power)
  352. return pointNum * 10000000000000000 + -- 10^16
  353. pointAllWeight * 10000000000 + -- 10^10
  354. power
  355. end
  356. -- 使用组合键进行比较
  357. local function comparePlayers(a, b)
  358. local keyA = getPlayerSortKey(a.pointNum, a.pointAllWeight, a.power)
  359. local keyB = getPlayerSortKey(b.pointNum, b.pointAllWeight, b.power)
  360. if keyA ~= keyB then
  361. return keyA > keyB -- 组合键大的排名高
  362. end
  363. -- 组合键相同,按ID排序
  364. return a.id < b.id
  365. end
  366. -- 二分查找插入位置(使用组合键)
  367. local function findInsertPosition(playerData)
  368. local left, right = 1, state.size
  369. local key = getPlayerSortKey(playerData.pointNum, playerData.pointAllWeight, playerData.power)
  370. while left <= right do
  371. local mid = math.floor((left + right) / 2)
  372. local midPlayer = state.rankArray[mid]
  373. local midKey = getPlayerSortKey(midPlayer.pointNum, midPlayer.pointAllWeight, midPlayer.power)
  374. if key > midKey then
  375. right = mid - 1
  376. else
  377. left = mid + 1
  378. end
  379. end
  380. return left
  381. end
  382. -- 插入玩家到排行榜
  383. local function insertToRank(playerData)
  384. if state.size == 0 then
  385. state.rankArray[1] = playerData
  386. state.playerIndex[playerData.id] = 1
  387. state.size = 1
  388. return
  389. end
  390. local pos = findInsertPosition(playerData)
  391. -- 向后移动元素
  392. for i = state.size, pos, -1 do
  393. state.rankArray[i + 1] = state.rankArray[i]
  394. state.playerIndex[state.rankArray[i].id] = i + 1
  395. end
  396. -- 插入新元素
  397. state.rankArray[pos] = playerData
  398. state.playerIndex[playerData.id] = pos
  399. state.size = state.size + 1
  400. -- 如果超过最大大小,移除最后一个
  401. if state.size > state.maxSize then
  402. local removedPlayer = state.rankArray[state.maxSize + 1]
  403. if removedPlayer then
  404. state.playerIndex[removedPlayer.id] = nil
  405. state.candidateMap[removedPlayer.id] = true
  406. end
  407. state.size = state.maxSize
  408. end
  409. end
  410. -- 从排行榜移除玩家
  411. local function removeFromRank(playerId)
  412. local index = state.playerIndex[playerId]
  413. if not index then return false end
  414. -- 向前移动元素
  415. for i = index, state.size - 1 do
  416. state.rankArray[i] = state.rankArray[i + 1]
  417. state.playerIndex[state.rankArray[i].id] = i
  418. end
  419. state.rankArray[state.size] = nil
  420. state.playerIndex[playerId] = nil
  421. state.size = state.size - 1
  422. return true
  423. end
  424. -- 调整玩家在排行榜中的位置
  425. local function adjustPlayerPosition(playerId)
  426. local currentIndex = state.playerIndex[playerId]
  427. if not currentIndex then return end
  428. local playerData = state.players[playerId]
  429. if not playerData then return end
  430. -- 先移除,再重新插入(确保位置正确)
  431. removeFromRank(playerId)
  432. insertToRank(playerData)
  433. end
  434. -- 检查候选玩家
  435. local function checkCandidates()
  436. if state.size < state.maxSize then
  437. -- 排行榜未满,找到最佳候选加入
  438. local bestCandidate = nil
  439. local bestKey = -1
  440. for playerId, _ in pairs(state.candidateMap) do
  441. local player = state.players[playerId]
  442. if player then
  443. local key = getPlayerSortKey(player.pointNum, player.pointAllWeight, player.power)
  444. if key > bestKey then
  445. bestCandidate = playerId
  446. bestKey = key
  447. elseif key == bestKey and player.id < bestCandidate then
  448. bestCandidate = playerId
  449. bestKey = key
  450. end
  451. end
  452. end
  453. if bestCandidate then
  454. state.candidateMap[bestCandidate] = nil
  455. insertToRank(state.players[bestCandidate])
  456. end
  457. else
  458. -- 检查候选是否应该替换最后一名
  459. local lastPlayer = state.rankArray[state.size]
  460. local lastKey = getPlayerSortKey(lastPlayer.pointNum, lastPlayer.pointAllWeight, lastPlayer.power)
  461. local bestCandidate = nil
  462. local bestKey = lastKey
  463. for playerId, _ in pairs(state.candidateMap) do
  464. local player = state.players[playerId]
  465. if player then
  466. local key = getPlayerSortKey(player.pointNum, player.pointAllWeight, player.power)
  467. if key > bestKey then
  468. bestCandidate = playerId
  469. bestKey = key
  470. elseif key == bestKey and player.id < bestCandidate then
  471. bestCandidate = playerId
  472. bestKey = key
  473. end
  474. end
  475. end
  476. if bestCandidate then
  477. state.candidateMap[bestCandidate] = nil
  478. state.candidateMap[lastPlayer.id] = true
  479. removeFromRank(lastPlayer.id)
  480. insertToRank(state.players[bestCandidate])
  481. end
  482. end
  483. end
  484. -- 完全移除玩家(包括从候选集)
  485. local function removePlayerCompletely(playerId)
  486. -- 从排行榜移除
  487. removeFromRank(playerId)
  488. -- 从候选集移除
  489. state.candidateMap[playerId] = nil
  490. -- 从玩家数据移除
  491. state.players[playerId] = nil
  492. return true
  493. end
  494. -- 定义接口函数
  495. function interface.updatePlayer(playerId, name, power, pointNum, pointAllWeight)
  496. local playerData = state.players[playerId]
  497. if not playerData then
  498. -- 新玩家
  499. playerData = {
  500. id = playerId,
  501. name = name,
  502. power = power,
  503. pointNum = pointNum or 0,
  504. pointAllWeight = pointAllWeight or 0
  505. }
  506. state.players[playerId] = playerData
  507. if state.size < state.maxSize then
  508. insertToRank(playerData)
  509. else
  510. -- 检查是否能直接进入排行榜
  511. local lastPlayer = state.rankArray[state.size]
  512. local lastKey = getPlayerSortKey(lastPlayer.pointNum, lastPlayer.pointAllWeight, lastPlayer.power)
  513. local newKey = getPlayerSortKey(pointNum or 0, pointAllWeight or 0, power)
  514. if newKey > lastKey or (newKey == lastKey and playerId < lastPlayer.id) then
  515. state.candidateMap[lastPlayer.id] = true
  516. removeFromRank(lastPlayer.id)
  517. insertToRank(playerData)
  518. else
  519. state.candidateMap[playerId] = true
  520. end
  521. end
  522. else
  523. -- 已有玩家
  524. playerData.power = power
  525. playerData.pointNum = pointNum or playerData.pointNum
  526. playerData.pointAllWeight = pointAllWeight or playerData.pointAllWeight
  527. if name then
  528. playerData.name = name
  529. end
  530. local currentIndex = state.playerIndex[playerId]
  531. if currentIndex then
  532. -- 玩家在排行榜中,需要调整位置
  533. adjustPlayerPosition(playerId)
  534. else
  535. -- 玩家不在排行榜中,检查候选集
  536. if state.candidateMap[playerId] then
  537. if state.size < state.maxSize then
  538. state.candidateMap[playerId] = nil
  539. insertToRank(playerData)
  540. else
  541. local lastPlayer = state.rankArray[state.size]
  542. local lastKey = getPlayerSortKey(lastPlayer.pointNum, lastPlayer.pointAllWeight, lastPlayer.power)
  543. local newKey = getPlayerSortKey(playerData.pointNum, playerData.pointAllWeight, playerData.power)
  544. if newKey > lastKey or (newKey == lastKey and playerId < lastPlayer.id) then
  545. state.candidateMap[lastPlayer.id] = true
  546. state.candidateMap[playerId] = nil
  547. removeFromRank(lastPlayer.id)
  548. insertToRank(playerData)
  549. end
  550. end
  551. end
  552. end
  553. end
  554. end
  555. function interface.updatePointNum(playerId, pointNum)
  556. if state.players[playerId] then
  557. state.players[playerId].pointNum = pointNum
  558. local currentIndex = state.playerIndex[playerId]
  559. if currentIndex then
  560. adjustPlayerPosition(playerId)
  561. else
  562. -- 不在排行榜中,检查候选集
  563. if state.candidateMap[playerId] then
  564. checkCandidates()
  565. end
  566. end
  567. end
  568. end
  569. function interface.updatePointAllWeight(playerId, pointAllWeight)
  570. if state.players[playerId] then
  571. state.players[playerId].pointAllWeight = pointAllWeight
  572. local currentIndex = state.playerIndex[playerId]
  573. if currentIndex then
  574. adjustPlayerPosition(playerId)
  575. else
  576. -- 不在排行榜中,检查候选集
  577. if state.candidateMap[playerId] then
  578. checkCandidates()
  579. end
  580. end
  581. end
  582. end
  583. function interface.updatePower(playerId, power)
  584. if state.players[playerId] then
  585. state.players[playerId].power = power
  586. local currentIndex = state.playerIndex[playerId]
  587. if currentIndex then
  588. adjustPlayerPosition(playerId)
  589. else
  590. -- 不在排行榜中,检查候选集
  591. if state.candidateMap[playerId] then
  592. checkCandidates()
  593. end
  594. end
  595. end
  596. end
  597. function interface.removePlayer(playerId)
  598. return removePlayerCompletely(playerId)
  599. end
  600. function interface.getRankList()
  601. checkCandidates() -- 每次获取时检查候选
  602. local result = {}
  603. for i = 1, state.size do
  604. local player = state.rankArray[i]
  605. table.insert(result, {
  606. playerId = player.id,
  607. name = player.name,
  608. rank = i,
  609. power = player.power,
  610. pointNum = player.pointNum,
  611. pointAllWeight = player.pointAllWeight
  612. })
  613. end
  614. return result
  615. end
  616. function interface.getPlayerRank(playerId)
  617. local index = state.playerIndex[playerId]
  618. return index
  619. end
  620. function interface.getPlayerDetail(playerId)
  621. local index = state.playerIndex[playerId]
  622. if index then
  623. local player = state.rankArray[index]
  624. return {
  625. rank = index,
  626. playerId = player.id,
  627. name = player.name,
  628. power = player.power,
  629. pointNum = player.pointNum,
  630. pointAllWeight = player.pointAllWeight
  631. }
  632. end
  633. return nil
  634. end
  635. function interface.hasPlayer(playerId)
  636. return state.players[playerId] ~= nil
  637. end
  638. function interface.getTotalPlayers()
  639. return tableCount(state.players)
  640. end
  641. function interface.batchUpdate(updates)
  642. for _, update in ipairs(updates) do
  643. if update.playerId then
  644. interface.updatePlayer(
  645. update.playerId,
  646. update.name,
  647. update.power,
  648. update.pointNum,
  649. update.pointAllWeight
  650. )
  651. end
  652. end
  653. end
  654. function interface._getState()
  655. return {
  656. totalPlayers = tableCount(state.players),
  657. rankSize = state.size,
  658. candidateCount = tableCount(state.candidateMap)
  659. }
  660. end
  661. return interface
  662. end
  663. -- 辅助函数:计算表的元素数量
  664. function tableCount(t)
  665. local count = 0
  666. for _ in pairs(t) do count = count + 1 end
  667. return count
  668. end
  669. -- 辅助函数:计算表的元素数量
  670. function tableCount(t)
  671. local count = 0
  672. for _ in pairs(t) do count = count + 1 end
  673. return count
  674. end
  675. -- 生成公会排行榜
  676. local function genGroupUnionRankList(unionRank, unionIdArr)
  677. local function getUnionRankVal(union)
  678. local occupyCityNum, occupyPointNum, power = 0, 0, 0
  679. power = union.power or 0
  680. for _, v in pairs(union.occupCityList or {}) do
  681. if v.isOccupy then
  682. occupyCityNum = occupyCityNum + 1
  683. end
  684. for _, _ in pairs(v.occupyPointList or {}) do
  685. occupyPointNum = occupyPointNum + 1
  686. end
  687. end
  688. return occupyCityNum, occupyPointNum, power
  689. end
  690. for _, unionId in ipairs(unionIdArr) do
  691. local unionData = AnotherWorldBattleData.unionList[unionId]
  692. if unionData then
  693. local occupyCityNum, occupyPointNum, power = getUnionRankVal(unionData)
  694. unionRank.updateGuild(unionId, unionData.name, power, occupyCityNum, occupyPointNum )
  695. end
  696. end
  697. end
  698. -- 生成个人排行榜
  699. local function genGroupPlayerRankList(playerRank, unionIdArr, playerListData)
  700. local playerArr = {}
  701. local function insertPlayerArr(unionId)
  702. if not playerListData then
  703. return
  704. end
  705. for playerUuid, playerInfo in pairs(playerListData) do
  706. if playerInfo.unionId == unionId then
  707. local pointNum, pointAllWeight = 0, 0
  708. for cityId, pointList in pairs(playerInfo.heroList or {}) do
  709. for _, _ in pairs(pointList) do
  710. pointNum = pointNum + 1
  711. local cityCfg = AnotherWorldBattleConfig.city[cityId]
  712. pointAllWeight = pointAllWeight + (cityCfg and cityCfg.pointWeight or 0)
  713. end
  714. end
  715. playerArr[#playerArr+1] = {playerId = playerUuid, name = playerInfo.name, power = playerInfo.power, pointNum = pointNum, pointAllWeight = pointAllWeight}
  716. end
  717. end
  718. end
  719. for _, unionId in ipairs(unionIdArr) do
  720. insertPlayerArr(unionId)
  721. end
  722. playerRank.batchUpdate(playerArr)
  723. end
  724. -- 生成 "公会-公会所属分组Id" 映射表
  725. local function genUnion2GroupList(groupId, unionIdArr)
  726. for _, unionId in ipairs(unionIdArr) do
  727. Union_2_Group[unionId] = groupId
  728. end
  729. end
  730. -- 生成 "serverId - 公会Array" 映射表
  731. local function genServer2UnionArr(unionRank)
  732. local rankList = unionRank.getRankList()
  733. for _, rankInfo in ipairs(rankList) do
  734. local unionId = rankInfo.guildId
  735. local unionInfo = AnotherWorldBattleData.unionList[unionId]
  736. if unionInfo then
  737. local serverId = unionInfo.serverId
  738. Server_2_UnionArr[serverId] = Server_2_UnionArr[serverId] or {}
  739. Server_2_UnionArr[serverId][#Server_2_UnionArr[serverId]+1] = unionId
  740. end
  741. end
  742. end
  743. -- 生成各组的缓存数据
  744. local function genGroupCache()
  745. if not AnotherWorldBattleData.groupArray then
  746. return
  747. end
  748. local playerListData = AnotherWorldBattleData.playerList
  749. for groupId, unionIdArr in ipairs(AnotherWorldBattleData.groupArray) do
  750. -- 城池
  751. Group_2_CityList[groupId] = {}
  752. genCityList(Group_2_CityList[groupId], unionIdArr)
  753. -- 公会排行榜
  754. Group_2_UnionRankList[groupId] = createGuildRank()
  755. genGroupUnionRankList(Group_2_UnionRankList[groupId], unionIdArr)
  756. -- "serverId -- unionIdArray" 映射表
  757. genServer2UnionArr(Group_2_UnionRankList[groupId])
  758. -- 个人排行榜
  759. Group_2_PlayerRankList[groupId] = createPlayerRank()
  760. genGroupPlayerRankList(Group_2_PlayerRankList[groupId], unionIdArr, playerListData)
  761. -- "公会-公会所属分组" 映射表
  762. genUnion2GroupList(groupId, unionIdArr)
  763. end
  764. end
  765. function initAfterStart()
  766. if _G.is_middle ~= true then return end
  767. loadData()
  768. genGroupCache()
  769. end
  770. -- 重置数据
  771. function ResetData()
  772. Group_2_CityList = {}
  773. Group_2_UnionRankList = {}
  774. Group_2_PlayerRankList = {}
  775. Union_2_Group = {}
  776. Server_2_UnionArr = {}
  777. AnotherWorldBattleData.lastRoundStartTime = os.time()
  778. -- AnotherWorldBattleData.stage = AnotherWorldBattleDefine.AB_STATE_JOIN
  779. AnotherWorldBattleData.joinUnionArr = nil
  780. AnotherWorldBattleData.groupArray = nil
  781. AnotherWorldBattleData.unionList = nil
  782. AnotherWorldBattleData.playerList = nil
  783. dbUpdate._id = AnotherWorldBattleData._id
  784. LuaMongo.update(DB.db_anotherWorldBattle, dbUpdate, AnotherWorldBattleData)
  785. end
  786. -- 获取公会所在分组的Id
  787. function GetUnionGroupId(unionId)
  788. return Union_2_Group[unionId]
  789. end
  790. -- 当自己公会没有参赛时, 获取本服第一个公会所在分组Id
  791. function GetGroupIdByServerId(serverId)
  792. local unionArr = Server_2_UnionArr[serverId]
  793. if unionArr and unionArr[1] then
  794. local unionId = unionArr[1]
  795. return GetUnionGroupId(unionId)
  796. end
  797. end
  798. -- 获取活动当前阶段
  799. function GetStage()
  800. return AnotherWorldBattleData.stage
  801. end
  802. -- 更新活动当前阶段
  803. function UpdateStage(newStage)
  804. AnotherWorldBattleData.stage = newStage
  805. updateValue("stage", newStage)
  806. if newStage == AnotherWorldBattleDefine.AB_STATE_BATTLE then
  807. genGroupCache()
  808. end
  809. end
  810. -- 获取活动上一轮的开始时间
  811. function GetLastRoundStartTime()
  812. return AnotherWorldBattleData.lastRoundStartTime
  813. end
  814. function UpdateLastRoundStartTime(newTime)
  815. AnotherWorldBattleData.lastRoundStartTime = newTime
  816. updateValue("lastRoundStartTime", newTime)
  817. end
  818. -- 获取参赛公会列表
  819. function GetJoinUnionArr()
  820. return AnotherWorldBattleData.joinUnionArr
  821. end
  822. -- 更新参赛公会列表
  823. function UpdateJoinUnionArr(newJoinUnionArr)
  824. AnotherWorldBattleData.joinUnionArr = newJoinUnionArr
  825. updateValue("joinUnionArr", newJoinUnionArr)
  826. end
  827. -- 获取分组列表
  828. function GetGroupArray()
  829. return AnotherWorldBattleData.groupArray
  830. end
  831. -- 更新分组列表
  832. function UpdateGroupArray(newGroupArray)
  833. AnotherWorldBattleData.groupArray = newGroupArray
  834. updateValue("groupArray", newGroupArray)
  835. end
  836. -- 获取公会名字
  837. function GetUnionName(unionId)
  838. return AnotherWorldBattleData.unionList and AnotherWorldBattleData.unionList[unionId].name or ""
  839. end
  840. -- 获取某个公会数据
  841. function GetUnionData(unionId)
  842. return AnotherWorldBattleData.unionList and AnotherWorldBattleData.unionList[unionId]
  843. end
  844. -- 更新某个公会数据
  845. function UpdateUnionData(unionId, newUnionData)
  846. if not AnotherWorldBattleData.unionList then
  847. AnotherWorldBattleData.unionList = {}
  848. -- updateValue("unionList", AnotherWorldBattleData.unionList)
  849. end
  850. AnotherWorldBattleData.unionList[unionId] = newUnionData
  851. updateValue("unionList"..".".. unionId, newUnionData)
  852. end
  853. -- 获取公会列表
  854. function GetUnionList()
  855. return AnotherWorldBattleData.unionList
  856. end
  857. -- 获取玩家名字
  858. function GetPlayerName(playerUuid)
  859. local playerListData = AnotherWorldBattleData.playerList
  860. if playerListData and playerListData[playerUuid] then
  861. return playerListData[playerUuid].name or ""
  862. end
  863. return ""
  864. end
  865. -- 获取玩家数据
  866. function GetPlayerData(playerUuid)
  867. return AnotherWorldBattleData.playerList and AnotherWorldBattleData.playerList[playerUuid]
  868. end
  869. -- 更新玩家数据
  870. function UpdatePlayerData(playerUuid, newPlayerData)
  871. if not AnotherWorldBattleData.playerList then
  872. AnotherWorldBattleData.playerList = {}
  873. -- updateValue("playerList", AnotherWorldBattleData.playerList)
  874. end
  875. AnotherWorldBattleData.playerList[playerUuid] = newPlayerData
  876. updateValue("playerList".. "." .. playerUuid, newPlayerData)
  877. end
  878. -- 获取公会列表
  879. function GetPlayerList()
  880. return AnotherWorldBattleData.playerList
  881. end
  882. -- 获取城池数据
  883. function GetCityListByGroupId(groupId)
  884. return Group_2_CityList[groupId]
  885. end
  886. -- 更新城池数据
  887. function UpdateCityList(groupId, newCityList)
  888. Group_2_CityList[groupId] = newCityList
  889. end
  890. -- 获取公会排行数据
  891. function GetUnionRankList(groupId)
  892. local unionRank = Group_2_UnionRankList[groupId]
  893. if unionRank then
  894. return unionRank.getRankList()
  895. end
  896. end
  897. -- 更新公会的排行榜数据, cityVal, pointVal为变化的值
  898. function UpdateUnionRankList(groupId, unionId, cityVal, pointVal, newPower)
  899. local unionRank = Group_2_UnionRankList[groupId]
  900. if unionRank then
  901. local unionRankInfo = unionRank.getGuildDetail(unionId)
  902. unionRankInfo.occupyCityNum = unionRankInfo.occupyCityNum + cityVal
  903. unionRankInfo.occupyPointNum = unionRankInfo.occupyPointNum + pointVal
  904. if newPower then
  905. unionRankInfo.power = newPower
  906. end
  907. unionRank.updateGuild(unionId, unionRankInfo.name, unionRankInfo.power, unionRankInfo.occupyCityNum, unionRankInfo.occupyPointNum)
  908. end
  909. end
  910. -- 生成玩家用于排名的数据
  911. local function genPlayerRankVal(playerUuid)
  912. local playerListData = AnotherWorldBattleData.playerList
  913. local name, power, pointNum, pointAllWeight = "", 0, 0, 0
  914. if playerListData and playerListData[playerUuid] then
  915. power = playerListData[playerUuid].power or 0
  916. name = playerListData[playerUuid].name or ""
  917. for cityId, pointList in pairs(playerListData[playerUuid].heroList or {}) do
  918. for _, _ in pairs(pointList) do
  919. pointNum = pointNum + 1
  920. local cityCfg = AnotherWorldBattleConfig.city[cityId]
  921. pointAllWeight = pointAllWeight + (cityCfg and cityCfg.pointWeight or 0)
  922. end
  923. end
  924. end
  925. return name, power, pointNum, pointAllWeight
  926. end
  927. -- 获取玩家排行数据
  928. function GetPlayerRankList(groupId)
  929. local playerRank = Group_2_PlayerRankList[groupId]
  930. if playerRank then
  931. return playerRank.getRankList()
  932. end
  933. end
  934. -- 更新玩家排行数据, pointVal, pointWeightVal为变化的值
  935. function UpdatePlayerRankList(groupId, playerUuid, pointVal, pointWeightVal, newPower)
  936. local playerRank = Group_2_PlayerRankList[groupId]
  937. if playerRank then
  938. local playerRankData = playerRank.getPlayerDetail(playerUuid)
  939. if not playerRankData then
  940. playerRankData = {}
  941. local name, power, pointNum, pointAllWeight = genPlayerRankVal(playerUuid)
  942. playerRankData.name = name
  943. playerRankData.power = power
  944. playerRankData.pointNum = pointNum
  945. playerRankData.pointAllWeight = pointAllWeight
  946. else
  947. playerRankData.pointNum = playerRankData.pointNum + pointVal
  948. playerRankData.pointAllWeight = playerRankData.pointAllWeight + pointWeightVal
  949. if newPower then
  950. playerRankData.power = newPower
  951. end
  952. end
  953. playerRank.updatePlayer(playerUuid, playerRankData.name, playerRankData.power, playerRankData.pointNum, playerRankData.pointAllWeight)
  954. end
  955. end