diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index d196d904e..d6d48871d 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -111,7 +111,6 @@ export class PvpHandler { let checkHeroes = await checkBattleHeroesByHid(roleId, heroes); if(!checkHeroes) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - const pvpDefense = await PvpDefenseModel.findByRoleId(roleId); if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); // 检查挑战次数 @@ -196,7 +195,7 @@ export class PvpHandler { $set: { status: isSuccess?1:2 } }, true); - // 增加挑战次数 + // 减少挑战次数 let { challengeCnt, challengeRefTime } = comsumeChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, pvpDefense.seasonEndTime); if ( hisScore < score) { hisScore = score; @@ -371,16 +370,13 @@ export class PvpHandler { } receivedBox.push(id); let { challengeCnt, challengeRefTime } = refresh(lastChallengeCnt, lastChallengeRefTime, seasonEndTime); - await PvpDefenseModel.updateInfo(roleId, {receivedBox, challengeCnt, challengeRefTime}); - let result = await addItems(roleId, roleName, sid, pvpBox.reward ); return resResult(STATUS.SUCCESS,{goods: result, receivedBox, challengeCnt, challengeRefTime}); } async getRec(msg: {}, session: BackendSession ) { let roleId = session.get('roleId'); - let roleName = session.get('roleName'); let pvpRecords = await PvpRecordModel.getRecByRoleId(roleId); return resResult(STATUS.SUCCESS, {list: pvpRecords}); } diff --git a/game-server/app/servers/connector/handler/entryHandler.ts b/game-server/app/servers/connector/handler/entryHandler.ts index 7c3f2922e..ca027ae38 100644 --- a/game-server/app/servers/connector/handler/entryHandler.ts +++ b/game-server/app/servers/connector/handler/entryHandler.ts @@ -12,6 +12,7 @@ import { getAp } from '../../../services/actionPointService'; import { ItemModel } from '../../../db/Item'; import { chackFunOpenWhenLogin } from '../../../services/funcSwitchService'; import { loginRefresh } from '../../../services/playerEventService'; +import { getRedis, setRedis } from '../../../services/redisService'; export default function (app: Application) { return new EntryHandler(app); } @@ -29,7 +30,6 @@ export class EntryHandler { async enter(msg: { token: string, serverId: number }, session: FrontendSession) { let self = this; let serverId = msg.serverId; - let sessionService = self.app.get('sessionService'); let user = await UserModel.findUserByToken(msg.token); if (!user) { @@ -41,8 +41,13 @@ export class EntryHandler { if (!role) { return resResult(STATUS.ROLE_NOT_FOUND); } - self.remoteLogin(role.roleId); - await sessionService.akick(role.roleId);// + let key = 'login_roleId_' + role.roleId; + let connect = await getRedis(key); + if (!!connect) { + self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect, role.roleId); + } + let serverName = this.app.getServerId(); + setRedis(key, serverName); await session.abind(role.roleId); session.set('uid', role.roleId); session.set('roleId', role.roleId); @@ -88,21 +93,10 @@ export class EntryHandler { role['apJson'] = apJson; role['ce'] = reduceCe(role.ce); role['topFiveCe'] = reduceCe(role.topFiveCe); + return resResult(STATUS.SUCCESS, { role }); } - remoteLogin(uid: string) { - let sessionService = this.app.get('sessionService'); - let sessions = sessionService.getByUid(uid); - if (!!sessions) { - sessions.forEach(session=>{ - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let uids = [{uid: roleId, sid}]; - this.app.get('channelService').pushMessageByUids('onRemoteLogin', resResult(STATUS.LOGIN_ERR ), uids); - }); - } - } /** * User log out handler * diff --git a/game-server/app/servers/connector/remote/connectorRemote.ts b/game-server/app/servers/connector/remote/connectorRemote.ts new file mode 100644 index 000000000..ef4ecc012 --- /dev/null +++ b/game-server/app/servers/connector/remote/connectorRemote.ts @@ -0,0 +1,29 @@ +import { Application, ChannelService, FrontendSession, RemoterClass } from 'pinus'; +import { STATUS } from '../../../consts/statusCode'; +import { resResult } from '../../../pubUtils/util'; +export default function (app: Application) { + return new ConnectorRemote(app); +} + +export class ConnectorRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + private channelService: ChannelService; + + public async remoteLogin(uid: string) { + let sessionService = this.app.get('sessionService'); + let sessions = sessionService.getByUid(uid); + if (!!sessions) { + sessions.forEach(session=>{ + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let uids = [{uid: roleId, sid}]; + this.channelService.pushMessageByUids('onRemoteLogin', resResult(STATUS.LOGIN_ERR ), uids); + }); + } + await sessionService.akick(uid); + } +} diff --git a/game-server/app/servers/role/remote/roleRemote.ts b/game-server/app/servers/role/remote/roleRemote.ts index f12e9d95d..2f595e64a 100644 --- a/game-server/app/servers/role/remote/roleRemote.ts +++ b/game-server/app/servers/role/remote/roleRemote.ts @@ -1,5 +1,6 @@ import { Application, ChannelService, FrontendSession, RemoterClass } from 'pinus'; - +import { STATUS } from '../../../consts/statusCode'; +import { resResult } from '../../../pubUtils/util'; export default function (app: Application) { return new RoleRemote(app); } diff --git a/game-server/app/servers/user.rpc.define.ts b/game-server/app/servers/user.rpc.define.ts index 214a7dc33..1247f630f 100644 --- a/game-server/app/servers/user.rpc.define.ts +++ b/game-server/app/servers/user.rpc.define.ts @@ -6,6 +6,7 @@ import { FrontendSession, RemoterClass } from 'pinus'; import { ChatRemote } from './chat/remote/chatRemote'; import { ComBattleRemote } from './battle/remote/comBattleRemote'; import { BattleRemote } from './battle/remote/battleRemote'; +import { ConnectorRemote } from './connector/remote/connectorRemote'; declare global { interface UserRpc { @@ -16,5 +17,8 @@ declare global { comBattleRemote: RemoterClass; battleRemote: RemoterClass; }; + connector: { + connectorRemote: RemoterClass; + } } } \ No newline at end of file diff --git a/game-server/app/services/playerEventService.ts b/game-server/app/services/playerEventService.ts index 7263eee23..af1e78e42 100644 --- a/game-server/app/services/playerEventService.ts +++ b/game-server/app/services/playerEventService.ts @@ -1,6 +1,4 @@ -/** - * 体力系统 - */ + import { fromCallback } from 'bluebird'; import { checkPvp, findPvpDefByRoleId } from '../services/pvpService' import { getFuncsSwitch } from '../pubUtils/data'; diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 8e071439b..564abfc76 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -224,4 +224,14 @@ export async function clearComBtlQueue() { } } +export function setRedis(key: string, data: string) { + const client: Redis.RedisClient = pinus.app.get('redis'); + client.setAsync(key, data); +} + +export async function getRedis(key: string) { + const client: Redis.RedisClient = pinus.app.get('redis'); + const str = await client.getAsync(key); + return str; +} /**************** 寻宝相关 end */ diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 8adba0574..f4674c9f8 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -10,8 +10,11 @@ import { nowSeconds, getTodayZeroPoint } from '../pubUtils/timeUtil'; import { getPvpGkWarIds, getPvpRankRewards, getPvpHeroRewards } from '../pubUtils/data'; import { getRandomArr } from '../pubUtils/util'; import { getLvByScore } from './pvpService'; -import { getMyRank } from './redisService'; +import { getMyRank, setRank } from './redisService'; import { REDIS_KEY } from '../consts'; +import { RankParam } from '../pubUtils/interface'; +import { RoleModel } from '../db/Role'; +import { MailModel, MailType } from '../db/Mail'; const _ = require('underscore'); const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -42,15 +45,36 @@ export async function init() { export async function setPvpSeasonResult(obj:{ name:string }) { console.log('exce setPvpSeasonResult'+ obj.name); let { seasonNum, seasonEndTime } = await setNextPvpTime(); - let pvpDefenses = await PvpDefenseModel.getPvpDef(LIMIT_NUM); - for (let pvpDefense of pvpDefenses) { - if (pvpDefense.seasonNum !== seasonNum) { - await setPvpDefResult(pvpDefense, seasonNum, seasonEndTime); + for (let page = 0; page < 3; page++) { + let pvpDefenses = await PvpDefenseModel.getPvpDef(500, page); + let addMails = new Array(); + for (let pvpDefense of pvpDefenses) { + if (pvpDefense.seasonNum !== seasonNum) { + await setPvpDefResultOnTime(pvpDefense, seasonNum, seasonEndTime, addMails); + } } + await MailModel.addMails(addMails); } } -export async function setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime:number) { +export async function setPvpDefResultOnTime(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime:number, addMails: Array) { + let role = await RoleModel.findByRoleId(pvpDefense.roleId); + 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 { 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(), { goods, sendName: '系统', mailId: 1, sendTime: nowSeconds()}); + addMails.push(mail); + return pvpDefense; +} + +export async function checkResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime:number) { let pvpRankRewards = getPvpRankRewards(); let pvpHeroRewards = getPvpHeroRewards(); let goods = []; @@ -70,8 +94,22 @@ export async function setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: num score += heroScore.score; } let pLv = getLvByScore(pvpDefense.heroScores); - pvpDefense = await PvpDefenseModel.updateInfo(pvpDefense.roleId, {score:score, pLv, heroScores: pvpDefense.heroScores, winStreakNum:0, seasonNum, challengeCnt:PVP.PVP_CHALLENGE_COUNTS, challengeRefTime:0, seasonEndTime}); - //TODO 下发邮件 + return {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) { + let role = await RoleModel.findByRoleId(pvpDefense.roleId); + 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 { 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); + //下发邮件 + let sendTime = seasonEndTime - PVP.PVP_SEASON_DAYS * PER_DAY + SETTLE_DIFF; + await MailModel.addMail({ goods, sendName: '系统', mailId: 1, sendTime: sendTime}); return pvpDefense; } diff --git a/game-server/config/redis.ts b/game-server/config/redis.ts index 00b2f42ef..e2e936c19 100644 --- a/game-server/config/redis.ts +++ b/game-server/config/redis.ts @@ -10,7 +10,12 @@ declare module 'redis' { delAsync(key: string): Promise; // 设置过期时间 expireAsync(key: string, time: number): Promise; - + // string类型存储 + setexAsync(key: string, time: number, value: string): Promise; + // 获取存储string类型value + getAsync(key: string): Promise; + // 获取存储string类型value + setAsync(key: string, value: string): Promise; // 删除哈希表 key 中的一个或多个指定字段 hdelAsync(key: string, field: string): Promise; // 将哈希表 key 中的字段 field 的值设为 value diff --git a/shared/db/Item.ts b/shared/db/Item.ts index 45aa80159..a5dbf1da9 100644 --- a/shared/db/Item.ts +++ b/shared/db/Item.ts @@ -1,7 +1,7 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; const _ = require('underscore'); -// const Transaction = require('mongoose-transactions'); +// const Transaction = require("mongoose-transactions"); @index({ roleId: 1, id: 1 }) @index({ seqId: 1 }) @modelOptions({ schemaOptions: { id: false } }) @@ -86,14 +86,8 @@ export default class Item extends BaseModel { // let hasError: boolean = false, result = new Array(); // try { // for (let { id, count, ratio } of items) { - // if (ratio) ratio = -1; - // await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}); - // const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean); - // if (!!rec) { - // result.push({ id: rec.id, count: rec.count }); - // } else { - // hasError = true; break; - // } + // if (!ratio) ratio = -1; + // await transaction.update("Item", { roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}); // } // await transaction.run(); // return {hasError, result}; diff --git a/shared/db/Mail.ts b/shared/db/Mail.ts new file mode 100644 index 000000000..419d5f363 --- /dev/null +++ b/shared/db/Mail.ts @@ -0,0 +1,41 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; +import { RewardInter } from '../pubUtils/interface'; +import { nowSeconds } from '../pubUtils/timeUtil'; + +@index({ roleId: 1 }) + +export default class Mail extends BaseModel { + @prop({ required: true }) + roleId: number; + + @prop({ required: true }) + seqId: number; + + @prop({ required: true }) + mailId: number; + + @prop({ required: true }) + goods: Array; + + @prop({ required: true, default: nowSeconds() }) + sendTime: number; + + @prop({ required: true }) + sendName: string; + + public static async addMails( mails: Array) { + await MailModel.insertMany(mails); + } + + public static async addMail(params:{ goods: Array, sendName: string, mailId: number, sendTime?: number}) { + const doc = new MailModel(); + const mail = Object.assign(doc.toJSON(), params); + const mailInfo: MailType = await MailModel.create(mail); + return mailInfo; + } +} + +export const MailModel = getModelForClass(Mail); + +export interface MailType extends Pick, keyof Mail> { }; \ No newline at end of file diff --git a/shared/db/PvpDefense.ts b/shared/db/PvpDefense.ts index 05aba19b3..6cd54b6ac 100644 --- a/shared/db/PvpDefense.ts +++ b/shared/db/PvpDefense.ts @@ -233,14 +233,14 @@ export default class PvpDefense extends BaseModel { return result; } - public static async getPvpDef(limitNum: number, lean = true) { - let result: Array = await PvpDefenseModel.find().sort({ score: -1 }).limit(limitNum).lean(lean); + public static async getPvpDef(limit: number, page: number, lean = true) { + let result: Array = await PvpDefenseModel.find().sort({ score: -1 }).limit(limit).skip((page) * limit).lean(lean); return result; } public static async getRank(page = 1, limit = 1000, lean = true) { let sortBy = { score: -1, updatedAt: 1 }; - const ranks: PvpDefenseType[] = await PvpDefenseModel.find().limit(limit).skip(page - 1).select('roleId role score updatedAt') + const ranks: PvpDefenseType[] = await PvpDefenseModel.find().select('roleId role score updatedAt') .populate('role', 'roleId roleName headHid sHid title lv vLv') .sort(sortBy).limit(limit).skip((page - 1) * limit).lean(lean); return ranks;