server-master/srcs/Plugin.RainbowBattle/RecurrentJob/RainbowBattleSystem.cs
2026-02-10 18:21:30 +01:00

294 lines
No EOL
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using PhoenixLib.Events;
using PhoenixLib.Logging;
using WingsEmu.Game._enum;
using WingsEmu.Game._i18n;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Managers;
using WingsEmu.Game.Networking;
using WingsEmu.Game.RainbowBattle;
using WingsEmu.Game.RainbowBattle.Event;
using WingsEmu.Packets.Enums.Chat;
namespace Plugin.RainbowBattle.RecurrentJob
{
public class RainbowBattleSystem : BackgroundService
{
private static readonly TimeSpan Interval = TimeSpan.FromSeconds(1);
private static readonly TimeSpan Start = TimeSpan.FromMinutes(5);
private static List<(TimeSpan, int, TimeType)> _times = new();
private readonly IAsyncEventPipeline _eventPipeline;
private readonly IRainbowBattleManager _rainbowBattleManager;
private readonly ISessionManager _sessionManager;
public RainbowBattleSystem(IAsyncEventPipeline eventPipeline, IRainbowBattleManager rainbowBattleManager, ISessionManager sessionManager)
{
_eventPipeline = eventPipeline;
_rainbowBattleManager = rainbowBattleManager;
_sessionManager = sessionManager;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Log.Info("[RAINBOW_SYSTEM] Start Rainbow Battle system...");
_times = _rainbowBattleManager.Warnings.ToList();
while (!stoppingToken.IsCancellationRequested)
{
try
{
await MainProcess();
}
catch (Exception e)
{
Log.Error("[RAINBOW_SYSTEM] ", e);
}
await Task.Delay(Interval, stoppingToken);
}
}
private async Task MainProcess()
{
DateTime dateNow = DateTime.UtcNow;
switch (_rainbowBattleManager.IsRegistrationActive)
{
case true:
await ProcessRegistration(dateNow);
return;
case false when !_rainbowBattleManager.IsActive:
ProcessTime(dateNow);
await ProcessStart(dateNow);
return;
}
if (_rainbowBattleManager.IsActive && !_rainbowBattleManager.RainbowBattleParties.Any())
{
_rainbowBattleManager.IsActive = false;
_times.Clear();
_times = _rainbowBattleManager.Warnings.ToList();
return;
}
foreach (RainbowBattleParty rainbowBattleParty in _rainbowBattleManager.RainbowBattleParties)
{
await ProcessRainbowBattle(rainbowBattleParty, dateNow);
}
}
private async Task ProcessStart(DateTime dateNow)
{
if (_rainbowBattleManager.RainbowBattleProcessTime is null)
{
return;
}
if (dateNow < _rainbowBattleManager.RainbowBattleProcessTime + Start)
{
return;
}
_times.Clear();
_times = _rainbowBattleManager.Warnings.ToList();
await _eventPipeline.ProcessEventAsync(new RainbowBattleStartRegisterEvent());
}
private void ProcessTime(DateTime dateNow)
{
if (_rainbowBattleManager.RainbowBattleProcessTime is null)
{
return;
}
if (_times.Count < 1)
{
return;
}
(TimeSpan, int, TimeType) warning = _times.OrderBy(x => x.Item1).First();
if (dateNow < _rainbowBattleManager.RainbowBattleProcessTime + warning.Item1)
{
return;
}
_times.Remove(warning);
GameDialogKey gameDialogKey = warning.Item3 == TimeType.SECONDS ? GameDialogKey.GAMEEVENT_SHOUTMESSAGE_PREPARATION_SECONDS : GameDialogKey.GAMEEVENT_SHOUTMESSAGE_PREPARATION_MINUTES;
_sessionManager.Broadcast(x =>
{
string rainbowBattleName = x.GetLanguage(GameDialogKey.RAINBOW_BATTLE_EVENT_NAME);
return x.GenerateMsgPacket(x.GetLanguageFormat(gameDialogKey, rainbowBattleName, warning.Item2), MsgMessageType.Middle);
});
_sessionManager.Broadcast(x =>
{
string rainbowBattleName = x.GetLanguage(GameDialogKey.RAINBOW_BATTLE_EVENT_NAME);
return x.GenerateMsgPacket(x.GetLanguageFormat(gameDialogKey, rainbowBattleName, warning.Item2), MsgMessageType.BottomCard);
});
}
private async Task ProcessRegistration(DateTime dateTime)
{
if (_rainbowBattleManager.RegistrationStartTime > dateTime)
{
return;
}
await _eventPipeline.ProcessEventAsync(new RainbowBattleStartProcessRegistrationEvent());
}
private async Task ProcessRainbowBattle(RainbowBattleParty rainbowBattleParty, DateTime dateTime)
{
ProcessStartGame(rainbowBattleParty, dateTime);
await ProcessFrozenMembers(rainbowBattleParty);
await TryEndRainbowBattle(rainbowBattleParty, dateTime);
await TryDestroyRainbowBattle(rainbowBattleParty, dateTime);
await ProcessTeamPoints(rainbowBattleParty, dateTime);
await ProcessActivityTeamPoints(rainbowBattleParty, dateTime);
await ProcessMembersLife(rainbowBattleParty, dateTime);
}
private async Task ProcessActivityTeamPoints(RainbowBattleParty rainbowBattleParty, DateTime dateTime)
{
if (!rainbowBattleParty.Started || rainbowBattleParty.FinishTime != null)
{
return;
}
if (rainbowBattleParty.LastActivityPointsTeamAdd > dateTime)
{
return;
}
rainbowBattleParty.LastActivityPointsTeamAdd = dateTime.AddSeconds(59);
await _eventPipeline.ProcessEventAsync(new RainbowBattleProcessActivityPointsEvent
{
RainbowBattleParty = rainbowBattleParty
});
}
private async Task ProcessFrozenMembers(RainbowBattleParty rainbowBattleParty)
{
if (!rainbowBattleParty.Started)
{
return;
}
await _eventPipeline.ProcessEventAsync(new RainbowBattleUnfreezeProcessEvent
{
RainbowBattleParty = rainbowBattleParty
});
}
private async Task ProcessTeamPoints(RainbowBattleParty rainbowBattleParty, DateTime dateTime)
{
if (!rainbowBattleParty.Started || rainbowBattleParty.FinishTime != null)
{
return;
}
if (rainbowBattleParty.LastPointsTeamAdd > dateTime)
{
return;
}
rainbowBattleParty.LastPointsTeamAdd = dateTime.AddSeconds(30);
await _eventPipeline.ProcessEventAsync(new RainbowBattleProcessFlagPointsEvent
{
RainbowBattleParty = rainbowBattleParty
});
}
private async Task TryEndRainbowBattle(RainbowBattleParty rainbowBattleParty, DateTime dateTime)
{
if (!rainbowBattleParty.Started || rainbowBattleParty.EndTime > dateTime || rainbowBattleParty.FinishTime != null)
{
return;
}
await _eventPipeline.ProcessEventAsync(new RainbowBattleEndEvent
{
RainbowBattleParty = rainbowBattleParty
});
}
private async Task TryDestroyRainbowBattle(RainbowBattleParty rainbowBattleParty, DateTime dateTime)
{
if (rainbowBattleParty.MapInstance != null && rainbowBattleParty.MapInstance.Sessions.Count < 1)
{
Log.Warn("[RAINBOW_SYSTEM] Destroying Rainbow Battle instance");
await _eventPipeline.ProcessEventAsync(new RainbowBattleDestroyEvent
{
RainbowBattleParty = rainbowBattleParty
});
return;
}
if (!rainbowBattleParty.Started || rainbowBattleParty.FinishTime == null)
{
return;
}
if (rainbowBattleParty.FinishTime > dateTime)
{
return;
}
Log.Warn("[RAINBOW_SYSTEM] Destroying Rainbow Battle instance");
await _eventPipeline.ProcessEventAsync(new RainbowBattleDestroyEvent
{
RainbowBattleParty = rainbowBattleParty
});
}
private async Task ProcessMembersLife(RainbowBattleParty rainbowBattleParty, DateTime dateTime)
{
if (!rainbowBattleParty.Started || rainbowBattleParty.FinishTime != null)
{
return;
}
if (rainbowBattleParty.LastMembersLife > dateTime)
{
return;
}
rainbowBattleParty.LastMembersLife = dateTime.AddSeconds(2);
await _eventPipeline.ProcessEventAsync(new RainbowBattleProcessLifeEvent
{
RainbowBattleParty = rainbowBattleParty
});
}
private void ProcessStartGame(RainbowBattleParty rainbowBattleParty, in DateTime time)
{
if (rainbowBattleParty.Started)
{
return;
}
if (rainbowBattleParty.StartTime.AddSeconds(5) > time)
{
return;
}
rainbowBattleParty.Started = true;
foreach (IClientSession session in rainbowBattleParty.MapInstance.Sessions)
{
session.SendCondPacket();
}
rainbowBattleParty.MapInstance.Broadcast(x => x.GenerateMsgPacket(x.GetLanguage(GameDialogKey.RAINBOW_BATTLE_SHOUTMESSAGE_START), MsgMessageType.Middle));
}
}
}