diff --git a/game-server/app/servers/chat/remote/guildRemote.ts b/game-server/app/servers/chat/remote/guildRemote.ts index fab4125da..b7a5cd508 100644 --- a/game-server/app/servers/chat/remote/guildRemote.ts +++ b/game-server/app/servers/chat/remote/guildRemote.ts @@ -27,7 +27,9 @@ export class GuildRemote { private GUILD_REC_ADD = 'onGuildRecAdd'; private GUILD_ACT_RANK = 'onGuildGateRankUpdate'; // 军团活动排行榜 private GUILD_GATE_ACT_HP = 'onGuildGateHpUpdate'; // 军团活动蛮夷入侵排行榜 - private GUILD_ACTIVITY_END = 'onGuildActivityEnd'; + private GUILD_ACTIVITY_END = 'onGuildActivityEnd'; // 军团活动结束 + private GUILD_CITY_DECLARE = 'onGuildCityDeclare'; // 有军团对这个城池进行宣战了 + private GUILD_CITY_ACT_HP = 'onGuildCityGateHpUpdate'; // 诸侯入侵城门血条 /** * 封装,军团相关channel名: 'guild'+guildCode @@ -76,6 +78,31 @@ export class GuildRemote { return channel } + /** + * 诸侯混战,按城池区分channel + * @param cityId 城池id + * @param create 是否创建channel + */ + private getCityChannel(cityId: number, create: boolean = false) { + let channelName = groupRoomId(CHANNEL_PREFIX.CITY, cityId); + let channel = this.channelService.getChannel(channelName, create); + return channel + } + + /** + * 封装,向channel发推送 + * @param cityId 城池id + * @param path 推送地址 + * @param message 推送信息 + */ + private pushMessageToCity(cityId: number, path: string, message: any) { + let channel = this.getCityChannel(cityId); + if(!!channel) { + channel.pushMessage(path, resResult(STATUS.SUCCESS, message)); + } + return channel + } + /** * 踢出某个成员 * @param guildCode 军团code @@ -163,8 +190,8 @@ export class GuildRemote { * 向军团推送城门血量 * @param guildCode */ - public pushGateHp(guildCode: string, msg: GuildGateRankParam) { - this.pushMessage(guildCode, this.GUILD_GATE_ACT_HP, msg); + public pushGateHp(guildCode: string, gateHp: number) { + this.pushMessage(guildCode, this.GUILD_GATE_ACT_HP, { gateHp }); } /** @@ -183,4 +210,29 @@ export class GuildRemote { console.log("MSG END") this.pushMessage(guildCode, this.GUILD_ACTIVITY_END, {}); } + + /** + * @description 向城池推送有宣战 + * @param cityId 城池 + * @param declareGuildCode 宣战的军团code + * @param declareCount 宣战数量 + */ + public async sendGuildCityDeclare(cityId: number, declareGuildCode: string, declareCount: number ) { + this.pushMessageToCity(cityId, this.GUILD_CITY_DECLARE, { + cityId, + declareGuildCode, + declareCount + }); + } + + /** + * @description 推送城池城门血条 + * @param guildCode + */ + public async pushCityGateHp(cityId: number, gateHp: number ) { + this.pushMessageToCity(cityId, this.GUILD_CITY_ACT_HP, { + cityId, + gateHp + }); + } } \ No newline at end of file diff --git a/game-server/app/servers/guild/handler/cityActivityHandler.ts b/game-server/app/servers/guild/handler/cityActivityHandler.ts index 637dedb8e..d6921099a 100644 --- a/game-server/app/servers/guild/handler/cityActivityHandler.ts +++ b/game-server/app/servers/guild/handler/cityActivityHandler.ts @@ -1,10 +1,22 @@ -import { Application, ChannelService, BackendSession } from "pinus"; -import { GUILD_ACTIVITY_TYPE, STATUS, CITY_STATUS } from "../../../consts"; +import { Application, ChannelService, BackendSession, pinus } from "pinus"; +import { GUILD_ACTIVITY_TYPE, STATUS, REDIS_KEY, GUILD_POINT_WAYS } from "../../../consts"; import { resResult } from "../../../pubUtils/util"; -import { getGuildActivityStatus } from "../../../services/guildActivityService"; +import { getGuildActivityStatus, getCityActivityObj, getCityStatus as pubGetCityStatus, getCities, getCityActivityRank } from "../../../services/guildActivityService"; import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; -import { CityParam } from "../../../domain/battleField/guildActivity"; import { gameData } from "../../../pubUtils/data"; +import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; +import { leaveCityChannel, addRoleToCityChannel, getCityChannelSid } from "../../../services/chatService"; +import { UserGuildModel } from "../../../db/UserGuild"; +import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; +import { nowSeconds, getBeforeMinuteSeconds } from "../../../pubUtils/timeUtil"; +import { getGoldObject } from "../../../pubUtils/itemUtils"; +import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; +import { handleCost } from "../../../services/rewardService"; +import { getRankScore, getCityKeyName, getGuildKeyName, setGuildActivityRank, setRank } from "../../../services/redisService"; +import { RoleModel, RoleType } from "../../../db/Role"; +import { RankParam, GuildRankParam } from "../../../domain/rank"; +import { GuildModel } from "../../../db/Guild"; +import { addActive } from "../../../services/guildService"; export default function (app: Application) { return new CityActivityHandler(app); @@ -30,36 +42,7 @@ export class CityActivityHandler { if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); const dbCities = await GuildActivityCityModel.getAllCities(serverId); - - let cities = new Array(); - for(let [ cityId, dic ] of gameData.cityActivity) { - let param = new CityParam(cityId); - let curCity = dbCities.find(cur => cur.cityId == cityId); - - let preCity = dic.preCity; - if(preCity && preCity.length) { - let hasGuardCity = dbCities.find(cur => { - return preCity.includes(cur.cityId) && cur.guardGuildCode == guildCode; - }); - if(!!hasGuardCity) { - param.status = CITY_STATUS.CAN_DECLARE; - } - } else { - param.status = CITY_STATUS.CAN_DECLARE; - } - - if(curCity) { - if(curCity.guardGuildCode == guildCode) { - param.status = CITY_STATUS.GUARD; - } else if (curCity.declareGuilds.includes(guildCode)) { - param.status = CITY_STATUS.DECLARED; - } - param.guardGuildCode = curCity.guardGuildCode; - param.guardGuildName = curCity.guardGuildName; - param.declareCount = curCity.declareCount; - } - cities.push(param); - } + let cities = getCities(guildCode, dbCities); return resResult(STATUS.SUCCESS, { ...statusResult, @@ -68,27 +51,234 @@ export class CityActivityHandler { } // 获取单个城池状态 - async getCityStatus(msg: {}, session: BackendSession) { + async getCityStatus(msg: { cityId: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + let sid = session.get('sid'); + + const { cityId } = msg; + + let statusResult = getGuildActivityStatus(this.aid); + if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let dicCity = gameData.cityActivity.get(cityId); + if(!dicCity) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let obj = getCityActivityObj(); + let gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp); + + let myGuildActivityRec = await UserGuildActivityRecModel.findByRoleId(roleId, this.aid); + let challengeTime = 0; + if(myGuildActivityRec) { + challengeTime = myGuildActivityRec.challengeTime; + } + + const dbCities = await GuildActivityCityModel.getAllCities(serverId); + let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity.preCity, dbCities); + + let historyCity = obj.getHistoryCity(roleId); + if(historyCity) { + await leaveCityChannel(roleId, sid, historyCity); + } + await addRoleToCityChannel(roleId, sid, cityId); + obj.setHistoryCity(roleId, cityId); + + let ranks = await getCityActivityRank(guildCode, serverId, cityId, roleId, roleName); + + return resResult(STATUS.SUCCESS, { + cityId, + ...statusResult, + cityStatus, + gateHp, + challengeTime, + ...ranks + }); } // 宣战 - async declareCity(msg: {}, session: BackendSession) { + async declareCity(msg: { cityId: number }, session: BackendSession) { + // const roleId = session.get('roleId'); + // const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + //TODO 权限校验 + + let { cityId } = msg; + let checkResult = await GuildActivityCityModel.checkDeclartion(serverId, guildCode); + if(!!checkResult) return resResult(STATUS.HAS_DECLARED); + + let rec = await GuildActivityCityModel.declare(serverId, cityId, guildCode); + + let chatSid = await getCityChannelSid(guildCode); + pinus.app.rpc.chat.guildRemote.sendGuildCityDeclare.toServer(chatSid, cityId, guildCode, rec.declareCount); + + let obj = getCityActivityObj(); + obj.pushGuild(guildCode, serverId, cityId); + + const dbCities = await GuildActivityCityModel.getAllCities(serverId); + let cities = getCities(guildCode, dbCities); + return resResult(STATUS.SUCCESS, { cities }); } // 开始挑战 - async checkBattle(msg: {}, session: BackendSession) { + async checkBattle(msg: {cityId: number, costGold: boolean, heroes: number[]}, session: BackendSession) { + let { cityId, costGold, heroes } = msg; + if(!heroes || heroes.length <= 0) return resResult(STATUS.WRONG_PARMS); + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + + if(!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + let obj = getCityActivityObj(); + + const dicCity = gameData.cityActivity.get(cityId); + + let gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp); + if(gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); + + let statusResult = getGuildActivityStatus(this.aid); + if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + // TODO 测试完成后去掉这条判断 + // if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + + let userGuild = await UserGuildModel.getMyGuild(roleId, 'job'); + + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid); + if(!guildActivityRec) return resResult(STATUS.INTERNAL_ERR); + + let { code: sourceCode } = guildActivityRec; + + let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); + if(costGold) { + let goldObj = getGoldObject(GUILDACTIVITY.CITYACTIVITY_CD_COST); + const costRes = await handleCost(roleId, sid, [goldObj]); + if (!costRes) { + return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + } + } else { + if(myGuildActivityRec.challengeTime > nowSeconds()) { + return resResult(STATUS.CHALLENGE_TIME_NOT_REACH); + } + } + myGuildActivityRec = await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); + + let { code } = myGuildActivityRec; + + // 更新公会参与的玩家 + obj.pushMembers(guildCode, roleId, userGuild.job); + + // // 返回当前军团总军功 + let guildScore = await getRankScore(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, guildCode); + + const dbCities = await GuildActivityCityModel.getAllCities(serverId); + let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity.preCity, dbCities); + + return resResult(STATUS.SUCCESS, { + code, + cityId, + cityStatus, + ...statusResult, + gateHp, + guildScore, + myScore: 0 + }); } // 上报城门受到伤害 - async hitGate(msg: {}, session: BackendSession) { + async hitGate(msg: { cityId: number, code: string, damage: number, hid: number, round: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + let { cityId, code, damage, hid, round } = msg; + if(!damage || damage < 0) return resResult(STATUS.WRONG_PARMS); + + const dicCity = gameData.cityActivity.get(cityId); + let obj = getCityActivityObj(); + let gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp); + if(gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); + + let statusResult = getGuildActivityStatus(this.aid); + if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + // TODO 测试完成后去掉这条判断 + // if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + + let pushResult = await UserGuildActivityRecModel.pushCityRecord(code, { round, hid, damage }); + if(!pushResult) return resResult(STATUS.WRONG_PARMS); + + gateHp = obj.getGateHpAndInc(serverId, cityId, -1 * damage); + if(gateHp <= 0) { + // TODO 推送 停止活动并结算奖励 + } + // 推送 城门血量 + let chatSid = await getCityChannelSid(cityId); + pinus.app.rpc.chat.guildRemote.pushCityGateHp.toServer(chatSid, cityId, gateHp); + + // 更新redis数据 + let role = await RoleModel.findByRoleId(roleId); + let { lv, vLv, head, frame, spine, title } = role; + let userParam = new RankParam(roleName, lv, vLv, head, frame, spine, title); + let myScore = await setGuildActivityRank(REDIS_KEY.USER_CITY_ACTIVITY, guildCode, serverId, roleId, damage, Date.now(), userParam); + + let guild = await GuildModel.findByCode(guildCode, serverId); + let leader = guild.leader; + let params = new GuildRankParam(guild.icon, guild.name, guild.lv, leader); + let guildScore = await setRank(REDIS_KEY.GATE_ACTIVITY, serverId, guild.code, damage, Date.now(), params, true); + + return resResult(STATUS.SUCCESS, { + code, + ...statusResult, + guildScore, + myScore, + gateHp + }) } // 结束挑战 - async battleEnd(msg: {}, session: BackendSession) { + async battleEnd(msg: { cityId: number, code: string, isSuccess: boolean }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + let { cityId, code, isSuccess } = msg; + let obj = getCityActivityObj(); + + let statusResult = getGuildActivityStatus(this.aid); + if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let dicCity = gameData.cityActivity.get(cityId); + if(!dicCity) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 更新userGuildActivityRecord + let challengeTime = getBeforeMinuteSeconds(-1 * GUILDACTIVITY.CITYACTIVITY_CD_COST); + let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true, cityId, challengeTime }); + if(!myGuildActivityRec) return resResult(STATUS.INTERNAL_ERR); + + // 发放活跃 + await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 + // 返回当前军团总军功 + let guildScore = await getRankScore(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, guildCode); + let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_CITY_ACTIVITY, guildCode), serverId, roleId, true); + let gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp); + + return resResult(STATUS.SUCCESS, { + isSuccess, + code, + ...statusResult, + guildScore, + myScore, + gateHp, + challengeTime: myGuildActivityRec.challengeTime + }); } } \ No newline at end of file diff --git a/game-server/app/servers/guild/handler/gateActivityHandler.ts b/game-server/app/servers/guild/handler/gateActivityHandler.ts index d61dfe05f..ebab88a80 100644 --- a/game-server/app/servers/guild/handler/gateActivityHandler.ts +++ b/game-server/app/servers/guild/handler/gateActivityHandler.ts @@ -1,13 +1,12 @@ import { Application, BackendSession, ChannelService, pinus } from "pinus"; -import { setMedianCe, getMedianCe, getGuildActivityStatus, getRecordScore, getGuildActivityObj, getGuildActivityRank, sendSingleGuildGateActEndMsg, sendGuildActEndMsg, participants } from "../../../services/guildActivityService"; +import { getMedianCe, getGuildActivityStatus, getRecordScore, getGateActivityObj, sendSingleGuildGateActEndMsg, sendGuildActEndMsg, participants, getGateActivityRank } from "../../../services/guildActivityService"; import { resResult } from "../../../pubUtils/util"; import { STATUS, GUILD_ACTIVITY_TYPE, GUILD_POINT_WAYS, ENEMIES_TYPE, GET_POINT_WAYS } from "../../../consts"; import { GameModel } from "../../../db/Game"; import { ServerlistModel } from "../../../db/Serverlist"; -import { UserGuildActivityRecModel, Record } from "../../../db/UserGuildActivityRec"; +import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; -import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; import { RoleModel, RoleType } from "../../../db/Role"; import { GuildModel } from "../../../db/Guild"; import { RankParam, GuildRankParam } from "../../../domain/rank"; @@ -49,7 +48,7 @@ export class GateActivityHandler { let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); let { challengeCnt } = myGuildActivityRec; - let ranks = await getGuildActivityRank(guildCode, serverId, roleId, roleName); + let ranks = await getGateActivityRank(guildCode, serverId, roleId, roleName); return resResult(STATUS.SUCCESS, { ...statusResult, @@ -68,7 +67,7 @@ export class GateActivityHandler { const serverId = session.get('serverId'); const guildCode = session.get('guildCode'); if(!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - let obj = getGuildActivityObj(this.aid); + let obj = getGateActivityObj(); let gateHp = obj.getGateHpAndInc(guildCode); if(gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); @@ -88,7 +87,7 @@ export class GateActivityHandler { if(myGuildActivityRec.challengeCnt > 0) { return resResult(STATUS.CHALLENGE_CNT_NOT_ENOUGH); } - await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); + myGuildActivityRec = await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); let { code, challengeCnt } = myGuildActivityRec; // 更新公会参与的玩家 @@ -119,7 +118,7 @@ export class GateActivityHandler { let serverId = session.get('serverId'); let { code, record } = msg; - let obj = getGuildActivityObj(this.aid); + let obj = getGateActivityObj(); let statusResult = getGuildActivityStatus(this.aid); if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); @@ -166,7 +165,7 @@ export class GateActivityHandler { let serverId = session.get('serverId'); let { code, damage } = msg; - let obj = getGuildActivityObj(this.aid); + let obj = getGateActivityObj(); let gateHp = obj.getGateHpAndInc(guildCode); if(gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); @@ -182,7 +181,7 @@ export class GateActivityHandler { } // 推送 城门血量 let chatSid = await getGuildChannelSid(guildCode); - pinus.app.rpc.chat.guildRemote.pushGateHp.toServer(chatSid, guildCode, { gateHp }); + pinus.app.rpc.chat.guildRemote.pushGateHp.toServer(chatSid, guildCode, gateHp); // 返回当前军团总军功 let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); @@ -205,7 +204,7 @@ export class GateActivityHandler { let serverId = session.get('serverId'); let { code, isSuccess } = msg; - let obj = getGuildActivityObj(this.aid); + let obj = getGateActivityObj(); let statusResult = getGuildActivityStatus(this.aid); if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); @@ -280,7 +279,7 @@ export class GateActivityHandler { let guildCode = session.get('guildCode'); console.log(guildCode); let serverId = session.get('serverId'); - let res = getGuildActivityObj(this.aid).getObj(guildCode, serverId); + let res = getGateActivityObj().getObj(guildCode, serverId); return resResult(STATUS.SUCCESS, res) } diff --git a/game-server/app/services/chatChannelService.ts b/game-server/app/services/chatChannelService.ts index ade3eeaf2..618399f30 100644 --- a/game-server/app/services/chatChannelService.ts +++ b/game-server/app/services/chatChannelService.ts @@ -41,6 +41,11 @@ export async function addRoleToGuildChannel(roleId: string, sid: string, guildCo await addRoleToChannel(roomId, roleId, sid); } +export async function addRoleToCityChannel(roleId: string, sid: string, cityId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, cityId); + 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); @@ -56,6 +61,12 @@ export async function leaveWorldChannel(roleId: string, sid: string, serverId: n await leaveChannel(roomId, roleId, sid); } +export async function leaveCityChannel(roleId: string, sid: string, cityId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, cityId); + await leaveChannel(roomId, roleId, sid); +} + + export async function leaveGuildChannel(roleId: string, sid: string) { const { guildCode } = await RoleModel.findByRoleId(roleId, 'guildCode'); if (!guildCode) return; @@ -74,3 +85,9 @@ export async function getGuildChannelSid(guildCode: string) { const channelSid = await channelServer(roomId); return channelSid; } + +export async function getCityChannelSid(cityId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, cityId); + const channelSid = await channelServer(roomId); + return channelSid; +} \ No newline at end of file diff --git a/game-server/app/services/guildActivityService.ts b/game-server/app/services/guildActivityService.ts index 237e20157..913300dd8 100644 --- a/game-server/app/services/guildActivityService.ts +++ b/game-server/app/services/guildActivityService.ts @@ -2,14 +2,14 @@ import { ServerlistModel } from "../db/Serverlist"; import { RoleModel } from "../db/Role"; import { reduceCe } from "../pubUtils/util"; import { GUILDACTIVITY } from "../pubUtils/dicParam"; -import { gameData, getGuildAuctionRewards, getTodayGuildActivity } from "../pubUtils/data"; +import { gameData, getGuildAuctionRewards } from "../pubUtils/data"; import { getCurHourPoint, getCutDay, nowSeconds } from "../pubUtils/timeUtil"; -import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, AUCTION_SOURCE, MAIL_TYPE } from "../consts"; +import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, AUCTION_SOURCE, MAIL_TYPE, CITY_STATUS } from "../consts"; import { Record, UserGuildActivityRecModel } from "../db/UserGuildActivityRec"; -import { GateMembersRec, GateActivityObject } from "../domain/battleField/guildActivity"; +import { GateMembersRec, GateActivityObject, CityActivityObject, CityParam } from "../domain/battleField/guildActivity"; import { DicGuildActivity } from "../pubUtils/dictionary/DicGuildActivity"; -import { getUnionRank, getRank, getGuildKeyName, getMyUnionRank, getRankScore } from "./redisService"; -import Guild, { GuildModel } from "../db/Guild"; +import { getUnionRank, getRank, getGuildKeyName, getMyUnionRank, getRankScore, getCityKeyName } from "./redisService"; +import { GuildModel } from "../db/Guild"; import { SimpleGuildRankParam, SimpleRoleRankParam } from "../domain/rank"; import { getGuildChannelSid, getWorldChannelSid } from "./chatChannelService"; import { pinus } from "pinus"; @@ -18,15 +18,22 @@ import { uniq } from 'underscore' import { genAuction } from "./auctionService"; import { sendMail } from "./mailService"; import { getHonourObject } from '../pubUtils/itemUtils'; +import { GuildActivityCityType } from "../db/GuildActivityCity"; let gateActivityObj: GateActivityObject; -export function getGuildActivityObj(aid: number) { - if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - if(!gateActivityObj) { - gateActivityObj = new GateActivityObject() - } - return gateActivityObj; +let cityActivityObj: CityActivityObject; +export function getGateActivityObj() { + if(!gateActivityObj) { + gateActivityObj = new GateActivityObject(); } + return gateActivityObj; +} + +export function getCityActivityObj() { + if(!cityActivityObj) { + cityActivityObj = new CityActivityObject(); + } + return cityActivityObj } /** @@ -137,6 +144,20 @@ export function getRecordScore(aid: number, record: { round: number, dataId: num return { score: sum, newRecords, memberRecord } } +export async function getGateActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) { + let guildKey = REDIS_KEY.GATE_ACTIVITY; + let memberKey = getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode); + let rec = await getGuildActivityRank(guildKey, memberKey, guildCode, serverId, roleId, roleName); + return rec; +} + +export async function getCityActivityRank(guildCode: string, serverId: number, cityId: number, roleId?: string, roleName?: string) { + let guildKey = getCityKeyName(REDIS_KEY.USER_CITY_ACTIVITY, cityId); + let memberKey = getGuildKeyName(REDIS_KEY.USER_CITY_ACTIVITY, guildCode); + let rec = await getGuildActivityRank(guildKey, memberKey, guildCode, serverId, roleId, roleName); + return rec; +} + /** * 获得军团活动排行榜 * @param guildCode @@ -144,9 +165,9 @@ export function getRecordScore(aid: number, record: { round: number, dataId: num * @param roleId * @param roleName */ -export async function getGuildActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) { +export async function getGuildActivityRank(guildKey: string, memberKey: string, guildCode: string, serverId: number, roleId?: string, roleName?: string) { - let guildRankResult = await getUnionRank(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); + let guildRankResult = await getUnionRank(guildKey, serverId, guildCode); let guildRank = new Array(); for(let { rank, code, name, num } of guildRankResult.ranks) { let param = new SimpleGuildRankParam(rank, code, name, num); @@ -161,7 +182,7 @@ export async function getGuildActivityRank(guildCode: string, serverId: number, myGuildRank = new SimpleGuildRankParam(0, guildCode, guild.name, 0); } - let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, roleId); + let memberRankResult = await getRank(memberKey, serverId, roleId); let memberRank = new Array(); for(let { rank, roleId, roleName, num } of memberRankResult.ranks) { let param = new SimpleRoleRankParam(rank, roleId, roleName, num); @@ -185,14 +206,16 @@ export async function getGuildActivityRank(guildCode: string, serverId: number, * @param aid 活动类型 */ export async function sendAllGuildRanks(aid: number) { - let obj = getGuildActivityObj(aid); - let guilds = obj.getGuilds(); - for(let [ serverId, guildCodes ] of guilds) { - // TODO 不需要每个军团都排序一次 - for(let guildCode of guildCodes) { - let ranks = await getGuildActivityRank(guildCode, serverId); - let chatSid = await getGuildChannelSid(guildCode); - pinus.app.rpc.chat.guildRemote.pushRank.toServer(chatSid, guildCode, ranks); + if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + let obj = getGateActivityObj(); + let guilds = obj.getGuilds(); + for(let [ serverId, guildCodes ] of guilds) { + // TODO 不需要每个军团都排序一次 + for(let guildCode of guildCodes) { + let ranks = await getGateActivityRank(guildCode, serverId); + let chatSid = await getGuildChannelSid(guildCode); + pinus.app.rpc.chat.guildRemote.pushRank.toServer(chatSid, guildCode, ranks); + } } } } @@ -202,7 +225,7 @@ export async function sendAllGuildRanks(aid: number) { * @param aid 活动类型 */ export async function sendGuildActEndMsg(aid: number) { - let obj = getGuildActivityObj(aid); + let obj = getGateActivityObj(); let guilds = obj.getGuilds(); for(let [ serverId, guildCodes ] of guilds) { let chatSid = await getWorldChannelSid(serverId); @@ -232,7 +255,7 @@ export async function sendSingleGuildGateActEndMsg(guildCode: string, serverId: * @param serverId */ export async function gateActivitySettleReward(guildCode: string, serverId: number) { - let obj = getGuildActivityObj(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + let obj = getGateActivityObj(); let { gateHp, members } = obj.getObj(guildCode, serverId); members = uniq(members, cur => cur.roleId); @@ -277,4 +300,54 @@ export async function participants(guildCode: string, sourceType: number, source if(!rec) return []; return rec.members||[]; +} + +export function getCities(guildCode: string, dbCities: GuildActivityCityType[]) { + + let cities = new Array(); + for(let [ cityId, dic ] of gameData.cityActivity) { + let param = new CityParam(cityId); + let curCity = dbCities.find(cur => cur.cityId == cityId); + + if(curCity) { + param.guardGuildCode = curCity.guardGuildCode; + param.guardGuildName = curCity.guardGuildName; + param.declareCount = curCity.declareCount; + } + + param.status = getCityStatus(guildCode, cityId, dic.preCity, dbCities); + cities.push(param); + } + return cities +} + + +/** + * 诸侯混战 获取城池状态 + * @param guildCode + * @param cityId + * @param preCity + * @param dbCities + */ +export function getCityStatus(guildCode: string, cityId: number, preCity: number[], dbCities: GuildActivityCityType[]) { + let status = CITY_STATUS.NOT_OPEN; + if(preCity && preCity.length) { + let hasGuardCity = dbCities.find(cur => { + return preCity.includes(cur.cityId) && cur.guardGuildCode == guildCode; + }); + if(!!hasGuardCity) { + status = CITY_STATUS.CAN_DECLARE; + } + } else { + status = CITY_STATUS.CAN_DECLARE; + } + let curCity = dbCities.find(cur => cur.cityId == cityId); + if(curCity) { + if(curCity.guardGuildCode == guildCode) { + status = CITY_STATUS.GUARD; + } else if (curCity.declareGuilds.includes(guildCode)) { + status = CITY_STATUS.DECLARED; + } + } + return status; } \ No newline at end of file diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 1589ec2b4..c61d8efee 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -182,7 +182,8 @@ export async function getRank(key: string, serverId: number, roleId: string, lim let ranks = [], myRank = null; const rankFromDb = await redisClient().zrevrangebyscoreAsync(getKeyName(key, serverId), '+inf', '-inf', "WITHSCORES", "LIMIT", 0, limit); - let infoKey = REDIS_RANK_TO_INFO.get(key)||REDIS_KEY.USER_INFO; + let _key = key.split(':')[0]; + let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; for(let ii = 0; ii < rankFromDb.length; ii+=2) { const _roleId = rankFromDb[ii]; @@ -604,7 +605,8 @@ export async function getUnionRank(key: string, serverId: number, roleId: string let unionKey = await generateUnionRank(key, serverId); const rankFromDb = await redisClient().zrevrangebyscoreAsync(unionKey, '+inf', '-inf', "WITHSCORES", "LIMIT", 0, limit); - let infoKey = REDIS_RANK_TO_INFO.get(key)||REDIS_KEY.USER_INFO; + let _key = key.split(':')[0]; + let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; for(let ii = 0; ii < rankFromDb.length; ii+=2) { const _roleId = rankFromDb[ii]; @@ -661,6 +663,10 @@ export function getGuildKeyName(key: string, guildCode: string) { return `${key}:${guildCode}`; } +export function getCityKeyName(key: string, cityId: number) { + return `${key}:${cityId}`; +} + /** * debug接口使用,直接删除排行榜数据 * @param params serverId => guildCodes @@ -676,4 +682,5 @@ export async function delGuildActivityRank(params: Map) { } } } + /**************** 军团活动排行end */ \ No newline at end of file diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index b5444141a..319c5791a 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -20,7 +20,7 @@ import { STATUS } from '../consts/statusCode'; import { getMailContent, sendMail } from './mailService'; import { reportOnline } from '../pubUtils/httpUtil'; import User, { UserModel } from '../db/User'; -import { getGuildActivityByDic, getGuildActivityRank, setMedianCe } from './guildActivityService'; +import { getGuildActivityByDic, setMedianCe } from './guildActivityService'; import { sendUngotDividend, startGuildAuction, startWorldAuction, stopAuction } from './auctionService'; import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity'; const PER_SECOND = 1 * 1000; diff --git a/shared/consts/constModules/chatConst.ts b/shared/consts/constModules/chatConst.ts index 0ea799aeb..a9f94a896 100644 --- a/shared/consts/constModules/chatConst.ts +++ b/shared/consts/constModules/chatConst.ts @@ -20,6 +20,7 @@ export const CHANNEL_PREFIX = { WORLD: 'world', GUILD: 'guild', TEAM: 'com_btl_team', + CITY: 'city', // 军团活动,诸侯混战,按城池分channel } // 消息来源 diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 6043ae520..c832c5ea4 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -232,8 +232,11 @@ export const REDIS_KEY = { DB_GAME: 'db_game', // 服务器列表 ONLINE_USERS: 'onlineUsers', // 在线用户情况 CHANNEL_SERVERS: 'chat:channelServers', // 渠道对应的 chat 服务器 Id, - USER_GATE_ACTIVITY: 'usrGateAct', - GATE_ACTIVITY: 'gateAct', + USER_GATE_ACTIVITY: 'usrGateAct', // 蛮夷入侵玩家排行 + GATE_ACTIVITY: 'gateAct', // 蛮夷入侵军团排行 + USER_CITY_ACTIVITY: 'usrCityAct', // 诸侯混战玩家排行 + CITY_ACTIVITY: 'cityAct', // 诸侯混战军团排行 + } // 各排行榜对应hash的key diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 5b5a778d8..666d8d16a 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -34,6 +34,7 @@ export const STATUS = { BATTLE_HERO_NOT_FOUND: { code: 20006, simStr: '使用的武将不存在' }, BATTLE_CONSUMES_NOT_ENOUGH: { code: 20007, simStr: '道具不足' }, BATTLE_END_WRONG_TYPE: { code: 20008, simStr: '此类型无法使用通用结算' }, + BATTLE_GOLD_NOT_ENOUGH: { code: 20009, simStr: '元宝不足' }, // 主线 20100 - 20199 BATTLE_INFO_VALIDATE_ERR: { code: 20101, simStr: '关卡信息不同' }, @@ -202,6 +203,8 @@ export const STATUS = { GUILD_ACTIVITY_NOT_OPEN: { code: 21100, simStr: '活动未开放' }, GATE_HP_IS_ZERO: { code: 21101, simStr: '城门已被击破' }, CHALLENGE_CNT_NOT_ENOUGH: { code: 21102, simStr: '挑战次数不足' }, + HAS_DECLARED: { code: 21103, simStr: '已宣战过' }, + CHALLENGE_TIME_NOT_REACH: { code: 21104, simStr: '挑战冷却中' }, // 通用 30000 - 30099 DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' }, diff --git a/shared/db/GuildActivityCity.ts b/shared/db/GuildActivityCity.ts index 0bc19329b..9fe04b63c 100644 --- a/shared/db/GuildActivityCity.ts +++ b/shared/db/GuildActivityCity.ts @@ -32,11 +32,20 @@ export default class GuildActivityCity extends BaseModel { return rec; } + // 检查是否宣战过 + public static async checkDeclartion(serverId: number, guildCode: string) { + let today = getTodayZeroDate(); + let rec: GuildActivityCityType = await GuildActivityCityModel.findOne( + { serverId, createdAt: { $gte: today }, $in: { declareGuilds: [guildCode]}}).lean(); + + return rec; + } + // 每天宣战一次 public static async declare(serverId: number, cityId: number, guildCode: string) { let today = getTodayZeroDate(); let rec: GuildActivityCityType = await GuildActivityCityModel.findOneAndUpdate( - { serverId, cityId, createdAt: { $gte: today }, declareGuilds: { $nin: [guildCode] }}, + { serverId, cityId, createdAt: { $gte: today } }, { $setOnInsert: { cityId }, $push: { declareGuilds: guildCode }, $inc: {declareCount: 1 } }, {new: true, upsert: true}).lean(); diff --git a/shared/db/UserGuildActivityRec.ts b/shared/db/UserGuildActivityRec.ts index 846e811c9..10907f647 100644 --- a/shared/db/UserGuildActivityRec.ts +++ b/shared/db/UserGuildActivityRec.ts @@ -18,6 +18,17 @@ export class Record { } +export class DamageRecord { + @prop({ required: true }) + round: number; // 第几回合 + + @prop({ required: true }) + hid: number; // 造成伤害的武将 + + @prop({ required: true }) + damage: number; // 伤害 +} + @index({ code: 1 }) export default class UserGuildActivityRec extends BaseModel { @@ -54,17 +65,26 @@ export default class UserGuildActivityRec extends BaseModel { @prop({ required: true, default: 0 }) challengeCnt: number; // 向上累加的挑战次数 - // 南蛮入侵字段 @prop({ required: true, type: Number }) - heroes: number[]; // 使用的武将 + heroes: number[]; // 南蛮&诸侯混战 使用的武将 @prop({ required: true }) - score: number; // 个人总军功 + score: number; // 个人总军功/个人总伤害 + // 南蛮入侵字段 @prop({ required: true, type: Record, _id: false }) record: Record[]; // 个人总军功 + // 诸侯混战字段 + @prop({ required: true, default: 0 }) + challengeTime: number; // cd结束时间 + @prop({ required: true, type: DamageRecord, _id: false }) + damageRecord: DamageRecord[]; // 城门伤害记录 + @prop({ required: true, default: 0 }) + cityId: number; // 挑战城池 + + // 每天一条记录 public static async getRecord(roleId: string, roleName: string, guildCode: string, serverId: number, sourceCode: string, aid: number) { let today = getTodayZeroDate(); @@ -80,6 +100,14 @@ export default class UserGuildActivityRec extends BaseModel { return rec; } + + public static async findByRoleId(roleId: string, aid: number) { + let today = getTodayZeroDate(); + let rec: UserGuildActivityRecType = await UserGuildActivityRecModel.findOne({ roleId, aid, createdAt: { $gte: today }}).lean(); + + return rec; + } + public static async incChallengeCnt(code: string, heroes: number[], inc: number = 1 ) { let rec = await UserGuildActivityRecModel.findOneAndUpdate( { code}, { $push: { heroes: { $each: heroes}}, $inc: { challengeCnt: inc }}, {new: true}).lean(); return rec; @@ -94,6 +122,15 @@ export default class UserGuildActivityRec extends BaseModel { return rec; } + public static async pushCityRecord(code: string, damageRecord: DamageRecord) { + let rec: UserGuildActivityRecType = await UserGuildActivityRecModel.findOneAndUpdate( + { code }, + { $push: { damageRecord }}, + { new: true } + ).lean(); + return rec; + } + public static async updateInfo(code: string, update: UserGuildActivityRecUpdateParam) { let rec: UserGuildActivityRecType = await UserGuildActivityRecModel.findOneAndUpdate({ code }, { $set: update }, { new: true }).lean(); return rec; diff --git a/shared/domain/battleField/guildActivity.ts b/shared/domain/battleField/guildActivity.ts index 733529211..bd92ab234 100644 --- a/shared/domain/battleField/guildActivity.ts +++ b/shared/domain/battleField/guildActivity.ts @@ -16,7 +16,7 @@ export class GateMembersRec { export class GateActivityObject { private gateHp: Map = new Map(); // 城门血条,每个军团有一条血条 guildCode => hp - private members: Map> = new Map(); // 每个军团参与的成员 guildCode => [roleId] + private members: Map> = new Map(); // 每个军团参与的成员 guildCode => [{roleId, job}] private membersRecord: Map = new Map(); // 每个成员的回合数和敌军数,防刷 recCode => GateMembersRec private guilds: Map = new Map(); // 参加的所有军团 server => [guildCode] @@ -89,6 +89,73 @@ export class GateActivityObject { } } +// 军团诸侯混战等数据 +export class CityActivityObject { + private gateHp: Map = new Map(); // 城门血条,每个cityId有一条血条 serverId&cityId => gateHp + private members: Map> = new Map(); // 每个军团参与的成员 guildCode => [{roleId, job}] + private cities: Map = new Map(); // 各个城池参与的军团 serverId&cityId => [guildCode] + private guilds: Map = new Map(); // 军团所在的城池 guildCode => cityId + private historyCity: Map = new Map(); // 获取自己打开过的城池的页面 roleId => cityId + + private getKey(serverId: number, cityId: number) { + return `${serverId}_${cityId}`; + } + + public getObj( serverId: number, cityId: number, guildCode: string) { + let key = this.getKey(serverId, cityId); + return { + gateHp: this.gateHp.get(key), + members: this.members.get(guildCode), + city: this.cities.get(key), + guild: this.guilds.get(guildCode) + } + } + + public getGateHpAndInc(serverId: number, cityId: number, maxHp: number, inc: number = 0) { + let key = this.getKey(serverId, cityId); + let gateHp = this.gateHp.get(key); + if(!this.gateHp.has(key)) { + gateHp = maxHp; + } + if(inc != 0) { + gateHp += inc; + this.gateHp.set(key, gateHp); + } + if(gateHp <= 0) gateHp = 0; + return gateHp + } + + public getHistoryCity(roleId: string) { + return this.historyCity.get(roleId) + } + + public setHistoryCity(roleId: string, cityId: number) { + return this.historyCity.set(roleId, cityId); + } + + + public pushMembers(guildCode: string, roleId: string, job: number) { + + if(this.members.has(guildCode)) { + this.members.get(guildCode).push({ roleId, job }); + } else { + let arr = new Array(); + arr.push(roleId); + this.members.set(guildCode, [{ roleId, job }]); + } + } + + public pushGuild(guildCode: string, serverId: number, cityId: number) { + let key = this.getKey(serverId, cityId); + if(!this.cities.has(key)) { + this.cities.set(key, [guildCode]); + } else { + this.cities.get(key).push(guildCode); + } + this.guilds.set(guildCode, cityId); + } +} + export interface GuildGateRankParam { guildRank: SimpleGuildRankParam[], myGuildRank: SimpleGuildRankParam, diff --git a/shared/pubUtils/timeUtil.ts b/shared/pubUtils/timeUtil.ts index 29e662d05..8a695e34d 100644 --- a/shared/pubUtils/timeUtil.ts +++ b/shared/pubUtils/timeUtil.ts @@ -2,6 +2,7 @@ import { TIME_FORMAT } from '../consts'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; +const PER_MINUTE = 60; const PER_HOUR = 60 * 60; export function getSeconds(time: Date) { @@ -47,6 +48,10 @@ export function getBeforeHourSeconds(hour: number) { return time; } +export function getBeforeMinuteSeconds(minute: number) { + let time = nowSeconds() - minute * PER_MINUTE; + return time; +} export function getCurWeekDate(day: number, hour: number) { return getWeekDate(new Date(), day, hour);