diff --git a/game-server/app/servers/battle/handler/ladderHandler.ts b/game-server/app/servers/battle/handler/ladderHandler.ts index 93ed1b122..7c574cf01 100644 --- a/game-server/app/servers/battle/handler/ladderHandler.ts +++ b/game-server/app/servers/battle/handler/ladderHandler.ts @@ -119,6 +119,7 @@ export class LadderHandler { let rec = await LadderMatchRecModel.giveup(battleCode); if(rec) { pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(rec.battleCode); + if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId); } return resResult(STATUS.SUCCESS, { status: 0, time: 0 }); @@ -168,7 +169,7 @@ export class LadderHandler { pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.battleTime, LADDER_STATUS.BATTLE); return resResult(STATUS.SUCCESS, { - time: rec.battleTime + LADDER.LADDER_BATTLE_COUNTDOWN, + time: Math.floor(rec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN, battleCode: rec.battleCode }) } @@ -194,18 +195,18 @@ export class LadderHandler { let result = new LadderDataReturn(); // 交换双方排名, transaction - let { isChange, atkLadderMatch, defLadderMatch } = await LadderMatchModel.changeRank(isSuccess, rec.attackInfo, rec.defenseInfo); + let { isChange, atkLadderMatch, defLadderMatch, endTime } = await LadderMatchModel.changeRank(isSuccess, rec.attackInfo, rec.defenseInfo); if(isChange) { let oppPlayers = await battleEndWhenChange(atkLadderMatch, true); await battleEndWhenChange(defLadderMatch, true); result.setOppPlayers(oppPlayers); - rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, atkLadderMatch.rank, defLadderMatch? defLadderMatch.rank: rec.attackInfo.oldRank); + rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime, atkLadderMatch.rank, defLadderMatch? defLadderMatch.rank: rec.attackInfo.oldRank); if(atkLadderMatch.rank == 1) { pushLadderTopChangeMsg(roleId, roleName, serverId); } } else { - rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess); + rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime); let oppPlayers = await getLadderEnemies(atkLadderMatch); result.setOppPlayers(oppPlayers); } @@ -372,13 +373,28 @@ export class LadderHandler { } let roleId = session.get('roleId'); + let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); - ladderData = await LadderMatchModel.updateByRoleId(roleId, { rank, historyRank: (ladderData.historyRank > rank || ladderData.historyRank == 0)? rank: ladderData.historyRank }); - await battleEndWhenChange(ladderData, false); + let defenseInfo: { isRobot: boolean, roleId: string, oldRank: number }; + let hisLadderData = await LadderMatchModel.findByRank(rank); + if(hisLadderData) { + defenseInfo = { isRobot: false, roleId: hisLadderData.roleId, oldRank: hisLadderData.rank }; + } else { + defenseInfo = { isRobot: true, roleId: `robot${rank}`, oldRank: rank }; + } - await LadderMatchModel.updateByRoleId(roleId, { refDaily: new Date(Date.now() - 86400000) }); + let result = new LadderDataReturn(); + // 交换双方排名, transaction + let { isChange, atkLadderMatch, defLadderMatch } = await LadderMatchModel.changeRank(true, { roleId }, defenseInfo); + + if(isChange) { + let oppPlayers = await battleEndWhenChange(atkLadderMatch, true); + await battleEndWhenChange(defLadderMatch, true); + result.setOppPlayers(oppPlayers); + } + ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: rank }); return resResult(STATUS.SUCCESS); } diff --git a/game-server/app/services/ladderService.ts b/game-server/app/services/ladderService.ts index 2f44d6ba7..4759c2b15 100644 --- a/game-server/app/services/ladderService.ts +++ b/game-server/app/services/ladderService.ts @@ -196,18 +196,25 @@ export function checkRank(myRank: number, targetRank: number) { export async function getLadderOppStatus(ladderData: LadderMatchType, targetRoleId: string, myRank: number, rank: number) { if(ladderData.rank != myRank) return { status: LADDER_OPP_STATUS.MY_RANK_CHANGE }; - let { oppPlayers } = ladderData; - let curOppPlayer = oppPlayers.find(cur => cur.roleId == targetRoleId); - if(!curOppPlayer|| curOppPlayer.rank != rank) return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; + let isRobot = targetRoleId.startsWith('robot'); - if(curOppPlayer.isRobot) { + if(isRobot) { if(rank <= 3000) { let hisLadderData = await LadderMatchRecModel.checkByRank(ladderData.serverId, `robot${rank}`); - if(hisLadderData) return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; + if(hisLadderData) return { status: LADDER_OPP_STATUS.OPP_IS_LOCKED }; + + let ladderMatch = await LadderMatchModel.isRankExist(rank); + if(ladderMatch) { + return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; + } } return { status: LADDER_OPP_STATUS.BATTLE, isRobot: true }; } else { + let ladderMatch = await LadderMatchModel.findByRoleId(targetRoleId); + if(!ladderMatch || ladderMatch.rank != rank) { + return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; + } let hisLadderData = await LadderMatchModel.lock(ladderData.serverId, targetRoleId, rank); if(!hisLadderData) return { status: LADDER_OPP_STATUS.OPP_IS_LOCKED }; diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index ee4fcf295..b62552b18 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -746,12 +746,12 @@ export async function setLadderCountDown(battleCode: string, time: number, statu if(scheduledJobs[`ladder${battleCode}`]) { scheduledJobs[`ladder${battleCode}`].cancel(); } - let endTime = time + (status == LADDER_STATUS.CHECK? LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN: LADDER.LADDER_BATTLE_COUNTDOWN); - scheduleJob(`ladder${battleCode}`, endTime * 1000, async () => { + let endTime = time + (status == LADDER_STATUS.CHECK? LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN: LADDER.LADDER_BATTLE_COUNTDOWN) * 1000; + scheduleJob(`ladder${battleCode}`, endTime, async () => { await ladderTimeWillout(battleCode, status); scheduledJobs[`ladder${battleCode}`].cancel(); - scheduleJob(`ladder${battleCode}`, endTime * 1000 + LADDER_SERVER_GAP_TIME * 1000, async () => { + scheduleJob(`ladder${battleCode}`, endTime + LADDER_SERVER_GAP_TIME * 1000, async () => { await ladderTimeout(battleCode, status); scheduledJobs[`ladder${battleCode}`].cancel(); }); diff --git a/shared/db/LadderMatch.ts b/shared/db/LadderMatch.ts index a766ec23a..e637d5e08 100644 --- a/shared/db/LadderMatch.ts +++ b/shared/db/LadderMatch.ts @@ -1,6 +1,6 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose'; -import { LadderDefense, LadderOppPlayerInDB, LadderOppPlayerInfo } from '../domain/battleField/ladder'; +import { LadderDefense, LadderOppPlayerInDB } from '../domain/battleField/ladder'; import Role from './Role'; @index({ roleId: 1 }) @@ -41,6 +41,15 @@ export default class LadderMatch extends BaseModel { return result; } + public static async findByRank(rank: number) { + const result: LadderMatchType = await LadderMatchModel.findOne({ rank }).lean(); + return result; + } + + public static async isRankExist(rank: number) { + const result = await LadderMatchModel.exists({ rank }); + return result; + } public static async findByRoleIdAndInclude(roleId: string) { const result: LadderMatchType = await LadderMatchModel.findOne({ roleId }) .populate('role', 'roleId roleName head frame spine heads frames spines title lv updatedAt') @@ -96,19 +105,20 @@ export default class LadderMatch extends BaseModel { return defense; } - public static async changeRank(isSuccess: boolean, attackInfo: LadderOppPlayerInfo, defenseInfo: LadderOppPlayerInfo, times = 0) { + public static async changeRank(isSuccess: boolean, attackInfo: { roleId: string }, defenseInfo: { isRobot: boolean, roleId: string, oldRank: number }, times = 0) { if(times > 10) return { isChange: false } const session = await mongoose.connection.startSession(); session.startTransaction() try { - let newAtkLadderMatch: LadderMatchType, newDefLadderMatch: LadderMatchType, isChange = false; + let newAtkLadderMatch: LadderMatchType, newDefLadderMatch: LadderMatchType, isChange = false, endTime = Date.now(); if(defenseInfo.isRobot) { let atkLadderMatch = await LadderMatchModel.findOne({ roleId: attackInfo.roleId }).lean(); if(isSuccess && atkLadderMatch && (atkLadderMatch.rank == 0 || atkLadderMatch.rank > defenseInfo.oldRank)) { newAtkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: attackInfo.roleId }, { $set: { rank: defenseInfo.oldRank, oldRank: atkLadderMatch.rank } }, { new: true }).lean(); isChange = true; + endTime = Date.now(); } else { newAtkLadderMatch = atkLadderMatch; } @@ -119,13 +129,14 @@ export default class LadderMatch extends BaseModel { newAtkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: attackInfo.roleId }, { $set: { rank: defLadderMatch.rank, oldRank: atkLadderMatch.rank } }, { new: true }).lean(); newDefLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defenseInfo.roleId }, { $set: { rank: atkLadderMatch.rank, oldRank: defLadderMatch.rank } }, { new: true }).lean(); isChange = true; + endTime = Date.now(); } else { newAtkLadderMatch = atkLadderMatch; newDefLadderMatch = defLadderMatch; } } await session.commitTransaction() - return { isChange, atkLadderMatch: newAtkLadderMatch, defLadderMatch: newDefLadderMatch } + return { isChange, atkLadderMatch: newAtkLadderMatch, defLadderMatch: newDefLadderMatch, endTime } } catch(e) { return await this.changeRank(isSuccess, attackInfo, defenseInfo, times + 1); } finally { diff --git a/shared/db/LadderMatchRec.ts b/shared/db/LadderMatchRec.ts index 52174b929..cfdc651d7 100644 --- a/shared/db/LadderMatchRec.ts +++ b/shared/db/LadderMatchRec.ts @@ -3,7 +3,6 @@ import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoos import { LADDER_STATUS } from '../consts'; import { LadderDefense, LadderOppPlayerInfo, LadderOppPlayerHeroInfo } from '../domain/battleField/ladder'; import { genCode } from '../pubUtils/util'; -import { nowSeconds } from '../pubUtils/timeUtil'; import { LADDER } from '../pubUtils/dicParam'; @index({ battleCode: 1 }) @@ -21,11 +20,11 @@ export default class LadderMatchRec extends BaseModel { @prop({ required: true }) timeout: boolean; // 是否超时 @prop({ required: true }) - checkTime: number; // 开始出兵的时间,10位时间戳 + checkTime: number; // 开始出兵的时间,13位时间戳 @prop({ required: true }) - battleTime: number; // 开始挑战的时间,10位时间 + battleTime: number; // 开始挑战的时间,13位时间 @prop({ required: true }) - endTime: number; // 结束时间 + endTime: number; // 结束时间,13位时间戳 @prop({ required: true, type: () => LadderOppPlayerInfo, default: {}, _id: false }) attackInfo: LadderOppPlayerInfo; // 攻方信息 @prop({ required: true, type: () => LadderOppPlayerInfo, default: {}, _id: false }) @@ -46,13 +45,13 @@ export default class LadderMatchRec extends BaseModel { public static async createRec(serverId: number, roleId1: string, roleId2: string, defense: LadderDefense, attackInfo: LadderOppPlayerInfo, defenseInfo: LadderOppPlayerInfo) { const battleCode = genCode(10); const result: LadderMatchRecType = await LadderMatchRecModel.findOneAndUpdate({ battleCode }, { - $set: { roleId1, roleId2, serverId, defense, status: LADDER_STATUS.CHECK, checkTime: nowSeconds(), attackInfo, defenseInfo } + $set: { roleId1, roleId2, serverId, defense, status: LADDER_STATUS.CHECK, checkTime: Date.now(), attackInfo, defenseInfo } }, { new: true, upsert: true }).lean(); return result; } public static async timeout(battleCode: string) { - const result: LadderMatchRecType = await LadderMatchRecModel.findOneAndUpdate({ battleCode }, { $set: { status: LADDER_STATUS.COMPLETE, timeout: true, endTime: nowSeconds() } }, { new: true }).lean(); + const result: LadderMatchRecType = await LadderMatchRecModel.findOneAndUpdate({ battleCode }, { $set: { status: LADDER_STATUS.COMPLETE, timeout: true, endTime: Date.now() } }, { new: true }).lean(); return result; } @@ -68,13 +67,13 @@ export default class LadderMatchRec extends BaseModel { public static async startBattle(battleCode: string, attackHeroes: LadderOppPlayerHeroInfo[]) { const result: LadderMatchRecType = await LadderMatchRecModel.findOneAndUpdate({ battleCode }, { - $set: { status: LADDER_STATUS.BATTLE, battleTime: nowSeconds(), 'attackInfo.heroes': attackHeroes } + $set: { status: LADDER_STATUS.BATTLE, battleTime: Date.now(), 'attackInfo.heroes': attackHeroes } }, { new: true }).lean(); return result; } - public static async battleEnd(battleCode: string, isSuccess: boolean, atkNewRank?: number, defNewRank?: number) { - let update: LadderMatchRecUpdate = { status: LADDER_STATUS.COMPLETE, endTime: nowSeconds(), timeout: false }; + public static async battleEnd(battleCode: string, isSuccess: boolean, endTime: number, atkNewRank?: number, defNewRank?: number) { + let update: LadderMatchRecUpdate = { status: LADDER_STATUS.COMPLETE, endTime, timeout: false }; if(isSuccess) { update['attackInfo.isSuccess'] = true; update['defenseInfo.isSuccess'] = false; @@ -106,8 +105,8 @@ export default class LadderMatchRec extends BaseModel { public static async clearLock() { let recs = await LadderMatchRecModel.find({ $or: [ - { status: LADDER_STATUS.CHECK, checkTime: { $lt: nowSeconds() - LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN } }, - { status: LADDER_STATUS.BATTLE, checkTime: { $lt: nowSeconds() - LADDER.LADDER_BATTLE_COUNTDOWN } } + { status: LADDER_STATUS.CHECK, checkTime: { $lt: Date.now() - LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN * 1000 } }, + { status: LADDER_STATUS.BATTLE, checkTime: { $lt: Date.now() - LADDER.LADDER_BATTLE_COUNTDOWN * 1000 } } ] }); await LadderMatchRecModel.updateMany({ diff --git a/shared/domain/battleField/ladder.ts b/shared/domain/battleField/ladder.ts index f0bd12fbc..b9471ab8c 100644 --- a/shared/domain/battleField/ladder.ts +++ b/shared/domain/battleField/ladder.ts @@ -250,9 +250,9 @@ export class LadderDataReturn { this.battleCode = ladderRec.battleCode; this.status = ladderRec.status; if(this.status == LADDER_STATUS.BATTLE) { - this.time = ladderRec.battleTime + LADDER.LADDER_BATTLE_COUNTDOWN; + this.time = Math.floor(ladderRec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN; } else if (this.status == LADDER_STATUS.CHECK) { - this.time = ladderRec.checkTime + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN; + this.time = Math.floor(ladderRec.checkTime/1000) + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN; } } } @@ -380,9 +380,9 @@ export class LadderOppDetailReturn { this.roleId = ladderRec.roleId2; this.status = ladderRec.status; if(this.status == LADDER_STATUS.BATTLE) { - this.time = ladderRec.battleTime + LADDER.LADDER_BATTLE_COUNTDOWN; + this.time = Math.floor(ladderRec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN; } else if (this.status == LADDER_STATUS.CHECK) { - this.time = ladderRec.checkTime + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN; + this.time = Math.floor(ladderRec.checkTime/1000) + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN; } }