diff --git a/game-server/app/servers/battle/handler/guildHandler.ts b/game-server/app/servers/battle/handler/guildHandler.ts index d2d97f4f8..15085c45b 100644 --- a/game-server/app/servers/battle/handler/guildHandler.ts +++ b/game-server/app/servers/battle/handler/guildHandler.ts @@ -1,6 +1,6 @@ import { Application, BackendSession, pinus, ChannelService } from 'pinus'; import { resResult, getRandEelm, reduceCe, getRefTime } from '../../../pubUtils/util'; -import { STATUS, GUILD_OPERATE, GUILD_AUTH, GUILD_JOB, GUILD_APPLY_TYPE, GUILD_STRUCTURE, GUILD_REC_TYPE, GUILD_STRUCTURE_NAME, MAIL_TYPE } from '../../../consts'; +import { STATUS, GUILD_OPERATE, GUILD_AUTH, GUILD_JOB, GUILD_APPLY_TYPE, GUILD_STRUCTURE, GUILD_REC_TYPE, GUILD_STRUCTURE_NAME, MAIL_TYPE, REDIS_KEY } from '../../../consts'; import { UserGuildModel } from '../../../db/UserGuild'; import { checkAuth, joinGuild, getGuildWithRefActive, getUserGuildWithRefActive, addActive, message, settleGuildWeekly } from '../../../services/guildService'; import { GuildModel, GuildType } from '../../../db/Guild'; @@ -8,12 +8,13 @@ import { RoleModel, RoleType } from '../../../db/Role'; import { ARMY } from '../../../pubUtils/dicParam'; import { handleCost, addItems } from '../../../services/rewardService'; import { getGoldObject } from '../../../pubUtils/itemUtils'; -import { nowSeconds, getBeforeDaySeconds } from '../../../pubUtils/timeUtil'; -import { GuildListInfo } from '../../../pubUtils/interface'; +import { nowSeconds, getBeforeDaySeconds, getSeconds } from '../../../pubUtils/timeUtil'; +import { GuildListInfo, GuildRankParam, GuildLeader } from '../../../pubUtils/interface'; import { UserGuildApplyModel } from '../../../db/UserGuildApply'; import { hasStructureConsume, getStructureConsume, gameData } from '../../../pubUtils/data'; import { GuildRecModel } from '../../../db/GuildRec'; import { sendMail } from '../../../services/mailService'; +import { existsRank, initSingleRankWithServer, getRank, setRank, redisUserInfoUpdate, redisUserInfoAdd, removeFromRank, getMyRank } from '../../../services/redisService'; export default function (app: Application) { return new GuildHandler(app); @@ -61,8 +62,12 @@ export class GuildHandler { await RoleModel.joinGuild(roleId); await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 - // TODO 加入排行 - const rank = 0; + // 加入排行 + let params = new GuildRankParam(guild.icon, guild.name, guild.lv, guild.leader); + await setRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code, 0, Date.now(), params); + + let rank = await getMyRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code); + // 加入channel message.enterChannel(guild.code, roleId, sid); @@ -114,6 +119,8 @@ export class GuildHandler { const select = ['code', 'name', 'notice', 'introduce', 'ceLimit', 'isAuto', 'icon']; const guild = await GuildModel.updateInfo(code, { name, notice, introduce, ceLimit, isAuto }, {}, select.join(' ')); message.updateInfo(code, { name, notice, introduce, ceLimit, isAuto }); + + await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{ field: 'name', value: name }]); // 返回 return resResult(STATUS.SUCCESS, { ...guild }); @@ -192,7 +199,8 @@ export class GuildHandler { let updateObject = {}; if(auth == GUILD_AUTH.LEADER) { // 转让团长 updateObject['leader'] = role._id; - await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.MEMBER }); // 自己降权限 + await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.MEMBER }, {}); // 自己降权限 + await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(role) } ]); } guild = await GuildModel.updateInfo(code, updateObject, { managerCnt: managerCntInc }, 'managerCnt code name'); // 如果有转让团长设置leader @@ -249,8 +257,8 @@ export class GuildHandler { // 打开公会页面,加入channel message.enterChannel(userGuild.guildCode, roleId, sid); - // TODO 获取排行榜 - const rank = 0; + // 获取排行榜 + const rank = await getMyRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code); // 返回 const result = { hasGuild: true, ...guild, rank, myInfo: userGuild}; @@ -550,6 +558,7 @@ export class GuildHandler { message.dismiss(code); + await removeFromRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, code); return resResult(STATUS.SUCCESS, { code, status: guild.status }); } @@ -672,6 +681,8 @@ export class GuildHandler { await sendMail(MAIL_TYPE.GUILD_BE_IMPEACH, leaderRoleId, roleName, [guild.name]); await sendMail(MAIL_TYPE.GUILD_BE_SET_LEADER, topUser.roleId, roleName, [guild.name]); + await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(topUser) } ]); + const leader = { ...topUser, ce: reduceCe(topUser.ce) } return resResult(STATUS.SUCCESS, { code, managerCnt: guild.managerCnt, leader @@ -723,6 +734,7 @@ export class GuildHandler { // 修改信息 message.updateInfo(code, { ...result }); + await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{field: 'lv', value: result.lv } ]); // 添加动态 const structureName = GUILD_STRUCTURE_NAME.get(id); @@ -743,7 +755,8 @@ export class GuildHandler { if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); let startTime = getRefTime(new Date(), 0, -3); - const list = await GuildRecModel.getGuildRec(code, startTime.getTime()); + console.log(startTime) + const list = await GuildRecModel.getGuildRec(code, getSeconds(startTime)); return resResult(STATUS.SUCCESS, { list }); } @@ -828,6 +841,29 @@ export class GuildHandler { return resResult(STATUS.SUCCESS, { goods, receivedActive: userGuild.receivedActive }); } + // 查看活跃排行榜 + async getActiveRank(msg: { }, session: BackendSession) { + + let roleId = session.get('roleId'); + let serverId = session.get('serverId') + + const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode'); + if(!myUserGuild) return resResult(STATUS.GUILD_NOT_FOUND); + + const hasRank = await existsRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); + if(!hasRank) await initSingleRankWithServer(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); + + let {ranks, myRank} = await getRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, myUserGuild.guildCode); + if(!myRank) { + let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly'); + let {icon, name, lv, leader, activeWeekly} = guild; + let _leader = leader; + let param = new GuildRankParam(icon, name, lv, _leader); + myRank = {...param, num: activeWeekly, rank: 0}; + } + + return resResult(STATUS.SUCCESS, { ranks, myRank }); + } // debug接口: 添加公会活跃值 async debugAddActive(msg: { code: string, active: number, id: number }, session: BackendSession) { @@ -836,8 +872,8 @@ export class GuildHandler { const serverId = session.get('serverId'); const { code, active, id } = msg; - const result = await addActive(roleId, serverId, id, active); - if(!result) return resResult(STATUS.GUILD_NOT_FOUND); + const result = await addActive(roleId, serverId, id, 1); + if(result.status == 0) return result.resResult; const { guild, userGuild } = result; let { activeDaily, activeWeekly } = guild; diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index c0b349700..ce3f68747 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -15,7 +15,7 @@ import { HeroModel } from '../../../db/Hero'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { BattleRecordModel } from '../../../db/BattleRecord'; import { PvpRecordModel } from '../../../db/PvpRecord'; -import { existsRank, initRank, getRank, setRank, getMyRank } from '../../../services/redisService'; +import { existsRank, getRank, setRank, getMyRank, initSingleRankWithServer } from '../../../services/redisService'; import { handleCost } from '../../../services/rewardService'; import { nowSeconds } from '../../../pubUtils/timeUtil'; import { setPvpSeasonResult, resetPvpWarId, resetPvpSeasonTime } from '../../../services/timeTaskService'; @@ -358,7 +358,7 @@ export class PvpHandler { let serverId = session.get('serverId') const hasRank = await existsRank(REDIS_KEY.PVP_RANK, serverId); - if(!hasRank) await initRank(serverId); + if(!hasRank) await initSingleRankWithServer(REDIS_KEY.PVP_RANK, serverId); let {ranks, myRank} = await getRank(REDIS_KEY.PVP_RANK, 0, roleId); if(!myRank) { diff --git a/game-server/app/servers/battle/handler/towerBattleHandler.ts b/game-server/app/servers/battle/handler/towerBattleHandler.ts index cac466cb8..53605c1e0 100644 --- a/game-server/app/servers/battle/handler/towerBattleHandler.ts +++ b/game-server/app/servers/battle/handler/towerBattleHandler.ts @@ -11,7 +11,7 @@ import { decodeArrayStr, resResult, shouldRefresh, calculateNum, getRefTime, gen import { calcuHangUpReward, checkTaskConditions, checkHangUpSpdUpCnt, createCurTasks, treatTask, getRemainTime, getTasksReward, getTaskStatus, getDoingOrWaitingTasks } from '../../../services/battleService'; import { handleFixedReward, addItems, handleCost } from '../../../services/rewardService'; import { checkBattleHeroes } from '../../../services/normalBattleService'; -import { getRank, setRank, initRank, existsRank } from '../../../services/redisService'; +import { getRank, setRank, existsRank, initSingleRankWithServer } from '../../../services/redisService'; import { RankParam } from '../../../pubUtils/interface'; import { getGoldObject } from '../../../pubUtils/itemUtils'; @@ -317,7 +317,7 @@ export class TowerBattleHandler { let serverId = session.get('serverId') const hasTowerRank = await existsRank(REDIS_KEY.TOWER_RANK, serverId); - if(!hasTowerRank) await initRank(serverId); + if(!hasTowerRank) await initSingleRankWithServer(REDIS_KEY.TOWER_RANK, serverId); let {ranks, myRank} = await getRank(REDIS_KEY.TOWER_RANK, serverId, roleId); if(!myRank) { diff --git a/game-server/app/services/guildService.ts b/game-server/app/services/guildService.ts index db192ecb8..ac276aa39 100644 --- a/game-server/app/services/guildService.ts +++ b/game-server/app/services/guildService.ts @@ -1,7 +1,7 @@ -import { gameData, getGuildActiveWeekReward } from "../pubUtils/data"; +import { gameData, getGuildActiveWeekReward, getGuildActiveByIdAndType } from "../pubUtils/data"; import { GuildModel, GuildType } from "../db/Guild"; import { resResult, shouldRefreshWeek, shouldRefresh } from "../pubUtils/util"; -import { STATUS, GUILD_OPERATE, MAIL_TYPE, GUILD_AUTH, GUILD_JOB } from "../consts"; +import { STATUS, GUILD_OPERATE, MAIL_TYPE, GUILD_AUTH, GUILD_JOB, REDIS_KEY, } from "../consts"; import { RoleModel, RoleType } from "../db/Role"; import { UserGuildModel, UserGuildType } from "../db/UserGuild"; import { UserGuildApplyModel } from "../db/UserGuildApply"; @@ -11,6 +11,8 @@ import { pinus } from "pinus"; import { GuildRecType } from "../db/GuildRec"; import { ARMY } from "../pubUtils/dicParam"; import { sendMail } from "./mailService"; +import { setRank } from "./redisService"; +import { GuildRankParam, GuildLeader } from "../pubUtils/interface"; /** * @description 检查该玩家是否有权限做操作 @@ -90,16 +92,26 @@ export async function getGuildWithRefActive(guildCode: string, serverId: number) * 增加活跃 * @param guildCode 军团唯一code * @param serverId 区 - * @param active 增加的活跃 + * @param id 增加活跃的操作 + * @param type 类型 activePoint内配的type + * @param active debug直接增加的活跃 */ -export async function addActive(roleId: string, serverId: number, id: number, active: number) { +export async function addActive(roleId: string, serverId: number, id: number, type: number, active?: number) { + + let dicActiveWay = gameData.guildActiveWays.get(id); + if(id && !dicActiveWay) { + return { status: 0, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) }; + } + if(!active) { + active = getGuildActiveByIdAndType(id, type); + } let userGuild = await getUserGuildWithRefActive(roleId, 'activeRecord receivedActive activeDaily activeWeekly guildCode'); - if(!userGuild) return false; + if(!userGuild) return { status: 0, resResult: resResult(STATUS.GUILD_NOT_FOUND) }; let guildCode = userGuild.guildCode; let guild = await getGuildWithRefActive(guildCode, serverId); - if(!guild) return false; + if(!guild) return { status: 0, resResult: resResult(STATUS.GUILD_NOT_FOUND) }; let {activeRecord} = userGuild; if(id != 0) { // 用于debug,传0时直接增加活跃 @@ -107,13 +119,22 @@ export async function addActive(roleId: string, serverId: number, id: number, ac if( curActiveRecord ) { curActiveRecord.count ++; } else { - activeRecord.push({id, count: 1}); + curActiveRecord = {id, count: 1}; + activeRecord.push(curActiveRecord); + } + if(curActiveRecord.count > dicActiveWay.count) { // 次数超过时,不增加活跃 + active = 0; } } - userGuild = await UserGuildModel.updateInfo(roleId, { activeRecord }, { activeDaily: active, activeWeekly: active }); + userGuild = await UserGuildModel.updateInfo(roleId, { activeRecord, activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); - guild = await GuildModel.updateInfo(guildCode, { }, { activeDaily: active, activeWeekly: active }); - return { guild, userGuild }; + guild = await GuildModel.updateInfo(guildCode, { activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); + + // 排行榜更新 + let leader = await RoleModel.findById(guild.leader); + let guildRankParam = new GuildRankParam(guild.icon, guild.name, guild.lv, new GuildLeader(leader)); + await setRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code, guild.activeWeekly, guild.activeUpdateTime * 1000, guildRankParam); + return { status: 1, guild, userGuild }; } /** @@ -176,7 +197,7 @@ export async function settleGuildWeekly() { if(otherMemberCnt < rankCnt) break; } } - await UserGuildModel.updateInfo(roleId, { job, activeWeekly: 0 }); + await UserGuildModel.updateInfo(roleId, { job, activeWeekly: 0 }, {}); jobNum += gameData.guildPosition.get(job).activeRatio; members.set(roleId, {job, active}); diff --git a/game-server/app/services/guildTrainService.ts b/game-server/app/services/guildTrainService.ts index ee12342af..8953ed927 100644 --- a/game-server/app/services/guildTrainService.ts +++ b/game-server/app/services/guildTrainService.ts @@ -21,8 +21,9 @@ export async function getUserGuild(roleId: string, serverId: number) { if (trainTime < getHourPoint(REFRESH_HOUR)) { trainCount = ARMY.ARMY_TRAIN_BUYTIMES; buyTrainCount = 0; - userGuild = await UserGuildModel.updateInfo(roleId, {trainCount, trainTime: nowSeconds(), buyTrainCount}); + userGuild = await UserGuildModel.updateInfo(roleId, {trainCount, trainTime: nowSeconds(), buyTrainCount}, {}); } + return userGuild; } @@ -34,7 +35,7 @@ export async function recordUserGuild(roleId: string, code: string) { if (trainTime < getHourPoint(REFRESH_HOUR)) { trainCount = 0; } - userGuild = await UserGuildModel.updateInfo(roleId, {trainCount, trainTime: nowSeconds()}); + userGuild = await UserGuildModel.updateInfo(roleId, {trainCount, trainTime: nowSeconds()}, {}); return userGuild; } diff --git a/game-server/app/services/normalBattleService.ts b/game-server/app/services/normalBattleService.ts index b9b3e902b..6a90a7581 100644 --- a/game-server/app/services/normalBattleService.ts +++ b/game-server/app/services/normalBattleService.ts @@ -6,6 +6,7 @@ import { redisUserInfoUpdate } from './redisService'; import { switchOnFunc } from './funcSwitchService'; import { FUNC_OPT_TYPE } from '../consts'; import { BackendSession } from 'pinus'; +import { REDIS_KEY } from '../consts/consts'; export async function roleLevelup(roleId: string, kingExp: number, session: BackendSession) { let role = await RoleModel.findByRoleId(roleId); @@ -23,7 +24,7 @@ export async function roleLevelup(roleId: string, kingExp: number, session: Back role = await RoleModel.levelup(roleId, newLv, newExp); if(newLv > lv) { // 升级 await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session); - await redisUserInfoUpdate(roleId, [{field: 'lv', value: newLv}]) + await redisUserInfoUpdate(REDIS_KEY.USER_INFO, roleId, [{field: 'lv', value: newLv}]) } let actordata = []; for(let i = lv; i <= newLv; i++) { diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index b238bc43c..2c200785d 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -1,4 +1,4 @@ -import { GOOD_QUALITY } from './../consts'; +import { GOOD_QUALITY, REDIS_RANK_TO_INFO } from './../consts'; import { RoleModel, RoleType } from "../db/Role"; import * as Redis from 'redis'; import {REDIS_KEY} from '../consts' @@ -7,9 +7,9 @@ import { promisifyAll } from 'bluebird'; import { pinus } from 'pinus'; import { PvpDefenseModel } from '../db/PvpDefense'; import { SystemConfigModel } from '../db/SystemConfig'; -import { RankParam } from '../pubUtils/interface'; -import { accessSync } from 'fs'; -import { values } from 'underscore'; +import { RankParam, GuildRankParam, GuildLeader } from '../pubUtils/interface'; +import { GuildModel } from '../db/Guild'; + /** * 在服务重新启动时,将信息存入redis */ @@ -17,28 +17,87 @@ export async function initAllRank() { const client: Redis.RedisClient = pinus.app.get('redis'); const serverList = await GameModel.getAllServerList(); await client.delAsync(REDIS_KEY.USER_INFO); + + await client.delAsync(REDIS_KEY.GUILD_INFO); + await client.delAsync(REDIS_KEY.PVP_RANK); for(let {id} of serverList) { await client.delAsync(getKeyName(REDIS_KEY.TOWER_RANK, id)); + await client.delAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, id)); await initRank(id); } } +/** + * 分服内初始redis排行榜 + * + * @param serverId 服务器 + */ export async function initRank(serverId: number) { // console.log('*****', 'initRank') const client: Redis.RedisClient = pinus.app.get('redis'); await client.expireAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.PVP_RANK, 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.USER_INFO, 30 * 24 * 60 * 60); + await client.expireAsync(REDIS_KEY.GUILD_INFO, 30 * 24 * 60 * 60); + await client.expireAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), 30 * 24 * 60 * 60); + await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, serverId); + await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); - let ranks = await RoleModel.getRank('tower', serverId, ['roleId', 'roleName', 'towerLv', 'lv', 'vLv', 'headHid', 'sHid', 'title', 'updatedAt']); - for(let {towerLv, roleId, roleName, lv, vLv, towerUpTime, headHid, sHid, title} of ranks) { - // console.log(roleId); - await client.zaddAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), encodeScoreWithTime(towerLv, towerUpTime?towerUpTime.getTime():0), roleId); - let rankPram = new RankParam(roleName, lv, vLv, headHid, sHid, title); - await redisUserInfoAdd(roleId, rankPram); +} + +/** + * 初始化某一个排行榜,如定时器内 + * @param key redis内的key + */ +export async function initSingleRank(key: string) { + + const serverList = await GameModel.getAllServerList(); + for(let {id} of serverList) { + await initSingleRankWithServer(key, id); } } +/** + * 初始化某一服内的某一种排行榜 + * @param key redis key + */ +export async function initSingleRankWithServer(key: string, serverId: number) { + + const client: Redis.RedisClient = pinus.app.get('redis'); + await client.delAsync(getKeyName(key, serverId)); + await client.expireAsync(key, 30 * 24 * 60 * 60); + await setRankRedisFromDb(key, serverId); +} + +/** + * 从数据库内获取排行榜存入redis + * @param type 排行榜类型 + * @param serverId 分服 + */ +async function setRankRedisFromDb(type: string, serverId: number) { + const client: Redis.RedisClient = pinus.app.get('redis'); + if(type == REDIS_KEY.TOWER_RANK) { + let ranks = await RoleModel.getRank('tower', serverId, ['roleId', 'roleName', 'towerLv', 'lv', 'vLv', 'headHid', 'sHid', 'title', 'updatedAt']); + for(let {towerLv, roleId, roleName, lv, vLv, towerUpTime, headHid, sHid, title} of ranks) { + // console.log(roleId); + await client.zaddAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), encodeScoreWithTime(towerLv, towerUpTime?towerUpTime.getTime():0), roleId); + let rankPram = new RankParam(roleName, lv, vLv, headHid, sHid, title); + await redisUserInfoAdd(REDIS_KEY.USER_INFO, roleId, rankPram); + } + } else if (type == REDIS_KEY.GUILD_ACTIVE_RANK) { + let ranks = await GuildModel.getRank(serverId); + for(let { code, icon, name, lv, leader, activeWeekly = 0, activeUpdateTime = 0 } of ranks) { + let _leader = leader; + let { roleName, title, sHid, headHid, lv: leaderLv } = _leader; + console.log(activeWeekly, activeUpdateTime * 1000) + await client.zaddAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), encodeScoreWithTime(activeWeekly, activeUpdateTime * 1000 ), code); + let rankParam = new GuildRankParam(icon, name, lv, { roleName, title, sHid, headHid, lv: leaderLv }); + await redisUserInfoAdd(REDIS_KEY.GUILD_INFO, code, rankParam); + } + } + +} + // 排行榜是否存在 export async function existsRank(key: string, serverId: number) { const client: Redis.RedisClient = pinus.app.get('redis'); @@ -55,38 +114,40 @@ export function getKeyName(key: string, serverId?: number) { } // 更新玩家信息 -export async function redisUserInfoUpdate(roleId: string, arr: Array<{field: string, value:(string|number)}>) { +export async function redisUserInfoUpdate(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader)}>) { const client: Redis.RedisClient = pinus.app.get('redis'); - let params = await client.hgetAsync(REDIS_KEY.USER_INFO, roleId); + let params = await client.hgetAsync(key, roleId); if(params) { let obj = JSON.parse(params); for(let {field, value} of arr) { obj[field] = value; } - return await client.hsetAsync(REDIS_KEY.USER_INFO, roleId, JSON.stringify(obj)); + return await client.hsetAsync(key, roleId, JSON.stringify(obj)); } } // 添加玩家信息缓存 -export async function redisUserInfoAdd(roleId: string, params: RankParam) { +export async function redisUserInfoAdd(key: string, roleId: string, params: RankParam|GuildRankParam) { const client: Redis.RedisClient = pinus.app.get('redis'); let value = JSON.stringify(params); - return await client.hsetAsync(REDIS_KEY.USER_INFO, roleId, value); + return await client.hsetAsync(key, roleId, value); } // 更新排行榜, 如pvp这样跨服的,serverId传0 -export async function setRank(key: string, serverId: number, roleId: string, score: number, timestamp: number, params: RankParam, limit = 100) { +export async function setRank(key: string, serverId: number, myId: string, score: number, timestamp: number, params: RankParam|GuildRankParam, limit = 100) { const client: Redis.RedisClient = pinus.app.get('redis'); // 更新分数 const _score = encodeScoreWithTime(score, timestamp); - await client.zaddAsync(getKeyName(key, serverId), _score, roleId); + await client.zaddAsync(getKeyName(key, serverId), _score, myId); // 移除100名以外 await client.zremrangebyrankAsync(getKeyName(key, serverId), limit, 10000); + + let infoKey = REDIS_RANK_TO_INFO.get(key); // 如果没有信息,更新玩家信息 - const hasCurUser = await client.hexistsAsync(REDIS_KEY.USER_INFO, roleId); + const hasCurUser = await client.hexistsAsync(infoKey, myId); if(!hasCurUser) { - await redisUserInfoAdd(roleId, params); + await redisUserInfoAdd(infoKey, myId, params); } return true; } @@ -97,12 +158,20 @@ export async function getRank(key: string, serverId: number, roleId: string) { const client: Redis.RedisClient = pinus.app.get('redis'); let ranks = [], myRank = null; const rankFromDb = await client.zrevrangebyscoreAsync(getKeyName(key, serverId), '+inf', '-inf', "WITHSCORES", "LIMIT", 0, 100); + + let infoKey = REDIS_RANK_TO_INFO.get(key); + for(let ii = 0; ii < rankFromDb.length; ii+=2) { const _roleId = rankFromDb[ii]; const _score = decodeScoreWithTime(rankFromDb[ii + 1]); - const userInfo = await client.hgetAsync(REDIS_KEY.USER_INFO, _roleId); - const _userInfo = JSON.parse(userInfo); - const tmp = {..._userInfo, roleId: _roleId, num: _score, rank: Math.floor(ii/2)+1} + const info = await client.hgetAsync(infoKey, _roleId); + const _userInfo = JSON.parse(info); + const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; + if(infoKey == REDIS_KEY.USER_INFO) { + tmp["roleId"] = _roleId; + } else if(infoKey == REDIS_KEY.GUILD_INFO) { + tmp["code"] = _roleId; + } ranks.push(tmp); if(roleId == _roleId) myRank = tmp; } @@ -138,6 +207,14 @@ function decodeScoreWithTime(num: string): number { return Math.floor(_num/pow); } +// 从排行榜中移除 +export async function removeFromRank(key: string, serverId: number, myId: string) { + const client: Redis.RedisClient = pinus.app.get('redis'); + await client.zremAsync(getKeyName(key, serverId), myId); + + return true; +} + /**************** 寻宝相关 start */ // 把寻宝的玩家信息存入 redis @@ -245,7 +322,7 @@ export async function resetPvpRanks() { const hasCurUser = await client.hexistsAsync(REDIS_KEY.USER_INFO, roleId); if(!hasCurUser) { let rankPram = new RankParam(roleName, lv, vLv, headHid, sHid, title); - await redisUserInfoAdd(roleId, rankPram); + await redisUserInfoAdd(REDIS_KEY.USER_INFO, roleId, rankPram); } } } diff --git a/game-server/config/redis.ts b/game-server/config/redis.ts index 4938cad3b..54f995a34 100644 --- a/game-server/config/redis.ts +++ b/game-server/config/redis.ts @@ -42,6 +42,8 @@ declare module 'redis' { zcardAsync(key: string): Promise; // 移除有序集合中给定的排名区间的所有成员 zremrangebyrankAsync(key: string, start: number, stop: number): Promise; + // 移除有序集中的一个或多个成员 + zremAsync(key: string, member: string): Promise; // 返回有序集中指定成员的排名,从小到大 zrankAsync(key: string, field: string): Promise; // 返回有序集中指定成员的排名,从大到小 diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 7565feb9a..0bbd80e03 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -221,8 +221,17 @@ export const REDIS_KEY = { TOWER_RANK: "towerRank", // 天梯排行榜 COM_TEAM_SEARCH_PRE: 'comTeamSerQ', // 匹配中的玩家,按品质分 PVP_RANK: "pvpRank", // pvp排行榜 + GUILD_INFO: "guildInfo", // 公会信息 + GUILD_ACTIVE_RANK: "guildActiveRank", // 公会周活跃排行榜 } +// 各排行榜对应hash的key +export const REDIS_RANK_TO_INFO = new Map([ + [REDIS_KEY.TOWER_RANK, REDIS_KEY.USER_INFO], + [REDIS_KEY.PVP_RANK, REDIS_KEY.PVP_RANK], + [REDIS_KEY.GUILD_ACTIVE_RANK, REDIS_KEY.GUILD_INFO] +]); + export const FUNC_OPT_TYPE = { LEVEL_UP: 1, BATTLE_END: 2 @@ -310,7 +319,8 @@ export const FILENAME = { DIC_ACTIVE_WEEK_REWARD: 'dic_army_activeWeekReward', DIC_MAIL: 'dic_email_army', DIC_ARMY_TRAIN_JU_DIAN: 'dic_army_trainJuDian', - DIC_ARMY_TRAIN_SOLO_REWARD: 'dic_army_trainSoloReward' + DIC_ARMY_TRAIN_SOLO_REWARD: 'dic_army_trainSoloReward', + DIC_ARMY_ACTIVE_POINT_WAYS: 'dic_army_activePointWays' } diff --git a/shared/db/Guild.ts b/shared/db/Guild.ts index dc2ec25e7..8de08bb94 100644 --- a/shared/db/Guild.ts +++ b/shared/db/Guild.ts @@ -60,6 +60,9 @@ export default class Guild extends BaseModel { @prop({ required: true, default: 0 }) activeWeekly: number; + @prop({ required: true, default: Date.now() }) + activeUpdateTime: number; + @prop({ required: true, default: new Date(), select: false }) refTimeDaily: Date; @@ -90,7 +93,7 @@ export default class Guild extends BaseModel { delete update._id; const code = genCode(6); const result: GuildType = await GuildModel.findOneAndUpdate({ code }, update, { upsert: true, new: true }) - .populate('leader', 'roleId roleName sHid headHid lv loginTime ce', 'Role') + .populate('leader', { roleId: 1, roleName: 1, sHid: 1, headHid: 1, lv: 1, loginTime: 1, ce: 1, title: 1, _id: 0 }, 'Role') .lean(); return result; @@ -113,7 +116,19 @@ export default class Guild extends BaseModel { .sort({ lv: -1, guildCe: -1 }) .limit(GUILD_PER_PAGE).skip((page - 1) * GUILD_PER_PAGE) .select('code icon name lv memberCnt leader ceLimit isAuto') - .populate('leader', 'roleName', 'Role') + .populate('leader', { roleName: 1, _id: 0 }, 'Role') + .lean(); + return guildList; + } + + + public static async getRank(serverId: number, page: number = 1) { + + const guildList: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, serverId }, {_id: 0}) + .sort({ activeWeekly: -1, activeUpdateTime: -1 }) + .limit(100).skip((page - 1) * 100) + .select('code icon name lv leader activeWeekly activeUpdateTime') + .populate('leader', {roleName: 1, title: 1, sHid: 1, headHid: 1, lv: 1, _id: 0}, 'Role') .lean(); return guildList; } @@ -126,7 +141,7 @@ export default class Guild extends BaseModel { public static async findByCode(code: string, serverId: number, select?: string) { const result: GuildType = await GuildModel.findOne({ code, status: GUILD_STATUS.RUNNING, serverId }) .select(select) - .populate('leader', 'roleId roleName sHid headHid lv loginTime ce', 'Role') + .populate('leader', {roleId: 1, roleName: 1, sHid: 1, headHid: 1, lv: 1, loginTime: 1, ce: 1, title: 1, _id: 0}, 'Role') .lean(); return result; } diff --git a/shared/db/UserGuild.ts b/shared/db/UserGuild.ts index 3da33a82d..8004039ee 100644 --- a/shared/db/UserGuild.ts +++ b/shared/db/UserGuild.ts @@ -127,8 +127,9 @@ export default class UserGuild extends BaseModel { return result; } - public static async updateInfo(roleId: string, update: UserGuildUpdateParam, incParam?: { activeDaily?: number, activeWeekly?: number, trainCount?: number }, select?: string) { - const result = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $set: update, $inc: incParam }, { new: true }).select(select).lean(); + public static async updateInfo(roleId: string, update: UserGuildUpdateParam, incParam: { activeDaily?: number, activeWeekly?: number, trainCount?: number }, select?: string) { + console.log(roleId, JSON.stringify(update)) + const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $set: update, $inc: incParam }, { new: true }).select(select).lean(); return result; } diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index 4465266ab..3a9b50136 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -47,6 +47,7 @@ import { dicGuildAuth } from './dictionary/DicGuildAuth'; import { dicCenterBase, dicEquipPriduceBase, dicBossBase, dicTrainBase, dicDonateBase, dicWishPoolBase, dicStoreBase, dicStructureConsume } from "./dictionary/DicStructure"; import { dicGuildActiveDayReward } from './dictionary/DicGuildActiveDayReward'; import { dicGuildActiveWeekReward } from './dictionary/DicGuildActiveWeekReward'; +import { dicGuildActiveWays } from './dictionary/DicGuildActiveWays'; import { dicGuildPosition } from "./dictionary/DicGuildPosition"; import { dicMail } from "./dictionary/DicMail"; import { dicArmyTrainJuDian } from './dictionary/DicArmyTrainJuDian'; @@ -126,7 +127,8 @@ export const gameData = { guildPosition: dicGuildPosition, armyTrainJuDian: dicArmyTrainJuDian, trainSoloReward: dicTrainSoloReward, - mail: dicMail + mail: dicMail, + guildActiveWays: dicGuildActiveWays }; // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 @@ -362,3 +364,9 @@ export function getGuildActiveWeekReward(point: number) { if(result) reward = result.reward; return reward; } + +export function getGuildActiveByIdAndType(id: number, type: number) { + let dicWay = gameData.guildActiveWays.get(id); + if(!dicWay) return 0; + return dicWay.activePoint.get(type.toString()); +} diff --git a/shared/pubUtils/dictionary/DicGuildActiveWays.ts b/shared/pubUtils/dictionary/DicGuildActiveWays.ts new file mode 100644 index 000000000..66b50bda4 --- /dev/null +++ b/shared/pubUtils/dictionary/DicGuildActiveWays.ts @@ -0,0 +1,25 @@ +// 各种操作可以增加的活跃 +import { readJsonFile, decodeIdCntArrayStr } from '../util' +import { FILENAME } from '../../consts' + +export interface DicGuildActiveWays { + + // id + readonly id: number; + // 最大次数 + readonly count: number; + // 奖励 + readonly activePoint: Map; + +} + +const str = readJsonFile(FILENAME.DIC_ARMY_ACTIVE_POINT_WAYS); +let arr = JSON.parse(str); + +export const dicGuildActiveWays = new Map(); + +arr.forEach(o => { + o.activePoint = decodeIdCntArrayStr(o.activePoint, 1); + dicGuildActiveWays.set(o.id, o); +}); +arr = undefined; \ No newline at end of file diff --git a/shared/pubUtils/interface.ts b/shared/pubUtils/interface.ts index 923ce8f15..6cc9349f6 100644 --- a/shared/pubUtils/interface.ts +++ b/shared/pubUtils/interface.ts @@ -122,6 +122,43 @@ export class RankParam { } } +export class GuildRankParam { + icon: number; + name: string; + lv: number; + leader: { + roleName: string; + title: number; + lv: number; + headHid: number; + sHid: number; + } + + constructor(icon: number, name: string, lv: number, leader: {roleName: string, title: number, lv: number, headHid: number, sHid: number}) { + this.icon = icon; + this.name = name; + this.lv = lv; + let _leader = new GuildLeader(leader); + this.leader = _leader; + } +} + +export class GuildLeader { + roleName: string; + title: number; + lv: number; + headHid: number; + sHid: number; + + constructor(leader: {roleName: string, title: number, lv: number, headHid: number, sHid: number}) { + this.roleName = leader.roleName; + this.title = leader.title; + this.lv = leader.lv; + this.headHid = leader.headHid; + this.sHid = leader.sHid; + } +} + export class PlayerDetailHero { actorId: number; lv: number;