import { gameData, getGuildActiveWeekReward, getGuildActiveByIdAndType, getGoodById } from "../pubUtils/data"; import { GuildModel } from "../db/Guild"; import { resResult, shouldRefresh } from "../pubUtils/util"; import { STATUS, MAIL_TYPE, GUILD_AUTH, GUILD_JOB, REDIS_KEY, CHAT_SERVER, TASK_TYPE } from "../consts"; import { RoleModel } from "../db/Role"; import { UserGuildModel, UserGuildType } from "../db/UserGuild"; import { UserGuildApplyModel } from "../db/UserGuildApply"; import { SystemConfigModel } from "../db/SystemConfig"; import { nowSeconds } from "../pubUtils/timeUtil"; import { pinus, BackendSession } from "pinus"; import { ARMY } from "../pubUtils/dicParam"; import { sendMail } from "./mailService"; import { initSingleRank, getRoleOnlineInfo, updateUserInfo } from "./redisService"; import { GuildRankParam, GuildLeader } from "../domain/rank"; import { lockData, lockDataNoRetry } from '../services/redLockService'; import { ErrLogModel } from '../db/ErrLog'; import { MailType, MailModel } from '../db/Mail'; import { pushMail } from '../pubUtils/interface'; import { getMailContent } from '../services/mailService'; import { DATA_NAME } from '../consts/dataName'; import { addRoleToGuildChannel } from "./chatService"; import { Rank } from "./rankService"; import { checkTask } from "./taskService"; import { accomplishTask } from "../pubUtils/taskUtil"; /** * @description 检查该玩家是否有权限做操作 * @param func 操作id * @param auth 权限 */ export async function checkAuth(func: number, roleId: string, code?: string, userGuild?: UserGuildType) { const auth = await UserGuildModel.getMyAuth(roleId, code, userGuild); const dicGuildAuth = gameData.guildAuth.get(func); // console.log('*checkAuth*', auth, dicGuildAuth) if (!dicGuildAuth) return false; return dicGuildAuth.includes(auth); } /** * @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 accomplishTask(roleId, TASK_TYPE.GUILD_JOIN, 1); session.set('guildCode', code); session.push('guildCode', () => { }); 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); 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; let { receivedActive, refTimeDaily, activeDaily, activeRecord, wishGoods } = userGuild; const now = new Date(); let isRefDaily = shouldRefresh(refTimeDaily, now); if (isRefDaily) { let mails = new Array(); let pushMessage = new Array(); 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 getMailContent(roleId, MAIL_TYPE.WISH_POOL_REWARD, [donateName, goodInfo.name], [{ id: goodId, count: drawCnt }], mails, pushMessage); } }); if (!!mails.length) { await MailModel.addMails(mails); if (!notPush) { pushMessage.forEach(({ route, data, uids }) => { pinus.app.channelService.pushMessageByUids(route, resResult(STATUS.SUCCESS, { mails: data }), uids); }); } } receivedActive = []; refTimeDaily = now; activeDaily = 0; activeRecord = []; wishGoods = []; let receiveBoxs = [], wishDntCnt = 0, donateCnt = 0; userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive, refTimeDaily, activeDaily, activeRecord, wishGoods, receiveBoxs, wishDntCnt, donateCnt }, {}, select); 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 sendMail(MAIL_TYPE.GUILD_ACTIVE_REWARD, roleId, '系统', [], reward); // 任务 await checkTask(roleId, null, null, TASK_TYPE.GUILD_JOB, 1, false, { job }); } await GuildModel.updateInfo(code, { activeWeekly: 0 }, {}); res.releaseCallback();//解锁 } await initSingleRank(REDIS_KEY.GUILD_ACTIVE_RANK); await SystemConfigModel.updateSystemConfig({ settleGuildWeeklyTime: nowSeconds() }); // 记录一下 console.log('————— settleGuildWeekly结束 —————'); }