Files
ZYZ/game-server/app/servers/guild/handler/gvgBattleHandler.ts
2023-02-17 10:58:47 +08:00

291 lines
12 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 { LeagueCityPoint, GVGTeamMem } from './../../../domain/battleField/gvgBattle';
import { GVGRecModel } from '../../../db/GVGRec';
import { LeagueGood } from '../../../domain/gvgField/returnData';
import { GVGTeamModel } 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, getGVGPeriodData } from '../../../services/gvg/gvgService';
export default function (app: Application) {
new HandlerService(app, {});
return new GVGBattleHandler(app);
}
export class GVGBattleHandler {
channelService: ChannelService;
// 积分点占领情况cityId -> LeagueCode -> LeagueCityPoint
private pointOccupy: Map<number, Map<string, LeagueCityPoint>> = new Map();
// 城池队伍状态cityId -> areaId -> GVGTeamMem
private cityTeamStatus: Map<number, Map<number, GVGTeamMem>> = new Map();
constructor(private app: Application) {
this.channelService = app.get('channelService');
}
// 保存队伍
// 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) {
if(checkGVGPeriod(GVG_PERIOD.BATTLE)) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
const { cityId } = msg;
let { configId } = getGVGPeriodData();
const city = await GVGCityModel.findOne({ configId, cityId }).lean();
return resResult(STATUS.SUCCESS, { city });
}
// 进入城池
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 guildCode = session.get('guildCode')
const { cityId } = msg;
let { configId } = getGVGPeriodData();
let city: GVGCityType = await GVGCityModel.findOne({ cityId, configId }).lean();
if (!city) {
return resResult(STATUS.GVG_CITY_NOT_FOUND);
}
// 检测是否已经在城池中,如果在城池中,直接返回城池信息
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.SUCCESS, { city });
}
// 不在城池则检测是否满员
const { userCnt } = city;
// 检测是否满员
if (userCnt >= 200) {
return resResult(STATUS.GVG_BATTLE_CITY_FULL);
}
// 检测玩家是否已经在其他城池中,由 checkMyTeam 接口检测
// if (gvgUserData.cityId) {
// }
const roleTeamCnt = await GVGTeamModel.getTeamCnt(roleId);
city = await GVGCityModel.updateCityUser(configId, cityId, 1, roleTeamCnt);
gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, cityId);
// ! 队伍默认进入的据点暂时设为 0更新内存队伍信息
const res = await GVGTeamModel.resetTeamsLoc(roleId, cityId, 0);
if (!res) {
return resResult(STATUS.GVG_RESET_TEAM_LOC_FAILED);
}
return resResult(STATUS.SUCCESS, { city });
}
// 离开城池
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 { cityId } = msg;
let { configId } = getGVGPeriodData();
// 检测是否已经在城池中
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 roleTeamCnt = await GVGTeamModel.getTeamCnt(roleId);
const city = await GVGCityModel.updateCityUser(configId, cityId, -1, -roleTeamCnt);
if (!city) {
return resResult(STATUS.GVG_CITY_NOT_FOUND);
}
// 更新玩家城池和队伍城池
gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, 0);
const res = await GVGTeamModel.resetTeamsLoc(roleId, 0, 0);
if (!res) {
return resResult(STATUS.GVG_RESET_TEAM_LOC_FAILED);
}
// ! 还需处理内存数据
return resResult(STATUS.SUCCESS);
}
// 开始移动
// areaId: 要移动的目标据点 id
async startMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) {
const { areaId, cityId } = msg;
const moveTime = Date.now();
return resResult(STATUS.SUCCESS, { areaId, cityId, moveTime });
}
// 停止移动
// areaId: 移动到的目标据点 id
async stopMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) {
const { areaId, cityId, teamCode } = msg;
const players = await GVGUserDataModel.find({ cityId, areaId }).limit(20).lean();
const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, { areaId }).lean();
return resResult(STATUS.SUCCESS, { areaId, cityId, players, curTeam });
}
// 队伍入驻积分点
async teamSettle(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) {
const { pointId, teamCode } = msg;
const curTeam = await GVGTeamModel.findOneAndUpdate({ teamCode }, { pointId }).lean();
return resResult(STATUS.SUCCESS, { curTeam });
}
// 队伍离开积分点
async teamLeave(msg: any, session: BackendSession) {
return resResult(STATUS.SUCCESS);
}
// 队伍开始攻击
// teamCode: 攻击方队伍
// oppoTeamCode: 防守方队伍
async battleStart(msg: { teamCode: string, oppoTeamCode: string }, session: BackendSession) {
const { teamCode, oppoTeamCode } = msg;
const teams = await GVGTeamModel.find({ teamCode: { $in: [ teamCode, oppoTeamCode ] } }).lean();
let teamInvalid = false;
let invalidTeamCode = '';
teams.forEach(team => {
if (team.attackTime > Date.now() - 1000 * 5) {
teamInvalid = true;
invalidTeamCode = team.teamCode;
}
});
if (teamInvalid) {
return resResult(STATUS.GVG_BATTLE_TEAM_INVALID, { teamCode: invalidTeamCode });
}
// 生成 battleCode
const battleCode = genCode(8);
return resResult(STATUS.SUCCESS, { battleCode });
}
// 队伍停止攻击
async battleEnd(msg: { battleCode: string, isSuccess: boolean }, session: BackendSession) {
const { battleCode, isSuccess } = msg;
// ! 根据 battleCode 获取 teamCode
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: { 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: { 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 });
}
// debug 接口,创建城市
async createCity(msg: { cityId: number, magicWord: string }, session: BackendSession) {
const { cityId, magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.INTERNAL_ERR);
}
let { configId } = getGVGPeriodData();
// 检查城市是否存在
let city = await GVGCityModel.getCityByCityId(configId, cityId);
if (city) {
return resResult(STATUS.SUCCESS, { city });
}
city = await GVGCityModel.createCity(configId, cityId);
return resResult(STATUS.SUCCESS, { city });
}
}