Compare commits
15 Commits
4688043f6a
...
main-legac
| Author | SHA1 | Date | |
|---|---|---|---|
|
46f2443824
|
|||
|
eeab8354b6
|
|||
|
b5d8f288f9
|
|||
| 3c2dab4d21 | |||
| edb49f710a | |||
| 9ff21dc341 | |||
| 17962a37b3 | |||
| 4495177f02 | |||
| 14bb5c14f7 | |||
| 6101686a33 | |||
| bc6cde48de | |||
| 9ce213f949 | |||
| cd5bf3f06f | |||
| 52eaa0cf95 | |||
| 6edb90f4d7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,14 +2,13 @@
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
.idea
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.bak
|
||||
.DS_Store
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
|
||||
12
.gitmodules
vendored
12
.gitmodules
vendored
@@ -1,12 +1,12 @@
|
||||
[submodule "UmbraAPI"]
|
||||
path = UmbraAPI
|
||||
[submodule "MareAPI"]
|
||||
path = MareAPI
|
||||
url = https://git.umbra-sync.net/SirConstance/UmbraAPI.git
|
||||
branch = main
|
||||
[submodule "Penumbra.Api"]
|
||||
path = Penumbra.Api
|
||||
url = https://github.com/Ottermandias/Penumbra.Api.git
|
||||
branch = main
|
||||
[submodule "Glamourer.Api"]
|
||||
path = Glamourer.Api
|
||||
url = https://github.com/Ottermandias/Glamourer.Api
|
||||
[submodule "Chaos.NaCl"]
|
||||
path = Chaos.NaCl
|
||||
url = https://github.com/CodesInChaos/Chaos.NaCl.git
|
||||
url = https://github.com/Ottermandias/Glamourer.Api.git
|
||||
branch = main
|
||||
|
||||
Submodule Chaos.NaCl deleted from 2c861348dc
1
Glamourer.Api
Submodule
1
Glamourer.Api
Submodule
Submodule Glamourer.Api added at 54c1944dc7
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mare Synchronos
|
||||
Copyright (c) 2022 Penumbra-Sync
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
1
MareAPI
Submodule
1
MareAPI
Submodule
Submodule MareAPI added at ff262bf690
@@ -5,7 +5,7 @@ VisualStudioVersion = 17.1.32328.378
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos", "MareSynchronos\MareSynchronos.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos.API", "UmbraAPI\MareSynchronosAPI\MareSynchronos.API.csproj", "{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos.API", "MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj", "{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{585B740D-BA2C-429B-9CF3-B2D223423748}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
||||
BIN
MareSynchronos/.DS_Store
vendored
Normal file
BIN
MareSynchronos/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -122,24 +122,24 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
||||
|
||||
public bool StorageisNTFS { get; private set; } = false;
|
||||
|
||||
public void StartMareWatcher(string? marePath)
|
||||
public void StartMareWatcher(string? snowPath)
|
||||
{
|
||||
MareWatcher?.Dispose();
|
||||
if (string.IsNullOrEmpty(marePath) || !Directory.Exists(marePath))
|
||||
if (string.IsNullOrEmpty(snowPath) || !Directory.Exists(snowPath))
|
||||
{
|
||||
MareWatcher = null;
|
||||
Logger.LogWarning("Mare file path is not set, cannot start the FSW for Mare.");
|
||||
Logger.LogWarning("Umbra file path is not set, cannot start the FSW for Umbra.");
|
||||
return;
|
||||
}
|
||||
|
||||
DriveInfo di = new(new DirectoryInfo(_configService.Current.CacheFolder).Root.FullName);
|
||||
StorageisNTFS = string.Equals("NTFS", di.DriveFormat, StringComparison.OrdinalIgnoreCase);
|
||||
Logger.LogInformation("Mare Storage is on NTFS drive: {isNtfs}", StorageisNTFS);
|
||||
Logger.LogInformation("Umbra Storage is on NTFS drive: {isNtfs}", StorageisNTFS);
|
||||
|
||||
Logger.LogDebug("Initializing Mare FSW on {path}", marePath);
|
||||
Logger.LogDebug("Initializing Mare FSW on {path}", snowPath);
|
||||
MareWatcher = new()
|
||||
{
|
||||
Path = marePath,
|
||||
Path = snowPath,
|
||||
InternalBufferSize = 8388608,
|
||||
NotifyFilter = NotifyFilters.CreationTime
|
||||
| NotifyFilters.LastWrite
|
||||
@@ -161,7 +161,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
||||
if (string.IsNullOrEmpty(substPath))
|
||||
{
|
||||
SubstWatcher = null;
|
||||
Logger.LogWarning("Mare file path is not set, cannot start the FSW for Mare.");
|
||||
Logger.LogWarning("Umbra file path is not set, cannot start the FSW for Umbra.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
||||
|
||||
private void MareWatcher_FileChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
Logger.LogTrace("Mare FSW: FileChanged: {change} => {path}", e.ChangeType, e.FullPath);
|
||||
Logger.LogTrace("Umbra FSW: FileChanged: {change} => {path}", e.ChangeType, e.FullPath);
|
||||
|
||||
if (!AllowedFileExtensions.Any(ext => e.FullPath.EndsWith(ext, StringComparison.OrdinalIgnoreCase))) return;
|
||||
|
||||
@@ -631,7 +631,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
||||
if (string.IsNullOrEmpty(_configService.Current.CacheFolder) || !Directory.Exists(_configService.Current.CacheFolder))
|
||||
{
|
||||
cacheDirExists = false;
|
||||
Logger.LogWarning("UmbraSync Cache directory is not set or does not exist.");
|
||||
Logger.LogWarning("Umbra Cache directory is not set or does not exist.");
|
||||
}
|
||||
if (!penDirExists || !cacheDirExists)
|
||||
{
|
||||
|
||||
@@ -236,7 +236,6 @@ public sealed class FileCacheManager : IHostedService
|
||||
|
||||
foreach (var entry in cleanedPaths)
|
||||
{
|
||||
//_logger.LogDebug("Checking {path}", entry.Value);
|
||||
|
||||
if (dict.TryGetValue(entry.Value, out var entity))
|
||||
{
|
||||
@@ -366,7 +365,6 @@ public sealed class FileCacheManager : IHostedService
|
||||
|
||||
if (!entries.Exists(u => string.Equals(u.PrefixedFilePath, fileCache.PrefixedFilePath, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
//_logger.LogTrace("Adding to DB: {hash} => {path}", fileCache.Hash, fileCache.PrefixedFilePath);
|
||||
entries.Add(fileCache);
|
||||
}
|
||||
}
|
||||
@@ -389,7 +387,6 @@ public sealed class FileCacheManager : IHostedService
|
||||
private FileCacheEntity? GetValidatedFileCache(FileCacheEntity fileCache)
|
||||
{
|
||||
var resultingFileCache = ReplacePathPrefixes(fileCache);
|
||||
//_logger.LogTrace("Validating {path}", fileCache.PrefixedFilePath);
|
||||
resultingFileCache = Validate(resultingFileCache);
|
||||
return resultingFileCache;
|
||||
}
|
||||
@@ -465,7 +462,7 @@ public sealed class FileCacheManager : IHostedService
|
||||
if (!_ipcManager.Penumbra.APIAvailable || string.IsNullOrEmpty(_ipcManager.Penumbra.ModDirectory))
|
||||
{
|
||||
_mareMediator.Publish(new NotificationMessage("Penumbra not connected",
|
||||
"Could not load local file cache data. Penumbra is not connected or not properly set up. Please enable and/or configure Penumbra properly to use UmbraSync. After, reload UmbraSync in the Plugin installer.",
|
||||
"Could not load local file cache data. Penumbra is not connected or not properly set up. Please enable and/or configure Penumbra properly to use Umbra. After, reload Umbra in the Plugin installer.",
|
||||
MareConfiguration.Models.NotificationType.Error));
|
||||
}
|
||||
|
||||
|
||||
@@ -95,8 +95,6 @@ public sealed class IpcCallerBrio : IIpcCaller
|
||||
if (gameObject == null) return default;
|
||||
var data = await _dalamudUtilService.RunOnFrameworkThread(() => _brioGetModelTransform.InvokeFunc(gameObject)).ConfigureAwait(false);
|
||||
if (data.Item1 == null || data.Item2 == null || data.Item3 == null) return default;
|
||||
//_logger.LogDebug("Getting Transform from Actor {actor}", gameObject.Name.TextValue);
|
||||
|
||||
return new WorldData()
|
||||
{
|
||||
PositionX = data.Item1.Value.X,
|
||||
|
||||
@@ -109,7 +109,7 @@ public sealed class IpcCallerGlamourer : DisposableMediatorSubscriberBase, IIpcC
|
||||
if (!apiAvailable && !_shownGlamourerUnavailable)
|
||||
{
|
||||
_shownGlamourerUnavailable = true;
|
||||
_mareMediator.Publish(new NotificationMessage("Glamourer inactive", "Your Glamourer installation is not active or out of date. Update Glamourer to continue to use UmbraSync. If you just updated Glamourer, ignore this message.",
|
||||
_mareMediator.Publish(new NotificationMessage("Glamourer inactive", "Your Glamourer installation is not active or out of date. Update Glamourer to continue to use Umbra. If you just updated Glamourer, ignore this message.",
|
||||
NotificationType.Error));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ public sealed class IpcCallerMoodles : IIpcCaller
|
||||
|
||||
_moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version");
|
||||
_moodlesOnChange = pi.GetIpcSubscriber<IPlayerCharacter, object>("Moodles.StatusManagerModified");
|
||||
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtr");
|
||||
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtr");
|
||||
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtr");
|
||||
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtrV2");
|
||||
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtrV2");
|
||||
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtrV2");
|
||||
|
||||
_moodlesOnChange.Subscribe(OnMoodlesChange);
|
||||
|
||||
@@ -47,7 +47,7 @@ public sealed class IpcCallerMoodles : IIpcCaller
|
||||
{
|
||||
try
|
||||
{
|
||||
APIAvailable = _moodlesApiVersion.InvokeFunc() == 1;
|
||||
APIAvailable = _moodlesApiVersion.InvokeFunc() == 3;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -114,7 +114,7 @@ public sealed class IpcCallerPenumbra : DisposableMediatorSubscriberBase, IIpcCa
|
||||
bool penumbraAvailable = false;
|
||||
try
|
||||
{
|
||||
penumbraAvailable = _pluginLoaded && _pluginVersion >= new Version(1, 0, 1, 0);
|
||||
penumbraAvailable = _pluginLoaded && _pluginVersion >= new Version(1, 5, 1, 0);
|
||||
try
|
||||
{
|
||||
penumbraAvailable &= _penumbraEnabled.Invoke();
|
||||
@@ -136,7 +136,7 @@ public sealed class IpcCallerPenumbra : DisposableMediatorSubscriberBase, IIpcCa
|
||||
{
|
||||
_shownPenumbraUnavailable = true;
|
||||
_mareMediator.Publish(new NotificationMessage("Penumbra inactive",
|
||||
"Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use UmbraSync. If you just updated Penumbra, ignore this message.",
|
||||
"Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Umbra. If you just updated Penumbra, ignore this message.",
|
||||
NotificationType.Error));
|
||||
}
|
||||
}
|
||||
@@ -225,9 +225,15 @@ public sealed class IpcCallerPenumbra : DisposableMediatorSubscriberBase, IIpcCa
|
||||
|
||||
return await _dalamudUtil.RunOnFrameworkThread(() =>
|
||||
{
|
||||
var collName = "UmbraSync_" + uid;
|
||||
var collId = _penumbraCreateNamedTemporaryCollection.Invoke(collName);
|
||||
Guid collId;
|
||||
var collName = "ElfSync_" + uid;
|
||||
PenumbraApiEc penEC = _penumbraCreateNamedTemporaryCollection.Invoke(uid, collName, out collId);
|
||||
logger.LogTrace("Creating Temp Collection {collName}, GUID: {collId}", collName, collId);
|
||||
if (penEC != PenumbraApiEc.Success)
|
||||
{
|
||||
logger.LogError("Failed to create temporary collection for {collName} with error code {penEC}. Please include this line in any error reports", collName, penEC);
|
||||
return Guid.Empty;
|
||||
}
|
||||
return collId;
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
@@ -30,12 +30,12 @@ public sealed class IpcCallerPetNames : IIpcCaller
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_mareMediator = mareMediator;
|
||||
|
||||
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.Ready");
|
||||
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.Disposing");
|
||||
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.OnReady");
|
||||
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.OnDisposing");
|
||||
_apiVersion = pi.GetIpcSubscriber<(uint, uint)>("PetRenamer.ApiVersion");
|
||||
_enabled = pi.GetIpcSubscriber<bool>("PetRenamer.Enabled");
|
||||
_enabled = pi.GetIpcSubscriber<bool>("PetRenamer.IsEnabled");
|
||||
|
||||
_playerDataChanged = pi.GetIpcSubscriber<string, object>("PetRenamer.PlayerDataChanged");
|
||||
_playerDataChanged = pi.GetIpcSubscriber<string, object>("PetRenamer.OnPlayerDataChanged");
|
||||
_getPlayerData = pi.GetIpcSubscriber<string>("PetRenamer.GetPlayerData");
|
||||
_setPlayerData = pi.GetIpcSubscriber<string, object>("PetRenamer.SetPlayerData");
|
||||
_clearPlayerData = pi.GetIpcSubscriber<ushort, object>("PetRenamer.ClearPlayerData");
|
||||
@@ -56,7 +56,7 @@ public sealed class IpcCallerPetNames : IIpcCaller
|
||||
APIAvailable = _enabled?.InvokeFunc() ?? false;
|
||||
if (APIAvailable)
|
||||
{
|
||||
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 3, Item2: >= 1 };
|
||||
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 4, Item2: >= 0 };
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -66,11 +66,11 @@ public class IpcProvider : IHostedService, IMediatorSubscriber
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogDebug("Starting IpcProvider Service");
|
||||
_loadFileProvider = _pi.GetIpcProvider<string, IGameObject, bool>("UmbraSyncSync.LoadMcdf");
|
||||
_loadFileProvider = _pi.GetIpcProvider<string, IGameObject, bool>("ElfSync.LoadMcdf");
|
||||
_loadFileProvider.RegisterFunc(LoadMcdf);
|
||||
_loadFileAsyncProvider = _pi.GetIpcProvider<string, IGameObject, Task<bool>>("UmbraSyncSync.LoadMcdfAsync");
|
||||
_loadFileAsyncProvider = _pi.GetIpcProvider<string, IGameObject, Task<bool>>("UmbraSync.LoadMcdfAsync");
|
||||
_loadFileAsyncProvider.RegisterFunc(LoadMcdfAsync);
|
||||
_handledGameAddresses = _pi.GetIpcProvider<List<nint>>("UmbraSyncSync.GetHandledAddresses");
|
||||
_handledGameAddresses = _pi.GetIpcProvider<List<nint>>("UmbraSync.GetHandledAddresses");
|
||||
_handledGameAddresses.RegisterFunc(GetHandledAddresses);
|
||||
|
||||
_loadFileProviderMare = _pi.GetIpcProvider<string, IGameObject, bool>("MareSynchronos.LoadMcdf");
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace MareSynchronos.MareConfiguration.Configurations;
|
||||
[Serializable]
|
||||
public class MareConfig : IMareConfiguration
|
||||
{
|
||||
public int ExpectedTOSVersion = 2;
|
||||
public int AcceptedTOSVersion { get; set; } = 0;
|
||||
public bool AcceptedAgreement { get; set; } = false;
|
||||
public string CacheFolder { get; set; } = string.Empty;
|
||||
public bool DisableOptionalPluginWarnings { get; set; } = false;
|
||||
@@ -31,7 +33,7 @@ public class MareConfig : IMareConfiguration
|
||||
public bool LogPerformance { get; set; } = false;
|
||||
public bool LogEvents { get; set; } = true;
|
||||
public bool HoldCombatApplication { get; set; } = false;
|
||||
public double MaxLocalCacheInGiB { get; set; } = 20;
|
||||
public double MaxLocalCacheInGiB { get; set; } = 100;
|
||||
public bool OpenGposeImportOnGposeStart { get; set; } = false;
|
||||
public bool OpenPopupOnAdd { get; set; } = true;
|
||||
public int ParallelDownloads { get; set; } = 10;
|
||||
|
||||
@@ -5,11 +5,11 @@ namespace MareSynchronos.MareConfiguration.Configurations;
|
||||
public class PlayerPerformanceConfig : IMareConfiguration
|
||||
{
|
||||
public int Version { get; set; } = 1;
|
||||
public bool AutoPausePlayersExceedingThresholds { get; set; } = false;
|
||||
public bool AutoPausePlayersExceedingThresholds { get; set; } = true;
|
||||
public bool NotifyAutoPauseDirectPairs { get; set; } = true;
|
||||
public bool NotifyAutoPauseGroupPairs { get; set; } = false;
|
||||
public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 550;
|
||||
public int TrisAutoPauseThresholdThousands { get; set; } = 375;
|
||||
public bool NotifyAutoPauseGroupPairs { get; set; } = true;
|
||||
public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 500;
|
||||
public int TrisAutoPauseThresholdThousands { get; set; } = 400;
|
||||
public bool IgnoreDirectPairs { get; set; } = true;
|
||||
public TextureShrinkMode TextureShrinkMode { get; set; } = TextureShrinkMode.Default;
|
||||
public bool TextureShrinkDeleteOriginal { get; set; } = false;
|
||||
|
||||
@@ -10,7 +10,7 @@ public class ServerConfig : IMareConfiguration
|
||||
|
||||
public List<ServerStorage> ServerStorage { get; set; } = new()
|
||||
{
|
||||
{ new ServerStorage() { ServerName = ApiController.UmbraSyncServer, ServerUri = ApiController.UmbraSyncServiceUri } },
|
||||
{ new ServerStorage() { ServerName = ApiController.UmbraServer, ServerUri = ApiController.UmbraServiceUri } },
|
||||
};
|
||||
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
@@ -89,9 +89,9 @@ public class MarePlugin : MediatorSubscriberBase, IHostedService
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
Logger.LogInformation("Launching {name} {major}.{minor}.{build}.{rev}", "UmbraSync", version.Major, version.Minor, version.Build, version.Revision);
|
||||
Logger.LogInformation("Launching {name} {major}.{minor}.{build}.{rev}", "Umbra Sync", version.Major, version.Minor, version.Build, version.Revision);
|
||||
Mediator.Publish(new EventMessage(new Services.Events.Event(nameof(MarePlugin), Services.Events.EventSeverity.Informational,
|
||||
$"Starting UmbraSync {version.Major}.{version.Minor}.{version.Build}.{version.Revision}")));
|
||||
$"Starting Umbra Sync {version.Major}.{version.Minor}.{version.Build}.{version.Revision}")));
|
||||
|
||||
Mediator.Subscribe<SwitchToMainUiMessage>(this, (msg) => { if (_launchTask == null || _launchTask.IsCompleted) _launchTask = Task.Run(WaitForPlayerAndLaunchCharacterManager); });
|
||||
Mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn());
|
||||
@@ -157,7 +157,7 @@ public class MarePlugin : MediatorSubscriberBase, IHostedService
|
||||
if (_mareConfigService.Current.LogLevel != LogLevel.Information)
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Abnormal Log Level",
|
||||
$"Your log level is set to '{_mareConfigService.Current.LogLevel}' which is not recommended for normal usage. Set it to '{LogLevel.Information}' in \"UmbraSync Settings -> Debug\" unless instructed otherwise.",
|
||||
$"Your log level is set to '{_mareConfigService.Current.LogLevel}' which is not recommended for normal usage. Set it to '{LogLevel.Information}' in \"Umbra Settings -> Debug\" unless instructed otherwise.",
|
||||
MareConfiguration.Models.NotificationType.Error, TimeSpan.FromSeconds(15000)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
||||
<PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyName>UmbraSync</AssemblyName>
|
||||
<Version>1.0.0</Version>
|
||||
<PackageProjectUrl></PackageProjectUrl>
|
||||
</PropertyGroup>
|
||||
<RootNamespace>UmbraSync</RootNamespace>
|
||||
<Version>0.1.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="PlayerData\Export\**" />
|
||||
@@ -13,37 +13,38 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Chaos.NaCl.Standard" Version="1.0.0" />
|
||||
<PackageReference Include="Downloader" Version="3.3.4" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Legacy" Version="1.3.8" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.3.8" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.189">
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.212">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.3" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.7.0.110445">
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.8" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.15.0.120848">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.7.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('..\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
<ProjectReference Include="..\Penumbra.Api\Penumbra.Api.csproj" />
|
||||
<ItemGroup Condition="Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
<ProjectReference Include=".\Penumbra.Api\Penumbra.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="!Exists('..\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
<PackageReference Include="Penumbra.Api" Version="5.6.1" />
|
||||
<ItemGroup Condition="!Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
<PackageReference Include="Penumbra.Api" Version="5.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('..\Glamourer.Api\Glamourer.Api.csproj')">
|
||||
<ProjectReference Include="..\Glamourer.Api\Glamourer.Api.csproj" />
|
||||
<ItemGroup Condition="Exists('.\Glamourer.Api\Glamourer.Api.csproj')">
|
||||
<ProjectReference Include=".\Glamourer.Api\Glamourer.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="!Exists('..\Glamourer.Api\Glamourer.Api.csproj')">
|
||||
<PackageReference Include="Glamourer.Api" Version="2.4.1" />
|
||||
<ItemGroup Condition="!Exists('.\Glamourer.Api\Glamourer.Api.csproj')">
|
||||
<PackageReference Include="Glamourer.Api" Version="2.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -52,14 +53,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UmbraAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||
<ProjectReference Include="..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('..\\Chaos.NaCl\\Chaos.NaCl\\Chaos.NaCl.csproj')">
|
||||
<ProjectReference Include="..\\Chaos.NaCl\\Chaos.NaCl\\Chaos.NaCl.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -27,14 +27,13 @@ public class PairHandlerFactory
|
||||
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
||||
private readonly PairAnalyzerFactory _pairAnalyzerFactory;
|
||||
private readonly VisibilityService _visibilityService;
|
||||
private readonly NoSnapService _noSnapService;
|
||||
|
||||
public PairHandlerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
|
||||
FileDownloadManagerFactory fileDownloadManagerFactory, DalamudUtilService dalamudUtilService,
|
||||
PluginWarningNotificationService pluginWarningNotificationManager, IHostApplicationLifetime hostApplicationLifetime,
|
||||
FileCacheManager fileCacheManager, MareMediator mareMediator, PlayerPerformanceService playerPerformanceService,
|
||||
ServerConfigurationManager serverConfigManager, PairAnalyzerFactory pairAnalyzerFactory,
|
||||
MareConfigService configService, VisibilityService visibilityService, NoSnapService noSnapService)
|
||||
MareConfigService configService, VisibilityService visibilityService)
|
||||
{
|
||||
_loggerFactory = loggerFactory;
|
||||
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
||||
@@ -50,13 +49,12 @@ public class PairHandlerFactory
|
||||
_pairAnalyzerFactory = pairAnalyzerFactory;
|
||||
_configService = configService;
|
||||
_visibilityService = visibilityService;
|
||||
_noSnapService = noSnapService;
|
||||
}
|
||||
|
||||
public PairHandler Create(Pair pair)
|
||||
{
|
||||
return new PairHandler(_loggerFactory.CreateLogger<PairHandler>(), pair, _pairAnalyzerFactory.Create(pair), _gameObjectHandlerFactory,
|
||||
_ipcManager, _fileDownloadManagerFactory.Create(), _pluginWarningNotificationManager, _dalamudUtilService, _hostApplicationLifetime,
|
||||
_fileCacheManager, _mareMediator, _playerPerformanceService, _serverConfigManager, _configService, _visibilityService, _noSnapService);
|
||||
_fileCacheManager, _mareMediator, _playerPerformanceService, _serverConfigManager, _configService, _visibilityService);
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
||||
private readonly ServerConfigurationManager _serverConfigManager;
|
||||
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
||||
private readonly VisibilityService _visibilityService;
|
||||
private readonly NoSnapService _noSnapService;
|
||||
private CancellationTokenSource? _applicationCancellationTokenSource = new();
|
||||
private Guid _applicationId;
|
||||
private Task? _applicationTask;
|
||||
@@ -55,8 +54,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
||||
FileCacheManager fileDbManager, MareMediator mediator,
|
||||
PlayerPerformanceService playerPerformanceService,
|
||||
ServerConfigurationManager serverConfigManager,
|
||||
MareConfigService configService, VisibilityService visibilityService,
|
||||
NoSnapService noSnapService) : base(logger, mediator)
|
||||
MareConfigService configService, VisibilityService visibilityService) : base(logger, mediator)
|
||||
{
|
||||
Pair = pair;
|
||||
PairAnalyzer = pairAnalyzer;
|
||||
@@ -70,7 +68,6 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
||||
_serverConfigManager = serverConfigManager;
|
||||
_configService = configService;
|
||||
_visibilityService = visibilityService;
|
||||
_noSnapService = noSnapService;
|
||||
|
||||
_visibilityService.StartTracking(Pair.Ident);
|
||||
|
||||
@@ -319,24 +316,6 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
||||
});
|
||||
}
|
||||
|
||||
private void RegisterGposeClones()
|
||||
{
|
||||
var name = PlayerName;
|
||||
if (name == null)
|
||||
return;
|
||||
_ = _dalamudUtil.RunOnFrameworkThread(() =>
|
||||
{
|
||||
foreach (var actor in _dalamudUtil.GetGposeCharactersFromObjectTable())
|
||||
{
|
||||
if (actor == null) continue;
|
||||
var gposeName = actor.Name.TextValue;
|
||||
if (!name.Equals(gposeName, StringComparison.Ordinal))
|
||||
continue;
|
||||
_noSnapService.AddGposer(actor.ObjectIndex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task UndoApplicationAsync(Guid applicationId = default)
|
||||
{
|
||||
Logger.LogDebug($"Undoing application of {Pair.UserPair}");
|
||||
@@ -353,7 +332,6 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
||||
{
|
||||
await _ipcManager.Penumbra.RemoveTemporaryCollectionAsync(Logger, applicationId, _penumbraCollection).ConfigureAwait(false);
|
||||
_penumbraCollection = Guid.Empty;
|
||||
RegisterGposeClones();
|
||||
}
|
||||
|
||||
if (_dalamudUtil is { IsZoning: false, IsInCutscene: false } && !string.IsNullOrEmpty(name))
|
||||
@@ -385,10 +363,6 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_dalamudUtil.IsInCutscene && !string.IsNullOrEmpty(name))
|
||||
{
|
||||
_noSnapService.AddGposerNamed(name);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -86,8 +86,8 @@ public class Pair : DisposableMediatorSubscriberBase
|
||||
{
|
||||
Name = name,
|
||||
OnClicked = action,
|
||||
PrefixColor = 559,
|
||||
PrefixChar = 'L'
|
||||
PrefixColor = 526,
|
||||
PrefixChar = 'S'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -171,11 +171,6 @@ public class Pair : DisposableMediatorSubscriberBase
|
||||
if (_serverConfigurationManager.IsUidBlacklisted(UserData.UID))
|
||||
HoldApplication("Blacklist", maxValue: 1);
|
||||
|
||||
if (NoSnapService.AnyLoaded)
|
||||
HoldApplication("NoSnap", maxValue: 1);
|
||||
else
|
||||
UnholdApplication("NoSnap", skipApplication: true);
|
||||
|
||||
CachedPlayer.ApplyCharacterData(Guid.NewGuid(), RemoveNotSyncedFiles(LastReceivedCharacterData.DeepClone())!, forced);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ using MareSynchronos.Services.CharaData;
|
||||
|
||||
using MareSynchronos;
|
||||
|
||||
namespace UmbraSyncSync;
|
||||
namespace Umbra;
|
||||
|
||||
public sealed class Plugin : IDalamudPlugin
|
||||
{
|
||||
@@ -39,8 +39,6 @@ public sealed class Plugin : IDalamudPlugin
|
||||
public static Plugin Self;
|
||||
#pragma warning restore CA2211, CS8618, MA0069, S1104, S2223
|
||||
public Action<IFramework>? RealOnFrameworkUpdate { get; set; }
|
||||
|
||||
// Proxy function in the UmbraSyncSync namespace to avoid confusion in /xlstats
|
||||
public void OnFrameworkUpdate(IFramework framework)
|
||||
{
|
||||
RealOnFrameworkUpdate?.Invoke(framework);
|
||||
@@ -126,7 +124,6 @@ public sealed class Plugin : IDalamudPlugin
|
||||
collection.AddSingleton<BlockedCharacterHandler>();
|
||||
collection.AddSingleton<IpcProvider>();
|
||||
collection.AddSingleton<VisibilityService>();
|
||||
collection.AddSingleton<RepoChangeService>();
|
||||
collection.AddSingleton<EventAggregator>();
|
||||
collection.AddSingleton<DalamudUtilService>();
|
||||
collection.AddSingleton<DtrEntry>();
|
||||
@@ -143,7 +140,6 @@ public sealed class Plugin : IDalamudPlugin
|
||||
collection.AddSingleton<IpcCallerMare>();
|
||||
collection.AddSingleton<IpcManager>();
|
||||
collection.AddSingleton<NotificationService>();
|
||||
collection.AddSingleton<NoSnapService>();
|
||||
|
||||
collection.AddSingleton((s) => new MareConfigService(pluginInterface.ConfigDirectory.FullName));
|
||||
collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName));
|
||||
@@ -169,7 +165,6 @@ public sealed class Plugin : IDalamudPlugin
|
||||
collection.AddSingleton<IConfigService<IMareConfiguration>>(s => s.GetRequiredService<RemoteConfigCacheService>());
|
||||
collection.AddSingleton<ConfigurationMigrator>();
|
||||
collection.AddSingleton<ConfigurationSaveService>();
|
||||
collection.AddSingleton<RemoteConfigurationService>();
|
||||
|
||||
collection.AddSingleton<HubFactory>();
|
||||
|
||||
@@ -210,8 +205,6 @@ public sealed class Plugin : IDalamudPlugin
|
||||
collection.AddHostedService(p => p.GetRequiredService<EventAggregator>());
|
||||
collection.AddHostedService(p => p.GetRequiredService<MarePlugin>());
|
||||
collection.AddHostedService(p => p.GetRequiredService<IpcProvider>());
|
||||
collection.AddHostedService(p => p.GetRequiredService<RepoChangeService>());
|
||||
collection.AddHostedService(p => p.GetRequiredService<NoSnapService>());
|
||||
})
|
||||
.Build();
|
||||
|
||||
|
||||
@@ -13,20 +13,18 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly NoSnapService _noSnapService;
|
||||
private readonly Dictionary<string, HandledCharaDataEntry> _handledCharaData = new(StringComparer.Ordinal);
|
||||
|
||||
public IReadOnlyDictionary<string, HandledCharaDataEntry> HandledCharaData => _handledCharaData;
|
||||
|
||||
public CharaDataCharacterHandler(ILogger<CharaDataCharacterHandler> logger, MareMediator mediator,
|
||||
GameObjectHandlerFactory gameObjectHandlerFactory, DalamudUtilService dalamudUtilService,
|
||||
IpcManager ipcManager, NoSnapService noSnapService)
|
||||
IpcManager ipcManager)
|
||||
: base(logger, mediator)
|
||||
{
|
||||
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
_ipcManager = ipcManager;
|
||||
_noSnapService = noSnapService;
|
||||
mediator.Subscribe<GposeEndMessage>(this, msg =>
|
||||
{
|
||||
foreach (var chara in _handledCharaData)
|
||||
@@ -94,7 +92,6 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
_handledCharaData.Remove(handled.Name);
|
||||
await _dalamudUtilService.RunOnFrameworkThread(async () =>
|
||||
{
|
||||
RemoveGposer(handled);
|
||||
await RevertChara(handled.Name, handled.CustomizePlus).ConfigureAwait(false);
|
||||
}).ConfigureAwait(false);
|
||||
return true;
|
||||
@@ -103,7 +100,6 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
internal void AddHandledChara(HandledCharaDataEntry handledCharaDataEntry)
|
||||
{
|
||||
_handledCharaData.Add(handledCharaDataEntry.Name, handledCharaDataEntry);
|
||||
_ = _dalamudUtilService.RunOnFrameworkThread(() => AddGposer(handledCharaDataEntry));
|
||||
}
|
||||
|
||||
public void UpdateHandledData(Dictionary<string, CharaDataMetaInfoExtendedDto?> newData)
|
||||
@@ -134,23 +130,4 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
if (handler.Address == nint.Zero) return null;
|
||||
return handler;
|
||||
}
|
||||
|
||||
private int GetGposerObjectIndex(string name)
|
||||
{
|
||||
return _dalamudUtilService.GetGposeCharacterFromObjectTableByName(name, _dalamudUtilService.IsInGpose)?.ObjectIndex ?? -1;
|
||||
}
|
||||
|
||||
private void AddGposer(HandledCharaDataEntry handled)
|
||||
{
|
||||
int objectIndex = GetGposerObjectIndex(handled.Name);
|
||||
if (objectIndex > 0)
|
||||
_noSnapService.AddGposer(objectIndex);
|
||||
}
|
||||
|
||||
private void RemoveGposer(HandledCharaDataEntry handled)
|
||||
{
|
||||
int objectIndex = GetGposerObjectIndex(handled.Name);
|
||||
if (objectIndex > 0)
|
||||
_noSnapService.RemoveGposer(objectIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class ChatService : DisposableMediatorSubscriberBase
|
||||
{
|
||||
var chatMsg = message.ChatMsg;
|
||||
var prefix = new SeStringBuilder();
|
||||
prefix.AddText("[BnnuyChat] ");
|
||||
prefix.AddText("[UmbraChat] ");
|
||||
_chatGui.Print(new XivChatEntry{
|
||||
MessageBytes = [..prefix.Build().Encode(), ..message.ChatMsg.PayloadContent],
|
||||
Name = chatMsg.SenderName,
|
||||
@@ -207,7 +207,7 @@ public class ChatService : DisposableMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
_chatGui.PrintError($"[UmbraSyncSync] Syncshell number #{shellNumber} not found");
|
||||
_chatGui.PrintError($"[UmbraSync] Syncshell number #{shellNumber} not found");
|
||||
}
|
||||
|
||||
public void SendChatShell(int shellNumber, byte[] chatBytes)
|
||||
@@ -236,6 +236,6 @@ public class ChatService : DisposableMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
_chatGui.PrintError($"[UmbraSyncSync] Syncshell number #{shellNumber} not found");
|
||||
_chatGui.PrintError($"[UmbraSync] Syncshell number #{shellNumber} not found");
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace MareSynchronos.Services;
|
||||
public sealed class CommandManagerService : IDisposable
|
||||
{
|
||||
private const string _commandName = "/sync";
|
||||
private const string _commandName2 = "/loporrit";
|
||||
private const string _commandName2 = "/usync";
|
||||
|
||||
private const string _ssCommandPrefix = "/ss";
|
||||
|
||||
@@ -42,11 +42,11 @@ public sealed class CommandManagerService : IDisposable
|
||||
_mareConfigService = mareConfigService;
|
||||
_commandManager.AddHandler(_commandName, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = "Opens the UmbraSync UI"
|
||||
HelpMessage = "Opens the Umbra UI"
|
||||
});
|
||||
_commandManager.AddHandler(_commandName2, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = "Opens the UmbraSync UI"
|
||||
HelpMessage = "Opens the Umbra UI"
|
||||
});
|
||||
|
||||
// Lazy registration of all possible /ss# commands which tbf is what the game does for linkshells anyway
|
||||
@@ -86,7 +86,7 @@ public sealed class CommandManagerService : IDisposable
|
||||
{
|
||||
if (_apiController.ServerState == WebAPI.SignalR.Utils.ServerState.Disconnecting)
|
||||
{
|
||||
_mediator.Publish(new NotificationMessage("UmbraSync disconnecting", "Cannot use /toggle while UmbraSync is still disconnecting",
|
||||
_mediator.Publish(new NotificationMessage("Umbra disconnecting", "Cannot use /toggle while Umbra is still disconnecting",
|
||||
NotificationType.Error));
|
||||
}
|
||||
|
||||
|
||||
@@ -462,9 +462,9 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
||||
{
|
||||
_logger.LogInformation("Starting DalamudUtilService");
|
||||
#pragma warning disable S2696 // Instance members should not write to "static" fields
|
||||
UmbraSyncSync.Plugin.Self.RealOnFrameworkUpdate = this.FrameworkOnUpdate;
|
||||
Umbra.Plugin.Self.RealOnFrameworkUpdate = this.FrameworkOnUpdate;
|
||||
#pragma warning restore S2696
|
||||
_framework.Update += UmbraSyncSync.Plugin.Self.OnFrameworkUpdate;
|
||||
_framework.Update += Umbra.Plugin.Self.OnFrameworkUpdate;
|
||||
if (IsLoggedIn)
|
||||
{
|
||||
_classJobId = _clientState.LocalPlayer!.ClassJob.RowId;
|
||||
@@ -479,7 +479,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
||||
_logger.LogTrace("Stopping {type}", GetType());
|
||||
|
||||
Mediator.UnsubscribeAll(this);
|
||||
_framework.Update -= UmbraSyncSync.Plugin.Self.OnFrameworkUpdate;
|
||||
_framework.Update -= Umbra.Plugin.Self.OnFrameworkUpdate;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using MareSynchronos.Interop.Ipc;
|
||||
using MareSynchronos.MareConfiguration.Models;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MareSynchronos.Services;
|
||||
|
||||
public sealed class NoSnapService : IHostedService, IMediatorSubscriber
|
||||
{
|
||||
private record NoSnapConfig
|
||||
{
|
||||
[JsonPropertyName("listOfPlugins")]
|
||||
public string[]? ListOfPlugins { get; set; }
|
||||
}
|
||||
|
||||
private readonly ILogger<NoSnapService> _logger;
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private readonly Dictionary<string, bool> _listOfPlugins = new(StringComparer.Ordinal)
|
||||
{
|
||||
["Snapper"] = false,
|
||||
["Snappy"] = false,
|
||||
["Meddle.Plugin"] = false,
|
||||
};
|
||||
private static readonly HashSet<int> _gposers = new();
|
||||
private static readonly HashSet<string> _gposersNamed = new(StringComparer.Ordinal);
|
||||
private readonly IHostApplicationLifetime _hostApplicationLifetime;
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly RemoteConfigurationService _remoteConfig;
|
||||
|
||||
public static bool AnyLoaded { get; private set; } = false;
|
||||
public static string ActivePlugins { get; private set; } = string.Empty;
|
||||
|
||||
public MareMediator Mediator { get; init; }
|
||||
|
||||
public NoSnapService(ILogger<NoSnapService> logger, IDalamudPluginInterface pluginInterface, MareMediator mediator,
|
||||
IHostApplicationLifetime hostApplicationLifetime, DalamudUtilService dalamudUtilService, IpcManager ipcManager,
|
||||
RemoteConfigurationService remoteConfig)
|
||||
{
|
||||
_logger = logger;
|
||||
_pluginInterface = pluginInterface;
|
||||
Mediator = mediator;
|
||||
_hostApplicationLifetime = hostApplicationLifetime;
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
_ipcManager = ipcManager;
|
||||
_remoteConfig = remoteConfig;
|
||||
|
||||
Mediator.Subscribe<GposeEndMessage>(this, msg => ClearGposeList());
|
||||
Mediator.Subscribe<CutsceneEndMessage>(this, msg => ClearGposeList());
|
||||
}
|
||||
|
||||
public void AddGposer(int objectIndex)
|
||||
{
|
||||
if (AnyLoaded || _hostApplicationLifetime.ApplicationStopping.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogTrace("Immediately reverting object index {id}", objectIndex);
|
||||
RevertAndRedraw(objectIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogTrace("Registering gposer object index {id}", objectIndex);
|
||||
lock (_gposers)
|
||||
_gposers.Add(objectIndex);
|
||||
}
|
||||
|
||||
public void RemoveGposer(int objectIndex)
|
||||
{
|
||||
_logger.LogTrace("Un-registering gposer object index {id}", objectIndex);
|
||||
lock (_gposers)
|
||||
_gposers.Remove(objectIndex);
|
||||
}
|
||||
|
||||
public void AddGposerNamed(string name)
|
||||
{
|
||||
if (AnyLoaded || _hostApplicationLifetime.ApplicationStopping.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogTrace("Immediately reverting {name}", name);
|
||||
RevertAndRedraw(name);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogTrace("Registering gposer {name}", name);
|
||||
lock (_gposers)
|
||||
_gposersNamed.Add(name);
|
||||
}
|
||||
|
||||
private void ClearGposeList()
|
||||
{
|
||||
if (_gposers.Count > 0 || _gposersNamed.Count > 0)
|
||||
_logger.LogTrace("Clearing gposer list");
|
||||
lock (_gposers)
|
||||
_gposers.Clear();
|
||||
lock (_gposersNamed)
|
||||
_gposersNamed.Clear();
|
||||
}
|
||||
|
||||
private void RevertAndRedraw(int objIndex, Guid applicationId = default)
|
||||
{
|
||||
if (applicationId == default)
|
||||
applicationId = Guid.NewGuid();
|
||||
|
||||
try
|
||||
{
|
||||
_ipcManager.Glamourer.RevertNow(_logger, applicationId, objIndex);
|
||||
_ipcManager.Penumbra.RedrawNow(_logger, applicationId, objIndex);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RevertAndRedraw(string name, Guid applicationId = default)
|
||||
{
|
||||
if (applicationId == default)
|
||||
applicationId = Guid.NewGuid();
|
||||
|
||||
try
|
||||
{
|
||||
_ipcManager.Glamourer.RevertByNameNow(_logger, applicationId, name);
|
||||
var addr = _dalamudUtilService.GetPlayerCharacterFromCachedTableByName(name);
|
||||
if (addr != 0)
|
||||
{
|
||||
var obj = _dalamudUtilService.CreateGameObject(addr);
|
||||
if (obj != null)
|
||||
_ipcManager.Penumbra.RedrawNow(_logger, applicationId, obj.ObjectIndex);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RevertGposers()
|
||||
{
|
||||
List<int>? gposersList = null;
|
||||
List<string>? gposersList2 = null;
|
||||
|
||||
lock (_gposers)
|
||||
{
|
||||
if (_gposers.Count > 0)
|
||||
{
|
||||
gposersList = _gposers.ToList();
|
||||
_gposers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
lock (_gposersNamed)
|
||||
{
|
||||
if (_gposersNamed.Count > 0)
|
||||
{
|
||||
gposersList2 = _gposersNamed.ToList();
|
||||
_gposersNamed.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (gposersList == null && gposersList2 == null)
|
||||
return;
|
||||
|
||||
_logger.LogInformation("Reverting gposers");
|
||||
|
||||
_dalamudUtilService.RunOnFrameworkThread(() =>
|
||||
{
|
||||
Guid applicationId = Guid.NewGuid();
|
||||
|
||||
foreach (var gposer in gposersList ?? [])
|
||||
RevertAndRedraw(gposer, applicationId);
|
||||
|
||||
foreach (var gposerName in gposersList2 ?? [])
|
||||
RevertAndRedraw(gposerName, applicationId);
|
||||
}).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var config = await _remoteConfig.GetConfigAsync<NoSnapConfig>("noSnap").ConfigureAwait(false) ?? new();
|
||||
|
||||
if (config.ListOfPlugins != null)
|
||||
{
|
||||
_listOfPlugins.Clear();
|
||||
foreach (var pluginName in config.ListOfPlugins)
|
||||
_listOfPlugins.TryAdd(pluginName, value: false);
|
||||
}
|
||||
|
||||
foreach (var pluginName in _listOfPlugins.Keys)
|
||||
{
|
||||
_listOfPlugins[pluginName] = PluginWatcherService.GetInitialPluginState(_pluginInterface, pluginName)?.IsLoaded ?? false;
|
||||
Mediator.SubscribeKeyed<PluginChangeMessage>(this, pluginName, (msg) =>
|
||||
{
|
||||
_listOfPlugins[pluginName] = msg.IsLoaded;
|
||||
_logger.LogDebug("{pluginName} isLoaded = {isLoaded}", pluginName, msg.IsLoaded);
|
||||
Update();
|
||||
});
|
||||
}
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
RevertGposers();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
bool anyLoadedNow = _listOfPlugins.Values.Any(p => p);
|
||||
|
||||
if (AnyLoaded != anyLoadedNow)
|
||||
{
|
||||
AnyLoaded = anyLoadedNow;
|
||||
Mediator.Publish(new RecalculatePerformanceMessage(null));
|
||||
|
||||
if (AnyLoaded)
|
||||
{
|
||||
RevertGposers();
|
||||
var pluginList = string.Join(", ", _listOfPlugins.Where(p => p.Value).Select(p => p.Key));
|
||||
Mediator.Publish(new NotificationMessage("Incompatible plugin loaded", $"Synced player appearances will not apply until incompatible plugins are disabled: {pluginList}.",
|
||||
NotificationType.Error));
|
||||
ActivePlugins = pluginList;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivePlugins = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,19 +41,19 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
|
||||
|
||||
private void PrintErrorChat(string? message)
|
||||
{
|
||||
SeStringBuilder se = new SeStringBuilder().AddText("[UmbraSyncSync] Error: " + message);
|
||||
SeStringBuilder se = new SeStringBuilder().AddText("[UmbraSync] Error: " + message);
|
||||
_chatGui.PrintError(se.BuiltString);
|
||||
}
|
||||
|
||||
private void PrintInfoChat(string? message)
|
||||
{
|
||||
SeStringBuilder se = new SeStringBuilder().AddText("[UmbraSyncSync] Info: ").AddItalics(message ?? string.Empty);
|
||||
SeStringBuilder se = new SeStringBuilder().AddText("[UmbraSync] Info: ").AddItalics(message ?? string.Empty);
|
||||
_chatGui.Print(se.BuiltString);
|
||||
}
|
||||
|
||||
private void PrintWarnChat(string? message)
|
||||
{
|
||||
SeStringBuilder se = new SeStringBuilder().AddText("[UmbraSyncSync] ").AddUiForeground("Warning: " + (message ?? string.Empty), 31).AddUiForegroundOff();
|
||||
SeStringBuilder se = new SeStringBuilder().AddText("[UmbraSync] ").AddUiForeground("Warning: " + (message ?? string.Empty), 31).AddUiForegroundOff();
|
||||
_chatGui.Print(se.BuiltString);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
using Chaos.NaCl;
|
||||
using MareSynchronos.MareConfiguration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace MareSynchronos.Services;
|
||||
|
||||
public sealed class RemoteConfigurationService
|
||||
{
|
||||
private readonly static Dictionary<string, string> ConfigPublicKeys = new(StringComparer.Ordinal)
|
||||
{
|
||||
{ "UMBR4KEY", "+MwCXedODmU+yD7vtdI+Ho2iLx+PV3U0H2XRLP/gReA=" }
|
||||
};
|
||||
|
||||
private readonly static string[] ConfigSources = [
|
||||
"https://umbra-sync.net/config/umbra.json"
|
||||
];
|
||||
|
||||
private readonly ILogger<RemoteConfigurationService> _logger;
|
||||
private readonly RemoteConfigCacheService _configService;
|
||||
private readonly Task _initTask;
|
||||
|
||||
public RemoteConfigurationService(ILogger<RemoteConfigurationService> logger, RemoteConfigCacheService configService)
|
||||
{
|
||||
_logger = logger;
|
||||
_configService = configService;
|
||||
_initTask = Task.Run(DownloadConfig);
|
||||
}
|
||||
|
||||
public async Task<JsonObject> GetConfigAsync(string sectionName)
|
||||
{
|
||||
await _initTask.ConfigureAwait(false);
|
||||
if (!_configService.Current.Configuration.TryGetPropertyValue(sectionName, out var section))
|
||||
section = null;
|
||||
return (section as JsonObject) ?? new();
|
||||
}
|
||||
|
||||
public async Task<T?> GetConfigAsync<T>(string sectionName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = await GetConfigAsync(sectionName).ConfigureAwait(false);
|
||||
return JsonSerializer.Deserialize<T>(json);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Invalid JSON in remote config: {sectionName}", sectionName);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadConfig()
|
||||
{
|
||||
string? jsonResponse = null;
|
||||
|
||||
foreach (var remoteUrl in ConfigSources)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Fetching {url}", remoteUrl);
|
||||
|
||||
using var httpClient = new HttpClient(
|
||||
new HttpClientHandler
|
||||
{
|
||||
AllowAutoRedirect = true,
|
||||
MaxAutomaticRedirections = 5
|
||||
}
|
||||
);
|
||||
|
||||
httpClient.Timeout = TimeSpan.FromSeconds(6);
|
||||
|
||||
var ver = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MareSynchronos", ver!.Major + "." + ver!.Minor + "." + ver!.Build));
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, remoteUrl);
|
||||
|
||||
if (remoteUrl.Equals(_configService.Current.Origin, StringComparison.Ordinal))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_configService.Current.ETag))
|
||||
request.Headers.IfNoneMatch.Add(new EntityTagHeaderValue(_configService.Current.ETag));
|
||||
|
||||
if (_configService.Current.LastModified != null)
|
||||
request.Headers.IfModifiedSince = _configService.Current.LastModified;
|
||||
}
|
||||
|
||||
var response = await httpClient.SendAsync(request).ConfigureAwait(false);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NotModified)
|
||||
{
|
||||
_logger.LogDebug("Using cached remote configuration from {url}", remoteUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var contentType = response.Content.Headers.ContentType?.MediaType;
|
||||
|
||||
if (contentType == null || !contentType.Equals("application/json", StringComparison.Ordinal))
|
||||
{
|
||||
_logger.LogWarning("HTTP request for remote config failed: wrong MIME type");
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Downloaded new configuration from {url}", remoteUrl);
|
||||
|
||||
_configService.Current.Origin = remoteUrl;
|
||||
_configService.Current.ETag = response.Headers.ETag?.ToString() ?? string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
if (response.Content.Headers.Contains("Last-Modified"))
|
||||
{
|
||||
var lastModified = response.Content.Headers.GetValues("Last-Modified").First();
|
||||
_configService.Current.LastModified = DateTimeOffset.Parse(lastModified, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_configService.Current.LastModified = null;
|
||||
}
|
||||
|
||||
jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "HTTP request for remote config failed");
|
||||
|
||||
if (remoteUrl.Equals(_configService.Current.Origin, StringComparison.Ordinal))
|
||||
{
|
||||
_configService.Current.ETag = string.Empty;
|
||||
_configService.Current.LastModified = null;
|
||||
_configService.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
_logger.LogWarning("Could not download remote config");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var jsonDoc = JsonNode.Parse(jsonResponse) as JsonObject;
|
||||
|
||||
if (jsonDoc == null)
|
||||
{
|
||||
_logger.LogWarning("Downloaded remote config is not a JSON object");
|
||||
return;
|
||||
}
|
||||
|
||||
LoadConfig(jsonDoc);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Invalid JSON in remote config response");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool VerifySignature(string message, ulong ts, string signature, string pubKey)
|
||||
{
|
||||
byte[] msg = [.. BitConverter.GetBytes(ts), .. Encoding.UTF8.GetBytes(message)];
|
||||
byte[] sig = Convert.FromBase64String(signature);
|
||||
byte[] pub = Convert.FromBase64String(pubKey);
|
||||
return Ed25519.Verify(sig, msg, pub);
|
||||
}
|
||||
|
||||
private void LoadConfig(JsonObject jsonDoc)
|
||||
{
|
||||
var ts = jsonDoc["ts"]!.GetValue<ulong>();
|
||||
|
||||
if (ts <= _configService.Current.Timestamp)
|
||||
{
|
||||
_logger.LogDebug("Remote configuration is not newer than cached config");
|
||||
return;
|
||||
}
|
||||
|
||||
var signatures = jsonDoc["sig"]!.AsObject();
|
||||
var configString = jsonDoc["config"]!.GetValue<string>();
|
||||
bool verified = signatures.Any(sig =>
|
||||
ConfigPublicKeys.TryGetValue(sig.Key, out var pubKey) &&
|
||||
VerifySignature(configString, ts, sig.Value!.GetValue<string>(), pubKey));
|
||||
|
||||
if (!verified)
|
||||
{
|
||||
_logger.LogWarning("Could not verify signature for downloaded remote config");
|
||||
return;
|
||||
}
|
||||
|
||||
_configService.Current.Configuration = JsonNode.Parse(configString)!.AsObject();
|
||||
_configService.Current.Timestamp = ts;
|
||||
_configService.Save();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MareSynchronos.Services;
|
||||
|
||||
public record RepoChangeConfig
|
||||
{
|
||||
[JsonPropertyName("current_repo")]
|
||||
public string? CurrentRepo { get; set; }
|
||||
|
||||
[JsonPropertyName("valid_repos")]
|
||||
public string[]? ValidRepos { get; set; }
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MareSynchronos.Services;
|
||||
|
||||
/* Reflection code based almost entirely on ECommons DalamudReflector
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 NightmareXIV
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
public sealed class RepoChangeService : IHostedService
|
||||
{
|
||||
#region Reflection Helpers
|
||||
private const BindingFlags AllFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
|
||||
private const BindingFlags StaticFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
private const BindingFlags InstanceFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
|
||||
private static object GetFoP(object obj, string name)
|
||||
{
|
||||
Type? type = obj.GetType();
|
||||
while (type != null)
|
||||
{
|
||||
var fieldInfo = type.GetField(name, AllFlags);
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
return fieldInfo.GetValue(obj)!;
|
||||
}
|
||||
var propertyInfo = type.GetProperty(name, AllFlags);
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
return propertyInfo.GetValue(obj)!;
|
||||
}
|
||||
type = type.BaseType;
|
||||
}
|
||||
throw new Exception($"Reflection GetFoP failed (not found: {obj.GetType().Name}.{name})");
|
||||
}
|
||||
|
||||
private static T GetFoP<T>(object obj, string name)
|
||||
{
|
||||
return (T)GetFoP(obj, name);
|
||||
}
|
||||
|
||||
private static void SetFoP(object obj, string name, object value)
|
||||
{
|
||||
var type = obj.GetType();
|
||||
var field = type.GetField(name, AllFlags);
|
||||
if (field != null)
|
||||
{
|
||||
field.SetValue(obj, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var prop = type.GetProperty(name, AllFlags)!;
|
||||
if (prop == null)
|
||||
throw new Exception($"Reflection SetFoP failed (not found: {type.Name}.{name})");
|
||||
prop.SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static object? Call(object obj, string name, object[] @params, bool matchExactArgumentTypes = false)
|
||||
{
|
||||
MethodInfo? info;
|
||||
var type = obj.GetType();
|
||||
if (!matchExactArgumentTypes)
|
||||
{
|
||||
info = type.GetMethod(name, AllFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = type.GetMethod(name, AllFlags, @params.Select(x => x.GetType()).ToArray());
|
||||
}
|
||||
if (info == null)
|
||||
throw new Exception($"Reflection Call failed (not found: {type.Name}.{name})");
|
||||
return info.Invoke(obj, @params);
|
||||
}
|
||||
|
||||
private static T Call<T>(object obj, string name, object[] @params, bool matchExactArgumentTypes = false)
|
||||
{
|
||||
return (T)Call(obj, name, @params, matchExactArgumentTypes)!;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Dalamud Reflection
|
||||
public object GetService(string serviceFullName)
|
||||
{
|
||||
return _pluginInterface.GetType().Assembly.
|
||||
GetType("Dalamud.Service`1", true)!.MakeGenericType(_pluginInterface.GetType().Assembly.GetType(serviceFullName, true)!).
|
||||
GetMethod("Get")!.Invoke(null, BindingFlags.Default, null, Array.Empty<object>(), null)!;
|
||||
}
|
||||
|
||||
private object GetPluginManager()
|
||||
{
|
||||
return _pluginInterface.GetType().Assembly.
|
||||
GetType("Dalamud.Service`1", true)!.MakeGenericType(_pluginInterface.GetType().Assembly.GetType("Dalamud.Plugin.Internal.PluginManager", true)!).
|
||||
GetMethod("Get")!.Invoke(null, BindingFlags.Default, null, Array.Empty<object>(), null)!;
|
||||
}
|
||||
|
||||
private void ReloadPluginMasters()
|
||||
{
|
||||
var mgr = GetService("Dalamud.Plugin.Internal.PluginManager");
|
||||
var pluginReload = mgr.GetType().GetMethod("SetPluginReposFromConfigAsync", BindingFlags.Instance | BindingFlags.Public)!;
|
||||
pluginReload.Invoke(mgr, [true]);
|
||||
}
|
||||
|
||||
public void SaveDalamudConfig()
|
||||
{
|
||||
var conf = GetService("Dalamud.Configuration.Internal.DalamudConfiguration");
|
||||
var configSave = conf?.GetType().GetMethod("QueueSave", BindingFlags.Instance | BindingFlags.Public);
|
||||
configSave?.Invoke(conf, null);
|
||||
}
|
||||
|
||||
private IEnumerable<object> GetRepoByURL(string repoURL)
|
||||
{
|
||||
var conf = GetService("Dalamud.Configuration.Internal.DalamudConfiguration");
|
||||
var repolist = (System.Collections.IEnumerable)GetFoP(conf, "ThirdRepoList");
|
||||
foreach (var r in repolist)
|
||||
{
|
||||
if (((string)GetFoP(r, "Url")).Equals(repoURL, StringComparison.OrdinalIgnoreCase))
|
||||
yield return r;
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasRepo(string repoURL)
|
||||
{
|
||||
var conf = GetService("Dalamud.Configuration.Internal.DalamudConfiguration");
|
||||
var repolist = (System.Collections.IEnumerable)GetFoP(conf, "ThirdRepoList");
|
||||
foreach (var r in repolist)
|
||||
{
|
||||
if (((string)GetFoP(r, "Url")).Equals(repoURL, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddRepo(string repoURL, bool enabled)
|
||||
{
|
||||
var conf = GetService("Dalamud.Configuration.Internal.DalamudConfiguration");
|
||||
var repolist = (System.Collections.IEnumerable)GetFoP(conf, "ThirdRepoList");
|
||||
foreach (var r in repolist)
|
||||
{
|
||||
if (((string)GetFoP(r, "Url")).Equals(repoURL, StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
}
|
||||
var instance = Activator.CreateInstance(_pluginInterface.GetType().Assembly.GetType("Dalamud.Configuration.ThirdPartyRepoSettings")!)!;
|
||||
SetFoP(instance, "Url", repoURL);
|
||||
SetFoP(instance, "IsEnabled", enabled);
|
||||
GetFoP<System.Collections.IList>(conf, "ThirdRepoList").Add(instance!);
|
||||
}
|
||||
|
||||
private void RemoveRepo(string repoURL)
|
||||
{
|
||||
var toRemove = new List<object>();
|
||||
var conf = GetService("Dalamud.Configuration.Internal.DalamudConfiguration");
|
||||
var repolist = (System.Collections.IList)GetFoP(conf, "ThirdRepoList");
|
||||
foreach (var r in repolist)
|
||||
{
|
||||
if (((string)GetFoP(r, "Url")).Equals(repoURL, StringComparison.OrdinalIgnoreCase))
|
||||
toRemove.Add(r);
|
||||
}
|
||||
foreach (var r in toRemove)
|
||||
repolist.Remove(r);
|
||||
}
|
||||
|
||||
public List<(object LocalPlugin, string InstalledFromUrl)> GetLocalPluginsByName(string internalName)
|
||||
{
|
||||
List<(object LocalPlugin, string RepoURL)> result = [];
|
||||
|
||||
var pluginManager = GetPluginManager();
|
||||
var installedPlugins = (System.Collections.IList)pluginManager.GetType().GetProperty("InstalledPlugins")!.GetValue(pluginManager)!;
|
||||
|
||||
foreach (var plugin in installedPlugins)
|
||||
{
|
||||
if (((string)plugin.GetType().GetProperty("InternalName")!.GetValue(plugin)!).Equals(internalName, StringComparison.Ordinal))
|
||||
{
|
||||
var type = plugin.GetType();
|
||||
if (type.Name.Equals("LocalDevPlugin", StringComparison.Ordinal))
|
||||
continue;
|
||||
var manifest = GetFoP(plugin, "manifest");
|
||||
string installedFromUrl = (string)GetFoP(manifest, "InstalledFromUrl");
|
||||
result.Add((plugin, installedFromUrl));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private readonly ILogger<RepoChangeService> _logger;
|
||||
private readonly RemoteConfigurationService _remoteConfig;
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private readonly IFramework _framework;
|
||||
|
||||
public RepoChangeService(ILogger<RepoChangeService> logger, RemoteConfigurationService remoteConfig, IDalamudPluginInterface pluginInterface, IFramework framework)
|
||||
{
|
||||
_logger = logger;
|
||||
_remoteConfig = remoteConfig;
|
||||
_pluginInterface = pluginInterface;
|
||||
_framework = framework;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogDebug("Starting RepoChange Service");
|
||||
var repoChangeConfig = await _remoteConfig.GetConfigAsync<RepoChangeConfig>("repoChange").ConfigureAwait(false) ?? new();
|
||||
|
||||
var currentRepo = repoChangeConfig.CurrentRepo;
|
||||
var validRepos = (repoChangeConfig.ValidRepos ?? []).ToList();
|
||||
|
||||
if (!currentRepo.IsNullOrEmpty() && !validRepos.Contains(currentRepo, StringComparer.Ordinal))
|
||||
validRepos.Add(currentRepo);
|
||||
|
||||
if (validRepos.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("No valid repos configured, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
await _framework.RunOnTick(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var internalName = Assembly.GetExecutingAssembly().GetName().Name!;
|
||||
var localPlugins = GetLocalPluginsByName(internalName);
|
||||
|
||||
var suffix = string.Empty;
|
||||
|
||||
if (localPlugins.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("Skipping: No intalled plugin found");
|
||||
return;
|
||||
}
|
||||
|
||||
var hasValidCustomRepoUrl = false;
|
||||
|
||||
foreach (var vr in validRepos)
|
||||
{
|
||||
var vrCN = vr.Replace(".json", "_CN.json", StringComparison.Ordinal);
|
||||
var vrKR = vr.Replace(".json", "_KR.json", StringComparison.Ordinal);
|
||||
if (HasRepo(vr) || HasRepo(vrCN) || HasRepo(vrKR))
|
||||
{
|
||||
hasValidCustomRepoUrl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
List<string> oldRepos = [];
|
||||
var pluginRepoUrl = localPlugins[0].InstalledFromUrl;
|
||||
|
||||
if (pluginRepoUrl.Contains("_CN.json", StringComparison.Ordinal))
|
||||
suffix = "_CN";
|
||||
else if (pluginRepoUrl.Contains("_KR.json", StringComparison.Ordinal))
|
||||
suffix = "_KR";
|
||||
|
||||
bool hasOldPluginRepoUrl = false;
|
||||
|
||||
foreach (var plugin in localPlugins)
|
||||
{
|
||||
foreach (var vr in validRepos)
|
||||
{
|
||||
var validRepo = vr.Replace(".json", $"{suffix}.json");
|
||||
if (!plugin.InstalledFromUrl.Equals(validRepo, StringComparison.Ordinal))
|
||||
{
|
||||
oldRepos.Add(plugin.InstalledFromUrl);
|
||||
hasOldPluginRepoUrl = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasValidCustomRepoUrl)
|
||||
{
|
||||
if (hasOldPluginRepoUrl)
|
||||
_logger.LogInformation("Result: Repo URL is up to date, but plugin install source is incorrect");
|
||||
else
|
||||
_logger.LogInformation("Result: Repo URL is up to date");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Result: Repo URL needs to be replaced");
|
||||
}
|
||||
|
||||
if (currentRepo.IsNullOrEmpty())
|
||||
{
|
||||
_logger.LogWarning("No current repo URL configured");
|
||||
return;
|
||||
}
|
||||
|
||||
// Pre-test plugin repo url rewriting to ensure it succeeds before replacing the custom repo URL
|
||||
if (hasOldPluginRepoUrl)
|
||||
{
|
||||
foreach (var plugin in localPlugins)
|
||||
{
|
||||
var manifest = GetFoP(plugin.LocalPlugin, "manifest");
|
||||
if (manifest == null)
|
||||
throw new Exception("Plugin manifest is null");
|
||||
var manifestFile = GetFoP(plugin.LocalPlugin, "manifestFile");
|
||||
if (manifestFile == null)
|
||||
throw new Exception("Plugin manifestFile is null");
|
||||
var repo = GetFoP(manifest, "InstalledFromUrl");
|
||||
if (((string)repo).IsNullOrEmpty())
|
||||
throw new Exception("Plugin repo url is null or empty");
|
||||
SetFoP(manifest, "InstalledFromUrl", repo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasValidCustomRepoUrl)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var oldRepo in oldRepos)
|
||||
{
|
||||
_logger.LogInformation("* Removing old repo: {r}", oldRepo);
|
||||
RemoveRepo(oldRepo);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_logger.LogInformation("* Adding current repo: {r}", currentRepo);
|
||||
AddRepo(currentRepo, true);
|
||||
}
|
||||
}
|
||||
|
||||
// This time do it for real, and crash the game if we fail, to avoid saving a broken state
|
||||
if (hasOldPluginRepoUrl)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("* Updating plugins");
|
||||
foreach (var plugin in localPlugins)
|
||||
{
|
||||
var manifest = GetFoP(plugin.LocalPlugin, "manifest");
|
||||
if (manifest == null)
|
||||
throw new Exception("Plugin manifest is null");
|
||||
var manifestFile = GetFoP(plugin.LocalPlugin, "manifestFile");
|
||||
if (manifestFile == null)
|
||||
throw new Exception("Plugin manifestFile is null");
|
||||
var repo = GetFoP(manifest, "InstalledFromUrl");
|
||||
if (((string)repo).IsNullOrEmpty())
|
||||
throw new Exception("Plugin repo url is null or empty");
|
||||
SetFoP(manifest, "InstalledFromUrl", currentRepo);
|
||||
Call(manifest, "Save", [manifestFile, "RepoChange"]);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Exception while changing plugin install repo");
|
||||
foreach (var oldRepo in oldRepos)
|
||||
{
|
||||
_logger.LogInformation("* Restoring old repo: {r}", oldRepo);
|
||||
AddRepo(oldRepo, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasValidCustomRepoUrl || hasOldPluginRepoUrl)
|
||||
{
|
||||
_logger.LogInformation("* Saving dalamud config");
|
||||
SaveDalamudConfig();
|
||||
_logger.LogInformation("* Reloading plugin masters");
|
||||
ReloadPluginMasters();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Exception in RepoChangeService");
|
||||
}
|
||||
}, default, 10, cancellationToken).ConfigureAwait(false);
|
||||
_logger.LogInformation("Started RepoChangeService");
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_ = cancellationToken;
|
||||
_logger.LogDebug("Stopping RepoChange Service");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -496,17 +496,17 @@ public class ServerConfigurationManager
|
||||
|
||||
private void EnsureMainExists()
|
||||
{
|
||||
bool lopExists = false;
|
||||
bool elfExists = false;
|
||||
for (int i = 0; i < _configService.Current.ServerStorage.Count; ++i)
|
||||
{
|
||||
var x = _configService.Current.ServerStorage[i];
|
||||
if (x.ServerUri.Equals(ApiController.UmbraSyncServiceUri, StringComparison.OrdinalIgnoreCase))
|
||||
lopExists = true;
|
||||
if (x.ServerUri.Equals(ApiController.UmbraServiceUri, StringComparison.OrdinalIgnoreCase))
|
||||
elfExists = true;
|
||||
}
|
||||
if (!lopExists)
|
||||
if (!elfExists)
|
||||
{
|
||||
_logger.LogDebug("Re-adding missing server {uri}", ApiController.UmbraSyncServiceUri);
|
||||
_configService.Current.ServerStorage.Insert(0, new ServerStorage() { ServerUri = ApiController.UmbraSyncServiceUri, ServerName = ApiController.UmbraSyncServer });
|
||||
_logger.LogDebug("Re-adding missing server {uri}", ApiController.UmbraServiceUri);
|
||||
_configService.Current.ServerStorage.Insert(0, new ServerStorage() { ServerUri = ApiController.UmbraServiceUri, ServerName = ApiController.UmbraServer });
|
||||
if (_configService.Current.CurrentServer >= 0)
|
||||
_configService.Current.CurrentServer++;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
||||
UiSharedService uiSharedService, ServerConfigurationManager serverConfigurationManager,
|
||||
DalamudUtilService dalamudUtilService, FileDialogManager fileDialogManager, PairManager pairManager,
|
||||
CharaDataGposeTogetherManager charaDataGposeTogetherManager)
|
||||
: base(logger, mediator, "UmbraSync Character Data Hub###UmbraSyncCharaDataUI", performanceCollectorService)
|
||||
: base(logger, mediator, "Umbra Character Data Hub###UmbraCharaDataUI", performanceCollectorService)
|
||||
{
|
||||
SetWindowSizeConstraints();
|
||||
|
||||
|
||||
@@ -80,11 +80,11 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
#if DEBUG
|
||||
string dev = "Dev Build";
|
||||
var ver = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
WindowName = $"UmbraSync Sync {dev} ({ver.Major}.{ver.Minor}.{ver.Build})###UmbraSyncSyncMainUIDev";
|
||||
WindowName = $"UmbraSync {dev} ({ver.Major}.{ver.Minor}.{ver.Build})###UmbraSyncSyncMainUIDev";
|
||||
Toggle();
|
||||
#else
|
||||
var ver = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
WindowName = "UmbraSync Sync " + ver.Major + "." + ver.Minor + "." + ver.Build + "###UmbraSyncSyncMainUI";
|
||||
WindowName = "UmbraSync " + ver.Major + "." + ver.Minor + "." + ver.Build + "###UmbraSyncSyncMainUI";
|
||||
#endif
|
||||
Mediator.Subscribe<SwitchToMainUiMessage>(this, (_) => IsOpen = true);
|
||||
Mediator.Subscribe<SwitchToIntroUiMessage>(this, (_) => IsOpen = false);
|
||||
@@ -104,10 +104,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
|
||||
protected override void DrawInternal()
|
||||
{
|
||||
if (_serverManager.CurrentApiUrl.Equals(ApiController.UmbraSyncServiceUri, StringComparison.Ordinal))
|
||||
UiSharedService.AccentColor = new Vector4(1.0f, 0.8666f, 0.06666f, 1.0f);
|
||||
else
|
||||
UiSharedService.AccentColor = ImGuiColors.ParsedGreen;
|
||||
UiSharedService.AccentColor = new Vector4(0.2f, 0.6f, 1f, 1f); // custom blue
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().WindowPadding.Y - 1f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.Y);
|
||||
WindowContentWidth = UiSharedService.GetWindowContentRegionWidth();
|
||||
if (!_apiController.IsCurrentVersion)
|
||||
@@ -387,7 +384,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - (userSize.X + textSize.X) / 2 - ImGui.GetStyle().ItemSpacing.X / 2);
|
||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextColored(ImGuiColors.ParsedGreen, userCount);
|
||||
ImGui.TextColored(ImGuiColors.ParsedBlue, userCount);
|
||||
ImGui.SameLine();
|
||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Users Online");
|
||||
@@ -595,7 +592,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
ServerState.Connecting => ImGuiColors.DalamudYellow,
|
||||
ServerState.Reconnecting => ImGuiColors.DalamudRed,
|
||||
ServerState.Connected => UiSharedService.AccentColor,
|
||||
ServerState.Connected => new Vector4(0.2f, 0.6f, 1f, 1f), // custom blue
|
||||
ServerState.Disconnected => ImGuiColors.DalamudYellow,
|
||||
ServerState.Disconnecting => ImGuiColors.DalamudYellow,
|
||||
ServerState.Unauthorized => ImGuiColors.DalamudRed,
|
||||
|
||||
@@ -23,7 +23,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
|
||||
|
||||
public DownloadUi(ILogger<DownloadUi> logger, DalamudUtilService dalamudUtilService, MareConfigService configService,
|
||||
FileUploadManager fileTransferManager, MareMediator mediator, UiSharedService uiShared, PerformanceCollectorService performanceCollectorService)
|
||||
: base(logger, mediator, "UmbraSync Downloads", performanceCollectorService)
|
||||
: base(logger, mediator, "Umbra Downloads", performanceCollectorService)
|
||||
{
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
_configService = configService;
|
||||
@@ -163,13 +163,13 @@ public class DownloadUi : WindowMediatorSubscriberBase
|
||||
UiSharedService.Color(0, 0, 0, transparency), 1);
|
||||
drawList.AddRectFilled(dlBarStart with { X = dlBarStart.X - dlBarBorder, Y = dlBarStart.Y - dlBarBorder },
|
||||
dlBarEnd with { X = dlBarEnd.X + dlBarBorder, Y = dlBarEnd.Y + dlBarBorder },
|
||||
UiSharedService.Color(220, 220, 220, transparency), 1);
|
||||
UiSharedService.Color(220, 220, 255, transparency), 1);
|
||||
drawList.AddRectFilled(dlBarStart, dlBarEnd,
|
||||
UiSharedService.Color(0, 0, 0, transparency), 1);
|
||||
var dlProgressPercent = transferredBytes / (double)totalBytes;
|
||||
drawList.AddRectFilled(dlBarStart,
|
||||
dlBarEnd with { X = dlBarStart.X + (float)(dlProgressPercent * dlBarWidth) },
|
||||
UiSharedService.Color(50, 205, 50, transparency), 1);
|
||||
UiSharedService.Color(100, 100, 255, transparency), 1);
|
||||
|
||||
if (_configService.Current.TransferBarsShowText)
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
private IDtrBarEntry CreateEntry()
|
||||
{
|
||||
_logger.LogTrace("Creating new DtrBar entry");
|
||||
var entry = _dtrBar.Get("UmbraSync");
|
||||
var entry = _dtrBar.Get("Umbra");
|
||||
entry.OnClick = _ => _mareMediator.Publish(new UiToggleMessage(typeof(CompactUi)));
|
||||
|
||||
return entry;
|
||||
@@ -163,19 +163,19 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
.Select(x => string.Format("{0}", _configService.Current.PreferNoteInDtrTooltip ? x.GetNoteOrName() : x.PlayerName));
|
||||
}
|
||||
|
||||
tooltip = $"UmbraSync: Connected{Environment.NewLine}----------{Environment.NewLine}{string.Join(Environment.NewLine, visiblePairs)}";
|
||||
tooltip = $"Umbra: Connected{Environment.NewLine}----------{Environment.NewLine}{string.Join(Environment.NewLine, visiblePairs)}";
|
||||
colors = _configService.Current.DtrColorsPairsInRange;
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip = "UmbraSync: Connected";
|
||||
tooltip = "Umbra: Connected";
|
||||
colors = _configService.Current.DtrColorsDefault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text = RenderDtrStyle(_configService.Current.DtrStyle, "\uE04C");
|
||||
tooltip = "UmbraSync: Not Connected";
|
||||
tooltip = "Umbra: Not Connected";
|
||||
colors = _configService.Current.DtrColorsNotConnected;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
ApiController apiController, UiSharedService uiSharedService, FileDialogManager fileDialogManager,
|
||||
ServerConfigurationManager serverConfigurationManager,
|
||||
MareProfileManager mareProfileManager, PerformanceCollectorService performanceCollectorService)
|
||||
: base(logger, mediator, "UmbraSync Edit Profile###UmbraSyncSyncEditProfileUI", performanceCollectorService)
|
||||
: base(logger, mediator, "Umbra Edit Profile###UmbraSyncEditProfileUI", performanceCollectorService)
|
||||
{
|
||||
IsOpen = false;
|
||||
this.SizeConstraints = new()
|
||||
|
||||
@@ -38,7 +38,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
|
||||
public IntroUi(ILogger<IntroUi> logger, UiSharedService uiShared, MareConfigService configService,
|
||||
CacheMonitor fileCacheManager, ServerConfigurationManager serverConfigurationManager, MareMediator mareMediator,
|
||||
PerformanceCollectorService performanceCollectorService, DalamudUtilService dalamudUtilService, AccountRegistrationService registerService) : base(logger, mareMediator, "UmbraSync Setup", performanceCollectorService)
|
||||
PerformanceCollectorService performanceCollectorService, DalamudUtilService dalamudUtilService, AccountRegistrationService registerService) : base(logger, mareMediator, "Umbra Setup", performanceCollectorService)
|
||||
{
|
||||
_uiShared = uiShared;
|
||||
_configService = configService;
|
||||
@@ -108,9 +108,9 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
|
||||
if (!_configService.Current.AcceptedAgreement && !_readFirstPage)
|
||||
{
|
||||
_uiShared.BigText("Welcome to UmbraSync");
|
||||
_uiShared.BigText("Welcome to Umbra");
|
||||
ImGui.Separator();
|
||||
UiSharedService.TextWrapped("UmbraSync is a plugin that will replicate your full current character state including all Penumbra mods to other paired users. " +
|
||||
UiSharedService.TextWrapped("Umbra is a plugin that will replicate your full current character state including all Penumbra mods to other paired users. " +
|
||||
"Note that you will have to have Penumbra as well as Glamourer installed to use this plugin.");
|
||||
UiSharedService.TextWrapped("We will have to setup a few things first before you can start using this plugin. Click on next to continue.");
|
||||
|
||||
@@ -151,25 +151,36 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
UiSharedService.ColorText(readThis, ImGuiColors.DalamudRed);
|
||||
ImGui.SetWindowFontScale(1.0f);
|
||||
ImGui.Separator();
|
||||
|
||||
UiSharedService.TextWrapped("""
|
||||
All of the mod files currently active on your character as well as your current character state will be uploaded to the service you registered yourself at automatically. The plugin will exclusively upload the necessary mod files and not the whole mod.
|
||||
""");
|
||||
To use Umbra, you must be over the age of 18, or 21 in some jurisdictions.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
If you are on a data capped internet connection, higher fees due to data usage depending on the amount of downloaded and uploaded mod files might occur. Mod files will be compressed on up- and download to save on bandwidth usage. Due to varying up- and download speeds, changes in characters might not be visible immediately. Files present on the service that already represent your active mod files will not be uploaded again.
|
||||
""");
|
||||
All of the mod files currently active on your character as well as your current character state will be uploaded to the service you registered yourself at automatically. The plugin will exclusively upload the necessary mod files and not the whole mod.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
The mod files you are uploading are confidential and will not be distributed to parties other than the ones who are requesting the exact same mod files. Please think about who you are going to pair since it is unavoidable that they will receive and locally cache the necessary mod files that you have currently in use. Locally cached mod files will have arbitrary file names to discourage attempts at replicating the original mod.
|
||||
""");
|
||||
If you are on a data capped internet connection, higher fees due to data usage depending on the amount of downloaded and uploaded mod files might occur. Mod files will be compressed on up- and download to save on bandwidth usage. Due to varying up- and download speeds, changes in characters might not be visible immediately. Files present on the service that already represent your active mod files will not be uploaded again.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
The plugin creator tried their best to keep you secure. However, there is no guarantee for 100% security. Do not blindly pair your client with everyone.
|
||||
""");
|
||||
The mod files you are uploading are confidential and will not be distributed to parties other than the ones who are requesting the exact same mod files. Please think about who you are going to pair since it is unavoidable that they will receive and locally cache the necessary mod files that you have currently in use. Locally cached mod files will have arbitrary file names to discourage attempts at replicating the original mod.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
Mod files that are saved on the service will remain on the service as long as there are requests for the files from clients. After a period of not being used, the mod files will be automatically deleted.
|
||||
""");
|
||||
The plugin creator tried their best to keep you secure. However, there is no guarantee for 100% security. Do not blindly pair your client with everyone.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
This service is provided as-is.
|
||||
""");
|
||||
Mod files that are saved on the service will remain on the service as long as there are requests for the files from clients. After a period of not being used, the mod files will be automatically deleted.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
Accounts that are inactive for ninety (90) days will be deleted for privacy reasons.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
Umbra is operated from servers located in the European Union. You agree not to upload any content to the service that violates EU law; and more specifically, German law.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
You may delete your account at any time from within the Settings panel of the plugin. Any mods unique to you will then be removed from the server within 14 days.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
This service is provided as-is.
|
||||
""");
|
||||
|
||||
ImGui.Separator();
|
||||
if (_timeoutTask?.IsCompleted ?? true)
|
||||
@@ -201,11 +212,11 @@ This service is provided as-is.
|
||||
}
|
||||
else
|
||||
{
|
||||
UiSharedService.TextWrapped("To not unnecessary download files already present on your computer, UmbraSync will have to scan your Penumbra mod directory. " +
|
||||
"Additionally, a local storage folder must be set where UmbraSync will download other character files to. " +
|
||||
UiSharedService.TextWrapped("To not unnecessary download files already present on your computer, Umbra will have to scan your Penumbra mod directory. " +
|
||||
"Additionally, a local storage folder must be set where Umbra will download other character files to. " +
|
||||
"Once the storage folder is set and the scan complete, this page will automatically forward to registration at a service.");
|
||||
UiSharedService.TextWrapped("Note: The initial scan, depending on the amount of mods you have, might take a while. Please wait until it is completed.");
|
||||
UiSharedService.ColorTextWrapped("Warning: once past this step you should not delete the FileCache.csv of UmbraSync in the Plugin Configurations folder of Dalamud. " +
|
||||
UiSharedService.ColorTextWrapped("Warning: once past this step you should not delete the FileCache.csv of Umbra in the Plugin Configurations folder of Dalamud. " +
|
||||
"Otherwise on the next launch a full re-scan of the file cache database will be initiated.", ImGuiColors.DalamudYellow);
|
||||
UiSharedService.ColorTextWrapped("Warning: if the scan is hanging and does nothing for a long time, chances are high your Penumbra folder is not set up properly.", ImGuiColors.DalamudYellow);
|
||||
_uiShared.DrawCacheDirectorySetting();
|
||||
@@ -230,8 +241,8 @@ This service is provided as-is.
|
||||
_configService.Current.UseCompactor = useFileCompactor;
|
||||
_configService.Save();
|
||||
}
|
||||
UiSharedService.ColorTextWrapped("The File Compactor can save a tremendeous amount of space on the hard disk for downloads through UmbraSync. It will incur a minor CPU penalty on download but can speed up " +
|
||||
"loading of other characters. It is recommended to keep it enabled. You can change this setting later anytime in the UmbraSync settings.", ImGuiColors.DalamudYellow);
|
||||
UiSharedService.ColorTextWrapped("The File Compactor can save a tremendeous amount of space on the hard disk for downloads through Umbra. It will incur a minor CPU penalty on download but can speed up " +
|
||||
"loading of other characters. It is recommended to keep it enabled. You can change this setting later anytime in the Umbra settings.", ImGuiColors.DalamudYellow);
|
||||
}
|
||||
}
|
||||
else if (!_uiShared.ApiController.IsConnected)
|
||||
@@ -239,7 +250,7 @@ This service is provided as-is.
|
||||
using (_uiShared.UidFont.Push())
|
||||
ImGui.TextUnformatted("Service Registration");
|
||||
ImGui.Separator();
|
||||
UiSharedService.TextWrapped("To be able to use UmbraSync you will have to register an account.");
|
||||
UiSharedService.TextWrapped("To be able to use Umbra you will have to register an account.");
|
||||
UiSharedService.TextWrapped("Refer to the instructions at the location you obtained this plugin for more information or support.");
|
||||
|
||||
ImGui.Separator();
|
||||
@@ -251,8 +262,8 @@ This service is provided as-is.
|
||||
{
|
||||
ImGui.BeginDisabled(_registrationInProgress || _registrationSuccess || _secretKey.Length > 0);
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted("If you have not used UmbraSync before, click below to register a new account.");
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Register a new UmbraSync account"))
|
||||
ImGui.TextUnformatted("If you have not used Umbra before, click below to register a new account.");
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Register a new Umbra account"))
|
||||
{
|
||||
_registrationInProgress = true;
|
||||
_ = Task.Run(async () => {
|
||||
|
||||
@@ -22,7 +22,7 @@ public class PermissionWindowUI : WindowMediatorSubscriberBase
|
||||
|
||||
public PermissionWindowUI(ILogger<PermissionWindowUI> logger, Pair pair, MareMediator mediator, UiSharedService uiSharedService,
|
||||
ApiController apiController, PerformanceCollectorService performanceCollectorService)
|
||||
: base(logger, mediator, "Permissions for " + pair.UserData.AliasOrUID + "###UmbraSyncSyncPermissions" + pair.UserData.UID, performanceCollectorService)
|
||||
: base(logger, mediator, "Permissions for " + pair.UserData.AliasOrUID + "###UmbraSyncPermissions" + pair.UserData.UID, performanceCollectorService)
|
||||
{
|
||||
Pair = pair;
|
||||
_uiSharedService = uiSharedService;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PlayerAnalysisUI : WindowMediatorSubscriberBase
|
||||
|
||||
public PlayerAnalysisUI(ILogger<PlayerAnalysisUI> logger, Pair pair, MareMediator mediator, UiSharedService uiSharedService,
|
||||
PerformanceCollectorService performanceCollectorService)
|
||||
: base(logger, mediator, "Character Data Analysis for " + pair.UserData.AliasOrUID + "###UmbraSyncPairAnalysis" + pair.UserData.UID, performanceCollectorService)
|
||||
: base(logger, mediator, "Character Data Analysis for " + pair.UserData.AliasOrUID + "###UmbraPairAnalysis" + pair.UserData.UID, performanceCollectorService)
|
||||
{
|
||||
Pair = pair;
|
||||
_uiSharedService = uiSharedService;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class PopoutProfileUi : WindowMediatorSubscriberBase
|
||||
|
||||
public PopoutProfileUi(ILogger<PopoutProfileUi> logger, MareMediator mediator, UiSharedService uiSharedService,
|
||||
ServerConfigurationManager serverManager, MareConfigService mareConfigService,
|
||||
MareProfileManager mareProfileManager, PairManager pairManager, PerformanceCollectorService performanceCollectorService) : base(logger, mediator, "###UmbraSyncSyncPopoutProfileUI", performanceCollectorService)
|
||||
MareProfileManager mareProfileManager, PairManager pairManager, PerformanceCollectorService performanceCollectorService) : base(logger, mediator, "###UmbraSyncPopoutProfileUI", performanceCollectorService)
|
||||
{
|
||||
_uiSharedService = uiSharedService;
|
||||
_serverManager = serverManager;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
FileCacheManager fileCacheManager,
|
||||
FileCompactor fileCompactor, ApiController apiController,
|
||||
IpcManager ipcManager, IpcProvider ipcProvider, CacheMonitor cacheMonitor,
|
||||
DalamudUtilService dalamudUtilService, AccountRegistrationService registerService) : base(logger, mediator, "UmbraSync Settings", performanceCollector)
|
||||
DalamudUtilService dalamudUtilService, AccountRegistrationService registerService) : base(logger, mediator, "Umbra Settings", performanceCollector)
|
||||
{
|
||||
_configService = configService;
|
||||
_pairManager = pairManager;
|
||||
@@ -581,32 +581,32 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.BigText("Advanced");
|
||||
|
||||
bool mareApi = _configService.Current.MareAPI;
|
||||
if (ImGui.Checkbox("Enable Mare Synchronos API", ref mareApi))
|
||||
if (ImGui.Checkbox("Enable Umbra Sync API", ref mareApi))
|
||||
{
|
||||
_configService.Current.MareAPI = mareApi;
|
||||
_configService.Save();
|
||||
_ipcProvider.HandleMareImpersonation();
|
||||
}
|
||||
_uiShared.DrawHelpText("Enables handling of the Mare Synchronos API. This currently includes:\n\n" +
|
||||
_uiShared.DrawHelpText("Enables handling of the Umbra Sync API. This currently includes:\n\n" +
|
||||
" - MCDF loading support for other plugins\n" +
|
||||
" - Blocking Moodles applications to paired users\n\n" +
|
||||
"If the Mare Synchronos plugin is loaded while this option is enabled, control of its API will be relinquished.");
|
||||
"If the Umbra Sync plugin is loaded while this option is enabled, control of its API will be relinquished.");
|
||||
|
||||
using (_ = ImRaii.PushIndent())
|
||||
{
|
||||
ImGui.SameLine(300.0f * ImGuiHelpers.GlobalScale);
|
||||
if (_ipcProvider.ImpersonationActive)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Mare API active!", ImGuiColors.HealerGreen);
|
||||
UiSharedService.ColorTextWrapped("Umbra API active!", ImGuiColors.HealerGreen);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mareApi)
|
||||
UiSharedService.ColorTextWrapped("Mare API inactive: Option is disabled", ImGuiColors.DalamudYellow);
|
||||
UiSharedService.ColorTextWrapped("Umbra API inactive: Option is disabled", ImGuiColors.DalamudYellow);
|
||||
else if (_ipcProvider.MarePluginEnabled)
|
||||
UiSharedService.ColorTextWrapped("Mare API inactive: Mare plugin is loaded", ImGuiColors.DalamudYellow);
|
||||
UiSharedService.ColorTextWrapped("Umbra API inactive: Umbra plugin is loaded", ImGuiColors.DalamudYellow);
|
||||
else
|
||||
UiSharedService.ColorTextWrapped("Mare API inactive: Unknown reason", ImGuiColors.DalamudRed);
|
||||
UiSharedService.ColorTextWrapped("Umbra API inactive: Unknown reason", ImGuiColors.DalamudRed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -728,7 +728,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
_uiShared.BigText("Storage");
|
||||
|
||||
UiSharedService.TextWrapped("UmbraSync stores downloaded files from paired people permanently. This is to improve loading performance and requiring less downloads. " +
|
||||
UiSharedService.TextWrapped("Umbra stores downloaded files from paired people permanently. This is to improve loading performance and requiring less downloads. " +
|
||||
"The storage governs itself by clearing data beyond the set storage size. Please set the storage size accordingly. It is not necessary to manually clear the storage.");
|
||||
|
||||
_uiShared.DrawFileScanState();
|
||||
@@ -745,7 +745,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Monitoring UmbraSync Storage Folder: " + (_cacheMonitor.MareWatcher?.Path ?? "Not monitoring"));
|
||||
ImGui.TextUnformatted("Monitoring Umbra Storage Folder: " + (_cacheMonitor.MareWatcher?.Path ?? "Not monitoring"));
|
||||
if (string.IsNullOrEmpty(_cacheMonitor.MareWatcher?.Path))
|
||||
{
|
||||
ImGui.SameLine();
|
||||
@@ -763,7 +763,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_cacheMonitor.StartPenumbraWatcher(_ipcManager.Penumbra.ModDirectory);
|
||||
_cacheMonitor.InvokeScan();
|
||||
}
|
||||
UiSharedService.AttachToolTip("Attempts to resume monitoring for both Penumbra and UmbraSync Storage. "
|
||||
UiSharedService.AttachToolTip("Attempts to resume monitoring for both Penumbra and Umbra Storage. "
|
||||
+ "Resuming the monitoring will also force a full scan to run." + Environment.NewLine
|
||||
+ "If the button remains present after clicking it, consult /xllog for errors");
|
||||
}
|
||||
@@ -776,8 +776,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_cacheMonitor.StopMonitoring();
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Stops the monitoring for both Penumbra and UmbraSync Storage. "
|
||||
+ "Do not stop the monitoring, unless you plan to move the Penumbra and UmbraSync Storage folders, to ensure correct functionality of UmbraSync." + Environment.NewLine
|
||||
UiSharedService.AttachToolTip("Stops the monitoring for both Penumbra and Umbra Storage. "
|
||||
+ "Do not stop the monitoring, unless you plan to move the Penumbra and Umbra Storage folders, to ensure correct functionality of Umbra." + Environment.NewLine
|
||||
+ "If you stop the monitoring to move folders around, resume it after you are finished moving the files."
|
||||
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
|
||||
}
|
||||
@@ -794,7 +794,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
bool useFileCompactor = _configService.Current.UseCompactor;
|
||||
if (!useFileCompactor && !isLinux)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Hint: To free up space when using UmbraSync consider enabling the File Compactor", ImGuiColors.DalamudYellow);
|
||||
UiSharedService.ColorTextWrapped("Hint: To free up space when using Umbra consider enabling the File Compactor", ImGuiColors.DalamudYellow);
|
||||
}
|
||||
if (isLinux || !_cacheMonitor.StorageisNTFS) ImGui.BeginDisabled();
|
||||
if (ImGui.Checkbox("Use file compactor", ref useFileCompactor))
|
||||
@@ -903,7 +903,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
UiSharedService.AttachToolTip("You normally do not need to do this. THIS IS NOT SOMETHING YOU SHOULD BE DOING TO TRY TO FIX SYNC ISSUES." + Environment.NewLine
|
||||
+ "This will solely remove all downloaded data from all players and will require you to re-download everything again." + Environment.NewLine
|
||||
+ "UmbraSync's storage is self-clearing and will not surpass the limit you have set it to." + Environment.NewLine
|
||||
+ "Umbra's storage is self-clearing and will not surpass the limit you have set it to." + Environment.NewLine
|
||||
+ "If you still think you need to do this hold CTRL while pressing the button.");
|
||||
if (!_readClearCache)
|
||||
ImGui.EndDisabled();
|
||||
@@ -975,14 +975,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_configService.Current.EnableRightClickMenus = enableRightClickMenu;
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will add UmbraSync related right click menu entries in the game UI on paired players.");
|
||||
_uiShared.DrawHelpText("This will add Umbra related right click menu entries in the game UI on paired players.");
|
||||
|
||||
if (ImGui.Checkbox("Display status and visible pair count in Server Info Bar", ref enableDtrEntry))
|
||||
{
|
||||
_configService.Current.EnableDtrEntry = enableDtrEntry;
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will add UmbraSync connection status and visible pair count in the Server Info Bar.\nYou can further configure this through your Dalamud Settings.");
|
||||
_uiShared.DrawHelpText("This will add Umbra connection status and visible pair count in the Server Info Bar.\nYou can further configure this through your Dalamud Settings.");
|
||||
|
||||
using (ImRaii.Disabled(!enableDtrEntry))
|
||||
{
|
||||
@@ -1744,7 +1744,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
if (true) // Enable registration button for all servers
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Register a new UmbraSync account"))
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Register a new Umbra account"))
|
||||
{
|
||||
_registrationInProgress = true;
|
||||
_ = Task.Run(async () => {
|
||||
@@ -1800,7 +1800,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
var serverName = selectedServer.ServerName;
|
||||
var serverUri = selectedServer.ServerUri;
|
||||
var isMain = string.Equals(serverName, ApiController.UmbraSyncServer, StringComparison.OrdinalIgnoreCase);
|
||||
var isMain = string.Equals(serverName, ApiController.UmbraServer, StringComparison.OrdinalIgnoreCase);
|
||||
var flags = isMain ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None;
|
||||
|
||||
if (ImGui.InputText("Service URI", ref serverUri, 255, flags))
|
||||
|
||||
@@ -26,7 +26,7 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
public StandaloneProfileUi(ILogger<StandaloneProfileUi> logger, MareMediator mediator, UiSharedService uiBuilder,
|
||||
ServerConfigurationManager serverManager, MareProfileManager mareProfileManager, PairManager pairManager, Pair pair,
|
||||
PerformanceCollectorService performanceCollector)
|
||||
: base(logger, mediator, "Profile of " + pair.UserData.AliasOrUID + "##UmbraSyncSyncStandaloneProfileUI" + pair.UserData.AliasOrUID, performanceCollector)
|
||||
: base(logger, mediator, "Profile of " + pair.UserData.AliasOrUID + "##UmbraSyncStandaloneProfileUI" + pair.UserData.AliasOrUID, performanceCollector)
|
||||
{
|
||||
_uiSharedService = uiBuilder;
|
||||
_serverManager = serverManager;
|
||||
|
||||
@@ -534,7 +534,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
|
||||
public void DrawCacheDirectorySetting()
|
||||
{
|
||||
ColorTextWrapped("Note: The storage folder should be somewhere close to root (i.e. C:\\UmbraSyncStorage) in a new empty folder. DO NOT point this to your game folder. DO NOT point this to your Penumbra folder.", ImGuiColors.DalamudYellow);
|
||||
ColorTextWrapped("Note: The storage folder should be somewhere close to root (i.e. C:\\UmbraStorage) in a new empty folder. DO NOT point this to your game folder. DO NOT point this to your Penumbra folder.", ImGuiColors.DalamudYellow);
|
||||
var cacheDirectory = _configService.Current.CacheFolder;
|
||||
ImGui.SetNextItemWidth(400 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.InputText("Storage Folder##cache", ref cacheDirectory, 255, ImGuiInputTextFlags.ReadOnly);
|
||||
@@ -544,7 +544,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
{
|
||||
if (IconButton(FontAwesomeIcon.Folder))
|
||||
{
|
||||
FileDialogManager.OpenFolderDialog("Pick UmbraSync Storage Folder", (success, path) =>
|
||||
FileDialogManager.OpenFolderDialog("Pick Umbra Storage Folder", (success, path) =>
|
||||
{
|
||||
if (!success) return;
|
||||
|
||||
@@ -604,7 +604,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
}
|
||||
else if (_cacheDirectoryHasOtherFilesThanCache)
|
||||
{
|
||||
ColorTextWrapped("Your selected directory has files or directories inside that are not UmbraSync related. Use an empty directory or a previous storage directory only.", ImGuiColors.DalamudRed);
|
||||
ColorTextWrapped("Your selected directory has files or directories inside that are not Umbra related. Use an empty directory or a previous storage directory only.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
else if (!_cacheDirectoryIsValidPath)
|
||||
{
|
||||
@@ -619,7 +619,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
_configService.Current.MaxLocalCacheInGiB = maxCacheSize;
|
||||
_configService.Save();
|
||||
}
|
||||
DrawHelpText("The storage is automatically governed by UmbraSync. It will clear itself automatically once it reaches the set capacity by removing the oldest unused files. You typically do not need to clear it yourself.");
|
||||
DrawHelpText("The storage is automatically governed by Umbra. It will clear itself automatically once it reaches the set capacity by removing the oldest unused files. You typically do not need to clear it yourself.");
|
||||
}
|
||||
|
||||
public T? DrawCombo<T>(string comboName, IEnumerable<T> comboItems, Func<T, string> toName,
|
||||
@@ -848,17 +848,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
|
||||
if (!_penumbraExists || !_glamourerExists)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use UmbraSync.");
|
||||
return false;
|
||||
}
|
||||
else if (NoSnapService.AnyLoaded)
|
||||
{
|
||||
IconText(FontAwesomeIcon.ExclamationTriangle, ImGuiColors.DalamudYellow);
|
||||
ImGui.SameLine();
|
||||
var cursorX = ImGui.GetCursorPosX();
|
||||
ImGui.TextColored(ImGuiColors.DalamudYellow, "Synced player appearances will not apply until incompatible plugins are disabled:");
|
||||
ImGui.SetCursorPosX(cursorX + 16.0f);
|
||||
ImGui.TextColored(ImGuiColors.DalamudYellow, NoSnapService.ActivePlugins);
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use Umbra.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"Author": "SirConstance",
|
||||
"Name": "UmbraSync",
|
||||
"Punchline": "Il revient!",
|
||||
"Punchline": "Share your true self.",
|
||||
"Description": "This plugin will synchronize your Penumbra mods and current Glamourer state with other paired clients automatically.",
|
||||
"InternalName": "UmbraSync",
|
||||
"ApplicableVersion": "any",
|
||||
"Tags": [
|
||||
"customization"
|
||||
],
|
||||
"IconUrl": "",
|
||||
"RepoUrl": "",
|
||||
"IconUrl": "https://repo.umbra-sync.net/logo.png",
|
||||
"RepoUrl": "https://repo.umbra-sync.net/plugin.json",
|
||||
"CanUnloadAsync": true
|
||||
}
|
||||
|
||||
@@ -17,18 +17,16 @@ public sealed class AccountRegistrationService : IDisposable
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ILogger<AccountRegistrationService> _logger;
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly RemoteConfigurationService _remoteConfig;
|
||||
|
||||
private string GenerateSecretKey()
|
||||
{
|
||||
return Convert.ToHexString(SHA256.HashData(RandomNumberGenerator.GetBytes(64)));
|
||||
}
|
||||
|
||||
public AccountRegistrationService(ILogger<AccountRegistrationService> logger, ServerConfigurationManager serverManager, RemoteConfigurationService remoteConfig)
|
||||
public AccountRegistrationService(ILogger<AccountRegistrationService> logger, ServerConfigurationManager serverManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_serverManager = serverManager;
|
||||
_remoteConfig = remoteConfig;
|
||||
_httpClient = new(
|
||||
new HttpClientHandler
|
||||
{
|
||||
@@ -47,22 +45,10 @@ public sealed class AccountRegistrationService : IDisposable
|
||||
|
||||
public async Task<RegisterReplyDto> RegisterAccount(CancellationToken token)
|
||||
{
|
||||
var authApiUrl = _serverManager.CurrentApiUrl;
|
||||
|
||||
// Override the API URL used for auth from remote config, if one is available
|
||||
if (authApiUrl.Equals(ApiController.UmbraSyncServiceUri, StringComparison.Ordinal))
|
||||
{
|
||||
var config = await _remoteConfig.GetConfigAsync<HubConnectionConfig>("mainServer").ConfigureAwait(false) ?? new();
|
||||
if (!string.IsNullOrEmpty(config.ApiUrl))
|
||||
authApiUrl = config.ApiUrl;
|
||||
else
|
||||
authApiUrl = ApiController.UmbraSyncServiceApiUri;
|
||||
}
|
||||
|
||||
var secretKey = GenerateSecretKey();
|
||||
var hashedSecretKey = secretKey.GetHash256();
|
||||
|
||||
Uri postUri = MareAuth.AuthRegisterV2FullPath(new Uri(authApiUrl
|
||||
Uri postUri = MareAuth.AuthRegisterV2FullPath(new Uri(_serverManager.CurrentApiUrl
|
||||
.Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("ws://", "http://", StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ namespace MareSynchronos.WebAPI;
|
||||
#pragma warning disable MA0040
|
||||
public sealed partial class ApiController : DisposableMediatorSubscriberBase, IMareHubClient
|
||||
{
|
||||
public const string UmbraSyncServer = "UmbraSync Main Server (BETA)";
|
||||
public const string UmbraSyncServiceUri = "wss://umbra-sync.net/";
|
||||
public const string UmbraSyncServiceApiUri = "wss://umbra-sync.net/";
|
||||
public const string UmbraSyncServiceHubUri = "wss://umbra-sync.net/mare";
|
||||
public const string UmbraServer = "UmbraSync Main Server (BETA)";
|
||||
public const string UmbraServiceUri = "wss://umbra-sync.net/";
|
||||
public const string UmbraServiceApiUri = "wss://umbra-sync.net/";
|
||||
public const string UmbraServiceHubUri = "wss://umbra-sync.net/mare";
|
||||
|
||||
private readonly DalamudUtilService _dalamudUtil;
|
||||
private readonly HubFactory _hubFactory;
|
||||
@@ -194,7 +194,7 @@ public const string UmbraSyncServiceHubUri = "wss://umbra-sync.net/mare";
|
||||
Mediator.Publish(new NotificationMessage("Client incompatible",
|
||||
$"Your client is outdated ({currentClientVer.Major}.{currentClientVer.Minor}.{currentClientVer.Build}), current is: " +
|
||||
$"{_connectionDto.CurrentClientVersion.Major}.{_connectionDto.CurrentClientVersion.Minor}.{_connectionDto.CurrentClientVersion.Build}. " +
|
||||
$"This client version is incompatible and will not be able to connect. Please update your UmbraSync client.",
|
||||
$"This client version is incompatible and will not be able to connect. Please update your Umbra client.",
|
||||
NotificationType.Error));
|
||||
}
|
||||
await StopConnection(ServerState.VersionMisMatch).ConfigureAwait(false);
|
||||
@@ -206,7 +206,7 @@ public const string UmbraSyncServiceHubUri = "wss://umbra-sync.net/mare";
|
||||
Mediator.Publish(new NotificationMessage("Client outdated",
|
||||
$"Your client is outdated ({currentClientVer.Major}.{currentClientVer.Minor}.{currentClientVer.Build}), current is: " +
|
||||
$"{_connectionDto.CurrentClientVersion.Major}.{_connectionDto.CurrentClientVersion.Minor}.{_connectionDto.CurrentClientVersion.Build}. " +
|
||||
$"Please keep your UmbraSync client up-to-date.",
|
||||
$"Please keep your Umbra client up-to-date.",
|
||||
NotificationType.Warning, TimeSpan.FromSeconds(15)));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ public class HubFactory : MediatorSubscriberBase
|
||||
{
|
||||
private readonly ILoggerProvider _loggingProvider;
|
||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||
private readonly RemoteConfigurationService _remoteConfig;
|
||||
private readonly TokenProvider _tokenProvider;
|
||||
private HubConnection? _instance;
|
||||
private string _cachedConfigFor = string.Empty;
|
||||
@@ -27,11 +26,10 @@ public class HubFactory : MediatorSubscriberBase
|
||||
private bool _isDisposed = false;
|
||||
|
||||
public HubFactory(ILogger<HubFactory> logger, MareMediator mediator,
|
||||
ServerConfigurationManager serverConfigurationManager, RemoteConfigurationService remoteConfig,
|
||||
ServerConfigurationManager serverConfigurationManager,
|
||||
TokenProvider tokenProvider, ILoggerProvider pluginLog) : base(logger, mediator)
|
||||
{
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
_remoteConfig = remoteConfig;
|
||||
_tokenProvider = tokenProvider;
|
||||
_loggingProvider = pluginLog;
|
||||
}
|
||||
@@ -87,16 +85,6 @@ public class HubFactory : MediatorSubscriberBase
|
||||
};
|
||||
}
|
||||
|
||||
if (_serverConfigurationManager.CurrentApiUrl.Equals(ApiController.UmbraSyncServiceUri, StringComparison.Ordinal))
|
||||
{
|
||||
var mainServerConfig = await _remoteConfig.GetConfigAsync<HubConnectionConfig>("mainServer").ConfigureAwait(false) ?? new();
|
||||
defaultConfig = mainServerConfig;
|
||||
if (string.IsNullOrEmpty(mainServerConfig.ApiUrl))
|
||||
defaultConfig.ApiUrl = ApiController.UmbraSyncServiceApiUri;
|
||||
if (string.IsNullOrEmpty(mainServerConfig.HubUrl))
|
||||
defaultConfig.HubUrl = ApiController.UmbraSyncServiceHubUri;
|
||||
}
|
||||
|
||||
string jsonResponse;
|
||||
|
||||
if (stapledWellKnown != null)
|
||||
@@ -115,7 +103,7 @@ public class HubFactory : MediatorSubscriberBase
|
||||
_ => apiUrl.Scheme
|
||||
};
|
||||
|
||||
var wellKnownUrl = $"{httpScheme}://{apiUrl.Host}/.well-known/umbra/client";
|
||||
var wellKnownUrl = $"{httpScheme}://{apiUrl.Host}/.well-known/Umbra/client";
|
||||
Logger.LogTrace("Fetching hub config for {uri} via {wk}", _serverConfigurationManager.CurrentApiUrl, wellKnownUrl);
|
||||
|
||||
using var httpClient = new HttpClient(
|
||||
|
||||
@@ -20,16 +20,14 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ILogger<TokenProvider> _logger;
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly RemoteConfigurationService _remoteConfig;
|
||||
private readonly ConcurrentDictionary<JwtIdentifier, string> _tokenCache = new();
|
||||
private readonly ConcurrentDictionary<string, string?> _wellKnownCache = new(StringComparer.Ordinal);
|
||||
|
||||
public TokenProvider(ILogger<TokenProvider> logger, ServerConfigurationManager serverManager, RemoteConfigurationService remoteConfig,
|
||||
public TokenProvider(ILogger<TokenProvider> logger, ServerConfigurationManager serverManager,
|
||||
DalamudUtilService dalamudUtil, MareMediator mareMediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_serverManager = serverManager;
|
||||
_remoteConfig = remoteConfig;
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_httpClient = new(
|
||||
new HttpClientHandler
|
||||
@@ -70,23 +68,11 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
|
||||
Uri tokenUri;
|
||||
HttpResponseMessage result;
|
||||
|
||||
var authApiUrl = _serverManager.CurrentApiUrl;
|
||||
|
||||
// Override the API URL used for auth from remote config, if one is available
|
||||
if (authApiUrl.Equals(ApiController.UmbraSyncServiceUri, StringComparison.Ordinal))
|
||||
{
|
||||
var config = await _remoteConfig.GetConfigAsync<HubConnectionConfig>("mainServer").ConfigureAwait(false) ?? new();
|
||||
if (!string.IsNullOrEmpty(config.ApiUrl))
|
||||
authApiUrl = config.ApiUrl;
|
||||
else
|
||||
authApiUrl = ApiController.UmbraSyncServiceApiUri;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("GetNewToken: Requesting");
|
||||
|
||||
tokenUri = MareAuth.AuthV2FullPath(new Uri(authApiUrl
|
||||
tokenUri = MareAuth.AuthV2FullPath(new Uri(_serverManager.CurrentApiUrl
|
||||
.Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("ws://", "http://", StringComparison.OrdinalIgnoreCase)));
|
||||
var secretKey = _serverManager.GetSecretKey(out _)!;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB |
BIN
MareSynchronos/images/logo.png
Normal file
BIN
MareSynchronos/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 928 KiB |
@@ -2,6 +2,12 @@
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net9.0-windows7.0": {
|
||||
"Chaos.NaCl.Standard": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.0, )",
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "8ajPyzu49LSIdPgeg56eDdKu1j8FZJngKgTn9rXHV3GNVly49XFvPAwoWuUT8xPze3OjVUOWQZaO82HWrYFFEw=="
|
||||
},
|
||||
"DalamudPackager": {
|
||||
"type": "Direct",
|
||||
"requested": "[13.0.0, )",
|
||||
@@ -25,9 +31,9 @@
|
||||
},
|
||||
"Glamourer.Api": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.4.1, )",
|
||||
"resolved": "2.4.1",
|
||||
"contentHash": "Q9jrGWDlIAXoMXihu+HbSRu8FpgR9xNy2j5YpAoqDHzhl2MZLgqAJPlQ+N5ISp6cn7xqQVMmxB9PchW2uEYoEA=="
|
||||
"requested": "[2.6.0, )",
|
||||
"resolved": "2.6.0",
|
||||
"contentHash": "zysCZgNBRm3k3qvibyw/31MmEckX0Uh0ZsT+Sax3ZHnYIRELr9Qhbz3cjJz7u0RHGIrNJiRpktu/LxgHEqDItw=="
|
||||
},
|
||||
"K4os.Compression.LZ4.Legacy": {
|
||||
"type": "Direct",
|
||||
@@ -51,80 +57,80 @@
|
||||
},
|
||||
"Meziantou.Analyzer": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.0.189, )",
|
||||
"resolved": "2.0.189",
|
||||
"contentHash": "/e+dh95vDdvCTbViV2cWpXJEXAj+VHq7FsBXCTTTsLcffV0bkgXDFAPY0zMpy+Vt91Cl2cBoSOfaAoSdtn796Q=="
|
||||
"requested": "[2.0.212, )",
|
||||
"resolved": "2.0.212",
|
||||
"contentHash": "U91ktjjTRTccUs3Lk+hrLD9vW+2+lhnsOf4G1GpRSJi1pLn3uK5CU6wGP9Bmz1KlJs6Oz1GGoMhxQBoqQsmAuQ=="
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.3, )",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "V8K94AN9ADbpP2jxwt8Y++g7t/XZ7oEV+GZizNvLnR8dpCYWeveIZ/tItO54jfZJ5jmt5YyideOc+ErZbr1IZg==",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "cO+TZaWdhMn2cIYfPH9oFZaisJrx7X6SBAYdmGektPUAW2BYtMbH4HyLOnJ5CYo42zP9WgqhWHKqmoDm7+Ol5w==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Connections.Client": "9.0.3",
|
||||
"Microsoft.AspNetCore.SignalR.Client.Core": "9.0.3"
|
||||
"Microsoft.AspNetCore.Http.Connections.Client": "9.0.8",
|
||||
"Microsoft.AspNetCore.SignalR.Client.Core": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.MessagePack": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.3, )",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "mMQ21T4NuqGrX1UzSe1WBmg6TUlOmpMgCoA9kAy/uBWBZlAA4+NFavbCULyJy6zTSUAvZkG3cGSnQN4dLJlF/w==",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "e6SC/Tp+SZKeEVYdu8blz9q4MkFW08D56IkQv9V3perF3a7v+GgGZ0DAY/HRS9zBuhFrqpXhJvxeHMw3PJLcOg==",
|
||||
"dependencies": {
|
||||
"MessagePack": "2.5.187",
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.3"
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.3, )",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "ioFXglqFA9uCYcKHI3CLVTO3I75jWIhvVxiZBzGeSPxw7XdhDLh0QvbNFrMTbZk9qqEVQcylblcvcNXnFHYXyA==",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "O2VlzORrBbS2it203k5FOHrudDdmdrJovA73P/shdRGeLzvet4e4yXhGx52V2PNjYBQ0IO5M4xiNcL+6xIX6Bg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "9.0.3",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.3",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Diagnostics": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.3",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Console": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Debug": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.EventLog": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.EventSource": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Diagnostics": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.8",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Console": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Debug": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.EventLog": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.EventSource": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Penumbra.Api": {
|
||||
"type": "Direct",
|
||||
"requested": "[5.6.1, )",
|
||||
"resolved": "5.6.1",
|
||||
"contentHash": "pZesXuBB9cMXKN10EfLJclLay3vjRYQy376PXXcPdx33kNI0jHwgPXGcy6BtVmoaMvn4UvK+EqGVYlt2b/Ns9Q=="
|
||||
"requested": "[5.12.0, )",
|
||||
"resolved": "5.12.0",
|
||||
"contentHash": "XGWviAZgokj2djpH50FWgM24jOTpKUuDHvd0HwrzBRY6BEMmpb3HfGIl8+BDE/DqbpH63u6aO2TvzUV6BmXT5w=="
|
||||
},
|
||||
"SonarAnalyzer.CSharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[10.7.0.110445, )",
|
||||
"resolved": "10.7.0.110445",
|
||||
"contentHash": "U4v2LWopxADYkUv7Z5CX7ifKMdDVqHb7a1bzppIQnQi4WQR6z1Zi5rDkCHlVYGEd1U/WMz1IJCU8OmFZLJpVig=="
|
||||
"requested": "[10.15.0.120848, )",
|
||||
"resolved": "10.15.0.120848",
|
||||
"contentHash": "1hM3HVRl5jdC/ZBDu+G7CCYLXRGe/QaP01Zy+c9ETPhY7lWD8g8HiefY6sGaH0T3CJ4wAy0/waGgQTh0TYy0oQ=="
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.7.0, )",
|
||||
"resolved": "8.7.0",
|
||||
"contentHash": "8dKL3A9pVqYCJIXHd4H2epQqLxSvKeNxGonR0e5g89yMchyvsM/NLuB06otx29BicUd6+LUJZgNZmvYjjPsPGg==",
|
||||
"requested": "[8.14.0, )",
|
||||
"resolved": "8.14.0",
|
||||
"contentHash": "EYGgN/S+HK7S6F3GaaPLFAfK0UzMrkXFyWCvXpQWFYmZln3dqtbyIO7VuTM/iIIPMzkelg8ZLlBPvMhxj6nOAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.7.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.7.0"
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.14.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.14.0"
|
||||
}
|
||||
},
|
||||
"K4os.Compression.LZ4": {
|
||||
@@ -153,342 +159,342 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "MWkNy/Yhv2q5ZVYPHjHN6pEE5Ya1r4opqSpnsW60bgpDOT54zZ6Kpqub4Tcat8ENsR5PZcTZ3eeSAthweUb/KA==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "mONfcKx7I4h6Rg+3b20bRyuy/GWz2yLsCNzKKqh1X4OfxnI7l0rdSxBwO203ebZFhjrdXnqMl7Op0N1FQ1Q5DQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Features": "9.0.3"
|
||||
"Microsoft.Extensions.Features": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Connections.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "bLoLX67FBeYK1KKGfXrmBki/F9EAK8EKCNkyADtfFjQkJ1Qhhw1sjBlcL8TbVnZxk+FaFsyCeBPmSHgOwNIJ/A==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "Ob2n+H3358kvubgXu9hY95MZB6X91PUGJvtWaHGEX7eZ+9bYdUCYs57ukJiIziH+aD9yO9e36bgKIT1WJEtfmA==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3",
|
||||
"System.Net.ServerSentEvents": "9.0.3"
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"System.Net.ServerSentEvents": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "GYDAXEmaG/q9UgixPchsLAVbBUbdgG3hd8J7Af4k4GIKLsibAhos7QY7hHicyULJvRtl03totiRi5Z+JIKEnUA==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "150BRlecnjL+6C+yw/bDP49+ONh7BmaJZTRik6KtbaS+cWnEDVXnhE5PTKlFqCYBD5T8wdjKoF5+lzKHJUK47A==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.3"
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Client.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "R2N03AK5FH8KIENfJGER4SgjJFMJTBiYuLbovbRunp5R4knO+iysfbYMfEFO3kn98ElWr/747dS4AeWQOEEQsg==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "EZ4KaPVQ9rDxZYWQ1sYiPfXEbomhKwp5Fn/0q1XtOgTilV/nN2lgA06KTofVJSeVVRwYdlZggflcQNcKCG0xcg==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.3",
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": "9.0.3",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"System.Threading.Channels": "9.0.3"
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.8",
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"System.Threading.Channels": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "/568tq8YVas1mDgeScmQdQV4ZDRjdyqDS3rAo17R5Bs4puMaNM80wQSwcvsmN5gSwH6L/XRTmD1J1uRIyKXrCg==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "oNOEDf2UGLU63Qi7LB8OJdfG1CGybVO34bhotpkvAQUJ5zH8Ewf7EvqeHlUgg6cVyrdC+vewOFxTysw212FTyw==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3"
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "jvOdsquqrbWMP3/Aq4s8/yVeCxBkjvxarv/2WgubKkQT8nZ46aKY3Rvj1uolp4N3TuaMGlnd6mhK/tF7jCat2Q==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "9LtBkzS2iYOSiUx1NDI91abM5xxD5MUYtdlvwCtMMr6YdsMzHvDUrgPK2N3hpYE94vmj0srt423Kwd1aOqmGPg==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.3"
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "RIEeZxWYm77+OWLwgik7DzSVSONjqkmcbuCb1koZdGAV7BgOUWnLz80VMyHZMw3onrVwFCCMHBBdruBPuQTvkg==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "6m+8Xgmf8UWL0p/oGqBM+0KbHE5/ePXbV1hKXgC59zEv0aa0DW5oiiyxDbK5kH5j4gIvyD5uWL0+HadKBJngvQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "q5qlbm6GRUrle2ZZxy9aqS/wWoc+mRD3JeP6rcpiJTh5XcemYkplAcJKq8lU11ZfPom5lfbZZfnQvDqcUhqD5Q==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "yNou2KM35RvzOh4vUFtl2l33rWPvOCoba+nzEDJ+BgD8aOL/jew4WPCibQvntRfOJ2pJU8ARygSMD+pdjvDHuA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "ad82pYBUSQbd3WIboxsS1HzFdRuHKRa2CpYwie/o6dZAxUjt62yFwjoVdM7Iw2VO5fHV1rJwa7jJZBNZin0E7Q==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "0vK9DnYrYChdiH3yRZWkkp4x4LbrfkWEdBc5HOsQ8t/0CLOWKXKkkhOE8A1shlex0hGydbGrhObeypxz/QTm+w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.CommandLine": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "rVwz4ml/Jve/QzzUlyTVOKXVZ37op9RK6Ize4uPmJ3S5c2ErExoy816+dslBQ06ZrFq8M9bpnV5LVBuPD1ONHQ==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "vB6eDQ5prED5jHBqmSDNYzlCXsTSylYY7co9c7guhnz0zhx+jZ8BTHgO7y/Wl1dV2jAO15mKNWuyHRIRtWwGQg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "fo84UIa8aSBG3pOtzLsgkj1YkOVfYFy2YWcRTCevHHAkuVsxnYnKBrcW2pyFgqqfQ/rT8K1nmRXHDdQIZ8PDig==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "9qileEYXDodlPN9DfPd5sHSfU2nSrI1r5BHVqLaLyb/7mPi335cy4ar/0ix4tXb2Aer/Pu4e5/zdwxt7lrtSyQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "tBNMSDJ2q7WQK2zwPhHY5I/q95t7sf6dT079mGrNm0yOZF/gM9JvR/LtCb/rwhRmh7A6XMnzv5WbpCh9KLq9EQ==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "2jgx58Jpk3oKT7KRn8x/cFf3QDTjQP+KUbyBnynAcB2iBx1Eq9EdNMCu0QEbYuaZOaQru/Kwdffary+hn58Wwg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.3",
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "mjkp3ZwynNacZk4uq93I0DyCY48FZmi3yRV0xlfeDuWh44KcDunPXHwt8IWr4kL7cVM6eiFVe6YTJg97KzUAUA==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "vjxzcnL7ul322+kpvELisXaZl8/5MYs6JfI9DZLQWsao1nA/4FL48yPwDK986hbJTWc64JxOOaMym0SQ/dy32w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "vwkBQ5jqmfX7nD7CFvB3k1uSeNBKRcYRDvlk3pxJzJfm/cgT4R+hQg5AFXW/1aLKjz0q7brpRocHC5GK2sjvEw==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "UgH18nQkuMJgxjn1539I83N6LhnKQlLhQm3ppe+PGsFpYsC6eGpF/1KvDRm/bmqsrg0NXhurrv4k2r0e8vWX/Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "lDbxJpkl6X8KZGpkAxgrrthQ42YeiR0xjPp7KPx+sCPc3ZbpaIbjzd0QQ+9kDdK2RU2DOl3pc6tQyAgEZY3V0A==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "JJjI2Fa+QtZcUyuNjbKn04OjIUX5IgFGFu/Xc+qvzh1rXdZHLcnqqVXhR4093bGirTwacRlHiVg1XYI9xum6QQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "TfaHPSe39NyL2wxkisRxXK7xvHGZYBZ+dy3r+mqGvnxKgAPdHkMu3QMQZI4pquP6W5FIQBqs8FJpWV8ffCgDqQ=="
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "xY3lTjj4+ZYmiKIkyWitddrp1uL5uYiweQjqo4BKBw01ZC4HhcfgLghDpPZcUlppgWAFqFy9SgkiYWOMx365pw=="
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "gqhbIq6adm0+/9IlDYmchekoxNkmUTm7rfTG3k4zzoQkjRuD8TQGwL1WnIcTDt4aQ+j+Vu0OQrjI8GlpJQQhIA==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "BKkLCFXzJvNmdngeYBf72VXoZqTJSb1orvjdzDLaGobicoGFBPW8ug2ru1nnEewMEwJzMgnsjHQY8EaKWmVhKg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "/fn0Xe8t+3YbMfwyTk4hFirWyAG1pBA5ogVYsrKAuuD2gbqOWhFuSA28auCmS3z8Y2eq3miDIKq4pFVRWA+J6g==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "UDY7blv4DCyIJ/8CkNrQKLaAZFypXQavRZ2DWf/2zi1mxYYKKw2t8AOCBWxNntyPZHPGhtEmL3snFM98ADZqTw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "jZuO3APLh0ePwtT9PDxiMdPwpDdct/kuExlXLCZZ+XFje/Xt815MM827EFJuxTBAbL148ywyfJyjIZ92osP5WA=="
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "oyPrbpRFa0uWik3PMwpK1mbAr+inZTEkaBsnMjHyT74YN0ot6knA7OnyFLg+oM4MwW5PZIS4HHW9efy0+gj+oQ=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "umczZ3+QPpzlrW/lkvy+IB0p52+qZ5w++aqx2lTCMOaPKzwcbVdrJgiQ3ajw5QWBp7gChLUiCYkSlWUpfjv24g==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "4zZbQ4w+hCMm9J+z5NOj3giIPT2MhZxx05HX/MGuAmDBbjOuXlYIIRN+t4V6OLxy5nXZIcXO+dQMB/OWubuDkw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Physical": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "th2+tQBV5oWjgKhip9GjiIv2AEK3QvfAO3tZcqV3F3dEt5D6Gb411RntCj1+8GS9HaRRSxjSGx/fCrMqIjkb1Q==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "FlOe2i7UUIfY0l0ChaIYtlXjdWWutR4DMRKZaGD6z4G1uVTteFkbBfxUIoi1uGmrZQxXe/yv/cfwiT0tK2xyXA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "9.0.3",
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.FileSystemGlobbing": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "Rec77KHk4iNpFznHi5/6wF3MlUDcKqg26t8gRYbUm1PSukZ4B6mrXpZsJSNOiwyhhQVkjYbaoZxi5XJgRQ5lFg=="
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "96Ub5LmwYfIGVoXkbe4kjs+ivK6fLBTwKJAOMfUNV0R+AkZRItlgROFqXEWMUlXBTPM1/kKu26Ueu5As6RDzJA=="
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "rHabYVhQsGYNfgnfnYLqZRx/hLe85i6jW5rnDjA9pjt3x7yjPv8T/EXcgN5T9T38FAVwZRA+RMGUkEHbxvCOBQ==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "WNrad20tySNCPe9aJUK7Wfwh+RiyLF+id02FKW8Qfc+HAzNQHazcqMXAbwG/kmbS89uvan/nKK1MufkRahjrJA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "utIi2R1nm+PCWkvWBf1Ou6LWqg9iLfHU23r8yyU9VCvda4dEs7xbTZSwGa5KuwbpzpgCbHCIuKaFHB3zyFmnGw==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "Z/7ze+0iheT7FJeZPqJKARYvyC2bmwu3whbm/48BJjdlGVvgDguoCqJIkI/67NkroTYobd5geai1WheNQvWrgA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "H/MBMLt9A/69Ux4OrV7oCKt3DcMT04o5SCqDolulzQA66TLFEpYYb4qedMs/uwrLtyHXGuDGWKZse/oa8W9AZw==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "pYnAffJL7ARD/HCnnPvnFKSIHnTSmWz84WIlT9tPeQ4lHNiu0Az7N/8itihWvcF8sT+VVD5lq8V+ckMzu4SbOw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "eVZsaKNyK0g0C1qp0mmn4Q2PiX+bXdkz8+zVkXyVMk8IvoWfmTjLjEq1MQlwt1A22lToANPiUrxPJ7Tt3V5puw==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "Us4evDN3lbp1beVgrpxkSXKrbntVGAK+YbSo9P9driiU9PK05+ShhgesJ3aj7SuDfr3mqqcEgrMJ87Vu8t5dhw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.3",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Console": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "o9VXLOdpTAro1q7ZThIB3S8OHrRn5pr8cFUCiN85fiwlfAt2DhU4ZIfHy+jCNbf7y7S5Exbr3dlDE8mKNrs0Yg==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "mPp9xB9MjiPuodh9z/+6zEGNj2kSVeXQtdbIBHlhUYqxX22gzJkx0ycPY42q4/OT/SzFV/TJ989Pa3sA/8ZBeA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Debug": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "BlKgvNYjD6mY5GXpMCf9zPAsrovMgW5mzCOT7SpoOSyI1478zldf+7PKvDIscC277z5zjSO3yi/OuIWpnTZmdA==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "OwHQFVITsONEoizShc1yNYTUvMq0kT9j/LhwAKMsA7OZqtrBXuqjosbSvzkJZ9o+KWAozDh5Y1Vtpe5p/8/1qA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.EventLog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "/+elZUHGgB3oHKO9St/Ql/qfze9O+UbXj+9FOj1gIshLCFXcPlhpKoI11jE6eIV0kbs1P/EeffJl4KDFyvAiJQ==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "/gMwlll21UJcaXlitUqd+rs9jH36EJz5BpFVPshyOqz5u0qyV1pFnTWm5vhyx+g6gwVYENSLgpazR1urNv83xw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3",
|
||||
"System.Diagnostics.EventLog": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"System.Diagnostics.EventLog": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.EventSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "hgG0EGEHnngQFQNqJ5ungEykqaQ5Tik0Gpkb38pea2a5cR3pWlZR4vuYLDdtTgSiKEKByXz/3wNQ7qAqXamEEA==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "aGMFc/1P+315d07iyxSe6lEoZ0JjOPJ+Mfv9rrV2PvR2DFu1/pSi/SItHw1iChJOZgslNKJE97g1a9nLX3qQYA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Logging": "9.0.3",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3",
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "xE7MpY70lkw1oiid5y6FbL9dVw8oLfkx8RhSNGN8sSzBlCqGn0SyT3Fqc8tZnDaPIq7Z8R9RTKlS564DS+MV3g==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "OmTaQ0v4gxGQkehpwWIqPoEiwsPuG/u4HUsbOFoWGx4DKET2AXzopnFe/fE608FIhzc/kcg2p8JdyMRCCUzitQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "PcyYHQglKnWVZHSPaL6v2qnfsIuFw8tSq7cyXHg3OeuDVn/CqmdWUjRiZomCF/Gi+qCi+ksz0lFphg2cNvB8zQ==",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "eW2s6n06x0w6w4nsX+SvpgsFYkl+Y0CttYAt6DKUXeqprX+hzNqjSfOh637fwNJBg7wRBrOIRHe49gKiTgJxzQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.3",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
|
||||
"Microsoft.Extensions.Options": "9.0.3",
|
||||
"Microsoft.Extensions.Primitives": "9.0.3"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "yCCJHvBcRyqapMSNzP+kTc57Eaavq2cr5Tmuil6/XVnipQf5xmskxakSQ1enU6S4+fNg3sJ27WcInV64q24JsA=="
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "tizSIOEsIgSNSSh+hKeUVPK7xmTIjR8s+mJWOu1KXV3htvNQiPMFRMO17OdI1y/4ZApdBVk49u/08QGC9yvLug=="
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.7.0",
|
||||
"contentHash": "OQd5aVepYvh5evOmBMeAYjMIpEcTf1ZCBZaU7Nh/RlhhdXefjFDJeP1L2F2zeNT1unFr+wUu/h3Ac2Xb4BXU6w=="
|
||||
"resolved": "8.14.0",
|
||||
"contentHash": "iwbCpSjD3ehfTwBhtSNEtKPK0ICun6ov7Ibx6ISNA9bfwIyzI2Siwyi9eJFCJBwxowK9xcA1mj+jBWiigeqgcQ=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.7.0",
|
||||
"contentHash": "uzsSAWhNhbrkWbQKBTE8QhzviU6sr3bJ1Bkv7gERlhswfSKOp7HsxTRLTPBpx/whQ/GRRHEwMg8leRIPbMrOgw==",
|
||||
"resolved": "8.14.0",
|
||||
"contentHash": "4jOpiA4THdtpLyMdAb24dtj7+6GmvhOhxf5XHLYWmPKF8ApEnApal1UnJsKO4HxUWRXDA6C4WQVfYyqsRhpNpQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Tokens": "8.7.0"
|
||||
"Microsoft.IdentityModel.Tokens": "8.14.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.7.0",
|
||||
"contentHash": "Bs0TznPAu+nxa9rAVHJ+j3CYECHJkT3tG8AyBfhFYlT5ldsDhoxFT7J+PKxJHLf+ayqWfvDZHHc4639W2FQCxA==",
|
||||
"resolved": "8.14.0",
|
||||
"contentHash": "eqqnemdW38CKZEHS6diA50BV94QICozDZEvSrsvN3SJXUFwVB9gy+/oz76gldP7nZliA16IglXjXTCTdmU/Ejg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.7.0"
|
||||
"Microsoft.IdentityModel.Abstractions": "8.14.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.7.0",
|
||||
"contentHash": "5Z6voXjRXAnGklhmZd1mKz89UhcF5ZQQZaZc2iKrOuL4Li1UihG2vlJx8IbiFAOIxy/xdbsAm0A+WZEaH5fxng==",
|
||||
"resolved": "8.14.0",
|
||||
"contentHash": "lKIZiBiGd36k02TCdMHp1KlNWisyIvQxcYJvIkz7P4gSQ9zi8dgh6S5Grj8NNG7HWYIPfQymGyoZ6JB5d1Lo1g==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.2",
|
||||
"Microsoft.IdentityModel.Logging": "8.7.0"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.0",
|
||||
"Microsoft.IdentityModel.Logging": "8.14.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NET.StringTools": {
|
||||
@@ -498,8 +504,8 @@
|
||||
},
|
||||
"System.Diagnostics.EventLog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "0nDJBZ06DVdTG2vvCZ4XjazLVaFawdT0pnji23ISX8I8fEOlRJyzH2I0kWiAbCtFwry2Zir4qE4l/GStLATfFw=="
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "gebRF3JLLJ76jz1CQpvwezNapZUjFq20JQsaGHzBH0DzlkHBLpdhwkOei9usiOkIGMwU/L0ALWpNe1JE+5/itw=="
|
||||
},
|
||||
"System.IO.Pipelines": {
|
||||
"type": "Transitive",
|
||||
@@ -508,16 +514,13 @@
|
||||
},
|
||||
"System.Net.ServerSentEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "Vs/C2V27bjtwLqYag9ATzHilcUn8VQTICre4jSBMGFUeSTxEZffTjb+xZwjcmPsVAjmSZmBI5N7Ezq8UFvqQQg=="
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "wrpra4YvKXL7VdsQMKPcPxyA8pXK22LcxaKGA8oEndgjLZ1ZSdKXTxEA2cPvvNpMEUBwZlgJ6oZYQ8aJcpapPg=="
|
||||
},
|
||||
"System.Threading.Channels": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.3",
|
||||
"contentHash": "Ao0iegVONKYVw0eWxJv0ArtMVfkFjgyyYKtUXru6xX5H95flSZWW3QCavD4PAgwpc0ETP38kGHaYbPzSE7sw2w=="
|
||||
},
|
||||
"chaos.nacl": {
|
||||
"type": "Project"
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "kpvkzWJoHR9os3/4LL5feaTTLD92+XzTqPyYLU2tw2BoJ4MrWCfkjGXtL7MsdpV/20e1+SamCbrPj2L9ptwgBA=="
|
||||
},
|
||||
"maresynchronos.api": {
|
||||
"type": "Project",
|
||||
|
||||
1
Penumbra.Api
Submodule
1
Penumbra.Api
Submodule
Submodule Penumbra.Api added at dd14131793
@@ -1,2 +1,4 @@
|
||||
# UmbraClient
|
||||
# Umbra Sync
|
||||
|
||||
🇫🇷
|
||||
Ce projet est basé sur Mare Synchronos de DarkArchon. Le code original est sous licence MIT ; voir le fichier LICENSE_MIT pour plus de détails. Les commits après celui-ci sont sous licence AGPL v3.
|
||||
351
UmbraAPI/.gitignore
vendored
351
UmbraAPI/.gitignore
vendored
@@ -1,351 +0,0 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
.DS_Store
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
@@ -1,36 +0,0 @@
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace MareSynchronos.API.Data;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public class CharacterData
|
||||
{
|
||||
public CharacterData()
|
||||
{
|
||||
DataHash = new(() =>
|
||||
{
|
||||
var json = JsonSerializer.Serialize(this);
|
||||
#pragma warning disable SYSLIB0021 // Type or member is obsolete
|
||||
using SHA256CryptoServiceProvider cryptoProvider = new();
|
||||
#pragma warning restore SYSLIB0021 // Type or member is obsolete
|
||||
return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(json))).Replace("-", "", StringComparison.Ordinal);
|
||||
});
|
||||
}
|
||||
|
||||
public Dictionary<ObjectKind, string> CustomizePlusData { get; set; } = new();
|
||||
[JsonIgnore]
|
||||
public Lazy<string> DataHash { get; }
|
||||
|
||||
public Dictionary<ObjectKind, List<FileReplacementData>> FileReplacements { get; set; } = new();
|
||||
public Dictionary<ObjectKind, string> GlamourerData { get; set; } = new();
|
||||
public string HeelsData { get; set; } = string.Empty;
|
||||
public string HonorificData { get; set; } = string.Empty;
|
||||
public string ManipulationData { get; set; } = string.Empty;
|
||||
public string MoodlesData { get; set; } = string.Empty;
|
||||
public string PetNamesData { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Data;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record ChatMessage
|
||||
{
|
||||
public string SenderName { get; set; } = string.Empty;
|
||||
public uint SenderHomeWorldId { get; set; } = 0;
|
||||
public byte[] PayloadContent { get; set; } = [];
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Comparer;
|
||||
|
||||
public class GroupDataComparer : IEqualityComparer<GroupData>
|
||||
{
|
||||
public static GroupDataComparer Instance => _instance;
|
||||
private static GroupDataComparer _instance = new GroupDataComparer();
|
||||
|
||||
private GroupDataComparer() { }
|
||||
public bool Equals(GroupData? x, GroupData? y)
|
||||
{
|
||||
if (x == null || y == null) return false;
|
||||
return x.GID.Equals(y.GID, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(GroupData obj)
|
||||
{
|
||||
return obj.GID.GetHashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using MareSynchronos.API.Dto.Group;
|
||||
|
||||
namespace MareSynchronos.API.Data.Comparer;
|
||||
|
||||
|
||||
public class GroupDtoComparer : IEqualityComparer<GroupDto>
|
||||
{
|
||||
public static GroupDtoComparer Instance => _instance;
|
||||
private static GroupDtoComparer _instance = new GroupDtoComparer();
|
||||
|
||||
private GroupDtoComparer() { }
|
||||
|
||||
public bool Equals(GroupDto? x, GroupDto? y)
|
||||
{
|
||||
if (x == null || y == null) return false;
|
||||
return x.GID.Equals(y.GID, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(GroupDto obj)
|
||||
{
|
||||
return obj.Group.GID.GetHashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using MareSynchronos.API.Dto.Group;
|
||||
|
||||
namespace MareSynchronos.API.Data.Comparer;
|
||||
|
||||
public class GroupPairDtoComparer : IEqualityComparer<GroupPairDto>
|
||||
{
|
||||
public static GroupPairDtoComparer Instance => _instance;
|
||||
private static GroupPairDtoComparer _instance = new();
|
||||
private GroupPairDtoComparer() { }
|
||||
public bool Equals(GroupPairDto? x, GroupPairDto? y)
|
||||
{
|
||||
if (x == null || y == null) return false;
|
||||
return x.GID.Equals(y.GID, StringComparison.Ordinal) && x.UID.Equals(y.UID, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(GroupPairDto obj)
|
||||
{
|
||||
return HashCode.Combine(obj.Group.GID.GetHashCode(), obj.User.UID.GetHashCode());
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Comparer;
|
||||
|
||||
public class UserDataComparer : IEqualityComparer<UserData>
|
||||
{
|
||||
public static UserDataComparer Instance => _instance;
|
||||
private static UserDataComparer _instance = new();
|
||||
|
||||
private UserDataComparer() { }
|
||||
|
||||
public bool Equals(UserData? x, UserData? y)
|
||||
{
|
||||
if (x == null || y == null) return false;
|
||||
return x.UID.Equals(y.UID, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(UserData obj)
|
||||
{
|
||||
return obj.UID.GetHashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using MareSynchronos.API.Dto.User;
|
||||
|
||||
namespace MareSynchronos.API.Data.Comparer;
|
||||
|
||||
public class UserDtoComparer : IEqualityComparer<UserDto>
|
||||
{
|
||||
public static UserDtoComparer Instance => _instance;
|
||||
private static UserDtoComparer _instance = new();
|
||||
private UserDtoComparer() { }
|
||||
public bool Equals(UserDto? x, UserDto? y)
|
||||
{
|
||||
if (x == null || y == null) return false;
|
||||
return x.User.UID.Equals(y.User.UID, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(UserDto obj)
|
||||
{
|
||||
return obj.User.UID.GetHashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Enum;
|
||||
|
||||
[Flags]
|
||||
public enum GroupPermissions
|
||||
{
|
||||
NoneSet = 0x0,
|
||||
DisableAnimations = 0x1,
|
||||
DisableSounds = 0x2,
|
||||
DisableInvites = 0x4,
|
||||
DisableVFX = 0x8,
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Enum;
|
||||
|
||||
[Flags]
|
||||
public enum GroupUserInfo
|
||||
{
|
||||
None = 0x0,
|
||||
IsModerator = 0x2,
|
||||
IsPinned = 0x4
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Enum;
|
||||
|
||||
[Flags]
|
||||
public enum GroupUserPermissions
|
||||
{
|
||||
NoneSet = 0x0,
|
||||
Paused = 0x1,
|
||||
DisableAnimations = 0x2,
|
||||
DisableSounds = 0x4,
|
||||
DisableVFX = 0x8,
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Enum;
|
||||
|
||||
public enum MessageSeverity
|
||||
{
|
||||
Information,
|
||||
Warning,
|
||||
Error
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Enum;
|
||||
|
||||
public enum ObjectKind
|
||||
{
|
||||
Player = 0,
|
||||
MinionOrMount = 1,
|
||||
Companion = 2,
|
||||
Pet = 3,
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace MareSynchronos.API.Data.Enum;
|
||||
|
||||
[Flags]
|
||||
public enum UserPermissions
|
||||
{
|
||||
NoneSet = 0,
|
||||
Paired = 1,
|
||||
Paused = 2,
|
||||
DisableAnimations = 4,
|
||||
DisableSounds = 8,
|
||||
DisableVFX = 16,
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
|
||||
namespace MareSynchronos.API.Data.Extensions;
|
||||
|
||||
public static class GroupPermissionsExtensions
|
||||
{
|
||||
public static bool IsDisableAnimations(this GroupPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupPermissions.DisableAnimations);
|
||||
}
|
||||
|
||||
public static bool IsDisableSounds(this GroupPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupPermissions.DisableSounds);
|
||||
}
|
||||
|
||||
public static bool IsDisableInvites(this GroupPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupPermissions.DisableInvites);
|
||||
}
|
||||
|
||||
public static bool IsDisableVFX(this GroupPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupPermissions.DisableVFX);
|
||||
}
|
||||
|
||||
public static void SetDisableAnimations(this ref GroupPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupPermissions.DisableAnimations;
|
||||
else perm &= ~GroupPermissions.DisableAnimations;
|
||||
}
|
||||
|
||||
public static void SetDisableSounds(this ref GroupPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupPermissions.DisableSounds;
|
||||
else perm &= ~GroupPermissions.DisableSounds;
|
||||
}
|
||||
|
||||
public static void SetDisableInvites(this ref GroupPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupPermissions.DisableInvites;
|
||||
else perm &= ~GroupPermissions.DisableInvites;
|
||||
}
|
||||
|
||||
public static void SetDisableVFX(this ref GroupPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupPermissions.DisableVFX;
|
||||
else perm &= ~GroupPermissions.DisableVFX;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
|
||||
namespace MareSynchronos.API.Data.Extensions;
|
||||
|
||||
public static class GroupUserInfoExtensions
|
||||
{
|
||||
public static bool IsModerator(this GroupUserInfo info)
|
||||
{
|
||||
return info.HasFlag(GroupUserInfo.IsModerator);
|
||||
}
|
||||
|
||||
public static bool IsPinned(this GroupUserInfo info)
|
||||
{
|
||||
return info.HasFlag(GroupUserInfo.IsPinned);
|
||||
}
|
||||
|
||||
public static void SetModerator(this ref GroupUserInfo info, bool isModerator)
|
||||
{
|
||||
if (isModerator) info |= GroupUserInfo.IsModerator;
|
||||
else info &= ~GroupUserInfo.IsModerator;
|
||||
}
|
||||
|
||||
public static void SetPinned(this ref GroupUserInfo info, bool isPinned)
|
||||
{
|
||||
if (isPinned) info |= GroupUserInfo.IsPinned;
|
||||
else info &= ~GroupUserInfo.IsPinned;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
|
||||
namespace MareSynchronos.API.Data.Extensions;
|
||||
|
||||
public static class GroupUserPermissionsExtensions
|
||||
{
|
||||
public static bool IsDisableAnimations(this GroupUserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupUserPermissions.DisableAnimations);
|
||||
}
|
||||
|
||||
public static bool IsDisableSounds(this GroupUserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupUserPermissions.DisableSounds);
|
||||
}
|
||||
|
||||
public static bool IsPaused(this GroupUserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupUserPermissions.Paused);
|
||||
}
|
||||
|
||||
public static bool IsDisableVFX(this GroupUserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(GroupUserPermissions.DisableVFX);
|
||||
}
|
||||
|
||||
public static void SetDisableAnimations(this ref GroupUserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupUserPermissions.DisableAnimations;
|
||||
else perm &= ~GroupUserPermissions.DisableAnimations;
|
||||
}
|
||||
|
||||
public static void SetDisableSounds(this ref GroupUserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupUserPermissions.DisableSounds;
|
||||
else perm &= ~GroupUserPermissions.DisableSounds;
|
||||
}
|
||||
|
||||
public static void SetPaused(this ref GroupUserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupUserPermissions.Paused;
|
||||
else perm &= ~GroupUserPermissions.Paused;
|
||||
}
|
||||
|
||||
public static void SetDisableVFX(this ref GroupUserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= GroupUserPermissions.DisableVFX;
|
||||
else perm &= ~GroupUserPermissions.DisableVFX;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
|
||||
namespace MareSynchronos.API.Data.Extensions;
|
||||
|
||||
public static class UserPermissionsExtensions
|
||||
{
|
||||
public static bool IsPaired(this UserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(UserPermissions.Paired);
|
||||
}
|
||||
|
||||
public static bool IsPaused(this UserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(UserPermissions.Paused);
|
||||
}
|
||||
|
||||
public static bool IsDisableAnimations(this UserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(UserPermissions.DisableAnimations);
|
||||
}
|
||||
|
||||
public static bool IsDisableSounds(this UserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(UserPermissions.DisableSounds);
|
||||
}
|
||||
|
||||
public static bool IsDisableVFX(this UserPermissions perm)
|
||||
{
|
||||
return perm.HasFlag(UserPermissions.DisableVFX);
|
||||
}
|
||||
|
||||
public static void SetPaired(this ref UserPermissions perm, bool paired)
|
||||
{
|
||||
if (paired) perm |= UserPermissions.Paired;
|
||||
else perm &= ~UserPermissions.Paired;
|
||||
}
|
||||
|
||||
public static void SetPaused(this ref UserPermissions perm, bool paused)
|
||||
{
|
||||
if (paused) perm |= UserPermissions.Paused;
|
||||
else perm &= ~UserPermissions.Paused;
|
||||
}
|
||||
|
||||
public static void SetDisableAnimations(this ref UserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= UserPermissions.DisableAnimations;
|
||||
else perm &= ~UserPermissions.DisableAnimations;
|
||||
}
|
||||
|
||||
public static void SetDisableSounds(this ref UserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= UserPermissions.DisableSounds;
|
||||
else perm &= ~UserPermissions.DisableSounds;
|
||||
}
|
||||
|
||||
public static void SetDisableVFX(this ref UserPermissions perm, bool set)
|
||||
{
|
||||
if (set) perm |= UserPermissions.DisableVFX;
|
||||
else perm &= ~UserPermissions.DisableVFX;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
|
||||
namespace MareSynchronos.API.Data;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public class FileReplacementData
|
||||
{
|
||||
public FileReplacementData()
|
||||
{
|
||||
DataHash = new(() =>
|
||||
{
|
||||
var json = JsonSerializer.Serialize(this);
|
||||
#pragma warning disable SYSLIB0021 // Type or member is obsolete
|
||||
using SHA256CryptoServiceProvider cryptoProvider = new();
|
||||
#pragma warning restore SYSLIB0021 // Type or member is obsolete
|
||||
return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(json))).Replace("-", "", StringComparison.Ordinal);
|
||||
});
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public Lazy<string> DataHash { get; }
|
||||
public string[] GamePaths { get; set; } = Array.Empty<string>();
|
||||
public string Hash { get; set; } = string.Empty;
|
||||
public string FileSwapPath { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Data;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record GroupData(string GID, string? Alias = null)
|
||||
{
|
||||
[IgnoreMember]
|
||||
public string AliasOrGID => string.IsNullOrWhiteSpace(Alias) ? GID : Alias;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Data;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record SignedChatMessage(ChatMessage Message, UserData Sender) : ChatMessage(Message)
|
||||
{
|
||||
// Sender and timestamp are set by the server
|
||||
public UserData Sender { get; set; } = Sender;
|
||||
public long Timestamp { get; set; } = 0;
|
||||
// Signature is generated by the server as SHA256(Sender.UID | Timestamp | Destination | Message)
|
||||
// Where Destination is either the receiver's UID, or the group GID
|
||||
public string Signature { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Data;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record UserData(string UID, string? Alias = null)
|
||||
{
|
||||
[IgnoreMember]
|
||||
public string AliasOrUID => string.IsNullOrWhiteSpace(Alias) ? UID : Alias;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Account;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record RegisterReplyDto
|
||||
{
|
||||
public bool Success { get; set; } = false;
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
public string UID { get; set; } = string.Empty;
|
||||
public string SecretKey { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Account;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record RegisterReplyV2Dto
|
||||
{
|
||||
public bool Success { get; set; } = false;
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
public string UID { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record AuthReplyDto
|
||||
{
|
||||
public string Token { get; set; } = string.Empty;
|
||||
public string? WellKnown { get; set; }
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
public enum AccessTypeDto
|
||||
{
|
||||
Individuals,
|
||||
ClosePairs,
|
||||
AllPairs,
|
||||
Public
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record CharaDataDownloadDto(string Id, UserData Uploader) : CharaDataDto(Id, Uploader)
|
||||
{
|
||||
public string GlamourerData { get; init; } = string.Empty;
|
||||
public string CustomizeData { get; init; } = string.Empty;
|
||||
public string ManipulationData { get; set; } = string.Empty;
|
||||
public List<GamePathEntry> FileGamePaths { get; init; } = [];
|
||||
public List<GamePathEntry> FileSwaps { get; init; } = [];
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
public record CharaDataDto(string Id, UserData Uploader)
|
||||
{
|
||||
public string Description { get; init; } = string.Empty;
|
||||
public DateTime UpdatedDate { get; init; }
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record CharaDataFullDto(string Id, UserData Uploader) : CharaDataDto(Id, Uploader)
|
||||
{
|
||||
public DateTime CreatedDate { get; init; }
|
||||
public DateTime ExpiryDate { get; set; }
|
||||
public string GlamourerData { get; set; } = string.Empty;
|
||||
public string CustomizeData { get; set; } = string.Empty;
|
||||
public string ManipulationData { get; set; } = string.Empty;
|
||||
public int DownloadCount { get; set; } = 0;
|
||||
public List<UserData> AllowedUsers { get; set; } = [];
|
||||
public List<GroupData> AllowedGroups { get; set; } = [];
|
||||
public List<GamePathEntry> FileGamePaths { get; set; } = [];
|
||||
public List<GamePathEntry> FileSwaps { get; set; } = [];
|
||||
public List<GamePathEntry> OriginalFiles { get; set; } = [];
|
||||
public AccessTypeDto AccessType { get; set; }
|
||||
public ShareTypeDto ShareType { get; set; }
|
||||
public List<PoseEntry> PoseData { get; set; } = [];
|
||||
}
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record GamePathEntry(string HashOrFileSwap, string GamePath);
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record PoseEntry(long? Id)
|
||||
{
|
||||
public string? Description { get; set; } = string.Empty;
|
||||
public string? PoseData { get; set; } = string.Empty;
|
||||
public WorldData? WorldData { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public record struct WorldData
|
||||
{
|
||||
[Key(0)] public LocationInfo LocationInfo { get; set; }
|
||||
[Key(1)] public float PositionX { get; set; }
|
||||
[Key(2)] public float PositionY { get; set; }
|
||||
[Key(3)] public float PositionZ { get; set; }
|
||||
[Key(4)] public float RotationX { get; set; }
|
||||
[Key(5)] public float RotationY { get; set; }
|
||||
[Key(6)] public float RotationZ { get; set; }
|
||||
[Key(7)] public float RotationW { get; set; }
|
||||
[Key(8)] public float ScaleX { get; set; }
|
||||
[Key(9)] public float ScaleY { get; set; }
|
||||
[Key(10)] public float ScaleZ { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public record struct LocationInfo
|
||||
{
|
||||
[Key(0)] public uint ServerId { get; set; }
|
||||
[Key(1)] public uint MapId { get; set; }
|
||||
[Key(2)] public uint TerritoryId { get; set; }
|
||||
[Key(3)] public uint DivisionId { get; set; }
|
||||
[Key(4)] public uint WardId { get; set; }
|
||||
[Key(5)] public uint HouseId { get; set; }
|
||||
[Key(6)] public uint RoomId { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public record struct PoseData
|
||||
{
|
||||
[Key(0)] public bool IsDelta { get; set; }
|
||||
[Key(1)] public Dictionary<string, BoneData> Bones { get; set; }
|
||||
[Key(2)] public Dictionary<string, BoneData> MainHand { get; set; }
|
||||
[Key(3)] public Dictionary<string, BoneData> OffHand { get; set; }
|
||||
[Key(4)] public BoneData ModelDifference { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public record struct BoneData
|
||||
{
|
||||
[Key(0)] public bool Exists { get; set; }
|
||||
[Key(1)] public float PositionX { get; set; }
|
||||
[Key(2)] public float PositionY { get; set; }
|
||||
[Key(3)] public float PositionZ { get; set; }
|
||||
[Key(4)] public float RotationX { get; set; }
|
||||
[Key(5)] public float RotationY { get; set; }
|
||||
[Key(6)] public float RotationZ { get; set; }
|
||||
[Key(7)] public float RotationW { get; set; }
|
||||
[Key(8)] public float ScaleX { get; set; }
|
||||
[Key(9)] public float ScaleY { get; set; }
|
||||
[Key(10)] public float ScaleZ { get; set; }
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record CharaDataMetaInfoDto(string Id, UserData Uploader) : CharaDataDto(Id, Uploader)
|
||||
{
|
||||
public bool CanBeDownloaded { get; init; }
|
||||
public List<PoseEntry> PoseData { get; set; } = [];
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record CharaDataUpdateDto(string Id)
|
||||
{
|
||||
public string? Description { get; set; }
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
public string? GlamourerData { get; set; }
|
||||
public string? CustomizeData { get; set; }
|
||||
public string? ManipulationData { get; set; }
|
||||
public List<string>? AllowedUsers { get; set; }
|
||||
public List<string>? AllowedGroups { get; set; }
|
||||
public List<GamePathEntry>? FileGamePaths { get; set; }
|
||||
public List<GamePathEntry>? FileSwaps { get; set; }
|
||||
public AccessTypeDto? AccessType { get; set; }
|
||||
public ShareTypeDto? ShareType { get; set; }
|
||||
public List<PoseEntry>? Poses { get; set; }
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace MareSynchronos.API.Dto.CharaData;
|
||||
|
||||
public enum ShareTypeDto
|
||||
{
|
||||
Private,
|
||||
Shared
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MareSynchronos.API.Dto.Group;
|
||||
using MareSynchronos.API.Dto.User;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Chat;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record GroupChatMsgDto(GroupDto Group, SignedChatMessage Message)
|
||||
{
|
||||
public GroupDto Group = Group;
|
||||
public SignedChatMessage Message = Message;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MareSynchronos.API.Dto.User;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Chat;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record UserChatMsgDto(SignedChatMessage Message)
|
||||
{
|
||||
public SignedChatMessage Message = Message;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record ConnectionDto(UserData User)
|
||||
{
|
||||
public Version CurrentClientVersion { get; set; } = new(0, 0, 0);
|
||||
public int ServerVersion { get; set; }
|
||||
public bool IsAdmin { get; set; }
|
||||
public bool IsModerator { get; set; }
|
||||
public ServerInfo ServerInfo { get; set; } = new();
|
||||
}
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record ServerInfo
|
||||
{
|
||||
public string ShardName { get; set; } = string.Empty;
|
||||
public int MaxGroupUserCount { get; set; }
|
||||
public int MaxGroupsCreatedByUser { get; set; }
|
||||
public int MaxGroupsJoinedByUser { get; set; }
|
||||
public Uri FileServerAddress { get; set; } = new Uri("http://nonemptyuri");
|
||||
public int MaxCharaData { get; set; }
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Files;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record DownloadFileDto : ITransferFileDto
|
||||
{
|
||||
public bool FileExists { get; set; } = true;
|
||||
public string Hash { get; set; } = string.Empty;
|
||||
public string Url { get; set; } = string.Empty;
|
||||
public long Size { get; set; } = 0;
|
||||
public bool IsForbidden { get; set; } = false;
|
||||
public string ForbiddenBy { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Files;
|
||||
|
||||
public class FilesSendDto
|
||||
{
|
||||
public List<string> FileHashes { get; set; } = new();
|
||||
public List<string> UIDs { get; set; } = new();
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace MareSynchronos.API.Dto.Files;
|
||||
|
||||
public interface ITransferFileDto
|
||||
{
|
||||
string Hash { get; set; }
|
||||
bool IsForbidden { get; set; }
|
||||
string ForbiddenBy { get; set; }
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Files;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record UploadFileDto : ITransferFileDto
|
||||
{
|
||||
public string Hash { get; set; } = string.Empty;
|
||||
public bool IsForbidden { get; set; } = false;
|
||||
public string ForbiddenBy { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Group;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record BannedGroupUserDto : GroupPairDto
|
||||
{
|
||||
public BannedGroupUserDto(GroupData group, UserData user, string reason, DateTime bannedOn, string bannedBy) : base(group, user)
|
||||
{
|
||||
Reason = reason;
|
||||
BannedOn = bannedOn;
|
||||
BannedBy = bannedBy;
|
||||
}
|
||||
|
||||
public string Reason { get; set; }
|
||||
public DateTime BannedOn { get; set; }
|
||||
public string BannedBy { get; set; }
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Group;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record GroupDto(GroupData Group)
|
||||
{
|
||||
public GroupData Group { get; set; } = Group;
|
||||
public string GID => Group.GID;
|
||||
public string? GroupAlias => Group.Alias;
|
||||
public string GroupAliasOrGID => Group.AliasOrGID;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
using MessagePack;
|
||||
|
||||
namespace MareSynchronos.API.Dto.Group;
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public record GroupFullInfoDto(GroupData Group, UserData Owner, GroupPermissions GroupPermissions, GroupUserPermissions GroupUserPermissions, GroupUserInfo GroupUserInfo) : GroupInfoDto(Group, Owner, GroupPermissions)
|
||||
{
|
||||
public GroupUserPermissions GroupUserPermissions { get; set; } = GroupUserPermissions;
|
||||
public GroupUserInfo GroupUserInfo { get; set; } = GroupUserInfo;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user