210 lines
7.2 KiB
C#
210 lines
7.2 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Dalamud.Plugin.Services;
|
|
using Lumina.Excel.Sheets;
|
|
using MareSynchronos.MareConfiguration;
|
|
using MareSynchronos.MareConfiguration.Models;
|
|
using MareSynchronos.Services;
|
|
using MareSynchronos.Services.Mediator;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace MareSynchronos.Services.AutoDetect;
|
|
|
|
public sealed class AutoDetectSuppressionService : IHostedService, IMediatorSubscriber
|
|
{
|
|
private static readonly string[] ContentTypeKeywords =
|
|
[
|
|
"dungeon",
|
|
"donjon",
|
|
"raid",
|
|
"trial",
|
|
"défi",
|
|
"front",
|
|
"frontline",
|
|
"pvp",
|
|
"jcj",
|
|
"conflict",
|
|
"conflit"
|
|
];
|
|
|
|
private readonly ILogger<AutoDetectSuppressionService> _logger;
|
|
private readonly MareConfigService _configService;
|
|
private readonly IClientState _clientState;
|
|
private readonly IDataManager _dataManager;
|
|
private readonly MareMediator _mediator;
|
|
private readonly DalamudUtilService _dalamudUtilService;
|
|
|
|
private bool _isSuppressed;
|
|
private bool _hasSavedState;
|
|
private bool _savedDiscoveryEnabled;
|
|
private bool _savedAllowRequests;
|
|
private bool _suppressionWarningShown;
|
|
public bool IsSuppressed => _isSuppressed;
|
|
|
|
public AutoDetectSuppressionService(ILogger<AutoDetectSuppressionService> logger,
|
|
MareConfigService configService, IClientState clientState,
|
|
IDataManager dataManager, DalamudUtilService dalamudUtilService, MareMediator mediator)
|
|
{
|
|
_logger = logger;
|
|
_configService = configService;
|
|
_clientState = clientState;
|
|
_dataManager = dataManager;
|
|
_dalamudUtilService = dalamudUtilService;
|
|
_mediator = mediator;
|
|
}
|
|
|
|
public MareMediator Mediator => _mediator;
|
|
|
|
public Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
_mediator.Subscribe<ZoneSwitchEndMessage>(this, _ => UpdateSuppressionState());
|
|
_mediator.Subscribe<DalamudLoginMessage>(this, _ => UpdateSuppressionState());
|
|
_mediator.Subscribe<DalamudLogoutMessage>(this, _ => ClearSuppression());
|
|
UpdateSuppressionState();
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_mediator.UnsubscribeAll(this);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private void UpdateSuppressionState()
|
|
{
|
|
_ = _dalamudUtilService.RunOnFrameworkThread(() =>
|
|
{
|
|
try
|
|
{
|
|
if (!_clientState.IsLoggedIn || _clientState.LocalPlayer == null)
|
|
{
|
|
ClearSuppression();
|
|
return;
|
|
}
|
|
|
|
uint territoryId = _clientState.TerritoryType;
|
|
bool shouldSuppress = ShouldSuppressForTerritory(territoryId);
|
|
ApplySuppression(shouldSuppress, territoryId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Failed to update AutoDetect suppression state");
|
|
}
|
|
});
|
|
}
|
|
|
|
private void ApplySuppression(bool shouldSuppress, uint territoryId)
|
|
{
|
|
if (shouldSuppress)
|
|
{
|
|
if (!_isSuppressed)
|
|
{
|
|
_savedDiscoveryEnabled = _configService.Current.EnableAutoDetectDiscovery;
|
|
_savedAllowRequests = _configService.Current.AllowAutoDetectPairRequests;
|
|
_hasSavedState = true;
|
|
_isSuppressed = true;
|
|
}
|
|
|
|
bool changed = false;
|
|
if (_configService.Current.EnableAutoDetectDiscovery)
|
|
{
|
|
_configService.Current.EnableAutoDetectDiscovery = false;
|
|
changed = true;
|
|
}
|
|
if (_configService.Current.AllowAutoDetectPairRequests)
|
|
{
|
|
_configService.Current.AllowAutoDetectPairRequests = false;
|
|
changed = true;
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
_logger.LogInformation("AutoDetect temporarily disabled in instanced content (territory {territoryId}).", territoryId);
|
|
if (!_suppressionWarningShown)
|
|
{
|
|
_suppressionWarningShown = true;
|
|
const string warningText = "Zone instanciée détectée : les fonctions AutoDetect/Nearby sont coupées pour économiser de la bande passante.";
|
|
_mediator.Publish(new DualNotificationMessage("AutoDetect désactivé",
|
|
warningText,
|
|
NotificationType.Warning, TimeSpan.FromSeconds(5)));
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (!_isSuppressed) return;
|
|
|
|
bool changed = false;
|
|
bool wasSuppressed = _suppressionWarningShown;
|
|
if (_hasSavedState)
|
|
{
|
|
if (_configService.Current.EnableAutoDetectDiscovery != _savedDiscoveryEnabled)
|
|
{
|
|
_configService.Current.EnableAutoDetectDiscovery = _savedDiscoveryEnabled;
|
|
changed = true;
|
|
}
|
|
if (_configService.Current.AllowAutoDetectPairRequests != _savedAllowRequests)
|
|
{
|
|
_configService.Current.AllowAutoDetectPairRequests = _savedAllowRequests;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
_isSuppressed = false;
|
|
_hasSavedState = false;
|
|
_suppressionWarningShown = false;
|
|
|
|
if (changed || wasSuppressed)
|
|
{
|
|
_logger.LogInformation("AutoDetect restored after leaving instanced content (territory {territoryId}).", territoryId);
|
|
const string restoredText = "Vous avez quitté la zone instanciée : AutoDetect/Nearby fonctionnent de nouveau.";
|
|
_mediator.Publish(new DualNotificationMessage("AutoDetect réactivé",
|
|
restoredText,
|
|
NotificationType.Info, TimeSpan.FromSeconds(5)));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ClearSuppression()
|
|
{
|
|
if (!_isSuppressed) return;
|
|
_isSuppressed = false;
|
|
if (_hasSavedState)
|
|
{
|
|
_configService.Current.EnableAutoDetectDiscovery = _savedDiscoveryEnabled;
|
|
_configService.Current.AllowAutoDetectPairRequests = _savedAllowRequests;
|
|
}
|
|
_hasSavedState = false;
|
|
_suppressionWarningShown = false;
|
|
}
|
|
|
|
private bool ShouldSuppressForTerritory(uint territoryId)
|
|
{
|
|
if (territoryId == 0) return false;
|
|
|
|
var cfcSheet = _dataManager.GetExcelSheet<ContentFinderCondition>();
|
|
if (cfcSheet == null) return false;
|
|
|
|
var cfc = cfcSheet.FirstOrDefault(c => c.TerritoryType.RowId == territoryId);
|
|
if (cfc.RowId == 0) return false;
|
|
|
|
if (MatchesSuppressionKeyword(cfc.Name.ToString())) return true;
|
|
|
|
var contentType = cfc.ContentType.Value;
|
|
if (contentType.RowId == 0) return false;
|
|
|
|
return MatchesSuppressionKeyword(contentType.Name.ToString());
|
|
}
|
|
|
|
private static bool MatchesSuppressionKeyword(string? text)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text)) return false;
|
|
return ContentTypeKeywords.Any(keyword => text.Contains(keyword, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
}
|