Files
ZYZ/game-server/app/services/guildService.ts
2021-09-26 18:43:53 +08:00

349 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 = <RoleType>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 checkActivityTask(serverId, sid, roleId, TASK_TYPE.GUILD_JOIN, 1);
await pinus.app.rpc.connector.connectorRemote.setOtherUserGuildSession.toServer(sid,[{ roleId, userGuild }]);
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<string, number>();
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);
await PVPConfigModel.updatePVPConfig(curSeasonNum, { settleGuildWeeklyTime: nowSeconds() }); // 记录一下,不知道原作者有什么用处...
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', () => {});
}
}