Add Nameplates + Clean up.
* Yeet Token! * Cleaning up workflow * Testing auto version bump * ExistingNames * Remove a key * Github Token no work * Changing Assembly Version * Version Fix * Fixing version v2 * Cleanup naming * Update LightlessSync.csproj * Add nameplate settings + run code clean up * purple
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class CharaDataConfigService : ConfigurationServiceBase<CharaDataConfig>
|
||||
{
|
||||
public const string ConfigName = "charadata.json";
|
||||
|
||||
public CharaDataConfigService(string configDir) : base(configDir) { }
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public static class ConfigurationExtensions
|
||||
{
|
||||
public static bool HasValidSetup(this LightlessConfig configuration)
|
||||
{
|
||||
return configuration.AcceptedAgreement && configuration.InitialScanComplete
|
||||
&& !string.IsNullOrEmpty(configuration.CacheFolder)
|
||||
&& Directory.Exists(configuration.CacheFolder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using LightlessSync.WebAPI;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class ConfigurationMigrator(ILogger<ConfigurationMigrator> logger, TransientConfigService transientConfigService,
|
||||
ServerConfigService serverConfigService) : IHostedService
|
||||
{
|
||||
private readonly ILogger<ConfigurationMigrator> _logger = logger;
|
||||
|
||||
public void Migrate()
|
||||
{
|
||||
if (transientConfigService.Current.Version == 0)
|
||||
{
|
||||
_logger.LogInformation("Migrating Transient Config V0 => V1");
|
||||
transientConfigService.Current.TransientConfigs.Clear();
|
||||
transientConfigService.Current.Version = 1;
|
||||
transientConfigService.Save();
|
||||
}
|
||||
|
||||
if (serverConfigService.Current.Version == 1)
|
||||
{
|
||||
_logger.LogInformation("Migrating Server Config V1 => V2");
|
||||
var centralServer = serverConfigService.Current.ServerStorage.Find(f => f.ServerName.Equals("Follow the light (Central Server EU)", StringComparison.Ordinal));
|
||||
if (centralServer != null)
|
||||
{
|
||||
centralServer.ServerName = ApiController.MainServer;
|
||||
}
|
||||
serverConfigService.Current.Version = 2;
|
||||
serverConfigService.Save();
|
||||
}
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Migrate();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
137
LightlessSync/LightlessConfiguration/ConfigurationSaveService.cs
Normal file
137
LightlessSync/LightlessConfiguration/ConfigurationSaveService.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class ConfigurationSaveService : IHostedService
|
||||
{
|
||||
private readonly HashSet<object> _configsToSave = [];
|
||||
private readonly ILogger<ConfigurationSaveService> _logger;
|
||||
private readonly SemaphoreSlim _configSaveSemaphore = new(1, 1);
|
||||
private readonly CancellationTokenSource _configSaveCheckCts = new();
|
||||
public const string BackupFolder = "config_backup";
|
||||
private readonly MethodInfo _saveMethod;
|
||||
|
||||
public ConfigurationSaveService(ILogger<ConfigurationSaveService> logger, IEnumerable<IConfigService<ILightlessConfiguration>> configs)
|
||||
{
|
||||
foreach (var config in configs)
|
||||
{
|
||||
config.ConfigSave += OnConfigurationSave;
|
||||
}
|
||||
_logger = logger;
|
||||
#pragma warning disable S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
|
||||
_saveMethod = GetType().GetMethod(nameof(SaveConfig), BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
#pragma warning restore S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
|
||||
}
|
||||
|
||||
private void OnConfigurationSave(object? sender, EventArgs e)
|
||||
{
|
||||
_configSaveSemaphore.Wait();
|
||||
_configsToSave.Add(sender!);
|
||||
_configSaveSemaphore.Release();
|
||||
}
|
||||
|
||||
private async Task PeriodicSaveCheck(CancellationToken ct)
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
await SaveConfigs().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error during SaveConfigs");
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), ct).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveConfigs()
|
||||
{
|
||||
if (_configsToSave.Count == 0) return;
|
||||
|
||||
await _configSaveSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
var configList = _configsToSave.ToList();
|
||||
_configsToSave.Clear();
|
||||
_configSaveSemaphore.Release();
|
||||
|
||||
foreach (var config in configList)
|
||||
{
|
||||
var expectedType = config.GetType().BaseType!.GetGenericArguments()[0];
|
||||
var save = _saveMethod.MakeGenericMethod(expectedType);
|
||||
await ((Task)save.Invoke(this, [config])!).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveConfig<T>(IConfigService<T> config) where T : ILightlessConfiguration
|
||||
{
|
||||
_logger.LogTrace("Saving {configName}", config.ConfigurationName);
|
||||
var configDir = config.ConfigurationPath.Replace(config.ConfigurationName, string.Empty);
|
||||
|
||||
try
|
||||
{
|
||||
var configBackupFolder = Path.Join(configDir, BackupFolder);
|
||||
if (!Directory.Exists(configBackupFolder))
|
||||
Directory.CreateDirectory(configBackupFolder);
|
||||
|
||||
var configNameSplit = config.ConfigurationName.Split(".");
|
||||
var existingConfigs = Directory.EnumerateFiles(
|
||||
configBackupFolder,
|
||||
configNameSplit[0] + "*")
|
||||
.Select(c => new FileInfo(c))
|
||||
.OrderByDescending(c => c.LastWriteTime).ToList();
|
||||
if (existingConfigs.Skip(10).Any())
|
||||
{
|
||||
foreach (var oldBak in existingConfigs.Skip(10).ToList())
|
||||
{
|
||||
oldBak.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
string backupPath = Path.Combine(configBackupFolder, configNameSplit[0] + "." + DateTime.Now.ToString("yyyyMMddHHmmss") + "." + configNameSplit[1]);
|
||||
_logger.LogTrace("Backing up current config to {backupPath}", backupPath);
|
||||
File.Copy(config.ConfigurationPath, backupPath, overwrite: true);
|
||||
FileInfo fi = new(backupPath);
|
||||
fi.LastWriteTimeUtc = DateTime.UtcNow;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ignore if file cannot be backupped
|
||||
_logger.LogWarning(ex, "Could not create backup for {config}", config.ConfigurationPath);
|
||||
}
|
||||
|
||||
var temp = config.ConfigurationPath + ".tmp";
|
||||
try
|
||||
{
|
||||
await File.WriteAllTextAsync(temp, JsonSerializer.Serialize(config.Current, typeof(T), new JsonSerializerOptions()
|
||||
{
|
||||
WriteIndented = true
|
||||
})).ConfigureAwait(false);
|
||||
File.Move(temp, config.ConfigurationPath, true);
|
||||
config.UpdateLastWriteTime();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error during config save of {config}", config.ConfigurationName);
|
||||
}
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_ = Task.Run(() => PeriodicSaveCheck(_configSaveCheckCts.Token));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _configSaveCheckCts.CancelAsync().ConfigureAwait(false);
|
||||
_configSaveCheckCts.Dispose();
|
||||
|
||||
await SaveConfigs().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
146
LightlessSync/LightlessConfiguration/ConfigurationServiceBase.cs
Normal file
146
LightlessSync/LightlessConfiguration/ConfigurationServiceBase.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public abstract class ConfigurationServiceBase<T> : IConfigService<T> where T : ILightlessConfiguration
|
||||
{
|
||||
private readonly CancellationTokenSource _periodicCheckCts = new();
|
||||
private DateTime _configLastWriteTime;
|
||||
private Lazy<T> _currentConfigInternal;
|
||||
private bool _disposed = false;
|
||||
|
||||
public event EventHandler? ConfigSave;
|
||||
|
||||
protected ConfigurationServiceBase(string configDirectory)
|
||||
{
|
||||
ConfigurationDirectory = configDirectory;
|
||||
|
||||
_ = Task.Run(CheckForConfigUpdatesInternal, _periodicCheckCts.Token);
|
||||
|
||||
_currentConfigInternal = LazyConfig();
|
||||
}
|
||||
|
||||
public string ConfigurationDirectory { get; init; }
|
||||
public T Current => _currentConfigInternal.Value;
|
||||
public abstract string ConfigurationName { get; }
|
||||
public string ConfigurationPath => Path.Combine(ConfigurationDirectory, ConfigurationName);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
ConfigSave?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void UpdateLastWriteTime()
|
||||
{
|
||||
_configLastWriteTime = GetConfigLastWriteTime();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing || _disposed) return;
|
||||
_disposed = true;
|
||||
_periodicCheckCts.Cancel();
|
||||
_periodicCheckCts.Dispose();
|
||||
}
|
||||
|
||||
protected T LoadConfig()
|
||||
{
|
||||
T? config;
|
||||
if (!File.Exists(ConfigurationPath))
|
||||
{
|
||||
config = AttemptToLoadBackup();
|
||||
if (Equals(config, default(T)))
|
||||
{
|
||||
config = (T)Activator.CreateInstance(typeof(T))!;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
config = JsonSerializer.Deserialize<T>(File.ReadAllText(ConfigurationPath));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// config failed to load for some reason
|
||||
config = AttemptToLoadBackup();
|
||||
}
|
||||
|
||||
if (config == null || Equals(config, default(T)))
|
||||
{
|
||||
config = (T)Activator.CreateInstance(typeof(T))!;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
_configLastWriteTime = GetConfigLastWriteTime();
|
||||
return config;
|
||||
}
|
||||
|
||||
private T? AttemptToLoadBackup()
|
||||
{
|
||||
var configBackupFolder = Path.Join(ConfigurationDirectory, ConfigurationSaveService.BackupFolder);
|
||||
var configNameSplit = ConfigurationName.Split(".");
|
||||
if (!Directory.Exists(configBackupFolder))
|
||||
return default;
|
||||
|
||||
var existingBackups = Directory.EnumerateFiles(configBackupFolder, configNameSplit[0] + "*").OrderByDescending(f => new FileInfo(f).LastWriteTimeUtc);
|
||||
foreach (var file in existingBackups)
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = JsonSerializer.Deserialize<T>(File.ReadAllText(file));
|
||||
if (Equals(config, default(T)))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
|
||||
File.Copy(file, ConfigurationPath, true);
|
||||
return config;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// couldn't load backup, might as well delete it
|
||||
File.Delete(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private async Task CheckForConfigUpdatesInternal()
|
||||
{
|
||||
while (!_periodicCheckCts.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), _periodicCheckCts.Token).ConfigureAwait(false);
|
||||
|
||||
var lastWriteTime = GetConfigLastWriteTime();
|
||||
if (lastWriteTime != _configLastWriteTime)
|
||||
{
|
||||
_currentConfigInternal = LazyConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime GetConfigLastWriteTime()
|
||||
{
|
||||
try { return new FileInfo(ConfigurationPath).LastWriteTimeUtc; }
|
||||
catch { return DateTime.MinValue; }
|
||||
}
|
||||
|
||||
|
||||
private Lazy<T> LazyConfig()
|
||||
{
|
||||
_configLastWriteTime = GetConfigLastWriteTime();
|
||||
return new Lazy<T>(LoadConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public class CharaDataConfig : ILightlessConfiguration
|
||||
{
|
||||
public bool OpenLightlessHubOnGposeStart { get; set; } = false;
|
||||
public string LastSavedCharaDataLocation { get; set; } = string.Empty;
|
||||
public Dictionary<string, CharaDataFavorite> FavoriteCodes { get; set; } = [];
|
||||
public bool DownloadMcdDataOnConnection { get; set; } = true;
|
||||
public int Version { get; set; } = 0;
|
||||
public bool NearbyOwnServerOnly { get; set; } = false;
|
||||
public bool NearbyIgnoreHousingLimitations { get; set; } = false;
|
||||
public bool NearbyDrawWisps { get; set; } = true;
|
||||
public int NearbyDistanceFilter { get; set; } = 100;
|
||||
public bool NearbyShowOwnData { get; set; } = false;
|
||||
public bool ShowHelpTexts { get; set; } = true;
|
||||
public bool NearbyShowAlways { get; set; } = false;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public interface ILightlessConfiguration
|
||||
{
|
||||
int Version { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
using LightlessSync.UI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
[Serializable]
|
||||
public class LightlessConfig : ILightlessConfiguration
|
||||
{
|
||||
public bool AcceptedAgreement { get; set; } = false;
|
||||
public string CacheFolder { get; set; } = string.Empty;
|
||||
public bool DisableOptionalPluginWarnings { get; set; } = false;
|
||||
public bool EnableDtrEntry { get; set; } = false;
|
||||
public bool ShowUidInDtrTooltip { get; set; } = true;
|
||||
public bool PreferNoteInDtrTooltip { get; set; } = false;
|
||||
public bool IsNameplateColorsEnabled { get; set; } = false;
|
||||
public DtrEntry.Colors NameplateColors { get; set; } = new(Foreground: 0xE69138u, Glow: 0xFFBA47u);
|
||||
public bool UseColorsInDtr { get; set; } = true;
|
||||
public DtrEntry.Colors DtrColorsDefault { get; set; } = default;
|
||||
public DtrEntry.Colors DtrColorsNotConnected { get; set; } = new(Glow: 0x0428FFu);
|
||||
public DtrEntry.Colors DtrColorsPairsInRange { get; set; } = new(Glow: 0xFFBA47u);
|
||||
public bool EnableRightClickMenus { get; set; } = true;
|
||||
public NotificationLocation ErrorNotification { get; set; } = NotificationLocation.Both;
|
||||
public string ExportFolder { get; set; } = string.Empty;
|
||||
public bool FileScanPaused { get; set; } = false;
|
||||
public NotificationLocation InfoNotification { get; set; } = NotificationLocation.Toast;
|
||||
public bool InitialScanComplete { get; set; } = false;
|
||||
public LogLevel LogLevel { get; set; } = LogLevel.Information;
|
||||
public bool LogPerformance { get; set; } = false;
|
||||
public double MaxLocalCacheInGiB { get; set; } = 20;
|
||||
public bool OpenGposeImportOnGposeStart { get; set; } = false;
|
||||
public bool OpenPopupOnAdd { get; set; } = true;
|
||||
public int ParallelDownloads { get; set; } = 10;
|
||||
public int DownloadSpeedLimitInBytes { get; set; } = 0;
|
||||
public DownloadSpeeds DownloadSpeedType { get; set; } = DownloadSpeeds.MBps;
|
||||
public bool PreferNotesOverNamesForVisible { get; set; } = false;
|
||||
public float ProfileDelay { get; set; } = 1.5f;
|
||||
public bool ProfilePopoutRight { get; set; } = false;
|
||||
public bool ProfilesAllowNsfw { get; set; } = false;
|
||||
public bool ProfilesShow { get; set; } = true;
|
||||
public bool ShowSyncshellUsersInVisible { get; set; } = true;
|
||||
public bool ShowCharacterNameInsteadOfNotesForVisible { get; set; } = false;
|
||||
public bool ShowOfflineUsersSeparately { get; set; } = true;
|
||||
public bool ShowSyncshellOfflineUsersSeparately { get; set; } = true;
|
||||
public bool GroupUpSyncshells { get; set; } = true;
|
||||
public bool ShowOnlineNotifications { get; set; } = false;
|
||||
public bool ShowOnlineNotificationsOnlyForIndividualPairs { get; set; } = true;
|
||||
public bool ShowOnlineNotificationsOnlyForNamedPairs { get; set; } = false;
|
||||
public bool ShowTransferBars { get; set; } = true;
|
||||
public bool ShowTransferWindow { get; set; } = false;
|
||||
public bool ShowUploading { get; set; } = true;
|
||||
public bool ShowUploadingBigText { get; set; } = true;
|
||||
public bool ShowVisibleUsersSeparately { get; set; } = true;
|
||||
public int TimeSpanBetweenScansInSeconds { get; set; } = 30;
|
||||
public int TransferBarsHeight { get; set; } = 12;
|
||||
public bool TransferBarsShowText { get; set; } = true;
|
||||
public int TransferBarsWidth { get; set; } = 250;
|
||||
public bool UseAlternativeFileUpload { get; set; } = false;
|
||||
public bool UseCompactor { get; set; } = false;
|
||||
public bool DebugStopWhining { get; set; } = false;
|
||||
public bool AutoPopulateEmptyNotesFromCharaName { get; set; } = false;
|
||||
public int Version { get; set; } = 1;
|
||||
public NotificationLocation WarningNotification { get; set; } = NotificationLocation.Both;
|
||||
public bool UseFocusTarget { get; set; } = false;
|
||||
public bool overrideFriendColor { get; set; } = false;
|
||||
public bool overridePartyColor { get; set; } = false;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public class PlayerPerformanceConfig : ILightlessConfiguration
|
||||
{
|
||||
public int Version { get; set; } = 1;
|
||||
public bool ShowPerformanceIndicator { get; set; } = true;
|
||||
public bool WarnOnExceedingThresholds { get; set; } = true;
|
||||
public bool WarnOnPreferredPermissionsExceedingThresholds { get; set; } = false;
|
||||
public int VRAMSizeWarningThresholdMiB { get; set; } = 375;
|
||||
public int TrisWarningThresholdThousands { get; set; } = 165;
|
||||
public bool AutoPausePlayersExceedingThresholds { get; set; } = false;
|
||||
public bool AutoPausePlayersWithPreferredPermissionsExceedingThresholds { get; set; } = false;
|
||||
public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 550;
|
||||
public int TrisAutoPauseThresholdThousands { get; set; } = 250;
|
||||
public List<string> UIDsToIgnore { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
using LightlessSync.WebAPI;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
[Serializable]
|
||||
public class ServerConfig : ILightlessConfiguration
|
||||
{
|
||||
public int CurrentServer { get; set; } = 0;
|
||||
|
||||
public List<ServerStorage> ServerStorage { get; set; } = new()
|
||||
{
|
||||
{ new ServerStorage() { ServerName = ApiController.MainServer, ServerUri = ApiController.MainServiceUri, UseOAuth2 = true } },
|
||||
};
|
||||
|
||||
public bool SendCensusData { get; set; } = false;
|
||||
public bool ShownCensusPopup { get; set; } = false;
|
||||
|
||||
public int Version { get; set; } = 2;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public class ServerTagConfig : ILightlessConfiguration
|
||||
{
|
||||
public Dictionary<string, ServerTagStorage> ServerTagStorage { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
public int Version { get; set; } = 0;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using LightlessSync.API.Data.Enum;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public class TransientConfig : ILightlessConfiguration
|
||||
{
|
||||
public Dictionary<string, TransientPlayerConfig> TransientConfigs { get; set; } = [];
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
public class TransientPlayerConfig
|
||||
{
|
||||
public List<string> GlobalPersistentCache { get; set; } = [];
|
||||
public Dictionary<uint, List<string>> JobSpecificCache { get; set; } = [];
|
||||
public Dictionary<uint, List<string>> JobSpecificPetCache { get; set; } = [];
|
||||
|
||||
public TransientPlayerConfig()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private bool ElevateIfNeeded(uint jobId, string gamePath)
|
||||
{
|
||||
// check if it's in the job cache of other jobs and elevate if needed
|
||||
foreach (var kvp in JobSpecificCache)
|
||||
{
|
||||
if (kvp.Key == jobId) continue;
|
||||
|
||||
// elevate if the gamepath is included somewhere else
|
||||
if (kvp.Value.Contains(gamePath, StringComparer.Ordinal))
|
||||
{
|
||||
JobSpecificCache[kvp.Key].Remove(gamePath);
|
||||
GlobalPersistentCache.Add(gamePath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int RemovePath(string gamePath, ObjectKind objectKind)
|
||||
{
|
||||
int removedEntries = 0;
|
||||
if (objectKind == ObjectKind.Player)
|
||||
{
|
||||
if (GlobalPersistentCache.Remove(gamePath)) removedEntries++;
|
||||
foreach (var kvp in JobSpecificCache)
|
||||
{
|
||||
if (kvp.Value.Remove(gamePath)) removedEntries++;
|
||||
}
|
||||
}
|
||||
if (objectKind == ObjectKind.Pet)
|
||||
{
|
||||
foreach (var kvp in JobSpecificPetCache)
|
||||
{
|
||||
if (kvp.Value.Remove(gamePath)) removedEntries++;
|
||||
}
|
||||
}
|
||||
return removedEntries;
|
||||
}
|
||||
|
||||
public void AddOrElevate(uint jobId, string gamePath)
|
||||
{
|
||||
// check if it's in the global cache, if yes, do nothing
|
||||
if (GlobalPersistentCache.Contains(gamePath, StringComparer.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ElevateIfNeeded(jobId, gamePath)) return;
|
||||
|
||||
// check if the jobid is already in the cache to start
|
||||
if (!JobSpecificCache.TryGetValue(jobId, out var jobCache))
|
||||
{
|
||||
JobSpecificCache[jobId] = jobCache = new();
|
||||
}
|
||||
|
||||
// check if the path is already in the job specific cache
|
||||
if (!jobCache.Contains(gamePath, StringComparer.Ordinal))
|
||||
{
|
||||
jobCache.Add(gamePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public class UidNotesConfig : ILightlessConfiguration
|
||||
{
|
||||
public Dictionary<string, ServerNotesStorage> ServerNotes { get; set; } = new(StringComparer.Ordinal);
|
||||
public int Version { get; set; } = 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
public class XivDataStorageConfig : ILightlessConfiguration
|
||||
{
|
||||
public ConcurrentDictionary<string, long> TriangleDictionary { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
public ConcurrentDictionary<string, Dictionary<string, List<ushort>>> BonesDictionary { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
public int Version { get; set; } = 0;
|
||||
}
|
||||
12
LightlessSync/LightlessConfiguration/IConfigService.cs
Normal file
12
LightlessSync/LightlessConfiguration/IConfigService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public interface IConfigService<out T> : IDisposable where T : ILightlessConfiguration
|
||||
{
|
||||
T Current { get; }
|
||||
string ConfigurationName { get; }
|
||||
string ConfigurationPath { get; }
|
||||
public event EventHandler? ConfigSave;
|
||||
void UpdateLastWriteTime();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class LightlessConfigService : ConfigurationServiceBase<LightlessConfig>
|
||||
{
|
||||
public const string ConfigName = "config.json";
|
||||
|
||||
public LightlessConfigService(string configDir) : base(configDir)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
[Serializable]
|
||||
public record Authentication
|
||||
{
|
||||
public string CharacterName { get; set; } = string.Empty;
|
||||
public uint WorldId { get; set; } = 0;
|
||||
public int SecretKeyIdx { get; set; } = -1;
|
||||
public string? UID { get; set; }
|
||||
public bool AutoLogin { get; set; } = true;
|
||||
public ulong? LastSeenCID { get; set; } = null;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
[Serializable]
|
||||
public class CharaDataFavorite
|
||||
{
|
||||
public DateTime LastDownloaded { get; set; } = DateTime.MaxValue;
|
||||
public string CustomDescription { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
public enum DownloadSpeeds
|
||||
{
|
||||
Bps,
|
||||
KBps,
|
||||
MBps
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
public enum NotificationLocation
|
||||
{
|
||||
Nowhere,
|
||||
Chat,
|
||||
Toast,
|
||||
Both
|
||||
}
|
||||
|
||||
public enum NotificationType
|
||||
{
|
||||
Info,
|
||||
Warning,
|
||||
Error
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models.Obsolete;
|
||||
|
||||
[Serializable]
|
||||
[Obsolete("Deprecated, use ServerStorage")]
|
||||
public class ServerStorageV0
|
||||
{
|
||||
public List<Authentication> Authentications { get; set; } = [];
|
||||
public bool FullPause { get; set; } = false;
|
||||
public Dictionary<string, string> GidServerComments { get; set; } = new(StringComparer.Ordinal);
|
||||
public HashSet<string> OpenPairTags { get; set; } = new(StringComparer.Ordinal);
|
||||
public Dictionary<int, SecretKey> SecretKeys { get; set; } = [];
|
||||
public HashSet<string> ServerAvailablePairTags { get; set; } = new(StringComparer.Ordinal);
|
||||
public string ServerName { get; set; } = string.Empty;
|
||||
public string ServerUri { get; set; } = string.Empty;
|
||||
public Dictionary<string, string> UidServerComments { get; set; } = new(StringComparer.Ordinal);
|
||||
public Dictionary<string, List<string>> UidServerPairedUserTags { get; set; } = new(StringComparer.Ordinal);
|
||||
|
||||
public ServerStorage ToV1()
|
||||
{
|
||||
return new ServerStorage()
|
||||
{
|
||||
ServerUri = ServerUri,
|
||||
ServerName = ServerName,
|
||||
Authentications = [.. Authentications],
|
||||
FullPause = FullPause,
|
||||
SecretKeys = SecretKeys.ToDictionary(p => p.Key, p => p.Value)
|
||||
};
|
||||
}
|
||||
}
|
||||
8
LightlessSync/LightlessConfiguration/Models/SecretKey.cs
Normal file
8
LightlessSync/LightlessConfiguration/Models/SecretKey.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
[Serializable]
|
||||
public class SecretKey
|
||||
{
|
||||
public string FriendlyName { get; set; } = string.Empty;
|
||||
public string Key { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
public class ServerNotesStorage
|
||||
{
|
||||
public Dictionary<string, string> GidServerComments { get; set; } = new(StringComparer.Ordinal);
|
||||
public Dictionary<string, string> UidServerComments { get; set; } = new(StringComparer.Ordinal);
|
||||
}
|
||||
17
LightlessSync/LightlessConfiguration/Models/ServerStorage.cs
Normal file
17
LightlessSync/LightlessConfiguration/Models/ServerStorage.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
[Serializable]
|
||||
public class ServerStorage
|
||||
{
|
||||
public List<Authentication> Authentications { get; set; } = [];
|
||||
public bool FullPause { get; set; } = false;
|
||||
public Dictionary<int, SecretKey> SecretKeys { get; set; } = [];
|
||||
public string ServerName { get; set; } = string.Empty;
|
||||
public string ServerUri { get; set; } = string.Empty;
|
||||
public bool UseOAuth2 { get; set; } = false;
|
||||
public string? OAuthToken { get; set; } = null;
|
||||
public HttpTransportType HttpTransportType { get; set; } = HttpTransportType.WebSockets;
|
||||
public bool ForceWebSockets { get; set; } = false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace LightlessSync.LightlessConfiguration.Models;
|
||||
|
||||
[Serializable]
|
||||
public class ServerTagStorage
|
||||
{
|
||||
public HashSet<string> OpenPairTags { get; set; } = new(StringComparer.Ordinal);
|
||||
public HashSet<string> ServerAvailablePairTags { get; set; } = new(StringComparer.Ordinal);
|
||||
public Dictionary<string, List<string>> UidServerPairedUserTags { get; set; } = new(StringComparer.Ordinal);
|
||||
}
|
||||
14
LightlessSync/LightlessConfiguration/NotesConfigService.cs
Normal file
14
LightlessSync/LightlessConfiguration/NotesConfigService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class NotesConfigService : ConfigurationServiceBase<UidNotesConfig>
|
||||
{
|
||||
public const string ConfigName = "notes.json";
|
||||
|
||||
public NotesConfigService(string configDir) : base(configDir)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class PlayerPerformanceConfigService : ConfigurationServiceBase<PlayerPerformanceConfig>
|
||||
{
|
||||
public const string ConfigName = "playerperformance.json";
|
||||
public PlayerPerformanceConfigService(string configDir) : base(configDir) { }
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
14
LightlessSync/LightlessConfiguration/ServerConfigService.cs
Normal file
14
LightlessSync/LightlessConfiguration/ServerConfigService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class ServerConfigService : ConfigurationServiceBase<ServerConfig>
|
||||
{
|
||||
public const string ConfigName = "server.json";
|
||||
|
||||
public ServerConfigService(string configDir) : base(configDir)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class ServerTagConfigService : ConfigurationServiceBase<ServerTagConfig>
|
||||
{
|
||||
public const string ConfigName = "servertags.json";
|
||||
|
||||
public ServerTagConfigService(string configDir) : base(configDir)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class TransientConfigService : ConfigurationServiceBase<TransientConfig>
|
||||
{
|
||||
public const string ConfigName = "transient.json";
|
||||
|
||||
public TransientConfigService(string configDir) : base(configDir)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
|
||||
namespace LightlessSync.LightlessConfiguration;
|
||||
|
||||
public class XivDataStorageService : ConfigurationServiceBase<XivDataStorageConfig>
|
||||
{
|
||||
public const string ConfigName = "xivdatastorage.json";
|
||||
|
||||
public XivDataStorageService(string configDir) : base(configDir) { }
|
||||
|
||||
public override string ConfigurationName => ConfigName;
|
||||
}
|
||||
Reference in New Issue
Block a user