diff --git a/game-server/app/servers/gm/remote/gmRemote.ts b/game-server/app/servers/gm/remote/gmRemote.ts index b346a3bf0..01292f230 100644 --- a/game-server/app/servers/gm/remote/gmRemote.ts +++ b/game-server/app/servers/gm/remote/gmRemote.ts @@ -1,5 +1,6 @@ import { Application, ChannelService, HandlerService, } from 'pinus'; import { setHiddenData } from '../../../services/dataService'; +import { setGVGServerGroup } from '../../../services/gvg/gvgService'; import { errlogger } from '../../../util/logger'; export default function (app: Application) { @@ -35,5 +36,13 @@ export class GMRemote { errlogger.error(`remote ${__filename} \n ${e.stack}`); } } + + public async setGVGServerGroup() { + try { + await setGVGServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } } \ No newline at end of file diff --git a/game-server/app/servers/guild/handler/gvgHandler.ts b/game-server/app/servers/guild/handler/gvgHandler.ts index 3c7ff384b..3b7fc8bda 100644 --- a/game-server/app/servers/guild/handler/gvgHandler.ts +++ b/game-server/app/servers/guild/handler/gvgHandler.ts @@ -2,7 +2,7 @@ import { Application, BackendSession, ChannelService, HandlerService, pinus } fr import { GVG_ITEM, DATA_NAME, GVG_ACTIVE_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, LEAGUE_MANAGE_TYPE, STATUS, GVG_REC_TYPE, TASK_TYPE, GVG_TECH_TYPE, PUSH_ROUTE } from "../../../consts"; import { GVGLeagueModel } from "../../../db/GVGLeague"; import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare"; -import { GVGMainData, LeagueContributeInfo, LeagueMemberContributeInfo, LeagueMemberListInfo } from "../../../domain/gvgField/returnData"; +import { GuardCityInfoPage, GVGMainData, LeagueContributeInfo, LeagueMemberContributeInfo, LeagueRankInInfoPage } from "../../../domain/gvgField/returnData"; import { getRandEelm, resResult } from "../../../pubUtils/util"; import { calLeagueCe, getGroupIdOfServer, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType, getServerTypeByTime } from "../../../services/gvg/gvgService"; import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, checkLeagueAuth, getMyAuth } from "../../../services/gvg/gvgTeamService"; @@ -25,6 +25,8 @@ import { getFightTimeByPeriod, getMyVestiges, getVestiges } from "../../../servi import { getSeconds } from "../../../pubUtils/timeUtil"; import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank"; import { addTechActivateMessage, addTechUnlockMessage } from "../../../services/gvg/gvgRecService"; +import { GuildModel } from "../../../db/Guild"; +import { GVGCityModel } from "../../../db/GVGCity"; export default function (app: Application) { new HandlerService(app, {}); @@ -461,6 +463,78 @@ export class GVGHandler { }); } + // 情报页面:联军排名 + async getLeagueRankInfo(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const prepares = await GVGLeaguePrepareModel.getLvRank(configId); + const leagues = await GVGLeagueModel.findByCodes(prepares.map(cur => cur.leagueCode)); + const guilds = await GuildModel.findByCodesWithoutPopulate(leagues.reduce((pre, cur) => [...pre, ...cur.guildCodes], [])); + const cities = await GVGCityModel.findGuardCity(configId, groupKey); + + let ranks: LeagueRankInInfoPage[] = [], myRank: LeagueRankInInfoPage = undefined; + prepares.forEach((prepare, index) => { + let league = leagues.find(cur => cur.leagueCode == prepare.leagueCode); + if(!league) return; + let leagueGuilds = guilds.filter(cur => cur.leagueCode == league.leagueCode); + let leagueCe = leagueGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); + let guardCities = cities.filter(cur => cur.guardLeague == league.leagueCode).map(cur => cur.cityId); + let data = new LeagueRankInInfoPage(index + 1, league, prepare, leagueCe, guardCities); + if(myLeague.leagueCode == league.leagueCode) myRank = data; + ranks.push(data); + }); + + if(!myRank) { + let myGuilds = await GuildModel.findByCodes(myLeague.guildCodes); + let leagueCe = myGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); + let guardCities = cities.filter(cur => cur.guardLeague == myLeague.leagueCode).map(cur => cur.cityId); + myRank = new LeagueRankInInfoPage(0, myLeague, null, leagueCe, guardCities); + } + + return resResult(STATUS.SUCCESS, { + ranks, myRank + }) + } + + // 情报页面:城池占领 + async getGuardCityInfo(msg: {}, session: BackendSession) { + + const serverId = session.get('serverId'); + + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + + const cities = await GVGCityModel.findGuardCity(configId, groupKey); + const leagueCodes = cities.map(cur => cur.guardLeague); + const leagues = await GVGLeagueModel.findByCodes(leagueCodes); + const prepares = await GVGLeaguePrepareModel.findByLeagueCodes(configId, leagueCodes); + const guilds = await GuildModel.findByCodesWithoutPopulate(leagues.reduce((pre, cur) => [...pre, ...cur.guildCodes], [])); + + const result: GuardCityInfoPage[] = []; + for(let { cityId, guardLeagueCode } of result) { + let league = leagues.find(cur => cur.leagueCode == guardLeagueCode); + if(!league) continue; + let prepare = prepares.find(cur => cur.leagueCode == guardLeagueCode); + let leagueGuilds = guilds.filter(cur => cur.leagueCode == league.leagueCode); + let leagueCe = leagueGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); + + let data = new GuardCityInfoPage(cityId); + data.setGuardLeague(league, prepare, leagueCe); + } + + return resResult(STATUS.SUCCESS, { + cities: result + }) + } + // 获取道具 async debugAddLeagueItem(msg: { id: number, count: number }, session: BackendSession) { const roleId = session.get('roleId'); @@ -490,10 +564,4 @@ export class GVGHandler { const result = await handleGVGCost(roleId, myLeague.leagueCode, sid, leagueItems, items, ITEM_CHANGE_REASON.DEBUG); return resResult(STATUS.SUCCESS, { result }); } - - async getServerType(msg: { time: string }, session: BackendSession) { - let t = new Date(msg.time); - let serverType = getServerTypeByTime(getSeconds(t)); - return resResult(STATUS.SUCCESS, { serverType }); - } } \ No newline at end of file diff --git a/game-server/app/servers/systimer/remote/systimerRemote.ts b/game-server/app/servers/systimer/remote/systimerRemote.ts index 753177fff..c16469133 100644 --- a/game-server/app/servers/systimer/remote/systimerRemote.ts +++ b/game-server/app/servers/systimer/remote/systimerRemote.ts @@ -19,6 +19,7 @@ import { GUILD_ACTIVITY_TYPE, LADDER_STATUS } from '../../../consts'; import { setApiIsClose } from '../../../services/chatService'; import { setHiddenData } from '../../../services/dataService'; import { setKvToMemory } from '../../../services/pushService'; +import { setGVGServerGroup } from '../../../services/gvg/gvgService'; export default function (app: Application) { return new SystimerRemote(app); @@ -274,4 +275,12 @@ export class SystimerRemote { errlogger.error(`remote ${__filename} \n ${e.stack}`); } } + + public async setGVGServerGroup() { + try { + await setGVGServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } } diff --git a/game-server/app/services/gvg/gvgService.ts b/game-server/app/services/gvg/gvgService.ts index b29cf12be..761b3051d 100644 --- a/game-server/app/services/gvg/gvgService.ts +++ b/game-server/app/services/gvg/gvgService.ts @@ -35,6 +35,8 @@ export async function createNewGVGConfig() { await pinus.app.rpc.guild.guildRemote.setGVGServerGroup.broadcast(); await pinus.app.rpc.chat.chatRemote.setGVGServerGroup.broadcast(); await pinus.app.rpc.connector.connectorRemote.setGVGServerGroup.broadcast(); + await pinus.app.rpc.gm.gmRemote.setGVGServerGroup.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setGVGServerGroup.broadcast(); await pinus.app.rpc.guild?.guildRemote?.clearBattleMemory.broadcast(); } catch(e) { console.log('remote未初始完'); @@ -183,8 +185,15 @@ export async function initLeaguePrepare() { const config = await GVGConfigModel.findConfig(); if(!config) return; const leagues = await GVGLeagueModel.findAllLeague(); - for(let { leagueCode, memberCnt } of leagues) { - await GVGLeaguePrepareModel.initData(config.configId, leagueCode, memberCnt); + let groupKeyByServerId = new Map(); + for(let { leagueCode, memberCnt, serverId } of leagues) { + let groupKey = groupKeyByServerId.get(serverId); + if(!groupKey) { + groupKey = await getGroupKey(serverId); + groupKeyByServerId.set(serverId, groupKey); + } + + await GVGLeaguePrepareModel.initData(config.configId, groupKey, leagueCode, memberCnt); } } diff --git a/game-server/app/services/gvg/gvgTeamService.ts b/game-server/app/services/gvg/gvgTeamService.ts index 79213a34e..66e171f85 100644 --- a/game-server/app/services/gvg/gvgTeamService.ts +++ b/game-server/app/services/gvg/gvgTeamService.ts @@ -34,7 +34,8 @@ export async function autoCreateLeague(guildCode: string) { let { configId, period } = getGVGPeriodData(); if(period == GVG_PERIOD.PREPARE) { let league = await createLeague(guild, {}); - await GVGLeaguePrepareModel.initData(configId, league.leagueCode, guild.memberCnt); + let groupKey = await getGroupKey(guild.serverId); + await GVGLeaguePrepareModel.initData(configId, groupKey, league.leagueCode, guild.memberCnt); return league; } } diff --git a/shared/db/GVGLeague.ts b/shared/db/GVGLeague.ts index cf6c15536..61e3b50c4 100644 --- a/shared/db/GVGLeague.ts +++ b/shared/db/GVGLeague.ts @@ -137,9 +137,9 @@ export default class GVGLeague extends BaseModel { } public static async findAllLeague() { - const leagues: { leagueCode: string, memberCnt: number }[] = await GVGLeagueModel.aggregate([ + const leagues: { leagueCode: string, memberCnt: number, serverId: number }[] = await GVGLeagueModel.aggregate([ { $match: { status: 1 } }, - { $project: { leagueCode: 1, memberCnt: 1 } } + { $project: { leagueCode: 1, memberCnt: 1, serverId: 1 } } ]); return leagues; } diff --git a/shared/db/GVGLeaguePrepare.ts b/shared/db/GVGLeaguePrepare.ts index e6e6fe581..1f8eac607 100644 --- a/shared/db/GVGLeaguePrepare.ts +++ b/shared/db/GVGLeaguePrepare.ts @@ -44,11 +44,15 @@ class GuildActive { } @index({ leagueCode: 1, configId: 1 }) +@index({ configId: 1, lv: -1 }) export default class GVGLeaguePrepare extends BaseModel { @prop({ required: true }) configId: number; // 赛期配置id + @prop({ required: true }) + groupKey: string; // 战区 + @prop({ required: true }) leagueCode: string; // 联军 @@ -82,12 +86,12 @@ export default class GVGLeaguePrepare extends BaseModel { @prop({ required: true, default: [], type: GuildActive, _id: false }) guildActive: GuildActive[]; // 军团活跃 - public static async initData(configId: number, leagueCode: string, maxMemberCnt: number) { + public static async initData(configId: number, groupKey: string, leagueCode: string, maxMemberCnt: number) { const doc = new GVGLeaguePrepareModel(); const update = Object.assign(doc.toJSON(), { maxMemberCnt }); delete update._id; - const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({ configId, leagueCode }, { $setOnInsert: update }, { upsert: true, new: true }) + const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({ configId, leagueCode, groupKey }, { $setOnInsert: update }, { upsert: true, new: true }) .select({ _id: 0, __v: 0, createdAt: 0, updatedAt: 0 }).lean(); return result; } @@ -97,6 +101,12 @@ export default class GVGLeaguePrepare extends BaseModel { return result; } + + public static async findByLeagueCodes(configId: number, leagueCodes: string[]) { + const result: GVGLeaguePrepareType[] = await GVGLeaguePrepareModel.findOne({ configId, leagueCode: { $in: leagueCodes } }).lean(); + return result; + } + public static async chooseJob(configId: number, leagueCode: string, job: LEAGUE_JOB) { if(job == LEAGUE_JOB.FIGHTER) { const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({ configId, leagueCode }, { $inc: { fighterCnt: 1 } }, { new: true }).lean(); @@ -146,6 +156,11 @@ export default class GVGLeaguePrepare extends BaseModel { const result: GVGLeaguePrepareType[] = await GVGLeaguePrepareModel.aggregate([{ $match: {configId} }]); return result; } + + public static async getLvRank(configId: number) { + const result: GVGLeaguePrepareType[] = await GVGLeaguePrepareModel.find({ configId }).sort({ lv: -1 }).lean(); + return result; + } } export const GVGLeaguePrepareModel = getModelForClass(GVGLeaguePrepare); diff --git a/shared/db/Guild.ts b/shared/db/Guild.ts index 55edd4bec..25a32d39f 100644 --- a/shared/db/Guild.ts +++ b/shared/db/Guild.ts @@ -346,6 +346,10 @@ export default class Guild extends BaseModel { return result; } + public static async findByCodesWithoutPopulate(codes: string[]) { + const result: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, code: { $in: codes } }).select('+serverId').lean(); + return result; + } public static async quitFromLeague(guildCode: string, leagueCode: string, select = null) { const result: GuildType = await GuildModel.findOneAndUpdate({ code: guildCode, leagueCode }, { $set: { leagueCode: '' } }, { new: true }).select(select).lean(); return result; diff --git a/shared/domain/gvgField/returnData.ts b/shared/domain/gvgField/returnData.ts index 52cc64623..8ee8ba715 100644 --- a/shared/domain/gvgField/returnData.ts +++ b/shared/domain/gvgField/returnData.ts @@ -824,4 +824,55 @@ export class MyTeamInfo { this.pointId = team.pointId; this.curTeamBreak = team.curTeamBreak; } +} + +// 情报 +// 联军排名 +export class LeagueRankInInfoPage { + rank: number; + leagueCode: string = ''; + leagueName: string = ''; + lv: number = 1; + leaderName: string = ''; + leagueCe: number = 0; + cities: number[] = []; + + constructor(rank: number, league: GVGLeagueType, prepare: GVGLeaguePrepareType, ce: number, cities: number[]) { + this.rank = rank; + if(league) { + this.leagueCode = league.leagueCode; + this.leagueName = league.name; + this.leaderName = (league.leader)?.roleName; + } + if(prepare) { + this.lv = prepare.lv; + } + this.leagueCe = ce; + this.cities = cities; + } +} + +export class GuardCityInfoPage { + cityId: number; + guardLeagueCode: string = ''; + guardLeagueName: string = ''; + lv: number = 0; + leaderName: string = ''; + leagueCe: number = 0; + + constructor(cityId: number) { + this.cityId = cityId; + } + + setGuardLeague(league: GVGLeagueType, prepare: GVGLeaguePrepareType, ce: number) { + if(league) { + this.guardLeagueCode = league.leagueCode; + this.guardLeagueName = league.name; + this.leaderName = (league.leader)?.roleName; + } + if(prepare) { + this.lv = prepare.lv; + } + this.leagueCe = ce; + } } \ No newline at end of file