diff --git a/game-server/app/servers/connector/handler/entryHandler.ts b/game-server/app/servers/connector/handler/entryHandler.ts index cb72907b4..15c2f8355 100644 --- a/game-server/app/servers/connector/handler/entryHandler.ts +++ b/game-server/app/servers/connector/handler/entryHandler.ts @@ -9,7 +9,7 @@ import { genCode, generateStr, resResult } from '../../../pubUtils/util'; import { COM_BTL_QUALITY, HERO_SELECT, DEBUG_MAGIC_WORD, REDIS_KEY, TASK_TYPE, ENTERY_ROLE_PICK, COUNTER, DEFAULT_LV, TA_USERSET_TYPE, LOG_TYPE, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE } from '../../../consts'; // import { loginRefresh } from '../../../services/playerEventService'; import { nowSeconds, getZeroPoint } from '../../../pubUtils/timeUtil'; -import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin } from '../../../services/redisService'; +import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin, getOnlineRoleByUserCode } from '../../../services/redisService'; import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGuildAuctionChannel, leaveGuildChannel, leaveSysChannel, leaveWorldAuctionChannel, leaveWorldChannel, recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from '../../../services/chatService'; import { reportOneOnline, savePlayTime } from '../../../services/authenticateService'; @@ -47,21 +47,22 @@ export class EntryHandler { console.log('user token not found'); return resResult(STATUS.TOKEN_ERR); } + let onlineRoleId = await getOnlineRoleByUserCode(user.userCode); + + if (!!onlineRoleId) { // 多地登陆踢下线 + let connect = await getRoleOnlineInfo(onlineRoleId); + if (connect.sid = self.app.getServerId()) { + await kickUser(self.app, onlineRoleId); + } else { + await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect.sid, onlineRoleId); + } + } let role = await RoleModel.findByUidAndSetTime(user.uid, serverId, null, true); if (!role) { return resResult(STATUS.ROLE_NOT_FOUND); } - let connect = await getRoleOnlineInfo(role.roleId); - - if (connect.isOnline) { // 多地登陆踢下线 - if (connect.sid = self.app.getServerId()) { - await kickUser(self.app, role.roleId); - } else { - await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect.sid, role.roleId); - } - } let serverName = this.app.getServerId(); await roleLogin(role.roleId, user.userCode, serverName, user.pkgName, role.createTime, role.serverId); // 保存在线用户 await this.addSession(user, role, session); diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index ae9120ac3..b4c4dfa0f 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -312,6 +312,7 @@ export async function clearChannelServers() { */ export async function roleLogin(roleId: string, userCode: string, sid: string, pkgName: string, createTime: number, serverId: number) { await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, 1); + await redisClient().hsetAsync(REDIS_KEY.USER_CODE, userCode, roleId); return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${userCode}|${sid}|${pkgName}|${createTime}|${serverId}`); } @@ -323,7 +324,9 @@ export async function roleLeave(roleId: string) { let role = await getRoleOnlineInfo(roleId); let count = await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, -1); if(count <= 0) { + await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId); await redisClient().hdelAsync(REDIS_KEY.ONLINE_USERS, roleId); + await redisClient().hdelAsync(REDIS_KEY.USER_CODE, role.userCode); } return role; } @@ -337,6 +340,11 @@ export async function isRoleOnline(roleId: string) { return !!result; } +export async function getOnlineRoleByUserCode(userCode: string) { + let roleId = await redisClient().hgetAsync(REDIS_KEY.USER_CODE, userCode); + return roleId; +} + /** * 获得在线玩家userCode和sid * @param roleId @@ -550,7 +558,8 @@ export async function redisSubScribe() { let treatRoleChannel = getRedisSubChannel(REDIS_KEY.TREAT_ROLE_CHANNEL, env); let treatGuildChannel = getRedisSubChannel(REDIS_KEY.TREAT_GUILD_CHANNEL, env); let surveyChannel = getRedisSubChannel(REDIS_KEY.SURVEY_CHANNEL, env); - await redisClientPub().subscribeAsync(payChannel, treatRoleChannel, treatGuildChannel, refundChannel, surveyChannel); + let userChannel = getRedisSubChannel(REDIS_KEY.USER_CHANNEL, env); + await redisClientPub().subscribeAsync(payChannel, treatRoleChannel, treatGuildChannel, refundChannel, surveyChannel, userChannel); redisClientPub().on('message', (channel, message) => { console.log('**********redisSubScribe*******') console.log('channel: ', channel, payChannel); @@ -575,6 +584,9 @@ export async function redisSubScribe() { let servers = pinus.app.getServersByType('role'); let server = getRandSingleEelm(servers); pinus.app.rpc.role.roleRemote.sendSurveyMail.toServer(server.id, message); + } else if(channel == userChannel) { + let [sid, roleId] = (message||'').split('|'); + if(!!sid && !!roleId) pinus.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId); } }); } diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 353e32b73..b6406de51 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -242,6 +242,8 @@ export enum REDIS_KEY { GUILD_FUND = 'guildFund', // 限时排行 SUM_CE_SNAPSHOT = "sumCeTL", // 限时战力排行榜 SURVEY_CHANNEL = 'survey', // 文件频道 + USER_CHANNEL = 'userChannel', // 玩家登录频道 + USER_CODE = 'userCode', // 玩家userCode对应roleId } // 各排行榜对应hash的key diff --git a/web-server/app/service/Auth.ts b/web-server/app/service/Auth.ts index 4347f48dc..84ce1b78d 100644 --- a/web-server/app/service/Auth.ts +++ b/web-server/app/service/Auth.ts @@ -48,6 +48,9 @@ export default class Auth extends Service { if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } + if(user && user.userCode) { + ctx.service.utils.checkOnlineUser(user.userCode); + } let param = this.getReturnParam(user); return this.ctx.service.utils.resResult(STATUS.SUCCESS, { @@ -68,6 +71,9 @@ export default class Auth extends Service { if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(user.tel, getuiCID); } + if(user && user.userCode) { + ctx.service.utils.checkOnlineUser(user.userCode); + } let param = this.getReturnParam(user); let canLogin = true; @@ -219,6 +225,9 @@ export default class Auth extends Service { if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } + if(user && user.userCode) { + ctx.service.utils.checkOnlineUser(user.userCode); + } let param = this.getReturnParam(user); return ctx.service.utils.resResult(STATUS.SUCCESS, param); } @@ -281,6 +290,9 @@ export default class Auth extends Service { if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } + if(user && user.userCode) { + ctx.service.utils.checkOnlineUser(user.userCode); + } let param = this.getReturnParam(user); return ctx.service.utils.resResult(STATUS.SUCCESS, { ...param }); } @@ -410,11 +422,11 @@ export default class Auth extends Service { let channelId = getChannelId(channelType, requestResult.data.uid); const token = ctx.service.utils.generateStr(256); - let { isCreate, user} = await UserModel.createOrUpdateChannelUser(channelId, channelType, { + let { user} = await UserModel.createOrUpdateChannelUser(channelId, channelType, { ...requestResult.data, childGameId:`${childGameId}`, platformAppid }, token, platform, pkgName, serverType, deviceId, ctx.clientIp); - if(isCreate) { - // ctx.service.sdk.reportTAEventWithDistinctId(distinctId, TA_EVENT.REGISTER, null, ctx.clientIp); + if(user && user.userCode) { + ctx.service.utils.checkOnlineUser(user.userCode); } if (getuiCID) {//更新个推cid diff --git a/web-server/app/service/Utils.ts b/web-server/app/service/Utils.ts index d1e2d8acb..79dea65bc 100644 --- a/web-server/app/service/Utils.ts +++ b/web-server/app/service/Utils.ts @@ -3,6 +3,7 @@ import { resResult as pubResult } from '../pubUtils/util'; import { gameData } from 'app/pubUtils/data'; import { RedisClient } from 'redis'; import { REDIS_KEY } from '@consts'; +import { getRedisSubChannel } from 'app/pubUtils/sdkUtil'; const csprng = require('csprng'); /** * Utils Service @@ -57,6 +58,25 @@ export default class Utils extends Service { } } + public async checkOnlineUser(userCode: string) { + let redisClient: RedisClient = this.ctx.app.context.redisClient; + let onlineRoleId = await redisClient.hgetAsync(REDIS_KEY.USER_CODE, userCode); + + if (!!onlineRoleId) { // 多地登陆踢下线 + let str = await redisClient.hgetAsync(REDIS_KEY.ONLINE_USERS, onlineRoleId); + + if(str) { + try { + let [,sid] = str?.split('|')??[]; + let name = getRedisSubChannel(REDIS_KEY.USER_CHANNEL, this.ctx.app.config.env); + let result = await redisClient.publishAsync(name, `${sid}|${onlineRoleId}`); + } catch(e) { + console.error('checkOnlineUser', e); + } + } + } + } + // 检测是否可以登录 public async validateCanLogin() { if(gameData.serverConst.CLOSE_LOGIN == 1) return false;