diff --git a/game-server/app/servers/battle/handler/comBattleHandler.ts b/game-server/app/servers/battle/handler/comBattleHandler.ts index 6f8cfad20..1b36745f2 100644 --- a/game-server/app/servers/battle/handler/comBattleHandler.ts +++ b/game-server/app/servers/battle/handler/comBattleHandler.ts @@ -9,6 +9,7 @@ import { resResult, getRandomByLen, calculateNum } from '../../../pubUtils/util' import { RoleStatus } from '../../../db/ComBattleTeam'; import { ItemModel } from '../../../db/Item'; import { handleReward } from '../../../services/rewardService'; +import { getTeamSearchByQuality, setTeamSearchReq } from '../../../services/redisService'; export default function(app: Application) { return new ComBattleHandler(app); @@ -35,6 +36,17 @@ class ComTeam { bossHp: number; // 品质 quality: number; + + constructor(teamCode: string, pub: boolean, blueprtId: number, status: number, capId: string, ceLimit: number, bossHp: number, quality: number) { + this.teamCode = teamCode; + this.pub = pub; + this.blueprtId = blueprtId; + this.status = status; + this.capId = capId; + this.ceLimit = ceLimit; + this.bossHp = bossHp; + this.quality = quality; + } } export class ComBattleHandler { constructor(private app: Application) { @@ -54,7 +66,7 @@ export class ComBattleHandler { if (!goodData || goodData.itid !== IT_TYPE.BLUEPRT) return resResult(STATUS.COM_BATTLE_BLUEPRT_INVALID); // 检查藏宝图是否足够 - let { lv, headHid, topFiveCe, sHid } = await RoleModel.findByRoleId(roleId); + let { lv, headHid = 19, topFiveCe, sHid = 19 } = await RoleModel.findByRoleId(roleId); if (lv < COM_TEAM_ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); let blueprt = await ItemModel.findbyRoleAndGidAndCount(roleId, blueprtId, 1); @@ -62,48 +74,68 @@ export class ComBattleHandler { // 检查是否有已创建未结束的寻宝,预先占用一张藏宝图 let teams = await ComBattleTeamModel.getTeamByCapAndStatus(roleId, COM_TEAM_STATUS.FIGHTING); if (teams && blueprt.count <= teams.length) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); - // TODO: 检查武将是否拥有 + let roleStatus = []; + let roleIds = []; + roleIds.push(roleId); + let capStatus = new RoleStatus(roleId, roleName, true, false, headHid, sHid, topFiveCe, lv); + roleStatus.push(capStatus); + let teammates = await getTeamSearchByQuality(goodData.quality); + console.log('teammates: ', teammates); + if (teammates) { + for (let teammate of teammates) { + let roleInfo = await RoleModel.findByRoleId(teammate.roleId); + if (!roleInfo) continue; + // TODO: 没处理情谊助战 + roleStatus.push(new RoleStatus(roleInfo.roleId, roleInfo.roleName, false, false, roleInfo.headHid, roleInfo.sHid, roleInfo.topFiveCe, roleInfo.lv)); + roleIds.push(roleInfo.roleId); + } + } // 创建队伍数据结构 - let comTeam = new ComTeam(); - comTeam.blueprtId = blueprtId; - comTeam.quality = goodData.quality; - comTeam.capId = roleId; - comTeam.pub = pub; - comTeam.teamCode = teamCode; - comTeam.roleIds = [roleId]; - comTeam.status = COM_TEAM_STATUS.DEFAULT; - comTeam.ceLimit = ceLimit; - comTeam.bossHp = getBossHpByBlueprtId(blueprtId) || 10000; - - let roleStatus = new RoleStatus(); - roleStatus.heroes = heroes; - roleStatus.isCap = true; - roleStatus.headHid = headHid || 19; - roleStatus.topFiveCe = topFiveCe; - roleStatus.roleId = roleId; - roleStatus.isReady = true; - roleStatus.totalDmg = 0; - roleStatus.roleName = roleName; - roleStatus.lv = lv; - roleStatus.sHid = sHid || 19; - comTeam.roleStatus = [roleStatus]; + let comTeam = new ComTeam(teamCode, pub, blueprtId, 0, roleId, ceLimit, getBossHpByBlueprtId(blueprtId) || 10000, goodData.quality); + comTeam.roleStatus = roleStatus; + comTeam.roleIds = roleIds; this.teamMap.set(teamCode, comTeam); + // TODO: 处理助战回滚 const team = await ComBattleTeamModel.createTeam(comTeam); if (!team) return resResult(STATUS.COM_BATTLE_CREATE_ERR); let channelService = this.app.get('channelService'); let channel = channelService.getChannel(teamCode, true); let users = channel.getMembers(); - if (users.indexOf(roleId) === -1) { - channel.add(roleId, sid); + for (let roleId of roleIds) { + if (users.indexOf(roleId) === -1) { + channel.add(roleId, sid); + } + } + + if (teammates) { + let uids = []; + for (let teammate of teammates) { + let { roleId, sid } = teammate; + uids.push({uid: roleId, sid}); + } + // TODO: 处理助战 timer + channelService.pushMessageByUids('onTeamJoin', {teamInfo: comTeam}, uids); } return resResult(STATUS.SUCCESS, { teamCode, roleStatus }); } + async searchTeam(msg: {qualityArr: [number]}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + const { qualityArr } = msg; + let { lv, headHid = 19, topFiveCe, sHid = 19 } = await RoleModel.findByRoleId(roleId); + + await setTeamSearchReq(roleId, sid, qualityArr); + setTimeout(() => { + + }, 10000); + } + async joinTeam(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); @@ -113,7 +145,7 @@ export class ComBattleHandler { let teamStatus = this.teamMap.get(teamCode); if (!teamStatus || teamStatus.status !== 0 || teamStatus.roleIds.length === 3) return resResult(STATUS.COM_BATTLE_MEMBER_LIMIT); if (teamStatus.roleIds.indexOf(roleId) !== -1) return resResult(STATUS.COM_BATTLE_DUP_ENTER); - let { lv, headHid, topFiveCe, sHid } = await Role.findByRoleId(roleId); + let { lv, headHid = 19, topFiveCe = 0, sHid = 19 } = await Role.findByRoleId(roleId); let { quality } = getGoodById(teamStatus.blueprtId); let { assistanceLevel, assistanceTime } = getComBtlSetByQuality(quality); if (lv < COM_TEAM_ENABLE_LV) { @@ -127,18 +159,7 @@ export class ComBattleHandler { let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, teamStatus.quality, new Date(new Date().setHours(0, 0, 0, 0)), true); if (teams.length >= assistanceTime) resResult(STATUS.COM_BATTLE_ASSIST_NOT_ENOUGH); - let roleStatus = new RoleStatus(); - roleStatus.heroes = []; - roleStatus.isCap = false; - roleStatus.headHid = headHid || 19; // 默认给赵云 - roleStatus.topFiveCe = topFiveCe || 0; - roleStatus.roleId = roleId; - roleStatus.roleName = roleName; - roleStatus.isFrd = isFrd; - roleStatus.isReady = false; - roleStatus.totalDmg = 0; - roleStatus.lv = lv; - roleStatus.sHid = sHid || 19; + let roleStatus = new RoleStatus(roleId, roleName, false, isFrd, headHid, sHid, topFiveCe, lv); const team = await ComBattleTeamModel.addRole(teamCode, roleStatus); if (!team) { return resResult(STATUS.COM_BATTLE_CREATE_ERR); diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 92c74215f..c1590b00c 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -1,23 +1,40 @@ +import { GOOD_QUALITY } from './../consts/consts'; import { RoleModel } from "../db/Role"; -import * as redis from 'redis'; +import * as Redis from 'redis'; import {REDIS_KEY} from '../consts/consts' import { GameModel } from "../db/Game"; -import { exists } from "fs"; +import { promisifyAll } from 'bluebird'; + +// 映射 redis 接口 +declare module 'redis' { + export interface RedisClient extends NodeJS.EventEmitter { + hdelAsync(...args: any[]): Promise; + spopAsync(...args: any[]): Promise; + sremAsync(...args: any[]): Promise; + srandmemberAsync(...args: any[]): Promise; + } + export interface Multi extends Commands { + execAsync(...args: any[]): Promise; + } +} let redisArr = 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com'; if(process.env.NODE_ENV == 'local') { redisArr = '127.0.0.1'; } // 创建 redis 连接 -const client = redis.createClient(6379, redisArr, {detect_buffers: true}); -client.auth('zyz_2020', (err, reply) => { +const oldRedisClient = Redis.createClient(6379, redisArr, {detect_buffers: true}); +oldRedisClient.auth('zyz_2020', (err, reply) => { if (err) { console.log('redis err', err); } else { console.log('redis suc'); } }) -client.set('hello', 'redis', redis.print); + +// 转 promise +const client = promisifyAll(oldRedisClient) as Redis.RedisClient; +client.set('hello', 'redis', Redis.print); /** * 在服务重新启动时,将信息存入redis @@ -118,6 +135,49 @@ function decodeScoreWithTime(num: string): number { return Math.floor(_num/pow); } +/**************** 寻宝相关 start */ + +// 把寻宝的玩家信息存入 redis +export async function setTeamSearchReq(roleId: string, sid: string, qualityArr: Array) { + let cmds = []; + qualityArr.forEach(quality => { + if (quality) { + cmds.push(['sadd', `${REDIS_KEY.COM_TEAM_SEARCH_PRE}${quality}`, `${roleId}:${sid}`]); + } + }); + const multiClient = client.multi(cmds) as Redis.Multi; + const newMulti = promisifyAll(multiClient) as Redis.Multi; + const res = await newMulti.execAsync(); + console.log('setTeamSearchReq: ', res); + return res; +} + +// 取出 0 - 2 个某品质的匹配中玩家,并在其它品质中删除此玩家信息 +export async function getTeamSearchByQuality(quality: number) { + // TODO: 操作不具有原子性 + const userInfos = await client.srandmemberAsync(`${REDIS_KEY.COM_TEAM_SEARCH_PRE}${quality}`, 2); + console.log('getTeamSearchByQuality: ' + userInfos); + if (!userInfos || !userInfos.length) return null; + + let cmds = []; + let res = []; + for (let userInfo of userInfos) { + const decodeData = `${userInfo}`.split(':'); + if (decodeData.length !== 2) return null; + + res.push({roleId: decodeData[0], sid: decodeData[1]}); + GOOD_QUALITY.forEach((q) => { + cmds.push(['srem', `${REDIS_KEY.COM_TEAM_SEARCH_PRE}${q}`, userInfo]); + }) + const multiClient = client.multi(cmds) as Redis.Multi; + const newMulti = promisifyAll(multiClient) as Redis.Multi; + await newMulti.execAsync(); + } + console.log('getTeamSearchByQuality res: ', res); + return res; +} + +/**************** 寻宝相关 end */ ////// redis方法 diff --git a/shared/consts/consts.ts b/shared/consts/consts.ts index c9eb8271a..ac56742a1 100644 --- a/shared/consts/consts.ts +++ b/shared/consts/consts.ts @@ -32,6 +32,8 @@ export const IT_TYPE = { BLUEPRT: 28 } +export const GOOD_QUALITY = [1, 2, 3, 4, 5]; + // 大类型,区分存到哪张表里 export const GOOD_TYPE = { EQUIP: 1, @@ -284,13 +286,14 @@ export const COM_BATTLE_ROBOT_HURT_RATE = 0.4; // 每个机器人消耗 boss 血量百分比浮动范围 export const COM_BATTLE_ROBOT_HURT_RAND_RATE = 0.05; // 每日情谊点上限 -export const COM_BATTLE_FRDCNT_MAX = 100; +export const COM_BATTLE_FRDCNT_MAX = 150; // 情谊点掉落数量 export const COM_BATTLE_FRDCNT_DROP = 10; export const REDIS_KEY = { USER_INFO: "userInfo", // 玩家缓存信息 - TOWER_RANK: "towerRank" // 天梯排行榜 + TOWER_RANK: "towerRank", // 天梯排行榜 + COM_TEAM_SEARCH_PRE: 'comTeamSerQ', // 匹配中的玩家,按品质分 } export const FUNC_OPT_TYPE = { diff --git a/shared/db/ComBattleTeam.ts b/shared/db/ComBattleTeam.ts index b19f0629d..b533c2e6b 100644 --- a/shared/db/ComBattleTeam.ts +++ b/shared/db/ComBattleTeam.ts @@ -40,6 +40,20 @@ export class RoleStatus { // 主公等级 @prop({ required: true, default: 1 }) lv: number; + + constructor(roleId: string, roleName: string, isCap: boolean, isFrd: boolean, headHid: number, sHid: number, topFiveCe: number, lv: number) { + this.roleId = roleId; + this.roleName = roleName; + this.isCap = isCap; + this.totalDmg = 0; + this.isFrd = isFrd; + this.headHid = headHid; + this.sHid = sHid; + this.topFiveCe = topFiveCe; + this.lv = lv; + this.heroes = []; + this.killed = []; + } } @index({ teamCode: 1 })