Files
ZYZ/game-server/app/services/timeTaskService.ts
2022-03-01 10:10:11 +08:00

676 lines
28 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 { scheduleJob, Job, scheduledJobs, } from 'node-schedule';
import { PVPConfigModel, PVPConfigType } from '../db/SystemConfig';
import { nowSeconds, getTimeFun, getSeconds, getZeroPoint } from '../pubUtils/timeUtil';
import { getTodayGuildActivity, gameData } from '../pubUtils/data';
import { pvpSeasonEnd } from './pvpService';
import { getAllOnlineRoles, getAllServers, delGuildActivityRank } from './redisService';
import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, SEND_NAME, SERVER_OPEN_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_STATUS, SERVER_TIMER } from '../consts';
import { RoleModel } from '../db/Role';
import { pinus } from 'pinus';
import { indexOf } from 'underscore';
import { PvpSeasonResultModel } from '../db/PvpSeasonResult';
import { settleGuildWeekly } from './guildService';
import { sendMailByContent, SendMailFun } from './mailService';
import { getGuildActivityByDic, sendEndMsgToAll, autoDeclare, sendGuildActivityStatus } from './guildActivity/guildActivityService';
import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction } from './auctionService';
import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity';
import { dispatch } from '../pubUtils/dispatcher';
import { Rank } from './rankService';
import { checkTask } from './taskService';
import { everydayRefresh } from './connectorService';
import { createNewServer, initMarquee } from './gmService';
import moment = require('moment');
import { CounterModel } from '../db/Counter';
import { reportOneOnline } from './authenticateService';
import { PVP } from '../pubUtils/dicParam';
import { fetch37Words } from './sdkService';
import { GMMailModel } from '../db/GMMail';
import { Maintenance, ServerlistModel, ServerlistType, ServerlistUpdate } from '../db/Serverlist';
import { getWorldChannelSid } from './chatService';
import { createMarqueeMsg, pushMarqueeMsg } from './sysChatService';
import { RegionModel, RegionType } from '../db/Region';
import { CreateServerParam } from '../domain/backEndField/params';
import { infologger } from '../util/logger';
import { MailModel, MailType } from '../db/Mail';
import { GroupMailModel, GroupMailType } from '../db/GroupMail';
import { ServerMailModel, ServerMailType } from '../db/ServerMail';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
const PER_HOUR = 1 * 60 * 60;
const PER_MINUTE = 1 * 60;
var seasonMakeRewardTimJobId: Job;
var seasonRefreshTimeJobId: Job;
let guildWeeklyJobId: Job;
let guildActStartJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除
let guildActSecondsJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除
let guildActEndJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除
/**
* 初始定时器
*/
export async function init() {
console.log('******* init systimer *******')
// pvp赛季
await setPvpSeason();
// 周功勋结算任务
guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 ? * * 1', settleGuildWeekly);
// 每5分钟汇报在线玩家在线情况
scheduleJob('reportOnline', '0 0/5 * * * *', reportOnlineSchedule);
// 每天拉取37词库
scheduleJob('fetchWord', '0 0 4 * * ?', fetch37Words);
// 每天邮件
checkCircleMail();
// 每小时查询邮件推送
checkMailByHour();
// 军团活动排行榜
guildActivitySchedule();
// 拍卖行刷新:拍卖阶段刷新,分红发放
auctionSchedule();
// 每天5点推送刷新时间消息
// 顺便每天0点计算前一天活跃玩家中位数战力
scheduleJob('everyDayRefresh', `0 0 ${REFRESH_TIME} * * ?`, everydayRefresh);
// 跑马灯
await initMarquee();
// 维护信息
await initMaintenance();
// 自动开服
await initAutoCreateServer();
}
// —————————————— PVP 及赛季相关 —————————————— //
function getSeasonContinueDay(seasonNum: number) {
const pvpSeasonDuring = PVP.PVP_SEASON_DAYS.split('|').map(cur => {
let arr = cur.split('&');
let seasonNum = parseInt(arr[0]);
let day = parseInt(arr[1]);
if(isNaN(seasonNum) || isNaN(day)) return null;
return { seasonNum, day }
}).filter(cur => !!cur);
let maxDay = 0;
for(let {seasonNum: dicSeasonNum, day } of pvpSeasonDuring) {
if(seasonNum == dicSeasonNum) return day;
if(maxDay < day) maxDay = day;
}
return maxDay;
}
async function setPvpSeasonJob() {
await setPvpSeason();
}
async function setPvpSeason(isForce?: boolean, minute?: number) {
console.log(`******** setPvpSeason1 isForce-${isForce}, minute-${minute}`)
let during = minute? minute * PER_MINUTE: null; // 下一次重置赛季天数
let oldPvpConfig = await PVPConfigModel.findCurPVPConfig();
let pvpConfig = oldPvpConfig;
console.log(`******** setPvpSeason2 during-${during}, seasonEndTime-${pvpConfig?.seasonEndTime}, now-${nowSeconds()}`)
if(!pvpConfig || pvpConfig.seasonEndTime - PER_MINUTE <= nowSeconds() || isForce) {
if(pvpConfig && !pvpConfig.hasSettleReward) {
await pvpSeasonEnd(pvpConfig.seasonNum);
}
let lastSeasonNum = pvpConfig? pvpConfig.seasonNum: 0;
let lastSeasonEndTime = pvpConfig? pvpConfig.seasonEndTime: 0;
console.log(`******** setPvpSeason3 lastSeasonNum-${lastSeasonNum}, lastSeasonEndTime-${lastSeasonEndTime}`)
let newSeasonStartTime = lastSeasonEndTime;
if(!during) during = getSeasonContinueDay(lastSeasonNum + 1) * PER_DAY;
let rewardTime = PVP.PVP_SEASON_REWARD_TIME_BEFORE * PER_MINUTE;
if(nowSeconds() - newSeasonStartTime > during) {
newSeasonStartTime = <number>getTimeFun().getDayZeroPoint(0);
}
console.log(`******** setPvpSeason4 newSeasonStartTime-${newSeasonStartTime}, during-${during}`)
if(isForce) { // debug使用如果seasonEndTime是未来的强行结束掉新赛季从现在开始
newSeasonStartTime = nowSeconds();
} else { // 不是用debug的情况如果因为debugnewSeasonStartTime不是每天0点结算那么改成lastSeasonEndTime之后的0点开始
let d = new Date(newSeasonStartTime * 1000);
if(d.getHours() != 0) {
d.setHours(0, 0, 0, 0);
newSeasonStartTime = getSeconds(d);
}
}
console.log(`******** setPvpSeason5 isForce-${isForce}, newSeasonStartTime-${newSeasonStartTime}`)
let newSeasonNum = await CounterModel.getNewCounter(COUNTER.PVP_SEASON_NUM);
pvpConfig = await PVPConfigModel.createPVPConfig(newSeasonNum, newSeasonStartTime, newSeasonStartTime + during - rewardTime, newSeasonStartTime + during);
}
await setPvpSeasonMakeRewardJob(pvpConfig);
await setNextSeasonJob(pvpConfig);
setPvpSeasonNum(pvpConfig);
return pvpConfig;
}
function setPvpSeasonNum(pvpConfig: PVPConfigType) {
if(pvpConfig) {
pinus.app.set('pvpSeasonNum', pvpConfig.seasonNum);
pinus.app.set('pvpSeasonEndTime', pvpConfig.seasonEndTime);
pinus.app.rpc.battle.battleRemote.setPvpSeasonNum.broadcast(pvpConfig);
pinus.app.rpc.role.roleRemote.setPvpSeasonNum.broadcast(pvpConfig);
pinus.app.rpc.connector.connectorRemote.setPvpSeasonNum.broadcast(pvpConfig);
}
}
async function setPvpSeasonMakeRewardJob(pvpConfig: PVPConfigType) {
if (!!seasonMakeRewardTimJobId) {
seasonMakeRewardTimJobId.cancel();
}
if(!pvpConfig) return;
if(pvpConfig.seasonRewardTime < nowSeconds() && !pvpConfig.hasSettleReward) { // 未发奖励
await pvpSeasonEnd(pvpConfig.seasonNum);
} else {
seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', pvpConfig.seasonRewardTime * 1000, async () => {
console.log('************ seasonMakeRewardTimJobId *********');
await pvpSeasonEnd(pvpConfig.seasonNum);
});
}
}
async function setNextSeasonJob(pvpConfig: PVPConfigType) {
if (!!seasonRefreshTimeJobId) {
seasonRefreshTimeJobId.cancel();
}
//定时开启新赛季比seasonEndTime多定一分钟保证定时器时间没错
seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', (pvpConfig.seasonEndTime) * 1000, setPvpSeasonJob);
}
/**
* debug接口
* @param hour
*/
export async function resetPvpSeasonTime(minute: number) {
return await setPvpSeason(true, minute);
}
export async function reportOnlineSchedule() {
let allRoles = await getAllOnlineRoles();
infologger.info('reportOnlineSchedule all roles count: ', allRoles.length);
console.log('reportOnlineSchedule all roles count: ', allRoles.length)
for (let { roleId, userCode, sid } of allRoles) {
let result = reportOneOnline(roleId, userCode, sid, false);
if (!result) continue;
}
}
// —————————————— PVP 及赛季相关 end —————————————— //
// —————————————— 军团活动 —————————————— //
/**
* 军团活动每晚8点开启
*/
export async function guildActivitySchedule() {
/***********guildActivitySchedule***********/
if (guildActStartJobId) {
guildActStartJobId.cancel();
}
let dicGuildActivity = getTodayGuildActivity();
await delGuildActivityRank(dicGuildActivity.id);
// console.log(dicGuildActivity)
guildActStartJobId = scheduleJob('guildActivityStart', `${dicGuildActivity.startSeconds} ${dicGuildActivity.startMinute} ${dicGuildActivity.startTime} * * ?`, guildActivityStartSchedule);
}
// 军团晚间活动每天8点开始
async function guildActivityStartSchedule() {
await guildActivityStart();
}
export async function guildActivityStart(dicGuildActivity?: DicGuildActivity) {
console.log('*******开始军团晚间活动****')
if (!dicGuildActivity) dicGuildActivity = getTodayGuildActivity();
if (!dicGuildActivity) return;
console.log('********', dicGuildActivity.id, Date.now() + dicGuildActivity.duringTime * 1000)
let servers = await getAllServers(); // 玩家serverId列表
console.log('****** guildActSecondsJobId', guildActSecondsJobId)
if (guildActSecondsJobId) {
guildActSecondsJobId.cancel();
guildActSecondsJobId = undefined;
}
if (guildActEndJobId) {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
if (dicGuildActivity.id == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) {
guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', gateActivitySeconds);
// 结束时间
guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, gateActivityEnd);
} else if (dicGuildActivity.id == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) {
guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', cityActivitySeconds);
// 结束时间
guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, cityActivityEnd);
} else if (dicGuildActivity.id == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) {
// 开始活动
let guildServers = pinus.app.getServersByType('guild');
for (let serverId of servers) {
let sid = dispatch(serverId.toString(), guildServers, 'guild');
await pinus.app.rpc.guild.guildActivityRemote.raceActivityStart.toServer(sid.id, serverId);
}
guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/2 * * * * *', raceActivitySeconds);
// 结束时间
guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, raceActivityEnd);
}
for (let serverId of servers) {
await sendGuildActivityStatus(serverId);
}
return true;
}
// 蛮夷入侵
// 结束军团活动
export async function gateActivityEnd() {
console.log('*****gateActivityEnd');
await sendEndMsgToAll();
await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY);
if (guildActSecondsJobId) {
guildActSecondsJobId.cancel();
guildActSecondsJobId = undefined;
}
if (guildActEndJobId) {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
}
// 每10秒下发一次的任务
export async function gateActivitySeconds() {
console.log('*****gateActivitySeconds')
await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY);
}
// 诸侯混战
// 结束军团活动
export async function cityActivityEnd() {
console.log('*****cityActivityEnd');
await sendEndMsgToAll();
await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);
// 发完之后再做下周自动宣战
let serverlists = await getAllServers();
for (let serverId of serverlists) {
await autoDeclare(serverId);
}
if (guildActSecondsJobId) {
guildActSecondsJobId.cancel();
guildActSecondsJobId = undefined;
}
if (guildActEndJobId) {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
}
// 每10秒下发一次的任务
export async function cityActivitySeconds() {
console.log('*****cityActivitySeconds')
await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY);
}
// 粮草先行
// 结束军团活动
export async function raceActivityEnd() {
console.log('*****raceActivityEnd');
await sendEndMsgToAll();
await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY);
if (guildActSecondsJobId) {
guildActSecondsJobId.cancel();
guildActSecondsJobId = undefined;
}
if (guildActEndJobId) {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
}
// 每10秒下发一次的任务
export async function raceActivitySeconds() {
console.log('*****raveActivitySeconds')
let servers = await getAllServers(); // 玩家serverId列表
let guildServers = pinus.app.getServersByType('guild');
for (let serverId of servers) {
let sid = dispatch(serverId.toString(), guildServers, 'guild');
await pinus.app.rpc.guild.guildActivityRemote.calWoodenHorseAndSend.toServer(sid.id, serverId);
}
}
// —————————————— 军团活动 end —————————————— //
// —————————————— 拍卖行 —————————————— //
let startGuildAuctionJobId: Job;
let startWorldAuctionJobId: Job;
let stopAuctionJobId: Job;
let sendUngotDividendJobId: Job;
export function auctionSchedule() {
clearAuctionSchedule();
let guildOpen = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN);
let worldOpen = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN);
let worldClose = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE);
// console.log('***** auctionSchedule', guildOpen.hour, guildOpen.minute, guildOpen.seconds);
// console.log('***** auctionSchedule', worldOpen.hour, worldOpen.minute, worldOpen.seconds);
// console.log('***** auctionSchedule', worldClose.hour, worldClose.minute, worldClose.seconds);
startGuildAuctionJobId = scheduleJob('startGuildAuction', `${guildOpen.seconds} ${guildOpen.minute} ${guildOpen.hour} * * ?`, startGuildAuction);
startWorldAuctionJobId = scheduleJob('startWorldAuction', `${worldOpen.seconds} ${worldOpen.minute} ${worldOpen.hour} * * ?`, startWorldAuction);
stopAuctionJobId = scheduleJob('stopAuction', `${worldClose.seconds} ${worldClose.minute} ${worldClose.hour} * * ?`, stopAuction);
sendUngotDividendJobId = scheduleJob('sendUngotDividendJob', '0 0 5 00 * ?', sendUngotDividendJob);
}
function clearAuctionSchedule() {
if (startGuildAuctionJobId) {
startGuildAuctionJobId.cancel();
startGuildAuctionJobId = undefined;
}
if (startWorldAuctionJobId) {
startWorldAuctionJobId.cancel();
startWorldAuctionJobId = undefined;
}
if (stopAuctionJobId) {
stopAuctionJobId.cancel();
stopAuctionJobId = undefined;
}
if (sendUngotDividendJobId) {
sendUngotDividendJobId.cancel();
sendUngotDividendJobId = undefined;
}
}
// —————————————— 拍卖行 end —————————————— //
// —————————————— 邮件 —————————————— //
let circleMailJob: Job;
async function checkCircleMail() {
if(circleMailJob) {
circleMailJob.cancel();
}
circleMailJob = scheduleJob('circleMail', '0 0 20 * * ?', sendCircleMail);
sendCircleMail();
}
async function sendCircleMail() {
let gmmails = await GMMailModel.findCircleMails(pinus.app.get('env'));
let f = new SendMailFun();
for(let gmmail of gmmails) {
let { receivers, mailType, sendTimes } = gmmail;
let code = await f.setWithGmMail(gmmail);
let mapTemp = f.getMailTemp(code);
if(sendTimes.indexOf(mapTemp.sendTime) == -1) {
if(mailType == GM_MAIL_TYPE.SINGLE) {
await f.createSingleMails(code, receivers.map(cur => cur.roleId));
} else if (mailType == GM_MAIL_TYPE.GROUP) {
await f.createGroupMails(code, receivers.map(cur => cur.roleId));
} else if (mailType == GM_MAIL_TYPE.SERVER) {
await f.createServerMails(code, receivers.map(cur => cur.serverId));
}
}
}
await f.pushToUsers();
}
let mailByHourJob: Job;
async function checkMailByHour() {
if(mailByHourJob) {
mailByHourJob.cancel();
}
// 每小时一次为了和每天循环邮件任务不重复设在每小时05分
mailByHourJob = scheduleJob('setMailTimerByHour', '0 5 0/1 * * ?', async () => {
await setMailSchedule(false)
});
setMailSchedule(true); // 初始时候启动一次
}
async function setMailSchedule(isInit: boolean) {
let minuteNow = moment().minute();
let beforeTime = minuteNow >= 5? moment().minute(5).unix(): moment().minute(5).add(-1, 'h').unix();
let time = minuteNow >= 5? moment().minute(5).add(1, 'h').unix(): moment().minute(5).unix();
let mails = await MailModel.findByTimeGap(beforeTime, time);
let groupMails = await GroupMailModel.findByTimeGap(beforeTime, time);
let serverMails = await ServerMailModel.findByTimeGap(beforeTime, time);
let times: number[] = [];
for(let { sendTime } of [...mails, ...groupMails, ...serverMails]) {
if(times.indexOf(sendTime) == -1) times.push(sendTime);
}
for(let time of times) {
if(Date.now() > time * 1000) {
if(!isInit) await pushMailSchedule(time);
} else {
scheduleJob(`mailPush${time}`, time * 1000, async () => {
await pushMailSchedule(time);
});
}
}
}
// 当前时间到下一次定时器之间的定时器
export async function addMailsToSchedule(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) {
let minuteNow = moment().minute();
let time = minuteNow >= 5? moment().minute(5).add(1, 'h').unix(): moment().minute(5).unix();
let times: number[] = [];
for(let { sendTime } of [...mails, ...groupMails, ...serverMails]) {
if(sendTime * 1000 > Date.now() && sendTime < time && times.indexOf(sendTime) == -1) times.push(sendTime);
}
for(let time of times) {
if(!scheduledJobs[`mailPush${time}`]) {
scheduleJob(`mailPush${time}`, time * 1000, async () => {
await pushMailSchedule(time);
})
}
}
}
async function pushMailSchedule(time: number) {
if(scheduledJobs[`mailPush${time}`]) scheduledJobs[`mailPush${time}`].cancel();
let mails = await MailModel.findBySendTime(time);
let groupMails = await GroupMailModel.findBySendTime(time);
let serverMails = await ServerMailModel.findBySendTime(time);
let f = new SendMailFun();
f.setMails(mails, groupMails, serverMails);
await f.pushToUsers();
}
// —————————————— 邮件 end —————————————— //
// —————————————— 维护 —————————————— //
let maintenInfos = new Map<string, { servers: ServerlistType[], maintenance: Maintenance }>(); // batchCode => {servers, maintenance}
export async function initMaintenance(servers?: ServerlistType[]) {
if(!servers) servers = await ServerlistModel.findByEnv(pinus.app.get('env'));
for(let server of servers) {
let { maintenance } = server;
if(maintenance && maintenance.isOpen) {
if(!maintenInfos.has(maintenance.batchCode)) {
maintenInfos.set(maintenance.batchCode, { servers: [], maintenance });
}
maintenInfos.get(maintenance.batchCode).servers.push(server);
}
}
for(let [batchCode] of maintenInfos) {
await setMaintenance(batchCode);
}
}
// 设置维护
async function setMaintenance(batchCode: string) {
let { maintenance } = maintenInfos.get(batchCode);
console.log('***** maintenance', maintenance);
let now = nowSeconds();
// 发送消息
if(maintenance.hasNotify && now < maintenance.startTime) { // 提前5分钟发通知
if(now > maintenance.startTime - 5 * 60) {
maintenanceNotifySchedule(batchCode);
} else {
if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel();
scheduleJob(`maintenNotify${batchCode}`, (maintenance.startTime - 5 * 60) * 1000, () => {
maintenanceNotifySchedule(batchCode);
})
}
} else {
if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel();
}
// 开始维护
console.log('******* setMaintenance', now, now < maintenance.endTime, now > maintenance.startTime)
if(now < maintenance.endTime) {
if(now > maintenance.startTime) {
console.log('*******')
await startMaintenanceSchedule(batchCode);
} else {
scheduleJob(`startMainten${batchCode}`, maintenance.startTime * 1000, async () => {
await startMaintenanceSchedule(batchCode);
});
}
} else {
if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel();
}
}
// 维护前通知
async function maintenanceNotifySchedule(batchCode: string) {
let { servers, maintenance } = maintenInfos.get(batchCode);
if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel();
if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel();
scheduleJob(`maintenSec${batchCode}`, `0 */1 * * * *`, async () => {
for(let { id: serverId } of servers) {
let msgData = await createMarqueeMsg('', '系统', serverId, '服务器即将维护,请玩家提前退出游戏');
await pushMarqueeMsg(msgData);
}
})
}
// 开始维护
async function startMaintenanceSchedule(batchCode: string) {
let { servers, maintenance } = maintenInfos.get(batchCode);
let serverIds = servers.map(cur => cur.id);
if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel();
if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel();
if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel();
// 向全服发送
for(let { id: serverId } of servers) {
let chatSid = await getWorldChannelSid(serverId);
if(chatSid) {
await pinus.app.rpc.chat.chatRemote.sendServerMaintenance.toServer(chatSid, serverId);
}
}
// 更新connectorRemote里面的维护服务器
console.log('******** startMaintenanceSchedule', batchCode, serverIds, maintenance.startTime, maintenance.endTime)
pinus.app.rpc.connector.connectorRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
pinus.app.rpc.activity.activityRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
pinus.app.rpc.battle.battleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
pinus.app.rpc.chat.chatRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
pinus.app.rpc.guild.guildRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
pinus.app.rpc.order.orderRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
pinus.app.rpc.role.roleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime);
// 数数flush
pinus.app.rpc.activity.activityRemote.taflush.broadcast();
pinus.app.rpc.battle.battleRemote.taflush.broadcast();
pinus.app.rpc.chat.chatRemote.taflush.broadcast();
pinus.app.rpc.connector.connectorRemote.taflush.broadcast();
pinus.app.rpc.guild.guildRemote.taflush.broadcast();
pinus.app.rpc.order.orderRemote.taflush.broadcast();
pinus.app.rpc.role.roleRemote.taflush.broadcast();
pinus.app.rpc.systimer.systimerRemote.taflush.broadcast();
}
// 提前结束维护
export async function stopMaintenance(batchCode: string, serverIds: number[]) {
// console.log('***********', serverIds)
let { servers = [], maintenance = {} as Maintenance } = maintenInfos.get(batchCode)||{};
for(let id of serverIds) {
let index = servers.findIndex(cur => cur.id == id);
if(index != -1) servers.splice(index);
}
if(servers.length == 0) {
if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel();
if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel();
if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel();
maintenInfos.delete(batchCode);
}
// 更新connectorRemote里面的维护服务器
pinus.app.rpc.connector.connectorRemote.stopServerMainten.broadcast(serverIds);
pinus.app.rpc.activity.activityRemote.stopServerMainten.broadcast(serverIds);
pinus.app.rpc.battle.battleRemote.stopServerMainten.broadcast(serverIds);
pinus.app.rpc.chat.chatRemote.stopServerMainten.broadcast(serverIds);
pinus.app.rpc.guild.guildRemote.stopServerMainten.broadcast(serverIds);
pinus.app.rpc.order.orderRemote.stopServerMainten.broadcast(serverIds);
pinus.app.rpc.role.roleRemote.stopServerMainten.broadcast(serverIds);
}
// —————————————— 维护 end —————————————— //
// —————————————— 自动开服 —————————————— //
export async function initAutoCreateServer(region?: RegionType) {
if(!region) region = await RegionModel.findRegionByEnv(pinus.app.get('env'));
if(region && region.stategy) {
for(let timer of region.stategy.timers) {
setStategyTimer(timer, region)
}
}
}
function setStategyTimer(timerId: number, region: RegionType) {
if(scheduledJobs[`autoServer${timerId}`]) scheduledJobs[`autoServer${timerId}`].cancel();
let cron = '';
switch(timerId) {
case SERVER_TIMER.FIVE_HALF:
cron = '0 30 5 * * *'; break;
case SERVER_TIMER.TEN_HALF:
cron = '0 30 10 * * *'; break;
case SERVER_TIMER.FIFTEEN_HALF:
cron = '0 30 15 * * *'; break;
case SERVER_TIMER.NINETEEN_HALF:
cron = '0 30 19 * * *'; break;
}
if(cron) {
scheduleJob(`autoServer${timerId}`, cron, () => {
autoCreateServerSchedule(region);
})
}
}
async function autoCreateServerSchedule(region: RegionType) {
console.log('******* createNewServer *******')
let latestServer = await ServerlistModel.findByServerId(region.latestServerUniqId);
if(!latestServer || latestServer.playerCnt >= region.stategy.maxPlayerCnt) {
let params = new CreateServerParam();
params.setByRegionStategy(region, nowSeconds())
await createNewServer(region, (latestServer?.serverId||0) + 1, params);
}
}
// —————————————— 自动开服 end —————————————— //