diff --git a/game-server/app/servers/battle/handler/guildHandler.ts b/game-server/app/servers/battle/handler/guildHandler.ts index b80e6f745..97cb46cca 100644 --- a/game-server/app/servers/battle/handler/guildHandler.ts +++ b/game-server/app/servers/battle/handler/guildHandler.ts @@ -15,9 +15,8 @@ import { UserGuildApplyModel } from '../../../db/UserGuildApply'; import { hasStructureConsume, getStructureConsume, gameData } from '../../../pubUtils/data'; import { GuildRecModel } from '../../../db/GuildRec'; import { sendMail } from '../../../services/mailService'; -import { existsRank, initSingleRankWithServer, getRank, setRank, redisUserInfoUpdate, redisUserInfoAdd, removeFromRank, getMyRank, isRoleOnline, getRedis, redisSidKey } from '../../../services/redisService'; -import { lockData } from '../../../services/redLockService'; -import { DATA_NAME } from '../../../consts/dataName'; +import { existsRank, initSingleRankWithServer, getRank, setRank, redisUserInfoUpdate, removeFromRank, getMyRank, isRoleOnline, getRoleOnlineInfo } from '../../../services/redisService'; + import { openGuildRefine } from '../../../services/guildRefineService'; import { unlockTrain } from '../../../services/guildTrainService'; import { removeBossRank } from '../../../services/guildBossService'; @@ -450,8 +449,10 @@ export class GuildHandler { if(!role.hasGuild) { await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.INVITE); result.push(role.roleId); - let hisSid = await getRedis(redisSidKey(role.roleId)); - uids.push({ uid: role.roleId, sid: hisSid }) + let hisInfo = await getRoleOnlineInfo(role.roleId); + if(hisInfo.isOnline) { + uids.push({ uid: role.roleId, sid: hisInfo.sid }) + } } } await GuildModel.recordInvitedMember(code, serverId, roleIds, shouldRefresh(guild.inviteTime, new Date(), 0)); diff --git a/game-server/app/servers/battle/handler/wishPoolHandler.ts b/game-server/app/servers/battle/handler/wishPoolHandler.ts index f9c3d05bd..1f497187b 100644 --- a/game-server/app/servers/battle/handler/wishPoolHandler.ts +++ b/game-server/app/servers/battle/handler/wishPoolHandler.ts @@ -11,7 +11,7 @@ import { GUILD_STRUCTURE } from '../../../consts/constModules/guildConst'; import { getUserGuildWithRefActive } from '../../../services/guildService'; import { findIndex, findWhere } from 'underscore'; import { RoleModel } from '../../../db/Role'; -import { getRedis, redisSidKey } from '../../../services/redisService'; +import { getRoleOnlineInfo } from '../../../services/redisService'; import { ARMY } from '../../../pubUtils/dicParam'; export default function(app: Application) { return new WishPoolHandler(app); @@ -119,11 +119,11 @@ export class WishPoolHandler { return resResult(STATUS.HAS_RECEIVE_WISH_GOOD);//已经收到 let { wishDntCnt } = await UserGuildModel.donateGoods(dntRoleId, 1, 'wishDntCnt'); let { wishGoods: resWishGoods } = await UserGuildModel.donateUpdate(wishRoleId, dntRoleName, id, 'wishGoods'); - let key = redisSidKey(wishRoleId); - let sid = await getRedis(key); - await addItems(wishRoleId, role.roleName , sid , [{ id : wishGood.goodId, count: 1 }]); - if (!!sid) { - this.app.channelService.pushMessageByUids('onWishGoodsRecive', resResult(STATUS.SUCCESS, { wishGoods: resWishGoods }), [{uid:wishRoleId, sid}]); + + let hisOnlineInfo = await getRoleOnlineInfo(wishRoleId); + if(hisOnlineInfo.isOnline && hisOnlineInfo.sid) { + await addItems(wishRoleId, role.roleName, hisOnlineInfo.sid , [{ id : wishGood.goodId, count: 1 }]); + this.app.channelService.pushMessageByUids('onWishGoodsRecive', resResult(STATUS.SUCCESS, { wishGoods: resWishGoods }), [{uid:wishRoleId, sid: hisOnlineInfo.sid}]); } await WishPoolReportModel.addReport(code, wishRoleId, role.roleName , dntRoleId, dntRoleName, wishGood.goodId, 1); return resResult(STATUS.SUCCESS, { wishDntCnt, updateWishGoods: resWishGoods.map(({type, goodId, count, receiveCnt, drawCnt, id})=>{ diff --git a/game-server/app/servers/connector/handler/entryHandler.ts b/game-server/app/servers/connector/handler/entryHandler.ts index e1e7c0397..44798915f 100644 --- a/game-server/app/servers/connector/handler/entryHandler.ts +++ b/game-server/app/servers/connector/handler/entryHandler.ts @@ -13,7 +13,7 @@ import { ItemModel } from '../../../db/Item'; import { chackFunOpenWhenLogin } from '../../../services/funcSwitchService'; import { loginRefresh } from '../../../services/playerEventService'; import { nowSeconds } from '../../../pubUtils/timeUtil'; -import { getRedis, setRedis, delRedis, rmRoleFromQueue, redisSidKey } from '../../../services/redisService'; +import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin } from '../../../services/redisService'; import { UserGuildModel } from '../../../db/UserGuild'; import { GuildModel } from '../../../db/Guild'; import { gameData } from '../../../pubUtils/data'; @@ -47,13 +47,14 @@ export class EntryHandler { if (!role) { return resResult(STATUS.ROLE_NOT_FOUND); } - let key = redisSidKey(role.roleId); - let connect = await getRedis(key); - if (!!connect) { - await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect, role.roleId); + + let connect = await getRoleOnlineInfo(role.roleId); + + if (connect.isOnline) { // 多地登陆踢下线 + await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect.sid, role.roleId); } let serverName = this.app.getServerId(); - setRedis(key, serverName); + await roleLogin(role.roleId, user.userCode, serverName); // 保存在线用户 await session.abind(role.roleId); session.set('uid', role.roleId); session.set('roleId', role.roleId); @@ -139,8 +140,7 @@ export class EntryHandler { let roleId = session.get('roleId'); let sid = session.get('sid'); let serverId = session.get('serverId'); - let key = redisSidKey(roleId); - delRedis(key); + roleLeave(roleId); rmRoleFromQueue(roleId, sid, COM_BTL_QUALITY, null); // 删除redis中寻宝的匹配记录 let channelService = this.app.get('channelService'); let channel = channelService.getChannel(roleId, true); diff --git a/game-server/app/servers/connector/remote/connectorRemote.ts b/game-server/app/servers/connector/remote/connectorRemote.ts index d6e23f67c..3b90c3fc2 100644 --- a/game-server/app/servers/connector/remote/connectorRemote.ts +++ b/game-server/app/servers/connector/remote/connectorRemote.ts @@ -1,7 +1,6 @@ import { Application, ChannelService, FrontendSession, pinus, RemoterClass } from 'pinus'; import { STATUS } from '../../../consts/statusCode'; import { resResult } from '../../../pubUtils/util'; -import { getRedis, setRedis, delRedis } from '../../../services/redisService'; export default function (app: Application) { return new ConnectorRemote(app); } diff --git a/game-server/app/servers/role/handler/friendHandler.ts b/game-server/app/servers/role/handler/friendHandler.ts index e58b0a1e7..2a9af4043 100644 --- a/game-server/app/servers/role/handler/friendHandler.ts +++ b/game-server/app/servers/role/handler/friendHandler.ts @@ -7,7 +7,7 @@ import { FriendApplyModel } from "../../../db/FriendApply"; import { FriendApplyParams, FriendListParam, FriendRecommendParams, BlackListParam, FriendValueListParam } from "../../../domain/roleField/friend"; import { FriendShipModel, FriendShipType } from "../../../db/FriendShip"; import { FriendRelationModel, Relation } from "../../../db/FriendRelation"; -import { isRoleOnline, getServerName, getMyRank, getRedis, redisSidKey } from "../../../services/redisService"; +import { isRoleOnline, getServerName, getMyRank, getRoleOnlineInfo } from "../../../services/redisService"; import { increaseFrdCnt, getRecommendType, sortByBeSentHeart } from "../../../services/friendService"; import { FriendPointModel } from "../../../db/FriendPoint"; import { gameData } from "../../../pubUtils/data"; @@ -146,8 +146,10 @@ export class FriendHandler { await FriendApplyModel.createApply(hisRoleId, role); resultRoleIds.push(hisRoleId); - let hisSid = await getRedis(redisSidKey(hisRoleId)); - uids.push({ uid: hisRoleId, sid: hisSid }); + let hisOnlineInfo = await getRoleOnlineInfo(hisRoleId); + if(hisOnlineInfo.isOnline) { + uids.push({ uid: hisRoleId, sid: hisOnlineInfo.sid }); + } } this.channelService.pushMessageByUids('onFriendApply', resResult(STATUS.SUCCESS, { roleId }), uids); @@ -517,8 +519,10 @@ export class FriendHandler { todaySendCnt += FRIEND.FRIEND_FRIENDPOINT_ADD; todaySendInc += FRIEND.FRIEND_FRIENDPOINT_ADD; - let hisSid = await getRedis(redisSidKey(relation.roleId)); - uids.push({ uid: relation.roleId, sid: hisSid }) + let hisOnlineInfo = await getRoleOnlineInfo(relation.roleId); + if(hisOnlineInfo.isOnline) { + uids.push({ uid: relation.roleId, sid: hisOnlineInfo.sid }); + } } this.channelService.pushMessageByUids('onFriendSendHeart', resResult(STATUS.SUCCESS, {roleId}), uids); if(todaySendInc <= 0) return resResult(STATUS.FRIEND_HAS_SENT); diff --git a/game-server/app/servers/role/handler/heroHandler.ts b/game-server/app/servers/role/handler/heroHandler.ts index 96e18e88c..9f4b74c28 100644 --- a/game-server/app/servers/role/handler/heroHandler.ts +++ b/game-server/app/servers/role/handler/heroHandler.ts @@ -10,6 +10,7 @@ import { ItemModel } from '../../../db/Item'; import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, getHeroLvByExp, getMaxGradeByjobClass, getJobByGradeAndClass, getFriendShipById, getFavourLvByExp } from '../../../pubUtils/data'; import { RewardInter } from '../../../pubUtils/interface'; import { getDropItems } from '../../../consts/constModules/itemConst' +import { getRoleOnlineInfo, getAllOnlineRoles } from '../../../services/redisService'; export default function(app: Application) { return new HeroHandler(app); } @@ -22,17 +23,10 @@ export class HeroHandler { public async test(msg: { items:Array<{id: number, count: number, seqId:number, type:number}>}, session: BackendSession) { let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let {items} = msg; - - let result = await handleCost(roleId, sid, items ); - //let result = await addItems(roleId, roleName, sid, [{id, count}] ); - if(!result) { - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - } - return resResult(STATUS.SUCCESS,{result}); + let role = await getRoleOnlineInfo(roleId); + let list = await getAllOnlineRoles(); + return resResult(STATUS.SUCCESS, {role, list}); } diff --git a/game-server/app/services/guildBossService.ts b/game-server/app/services/guildBossService.ts index a38c83fb1..7df212034 100644 --- a/game-server/app/services/guildBossService.ts +++ b/game-server/app/services/guildBossService.ts @@ -1,9 +1,9 @@ import { BossInstanceType, BossInstanceModel } from '../db/BossInstance'; -import { getTodayZeroPoint, nowSeconds } from '../pubUtils/timeUtil'; +import { getTodayZeroPoint } from '../pubUtils/timeUtil'; import { lockData } from '../services/redLockService'; -import { findIndex, indexBy, values } from 'underscore'; +import { findIndex } from 'underscore'; import { MailModel, MailType } from '../db/Mail'; -import { getRedis, sismemberAsync, smembersAsync, saddAsync, delAsync, sremAsync, redisSidKey } from '../services/redisService'; +import { sismemberAsync, smembersAsync, saddAsync, delAsync, getRoleOnlineInfo } from '../services/redisService'; import { pinus } from 'pinus'; import { STATUS } from '../consts/statusCode'; import { deepCopy, resResult } from '../pubUtils/util'; @@ -159,12 +159,14 @@ export function getArmyBossRankReward(rankLv: number) { * @param roleId */ export async function addBossInstance(code: string, serverId:number, roleId: string) { - let loginKey = redisSidKey(roleId); - let sid = await getRedis(loginKey); - let key = 'serverId_' + serverId + 'guildCode_' + code; - let value = roleId+ '|' + sid; - saddAsync(key, [value]); + let hisOnlineInfo = await getRoleOnlineInfo(roleId); + if(hisOnlineInfo.isOnline) { + let key = 'serverId_' + serverId + 'guildCode_' + code; + let value = roleId+ '|' + hisOnlineInfo.sid; + await saddAsync(key, [value]); + } } + /** * 给当前正在挑战的玩家下发血量同步信息 * @param code @@ -194,10 +196,9 @@ export async function pushBossHpMessage(code: string, serverId:number, bossHp:nu * @param battleCode */ export async function checkBossBattleMemberExists(code: string, serverId:number, roleId: string, battleCode:string ) { - let loginKey = redisSidKey(roleId); - let sid = await getRedis(loginKey); + let hisOnlineInfo = await getRoleOnlineInfo(roleId); let key = 'serverId_' + serverId + 'guildCode_' + code ; - let value = roleId+ '|' + sid; + let value = roleId+ '|' + hisOnlineInfo.sid; let flag = await sismemberAsync(key, value); if (!flag) { const battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); diff --git a/game-server/app/services/mailService.ts b/game-server/app/services/mailService.ts index d29d6d874..d8ccabb19 100644 --- a/game-server/app/services/mailService.ts +++ b/game-server/app/services/mailService.ts @@ -1,6 +1,6 @@ import { RewardInter, pushMail, mailData } from "../pubUtils/interface"; import { MailModel, MailType } from "../db/Mail"; -import { getRedis, redisSidKey } from "./redisService"; +import { getRoleOnlineInfo } from "./redisService"; import { pinus } from "pinus"; import { gameData } from "../pubUtils/data"; import { nowSeconds } from '../pubUtils/timeUtil'; @@ -26,12 +26,14 @@ export async function sendMail(operate: number, toRoleId: string, sendName: stri if (!content) return; let mail = await MailModel.addMail({roleId: toRoleId, sendTime, goods, sendName, mailId: JSON.stringify(operate), endTime: time + nowSeconds(), mailTemType: MAIL_TEM_TYPE.GAMEMAIL, params}); - let key = redisSidKey(toRoleId); - let sid = await getRedis(key); - if (!!sid) {//下发邮件,对应前端红点提示 - pinus.app.channelService.pushMessageByUids('onMailsAdd', resResult(STATUS.SUCCESS, { mails:[{ - id: mail._id, goods, sendTime: mail.sendTime, endTime: mail.endTime, content, status: mail.status, mailType: MAIL_TYPE.SINGLEMAIL, sendName - }]}), [{uid: toRoleId, sid}]); + let hisOnlineInfo = await getRoleOnlineInfo(toRoleId); + if(hisOnlineInfo.isOnline) { + let sid = hisOnlineInfo.sid; + if (!!sid) {//下发邮件,对应前端红点提示 + pinus.app.channelService.pushMessageByUids('onMailsAdd', resResult(STATUS.SUCCESS, { mails:[{ + id: mail._id, goods, sendTime: mail.sendTime, endTime: mail.endTime, content, status: mail.status, mailType: MAIL_TYPE.SINGLEMAIL, sendName + }]}), [{uid: toRoleId, sid}]); + } } } /** @@ -68,12 +70,15 @@ export async function getMailContent(roleId: string, operate: number, params: st return; const mail = Object.assign(doc.toJSON(), { roleId, goods, sendName, mailId: operate, sendTime: sendTime||nowSeconds(), mailTemType: MAIL_TEM_TYPE.GAMEMAIL, endTime: time + nowSeconds(), params }); mails.push(mail); - let key = redisSidKey(roleId); - let sid = await getRedis(key); - if (!!sid) { - pushMessage.push({route: 'onMailsAdd', data:[{ - id: mail._id, goods, sendTime: mail.sendTime, endTime: mail.endTime, content, status: mail.status, mailType: MAIL_TYPE.SINGLEMAIL, sendName - }], uids: [{ uid: roleId, sid }]}); + + let hisOnlineInfo = await getRoleOnlineInfo(roleId); + if(hisOnlineInfo.isOnline) { + let sid = hisOnlineInfo.sid; + if (!!sid) { + pushMessage.push({route: 'onMailsAdd', data:[{ + id: mail._id, goods, sendTime: mail.sendTime, endTime: mail.endTime, content, status: mail.status, mailType: MAIL_TYPE.SINGLEMAIL, sendName + }], uids: [{ uid: roleId, sid }]}); + } } } /** @@ -167,10 +172,9 @@ export async function sendRolesMails(mails) { return; } for (let { roleId } of sendRoles) { - let key = redisSidKey(roleId); - let sid = await getRedis(key); - if (!!sid) { - uids.push({sid, uid: roleId}) + let hisOnlineInfo = await getRoleOnlineInfo(roleId); + if(hisOnlineInfo.isOnline && hisOnlineInfo.sid) { + uids.push({sid: hisOnlineInfo.sid, uid: roleId}); } } pushMessage.push({route: 'onMailsAdd', data:[{ diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 936823cea..bfb0929ad 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -16,6 +16,7 @@ import { comBtlRanges } from '../pubUtils/gamedata'; export async function initAllRank() { const client: Redis.RedisClient = pinus.app.get('redis'); const serverList = await GameModel.getAllServerList(); + await client.delAsync(REDIS_KEY.ONLINE_USERS); await client.delAsync(REDIS_KEY.USER_INFO); await client.delAsync(REDIS_KEY.GUILD_INFO); @@ -362,12 +363,69 @@ export function redisSidKey(roleId: string) { return `login_roleId_${roleId}`; } +/** + * 玩家上线 + * @param roleId role表id + * @param userCode user表唯一字符串标识 + * @param sid connector服的那个sid + */ +export async function roleLogin(roleId: string, userCode: string, sid: string) { + const client: Redis.RedisClient = pinus.app.get('redis'); + let param = { userCode, sid }; + return await client.hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, JSON.stringify(param)); +} + +/** + * 玩家下线 + * @param roleId role表id + */ +export async function roleLeave(roleId: string) { + const client: Redis.RedisClient = pinus.app.get('redis'); + return await client.hdelAsync(REDIS_KEY.ONLINE_USERS, roleId); +} + +/** + * 判断玩家是否在线 + * @param roleId role表id + */ export async function isRoleOnline(roleId: string) { - let key = redisSidKey(roleId); - let result = await getRedis(key); + const client: Redis.RedisClient = pinus.app.get('redis'); + let result = await client.hexistsAsync(REDIS_KEY.ONLINE_USERS, roleId); return !!result; } +/** + * 获得在线玩家userCode和sid + * @param roleId + */ +export async function getRoleOnlineInfo(roleId: string) { + const client: Redis.RedisClient = pinus.app.get('redis'); + let str = await client.hgetAsync(REDIS_KEY.ONLINE_USERS, roleId); + if(str) { + try { + let result = JSON.parse(str); + return { + isOnline: true, + userCode: result.userCode, + sid: result.sid + } + } catch(e) { + return { isOnline: false } + } + } else { + return { isOnline: false } + } +} + +/** + * 获得所有在线的玩家 + */ +export async function getAllOnlineRoles() { + const client: Redis.RedisClient = pinus.app.get('redis'); + let allRoles = await client.hgetallAsync(REDIS_KEY.ONLINE_USERS); + return allRoles; +} + export async function resetPvpRanks() { const client: Redis.RedisClient = pinus.app.get('redis'); await client.delAsync(REDIS_KEY.PVP_RANK); diff --git a/game-server/config/redis.ts b/game-server/config/redis.ts index 54f995a34..8fa9fb20f 100644 --- a/game-server/config/redis.ts +++ b/game-server/config/redis.ts @@ -24,6 +24,8 @@ declare module 'redis' { hgetAsync(key: string, field: string): Promise; // 获取存储在哈希表中指定字段的值。 hexistsAsync(key: string, field: string): Promise; + // 获取哈希表中所有字段和值 + hgetallAsync(key: string): Promise; // 移除并返回集合中的一个随机元素 spopAsync(key: string, count?: number): Promise; diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index e023ec868..b2548ba6f 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -223,7 +223,8 @@ export const REDIS_KEY = { PVP_RANK: "pvpRank", // pvp排行榜 GUILD_INFO: "guildInfo", // 公会信息 GUILD_ACTIVE_RANK: "guildActiveRank", // 公会周活跃排行榜 - DB_GAME: 'db_game' + DB_GAME: 'db_game', // 服务器列表 + ONLINE_USERS: 'onlineUsers', // 在线用户情况 } // 各排行榜对应hash的key diff --git a/shared/db/User.ts b/shared/db/User.ts index b047dfad7..aa8a17c5f 100644 --- a/shared/db/User.ts +++ b/shared/db/User.ts @@ -83,7 +83,7 @@ export default class User extends BaseModel { } public static async findUserByToken(token: string, lean = true) { - const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth').lean(lean); + const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth userCode').lean(lean); return user; }