297 lines
9.0 KiB
TypeScript
297 lines
9.0 KiB
TypeScript
import {ApiCall, BaseConnection} from "tsrpc";
|
||
import {FriendManage} from '../../public/friend/manage';
|
||
import {GHManage} from '../../public/gonghui/manage';
|
||
import {HeroFun} from "../../public/hero";
|
||
import {PlayerFun} from '../../public/player';
|
||
import {TaskFun} from "../../public/task";
|
||
import {defaultUserAppend, UserFun} from '../../public/user';
|
||
import {ReqLogin, ResLogin} from "../../shared/protocols/user/PtlLogin";
|
||
import {setUidProcessId} from "../../clusterUtils";
|
||
import * as crypto from 'crypto';
|
||
import {EmailFun} from "../../public/email";
|
||
import {PublicShared} from "../../shared/public/public";
|
||
import {getGud, initGud} from "../../public/gud";
|
||
|
||
//登陆排队中的conn.id
|
||
let queueLogin = [
|
||
//{call:call,binduid,binduid,conn:conn}
|
||
]
|
||
//排队间隔 ms
|
||
let delay = 1000;
|
||
|
||
setInterval(function () {
|
||
doLoginQueue();
|
||
}, delay);
|
||
|
||
//获取排队顺序
|
||
function getQueueIndex(bindUid) {
|
||
for (let i = 0; i < queueLogin.length; i++) {
|
||
if (queueLogin[i].bindUid == bindUid) {
|
||
return i;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
//conn断开了链接,取消排队
|
||
export function unQueueByConn(conn: BaseConnection) {
|
||
//从queueLogin删除指定conn
|
||
for (let i = 0; i < queueLogin.length; i++) {
|
||
if (queueLogin[i].conn == conn) {
|
||
queueLogin.splice(i, 1);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//默认入口
|
||
export default async function (call: ApiCall<ReqLogin, ResLogin>) {
|
||
let bindUid = call.req.bindUid;
|
||
let index = getQueueIndex(bindUid);
|
||
if (index == null) {
|
||
//增加到排队队列
|
||
queueLogin.push({call: call, bindUid: bindUid, conn: call.conn});
|
||
} else {
|
||
queueLogin[index].call = call;
|
||
queueLogin[index].conn = call.conn;
|
||
}
|
||
//需要排队的时间
|
||
let needTime = delay * queueLogin.length;
|
||
|
||
//需要等待的时间
|
||
G.server.sendMsgByUid(call.uid, 'msg_s2c/LoginQueue', {
|
||
delay: needTime
|
||
})
|
||
}
|
||
|
||
//每N时间消费1个排队
|
||
async function doLoginQueue() {
|
||
let data = queueLogin.shift();
|
||
if (!data) return;
|
||
let kickDelay = await kickUser(data.call.req.bindUid, data.call.req.sid);
|
||
console.log("排队登陆中,剩余数量", queueLogin.length, "kickDelay", kickDelay);
|
||
setTimeout(async function () {
|
||
return await doLogin(data.call);
|
||
}, kickDelay);
|
||
}
|
||
|
||
|
||
function md5String(password: string): string {
|
||
const md5 = crypto.createHash('md5');
|
||
md5.update(password);
|
||
return md5.digest('hex');
|
||
}
|
||
|
||
async function kickUser(bindUid: string, sid: string) {
|
||
let delayTime = 0;
|
||
let user = await G.mongodb.collection('user').findOne({bindUid: bindUid, sid: sid}, {
|
||
projection: {
|
||
uid: 1
|
||
}
|
||
});
|
||
if (user == null) {
|
||
return delayTime;
|
||
}
|
||
let uid = user.uid;
|
||
const loginConn = G.server.uid_connections[uid];
|
||
let checkPid = await G.redis.hGet("uid2processId", uid);
|
||
|
||
if (checkPid) {
|
||
if (~~checkPid == process.pid && loginConn) {
|
||
// 本进程踢线
|
||
loginConn.sendMsg('msg_s2c/OtherLogin', loginConn.ip).then(v => {
|
||
loginConn.close('otherLogin');
|
||
});
|
||
} else {
|
||
// 跨进程踢线,注意这里是异步的,留200ms等原进程清理数据
|
||
G.server.sendMsgByUid(uid, 'msg_s2c/OtherLogin', '1', String(process.pid));
|
||
delayTime = 200;
|
||
}
|
||
}
|
||
return delayTime;
|
||
}
|
||
|
||
async function doLogin(call: ApiCall<ReqLogin, ResLogin>) {
|
||
//合法性检测
|
||
let sign = call.req.sign;
|
||
//本地测试时,直接用通用鉴权秘钥
|
||
if (sign != "BPtqdLH9QTVbZk7v" && sign != md5String(call.req.bindUid + "ajklsdhjhquieb")) {
|
||
return call.error("shibai");
|
||
}
|
||
|
||
// 查询账号
|
||
let user = await G.mongodb.collection('user').findOne({bindUid: call.req.bindUid, sid: call.req.sid});
|
||
let {_id, ...gud} = user ? user : await UserFun.createUser(call.conn, call.req.bindUid, call.req.sid);
|
||
|
||
// 判断账号是否被封禁
|
||
if (gud.status == 1) {
|
||
return call.error(lng.user_10);
|
||
}
|
||
|
||
await initGud(gud.uid, gud);
|
||
|
||
// 修复公会id
|
||
await fixUnionData(gud);
|
||
|
||
//记录玩家所在的进程,change: 更换到处理完踢线操作在写入。
|
||
// setUidProcessId(gud.uid);
|
||
|
||
let obj = await UserFun.check(gud, call.req);
|
||
call.conn.onlineTime = G.time;
|
||
call.conn.uid = gud.uid;
|
||
call.conn.bindUid = gud.bindUid;
|
||
call.conn.gud = gud;
|
||
call.conn.lshd = {};
|
||
|
||
if (!!!user) {
|
||
await firstLoginFun(call);
|
||
firstLoginSendEmail(call)
|
||
}
|
||
|
||
G.mongodb.collection('loginLog').insertOne({
|
||
uid: gud.uid,
|
||
bindUid: gud.bindUid,
|
||
sid: gud.sid,
|
||
loginTime: G.time
|
||
})
|
||
|
||
call.succ({
|
||
gud: gud,
|
||
curTime: G.time,
|
||
openTime: G.config.openTime,
|
||
openDay: PublicShared.getOpenServerDay(),
|
||
firstLogin: !!!user,
|
||
otherData: obj
|
||
});
|
||
|
||
if (obj.todayFirstLogin) {
|
||
// gud.loginTime 在check时已近被赋值为G.time
|
||
G.emit('FIRST_LOGIN_EVERY_DAY', gud, (gud.loginTime || G.time) - 24 * 3600, G.time);
|
||
}
|
||
|
||
LoginFun(call);
|
||
}
|
||
|
||
/**新玩家首次登陆后执行 */
|
||
async function firstLoginFun(call: ApiCall<ReqLogin, ResLogin>) {
|
||
await Promise.all([
|
||
//插入探险数据
|
||
G.mongodb.collection('tanxian').insertOne({
|
||
uid: call.uid,
|
||
eventTime: G.time,
|
||
lastGuaJiTime: G.time,
|
||
useFastGuaJiNum: 0,
|
||
receivePrize: [],
|
||
resetTime: G.time
|
||
}),
|
||
// 首号奖励
|
||
await PlayerFun.sendPrize(call, G.gc.playerdata.hero),
|
||
// 自动上阵
|
||
HeroFun.setHeroPos(call),
|
||
TaskFun.generateAllTask(call),
|
||
]);
|
||
}
|
||
|
||
/**新玩家首次登陆后执行 */
|
||
function firstLoginSendEmail(call: ApiCall<ReqLogin, ResLogin>) {
|
||
let conf = G.gc.yuyuemail
|
||
|
||
if (G.time > conf.overtime || G.time < conf.opentime) return
|
||
|
||
setTimeout(() => {
|
||
EmailFun.addEmail({
|
||
uid: call.conn.uid,
|
||
type: 'system',
|
||
title: '',
|
||
content: '',
|
||
prize: conf.prize,
|
||
lngTitle: conf.title,
|
||
lngContent: conf.content
|
||
});
|
||
}, 10000)
|
||
}
|
||
|
||
/**玩家登陆后执行 */
|
||
async function LoginFun(call: ApiCall<ReqLogin, ResLogin>) {
|
||
|
||
//检测玩家头像、头像框、聊天框、模型是否过期
|
||
let modelChange = false;
|
||
const model: ResLogin['gud']['model'] = {};
|
||
const change: Partial<ResLogin['gud']> = {};
|
||
if (call.conn.gud.head.time > 0 && call.conn.gud.head.time < G.time) {
|
||
change.head = defaultUserAppend.head;
|
||
}
|
||
if (call.conn.gud.headFrame.time > 0 && call.conn.gud.headFrame.time < G.time) {
|
||
change.headFrame = defaultUserAppend.headFrame;
|
||
}
|
||
if (call.conn.gud.chatFrame.time > 0 && call.conn.gud.chatFrame.time < G.time) {
|
||
change.chatFrame = defaultUserAppend.chatFrame;
|
||
}
|
||
Object.entries(call.conn.gud.model).forEach(v => {
|
||
if (v[1].time > 0 && v[1].time < G.time) {
|
||
modelChange = true;
|
||
model[v[0]] = defaultUserAppend.model[v[0]];
|
||
} else model[v[0]] = Object.assign({}, v[1]);
|
||
});
|
||
if (modelChange) change.model = model;
|
||
Object.keys(change).length > 0 && PlayerFun.addAttr(call, change);
|
||
|
||
//上线重算战力
|
||
call.conn.refreshPower();
|
||
// ### globalDebug GHManage
|
||
if (call.conn.gud.ghLevel == 1 && await GHManage.getGH(call.conn.gud.ghId)) {
|
||
GHManage.hzsx(call.conn.gud);
|
||
}
|
||
|
||
if (!await G.redis.hGet('player:uids', call.conn.gud.uid)) {
|
||
G.redis.hSet('player:uids', call.conn.gud.uid, 1)
|
||
}
|
||
FriendManage.addNew(call.conn.gud.uid);
|
||
|
||
// 更新主线任务
|
||
TaskFun.updateMainTask(call)
|
||
|
||
// 推送当前主线任务信息,引导用
|
||
let _taskInfo = await TaskFun.getFinishByTtype(call, [2], {finish: 0});
|
||
G.server.sendMsgByUid(call.uid, 'msg_s2c/TaskChange', _taskInfo?.[2]?.[0])
|
||
|
||
// 存入当前玩家多语言信息
|
||
G.redis.rawSet(`user:lng:${call.uid}`, call.req.lng, {EX: 259200})
|
||
|
||
// 临时修补
|
||
// fixHeroShiwu(call)
|
||
}
|
||
|
||
// async function fixHeroShiwu(call: ApiCall) {
|
||
// let list = await G.mongodb.collection("hero").find({$and: [{"uid": call.uid}, {"shiwu": {$exists: true}}]}).toArray()
|
||
//
|
||
// list.map(i => {
|
||
// let list = R.values(i.shiwu).filter(i => !i._id)
|
||
// if (list.length == 0) return ''
|
||
//
|
||
// let shiwuChange = {}
|
||
// if (i.shiwu?.['1']?._id) {
|
||
// shiwuChange['1'] = i.shiwu['1']
|
||
// }
|
||
// if (i.shiwu?.['2']?._id) {
|
||
// shiwuChange['2'] = i.shiwu['2']
|
||
// }
|
||
//
|
||
// G.mongodb.collection("hero").findOneAndUpdate({_id: i._id}, {$set: {shiwu: shiwuChange}})
|
||
// })
|
||
// }
|
||
|
||
// 修复玩家退出公会 但是gud中残留公会id
|
||
async function fixUnionData(gud: ResLogin["gud"]) {
|
||
if (gud.ghId) {
|
||
let ghdata = await G.mongodb.collection("gonghui").findOne(
|
||
{_id: G.mongodb.conversionId(gud.ghId), 'players.uid': gud.uid}
|
||
)
|
||
if (!ghdata) {
|
||
gud.ghId = "";
|
||
gud.ghName = "";
|
||
gud.ghLevel = 0;
|
||
PlayerFun.changeAttr(gud.uid, {ghId: '', ghLevel: 0})
|
||
}
|
||
}
|
||
} |