diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index 864c81340..af960c407 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -20,6 +20,7 @@ import { existsRank, initRank, getRank, setRank, getMyRank } from '../../../serv import { handleCost } from '../../../services/rewardService'; import { nowSeconds } from '../../../pubUtils/timeUtil'; import { setPvpSeasonResult, resetPvpWarId, resetPvpSeasonTime } from '../../../services/timeTaskService'; +import { PvpSeasonResultModel } from '../../../db/PvpSeasonResult'; export default function(app: Application) { return new PvpHandler(app); } @@ -93,12 +94,30 @@ export class PvpHandler { if (isFirstEntry) { await PvpDefenseModel.updateInfo(roleId, {isFirstEntry:false}); } - let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);//去redis中获取排名 + let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId); + if (!!pvpSeasonResult) { + var { oldSeasonData, show } = pvpSeasonResult; + if ( oldSeasonData.seasonEndTime > nowSeconds()) { + seasonEndTime = oldSeasonData.seasonEndTime; + heroScores = oldSeasonData.heroScores; + score = oldSeasonData.score; + winStreakNum = oldSeasonData.winStreakNum; + refOppCnt = oldSeasonData.refOppCnt; + challengeCnt = oldSeasonData.challengeCnt; + challengeRefTime = oldSeasonData.challengeRefTime; + } else if(show) { + await PvpSeasonResultModel.updatePvpSeasonResult(roleId, {show: false}) + } + } + + let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);//去redis中获取排名 + let data = {warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes: heroes.map(cur => { let {actorId, dataId, order} = cur; return { actorId, dataId, order } - }), score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, isDefaultHero} + }), score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, isDefaultHero, oldSeasonData, show } + return resResult(STATUS.SUCCESS, data); } diff --git a/game-server/app/services/pvpService.ts b/game-server/app/services/pvpService.ts index 632f8730a..24cac0efa 100644 --- a/game-server/app/services/pvpService.ts +++ b/game-server/app/services/pvpService.ts @@ -1,6 +1,4 @@ -/** - * 体力系统 - */ + import { PvpDefenseModel, Heroes, OppPlayers, Robot, PvpDefenseType, HeroScores, pvpUpdateInter } from '../db/PvpDefense'; import { RoleType, RoleModel } from '../db/Role'; import { PVP_HERO_POS, ROBOT_NAME, REDIS_KEY, PVP_CONST } from '../consts'; @@ -397,6 +395,7 @@ export async function findPvpDefAllByRoleId(roleId: string) { pvpDefense.refOppCnt = refOppCnt; pvpDefense.refOppTime = refOppTime; } + return {pvpDefense, warId, shouldRefOpp}; } @@ -564,4 +563,3 @@ export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayers, score: 0 } } - diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 7a55eda73..b7b88e437 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -1,6 +1,3 @@ -/** - * 体力系统 - */ import { scheduleJob, Job } from 'node-schedule'; import { SystemConfigModel } from '../db/SystemConfig'; @@ -17,7 +14,7 @@ import { RoleModel } from '../db/Role'; import { MailModel, MailType } from '../db/Mail'; import { pinus } from 'pinus'; import { indexOf } from 'underscore'; -import { JsxEmit } from 'typescript'; +import { PvpSeasonResultModel } from '../db/PvpSeasonResult' const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; const SETTLE_DIFF = 29 * 60; @@ -72,14 +69,14 @@ export async function setPvpDefResultOnTime(pvpDefense: PvpDefenseType, seasonNu if (!role) { return; } - let {score, pLv, heroScores, winStreakNum, challengeCnt, challengeRefTime, goods } = await checkResult(pvpDefense, seasonNum, seasonEndTime); - pvpDefense = await PvpDefenseModel.updateInfo(pvpDefense.roleId, {score:score, pLv, heroScores, winStreakNum, seasonNum, challengeCnt, challengeRefTime, seasonEndTime}); + let { score, pLv, heroScores, winStreakNum, challengeCnt, challengeRefTime, goods } = await checkResult(pvpDefense, seasonNum, seasonEndTime); + pvpDefense = await PvpDefenseModel.updateInfo(pvpDefense.roleId, {score, pLv, heroScores, winStreakNum, seasonNum, challengeCnt, challengeRefTime, seasonEndTime, oldSeasonEndTime: pvpDefense.oldSeasonEndTime}); let { roleName, lv, vLv, headHid, sHid, title } = role; let params = new RankParam(roleName, lv, vLv, headHid, sHid, title); setRank(REDIS_KEY.PVP_RANK, 0, pvpDefense.roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params); //下发邮件 const doc = new MailModel(); - const mail = Object.assign(doc.toJSON(), {roleId: pvpDefense.roleId, goods, sendName: '系统', mailId: 1, sendTime: nowSeconds()}); + const mail = Object.assign(doc.toJSON(), {roleId: pvpDefense.roleId, goods, sendName: '系统', mailId: 1, sendTime: pvpDefense.seasonEndTime}); addMails.push(mail); let key = 'login_roleId_' + pvpDefense.roleId; let sid = await getRedis(key); @@ -94,6 +91,8 @@ export async function checkResult(pvpDefense: PvpDefenseType, seasonNum: number, let pvpHeroRewards = getPvpHeroRewards(); let goods = []; let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, pvpDefense.roleId);// 排行榜排名 + let oldPLv = getLvByScore(pvpDefense.heroScores); + let { winStreakNum, challengeCnt, challengeRefTime } = pvpDefense; let pvpRankReward = getScore(pvpRankRewards, rankLv); if(pvpRankReward) { goods = goods.concat(pvpRankReward.reward); @@ -109,7 +108,11 @@ export async function checkResult(pvpDefense: PvpDefenseType, seasonNum: number, score += heroScore.score; } let pLv = getLvByScore(pvpDefense.heroScores); - return {score, pLv, heroScores: pvpDefense.heroScores, winStreakNum:0, seasonNum, challengeCnt:PVP.PVP_CHALLENGE_COUNTS, challengeRefTime:0, seasonEndTime, goods}; + await PvpSeasonResultModel.updatePvpSeasonResult(pvpDefense.roleId, { + oldSeasonData:{refOppCnt: pvpDefense.refOppCnt, rankLv, score: pvpDefense.score, pLv: oldPLv, heroScores: deepCopy(pvpDefense.heroScores), winStreakNum, + seasonNum: pvpDefense.seasonNum, challengeCnt, challengeRefTime, seasonEndTime: pvpDefense.seasonEndTime + }, goods}); + return { rankLv, score, pLv, heroScores: pvpDefense.heroScores, winStreakNum:0, seasonNum, challengeCnt:PVP.PVP_CHALLENGE_COUNTS, challengeRefTime:0, seasonEndTime, goods}; } export async function setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime:number) { @@ -118,12 +121,12 @@ export async function setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: num return; } let {score, pLv, heroScores, winStreakNum, challengeCnt, challengeRefTime, goods } = await checkResult(pvpDefense, seasonNum, seasonEndTime); - pvpDefense = await PvpDefenseModel.updateInfo(pvpDefense.roleId, {score:score, pLv, heroScores, winStreakNum, seasonNum, challengeCnt, challengeRefTime, seasonEndTime}); + pvpDefense = await PvpDefenseModel.updateInfo(pvpDefense.roleId, {score, pLv, heroScores, winStreakNum, seasonNum, challengeCnt, challengeRefTime, seasonEndTime, oldSeasonEndTime: pvpDefense.oldSeasonEndTime}); let { roleName, lv, vLv, headHid, sHid, title , roleId } = role; let params = new RankParam(roleName, lv, vLv, headHid, sHid, title); setRank(REDIS_KEY.PVP_RANK, 0, pvpDefense.roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params); //下发邮件 - let sendTime = seasonEndTime - PVP.PVP_SEASON_DAYS * PER_DAY + SETTLE_DIFF; + let sendTime = seasonEndTime - PVP.PVP_SEASON_DAYS * PER_DAY; let mail = await MailModel.addMail({roleId, goods, sendName: '系统', mailId: 1, sendTime: sendTime}); let key = 'login_roleId_' + roleId; let sid = await getRedis(key); @@ -147,18 +150,15 @@ export async function resetPvpWarId() { } async function setNextPvpTime(notSetNext: boolean) { - let systemConfig = await SystemConfigModel.findSystemConfig(); - let seasonEndTime = (PVP.PVP_SEASON_DAYS + 1) * PER_DAY + getTodayZeroPoint(); - if (!notSetNext) { - return { seasonEndTime, seasonNum: systemConfig.seasonNum + 1 }; + let {seasonEndTime, seasonNum} = await SystemConfigModel.findSystemConfig(); + if (!!notSetNext) { + return { seasonEndTime, seasonNum }; } - seasonEndTimeJobId = scheduleJob(systemConfig.seasonEndTime * PER_SECOND, async function () { - seasonEndTime = PVP.PVP_SEASON_DAYS * PER_DAY + getTodayZeroPoint(); - systemConfig = await SystemConfigModel.updateSeason(seasonEndTime); - let settleTime = (seasonEndTime - SETTLE_DIFF)* PER_SECOND; - seasonJobId = scheduleJob(settleTime, setPvpSeasonResult, { name: 'setPvpSeasonResult' }); - }); - return { seasonEndTime, seasonNum: systemConfig.seasonNum + 1 }; + seasonEndTime = (PVP.PVP_SEASON_DAYS) * PER_DAY + seasonEndTime; + await SystemConfigModel.updateSeason(seasonEndTime); + let settleTime = (seasonEndTime - SETTLE_DIFF)* PER_SECOND; + seasonJobId = scheduleJob(settleTime, setPvpSeasonResult, { name: 'setPvpSeasonResult' }); + return { seasonEndTime, seasonNum: seasonNum + 1 }; } function getScore(arr, score) { diff --git a/shared/db/PvpDefense.ts b/shared/db/PvpDefense.ts index c5da71537..33b68f925 100644 --- a/shared/db/PvpDefense.ts +++ b/shared/db/PvpDefense.ts @@ -24,6 +24,7 @@ export interface pvpUpdateInter { receivedBox?: Array; seasonEndTime?:number; isDefaultHero?:boolean; + oldSeasonEndTime?:number; } export class Heroes { @@ -149,6 +150,8 @@ export default class PvpDefense extends BaseModel { seasonEndTime: number; @prop({ required: true, default: true }) isFirstEntry: boolean; + @prop({ required: true, default: 0 }) + oldSeasonEndTime:number; public static async findByRoleId(roleId: string, lean = true) { const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).lean(lean); return result; diff --git a/shared/db/PvpSeasonResult.ts b/shared/db/PvpSeasonResult.ts new file mode 100644 index 000000000..6862519bb --- /dev/null +++ b/shared/db/PvpSeasonResult.ts @@ -0,0 +1,80 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; +class RewardInter { + @prop({ required: true }) + id: number; + @prop({ required: true }) + count: number; +} +export class HeroScores { + @prop({ required: true }) + hid: number; + @prop({ required: true }) + score: number; +} + +export interface pvpUpdate { + goods?:Array; + oldSeasonData?: SeasonData; + show?: boolean; +} + +class SeasonData { + @prop({ required: true }) + score: number; + + @prop({ required: true }) + pLv: number; + + @prop({ required: true, type:HeroScores, default:[] }) + heroScores: HeroScores[]; + + @prop({ required: true }) + winStreakNum: number; + + @prop({ required: true }) + seasonNum: number; + + @prop({ required: true }) + challengeCnt: number; + + @prop({ required: true }) + challengeRefTime: number; + + @prop({ required: true }) + seasonEndTime: number; + + @prop({ required: true }) + rankLv: number; + + @prop({ required: true }) + refOppCnt:number; +} + +@index({ roleId: 1 }) +export default class PvpSeasonResult extends BaseModel { + @prop({ required: true }) + roleId: string; + + @prop({ required: true, type: RewardInter, default: [], _id: false}) + goods: Array; + + @prop({ required: true, type: SeasonData, _id: false}) + oldSeasonData: SeasonData; + + @prop({ required: true, default: true, _id: false}) + show: boolean; + + public static async updatePvpSeasonResult(roleId: string, update: pvpUpdate , lean = true) { + let result: PvpSeasonResultType = await PvpSeasonResultModel.findOneAndUpdate({roleId}, {$set: update}, {upsert: true, new: true}).lean(lean); + return result; + } + public static async getPvpSeasonResult(roleId: string, lean = true) { + let result: PvpSeasonResultType = await PvpSeasonResultModel.findOne({roleId}).lean(lean); + return result; + } +} + +export const PvpSeasonResultModel = getModelForClass(PvpSeasonResult); + +export interface PvpSeasonResultType extends Pick, keyof PvpSeasonResult> { }; \ No newline at end of file