import { gameData, getGuildActiveWeekReward, getGuildActiveByIdAndType, getGoodById } from "../pubUtils/data"; import { GuildModel, GuildType } from "../db/Guild"; import { resResult, shouldRefresh } from "../pubUtils/util"; import { STATUS, MAIL_TYPE, GUILD_AUTH, GUILD_JOB, REDIS_KEY, CHAT_SERVER, TASK_TYPE, COUNTER } from "../consts"; import { RoleModel, RoleType } from "../db/Role"; import { UserGuildModel, UserGuildType } from "../db/UserGuild"; import { UserGuildApplyModel } from "../db/UserGuildApply"; import { PVPConfigModel } from "../db/SystemConfig"; import { nowSeconds } from "../pubUtils/timeUtil"; import { pinus, BackendSession, FrontendOrBackendSession } from "pinus"; import { ARMY } from "../pubUtils/dicParam"; import { sendMailByContent } from "./mailService"; import { initSingleRank, getRoleOnlineInfo, updateUserInfo, isRoleOnline } from "./redisService"; import { lockData, lockDataNoRetry } from '../services/redLockService'; import { ErrLogModel } from '../db/ErrLog'; import { DATA_NAME } from '../consts/dataName'; import { addRoleToGuildChannel } from "./chatService"; import { Rank } from "./rankService"; import { checkActivityTask, checkTask } from "./taskService"; import { CounterModel } from "../db/Counter"; export async function getMyGuildInfo(roleId: string, sid: string, userGuild: UserGuildType, guild: GuildType, serverId: number, session: FrontendOrBackendSession) { let leader = guild.leader; let leaderIsOnline = await isRoleOnline(leader.roleId); // 打开公会页面,加入channel if (userGuild.guildCode) { addRoleToGuildChannel(roleId, sid, guild.code); session.set('guildCode', guild.code); session.push('guildCode', () => { }); } // 获取排行榜 let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); const rank = await r.getMyRank({ guildCode: guild.code }); let { lv: guildLv, memberCnt } = guild; let dicGuild = gameData.centerBase.get(guildLv); let guildMemberMax = dicGuild && memberCnt >= dicGuild.peopleNum; // 返回 return { hasGuild: true, guildMemberMax, ...guild, leader: { ...leader, isOnline: leaderIsOnline }, rank, myInfo: { ...userGuild } }; } /** * @description 检查该玩家是否有权限做操作 * @param func 操作id * @param auth 权限 */ export async function checkAuth(func: number, targetCode: string, guildAuth: number, myGuildCode = targetCode ) { if(targetCode != myGuildCode || !guildAuth) { guildAuth = GUILD_AUTH.OTHERS; } const dicGuildAuth = gameData.guildAuth.get(func); console.log('*checkAuth*', func, guildAuth, dicGuildAuth) if (!dicGuildAuth) return false; return dicGuildAuth.includes(guildAuth); } /** * @description 加入公会 * @param code 公会code * @param lv 公会当前等级,判断人数用 * @param roleId 加入的玩家 */ export async function joinGuild(code: string, guildName: string, lv: number, roleId: string, serverId: number, session: BackendSession) { // 周结算锁 let weeklySumLock = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, code); if (!!weeklySumLock.err) { weeklySumLock.releaseCallback(); return { status: -1, resResult: resResult(STATUS.GUILD_WEEKLY_SUM) }; } weeklySumLock.releaseCallback(); // 人数锁 let res: any = await lockData(serverId, DATA_NAME.JOIN_GUILD, code);// 加锁 if (!!res.err) return { status: -1, resResult: resResult(STATUS.REDLOCK_ERR) }; const result = await RoleModel.joinGuild(roleId, code, guildName); if (!result) { res.releaseCallback();//解锁 return { status: -1, resResult: resResult(STATUS.GUILD_HAS_JOIN) }; } const dicCenterBase = gameData.centerBase.get(lv); if (!dicCenterBase) { res.releaseCallback();//解锁 return { status: -1, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) }; } const maxMemberCnt = dicCenterBase.peopleNum; const guild = await GuildModel.addMember(code, roleId, maxMemberCnt, serverId, result.ce); if (!guild) { res.releaseCallback();//解锁 return { status: -1, resResult: resResult(STATUS.GUILD_MEMBER_MAX) }; } else { await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) } const role = await RoleModel.findByRoleId(roleId); const userGuild = await UserGuildModel.createUserGuild(guild.code, role, false); if (!userGuild) { res.releaseCallback();//解锁 return { status: -1, resResult: resResult(STATUS.GUILD_CREATE_ERROR) }; } await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 res.releaseCallback();//解锁 const { sid } = await getRoleOnlineInfo(roleId); if (sid) { await addRoleToGuildChannel(roleId, sid, code); await pinus.app.rpc.connector.connectorRemote.setOtherUserGuildSession.toServer(sid,[{ roleId, userGuild }]); } //成长任务-加入军团 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.GUILD_JOIN, 1); return { status: 0, guild, userGuild, roleName: role.roleName, memberCnt: guild.memberCnt, guildCe: guild.guildCe } } /** * 刷新军团日活跃 * @param guildCode 军团唯一code * @param serverId 区 */ export async function getGuildWithRefActive(guildCode: string, serverId: number) { let res: any = await lockData(serverId, DATA_NAME.REFRESH_ACTIVE, guildCode);// 加锁 if (!!res.err) return false; let guild = await GuildModel.findByCode(guildCode, serverId, '+refTimeDaily'); if (!guild) { res.releaseCallback();//解锁 return false; } const now = new Date(); let { activeDaily, refTimeDaily } = guild; let isRefDaily = shouldRefresh(refTimeDaily, now); if (isRefDaily) { activeDaily = 0; refTimeDaily = now; guild = await GuildModel.updateInfoWithLeader(guildCode, { activeDaily, refTimeDaily }, {}); } res.releaseCallback();//解锁 return guild; } /** * 增加活跃 * @param guildCode 军团唯一code * @param serverId 区 * @param id 增加活跃的操作 * @param type 类型 activePoint内配的type * @param active debug直接增加的活跃 */ export async function addActive(roleId: string, serverId: number, id: number, type: number = 1, 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 { status: 0, resResult: resResult(STATUS.GUILD_NOT_FOUND) }; let guildCode = userGuild.guildCode; let guild = await getGuildWithRefActive(guildCode, serverId); if (!guild) return { status: 0, resResult: resResult(STATUS.GUILD_NOT_FOUND) }; // 周结算锁 let weeklySumLock = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, guildCode); if (!!weeklySumLock.err) { weeklySumLock.releaseCallback(); return { status: 0, resResult: resResult(STATUS.GUILD_WEEKLY_SUM) }; } weeklySumLock.releaseCallback(); let { activeRecord } = userGuild; if (id != 0) { // 用于debug,传0时直接增加活跃 let curActiveRecord = activeRecord.find(cur => cur.id == id); if (curActiveRecord) { curActiveRecord.count++; } else { curActiveRecord = { id, count: 1 }; activeRecord.push(curActiveRecord); } if (curActiveRecord.count > dicActiveWay.count) { // 次数超过时,不增加活跃 active = 0; } } userGuild = await UserGuildModel.updateInfo(roleId, { activeRecord, activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); guild = await GuildModel.updateInfo(guildCode, { activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); // 排行榜更新 let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); await r.setRankWithGuildInfo(guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); await r2.setRankWithGuildInfo2(guildCode, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); pinus.app.rpc.chat.guildRemote.updateInfo.toServer(CHAT_SERVER, guildCode, { activeDaily: guild.activeDaily, activeWeekly: guild.activeWeekly }); return { status: 1, guild, userGuild }; } /** * 获取用户公会表并刷新活跃和每日捐赠以及每日许愿数据 * @param roleId 用户id * @param select 筛选字段 */ export async function getUserGuildWithRefActive(roleId: string, select?: string, notPush?: boolean) { let userGuild = await UserGuildModel.getMyGuild(roleId, select ? select + ' wishGoods +refTimeDaily' : '+refTimeDaily'); // console.log(JSON.stringify(userGuild)) if (!userGuild) return false; return await refreshUserGuild(userGuild, roleId, notPush); } export async function refreshUserGuild(userGuild: UserGuildType, roleId: string, notPush?: boolean) { if(!userGuild) return false; let { receivedActive, refTimeDaily, activeDaily, activeRecord, wishGoods, receivedWishPool } = userGuild; const now = new Date(); let isRefDaily = shouldRefresh(refTimeDaily, now); if (isRefDaily) { wishGoods.map(async function ({ donateNames, goodId, drawCnt }) { let goodInfo = getGoodById(goodId) if (!goodInfo) return; for (let i = 0; i < drawCnt; i++) { let donateName = donateNames[donateNames.length - i - 1]; await sendMailByContent(MAIL_TYPE.WISH_POOL_REWARD, roleId, { params: [donateName, goodInfo.name], goods: [{ id: goodId, count: drawCnt }], notPush }); } }); receivedActive = []; refTimeDaily = now; activeDaily = 0; activeRecord = []; wishGoods = []; receivedWishPool = []; let receiveBoxs = [], wishDntCnt = 0, donateCnt = 0; userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive, refTimeDaily, activeDaily, activeRecord, wishGoods, receiveBoxs, wishDntCnt, donateCnt, receivedWishPool }, {}); if (!userGuild) return false; } return userGuild; } /** * 每周结算上周公会周功勋和 活跃并发奖励(未完) * */ export async function settleGuildWeekly() { console.log('————— settleGuildWeekly —————'); const guildList = await GuildModel.findAllGuild('code activeWeekly memberCnt serverId'); // 周结算时,1. 不能变动memberCnt 2.玩家activeWeekly不能变动 3.公会activeWeekly不能变动 for (let { code, memberCnt, serverId } of guildList) { let res: any = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, code);//加锁 if (!!res.err) { await ErrLogModel.create(`settle guild lock data error: ${res.err}`) } const userGuildList = await UserGuildModel.getListByGuild(code, 'roleId auth activeWeekly', { activeWeekly: -1, activeUpdateTime: 1 }); let otherMemberCnt = 0; // 除了大将军以外从活跃高到底成员人数,用户计算活跃排名百分比 let members = new Map(); for (let { roleId, auth, activeWeekly } of userGuildList) { let job = 0; if (auth == GUILD_AUTH.LEADER) { job = GUILD_JOB.DAJIANGJUN; } else if (activeWeekly <= ARMY.ARMY_WEEKHONOUR_LIMIT) { job = GUILD_JOB.SHIBING; } else { otherMemberCnt++; for (let [id, { rankProportion }] of gameData.guildPosition) { let rankCnt = Math.ceil(memberCnt * rankProportion / 100); job = id; if (otherMemberCnt <= rankCnt) break; } } await UserGuildModel.updateInfo(roleId, { job, activeWeekly: 0 }, {}); if (activeWeekly > ARMY.ARMY_WEEKHONOUR_LIMIT) { // 低于一定不发奖励 members.set(roleId, job); } } // 转换周活跃奖励 let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); let rank = await r.getMyRank({ guildCode: code }); let allWeeklyReward = getGuildActiveWeekReward(rank); for (let [roleId, job] of members) { let jobActiveRatio = gameData.guildPosition.get(job).activeRatio; let reward = allWeeklyReward.map(cur => { return { id: cur.id, count: Math.ceil(cur.count * jobActiveRatio) } }); await sendMailByContent(MAIL_TYPE.GUILD_ACTIVE_REWARD, roleId, { goods: reward }); // 任务 await checkTask(roleId, null, TASK_TYPE.GUILD_JOB, 1, false, { job }); } await GuildModel.updateInfo(code, { activeWeekly: 0 }, {}); res.releaseCallback();//解锁 } await initSingleRank(REDIS_KEY.GUILD_ACTIVE_RANK); await initSingleRank(REDIS_KEY.GUILD_LV_RANK); let curSeasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM); console.log('————— settleGuildWeekly结束 —————'); } export async function getWishPool(userGuild: UserGuildType) { const { guildCode: code, wishDntCnt, wishGoods } = userGuild; let userGuilds = await UserGuildModel.getWishPoolGoods(code, ' wishDntCnt wishGoods roleId'); let list = []; userGuilds.map(({ wishGoods, roleId }) => { wishGoods.map(({ type, goodId, count, receiveCnt, drawCnt, id }) => { list.push({ type, goodId, count, receiveCnt, drawCnt, id, roleId }) }); }); return { list, wishDntCnt: wishDntCnt || 0, wishGoods }; } export function setUserGuildSession(session:FrontendOrBackendSession, myUserGuild: UserGuildType) { if(myUserGuild) { session.set('guildCode', myUserGuild.guildCode); session.set('guildAuth', myUserGuild.auth); session.push('guildCode', () => {}); session.push('guildAuth', () => {}); } else { session.set('guildCode', null); session.set('guildAuth', null); session.push('guildCode', () => {}); session.push('guildAuth', () => {}); } } export async function getInvitationList(roleId: string, lastApplyCode = '') { const result = await UserGuildApplyModel.findInviteByRole(roleId, lastApplyCode); const list = result.map(cur => { let guild = cur.guild; let leader = guild.leader; delete cur.guild; return { applyCode: cur.applyCode, ...guild, leader: leader.roleName }; }); return list; }