Files
ZYZ/game-server/app/servers/guild/handler/gvgBattleHandler.ts

354 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { GVGCityType } from './../../../db/GVGCity';
import { GVGRecModel } from '../../../db/GVGRec';
import { LeagueGood } from '../../../domain/gvgField/returnData';
import { GVGTeamModel, GVGTeamType } from '../../../db/GVGTeam';
import { GVGUserDataModel } from '../../../db/GVGUserData';
import { GVGCityModel } from '../../../db/GVGCity';
import { Application, BackendSession, ChannelService, HandlerService } from "pinus";
import { DEBUG_MAGIC_WORD, GVG_PERIOD, STATUS } from "../../../consts";
import { LineupHero } from "../../../domain/roleField/hero";
import { resResult, genCode } from "../../../pubUtils/util";
import { GVGLeagueModel } from '../../../db/GVGLeague';
import { checkGVGPeriod, getGroupIdOfServer, getGVGConfig, getGVGPeriodData, getGVGServerType } from '../../../services/gvg/gvgService';
import { checkMoveStatus, getBirthAreaOfCity, initRobots } from '../../../services/gvg/gvgBattleService';
import { getGVGBattleData } from '../../../services/gvg/gvgBattleMemory';
import { nowSeconds } from '../../../pubUtils/timeUtil';
import { GVGBattleRecModel } from '../../../db/GVGBattleRec';
export default function (app: Application) {
new HandlerService(app, {});
return new GVGBattleHandler(app);
}
export class GVGBattleHandler {
channelService: ChannelService;
constructor(private app: Application) {
this.channelService = app.get('channelService');
}
// 获取我的编队信息
async getTeams(msg: {}, session: BackendSession) {
}
// 保存队伍
// index: 队伍索引位置
// head: 头像
// frame: 相框
// spine: 形象
// lineup: 阵容
async saveTeam(msg: { index: number, head: number, frame: number, spine: number, lineup: [ LineupHero ] }, session: BackendSession) {
if(checkGVGPeriod(GVG_PERIOD.BATTLE)) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const { index, head, frame, spine, lineup } = msg;
const team = await GVGTeamModel.saveTeam(roleId, myLeague.leagueCode, index, head, frame, spine, lineup);
if (!team) {
return resResult(STATUS.GVG_SAVE_TEAM_FAILED);
}
return resResult(STATUS.SUCCESS, { teams: [ team.teamCode ] });
}
// 获取城池信息
async getCity(msg: { cityId: number }, session: BackendSession) {
const guildCode = session.get('guildCode');
const { cityId } = msg;
let { configId } = getGVGPeriodData();
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
const city = await GVGCityModel.findOne({ configId, cityId }).lean();
const { guardLeague: leagueCode, guardLeagueName: name, guardLeagueIcon: icon } = city;
const { battleTime: startTime, scheduleTime } = getGVGConfig();
const cityTeamCnt = await GVGTeamModel.getTeamCntByCity(cityId);
const leagueTeamCnt = await GVGTeamModel.getTeamCntByCity(cityId, myLeague.leagueCode);
return resResult(STATUS.SUCCESS, {
cityId,
guardLeague: { leagueCode, name, icon },
startTime,
endTime: scheduleTime, // ! endTime 修正
ourTeamCnt: leagueTeamCnt,
oppTeamCnt: cityTeamCnt - leagueTeamCnt, // ! 总数是否直接存储在城池中,或有其它更好的方案
});
}
// 进入城池之前的检查
async checkMyTeam(msg: { cityId: number }, session: BackendSession) {
if(!checkGVGPeriod(GVG_PERIOD.BATTLE)) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
const roleId = session.get('roleId');
const { cityId } = msg;
const resData = {};
const teams = await GVGTeamModel.findByRole(roleId);
// 玩家队伍信息中城池id不一致说明玩家已经进入了其他城池
if (teams && teams.length > 0 && teams[0].cityId && teams[0].cityId !== cityId) {
resData['hasSettled'] = true;
resData['cityId'] = teams[0].cityId;
}
return resResult(STATUS.SUCCESS, resData);
}
// 进入城池
async enterCity(msg: { cityId: number }, session: BackendSession) {
if(!checkGVGPeriod(GVG_PERIOD.BATTLE)) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { cityId } = msg;
let { configId } = getGVGPeriodData();
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
await initRobots(groupId, serverType, cityId);
let city: GVGCityType = await GVGCityModel.findByCityId(configId, groupId, serverType, cityId);
let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId);
if (!gvgUserData) {
return resResult(STATUS.GVG_USER_NOT_FOUND);
}
let teams: GVGTeamType[] = [];
// 检测是否已经在城池中,玩家不在这个城池中时进行处理
if (gvgUserData.cityId !== cityId) {
if(gvgUserData.cityId > 0) { // 如果leaveCity没有退出成功玩家还遗留在上一座城中做一下处理
await GVGCityModel.decreasePlayer(configId, groupId, serverType, gvgUserData.cityId, roleId);
}
city = await GVGCityModel.increasePlayer(configId, groupId, serverType, cityId, roleId, myLeague.leagueCode);
if(!city) return resResult(STATUS.GVG_BATTLE_CITY_FULL);
gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, cityId);
// 更新内存队伍信息
let areaId = getBirthAreaOfCity(city, myLeague.leagueCode);
await GVGTeamModel.enterCity(roleId, cityId, areaId, groupId, serverType);
teams = await GVGTeamModel.findByRole(roleId);
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.enterCity(teams);
}
if (!teams || teams.length === 0) {
teams = await GVGTeamModel.findByRole(roleId);
}
const recs = await GVGRecModel.findByCity(cityId, configId);
return resResult(STATUS.SUCCESS, {
cityId,
ranks: [], // ! redis 中积分排行榜
recs,
teams,
});
}
// 离开城池
async leaveCity(msg: { cityId: number }, session: BackendSession) {
if(!checkGVGPeriod(GVG_PERIOD.BATTLE)) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
const roleId = session.get('roleId');
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
const { cityId } = msg;
let { configId } = getGVGPeriodData();
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
// 检测是否已经在城池中
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId);
if (!gvgUserData) {
return resResult(STATUS.GVG_USER_NOT_FOUND);
}
if (gvgUserData.cityId != cityId) {
return resResult(STATUS.GVG_USER_NOT_IN_CITY);
}
const city = await GVGCityModel.decreasePlayer(configId, groupId, serverType, cityId, roleId);
if (!city) {
return resResult(STATUS.GVG_CITY_NOT_FOUND);
}
// 更新玩家城池和队伍城池
gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, 0);
await GVGTeamModel.enterCity(roleId, 0, 0, groupId, serverType);
// 处理内存数据
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.leaveCity(roleId);
return resResult(STATUS.SUCCESS);
}
// 开始移动
// areaId: 要移动的目标据点 id
async startMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const { areaId, cityId, teamCode } = msg;
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let team = await GVGTeamModel.findByTeamCode(roleId, teamCode);
let checkResult = checkMoveStatus(team, cityId, areaId);
if(checkResult.code != 0) return resResult(checkResult);
team = await GVGTeamModel.startMove(teamCode, areaId);
// 更新内存数据
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.move(teamCode, areaId, team.startMoveTime, team.stopMoveTime);
return resResult(STATUS.SUCCESS, { areaId, cityId, stopMoveTime: team.stopMoveTime });
}
// 停止移动
// areaId: 移动到的目标据点 id
async stopMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const { areaId, cityId, teamCode } = msg;
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let team = await GVGTeamModel.findByTeamCode(roleId, teamCode);
if(!team) return resResult(STATUS.GVG_BATTLE_TEAM_NOT_FOUND);
if(team.cityId != cityId && team.areaId != areaId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY);
team = await GVGTeamModel.stopMove(teamCode, areaId);
// 更新内存数据
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.move(teamCode, areaId, team.startMoveTime, team.stopMoveTime);
return resResult(STATUS.SUCCESS, { areaId, cityId, curTeam: team });
}
// 队伍入驻积分点
async teamSettle(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) {
const serverId = session.get('serverId');
const { pointId, teamCode } = msg;
const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, { pointId }).lean();
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.teamSettle(teamCode, pointId);
return resResult(STATUS.SUCCESS, { curTeam });
}
// 队伍离开积分点
async teamLeave(msg: any, session: BackendSession) {
return resResult(STATUS.SUCCESS);
}
// 队伍开始攻击
// teamCode: 攻击方队伍
// oppoTeamCode: 防守方队伍
async battleStart(msg: { cityId: number, teamCode: string, oppoTeamCode: string, pointId: number }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const { teamCode, oppoTeamCode } = msg;
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode);
if(!attackTeam || !defenseTeam) return resResult(STATUS.GVG_BATTLE_TEAM_INVALID);
if(attackTeam.attackTime > nowSeconds()) return resResult(STATUS.GVG_TEAM_ATTACKING);
if(defenseTeam.defenseTime > nowSeconds()) return resResult(STATUS.GVG_TEAM_DEFENSEING);
const battleRecord = await GVGBattleRecModel.createRec(attackTeam, defenseTeam);
attackTeam = await GVGTeamModel.lockAttack(teamCode, groupId, serverType);
defenseTeam = await GVGTeamModel.lockDefense(oppoTeamCode, groupId, serverType);
// 内存处理
let teamObj = getGVGBattleData(groupId, serverType);
teamObj.setTime(teamCode, attackTeam);
teamObj.setTime(teamCode, defenseTeam);
return resResult(STATUS.SUCCESS, { battleCode: battleRecord.battleCode, curTeam: attackTeam });
}
// 队伍停止攻击
async battleEnd(msg: { cityId: number, battleCode: string, isSuccess: boolean }, session: BackendSession) {
const { battleCode, isSuccess } = msg;
const record = await GVGBattleRecModel.findByBattleCode(battleCode);
if(!record) return resResult(STATUS.GVG_BATTLEREC_NOT_FOUND);
const teamCode = '';
const leagueGoods: LeagueGood[] = null;
// ! 计算并更新两支队伍耐久
const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean();
// ! 推送战斗结果给对手队伍
// const channel = this.channelService.getChannel(teamCode, false);
// if (!!channel) {
// channel.pushMessage('onBattleResult', { isSuccess });
// }
// ! 结算奖励
if (isSuccess) {
// ! 更新 leagueGoods
}
return resResult(STATUS.SUCCESS, { curTeam, leagueGoods });
}
// 使用道具
// teamCode: 要使用道具的队伍
async useItem(msg: { cityId: number, itemId: number, teamCode: string }, session: BackendSession) {
const { itemId, teamCode } = msg;
// ! 检查道具是否存在
// ! 检查道具是否可以使用在该队伍
const team = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean();
// ! 根据 item 使用效果更新 team
return resResult(STATUS.SUCCESS, { team });
}
// 复活队伍
async reviveTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) {
const { teamCode } = msg;
// ! 检查该队伍是否可以复活,可以的话更新队伍状态
const team = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean();
// 更新成功返回队伍信息
return resResult(STATUS.SUCCESS, { team });
}
// 获取战报
// type: 战报类型
async getRecs(msg: { type: number }, session: BackendSession) {
const { type } = msg;
// 根据 type 获取战报
const recs = await GVGRecModel.find({ type }).limit(20).lean();
return resResult(STATUS.SUCCESS, { recs });
}
// 获取概况
async getOverview(msg: {}, session: BackendSession) {
const cities = await GVGCityModel.find({}).lean();
// ! 重新组织每个城市的数据,添加据点和积分点的信息
return resResult(STATUS.SUCCESS, { cities });
}
// 获取区域上的队伍
async getAreaTeams(msg: { cityId: number, areaIds: [number] }, session: BackendSession) {
const { cityId, areaIds } = msg;
const queryParam = {};
areaIds.forEach(areaId => {
queryParam[areaId] = [{ $match: { areaId, cityId } }, { $limit: 20 }];
});
const teams = await GVGTeamModel.aggregate([
{ $facet: queryParam },
]);
return resResult(STATUS.SUCCESS, { teams });
}
}