diff --git a/game-server/app/servers/chat/remote/chatRemote.ts b/game-server/app/servers/chat/remote/chatRemote.ts index a81ad951f..a085adaa8 100644 --- a/game-server/app/servers/chat/remote/chatRemote.ts +++ b/game-server/app/servers/chat/remote/chatRemote.ts @@ -7,6 +7,7 @@ import { addUserToChannel, getSimpleRoleInfo } from '../../../services/roleServi import { ChannelUser } from '../../../domain/ChannelUser'; import { getWorldChannelSid, groupRoomId } from '../../../services/chatService'; import { reloadResources } from '../../../pubUtils/data'; +import { GeneralRankParamRole, GeneralRankParamBattle } from '../../../domain/rank'; export default function (app: Application) { return new ChatRemote(app); @@ -33,6 +34,7 @@ export class ChatRemote { private channelService: ChannelService; private GUILD_ACTIVITY_END = 'onGuildActivityEnd'; private RACE_ACTIVITY_START = 'onRaceStart'; + private RANK_TOP_UPDATE = 'onRankTopUpdated'; /** * 加入世界频道(分服). @@ -190,6 +192,18 @@ export class ChatRemote { channel.pushMessage(this.RACE_ACTIVITY_START, resResult(STATUS.SUCCESS, { })); } + /** + * @description 全服推送排行榜更新信息 + * @param serverId + */ + public async sendRankTopUpdated(serverId: number, rank: (GeneralRankParamRole|GeneralRankParamBattle)&{general: number}) { + + let roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); + let channel = this.channelService.getChannel(roomId, false); + if (!channel) return; + channel.pushMessage(this.RANK_TOP_UPDATE, resResult(STATUS.SUCCESS, { rank })); + } + /** * 重载json资源 */ diff --git a/game-server/app/services/rankService.ts b/game-server/app/services/rankService.ts index feb0de60e..11dda783d 100644 --- a/game-server/app/services/rankService.ts +++ b/game-server/app/services/rankService.ts @@ -8,6 +8,8 @@ import { SystemConfigModel } from "../db/SystemConfig"; import { PvpDefenseModel } from "../db/PvpDefense"; import { gameData } from "../pubUtils/data"; import { nowSeconds } from "../pubUtils/timeUtil"; +import { getWorldChannelSid } from "./chatChannelService"; +import { pinus } from "pinus"; /** @@ -16,6 +18,7 @@ import { nowSeconds } from "../pubUtils/timeUtil"; * @class Rank */ export class Rank { + isInit: boolean = false; // 初始排行榜 key: string; // 排行榜原始key keyName: KeyName; // 拼接之后的key infoKey: string; // 玩家数据key @@ -46,6 +49,10 @@ export class Rank { this.limit = limit; } + public setIsInit(init: boolean) { + this.isInit = init; + } + /** * 返回字段修改 * @param obj @@ -284,7 +291,8 @@ export class Rank { * @param isInc */ public async setRank(myId: myIdInter, score: number, timestamp: number, isInc = false) { - + let oldTop = await this.getRankByRank(0, 0); + let oldScore = oldTop.length > 0? oldTop[0].num: 0; // 更新分数 let newScore = score; if (this.isUnion) { @@ -292,6 +300,7 @@ export class Rank { } else { newScore = await this.updateRankScoreEncode(myId, score, timestamp, isInc) } + this.checkMyRankAndPush(myId, oldScore, newScore); return newScore; } @@ -599,6 +608,47 @@ export class Rank { return ranks } + public async getRankByRank(start: number, end: number) { + + let ranks = new Array(); + let key = this.keyName.getName(); + if (this.isUnion) { + key = await this.generateUnionRank(); + } + + const rankFromDb = await redisClient().zrevrangeAsync(key, start, end, "WITHSCORES"); + + let num = 0; + for (let ii = 0; ii < rankFromDb.length; ii += 2) { + if(num >= this.limit) break; + + const field = rankFromDb[ii]; + let myId = this.decodeFields(this.key, field); + const { score, time } = this.decodeScore(rankFromDb[ii + 1]); + const info = await redisClient().hgetAsync(this.infoKey, this.composeFields(this.infoKey, myId)); + const userInfo = JSON.parse(info); + + let param: RoleRankInfo | GuildRankInfo; + if (this.infoKey == REDIS_KEY.USER_INFO) { + if(nowSeconds() - userInfo.updatedAt > 2 * 30 * 24 * 60 * 60) { + continue; + } + param = new RoleRankInfo(userInfo, false); + param.setInfo(Math.floor(ii / 2) + 1, myId, score, time); + } else if (this.infoKey == REDIS_KEY.GUILD_INFO) { + param = new GuildRankInfo(userInfo); + param.setInfo(Math.floor(ii / 2) + 1, myId, score, time); + } + + for (let extraKey of this.extraKeys) { + await this.setExInfoToParam(extraKey, param, myId, {}); + } + ranks.push(param); + num ++; + } + return ranks + } + // 获取我的排名 public async getMyRank(myId: myIdInter) { @@ -681,6 +731,39 @@ export class Rank { } return timestamp } + + private async checkMyRankAndPush(myId: myIdInter, oldScore: number, newScore: number) { + if(this.isInit) return; + let myRank = await this.getMyRank(myId); + if(myRank == 1 && newScore > oldScore) { + let serverId = this.keyName.serverId; + let sid = await getWorldChannelSid(serverId); + for(let { id, general } of gameData.rank) { + let redisKey = RANK_TYPE_TO_KEY.get(id); + if(redisKey == this.key) { + if(general == 1) { + let r = new Rank(redisKey, { serverId }, false, 1); + let ranks = await r.getRankByRange(); + if(ranks.length > 0) { + let param = new GeneralRankParamRole(id, ranks[0]||new RoleRankInfo({}, false)); + pinus.app.rpc.chat.chatRemote.sendRankTopUpdated.toServer(sid, serverId, {...param, general}); + } + } else if (general = 2) { + let r = new Rank(redisKey, { serverId }, false, 1); + let ranks = await r.getRankByRange(); + let hero: HeroUpdate; + if(ranks.length > 0) { + hero = await HeroModel.getMyTopHero(ranks[0].roleId, 'hid skins'); + let param = new GeneralRankParamBattle(id, ranks[0]||new RoleRankInfo({}, false), hero); + pinus.app.rpc.chat.chatRemote.sendRankTopUpdated.toServer(sid, serverId, {...param, general}); + } + } + + break; + } + } + } + } } @@ -695,6 +778,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('tower', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { // console.log(roleId); await r.setRankWithRoleInfo(role.roleId, role.towerLv, role.towerUpTime?role.towerUpTime.getTime():0, role); @@ -703,6 +787,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await GuildModel.getRank(type, serverId); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let guild of ranks) { await r.setRankWithGuildInfo(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); } @@ -710,6 +795,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await GuildModel.getRank(type, serverId); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let guild of ranks) { await r.setRankWithGuildInfo(guild.code, guild.lv, guild.lvUpdateTime, guild); } @@ -718,6 +804,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number console.log('execute season resetPvpRanks seasonNum = ' + seasonNum); let ranks = await PvpDefenseModel.getRank(seasonNum);//获得全服前1000名的排名,加入到redis中 let r = new Rank(type, {}); + r.setIsInit(true); for(let {roleId, role: _role, score, updatedAt } of ranks) { let role = _role; if (!role) { @@ -729,6 +816,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('topLineup', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { // console.log(roleId); await r.setRankWithRoleInfo(role.roleId, role.topLineupCe, role.updatedAt.getTime(), role); @@ -737,6 +825,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await HeroModel.getAllRank(serverId, HERO_SELECT.RANK_LINEUP); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let hero of ranks) { await r.setRankWithHeroInfo(hero.roleId, hero.hid, hero.ce, hero.updatedAt.getTime(), hero); } @@ -744,6 +833,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('heroNum', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { await r.setRankWithRoleInfo(role.roleId, role.heroNum, role.heroNumUpdatedAt, role ); } @@ -751,6 +841,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('lv', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { await r.setRankWithRoleInfo(role.roleId, role.lv, role.updatedAt.getTime(), role); } @@ -758,6 +849,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('ce', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { await r.setRankWithRoleInfo(role.roleId, role.ce, role.updatedAt.getTime(), role); } @@ -765,6 +857,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('dungeon', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { await r.setRankWithRoleInfo(role.roleId, role.dungeonWarId, role.dungeonUpdatedAt, role); } @@ -772,6 +865,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('main', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { await r.setRankWithRoleInfo(role.roleId, role.mainWarId, role.mainUpdatedAt, role); } @@ -779,6 +873,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number let serverId = args.serverId; let ranks = await RoleModel.getRank('mainElite', serverId, ROLE_SELECT.RANK); let r = new Rank(type, { serverId }); + r.setIsInit(true); for(let role of ranks) { await r.setRankWithRoleInfo(role.roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); } @@ -788,6 +883,7 @@ export async function setRankRedisFromDb(type: string, args?: {serverId?: number for(let hid of gameData.dicMyHeroes) { let ranks = await HeroModel.getRank(hid, serverId, HERO_SELECT.RANK_LINEUP); let r = new Rank(type, { serverId, hid }); + r.setIsInit(true); for(let hero of ranks) { await r.setRankWithHeroInfo(hero.roleId, hid, hero.ce, hero.updatedAt.getTime(), hero); } diff --git a/shared/db/Role.ts b/shared/db/Role.ts index 1dd9299ac..06dd10b25 100644 --- a/shared/db/Role.ts +++ b/shared/db/Role.ts @@ -506,7 +506,7 @@ export default class Role extends BaseModel { let dungeonHeroes = role && role.dungeonHeroes; let hasHero = dungeonHeroes && dungeonHeroes.find(cur => cur.battleId == battleId); if (!dungeonHeroes || !hasHero) { - role = await RoleModel.findOneAndUpdate({ roleId }, { $push: { dungeonHeroes: { battleId, heroes } }, $set: { dungeonWarId: battleId, dungeonUpdatedAt: nowSeconds() } }); + role = await RoleModel.findOneAndUpdate({ roleId }, { $push: { dungeonHeroes: { battleId, heroes } }, $set: { dungeonWarId: battleId, dungeonUpdatedAt: nowSeconds() } }, { new: true }); } return role; } diff --git a/shared/domain/rank.ts b/shared/domain/rank.ts index 37d5a390b..3e10ac639 100644 --- a/shared/domain/rank.ts +++ b/shared/domain/rank.ts @@ -266,7 +266,7 @@ export class GeneralRankParamRole { num: number; received: number[]; - constructor(type: number, rankInfo: RoleRankInfo, received: number[]) { + constructor(type: number, rankInfo: RoleRankInfo, received?: number[]) { this.type = type; this.roleId = rankInfo.roleId; this.roleName = rankInfo.roleName; @@ -296,7 +296,7 @@ export class GeneralRankParamBattle { frame: number; spine: number; - constructor(type: number, rankInfo: RoleRankInfo, hero: HeroUpdate, received: number[]) { + constructor(type: number, rankInfo: RoleRankInfo, hero: HeroUpdate, received?: number[]) { this.type = type; this.roleId = rankInfo.roleId; this.roleName = rankInfo.roleName;