import { UserModel } from '@db/User'; import { LadderMatchRecModel } from '@db/LadderMatchRec'; import { PvpRecordModel } from '@db/PvpRecord'; import { BattleRecordModel } from '@db/BattleRecord'; import { STATUS, WAR_TYPE } from '@consts'; import { Controller } from 'egg'; import * as fs from 'fs'; import { RoleModel } from '@db/Role'; import { NoticeModel } from '@db/Notice'; import { ServerParamWithRole, GroupParam } from '../domain/gameField/serverlist'; import { reloadResources } from 'app/pubUtils/data'; import { ServerlistModel } from '@db/Serverlist'; import { dispatch } from 'app/pubUtils/dispatcher'; import { RedisClient } from 'redis'; import { REDIS_KEY } from '@consts'; import { RegionModel } from '@db/Region'; import { getRandEelmWithWeight } from 'app/pubUtils/util'; import { getLocalRplUrl, getRemoteRplUrl, getRemoteRplPrefix } from 'app/pubUtils/battleUtils' import { ChannelInfoModel } from '@db/ChannelInfo'; import { GVGVestigeRecModel } from '@db/GVGVestigeRec'; import { GVGBattleRecModel } from '@db/GVGBattleRec'; import { PackageModel } from '@db/Package'; const sendToWormhole = require('stream-wormhole'); const pump = require('mz-modules/pump'); export default class GameController extends Controller { public async checkVersion() { const { ctx } = this; const { version } = ctx.request.body; let curRegion = await RegionModel.findRegionByEnv(this.app.config.realEnv); if(!curRegion) { return ctx.body = ctx.service.utils.resResult(STATUS.VERSION_ERR); } const versionFlag = ctx.service.utils.compareVersion(version, curRegion.minVersion); if (versionFlag >= 0) { ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS); return; } //版本号太低 ctx.body = ctx.service.utils.resResult(STATUS.VERSION_ERR, { version: curRegion.minVersion }); return; } public async checkReview() { const { ctx } = this; const { version, platformAppid, platformAppId, addressType, platform: clientPlatform } = ctx.request.body; let curRegion = await RegionModel.findRegionByEnv(this.app.config.realEnv); if(!curRegion) { return ctx.body = ctx.service.utils.resResult(STATUS.VERSION_ERR); } if(curRegion.addressType != addressType) { return ctx.body = ctx.service.utils.resResult(STATUS.ADDRESS_ERR); } let hasPolicy = false, userPolicyLink = '', privacyPolicyLink = ''; // 是否需要替换协议,有就是用下面两个字段替换 let platform = platformAppid ?? platformAppId; let channelInfo = await ChannelInfoModel.findByPlatform(platform); if(channelInfo && !channelInfo.isDefaultPolicy) { hasPolicy = true; userPolicyLink = channelInfo.userPolicyLink; privacyPolicyLink = channelInfo.privacyPolicyLink; } let isReview = false; if (platform === 'ios' || clientPlatform === 'ios') { isReview = await ctx.service.update.checkReview(curRegion, version); } let hasNewWebServer = false, webServerUrl = ''; if(isReview && curRegion.reviewEnv) { let reviewRegion = await RegionModel.findRegionByEnv(curRegion.reviewEnv); if(reviewRegion) { hasNewWebServer = true, webServerUrl = reviewRegion.webHost; } } ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { isReview, hasNewWebServer, webServerUrl, hasPolicy, userPolicyLink, privacyPolicyLink }); return; } public async getServerList() { try { const { ctx } = this; let { uid } = ctx; const { pid, gid, version } = ctx.request.body; let serverList = new Array(); let loginServerList = new Array(); let curRegion = await RegionModel.findRegionByEnv(this.app.config.realEnv); if(!curRegion) { return ctx.body = ctx.service.utils.resResult(STATUS.VERSION_ERR); } // if(curRegion.addressType != addressType) { // return ctx.body = ctx.service.utils.resResult(STATUS.ADDRESS_ERR); // } // let isReview = await ctx.service.update.checkReview(curRegion, version); // let env = isReview? curRegion.reviewEnv: ctx.app.config.realEnv; let allServers = await ServerlistModel.findByEnv(ctx.app.config.realEnv, false); let hasRole = await RoleModel.checkHasRole(uid, curRegion.latestServerUniqId); if(pid && gid) { const pkg = await PackageModel.getPackageByGidPid(gid, pid); if(pkg && pkg.hideServers && pkg.hideServers.length > 0) { allServers = allServers.filter(server => !pkg.hideServers.includes(server.id)); } } let roles = await RoleModel.findAllByUid(uid, true, true); for (let server of allServers) { let status = ctx.service.utils.getServerStatus(server, version, hasRole) let curGroup = serverList.find(cur => cur.groupId == server.groupId); if (!curGroup) { curGroup = new GroupParam(server); serverList.push(curGroup); } curGroup.pushServer(server, status); let role = roles.find(role => role.serverId == server.id); if (!!role) { let curLoginInfo = new ServerParamWithRole(role, server, status); loginServerList.push(curLoginInfo); } } loginServerList.sort((a, b) => { return b.updatedAt.getTime() - a.updatedAt.getTime() }); if (serverList) { ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { serverList, loginServerList }); } else { ctx.body = ctx.service.utils.resResult(STATUS.SERVER_NOT_FOUND); } return }catch(e) { console.error(e); } } public async getnotice() { const { ctx } = this; const { pid, gid } = ctx.request.body; let packageCode = 'default'; if(pid && gid) { let pkg = await PackageModel.getPackageByGidPid(gid, pid); if(pkg) packageCode = pkg?.packageCode; } let notice = await NoticeModel.getAllNotice(packageCode); if(notice.length == 0) notice = await NoticeModel.getAllNotice('default'); let result = notice.map(cur => { let { id, title, tag, type, content, time } = cur; return { id, title, tag, type, content, time } }) ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { notice: result }); return } public async reloadResource() { const { ctx } = this; try { reloadResources(); ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { isOK: true }); return; } catch (e) { ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { isOK: false, err: (e).stack }); return; } } public async queryEnter() { const { ctx } = this; const { app, userCode } = ctx; let redisClient: RedisClient = app.context.redisClient; let hash = await redisClient.hvalsAsync(REDIS_KEY.SYS_SERVER); let connectors = hash.map(cur => JSON.parse(cur)); if (!connectors || connectors.length === 0) { ctx.body = ctx.service.utils.resResult(STATUS.CONNECTOR_ERR); return } // select connector let sum = connectors.reduce((pre, cur) => pre + (cur['num']||0), 0); let res; if(sum > 0) { let serversWithWeight = connectors.map(cur => ({...cur, weight: sum - (cur['num']||0)})); let randResult = getRandEelmWithWeight(serversWithWeight); res = randResult.dic; } if(!res) { res = await dispatch(ctx.app.context.redisClient, userCode, connectors, 'connector'); } let { id, serverType, clientHost, clientPort, num = 0 } = res; await redisClient.hsetAsync(REDIS_KEY.SYS_SERVER, id, JSON.stringify({ serverType, clientHost, clientPort, id, num: num + 1 })); ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { host: res.clientHost, port: res.clientPort }); return } public async upload() { const { ctx } = this; const parts = ctx.multipart(); let part; let [writePath, token, battleCode, fullPath, remoteUrl, warType, prefix] = ['', '', '', '', '', 0, '']; while ((part = await parts()) != null) { if (part.length) { console.log('kv: ', `${part[0]}: ${part[1]}`); if (part[0] === 'token') { token = part[1]; } else if (part[0] === 'battleCode') { battleCode = part[1]; } else if (part[0] === 'warType') { // 检测 part[1] 类型 if (typeof part[1] === 'number') { warType = part[1]; } else if (typeof part[1] === 'string' && !isNaN(parseInt(part[1]))) { warType = parseInt(part[1]); } } } else { if (!part.filename) { continue; } console.log(part); if (part.fieldname === 'rpl' && battleCode !== '') { console.log('field: ', part.fieldname); console.log('filename: ', part.filename); if (token === '') { ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS); return; } const user = await UserModel.findUserByToken(token); if (!user) { console.error('token invalid'); ctx.body = ctx.service.utils.resResult(STATUS.TOKEN_ERR); return; } let roleId = ''; if (!!warType && warType === WAR_TYPE.GVG_BATTLE) { // gvg激战期录像,没有通用 BattleRecord,单独处理 let gvgBattleRec = await GVGBattleRecModel.findByBattleCode(battleCode); if (!gvgBattleRec) return ctx.body = ctx.service.utils.resResult(STATUS.BATTLE_NOT_FOUND); roleId = gvgBattleRec.attackTeam?.roleId; if (!roleId) return ctx.body = ctx.service.utils.resResult(STATUS.BATTLE_NOT_FOUND); } else { let battleRec = await BattleRecordModel.getBattleRecordByCode(battleCode, true); if (!battleRec) return ctx.body = ctx.service.utils.resResult(STATUS.BATTLE_NOT_FOUND); roleId = battleRec.roleId; warType = battleRec.warType; // if (warType !== WAR_TYPE.PVP && warType !== WAR_TYPE.LADDER && warType !== WAR_TYPE.GVG_VESTIGE) return ctx.body = ctx.service.utils.resResult(STATUS.BATTLE_RPL_NOT_SUPPORT); } writePath = getLocalRplUrl(roleId, warType, battleCode); try { fs.accessSync(writePath); } catch (err) { if (err) { fs.mkdirSync(writePath, { recursive: true }); } } fullPath = `${writePath}/${battleCode}.bin` console.log(fullPath); if (!fs.existsSync(fullPath)) { fs.writeFileSync(fullPath, ''); } const writeStream = fs.createWriteStream(fullPath); await pump(part, writeStream); prefix = getRemoteRplPrefix(ctx.app.config.realEnv); remoteUrl = `${getRemoteRplUrl(ctx.app.config.sshHost,roleId, warType, battleCode)}/${battleCode}.bin`; let updateDBRes; if (warType === WAR_TYPE.PVP) { updateDBRes = await PvpRecordModel.updateRplStatus(battleCode, true, remoteUrl); } else if (warType === WAR_TYPE.LADDER) { updateDBRes = await LadderMatchRecModel.updateRplStatus(battleCode, true, remoteUrl); } else if (warType == WAR_TYPE.GVG_VESTIGE) { updateDBRes = await GVGVestigeRecModel.updateRplStatus(battleCode, true, remoteUrl); } else if (warType == WAR_TYPE.GVG_BATTLE) { updateDBRes = await GVGBattleRecModel.updateRplStatus(battleCode, true, remoteUrl); } else { updateDBRes = await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { remoteUrl }}); } if (!updateDBRes) return ctx.body = ctx.service.utils.resResult(STATUS.BATTLE_RPL_UPDATE_ERR); } else { await sendToWormhole(part); } } } ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { rplUrl: prefix + remoteUrl }); return; } // 根据 pid 和 gid 获取大区地址 public async getRegionAddr() { const { ctx } = this; const { pid, gid } = ctx.request.body; if (!pid || !gid) { ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS); return; } const pkg = await PackageModel.getPackageByGidPid(gid, pid); if (!pkg) { ctx.body = ctx.service.utils.resResult(STATUS.PACKAGE_NOT_FOUND); return; } const { regionId, loginPage = '', loadingPage = '' } = pkg; const region = await RegionModel.findRegionById(regionId); if (!region) { ctx.body = ctx.service.utils.resResult(STATUS.REGION_NOT_FOUND); return; } const { webHost = 'https://sq7-web-sgzzyz.yev242.com', addressType = 9 } = region; ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { webHost, addressType, loginPage, loadingPage }); return; } }