import { cloneDeep, pick } from 'lodash'; import { RoleModel } from './../db/Role'; import { GroupMessageModel } from './../db/GroupMessage'; import { CounterModel } from './../db/Counter'; import { STATUS } from './../consts/statusCode'; import { PrivateMessageModel, PrivateMessageParam, PrivateMessageType } from './../db/PrivateMessage'; import { GroupMessageParam, GroupMessageType } from '../db/GroupMessage'; import { genCode, resResult } from '../pubUtils/util'; import { pinus } from 'pinus'; import { CHANNEL_PREFIX, MSG_CODE_LEN, MSG_SOURCE, MSG_STATUS, MSG_TYPE, ON_MSG_ROUTE, RICH_TEXT_TABLE } from '../consts'; import { addRedisChannel, getRoleOnlineInfo, redisChannelServer } from './redisService'; import { crc32 } from 'crc'; import { HeroType } from '../db/Hero'; /** * @description 生成私聊房间号 * @export * @param {string[]} roleIds * @returns */ export function privateRoomId(roleId: string, targetRoleId: string) { return [roleId, targetRoleId].sort().join('_'); } /** * @description 生成群聊房间号 * @export * @param {string} channel * @param {string} channelId * @returns */ export function groupRoomId(channel: string, channelId: string) { return `${channel}_${channelId}`; } function msgCounterName(roomId: string) { return `chat_${roomId}`; } /** * @description 设置群消息和私聊消息的公共字段 * @param {(PrivateMessageParam | GroupMessageParam)} msg */ async function setupBaseMsgParm(msg: PrivateMessageParam | GroupMessageParam ) { msg.msgCode = genCode(MSG_CODE_LEN); msg.status = MSG_STATUS.NORMAL; if (!msg.roomId) { console.error('roomId needed while setup msg parameter'); return; } msg.seqId = await CounterModel.getNewCounter({name: msgCounterName(msg.roomId), def: 1}); } /** * @description 生成私聊消息数据 * @param {string} roleId * @param {string} roleName * @param {number} type * @param {string} content * @param {string} targetRoleId * @param {string} targetMsgCode * @returns */ async function createPrivateMsgData(roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string) { const result: PrivateMessageParam = {roleId, roleName, type, source, content, targetRoleId, targetMsgCode}; result.roomId = privateRoomId(roleId, targetRoleId); await setupBaseMsgParm(result); return result; } async function createGroupMsgData(roleId: string, roleName: string, channel: string, channelId: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string) { const result: GroupMessageParam = {roleId, roleName, channel, channelId, type, source, content, targetRoleId, targetMsgCode}; result.roomId = groupRoomId(channel, channelId); await setupBaseMsgParm(result); return result; } /** * @description 数据库中创建私聊数据 * @export * @param {string} roleId * @param {string} roleName * @param {number} type * @param {string} content * @param {string} targetRoleId * @param {string} targetMsgCode * @returns */ export async function createPrivateMsg(roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string) { const msgData: PrivateMessageParam = await createPrivateMsgData(roleId, roleName, type, source, content, targetRoleId, targetMsgCode); const result: PrivateMessageType = await PrivateMessageModel.createMsg(msgData); return result; } /** * @description 给某个玩家发送消息 * @export * @param {string} targetRoleId * @param {(PrivateMessageType | GroupMessageType)} msg */ export async function pushMsgToRole(targetRoleId: string, msg: PrivateMessageType | GroupMessageType) { const { sid } = await getRoleOnlineInfo(targetRoleId); if (sid) { pinus.app.get('channelService').pushMessageByUids(ON_MSG_ROUTE, resResult(STATUS.SUCCESS, msg), [{uid: targetRoleId, sid}]); } } /** * @description 获取私聊历史消息 * @export * @param {string} roleId * @param {string} targetRoleId * @param {number} fromSeqId * @param {number} count * @returns */ export async function getPrivateMessages(roleId: string, targetRoleId: string, fromSeqId: number, count: number) { const result = await PrivateMessageModel.getMsgs(privateRoomId(roleId, targetRoleId), fromSeqId, count); return result; } export async function createGroupMsg(roleId: string, roleName: string, channel: string, channelId: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string) { const msgData: GroupMessageParam = await createGroupMsgData(roleId, roleName, channel, channelId, type, source, content, targetRoleId, targetMsgCode); const result: GroupMessageType = await GroupMessageModel.createMsg(msgData); return result; } export async function pushGroupMsgToRoom(roomId: string, msg: GroupMessageType) { const channelSid = await channelServer(roomId); await pinus.app.rpc.chat.chatRemote.sendGroupMsg.toServer(channelSid, roomId, msg); } export async function channelServer(roomId: string) { const existSid = await redisChannelServer(roomId); if (existSid) { return existSid; } const servers = pinus.app.getServersByType('chat'); if (!servers || !servers.length) return null; let index = Math.abs(crc32(roomId)) % servers.length; const newSid = servers[index].id; const addResult = await addRedisChannel(roomId, newSid); if (!addResult) return null; return newSid; } async function addRoleToChannel(roomId: string, roleId: string, sid: string) { const channelSid = await channelServer(roomId); await pinus.app.rpc.chat.chatRemote.addChannel.toServer(channelSid, roomId, roleId, sid); } export async function addRoleToSysChannel(roleId: string, sid: string, serverId: number) { const roomId = groupRoomId('sys', `${serverId}`); await addRoleToChannel(roomId, roleId, sid); } export async function addRoleToWorldChannel(roleId: string, sid: string, serverId: number) { const roomId = groupRoomId('new_world', `${serverId}`); await addRoleToChannel(roomId, roleId, sid); } export async function addRoleToGuildChannel(roleId: string, sid: string, guildCode: string) { const roomId = groupRoomId('new_guild', guildCode); await addRoleToChannel(roomId, roleId, sid); } async function leaveChannel(roomId: string, roleId: string, sid: string) { const channelSid = await channelServer(roomId); await pinus.app.rpc.chat.chatRemote.leaveChannel.toServer(channelSid, roomId, roleId, sid); } export async function leaveSysChannel(roleId: string, sid: string, serverId: number) { const roomId = groupRoomId('sys', `${serverId}`); await leaveChannel(roomId, roleId, sid); } export async function leaveWorldChannel(roleId: string, sid: string, serverId: number) { const roomId = groupRoomId('new_world', `${serverId}`); await leaveChannel(roomId, roleId, sid); } export async function leaveGuildChannel(roleId: string, sid: string) { const { guildCode } = await RoleModel.findByRoleId(roleId, 'guildCode'); if (!guildCode) return; const roomId = groupRoomId('new_guild', guildCode); await leaveChannel(roomId, roleId, sid); } function richTextSetting(type, jumpTo) { const settings = cloneDeep(RICH_TEXT_TABLE); for (let setting of settings) { if (setting.type === type && setting.jumpTo === jumpTo) { return setting; } } } export function wrapRichText(type: string, jumpTo: string, content: string, parm: string) { const setting = richTextSetting(type, jumpTo); return JSON.stringify({ id: setting.id, content, parm }); } export async function pushHeroQualityUpMsg(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { const hero = pick(heroInfo, ['hName', 'hid', 'seqId', 'quality']); const content = JSON.stringify({ roleId, roleName, hero }); const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.HERO_QUALITY_UP, content, null, null); const roomId = groupRoomId(CHANNEL_PREFIX.SYS, `${serverId}`); await pushGroupMsgToRoom(roomId, msgData); }