Files
ZYZ/game-server/app/services/timeTaskService.ts
2021-11-02 13:18:59 +08:00

370 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 { scheduleJob, Job, } from 'node-schedule';
import { PVPConfigModel, PVPConfigType } from '../db/SystemConfig';
import { nowSeconds, getTimeFun, getSeconds } 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 } 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 } from './mailService';
import { getGuildActivityByDic, sendEndMsgToAll, autoDeclare, sendGuildActivityStatus } from './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 { initMarquee, initMaintenance } from './gmService';
import moment = require('moment');
import { CounterModel } from '../db/Counter';
import { reportOneOnline } from './authenticateService';
import { PVP } from '../pubUtils/dicParam';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
const PER_HOUR = 1 * 60 * 60;
const SETTLE_DIFF_SECONDS = 29 * 60;
const PER_MINUTE = 1 * 60;
var seasonMakeRewardTimJobId: Job;
var warJobId: 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)秒循环的定时任务,到结束活动清除
let pvpMakeRewardInterval = null;
let pvpRefreshInterval = null;
/**
* 服务器启动即开启定时任务结算时常是23-24点实际结算的时间点是2331分钟
*/
export async function init() {
// pvp赛季
await setPvpSeason();
// 周功勋结算任务
guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 0 * * 1', settleGuildWeekly);
// 每5分钟汇报在线玩家在线情况
scheduleJob('reportOnline', '0 0/5 * * * *', reportOnlineSchedule);
// 军团活动排行榜
guildActivitySchedule();
// 拍卖行刷新:拍卖阶段刷新,分红发放
auctionSchedule();
// 每天5点推送刷新时间消息
// 顺便每天0点计算前一天活跃玩家中位数战力
scheduleJob('everyDayRefresh', `0 0 ${REFRESH_TIME} * * ?`, everydayRefresh);
// 跑马灯
await initMarquee();
// 维护信息
await initMaintenance();
}
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, hour?: number) {
console.log(`******** setPvpSeason1 isForce-${isForce}, hour-${hour}`)
let during = hour? hour * PER_HOUR: null; // 下一次重置赛季天数
let oldPvpConfig = await PVPConfigModel.findCurPVPConfig();
let pvpConfig = oldPvpConfig;
console.log(`******** setPvpSeason2 during-${during}, seasonEndTime-${pvpConfig?.seasonEndTime}, now-${nowSeconds()}`)
if(!pvpConfig || pvpConfig.seasonEndTime <= nowSeconds() || isForce) {
if(pvpConfig && !pvpConfig.hasSettleReward) {
await pvpSeasonEnd(pvpConfig);
}
let lastSeasonNum = pvpConfig? pvpConfig.seasonNum: 0;
let lastSeasonEndTime = pvpConfig? pvpConfig.seasonEndTime: 0;
console.log(`******** setPvpSeason3 lastSeasonNum-${lastSeasonNum}, lastSeasonEndTime-${lastSeasonEndTime}`)
let newSeasonStartTime = lastSeasonEndTime + PER_MINUTE;
if(!during) during = getSeasonContinueDay(lastSeasonNum + 1) * PER_DAY;
let rewardTime = SETTLE_DIFF_SECONDS;
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 - PER_MINUTE);
}
await setPvpSeasonMakeRewardJob(oldPvpConfig);
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);
}
}
async function setPvpSeasonMakeRewardJob(pvpConfig: PVPConfigType) {
if (!!seasonMakeRewardTimJobId) {
seasonMakeRewardTimJobId.cancel();
}
if(!pvpConfig) return;
if(pvpConfig.seasonRewardTime < nowSeconds() && !pvpConfig.hasSettleReward) { // 未发奖励
await pvpSeasonEnd(pvpConfig);
} else {
seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', pvpConfig.seasonRewardTime, async () => {
await pvpSeasonEnd(pvpConfig);
});
}
}
async function setNextSeasonJob(pvpConfig: PVPConfigType) {
if (!!seasonRefreshTimeJobId) {
seasonRefreshTimeJobId.cancel();
}
//定时开启新赛季比seasonEndTime多定一分钟保证定时器时间没错
seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', pvpConfig.seasonEndTime + PER_MINUTE, setPvpSeasonJob);
}
/**
* debug接口
* @param hour
*/
export async function resetPvpSeasonTime(hour: number) {
return await setPvpSeason(true, hour);
}
export async function reportOnlineSchedule() {
let allRoles = await getAllOnlineRoles();
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;
}
}
/**
* 军团活动每晚8点开启
*/
export async function guildActivitySchedule() {
/***********guildActivitySchedule***********/
if (guildActStartJobId) {
guildActStartJobId.cancel();
}
if (guildActSecondsJobId) {
guildActSecondsJobId.cancel();
guildActSecondsJobId = undefined;
}
if (guildActEndJobId) {
guildActEndJobId.cancel();
guildActEndJobId = undefined;
}
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列表
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', '*/1 * * * * *', 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);
}
}
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;
}
}